1package godo 2 3import ( 4 "context" 5 "fmt" 6 "net/http" 7) 8 9const floatingBasePath = "v2/floating_ips" 10 11// FloatingIPsService is an interface for interfacing with the floating IPs 12// endpoints of the Digital Ocean API. 13// See: https://docs.digitalocean.com/reference/api/api-reference/#tag/Floating-IPs 14type FloatingIPsService interface { 15 List(context.Context, *ListOptions) ([]FloatingIP, *Response, error) 16 Get(context.Context, string) (*FloatingIP, *Response, error) 17 Create(context.Context, *FloatingIPCreateRequest) (*FloatingIP, *Response, error) 18 Delete(context.Context, string) (*Response, error) 19} 20 21// FloatingIPsServiceOp handles communication with the floating IPs related methods of the 22// DigitalOcean API. 23type FloatingIPsServiceOp struct { 24 client *Client 25} 26 27var _ FloatingIPsService = &FloatingIPsServiceOp{} 28 29// FloatingIP represents a Digital Ocean floating IP. 30type FloatingIP struct { 31 Region *Region `json:"region"` 32 Droplet *Droplet `json:"droplet"` 33 IP string `json:"ip"` 34} 35 36func (f FloatingIP) String() string { 37 return Stringify(f) 38} 39 40// URN returns the floating IP in a valid DO API URN form. 41func (f FloatingIP) URN() string { 42 return ToURN("FloatingIP", f.IP) 43} 44 45type floatingIPsRoot struct { 46 FloatingIPs []FloatingIP `json:"floating_ips"` 47 Links *Links `json:"links"` 48 Meta *Meta `json:"meta"` 49} 50 51type floatingIPRoot struct { 52 FloatingIP *FloatingIP `json:"floating_ip"` 53 Links *Links `json:"links,omitempty"` 54} 55 56// FloatingIPCreateRequest represents a request to create a floating IP. 57// Specify DropletID to assign the floating IP to a Droplet or Region 58// to reserve it to the region. 59type FloatingIPCreateRequest struct { 60 Region string `json:"region,omitempty"` 61 DropletID int `json:"droplet_id,omitempty"` 62} 63 64// List all floating IPs. 65func (f *FloatingIPsServiceOp) List(ctx context.Context, opt *ListOptions) ([]FloatingIP, *Response, error) { 66 path := floatingBasePath 67 path, err := addOptions(path, opt) 68 if err != nil { 69 return nil, nil, err 70 } 71 72 req, err := f.client.NewRequest(ctx, http.MethodGet, path, nil) 73 if err != nil { 74 return nil, nil, err 75 } 76 77 root := new(floatingIPsRoot) 78 resp, err := f.client.Do(ctx, req, root) 79 if err != nil { 80 return nil, resp, err 81 } 82 if l := root.Links; l != nil { 83 resp.Links = l 84 } 85 if m := root.Meta; m != nil { 86 resp.Meta = m 87 } 88 89 return root.FloatingIPs, resp, err 90} 91 92// Get an individual floating IP. 93func (f *FloatingIPsServiceOp) Get(ctx context.Context, ip string) (*FloatingIP, *Response, error) { 94 path := fmt.Sprintf("%s/%s", floatingBasePath, ip) 95 96 req, err := f.client.NewRequest(ctx, http.MethodGet, path, nil) 97 if err != nil { 98 return nil, nil, err 99 } 100 101 root := new(floatingIPRoot) 102 resp, err := f.client.Do(ctx, req, root) 103 if err != nil { 104 return nil, resp, err 105 } 106 107 return root.FloatingIP, resp, err 108} 109 110// Create a floating IP. If the DropletID field of the request is not empty, 111// the floating IP will also be assigned to the droplet. 112func (f *FloatingIPsServiceOp) Create(ctx context.Context, createRequest *FloatingIPCreateRequest) (*FloatingIP, *Response, error) { 113 path := floatingBasePath 114 115 req, err := f.client.NewRequest(ctx, http.MethodPost, path, createRequest) 116 if err != nil { 117 return nil, nil, err 118 } 119 120 root := new(floatingIPRoot) 121 resp, err := f.client.Do(ctx, req, root) 122 if err != nil { 123 return nil, resp, err 124 } 125 if l := root.Links; l != nil { 126 resp.Links = l 127 } 128 129 return root.FloatingIP, resp, err 130} 131 132// Delete a floating IP. 133func (f *FloatingIPsServiceOp) Delete(ctx context.Context, ip string) (*Response, error) { 134 path := fmt.Sprintf("%s/%s", floatingBasePath, ip) 135 136 req, err := f.client.NewRequest(ctx, http.MethodDelete, path, nil) 137 if err != nil { 138 return nil, err 139 } 140 141 resp, err := f.client.Do(ctx, req, nil) 142 143 return resp, err 144} 145