bare_metal_server.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 bmPath = "/v2/bare-metals"
12
13 // BareMetalServerService is the interface to interact with the Bare Metal endpoints on the Vultr API
14 // Link : https://www.vultr.com/api/#tag/baremetal
15 type BareMetalServerService interface {
16 Create(ctx context.Context, bmCreate *BareMetalCreate) (*BareMetalServer, *http.Response, error)
17 Get(ctx context.Context, serverID string) (*BareMetalServer, *http.Response, error)
18 Update(ctx context.Context, serverID string, bmReq *BareMetalUpdate) (*BareMetalServer, *http.Response, error)
19 Delete(ctx context.Context, serverID string) error
20 List(ctx context.Context, options *ListOptions) ([]BareMetalServer, *Meta, *http.Response, error)
21
22 GetBandwidth(ctx context.Context, serverID string) (*Bandwidth, *http.Response, error)
23 GetUserData(ctx context.Context, serverID string) (*UserData, *http.Response, error)
24 GetVNCUrl(ctx context.Context, serverID string) (*VNCUrl, *http.Response, error)
25
26 ListIPv4s(ctx context.Context, serverID string, options *ListOptions) ([]IPv4, *Meta, *http.Response, error)
27 ListIPv6s(ctx context.Context, serverID string, options *ListOptions) ([]IPv6, *Meta, *http.Response, error)
28
29 Halt(ctx context.Context, serverID string) error
30 Reboot(ctx context.Context, serverID string) error
31 Start(ctx context.Context, serverID string) error
32 Reinstall(ctx context.Context, serverID string) (*BareMetalServer, *http.Response, error)
33
34 MassStart(ctx context.Context, serverList []string) error
35 MassHalt(ctx context.Context, serverList []string) error
36 MassReboot(ctx context.Context, serverList []string) error
37
38 GetUpgrades(ctx context.Context, serverID string) (*Upgrades, *http.Response, error)
39
40 ListVPCInfo(ctx context.Context, serverID string) ([]VPCInfo, *http.Response, error)
41 AttachVPC(ctx context.Context, serverID, vpcID string) error
42 DetachVPC(ctx context.Context, serverID, vpcID string) error
43
44 // Deprecated: VPC2 is no longer supported
45 ListVPC2Info(ctx context.Context, serverID string) ([]VPC2Info, *http.Response, error)
46
47 // Deprecated: VPC2 is no longer supported
48 AttachVPC2(ctx context.Context, serverID string, vpc2Req *AttachVPC2Req) error
49
50 // Deprecated: VPC2 is no longer supported
51 DetachVPC2(ctx context.Context, serverID, vpcID string) error
52 }
53
54 // BareMetalServerServiceHandler handles interaction with the Bare Metal methods for the Vultr API
55 type BareMetalServerServiceHandler struct {
56 client *Client
57 }
58
59 // BareMetalServer represents a Bare Metal server on Vultr
60 type BareMetalServer struct {
61 ID string `json:"id"`
62 Os string `json:"os"`
63 RAM string `json:"ram"`
64 Disk string `json:"disk"`
65 MainIP string `json:"main_ip"`
66 CPUCount int `json:"cpu_count"`
67 Region string `json:"region"`
68 DefaultPassword string `json:"default_password"`
69 DateCreated string `json:"date_created"`
70 Status string `json:"status"`
71 NetmaskV4 string `json:"netmask_v4"`
72 GatewayV4 string `json:"gateway_v4"`
73 Plan string `json:"plan"`
74 V6Network string `json:"v6_network"`
75 V6MainIP string `json:"v6_main_ip"`
76 V6NetworkSize int `json:"v6_network_size"`
77 MacAddress int `json:"mac_address"`
78 Label string `json:"label"`
79 OsID int `json:"os_id"`
80 AppID int `json:"app_id"`
81 ImageID string `json:"image_id"`
82 SnapshotID string `json:"snapshot_id"`
83 Features []string `json:"features"`
84 Tags []string `json:"tags"`
85 UserScheme string `json:"user_scheme"`
86 }
87
88 // BareMetalCreate represents the optional parameters that can be set when creating a Bare Metal server
89 type BareMetalCreate struct {
90 Region string `json:"region"`
91 Plan string `json:"plan"`
92 OsID int `json:"os_id,omitempty"`
93 StartupScriptID string `json:"script_id,omitempty"`
94 SnapshotID string `json:"snapshot_id,omitempty"`
95 EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
96 Label string `json:"label,omitempty"`
97 SSHKeyIDs []string `json:"sshkey_id,omitempty"`
98 AppID int `json:"app_id,omitempty"`
99 ImageID string `json:"image_id,omitempty"`
100 UserData string `json:"user_data,omitempty"`
101 ActivationEmail *bool `json:"activation_email,omitempty"`
102 Hostname string `json:"hostname,omitempty"`
103 MdiskMode string `json:"mdisk_mode,omitempty"`
104 ReservedIPv4 string `json:"reserved_ipv4,omitempty"`
105 PersistentPxe *bool `json:"persistent_pxe,omitempty"`
106 IPXEChainURL string `json:"ipxe_chain_url,omitempty"`
107 Tags []string `json:"tags,omitempty"`
108 UserScheme string `json:"user_scheme,omitempty"`
109 AppVariables map[string]string `json:"app_variables,omitempty"`
110
111 // Deprecated: VPC2 is no longer supported
112 AttachVPC2 []string `json:"attach_vpc2,omitempty"`
113
114 // Deprecated: VPC2 is no longer supported
115 DetachVPC2 []string `json:"detach_vpc2,omitempty"`
116
117 // Deprecated: VPC2 is no longer supported
118 EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
119 }
120
121 // BareMetalUpdate represents the optional parameters that can be set when updating a Bare Metal server
122 type BareMetalUpdate struct {
123 OsID int `json:"os_id,omitempty"`
124 EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
125 Label string `json:"label,omitempty"`
126 AppID int `json:"app_id,omitempty"`
127 ImageID string `json:"image_id,omitempty"`
128 UserData string `json:"user_data,omitempty"`
129 IPXEChainURL string `json:"ipxe_chain_url,omitempty"`
130 MdiskMode string `json:"mdisk_mode,omitempty"`
131 Tags []string `json:"tags,omitempty"`
132 UserScheme string `json:"user_scheme,omitempty"`
133
134 // Deprecated: VPC2 is no longer supported
135 AttachVPC2 []string `json:"attach_vpc2,omitempty"`
136
137 // Deprecated: VPC2 is no longer supported
138 DetachVPC2 []string `json:"detach_vpc2,omitempty"`
139
140 // Deprecated: VPC2 is no longer supported
141 EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
142 }
143
144 // BareMetalServerBandwidth represents bandwidth information for a Bare Metal server
145 type BareMetalServerBandwidth struct {
146 IncomingBytes int `json:"incoming_bytes"`
147 OutgoingBytes int `json:"outgoing_bytes"`
148 }
149
150 type bareMetalsBase struct {
151 BareMetals []BareMetalServer `json:"bare_metals"`
152 Meta *Meta `json:"meta"`
153 }
154
155 type bareMetalBase struct {
156 BareMetal *BareMetalServer `json:"bare_metal"`
157 }
158
159 // BMBareMetalBase represents the base struct for a Bare Metal server
160 type BMBareMetalBase struct {
161 BareMetalBandwidth map[string]BareMetalServerBandwidth `json:"bandwidth"`
162 }
163
164 type vncBase struct {
165 VNCUrl *VNCUrl `json:"vnc"`
166 }
167
168 // VNCUrl contains the URL for a given Bare Metals VNC
169 type VNCUrl struct {
170 URL string `json:"url"`
171 }
172
173 // Create a new Bare Metal server.
174 func (b *BareMetalServerServiceHandler) Create(ctx context.Context, bmCreate *BareMetalCreate) (*BareMetalServer, *http.Response, error) {
175 req, err := b.client.NewRequest(ctx, http.MethodPost, bmPath, bmCreate)
176 if err != nil {
177 return nil, nil, err
178 }
179
180 bm := new(bareMetalBase)
181 resp, err := b.client.DoWithContext(ctx, req, bm)
182 if err != nil {
183 return nil, resp, err
184 }
185
186 return bm.BareMetal, resp, nil
187 }
188
189 // Get information for a Bare Metal instance.
190 func (b *BareMetalServerServiceHandler) Get(ctx context.Context, serverID string) (*BareMetalServer, *http.Response, error) {
191 uri := fmt.Sprintf("%s/%s", bmPath, serverID)
192 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
193 if err != nil {
194 return nil, nil, err
195 }
196
197 bms := new(bareMetalBase)
198 resp, err := b.client.DoWithContext(ctx, req, bms)
199 if err != nil {
200 return nil, resp, err
201 }
202
203 return bms.BareMetal, resp, nil
204 }
205
206 // Update a Bare Metal server
207 func (b *BareMetalServerServiceHandler) Update(ctx context.Context, serverID string, bmReq *BareMetalUpdate) (*BareMetalServer, *http.Response, error) { //nolint:lll
208 uri := fmt.Sprintf("%s/%s", bmPath, serverID)
209 req, err := b.client.NewRequest(ctx, http.MethodPatch, uri, bmReq)
210 if err != nil {
211 return nil, nil, err
212 }
213
214 bms := new(bareMetalBase)
215 resp, err := b.client.DoWithContext(ctx, req, bms)
216 if err != nil {
217 return nil, resp, err
218 }
219
220 return bms.BareMetal, resp, nil
221 }
222
223 // Delete a Bare Metal server.
224 func (b *BareMetalServerServiceHandler) Delete(ctx context.Context, serverID string) error {
225 uri := fmt.Sprintf("%s/%s", bmPath, serverID)
226 req, err := b.client.NewRequest(ctx, http.MethodDelete, uri, nil)
227 if err != nil {
228 return nil
229 }
230 _, err = b.client.DoWithContext(ctx, req, nil)
231 return err
232 }
233
234 // List all Bare Metal instances in your account.
235 func (b *BareMetalServerServiceHandler) List(ctx context.Context, options *ListOptions) ([]BareMetalServer, *Meta, *http.Response, error) { //nolint:dupl,lll
236 req, err := b.client.NewRequest(ctx, http.MethodGet, bmPath, nil)
237 if err != nil {
238 return nil, nil, nil, err
239 }
240
241 newValues, err := query.Values(options)
242 if err != nil {
243 return nil, nil, nil, err
244 }
245
246 req.URL.RawQuery = newValues.Encode()
247
248 bms := new(bareMetalsBase)
249 resp, err := b.client.DoWithContext(ctx, req, bms)
250 if err != nil {
251 return nil, nil, resp, err
252 }
253
254 return bms.BareMetals, bms.Meta, resp, nil
255 }
256
257 // GetBandwidth used by a Bare Metal server.
258 func (b *BareMetalServerServiceHandler) GetBandwidth(ctx context.Context, serverID string) (*Bandwidth, *http.Response, error) {
259 uri := fmt.Sprintf("%s/%s/bandwidth", bmPath, serverID)
260 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
261 if err != nil {
262 return nil, nil, err
263 }
264
265 bms := new(Bandwidth)
266 resp, err := b.client.DoWithContext(ctx, req, &bms)
267 if err != nil {
268 return nil, resp, err
269 }
270
271 return bms, resp, nil
272 }
273
274 // GetUserData for a Bare Metal server. The userdata returned will be in base64 encoding.
275 func (b *BareMetalServerServiceHandler) GetUserData(ctx context.Context, serverID string) (*UserData, *http.Response, error) {
276 uri := fmt.Sprintf("%s/%s/user-data", bmPath, serverID)
277 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
278 if err != nil {
279 return nil, nil, err
280 }
281
282 userData := new(userDataBase)
283 resp, err := b.client.DoWithContext(ctx, req, userData)
284 if err != nil {
285 return nil, nil, err
286 }
287
288 return userData.UserData, resp, nil
289 }
290
291 // GetVNCUrl gets the vnc url for a given Bare Metal server.
292 func (b *BareMetalServerServiceHandler) GetVNCUrl(ctx context.Context, serverID string) (*VNCUrl, *http.Response, error) {
293 uri := fmt.Sprintf("%s/%s/vnc", bmPath, serverID)
294 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
295 if err != nil {
296 return nil, nil, err
297 }
298
299 vnc := new(vncBase)
300 resp, err := b.client.DoWithContext(ctx, req, vnc)
301 if err != nil {
302 return nil, resp, err
303 }
304
305 return vnc.VNCUrl, resp, nil
306 }
307
308 // ListIPv4s information of a Bare Metal server.
309 // IP information is only available for Bare Metal servers in the "active" state.
310 func (b *BareMetalServerServiceHandler) ListIPv4s(ctx context.Context, serverID string, options *ListOptions) ([]IPv4, *Meta, *http.Response, error) { //nolint:lll,dupl
311 uri := fmt.Sprintf("%s/%s/ipv4", bmPath, serverID)
312 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
313 if err != nil {
314 return nil, nil, nil, err
315 }
316
317 newValues, err := query.Values(options)
318 if err != nil {
319 return nil, nil, nil, err
320 }
321
322 req.URL.RawQuery = newValues.Encode()
323
324 ipv4 := new(ipBase)
325 resp, err := b.client.DoWithContext(ctx, req, ipv4)
326 if err != nil {
327 return nil, nil, resp, err
328 }
329
330 return ipv4.IPv4s, ipv4.Meta, resp, nil
331 }
332
333 // ListIPv6s information of a Bare Metal server.
334 // IP information is only available for Bare Metal servers in the "active" state.
335 // If the Bare Metal server does not have IPv6 enabled, then an empty array is returned.
336 func (b *BareMetalServerServiceHandler) ListIPv6s(ctx context.Context, serverID string, options *ListOptions) ([]IPv6, *Meta, *http.Response, error) { //nolint:lll,dupl
337 uri := fmt.Sprintf("%s/%s/ipv6", bmPath, serverID)
338 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
339 if err != nil {
340 return nil, nil, nil, err
341 }
342
343 newValues, err := query.Values(options)
344 if err != nil {
345 return nil, nil, nil, err
346 }
347
348 req.URL.RawQuery = newValues.Encode()
349
350 ipv6 := new(ipBase)
351 resp, err := b.client.DoWithContext(ctx, req, ipv6)
352 if err != nil {
353 return nil, nil, resp, err
354 }
355
356 return ipv6.IPv6s, ipv6.Meta, resp, nil
357 }
358
359 // Halt a Bare Metal server.
360 // This is a hard power off, meaning that the power to the machine is severed.
361 // The data on the machine will not be modified, and you will still be billed for the machine.
362 func (b *BareMetalServerServiceHandler) Halt(ctx context.Context, serverID string) error {
363 uri := fmt.Sprintf("%s/%s/halt", bmPath, serverID)
364 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, nil)
365 if err != nil {
366 return err
367 }
368
369 _, err = b.client.DoWithContext(ctx, req, nil)
370 return err
371 }
372
373 // Reboot a Bare Metal server. This is a hard reboot, which means that the server is powered off, then back on.
374 func (b *BareMetalServerServiceHandler) Reboot(ctx context.Context, serverID string) error {
375 uri := fmt.Sprintf("%s/%s/reboot", bmPath, serverID)
376
377 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, nil)
378 if err != nil {
379 return err
380 }
381
382 _, err = b.client.DoWithContext(ctx, req, nil)
383 return err
384 }
385
386 // Start a Bare Metal server.
387 func (b *BareMetalServerServiceHandler) Start(ctx context.Context, serverID string) error {
388 uri := fmt.Sprintf("%s/%s/start", bmPath, serverID)
389 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, nil)
390 if err != nil {
391 return err
392 }
393
394 _, err = b.client.DoWithContext(ctx, req, nil)
395 return err
396 }
397
398 // Reinstall the operating system on a Bare Metal server.
399 // All data will be permanently lost, but the IP address will remain the same.
400 func (b *BareMetalServerServiceHandler) Reinstall(ctx context.Context, serverID string) (*BareMetalServer, *http.Response, error) {
401 uri := fmt.Sprintf("%s/%s/reinstall", bmPath, serverID)
402 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, nil)
403 if err != nil {
404 return nil, nil, err
405 }
406
407 bms := new(bareMetalBase)
408 resp, err := b.client.DoWithContext(ctx, req, bms)
409 if err != nil {
410 return nil, resp, err
411 }
412
413 return bms.BareMetal, resp, nil
414 }
415
416 // MassStart will start a list of Bare Metal servers the machine is already running, it will be restarted.
417 func (b *BareMetalServerServiceHandler) MassStart(ctx context.Context, serverList []string) error {
418 uri := fmt.Sprintf("%s/start", bmPath)
419
420 reqBody := RequestBody{"baremetal_ids": serverList}
421 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
422 if err != nil {
423 return err
424 }
425 _, err = b.client.DoWithContext(ctx, req, nil)
426 return err
427 }
428
429 // MassHalt a list of Bare Metal servers.
430 func (b *BareMetalServerServiceHandler) MassHalt(ctx context.Context, serverList []string) error {
431 uri := fmt.Sprintf("%s/halt", bmPath)
432
433 reqBody := RequestBody{"baremetal_ids": serverList}
434 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
435 if err != nil {
436 return err
437 }
438 _, err = b.client.DoWithContext(ctx, req, nil)
439 return err
440 }
441
442 // MassReboot a list of Bare Metal servers.
443 func (b *BareMetalServerServiceHandler) MassReboot(ctx context.Context, serverList []string) error {
444 uri := fmt.Sprintf("%s/reboot", bmPath)
445
446 reqBody := RequestBody{"baremetal_ids": serverList}
447 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, reqBody)
448 if err != nil {
449 return err
450 }
451 _, err = b.client.DoWithContext(ctx, req, nil)
452 return err
453 }
454
455 // GetUpgrades that are available for a Bare Metal server.
456 func (b *BareMetalServerServiceHandler) GetUpgrades(ctx context.Context, serverID string) (*Upgrades, *http.Response, error) {
457 uri := fmt.Sprintf("%s/%s/upgrades", bmPath, serverID)
458 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
459 if err != nil {
460 return nil, nil, err
461 }
462
463 upgrades := new(upgradeBase)
464 resp, err := b.client.DoWithContext(ctx, req, upgrades)
465 if err != nil {
466 return nil, resp, err
467 }
468
469 return upgrades.Upgrades, resp, nil
470 }
471
472 // ListVPCInfo will list all currently attached VPC IP information for the
473 // given bare metal server.
474 func (b *BareMetalServerServiceHandler) ListVPCInfo(ctx context.Context, serverID string) ([]VPCInfo, *http.Response, error) {
475 uri := fmt.Sprintf("%s/%s/vpcs", bmPath, serverID)
476 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
477 if err != nil {
478 return nil, nil, err
479 }
480
481 vpcs := new(vpcInfoBase)
482 resp, err := b.client.DoWithContext(ctx, req, vpcs)
483 if err != nil {
484 return nil, resp, err
485 }
486
487 return vpcs.VPCs, resp, nil
488 }
489
490 // AttachVPC serves to attach a VPC to a bare metal server.
491 func (b *BareMetalServerServiceHandler) AttachVPC(ctx context.Context, serverID, vpcID string) error {
492 uri := fmt.Sprintf("%s/%s/vpcs/attach", bmPath, serverID)
493 body := RequestBody{"vpc_id": vpcID}
494
495 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, body)
496 if err != nil {
497 return err
498 }
499
500 _, err = b.client.DoWithContext(ctx, req, nil)
501 return err
502 }
503
504 // DetachVPC will detach a VPC from a bare metal server.
505 func (b *BareMetalServerServiceHandler) DetachVPC(ctx context.Context, serverID, vpcID string) error {
506 uri := fmt.Sprintf("%s/%s/vpcs/detach", bmPath, serverID)
507 body := RequestBody{"vpc_id": vpcID}
508
509 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, body)
510 if err != nil {
511 return err
512 }
513
514 _, err = b.client.DoWithContext(ctx, req, nil)
515 return err
516 }
517
518 // ListVPC2Info currently attached to a Bare Metal server.
519 //
520 // Deprecated: VPC2 is no longer supported
521 func (b *BareMetalServerServiceHandler) ListVPC2Info(ctx context.Context, serverID string) ([]VPC2Info, *http.Response, error) {
522 uri := fmt.Sprintf("%s/%s/vpc2", bmPath, serverID)
523 req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
524 if err != nil {
525 return nil, nil, err
526 }
527
528 vpcs := new(vpc2InfoBase)
529 resp, err := b.client.DoWithContext(ctx, req, vpcs)
530 if err != nil {
531 return nil, resp, err
532 }
533
534 return vpcs.VPCs, resp, nil
535 }
536
537 // AttachVPC2 to a Bare Metal server.
538 //
539 // Deprecated: VPC2 is no longer supported
540 func (b *BareMetalServerServiceHandler) AttachVPC2(ctx context.Context, serverID string, vpc2Req *AttachVPC2Req) error {
541 uri := fmt.Sprintf("%s/%s/vpc2/attach", bmPath, serverID)
542
543 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, vpc2Req)
544 if err != nil {
545 return err
546 }
547
548 _, err = b.client.DoWithContext(ctx, req, nil)
549 return err
550 }
551
552 // DetachVPC2 from a Bare Metal server.
553 //
554 // Deprecated: VPC2 is no longer supported
555 func (b *BareMetalServerServiceHandler) DetachVPC2(ctx context.Context, serverID, vpcID string) error {
556 uri := fmt.Sprintf("%s/%s/vpc2/detach", bmPath, serverID)
557 body := RequestBody{"vpc_id": vpcID}
558
559 req, err := b.client.NewRequest(ctx, http.MethodPost, uri, body)
560 if err != nil {
561 return err
562 }
563
564 _, err = b.client.DoWithContext(ctx, req, nil)
565 return err
566 }
567