diff --git a/droplets.go b/droplets.go index f8c07777..7a0e6672 100644 --- a/droplets.go +++ b/droplets.go @@ -31,6 +31,8 @@ type DropletsService interface { Actions(context.Context, int, *ListOptions) ([]Action, *Response, error) Neighbors(context.Context, int) ([]Droplet, *Response, error) GetBackupPolicy(context.Context, int) (*DropletBackupPolicy, *Response, error) + ListBackupPolicies(context.Context) ([]*DropletBackupPolicy, *Response, error) + ListSupportedBackupPolicies(context.Context) ([]*SupportedBackupPolicy, *Response, error) } // DropletsServiceOp handles communication with the Droplet related methods of the @@ -631,7 +633,7 @@ func (s *DropletsServiceOp) dropletActionStatus(ctx context.Context, uri string) // DropletBackupPolicy defines the information about a droplet's backup policy. type DropletBackupPolicy struct { - DropletID int `json:"droplet_id"` + DropletID int `json:"droplet_id,omitempty"` BackupEnabled bool `json:"backup_enabled,omitempty"` BackupPolicy *BackupPolicy `json:"backup_policy,omitempty"` NextBackupWindow *BackupWindow `json:"next_backup_window,omitempty"` @@ -641,7 +643,7 @@ type DropletBackupPolicy struct { type BackupPolicy struct { Plan string `json:"plan,omitempty"` Weekday string `json:"weekday,omitempty"` - Hour string `json:"hour,omitempty"` + Hour int `json:"hour,omitempty"` WindowLengthHours int `json:"window_length_hours,omitempty"` RetentionPeriodDays int `json:"retention_period_days,omitempty"` } @@ -653,7 +655,7 @@ type dropletBackupPolicyRoot struct { type dropletBackupPoliciesRoot struct { DropletBackupPolicies []*DropletBackupPolicy `json:"policies,omitempty"` - Links *Links `json:"links"` + Links *Links `json:"links,omitempty"` Meta *Meta `json:"meta"` } @@ -699,7 +701,7 @@ func (s *DropletsServiceOp) ListBackupPolicies(ctx context.Context) ([]*DropletB resp.Meta = m } - return root.DropletBackupPolicies, resp, err + return root.DropletBackupPolicies, resp, nil } type SupportedBackupPolicy struct { @@ -728,5 +730,5 @@ func (s *DropletsServiceOp) ListSupportedBackupPolicies(ctx context.Context) ([] return nil, resp, err } - return root.SupportedBackupPolicies, resp, err + return root.SupportedBackupPolicies, resp, nil } diff --git a/droplets_test.go b/droplets_test.go index 6c9016e1..102a737d 100644 --- a/droplets_test.go +++ b/droplets_test.go @@ -1,11 +1,16 @@ package godo import ( + "context" "encoding/json" "fmt" "net/http" "reflect" "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDroplets_ListDroplets(t *testing.T) { @@ -952,3 +957,118 @@ func TestDroplets_IPMethods(t *testing.T) { t.Errorf("Droplet.PublicIPv6 returned %s; expected %s", got, expected) } } + +func TestDroplets_GetBackupPolicy(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/droplets/12345/backups/policy", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{ + "policy": { + "droplet_id": 12345, + "backup_enabled": true, + "backup_policy": { + "plan": "weekly", + "weekday": "SUN", + "hour": 0, + "window_length_hours": 4, + "retention_period_days": 28 + }, + "next_backup_window": { + "start": "2021-01-01T00:00:00Z", + "end": "2021-01-01T00:00:00Z" + } + } + }`) + }) + + policy, _, err := client.Droplets.GetBackupPolicy(ctx, 12345) + if err != nil { + t.Errorf("Droplets.GetBackupPolicy returned error: %v", err) + } + + pt, err := time.Parse(time.RFC3339, "2021-01-01T00:00:00Z") + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + expected := &DropletBackupPolicy{ + DropletID: 12345, + BackupEnabled: true, + BackupPolicy: &BackupPolicy{ + Plan: "weekly", + Weekday: "SUN", + Hour: 0, + WindowLengthHours: 4, + RetentionPeriodDays: 28, + }, + NextBackupWindow: &BackupWindow{ + Start: &Timestamp{Time: pt}, + End: &Timestamp{Time: pt}, + }, + } + if !reflect.DeepEqual(policy, expected) { + t.Errorf("Droplets.GetBackupPolicy\n got=%#v\nwant=%#v", policy, expected) + } +} + +func TestDroplets_ListBackupPolicies(t *testing.T) { + setup() + defer teardown() + + ctx := context.Background() + pt, err := time.Parse(time.RFC3339, "2021-01-01T00:00:00Z") + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + testBackupPolicy := DropletBackupPolicy{ + DropletID: 12345, + BackupEnabled: true, + BackupPolicy: &BackupPolicy{ + Plan: "weekly", + Weekday: "SUN", + Hour: 0, + WindowLengthHours: 4, + RetentionPeriodDays: 28, + }, + NextBackupWindow: &BackupWindow{ + Start: &Timestamp{Time: pt}, + End: &Timestamp{Time: pt}, + }, + } + + mux.HandleFunc("/v2/droplets/backups/policies", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + + json.NewEncoder(w).Encode(&dropletBackupPoliciesRoot{DropletBackupPolicies: []*DropletBackupPolicy{&testBackupPolicy}}) + }) + + policies, _, err := client.Droplets.ListBackupPolicies(ctx) + require.NoError(t, err) + assert.Equal(t, []*DropletBackupPolicy{&testBackupPolicy}, policies) +} + +func TestDroplets_ListSupportedBackupPolicies(t *testing.T) { + setup() + defer teardown() + + ctx := context.Background() + testSupportedBackupPolicy := SupportedBackupPolicy{ + Name: "weekly", + PossibleWindowStarts: []int{0, 4, 8, 12, 16, 20}, + WindowLengthHours: 4, + RetentionPeriodDays: 28, + PossibleDays: []string{"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}, + } + + mux.HandleFunc("/v2/droplets/backups/supported_policies", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + + json.NewEncoder(w).Encode(&dropletSupportedBackupPoliciesRoot{SupportedBackupPolicies: []*SupportedBackupPolicy{&testSupportedBackupPolicy}}) + }) + + policies, _, err := client.Droplets.ListSupportedBackupPolicies(ctx) + require.NoError(t, err) + assert.Equal(t, []*SupportedBackupPolicy{&testSupportedBackupPolicy}, policies) +}