From d91733b97d5b86b5b017ed24576450f9587dcd63 Mon Sep 17 00:00:00 2001 From: Ashwani Date: Tue, 26 Nov 2024 11:37:12 +0530 Subject: [PATCH 01/13] updated godo version to 1.131.0 --- go.mod | 2 +- go.sum | 4 +- .../github.com/digitalocean/godo/CHANGELOG.md | 13 ++ .../github.com/digitalocean/godo/apps.gen.go | 4 +- vendor/github.com/digitalocean/godo/apps.go | 49 +++++++ .../github.com/digitalocean/godo/databases.go | 40 ++++-- vendor/github.com/digitalocean/godo/godo.go | 80 ++++++----- .../digitalocean/godo/load_balancers.go | 1 + .../digitalocean/godo/reserved_ipv6.go | 132 ++++++++++++++++++ .../godo/reserved_ipv6_actions.go | 57 ++++++++ vendor/modules.txt | 2 +- 11 files changed, 329 insertions(+), 55 deletions(-) create mode 100644 vendor/github.com/digitalocean/godo/reserved_ipv6.go create mode 100644 vendor/github.com/digitalocean/godo/reserved_ipv6_actions.go diff --git a/go.mod b/go.mod index b7efc11bf..1627d3d4a 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.129.0 + github.com/digitalocean/godo v1.131.0 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 6f2f8aceb..96132634a 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.129.0 h1:ov6v/O1N3cSuODgXBeTrwx9iYw44F4ZOHh/m9WsBp0I= -github.com/digitalocean/godo v1.129.0/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= +github.com/digitalocean/godo v1.131.0 h1:0WHymufAV5avpodT0h5/pucUVfO4v7biquOIqhLeROY= +github.com/digitalocean/godo v1.131.0/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/CHANGELOG.md b/vendor/github.com/digitalocean/godo/CHANGELOG.md index 735ab4ff0..3fb2a160c 100644 --- a/vendor/github.com/digitalocean/godo/CHANGELOG.md +++ b/vendor/github.com/digitalocean/godo/CHANGELOG.md @@ -1,5 +1,18 @@ # Change Log +## [v1.131.0] - 2024-11-25 + +- #760 - @jvasilevsky - LBAAS: add ipv6 field to loadbalancer model +- #759 - @imaskm - Add reserved ipv6 changes as Beta +- #758 - @dvigueras - Add Rules field to create Databases with Firewall Rules +- #751 - @blesswinsamuel - APPS-9766 Add method to restart apps + + +## [v1.130.0] - 2024-11-14 + +- #755 - @vsharma6855 - Add Missing Database Configs for Postgresql and MYSQL +- #754 - @blesswinsamuel - APPS-9858 Add method to obtain websocket URL to get console access into components + ## [v1.129.0] - 2024-11-06 - #752 - @andrewsomething - Support maps in Stringify diff --git a/vendor/github.com/digitalocean/godo/apps.gen.go b/vendor/github.com/digitalocean/godo/apps.gen.go index 0232ae943..6fc029cb9 100644 --- a/vendor/github.com/digitalocean/godo/apps.gen.go +++ b/vendor/github.com/digitalocean/godo/apps.gen.go @@ -466,8 +466,7 @@ type AppLogDestinationSpecPapertrail struct { type AppMaintenanceSpec struct { // Indicates whether maintenance mode should be enabled for the app. Enabled bool `json:"enabled,omitempty"` - // Indicates whether the app should be archived. Setting this to true implies that enabled is set to true. - // Note that this feature is currently in closed beta. + // Indicates whether the app should be archived. Setting this to true implies that enabled is set to true. Note that this feature is currently in closed beta. Archive bool `json:"archive,omitempty"` } @@ -1004,6 +1003,7 @@ const ( DeploymentCauseDetailsDigitalOceanUserActionName_RollbackApp DeploymentCauseDetailsDigitalOceanUserActionName = "ROLLBACK_APP" DeploymentCauseDetailsDigitalOceanUserActionName_RevertAppRollback DeploymentCauseDetailsDigitalOceanUserActionName = "REVERT_APP_ROLLBACK" DeploymentCauseDetailsDigitalOceanUserActionName_UpgradeBuildpack DeploymentCauseDetailsDigitalOceanUserActionName = "UPGRADE_BUILDPACK" + DeploymentCauseDetailsDigitalOceanUserActionName_Restart DeploymentCauseDetailsDigitalOceanUserActionName = "RESTART" ) // AppDomain struct for AppDomain diff --git a/vendor/github.com/digitalocean/godo/apps.go b/vendor/github.com/digitalocean/godo/apps.go index ac792658e..97b0cbd73 100644 --- a/vendor/github.com/digitalocean/godo/apps.go +++ b/vendor/github.com/digitalocean/godo/apps.go @@ -35,11 +35,13 @@ type AppsService interface { Delete(ctx context.Context, appID string) (*Response, error) Propose(ctx context.Context, propose *AppProposeRequest) (*AppProposeResponse, *Response, error) + Restart(ctx context.Context, appID string, opts *AppRestartRequest) (*Deployment, *Response, error) GetDeployment(ctx context.Context, appID, deploymentID string) (*Deployment, *Response, error) ListDeployments(ctx context.Context, appID string, opts *ListOptions) ([]*Deployment, *Response, error) CreateDeployment(ctx context.Context, appID string, create ...*DeploymentCreateRequest) (*Deployment, *Response, error) GetLogs(ctx context.Context, appID, deploymentID, component string, logType AppLogType, follow bool, tailLines int) (*AppLogs, *Response, error) + GetExec(ctx context.Context, appID, deploymentID, component string) (*AppExec, *Response, error) ListRegions(ctx context.Context) ([]*AppRegion, *Response, error) @@ -77,6 +79,11 @@ type AppLogs struct { HistoricURLs []string `json:"historic_urls"` } +// AppExec represents the websocket URL used for sending/receiving console input and output. +type AppExec struct { + URL string `json:"url"` +} + // AppUpdateRequest represents a request to update an app. type AppUpdateRequest struct { Spec *AppSpec `json:"spec"` @@ -89,6 +96,11 @@ type DeploymentCreateRequest struct { ForceBuild bool `json:"force_build"` } +// AppRestartRequest represents a request to restart an app. +type AppRestartRequest struct { + Components []string `json:"components"` +} + // AlertDestinationUpdateRequest represents a request to update alert destinations. type AlertDestinationUpdateRequest struct { Emails []string `json:"emails"` @@ -279,6 +291,22 @@ func (s *AppsServiceOp) Propose(ctx context.Context, propose *AppProposeRequest) return res, resp, nil } +// Restart restarts an app. +func (s *AppsServiceOp) Restart(ctx context.Context, appID string, opts *AppRestartRequest) (*Deployment, *Response, error) { + path := fmt.Sprintf("%s/%s/restart", appsBasePath, appID) + + req, err := s.client.NewRequest(ctx, http.MethodPost, path, opts) + if err != nil { + return nil, nil, err + } + root := new(deploymentRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Deployment, resp, nil +} + // GetDeployment gets an app deployment. func (s *AppsServiceOp) GetDeployment(ctx context.Context, appID, deploymentID string) (*Deployment, *Response, error) { path := fmt.Sprintf("%s/%s/deployments/%s", appsBasePath, appID, deploymentID) @@ -368,6 +396,27 @@ func (s *AppsServiceOp) GetLogs(ctx context.Context, appID, deploymentID, compon return logs, resp, nil } +// GetExec retrieves the websocket URL used for sending/receiving console input and output. +func (s *AppsServiceOp) GetExec(ctx context.Context, appID, deploymentID, component string) (*AppExec, *Response, error) { + var url string + if deploymentID == "" { + url = fmt.Sprintf("%s/%s/components/%s/exec", appsBasePath, appID, component) + } else { + url = fmt.Sprintf("%s/%s/deployments/%s/components/%s/exec", appsBasePath, appID, deploymentID, component) + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, nil, err + } + logs := new(AppExec) + resp, err := s.client.Do(ctx, req, logs) + if err != nil { + return nil, resp, err + } + return logs, resp, nil +} + // ListRegions lists all regions supported by App Platform. func (s *AppsServiceOp) ListRegions(ctx context.Context) ([]*AppRegion, *Response, error) { path := fmt.Sprintf("%s/regions", appsBasePath) diff --git a/vendor/github.com/digitalocean/godo/databases.go b/vendor/github.com/digitalocean/godo/databases.go index 276fb4a6b..1217ef05e 100644 --- a/vendor/github.com/digitalocean/godo/databases.go +++ b/vendor/github.com/digitalocean/godo/databases.go @@ -299,19 +299,27 @@ type DatabaseBackupRestore struct { BackupCreatedAt string `json:"backup_created_at,omitempty"` } +// DatabaseCreateFirewallRule is a rule describing an inbound source to a database +type DatabaseCreateFirewallRule struct { + UUID string `json:"uuid"` + Type string `json:"type"` + Value string `json:"value"` +} + // DatabaseCreateRequest represents a request to create a database cluster type DatabaseCreateRequest struct { - Name string `json:"name,omitempty"` - EngineSlug string `json:"engine,omitempty"` - Version string `json:"version,omitempty"` - SizeSlug string `json:"size,omitempty"` - Region string `json:"region,omitempty"` - NumNodes int `json:"num_nodes,omitempty"` - PrivateNetworkUUID string `json:"private_network_uuid"` - Tags []string `json:"tags,omitempty"` - BackupRestore *DatabaseBackupRestore `json:"backup_restore,omitempty"` - ProjectID string `json:"project_id"` - StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` + Name string `json:"name,omitempty"` + EngineSlug string `json:"engine,omitempty"` + Version string `json:"version,omitempty"` + SizeSlug string `json:"size,omitempty"` + Region string `json:"region,omitempty"` + NumNodes int `json:"num_nodes,omitempty"` + PrivateNetworkUUID string `json:"private_network_uuid"` + Tags []string `json:"tags,omitempty"` + BackupRestore *DatabaseBackupRestore `json:"backup_restore,omitempty"` + ProjectID string `json:"project_id"` + StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` + Rules []*DatabaseCreateFirewallRule `json:"rules"` } // DatabaseResizeRequest can be used to initiate a database resize operation. @@ -589,6 +597,9 @@ type PostgreSQLConfig struct { BackupMinute *int `json:"backup_minute,omitempty"` WorkMem *int `json:"work_mem,omitempty"` TimeScaleDB *PostgreSQLTimeScaleDBConfig `json:"timescaledb,omitempty"` + SynchronousReplication *string `json:"synchronous_replication,omitempty"` + StatMonitorEnable *bool `json:"stat_monitor_enable,omitempty"` + MaxFailoverReplicationTimeLag *int64 `json:"max_failover_replication_time_lag,omitempty"` } // PostgreSQLBouncerConfig configuration @@ -653,6 +664,13 @@ type MySQLConfig struct { BackupHour *int `json:"backup_hour,omitempty"` BackupMinute *int `json:"backup_minute,omitempty"` BinlogRetentionPeriod *int `json:"binlog_retention_period,omitempty"` + InnodbChangeBufferMaxSize *int `json:"innodb_change_buffer_max_size,omitempty"` + InnodbFlushNeighbors *int `json:"innodb_flush_neighbors,omitempty"` + InnodbReadIoThreads *int `json:"innodb_read_io_threads,omitempty"` + InnodbThreadConcurrency *int `json:"innodb_thread_concurrency,omitempty"` + InnodbWriteIoThreads *int `json:"innodb_write_io_threads,omitempty"` + NetBufferLength *int `json:"net_buffer_length,omitempty"` + LogOutput *string `json:"log_output,omitempty"` } // MongoDBConfig holds advanced configurations for MongoDB database clusters. diff --git a/vendor/github.com/digitalocean/godo/godo.go b/vendor/github.com/digitalocean/godo/godo.go index a399bc3eb..62498fc44 100644 --- a/vendor/github.com/digitalocean/godo/godo.go +++ b/vendor/github.com/digitalocean/godo/godo.go @@ -21,7 +21,7 @@ import ( ) const ( - libraryVersion = "1.129.0" + libraryVersion = "1.131.0" defaultBaseURL = "https://api.digitalocean.com/" userAgent = "godo/" + libraryVersion mediaType = "application/json" @@ -54,43 +54,45 @@ type Client struct { ratemtx sync.Mutex // Services used for communicating with the API - Account AccountService - Actions ActionsService - Apps AppsService - Balance BalanceService - BillingHistory BillingHistoryService - CDNs CDNService - Certificates CertificatesService - Databases DatabasesService - Domains DomainsService - Droplets DropletsService - DropletActions DropletActionsService - DropletAutoscale DropletAutoscaleService - Firewalls FirewallsService - FloatingIPs FloatingIPsService - FloatingIPActions FloatingIPActionsService - Functions FunctionsService - Images ImagesService - ImageActions ImageActionsService - Invoices InvoicesService - Keys KeysService - Kubernetes KubernetesService - LoadBalancers LoadBalancersService - Monitoring MonitoringService - OneClick OneClickService - Projects ProjectsService - Regions RegionsService - Registry RegistryService - Registries RegistriesService - ReservedIPs ReservedIPsService - ReservedIPActions ReservedIPActionsService - Sizes SizesService - Snapshots SnapshotsService - Storage StorageService - StorageActions StorageActionsService - Tags TagsService - UptimeChecks UptimeChecksService - VPCs VPCsService + Account AccountService + Actions ActionsService + Apps AppsService + Balance BalanceService + BillingHistory BillingHistoryService + CDNs CDNService + Certificates CertificatesService + Databases DatabasesService + Domains DomainsService + Droplets DropletsService + DropletActions DropletActionsService + DropletAutoscale DropletAutoscaleService + Firewalls FirewallsService + FloatingIPs FloatingIPsService + FloatingIPActions FloatingIPActionsService + Functions FunctionsService + Images ImagesService + ImageActions ImageActionsService + Invoices InvoicesService + Keys KeysService + Kubernetes KubernetesService + LoadBalancers LoadBalancersService + Monitoring MonitoringService + OneClick OneClickService + Projects ProjectsService + Regions RegionsService + Registry RegistryService + Registries RegistriesService + ReservedIPs ReservedIPsService + ReservedIPV6s ReservedIPV6sService + ReservedIPActions ReservedIPActionsService + ReservedIPV6Actions ReservedIPV6ActionsService + Sizes SizesService + Snapshots SnapshotsService + Storage StorageService + StorageActions StorageActionsService + Tags TagsService + UptimeChecks UptimeChecksService + VPCs VPCsService // Optional function called after every successful request made to the DO APIs onRequestCompleted RequestCompletionCallback @@ -295,7 +297,9 @@ func NewClient(httpClient *http.Client) *Client { c.Registry = &RegistryServiceOp{client: c} c.Registries = &RegistriesServiceOp{client: c} c.ReservedIPs = &ReservedIPsServiceOp{client: c} + c.ReservedIPV6s = &ReservedIPV6sServiceOp{client: c} c.ReservedIPActions = &ReservedIPActionsServiceOp{client: c} + c.ReservedIPV6Actions = &ReservedIPV6ActionsServiceOp{client: c} c.Sizes = &SizesServiceOp{client: c} c.Snapshots = &SnapshotsServiceOp{client: c} c.Storage = &StorageServiceOp{client: c} diff --git a/vendor/github.com/digitalocean/godo/load_balancers.go b/vendor/github.com/digitalocean/godo/load_balancers.go index a24952b71..a12729dd6 100644 --- a/vendor/github.com/digitalocean/godo/load_balancers.go +++ b/vendor/github.com/digitalocean/godo/load_balancers.go @@ -45,6 +45,7 @@ type LoadBalancer struct { ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` IP string `json:"ip,omitempty"` + IPv6 string `json:"ipv6,omitempty"` // SizeSlug is mutually exclusive with SizeUnit. Only one should be specified SizeSlug string `json:"size,omitempty"` // SizeUnit is mutually exclusive with SizeSlug. Only one should be specified diff --git a/vendor/github.com/digitalocean/godo/reserved_ipv6.go b/vendor/github.com/digitalocean/godo/reserved_ipv6.go new file mode 100644 index 000000000..aa2656359 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/reserved_ipv6.go @@ -0,0 +1,132 @@ +package godo + +import ( + "context" + "fmt" + "net/http" + "time" +) + +const resourceV6Type = "ReservedIPv6" +const reservedIPV6sBasePath = "v2/reserved_ipv6" + +// ReservedIPV6sService is an interface for interfacing with the reserved IPV6s +// endpoints of the Digital Ocean API. +type ReservedIPV6sService interface { + List(context.Context, *ListOptions) ([]ReservedIPV6, *Response, error) + Get(context.Context, string) (*ReservedIPV6, *Response, error) + Create(context.Context, *ReservedIPV6CreateRequest) (*ReservedIPV6, *Response, error) + Delete(context.Context, string) (*Response, error) +} + +// ReservedIPV6sServiceOp handles communication with the reserved IPs related methods of the +// DigitalOcean API. +type ReservedIPV6sServiceOp struct { + client *Client +} + +var _ ReservedIPV6sService = (*ReservedIPV6sServiceOp)(nil) + +// ReservedIPV6 represents a Digital Ocean reserved IP. +type ReservedIPV6 struct { + RegionSlug string `json:"region_slug"` + IP string `json:"ip"` + ReservedAt time.Time `json:"reserved_at"` + Droplet *Droplet `json:"droplet,omitempty"` +} + +func (f ReservedIPV6) String() string { + return Stringify(f) +} + +// URN returns the reserved IP in a valid DO API URN form. +func (f ReservedIPV6) URN() string { + return ToURN(resourceV6Type, f.IP) +} + +type reservedIPV6sRoot struct { + ReservedIPs []ReservedIPV6 `json:"reserved_ips"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +// ReservedIPV6CreateRequest represents a request to reserve a reserved IP. +type ReservedIPV6CreateRequest struct { + Region string `json:"region_slug,omitempty"` +} + +// List all reserved IPV6s. +func (r *ReservedIPV6sServiceOp) List(ctx context.Context, opt *ListOptions) ([]ReservedIPV6, *Response, error) { + path := reservedIPV6sBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := r.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(reservedIPV6sRoot) + resp, err := r.client.Do(ctx, req, root) + if err != nil { + return nil, nil, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.ReservedIPs, resp, err +} + +// Get an individual reserved IPv6. +func (r *ReservedIPV6sServiceOp) Get(ctx context.Context, ip string) (*ReservedIPV6, *Response, error) { + path := fmt.Sprintf("%s/%s", reservedIPV6sBasePath, ip) + + req, err := r.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(ReservedIPV6) + resp, err := r.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, err +} + +// Create a new IPv6 +func (r *ReservedIPV6sServiceOp) Create(ctx context.Context, reserveRequest *ReservedIPV6CreateRequest) (*ReservedIPV6, *Response, error) { + path := reservedIPV6sBasePath + + req, err := r.client.NewRequest(ctx, http.MethodPost, path, reserveRequest) + if err != nil { + return nil, nil, err + } + + root := new(ReservedIPV6) + resp, err := r.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, err +} + +// Delete a reserved IPv6. +func (r *ReservedIPV6sServiceOp) Delete(ctx context.Context, ip string) (*Response, error) { + path := fmt.Sprintf("%s/%s", reservedIPV6sBasePath, ip) + + req, err := r.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + return r.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/digitalocean/godo/reserved_ipv6_actions.go b/vendor/github.com/digitalocean/godo/reserved_ipv6_actions.go new file mode 100644 index 000000000..dd14bc58b --- /dev/null +++ b/vendor/github.com/digitalocean/godo/reserved_ipv6_actions.go @@ -0,0 +1,57 @@ +package godo + +import ( + "context" + "fmt" + "net/http" +) + +// ReservedIPActionsService is an interface for interfacing with the +// reserved IPs actions endpoints of the Digital Ocean API. +// See: https://docs.digitalocean.com/reference/api/api-reference/#tag/Reserved-IP-Actions +type ReservedIPV6ActionsService interface { + Assign(ctx context.Context, ip string, dropletID int) (*Action, *Response, error) + Unassign(ctx context.Context, ip string) (*Action, *Response, error) +} + +// ReservedIPActionsServiceOp handles communication with the reserved IPs +// action related methods of the DigitalOcean API. +type ReservedIPV6ActionsServiceOp struct { + client *Client +} + +// Assign a reserved IP to a droplet. +func (s *ReservedIPV6ActionsServiceOp) Assign(ctx context.Context, ip string, dropletID int) (*Action, *Response, error) { + request := &ActionRequest{ + "type": "assign", + "droplet_id": dropletID, + } + return s.doV6Action(ctx, ip, request) +} + +// Unassign a rerserved IP from the droplet it is currently assigned to. +func (s *ReservedIPV6ActionsServiceOp) Unassign(ctx context.Context, ip string) (*Action, *Response, error) { + request := &ActionRequest{"type": "unassign"} + return s.doV6Action(ctx, ip, request) +} + +func (s *ReservedIPV6ActionsServiceOp) doV6Action(ctx context.Context, ip string, request *ActionRequest) (*Action, *Response, error) { + path := reservedIPV6ActionPath(ip) + + req, err := s.client.NewRequest(ctx, http.MethodPost, path, request) + if err != nil { + return nil, nil, err + } + + root := new(actionRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Event, resp, err +} + +func reservedIPV6ActionPath(ip string) string { + return fmt.Sprintf("%s/%s/actions", reservedIPV6sBasePath, ip) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9c3c4ecfe..5852bf786 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.129.0 +# github.com/digitalocean/godo v1.131.0 ## explicit; go 1.22 github.com/digitalocean/godo github.com/digitalocean/godo/metrics From ee9364db067daabc145e844d199ed17c05d52e6a Mon Sep 17 00:00:00 2001 From: Ashwani Date: Tue, 26 Nov 2024 14:18:04 +0530 Subject: [PATCH 02/13] added reserved ipv6 resource --- .../reservedipv6/datasource_reserved_ipv6.go | 46 ++++ .../datasource_reserved_ipv6_test.go | 110 +++++++++ .../reservedipv6/import_reserved_ipv6_test.go | 51 ++++ .../reservedipv6/resource_reserved_ipv6.go | 226 +++++++++++++++++ .../resource_reserved_ipv6_assignment.go | 172 +++++++++++++ .../resource_reserved_ipv6_assignment_test.go | 227 ++++++++++++++++++ .../resource_reserved_ipv6_test.go | 179 ++++++++++++++ 7 files changed, 1011 insertions(+) create mode 100644 digitalocean/reservedipv6/datasource_reserved_ipv6.go create mode 100644 digitalocean/reservedipv6/datasource_reserved_ipv6_test.go create mode 100644 digitalocean/reservedipv6/import_reserved_ipv6_test.go create mode 100644 digitalocean/reservedipv6/resource_reserved_ipv6.go create mode 100644 digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go create mode 100644 digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go create mode 100644 digitalocean/reservedipv6/resource_reserved_ipv6_test.go diff --git a/digitalocean/reservedipv6/datasource_reserved_ipv6.go b/digitalocean/reservedipv6/datasource_reserved_ipv6.go new file mode 100644 index 000000000..07d704c1c --- /dev/null +++ b/digitalocean/reservedipv6/datasource_reserved_ipv6.go @@ -0,0 +1,46 @@ +package reservedipv6 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func DataSourceDigitalOceanReservedIPV6() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceDigitalOceanReservedIPV6Read, + Schema: map[string]*schema.Schema{ + "ip": { + Type: schema.TypeString, + Required: true, + Description: "reserved ipv6 address", + ValidateFunc: validation.NoZeroValues, + }, + // computed attributes + "urn": { + Type: schema.TypeString, + Computed: true, + Description: "the uniform resource name for the reserved ipv6", + }, + "region_slug": { + Type: schema.TypeString, + Computed: true, + Description: "the regionSlug that the reserved ipv6 is reserved to", + }, + "droplet_id": { + Type: schema.TypeInt, + Computed: true, + Description: "the droplet id that the reserved ip has been assigned to.", + }, + }, + } +} + +func dataSourceDigitalOceanReservedIPV6Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ipAddress := d.Get("ip").(string) + d.SetId(ipAddress) + + return resourceDigitalOceanReservedIPV6Read(ctx, d, meta) +} diff --git a/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go b/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go new file mode 100644 index 000000000..c66664188 --- /dev/null +++ b/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go @@ -0,0 +1,110 @@ +package reservedipv6_test + +import ( + "context" + "fmt" + "regexp" + "testing" + + "github.com/digitalocean/godo" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccDataSourceDigitalOceanReservedIPV6_Basic(t *testing.T) { + var reservedIPv6 godo.ReservedIPV6 + + expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i`) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccCheckDataSourceDigitalOceanReservedIPConfig_Basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceDigitalOceanReservedIPV6Exists("data.digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestCheckResourceAttrSet( + "data.digitalocean_reserved_ipv6.foobar", "ip"), + resource.TestCheckResourceAttr( + "data.digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), + resource.TestMatchResourceAttr("data.digitalocean_reserved_ipv6.foobar", "urn", expectedURNRegex), + ), + }, + }, + }) +} + +func TestAccDataSourceDigitalOceanReservedIPV6_FindsReservedIP(t *testing.T) { + var reservedIPv6 godo.ReservedIPV6 + + expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i`) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccCheckDataSourceDigitalOceanReservedIPConfig_FindsFloatingIP, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceDigitalOceanReservedIPV6Exists("data.digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestCheckResourceAttrSet( + "data.digitalocean_reserved_ipv6.foobar", "ip"), + resource.TestCheckResourceAttr( + "data.digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), + resource.TestMatchResourceAttr("data.digitalocean_reserved_ipv6.foobar", "urn", expectedURNRegex), + ), + }, + }, + }) +} + +func testAccCheckDataSourceDigitalOceanReservedIPV6Exists(n string, reservedIPv6 *godo.ReservedIPV6) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No reserved IPv6 ID is set") + } + + client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() + + foundReservedIP, _, err := client.ReservedIPV6s.Get(context.Background(), rs.Primary.ID) + + if err != nil { + return err + } + + if foundReservedIP.IP != rs.Primary.ID { + return fmt.Errorf("reserved IPv6 not found") + } + + *reservedIPv6 = *foundReservedIP + + return nil + } +} + +const testAccCheckDataSourceDigitalOceanReservedIPConfig_FindsFloatingIP = ` +resource "digitalocean_reserved_ipv6" "foo" { + region_slug = "nyc3" +} + +data "digitalocean_reserved_ipv6" "foobar" { + ip = digitalocean_reserved_ipv6.foo.ip +}` + +const testAccCheckDataSourceDigitalOceanReservedIPConfig_Basic = ` +resource "digitalocean_reserved_ipv6" "foo" { + region_slug = "nyc3" +} + +data "digitalocean_reserved_ipv6" "foobar" { + ip = digitalocean_reserved_ipv6.foo.ip +}` diff --git a/digitalocean/reservedipv6/import_reserved_ipv6_test.go b/digitalocean/reservedipv6/import_reserved_ipv6_test.go new file mode 100644 index 000000000..93c3d61b8 --- /dev/null +++ b/digitalocean/reservedipv6/import_reserved_ipv6_test.go @@ -0,0 +1,51 @@ +package reservedipv6_test + +import ( + "testing" + + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDigitalOceanReservedIPV6_importBasicRegion(t *testing.T) { + resourceName := "digitalocean_reserved_ipv6.foobar" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6Config_regionSlug, + }, + + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccDigitalOceanReservedIPV6_importBasicDroplet(t *testing.T) { + resourceName := "digitalocean_reserved_ipv6.foobar" + name := acceptance.RandomTestName() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6Config_droplet(name), + }, + + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6.go b/digitalocean/reservedipv6/resource_reserved_ipv6.go new file mode 100644 index 000000000..60f743e75 --- /dev/null +++ b/digitalocean/reservedipv6/resource_reserved_ipv6.go @@ -0,0 +1,226 @@ +package reservedipv6 + +import ( + "context" + "fmt" + "log" + "strings" + "time" + + "github.com/digitalocean/godo" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func ResourceDigitalOceanReservedIPV6() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceDigitalOceanReservedIPV6Create, + UpdateContext: resourceDigitalOceanReservedIPV6Update, + ReadContext: resourceDigitalOceanReservedIPV6Read, + DeleteContext: resourceDigitalOceanReservedIPV6Delete, + Importer: &schema.ResourceImporter{ + StateContext: resourceDigitalOceanReservedIPV6Import, + }, + + Schema: map[string]*schema.Schema{ + "region_slug": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: func(val interface{}) string { + // DO API V2 region slug is always lowercase + return strings.ToLower(val.(string)) + }, + }, + "urn": { + Type: schema.TypeString, + Computed: true, + Description: "the uniform resource name for the reserved ipv6", + }, + "ip": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.IsIPv6Address, + }, + "droplet_id": { + Type: schema.TypeInt, + Optional: true, + }, + }, + } +} + +func resourceDigitalOceanReservedIPV6Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + log.Printf("[INFO] Creating a reserved IPv6 in a region") + regionOpts := &godo.ReservedIPV6CreateRequest{ + Region: d.Get("region_slug").(string), + } + + log.Printf("[DEBUG] Reserved IPv6 create: %#v", regionOpts) + reservedIP, _, err := client.ReservedIPV6s.Create(context.Background(), regionOpts) + if err != nil { + return diag.Errorf("Error creating reserved IP: %s", err) + } + + d.SetId(reservedIP.IP) + + return resourceDigitalOceanReservedIPV6Read(ctx, d, meta) +} + +func resourceDigitalOceanReservedIPV6Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + if d.HasChange("droplet_id") { + if v, ok := d.GetOk("droplet_id"); ok { + log.Printf("[INFO] Assigning the reserved IPv6 %s to the Droplet %d", d.Id(), v.(int)) + action, _, err := client.ReservedIPV6Actions.Assign(context.Background(), d.Id(), v.(int)) + if err != nil { + return diag.Errorf( + "Error assigning reserved IPv6 (%s) to the Droplet: %s", d.Id(), err) + } + + _, unassignedErr := waitForReservedIPV6Ready(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if unassignedErr != nil { + return diag.Errorf( + "Error waiting for reserved IP (%s) to be Assigned: %s", d.Id(), unassignedErr) + } + } else { + log.Printf("[INFO] Unassigning the reserved IP %s", d.Id()) + action, _, err := client.ReservedIPV6Actions.Unassign(context.Background(), d.Id()) + if err != nil { + return diag.Errorf( + "Error unassigning reserved IP (%s): %s", d.Id(), err) + } + + _, unassignedErr := waitForReservedIPV6Ready(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if unassignedErr != nil { + return diag.Errorf( + "Error waiting for reserved IP (%s) to be Unassigned: %s", d.Id(), unassignedErr) + } + } + } + + return resourceDigitalOceanReservedIPV6Read(ctx, d, meta) +} + +func resourceDigitalOceanReservedIPV6Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + log.Printf("[INFO] Reading the details of the reserved IPv6 %s", d.Id()) + reservedIP, resp, err := client.ReservedIPV6s.Get(context.Background(), d.Id()) + if err != nil { + if resp != nil && resp.StatusCode == 404 { + log.Printf("[WARN] Reserved IPv6 (%s) not found", d.Id()) + d.SetId("") + return nil + } + + return diag.Errorf("Error retrieving reserved IPv6: %s", err) + } + + if _, ok := d.GetOk("droplet_id"); ok && reservedIP.Droplet != nil { + d.Set("region_slug", reservedIP.Droplet.Region.Slug) + d.Set("droplet_id", reservedIP.Droplet.ID) + } else { + d.Set("region_slug", reservedIP.RegionSlug) + } + + d.Set("ip", reservedIP.IP) + d.Set("urn", reservedIP.URN()) + + return nil +} + +func resourceDigitalOceanReservedIPV6Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + if _, ok := d.GetOk("droplet_id"); ok { + log.Printf("[INFO] Unassigning the reserved IPv7 from the Droplet") + action, resp, err := client.ReservedIPV6Actions.Unassign(context.Background(), d.Id()) + if resp.StatusCode != 422 { + if err != nil { + return diag.Errorf( + "Error unassigning reserved IP (%s) from the droplet: %s", d.Id(), err) + } + + _, unassignedErr := waitForReservedIPV6Ready(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if unassignedErr != nil { + return diag.Errorf( + "Error waiting for reserved IPv6 (%s) to be unassigned: %s", d.Id(), unassignedErr) + } + } else { + log.Printf("[DEBUG] Couldn't unassign reserved IPv6 (%s) from droplet, possibly out of sync: %s", d.Id(), err) + } + } + + log.Printf("[INFO] Deleting reserved IPv6: %s", d.Id()) + _, err := client.ReservedIPV6s.Delete(context.Background(), d.Id()) + if err != nil { + return diag.Errorf("Error deleting reserved IPv6: %s", err) + } + + d.SetId("") + return nil +} + +func resourceDigitalOceanReservedIPV6Import(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + client := meta.(*config.CombinedConfig).GodoClient() + reservedIP, resp, err := client.ReservedIPV6s.Get(context.Background(), d.Id()) + if resp.StatusCode != 404 { + if err != nil { + return nil, err + } + + d.Set("ip", reservedIP.IP) + d.Set("urn", reservedIP.URN()) + d.Set("region_slug", reservedIP.RegionSlug) + + if reservedIP.Droplet != nil { + d.Set("droplet_id", reservedIP.Droplet.ID) + } + } + + return []*schema.ResourceData{d}, nil +} + +func waitForReservedIPV6Ready( + ctx context.Context, d *schema.ResourceData, target string, pending []string, attribute string, meta interface{}, actionID int) (interface{}, error) { + log.Printf( + "[INFO] Waiting for reserved IPv6 (%s) to have %s of %s", + d.Id(), attribute, target) + + stateConf := &retry.StateChangeConf{ + Pending: pending, + Target: []string{target}, + Refresh: newReservedIPV6StateRefreshFunc(d, meta, actionID), + Timeout: 60 * time.Minute, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + + NotFoundChecks: 60, + } + + return stateConf.WaitForStateContext(ctx) +} + +func newReservedIPV6StateRefreshFunc( + d *schema.ResourceData, meta interface{}, actionID int) retry.StateRefreshFunc { + client := meta.(*config.CombinedConfig).GodoClient() + return func() (interface{}, string, error) { + + log.Printf("[INFO] Assigning the reserved IPv6 to the Droplet") + action, _, err := client.Actions.Get(context.Background(), actionID) + if err != nil { + return nil, "", fmt.Errorf("error retrieving reserved IPv6 (%s) ActionId (%d): %s", d.Id(), actionID, err) + } + + log.Printf("[INFO] The reserved IP Action Status is %s", action.Status) + return &action, action.Status, nil + } +} diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go new file mode 100644 index 000000000..08663b141 --- /dev/null +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go @@ -0,0 +1,172 @@ +package reservedipv6 + +import ( + "context" + "errors" + "fmt" + "log" + "strconv" + "strings" + "time" + + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func ResourceDigitalOceanReservedIPV6Assignment() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceDigitalOceanReservedIPV6AssignmentCreate, + ReadContext: resourceDigitalOceanReservedIPV6AssignmentRead, + DeleteContext: resourceDigitalOceanReservedIPV6AssignmentDelete, + Importer: &schema.ResourceImporter{ + StateContext: resourceDigitalOceanReservedIPV6AssignmentImport, + }, + + Schema: map[string]*schema.Schema{ + "ip": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.IsIPv4Address, + }, + "droplet_id": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.NoZeroValues, + }, + }, + } +} + +func resourceDigitalOceanReservedIPV6AssignmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + ipAddress := d.Get("ip").(string) + dropletID := d.Get("droplet_id").(int) + + log.Printf("[INFO] Assigning the reserved IPv6 (%s) to the Droplet %d", ipAddress, dropletID) + action, _, err := client.ReservedIPV6Actions.Assign(context.Background(), ipAddress, dropletID) + if err != nil { + return diag.Errorf( + "Error Assigning reserved IPv6 (%s) to the droplet: %s", ipAddress, err) + } + + _, unassignedErr := waitForReservedIPV6AssignmentReady(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if unassignedErr != nil { + return diag.Errorf( + "Error waiting for reserved IPv6 (%s) to be Assigned: %s", ipAddress, unassignedErr) + } + + d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%d-%s-", dropletID, ipAddress))) + return resourceDigitalOceanReservedIPV6AssignmentRead(ctx, d, meta) +} + +func resourceDigitalOceanReservedIPV6AssignmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + ipAddress := d.Get("ip").(string) + dropletID := d.Get("droplet_id").(int) + + log.Printf("[INFO] Reading the details of the reserved IPv6 %s", ipAddress) + reservedIPv6, _, err := client.ReservedIPV6s.Get(context.Background(), ipAddress) + if err != nil { + return diag.Errorf("Error retrieving reserved IPv6: %s", err) + } + + if reservedIPv6.Droplet == nil || reservedIPv6.Droplet.ID != dropletID { + log.Printf("[INFO] A Droplet was detected on the reserved IPv6.") + d.SetId("") + } + + return nil +} + +func resourceDigitalOceanReservedIPV6AssignmentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.CombinedConfig).GodoClient() + + ipAddress := d.Get("ip").(string) + dropletID := d.Get("droplet_id").(int) + + log.Printf("[INFO] Reading the details of the reserved IPv6 %s", ipAddress) + reservedIPv6, _, err := client.ReservedIPV6s.Get(context.Background(), ipAddress) + if err != nil { + return diag.Errorf("Error retrieving reserved IPv6: %s", err) + } + + if reservedIPv6.Droplet.ID == dropletID { + log.Printf("[INFO] Unassigning the reserved IPv6 from the Droplet") + action, _, err := client.ReservedIPActions.Unassign(context.Background(), ipAddress) + if err != nil { + return diag.Errorf("Error unassigning reserved IPv6 (%s) from the droplet: %s", ipAddress, err) + } + + _, unassignedErr := waitForReservedIPV6AssignmentReady(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if unassignedErr != nil { + return diag.Errorf( + "Error waiting for reserved IPv6 (%s) to be unassigned: %s", ipAddress, unassignedErr) + } + } else { + log.Printf("[INFO] reserved IPv6 already unassigned, removing from state.") + } + + d.SetId("") + return nil +} + +func waitForReservedIPV6AssignmentReady( + ctx context.Context, d *schema.ResourceData, target string, pending []string, attribute string, meta interface{}, actionID int) (interface{}, error) { + log.Printf( + "[INFO] Waiting for reserved IPv6 (%s) to have %s of %s", + d.Get("ip").(string), attribute, target) + + stateConf := &retry.StateChangeConf{ + Pending: pending, + Target: []string{target}, + Refresh: newReservedIPV6AssignmentStateRefreshFunc(d, meta, actionID), + Timeout: 60 * time.Minute, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + + NotFoundChecks: 60, + } + + return stateConf.WaitForStateContext(ctx) +} + +func newReservedIPV6AssignmentStateRefreshFunc( + d *schema.ResourceData, meta interface{}, actionID int) retry.StateRefreshFunc { + client := meta.(*config.CombinedConfig).GodoClient() + return func() (interface{}, string, error) { + + log.Printf("[INFO] Refreshing the reserved IPv6 state") + action, _, err := client.Actions.Get(context.Background(), actionID) + if err != nil { + return nil, "", fmt.Errorf("error retrieving reserved IPv6 (%s) ActionId (%d): %s", d.Get("ip_address").(string), actionID, err) + } + + log.Printf("[INFO] The reserved IPv6 Action Status is %s", action.Status) + return &action, action.Status, nil + } +} + +func resourceDigitalOceanReservedIPV6AssignmentImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + if strings.Contains(d.Id(), ",") { + s := strings.Split(d.Id(), ",") + d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-%s-", s[1], s[0]))) + d.Set("ip", s[0]) + dropletID, err := strconv.Atoi(s[1]) + if err != nil { + return nil, err + } + d.Set("droplet_id", dropletID) + } else { + return nil, errors.New("must use the reserved IPv6 and the ID of the Droplet joined with a comma (e.g. `ip,droplet_id`)") + } + + return []*schema.ResourceData{d}, nil +} diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go new file mode 100644 index 000000000..057c75b3b --- /dev/null +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go @@ -0,0 +1,227 @@ +package reservedipv6_test + +import ( + "context" + "fmt" + "regexp" + "strconv" + "testing" + + "github.com/digitalocean/godo" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccDigitalOceanReservedIPV6Assignment(t *testing.T) { + var reservedIPv6 godo.ReservedIPV6 + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentReassign, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentDeleteAssignment, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6.foobar", "ip", regexp.MustCompile("[0-9.]+")), + ), + }, + }, + }) +} + +func TestAccDigitalOceanReservedIPV6Assignment_createBeforeDestroy(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroy, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroyReassign, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + }, + }) +} + +func testAccCheckDigitalOceanReservedIPV6AttachmentExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.Attributes["ip_address"] == "" { + return fmt.Errorf("No floating IP is set") + } + fipID := rs.Primary.Attributes["ip_address"] + dropletID, err := strconv.Atoi(rs.Primary.Attributes["droplet_id"]) + if err != nil { + return err + } + + client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() + + // Try to find the ReservedIP + foundReservedIP, _, err := client.ReservedIPs.Get(context.Background(), fipID) + if err != nil { + return err + } + + if foundReservedIP.IP != fipID || foundReservedIP.Droplet.ID != dropletID { + return fmt.Errorf("wrong floating IP attachment found") + } + + return nil + } +} + +var testAccCheckDigitalOceanReservedIPV6AssignmentConfig = ` +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_droplet" "foobar" { + count = 2 + name = "tf-acc-test-${count.index}" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true +} + +resource "digitalocean_reserved_ipv6_assignment" "foobar" { + ip = digitalocean_reserved_ipv6.foobar.ip + droplet_id = digitalocean_droplet.foobar.0.id +} +` + +var testAccCheckDigitalOceanReservedIPV6AssignmentReassign = ` +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_droplet" "foobar" { + count = 2 + name = "tf-acc-test-${count.index}" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true +} + +resource "digitalocean_reserved_ipv6_assignment" "foobar" { + ip = digitalocean_reserved_ipv6.foobar.ip + droplet_id = digitalocean_droplet.foobar.1.id +} +` + +var testAccCheckDigitalOceanReservedIPV6AssignmentDeleteAssignment = ` +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_droplet" "foobar" { + count = 2 + name = "tf-acc-test-${count.index}" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true +} +` + +var testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroy = ` +resource "digitalocean_droplet" "foobar" { + image = "ubuntu-22-04-x64" + name = "tf-acc-test" + region = "nyc3" + size = "s-1vcpu-1gb" + + lifecycle { + create_before_destroy = true + } +} + +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_reserved_ipv6_assignment" "foobar" { + ip = digitalocean_reserved_ipv6.foobar.id + droplet_id = digitalocean_droplet.foobar.id + + lifecycle { + create_before_destroy = true + } +} +` + +var testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroyReassign = ` +resource "digitalocean_droplet" "foobar" { + image = "ubuntu-18-04-x64" + name = "tf-acc-test-01" + region = "nyc3" + size = "s-1vcpu-1gb" + + lifecycle { + create_before_destroy = true + } +} + +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_reserved_ipv6_assignment" "foobar" { + ip = digitalocean_reserved_ipv6.foobar.id + droplet_id = digitalocean_droplet.foobar.id + + lifecycle { + create_before_destroy = true + } +} +` diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go new file mode 100644 index 000000000..4b655b311 --- /dev/null +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go @@ -0,0 +1,179 @@ +package reservedipv6_test + +import ( + "context" + "fmt" + "regexp" + "testing" + + "github.com/digitalocean/godo" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccDigitalOceanReservedIPV6_RegionSlug(t *testing.T) { + var reservedIPv6 godo.ReservedIPV6 + + expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i`) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6Config_regionSlug, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestCheckResourceAttr( + "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), + resource.TestMatchResourceAttr("digitalocean_reserved_ipv6.foobar", "urn", expectedURNRegex), + ), + }, + }, + }) +} + +func TestAccDigitalOceanReservedIPV6_Droplet(t *testing.T) { + var reservedIPv6 godo.ReservedIPV6 + name := acceptance.RandomTestName() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6Config_droplet(name), + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestCheckResourceAttr( + "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), + ), + }, + { + Config: testAccCheckDigitalOceanReservedIPv6Config_Reassign(name), + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestCheckResourceAttr( + "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), + ), + }, + { + Config: testAccCheckDigitalOceanReservedIPV6Config_Unassign(name), + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), + resource.TestCheckResourceAttr( + "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), + ), + }, + }, + }) +} + +func testAccCheckDigitalOceanReservedIPV6Destroy(s *terraform.State) error { + client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "digitalocean_reserved_ipv6" { + continue + } + + // Try to find the key + _, _, err := client.ReservedIPV6s.Get(context.Background(), rs.Primary.ID) + + if err == nil { + return fmt.Errorf("Reserved IPv6 still exists") + } + } + + return nil +} + +func testAccCheckDigitalOceanReservedIPV6Exists(n string, reservedIPv6 *godo.ReservedIPV6) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No Record ID is set") + } + + client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() + + // Try to find the ReservedIPv6 + foundReservedIP, _, err := client.ReservedIPV6s.Get(context.Background(), rs.Primary.ID) + + if err != nil { + return err + } + + if foundReservedIP.IP != rs.Primary.ID { + return fmt.Errorf("Record not found") + } + + *reservedIPv6 = *foundReservedIP + + return nil + } +} + +var testAccCheckDigitalOceanReservedIPV6Config_regionSlug = ` +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +}` + +func testAccCheckDigitalOceanReservedIPV6Config_droplet(name string) string { + return fmt.Sprintf(` +resource "digitalocean_droplet" "foobar" { + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true +} + +resource "digitalocean_reserved_ipv6" "foobar" { + droplet_id = digitalocean_droplet.foobar.id + region_slug = digitalocean_droplet.foobar.region +}`, name) +} + +func testAccCheckDigitalOceanReservedIPv6Config_Reassign(name string) string { + return fmt.Sprintf(` +resource "digitalocean_droplet" "baz" { + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true +} + +resource "digitalocean_reserved_ipv6" "foobar" { + droplet_id = digitalocean_droplet.baz.id + region_slug = digitalocean_droplet.baz.region +}`, name) +} + +func testAccCheckDigitalOceanReservedIPV6Config_Unassign(name string) string { + return fmt.Sprintf(` +resource "digitalocean_droplet" "baz" { + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true +} + +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +}`, name) +} From 7e2b2d54a3ef9d944576c0f846235fc45243de6d Mon Sep 17 00:00:00 2001 From: Ashwani Date: Fri, 29 Nov 2024 00:03:47 +0530 Subject: [PATCH 03/13] updated godo commit --- go.mod | 6 ++-- go.sum | 12 +++---- .../digitalocean/godo/reserved_ipv6.go | 33 ++++++++++--------- vendor/golang.org/x/oauth2/README.md | 15 +++------ vendor/golang.org/x/time/rate/rate.go | 17 ++-------- vendor/modules.txt | 6 ++-- 6 files changed, 38 insertions(+), 51 deletions(-) diff --git a/go.mod b/go.mod index 1627d3d4a..2a2151d16 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.131.0 + github.com/digitalocean/godo v1.131.1-0.20241127211050-a97e39731918 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 @@ -11,7 +11,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure/v2 v2.0.1 github.com/stretchr/testify v1.8.4 - golang.org/x/oauth2 v0.23.0 + golang.org/x/oauth2 v0.24.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -60,7 +60,7 @@ require ( golang.org/x/net v0.23.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.6.0 // indirect + golang.org/x/time v0.8.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect diff --git a/go.sum b/go.sum index 96132634a..c7d6398bd 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.131.0 h1:0WHymufAV5avpodT0h5/pucUVfO4v7biquOIqhLeROY= -github.com/digitalocean/godo v1.131.0/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= +github.com/digitalocean/godo v1.131.1-0.20241127211050-a97e39731918 h1:7xOw7i5AFH1n5vIMMH7HtR87jdxV8XnLKOBafNbVetM= +github.com/digitalocean/godo v1.131.1-0.20241127211050-a97e39731918/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= @@ -238,8 +238,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -281,8 +281,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/vendor/github.com/digitalocean/godo/reserved_ipv6.go b/vendor/github.com/digitalocean/godo/reserved_ipv6.go index aa2656359..119c6bde3 100644 --- a/vendor/github.com/digitalocean/godo/reserved_ipv6.go +++ b/vendor/github.com/digitalocean/godo/reserved_ipv6.go @@ -34,6 +34,15 @@ type ReservedIPV6 struct { ReservedAt time.Time `json:"reserved_at"` Droplet *Droplet `json:"droplet,omitempty"` } +type reservedIPV6Root struct { + ReservedIPV6 *ReservedIPV6 `json:"reserved_ipv6"` +} + +type reservedIPV6sRoot struct { + ReservedIPV6s []ReservedIPV6 `json:"reserved_ipv6s"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} func (f ReservedIPV6) String() string { return Stringify(f) @@ -44,12 +53,6 @@ func (f ReservedIPV6) URN() string { return ToURN(resourceV6Type, f.IP) } -type reservedIPV6sRoot struct { - ReservedIPs []ReservedIPV6 `json:"reserved_ips"` - Links *Links `json:"links"` - Meta *Meta `json:"meta"` -} - // ReservedIPV6CreateRequest represents a request to reserve a reserved IP. type ReservedIPV6CreateRequest struct { Region string `json:"region_slug,omitempty"` @@ -73,14 +76,14 @@ func (r *ReservedIPV6sServiceOp) List(ctx context.Context, opt *ListOptions) ([] if err != nil { return nil, nil, err } - if l := root.Links; l != nil { - resp.Links = l + if root.Meta != nil { + resp.Meta = root.Meta } - if m := root.Meta; m != nil { - resp.Meta = m + if root.Links != nil { + resp.Links = root.Links } - return root.ReservedIPs, resp, err + return root.ReservedIPV6s, resp, err } // Get an individual reserved IPv6. @@ -92,13 +95,13 @@ func (r *ReservedIPV6sServiceOp) Get(ctx context.Context, ip string) (*ReservedI return nil, nil, err } - root := new(ReservedIPV6) + root := new(reservedIPV6Root) resp, err := r.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root, resp, err + return root.ReservedIPV6, resp, err } // Create a new IPv6 @@ -110,13 +113,13 @@ func (r *ReservedIPV6sServiceOp) Create(ctx context.Context, reserveRequest *Res return nil, nil, err } - root := new(ReservedIPV6) + root := new(reservedIPV6Root) resp, err := r.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root, resp, err + return root.ReservedIPV6, resp, err } // Delete a reserved IPv6. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md index 781770c20..48dbb9d84 100644 --- a/vendor/golang.org/x/oauth2/README.md +++ b/vendor/golang.org/x/oauth2/README.md @@ -5,15 +5,6 @@ oauth2 package contains a client implementation for OAuth 2.0 spec. -## Installation - -~~~~ -go get golang.org/x/oauth2 -~~~~ - -Or you can manually git clone the repository to -`$(go env GOPATH)/src/golang.org/x/oauth2`. - See pkg.go.dev for further documentation and examples. * [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) @@ -33,7 +24,11 @@ The main issue tracker for the oauth2 repository is located at https://github.com/golang/oauth2/issues. This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. In particular: +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/oauth2. + +Note: * Excluding trivial changes, all contributions should be connected to an existing issue. * API changes must go through the [change proposal process](https://go.dev/s/proposal-process) before they can be accepted. diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go index 8f6c7f493..93a798ab6 100644 --- a/vendor/golang.org/x/time/rate/rate.go +++ b/vendor/golang.org/x/time/rate/rate.go @@ -99,8 +99,9 @@ func (lim *Limiter) Tokens() float64 { // bursts of at most b tokens. func NewLimiter(r Limit, b int) *Limiter { return &Limiter{ - limit: r, - burst: b, + limit: r, + burst: b, + tokens: float64(b), } } @@ -344,18 +345,6 @@ func (lim *Limiter) reserveN(t time.Time, n int, maxFutureReserve time.Duration) tokens: n, timeToAct: t, } - } else if lim.limit == 0 { - var ok bool - if lim.burst >= n { - ok = true - lim.burst -= n - } - return Reservation{ - ok: ok, - lim: lim, - tokens: lim.burst, - timeToAct: t, - } } t, tokens := lim.advance(t) diff --git a/vendor/modules.txt b/vendor/modules.txt index 5852bf786..1a2d97ae0 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.131.0 +# github.com/digitalocean/godo v1.131.1-0.20241127211050-a97e39731918 ## explicit; go 1.22 github.com/digitalocean/godo github.com/digitalocean/godo/metrics @@ -308,7 +308,7 @@ golang.org/x/net/http2/hpack golang.org/x/net/idna golang.org/x/net/internal/timeseries golang.org/x/net/trace -# golang.org/x/oauth2 v0.23.0 +# golang.org/x/oauth2 v0.24.0 ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/internal @@ -323,7 +323,7 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/time v0.6.0 +# golang.org/x/time v0.8.0 ## explicit; go 1.18 golang.org/x/time/rate # google.golang.org/appengine v1.6.7 From 890e30d816e5dba4ec47d990e152e0232b39432c Mon Sep 17 00:00:00 2001 From: Ashwani Date: Fri, 29 Nov 2024 11:36:12 +0530 Subject: [PATCH 04/13] Addressed review comments --- digitalocean/provider.go | 4 ++++ digitalocean/reservedipv6/resource_reserved_ipv6.go | 6 +++--- .../reservedipv6/resource_reserved_ipv6_test.go | 11 +++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/digitalocean/provider.go b/digitalocean/provider.go index f0d682d5c..9eb4741b0 100644 --- a/digitalocean/provider.go +++ b/digitalocean/provider.go @@ -20,6 +20,7 @@ import ( "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/region" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/registry" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/reservedip" + "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/reservedipv6" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/size" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/snapshot" "github.com/digitalocean/terraform-provider-digitalocean/digitalocean/spaces" @@ -125,6 +126,7 @@ func Provider() *schema.Provider { "digitalocean_region": region.DataSourceDigitalOceanRegion(), "digitalocean_regions": region.DataSourceDigitalOceanRegions(), "digitalocean_reserved_ip": reservedip.DataSourceDigitalOceanReservedIP(), + "digitalocean_reserved_ipv6": reservedipv6.DataSourceDigitalOceanReservedIPV6(), "digitalocean_sizes": size.DataSourceDigitalOceanSizes(), "digitalocean_spaces_bucket": spaces.DataSourceDigitalOceanSpacesBucket(), "digitalocean_spaces_buckets": spaces.DataSourceDigitalOceanSpacesBuckets(), @@ -174,6 +176,8 @@ func Provider() *schema.Provider { "digitalocean_record": domain.ResourceDigitalOceanRecord(), "digitalocean_reserved_ip": reservedip.ResourceDigitalOceanReservedIP(), "digitalocean_reserved_ip_assignment": reservedip.ResourceDigitalOceanReservedIPAssignment(), + "digitalocean_reserved_ipv6": reservedipv6.ResourceDigitalOceanReservedIPV6(), + "digitalocean_reserved_ipv6_assignment": reservedipv6.ResourceDigitalOceanReservedIPV6Assignment(), "digitalocean_spaces_bucket": spaces.ResourceDigitalOceanBucket(), "digitalocean_spaces_bucket_cors_configuration": spaces.ResourceDigitalOceanBucketCorsConfiguration(), "digitalocean_spaces_bucket_object": spaces.ResourceDigitalOceanSpacesBucketObject(), diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6.go b/digitalocean/reservedipv6/resource_reserved_ipv6.go index 60f743e75..a46956d53 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6.go @@ -141,12 +141,12 @@ func resourceDigitalOceanReservedIPV6Delete(ctx context.Context, d *schema.Resou client := meta.(*config.CombinedConfig).GodoClient() if _, ok := d.GetOk("droplet_id"); ok { - log.Printf("[INFO] Unassigning the reserved IPv7 from the Droplet") + log.Printf("[INFO] Unassigning the reserved IPv6 from the Droplet") action, resp, err := client.ReservedIPV6Actions.Unassign(context.Background(), d.Id()) if resp.StatusCode != 422 { if err != nil { return diag.Errorf( - "Error unassigning reserved IP (%s) from the droplet: %s", d.Id(), err) + "Error unassigning reserved IPv6 (%s) from the droplet: %s", d.Id(), err) } _, unassignedErr := waitForReservedIPV6Ready(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) @@ -220,7 +220,7 @@ func newReservedIPV6StateRefreshFunc( return nil, "", fmt.Errorf("error retrieving reserved IPv6 (%s) ActionId (%d): %s", d.Id(), actionID, err) } - log.Printf("[INFO] The reserved IP Action Status is %s", action.Status) + log.Printf("[INFO] The reserved IPv6 Action Status is %s", action.Status) return &action, action.Status, nil } } diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go index 4b655b311..64653c5f9 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go @@ -131,12 +131,11 @@ resource "digitalocean_reserved_ipv6" "foobar" { func testAccCheckDigitalOceanReservedIPV6Config_droplet(name string) string { return fmt.Sprintf(` resource "digitalocean_droplet" "foobar" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true } resource "digitalocean_reserved_ipv6" "foobar" { From ba7f286ad5412ec7ef99eb55a33550c39f7559c7 Mon Sep 17 00:00:00 2001 From: Ashwani Date: Fri, 29 Nov 2024 22:43:06 +0530 Subject: [PATCH 05/13] updated test config --- .../resource_reserved_ipv6_test.go | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go index 64653c5f9..ca024c363 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go @@ -147,12 +147,11 @@ resource "digitalocean_reserved_ipv6" "foobar" { func testAccCheckDigitalOceanReservedIPv6Config_Reassign(name string) string { return fmt.Sprintf(` resource "digitalocean_droplet" "baz" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true } resource "digitalocean_reserved_ipv6" "foobar" { @@ -164,12 +163,11 @@ resource "digitalocean_reserved_ipv6" "foobar" { func testAccCheckDigitalOceanReservedIPV6Config_Unassign(name string) string { return fmt.Sprintf(` resource "digitalocean_droplet" "baz" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true } resource "digitalocean_reserved_ipv6" "foobar" { From fded4161154df69679c7674c163e05642ccaaa4e Mon Sep 17 00:00:00 2001 From: Ashwani Date: Mon, 9 Dec 2024 22:53:15 +0530 Subject: [PATCH 06/13] added some fixes --- digitalocean/droplet/resource_droplet.go | 2 +- .../datasource_reserved_ipv6_test.go | 4 +- .../reservedipv6/resource_reserved_ipv6.go | 2 +- .../resource_reserved_ipv6_assignment.go | 6 +-- .../resource_reserved_ipv6_assignment_test.go | 42 +++++++++---------- .../resource_reserved_ipv6_test.go | 14 ++++--- 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/digitalocean/droplet/resource_droplet.go b/digitalocean/droplet/resource_droplet.go index 81010de32..97bffa284 100644 --- a/digitalocean/droplet/resource_droplet.go +++ b/digitalocean/droplet/resource_droplet.go @@ -843,7 +843,7 @@ func waitForDropletDestroy(ctx context.Context, d *schema.ResourceData, meta int stateConf := &retry.StateChangeConf{ Pending: []string{"active", "off"}, - Target: []string{"archived"}, + Target: []string{"archive"}, Refresh: dropletStateRefreshFunc(ctx, d, "status", meta), Timeout: 60 * time.Second, Delay: 10 * time.Second, diff --git a/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go b/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go index c66664188..2d933807d 100644 --- a/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/datasource_reserved_ipv6_test.go @@ -16,7 +16,7 @@ import ( func TestAccDataSourceDigitalOceanReservedIPV6_Basic(t *testing.T) { var reservedIPv6 godo.ReservedIPV6 - expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i`) + expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:` + ipv6Regex) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.TestAccPreCheck(t) }, @@ -40,7 +40,7 @@ func TestAccDataSourceDigitalOceanReservedIPV6_Basic(t *testing.T) { func TestAccDataSourceDigitalOceanReservedIPV6_FindsReservedIP(t *testing.T) { var reservedIPv6 godo.ReservedIPV6 - expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i`) + expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:` + ipv6Regex) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.TestAccPreCheck(t) }, diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6.go b/digitalocean/reservedipv6/resource_reserved_ipv6.go index a46956d53..f8db4c651 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6.go @@ -161,7 +161,7 @@ func resourceDigitalOceanReservedIPV6Delete(ctx context.Context, d *schema.Resou log.Printf("[INFO] Deleting reserved IPv6: %s", d.Id()) _, err := client.ReservedIPV6s.Delete(context.Background(), d.Id()) - if err != nil { + if err != nil && strings.Contains(err.Error(), "404") { return diag.Errorf("Error deleting reserved IPv6: %s", err) } diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go index 08663b141..9cadfb086 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go @@ -31,7 +31,7 @@ func ResourceDigitalOceanReservedIPV6Assignment() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.IsIPv4Address, + ValidateFunc: validation.IsIPv6Address, }, "droplet_id": { Type: schema.TypeInt, @@ -100,7 +100,7 @@ func resourceDigitalOceanReservedIPV6AssignmentDelete(ctx context.Context, d *sc if reservedIPv6.Droplet.ID == dropletID { log.Printf("[INFO] Unassigning the reserved IPv6 from the Droplet") - action, _, err := client.ReservedIPActions.Unassign(context.Background(), ipAddress) + action, _, err := client.ReservedIPV6Actions.Unassign(context.Background(), ipAddress) if err != nil { return diag.Errorf("Error unassigning reserved IPv6 (%s) from the droplet: %s", ipAddress, err) } @@ -146,7 +146,7 @@ func newReservedIPV6AssignmentStateRefreshFunc( log.Printf("[INFO] Refreshing the reserved IPv6 state") action, _, err := client.Actions.Get(context.Background(), actionID) if err != nil { - return nil, "", fmt.Errorf("error retrieving reserved IPv6 (%s) ActionId (%d): %s", d.Get("ip_address").(string), actionID, err) + return nil, "", fmt.Errorf("error retrieving reserved IPv6 (%s) ActionId (%d): %s", d.Get("ip_address"), actionID, err) } log.Printf("[INFO] The reserved IPv6 Action Status is %s", action.Status) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go index 057c75b3b..fab804c09 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go @@ -27,7 +27,7 @@ func TestAccDigitalOceanReservedIPV6Assignment(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), resource.TestMatchResourceAttr( "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), @@ -37,7 +37,7 @@ func TestAccDigitalOceanReservedIPV6Assignment(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), resource.TestMatchResourceAttr( "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), @@ -47,7 +47,7 @@ func TestAccDigitalOceanReservedIPV6Assignment(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6.foobar", "ip", regexp.MustCompile("[0-9.]+")), + "digitalocean_reserved_ipv6.foobar", "ip", regexp.MustCompile(ipv6Regex)), ), }, }, @@ -65,7 +65,7 @@ func TestAccDigitalOceanReservedIPV6Assignment_createBeforeDestroy(t *testing.T) Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), resource.TestMatchResourceAttr( "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), @@ -75,7 +75,7 @@ func TestAccDigitalOceanReservedIPV6Assignment_createBeforeDestroy(t *testing.T) Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), resource.TestMatchResourceAttr( "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), @@ -103,7 +103,7 @@ func testAccCheckDigitalOceanReservedIPV6AttachmentExists(n string) resource.Tes client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() // Try to find the ReservedIP - foundReservedIP, _, err := client.ReservedIPs.Get(context.Background(), fipID) + foundReservedIP, _, err := client.ReservedIPV6s.Get(context.Background(), fipID) if err != nil { return err } @@ -122,13 +122,12 @@ resource "digitalocean_reserved_ipv6" "foobar" { } resource "digitalocean_droplet" "foobar" { - count = 2 - name = "tf-acc-test-${count.index}" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true + count = 2 + name = "tf-acc-test-${count.index}" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true } resource "digitalocean_reserved_ipv6_assignment" "foobar" { @@ -143,13 +142,12 @@ resource "digitalocean_reserved_ipv6" "foobar" { } resource "digitalocean_droplet" "foobar" { - count = 2 - name = "tf-acc-test-${count.index}" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true + count = 2 + name = "tf-acc-test-${count.index}" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true } resource "digitalocean_reserved_ipv6_assignment" "foobar" { @@ -191,7 +189,7 @@ resource "digitalocean_reserved_ipv6" "foobar" { } resource "digitalocean_reserved_ipv6_assignment" "foobar" { - ip = digitalocean_reserved_ipv6.foobar.id + ip = digitalocean_reserved_ipv6.foobar.ip droplet_id = digitalocean_droplet.foobar.id lifecycle { @@ -217,7 +215,7 @@ resource "digitalocean_reserved_ipv6" "foobar" { } resource "digitalocean_reserved_ipv6_assignment" "foobar" { - ip = digitalocean_reserved_ipv6.foobar.id + ip = digitalocean_reserved_ipv6.foobar.ip droplet_id = digitalocean_droplet.foobar.id lifecycle { diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go index ca024c363..cb8f826e0 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go @@ -13,10 +13,12 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) +const ipv6Regex = "(([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]))$" + func TestAccDigitalOceanReservedIPV6_RegionSlug(t *testing.T) { var reservedIPv6 godo.ReservedIPV6 - expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i`) + expectedURNRegex, _ := regexp.Compile(`do:reservedipv6:` + ipv6Regex) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.TestAccPreCheck(t) }, @@ -133,9 +135,10 @@ func testAccCheckDigitalOceanReservedIPV6Config_droplet(name string) string { resource "digitalocean_droplet" "foobar" { name = "%s" size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true + private_networking = true } resource "digitalocean_reserved_ipv6" "foobar" { @@ -151,7 +154,8 @@ resource "digitalocean_droplet" "baz" { size = "s-1vcpu-1gb" image = "ubuntu-22-04-x64" region = "nyc3" - ipv6 = true + ipv6 = true + private_networking = true } resource "digitalocean_reserved_ipv6" "foobar" { From 1bd914dbaa506872d156e825db5d0a60504c2e35 Mon Sep 17 00:00:00 2001 From: Anna Lushnikova Date: Tue, 10 Dec 2024 10:16:58 -0500 Subject: [PATCH 07/13] Update vendor/github.com/digitalocean/godo/reserved_ipv6.go --- vendor/github.com/digitalocean/godo/reserved_ipv6.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/github.com/digitalocean/godo/reserved_ipv6.go b/vendor/github.com/digitalocean/godo/reserved_ipv6.go index ccc4a80af..ff6e8cfaa 100644 --- a/vendor/github.com/digitalocean/godo/reserved_ipv6.go +++ b/vendor/github.com/digitalocean/godo/reserved_ipv6.go @@ -78,7 +78,7 @@ func (r *ReservedIPV6sServiceOp) List(ctx context.Context, opt *ListOptions) ([] return nil, nil, err } - if root.Meta != nil { + if root.Meta != nil { resp.Meta = root.Meta } if root.Links != nil { From e61062a54918aefd77c2c5e25e9b73b3d65c286d Mon Sep 17 00:00:00 2001 From: Ashwani Date: Tue, 10 Dec 2024 21:13:16 +0530 Subject: [PATCH 08/13] fixes all tests but one --- .../resource_reserved_ip_assignment_test.go | 2 +- .../reservedipv6/datasource_reserved_ipv6.go | 2 +- .../reservedipv6/import_reserved_ipv6_test.go | 22 ----- .../resource_reserved_ipv6_assignment.go | 11 +-- .../resource_reserved_ipv6_assignment_test.go | 83 ++----------------- .../resource_reserved_ipv6_test.go | 16 ++-- 6 files changed, 25 insertions(+), 111 deletions(-) diff --git a/digitalocean/reservedip/resource_reserved_ip_assignment_test.go b/digitalocean/reservedip/resource_reserved_ip_assignment_test.go index 1b593b05a..a7aea2b55 100644 --- a/digitalocean/reservedip/resource_reserved_ip_assignment_test.go +++ b/digitalocean/reservedip/resource_reserved_ip_assignment_test.go @@ -202,7 +202,7 @@ resource "digitalocean_reserved_ip_assignment" "foobar" { var testAccCheckDigitalOceanReservedIPAssignmentConfig_createBeforeDestroyReassign = ` resource "digitalocean_droplet" "foobar" { - image = "ubuntu-18-04-x64" + image = "ubuntu-22-04-x64" name = "tf-acc-test-01" region = "nyc3" size = "s-1vcpu-1gb" diff --git a/digitalocean/reservedipv6/datasource_reserved_ipv6.go b/digitalocean/reservedipv6/datasource_reserved_ipv6.go index 07d704c1c..81efa3250 100644 --- a/digitalocean/reservedipv6/datasource_reserved_ipv6.go +++ b/digitalocean/reservedipv6/datasource_reserved_ipv6.go @@ -32,7 +32,7 @@ func DataSourceDigitalOceanReservedIPV6() *schema.Resource { "droplet_id": { Type: schema.TypeInt, Computed: true, - Description: "the droplet id that the reserved ip has been assigned to.", + Description: "the droplet id that the reserved ipv6 has been assigned to.", }, }, } diff --git a/digitalocean/reservedipv6/import_reserved_ipv6_test.go b/digitalocean/reservedipv6/import_reserved_ipv6_test.go index 93c3d61b8..b297e7090 100644 --- a/digitalocean/reservedipv6/import_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/import_reserved_ipv6_test.go @@ -27,25 +27,3 @@ func TestAccDigitalOceanReservedIPV6_importBasicRegion(t *testing.T) { }, }) } - -func TestAccDigitalOceanReservedIPV6_importBasicDroplet(t *testing.T) { - resourceName := "digitalocean_reserved_ipv6.foobar" - name := acceptance.RandomTestName() - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.TestAccPreCheck(t) }, - ProviderFactories: acceptance.TestAccProviderFactories, - CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, - Steps: []resource.TestStep{ - { - Config: testAccCheckDigitalOceanReservedIPV6Config_droplet(name), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go index 9cadfb086..f5fb427dd 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go @@ -56,13 +56,14 @@ func resourceDigitalOceanReservedIPV6AssignmentCreate(ctx context.Context, d *sc "Error Assigning reserved IPv6 (%s) to the droplet: %s", ipAddress, err) } - _, unassignedErr := waitForReservedIPV6AssignmentReady(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) - if unassignedErr != nil { + _, assignedErr := waitForReservedIPV6AssignmentReady(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if assignedErr != nil { return diag.Errorf( - "Error waiting for reserved IPv6 (%s) to be Assigned: %s", ipAddress, unassignedErr) + "Error waiting for reserved IPv6 (%s) to be Assigned: %s", ipAddress, assignedErr) } d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%d-%s-", dropletID, ipAddress))) + return resourceDigitalOceanReservedIPV6AssignmentRead(ctx, d, meta) } @@ -79,8 +80,8 @@ func resourceDigitalOceanReservedIPV6AssignmentRead(ctx context.Context, d *sche } if reservedIPv6.Droplet == nil || reservedIPv6.Droplet.ID != dropletID { - log.Printf("[INFO] A Droplet was detected on the reserved IPv6.") - d.SetId("") + // log.Printf("[INFO] Droplet assignment was unsuccessful on the reserved IPv6.") + return diag.Errorf("Error assigning reserved IPv6 %s to dropletID %d", ipAddress, dropletID) } return nil diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go index fab804c09..4348d9e2a 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go @@ -27,21 +27,12 @@ func TestAccDigitalOceanReservedIPV6Assignment(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), - resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), - ), - }, - { - Config: testAccCheckDigitalOceanReservedIPV6AssignmentReassign, - Check: resource.ComposeTestCheckFunc( - testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), - resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), + "digitalocean_reserved_ipv6_assignment.foobar", "ip", regexp.MustCompile(ipv6Regex)), resource.TestMatchResourceAttr( "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), }, + { Config: testAccCheckDigitalOceanReservedIPV6AssignmentDeleteAssignment, Check: resource.ComposeTestCheckFunc( @@ -65,17 +56,7 @@ func TestAccDigitalOceanReservedIPV6Assignment_createBeforeDestroy(t *testing.T) Check: resource.ComposeTestCheckFunc( testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), - resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), - ), - }, - { - Config: testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroyReassign, - Check: resource.ComposeTestCheckFunc( - testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), - resource.TestMatchResourceAttr( - "digitalocean_reserved_ipv6_assignment.foobar", "id", regexp.MustCompile(ipv6Regex)), + "digitalocean_reserved_ipv6_assignment.foobar", "ip", regexp.MustCompile(ipv6Regex)), resource.TestMatchResourceAttr( "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), @@ -91,10 +72,10 @@ func testAccCheckDigitalOceanReservedIPV6AttachmentExists(n string) resource.Tes return fmt.Errorf("Not found: %s", n) } - if rs.Primary.Attributes["ip_address"] == "" { - return fmt.Errorf("No floating IP is set") + if rs.Primary.Attributes["ip"] == "" { + return fmt.Errorf("No reserved IPv6 is set") } - fipID := rs.Primary.Attributes["ip_address"] + fipID := rs.Primary.Attributes["ip"] dropletID, err := strconv.Atoi(rs.Primary.Attributes["droplet_id"]) if err != nil { return err @@ -102,7 +83,7 @@ func testAccCheckDigitalOceanReservedIPV6AttachmentExists(n string) resource.Tes client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() - // Try to find the ReservedIP + // Try to find the ReservedIPv6 foundReservedIP, _, err := client.ReservedIPV6s.Get(context.Background(), fipID) if err != nil { return err @@ -122,7 +103,7 @@ resource "digitalocean_reserved_ipv6" "foobar" { } resource "digitalocean_droplet" "foobar" { - count = 2 + count = 1 name = "tf-acc-test-${count.index}" size = "s-1vcpu-1gb" image = "ubuntu-22-04-x64" @@ -136,33 +117,13 @@ resource "digitalocean_reserved_ipv6_assignment" "foobar" { } ` -var testAccCheckDigitalOceanReservedIPV6AssignmentReassign = ` -resource "digitalocean_reserved_ipv6" "foobar" { - region_slug = "nyc3" -} - -resource "digitalocean_droplet" "foobar" { - count = 2 - name = "tf-acc-test-${count.index}" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true -} - -resource "digitalocean_reserved_ipv6_assignment" "foobar" { - ip = digitalocean_reserved_ipv6.foobar.ip - droplet_id = digitalocean_droplet.foobar.1.id -} -` - var testAccCheckDigitalOceanReservedIPV6AssignmentDeleteAssignment = ` resource "digitalocean_reserved_ipv6" "foobar" { region_slug = "nyc3" } resource "digitalocean_droplet" "foobar" { - count = 2 + count = 1 name = "tf-acc-test-${count.index}" size = "s-1vcpu-1gb" image = "ubuntu-22-04-x64" @@ -197,29 +158,3 @@ resource "digitalocean_reserved_ipv6_assignment" "foobar" { } } ` - -var testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroyReassign = ` -resource "digitalocean_droplet" "foobar" { - image = "ubuntu-18-04-x64" - name = "tf-acc-test-01" - region = "nyc3" - size = "s-1vcpu-1gb" - - lifecycle { - create_before_destroy = true - } -} - -resource "digitalocean_reserved_ipv6" "foobar" { - region_slug = "nyc3" -} - -resource "digitalocean_reserved_ipv6_assignment" "foobar" { - ip = digitalocean_reserved_ipv6.foobar.ip - droplet_id = digitalocean_droplet.foobar.id - - lifecycle { - create_before_destroy = true - } -} -` diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go index cb8f826e0..77658bfa5 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go @@ -133,10 +133,10 @@ resource "digitalocean_reserved_ipv6" "foobar" { func testAccCheckDigitalOceanReservedIPV6Config_droplet(name string) string { return fmt.Sprintf(` resource "digitalocean_droplet" "foobar" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" ipv6 = true private_networking = true } @@ -150,10 +150,10 @@ resource "digitalocean_reserved_ipv6" "foobar" { func testAccCheckDigitalOceanReservedIPv6Config_Reassign(name string) string { return fmt.Sprintf(` resource "digitalocean_droplet" "baz" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" + name = "%s" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" ipv6 = true private_networking = true } From 646e5e855d61213a6720fcb27765c44846be6a4a Mon Sep 17 00:00:00 2001 From: Ashwani Date: Tue, 10 Dec 2024 23:38:02 +0530 Subject: [PATCH 09/13] fixed test failures --- .../reservedipv6/resource_reserved_ipv6.go | 2 +- .../resource_reserved_ipv6_assignment_test.go | 37 ++++++++ .../resource_reserved_ipv6_test.go | 86 ------------------- 3 files changed, 38 insertions(+), 87 deletions(-) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6.go b/digitalocean/reservedipv6/resource_reserved_ipv6.go index f8db4c651..a42d9c773 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6.go @@ -65,7 +65,7 @@ func resourceDigitalOceanReservedIPV6Create(ctx context.Context, d *schema.Resou log.Printf("[DEBUG] Reserved IPv6 create: %#v", regionOpts) reservedIP, _, err := client.ReservedIPV6s.Create(context.Background(), regionOpts) if err != nil { - return diag.Errorf("Error creating reserved IP: %s", err) + return diag.Errorf("Error creating reserved IPv6: %s", err) } d.SetId(reservedIP.IP) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go index 4348d9e2a..29fd6a3a4 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go @@ -61,6 +61,16 @@ func TestAccDigitalOceanReservedIPV6Assignment_createBeforeDestroy(t *testing.T) "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), ), }, + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroyReassign, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "ip", regexp.MustCompile(ipv6Regex)), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, }, }) } @@ -139,6 +149,33 @@ resource "digitalocean_droplet" "foobar" { name = "tf-acc-test" region = "nyc3" size = "s-1vcpu-1gb" + ipv6 = true + + lifecycle { + create_before_destroy = true + } +} + +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_reserved_ipv6_assignment" "foobar" { + ip = digitalocean_reserved_ipv6.foobar.ip + droplet_id = digitalocean_droplet.foobar.id + + lifecycle { + create_before_destroy = true + } +} +` +var testAccCheckDigitalOceanReservedIPV6AssignmentConfig_createBeforeDestroyReassign = ` +resource "digitalocean_droplet" "foobar" { + image = "ubuntu-22-04-x64" + name = "tf-acc-test-01" + region = "nyc3" + size = "s-1vcpu-1gb" + ipv6 = true lifecycle { create_before_destroy = true diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go index 77658bfa5..5982b800a 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_test.go @@ -38,43 +38,6 @@ func TestAccDigitalOceanReservedIPV6_RegionSlug(t *testing.T) { }) } -func TestAccDigitalOceanReservedIPV6_Droplet(t *testing.T) { - var reservedIPv6 godo.ReservedIPV6 - name := acceptance.RandomTestName() - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.TestAccPreCheck(t) }, - ProviderFactories: acceptance.TestAccProviderFactories, - CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, - Steps: []resource.TestStep{ - { - Config: testAccCheckDigitalOceanReservedIPV6Config_droplet(name), - Check: resource.ComposeTestCheckFunc( - testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), - resource.TestCheckResourceAttr( - "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), - ), - }, - { - Config: testAccCheckDigitalOceanReservedIPv6Config_Reassign(name), - Check: resource.ComposeTestCheckFunc( - testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), - resource.TestCheckResourceAttr( - "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), - ), - }, - { - Config: testAccCheckDigitalOceanReservedIPV6Config_Unassign(name), - Check: resource.ComposeTestCheckFunc( - testAccCheckDigitalOceanReservedIPV6Exists("digitalocean_reserved_ipv6.foobar", &reservedIPv6), - resource.TestCheckResourceAttr( - "digitalocean_reserved_ipv6.foobar", "region_slug", "nyc3"), - ), - }, - }, - }) -} - func testAccCheckDigitalOceanReservedIPV6Destroy(s *terraform.State) error { client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient() @@ -129,52 +92,3 @@ var testAccCheckDigitalOceanReservedIPV6Config_regionSlug = ` resource "digitalocean_reserved_ipv6" "foobar" { region_slug = "nyc3" }` - -func testAccCheckDigitalOceanReservedIPV6Config_droplet(name string) string { - return fmt.Sprintf(` -resource "digitalocean_droplet" "foobar" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true -} - -resource "digitalocean_reserved_ipv6" "foobar" { - droplet_id = digitalocean_droplet.foobar.id - region_slug = digitalocean_droplet.foobar.region -}`, name) -} - -func testAccCheckDigitalOceanReservedIPv6Config_Reassign(name string) string { - return fmt.Sprintf(` -resource "digitalocean_droplet" "baz" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true - private_networking = true -} - -resource "digitalocean_reserved_ipv6" "foobar" { - droplet_id = digitalocean_droplet.baz.id - region_slug = digitalocean_droplet.baz.region -}`, name) -} - -func testAccCheckDigitalOceanReservedIPV6Config_Unassign(name string) string { - return fmt.Sprintf(` -resource "digitalocean_droplet" "baz" { - name = "%s" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true -} - -resource "digitalocean_reserved_ipv6" "foobar" { - region_slug = "nyc3" -}`, name) -} From 1a7fcdcd30298d4b125c8a65efd5a5bee5151df7 Mon Sep 17 00:00:00 2001 From: Ashwani Date: Wed, 11 Dec 2024 21:20:29 +0530 Subject: [PATCH 10/13] removed Update context for reservedIPv6 --- .../reservedipv6/resource_reserved_ipv6.go | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6.go b/digitalocean/reservedipv6/resource_reserved_ipv6.go index a42d9c773..75f04a2fe 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6.go @@ -18,7 +18,6 @@ import ( func ResourceDigitalOceanReservedIPV6() *schema.Resource { return &schema.Resource{ CreateContext: resourceDigitalOceanReservedIPV6Create, - UpdateContext: resourceDigitalOceanReservedIPV6Update, ReadContext: resourceDigitalOceanReservedIPV6Read, DeleteContext: resourceDigitalOceanReservedIPV6Delete, Importer: &schema.ResourceImporter{ @@ -73,42 +72,6 @@ func resourceDigitalOceanReservedIPV6Create(ctx context.Context, d *schema.Resou return resourceDigitalOceanReservedIPV6Read(ctx, d, meta) } -func resourceDigitalOceanReservedIPV6Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*config.CombinedConfig).GodoClient() - - if d.HasChange("droplet_id") { - if v, ok := d.GetOk("droplet_id"); ok { - log.Printf("[INFO] Assigning the reserved IPv6 %s to the Droplet %d", d.Id(), v.(int)) - action, _, err := client.ReservedIPV6Actions.Assign(context.Background(), d.Id(), v.(int)) - if err != nil { - return diag.Errorf( - "Error assigning reserved IPv6 (%s) to the Droplet: %s", d.Id(), err) - } - - _, unassignedErr := waitForReservedIPV6Ready(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) - if unassignedErr != nil { - return diag.Errorf( - "Error waiting for reserved IP (%s) to be Assigned: %s", d.Id(), unassignedErr) - } - } else { - log.Printf("[INFO] Unassigning the reserved IP %s", d.Id()) - action, _, err := client.ReservedIPV6Actions.Unassign(context.Background(), d.Id()) - if err != nil { - return diag.Errorf( - "Error unassigning reserved IP (%s): %s", d.Id(), err) - } - - _, unassignedErr := waitForReservedIPV6Ready(ctx, d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) - if unassignedErr != nil { - return diag.Errorf( - "Error waiting for reserved IP (%s) to be Unassigned: %s", d.Id(), unassignedErr) - } - } - } - - return resourceDigitalOceanReservedIPV6Read(ctx, d, meta) -} - func resourceDigitalOceanReservedIPV6Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.CombinedConfig).GodoClient() From 79942182c8e3738aa5b2f66a47d6cbce56fae139 Mon Sep 17 00:00:00 2001 From: Ashwani Date: Wed, 11 Dec 2024 21:42:41 +0530 Subject: [PATCH 11/13] setting droplet_id as computed --- digitalocean/reservedipv6/resource_reserved_ipv6.go | 1 + 1 file changed, 1 insertion(+) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6.go b/digitalocean/reservedipv6/resource_reserved_ipv6.go index 75f04a2fe..6986b7b9d 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6.go @@ -48,6 +48,7 @@ func ResourceDigitalOceanReservedIPV6() *schema.Resource { "droplet_id": { Type: schema.TypeInt, Optional: true, + Computed: true, }, }, } From cd7448dcadccbfbb84d104106b27a3eb5af466ae Mon Sep 17 00:00:00 2001 From: Ashwani Date: Thu, 12 Dec 2024 01:08:16 +0530 Subject: [PATCH 12/13] updated godo, added 're-assign' test --- .../resource_reserved_ipv6_assignment.go | 1 + .../resource_reserved_ipv6_assignment_test.go | 80 ++++++++++++++++++- go.mod | 2 +- go.sum | 4 +- .../github.com/digitalocean/godo/CHANGELOG.md | 3 + vendor/github.com/digitalocean/godo/godo.go | 2 +- .../digitalocean/godo/reserved_ipv6.go | 4 +- vendor/modules.txt | 2 +- 8 files changed, 88 insertions(+), 10 deletions(-) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go index f5fb427dd..49423033b 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment.go @@ -65,6 +65,7 @@ func resourceDigitalOceanReservedIPV6AssignmentCreate(ctx context.Context, d *sc d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%d-%s-", dropletID, ipAddress))) return resourceDigitalOceanReservedIPV6AssignmentRead(ctx, d, meta) + } func resourceDigitalOceanReservedIPV6AssignmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go index 29fd6a3a4..71d80bcbb 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go @@ -75,6 +75,39 @@ func TestAccDigitalOceanReservedIPV6Assignment_createBeforeDestroy(t *testing.T) }) } +func TestAccDigitalOceanReservedIPV6Assignment_unassignAndAssignToNewDroplet(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + ProviderFactories: acceptance.TestAccProviderFactories, + CheckDestroy: testAccCheckDigitalOceanReservedIPV6Destroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "ip", regexp.MustCompile(ipv6Regex)), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + { + Config: testAccCheckDigitalOceanReservedIPV6AssignmentUnAssign, + }, + { + Config: testAccCheckDigitalOceanReservedIPV6ReAssignmentConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanReservedIPV6AttachmentExists("digitalocean_reserved_ipv6_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "ip", regexp.MustCompile(ipv6Regex)), + resource.TestMatchResourceAttr( + "digitalocean_reserved_ipv6_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + }, + }) +} + func testAccCheckDigitalOceanReservedIPV6AttachmentExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -114,7 +147,7 @@ resource "digitalocean_reserved_ipv6" "foobar" { resource "digitalocean_droplet" "foobar" { count = 1 - name = "tf-acc-test-${count.index}" + name = "tf-acc-test-assign" size = "s-1vcpu-1gb" image = "ubuntu-22-04-x64" region = "nyc3" @@ -127,6 +160,50 @@ resource "digitalocean_reserved_ipv6_assignment" "foobar" { } ` +var testAccCheckDigitalOceanReservedIPV6AssignmentUnAssign = ` +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_droplet" "foobar" { + count = 1 + image = "ubuntu-22-04-x64" + name = "tf-acc-test-assign" + region = "nyc3" + size = "s-1vcpu-1gb" + ipv6 = true +} + +` + +var testAccCheckDigitalOceanReservedIPV6ReAssignmentConfig = ` +resource "digitalocean_reserved_ipv6" "foobar" { + region_slug = "nyc3" +} + +resource "digitalocean_droplet" "foobar1" { + count = 1 + name = "tf-acc-test-reassign" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true +} +resource "digitalocean_droplet" "foobar" { + count = 1 + name = "tf-acc-test-assign" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true +} + +resource "digitalocean_reserved_ipv6_assignment" "foobar" { + ip = digitalocean_reserved_ipv6.foobar.ip + droplet_id = digitalocean_droplet.foobar1.0.id +} +` + var testAccCheckDigitalOceanReservedIPV6AssignmentDeleteAssignment = ` resource "digitalocean_reserved_ipv6" "foobar" { region_slug = "nyc3" @@ -139,7 +216,6 @@ resource "digitalocean_droplet" "foobar" { image = "ubuntu-22-04-x64" region = "nyc3" ipv6 = true - private_networking = true } ` diff --git a/go.mod b/go.mod index 2a2151d16..1f0a5e244 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.131.1-0.20241127211050-a97e39731918 + github.com/digitalocean/godo v1.131.1 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 c7d6398bd..6fa43ba64 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.131.1-0.20241127211050-a97e39731918 h1:7xOw7i5AFH1n5vIMMH7HtR87jdxV8XnLKOBafNbVetM= -github.com/digitalocean/godo v1.131.1-0.20241127211050-a97e39731918/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= +github.com/digitalocean/godo v1.131.1 h1:2QsRwjNukKgOQbflMxOsTDoC05o5UKBpqQMFKXegYKE= +github.com/digitalocean/godo v1.131.1/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/CHANGELOG.md b/vendor/github.com/digitalocean/godo/CHANGELOG.md index 3fb2a160c..8b177989d 100644 --- a/vendor/github.com/digitalocean/godo/CHANGELOG.md +++ b/vendor/github.com/digitalocean/godo/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## [v1.131.1] - 2024-12-10 +- #762 - @imaskm - Updated list ipv6 response + ## [v1.131.0] - 2024-11-25 - #760 - @jvasilevsky - LBAAS: add ipv6 field to loadbalancer model diff --git a/vendor/github.com/digitalocean/godo/godo.go b/vendor/github.com/digitalocean/godo/godo.go index 62498fc44..94d31631a 100644 --- a/vendor/github.com/digitalocean/godo/godo.go +++ b/vendor/github.com/digitalocean/godo/godo.go @@ -21,7 +21,7 @@ import ( ) const ( - libraryVersion = "1.131.0" + libraryVersion = "1.131.1" defaultBaseURL = "https://api.digitalocean.com/" userAgent = "godo/" + libraryVersion mediaType = "application/json" diff --git a/vendor/github.com/digitalocean/godo/reserved_ipv6.go b/vendor/github.com/digitalocean/godo/reserved_ipv6.go index ff6e8cfaa..119c6bde3 100644 --- a/vendor/github.com/digitalocean/godo/reserved_ipv6.go +++ b/vendor/github.com/digitalocean/godo/reserved_ipv6.go @@ -34,7 +34,6 @@ type ReservedIPV6 struct { ReservedAt time.Time `json:"reserved_at"` Droplet *Droplet `json:"droplet,omitempty"` } - type reservedIPV6Root struct { ReservedIPV6 *ReservedIPV6 `json:"reserved_ipv6"` } @@ -77,8 +76,7 @@ func (r *ReservedIPV6sServiceOp) List(ctx context.Context, opt *ListOptions) ([] if err != nil { return nil, nil, err } - - if root.Meta != nil { + if root.Meta != nil { resp.Meta = root.Meta } if root.Links != nil { diff --git a/vendor/modules.txt b/vendor/modules.txt index 1a2d97ae0..13fa4e7be 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.131.1-0.20241127211050-a97e39731918 +# github.com/digitalocean/godo v1.131.1 ## explicit; go 1.22 github.com/digitalocean/godo github.com/digitalocean/godo/metrics From e6889bcb04db9eae6b0802f6d543143ce26f7bfe Mon Sep 17 00:00:00 2001 From: Ashwani Date: Thu, 12 Dec 2024 01:15:36 +0530 Subject: [PATCH 13/13] terrafmt-ed the changes --- .../resource_reserved_ipv6_assignment_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go index 71d80bcbb..5715f1bd2 100644 --- a/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go +++ b/digitalocean/reservedipv6/resource_reserved_ipv6_assignment_test.go @@ -210,12 +210,12 @@ resource "digitalocean_reserved_ipv6" "foobar" { } resource "digitalocean_droplet" "foobar" { - count = 1 - name = "tf-acc-test-${count.index}" - size = "s-1vcpu-1gb" - image = "ubuntu-22-04-x64" - region = "nyc3" - ipv6 = true + count = 1 + name = "tf-acc-test-${count.index}" + size = "s-1vcpu-1gb" + image = "ubuntu-22-04-x64" + region = "nyc3" + ipv6 = true } `