-
Notifications
You must be signed in to change notification settings - Fork 88
/
Copy pathvolumes.go
183 lines (153 loc) · 5.89 KB
/
volumes.go
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
180
181
182
183
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) {
response, err := getPaginatedResults[Volume](ctx, c, "volumes", opts)
return response, err
}
// GetVolume gets the template with the provided ID
func (c *Client) GetVolume(ctx context.Context, volumeID int) (*Volume, error) {
e := formatAPIPath("volumes/%d", volumeID)
response, err := doGETRequest[Volume](ctx, c, e)
return response, err
}
// 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)
response, err := doPOSTRequest[Volume](ctx, c, e, opts)
return response, err
}
// CreateVolume creates a Linode Volume
func (c *Client) CreateVolume(ctx context.Context, opts VolumeCreateOptions) (*Volume, error) {
e := "volumes"
response, err := doPOSTRequest[Volume](ctx, c, e, opts)
return response, err
}
// 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)
response, err := doPUTRequest[Volume](ctx, c, e, opts)
return response, err
}
// 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)
response, err := doPOSTRequest[Volume](ctx, c, e, opts)
return response, err
}
// DetachVolume detaches a Linode volume
func (c *Client) DetachVolume(ctx context.Context, volumeID int) error {
e := formatAPIPath("volumes/%d/detach", volumeID)
_, err := doPOSTRequest[Volume, any](ctx, c, e)
return err
}
// 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)
_, err := doPOSTRequest[Volume](ctx, c, e, opts)
return err
}
// DeleteVolume deletes the Volume with the specified id
func (c *Client) DeleteVolume(ctx context.Context, volumeID int) error {
e := formatAPIPath("volumes/%d", volumeID)
err := doDELETERequest(ctx, c, e)
return err
}