diff --git a/digitalocean/droplet/resource_droplet.go b/digitalocean/droplet/resource_droplet.go index 17d5651e8..05d71f21f 100644 --- a/digitalocean/droplet/resource_droplet.go +++ b/digitalocean/droplet/resource_droplet.go @@ -2,6 +2,7 @@ package droplet import ( "context" + "errors" "fmt" "log" "net" @@ -355,46 +356,42 @@ func resourceDigitalOceanDropletCreate(ctx context.Context, d *schema.ResourceDa // Get configured backup_policy if policy, ok := d.GetOk("backup_policy"); ok { - objectList := policy.([]interface{}) - for _, rawObject := range objectList { - objectMap, ok := rawObject.(map[string]interface{}) + policyList := policy.([]interface{}) + for _, rawPolicy := range policyList { + policyMap, ok := rawPolicy.(map[string]interface{}) if !ok { return diag.FromErr(err) } - if planValue, exists := objectMap["plan"]; exists { - if plan, ok := planValue.(string); ok { - opts.BackupPolicy.Plan = plan - } else { - log.Println(">>> Error: plan is not a string") - } - } else { - log.Println(">>> Error: plan key does not exist") + planVal, exists := policyMap["plan"] + if !exists { + return diag.FromErr(errors.New("backup_policy plan key does not exist")) } - - if weekdayValue, exists := objectMap["weekday"]; exists { - if weekday, ok := weekdayValue.(string); ok { - fmt.Println("Weekday:", weekday) - opts.BackupPolicy.Weekday = weekday - } else { - log.Println(">>> Error: weekday is not a string") - } - } else { - log.Println(">>> Error: weekday key does not exist") + plan, ok := planVal.(string) + if !ok { + return diag.FromErr(errors.New("backup_policy plan is not a string")) } + opts.BackupPolicy.Plan = plan - if hourValue, exists := objectMap["hour"]; exists { - if hour, ok := hourValue.(int); ok { - fmt.Println("Hour:", hour) - opts.BackupPolicy.Hour = hour - } else { - log.Println(">>> Error: hour is not a float64") - } - } else { - log.Println(">>> Error: hour key does not exist") + weekdayVal, exists := policyMap["weekday"] + if !exists { + return diag.FromErr(errors.New("backup_policy weekday key does not exist")) } + weekday, ok := weekdayVal.(string) + if !ok { + return diag.FromErr(errors.New("backup_policy weekday is not a string")) + } + opts.BackupPolicy.Weekday = weekday - log.Println(">>> opts.BackupPolicy: ", opts.BackupPolicy) + hourVal, exists := policyMap["hour"] + if !exists { + return diag.FromErr(errors.New("backup_policy hour key does not exist")) + } + hour, ok := hourVal.(int) + if !ok { + return diag.FromErr(errors.New("backup_policy hour is not an int")) + } + opts.BackupPolicy.Hour = hour } } diff --git a/go.mod b/go.mod index 2b7f31fc6..2b5a02e68 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/digitalocean/terraform-provider-digitalocean require ( github.com/aws/aws-sdk-go v1.42.18 - github.com/digitalocean/godo v1.128.1-0.20241031134431-3a7bfd290da0 + github.com/digitalocean/godo v1.128.1-0.20241101193706-e886602c9e0c github.com/hashicorp/awspolicyequivalence v1.5.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/go-uuid v1.0.3 diff --git a/go.sum b/go.sum index a1c889f5c..30b03a293 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/digitalocean/godo v1.128.1-0.20241031134431-3a7bfd290da0 h1:WlqeI3UYtmkg10jNJYr/JwIfnWMomgIycRmhYqqaLB8= -github.com/digitalocean/godo v1.128.1-0.20241031134431-3a7bfd290da0/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= +github.com/digitalocean/godo v1.128.1-0.20241101193706-e886602c9e0c h1:701F+MG+3bwyBCEez9q8OKpgQ9fmkOVPrXTRIoI/MZI= +github.com/digitalocean/godo v1.128.1-0.20241101193706-e886602c9e0c/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= diff --git a/vendor/github.com/digitalocean/godo/droplet_actions.go b/vendor/github.com/digitalocean/godo/droplet_actions.go index 2e09d0c59..ba5019ed3 100644 --- a/vendor/github.com/digitalocean/godo/droplet_actions.go +++ b/vendor/github.com/digitalocean/godo/droplet_actions.go @@ -30,6 +30,7 @@ type DropletActionsService interface { SnapshotByTag(context.Context, string, string) ([]Action, *Response, error) EnableBackups(context.Context, int) (*Action, *Response, error) EnableBackupsByTag(context.Context, string) ([]Action, *Response, error) + EnableBackupsWithPolicy(context.Context, int, map[string]interface{}) (*Action, *Response, error) DisableBackups(context.Context, int) (*Action, *Response, error) DisableBackupsByTag(context.Context, string) ([]Action, *Response, error) PasswordReset(context.Context, int) (*Action, *Response, error) @@ -169,6 +170,12 @@ func (s *DropletActionsServiceOp) EnableBackupsByTag(ctx context.Context, tag st return s.doActionByTag(ctx, tag, request) } +// EnableBackupsWithPolicy enables droplet's backup with a backup policy applied. +func (s *DropletActionsServiceOp) EnableBackupsWithPolicy(ctx context.Context, id int, policy map[string]interface{}) (*Action, *Response, error) { + request := &ActionRequest{"type": "change_backup_policy", "backup_policy": policy} + return s.doAction(ctx, id, request) +} + // DisableBackups disables backups for a Droplet. func (s *DropletActionsServiceOp) DisableBackups(ctx context.Context, id int) (*Action, *Response, error) { request := &ActionRequest{"type": "disable_backups"} diff --git a/vendor/github.com/digitalocean/godo/droplets.go b/vendor/github.com/digitalocean/godo/droplets.go index 19a099d99..0366da7ab 100644 --- a/vendor/github.com/digitalocean/godo/droplets.go +++ b/vendor/github.com/digitalocean/godo/droplets.go @@ -260,7 +260,7 @@ type DropletMultiCreateRequest struct { type DropletBackupPolicyRequest struct { Plan string `json:"plan,omitempty"` Weekday string `json:"weekday,omitempty"` - Hour int `json:"hour,omitempty"` + Hour int `json:"hour"` // Avoid using omitempty to ensure zero values are included in the JSON output. } func (d DropletCreateRequest) String() string { @@ -633,14 +633,14 @@ 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,omitempty"` - BackupEnabled bool `json:"backup_enabled,omitempty"` - BackupPolicy *BackupPolicy `json:"backup_policy,omitempty"` - NextBackupWindow *BackupWindow `json:"next_backup_window,omitempty"` + DropletID int `json:"droplet_id,omitempty"` + BackupEnabled bool `json:"backup_enabled,omitempty"` + BackupPolicy *DropletBackupPolicyConfig `json:"backup_policy,omitempty"` + NextBackupWindow *BackupWindow `json:"next_backup_window,omitempty"` } -// BackupPolicy defines the backup policy for a Droplet. -type BackupPolicy struct { +// DropletBackupPolicyConfig defines the backup policy for a Droplet. +type DropletBackupPolicyConfig struct { Plan string `json:"plan,omitempty"` Weekday string `json:"weekday,omitempty"` Hour int `json:"hour,omitempty"` diff --git a/vendor/github.com/digitalocean/godo/godo.go b/vendor/github.com/digitalocean/godo/godo.go index edf0f6d46..efa1bd616 100644 --- a/vendor/github.com/digitalocean/godo/godo.go +++ b/vendor/github.com/digitalocean/godo/godo.go @@ -81,6 +81,7 @@ type Client struct { Projects ProjectsService Regions RegionsService Registry RegistryService + Registries RegistriesService ReservedIPs ReservedIPsService ReservedIPActions ReservedIPActionsService Sizes SizesService @@ -292,6 +293,7 @@ func NewClient(httpClient *http.Client) *Client { c.Projects = &ProjectsServiceOp{client: c} c.Regions = &RegionsServiceOp{client: c} c.Registry = &RegistryServiceOp{client: c} + c.Registries = &RegistriesServiceOp{client: c} c.ReservedIPs = &ReservedIPsServiceOp{client: c} c.ReservedIPActions = &ReservedIPActionsServiceOp{client: c} c.Sizes = &SizesServiceOp{client: c} diff --git a/vendor/github.com/digitalocean/godo/registry.go b/vendor/github.com/digitalocean/godo/registry.go index b0c243281..e64822682 100644 --- a/vendor/github.com/digitalocean/godo/registry.go +++ b/vendor/github.com/digitalocean/godo/registry.go @@ -14,6 +14,9 @@ const ( registryPath = "/v2/registry" // RegistryServer is the hostname of the DigitalOcean registry service RegistryServer = "registry.digitalocean.com" + + // Multi-registry Open Beta API constants + registriesPath = "/v2/registries" ) // RegistryService is an interface for interfacing with the Registry endpoints @@ -240,6 +243,19 @@ type RegistryValidateNameRequest struct { Name string `json:"name"` } +// Multi-registry Open Beta API structs + +type registriesRoot struct { + Registries []*Registry `json:"registries,omitempty"` + TotalStorageUsageBytes uint64 `json:"total_storage_usage_bytes,omitempty"` +} + +// RegistriesCreateRequest represents a request to create a secondary registry. +type RegistriesCreateRequest struct { + Name string `json:"name,omitempty"` + Region string `json:"region,omitempty"` +} + // Get retrieves the details of a Registry. func (svc *RegistryServiceOp) Get(ctx context.Context) (*Registry, *Response, error) { req, err := svc.client.NewRequest(ctx, http.MethodGet, registryPath, nil) @@ -610,3 +626,107 @@ func (svc *RegistryServiceOp) ValidateName(ctx context.Context, request *Registr } return resp, nil } + +// RegistriesService is an interface for interfacing with the new multiple-registry beta endpoints +// of the DigitalOcean API. +// +// We are creating a separate Service in alignment with the new /v2/registries endpoints. +type RegistriesService interface { + Get(context.Context, string) (*Registry, *Response, error) + List(context.Context) ([]*Registry, *Response, error) + Create(context.Context, *RegistriesCreateRequest) (*Registry, *Response, error) + Delete(context.Context, string) (*Response, error) + DockerCredentials(context.Context, string, *RegistryDockerCredentialsRequest) (*DockerCredentials, *Response, error) +} + +var _ RegistriesService = &RegistriesServiceOp{} + +// RegistriesServiceOp handles communication with the multiple-registry beta methods. +type RegistriesServiceOp struct { + client *Client +} + +// Get returns the details of a named Registry. +func (svc *RegistriesServiceOp) Get(ctx context.Context, registry string) (*Registry, *Response, error) { + path := fmt.Sprintf("%s/%s", registriesPath, registry) + req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + root := new(registryRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Registry, resp, nil +} + +// List returns a list of the named Registries. +func (svc *RegistriesServiceOp) List(ctx context.Context) ([]*Registry, *Response, error) { + req, err := svc.client.NewRequest(ctx, http.MethodGet, registriesPath, nil) + if err != nil { + return nil, nil, err + } + root := new(registriesRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Registries, resp, nil +} + +// Create creates a named Registry. +func (svc *RegistriesServiceOp) Create(ctx context.Context, create *RegistriesCreateRequest) (*Registry, *Response, error) { + req, err := svc.client.NewRequest(ctx, http.MethodPost, registriesPath, create) + if err != nil { + return nil, nil, err + } + root := new(registryRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Registry, resp, nil +} + +// Delete deletes a named Registry. There is no way to recover a Registry once it has +// been destroyed. +func (svc *RegistriesServiceOp) Delete(ctx context.Context, registry string) (*Response, error) { + path := fmt.Sprintf("%s/%s", registriesPath, registry) + req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + resp, err := svc.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + +// DockerCredentials retrieves a Docker config file containing named Registry's credentials. +func (svc *RegistriesServiceOp) DockerCredentials(ctx context.Context, registry string, request *RegistryDockerCredentialsRequest) (*DockerCredentials, *Response, error) { + path := fmt.Sprintf("%s/%s/%s", registriesPath, registry, "docker-credentials") + req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + q := req.URL.Query() + q.Add("read_write", strconv.FormatBool(request.ReadWrite)) + if request.ExpirySeconds != nil { + q.Add("expiry_seconds", strconv.Itoa(*request.ExpirySeconds)) + } + req.URL.RawQuery = q.Encode() + + var buf bytes.Buffer + resp, err := svc.client.Do(ctx, req, &buf) + if err != nil { + return nil, resp, err + } + + dc := &DockerCredentials{ + DockerConfigJSON: buf.Bytes(), + } + return dc, resp, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 7b5245042..34ae1e286 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -58,7 +58,7 @@ github.com/aws/aws-sdk-go/service/sts/stsiface # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew/spew -# github.com/digitalocean/godo v1.128.1-0.20241031134431-3a7bfd290da0 +# github.com/digitalocean/godo v1.128.1-0.20241101193706-e886602c9e0c ## explicit; go 1.22 github.com/digitalocean/godo github.com/digitalocean/godo/metrics