instance.go raw
1 package govultr
2
3 import (
4 "context"
5 "fmt"
6 "net/http"
7
8 "github.com/google/go-querystring/query"
9 )
10
11 const instancePath = "/v2/instances"
12
13 // InstanceService is the interface to interact with the instance endpoints on the Vultr API
14 // Link: https://www.vultr.com/api/#tag/instances
15 type InstanceService interface {
16 Create(ctx context.Context, instanceReq *InstanceCreateReq) (*Instance, *http.Response, error)
17 Get(ctx context.Context, instanceID string) (*Instance, *http.Response, error)
18 Update(ctx context.Context, instanceID string, instanceReq *InstanceUpdateReq) (*Instance, *http.Response, error)
19 Delete(ctx context.Context, instanceID string) error
20 List(ctx context.Context, options *ListOptions) ([]Instance, *Meta, *http.Response, error)
21
22 Start(ctx context.Context, instanceID string) error
23 Halt(ctx context.Context, instanceID string) error
24 Reboot(ctx context.Context, instanceID string) error
25 Reinstall(ctx context.Context, instanceID string, reinstallReq *ReinstallReq) (*Instance, *http.Response, error)
26
27 MassStart(ctx context.Context, instanceList []string) error
28 MassHalt(ctx context.Context, instanceList []string) error
29 MassReboot(ctx context.Context, instanceList []string) error
30
31 Restore(ctx context.Context, instanceID string, restoreReq *RestoreReq) (*http.Response, error)
32
33 GetBandwidth(ctx context.Context, instanceID string) (*Bandwidth, *http.Response, error)
34 GetNeighbors(ctx context.Context, instanceID string) (*Neighbors, *http.Response, error)
35
36 ListVPCInfo(ctx context.Context, instanceID string, options *ListOptions) ([]VPCInfo, *Meta, *http.Response, error)
37 AttachVPC(ctx context.Context, instanceID, vpcID string) error
38 DetachVPC(ctx context.Context, instanceID, vpcID string) error
39
40 ISOStatus(ctx context.Context, instanceID string) (*Iso, *http.Response, error)
41 AttachISO(ctx context.Context, instanceID, isoID string) (*http.Response, error)
42 DetachISO(ctx context.Context, instanceID string) (*http.Response, error)
43
44 GetBackupSchedule(ctx context.Context, instanceID string) (*BackupSchedule, *http.Response, error)
45 SetBackupSchedule(ctx context.Context, instanceID string, backup *BackupScheduleReq) (*http.Response, error)
46
47 CreateIPv4(ctx context.Context, instanceID string, reboot *bool) (*IPv4, *http.Response, error)
48 ListIPv4(ctx context.Context, instanceID string, option *ListOptions) ([]IPv4, *Meta, *http.Response, error)
49 DeleteIPv4(ctx context.Context, instanceID, ip string) error
50 ListIPv6(ctx context.Context, instanceID string, option *ListOptions) ([]IPv6, *Meta, *http.Response, error)
51
52 CreateReverseIPv6(ctx context.Context, instanceID string, reverseReq *ReverseIP) error
53 ListReverseIPv6(ctx context.Context, instanceID string) ([]ReverseIP, *http.Response, error)
54 DeleteReverseIPv6(ctx context.Context, instanceID, ip string) error
55
56 CreateReverseIPv4(ctx context.Context, instanceID string, reverseReq *ReverseIP) error
57 DefaultReverseIPv4(ctx context.Context, instanceID, ip string) error
58
59 GetUserData(ctx context.Context, instanceID string) (*UserData, *http.Response, error)
60
61 GetUpgrades(ctx context.Context, instanceID string) (*Upgrades, *http.Response, error)
62
63 // Deprecated: VPC2 is no longer supported
64 ListVPC2Info(ctx context.Context, instanceID string, options *ListOptions) ([]VPC2Info, *Meta, *http.Response, error)
65
66 // Deprecated: VPC2 is no longer supported
67 AttachVPC2(ctx context.Context, instanceID string, vpc2Req *AttachVPC2Req) error
68
69 // Deprecated: VPC2 is no longer supported
70 DetachVPC2(ctx context.Context, instanceID, vpcID string) error
71 }
72
73 // InstanceServiceHandler handles interaction with the server methods for the Vultr API
74 type InstanceServiceHandler struct {
75 client *Client
76 }
77
78 // Instance represents a VPS
79 type Instance struct {
80 ID string `json:"id"`
81 Os string `json:"os"`
82 RAM int `json:"ram"`
83 Disk int `json:"disk"`
84 Plan string `json:"plan"`
85 MainIP string `json:"main_ip"`
86 VPCOnly bool `json:"vpc_only"`
87 VCPUCount int `json:"vcpu_count"`
88 Region string `json:"region"`
89 DefaultPassword string `json:"default_password,omitempty"`
90 DateCreated string `json:"date_created"`
91 Status string `json:"status"`
92 AllowedBandwidth int `json:"allowed_bandwidth"`
93 NetmaskV4 string `json:"netmask_v4"`
94 GatewayV4 string `json:"gateway_v4"`
95 PowerStatus string `json:"power_status"`
96 ServerStatus string `json:"server_status"`
97 V6Network string `json:"v6_network"`
98 V6MainIP string `json:"v6_main_ip"`
99 V6NetworkSize int `json:"v6_network_size"`
100 Label string `json:"label"`
101 InternalIP string `json:"internal_ip"`
102 KVM string `json:"kvm"`
103 OsID int `json:"os_id"`
104 AppID int `json:"app_id"`
105 ImageID string `json:"image_id"`
106 SnapshotID string `json:"snapshot_id"`
107 FirewallGroupID string `json:"firewall_group_id"`
108 Features []string `json:"features"`
109 Hostname string `json:"hostname"`
110 Tags []string `json:"tags"`
111 UserScheme string `json:"user_scheme"`
112 }
113
114 type instanceBase struct {
115 Instance *Instance `json:"instance"`
116 }
117
118 type ipv4Base struct {
119 IPv4 *IPv4 `json:"ipv4"`
120 }
121
122 type instancesBase struct {
123 Instances []Instance `json:"instances"`
124 Meta *Meta `json:"meta"`
125 }
126
127 // Neighbors that might exist on the same host.
128 type Neighbors struct {
129 Neighbors []string `json:"neighbors"`
130 }
131
132 // Bandwidth used on a given instance.
133 type Bandwidth struct {
134 Bandwidth map[string]struct {
135 IncomingBytes int `json:"incoming_bytes"`
136 OutgoingBytes int `json:"outgoing_bytes"`
137 } `json:"bandwidth"`
138 }
139
140 type vpcInfoBase struct {
141 VPCs []VPCInfo `json:"vpcs"`
142 Meta *Meta `json:"meta"`
143 }
144
145 // VPCInfo information for a given instance.
146 type VPCInfo struct {
147 ID string `json:"id"`
148 MacAddress string `json:"mac_address"`
149 IPAddress string `json:"ip_address"`
150 }
151
152 type vpc2InfoBase struct {
153 VPCs []VPC2Info `json:"vpcs"`
154 Meta *Meta `json:"meta"`
155 }
156
157 // VPC2Info information for a given instance.
158 //
159 // Deprecated: VPC2 is no longer supported
160 type VPC2Info struct {
161 ID string `json:"id"`
162 MacAddress string `json:"mac_address"`
163 IPAddress string `json:"ip_address"`
164 }
165
166 // AttachVPC2Req parameters for attaching a VPC 2.0 network
167 //
168 // Deprecated: VPC2 is no longer supported
169 type AttachVPC2Req struct {
170 VPCID string `json:"vpc_id,omitempty"`
171 IPAddress *string `json:"ip_address,omitempty"`
172 }
173
174 type isoStatusBase struct {
175 IsoStatus *Iso `json:"iso_status"`
176 }
177
178 // Iso information for a given instance.
179 type Iso struct {
180 State string `json:"state"`
181 IsoID string `json:"iso_id"`
182 }
183
184 type backupScheduleBase struct {
185 BackupSchedule *BackupSchedule `json:"backup_schedule"`
186 }
187
188 // BackupSchedule information for a given instance.
189 type BackupSchedule struct {
190 Enabled *bool `json:"enabled,omitempty"`
191 Type string `json:"type,omitempty"`
192 NextScheduleTimeUTC string `json:"next_scheduled_time_utc,omitempty"`
193 Hour int `json:"hour,omitempty"`
194 Dow int `json:"dow,omitempty"`
195 Dom int `json:"dom,omitempty"`
196 }
197
198 // BackupScheduleReq struct used to create a backup schedule for an instance.
199 type BackupScheduleReq struct {
200 Type string `json:"type"`
201 Hour *int `json:"hour,omitempty"`
202 Dow *int `json:"dow,omitempty"`
203 Dom int `json:"dom,omitempty"`
204 }
205
206 // RestoreReq struct used to supply whether a restore should be from a backup or snapshot.
207 type RestoreReq struct {
208 BackupID string `json:"backup_id,omitempty"`
209 SnapshotID string `json:"snapshot_id,omitempty"`
210 }
211
212 // todo can we remove this list and return this data back in the list?
213 type reverseIPv6sBase struct {
214 ReverseIPv6s []ReverseIP `json:"reverse_ipv6s"`
215 // no meta?
216 }
217
218 // ReverseIP information for a given instance.
219 type ReverseIP struct {
220 IP string `json:"ip"`
221 Reverse string `json:"reverse"`
222 }
223
224 type userDataBase struct {
225 UserData *UserData `json:"user_data"`
226 }
227
228 // UserData information for a given struct.
229 type UserData struct {
230 Data string `json:"data"`
231 }
232
233 type upgradeBase struct {
234 Upgrades *Upgrades `json:"upgrades"`
235 }
236
237 // Upgrades that are available for a given Instance.
238 type Upgrades struct {
239 Applications []Application `json:"applications,omitempty"`
240 OS []OS `json:"os,omitempty"`
241 Plans []string `json:"plans,omitempty"`
242 }
243
244 // InstanceCreateReq struct used to create an instance.
245 type InstanceCreateReq struct {
246 Region string `json:"region,omitempty"`
247 Plan string `json:"plan,omitempty"`
248 Label string `json:"label,omitempty"`
249 Tags []string `json:"tags"`
250 OsID int `json:"os_id,omitempty"`
251 ISOID string `json:"iso_id,omitempty"`
252 AppID int `json:"app_id,omitempty"`
253 ImageID string `json:"image_id,omitempty"`
254 FirewallGroupID string `json:"firewall_group_id,omitempty"`
255 Hostname string `json:"hostname,omitempty"`
256 IPXEChainURL string `json:"ipxe_chain_url,omitempty"`
257 ScriptID string `json:"script_id,omitempty"`
258 SnapshotID string `json:"snapshot_id,omitempty"`
259 EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
260 DisablePublicIPv4 *bool `json:"disable_public_ipv4,omitempty"`
261 EnableVPC *bool `json:"enable_vpc,omitempty"`
262 AttachVPC []string `json:"attach_vpc,omitempty"`
263 VPCOnly *bool `json:"vpc_only,omitempty"`
264
265 SSHKeys []string `json:"sshkey_id,omitempty"`
266 Backups string `json:"backups,omitempty"`
267 DDOSProtection *bool `json:"ddos_protection,omitempty"`
268 UserData string `json:"user_data,omitempty"`
269 ReservedIPv4 string `json:"reserved_ipv4,omitempty"`
270 ActivationEmail *bool `json:"activation_email,omitempty"`
271 UserScheme string `json:"user_scheme,omitempty"`
272 AppVariables map[string]string `json:"app_variables,omitempty"`
273
274 // Deprecated: VPC2 is no longer supported
275 EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
276
277 // Deprecated: VPC2 is no longer supported
278 AttachVPC2 []string `json:"attach_vpc2,omitempty"`
279 }
280
281 // InstanceUpdateReq struct used to update an instance.
282 type InstanceUpdateReq struct {
283 Plan string `json:"plan,omitempty"`
284 Label string `json:"label,omitempty"`
285 Tags []string `json:"tags"`
286 OsID int `json:"os_id,omitempty"`
287 AppID int `json:"app_id,omitempty"`
288 ImageID string `json:"image_id,omitempty"`
289 EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
290 EnableVPC *bool `json:"enable_vpc,omitempty"`
291 AttachVPC []string `json:"attach_vpc,omitempty"`
292 DetachVPC []string `json:"detach_vpc,omitempty"`
293 Backups string `json:"backups,omitempty"`
294 DDOSProtection *bool `json:"ddos_protection"`
295 UserData string `json:"user_data,omitempty"`
296 FirewallGroupID string `json:"firewall_group_id,omitempty"`
297 UserScheme string `json:"user_scheme,omitempty"`
298
299 // Deprecated: VPC2 is no longer supported
300 EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
301
302 // Deprecated: VPC2 is no longer supported
303 AttachVPC2 []string `json:"attach_vpc2,omitempty"`
304
305 // Deprecated: VPC2 is no longer supported
306 DetachVPC2 []string `json:"detach_vpc2,omitempty"`
307 }
308
309 // ReinstallReq struct used to allow changes during a reinstall
310 type ReinstallReq struct {
311 Hostname string `json:"hostname,omitempty"`
312 }
313
314 // Create will create the server with the given parameters
315 func (i *InstanceServiceHandler) Create(ctx context.Context, instanceReq *InstanceCreateReq) (*Instance, *http.Response, error) {
316 req, err := i.client.NewRequest(ctx, http.MethodPost, instancePath, instanceReq)
317 if err != nil {
318 return nil, nil, err
319 }
320
321 instance := new(instanceBase)
322 resp, err := i.client.DoWithContext(ctx, req, instance)
323 if err != nil {
324 return nil, resp, err
325 }
326
327 return instance.Instance, resp, nil
328 }
329
330 // Get will get the server with the given instanceID
331 func (i *InstanceServiceHandler) Get(ctx context.Context, instanceID string) (*Instance, *http.Response, error) {
332 uri := fmt.Sprintf("%s/%s", instancePath, instanceID)
333
334 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
335 if err != nil {
336 return nil, nil, err
337 }
338
339 instance := new(instanceBase)
340 resp, err := i.client.DoWithContext(ctx, req, instance)
341 if err != nil {
342 return nil, resp, err
343 }
344
345 return instance.Instance, resp, nil
346 }
347
348 // Update will update the server with the given parameters
349 func (i *InstanceServiceHandler) Update(ctx context.Context, instanceID string, instanceReq *InstanceUpdateReq) (*Instance, *http.Response, error) { //nolint:lll
350 uri := fmt.Sprintf("%s/%s", instancePath, instanceID)
351
352 req, err := i.client.NewRequest(ctx, http.MethodPatch, uri, instanceReq)
353 if err != nil {
354 return nil, nil, err
355 }
356
357 instance := new(instanceBase)
358 resp, err := i.client.DoWithContext(ctx, req, instance)
359 if err != nil {
360 return nil, resp, err
361 }
362
363 return instance.Instance, resp, nil
364 }
365
366 // Delete an instance. All data will be permanently lost, and the IP address will be released
367 func (i *InstanceServiceHandler) Delete(ctx context.Context, instanceID string) error {
368 uri := fmt.Sprintf("%s/%s", instancePath, instanceID)
369
370 req, err := i.client.NewRequest(ctx, http.MethodDelete, uri, nil)
371 if err != nil {
372 return err
373 }
374
375 _, err = i.client.DoWithContext(ctx, req, nil)
376 return err
377 }
378
379 // List all instances on your account.
380 func (i *InstanceServiceHandler) List(ctx context.Context, options *ListOptions) ([]Instance, *Meta, *http.Response, error) { //nolint:dupl
381 req, err := i.client.NewRequest(ctx, http.MethodGet, instancePath, nil)
382 if err != nil {
383 return nil, nil, nil, err
384 }
385
386 newValues, err := query.Values(options)
387 if err != nil {
388 return nil, nil, nil, err
389 }
390
391 req.URL.RawQuery = newValues.Encode()
392
393 instances := new(instancesBase)
394 resp, err := i.client.DoWithContext(ctx, req, instances)
395 if err != nil {
396 return nil, nil, resp, err
397 }
398
399 return instances.Instances, instances.Meta, resp, nil
400 }
401
402 // Start will start a vps instance the machine is already running, it will be restarted.
403 func (i *InstanceServiceHandler) Start(ctx context.Context, instanceID string) error {
404 uri := fmt.Sprintf("%s/%s/start", instancePath, instanceID)
405
406 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, nil)
407 if err != nil {
408 return err
409 }
410 _, err = i.client.DoWithContext(ctx, req, nil)
411 return err
412 }
413
414 // Halt will pause an instance.
415 func (i *InstanceServiceHandler) Halt(ctx context.Context, instanceID string) error {
416 uri := fmt.Sprintf("%s/%s/halt", instancePath, instanceID)
417
418 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, nil)
419 if err != nil {
420 return err
421 }
422 _, err = i.client.DoWithContext(ctx, req, nil)
423 return err
424 }
425
426 // Reboot an instance.
427 func (i *InstanceServiceHandler) Reboot(ctx context.Context, instanceID string) error {
428 uri := fmt.Sprintf("%s/%s/reboot", instancePath, instanceID)
429
430 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, nil)
431 if err != nil {
432 return err
433 }
434 _, err = i.client.DoWithContext(ctx, req, nil)
435 return err
436 }
437
438 // Reinstall an instance.
439 func (i *InstanceServiceHandler) Reinstall(ctx context.Context, instanceID string, reinstallReq *ReinstallReq) (*Instance, *http.Response, error) { //nolint:lll
440 uri := fmt.Sprintf("%s/%s/reinstall", instancePath, instanceID)
441
442 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reinstallReq)
443 if err != nil {
444 return nil, nil, err
445 }
446
447 instance := new(instanceBase)
448 resp, err := i.client.DoWithContext(ctx, req, instance)
449 if err != nil {
450 return nil, resp, err
451 }
452 return instance.Instance, resp, nil
453 }
454
455 // MassStart will start a list of instances the machine is already running, it will be restarted.
456 func (i *InstanceServiceHandler) MassStart(ctx context.Context, instanceList []string) error {
457 uri := fmt.Sprintf("%s/start", instancePath)
458
459 reqBody := RequestBody{"instance_ids": instanceList}
460 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
461 if err != nil {
462 return err
463 }
464 _, err = i.client.DoWithContext(ctx, req, nil)
465 return err
466 }
467
468 // MassHalt will pause a list of instances.
469 func (i *InstanceServiceHandler) MassHalt(ctx context.Context, instanceList []string) error {
470 uri := fmt.Sprintf("%s/halt", instancePath)
471
472 reqBody := RequestBody{"instance_ids": instanceList}
473 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
474 if err != nil {
475 return err
476 }
477 _, err = i.client.DoWithContext(ctx, req, nil)
478 return err
479 }
480
481 // MassReboot reboots a list of instances.
482 func (i *InstanceServiceHandler) MassReboot(ctx context.Context, instanceList []string) error {
483 uri := fmt.Sprintf("%s/reboot", instancePath)
484
485 reqBody := RequestBody{"instance_ids": instanceList}
486 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
487 if err != nil {
488 return err
489 }
490 _, err = i.client.DoWithContext(ctx, req, nil)
491 return err
492 }
493
494 // Restore an instance.
495 func (i *InstanceServiceHandler) Restore(ctx context.Context, instanceID string, restoreReq *RestoreReq) (*http.Response, error) {
496 uri := fmt.Sprintf("%s/%s/restore", instancePath, instanceID)
497
498 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, restoreReq)
499 if err != nil {
500 return nil, err
501 }
502
503 return i.client.DoWithContext(ctx, req, nil)
504 }
505
506 // GetBandwidth for a given instance.
507 func (i *InstanceServiceHandler) GetBandwidth(ctx context.Context, instanceID string) (*Bandwidth, *http.Response, error) {
508 uri := fmt.Sprintf("%s/%s/bandwidth", instancePath, instanceID)
509 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
510 if err != nil {
511 return nil, nil, err
512 }
513
514 bandwidth := new(Bandwidth)
515 resp, err := i.client.DoWithContext(ctx, req, bandwidth)
516 if err != nil {
517 return nil, resp, err
518 }
519
520 return bandwidth, resp, nil
521 }
522
523 // GetNeighbors gets a list of other instances in the same location as this Instance.
524 func (i *InstanceServiceHandler) GetNeighbors(ctx context.Context, instanceID string) (*Neighbors, *http.Response, error) {
525 uri := fmt.Sprintf("%s/%s/neighbors", instancePath, instanceID)
526 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
527 if err != nil {
528 return nil, nil, err
529 }
530
531 neighbors := new(Neighbors)
532 resp, err := i.client.DoWithContext(ctx, req, neighbors)
533 if err != nil {
534 return nil, resp, err
535 }
536
537 return neighbors, resp, nil
538 }
539
540 // ListVPCInfo currently attached to an instance.
541 func (i *InstanceServiceHandler) ListVPCInfo(ctx context.Context, instanceID string, options *ListOptions) ([]VPCInfo, *Meta, *http.Response, error) { //nolint:lll,dupl
542 uri := fmt.Sprintf("%s/%s/vpcs", instancePath, instanceID)
543 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
544 if err != nil {
545 return nil, nil, nil, err
546 }
547
548 newValues, err := query.Values(options)
549 if err != nil {
550 return nil, nil, nil, err
551 }
552
553 req.URL.RawQuery = newValues.Encode()
554
555 vpcs := new(vpcInfoBase)
556 resp, err := i.client.DoWithContext(ctx, req, vpcs)
557 if err != nil {
558 return nil, nil, resp, err
559 }
560
561 return vpcs.VPCs, vpcs.Meta, resp, nil
562 }
563
564 // AttachVPC to an instance
565 func (i *InstanceServiceHandler) AttachVPC(ctx context.Context, instanceID, vpcID string) error {
566 uri := fmt.Sprintf("%s/%s/vpcs/attach", instancePath, instanceID)
567 body := RequestBody{"vpc_id": vpcID}
568
569 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
570 if err != nil {
571 return err
572 }
573
574 _, err = i.client.DoWithContext(ctx, req, nil)
575 return err
576 }
577
578 // DetachVPC from an instance.
579 func (i *InstanceServiceHandler) DetachVPC(ctx context.Context, instanceID, vpcID string) error {
580 uri := fmt.Sprintf("%s/%s/vpcs/detach", instancePath, instanceID)
581 body := RequestBody{"vpc_id": vpcID}
582
583 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
584 if err != nil {
585 return err
586 }
587 _, err = i.client.DoWithContext(ctx, req, nil)
588 return err
589 }
590
591 // ListVPC2Info currently attached to an instance.
592 //
593 // Deprecated: VPC2 is no longer supported
594 func (i *InstanceServiceHandler) ListVPC2Info(ctx context.Context, instanceID string, options *ListOptions) ([]VPC2Info, *Meta, *http.Response, error) { //nolint:lll,dupl
595 uri := fmt.Sprintf("%s/%s/vpc2", instancePath, instanceID)
596 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
597 if err != nil {
598 return nil, nil, nil, err
599 }
600
601 newValues, err := query.Values(options)
602 if err != nil {
603 return nil, nil, nil, err
604 }
605
606 req.URL.RawQuery = newValues.Encode()
607
608 vpcs := new(vpc2InfoBase)
609 resp, err := i.client.DoWithContext(ctx, req, vpcs)
610 if err != nil {
611 return nil, nil, resp, err
612 }
613
614 return vpcs.VPCs, vpcs.Meta, resp, nil
615 }
616
617 // AttachVPC2 to an instance
618 //
619 // Deprecated: VPC2 is no longer supported
620 func (i *InstanceServiceHandler) AttachVPC2(ctx context.Context, instanceID string, vpc2Req *AttachVPC2Req) error {
621 uri := fmt.Sprintf("%s/%s/vpc2/attach", instancePath, instanceID)
622
623 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, vpc2Req)
624 if err != nil {
625 return err
626 }
627
628 _, err = i.client.DoWithContext(ctx, req, nil)
629 return err
630 }
631
632 // DetachVPC2 from an instance.
633 //
634 // Deprecated: VPC2 is no longer supported
635 func (i *InstanceServiceHandler) DetachVPC2(ctx context.Context, instanceID, vpcID string) error {
636 uri := fmt.Sprintf("%s/%s/vpc2/detach", instancePath, instanceID)
637 body := RequestBody{"vpc_id": vpcID}
638
639 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
640 if err != nil {
641 return err
642 }
643
644 _, err = i.client.DoWithContext(ctx, req, nil)
645 return err
646 }
647
648 // ISOStatus retrieves the current ISO state for a given VPS.
649 // The returned state may be one of: ready | isomounting | isomounted.
650 func (i *InstanceServiceHandler) ISOStatus(ctx context.Context, instanceID string) (*Iso, *http.Response, error) {
651 uri := fmt.Sprintf("%s/%s/iso", instancePath, instanceID)
652 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
653 if err != nil {
654 return nil, nil, err
655 }
656
657 iso := new(isoStatusBase)
658 resp, err := i.client.DoWithContext(ctx, req, iso)
659 if err != nil {
660 return nil, resp, err
661 }
662 return iso.IsoStatus, resp, nil
663 }
664
665 // AttachISO will attach an ISO to the given instance and reboot it
666 func (i *InstanceServiceHandler) AttachISO(ctx context.Context, instanceID, isoID string) (*http.Response, error) {
667 uri := fmt.Sprintf("%s/%s/iso/attach", instancePath, instanceID)
668 body := RequestBody{"iso_id": isoID}
669
670 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
671 if err != nil {
672 return nil, err
673 }
674
675 return i.client.DoWithContext(ctx, req, nil)
676 }
677
678 // DetachISO will detach the currently mounted ISO and reboot the instance.
679 func (i *InstanceServiceHandler) DetachISO(ctx context.Context, instanceID string) (*http.Response, error) {
680 uri := fmt.Sprintf("%s/%s/iso/detach", instancePath, instanceID)
681
682 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, nil)
683 if err != nil {
684 return nil, err
685 }
686
687 return i.client.DoWithContext(ctx, req, nil)
688 }
689
690 // GetBackupSchedule retrieves the backup schedule for a given instance - all time values are in UTC
691 func (i *InstanceServiceHandler) GetBackupSchedule(ctx context.Context, instanceID string) (*BackupSchedule, *http.Response, error) {
692 uri := fmt.Sprintf("%s/%s/backup-schedule", instancePath, instanceID)
693 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
694 if err != nil {
695 return nil, nil, err
696 }
697
698 backup := new(backupScheduleBase)
699 resp, err := i.client.DoWithContext(ctx, req, backup)
700 if err != nil {
701 return nil, resp, err
702 }
703
704 return backup.BackupSchedule, resp, nil
705 }
706
707 // SetBackupSchedule sets the backup schedule for a given instance - all time values are in UTC.
708 func (i *InstanceServiceHandler) SetBackupSchedule(ctx context.Context, instanceID string, backup *BackupScheduleReq) (*http.Response, error) { //nolint:lll
709 uri := fmt.Sprintf("%s/%s/backup-schedule", instancePath, instanceID)
710 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, backup)
711 if err != nil {
712 return nil, err
713 }
714
715 return i.client.DoWithContext(ctx, req, nil)
716 }
717
718 // CreateIPv4 an additional IPv4 address for given instance.
719 func (i *InstanceServiceHandler) CreateIPv4(ctx context.Context, instanceID string, reboot *bool) (*IPv4, *http.Response, error) {
720 uri := fmt.Sprintf("%s/%s/ipv4", instancePath, instanceID)
721
722 body := RequestBody{"reboot": reboot}
723
724 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
725 if err != nil {
726 return nil, nil, err
727 }
728
729 ip := new(ipv4Base)
730 resp, err := i.client.DoWithContext(ctx, req, ip)
731 if err != nil {
732 return nil, resp, err
733 }
734
735 return ip.IPv4, resp, nil
736 }
737
738 // ListIPv4 addresses that are currently assigned to a given instance.
739 func (i *InstanceServiceHandler) ListIPv4(ctx context.Context, instanceID string, options *ListOptions) ([]IPv4, *Meta, *http.Response, error) { //nolint:lll,dupl
740 uri := fmt.Sprintf("%s/%s/ipv4", instancePath, instanceID)
741 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
742 if err != nil {
743 return nil, nil, nil, err
744 }
745
746 newValues, err := query.Values(options)
747 if err != nil {
748 return nil, nil, nil, err
749 }
750
751 req.URL.RawQuery = newValues.Encode()
752 ips := new(ipBase)
753 resp, err := i.client.DoWithContext(ctx, req, ips)
754 if err != nil {
755 return nil, nil, resp, err
756 }
757
758 return ips.IPv4s, ips.Meta, resp, nil
759 }
760
761 // DeleteIPv4 address from a given instance.
762 func (i *InstanceServiceHandler) DeleteIPv4(ctx context.Context, instanceID, ip string) error {
763 uri := fmt.Sprintf("%s/%s/ipv4/%s", instancePath, instanceID, ip)
764 req, err := i.client.NewRequest(ctx, http.MethodDelete, uri, nil)
765 if err != nil {
766 return err
767 }
768
769 _, err = i.client.DoWithContext(ctx, req, nil)
770 return err
771 }
772
773 // ListIPv6 addresses that are currently assigned to a given instance.
774 func (i *InstanceServiceHandler) ListIPv6(ctx context.Context, instanceID string, options *ListOptions) ([]IPv6, *Meta, *http.Response, error) { //nolint:lll,dupl
775 uri := fmt.Sprintf("%s/%s/ipv6", instancePath, instanceID)
776 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
777 if err != nil {
778 return nil, nil, nil, err
779 }
780
781 newValues, err := query.Values(options)
782 if err != nil {
783 return nil, nil, nil, err
784 }
785
786 req.URL.RawQuery = newValues.Encode()
787 ips := new(ipBase)
788 resp, err := i.client.DoWithContext(ctx, req, ips)
789 if err != nil {
790 return nil, nil, resp, err
791 }
792
793 return ips.IPv6s, ips.Meta, resp, nil
794 }
795
796 // CreateReverseIPv6 for a given instance.
797 func (i *InstanceServiceHandler) CreateReverseIPv6(ctx context.Context, instanceID string, reverseReq *ReverseIP) error {
798 uri := fmt.Sprintf("%s/%s/ipv6/reverse", instancePath, instanceID)
799 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reverseReq)
800 if err != nil {
801 return err
802 }
803 _, err = i.client.DoWithContext(ctx, req, nil)
804 return err
805 }
806
807 // ListReverseIPv6 currently assigned to a given instance.
808 func (i *InstanceServiceHandler) ListReverseIPv6(ctx context.Context, instanceID string) ([]ReverseIP, *http.Response, error) {
809 uri := fmt.Sprintf("%s/%s/ipv6/reverse", instancePath, instanceID)
810 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
811 if err != nil {
812 return nil, nil, err
813 }
814
815 reverse := new(reverseIPv6sBase)
816 resp, err := i.client.DoWithContext(ctx, req, reverse)
817 if err != nil {
818 return nil, resp, err
819 }
820
821 return reverse.ReverseIPv6s, resp, nil
822 }
823
824 // DeleteReverseIPv6 a given reverse IPv6.
825 func (i *InstanceServiceHandler) DeleteReverseIPv6(ctx context.Context, instanceID, ip string) error {
826 uri := fmt.Sprintf("%s/%s/ipv6/reverse/%s", instancePath, instanceID, ip)
827 req, err := i.client.NewRequest(ctx, http.MethodDelete, uri, nil)
828 if err != nil {
829 return err
830 }
831 _, err = i.client.DoWithContext(ctx, req, nil)
832 return err
833 }
834
835 // CreateReverseIPv4 for a given IP on a given instance.
836 func (i *InstanceServiceHandler) CreateReverseIPv4(ctx context.Context, instanceID string, reverseReq *ReverseIP) error {
837 uri := fmt.Sprintf("%s/%s/ipv4/reverse", instancePath, instanceID)
838 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reverseReq)
839 if err != nil {
840 return err
841 }
842 _, err = i.client.DoWithContext(ctx, req, nil)
843 return err
844 }
845
846 // DefaultReverseIPv4 will set the IPs reverse setting back to the original one supplied by Vultr.
847 func (i *InstanceServiceHandler) DefaultReverseIPv4(ctx context.Context, instanceID, ip string) error {
848 uri := fmt.Sprintf("%s/%s/ipv4/reverse/default", instancePath, instanceID)
849 reqBody := RequestBody{"ip": ip}
850
851 req, err := i.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
852 if err != nil {
853 return err
854 }
855 _, err = i.client.DoWithContext(ctx, req, nil)
856 return err
857 }
858
859 // GetUserData from given instance. The userdata returned will be in base64 encoding.
860 func (i *InstanceServiceHandler) GetUserData(ctx context.Context, instanceID string) (*UserData, *http.Response, error) {
861 uri := fmt.Sprintf("%s/%s/user-data", instancePath, instanceID)
862 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
863 if err != nil {
864 return nil, nil, err
865 }
866
867 userData := new(userDataBase)
868 resp, err := i.client.DoWithContext(ctx, req, userData)
869 if err != nil {
870 return nil, resp, err
871 }
872
873 return userData.UserData, resp, nil
874 }
875
876 // GetUpgrades that are available for a given instance.
877 func (i *InstanceServiceHandler) GetUpgrades(ctx context.Context, instanceID string) (*Upgrades, *http.Response, error) {
878 uri := fmt.Sprintf("%s/%s/upgrades", instancePath, instanceID)
879 req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
880 if err != nil {
881 return nil, nil, err
882 }
883
884 upgrades := new(upgradeBase)
885 resp, err := i.client.DoWithContext(ctx, req, upgrades)
886 if err != nil {
887 return nil, resp, err
888 }
889
890 return upgrades.Upgrades, resp, nil
891 }
892