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 {
|
type actionRoot struct {
|
||||||
Event Action `json:"action"`
|
Event *Action `json:"action"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action represents a DigitalOcean Action
|
// Action represents a DigitalOcean Action
|
||||||
|
@ -92,7 +92,7 @@ func (s *ActionsServiceOp) Get(id int) (*Action, *Response, error) {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Event, resp, err
|
return root.Event, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Action) String() string {
|
func (a Action) String() string {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
// ActionRequest reprents DigitalOcean Action Request
|
// ActionRequest reprents DigitalOcean Action Request
|
||||||
type ActionRequest map[string]interface{}
|
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
|
// endpoints of the DigitalOcean API
|
||||||
// See: https://developers.digitalocean.com/documentation/v2#droplet-actions
|
// See: https://developers.digitalocean.com/documentation/v2#droplet-actions
|
||||||
type DropletActionsService interface {
|
type DropletActionsService interface {
|
||||||
|
@ -43,7 +43,7 @@ type DropletActionsService interface {
|
||||||
GetByURI(string) (*Action, *Response, error)
|
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.
|
// methods of the DigitalOcean API.
|
||||||
type DropletActionsServiceOp struct {
|
type DropletActionsServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
|
@ -57,7 +57,7 @@ func (s *DropletActionsServiceOp) Shutdown(id int) (*Action, *Response, error) {
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) ShutdownByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "shutdown"}
|
request := &ActionRequest{"type": "shutdown"}
|
||||||
return s.doActionByTag(tag, request)
|
return s.doActionByTag(tag, request)
|
||||||
|
@ -69,7 +69,7 @@ func (s *DropletActionsServiceOp) PowerOff(id int) (*Action, *Response, error) {
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) PowerOffByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "power_off"}
|
request := &ActionRequest{"type": "power_off"}
|
||||||
return s.doActionByTag(tag, request)
|
return s.doActionByTag(tag, request)
|
||||||
|
@ -81,7 +81,7 @@ func (s *DropletActionsServiceOp) PowerOn(id int) (*Action, *Response, error) {
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) PowerOnByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "power_on"}
|
request := &ActionRequest{"type": "power_on"}
|
||||||
return s.doActionByTag(tag, request)
|
return s.doActionByTag(tag, request)
|
||||||
|
@ -93,7 +93,7 @@ func (s *DropletActionsServiceOp) PowerCycle(id int) (*Action, *Response, error)
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) PowerCycleByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "power_cycle"}
|
request := &ActionRequest{"type": "power_cycle"}
|
||||||
return s.doActionByTag(tag, request)
|
return s.doActionByTag(tag, request)
|
||||||
|
@ -146,7 +146,7 @@ func (s *DropletActionsServiceOp) Snapshot(id int, name string) (*Action, *Respo
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) SnapshotByTag(tag string, name string) (*Action, *Response, error) {
|
||||||
requestType := "snapshot"
|
requestType := "snapshot"
|
||||||
request := &ActionRequest{
|
request := &ActionRequest{
|
||||||
|
@ -156,79 +156,79 @@ func (s *DropletActionsServiceOp) SnapshotByTag(tag string, name string) (*Actio
|
||||||
return s.doActionByTag(tag, request)
|
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) {
|
func (s *DropletActionsServiceOp) EnableBackups(id int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "enable_backups"}
|
request := &ActionRequest{"type": "enable_backups"}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) EnableBackupsByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "enable_backups"}
|
request := &ActionRequest{"type": "enable_backups"}
|
||||||
return s.doActionByTag(tag, request)
|
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) {
|
func (s *DropletActionsServiceOp) DisableBackups(id int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "disable_backups"}
|
request := &ActionRequest{"type": "disable_backups"}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) DisableBackupsByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "disable_backups"}
|
request := &ActionRequest{"type": "disable_backups"}
|
||||||
return s.doActionByTag(tag, request)
|
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) {
|
func (s *DropletActionsServiceOp) PasswordReset(id int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "password_reset"}
|
request := &ActionRequest{"type": "password_reset"}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) RebuildByImageID(id, imageID int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "rebuild", "image": imageID}
|
request := &ActionRequest{"type": "rebuild", "image": imageID}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) RebuildByImageSlug(id int, slug string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "rebuild", "image": slug}
|
request := &ActionRequest{"type": "rebuild", "image": slug}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) ChangeKernel(id, kernelID int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "change_kernel", "kernel": kernelID}
|
request := &ActionRequest{"type": "change_kernel", "kernel": kernelID}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) EnableIPv6(id int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "enable_ipv6"}
|
request := &ActionRequest{"type": "enable_ipv6"}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) EnableIPv6ByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "enable_ipv6"}
|
request := &ActionRequest{"type": "enable_ipv6"}
|
||||||
return s.doActionByTag(tag, request)
|
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) {
|
func (s *DropletActionsServiceOp) EnablePrivateNetworking(id int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "enable_private_networking"}
|
request := &ActionRequest{"type": "enable_private_networking"}
|
||||||
return s.doAction(id, request)
|
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) {
|
func (s *DropletActionsServiceOp) EnablePrivateNetworkingByTag(tag string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "enable_private_networking"}
|
request := &ActionRequest{"type": "enable_private_networking"}
|
||||||
return s.doActionByTag(tag, request)
|
return s.doActionByTag(tag, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade a droplet.
|
// Upgrade a Droplet.
|
||||||
func (s *DropletActionsServiceOp) Upgrade(id int) (*Action, *Response, error) {
|
func (s *DropletActionsServiceOp) Upgrade(id int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{"type": "upgrade"}
|
request := &ActionRequest{"type": "upgrade"}
|
||||||
return s.doAction(id, request)
|
return s.doAction(id, request)
|
||||||
|
@ -256,7 +256,7 @@ func (s *DropletActionsServiceOp) doAction(id int, request *ActionRequest) (*Act
|
||||||
return nil, resp, err
|
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) {
|
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 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) {
|
func (s *DropletActionsServiceOp) Get(dropletID, actionID int) (*Action, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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)
|
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) {
|
func (s *DropletActionsServiceOp) GetByURI(rawurl string) (*Action, *Response, error) {
|
||||||
u, err := url.Parse(rawurl)
|
u, err := url.Parse(rawurl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -321,7 +321,7 @@ func (s *DropletActionsServiceOp) get(path string) (*Action, *Response, error) {
|
||||||
return nil, resp, err
|
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")
|
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
|
// endpoints of the DigitalOcean API
|
||||||
// See: https://developers.digitalocean.com/documentation/v2#droplets
|
// See: https://developers.digitalocean.com/documentation/v2#droplets
|
||||||
type DropletsService interface {
|
type DropletsService interface {
|
||||||
|
@ -28,7 +28,7 @@ type DropletsService interface {
|
||||||
Neighbors(int) ([]Droplet, *Response, error)
|
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.
|
// DigitalOcean API.
|
||||||
type DropletsServiceOp struct {
|
type DropletsServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
|
@ -38,24 +38,26 @@ var _ DropletsService = &DropletsServiceOp{}
|
||||||
|
|
||||||
// Droplet represents a DigitalOcean Droplet
|
// Droplet represents a DigitalOcean Droplet
|
||||||
type Droplet struct {
|
type Droplet struct {
|
||||||
ID int `json:"id,float64,omitempty"`
|
ID int `json:"id,float64,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Memory int `json:"memory,omitempty"`
|
Memory int `json:"memory,omitempty"`
|
||||||
Vcpus int `json:"vcpus,omitempty"`
|
Vcpus int `json:"vcpus,omitempty"`
|
||||||
Disk int `json:"disk,omitempty"`
|
Disk int `json:"disk,omitempty"`
|
||||||
Region *Region `json:"region,omitempty"`
|
Region *Region `json:"region,omitempty"`
|
||||||
Image *Image `json:"image,omitempty"`
|
Image *Image `json:"image,omitempty"`
|
||||||
Size *Size `json:"size,omitempty"`
|
Size *Size `json:"size,omitempty"`
|
||||||
SizeSlug string `json:"size_slug,omitempty"`
|
SizeSlug string `json:"size_slug,omitempty"`
|
||||||
BackupIDs []int `json:"backup_ids,omitempty"`
|
BackupIDs []int `json:"backup_ids,omitempty"`
|
||||||
SnapshotIDs []int `json:"snapshot_ids,omitempty"`
|
NextBackupWindow *BackupWindow `json:"next_backup_window,omitempty"`
|
||||||
Locked bool `json:"locked,bool,omitempty"`
|
SnapshotIDs []int `json:"snapshot_ids,omitempty"`
|
||||||
Status string `json:"status,omitempty"`
|
Features []string `json:"features,omitempty"`
|
||||||
Networks *Networks `json:"networks,omitempty"`
|
Locked bool `json:"locked,bool,omitempty"`
|
||||||
Created string `json:"created_at,omitempty"`
|
Status string `json:"status,omitempty"`
|
||||||
Kernel *Kernel `json:"kernel,omitempty"`
|
Networks *Networks `json:"networks,omitempty"`
|
||||||
Tags []string `json:"tags,ommitempty"`
|
Created string `json:"created_at,omitempty"`
|
||||||
VolumeIDs []string `json:"volumes"`
|
Kernel *Kernel `json:"kernel,omitempty"`
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
|
VolumeIDs []string `json:"volume_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublicIPv4 returns the public IPv4 address for the Droplet.
|
// PublicIPv4 returns the public IPv4 address for the Droplet.
|
||||||
|
@ -110,6 +112,12 @@ type Kernel struct {
|
||||||
Version string `json:"version,omitempty"`
|
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
|
// Convert Droplet to a string
|
||||||
func (d Droplet) String() string {
|
func (d Droplet) String() string {
|
||||||
return Stringify(d)
|
return Stringify(d)
|
||||||
|
@ -131,7 +139,7 @@ type kernelsRoot struct {
|
||||||
Links *Links `json:"links"`
|
Links *Links `json:"links"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type snapshotsRoot struct {
|
type dropletSnapshotsRoot struct {
|
||||||
Snapshots []Image `json:"snapshots,omitempty"`
|
Snapshots []Image `json:"snapshots,omitempty"`
|
||||||
Links *Links `json:"links"`
|
Links *Links `json:"links"`
|
||||||
}
|
}
|
||||||
|
@ -147,6 +155,16 @@ type DropletCreateImage struct {
|
||||||
Slug string
|
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
|
// DropletCreateVolume identifies a volume to attach for the create request. It
|
||||||
// prefers Name over ID,
|
// prefers Name over ID,
|
||||||
type DropletCreateVolume struct {
|
type DropletCreateVolume struct {
|
||||||
|
@ -168,16 +186,6 @@ func (d DropletCreateVolume) MarshalJSON() ([]byte, error) {
|
||||||
}{ID: d.ID})
|
}{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.
|
// DropletCreateSSHKey identifies a SSH Key for the create request. It prefers fingerprint over ID.
|
||||||
type DropletCreateSSHKey struct {
|
type DropletCreateSSHKey struct {
|
||||||
ID int
|
ID int
|
||||||
|
@ -194,7 +202,7 @@ func (d DropletCreateSSHKey) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(d.ID)
|
return json.Marshal(d.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropletCreateRequest represents a request to create a droplet.
|
// DropletCreateRequest represents a request to create a Droplet.
|
||||||
type DropletCreateRequest struct {
|
type DropletCreateRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
|
@ -204,11 +212,13 @@ type DropletCreateRequest struct {
|
||||||
Backups bool `json:"backups"`
|
Backups bool `json:"backups"`
|
||||||
IPv6 bool `json:"ipv6"`
|
IPv6 bool `json:"ipv6"`
|
||||||
PrivateNetworking bool `json:"private_networking"`
|
PrivateNetworking bool `json:"private_networking"`
|
||||||
|
Monitoring bool `json:"monitoring"`
|
||||||
UserData string `json:"user_data,omitempty"`
|
UserData string `json:"user_data,omitempty"`
|
||||||
Volumes []DropletCreateVolume `json:"volumes,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 {
|
type DropletMultiCreateRequest struct {
|
||||||
Names []string `json:"names"`
|
Names []string `json:"names"`
|
||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
|
@ -218,7 +228,9 @@ type DropletMultiCreateRequest struct {
|
||||||
Backups bool `json:"backups"`
|
Backups bool `json:"backups"`
|
||||||
IPv6 bool `json:"ipv6"`
|
IPv6 bool `json:"ipv6"`
|
||||||
PrivateNetworking bool `json:"private_networking"`
|
PrivateNetworking bool `json:"private_networking"`
|
||||||
|
Monitoring bool `json:"monitoring"`
|
||||||
UserData string `json:"user_data,omitempty"`
|
UserData string `json:"user_data,omitempty"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DropletCreateRequest) String() string {
|
func (d DropletCreateRequest) String() string {
|
||||||
|
@ -229,13 +241,13 @@ func (d DropletMultiCreateRequest) String() string {
|
||||||
return Stringify(d)
|
return Stringify(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networks represents the droplet's networks
|
// Networks represents the Droplet's Networks.
|
||||||
type Networks struct {
|
type Networks struct {
|
||||||
V4 []NetworkV4 `json:"v4,omitempty"`
|
V4 []NetworkV4 `json:"v4,omitempty"`
|
||||||
V6 []NetworkV6 `json:"v6,omitempty"`
|
V6 []NetworkV6 `json:"v6,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkV4 represents a DigitalOcean IPv4 Network
|
// NetworkV4 represents a DigitalOcean IPv4 Network.
|
||||||
type NetworkV4 struct {
|
type NetworkV4 struct {
|
||||||
IPAddress string `json:"ip_address,omitempty"`
|
IPAddress string `json:"ip_address,omitempty"`
|
||||||
Netmask string `json:"netmask,omitempty"`
|
Netmask string `json:"netmask,omitempty"`
|
||||||
|
@ -259,7 +271,7 @@ func (n NetworkV6) String() string {
|
||||||
return Stringify(n)
|
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) {
|
func (s *DropletsServiceOp) list(path string) ([]Droplet, *Response, error) {
|
||||||
req, err := s.client.NewRequest("GET", path, nil)
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -278,7 +290,7 @@ func (s *DropletsServiceOp) list(path string) ([]Droplet, *Response, error) {
|
||||||
return root.Droplets, resp, err
|
return root.Droplets, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// List all droplets
|
// List all Droplets.
|
||||||
func (s *DropletsServiceOp) List(opt *ListOptions) ([]Droplet, *Response, error) {
|
func (s *DropletsServiceOp) List(opt *ListOptions) ([]Droplet, *Response, error) {
|
||||||
path := dropletBasePath
|
path := dropletBasePath
|
||||||
path, err := addOptions(path, opt)
|
path, err := addOptions(path, opt)
|
||||||
|
@ -289,7 +301,7 @@ func (s *DropletsServiceOp) List(opt *ListOptions) ([]Droplet, *Response, error)
|
||||||
return s.list(path)
|
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) {
|
func (s *DropletsServiceOp) ListByTag(tag string, opt *ListOptions) ([]Droplet, *Response, error) {
|
||||||
path := fmt.Sprintf("%s?tag_name=%s", dropletBasePath, tag)
|
path := fmt.Sprintf("%s?tag_name=%s", dropletBasePath, tag)
|
||||||
path, err := addOptions(path, opt)
|
path, err := addOptions(path, opt)
|
||||||
|
@ -300,7 +312,7 @@ func (s *DropletsServiceOp) ListByTag(tag string, opt *ListOptions) ([]Droplet,
|
||||||
return s.list(path)
|
return s.list(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get individual droplet
|
// Get individual Droplet.
|
||||||
func (s *DropletsServiceOp) Get(dropletID int) (*Droplet, *Response, error) {
|
func (s *DropletsServiceOp) Get(dropletID int) (*Droplet, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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
|
return root.Droplet, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create droplet
|
// Create Droplet
|
||||||
func (s *DropletsServiceOp) Create(createRequest *DropletCreateRequest) (*Droplet, *Response, error) {
|
func (s *DropletsServiceOp) Create(createRequest *DropletCreateRequest) (*Droplet, *Response, error) {
|
||||||
if createRequest == nil {
|
if createRequest == nil {
|
||||||
return nil, nil, NewArgError("createRequest", "cannot be 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
|
return root.Droplet, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateMultiple creates multiple droplets.
|
// CreateMultiple creates multiple Droplets.
|
||||||
func (s *DropletsServiceOp) CreateMultiple(createRequest *DropletMultiCreateRequest) ([]Droplet, *Response, error) {
|
func (s *DropletsServiceOp) CreateMultiple(createRequest *DropletMultiCreateRequest) ([]Droplet, *Response, error) {
|
||||||
if createRequest == nil {
|
if createRequest == nil {
|
||||||
return nil, nil, NewArgError("createRequest", "cannot be nil")
|
return nil, nil, NewArgError("createRequest", "cannot be nil")
|
||||||
|
@ -384,7 +396,7 @@ func (s *DropletsServiceOp) delete(path string) (*Response, error) {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete droplet
|
// Delete Droplet.
|
||||||
func (s *DropletsServiceOp) Delete(dropletID int) (*Response, error) {
|
func (s *DropletsServiceOp) Delete(dropletID int) (*Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, NewArgError("dropletID", "cannot be less than 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)
|
return s.delete(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete droplets by tag
|
// DeleteByTag deletes Droplets matched by a Tag.
|
||||||
func (s *DropletsServiceOp) DeleteByTag(tag string) (*Response, error) {
|
func (s *DropletsServiceOp) DeleteByTag(tag string) (*Response, error) {
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
return nil, NewArgError("tag", "cannot be empty")
|
return nil, NewArgError("tag", "cannot be empty")
|
||||||
|
@ -406,7 +418,7 @@ func (s *DropletsServiceOp) DeleteByTag(tag string) (*Response, error) {
|
||||||
return s.delete(path)
|
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) {
|
func (s *DropletsServiceOp) Kernels(dropletID int, opt *ListOptions) ([]Kernel, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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
|
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) {
|
func (s *DropletsServiceOp) Actions(dropletID int, opt *ListOptions) ([]Action, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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
|
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) {
|
func (s *DropletsServiceOp) Backups(dropletID int, opt *ListOptions) ([]Image, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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
|
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) {
|
func (s *DropletsServiceOp) Snapshots(dropletID int, opt *ListOptions) ([]Image, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(snapshotsRoot)
|
root := new(dropletSnapshotsRoot)
|
||||||
resp, err := s.client.Do(req, root)
|
resp, err := s.client.Do(req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
|
@ -519,7 +531,7 @@ func (s *DropletsServiceOp) Snapshots(dropletID int, opt *ListOptions) ([]Image,
|
||||||
return root.Snapshots, resp, err
|
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) {
|
func (s *DropletsServiceOp) Neighbors(dropletID int) ([]Droplet, *Response, error) {
|
||||||
if dropletID < 1 {
|
if dropletID < 1 {
|
||||||
return nil, nil, NewArgError("dropletID", "cannot be less than 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 nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Event, resp, err
|
return root.Event, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FloatingIPActionsServiceOp) get(path string) (*Action, *Response, error) {
|
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 nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Event, resp, err
|
return root.Event, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FloatingIPActionsServiceOp) list(path string) ([]Action, *Response, error) {
|
func (s *FloatingIPActionsServiceOp) list(path string) ([]Action, *Response, error) {
|
||||||
|
|
|
@ -55,9 +55,11 @@ type Client struct {
|
||||||
Sizes SizesService
|
Sizes SizesService
|
||||||
FloatingIPs FloatingIPsService
|
FloatingIPs FloatingIPsService
|
||||||
FloatingIPActions FloatingIPActionsService
|
FloatingIPActions FloatingIPActionsService
|
||||||
|
Snapshots SnapshotsService
|
||||||
Storage StorageService
|
Storage StorageService
|
||||||
StorageActions StorageActionsService
|
StorageActions StorageActionsService
|
||||||
Tags TagsService
|
Tags TagsService
|
||||||
|
LoadBalancers LoadBalancersService
|
||||||
|
|
||||||
// Optional function called after every successful request made to the DO APIs
|
// Optional function called after every successful request made to the DO APIs
|
||||||
onRequestCompleted RequestCompletionCallback
|
onRequestCompleted RequestCompletionCallback
|
||||||
|
@ -155,16 +157,18 @@ func NewClient(httpClient *http.Client) *Client {
|
||||||
c.Domains = &DomainsServiceOp{client: c}
|
c.Domains = &DomainsServiceOp{client: c}
|
||||||
c.Droplets = &DropletsServiceOp{client: c}
|
c.Droplets = &DropletsServiceOp{client: c}
|
||||||
c.DropletActions = &DropletActionsServiceOp{client: c}
|
c.DropletActions = &DropletActionsServiceOp{client: c}
|
||||||
|
c.FloatingIPs = &FloatingIPsServiceOp{client: c}
|
||||||
|
c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c}
|
||||||
c.Images = &ImagesServiceOp{client: c}
|
c.Images = &ImagesServiceOp{client: c}
|
||||||
c.ImageActions = &ImageActionsServiceOp{client: c}
|
c.ImageActions = &ImageActionsServiceOp{client: c}
|
||||||
c.Keys = &KeysServiceOp{client: c}
|
c.Keys = &KeysServiceOp{client: c}
|
||||||
c.Regions = &RegionsServiceOp{client: c}
|
c.Regions = &RegionsServiceOp{client: c}
|
||||||
|
c.Snapshots = &SnapshotsServiceOp{client: c}
|
||||||
c.Sizes = &SizesServiceOp{client: c}
|
c.Sizes = &SizesServiceOp{client: c}
|
||||||
c.FloatingIPs = &FloatingIPsServiceOp{client: c}
|
|
||||||
c.FloatingIPActions = &FloatingIPActionsServiceOp{client: c}
|
|
||||||
c.Storage = &StorageServiceOp{client: c}
|
c.Storage = &StorageServiceOp{client: c}
|
||||||
c.StorageActions = &StorageActionsServiceOp{client: c}
|
c.StorageActions = &StorageActionsServiceOp{client: c}
|
||||||
c.Tags = &TagsServiceOp{client: c}
|
c.Tags = &TagsServiceOp{client: c}
|
||||||
|
c.LoadBalancers = &LoadBalancersServiceOp{client: c}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -218,7 +222,7 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
if body != nil {
|
if body != nil {
|
||||||
err := json.NewEncoder(buf).Encode(body)
|
err = json.NewEncoder(buf).Encode(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -310,12 +314,12 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
|
||||||
|
|
||||||
if v != nil {
|
if v != nil {
|
||||||
if w, ok := v.(io.Writer); ok {
|
if w, ok := v.(io.Writer); ok {
|
||||||
_, err := io.Copy(w, resp.Body)
|
_, err = io.Copy(w, resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := json.NewDecoder(resp.Body).Decode(v)
|
err = json.NewDecoder(resp.Body).Decode(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func (i *ImageActionsServiceOp) Transfer(imageID int, transferRequest *ActionReq
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Event, resp, err
|
return root.Event, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an action for a particular image by id.
|
// 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 nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Event, resp, err
|
return root.Event, resp, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ type ImageUpdateRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type imageRoot struct {
|
type imageRoot struct {
|
||||||
Image Image
|
Image *Image
|
||||||
}
|
}
|
||||||
|
|
||||||
type imagesRoot struct {
|
type imagesRoot struct {
|
||||||
|
@ -125,7 +125,7 @@ func (s *ImagesServiceOp) Update(imageID int, updateRequest *ImageUpdateRequest)
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Image, resp, err
|
return root.Image, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete an image.
|
// Delete an image.
|
||||||
|
@ -161,7 +161,7 @@ func (s *ImagesServiceOp) get(ID interface{}) (*Image, *Response, error) {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.Image, resp, err
|
return root.Image, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method for listing images
|
// Helper method for listing images
|
||||||
|
|
|
@ -45,7 +45,7 @@ type keysRoot struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type keyRoot struct {
|
type keyRoot struct {
|
||||||
SSHKey Key `json:"ssh_key"`
|
SSHKey *Key `json:"ssh_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Key) String() string {
|
func (s Key) String() string {
|
||||||
|
@ -96,7 +96,7 @@ func (s *KeysServiceOp) get(path string) (*Key, *Response, error) {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.SSHKey, resp, err
|
return root.SSHKey, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByID gets a Key by id
|
// GetByID gets a Key by id
|
||||||
|
@ -136,7 +136,7 @@ func (s *KeysServiceOp) Create(createRequest *KeyCreateRequest) (*Key, *Response
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.SSHKey, resp, err
|
return root.SSHKey, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateByID updates a key name by ID.
|
// UpdateByID updates a key name by ID.
|
||||||
|
@ -161,7 +161,7 @@ func (s *KeysServiceOp) UpdateByID(keyID int, updateRequest *KeyUpdateRequest) (
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.SSHKey, resp, err
|
return root.SSHKey, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateByFingerprint updates a key name by fingerprint.
|
// UpdateByFingerprint updates a key name by fingerprint.
|
||||||
|
@ -186,7 +186,7 @@ func (s *KeysServiceOp) UpdateByFingerprint(fingerprint string, updateRequest *K
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &root.SSHKey, resp, err
|
return root.SSHKey, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete key using a path
|
// Delete key using a path
|
||||||
|
|
|
@ -58,11 +58,7 @@ func (l *Links) IsLastPage() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pages) isLast() bool {
|
func (p *Pages) isLast() bool {
|
||||||
if p.Last == "" {
|
return p.Last == ""
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageForURL(urlText string) (int, error) {
|
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"`
|
Links *Links `json:"links"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type regionRoot struct {
|
|
||||||
Region Region
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Region) String() string {
|
func (r Region) String() string {
|
||||||
return Stringify(r)
|
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)
|
GetVolume(string) (*Volume, *Response, error)
|
||||||
CreateVolume(*VolumeCreateRequest) (*Volume, *Response, error)
|
CreateVolume(*VolumeCreateRequest) (*Volume, *Response, error)
|
||||||
DeleteVolume(string) (*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)
|
ListSnapshots(volumeID string, opts *ListOptions) ([]Snapshot, *Response, error)
|
||||||
GetSnapshot(string) (*Snapshot, *Response, error)
|
GetSnapshot(string) (*Snapshot, *Response, error)
|
||||||
CreateSnapshot(*SnapshotCreateRequest) (*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)
|
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
|
// SnapshotCreateRequest represents a request to create a block store
|
||||||
// volume.
|
// volume.
|
||||||
type SnapshotCreateRequest struct {
|
type SnapshotCreateRequest struct {
|
||||||
|
@ -192,7 +159,7 @@ func (svc *StorageServiceOp) ListSnapshots(volumeID string, opt *ListOptions) ([
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(storageSnapsRoot)
|
root := new(snapshotsRoot)
|
||||||
resp, err := svc.client.Do(req, root)
|
resp, err := svc.client.Do(req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
|
@ -214,7 +181,7 @@ func (svc *StorageServiceOp) CreateSnapshot(createRequest *SnapshotCreateRequest
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(storageSnapRoot)
|
root := new(snapshotRoot)
|
||||||
resp, err := svc.client.Do(req, root)
|
resp, err := svc.client.Do(req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
|
@ -231,7 +198,7 @@ func (svc *StorageServiceOp) GetSnapshot(id string) (*Snapshot, *Response, error
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(storageSnapRoot)
|
root := new(snapshotRoot)
|
||||||
resp, err := svc.client.Do(req, root)
|
resp, err := svc.client.Do(req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
|
|
|
@ -8,21 +8,25 @@ import "fmt"
|
||||||
type StorageActionsService interface {
|
type StorageActionsService interface {
|
||||||
Attach(volumeID string, dropletID int) (*Action, *Response, error)
|
Attach(volumeID string, dropletID int) (*Action, *Response, error)
|
||||||
Detach(volumeID string) (*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.
|
// action related methods of the DigitalOcean API.
|
||||||
type StorageActionsServiceOp struct {
|
type StorageActionsServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorageAttachment represents the attachement of a block storage
|
// 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 {
|
type StorageAttachment struct {
|
||||||
DropletID int `json:"droplet_id"`
|
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) {
|
func (s *StorageActionsServiceOp) Attach(volumeID string, dropletID int) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{
|
request := &ActionRequest{
|
||||||
"type": "attach",
|
"type": "attach",
|
||||||
|
@ -31,7 +35,7 @@ func (s *StorageActionsServiceOp) Attach(volumeID string, dropletID int) (*Actio
|
||||||
return s.doAction(volumeID, request)
|
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) {
|
func (s *StorageActionsServiceOp) Detach(volumeID string) (*Action, *Response, error) {
|
||||||
request := &ActionRequest{
|
request := &ActionRequest{
|
||||||
"type": "detach",
|
"type": "detach",
|
||||||
|
@ -39,6 +43,42 @@ func (s *StorageActionsServiceOp) Detach(volumeID string) (*Action, *Response, e
|
||||||
return s.doAction(volumeID, request)
|
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) {
|
func (s *StorageActionsServiceOp) doAction(volumeID string, request *ActionRequest) (*Action, *Response, error) {
|
||||||
path := storageAllocationActionPath(volumeID)
|
path := storageAllocationActionPath(volumeID)
|
||||||
|
|
||||||
|
@ -53,7 +93,40 @@ func (s *StorageActionsServiceOp) doAction(volumeID string, request *ActionReque
|
||||||
return nil, resp, err
|
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 {
|
func storageAllocationActionPath(volumeID string) string {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package godo
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ func Stringify(message interface{}) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// stringifyValue was graciously cargoculted from the goprotubuf library
|
// 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() {
|
if val.Kind() == reflect.Ptr && val.IsNil() {
|
||||||
_, _ = w.Write([]byte("<nil>"))
|
_, _ = w.Write([]byte("<nil>"))
|
||||||
return
|
return
|
||||||
|
@ -29,55 +30,63 @@ func stringifyValue(w *bytes.Buffer, val reflect.Value) {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
fmt.Fprintf(w, `"%s"`, v)
|
fmt.Fprintf(w, `"%s"`, v)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
_, _ = w.Write([]byte{'['})
|
stringifySlice(w, v)
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
if i > 0 {
|
|
||||||
_, _ = w.Write([]byte{' '})
|
|
||||||
}
|
|
||||||
|
|
||||||
stringifyValue(w, v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = w.Write([]byte{']'})
|
|
||||||
return
|
return
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if v.Type().Name() != "" {
|
stringifyStruct(w, v)
|
||||||
_, _ = 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{'}'})
|
|
||||||
default:
|
default:
|
||||||
if v.CanInterface() {
|
if v.CanInterface() {
|
||||||
fmt.Fprint(w, v.Interface())
|
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
|
type ResourceType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
//DropletResourceType holds the string representing our ResourceType of Droplet.
|
||||||
DropletResourceType ResourceType = "droplet"
|
DropletResourceType ResourceType = "droplet"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,18 +57,22 @@ type Tag struct {
|
||||||
Resources *TaggedResources `json:"resources,omitempty"`
|
Resources *TaggedResources `json:"resources,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TagCreateRequest represents the JSON structure of a request of that type.
|
||||||
type TagCreateRequest struct {
|
type TagCreateRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TagUpdateRequest represents the JSON structure of a request of that type.
|
||||||
type TagUpdateRequest struct {
|
type TagUpdateRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TagResourcesRequest represents the JSON structure of a request of that type.
|
||||||
type TagResourcesRequest struct {
|
type TagResourcesRequest struct {
|
||||||
Resources []Resource `json:"resources"`
|
Resources []Resource `json:"resources"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UntagResourcesRequest represents the JSON structure of a request of that type.
|
||||||
type UntagResourcesRequest struct {
|
type UntagResourcesRequest struct {
|
||||||
Resources []Resource `json:"resources"`
|
Resources []Resource `json:"resources"`
|
||||||
}
|
}
|
||||||
|
@ -183,7 +188,7 @@ func (s *TagsServiceOp) Delete(name string) (*Response, error) {
|
||||||
return resp, err
|
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) {
|
func (s *TagsServiceOp) TagResources(name string, tagRequest *TagResourcesRequest) (*Response, error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil, NewArgError("name", "cannot be empty")
|
return nil, NewArgError("name", "cannot be empty")
|
||||||
|
@ -204,7 +209,7 @@ func (s *TagsServiceOp) TagResources(name string, tagRequest *TagResourcesReques
|
||||||
return resp, err
|
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) {
|
func (s *TagsServiceOp) UntagResources(name string, untagRequest *UntagResourcesRequest) (*Response, error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil, NewArgError("name", "cannot be empty")
|
return nil, NewArgError("name", "cannot be empty")
|
||||||
|
|
|
@ -1230,11 +1230,11 @@
|
||||||
"revisionTime": "2016-06-17T17:01:58Z"
|
"revisionTime": "2016-06-17T17:01:58Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "mbMr6wMbQnMrfIwUtej8QcGsx0A=",
|
"checksumSHA1": "tOlmmumwQ9pCv5cQgs+W7sgPVgU=",
|
||||||
"comment": "v0.9.0-20-gf75d769",
|
"comment": "v0.9.0-20-gf75d769",
|
||||||
"path": "github.com/digitalocean/godo",
|
"path": "github.com/digitalocean/godo",
|
||||||
"revision": "e03ac28c3d9b216f7e9ed16bc6aa39e344d56491",
|
"revision": "767976000cc435d38646653b52be9be572727f30",
|
||||||
"revisionTime": "2016-06-27T19:55:12Z"
|
"revisionTime": "2017-02-14T20:43:37Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "zkENTbOfU8YoxPfFwVAhTz516Dg=",
|
"checksumSHA1": "zkENTbOfU8YoxPfFwVAhTz516Dg=",
|
||||||
|
|
Loading…
Reference in New Issue