provider/digitalocean: Bump SDK version of godo for loadbalancer support (#11964)
This commit is contained in:
parent
d29f2d6f6d
commit
f681fbf4f6
|
@ -33,7 +33,7 @@ type actionsRoot struct {
|
|||
}
|
||||
|
||||
type actionRoot struct {
|
||||
Event Action `json:"action"`
|
||||
Event *Action `json:"action"`
|
||||
}
|
||||
|
||||
// Action represents a DigitalOcean Action
|
||||
|
@ -92,7 +92,7 @@ func (s *ActionsServiceOp) Get(id int) (*Action, *Response, error) {
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
func (a Action) String() string {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
// ActionRequest reprents DigitalOcean Action Request
|
||||
type ActionRequest map[string]interface{}
|
||||
|
||||
// DropletActionsService is an interface for interfacing with the droplet actions
|
||||
// DropletActionsService is an interface for interfacing with the Droplet actions
|
||||
// endpoints of the DigitalOcean API
|
||||
// See: https://developers.digitalocean.com/documentation/v2#droplet-actions
|
||||
type DropletActionsService interface {
|
||||
|
@ -43,7 +43,7 @@ type DropletActionsService interface {
|
|||
GetByURI(string) (*Action, *Response, error)
|
||||
}
|
||||
|
||||
// DropletActionsServiceOp handles communication with the droplet action related
|
||||
// DropletActionsServiceOp handles communication with the Droplet action related
|
||||
// methods of the DigitalOcean API.
|
||||
type DropletActionsServiceOp struct {
|
||||
client *Client
|
||||
|
@ -57,7 +57,7 @@ func (s *DropletActionsServiceOp) Shutdown(id int) (*Action, *Response, error) {
|
|||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// Shutdown Droplets by Tag
|
||||
// ShutdownByTag shuts down Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) ShutdownByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "shutdown"}
|
||||
return s.doActionByTag(tag, request)
|
||||
|
@ -69,7 +69,7 @@ func (s *DropletActionsServiceOp) PowerOff(id int) (*Action, *Response, error) {
|
|||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// PowerOff a Droplet by Tag
|
||||
// PowerOffByTag powers off Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) PowerOffByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "power_off"}
|
||||
return s.doActionByTag(tag, request)
|
||||
|
@ -81,7 +81,7 @@ func (s *DropletActionsServiceOp) PowerOn(id int) (*Action, *Response, error) {
|
|||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// PowerOn a Droplet by Tag
|
||||
// PowerOnByTag powers on Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) PowerOnByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "power_on"}
|
||||
return s.doActionByTag(tag, request)
|
||||
|
@ -93,7 +93,7 @@ func (s *DropletActionsServiceOp) PowerCycle(id int) (*Action, *Response, error)
|
|||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// PowerCycle a Droplet by Tag
|
||||
// PowerCycleByTag power cycles Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) PowerCycleByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "power_cycle"}
|
||||
return s.doActionByTag(tag, request)
|
||||
|
@ -146,7 +146,7 @@ func (s *DropletActionsServiceOp) Snapshot(id int, name string) (*Action, *Respo
|
|||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// Snapshot a Droplet by Tag
|
||||
// SnapshotByTag snapshots Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) SnapshotByTag(tag string, name string) (*Action, *Response, error) {
|
||||
requestType := "snapshot"
|
||||
request := &ActionRequest{
|
||||
|
@ -156,79 +156,79 @@ func (s *DropletActionsServiceOp) SnapshotByTag(tag string, name string) (*Actio
|
|||
return s.doActionByTag(tag, request)
|
||||
}
|
||||
|
||||
// EnableBackups enables backups for a droplet.
|
||||
// EnableBackups enables backups for a Droplet.
|
||||
func (s *DropletActionsServiceOp) EnableBackups(id int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "enable_backups"}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// EnableBackups enables backups for a droplet by Tag
|
||||
// EnableBackupsByTag enables backups for Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) EnableBackupsByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "enable_backups"}
|
||||
return s.doActionByTag(tag, request)
|
||||
}
|
||||
|
||||
// DisableBackups disables backups for a droplet.
|
||||
// DisableBackups disables backups for a Droplet.
|
||||
func (s *DropletActionsServiceOp) DisableBackups(id int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "disable_backups"}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// DisableBackups disables backups for a droplet by tag
|
||||
// DisableBackupsByTag disables backups for Droplet matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) DisableBackupsByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "disable_backups"}
|
||||
return s.doActionByTag(tag, request)
|
||||
}
|
||||
|
||||
// PasswordReset resets the password for a droplet.
|
||||
// PasswordReset resets the password for a Droplet.
|
||||
func (s *DropletActionsServiceOp) PasswordReset(id int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "password_reset"}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// RebuildByImageID rebuilds a droplet droplet from an image with a given id.
|
||||
// RebuildByImageID rebuilds a Droplet from an image with a given id.
|
||||
func (s *DropletActionsServiceOp) RebuildByImageID(id, imageID int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "rebuild", "image": imageID}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// RebuildByImageSlug rebuilds a droplet from an image with a given slug.
|
||||
// RebuildByImageSlug rebuilds a Droplet from an Image matched by a given Slug.
|
||||
func (s *DropletActionsServiceOp) RebuildByImageSlug(id int, slug string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "rebuild", "image": slug}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// ChangeKernel changes the kernel for a droplet.
|
||||
// ChangeKernel changes the kernel for a Droplet.
|
||||
func (s *DropletActionsServiceOp) ChangeKernel(id, kernelID int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "change_kernel", "kernel": kernelID}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// EnableIPv6 enables IPv6 for a droplet.
|
||||
// EnableIPv6 enables IPv6 for a Droplet.
|
||||
func (s *DropletActionsServiceOp) EnableIPv6(id int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "enable_ipv6"}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// EnableIPv6 enables IPv6 for a droplet by Tag
|
||||
// EnableIPv6ByTag enables IPv6 for Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) EnableIPv6ByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "enable_ipv6"}
|
||||
return s.doActionByTag(tag, request)
|
||||
}
|
||||
|
||||
// EnablePrivateNetworking enables private networking for a droplet.
|
||||
// EnablePrivateNetworking enables private networking for a Droplet.
|
||||
func (s *DropletActionsServiceOp) EnablePrivateNetworking(id int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "enable_private_networking"}
|
||||
return s.doAction(id, request)
|
||||
}
|
||||
|
||||
// EnablePrivateNetworking enables private networking for a droplet by Tag
|
||||
// EnablePrivateNetworkingByTag enables private networking for Droplets matched by a Tag.
|
||||
func (s *DropletActionsServiceOp) EnablePrivateNetworkingByTag(tag string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "enable_private_networking"}
|
||||
return s.doActionByTag(tag, request)
|
||||
}
|
||||
|
||||
// Upgrade a droplet.
|
||||
// Upgrade a Droplet.
|
||||
func (s *DropletActionsServiceOp) Upgrade(id int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{"type": "upgrade"}
|
||||
return s.doAction(id, request)
|
||||
|
@ -256,7 +256,7 @@ func (s *DropletActionsServiceOp) doAction(id int, request *ActionRequest) (*Act
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
func (s *DropletActionsServiceOp) doActionByTag(tag string, request *ActionRequest) (*Action, *Response, error) {
|
||||
|
@ -281,10 +281,10 @@ func (s *DropletActionsServiceOp) doActionByTag(tag string, request *ActionReque
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
// Get an action for a particular droplet by id.
|
||||
// Get an action for a particular Droplet by id.
|
||||
func (s *DropletActionsServiceOp) Get(dropletID, actionID int) (*Action, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -298,7 +298,7 @@ func (s *DropletActionsServiceOp) Get(dropletID, actionID int) (*Action, *Respon
|
|||
return s.get(path)
|
||||
}
|
||||
|
||||
// GetByURI gets an action for a particular droplet by id.
|
||||
// GetByURI gets an action for a particular Droplet by id.
|
||||
func (s *DropletActionsServiceOp) GetByURI(rawurl string) (*Action, *Response, error) {
|
||||
u, err := url.Parse(rawurl)
|
||||
if err != nil {
|
||||
|
@ -321,7 +321,7 @@ func (s *DropletActionsServiceOp) get(path string) (*Action, *Response, error) {
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ const dropletBasePath = "v2/droplets"
|
|||
|
||||
var errNoNetworks = errors.New("no networks have been defined")
|
||||
|
||||
// DropletsService is an interface for interfacing with the droplet
|
||||
// DropletsService is an interface for interfacing with the Droplet
|
||||
// endpoints of the DigitalOcean API
|
||||
// See: https://developers.digitalocean.com/documentation/v2#droplets
|
||||
type DropletsService interface {
|
||||
|
@ -28,7 +28,7 @@ type DropletsService interface {
|
|||
Neighbors(int) ([]Droplet, *Response, error)
|
||||
}
|
||||
|
||||
// DropletsServiceOp handles communication with the droplet related methods of the
|
||||
// DropletsServiceOp handles communication with the Droplet related methods of the
|
||||
// DigitalOcean API.
|
||||
type DropletsServiceOp struct {
|
||||
client *Client
|
||||
|
@ -38,24 +38,26 @@ var _ DropletsService = &DropletsServiceOp{}
|
|||
|
||||
// Droplet represents a DigitalOcean Droplet
|
||||
type Droplet struct {
|
||||
ID int `json:"id,float64,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Memory int `json:"memory,omitempty"`
|
||||
Vcpus int `json:"vcpus,omitempty"`
|
||||
Disk int `json:"disk,omitempty"`
|
||||
Region *Region `json:"region,omitempty"`
|
||||
Image *Image `json:"image,omitempty"`
|
||||
Size *Size `json:"size,omitempty"`
|
||||
SizeSlug string `json:"size_slug,omitempty"`
|
||||
BackupIDs []int `json:"backup_ids,omitempty"`
|
||||
SnapshotIDs []int `json:"snapshot_ids,omitempty"`
|
||||
Locked bool `json:"locked,bool,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Networks *Networks `json:"networks,omitempty"`
|
||||
Created string `json:"created_at,omitempty"`
|
||||
Kernel *Kernel `json:"kernel,omitempty"`
|
||||
Tags []string `json:"tags,ommitempty"`
|
||||
VolumeIDs []string `json:"volumes"`
|
||||
ID int `json:"id,float64,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Memory int `json:"memory,omitempty"`
|
||||
Vcpus int `json:"vcpus,omitempty"`
|
||||
Disk int `json:"disk,omitempty"`
|
||||
Region *Region `json:"region,omitempty"`
|
||||
Image *Image `json:"image,omitempty"`
|
||||
Size *Size `json:"size,omitempty"`
|
||||
SizeSlug string `json:"size_slug,omitempty"`
|
||||
BackupIDs []int `json:"backup_ids,omitempty"`
|
||||
NextBackupWindow *BackupWindow `json:"next_backup_window,omitempty"`
|
||||
SnapshotIDs []int `json:"snapshot_ids,omitempty"`
|
||||
Features []string `json:"features,omitempty"`
|
||||
Locked bool `json:"locked,bool,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Networks *Networks `json:"networks,omitempty"`
|
||||
Created string `json:"created_at,omitempty"`
|
||||
Kernel *Kernel `json:"kernel,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
VolumeIDs []string `json:"volume_ids"`
|
||||
}
|
||||
|
||||
// PublicIPv4 returns the public IPv4 address for the Droplet.
|
||||
|
@ -110,6 +112,12 @@ type Kernel struct {
|
|||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// BackupWindow object
|
||||
type BackupWindow struct {
|
||||
Start *Timestamp `json:"start,omitempty"`
|
||||
End *Timestamp `json:"end,omitempty"`
|
||||
}
|
||||
|
||||
// Convert Droplet to a string
|
||||
func (d Droplet) String() string {
|
||||
return Stringify(d)
|
||||
|
@ -131,7 +139,7 @@ type kernelsRoot struct {
|
|||
Links *Links `json:"links"`
|
||||
}
|
||||
|
||||
type snapshotsRoot struct {
|
||||
type dropletSnapshotsRoot struct {
|
||||
Snapshots []Image `json:"snapshots,omitempty"`
|
||||
Links *Links `json:"links"`
|
||||
}
|
||||
|
@ -147,6 +155,16 @@ type DropletCreateImage struct {
|
|||
Slug string
|
||||
}
|
||||
|
||||
// MarshalJSON returns either the slug or id of the image. It returns the id
|
||||
// if the slug is empty.
|
||||
func (d DropletCreateImage) MarshalJSON() ([]byte, error) {
|
||||
if d.Slug != "" {
|
||||
return json.Marshal(d.Slug)
|
||||
}
|
||||
|
||||
return json.Marshal(d.ID)
|
||||
}
|
||||
|
||||
// DropletCreateVolume identifies a volume to attach for the create request. It
|
||||
// prefers Name over ID,
|
||||
type DropletCreateVolume struct {
|
||||
|
@ -168,16 +186,6 @@ func (d DropletCreateVolume) MarshalJSON() ([]byte, error) {
|
|||
}{ID: d.ID})
|
||||
}
|
||||
|
||||
// MarshalJSON returns either the slug or id of the image. It returns the id
|
||||
// if the slug is empty.
|
||||
func (d DropletCreateImage) MarshalJSON() ([]byte, error) {
|
||||
if d.Slug != "" {
|
||||
return json.Marshal(d.Slug)
|
||||
}
|
||||
|
||||
return json.Marshal(d.ID)
|
||||
}
|
||||
|
||||
// DropletCreateSSHKey identifies a SSH Key for the create request. It prefers fingerprint over ID.
|
||||
type DropletCreateSSHKey struct {
|
||||
ID int
|
||||
|
@ -194,7 +202,7 @@ func (d DropletCreateSSHKey) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(d.ID)
|
||||
}
|
||||
|
||||
// DropletCreateRequest represents a request to create a droplet.
|
||||
// DropletCreateRequest represents a request to create a Droplet.
|
||||
type DropletCreateRequest struct {
|
||||
Name string `json:"name"`
|
||||
Region string `json:"region"`
|
||||
|
@ -204,11 +212,13 @@ type DropletCreateRequest struct {
|
|||
Backups bool `json:"backups"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
PrivateNetworking bool `json:"private_networking"`
|
||||
Monitoring bool `json:"monitoring"`
|
||||
UserData string `json:"user_data,omitempty"`
|
||||
Volumes []DropletCreateVolume `json:"volumes,omitempty"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// DropletMultiCreateRequest is a request to create multiple droplets.
|
||||
// DropletMultiCreateRequest is a request to create multiple Droplets.
|
||||
type DropletMultiCreateRequest struct {
|
||||
Names []string `json:"names"`
|
||||
Region string `json:"region"`
|
||||
|
@ -218,7 +228,9 @@ type DropletMultiCreateRequest struct {
|
|||
Backups bool `json:"backups"`
|
||||
IPv6 bool `json:"ipv6"`
|
||||
PrivateNetworking bool `json:"private_networking"`
|
||||
Monitoring bool `json:"monitoring"`
|
||||
UserData string `json:"user_data,omitempty"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
func (d DropletCreateRequest) String() string {
|
||||
|
@ -229,13 +241,13 @@ func (d DropletMultiCreateRequest) String() string {
|
|||
return Stringify(d)
|
||||
}
|
||||
|
||||
// Networks represents the droplet's networks
|
||||
// Networks represents the Droplet's Networks.
|
||||
type Networks struct {
|
||||
V4 []NetworkV4 `json:"v4,omitempty"`
|
||||
V6 []NetworkV6 `json:"v6,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkV4 represents a DigitalOcean IPv4 Network
|
||||
// NetworkV4 represents a DigitalOcean IPv4 Network.
|
||||
type NetworkV4 struct {
|
||||
IPAddress string `json:"ip_address,omitempty"`
|
||||
Netmask string `json:"netmask,omitempty"`
|
||||
|
@ -259,7 +271,7 @@ func (n NetworkV6) String() string {
|
|||
return Stringify(n)
|
||||
}
|
||||
|
||||
// Performs a list request given a path
|
||||
// Performs a list request given a path.
|
||||
func (s *DropletsServiceOp) list(path string) ([]Droplet, *Response, error) {
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
|
@ -278,7 +290,7 @@ func (s *DropletsServiceOp) list(path string) ([]Droplet, *Response, error) {
|
|||
return root.Droplets, resp, err
|
||||
}
|
||||
|
||||
// List all droplets
|
||||
// List all Droplets.
|
||||
func (s *DropletsServiceOp) List(opt *ListOptions) ([]Droplet, *Response, error) {
|
||||
path := dropletBasePath
|
||||
path, err := addOptions(path, opt)
|
||||
|
@ -289,7 +301,7 @@ func (s *DropletsServiceOp) List(opt *ListOptions) ([]Droplet, *Response, error)
|
|||
return s.list(path)
|
||||
}
|
||||
|
||||
// List all droplets by tag
|
||||
// ListByTag lists all Droplets matched by a Tag.
|
||||
func (s *DropletsServiceOp) ListByTag(tag string, opt *ListOptions) ([]Droplet, *Response, error) {
|
||||
path := fmt.Sprintf("%s?tag_name=%s", dropletBasePath, tag)
|
||||
path, err := addOptions(path, opt)
|
||||
|
@ -300,7 +312,7 @@ func (s *DropletsServiceOp) ListByTag(tag string, opt *ListOptions) ([]Droplet,
|
|||
return s.list(path)
|
||||
}
|
||||
|
||||
// Get individual droplet
|
||||
// Get individual Droplet.
|
||||
func (s *DropletsServiceOp) Get(dropletID int) (*Droplet, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -322,7 +334,7 @@ func (s *DropletsServiceOp) Get(dropletID int) (*Droplet, *Response, error) {
|
|||
return root.Droplet, resp, err
|
||||
}
|
||||
|
||||
// Create droplet
|
||||
// Create Droplet
|
||||
func (s *DropletsServiceOp) Create(createRequest *DropletCreateRequest) (*Droplet, *Response, error) {
|
||||
if createRequest == nil {
|
||||
return nil, nil, NewArgError("createRequest", "cannot be nil")
|
||||
|
@ -347,7 +359,7 @@ func (s *DropletsServiceOp) Create(createRequest *DropletCreateRequest) (*Drople
|
|||
return root.Droplet, resp, err
|
||||
}
|
||||
|
||||
// CreateMultiple creates multiple droplets.
|
||||
// CreateMultiple creates multiple Droplets.
|
||||
func (s *DropletsServiceOp) CreateMultiple(createRequest *DropletMultiCreateRequest) ([]Droplet, *Response, error) {
|
||||
if createRequest == nil {
|
||||
return nil, nil, NewArgError("createRequest", "cannot be nil")
|
||||
|
@ -384,7 +396,7 @@ func (s *DropletsServiceOp) delete(path string) (*Response, error) {
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// Delete droplet
|
||||
// Delete Droplet.
|
||||
func (s *DropletsServiceOp) Delete(dropletID int) (*Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -395,7 +407,7 @@ func (s *DropletsServiceOp) Delete(dropletID int) (*Response, error) {
|
|||
return s.delete(path)
|
||||
}
|
||||
|
||||
// Delete droplets by tag
|
||||
// DeleteByTag deletes Droplets matched by a Tag.
|
||||
func (s *DropletsServiceOp) DeleteByTag(tag string) (*Response, error) {
|
||||
if tag == "" {
|
||||
return nil, NewArgError("tag", "cannot be empty")
|
||||
|
@ -406,7 +418,7 @@ func (s *DropletsServiceOp) DeleteByTag(tag string) (*Response, error) {
|
|||
return s.delete(path)
|
||||
}
|
||||
|
||||
// Kernels lists kernels available for a droplet.
|
||||
// Kernels lists kernels available for a Droplet.
|
||||
func (s *DropletsServiceOp) Kernels(dropletID int, opt *ListOptions) ([]Kernel, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -432,7 +444,7 @@ func (s *DropletsServiceOp) Kernels(dropletID int, opt *ListOptions) ([]Kernel,
|
|||
return root.Kernels, resp, err
|
||||
}
|
||||
|
||||
// Actions lists the actions for a droplet.
|
||||
// Actions lists the actions for a Droplet.
|
||||
func (s *DropletsServiceOp) Actions(dropletID int, opt *ListOptions) ([]Action, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -461,7 +473,7 @@ func (s *DropletsServiceOp) Actions(dropletID int, opt *ListOptions) ([]Action,
|
|||
return root.Actions, resp, err
|
||||
}
|
||||
|
||||
// Backups lists the backups for a droplet.
|
||||
// Backups lists the backups for a Droplet.
|
||||
func (s *DropletsServiceOp) Backups(dropletID int, opt *ListOptions) ([]Image, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -490,7 +502,7 @@ func (s *DropletsServiceOp) Backups(dropletID int, opt *ListOptions) ([]Image, *
|
|||
return root.Backups, resp, err
|
||||
}
|
||||
|
||||
// Snapshots lists the snapshots available for a droplet.
|
||||
// Snapshots lists the snapshots available for a Droplet.
|
||||
func (s *DropletsServiceOp) Snapshots(dropletID int, opt *ListOptions) ([]Image, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
@ -507,7 +519,7 @@ func (s *DropletsServiceOp) Snapshots(dropletID int, opt *ListOptions) ([]Image,
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(snapshotsRoot)
|
||||
root := new(dropletSnapshotsRoot)
|
||||
resp, err := s.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
|
@ -519,7 +531,7 @@ func (s *DropletsServiceOp) Snapshots(dropletID int, opt *ListOptions) ([]Image,
|
|||
return root.Snapshots, resp, err
|
||||
}
|
||||
|
||||
// Neighbors lists the neighbors for a droplet.
|
||||
// Neighbors lists the neighbors for a Droplet.
|
||||
func (s *DropletsServiceOp) Neighbors(dropletID int) ([]Droplet, *Response, error) {
|
||||
if dropletID < 1 {
|
||||
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
|
||||
|
|
|
@ -64,7 +64,7 @@ func (s *FloatingIPActionsServiceOp) doAction(ip string, request *ActionRequest)
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
func (s *FloatingIPActionsServiceOp) get(path string) (*Action, *Response, error) {
|
||||
|
@ -79,7 +79,7 @@ func (s *FloatingIPActionsServiceOp) get(path string) (*Action, *Response, error
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
func (s *FloatingIPActionsServiceOp) list(path string) ([]Action, *Response, error) {
|
||||
|
|
|
@ -55,9 +55,11 @@ type Client struct {
|
|||
Sizes SizesService
|
||||
FloatingIPs FloatingIPsService
|
||||
FloatingIPActions FloatingIPActionsService
|
||||
Snapshots SnapshotsService
|
||||
Storage StorageService
|
||||
StorageActions StorageActionsService
|
||||
Tags TagsService
|
||||
LoadBalancers LoadBalancersService
|
||||
|
||||
// Optional function called after every successful request made to the DO APIs
|
||||
onRequestCompleted RequestCompletionCallback
|
||||
|
@ -155,16 +157,18 @@ func NewClient(httpClient *http.Client) *Client {
|
|||
c.Domains = &DomainsServiceOp{client: c}
|
||||
c.Droplets = &DropletsServiceOp{client: c}
|
||||
c.DropletActions = &DropletActionsServiceOp{client: c}
|
||||
c.FloatingIPs = &FloatingIPsServiceOp{client: c}
|
||||
c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c}
|
||||
c.Images = &ImagesServiceOp{client: c}
|
||||
c.ImageActions = &ImageActionsServiceOp{client: c}
|
||||
c.Keys = &KeysServiceOp{client: c}
|
||||
c.Regions = &RegionsServiceOp{client: c}
|
||||
c.Snapshots = &SnapshotsServiceOp{client: c}
|
||||
c.Sizes = &SizesServiceOp{client: c}
|
||||
c.FloatingIPs = &FloatingIPsServiceOp{client: c}
|
||||
c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c}
|
||||
c.Storage = &StorageServiceOp{client: c}
|
||||
c.StorageActions = &StorageActionsServiceOp{client: c}
|
||||
c.Tags = &TagsServiceOp{client: c}
|
||||
c.LoadBalancers = &LoadBalancersServiceOp{client: c}
|
||||
|
||||
return c
|
||||
}
|
||||
|
@ -218,7 +222,7 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
|
|||
|
||||
buf := new(bytes.Buffer)
|
||||
if body != nil {
|
||||
err := json.NewEncoder(buf).Encode(body)
|
||||
err = json.NewEncoder(buf).Encode(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -310,12 +314,12 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
|
|||
|
||||
if v != nil {
|
||||
if w, ok := v.(io.Writer); ok {
|
||||
_, err := io.Copy(w, resp.Body)
|
||||
_, err = io.Copy(w, resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
err := json.NewDecoder(resp.Body).Decode(v)
|
||||
err = json.NewDecoder(resp.Body).Decode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func (i *ImageActionsServiceOp) Transfer(imageID int, transferRequest *ActionReq
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
// Get an action for a particular image by id.
|
||||
|
@ -67,5 +67,5 @@ func (i *ImageActionsServiceOp) Get(imageID, actionID int) (*Action, *Response,
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ type ImageUpdateRequest struct {
|
|||
}
|
||||
|
||||
type imageRoot struct {
|
||||
Image Image
|
||||
Image *Image
|
||||
}
|
||||
|
||||
type imagesRoot struct {
|
||||
|
@ -125,7 +125,7 @@ func (s *ImagesServiceOp) Update(imageID int, updateRequest *ImageUpdateRequest)
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Image, resp, err
|
||||
return root.Image, resp, err
|
||||
}
|
||||
|
||||
// Delete an image.
|
||||
|
@ -161,7 +161,7 @@ func (s *ImagesServiceOp) get(ID interface{}) (*Image, *Response, error) {
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Image, resp, err
|
||||
return root.Image, resp, err
|
||||
}
|
||||
|
||||
// Helper method for listing images
|
||||
|
|
|
@ -45,7 +45,7 @@ type keysRoot struct {
|
|||
}
|
||||
|
||||
type keyRoot struct {
|
||||
SSHKey Key `json:"ssh_key"`
|
||||
SSHKey *Key `json:"ssh_key"`
|
||||
}
|
||||
|
||||
func (s Key) String() string {
|
||||
|
@ -96,7 +96,7 @@ func (s *KeysServiceOp) get(path string) (*Key, *Response, error) {
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.SSHKey, resp, err
|
||||
return root.SSHKey, resp, err
|
||||
}
|
||||
|
||||
// GetByID gets a Key by id
|
||||
|
@ -136,7 +136,7 @@ func (s *KeysServiceOp) Create(createRequest *KeyCreateRequest) (*Key, *Response
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.SSHKey, resp, err
|
||||
return root.SSHKey, resp, err
|
||||
}
|
||||
|
||||
// UpdateByID updates a key name by ID.
|
||||
|
@ -161,7 +161,7 @@ func (s *KeysServiceOp) UpdateByID(keyID int, updateRequest *KeyUpdateRequest) (
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.SSHKey, resp, err
|
||||
return root.SSHKey, resp, err
|
||||
}
|
||||
|
||||
// UpdateByFingerprint updates a key name by fingerprint.
|
||||
|
@ -186,7 +186,7 @@ func (s *KeysServiceOp) UpdateByFingerprint(fingerprint string, updateRequest *K
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.SSHKey, resp, err
|
||||
return root.SSHKey, resp, err
|
||||
}
|
||||
|
||||
// Delete key using a path
|
||||
|
|
|
@ -58,11 +58,7 @@ func (l *Links) IsLastPage() bool {
|
|||
}
|
||||
|
||||
func (p *Pages) isLast() bool {
|
||||
if p.Last == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return p.Last == ""
|
||||
}
|
||||
|
||||
func pageForURL(urlText string) (int, error) {
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const loadBalancersBasePath = "/v2/load_balancers"
|
||||
const forwardingRulesPath = "forwarding_rules"
|
||||
const dropletsPath = "droplets"
|
||||
|
||||
// LoadBalancersService is an interface for managing load balancers with the DigitalOcean API.
|
||||
// See: https://developers.digitalocean.com/documentation/v2#load-balancers
|
||||
type LoadBalancersService interface {
|
||||
Get(lbID string) (*LoadBalancer, *Response, error)
|
||||
List(opt *ListOptions) ([]LoadBalancer, *Response, error)
|
||||
Create(lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error)
|
||||
Update(lbID string, lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error)
|
||||
Delete(lbID string) (*Response, error)
|
||||
AddDroplets(lbID string, dropletIDs ...int) (*Response, error)
|
||||
RemoveDroplets(lbID string, dropletIDs ...int) (*Response, error)
|
||||
AddForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error)
|
||||
RemoveForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error)
|
||||
}
|
||||
|
||||
// LoadBalancer represents a DigitalOcean load balancer configuration.
|
||||
type LoadBalancer struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
IP string `json:"ip,omitempty"`
|
||||
Algorithm string `json:"algorithm,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Created string `json:"created_at,omitempty"`
|
||||
ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"`
|
||||
HealthCheck *HealthCheck `json:"health_check,omitempty"`
|
||||
StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
|
||||
Region *Region `json:"region,omitempty"`
|
||||
DropletIDs []int `json:"droplet_ids,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"`
|
||||
}
|
||||
|
||||
// String creates a human-readable description of a LoadBalancer.
|
||||
func (l LoadBalancer) String() string {
|
||||
return Stringify(l)
|
||||
}
|
||||
|
||||
// ForwardingRule represents load balancer forwarding rules.
|
||||
type ForwardingRule struct {
|
||||
EntryProtocol string `json:"entry_protocol,omitempty"`
|
||||
EntryPort int `json:"entry_port,omitempty"`
|
||||
TargetProtocol string `json:"target_protocol,omitempty"`
|
||||
TargetPort int `json:"target_port,omitempty"`
|
||||
CertificateID string `json:"certificate_id,omitempty"`
|
||||
TlsPassthrough bool `json:"tls_passthrough,omitempty"`
|
||||
}
|
||||
|
||||
// String creates a human-readable description of a ForwardingRule.
|
||||
func (f ForwardingRule) String() string {
|
||||
return Stringify(f)
|
||||
}
|
||||
|
||||
// HealthCheck represents optional load balancer health check rules.
|
||||
type HealthCheck struct {
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
CheckIntervalSeconds int `json:"check_interval_seconds,omitempty"`
|
||||
ResponseTimeoutSeconds int `json:"response_timeout_seconds,omitempty"`
|
||||
HealthyThreshold int `json:"healthy_threshold,omitempty"`
|
||||
UnhealthyThreshold int `json:"unhealthy_threshold,omitempty"`
|
||||
}
|
||||
|
||||
// String creates a human-readable description of a HealthCheck.
|
||||
func (h HealthCheck) String() string {
|
||||
return Stringify(h)
|
||||
}
|
||||
|
||||
// StickySessions represents optional load balancer session affinity rules.
|
||||
type StickySessions struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
CookieName string `json:"cookie_name,omitempty"`
|
||||
CookieTtlSeconds int `json:"cookie_ttl_seconds,omitempty"`
|
||||
}
|
||||
|
||||
// String creates a human-readable description of a StickySessions instance.
|
||||
func (s StickySessions) String() string {
|
||||
return Stringify(s)
|
||||
}
|
||||
|
||||
// LoadBalancerRequest represents the configuration to be applied to an existing or a new load balancer.
|
||||
type LoadBalancerRequest struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Algorithm string `json:"algorithm,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"`
|
||||
HealthCheck *HealthCheck `json:"health_check,omitempty"`
|
||||
StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
|
||||
DropletIDs []int `json:"droplet_ids,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"`
|
||||
}
|
||||
|
||||
// String creates a human-readable description of a LoadBalancerRequest.
|
||||
func (l LoadBalancerRequest) String() string {
|
||||
return Stringify(l)
|
||||
}
|
||||
|
||||
type forwardingRulesRequest struct {
|
||||
Rules []ForwardingRule `json:"forwarding_rules,omitempty"`
|
||||
}
|
||||
|
||||
func (l forwardingRulesRequest) String() string {
|
||||
return Stringify(l)
|
||||
}
|
||||
|
||||
type dropletIDsRequest struct {
|
||||
IDs []int `json:"droplet_ids,omitempty"`
|
||||
}
|
||||
|
||||
func (l dropletIDsRequest) String() string {
|
||||
return Stringify(l)
|
||||
}
|
||||
|
||||
type loadBalancersRoot struct {
|
||||
LoadBalancers []LoadBalancer `json:"load_balancers"`
|
||||
Links *Links `json:"links"`
|
||||
}
|
||||
|
||||
type loadBalancerRoot struct {
|
||||
LoadBalancer *LoadBalancer `json:"load_balancer"`
|
||||
}
|
||||
|
||||
// LoadBalancersServiceOp handles communication with load balancer-related methods of the DigitalOcean API.
|
||||
type LoadBalancersServiceOp struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
var _ LoadBalancersService = &LoadBalancersServiceOp{}
|
||||
|
||||
// Get an existing load balancer by its identifier.
|
||||
func (l *LoadBalancersServiceOp) Get(lbID string) (*LoadBalancer, *Response, error) {
|
||||
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, lbID)
|
||||
|
||||
req, err := l.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(loadBalancerRoot)
|
||||
resp, err := l.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return root.LoadBalancer, resp, err
|
||||
}
|
||||
|
||||
// List load balancers, with optional pagination.
|
||||
func (l *LoadBalancersServiceOp) List(opt *ListOptions) ([]LoadBalancer, *Response, error) {
|
||||
path, err := addOptions(loadBalancersBasePath, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
req, err := l.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(loadBalancersRoot)
|
||||
resp, err := l.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
if l := root.Links; l != nil {
|
||||
resp.Links = l
|
||||
}
|
||||
|
||||
return root.LoadBalancers, resp, err
|
||||
}
|
||||
|
||||
// Create a new load balancer with a given configuration.
|
||||
func (l *LoadBalancersServiceOp) Create(lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error) {
|
||||
req, err := l.client.NewRequest("POST", loadBalancersBasePath, lbr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(loadBalancerRoot)
|
||||
resp, err := l.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return root.LoadBalancer, resp, err
|
||||
}
|
||||
|
||||
// Update an existing load balancer with new configuration.
|
||||
func (l *LoadBalancersServiceOp) Update(lbID string, lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error) {
|
||||
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, lbID)
|
||||
|
||||
req, err := l.client.NewRequest("PUT", path, lbr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(loadBalancerRoot)
|
||||
resp, err := l.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return root.LoadBalancer, resp, err
|
||||
}
|
||||
|
||||
// Delete a load balancer by its identifier.
|
||||
func (l *LoadBalancersServiceOp) Delete(ldID string) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, ldID)
|
||||
|
||||
req, err := l.client.NewRequest("DELETE", path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// AddDroplets adds droplets to a load balancer.
|
||||
func (l *LoadBalancersServiceOp) AddDroplets(lbID string, dropletIDs ...int) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath)
|
||||
|
||||
req, err := l.client.NewRequest("POST", path, &dropletIDsRequest{IDs: dropletIDs})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// RemoveDroplets removes droplets from a load balancer.
|
||||
func (l *LoadBalancersServiceOp) RemoveDroplets(lbID string, dropletIDs ...int) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath)
|
||||
|
||||
req, err := l.client.NewRequest("DELETE", path, &dropletIDsRequest{IDs: dropletIDs})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// AddForwardingRules adds forwarding rules to a load balancer.
|
||||
func (l *LoadBalancersServiceOp) AddForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath)
|
||||
|
||||
req, err := l.client.NewRequest("POST", path, &forwardingRulesRequest{Rules: rules})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// RemoveForwardingRules removes forwarding rules from a load balancer.
|
||||
func (l *LoadBalancersServiceOp) RemoveForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath)
|
||||
|
||||
req, err := l.client.NewRequest("DELETE", path, &forwardingRulesRequest{Rules: rules})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l.client.Do(req, nil)
|
||||
}
|
|
@ -29,10 +29,6 @@ type regionsRoot struct {
|
|||
Links *Links `json:"links"`
|
||||
}
|
||||
|
||||
type regionRoot struct {
|
||||
Region Region
|
||||
}
|
||||
|
||||
func (r Region) String() string {
|
||||
return Stringify(r)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
package godo
|
||||
|
||||
import "fmt"
|
||||
|
||||
const snapshotBasePath = "v2/snapshots"
|
||||
|
||||
// SnapshotsService is an interface for interfacing with the snapshots
|
||||
// endpoints of the DigitalOcean API
|
||||
// See: https://developers.digitalocean.com/documentation/v2#snapshots
|
||||
type SnapshotsService interface {
|
||||
List(*ListOptions) ([]Snapshot, *Response, error)
|
||||
ListVolume(*ListOptions) ([]Snapshot, *Response, error)
|
||||
ListDroplet(*ListOptions) ([]Snapshot, *Response, error)
|
||||
Get(string) (*Snapshot, *Response, error)
|
||||
Delete(string) (*Response, error)
|
||||
}
|
||||
|
||||
// SnapshotsServiceOp handles communication with the snapshot related methods of the
|
||||
// DigitalOcean API.
|
||||
type SnapshotsServiceOp struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
var _ SnapshotsService = &SnapshotsServiceOp{}
|
||||
|
||||
// Snapshot represents a DigitalOcean Snapshot
|
||||
type Snapshot struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ResourceID string `json:"resource_id,omitempty"`
|
||||
ResourceType string `json:"resource_type,omitempty"`
|
||||
Regions []string `json:"regions,omitempty"`
|
||||
MinDiskSize int `json:"min_disk_size,omitempty"`
|
||||
SizeGigaBytes float64 `json:"size_gigabytes,omitempty"`
|
||||
Created string `json:"created_at,omitempty"`
|
||||
}
|
||||
|
||||
type snapshotRoot struct {
|
||||
Snapshot *Snapshot `json:"snapshot"`
|
||||
}
|
||||
|
||||
type snapshotsRoot struct {
|
||||
Snapshots []Snapshot `json:"snapshots"`
|
||||
Links *Links `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
type listSnapshotOptions struct {
|
||||
ResourceType string `url:"resource_type,omitempty"`
|
||||
}
|
||||
|
||||
func (s Snapshot) String() string {
|
||||
return Stringify(s)
|
||||
}
|
||||
|
||||
// List lists all the snapshots available.
|
||||
func (s *SnapshotsServiceOp) List(opt *ListOptions) ([]Snapshot, *Response, error) {
|
||||
return s.list(opt, nil)
|
||||
}
|
||||
|
||||
// ListDroplet lists all the Droplet snapshots.
|
||||
func (s *SnapshotsServiceOp) ListDroplet(opt *ListOptions) ([]Snapshot, *Response, error) {
|
||||
listOpt := listSnapshotOptions{ResourceType: "droplet"}
|
||||
return s.list(opt, &listOpt)
|
||||
}
|
||||
|
||||
// ListVolume lists all the volume snapshots.
|
||||
func (s *SnapshotsServiceOp) ListVolume(opt *ListOptions) ([]Snapshot, *Response, error) {
|
||||
listOpt := listSnapshotOptions{ResourceType: "volume"}
|
||||
return s.list(opt, &listOpt)
|
||||
}
|
||||
|
||||
// Get retrieves an snapshot by id.
|
||||
func (s *SnapshotsServiceOp) Get(snapshotID string) (*Snapshot, *Response, error) {
|
||||
return s.get(interface{}(snapshotID))
|
||||
}
|
||||
|
||||
// Delete an snapshot.
|
||||
func (s *SnapshotsServiceOp) Delete(snapshotID string) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s", snapshotBasePath, snapshotID)
|
||||
|
||||
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Helper method for getting an individual snapshot
|
||||
func (s *SnapshotsServiceOp) get(ID interface{}) (*Snapshot, *Response, error) {
|
||||
path := fmt.Sprintf("%s/%v", snapshotBasePath, ID)
|
||||
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(snapshotRoot)
|
||||
resp, err := s.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return root.Snapshot, resp, err
|
||||
}
|
||||
|
||||
// Helper method for listing snapshots
|
||||
func (s *SnapshotsServiceOp) list(opt *ListOptions, listOpt *listSnapshotOptions) ([]Snapshot, *Response, error) {
|
||||
path := snapshotBasePath
|
||||
path, err := addOptions(path, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
path, err = addOptions(path, listOpt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(snapshotsRoot)
|
||||
resp, err := s.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
if l := root.Links; l != nil {
|
||||
resp.Links = l
|
||||
}
|
||||
|
||||
return root.Snapshots, resp, err
|
||||
}
|
|
@ -19,18 +19,6 @@ type StorageService interface {
|
|||
GetVolume(string) (*Volume, *Response, error)
|
||||
CreateVolume(*VolumeCreateRequest) (*Volume, *Response, error)
|
||||
DeleteVolume(string) (*Response, error)
|
||||
}
|
||||
|
||||
// BetaStorageService is an interface for the storage services that are
|
||||
// not yet stable. The interface is not exposed in the godo.Client and
|
||||
// requires type-asserting the `StorageService` to make it available.
|
||||
//
|
||||
// Note that Beta features will change and compiling against those
|
||||
// symbols (using type-assertion) is prone to breaking your build
|
||||
// if you use our master.
|
||||
type BetaStorageService interface {
|
||||
StorageService
|
||||
|
||||
ListSnapshots(volumeID string, opts *ListOptions) ([]Snapshot, *Response, error)
|
||||
GetSnapshot(string) (*Snapshot, *Response, error)
|
||||
CreateSnapshot(*SnapshotCreateRequest) (*Snapshot, *Response, error)
|
||||
|
@ -150,27 +138,6 @@ func (svc *StorageServiceOp) DeleteVolume(id string) (*Response, error) {
|
|||
return svc.client.Do(req, nil)
|
||||
}
|
||||
|
||||
// Snapshot represents a Digital Ocean block store snapshot.
|
||||
type Snapshot struct {
|
||||
ID string `json:"id"`
|
||||
VolumeID string `json:"volume_id"`
|
||||
Region *Region `json:"region"`
|
||||
Name string `json:"name"`
|
||||
SizeGigaBytes int64 `json:"size_gigabytes"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type storageSnapsRoot struct {
|
||||
Snapshots []Snapshot `json:"snapshots"`
|
||||
Links *Links `json:"links"`
|
||||
}
|
||||
|
||||
type storageSnapRoot struct {
|
||||
Snapshot *Snapshot `json:"snapshot"`
|
||||
Links *Links `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
// SnapshotCreateRequest represents a request to create a block store
|
||||
// volume.
|
||||
type SnapshotCreateRequest struct {
|
||||
|
@ -192,7 +159,7 @@ func (svc *StorageServiceOp) ListSnapshots(volumeID string, opt *ListOptions) ([
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(storageSnapsRoot)
|
||||
root := new(snapshotsRoot)
|
||||
resp, err := svc.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
|
@ -214,7 +181,7 @@ func (svc *StorageServiceOp) CreateSnapshot(createRequest *SnapshotCreateRequest
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(storageSnapRoot)
|
||||
root := new(snapshotRoot)
|
||||
resp, err := svc.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
|
@ -231,7 +198,7 @@ func (svc *StorageServiceOp) GetSnapshot(id string) (*Snapshot, *Response, error
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(storageSnapRoot)
|
||||
root := new(snapshotRoot)
|
||||
resp, err := svc.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
|
|
|
@ -8,21 +8,25 @@ import "fmt"
|
|||
type StorageActionsService interface {
|
||||
Attach(volumeID string, dropletID int) (*Action, *Response, error)
|
||||
Detach(volumeID string) (*Action, *Response, error)
|
||||
DetachByDropletID(volumeID string, dropletID int) (*Action, *Response, error)
|
||||
Get(volumeID string, actionID int) (*Action, *Response, error)
|
||||
List(volumeID string, opt *ListOptions) ([]Action, *Response, error)
|
||||
Resize(volumeID string, sizeGigabytes int, regionSlug string) (*Action, *Response, error)
|
||||
}
|
||||
|
||||
// StorageActionsServiceOp handles communication with the floating IPs
|
||||
// StorageActionsServiceOp handles communication with the storage volumes
|
||||
// action related methods of the DigitalOcean API.
|
||||
type StorageActionsServiceOp struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// StorageAttachment represents the attachement of a block storage
|
||||
// volume to a specific droplet under the device name.
|
||||
// volume to a specific Droplet under the device name.
|
||||
type StorageAttachment struct {
|
||||
DropletID int `json:"droplet_id"`
|
||||
}
|
||||
|
||||
// Attach a storage volume to a droplet.
|
||||
// Attach a storage volume to a Droplet.
|
||||
func (s *StorageActionsServiceOp) Attach(volumeID string, dropletID int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{
|
||||
"type": "attach",
|
||||
|
@ -31,7 +35,7 @@ func (s *StorageActionsServiceOp) Attach(volumeID string, dropletID int) (*Actio
|
|||
return s.doAction(volumeID, request)
|
||||
}
|
||||
|
||||
// Detach a storage volume from a droplet.
|
||||
// Detach a storage volume from a Droplet.
|
||||
func (s *StorageActionsServiceOp) Detach(volumeID string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{
|
||||
"type": "detach",
|
||||
|
@ -39,6 +43,42 @@ func (s *StorageActionsServiceOp) Detach(volumeID string) (*Action, *Response, e
|
|||
return s.doAction(volumeID, request)
|
||||
}
|
||||
|
||||
// DetachByDropletID a storage volume from a Droplet by Droplet ID.
|
||||
func (s *StorageActionsServiceOp) DetachByDropletID(volumeID string, dropletID int) (*Action, *Response, error) {
|
||||
request := &ActionRequest{
|
||||
"type": "detach",
|
||||
"droplet_id": dropletID,
|
||||
}
|
||||
return s.doAction(volumeID, request)
|
||||
}
|
||||
|
||||
// Get an action for a particular storage volume by id.
|
||||
func (s *StorageActionsServiceOp) Get(volumeID string, actionID int) (*Action, *Response, error) {
|
||||
path := fmt.Sprintf("%s/%d", storageAllocationActionPath(volumeID), actionID)
|
||||
return s.get(path)
|
||||
}
|
||||
|
||||
// List the actions for a particular storage volume.
|
||||
func (s *StorageActionsServiceOp) List(volumeID string, opt *ListOptions) ([]Action, *Response, error) {
|
||||
path := storageAllocationActionPath(volumeID)
|
||||
path, err := addOptions(path, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return s.list(path)
|
||||
}
|
||||
|
||||
// Resize a storage volume.
|
||||
func (s *StorageActionsServiceOp) Resize(volumeID string, sizeGigabytes int, regionSlug string) (*Action, *Response, error) {
|
||||
request := &ActionRequest{
|
||||
"type": "resize",
|
||||
"size_gigabytes": sizeGigabytes,
|
||||
"region": regionSlug,
|
||||
}
|
||||
return s.doAction(volumeID, request)
|
||||
}
|
||||
|
||||
func (s *StorageActionsServiceOp) doAction(volumeID string, request *ActionRequest) (*Action, *Response, error) {
|
||||
path := storageAllocationActionPath(volumeID)
|
||||
|
||||
|
@ -53,7 +93,40 @@ func (s *StorageActionsServiceOp) doAction(volumeID string, request *ActionReque
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
return &root.Event, resp, err
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
func (s *StorageActionsServiceOp) get(path string) (*Action, *Response, error) {
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(actionRoot)
|
||||
resp, err := s.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return root.Event, resp, err
|
||||
}
|
||||
|
||||
func (s *StorageActionsServiceOp) list(path string) ([]Action, *Response, error) {
|
||||
req, err := s.client.NewRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
root := new(actionsRoot)
|
||||
resp, err := s.client.Do(req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
if l := root.Links; l != nil {
|
||||
resp.Links = l
|
||||
}
|
||||
|
||||
return root.Actions, resp, err
|
||||
}
|
||||
|
||||
func storageAllocationActionPath(volumeID string) string {
|
||||
|
|
|
@ -3,6 +3,7 @@ package godo
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
|
@ -17,7 +18,7 @@ func Stringify(message interface{}) string {
|
|||
}
|
||||
|
||||
// stringifyValue was graciously cargoculted from the goprotubuf library
|
||||
func stringifyValue(w *bytes.Buffer, val reflect.Value) {
|
||||
func stringifyValue(w io.Writer, val reflect.Value) {
|
||||
if val.Kind() == reflect.Ptr && val.IsNil() {
|
||||
_, _ = w.Write([]byte("<nil>"))
|
||||
return
|
||||
|
@ -29,55 +30,63 @@ func stringifyValue(w *bytes.Buffer, val reflect.Value) {
|
|||
case reflect.String:
|
||||
fmt.Fprintf(w, `"%s"`, v)
|
||||
case reflect.Slice:
|
||||
_, _ = w.Write([]byte{'['})
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if i > 0 {
|
||||
_, _ = w.Write([]byte{' '})
|
||||
}
|
||||
|
||||
stringifyValue(w, v.Index(i))
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte{']'})
|
||||
stringifySlice(w, v)
|
||||
return
|
||||
case reflect.Struct:
|
||||
if v.Type().Name() != "" {
|
||||
_, _ = w.Write([]byte(v.Type().String()))
|
||||
}
|
||||
|
||||
// special handling of Timestamp values
|
||||
if v.Type() == timestampType {
|
||||
fmt.Fprintf(w, "{%s}", v.Interface())
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte{'{'})
|
||||
|
||||
var sep bool
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fv := v.Field(i)
|
||||
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
||||
continue
|
||||
}
|
||||
if fv.Kind() == reflect.Slice && fv.IsNil() {
|
||||
continue
|
||||
}
|
||||
|
||||
if sep {
|
||||
_, _ = w.Write([]byte(", "))
|
||||
} else {
|
||||
sep = true
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte(v.Type().Field(i).Name))
|
||||
_, _ = w.Write([]byte{':'})
|
||||
stringifyValue(w, fv)
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte{'}'})
|
||||
stringifyStruct(w, v)
|
||||
default:
|
||||
if v.CanInterface() {
|
||||
fmt.Fprint(w, v.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stringifySlice(w io.Writer, v reflect.Value) {
|
||||
_, _ = w.Write([]byte{'['})
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if i > 0 {
|
||||
_, _ = w.Write([]byte{' '})
|
||||
}
|
||||
|
||||
stringifyValue(w, v.Index(i))
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte{']'})
|
||||
}
|
||||
|
||||
func stringifyStruct(w io.Writer, v reflect.Value) {
|
||||
if v.Type().Name() != "" {
|
||||
_, _ = w.Write([]byte(v.Type().String()))
|
||||
}
|
||||
|
||||
// special handling of Timestamp values
|
||||
if v.Type() == timestampType {
|
||||
fmt.Fprintf(w, "{%s}", v.Interface())
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte{'{'})
|
||||
|
||||
var sep bool
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fv := v.Field(i)
|
||||
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
||||
continue
|
||||
}
|
||||
if fv.Kind() == reflect.Slice && fv.IsNil() {
|
||||
continue
|
||||
}
|
||||
|
||||
if sep {
|
||||
_, _ = w.Write([]byte(", "))
|
||||
} else {
|
||||
sep = true
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte(v.Type().Field(i).Name))
|
||||
_, _ = w.Write([]byte{':'})
|
||||
stringifyValue(w, fv)
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte{'}'})
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ var _ TagsService = &TagsServiceOp{}
|
|||
type ResourceType string
|
||||
|
||||
const (
|
||||
//DropletResourceType holds the string representing our ResourceType of Droplet.
|
||||
DropletResourceType ResourceType = "droplet"
|
||||
)
|
||||
|
||||
|
@ -56,18 +57,22 @@ type Tag struct {
|
|||
Resources *TaggedResources `json:"resources,omitempty"`
|
||||
}
|
||||
|
||||
//TagCreateRequest represents the JSON structure of a request of that type.
|
||||
type TagCreateRequest struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
//TagUpdateRequest represents the JSON structure of a request of that type.
|
||||
type TagUpdateRequest struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// TagResourcesRequest represents the JSON structure of a request of that type.
|
||||
type TagResourcesRequest struct {
|
||||
Resources []Resource `json:"resources"`
|
||||
}
|
||||
|
||||
// UntagResourcesRequest represents the JSON structure of a request of that type.
|
||||
type UntagResourcesRequest struct {
|
||||
Resources []Resource `json:"resources"`
|
||||
}
|
||||
|
@ -183,7 +188,7 @@ func (s *TagsServiceOp) Delete(name string) (*Response, error) {
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// Associate resources with a tag
|
||||
// TagResources associates resources with a given Tag.
|
||||
func (s *TagsServiceOp) TagResources(name string, tagRequest *TagResourcesRequest) (*Response, error) {
|
||||
if name == "" {
|
||||
return nil, NewArgError("name", "cannot be empty")
|
||||
|
@ -204,7 +209,7 @@ func (s *TagsServiceOp) TagResources(name string, tagRequest *TagResourcesReques
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// Dissociate resources with a tag
|
||||
// UntagResources dissociates resources with a given Tag.
|
||||
func (s *TagsServiceOp) UntagResources(name string, untagRequest *UntagResourcesRequest) (*Response, error) {
|
||||
if name == "" {
|
||||
return nil, NewArgError("name", "cannot be empty")
|
||||
|
|
|
@ -1230,11 +1230,11 @@
|
|||
"revisionTime": "2016-06-17T17:01:58Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "mbMr6wMbQnMrfIwUtej8QcGsx0A=",
|
||||
"checksumSHA1": "tOlmmumwQ9pCv5cQgs+W7sgPVgU=",
|
||||
"comment": "v0.9.0-20-gf75d769",
|
||||
"path": "github.com/digitalocean/godo",
|
||||
"revision": "e03ac28c3d9b216f7e9ed16bc6aa39e344d56491",
|
||||
"revisionTime": "2016-06-27T19:55:12Z"
|
||||
"revision": "767976000cc435d38646653b52be9be572727f30",
|
||||
"revisionTime": "2017-02-14T20:43:37Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "zkENTbOfU8YoxPfFwVAhTz516Dg=",
|
||||
|
|
Loading…
Reference in New Issue