From c780172c682996f0456171b13a2913792c551118 Mon Sep 17 00:00:00 2001
From: cliedeman
Date: Mon, 3 Sep 2018 15:34:11 +0200
Subject: [PATCH 01/18] Adding Nodebalancer rebuild
---
nodebalancer.go | 7 +++---
nodebalancer_configs.go | 54 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/nodebalancer.go b/nodebalancer.go
index bc6fc0a07..22e6e60e3 100644
--- a/nodebalancer.go
+++ b/nodebalancer.go
@@ -44,9 +44,10 @@ type NodeBalancerTransfer struct {
// NodeBalancerCreateOptions are the options permitted for CreateNodeBalancer
type NodeBalancerCreateOptions struct {
- Label *string `json:"label,omitempty"`
- Region string `json:"region,omitempty"`
- ClientConnThrottle *int `json:"client_conn_throttle,omitempty"`
+ Label *string `json:"label,omitempty"`
+ Region string `json:"region,omitempty"`
+ ClientConnThrottle *int `json:"client_conn_throttle,omitempty"`
+ Configs []*NodeBalancerConfigCreateOptions `json:"configs,omitempty"`
}
// NodeBalancerUpdateOptions are the options permitted for UpdateNodeBalancer
diff --git a/nodebalancer_configs.go b/nodebalancer_configs.go
index babbcb35f..d4538b396 100644
--- a/nodebalancer_configs.go
+++ b/nodebalancer_configs.go
@@ -103,6 +103,33 @@ type NodeBalancerConfigCreateOptions struct {
SSLKey string `json:"ssl_key,omitempty"`
}
+// NodeBalancerConfigRebuildOptionsNode for a nodebalancer instance mapping
+type NodeBalancerConfigRebuildOptionsNode struct {
+ Address *string `json:"address"`
+ Label *string `json:"label"`
+ Weight *int `json:"weight"`
+ Mode *string `json:"mode"`
+}
+
+// NodeBalancerConfigRebuildOptions used by RebuildNodeBalancerConfig
+type NodeBalancerConfigRebuildOptions struct {
+ Port int `json:"port"`
+ Protocol ConfigProtocol `json:"protocol,omitempty"`
+ Algorithm ConfigAlgorithm `json:"algorithm,omitempty"`
+ Stickiness ConfigStickiness `json:"stickiness,omitempty"`
+ Check ConfigCheck `json:"check,omitempty"`
+ CheckInterval int `json:"check_interval,omitempty"`
+ CheckAttempts int `json:"check_attempts,omitempty"`
+ CheckPath string `json:"check_path,omitempty"`
+ CheckBody string `json:"check_body,omitempty"`
+ CheckPassive *bool `json:"check_passive,omitempty"`
+ CheckTimeout int `json:"check_timeout,omitempty"`
+ CipherSuite ConfigCipher `json:"cipher_suite,omitempty"`
+ SSLCert string `json:"ssl_cert,omitempty"`
+ SSLKey string `json:"ssl_key,omitempty"`
+ Nodes []*NodeBalancerConfigRebuildOptionsNode `json:"nodes,omitempty"`
+}
+
// NodeBalancerConfigUpdateOptions are permitted by UpdateNodeBalancerConfig
type NodeBalancerConfigUpdateOptions NodeBalancerConfigCreateOptions
@@ -264,3 +291,30 @@ func (c *Client) DeleteNodeBalancerConfig(ctx context.Context, nodebalancerID in
_, err = coupleAPIErrors(c.R(ctx).Delete(e))
return err
}
+
+// RebuildNodeBalancerConfig updates the NodeBalancer with the specified id
+func (c *Client) RebuildNodeBalancerConfig(ctx context.Context, nodeBalancerID int, configID int, rebuildOpts NodeBalancerConfigRebuildOptions) (*NodeBalancer, error) {
+ var body string
+ e, err := c.NodeBalancerConfigs.endpointWithID(nodeBalancerID)
+ if err != nil {
+ return nil, err
+ }
+ e = fmt.Sprintf("%s/%d/rebuild", e, configID)
+
+ req := c.R(ctx).SetResult(&NodeBalancer{})
+
+ if bodyData, err := json.Marshal(rebuildOpts); err == nil {
+ body = string(bodyData)
+ } else {
+ return nil, NewError(err)
+ }
+
+ r, err := coupleAPIErrors(req.
+ SetBody(body).
+ Put(e))
+
+ if err != nil {
+ return nil, err
+ }
+ return r.Result().(*NodeBalancer).fixDates(), nil
+}
From 14df0566c96e8bdb3eaacea130d72d48c1f549a8 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Mon, 3 Sep 2018 13:50:59 -0400
Subject: [PATCH 02/18] devices are optional for InstanceConfigUpdateOptions
---
instance_configs.go | 10 +++++-----
waitfor.go | 1 +
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/instance_configs.go b/instance_configs.go
index 1a7adceb1..8da71ca5f 100644
--- a/instance_configs.go
+++ b/instance_configs.go
@@ -76,10 +76,10 @@ type InstanceConfigCreateOptions struct {
// InstanceConfigUpdateOptions are InstanceConfig settings that can be used in updates
type InstanceConfigUpdateOptions struct {
- Label string `json:"label,omitempty"`
- Comments string `json:"comments"`
- Devices InstanceConfigDeviceMap `json:"devices"`
- Helpers *InstanceConfigHelpers `json:"helpers,omitempty"`
+ Label string `json:"label,omitempty"`
+ Comments string `json:"comments"`
+ Devices *InstanceConfigDeviceMap `json:"devices,omitempty"`
+ Helpers *InstanceConfigHelpers `json:"helpers,omitempty"`
// MemoryLimit 0 means unlimitted, this is not omitted
MemoryLimit int `json:"memory_limit"`
Kernel string `json:"kernel,omitempty"`
@@ -111,7 +111,7 @@ func (i InstanceConfig) GetUpdateOptions() InstanceConfigUpdateOptions {
return InstanceConfigUpdateOptions{
Label: i.Label,
Comments: i.Comments,
- Devices: *i.Devices,
+ Devices: i.Devices,
Helpers: i.Helpers,
MemoryLimit: i.MemoryLimit,
Kernel: i.Kernel,
diff --git a/waitfor.go b/waitfor.go
index 420423da8..2203f76b1 100644
--- a/waitfor.go
+++ b/waitfor.go
@@ -226,6 +226,7 @@ func (client Client) WaitForEventFinished(ctx context.Context, id interface{}, e
log.Printf("[INFO] %s %v action %s is finished", titledEntityType, id, action)
return event, nil
}
+ // TODO(displague) can we bump the ticker to TimeRemaining/2 (>=1) when non-nil?
log.Printf("[INFO] %s %v action %s is %s", titledEntityType, id, action, event.Status)
}
case <-ctx.Done():
From 24611be5de3c8b78debf69847cb837e4be9c0815 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Mon, 3 Sep 2018 14:01:46 -0400
Subject: [PATCH 03/18] fix event parsing of time_remaining which may be int,
string, or null
---
account_events.go | 49 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/account_events.go b/account_events.go
index 527fe3074..05f39030c 100644
--- a/account_events.go
+++ b/account_events.go
@@ -2,7 +2,10 @@ package linodego
import (
"context"
+ "encoding/json"
"fmt"
+ "strconv"
+ "strings"
"time"
)
@@ -23,7 +26,7 @@ type Event struct {
PercentComplete int `json:"percent_complete"`
// The rate of completion of the Event. Only some Events will return rate; for example, migration and resize Events.
- Rate string `json:"rate"`
+ Rate *string `json:"rate"`
// If this Event has been read.
Read bool `json:"read"`
@@ -32,7 +35,8 @@ type Event struct {
Seen bool `json:"seen"`
// The estimated time remaining until the completion of this Event. This value is only returned for in-progress events.
- TimeRemaining int `json:"time_remaining"`
+ TimeRemainingMsg json.RawMessage `json:"time_remaining"`
+ TimeRemaining *int `json:"-"`
// The username of the User who caused the Event.
Username string `json:"username"`
@@ -200,6 +204,7 @@ func (c *Client) GetEvent(ctx context.Context, id int) (*Event, error) {
// fixDates converts JSON timestamps to Go time.Time values
func (e *Event) fixDates() *Event {
e.Created, _ = parseDates(e.CreatedStr)
+ e.TimeRemaining = unmarshalTimeRemaining(e.TimeRemainingMsg)
return e
}
@@ -222,3 +227,43 @@ func (c *Client) MarkEventsSeen(ctx context.Context, event *Event) error {
return err
}
+
+func unmarshalTimeRemaining(m json.RawMessage) *int {
+ var intPtr *int
+ jsonBytes, err := m.MarshalJSON()
+ if err != nil {
+ panic(err)
+ }
+ if err := json.Unmarshal(jsonBytes, intPtr); err == nil {
+ return intPtr
+ }
+ var timeStr string
+ if err := json.Unmarshal(jsonBytes, timeStr); err == nil {
+ if dur, err := durationToSeconds(timeStr); err != nil {
+ panic(err)
+ } else {
+ return &dur
+ }
+ }
+
+ return nil
+}
+
+// durationToSeconds takes a hh:mm:ss string and returns the number of seconds
+func durationToSeconds(s string) (int, error) {
+ multipliers := [3]int{60 * 60, 60, 1}
+ segs := strings.Split(s, ":")
+ if len(segs) > len(multipliers) {
+ return 0, fmt.Errorf("too many ':' separators in time duration: %s", s)
+ }
+ var d int
+ l := len(segs)
+ for i := 0; i < l; i++ {
+ m, err := strconv.Atoi(segs[i])
+ if err != nil {
+ return 0, err
+ }
+ d += m * multipliers[i+len(multipliers)-l]
+ }
+ return d, nil
+}
From cd81cca830323670725d0b66bb04e164b36d29e3 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Mon, 3 Sep 2018 14:05:46 -0400
Subject: [PATCH 04/18] instance_config: make null and "" options possible for
init_rd and root_device
---
instance_configs.go | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/instance_configs.go b/instance_configs.go
index 8da71ca5f..d9b0f333b 100644
--- a/instance_configs.go
+++ b/instance_configs.go
@@ -69,7 +69,7 @@ type InstanceConfigCreateOptions struct {
MemoryLimit int `json:"memory_limit,omitempty"`
Kernel string `json:"kernel,omitempty"`
InitRD int `json:"init_rd,omitempty"`
- RootDevice string `json:"root_device,omitempty"`
+ RootDevice *string `json:"root_device,omitempty"`
RunLevel string `json:"run_level,omitempty"`
VirtMode string `json:"virt_mode,omitempty"`
}
@@ -84,14 +84,18 @@ type InstanceConfigUpdateOptions struct {
MemoryLimit int `json:"memory_limit"`
Kernel string `json:"kernel,omitempty"`
// InitRD is nullable, permit the sending of null
- InitRD *int `json:"init_rd"`
- RootDevice string `json:"root_device,omitempty"`
- RunLevel string `json:"run_level,omitempty"`
- VirtMode string `json:"virt_mode,omitempty"`
+ InitRD *int `json:"init_rd"`
+ RootDevice *string `json:"root_device,omitempty"`
+ RunLevel string `json:"run_level,omitempty"`
+ VirtMode string `json:"virt_mode,omitempty"`
}
// GetCreateOptions converts a InstanceConfig to InstanceConfigCreateOptions for use in CreateInstanceConfig
func (i InstanceConfig) GetCreateOptions() InstanceConfigCreateOptions {
+ initrd := 0
+ if i.InitRD != nil {
+ initrd = *i.InitRD
+ }
return InstanceConfigCreateOptions{
Label: i.Label,
Comments: i.Comments,
@@ -99,8 +103,8 @@ func (i InstanceConfig) GetCreateOptions() InstanceConfigCreateOptions {
Helpers: i.Helpers,
MemoryLimit: i.MemoryLimit,
Kernel: i.Kernel,
- InitRD: *i.InitRD,
- RootDevice: i.RootDevice,
+ InitRD: initrd,
+ RootDevice: copyString(&i.RootDevice),
RunLevel: i.RunLevel,
VirtMode: i.VirtMode,
}
@@ -116,7 +120,7 @@ func (i InstanceConfig) GetUpdateOptions() InstanceConfigUpdateOptions {
MemoryLimit: i.MemoryLimit,
Kernel: i.Kernel,
InitRD: copyInt(i.InitRD),
- RootDevice: i.RootDevice,
+ RootDevice: copyString(&i.RootDevice),
RunLevel: i.RunLevel,
VirtMode: i.VirtMode,
}
From 86c70be4713f54d9df9bf8264673781c6f499db4 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Mon, 3 Sep 2018 22:38:20 -0400
Subject: [PATCH 05/18] disable gosec lint tests
---
.travis.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 272f1b172..b520a18d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,8 +15,8 @@ install:
script:
- touch .env
- make test ARGS='-coverprofile=coverage.txt -covermode=atomic'
- - gometalinter.v2 --enable-all --disable=vetshadow --disable=gocyclo --disable=unparam --disable=nakedret --disable=lll --disable=dupl --disable=gochecknoinits --disable=gochecknoglobals --disable=test --deadline=120s
- - gometalinter.v2 --disable-all --enable=vetshadow --enable=gocyclo --enable=unparam --enable=nakedret --enable=lll --enable=dupl --enable=gochecknoinits --enable=gochecknoglobals --deadline=120s || true
+ - gometalinter.v2 --enable-all --disable=vetshadow --disable=gocyclo --disable=unparam --disable=nakedret --disable=lll --disable=dupl --disable=gosec --disable=gochecknoinits --disable=gochecknoglobals --disable=test --deadline=120s
+ - gometalinter.v2 --disable-all --enable=vetshadow --enable=gocyclo --enable=unparam --enable=nakedret --enable=lll --enable=dupl --enable=gosec --enable=gochecknoinits --enable=gochecknoglobals --deadline=120s || true
after_success:
- bash <(curl -s https://codecov.io/bash)
From ec78d2cbb804afbda57a48d3e25d4744d561a47d Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Mon, 3 Sep 2018 23:41:24 -0400
Subject: [PATCH 06/18] add tests and fixtures for account/events
time_remaining
---
account_events.go | 8 +--
account_events_test.go | 32 ++++++++++
fixtures/TestListEvents_resizing.yaml | 87 +++++++++++++++++++++++++++
3 files changed, 123 insertions(+), 4 deletions(-)
create mode 100644 account_events_test.go
create mode 100644 fixtures/TestListEvents_resizing.yaml
diff --git a/account_events.go b/account_events.go
index 05f39030c..4905b1184 100644
--- a/account_events.go
+++ b/account_events.go
@@ -234,12 +234,12 @@ func unmarshalTimeRemaining(m json.RawMessage) *int {
if err != nil {
panic(err)
}
- if err := json.Unmarshal(jsonBytes, intPtr); err == nil {
+ if err := json.Unmarshal(jsonBytes, intPtr); err == nil && intPtr != nil {
return intPtr
}
- var timeStr string
- if err := json.Unmarshal(jsonBytes, timeStr); err == nil {
- if dur, err := durationToSeconds(timeStr); err != nil {
+ var timeStr *string
+ if err := json.Unmarshal(jsonBytes, timeStr); err == nil && timeStr != nil {
+ if dur, err := durationToSeconds(*timeStr); err != nil {
panic(err)
} else {
return &dur
diff --git a/account_events_test.go b/account_events_test.go
new file mode 100644
index 000000000..d4602f22e
--- /dev/null
+++ b/account_events_test.go
@@ -0,0 +1,32 @@
+package linodego_test
+
+import (
+ "context"
+ "testing"
+)
+
+func TestListEvents_resizing(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping test in short mode.")
+ }
+
+ client, teardown := createTestClient(t, "fixtures/TestListEvents_resizing")
+ defer teardown()
+
+ events, err := client.ListEvents(context.Background(), nil)
+ if err != nil {
+ t.Errorf("Error getting Events, expected struct, got error %v", err)
+ }
+
+ if events[2].TimeRemaining != nil {
+ t.Errorf("Error listing Events, expected resize event time_remaining to be nil, got %v", events[2].TimeRemaining)
+ }
+
+ if events[1].TimeRemaining == nil || *events[1].TimeRemaining != 0 {
+ t.Errorf("Error listing Events, expected resize event time_remaining to be 0 seconds, got %v", events[1].TimeRemaining)
+ }
+
+ if events[0].TimeRemaining == nil || *events[0].TimeRemaining != 60+23 {
+ t.Errorf("Error listing Events, expected resize event time_remaining to be 83 seconds, got %v", events[0].TimeRemaining)
+ }
+}
diff --git a/fixtures/TestListEvents_resizing.yaml b/fixtures/TestListEvents_resizing.yaml
new file mode 100644
index 000000000..b3d1eaf28
--- /dev/null
+++ b/fixtures/TestListEvents_resizing.yaml
@@ -0,0 +1,87 @@
+---
+version: 1
+interactions:
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.1.1 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/account/events
+ method: GET
+ response:
+ body: '{"data": [{"created": "2018-01-02T03:04:05", "username": "restricted_tester",
+ "status": "resizing", "time_remaining": "1:23", "id": 11846172, "percent_complete":
+ 0, "entity": {"label": "linodego-test-instance", "url": "/v4/linode/instances/9588435",
+ "id": 9588435, "type": "linode"}, "read": false, "rate": "1.23 MB/s", "seen": false,
+ "action": "linode_resize"}, {"created": "2018-01-02T03:04:05", "username": "restricted_tester",
+ "status": "finished", "time_remaining": 0, "id": 11846182, "percent_complete":
+ 100, "entity": {"label": "linodego-test-instance", "url": "/v4/linode/instances/9588435",
+ "id": 9588435, "type": "linode"}, "read": false, "rate": null, "seen": false,
+ "action": "linode_resize"},{"created": "2018-01-02T03:04:05", "username": "restricted_tester",
+ "status": "finished", "time_remaining": null, "id": 11846192, "percent_complete":
+ null, "entity": {"label": "linodego-test-instance", "url": "/v4/linode/instances/9588435",
+ "id": 9588435, "type": "linode"}, "read": false, "rate": null, "seen": false,
+ "action": "linode_resize"}], "page": 1, "pages": 1, "results": 3}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=0, s-maxage=0, no-cache, no-store
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "35494"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 11 Aug 2018 00:02:11 GMT
+ Retry-After:
+ - "114"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - events:read_only
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "397"
+ X-Ratelimit-Reset:
+ - "1533945846"
+ X-Spec-Version:
+ - 4.0.3
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
From f701f1a69e978c07f166936453636bea8b178251 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Wed, 5 Sep 2018 22:55:30 -0400
Subject: [PATCH 07/18] List*: use slice of thing, not slice of pointer
---
account_events.go | 6 +++---
account_invoices.go | 12 ++++++------
account_notifications.go | 6 +++---
domain_records.go | 6 +++---
domain_records_test.go | 2 +-
domains.go | 6 +++---
images.go | 6 +++---
instance_configs.go | 6 +++---
instance_disks.go | 6 +++---
instance_volumes.go | 6 +++---
instances.go | 6 +++---
kernels.go | 6 +++---
longview.go | 6 +++---
longview_subscriptions.go | 6 +++---
network_ips.go | 6 +++---
network_pools.go | 6 +++---
network_ranges.go | 6 +++---
nodebalancer.go | 6 +++---
nodebalancer_config_nodes.go | 6 +++---
nodebalancer_configs.go | 6 +++---
regions.go | 6 +++---
stackscripts.go | 6 +++---
support.go | 6 +++---
template.go | 6 +++---
types.go | 6 +++---
volumes.go | 6 +++---
waitfor.go | 4 ++--
27 files changed, 81 insertions(+), 81 deletions(-)
diff --git a/account_events.go b/account_events.go
index 527fe3074..d1cbab4bc 100644
--- a/account_events.go
+++ b/account_events.go
@@ -141,7 +141,7 @@ type EventEntity struct {
// EventsPagedResponse represents a paginated Events API response
type EventsPagedResponse struct {
*PageOptions
- Data []*Event `json:"data"`
+ Data []Event `json:"data"`
}
// endpoint gets the endpoint URL for Event
@@ -165,13 +165,13 @@ func (e Event) endpointWithID(c *Client) string {
// appendData appends Events when processing paginated Event responses
func (resp *EventsPagedResponse) appendData(r *EventsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListEvents gets a collection of Event objects representing actions taken
// on the Account. The Events returned depend on the token grants and the grants
// of the associated user.
-func (c *Client) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, error) {
+func (c *Client) ListEvents(ctx context.Context, opts *ListOptions) ([]Event, error) {
response := EventsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/account_invoices.go b/account_invoices.go
index 200398715..22b9fcc18 100644
--- a/account_invoices.go
+++ b/account_invoices.go
@@ -33,7 +33,7 @@ type InvoiceItem struct {
// InvoicesPagedResponse represents a paginated Invoice API response
type InvoicesPagedResponse struct {
*PageOptions
- Data []*Invoice `json:"data"`
+ Data []Invoice `json:"data"`
}
// endpoint gets the endpoint URL for Invoice
@@ -47,11 +47,11 @@ func (InvoicesPagedResponse) endpoint(c *Client) string {
// appendData appends Invoices when processing paginated Invoice responses
func (resp *InvoicesPagedResponse) appendData(r *InvoicesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListInvoices gets a paginated list of Invoices against the Account
-func (c *Client) ListInvoices(ctx context.Context, opts *ListOptions) ([]*Invoice, error) {
+func (c *Client) ListInvoices(ctx context.Context, opts *ListOptions) ([]Invoice, error) {
response := InvoicesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
@@ -94,7 +94,7 @@ func (c *Client) GetInvoice(ctx context.Context, id int) (*Invoice, error) {
// InvoiceItemsPagedResponse represents a paginated Invoice Item API response
type InvoiceItemsPagedResponse struct {
*PageOptions
- Data []*InvoiceItem `json:"data"`
+ Data []InvoiceItem `json:"data"`
}
// endpointWithID gets the endpoint URL for InvoiceItems associated with a specific Invoice
@@ -108,11 +108,11 @@ func (InvoiceItemsPagedResponse) endpointWithID(c *Client, id int) string {
// appendData appends InvoiceItems when processing paginated Invoice Item responses
func (resp *InvoiceItemsPagedResponse) appendData(r *InvoiceItemsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListInvoiceItems gets the invoice items associated with a specific Invoice
-func (c *Client) ListInvoiceItems(ctx context.Context, id int, opts *ListOptions) ([]*InvoiceItem, error) {
+func (c *Client) ListInvoiceItems(ctx context.Context, id int, opts *ListOptions) ([]InvoiceItem, error) {
response := InvoiceItemsPagedResponse{}
err := c.listHelperWithID(ctx, &response, id, opts)
for _, el := range response.Data {
diff --git a/account_notifications.go b/account_notifications.go
index f5a35e093..59504dae8 100644
--- a/account_notifications.go
+++ b/account_notifications.go
@@ -31,7 +31,7 @@ type NotificationEntity struct {
// NotificationsPagedResponse represents a paginated Notifications API response
type NotificationsPagedResponse struct {
*PageOptions
- Data []*Notification `json:"data"`
+ Data []Notification `json:"data"`
}
// endpoint gets the endpoint URL for Notification
@@ -45,7 +45,7 @@ func (NotificationsPagedResponse) endpoint(c *Client) string {
// appendData appends Notifications when processing paginated Notification responses
func (resp *NotificationsPagedResponse) appendData(r *NotificationsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListNotifications gets a collection of Notification objects representing important,
@@ -53,7 +53,7 @@ func (resp *NotificationsPagedResponse) appendData(r *NotificationsPagedResponse
// Notifications, and a Notification will disappear when the circumstances causing it
// have been resolved. For example, if the account has an important Ticket open, a response
// to the Ticket will dismiss the Notification.
-func (c *Client) ListNotifications(ctx context.Context, opts *ListOptions) ([]*Notification, error) {
+func (c *Client) ListNotifications(ctx context.Context, opts *ListOptions) ([]Notification, error) {
response := NotificationsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/domain_records.go b/domain_records.go
index b2ff8e0c1..2ebbff5b7 100644
--- a/domain_records.go
+++ b/domain_records.go
@@ -99,7 +99,7 @@ func copyString(sPtr *string) *string {
// DomainRecordsPagedResponse represents a paginated DomainRecord API response
type DomainRecordsPagedResponse struct {
*PageOptions
- Data []*DomainRecord `json:"data"`
+ Data []DomainRecord `json:"data"`
}
// endpoint gets the endpoint URL for InstanceConfig
@@ -113,11 +113,11 @@ func (DomainRecordsPagedResponse) endpointWithID(c *Client, id int) string {
// appendData appends DomainRecords when processing paginated DomainRecord responses
func (resp *DomainRecordsPagedResponse) appendData(r *DomainRecordsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListDomainRecords lists DomainRecords
-func (c *Client) ListDomainRecords(ctx context.Context, domainID int, opts *ListOptions) ([]*DomainRecord, error) {
+func (c *Client) ListDomainRecords(ctx context.Context, domainID int, opts *ListOptions) ([]DomainRecord, error) {
response := DomainRecordsPagedResponse{}
err := c.listHelperWithID(ctx, &response, domainID, opts)
if err != nil {
diff --git a/domain_records_test.go b/domain_records_test.go
index e5ee2331e..154cecb30 100644
--- a/domain_records_test.go
+++ b/domain_records_test.go
@@ -107,7 +107,7 @@ func TestListDomainRecordsMultiplePages(t *testing.T) {
t.Errorf("Error listing domains records, expected array, got error %v", err)
}
if len(records) != 2 {
- t.Errorf("Expected ListDomainRecords to match one result")
+ t.Errorf("Expected ListDomainRecords to match two results")
}
}
diff --git a/domains.go b/domains.go
index 207d93117..f0f048a82 100644
--- a/domains.go
+++ b/domains.go
@@ -173,7 +173,7 @@ func (d Domain) GetUpdateOptions() (du DomainUpdateOptions) {
// DomainsPagedResponse represents a paginated Domain API response
type DomainsPagedResponse struct {
*PageOptions
- Data []*Domain `json:"data"`
+ Data []Domain `json:"data"`
}
// endpoint gets the endpoint URL for Domain
@@ -187,11 +187,11 @@ func (DomainsPagedResponse) endpoint(c *Client) string {
// appendData appends Domains when processing paginated Domain responses
func (resp *DomainsPagedResponse) appendData(r *DomainsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListDomains lists Domains
-func (c *Client) ListDomains(ctx context.Context, opts *ListOptions) ([]*Domain, error) {
+func (c *Client) ListDomains(ctx context.Context, opts *ListOptions) ([]Domain, error) {
response := DomainsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/images.go b/images.go
index 814c0a0a8..1ed99fa3d 100644
--- a/images.go
+++ b/images.go
@@ -54,7 +54,7 @@ func (i Image) GetUpdateOptions() (iu ImageUpdateOptions) {
// ImagesPagedResponse represents a linode API response for listing of images
type ImagesPagedResponse struct {
*PageOptions
- Data []*Image `json:"data"`
+ Data []Image `json:"data"`
}
func (ImagesPagedResponse) endpoint(c *Client) string {
@@ -66,11 +66,11 @@ func (ImagesPagedResponse) endpoint(c *Client) string {
}
func (resp *ImagesPagedResponse) appendData(r *ImagesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListImages lists Images
-func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]*Image, error) {
+func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]Image, error) {
response := ImagesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/instance_configs.go b/instance_configs.go
index 1a7adceb1..3980e8fbc 100644
--- a/instance_configs.go
+++ b/instance_configs.go
@@ -57,7 +57,7 @@ type InstanceConfigHelpers struct {
// InstanceConfigsPagedResponse represents a paginated InstanceConfig API response
type InstanceConfigsPagedResponse struct {
*PageOptions
- Data []*InstanceConfig `json:"data"`
+ Data []InstanceConfig `json:"data"`
}
// InstanceConfigCreateOptions are InstanceConfig settings that can be used at creation
@@ -133,11 +133,11 @@ func (InstanceConfigsPagedResponse) endpointWithID(c *Client, id int) string {
// appendData appends InstanceConfigs when processing paginated InstanceConfig responses
func (resp *InstanceConfigsPagedResponse) appendData(r *InstanceConfigsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListInstanceConfigs lists InstanceConfigs
-func (c *Client) ListInstanceConfigs(ctx context.Context, linodeID int, opts *ListOptions) ([]*InstanceConfig, error) {
+func (c *Client) ListInstanceConfigs(ctx context.Context, linodeID int, opts *ListOptions) ([]InstanceConfig, error) {
response := InstanceConfigsPagedResponse{}
err := c.listHelperWithID(ctx, &response, linodeID, opts)
for _, el := range response.Data {
diff --git a/instance_disks.go b/instance_disks.go
index ce086630c..b6734fed0 100644
--- a/instance_disks.go
+++ b/instance_disks.go
@@ -36,7 +36,7 @@ const (
// InstanceDisksPagedResponse represents a paginated InstanceDisk API response
type InstanceDisksPagedResponse struct {
*PageOptions
- Data []*InstanceDisk `json:"data"`
+ Data []InstanceDisk `json:"data"`
}
// InstanceDiskCreateOptions are InstanceDisk settings that can be used at creation
@@ -72,11 +72,11 @@ func (InstanceDisksPagedResponse) endpointWithID(c *Client, id int) string {
// appendData appends InstanceDisks when processing paginated InstanceDisk responses
func (resp *InstanceDisksPagedResponse) appendData(r *InstanceDisksPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListInstanceDisks lists InstanceDisks
-func (c *Client) ListInstanceDisks(ctx context.Context, linodeID int, opts *ListOptions) ([]*InstanceDisk, error) {
+func (c *Client) ListInstanceDisks(ctx context.Context, linodeID int, opts *ListOptions) ([]InstanceDisk, error) {
response := InstanceDisksPagedResponse{}
err := c.listHelperWithID(ctx, &response, linodeID, opts)
for _, el := range response.Data {
diff --git a/instance_volumes.go b/instance_volumes.go
index 88d61bab2..f27268628 100644
--- a/instance_volumes.go
+++ b/instance_volumes.go
@@ -7,7 +7,7 @@ import (
// InstanceVolumesPagedResponse represents a paginated InstanceVolume API response
type InstanceVolumesPagedResponse struct {
*PageOptions
- Data []*Volume `json:"data"`
+ Data []Volume `json:"data"`
}
// endpoint gets the endpoint URL for InstanceVolume
@@ -21,11 +21,11 @@ func (InstanceVolumesPagedResponse) endpointWithID(c *Client, id int) string {
// appendData appends InstanceVolumes when processing paginated InstanceVolume responses
func (resp *InstanceVolumesPagedResponse) appendData(r *InstanceVolumesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListInstanceVolumes lists InstanceVolumes
-func (c *Client) ListInstanceVolumes(ctx context.Context, linodeID int, opts *ListOptions) ([]*Volume, error) {
+func (c *Client) ListInstanceVolumes(ctx context.Context, linodeID int, opts *ListOptions) ([]Volume, error) {
response := InstanceVolumesPagedResponse{}
err := c.listHelperWithID(ctx, &response, linodeID, opts)
for _, el := range response.Data {
diff --git a/instances.go b/instances.go
index dcdee058f..5a92c19fb 100644
--- a/instances.go
+++ b/instances.go
@@ -131,7 +131,7 @@ func (l *Instance) fixDates() *Instance {
// InstancesPagedResponse represents a linode API response for listing
type InstancesPagedResponse struct {
*PageOptions
- Data []*Instance `json:"data"`
+ Data []Instance `json:"data"`
}
// endpoint gets the endpoint URL for Instance
@@ -145,11 +145,11 @@ func (InstancesPagedResponse) endpoint(c *Client) string {
// appendData appends Instances when processing paginated Instance responses
func (resp *InstancesPagedResponse) appendData(r *InstancesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListInstances lists linode instances
-func (c *Client) ListInstances(ctx context.Context, opts *ListOptions) ([]*Instance, error) {
+func (c *Client) ListInstances(ctx context.Context, opts *ListOptions) ([]Instance, error) {
response := InstancesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/kernels.go b/kernels.go
index 4bc165f9c..233a38db5 100644
--- a/kernels.go
+++ b/kernels.go
@@ -19,11 +19,11 @@ type LinodeKernel struct {
// LinodeKernelsPagedResponse represents a Linode kernels API response for listing
type LinodeKernelsPagedResponse struct {
*PageOptions
- Data []*LinodeKernel `json:"data"`
+ Data []LinodeKernel `json:"data"`
}
// ListKernels lists linode kernels
-func (c *Client) ListKernels(ctx context.Context, opts *ListOptions) ([]*LinodeKernel, error) {
+func (c *Client) ListKernels(ctx context.Context, opts *ListOptions) ([]LinodeKernel, error) {
response := LinodeKernelsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
@@ -41,7 +41,7 @@ func (LinodeKernelsPagedResponse) endpoint(c *Client) string {
}
func (resp *LinodeKernelsPagedResponse) appendData(r *LinodeKernelsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// GetKernel gets the kernel with the provided ID
diff --git a/longview.go b/longview.go
index 649ecdb60..70508f967 100644
--- a/longview.go
+++ b/longview.go
@@ -15,7 +15,7 @@ type LongviewClient struct {
// LongviewClientsPagedResponse represents a paginated LongviewClient API response
type LongviewClientsPagedResponse struct {
*PageOptions
- Data []*LongviewClient `json:"data"`
+ Data []LongviewClient `json:"data"`
}
// endpoint gets the endpoint URL for LongviewClient
@@ -29,11 +29,11 @@ func (LongviewClientsPagedResponse) endpoint(c *Client) string {
// appendData appends LongviewClients when processing paginated LongviewClient responses
func (resp *LongviewClientsPagedResponse) appendData(r *LongviewClientsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListLongviewClients lists LongviewClients
-func (c *Client) ListLongviewClients(ctx context.Context, opts *ListOptions) ([]*LongviewClient, error) {
+func (c *Client) ListLongviewClients(ctx context.Context, opts *ListOptions) ([]LongviewClient, error) {
response := LongviewClientsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/longview_subscriptions.go b/longview_subscriptions.go
index a62b6d302..816acd2a6 100644
--- a/longview_subscriptions.go
+++ b/longview_subscriptions.go
@@ -18,7 +18,7 @@ type LongviewSubscription struct {
// LongviewSubscriptionsPagedResponse represents a paginated LongviewSubscription API response
type LongviewSubscriptionsPagedResponse struct {
*PageOptions
- Data []*LongviewSubscription `json:"data"`
+ Data []LongviewSubscription `json:"data"`
}
// endpoint gets the endpoint URL for LongviewSubscription
@@ -32,11 +32,11 @@ func (LongviewSubscriptionsPagedResponse) endpoint(c *Client) string {
// appendData appends LongviewSubscriptions when processing paginated LongviewSubscription responses
func (resp *LongviewSubscriptionsPagedResponse) appendData(r *LongviewSubscriptionsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListLongviewSubscriptions lists LongviewSubscriptions
-func (c *Client) ListLongviewSubscriptions(ctx context.Context, opts *ListOptions) ([]*LongviewSubscription, error) {
+func (c *Client) ListLongviewSubscriptions(ctx context.Context, opts *ListOptions) ([]LongviewSubscription, error) {
response := LongviewSubscriptionsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/network_ips.go b/network_ips.go
index 73429a201..29b6f6b8e 100644
--- a/network_ips.go
+++ b/network_ips.go
@@ -8,7 +8,7 @@ import (
// IPAddressesPagedResponse represents a paginated IPAddress API response
type IPAddressesPagedResponse struct {
*PageOptions
- Data []*InstanceIP `json:"data"`
+ Data []InstanceIP `json:"data"`
}
// endpoint gets the endpoint URL for IPAddress
@@ -22,11 +22,11 @@ func (IPAddressesPagedResponse) endpoint(c *Client) string {
// appendData appends IPAddresses when processing paginated InstanceIPAddress responses
func (resp *IPAddressesPagedResponse) appendData(r *IPAddressesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListIPAddresses lists IPAddresses
-func (c *Client) ListIPAddresses(ctx context.Context, opts *ListOptions) ([]*InstanceIP, error) {
+func (c *Client) ListIPAddresses(ctx context.Context, opts *ListOptions) ([]InstanceIP, error) {
response := IPAddressesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/network_pools.go b/network_pools.go
index 7fa7392b3..03085923c 100644
--- a/network_pools.go
+++ b/network_pools.go
@@ -8,7 +8,7 @@ import (
// IPv6PoolsPagedResponse represents a paginated IPv6Pool API response
type IPv6PoolsPagedResponse struct {
*PageOptions
- Data []*IPv6Range `json:"data"`
+ Data []IPv6Range `json:"data"`
}
// endpoint gets the endpoint URL for IPv6Pool
@@ -22,11 +22,11 @@ func (IPv6PoolsPagedResponse) endpoint(c *Client) string {
// appendData appends IPv6Pools when processing paginated IPv6Pool responses
func (resp *IPv6PoolsPagedResponse) appendData(r *IPv6PoolsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListIPv6Pools lists IPv6Pools
-func (c *Client) ListIPv6Pools(ctx context.Context, opts *ListOptions) ([]*IPv6Range, error) {
+func (c *Client) ListIPv6Pools(ctx context.Context, opts *ListOptions) ([]IPv6Range, error) {
response := IPv6PoolsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/network_ranges.go b/network_ranges.go
index 0888c780e..0c0ba15a3 100644
--- a/network_ranges.go
+++ b/network_ranges.go
@@ -8,7 +8,7 @@ import (
// IPv6RangesPagedResponse represents a paginated IPv6Range API response
type IPv6RangesPagedResponse struct {
*PageOptions
- Data []*IPv6Range `json:"data"`
+ Data []IPv6Range `json:"data"`
}
// endpoint gets the endpoint URL for IPv6Range
@@ -22,11 +22,11 @@ func (IPv6RangesPagedResponse) endpoint(c *Client) string {
// appendData appends IPv6Ranges when processing paginated IPv6Range responses
func (resp *IPv6RangesPagedResponse) appendData(r *IPv6RangesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListIPv6Ranges lists IPv6Ranges
-func (c *Client) ListIPv6Ranges(ctx context.Context, opts *ListOptions) ([]*IPv6Range, error) {
+func (c *Client) ListIPv6Ranges(ctx context.Context, opts *ListOptions) ([]IPv6Range, error) {
response := IPv6RangesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/nodebalancer.go b/nodebalancer.go
index bc6fc0a07..ce4eb790b 100644
--- a/nodebalancer.go
+++ b/nodebalancer.go
@@ -75,7 +75,7 @@ func (i NodeBalancer) GetUpdateOptions() NodeBalancerUpdateOptions {
// NodeBalancersPagedResponse represents a paginated NodeBalancer API response
type NodeBalancersPagedResponse struct {
*PageOptions
- Data []*NodeBalancer `json:"data"`
+ Data []NodeBalancer `json:"data"`
}
func (NodeBalancersPagedResponse) endpoint(c *Client) string {
@@ -87,11 +87,11 @@ func (NodeBalancersPagedResponse) endpoint(c *Client) string {
}
func (resp *NodeBalancersPagedResponse) appendData(r *NodeBalancersPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListNodeBalancers lists NodeBalancers
-func (c *Client) ListNodeBalancers(ctx context.Context, opts *ListOptions) ([]*NodeBalancer, error) {
+func (c *Client) ListNodeBalancers(ctx context.Context, opts *ListOptions) ([]NodeBalancer, error) {
response := NodeBalancersPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/nodebalancer_config_nodes.go b/nodebalancer_config_nodes.go
index de9aaf4d6..08b1a9f9b 100644
--- a/nodebalancer_config_nodes.go
+++ b/nodebalancer_config_nodes.go
@@ -71,7 +71,7 @@ func (i NodeBalancerNode) GetUpdateOptions() NodeBalancerNodeUpdateOptions {
// NodeBalancerNodesPagedResponse represents a paginated NodeBalancerNode API response
type NodeBalancerNodesPagedResponse struct {
*PageOptions
- Data []*NodeBalancerNode `json:"data"`
+ Data []NodeBalancerNode `json:"data"`
}
// endpoint gets the endpoint URL for NodeBalancerNode
@@ -85,11 +85,11 @@ func (NodeBalancerNodesPagedResponse) endpointWithTwoIDs(c *Client, nodebalancer
// appendData appends NodeBalancerNodes when processing paginated NodeBalancerNode responses
func (resp *NodeBalancerNodesPagedResponse) appendData(r *NodeBalancerNodesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListNodeBalancerNodes lists NodeBalancerNodes
-func (c *Client) ListNodeBalancerNodes(ctx context.Context, nodebalancerID int, configID int, opts *ListOptions) ([]*NodeBalancerNode, error) {
+func (c *Client) ListNodeBalancerNodes(ctx context.Context, nodebalancerID int, configID int, opts *ListOptions) ([]NodeBalancerNode, error) {
response := NodeBalancerNodesPagedResponse{}
err := c.listHelperWithTwoIDs(ctx, &response, nodebalancerID, configID, opts)
for _, el := range response.Data {
diff --git a/nodebalancer_configs.go b/nodebalancer_configs.go
index babbcb35f..290c1d62c 100644
--- a/nodebalancer_configs.go
+++ b/nodebalancer_configs.go
@@ -149,7 +149,7 @@ func (i NodeBalancerConfig) GetUpdateOptions() NodeBalancerConfigUpdateOptions {
// NodeBalancerConfigsPagedResponse represents a paginated NodeBalancerConfig API response
type NodeBalancerConfigsPagedResponse struct {
*PageOptions
- Data []*NodeBalancerConfig `json:"data"`
+ Data []NodeBalancerConfig `json:"data"`
}
// endpointWithID gets the endpoint URL for NodeBalancerConfig
@@ -163,11 +163,11 @@ func (NodeBalancerConfigsPagedResponse) endpointWithID(c *Client, id int) string
// appendData appends NodeBalancerConfigs when processing paginated NodeBalancerConfig responses
func (resp *NodeBalancerConfigsPagedResponse) appendData(r *NodeBalancerConfigsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListNodeBalancerConfigs lists NodeBalancerConfigs
-func (c *Client) ListNodeBalancerConfigs(ctx context.Context, nodebalancerID int, opts *ListOptions) ([]*NodeBalancerConfig, error) {
+func (c *Client) ListNodeBalancerConfigs(ctx context.Context, nodebalancerID int, opts *ListOptions) ([]NodeBalancerConfig, error) {
response := NodeBalancerConfigsPagedResponse{}
err := c.listHelperWithID(ctx, &response, nodebalancerID, opts)
for _, el := range response.Data {
diff --git a/regions.go b/regions.go
index 7e45e26f2..d9c8e317e 100644
--- a/regions.go
+++ b/regions.go
@@ -14,7 +14,7 @@ type Region struct {
// RegionsPagedResponse represents a linode API response for listing
type RegionsPagedResponse struct {
*PageOptions
- Data []*Region `json:"data"`
+ Data []Region `json:"data"`
}
// endpoint gets the endpoint URL for Region
@@ -28,11 +28,11 @@ func (RegionsPagedResponse) endpoint(c *Client) string {
// appendData appends Regions when processing paginated Region responses
func (resp *RegionsPagedResponse) appendData(r *RegionsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListRegions lists Regions
-func (c *Client) ListRegions(ctx context.Context, opts *ListOptions) ([]*Region, error) {
+func (c *Client) ListRegions(ctx context.Context, opts *ListOptions) ([]Region, error) {
response := RegionsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/stackscripts.go b/stackscripts.go
index eb76e3e56..2dd9e82a0 100644
--- a/stackscripts.go
+++ b/stackscripts.go
@@ -89,7 +89,7 @@ func (i Stackscript) GetUpdateOptions() StackscriptUpdateOptions {
// StackscriptsPagedResponse represents a paginated Stackscript API response
type StackscriptsPagedResponse struct {
*PageOptions
- Data []*Stackscript `json:"data"`
+ Data []Stackscript `json:"data"`
}
// endpoint gets the endpoint URL for Stackscript
@@ -103,11 +103,11 @@ func (StackscriptsPagedResponse) endpoint(c *Client) string {
// appendData appends Stackscripts when processing paginated Stackscript responses
func (resp *StackscriptsPagedResponse) appendData(r *StackscriptsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListStackscripts lists Stackscripts
-func (c *Client) ListStackscripts(ctx context.Context, opts *ListOptions) ([]*Stackscript, error) {
+func (c *Client) ListStackscripts(ctx context.Context, opts *ListOptions) ([]Stackscript, error) {
response := StackscriptsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/support.go b/support.go
index 88392ca4c..6c72a4adf 100644
--- a/support.go
+++ b/support.go
@@ -43,7 +43,7 @@ const (
// TicketsPagedResponse represents a paginated ticket API response
type TicketsPagedResponse struct {
*PageOptions
- Data []*Ticket `json:"data"`
+ Data []Ticket `json:"data"`
}
func (TicketsPagedResponse) endpoint(c *Client) string {
@@ -55,14 +55,14 @@ func (TicketsPagedResponse) endpoint(c *Client) string {
}
func (resp *TicketsPagedResponse) appendData(r *TicketsPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListTickets returns a collection of Support Tickets on the Account. Support Tickets
// can be both tickets opened with Linode for support, as well as tickets generated by
// Linode regarding the Account. This collection includes all Support Tickets generated
// on the Account, with open tickets returned first.
-func (c *Client) ListTickets(ctx context.Context, opts *ListOptions) ([]*Ticket, error) {
+func (c *Client) ListTickets(ctx context.Context, opts *ListOptions) ([]Ticket, error) {
response := TicketsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/template.go b/template.go
index fe215b5f6..f88670177 100644
--- a/template.go
+++ b/template.go
@@ -46,7 +46,7 @@ func (i Template) GetUpdateOptions() (o TemplateCreateOptions) {
// TemplatesPagedResponse represents a paginated Template API response
type TemplatesPagedResponse struct {
*PageOptions
- Data []*Template `json:"data"`
+ Data []Template `json:"data"`
}
// endpoint gets the endpoint URL for Template
@@ -60,11 +60,11 @@ func (TemplatesPagedResponse) endpoint(c *Client) string {
// appendData appends Templates when processing paginated Template responses
func (resp *TemplatesPagedResponse) appendData(r *TemplatesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListTemplates lists Templates
-func (c *Client) ListTemplates(ctx context.Context, opts *ListOptions) ([]*Template, error) {
+func (c *Client) ListTemplates(ctx context.Context, opts *ListOptions) ([]Template, error) {
response := TemplatesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/types.go b/types.go
index d87e92af7..edeada84a 100644
--- a/types.go
+++ b/types.go
@@ -48,7 +48,7 @@ const (
// LinodeTypesPagedResponse represents a linode types API response for listing
type LinodeTypesPagedResponse struct {
*PageOptions
- Data []*LinodeType `json:"data"`
+ Data []LinodeType `json:"data"`
}
func (LinodeTypesPagedResponse) endpoint(c *Client) string {
@@ -60,11 +60,11 @@ func (LinodeTypesPagedResponse) endpoint(c *Client) string {
}
func (resp *LinodeTypesPagedResponse) appendData(r *LinodeTypesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListTypes lists linode types
-func (c *Client) ListTypes(ctx context.Context, opts *ListOptions) ([]*LinodeType, error) {
+func (c *Client) ListTypes(ctx context.Context, opts *ListOptions) ([]LinodeType, error) {
response := LinodeTypesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
if err != nil {
diff --git a/volumes.go b/volumes.go
index 6f00df96c..98e165775 100644
--- a/volumes.go
+++ b/volumes.go
@@ -59,7 +59,7 @@ type VolumeAttachOptions struct {
// VolumesPagedResponse represents a linode API response for listing of volumes
type VolumesPagedResponse struct {
*PageOptions
- Data []*Volume `json:"data"`
+ Data []Volume `json:"data"`
}
// endpoint gets the endpoint URL for Volume
@@ -73,11 +73,11 @@ func (VolumesPagedResponse) endpoint(c *Client) string {
// appendData appends Volumes when processing paginated Volume responses
func (resp *VolumesPagedResponse) appendData(r *VolumesPagedResponse) {
- (*resp).Data = append(resp.Data, r.Data...)
+ resp.Data = append(resp.Data, r.Data...)
}
// ListVolumes lists Volumes
-func (c *Client) ListVolumes(ctx context.Context, opts *ListOptions) ([]*Volume, error) {
+func (c *Client) ListVolumes(ctx context.Context, opts *ListOptions) ([]Volume, error) {
response := VolumesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for _, el := range response.Data {
diff --git a/waitfor.go b/waitfor.go
index 420423da8..d213efd96 100644
--- a/waitfor.go
+++ b/waitfor.go
@@ -219,12 +219,12 @@ func (client Client) WaitForEventFinished(ctx context.Context, id interface{}, e
}
if event.Status == EventFailed {
- return event, fmt.Errorf("%s %v action %s failed", titledEntityType, id, action)
+ return &event, fmt.Errorf("%s %v action %s failed", titledEntityType, id, action)
} else if event.Status == EventScheduled {
log.Printf("[INFO] %s %v action %s is scheduled", titledEntityType, id, action)
} else if event.Status == EventFinished {
log.Printf("[INFO] %s %v action %s is finished", titledEntityType, id, action)
- return event, nil
+ return &event, nil
}
log.Printf("[INFO] %s %v action %s is %s", titledEntityType, id, action, event.Status)
}
From e35f7b576a58c13cb39d3c1c272c7c801359ea4b Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Thu, 6 Sep 2018 14:37:09 -0400
Subject: [PATCH 08/18] warn when encountering Event with nil Created
---
.travis.yml | 2 +-
waitfor.go | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 272f1b172..4ffecc4c7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ install:
script:
- touch .env
- - make test ARGS='-coverprofile=coverage.txt -covermode=atomic'
+ - make test ARGS='-v -race -count=2 -coverprofile=coverage.txt -covermode=atomic ./...'
- gometalinter.v2 --enable-all --disable=vetshadow --disable=gocyclo --disable=unparam --disable=nakedret --disable=lll --disable=dupl --disable=gochecknoinits --disable=gochecknoglobals --disable=test --deadline=120s
- gometalinter.v2 --disable-all --enable=vetshadow --enable=gocyclo --enable=unparam --enable=nakedret --enable=lll --enable=dupl --enable=gochecknoinits --enable=gochecknoglobals --deadline=120s || true
diff --git a/waitfor.go b/waitfor.go
index d213efd96..d36da2ed2 100644
--- a/waitfor.go
+++ b/waitfor.go
@@ -211,7 +211,11 @@ func (client Client) WaitForEventFinished(ctx context.Context, id interface{}, e
continue
}
- if *event.Created != minStart && !event.Created.After(minStart) {
+ // @TODO(displague) This event.Created check shouldn't be needed, but it appears
+ // that the ListEvents method is not populating it correctly
+ if event.Created == nil {
+ log.Printf("[WARN] event.Created is nil when API returned: %#+v", event.CreatedStr)
+ } else if *event.Created != minStart && !event.Created.After(minStart) {
// Not the event we were looking for
// log.Println(event.Created, "is not >=", minStart)
continue
From fac5aa13fcee27adf88de1391bdfafeb05accbab Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Thu, 6 Sep 2018 14:57:44 -0400
Subject: [PATCH 09/18] test that multipaged results ran fixDates
---
example_test.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/example_test.go b/example_test.go
index 7d1e2fd1a..a8070d36d 100644
--- a/example_test.go
+++ b/example_test.go
@@ -277,10 +277,12 @@ func ExampleClient_ListStackscripts_page1() {
fmt.Println("Pages > 1:", filterOpt.Pages > 1)
s := scripts[len(scripts)-1]
fmt.Println("StackScript Script has shebang:", strings.Contains(s.Script, "#!/"))
+ fmt.Println("Created is parsed:", s.Created != nil)
// Output:
// Fetched == 100: true
// Results > 100: true
// Pages > 1: true
// StackScript Script has shebang: true
+ // Created is parsed: true
}
From 033e138585bc518eee0eb5a2924f8df3dd0a67a1 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Thu, 6 Sep 2018 15:49:10 -0400
Subject: [PATCH 10/18] apply fixDates in-place on List results
---
account_events.go | 4 ++--
account_invoices.go | 8 ++++----
account_notifications.go | 4 ++--
images.go | 4 ++--
instance_configs.go | 4 ++--
instance_disks.go | 4 ++--
instance_snapshots.go | 4 ++--
instance_volumes.go | 4 ++--
instances.go | 4 ++--
longview.go | 4 ++--
longview_subscriptions.go | 4 ++--
nodebalancer_config_nodes.go | 4 ++--
nodebalancer_configs.go | 4 ++--
regions.go | 4 ++--
stackscripts.go | 4 ++--
template.go | 4 ++--
volumes.go | 4 ++--
17 files changed, 36 insertions(+), 36 deletions(-)
diff --git a/account_events.go b/account_events.go
index d1cbab4bc..44540e40a 100644
--- a/account_events.go
+++ b/account_events.go
@@ -174,8 +174,8 @@ func (resp *EventsPagedResponse) appendData(r *EventsPagedResponse) {
func (c *Client) ListEvents(ctx context.Context, opts *ListOptions) ([]Event, error) {
response := EventsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/account_invoices.go b/account_invoices.go
index 22b9fcc18..75ca2f73d 100644
--- a/account_invoices.go
+++ b/account_invoices.go
@@ -54,8 +54,8 @@ func (resp *InvoicesPagedResponse) appendData(r *InvoicesPagedResponse) {
func (c *Client) ListInvoices(ctx context.Context, opts *ListOptions) ([]Invoice, error) {
response := InvoicesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
@@ -115,8 +115,8 @@ func (resp *InvoiceItemsPagedResponse) appendData(r *InvoiceItemsPagedResponse)
func (c *Client) ListInvoiceItems(ctx context.Context, id int, opts *ListOptions) ([]InvoiceItem, error) {
response := InvoiceItemsPagedResponse{}
err := c.listHelperWithID(ctx, &response, id, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/account_notifications.go b/account_notifications.go
index 59504dae8..6b63e3850 100644
--- a/account_notifications.go
+++ b/account_notifications.go
@@ -56,8 +56,8 @@ func (resp *NotificationsPagedResponse) appendData(r *NotificationsPagedResponse
func (c *Client) ListNotifications(ctx context.Context, opts *ListOptions) ([]Notification, error) {
response := NotificationsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/images.go b/images.go
index 1ed99fa3d..91ab57bb9 100644
--- a/images.go
+++ b/images.go
@@ -73,8 +73,8 @@ func (resp *ImagesPagedResponse) appendData(r *ImagesPagedResponse) {
func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]Image, error) {
response := ImagesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/instance_configs.go b/instance_configs.go
index 3980e8fbc..ab3643935 100644
--- a/instance_configs.go
+++ b/instance_configs.go
@@ -140,8 +140,8 @@ func (resp *InstanceConfigsPagedResponse) appendData(r *InstanceConfigsPagedResp
func (c *Client) ListInstanceConfigs(ctx context.Context, linodeID int, opts *ListOptions) ([]InstanceConfig, error) {
response := InstanceConfigsPagedResponse{}
err := c.listHelperWithID(ctx, &response, linodeID, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/instance_disks.go b/instance_disks.go
index b6734fed0..c8f6392d7 100644
--- a/instance_disks.go
+++ b/instance_disks.go
@@ -79,8 +79,8 @@ func (resp *InstanceDisksPagedResponse) appendData(r *InstanceDisksPagedResponse
func (c *Client) ListInstanceDisks(ctx context.Context, linodeID int, opts *ListOptions) ([]InstanceDisk, error) {
response := InstanceDisksPagedResponse{}
err := c.listHelperWithID(ctx, &response, linodeID, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/instance_snapshots.go b/instance_snapshots.go
index 8e2932e11..7933507dc 100644
--- a/instance_snapshots.go
+++ b/instance_snapshots.go
@@ -178,8 +178,8 @@ func (l *InstanceBackupSnapshotResponse) fixDates() *InstanceBackupSnapshotRespo
}
func (l *InstanceBackupsResponse) fixDates() *InstanceBackupsResponse {
- for _, el := range l.Automatic {
- el.fixDates()
+ for i := range l.Automatic {
+ l.Automatic[i].fixDates()
}
if l.Snapshot != nil {
l.Snapshot.fixDates()
diff --git a/instance_volumes.go b/instance_volumes.go
index f27268628..b6c9a9ae0 100644
--- a/instance_volumes.go
+++ b/instance_volumes.go
@@ -28,8 +28,8 @@ func (resp *InstanceVolumesPagedResponse) appendData(r *InstanceVolumesPagedResp
func (c *Client) ListInstanceVolumes(ctx context.Context, linodeID int, opts *ListOptions) ([]Volume, error) {
response := InstanceVolumesPagedResponse{}
err := c.listHelperWithID(ctx, &response, linodeID, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/instances.go b/instances.go
index 5a92c19fb..ba081b665 100644
--- a/instances.go
+++ b/instances.go
@@ -152,8 +152,8 @@ func (resp *InstancesPagedResponse) appendData(r *InstancesPagedResponse) {
func (c *Client) ListInstances(ctx context.Context, opts *ListOptions) ([]Instance, error) {
response := InstancesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/longview.go b/longview.go
index 70508f967..524af6776 100644
--- a/longview.go
+++ b/longview.go
@@ -36,8 +36,8 @@ func (resp *LongviewClientsPagedResponse) appendData(r *LongviewClientsPagedResp
func (c *Client) ListLongviewClients(ctx context.Context, opts *ListOptions) ([]LongviewClient, error) {
response := LongviewClientsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/longview_subscriptions.go b/longview_subscriptions.go
index 816acd2a6..253316599 100644
--- a/longview_subscriptions.go
+++ b/longview_subscriptions.go
@@ -39,8 +39,8 @@ func (resp *LongviewSubscriptionsPagedResponse) appendData(r *LongviewSubscripti
func (c *Client) ListLongviewSubscriptions(ctx context.Context, opts *ListOptions) ([]LongviewSubscription, error) {
response := LongviewSubscriptionsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/nodebalancer_config_nodes.go b/nodebalancer_config_nodes.go
index 08b1a9f9b..e1ca55cb5 100644
--- a/nodebalancer_config_nodes.go
+++ b/nodebalancer_config_nodes.go
@@ -92,8 +92,8 @@ func (resp *NodeBalancerNodesPagedResponse) appendData(r *NodeBalancerNodesPaged
func (c *Client) ListNodeBalancerNodes(ctx context.Context, nodebalancerID int, configID int, opts *ListOptions) ([]NodeBalancerNode, error) {
response := NodeBalancerNodesPagedResponse{}
err := c.listHelperWithTwoIDs(ctx, &response, nodebalancerID, configID, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/nodebalancer_configs.go b/nodebalancer_configs.go
index 290c1d62c..422fc3612 100644
--- a/nodebalancer_configs.go
+++ b/nodebalancer_configs.go
@@ -170,8 +170,8 @@ func (resp *NodeBalancerConfigsPagedResponse) appendData(r *NodeBalancerConfigsP
func (c *Client) ListNodeBalancerConfigs(ctx context.Context, nodebalancerID int, opts *ListOptions) ([]NodeBalancerConfig, error) {
response := NodeBalancerConfigsPagedResponse{}
err := c.listHelperWithID(ctx, &response, nodebalancerID, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/regions.go b/regions.go
index d9c8e317e..b13b996ea 100644
--- a/regions.go
+++ b/regions.go
@@ -35,8 +35,8 @@ func (resp *RegionsPagedResponse) appendData(r *RegionsPagedResponse) {
func (c *Client) ListRegions(ctx context.Context, opts *ListOptions) ([]Region, error) {
response := RegionsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/stackscripts.go b/stackscripts.go
index 2dd9e82a0..daf339b2f 100644
--- a/stackscripts.go
+++ b/stackscripts.go
@@ -110,8 +110,8 @@ func (resp *StackscriptsPagedResponse) appendData(r *StackscriptsPagedResponse)
func (c *Client) ListStackscripts(ctx context.Context, opts *ListOptions) ([]Stackscript, error) {
response := StackscriptsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/template.go b/template.go
index f88670177..426a77915 100644
--- a/template.go
+++ b/template.go
@@ -67,8 +67,8 @@ func (resp *TemplatesPagedResponse) appendData(r *TemplatesPagedResponse) {
func (c *Client) ListTemplates(ctx context.Context, opts *ListOptions) ([]Template, error) {
response := TemplatesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
diff --git a/volumes.go b/volumes.go
index 98e165775..eef492d83 100644
--- a/volumes.go
+++ b/volumes.go
@@ -80,8 +80,8 @@ func (resp *VolumesPagedResponse) appendData(r *VolumesPagedResponse) {
func (c *Client) ListVolumes(ctx context.Context, opts *ListOptions) ([]Volume, error) {
response := VolumesPagedResponse{}
err := c.listHelper(ctx, &response, opts)
- for _, el := range response.Data {
- el.fixDates()
+ for i := range response.Data {
+ response.Data[i].fixDates()
}
if err != nil {
return nil, err
From ff5f45ea422f7755c77ba6e715bce2ae82a65c20 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Fri, 7 Sep 2018 11:04:28 -0400
Subject: [PATCH 11/18] feature: add support for SSHKeys
---
API_SUPPORT.md | 50 +++++++
client.go | 5 +-
fixtures/TestGetSSHKey_found.yaml | 220 +++++++++++++++++++++++++++
fixtures/TestGetSSHKey_missing.yaml | 59 ++++++++
fixtures/TestListSSHKey.yaml | 221 ++++++++++++++++++++++++++++
fixtures/TestUpdateSSHKey.yaml | 218 +++++++++++++++++++++++++++
pagination.go | 10 ++
profile_sshkeys.go | 162 ++++++++++++++++++++
profile_sshkeys_test.go | 132 +++++++++++++++++
resources.go | 2 +
template.go | 14 +-
11 files changed, 1087 insertions(+), 6 deletions(-)
create mode 100644 fixtures/TestGetSSHKey_found.yaml
create mode 100644 fixtures/TestGetSSHKey_missing.yaml
create mode 100644 fixtures/TestListSSHKey.yaml
create mode 100644 fixtures/TestUpdateSSHKey.yaml
create mode 100644 profile_sshkeys.go
create mode 100644 profile_sshkeys_test.go
diff --git a/API_SUPPORT.md b/API_SUPPORT.md
index 09778f444..60e9e5ee0 100644
--- a/API_SUPPORT.md
+++ b/API_SUPPORT.md
@@ -289,6 +289,56 @@
- `/account/users/$username/password`
- [ ] `POST`
+## Profile
+
+### Personalized User Settings
+
+- `/profile`
+ - [ ] `GET`
+ - [ ] `PUT`
+
+### Granted OAuth Apps
+
+- `/profile/apps`
+ - [ ] `GET`
+- `/profile/apps/$id`
+ - [ ] `GET`
+ - [ ] `DELETE`
+
+### Grants to Linode Resources
+
+- `/profile/grants`
+ - [ ] `GET`
+
+### SSH Keys
+
+- `/profile/sshkeys`
+ - [x] `GET`
+ - [x] `POST`
+- `/profile/sshkeys/$id`
+ - [x] `GET`
+ - [x] `PUT`
+ - [x] `DELETE`
+
+### Two-Factor
+
+- `/profile/tfa-disable`
+ - [ ] `POST`
+- `/profile/tfa-enable`
+ - [ ] `POST`
+- `/profile/tfa-enable-confirm`
+ - [ ] `POST`
+
+### Personal Access API Tokens
+
+- `/profile/tokens`
+ - [ ] `GET`
+ - [ ] `POST`
+- `/profile/tokens/$id`
+ - [ ] `GET`
+ - [ ] `PUT`
+ - [ ] `DELETE`
+
## Images
- `/images`
diff --git a/client.go b/client.go
index 5a96ddb95..3d0aec4f6 100644
--- a/client.go
+++ b/client.go
@@ -19,7 +19,7 @@ const (
// APIProto connect to API with http(s)
APIProto = "https"
// Version of linodego
- Version = "0.4.0"
+ Version = "0.5.0"
// APIEnvVar environment var to check for API token
APIEnvVar = "LINODE_TOKEN"
// APISecondsPerPoll how frequently to poll for new Events
@@ -61,6 +61,7 @@ type Client struct {
NodeBalancers *Resource
NodeBalancerConfigs *Resource
NodeBalancerNodes *Resource
+ SSHKeys *Resource
Tickets *Resource
Account *Resource
Invoices *Resource
@@ -154,6 +155,7 @@ func NewClient(hc *http.Client) (client Client) {
nodebalancersName: NewResource(&client, nodebalancersName, nodebalancersEndpoint, false, NodeBalancer{}, NodeBalancerConfigsPagedResponse{}),
nodebalancerconfigsName: NewResource(&client, nodebalancerconfigsName, nodebalancerconfigsEndpoint, true, NodeBalancerConfig{}, NodeBalancerConfigsPagedResponse{}),
nodebalancernodesName: NewResource(&client, nodebalancernodesName, nodebalancernodesEndpoint, true, NodeBalancerNode{}, NodeBalancerNodesPagedResponse{}),
+ sshkeysName: NewResource(&client, sshkeysName, sshkeysEndpoint, false, SSHKey{}, SSHKeysPagedResponse{}),
ticketsName: NewResource(&client, ticketsName, ticketsEndpoint, false, Ticket{}, TicketsPagedResponse{}),
accountName: NewResource(&client, accountName, accountEndpoint, false, Account{}, nil), // really?
eventsName: NewResource(&client, eventsName, eventsEndpoint, false, Event{}, EventsPagedResponse{}),
@@ -188,6 +190,7 @@ func NewClient(hc *http.Client) (client Client) {
client.NodeBalancers = resources[nodebalancersName]
client.NodeBalancerConfigs = resources[nodebalancerconfigsName]
client.NodeBalancerNodes = resources[nodebalancernodesName]
+ client.SSHKeys = resources[sshkeysName]
client.Tickets = resources[ticketsName]
client.Account = resources[accountName]
client.Events = resources[eventsName]
diff --git a/fixtures/TestGetSSHKey_found.yaml b/fixtures/TestGetSSHKey_found.yaml
new file mode 100644
index 000000000..d54dbaef4
--- /dev/null
+++ b/fixtures/TestGetSSHKey_found.yaml
@@ -0,0 +1,220 @@
+---
+version: 1
+interactions:
+- request:
+ body: '{"label":"lpq6h62z88m4-linodego-testing","ssh_key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys
+ method: POST
+ response:
+ body: '{"id": 43, "ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing", "label": "lpq6h62z88m4-linodego-testing", "created":
+ "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "511"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332646"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys/43
+ method: GET
+ response:
+ body: '{"ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing", "id": 43, "created": "2018-01-02T03:04:05",
+ "label": "lpq6h62z88m4-linodego-testing"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=0, s-maxage=0, no-cache, no-store
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "511"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_only
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332647"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys/43
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332647"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
diff --git a/fixtures/TestGetSSHKey_missing.yaml b/fixtures/TestGetSSHKey_missing.yaml
new file mode 100644
index 000000000..fa798b644
--- /dev/null
+++ b/fixtures/TestGetSSHKey_missing.yaml
@@ -0,0 +1,59 @@
+---
+version: 1
+interactions:
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys/123
+ method: GET
+ response:
+ body: '{"errors": [{"reason": "Not found"}]}'
+ headers:
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Cache-Control:
+ - private, max-age=0, s-maxage=0, no-cache, no-store
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "37"
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:06 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_only
+ X-Frame-Options:
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332646"
+ X-Spec-Version:
+ - 4.0.4
+ status: 404 NOT FOUND
+ code: 404
+ duration: ""
diff --git a/fixtures/TestListSSHKey.yaml b/fixtures/TestListSSHKey.yaml
new file mode 100644
index 000000000..fabbfdb74
--- /dev/null
+++ b/fixtures/TestListSSHKey.yaml
@@ -0,0 +1,221 @@
+---
+version: 1
+interactions:
+- request:
+ body: '{"label":"lpq6h62z88m4-linodego-testing","ssh_key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys
+ method: POST
+ response:
+ body: '{"id": 45, "ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing", "label": "lpq6h62z88m4-linodego-testing", "created":
+ "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "511"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332647"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys
+ method: GET
+ response:
+ body: '{"data": [{"ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing", "id": 45, "created": "2018-01-02T03:04:05",
+ "label": "lpq6h62z88m4-linodego-testing"}], "pages": 1, "page": 1, "results":
+ 1}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=0, s-maxage=0, no-cache, no-store
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "560"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:08 GMT
+ Retry-After:
+ - "118"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_only
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536332647"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys/45
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:08 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332648"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
diff --git a/fixtures/TestUpdateSSHKey.yaml b/fixtures/TestUpdateSSHKey.yaml
new file mode 100644
index 000000000..124ddbfae
--- /dev/null
+++ b/fixtures/TestUpdateSSHKey.yaml
@@ -0,0 +1,218 @@
+---
+version: 1
+interactions:
+- request:
+ body: '{"label":"lpq6h62z88m4-linodego-testing","ssh_key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys
+ method: POST
+ response:
+ body: '{"label": "lpq6h62z88m4-linodego-testing", "id": 44, "ssh_key": "ssh-rsa
+ AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing", "created": "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "511"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332647"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"lpq6h62z88m4-linodego-testing_r"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys/44
+ method: PUT
+ response:
+ body: '{"label": "lpq6h62z88m4-linodego-testing_r", "id": 44, "ssh_key": "ssh-rsa
+ AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X
+ lpq6h62z88m4-linodego-testing", "created": "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "513"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536332647"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.5.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/profile/sshkeys/44
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Fri, 07 Sep 2018 15:02:07 GMT
+ Retry-After:
+ - "118"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - account:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536332646"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
diff --git a/pagination.go b/pagination.go
index 7c0627a54..a9b73d196 100644
--- a/pagination.go
+++ b/pagination.go
@@ -145,6 +145,16 @@ func (c *Client) listHelper(ctx context.Context, i interface{}, opts *ListOption
v.appendData(r.Result().(*IPv6RangesPagedResponse))
// @TODO consolidate this type with IPv6PoolsPagedResponse?
}
+ case *SSHKeysPagedResponse:
+ if r, err = coupleAPIErrors(req.SetResult(SSHKeysPagedResponse{}).Get(v.endpoint(c))); err == nil {
+ response, ok := r.Result().(*SSHKeysPagedResponse)
+ if !ok {
+ return fmt.Errorf("Response is not a *SSHKeysPagedResponse")
+ }
+ pages = response.Pages
+ results = response.Results
+ v.appendData(response)
+ }
case *TicketsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(TicketsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*TicketsPagedResponse).Pages
diff --git a/profile_sshkeys.go b/profile_sshkeys.go
new file mode 100644
index 000000000..c6e20aed4
--- /dev/null
+++ b/profile_sshkeys.go
@@ -0,0 +1,162 @@
+package linodego
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+// SSHKey represents a SSHKey object
+type SSHKey struct {
+ ID int `json:"id"`
+ Label string `json:"label"`
+ SSHKey string `json:"ssh_key"`
+ CreatedStr string `json:"created"`
+ Created *time.Time `json:"-"`
+}
+
+// SSHKeyCreateOptions fields are those accepted by CreateSSHKey
+type SSHKeyCreateOptions struct {
+ Label string `json:"label"`
+ SSHKey string `json:"ssh_key"`
+}
+
+// SSHKeyUpdateOptions fields are those accepted by UpdateSSHKey
+type SSHKeyUpdateOptions struct {
+ Label string `json:"label"`
+}
+
+// GetCreateOptions converts a SSHKey to SSHKeyCreateOptions for use in CreateSSHKey
+func (i SSHKey) GetCreateOptions() (o SSHKeyCreateOptions) {
+ o.Label = i.Label
+ o.SSHKey = i.SSHKey
+ return
+}
+
+// GetUpdateOptions converts a SSHKey to SSHKeyCreateOptions for use in UpdateSSHKey
+func (i SSHKey) GetUpdateOptions() (o SSHKeyUpdateOptions) {
+ o.Label = i.Label
+ return
+}
+
+// SSHKeysPagedResponse represents a paginated SSHKey API response
+type SSHKeysPagedResponse struct {
+ *PageOptions
+ Data []SSHKey `json:"data"`
+}
+
+// endpoint gets the endpoint URL for SSHKey
+func (SSHKeysPagedResponse) endpoint(c *Client) string {
+ endpoint, err := c.SSHKeys.Endpoint()
+ if err != nil {
+ panic(err)
+ }
+ return endpoint
+}
+
+// appendData appends SSHKeys when processing paginated SSHKey responses
+func (resp *SSHKeysPagedResponse) appendData(r *SSHKeysPagedResponse) {
+ resp.Data = append(resp.Data, r.Data...)
+}
+
+// ListSSHKeys lists SSHKeys
+func (c *Client) ListSSHKeys(ctx context.Context, opts *ListOptions) ([]SSHKey, error) {
+ response := SSHKeysPagedResponse{}
+ err := c.listHelper(ctx, &response, opts)
+ for i := range response.Data {
+ response.Data[i].fixDates()
+ }
+ if err != nil {
+ return nil, err
+ }
+ return response.Data, nil
+}
+
+// fixDates converts JSON timestamps to Go time.Time values
+func (i *SSHKey) fixDates() *SSHKey {
+ i.Created, _ = parseDates(i.CreatedStr)
+ return i
+}
+
+// GetSSHKey gets the sshkey with the provided ID
+func (c *Client) GetSSHKey(ctx context.Context, id int) (*SSHKey, error) {
+ e, err := c.SSHKeys.Endpoint()
+ if err != nil {
+ return nil, err
+ }
+ e = fmt.Sprintf("%s/%d", e, id)
+ r, err := coupleAPIErrors(c.R(ctx).SetResult(&SSHKey{}).Get(e))
+ if err != nil {
+ return nil, err
+ }
+ return r.Result().(*SSHKey).fixDates(), nil
+}
+
+// CreateSSHKey creates a SSHKey
+func (c *Client) CreateSSHKey(ctx context.Context, createOpts SSHKeyCreateOptions) (*SSHKey, error) {
+ var body string
+ e, err := c.SSHKeys.Endpoint()
+ if err != nil {
+ return nil, err
+ }
+
+ req := c.R(ctx).SetResult(&SSHKey{})
+
+ if bodyData, err := json.Marshal(createOpts); err == nil {
+ body = string(bodyData)
+ } else {
+ return nil, NewError(err)
+ }
+
+ r, err := coupleAPIErrors(req.
+ SetBody(body).
+ Post(e))
+
+ if err != nil {
+ return nil, err
+ }
+ return r.Result().(*SSHKey).fixDates(), nil
+}
+
+// UpdateSSHKey updates the SSHKey with the specified id
+func (c *Client) UpdateSSHKey(ctx context.Context, id int, updateOpts SSHKeyUpdateOptions) (*SSHKey, error) {
+ var body string
+ e, err := c.SSHKeys.Endpoint()
+ if err != nil {
+ return nil, err
+ }
+ e = fmt.Sprintf("%s/%d", e, id)
+
+ req := c.R(ctx).SetResult(&SSHKey{})
+
+ if bodyData, err := json.Marshal(updateOpts); err == nil {
+ body = string(bodyData)
+ } else {
+ return nil, NewError(err)
+ }
+
+ r, err := coupleAPIErrors(req.
+ SetBody(body).
+ Put(e))
+
+ if err != nil {
+ return nil, err
+ }
+ return r.Result().(*SSHKey).fixDates(), nil
+}
+
+// DeleteSSHKey deletes the SSHKey with the specified id
+func (c *Client) DeleteSSHKey(ctx context.Context, id int) error {
+ e, err := c.SSHKeys.Endpoint()
+ if err != nil {
+ return err
+ }
+ e = fmt.Sprintf("%s/%d", e, id)
+
+ if _, err := coupleAPIErrors(c.R(ctx).Delete(e)); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/profile_sshkeys_test.go b/profile_sshkeys_test.go
new file mode 100644
index 000000000..8647ceeb5
--- /dev/null
+++ b/profile_sshkeys_test.go
@@ -0,0 +1,132 @@
+package linodego_test
+
+import (
+ "context"
+ "strings"
+
+ . "github.com/linode/linodego"
+
+ "testing"
+)
+
+var (
+ testSSHKeyCreateOpts = SSHKeyCreateOptions{
+ Label: label,
+ SSHKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYlv4Ns3tY2NEseuuMXEz1sLzO9sGC0cwaT2ECbWFyrsn1Fg5ISdkaJD8LiuhZ41/1Mh0Sq49wY89yLkmw+Ukrd+thFbhUqTzjL09U89kn3Ds/ajVJgwnJ4pXmBqhq0/3pmO/UkYIBi5ErTnPWL+yHAoQ1HsVetxYUmY2SPaT0pduDIrvNZRvWn3Nvn9qsUVfthWiGc8oHWE5xyd7+3UPLHSMkE4rZd2k6e7bJWCM/VJ7ZrJQ6UVTDXjBCkkT12WsOWxcEuL36RUGgGa4h5M4IY0SkgQSKHer01dJSj3c6OBzj2CRDZFoM8f/YC66s0+ZQ9cE/aADDycMIvqOJBI6X " + label,
+ }
+)
+
+func TestGetSSHKey_missing(t *testing.T) {
+ client, teardown := createTestClient(t, "fixtures/TestGetSSHKey_missing")
+ defer teardown()
+
+ notfoundID := 123
+ i, err := client.GetSSHKey(context.Background(), notfoundID)
+ if err == nil {
+ t.Errorf("should have received an error requesting a missing sshkey, got %v", i)
+ }
+ e, ok := err.(*Error)
+ if !ok {
+ t.Errorf("should have received an Error requesting a missing sshkey, got %v", e)
+ }
+
+ if e.Code != 404 {
+ t.Errorf("should have received a 404 Code requesting a missing sshkey, got %v", e.Code)
+ }
+}
+
+func TestGetSSHKey_found(t *testing.T) {
+ client, sshkey, teardown, err := setupSSHKey(t, "fixtures/TestGetSSHKey_found")
+ defer teardown()
+
+ i, err := client.GetSSHKey(context.Background(), sshkey.ID)
+ if err != nil {
+ t.Errorf("Error getting sshkey, expected struct, got %v and error %v", i, err)
+ }
+ if i.ID != sshkey.ID {
+ t.Errorf("Expected sshkey id %d, but got %d", i.ID, sshkey.ID)
+ }
+ if testSSHKeyCreateOpts.Label != sshkey.Label {
+ t.Errorf("Expected sshkey label '%s', but got '%s'", testSSHKeyCreateOpts.Label, sshkey.Label)
+ }
+ if testSSHKeyCreateOpts.SSHKey != sshkey.SSHKey {
+ t.Errorf("Expected sshkey sshkey, but got a different one")
+ }
+}
+
+func TestUpdateSSHKey(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping test in short mode.")
+ }
+ client, sshkey, teardown, err := setupSSHKey(t, "fixtures/TestUpdateSSHKey")
+ defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
+
+ renamedLabel := sshkey.Label + "_r"
+ updateOpts := SSHKeyUpdateOptions{
+ Label: renamedLabel,
+ }
+ sshkey, err = client.UpdateSSHKey(context.Background(), sshkey.ID, updateOpts)
+
+ if err != nil {
+ t.Errorf("Error renaming sshkey, %s", err)
+ }
+
+ if !strings.Contains(sshkey.Label, "-linodego-testing_r") {
+ t.Errorf("sshkey returned does not match sshkey update request")
+ }
+}
+
+func TestListSSHKeys(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping test in short mode.")
+ }
+ client, sshkey, teardown, err := setupSSHKey(t, "fixtures/TestListSSHKey")
+ defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
+
+ sshkeys, err := client.ListSSHKeys(context.Background(), nil)
+ if err != nil {
+ t.Errorf("Error listing sshkeys, expected struct, got error %v", err)
+ }
+ if len(sshkeys) == 0 {
+ t.Errorf("Expected a list of sshkeys, but got %v", sshkeys)
+ }
+ notFound := true
+ for i := range sshkeys {
+ if sshkeys[i].Label == sshkey.Label {
+ notFound = false
+
+ if sshkeys[i].Created == nil {
+ t.Errorf("Expected listed sshkeys to have parsed Created")
+ }
+ break
+ }
+ }
+ if notFound {
+ t.Errorf("Expected to find created sshkey, but '%s' was not found", sshkey.Label)
+ }
+}
+
+func setupSSHKey(t *testing.T, fixturesYaml string) (*Client, *SSHKey, func(), error) {
+ t.Helper()
+ var fixtureTeardown func()
+ client, fixtureTeardown := createTestClient(t, fixturesYaml)
+ createOpts := testSSHKeyCreateOpts
+ sshkey, err := client.CreateSSHKey(context.Background(), createOpts)
+ if err != nil {
+ t.Errorf("Error listing sshkeys, expected struct, got error %v", err)
+ }
+
+ teardown := func() {
+ if err := client.DeleteSSHKey(context.Background(), sshkey.ID); err != nil {
+ t.Errorf("Expected to delete a sshkey, but got %v", err)
+ }
+ fixtureTeardown()
+ }
+ return client, sshkey, teardown, err
+}
diff --git a/resources.go b/resources.go
index fe38dba2e..1a2027841 100644
--- a/resources.go
+++ b/resources.go
@@ -33,6 +33,7 @@ const (
nodebalancersName = "nodebalancers"
nodebalancerconfigsName = "nodebalancerconfigs"
nodebalancernodesName = "nodebalancernodes"
+ sshkeysName = "sshkeys"
ticketsName = "tickets"
accountName = "account"
eventsName = "events"
@@ -69,6 +70,7 @@ const (
// Should we include these fields in CreateOpts and UpdateOpts?
nodebalancerconfigsEndpoint = "nodebalancers/{{ .ID }}/configs"
nodebalancernodesEndpoint = "nodebalancers/{{ .ID }}/configs/{{ .SecondID }}/nodes"
+ sshkeysEndpoint = "profile/sshkeys"
ticketsEndpoint = "support/tickets"
accountEndpoint = "account"
eventsEndpoint = "account/events"
diff --git a/template.go b/template.go
index 426a77915..7edf0edc2 100644
--- a/template.go
+++ b/template.go
@@ -25,19 +25,23 @@ type Template struct {
// Updated *time.Time `json:"-"`
}
+// TemplateCreateOptions fields are those accepted by CreateTemplate
type TemplateCreateOptions struct {
}
+// TemplateUpdateOptions fields are those accepted by UpdateTemplate
type TemplateUpdateOptions struct {
}
+// GetCreateOptions converts a Template to TemplateCreateOptions for use in CreateTemplate
func (i Template) GetCreateOptions() (o TemplateCreateOptions) {
// o.Label = i.Label
// o.Description = copyString(o.Description)
return
}
-func (i Template) GetUpdateOptions() (o TemplateCreateOptions) {
+// GetUpdateOptions converts a Template to TemplateUpdateOptions for use in UpdateTemplate
+func (i Template) GetUpdateOptions() (o TemplateUpdateOptions) {
// o.Label = i.Label
// o.Description = copyString(o.Description)
return
@@ -77,10 +81,10 @@ func (c *Client) ListTemplates(ctx context.Context, opts *ListOptions) ([]Templa
}
// fixDates converts JSON timestamps to Go time.Time values
-func (v *Template) fixDates() *Template {
- // v.Created, _ = parseDates(v.CreatedStr)
- // v.Updated, _ = parseDates(v.UpdatedStr)
- return v
+func (i *Template) fixDates() *Template {
+ // i.Created, _ = parseDates(i.CreatedStr)
+ // i.Updated, _ = parseDates(i.UpdatedStr)
+ return i
}
// GetTemplate gets the template with the provided ID
From 7b71bcf3b86085c05075cf3b90ba4660884a997d Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Fri, 7 Sep 2018 14:17:10 -0400
Subject: [PATCH 12/18] fix json parsing for event time_remaining values
---
account_events.go | 22 +++++++++++++++-------
account_events_test.go | 2 ++
instances.go | 2 ++
resources_test.go | 13 +++++++++++++
4 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/account_events.go b/account_events.go
index 94911ae5d..e2365c35b 100644
--- a/account_events.go
+++ b/account_events.go
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "log"
"strconv"
"strings"
"time"
@@ -229,23 +230,30 @@ func (c *Client) MarkEventsSeen(ctx context.Context, event *Event) error {
}
func unmarshalTimeRemaining(m json.RawMessage) *int {
- var intPtr *int
jsonBytes, err := m.MarshalJSON()
if err != nil {
- panic(err)
+ panic(jsonBytes)
}
- if err := json.Unmarshal(jsonBytes, intPtr); err == nil && intPtr != nil {
- return intPtr
+
+ if len(jsonBytes) == 4 && string(jsonBytes) == "null" {
+ return nil
}
- var timeStr *string
- if err := json.Unmarshal(jsonBytes, timeStr); err == nil && timeStr != nil {
- if dur, err := durationToSeconds(*timeStr); err != nil {
+
+ var timeStr string
+ if err := json.Unmarshal(jsonBytes, &timeStr); err == nil && len(timeStr) > 0 {
+ if dur, err := durationToSeconds(timeStr); err != nil {
panic(err)
} else {
return &dur
}
+ } else {
+ var intPtr int
+ if err := json.Unmarshal(jsonBytes, &intPtr); err == nil {
+ return &intPtr
+ }
}
+ log.Println("[WARN] Unexpected unmarshalTimeRemaining value: ", jsonBytes)
return nil
}
diff --git a/account_events_test.go b/account_events_test.go
index d4602f22e..4de8aacf4 100644
--- a/account_events_test.go
+++ b/account_events_test.go
@@ -18,6 +18,8 @@ func TestListEvents_resizing(t *testing.T) {
t.Errorf("Error getting Events, expected struct, got error %v", err)
}
+ // TODO(displague) this test is dependent on specific fixture data, mock it here, or just test
+ // fixDates directly
if events[2].TimeRemaining != nil {
t.Errorf("Error listing Events, expected resize event time_remaining to be nil, got %v", events[2].TimeRemaining)
}
diff --git a/instances.go b/instances.go
index ba081b665..efb2bf814 100644
--- a/instances.go
+++ b/instances.go
@@ -87,6 +87,7 @@ type InstanceCreateOptions struct {
Group string `json:"group,omitempty"`
RootPass string `json:"root_pass,omitempty"`
AuthorizedKeys []string `json:"authorized_keys,omitempty"`
+ AuthorizedUsers []string `json:"authorized_users,omitempty"`
StackScriptID int `json:"stackscript_id,omitempty"`
StackScriptData map[string]string `json:"stackscript_data,omitempty"`
BackupID int `json:"backup_id,omitempty"`
@@ -335,6 +336,7 @@ type RebuildInstanceOptions struct {
Image string `json:"image"`
RootPass string `json:"root_pass"`
AuthorizedKeys []string `json:"authorized_keys"`
+ AuthorizedUsers []string `json:"authorized_users"`
StackscriptID int `json:"stackscript_id"`
StackscriptData map[string]string `json:"stackscript_data"`
Booted bool `json:"booted"`
diff --git a/resources_test.go b/resources_test.go
index c6b5252ee..7fb48d603 100644
--- a/resources_test.go
+++ b/resources_test.go
@@ -2,6 +2,7 @@ package linodego
import (
"context"
+ "encoding/json"
"fmt"
"testing"
@@ -41,3 +42,15 @@ func TestResourceTemplatedendpointWithID(t *testing.T) {
t.Errorf("Backups endpoint did not contain backup ID '%d'", backupID)
}
}
+
+func TestUnmarshalTimeRemaining(t *testing.T) {
+ if *unmarshalTimeRemaining(json.RawMessage("\"1:23\"")) != 83 {
+ t.Errorf("Error parsing duration style time_remaining")
+ }
+ if unmarshalTimeRemaining(json.RawMessage("null")) != nil {
+ t.Errorf("Error parsing null time_remaining")
+ }
+ if *unmarshalTimeRemaining(json.RawMessage("0")) != 0 {
+ t.Errorf("Error parsing int style time_remaining")
+ }
+}
From ff1dbedda36e66ebf3c993fbdeb9ab8d011cf424 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Sat, 8 Sep 2018 12:46:37 -0400
Subject: [PATCH 13/18] fixes and tests for RebuildNodeBalancerConfig
---
API_SUPPORT.md | 2 +
fixtures/TestRebuildNodeBalancer.yaml | 490 ++++++++++++++++++++++++++
nodebalancer_config_nodes_test.go | 28 +-
nodebalancer_configs.go | 96 ++---
4 files changed, 574 insertions(+), 42 deletions(-)
create mode 100644 fixtures/TestRebuildNodeBalancer.yaml
diff --git a/API_SUPPORT.md b/API_SUPPORT.md
index 09778f444..2332abd80 100644
--- a/API_SUPPORT.md
+++ b/API_SUPPORT.md
@@ -169,6 +169,8 @@
- [X] `GET`
- [X] `PUT`
- [X] `DELETE`
+- `/nodebalancers/$id/configs/$id/rebuild`
+ - [X] `POST`
## Networking
diff --git a/fixtures/TestRebuildNodeBalancer.yaml b/fixtures/TestRebuildNodeBalancer.yaml
new file mode 100644
index 000000000..28790e114
--- /dev/null
+++ b/fixtures/TestRebuildNodeBalancer.yaml
@@ -0,0 +1,490 @@
+---
+version: 1
+interactions:
+- request:
+ body: '{"label":"lpq6h62z88m4-linodego-testing","region":"us-west","client_conn_throttle":20}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers
+ method: POST
+ response:
+ body: '{"id": 38590, "ipv6": "1234::5678", "label": "lpq6h62z88m4-linodego-testing",
+ "region": "us-west", "created": "2018-01-02T03:04:05", "hostname": "nb-10-20-30-40.fremont.nodebalancer.linode.com",
+ "ipv4": "010.020.030.040", "transfer": {"out": null, "in": null, "total": null},
+ "client_conn_throttle": 20, "updated": "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "345"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:58 GMT
+ Retry-After:
+ - "118"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424857"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"port":80,"protocol":"http","algorithm":"roundrobin"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers/38590/configs
+ method: POST
+ response:
+ body: '{"check_attempts": 3, "ssl_commonname": "", "protocol": "http", "stickiness":
+ "none", "algorithm": "roundrobin", "check_path": "", "ssl_cert": null, "check":
+ "none", "check_interval": 0, "check_body": "", "port": 80, "nodebalancer_id":
+ 38590, "cipher_suite": "recommended", "id": 34233, "ssl_fingerprint": "", "ssl_key":
+ null, "check_passive": true, "check_timeout": 30, "nodes_status": {"up": 0,
+ "down": 0}}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "408"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:58 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424858"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"address":"192.168.030.040:8080","label":"test-label","weight":10,"mode":"accept"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers/38590/configs/34233/nodes
+ method: POST
+ response:
+ body: '{"address": "192.168.030.040:8080", "nodebalancer_id": 38590, "config_id":
+ 34233, "id": 320215, "label": "test-label", "status": "Unknown", "mode": "accept",
+ "weight": 10}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "169"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:58 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424858"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"port":80,"protocol":"http","algorithm":"roundrobin","stickiness":"none","check":"none","check_attempts":3,"check_passive":true,"check_timeout":30,"cipher_suite":"recommended","nodes":[]}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers/38590/configs/34233/rebuild
+ method: POST
+ response:
+ body: '{"check": "none", "nodebalancer_id": 38590, "nodes_status": {"down": 1,
+ "up": 0}, "stickiness": "none", "cipher_suite": "recommended", "id": 34233,
+ "ssl_fingerprint": "", "check_passive": true, "protocol": "http", "check_timeout":
+ 30, "check_body": "", "port": 80, "check_attempts": 3, "algorithm": "roundrobin",
+ "check_path": "", "ssl_commonname": "", "check_interval": 0, "ssl_key": null,
+ "ssl_cert": null}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "408"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:58 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424858"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers/38590/configs/34233/nodes/320215
+ method: DELETE
+ response:
+ body: '{"errors": [{"reason": "Not found"}]}'
+ headers:
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "37"
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:59 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Frame-Options:
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424859"
+ X-Spec-Version:
+ - 4.0.4
+ status: 404 NOT FOUND
+ code: 404
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers/38590/configs/34233
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:59 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424859"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/nodebalancers/38590
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 16:38:59 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - nodebalancers:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536424859"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
diff --git a/nodebalancer_config_nodes_test.go b/nodebalancer_config_nodes_test.go
index 8ae0fd03c..2df1a6e89 100644
--- a/nodebalancer_config_nodes_test.go
+++ b/nodebalancer_config_nodes_test.go
@@ -135,6 +135,28 @@ func TestGetNodeBalancerNode(t *testing.T) {
}
}
+func TestRebuildNodeBalancer(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping test in short mode.")
+ }
+ client, nodebalancer, config, _, teardown, err := setupNodeBalancerNode(t, "fixtures/TestRebuildNodeBalancer")
+ defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
+
+ nbcRebuildOpts := config.GetRebuildOptions()
+
+ nbcGot, err := client.RebuildNodeBalancerConfig(context.Background(), nodebalancer.ID, config.ID, nbcRebuildOpts)
+ if err != nil {
+ t.Errorf("Error rebuilding nodebalancer config %d: %v", config.ID, err)
+ }
+ if nbcGot.Port != config.Port {
+ t.Errorf("RebuildNodeBalancerConfig did not return the expected port")
+ }
+
+}
+
func setupNodeBalancerNode(t *testing.T, fixturesYaml string) (*linodego.Client, *linodego.NodeBalancer, *linodego.NodeBalancerConfig, *linodego.NodeBalancerNode, func(), error) {
t.Helper()
var fixtureTeardown func()
@@ -152,7 +174,11 @@ func setupNodeBalancerNode(t *testing.T, fixturesYaml string) (*linodego.Client,
teardown := func() {
// delete the NodeBalancerNode to exercise the code
if err := client.DeleteNodeBalancerNode(context.Background(), nodebalancer.ID, config.ID, node.ID); err != nil {
- t.Errorf("Expected to delete a NodeBalancer Config Node, but got %v", err)
+ e, ok := err.(*linodego.Error)
+ // Tollerate 404 because Rebuild testing will delete all Nodes
+ if !ok || e.Code != 404 {
+ t.Errorf("Expected to delete a NodeBalancer Config Node, but got %v", err)
+ }
}
fixtureTeardown()
}
diff --git a/nodebalancer_configs.go b/nodebalancer_configs.go
index d4538b396..4f5809d3e 100644
--- a/nodebalancer_configs.go
+++ b/nodebalancer_configs.go
@@ -87,47 +87,40 @@ type NodeBalancerNodeStatus struct {
// NodeBalancerConfigCreateOptions are permitted by CreateNodeBalancerConfig
type NodeBalancerConfigCreateOptions struct {
- Port int `json:"port"`
- Protocol ConfigProtocol `json:"protocol,omitempty"`
- Algorithm ConfigAlgorithm `json:"algorithm,omitempty"`
- Stickiness ConfigStickiness `json:"stickiness,omitempty"`
- Check ConfigCheck `json:"check,omitempty"`
- CheckInterval int `json:"check_interval,omitempty"`
- CheckAttempts int `json:"check_attempts,omitempty"`
- CheckPath string `json:"check_path,omitempty"`
- CheckBody string `json:"check_body,omitempty"`
- CheckPassive *bool `json:"check_passive,omitempty"`
- CheckTimeout int `json:"check_timeout,omitempty"`
- CipherSuite ConfigCipher `json:"cipher_suite,omitempty"`
- SSLCert string `json:"ssl_cert,omitempty"`
- SSLKey string `json:"ssl_key,omitempty"`
-}
-
-// NodeBalancerConfigRebuildOptionsNode for a nodebalancer instance mapping
-type NodeBalancerConfigRebuildOptionsNode struct {
- Address *string `json:"address"`
- Label *string `json:"label"`
- Weight *int `json:"weight"`
- Mode *string `json:"mode"`
+ Port int `json:"port"`
+ Protocol ConfigProtocol `json:"protocol,omitempty"`
+ Algorithm ConfigAlgorithm `json:"algorithm,omitempty"`
+ Stickiness ConfigStickiness `json:"stickiness,omitempty"`
+ Check ConfigCheck `json:"check,omitempty"`
+ CheckInterval int `json:"check_interval,omitempty"`
+ CheckAttempts int `json:"check_attempts,omitempty"`
+ CheckPath string `json:"check_path,omitempty"`
+ CheckBody string `json:"check_body,omitempty"`
+ CheckPassive *bool `json:"check_passive,omitempty"`
+ CheckTimeout int `json:"check_timeout,omitempty"`
+ CipherSuite ConfigCipher `json:"cipher_suite,omitempty"`
+ SSLCert string `json:"ssl_cert,omitempty"`
+ SSLKey string `json:"ssl_key,omitempty"`
+ Nodes []NodeBalancerNodeCreateOptions `json:"nodes,omitempty"`
}
// NodeBalancerConfigRebuildOptions used by RebuildNodeBalancerConfig
type NodeBalancerConfigRebuildOptions struct {
- Port int `json:"port"`
- Protocol ConfigProtocol `json:"protocol,omitempty"`
- Algorithm ConfigAlgorithm `json:"algorithm,omitempty"`
- Stickiness ConfigStickiness `json:"stickiness,omitempty"`
- Check ConfigCheck `json:"check,omitempty"`
- CheckInterval int `json:"check_interval,omitempty"`
- CheckAttempts int `json:"check_attempts,omitempty"`
- CheckPath string `json:"check_path,omitempty"`
- CheckBody string `json:"check_body,omitempty"`
- CheckPassive *bool `json:"check_passive,omitempty"`
- CheckTimeout int `json:"check_timeout,omitempty"`
- CipherSuite ConfigCipher `json:"cipher_suite,omitempty"`
- SSLCert string `json:"ssl_cert,omitempty"`
- SSLKey string `json:"ssl_key,omitempty"`
- Nodes []*NodeBalancerConfigRebuildOptionsNode `json:"nodes,omitempty"`
+ Port int `json:"port"`
+ Protocol ConfigProtocol `json:"protocol,omitempty"`
+ Algorithm ConfigAlgorithm `json:"algorithm,omitempty"`
+ Stickiness ConfigStickiness `json:"stickiness,omitempty"`
+ Check ConfigCheck `json:"check,omitempty"`
+ CheckInterval int `json:"check_interval,omitempty"`
+ CheckAttempts int `json:"check_attempts,omitempty"`
+ CheckPath string `json:"check_path,omitempty"`
+ CheckBody string `json:"check_body,omitempty"`
+ CheckPassive *bool `json:"check_passive,omitempty"`
+ CheckTimeout int `json:"check_timeout,omitempty"`
+ CipherSuite ConfigCipher `json:"cipher_suite,omitempty"`
+ SSLCert string `json:"ssl_cert,omitempty"`
+ SSLKey string `json:"ssl_key,omitempty"`
+ Nodes []NodeBalancerNodeCreateOptions `json:"nodes"`
}
// NodeBalancerConfigUpdateOptions are permitted by UpdateNodeBalancerConfig
@@ -173,6 +166,27 @@ func (i NodeBalancerConfig) GetUpdateOptions() NodeBalancerConfigUpdateOptions {
}
}
+// GetRebuildOptions converts a NodeBalancerConfig to NodeBalancerConfigRebuildOptions for use in RebuildNodeBalancerConfig
+func (i NodeBalancerConfig) GetRebuildOptions() NodeBalancerConfigRebuildOptions {
+ return NodeBalancerConfigRebuildOptions{
+ Port: i.Port,
+ Protocol: i.Protocol,
+ Algorithm: i.Algorithm,
+ Stickiness: i.Stickiness,
+ Check: i.Check,
+ CheckInterval: i.CheckInterval,
+ CheckAttempts: i.CheckAttempts,
+ CheckTimeout: i.CheckTimeout,
+ CheckPath: i.CheckPath,
+ CheckBody: i.CheckBody,
+ CheckPassive: &i.CheckPassive,
+ CipherSuite: i.CipherSuite,
+ SSLCert: i.SSLCert,
+ SSLKey: i.SSLKey,
+ Nodes: make([]NodeBalancerNodeCreateOptions, 0),
+ }
+}
+
// NodeBalancerConfigsPagedResponse represents a paginated NodeBalancerConfig API response
type NodeBalancerConfigsPagedResponse struct {
*PageOptions
@@ -293,7 +307,7 @@ func (c *Client) DeleteNodeBalancerConfig(ctx context.Context, nodebalancerID in
}
// RebuildNodeBalancerConfig updates the NodeBalancer with the specified id
-func (c *Client) RebuildNodeBalancerConfig(ctx context.Context, nodeBalancerID int, configID int, rebuildOpts NodeBalancerConfigRebuildOptions) (*NodeBalancer, error) {
+func (c *Client) RebuildNodeBalancerConfig(ctx context.Context, nodeBalancerID int, configID int, rebuildOpts NodeBalancerConfigRebuildOptions) (*NodeBalancerConfig, error) {
var body string
e, err := c.NodeBalancerConfigs.endpointWithID(nodeBalancerID)
if err != nil {
@@ -301,7 +315,7 @@ func (c *Client) RebuildNodeBalancerConfig(ctx context.Context, nodeBalancerID i
}
e = fmt.Sprintf("%s/%d/rebuild", e, configID)
- req := c.R(ctx).SetResult(&NodeBalancer{})
+ req := c.R(ctx).SetResult(&NodeBalancerConfig{})
if bodyData, err := json.Marshal(rebuildOpts); err == nil {
body = string(bodyData)
@@ -311,10 +325,10 @@ func (c *Client) RebuildNodeBalancerConfig(ctx context.Context, nodeBalancerID i
r, err := coupleAPIErrors(req.
SetBody(body).
- Put(e))
+ Post(e))
if err != nil {
return nil, err
}
- return r.Result().(*NodeBalancer).fixDates(), nil
+ return r.Result().(*NodeBalancerConfig).fixDates(), nil
}
From 03b2c582ccf2eebe2c10ca883b327859cfd87da8 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Sun, 9 Sep 2018 13:16:59 -0400
Subject: [PATCH 14/18] use setup functions in tests to avoid magic number
requirements during testing
Closes #32
---
Makefile | 12 +-
README.md | 5 +-
client_test.go | 14 -
env.sample | 2 -
fixtures/TestGetInstance.yaml | 254 ++++++++++++++-
fixtures/TestGetVolume.yaml | 160 +++++++++-
fixtures/TestListInstanceConfigs.yaml | 255 ++++++++++++++-
fixtures/TestListInstanceDisks.yaml | 170 +++++++++-
fixtures/TestListInstanceVolumes.yaml | 166 +++++++++-
.../TestListInstanceVolumes_instance.yaml | 301 +++++++++++++++++
fixtures/TestListInstances.yaml | 257 ++++++++++++++-
fixtures/TestUpdateInstanceConfig.yaml | 302 ++++++++++++++++++
instance_snapshots_test.go | 2 +-
instances_test.go | 94 ++++--
volumes_test.go | 13 +-
15 files changed, 1871 insertions(+), 136 deletions(-)
create mode 100644 fixtures/TestListInstanceVolumes_instance.yaml
create mode 100644 fixtures/TestUpdateInstanceConfig.yaml
diff --git a/Makefile b/Makefile
index bd911532c..cbed613e1 100644
--- a/Makefile
+++ b/Makefile
@@ -2,14 +2,9 @@ include .env
.PHONY: vendor example refresh-fixtures clean-fixtures
-LINODE_FIXTURE_INSTANCE:=76859403
-LINODE_FIXTURE_VOLUME:=6574839201
-
.PHONY: test
test: vendor
- @LINODE_TEST_INSTANCE=$(LINODE_FIXTURE_INSTANCE) \
- LINODE_TEST_VOLUME=$(LINODE_FIXTURE_VOLUME) \
- LINODE_FIXTURE_MODE="play" \
+ @LINODE_FIXTURE_MODE="play" \
LINODE_TOKEN="awesometokenawesometokenawesometoken" \
go test $(ARGS)
@@ -31,19 +26,16 @@ refresh-fixtures: clean-fixtures fixtures
fixtures:
@echo "* Running fixtures"
@LINODE_TOKEN=$(LINODE_TOKEN) \
- LINODE_TEST_INSTANCE=$(LINODE_TEST_INSTANCE) \
- LINODE_TEST_VOLUME=$(LINODE_TEST_VOLUME) \
LINODE_FIXTURE_MODE="record" go test $(ARGS)
@echo "* Santizing fixtures"
@for yaml in fixtures/*yaml; do \
sed -E -i "" -e "s/$(LINODE_TOKEN)/awesometokenawesometokenawesometoken/g" \
- -e "s/$(LINODE_TEST_INSTANCE)/$(LINODE_FIXTURE_INSTANCE)/g" \
-e 's/20[0-9]{2}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-9]{2}:[0-9]{2}/2018-01-02T03:04:05/g' \
-e 's/nb-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}\./nb-10-20-30-40./g' \
-e 's/192\.168\.((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.)(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])/192.168.030.040/g' \
-e '/^192\.168/!s/((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])/010.020.030.040/g' \
-e 's/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/1234::5678/g' \
- -e "s/$(LINODE_TEST_VOLUME)/$(LINODE_FIXTURE_VOLUME)/g" $$yaml; \
+ $$yaml; \
done
.PHONY: godoc
diff --git a/README.md b/README.md
index dfdd322ea..2a83dcda6 100644
--- a/README.md
+++ b/README.md
@@ -156,9 +156,8 @@ When performing a `POST` or `PUT` request, multiple field related errors will be
Run `make test` to run the unit tests. This is the same as running `go test` except that `make test` will
execute the tests while playing back API response fixtures that were recorded during a previous development build.
-`go test` can be used without the fixtures, so long as `LINODE_TEST_INSTANCE` and `LINODE_TEST_VOLUME` are set
-to an instance ID and volume ID that exists on your account. The Linode instance must have a backup and a snapshot to
-match the test expectations. Copy `env.sample` to `.env` and configure your persistent test settings, including an API token.
+`go test` can be used without the fixtures. Copy `env.sample` to `.env` and configure your persistent test
+settings, including an API token.
`go test -short` can be used to run live API tests that do not require an account token.
diff --git a/client_test.go b/client_test.go
index 0c6ff619f..1a227d97b 100644
--- a/client_test.go
+++ b/client_test.go
@@ -16,9 +16,6 @@ var testingMode = recorder.ModeDisabled
var debugAPI = false
var validTestAPIKey = "NOTANAPIKEY"
-var TestInstanceID int
-var TestVolumeID int
-
func init() {
if apiToken, ok := os.LookupEnv("LINODE_TOKEN"); ok {
validTestAPIKey = apiToken
@@ -42,17 +39,6 @@ func init() {
testingMode = recorder.ModeReplaying
}
}
-
- if apiTestInstance, ok := os.LookupEnv("LINODE_TEST_INSTANCE"); ok {
- TestInstanceID, _ = strconv.Atoi(apiTestInstance)
- log.Printf("[INFO] LINODE_TEST_INSTANCE %d will be examined for tests", TestInstanceID)
- }
-
- if apiTestVolume, ok := os.LookupEnv("LINODE_TEST_VOLUME"); ok {
- TestVolumeID, _ = strconv.Atoi(apiTestVolume)
- log.Printf("[INFO] LINODE_TEST_VOLUME %d will be examined for tests", TestVolumeID)
- }
-
}
// testRecorder returns a go-vcr recorder and an associated function that the caller must defer
diff --git a/env.sample b/env.sample
index 01d23cf49..b1c9d1803 100644
--- a/env.sample
+++ b/env.sample
@@ -1,4 +1,2 @@
LINODE_TOKEN=
LINODE_DEBUG=0
-LINODE_TEST_INSTANCE=
-LINODE_TEST_VOLUME=
diff --git a/fixtures/TestGetInstance.yaml b/fixtures/TestGetInstance.yaml
index 1c064510c..d91ba2add 100644
--- a/fixtures/TestGetInstance.yaml
+++ b/fixtures/TestGetInstance.yaml
@@ -1,6 +1,159 @@
---
version: 1
interactions:
+- request:
+ body: '{"region":"us-west","type":"g6-nanode-1","label":"linodego-test-instance","booted":false}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances
+ method: POST
+ response:
+ body: '{"region": "us-west", "alerts": {"network_in": 10, "io": 10000, "cpu":
+ 90, "transfer_quota": 80, "network_out": 10}, "created": "2018-01-02T03:04:05",
+ "label": "linodego-test-instance", "updated": "2018-01-02T03:04:05", "watchdog_enabled":
+ true, "image": null, "id": 10157452, "group": "", "ipv4": ["010.020.030.040"],
+ "status": "provisioning", "hypervisor": "kvm", "ipv6": "1234::5678/64",
+ "type": "g6-nanode-1", "backups": {"enabled": false, "schedule": {"day": null,
+ "window": null}}, "specs": {"vcpus": 1, "disk": 25600, "memory": 1024, "transfer":
+ 1000}}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "576"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 20:05:47 GMT
+ Retry-After:
+ - "118"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536437266"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"linodego-test-config","devices":{}}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10157452/configs
+ method: POST
+ response:
+ body: '{"virt_mode": "paravirt", "devices": {"sdg": null, "sda": null, "sdd":
+ null, "sdb": null, "sde": null, "sdc": null, "sdh": null, "sdf": null}, "memory_limit":
+ 0, "comments": "", "updated": "2018-01-02T03:04:05", "run_level": "default",
+ "label": "linodego-test-config", "id": 11404308, "created": "2018-01-02T03:04:05",
+ "initrd": null, "root_device": "/dev/sda", "helpers": {"distro": true, "modules_dep":
+ true, "network": true, "devtmpfs_automount": true, "updatedb_disabled": true},
+ "kernel": "linode/latest-64bit"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "516"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 20:05:47 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536437267"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
- request:
body: ""
form: {}
@@ -12,18 +165,17 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - linodego 0.0.1 https://github.com/linode/linodego
- url: https://api.linode.com/v4/linode/instances/76859403
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10157452
method: GET
response:
- body: '{"watchdog_enabled": true, "ipv6": "1234::5678/64",
- "hypervisor": "kvm", "ipv4": ["010.020.030.040", "192.168.030.040"], "status": "running",
- "label": "test-linode", "backups": {"schedule": {"window": "W16", "day": "Monday"},
- "enabled": true}, "updated": "2018-01-02T03:04:05", "image": "linode/ubuntu18.04",
- "created": "2018-01-02T03:04:05", "id": 76859403, "type": "g6-standard-1", "region":
- "us-east", "group": "", "specs": {"vcpus": 1, "disk": 51200, "memory": 2048,
- "transfer": 2000}, "alerts": {"cpu": 90, "io": 10000, "network_out": 10, "network_in":
- 10, "transfer_quota": 80}}'
+ body: '{"group": "", "backups": {"schedule": {"window": null, "day": null}, "enabled":
+ false}, "region": "us-west", "created": "2018-01-02T03:04:05", "label": "linodego-test-instance",
+ "id": 10157452, "status": "provisioning", "image": null, "specs": {"transfer":
+ 1000, "vcpus": 1, "disk": 25600, "memory": 1024}, "updated": "2018-01-02T03:04:05",
+ "ipv6": "1234::5678/64", "hypervisor": "kvm", "type": "g6-nanode-1",
+ "alerts": {"cpu": 90, "network_in": 10, "io": 10000, "transfer_quota": 80, "network_out":
+ 10}, "ipv4": ["010.020.030.040"], "watchdog_enabled": true}'
headers:
Access-Control-Allow-Credentials:
- "true"
@@ -41,15 +193,15 @@ interactions:
Connection:
- keep-alive
Content-Length:
- - "599"
+ - "576"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- - Tue, 03 Jul 2018 01:38:49 GMT
+ - Sat, 08 Sep 2018 20:05:48 GMT
Retry-After:
- - "28"
+ - "15"
Server:
- nginx
Strict-Transport-Security:
@@ -70,11 +222,81 @@ interactions:
X-Ratelimit-Limit:
- "400"
X-Ratelimit-Remaining:
- - "395"
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536437164"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10157452
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 20:05:48 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
X-Ratelimit-Reset:
- - "1530581958"
+ - "1536437268"
X-Spec-Version:
- - 4.0.2
+ - 4.0.4
X-Xss-Protection:
- 1; mode=block
status: 200 OK
diff --git a/fixtures/TestGetVolume.yaml b/fixtures/TestGetVolume.yaml
index 0359aeb73..8481bd1bb 100644
--- a/fixtures/TestGetVolume.yaml
+++ b/fixtures/TestGetVolume.yaml
@@ -1,6 +1,78 @@
---
version: 1
interactions:
+- request:
+ body: '{"label":"linodego-test-volume","region":"us-west"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/volumes
+ method: POST
+ response:
+ body: '{"updated": "2018-01-02T03:04:05", "filesystem_path": "/dev/disk/by-id/scsi-0Linode_Volume_linodego-test-volume",
+ "created": "2018-01-02T03:04:05", "id": 12771, "label": "linodego-test-volume",
+ "status": "creating", "region": "us-west", "linode_id": null, "size": 20}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "267"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 22:25:51 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - volumes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536445671"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
- request:
body: ""
form: {}
@@ -12,13 +84,13 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - linodego 0.0.1 https://github.com/linode/linodego
- url: https://api.linode.com/v4/volumes/6574839201
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/volumes/12771
method: GET
response:
- body: '{"updated": "2018-01-02T03:04:05", "linode_id": null, "created": "2018-01-02T03:04:05",
- "size": 11, "filesystem_path": "/dev/disk/by-id/scsi-0Linode_Volume_test-volume",
- "status": "active", "region": "us-east", "label": "test-volume", "id": 6574839201}'
+ body: '{"label": "linodego-test-volume", "filesystem_path": "/dev/disk/by-id/scsi-0Linode_Volume_linodego-test-volume",
+ "size": 20, "status": "creating", "updated": "2018-01-02T03:04:05", "created":
+ "2018-01-02T03:04:05", "linode_id": null, "region": "us-west", "id": 12771}'
headers:
Access-Control-Allow-Credentials:
- "true"
@@ -36,13 +108,13 @@ interactions:
Connection:
- keep-alive
Content-Length:
- - "246"
+ - "267"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- - Fri, 13 Jul 2018 04:53:18 GMT
+ - Sat, 08 Sep 2018 22:25:52 GMT
Retry-After:
- "119"
Server:
@@ -67,9 +139,79 @@ interactions:
X-Ratelimit-Remaining:
- "399"
X-Ratelimit-Reset:
- - "1531457718"
+ - "1536445672"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/volumes/12771
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 22:25:52 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - volumes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536445672"
X-Spec-Version:
- - 4.0.3
+ - 4.0.4
X-Xss-Protection:
- 1; mode=block
status: 200 OK
diff --git a/fixtures/TestListInstanceConfigs.yaml b/fixtures/TestListInstanceConfigs.yaml
index bf616d2c1..d92c11dc6 100644
--- a/fixtures/TestListInstanceConfigs.yaml
+++ b/fixtures/TestListInstanceConfigs.yaml
@@ -1,6 +1,159 @@
---
version: 1
interactions:
+- request:
+ body: '{"region":"us-west","type":"g6-nanode-1","label":"linodego-test-instance","booted":false}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances
+ method: POST
+ response:
+ body: '{"backups": {"enabled": false, "schedule": {"day": null, "window": null}},
+ "updated": "2018-01-02T03:04:05", "region": "us-west", "hypervisor": "kvm",
+ "label": "linodego-test-instance", "created": "2018-01-02T03:04:05", "image":
+ null, "alerts": {"network_in": 10, "cpu": 90, "network_out": 10, "transfer_quota":
+ 80, "io": 10000}, "group": "", "specs": {"vcpus": 1, "transfer": 1000, "disk":
+ 25600, "memory": 1024}, "ipv6": "1234::5678/64", "type":
+ "g6-nanode-1", "id": 10174066, "status": "provisioning", "watchdog_enabled":
+ true, "ipv4": ["010.020.030.040"]}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "578"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:11:24 GMT
+ Retry-After:
+ - "41"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536513126"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"linodego-test-config","devices":{}}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174066/configs
+ method: POST
+ response:
+ body: '{"helpers": {"distro": true, "network": true, "devtmpfs_automount": true,
+ "updatedb_disabled": true, "modules_dep": true}, "virt_mode": "paravirt", "created":
+ "2018-01-02T03:04:05", "label": "linodego-test-config", "id": 11421183, "devices":
+ {"sdc": null, "sdd": null, "sda": null, "sdf": null, "sdb": null, "sde": null,
+ "sdg": null, "sdh": null}, "run_level": "default", "updated": "2018-01-02T03:04:05",
+ "memory_limit": 0, "kernel": "linode/latest-64bit", "comments": "", "initrd":
+ null, "root_device": "/dev/sda"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "516"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:11:24 GMT
+ Retry-After:
+ - "40"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536513125"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
- request:
body: ""
form: {}
@@ -12,19 +165,17 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - linodego 0.0.1 https://github.com/linode/linodego
- url: https://api.linode.com/v4/linode/instances/76859403/configs
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174066/configs
method: GET
response:
- body: '{"pages": 1, "page": 1, "data": [{"updated": "2018-01-02T03:04:05", "root_device":
- "/dev/sda", "helpers": {"updatedb_disabled": true, "distro": true, "network":
- true, "modules_dep": true, "devtmpfs_automount": true}, "virt_mode": "paravirt",
- "id": 9958462, "memory_limit": 0, "label": "My Ubuntu 18.04 LTS Disk Profile",
- "run_level": "default", "kernel": "linode/grub2", "devices": {"sda": {"disk_id":
- 18974977, "volume_id": null}, "sdd": null, "sdg": null, "sdh": null, "sdf":
- null, "sde": null, "sdc": {"disk_id": null, "volume_id": 6574839201}, "sdb": {"disk_id":
- 18974978, "volume_id": null}}, "comments": "", "initrd": null, "created": "2018-01-02T03:04:05"}],
- "results": 1}'
+ body: '{"data": [{"helpers": {"distro": true, "devtmpfs_automount": true, "updatedb_disabled":
+ true, "network": true, "modules_dep": true}, "memory_limit": 0, "label": "linodego-test-config",
+ "comments": "", "updated": "2018-01-02T03:04:05", "run_level": "default", "id":
+ 11421183, "initrd": null, "root_device": "/dev/sda", "virt_mode": "paravirt",
+ "devices": {"sdg": null, "sde": null, "sdc": null, "sdh": null, "sda": null,
+ "sdf": null, "sdb": null, "sdd": null}, "kernel": "linode/latest-64bit", "created":
+ "2018-01-02T03:04:05"}], "pages": 1, "page": 1, "results": 1}'
headers:
Access-Control-Allow-Credentials:
- "true"
@@ -42,15 +193,15 @@ interactions:
Connection:
- keep-alive
Content-Length:
- - "673"
+ - "565"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- - Tue, 03 Jul 2018 01:38:49 GMT
+ - Sun, 09 Sep 2018 17:11:24 GMT
Retry-After:
- - "29"
+ - "119"
Server:
- nginx
Strict-Transport-Security:
@@ -71,11 +222,81 @@ interactions:
X-Ratelimit-Limit:
- "400"
X-Ratelimit-Remaining:
- - "395"
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513204"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174066
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:11:24 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
X-Ratelimit-Reset:
- - "1530581959"
+ - "1536513204"
X-Spec-Version:
- - 4.0.2
+ - 4.0.4
X-Xss-Protection:
- 1; mode=block
status: 200 OK
diff --git a/fixtures/TestListInstanceDisks.yaml b/fixtures/TestListInstanceDisks.yaml
index 37fba63c5..aaec90c34 100644
--- a/fixtures/TestListInstanceDisks.yaml
+++ b/fixtures/TestListInstanceDisks.yaml
@@ -1,6 +1,82 @@
---
version: 1
interactions:
+- request:
+ body: '{"region":"us-west","type":"g6-nanode-1","label":"linodego-test-instance","root_pass":"R34lBAdP455","image":"linode/debian9","booted":false}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances
+ method: POST
+ response:
+ body: '{"group": "", "specs": {"transfer": 1000, "memory": 1024, "disk": 25600,
+ "vcpus": 1}, "created": "2018-01-02T03:04:05", "region": "us-west", "hypervisor":
+ "kvm", "label": "linodego-test-instance", "image": "linode/debian9", "alerts":
+ {"network_out": 10, "transfer_quota": 80, "io": 10000, "cpu": 90, "network_in":
+ 10}, "status": "provisioning", "updated": "2018-01-02T03:04:05", "ipv6": "1234::5678/64",
+ "backups": {"enabled": false, "schedule": {"day": null, "window": null}}, "type":
+ "g6-nanode-1", "ipv4": ["010.020.030.040"], "watchdog_enabled": true, "id": 10158886}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "589"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 22:09:52 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536444712"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
- request:
body: ""
form: {}
@@ -12,15 +88,15 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - linodego 0.0.1 https://github.com/linode/linodego
- url: https://api.linode.com/v4/linode/instances/76859403/disks
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10158886/disks
method: GET
response:
- body: '{"data": [{"updated": "2018-01-02T03:04:05", "created": "2018-01-02T03:04:05",
- "size": 50688, "status": "ready", "filesystem": "ext4", "id": 18974977, "label":
- "Ubuntu 18.04 LTS Disk"}, {"updated": "2018-01-02T03:04:05", "created": "2018-01-02T03:04:05",
- "size": 512, "status": "ready", "filesystem": "swap", "id": 18974978, "label":
- "512 MB Swap Image"}], "page": 1, "pages": 1, "results": 2}'
+ body: '{"pages": 1, "results": 2, "data": [{"id": 21758686, "status": "not ready",
+ "label": "Debian 9 Disk", "created": "2018-01-02T03:04:05", "size": 25088, "filesystem":
+ "ext4", "updated": "2018-01-02T03:04:05"}, {"id": 21758687, "status": "not ready",
+ "label": "512 MB Swap Image", "created": "2018-01-02T03:04:05", "size": 512,
+ "filesystem": "swap", "updated": "2018-01-02T03:04:05"}], "page": 1}'
headers:
Access-Control-Allow-Credentials:
- "true"
@@ -44,9 +120,9 @@ interactions:
Content-Type:
- application/json
Date:
- - Tue, 03 Jul 2018 01:38:49 GMT
+ - Sat, 08 Sep 2018 22:09:53 GMT
Retry-After:
- - "28"
+ - "119"
Server:
- nginx
Strict-Transport-Security:
@@ -67,11 +143,81 @@ interactions:
X-Ratelimit-Limit:
- "400"
X-Ratelimit-Remaining:
- - "393"
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536444713"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10158886
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 22:09:53 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
X-Ratelimit-Reset:
- - "1530581958"
+ - "1536444713"
X-Spec-Version:
- - 4.0.2
+ - 4.0.4
X-Xss-Protection:
- 1; mode=block
status: 200 OK
diff --git a/fixtures/TestListInstanceVolumes.yaml b/fixtures/TestListInstanceVolumes.yaml
index 2e34185f4..99fc6d055 100644
--- a/fixtures/TestListInstanceVolumes.yaml
+++ b/fixtures/TestListInstanceVolumes.yaml
@@ -1,6 +1,78 @@
---
version: 1
interactions:
+- request:
+ body: '{"label":"linodego-test-volume","region":"us-west"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/volumes
+ method: POST
+ response:
+ body: '{"filesystem_path": "/dev/disk/by-id/scsi-0Linode_Volume_linodego-test-volume",
+ "linode_id": null, "region": "us-west", "status": "creating", "label": "linodego-test-volume",
+ "id": 12787, "created": "2018-01-02T03:04:05", "size": 20, "updated": "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "267"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:41 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - volumes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513281"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
- request:
body: ""
form: {}
@@ -12,14 +84,14 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - linodego 0.0.1 https://github.com/linode/linodego
- url: https://api.linode.com/v4/linode/instances/76859403/volumes
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174075/volumes
method: GET
response:
- body: '{"results": 1, "data": [{"created": "2018-01-02T03:04:05", "id": 6574839201,
- "linode_id": 76859403, "label": "test-volume", "filesystem_path": "/dev/disk/by-id/scsi-0Linode_Volume_test-volume",
- "region": "us-east", "status": "active", "size": 10, "updated": "2018-01-02T03:04:05"}],
- "pages": 1, "page": 1}'
+ body: '{"pages": 1, "results": 1, "data": [{"id": 12787, "status": "active", "label":
+ "linodego-test-volume", "updated": "2018-01-02T03:04:05", "created": "2018-01-02T03:04:05",
+ "filesystem_path": "/dev/disk/by-id/scsi-0Linode_Volume_linodego-test-volume",
+ "size": 20, "linode_id": 10174075, "region": "us-west"}], "page": 1}'
headers:
Access-Control-Allow-Credentials:
- "true"
@@ -37,15 +109,15 @@ interactions:
Connection:
- keep-alive
Content-Length:
- - "298"
+ - "318"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- - Tue, 03 Jul 2018 01:38:50 GMT
+ - Sun, 09 Sep 2018 17:12:42 GMT
Retry-After:
- - "27"
+ - "119"
Server:
- nginx
Strict-Transport-Security:
@@ -66,11 +138,81 @@ interactions:
X-Ratelimit-Limit:
- "400"
X-Ratelimit-Remaining:
- - "394"
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513282"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/volumes/12787
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:42 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - volumes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
X-Ratelimit-Reset:
- - "1530581958"
+ - "1536513282"
X-Spec-Version:
- - 4.0.2
+ - 4.0.4
X-Xss-Protection:
- 1; mode=block
status: 200 OK
diff --git a/fixtures/TestListInstanceVolumes_instance.yaml b/fixtures/TestListInstanceVolumes_instance.yaml
new file mode 100644
index 000000000..90f93478f
--- /dev/null
+++ b/fixtures/TestListInstanceVolumes_instance.yaml
@@ -0,0 +1,301 @@
+---
+version: 1
+interactions:
+- request:
+ body: '{"region":"us-west","type":"g6-nanode-1","label":"linodego-test-instance","booted":false}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances
+ method: POST
+ response:
+ body: '{"group": "", "specs": {"transfer": 1000, "memory": 1024, "disk": 25600,
+ "vcpus": 1}, "created": "2018-01-02T03:04:05", "region": "us-west", "hypervisor":
+ "kvm", "label": "linodego-test-instance", "image": null, "alerts": {"network_out":
+ 10, "transfer_quota": 80, "io": 10000, "cpu": 90, "network_in": 10}, "status":
+ "provisioning", "updated": "2018-01-02T03:04:05", "ipv6": "1234::5678/64",
+ "backups": {"enabled": false, "schedule": {"day": null, "window": null}}, "type":
+ "g6-nanode-1", "ipv4": ["010.020.030.040"], "watchdog_enabled": true, "id": 10174075}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "578"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:40 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513280"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"linodego-test-config","devices":{}}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174075/configs
+ method: POST
+ response:
+ body: '{"virt_mode": "paravirt", "devices": {"sdg": null, "sda": null, "sdd":
+ null, "sdb": null, "sde": null, "sdc": null, "sdh": null, "sdf": null}, "memory_limit":
+ 0, "comments": "", "updated": "2018-01-02T03:04:05", "run_level": "default",
+ "label": "linodego-test-config", "id": 11421192, "created": "2018-01-02T03:04:05",
+ "initrd": null, "root_device": "/dev/sda", "helpers": {"distro": true, "modules_dep":
+ true, "network": true, "devtmpfs_automount": true, "updatedb_disabled": true},
+ "kernel": "linode/latest-64bit"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "516"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:41 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513281"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"volume-test","comments":"","devices":{"sda":{"volume_id":12787}},"memory_limit":0,"init_rd":null}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174075/configs/11421192
+ method: PUT
+ response:
+ body: '{"root_device": "/dev/sda", "updated": "2018-01-02T03:04:05", "virt_mode":
+ "paravirt", "initrd": null, "label": "volume-test", "created": "2018-01-02T03:04:05",
+ "comments": "", "memory_limit": 0, "kernel": "linode/latest-64bit", "run_level":
+ "default", "devices": {"sdb": null, "sdg": null, "sdh": null, "sda": {"disk_id":
+ null, "volume_id": 12787}, "sdd": null, "sde": null, "sdf": null, "sdc": null},
+ "helpers": {"distro": true, "modules_dep": true, "devtmpfs_automount": true,
+ "network": true, "updatedb_disabled": true}, "id": 11421192}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "540"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:42 GMT
+ Retry-After:
+ - "118"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513281"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174075
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:42 GMT
+ Retry-After:
+ - "117"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536513280"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
diff --git a/fixtures/TestListInstances.yaml b/fixtures/TestListInstances.yaml
index eb57035b4..3fa3a5908 100644
--- a/fixtures/TestListInstances.yaml
+++ b/fixtures/TestListInstances.yaml
@@ -2,7 +2,7 @@
version: 1
interactions:
- request:
- body: ""
+ body: '{"region":"us-west","type":"g6-nanode-1","label":"linodego-test-instance","booted":false}'
form: {}
headers:
Accept:
@@ -12,19 +12,172 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - linodego 0.0.1 https://github.com/linode/linodego
+ - linodego 0.4.0 https://github.com/linode/linodego
url: https://api.linode.com/v4/linode/instances
+ method: POST
+ response:
+ body: '{"status": "provisioning", "group": "", "watchdog_enabled": true, "hypervisor":
+ "kvm", "specs": {"memory": 1024, "transfer": 1000, "disk": 25600, "vcpus": 1},
+ "ipv4": ["010.020.030.040"], "label": "linodego-test-instance", "updated": "2018-01-02T03:04:05",
+ "id": 10157365, "type": "g6-nanode-1", "image": null, "created": "2018-01-02T03:04:05",
+ "backups": {"schedule": {"window": null, "day": null}, "enabled": false}, "alerts":
+ {"network_in": 10, "network_out": 10, "cpu": 90, "transfer_quota": 80, "io":
+ 10000}, "ipv6": "1234::5678/64", "region": "us-west"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "576"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 20:04:03 GMT
+ Retry-After:
+ - "116"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536437160"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"linodego-test-config","devices":{}}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10157365/configs
+ method: POST
+ response:
+ body: '{"helpers": {"distro": true, "devtmpfs_automount": true, "updatedb_disabled":
+ true, "network": true, "modules_dep": true}, "memory_limit": 0, "label": "linodego-test-config",
+ "comments": "", "updated": "2018-01-02T03:04:05", "run_level": "default", "id":
+ 11404221, "initrd": null, "root_device": "/dev/sda", "virt_mode": "paravirt",
+ "devices": {"sdg": null, "sde": null, "sdc": null, "sdh": null, "sda": null,
+ "sdf": null, "sdb": null, "sdd": null}, "kernel": "linode/latest-64bit", "created":
+ "2018-01-02T03:04:05"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "516"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 20:04:03 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536437163"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ X-Filter:
+ - '{"id": 10157365}'
+ url: https://api.linode.com/v4/linode/instances?page=1
method: GET
response:
- body: '{"data": [{"region": "us-east", "alerts": {"network_in": 10, "network_out":
- 10, "io": 10000, "cpu": 90, "transfer_quota": 80}, "specs": {"disk": 51200,
- "transfer": 2000, "vcpus": 1, "memory": 2048}, "image": "linode/ubuntu18.04",
- "created": "2018-01-02T03:04:05", "ipv6": "1234::5678/64",
- "hypervisor": "kvm", "ipv4": ["010.020.030.040", "192.168.030.040"], "updated":
- "2018-01-02T03:04:05", "watchdog_enabled": true, "group": "", "id": 76859403,
- "status": "running", "backups": {"schedule": {"day": "Monday", "window": "W16"},
- "enabled": true}, "label": "test-linode", "type": "g6-standard-1"}], "page":
- 1, "pages": 1, "results": 1}'
+ body: '{"data": [{"backups": {"enabled": false, "schedule": {"window": null, "day":
+ null}}, "ipv6": "1234::5678/64", "status": "provisioning",
+ "group": "", "type": "g6-nanode-1", "hypervisor": "kvm", "specs": {"vcpus":
+ 1, "disk": 25600, "transfer": 1000, "memory": 1024}, "region": "us-west", "label":
+ "linodego-test-instance", "ipv4": ["010.020.030.040"], "id": 10157365, "created":
+ "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "alerts": {"cpu": 90,
+ "network_out": 10, "transfer_quota": 80, "network_in": 10, "io": 10000}, "image":
+ null, "watchdog_enabled": true}], "results": 1, "page": 1, "pages": 1}'
headers:
Access-Control-Allow-Credentials:
- "true"
@@ -42,15 +195,15 @@ interactions:
Connection:
- keep-alive
Content-Length:
- - "648"
+ - "625"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- - Tue, 03 Jul 2018 01:38:48 GMT
+ - Sat, 08 Sep 2018 20:04:04 GMT
Retry-After:
- - "29"
+ - "118"
Server:
- nginx
Strict-Transport-Security:
@@ -71,11 +224,81 @@ interactions:
X-Ratelimit-Limit:
- "400"
X-Ratelimit-Remaining:
- - "394"
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536437163"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10157365
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sat, 08 Sep 2018 20:04:04 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
X-Ratelimit-Reset:
- - "1530581958"
+ - "1536437164"
X-Spec-Version:
- - 4.0.2
+ - 4.0.4
X-Xss-Protection:
- 1; mode=block
status: 200 OK
diff --git a/fixtures/TestUpdateInstanceConfig.yaml b/fixtures/TestUpdateInstanceConfig.yaml
new file mode 100644
index 000000000..eba0bc39d
--- /dev/null
+++ b/fixtures/TestUpdateInstanceConfig.yaml
@@ -0,0 +1,302 @@
+---
+version: 1
+interactions:
+- request:
+ body: '{"region":"us-west","type":"g6-nanode-1","label":"linodego-test-instance","booted":false}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances
+ method: POST
+ response:
+ body: '{"region": "us-west", "alerts": {"network_in": 10, "io": 10000, "cpu":
+ 90, "transfer_quota": 80, "network_out": 10}, "created": "2018-01-02T03:04:05",
+ "label": "linodego-test-instance", "updated": "2018-01-02T03:04:05", "watchdog_enabled":
+ true, "image": null, "id": 10174070, "group": "", "ipv4": ["010.020.030.040"],
+ "status": "provisioning", "hypervisor": "kvm", "ipv6": "1234::5678/64",
+ "type": "g6-nanode-1", "backups": {"enabled": false, "schedule": {"day": null,
+ "window": null}}, "specs": {"vcpus": 1, "disk": 25600, "memory": 1024, "transfer":
+ 1000}}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "577"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:08 GMT
+ Retry-After:
+ - "75"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536513204"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"linodego-test-config","devices":{}}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174070/configs
+ method: POST
+ response:
+ body: '{"helpers": {"distro": true, "network": true, "devtmpfs_automount": true,
+ "updatedb_disabled": true, "modules_dep": true}, "virt_mode": "paravirt", "created":
+ "2018-01-02T03:04:05", "label": "linodego-test-config", "id": 11421187, "devices":
+ {"sdc": null, "sdd": null, "sda": null, "sdf": null, "sdb": null, "sde": null,
+ "sdg": null, "sdh": null}, "run_level": "default", "updated": "2018-01-02T03:04:05",
+ "memory_limit": 0, "kernel": "linode/latest-64bit", "comments": "", "initrd":
+ null, "root_device": "/dev/sda"}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "516"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:08 GMT
+ Retry-After:
+ - "119"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "399"
+ X-Ratelimit-Reset:
+ - "1536513248"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: '{"label":"bar","comments":"","devices":{},"memory_limit":0,"init_rd":null,"root_device":"/dev/root"}'
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174070/configs/11421187
+ method: PUT
+ response:
+ body: '{"root_device": "/dev/root", "updated": "2018-01-02T03:04:05", "virt_mode":
+ "paravirt", "initrd": null, "label": "bar", "created": "2018-01-02T03:04:05",
+ "comments": "", "memory_limit": 0, "kernel": "linode/latest-64bit", "run_level":
+ "default", "devices": {"sdb": null, "sdg": null, "sdh": null, "sda": null, "sdd":
+ null, "sde": null, "sdf": null, "sdc": null}, "helpers": {"distro": true, "modules_dep":
+ true, "devtmpfs_automount": true, "network": true, "updatedb_disabled": true},
+ "id": 11421187}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "500"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:08 GMT
+ Retry-After:
+ - "18"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536513147"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
+- request:
+ body: ""
+ form: {}
+ headers:
+ Accept:
+ - application/json
+ Authorization:
+ - Bearer awesometokenawesometokenawesometoken
+ Content-Type:
+ - application/json
+ User-Agent:
+ - linodego 0.4.0 https://github.com/linode/linodego
+ url: https://api.linode.com/v4/linode/instances/10174070
+ method: DELETE
+ response:
+ body: '{}'
+ headers:
+ Access-Control-Allow-Credentials:
+ - "true"
+ Access-Control-Allow-Headers:
+ - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
+ Access-Control-Allow-Methods:
+ - HEAD, GET, OPTIONS, POST, PUT, DELETE
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Expose-Headers:
+ - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
+ Cache-Control:
+ - private, max-age=60, s-maxage=60
+ Connection:
+ - keep-alive
+ Content-Length:
+ - "2"
+ Content-Security-Policy:
+ - default-src 'none'
+ Content-Type:
+ - application/json
+ Date:
+ - Sun, 09 Sep 2018 17:12:08 GMT
+ Retry-After:
+ - "16"
+ Server:
+ - nginx
+ Strict-Transport-Security:
+ - max-age=31536000
+ Vary:
+ - Authorization, X-Filter
+ X-Accepted-Oauth-Scopes:
+ - linodes:read_write
+ X-Content-Type-Options:
+ - nosniff
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ - DENY
+ X-Oauth-Scopes:
+ - '*'
+ X-Ratelimit-Limit:
+ - "400"
+ X-Ratelimit-Remaining:
+ - "398"
+ X-Ratelimit-Reset:
+ - "1536513145"
+ X-Spec-Version:
+ - 4.0.4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: ""
diff --git a/instance_snapshots_test.go b/instance_snapshots_test.go
index d8a2f1372..b642750c8 100644
--- a/instance_snapshots_test.go
+++ b/instance_snapshots_test.go
@@ -65,7 +65,7 @@ func TestListInstanceBackups(t *testing.T) {
func setupInstanceBackup(t *testing.T, fixturesYaml string) (*linodego.Client, *linodego.Instance, *linodego.InstanceSnapshot, func(), error) {
t.Helper()
- client, instance, fixtureTeardown, err := setupInstanceWithoutDisks(t, fixturesYaml)
+ client, instance, _, fixtureTeardown, err := setupInstanceWithoutDisks(t, fixturesYaml)
if err != nil {
t.Errorf("Error creating instance, got error %v", err)
}
diff --git a/instances_test.go b/instances_test.go
index df19ee140..1eb2157a9 100644
--- a/instances_test.go
+++ b/instances_test.go
@@ -2,6 +2,7 @@ package linodego_test
import (
"context"
+ "strconv"
"testing"
"github.com/linode/linodego"
@@ -11,31 +12,40 @@ func TestListInstances(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
- client, teardown := createTestClient(t, "fixtures/TestListInstances")
+ client, instance, _, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestListInstances")
defer teardown()
- linodes, err := client.ListInstances(context.Background(), nil)
+ listOpts := linodego.NewListOptions(1, "{\"id\": "+strconv.Itoa(instance.ID)+"}")
+ linodes, err := client.ListInstances(context.Background(), listOpts)
if err != nil {
t.Errorf("Error listing instances, expected struct, got error %v", err)
}
- if len(linodes) == 0 {
+ if len(linodes) != 1 {
t.Errorf("Expected a list of instances, but got %v", linodes)
}
+
+ if linodes[0].ID != instance.ID {
+ t.Errorf("Expected list of instances to include test instance, but got %v", linodes)
+ }
}
func TestGetInstance(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
- client, teardown := createTestClient(t, "fixtures/TestGetInstance")
+ client, instance, _, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestGetInstance")
defer teardown()
- instance, err := client.GetInstance(context.Background(), TestInstanceID)
+ instanceGot, err := client.GetInstance(context.Background(), instance.ID)
if err != nil {
- t.Errorf("Error getting instance TestInstanceID, expected *LinodeInstance, got error %v", err)
+ t.Errorf("Error getting instance: %s", err)
}
+ if instanceGot.ID != instance.ID {
+ t.Errorf("Expected instance ID %d to match %d", instanceGot.ID, instance.ID)
+ }
+
if instance.Specs.Disk <= 0 {
- t.Errorf("Error in instance TestInstanceID spec for disk size, %v", instance.Specs)
+ t.Errorf("Error parsing instance spec for disk size: %v", instance.Specs)
}
}
@@ -43,10 +53,10 @@ func TestListInstanceDisks(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
- client, teardown := createTestClient(t, "fixtures/TestListInstanceDisks")
+ client, instance, teardown, err := setupInstance(t, "fixtures/TestListInstanceDisks")
defer teardown()
- disks, err := client.ListInstanceDisks(context.Background(), TestInstanceID, nil)
+ disks, err := client.ListInstanceDisks(context.Background(), instance.ID, nil)
if err != nil {
t.Errorf("Error listing instance disks, expected struct, got error %v", err)
}
@@ -59,26 +69,71 @@ func TestListInstanceConfigs(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
- client, teardown := createTestClient(t, "fixtures/TestListInstanceConfigs")
+ client, instance, config, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestListInstanceConfigs")
defer teardown()
- configs, err := client.ListInstanceConfigs(context.Background(), TestInstanceID, nil)
+ configs, err := client.ListInstanceConfigs(context.Background(), instance.ID, nil)
if err != nil {
t.Errorf("Error listing instance configs, expected struct, got error %v", err)
}
if len(configs) == 0 {
t.Errorf("Expected a list of instance configs, but got %v", configs)
}
+ if configs[0].ID != config.ID {
+ t.Errorf("Expected config id %d, got %d", configs[0].ID, config.ID)
+ }
+}
+
+func TestUpdateInstanceConfig(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping test in short mode.")
+ }
+ client, instance, config, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestUpdateInstanceConfig")
+ defer teardown()
+
+ updateConfigOpts := linodego.InstanceConfigUpdateOptions{
+ Label: "bar",
+ Devices: linodego.InstanceConfigDeviceMap{},
+ RootDevice: "/dev/root",
+ }
+
+ _, err = client.UpdateInstanceConfig(context.Background(), instance.ID, config.ID, updateConfigOpts)
+ if err != nil {
+ t.Error(err)
+ }
}
func TestListInstanceVolumes(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
- client, teardown := createTestClient(t, "fixtures/TestListInstanceVolumes")
+
+ client, instance, config, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestListInstanceVolumes_instance")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
+
+ clientVol, volume, teardown, err := setupVolume(t, "fixtures/TestListInstanceVolumes")
+ defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
- volumes, err := client.ListInstanceVolumes(context.Background(), TestInstanceID, nil)
+ configOpts := linodego.InstanceConfigUpdateOptions{
+ Label: "volume-test",
+ Devices: linodego.InstanceConfigDeviceMap{
+ SDA: &linodego.InstanceConfigDevice{
+ VolumeID: volume.ID,
+ },
+ },
+ }
+ _, err = client.UpdateInstanceConfig(context.Background(), instance.ID, config.ID, configOpts)
+ if err != nil {
+ t.Error(err)
+ }
+
+ volumes, err := clientVol.ListInstanceVolumes(context.Background(), instance.ID, nil)
if err != nil {
t.Errorf("Error listing instance volumes, expected struct, got error %v", err)
}
@@ -90,11 +145,14 @@ func TestListInstanceVolumes(t *testing.T) {
func setupInstance(t *testing.T, fixturesYaml string) (*linodego.Client, *linodego.Instance, func(), error) {
t.Helper()
client, fixtureTeardown := createTestClient(t, fixturesYaml)
+ falseBool := false
createOpts := linodego.InstanceCreateOptions{
Label: "linodego-test-instance",
RootPass: "R34lBAdP455",
Region: "us-west",
Type: "g6-nanode-1",
+ Image: "linode/debian9",
+ Booted: &falseBool,
}
instance, err := client.CreateInstance(context.Background(), createOpts)
if err != nil {
@@ -110,7 +168,7 @@ func setupInstance(t *testing.T, fixturesYaml string) (*linodego.Client, *linode
return client, instance, teardown, err
}
-func setupInstanceWithoutDisks(t *testing.T, fixturesYaml string) (*linodego.Client, *linodego.Instance, func(), error) {
+func setupInstanceWithoutDisks(t *testing.T, fixturesYaml string) (*linodego.Client, *linodego.Instance, *linodego.InstanceConfig, func(), error) {
t.Helper()
client, fixtureTeardown := createTestClient(t, fixturesYaml)
falseBool := false
@@ -123,15 +181,15 @@ func setupInstanceWithoutDisks(t *testing.T, fixturesYaml string) (*linodego.Cli
instance, err := client.CreateInstance(context.Background(), createOpts)
if err != nil {
t.Errorf("Error creating test Instance: %s", err)
- return nil, nil, fixtureTeardown, err
+ return nil, nil, nil, fixtureTeardown, err
}
configOpts := linodego.InstanceConfigCreateOptions{
Label: "linodego-test-config",
}
- _, err = client.CreateInstanceConfig(context.Background(), instance.ID, configOpts)
+ config, err := client.CreateInstanceConfig(context.Background(), instance.ID, configOpts)
if err != nil {
t.Errorf("Error creating config: %s", err)
- return nil, nil, fixtureTeardown, err
+ return nil, nil, nil, fixtureTeardown, err
}
teardown := func() {
@@ -140,5 +198,5 @@ func setupInstanceWithoutDisks(t *testing.T, fixturesYaml string) (*linodego.Cli
}
fixtureTeardown()
}
- return client, instance, teardown, err
+ return client, instance, config, teardown, err
}
diff --git a/volumes_test.go b/volumes_test.go
index 7885e62ee..6898bf18b 100644
--- a/volumes_test.go
+++ b/volumes_test.go
@@ -83,12 +83,15 @@ func TestGetVolume(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
- client, teardown := createTestClient(t, "fixtures/TestGetVolume")
- defer teardown()
+ client, volume, teardownVolume, errVolume := setupVolume(t, "fixtures/TestGetVolume")
+ defer teardownVolume()
+ if errVolume != nil {
+ t.Error(errVolume)
+ }
- _, err := client.GetVolume(context.Background(), TestVolumeID)
+ _, err := client.GetVolume(context.Background(), volume.ID)
if err != nil {
- t.Errorf("Error getting volume %d, expected *LinodeVolume, got error %v", TestVolumeID, err)
+ t.Errorf("Error getting volume %d, expected *LinodeVolume, got error %v", volume.ID, err)
}
}
@@ -105,7 +108,7 @@ func TestWaitForVolumeLinodeID_nil(t *testing.T) {
_, err = client.WaitForVolumeLinodeID(context.Background(), volume.ID, nil, 3)
if err != nil {
- t.Errorf("Error getting volume %d, expected *LinodeVolume, got error %v", TestVolumeID, err)
+ t.Errorf("Error getting volume %d, expected *LinodeVolume, got error %v", volume.ID, err)
}
}
From dff010884298b42de9831251f6ae15fd22640299 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Sun, 9 Sep 2018 13:44:54 -0400
Subject: [PATCH 15/18] add authorized_keys to InstanceDiskCreateOptions
---
instance_disks.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/instance_disks.go b/instance_disks.go
index c8f6392d7..8c31491a2 100644
--- a/instance_disks.go
+++ b/instance_disks.go
@@ -50,6 +50,7 @@ type InstanceDiskCreateOptions struct {
Filesystem string `json:"filesystem,omitempty"`
AuthorizedKeys []string `json:"authorized_keys,omitempty"`
+ AuthorizedUsers []string `json:"authorized_users,omitempty"`
ReadOnly bool `json:"read_only,omitempty"`
StackscriptID int `json:"stackscript_id,omitempty"`
StackscriptData map[string]string `json:"stackscript_data,omitempty"`
From 7e5debd7bd68de9d12dcdf569c3131b97aa8e365 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Sun, 9 Sep 2018 14:06:46 -0400
Subject: [PATCH 16/18] root_device has no meaning as "", avoid pointers for
omission
---
instance_configs.go | 10 +++++-----
instances_test.go | 20 ++++++++++++++++++--
profile_sshkeys.go | 6 ++----
profile_sshkeys_test.go | 3 +++
template.go | 7 ++-----
template_test.go | 3 +++
6 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/instance_configs.go b/instance_configs.go
index e9aeb87f7..979a27495 100644
--- a/instance_configs.go
+++ b/instance_configs.go
@@ -84,10 +84,10 @@ type InstanceConfigUpdateOptions struct {
MemoryLimit int `json:"memory_limit"`
Kernel string `json:"kernel,omitempty"`
// InitRD is nullable, permit the sending of null
- InitRD *int `json:"init_rd"`
- RootDevice *string `json:"root_device,omitempty"`
- RunLevel string `json:"run_level,omitempty"`
- VirtMode string `json:"virt_mode,omitempty"`
+ InitRD *int `json:"init_rd"`
+ RootDevice string `json:"root_device,omitempty"`
+ RunLevel string `json:"run_level,omitempty"`
+ VirtMode string `json:"virt_mode,omitempty"`
}
// GetCreateOptions converts a InstanceConfig to InstanceConfigCreateOptions for use in CreateInstanceConfig
@@ -120,7 +120,7 @@ func (i InstanceConfig) GetUpdateOptions() InstanceConfigUpdateOptions {
MemoryLimit: i.MemoryLimit,
Kernel: i.Kernel,
InitRD: copyInt(i.InitRD),
- RootDevice: copyString(&i.RootDevice),
+ RootDevice: i.RootDevice,
RunLevel: i.RunLevel,
VirtMode: i.VirtMode,
}
diff --git a/instances_test.go b/instances_test.go
index 1eb2157a9..b73fbedaa 100644
--- a/instances_test.go
+++ b/instances_test.go
@@ -15,6 +15,10 @@ func TestListInstances(t *testing.T) {
client, instance, _, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestListInstances")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
+
listOpts := linodego.NewListOptions(1, "{\"id\": "+strconv.Itoa(instance.ID)+"}")
linodes, err := client.ListInstances(context.Background(), listOpts)
if err != nil {
@@ -35,6 +39,9 @@ func TestGetInstance(t *testing.T) {
}
client, instance, _, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestGetInstance")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
instanceGot, err := client.GetInstance(context.Background(), instance.ID)
if err != nil {
@@ -55,6 +62,9 @@ func TestListInstanceDisks(t *testing.T) {
}
client, instance, teardown, err := setupInstance(t, "fixtures/TestListInstanceDisks")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
disks, err := client.ListInstanceDisks(context.Background(), instance.ID, nil)
if err != nil {
@@ -71,6 +81,9 @@ func TestListInstanceConfigs(t *testing.T) {
}
client, instance, config, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestListInstanceConfigs")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
configs, err := client.ListInstanceConfigs(context.Background(), instance.ID, nil)
if err != nil {
@@ -90,10 +103,13 @@ func TestUpdateInstanceConfig(t *testing.T) {
}
client, instance, config, teardown, err := setupInstanceWithoutDisks(t, "fixtures/TestUpdateInstanceConfig")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
updateConfigOpts := linodego.InstanceConfigUpdateOptions{
Label: "bar",
- Devices: linodego.InstanceConfigDeviceMap{},
+ Devices: &linodego.InstanceConfigDeviceMap{},
RootDevice: "/dev/root",
}
@@ -122,7 +138,7 @@ func TestListInstanceVolumes(t *testing.T) {
configOpts := linodego.InstanceConfigUpdateOptions{
Label: "volume-test",
- Devices: linodego.InstanceConfigDeviceMap{
+ Devices: &linodego.InstanceConfigDeviceMap{
SDA: &linodego.InstanceConfigDevice{
VolumeID: volume.ID,
},
diff --git a/profile_sshkeys.go b/profile_sshkeys.go
index c6e20aed4..2ec4d4f71 100644
--- a/profile_sshkeys.go
+++ b/profile_sshkeys.go
@@ -154,9 +154,7 @@ func (c *Client) DeleteSSHKey(ctx context.Context, id int) error {
}
e = fmt.Sprintf("%s/%d", e, id)
- if _, err := coupleAPIErrors(c.R(ctx).Delete(e)); err != nil {
- return err
- }
+ _, err = coupleAPIErrors(c.R(ctx).Delete(e))
+ return err
- return nil
}
diff --git a/profile_sshkeys_test.go b/profile_sshkeys_test.go
index 8647ceeb5..267d1c4f4 100644
--- a/profile_sshkeys_test.go
+++ b/profile_sshkeys_test.go
@@ -38,6 +38,9 @@ func TestGetSSHKey_missing(t *testing.T) {
func TestGetSSHKey_found(t *testing.T) {
client, sshkey, teardown, err := setupSSHKey(t, "fixtures/TestGetSSHKey_found")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
i, err := client.GetSSHKey(context.Background(), sshkey.ID)
if err != nil {
diff --git a/template.go b/template.go
index 7edf0edc2..6048dded3 100644
--- a/template.go
+++ b/template.go
@@ -162,9 +162,6 @@ func (c *Client) DeleteTemplate(ctx context.Context, id int) error {
}
e = fmt.Sprintf("%s/%d", e, id)
- if _, err := coupleAPIErrors(c.R(ctx).Delete(e)); err != nil {
- return err
- }
-
- return nil
+ _, err = coupleAPIErrors(c.R(ctx).Delete(e))
+ return err
}
diff --git a/template_test.go b/template_test.go
index 960ca0c67..b974971d3 100644
--- a/template_test.go
+++ b/template_test.go
@@ -31,6 +31,9 @@ func TestGetTemplate_missing(t *testing.T) {
func TestGetTemplate_found(t *testing.T) {
client, teardown := createTestClient(t, "fixtures/TestGetTemplate_found")
defer teardown()
+ if err != nil {
+ t.Error(err)
+ }
i, err := client.GetTemplate(context.Background(), "linode/ubuntu16.04lts")
if err != nil {
From 4d828dc3419a316b8a15f0cf71f825de526088b3 Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Sun, 9 Sep 2018 14:33:31 -0400
Subject: [PATCH 17/18] v0.5.0 changelog bump
---
CHANGELOG.md | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25d7a042e..72740cffc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,22 @@
# Change Log
+
+## [v0.5.0](https://github.com/linode/linodego/compare/v0.4.0...v0.5.0) (2018-09-09)
+
+### Breaking Changes
+
+* List functions return slice of thing instead of slice of pointer to thing
+
+### Feature
+
+* add SSHKeys methods to client (also affects InstanceCreate, InstanceDiskCreate)
+* add RebuildNodeBalancerConfig (and CreateNodeBalancerConfig with Nodes)
+
+### Fixes
+
+* Event.TimeRemaining wouldn't parse all possible API value
+* Tests no longer rely on known/special instance and volume ids
+
## [0.4.0](https://github.com/linode/linodego/compare/v0.3.0...0.4.0) (2018-08-27)
From d0d31d8ca62fa3f7e4526ca0ce95de81e4ed001e Mon Sep 17 00:00:00 2001
From: Marques Johansson
Date: Mon, 10 Sep 2018 08:17:52 -0400
Subject: [PATCH 18/18] v0.5.1 fixes imported Domain.Status values
---
CHANGELOG.md | 7 +++++++
client.go | 2 +-
domains.go | 2 +-
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72740cffc..8fc2594d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Change Log
+
+## [v0.5.1](https://github.com/linode/linodego/compare/v0.5.0...v0.5.1) (2018-09-10)
+
+### Fixes
+
+* Domain.Status was not imported from API responses correctly
+
## [v0.5.0](https://github.com/linode/linodego/compare/v0.4.0...v0.5.0) (2018-09-09)
diff --git a/client.go b/client.go
index 3d0aec4f6..81c51f692 100644
--- a/client.go
+++ b/client.go
@@ -19,7 +19,7 @@ const (
// APIProto connect to API with http(s)
APIProto = "https"
// Version of linodego
- Version = "0.5.0"
+ Version = "0.5.1"
// APIEnvVar environment var to check for API token
APIEnvVar = "LINODE_TOKEN"
// APISecondsPerPoll how frequently to poll for new Events
diff --git a/domains.go b/domains.go
index f0f048a82..4ae7167fa 100644
--- a/domains.go
+++ b/domains.go
@@ -21,7 +21,7 @@ type Domain struct {
Group string `json:"group"`
// Used to control whether this Domain is currently being rendered.
- Status DomainStatus `json:"domain_status"` // Enum:"disabled" "active" "edit_mode" "has_errors"
+ Status DomainStatus `json:"status"` // Enum:"disabled" "active" "edit_mode" "has_errors"
// A description for this Domain. This is for display purposes only.
Description string `json:"description"`