provider/digitalocean: Bump SDK version of godo for loadbalancer support (#11964)

This commit is contained in:
Paul Stack 2017-02-15 14:35:41 +00:00 committed by GitHub
parent d29f2d6f6d
commit f681fbf4f6
17 changed files with 665 additions and 193 deletions

View File

@ -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 {

View File

@ -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
}

View File

@ -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")

View File

@ -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) {

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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) {

274
vendor/github.com/digitalocean/godo/load_balancers.go generated vendored Executable file
View File

@ -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)
}

View File

@ -29,10 +29,6 @@ type regionsRoot struct {
Links *Links `json:"links"`
}
type regionRoot struct {
Region Region
}
func (r Region) String() string {
return Stringify(r)
}

136
vendor/github.com/digitalocean/godo/snapshots.go generated vendored Normal file
View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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{'}'})
}

View File

@ -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")

6
vendor/vendor.json vendored
View File

@ -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=",