package govultr import ( "context" "fmt" "net/http" "github.com/google/go-querystring/query" ) const ripPath = "/v2/reserved-ips" // ReservedIPService is the interface to interact with the reserved IP endpoints on the Vultr API // Link : https://www.vultr.com/api/#tag/reserved-ip type ReservedIPService interface { Create(ctx context.Context, ripCreate *ReservedIPReq) (*ReservedIP, error) Update(ctx context.Context, id string, ripUpdate *ReservedIPUpdateReq) (*ReservedIP, error) Get(ctx context.Context, id string) (*ReservedIP, error) Delete(ctx context.Context, id string) error List(ctx context.Context, options *ListOptions) ([]ReservedIP, *Meta, error) Convert(ctx context.Context, ripConvert *ReservedIPConvertReq) (*ReservedIP, error) Attach(ctx context.Context, id, instance string) error Detach(ctx context.Context, id string) error } // ReservedIPServiceHandler handles interaction with the reserved IP methods for the Vultr API type ReservedIPServiceHandler struct { client *Client } // ReservedIP represents an reserved IP on Vultr type ReservedIP struct { ID string `json:"id"` Region string `json:"region"` IPType string `json:"ip_type"` Subnet string `json:"subnet"` SubnetSize int `json:"subnet_size"` Label string `json:"label"` InstanceID string `json:"instance_id"` } // ReservedIPReq represents the parameters for creating a new Reserved IP on Vultr type ReservedIPReq struct { Region string `json:"region,omitempty"` IPType string `json:"ip_type,omitempty"` IPAddress string `json:"ip_address,omitempty"` Label string `json:"label,omitempty"` InstanceID string `json:"instance_id,omitempty"` } // ReservedIPUpdateReq represents the parameters for updating a Reserved IP on Vultr type ReservedIPUpdateReq struct { Label *string `json:"label"` } type reservedIPsBase struct { ReservedIPs []ReservedIP `json:"reserved_ips"` Meta *Meta `json:"meta"` } type reservedIPBase struct { ReservedIP *ReservedIP `json:"reserved_ip"` } // ReservedIPConvertReq is the struct used for create and update calls. type ReservedIPConvertReq struct { IPAddress string `json:"ip_address,omitempty"` Label string `json:"label,omitempty"` } // Create adds the specified reserved IP to your Vultr account func (r *ReservedIPServiceHandler) Create(ctx context.Context, ripCreate *ReservedIPReq) (*ReservedIP, error) { req, err := r.client.NewRequest(ctx, http.MethodPost, ripPath, ripCreate) if err != nil { return nil, err } rip := new(reservedIPBase) if err = r.client.DoWithContext(ctx, req, rip); err != nil { return nil, err } return rip.ReservedIP, nil } // Update updates label on the Reserved IP func (r *ReservedIPServiceHandler) Update(ctx context.Context, id string, ripUpdate *ReservedIPUpdateReq) (*ReservedIP, error) { uri := fmt.Sprintf("%s/%s", ripPath, id) req, err := r.client.NewRequest(ctx, http.MethodPatch, uri, ripUpdate) if err != nil { return nil, err } rip := new(reservedIPBase) if err = r.client.DoWithContext(ctx, req, rip); err != nil { return nil, err } return rip.ReservedIP, nil } // Get gets the reserved IP associated with provided ID func (r *ReservedIPServiceHandler) Get(ctx context.Context, id string) (*ReservedIP, error) { uri := fmt.Sprintf("%s/%s", ripPath, id) req, err := r.client.NewRequest(ctx, http.MethodGet, uri, nil) if err != nil { return nil, err } rip := new(reservedIPBase) if err = r.client.DoWithContext(ctx, req, rip); err != nil { return nil, err } return rip.ReservedIP, nil } // Delete removes the specified reserved IP from your Vultr account func (r *ReservedIPServiceHandler) Delete(ctx context.Context, id string) error { uri := fmt.Sprintf("%s/%s", ripPath, id) req, err := r.client.NewRequest(ctx, http.MethodDelete, uri, nil) if err != nil { return err } return r.client.DoWithContext(ctx, req, nil) } // List lists all the reserved IPs associated with your Vultr account func (r *ReservedIPServiceHandler) List(ctx context.Context, options *ListOptions) ([]ReservedIP, *Meta, error) { req, err := r.client.NewRequest(ctx, http.MethodGet, ripPath, nil) if err != nil { return nil, nil, err } newValues, err := query.Values(options) if err != nil { return nil, nil, err } req.URL.RawQuery = newValues.Encode() ips := new(reservedIPsBase) if err = r.client.DoWithContext(ctx, req, ips); err != nil { return nil, nil, err } return ips.ReservedIPs, ips.Meta, nil } // Convert an existing IP on a subscription to a reserved IP. func (r *ReservedIPServiceHandler) Convert(ctx context.Context, ripConvert *ReservedIPConvertReq) (*ReservedIP, error) { uri := fmt.Sprintf("%s/convert", ripPath) req, err := r.client.NewRequest(ctx, http.MethodPost, uri, ripConvert) if err != nil { return nil, err } rip := new(reservedIPBase) if err = r.client.DoWithContext(ctx, req, rip); err != nil { return nil, err } return rip.ReservedIP, nil } // Attach a reserved IP to an existing subscription func (r *ReservedIPServiceHandler) Attach(ctx context.Context, id, instance string) error { uri := fmt.Sprintf("%s/%s/attach", ripPath, id) reqBody := RequestBody{"instance_id": instance} req, err := r.client.NewRequest(ctx, http.MethodPost, uri, reqBody) if err != nil { return err } return r.client.DoWithContext(ctx, req, nil) } // Detach a reserved IP from an existing subscription. func (r *ReservedIPServiceHandler) Detach(ctx context.Context, id string) error { uri := fmt.Sprintf("%s/%s/detach", ripPath, id) req, err := r.client.NewRequest(ctx, http.MethodPost, uri, nil) if err != nil { return err } return r.client.DoWithContext(ctx, req, nil) }