1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
package linodego
import (
"context"
"encoding/json"
"time"
"github.com/linode/linodego/internal/parseabletime"
)
// VolumeStatus indicates the status of the Volume
type VolumeStatus string
const (
// VolumeCreating indicates the Volume is being created and is not yet available for use
VolumeCreating VolumeStatus = "creating"
// VolumeActive indicates the Volume is online and available for use
VolumeActive VolumeStatus = "active"
// VolumeResizing indicates the Volume is in the process of upgrading its current capacity
VolumeResizing VolumeStatus = "resizing"
// VolumeContactSupport indicates there is a problem with the Volume. A support ticket must be opened to resolve the issue
VolumeContactSupport VolumeStatus = "contact_support"
)
// Volume represents a linode volume object
type Volume struct {
ID int `json:"id"`
Label string `json:"label"`
Status VolumeStatus `json:"status"`
Region string `json:"region"`
Size int `json:"size"`
LinodeID *int `json:"linode_id"`
FilesystemPath string `json:"filesystem_path"`
Tags []string `json:"tags"`
HardwareType string `json:"hardware_type"`
LinodeLabel string `json:"linode_label"`
Created *time.Time `json:"-"`
Updated *time.Time `json:"-"`
// Note: Block Storage Disk Encryption is not currently available to all users.
Encryption string `json:"encryption"`
}
// VolumeCreateOptions fields are those accepted by CreateVolume
type VolumeCreateOptions struct {
Label string `json:"label,omitempty"`
Region string `json:"region,omitempty"`
LinodeID int `json:"linode_id,omitempty"`
ConfigID int `json:"config_id,omitempty"`
// The Volume's size, in GiB. Minimum size is 10GiB, maximum size is 10240GiB. A "0" value will result in the default size.
Size int `json:"size,omitempty"`
// An array of tags applied to this object. Tags are for organizational purposes only.
Tags []string `json:"tags"`
PersistAcrossBoots *bool `json:"persist_across_boots,omitempty"`
Encryption string `json:"encryption,omitempty"`
}
// VolumeUpdateOptions fields are those accepted by UpdateVolume
type VolumeUpdateOptions struct {
Label string `json:"label,omitempty"`
Tags *[]string `json:"tags,omitempty"`
}
// VolumeAttachOptions fields are those accepted by AttachVolume
type VolumeAttachOptions struct {
LinodeID int `json:"linode_id"`
ConfigID int `json:"config_id,omitempty"`
PersistAcrossBoots *bool `json:"persist_across_boots,omitempty"`
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (v *Volume) UnmarshalJSON(b []byte) error {
type Mask Volume
p := struct {
*Mask
Created *parseabletime.ParseableTime `json:"created"`
Updated *parseabletime.ParseableTime `json:"updated"`
}{
Mask: (*Mask)(v),
}
if err := json.Unmarshal(b, &p); err != nil {
return err
}
v.Created = (*time.Time)(p.Created)
v.Updated = (*time.Time)(p.Updated)
return nil
}
// GetUpdateOptions converts a Volume to VolumeUpdateOptions for use in UpdateVolume
func (v Volume) GetUpdateOptions() (updateOpts VolumeUpdateOptions) {
updateOpts.Label = v.Label
updateOpts.Tags = &v.Tags
return
}
// GetCreateOptions converts a Volume to VolumeCreateOptions for use in CreateVolume
func (v Volume) GetCreateOptions() (createOpts VolumeCreateOptions) {
createOpts.Label = v.Label
createOpts.Tags = v.Tags
createOpts.Region = v.Region
createOpts.Size = v.Size
if v.LinodeID != nil && *v.LinodeID > 0 {
createOpts.LinodeID = *v.LinodeID
}
return
}
// ListVolumes lists Volumes
func (c *Client) ListVolumes(ctx context.Context, opts *ListOptions) ([]Volume, error) {
return getPaginatedResults[Volume](ctx, c, "volumes", opts)
}
// GetVolume gets the template with the provided ID
func (c *Client) GetVolume(ctx context.Context, volumeID int) (*Volume, error) {
e := formatAPIPath("volumes/%d", volumeID)
return doGETRequest[Volume](ctx, c, e)
}
// AttachVolume attaches a volume to a Linode instance
func (c *Client) AttachVolume(ctx context.Context, volumeID int, opts *VolumeAttachOptions) (*Volume, error) {
e := formatAPIPath("volumes/%d/attach", volumeID)
return doPOSTRequest[Volume](ctx, c, e, opts)
}
// CreateVolume creates a Linode Volume
func (c *Client) CreateVolume(ctx context.Context, opts VolumeCreateOptions) (*Volume, error) {
return doPOSTRequest[Volume](ctx, c, "volumes", opts)
}
// UpdateVolume updates the Volume with the specified id
func (c *Client) UpdateVolume(ctx context.Context, volumeID int, opts VolumeUpdateOptions) (*Volume, error) {
e := formatAPIPath("volumes/%d", volumeID)
return doPUTRequest[Volume](ctx, c, e, opts)
}
// CloneVolume clones a Linode volume
func (c *Client) CloneVolume(ctx context.Context, volumeID int, label string) (*Volume, error) {
opts := map[string]any{
"label": label,
}
e := formatAPIPath("volumes/%d/clone", volumeID)
return doPOSTRequest[Volume](ctx, c, e, opts)
}
// DetachVolume detaches a Linode volume
func (c *Client) DetachVolume(ctx context.Context, volumeID int) error {
e := formatAPIPath("volumes/%d/detach", volumeID)
return doPOSTRequestNoRequestResponseBody(ctx, c, e)
}
// ResizeVolume resizes an instance to new Linode type
func (c *Client) ResizeVolume(ctx context.Context, volumeID int, size int) error {
opts := map[string]int{
"size": size,
}
e := formatAPIPath("volumes/%d/resize", volumeID)
return doPOSTRequestNoResponseBody(ctx, c, e, opts)
}
// DeleteVolume deletes the Volume with the specified id
func (c *Client) DeleteVolume(ctx context.Context, volumeID int) error {
e := formatAPIPath("volumes/%d", volumeID)
return doDELETERequest(ctx, c, e)
}
|