From f544df8023ee3e31de962da649494251a977d20f Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 31 Jul 2024 12:02:06 -0500 Subject: [PATCH] update to new format --- ...exible_server_virtual_endpoint_resource.go | 332 ++++++++++-------- internal/services/postgres/registration.go | 16 +- 2 files changed, 192 insertions(+), 156 deletions(-) diff --git a/internal/services/postgres/postgresql_flexible_server_virtual_endpoint_resource.go b/internal/services/postgres/postgresql_flexible_server_virtual_endpoint_resource.go index 21cf15c91ab7..4fe56c331f27 100644 --- a/internal/services/postgres/postgresql_flexible_server_virtual_endpoint_resource.go +++ b/internal/services/postgres/postgresql_flexible_server_virtual_endpoint_resource.go @@ -10,204 +10,228 @@ import ( "github.com/hashicorp/go-azure-sdk/resource-manager/postgresql/2023-06-01-preview/servers" "github.com/hashicorp/go-azure-sdk/resource-manager/postgresql/2023-06-01-preview/virtualendpoints" "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" - "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/services/postgres/custompollers" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" - "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" ) -func resourcePostgresqlFlexibleServerVirtualEndpoint() *pluginsdk.Resource { - return &pluginsdk.Resource{ - Create: resourcePostgresqlFlexibleServerVirtualEndpointCreate, - Read: resourcePostgresqlFlexibleServerVirtualEndpointRead, - Update: resourcePostgresqlFlexibleServerVirtualEndpointUpdate, - Delete: resourcePostgresqlFlexibleServerVirtualEndpointDelete, - - Timeouts: &pluginsdk.ResourceTimeout{ - Create: pluginsdk.DefaultTimeout(10 * time.Minute), - Read: pluginsdk.DefaultTimeout(5 * time.Minute), - Update: pluginsdk.DefaultTimeout(10 * time.Minute), - Delete: pluginsdk.DefaultTimeout(10 * time.Minute), - }, +type PostgresqlFlexibleServerVirtualEndpointResource struct{} - Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := virtualendpoints.ParseVirtualEndpointID(id) - return err - }), - - Schema: map[string]*pluginsdk.Schema{ - "name": { - Type: pluginsdk.TypeString, - Description: "The name of the Virtual Endpoint", - ForceNew: true, - Required: true, - }, - "source_server_id": { - Type: pluginsdk.TypeString, - Description: "The Resource ID of the *Source* Postgres Flexible Server this should be associated with", - ForceNew: true, - Required: true, - ValidateFunc: servers.ValidateFlexibleServerID, - }, - "replica_server_id": { - Type: pluginsdk.TypeString, - Description: "The Resource ID of the *Replica* Postgres Flexible Server this should be associated with", - Required: true, - ValidateFunc: servers.ValidateFlexibleServerID, - }, - "type": { - Type: pluginsdk.TypeString, - Description: "The type of Virtual Endpoint", - ForceNew: true, - Required: true, - ValidateFunc: validation.StringInSlice(virtualendpoints.PossibleValuesForVirtualEndpointType(), true), - }, - }, - } +type PostgresqlFlexibleServerVirtualEndpointModel struct { + Name string `tfschema:"name"` + SourceServerId string `tfschema:"source_server_id"` + ReplicaServerId string `tfschema:"replica_server_id"` + Type string `tfschema:"type"` } -func resourcePostgresqlFlexibleServerVirtualEndpointCreate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Postgres.VirtualEndpointClient - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() +var _ sdk.ResourceWithUpdate = PostgresqlFlexibleServerVirtualEndpointResource{} - name := d.Get("name").(string) - sourceServer := d.Get("source_server_id").(string) - replicaServer := d.Get("replica_server_id").(string) - virtualEndpointType := d.Get("type").(string) +func (r PostgresqlFlexibleServerVirtualEndpointResource) ModelObject() interface{} { + return &PostgresqlFlexibleServerVirtualEndpointModel{} +} - sourceServerId, err := servers.ParseFlexibleServerID(sourceServer) - if err != nil { - return err - } +func (r PostgresqlFlexibleServerVirtualEndpointResource) ResourceType() string { + return "azurerm_postgresql_flexible_server_virtual_endpoint" +} - replicaServerId, err := servers.ParseFlexibleServerID(replicaServer) - if err != nil { - return err - } +func (r PostgresqlFlexibleServerVirtualEndpointResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return func(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := virtualendpoints.ParseVirtualEndpointID(v); err != nil { + errors = append(errors, err) + } - id := virtualendpoints.NewVirtualEndpointID(sourceServerId.SubscriptionId, sourceServerId.ResourceGroupName, sourceServerId.FlexibleServerName, name) + return + } +} - locks.ByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) - defer locks.UnlockByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) +func (r PostgresqlFlexibleServerVirtualEndpointResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} - // This API can be a bit flaky if the same named resource is created/destroyed quickly - // usually waiting a minute or two before redeploying is enough to resolve the conflict - if err = client.CreateThenPoll(ctx, id, virtualendpoints.VirtualEndpointResource{ - Name: &name, - Properties: &virtualendpoints.VirtualEndpointResourceProperties{ - EndpointType: (*virtualendpoints.VirtualEndpointType)(&virtualEndpointType), - Members: &[]string{replicaServerId.FlexibleServerName}, +func (r PostgresqlFlexibleServerVirtualEndpointResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Description: "The name of the Virtual Endpoint", + ForceNew: true, + Required: true, + }, + "source_server_id": { + Type: pluginsdk.TypeString, + Description: "The Resource ID of the *Source* Postgres Flexible Server this should be associated with", + ForceNew: true, + Required: true, + ValidateFunc: servers.ValidateFlexibleServerID, + }, + "replica_server_id": { + Type: pluginsdk.TypeString, + Description: "The Resource ID of the *Replica* Postgres Flexible Server this should be associated with", + Required: true, + ValidateFunc: servers.ValidateFlexibleServerID, + }, + "type": { + Type: pluginsdk.TypeString, + Description: "The type of Virtual Endpoint", + ForceNew: true, + Required: true, + ValidateFunc: validation.StringInSlice(virtualendpoints.PossibleValuesForVirtualEndpointType(), true), }, - }); err != nil { - return fmt.Errorf("creating %s: %+v", id, err) } +} - d.SetId(id.ID()) +func (r PostgresqlFlexibleServerVirtualEndpointResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var virtualEndpoint PostgresqlFlexibleServerVirtualEndpointModel - return nil -} + if err := metadata.Decode(&virtualEndpoint); err != nil { + return err + } -func resourcePostgresqlFlexibleServerVirtualEndpointRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Postgres.VirtualEndpointClient - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() + client := metadata.Client.Postgres.VirtualEndpointClient - id, err := virtualendpoints.ParseVirtualEndpointID(d.Id()) - if err != nil { - return err - } + sourceServerId, err := servers.ParseFlexibleServerID(virtualEndpoint.SourceServerId) + if err != nil { + return err + } - if err := d.Set("name", id.VirtualEndpointName); err != nil { - return fmt.Errorf("setting `name`: %+v", err) - } + replicaServerId, err := servers.ParseFlexibleServerID(virtualEndpoint.ReplicaServerId) + if err != nil { + return err + } - flexibleServerId := servers.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroupName, id.FlexibleServerName) - if err := d.Set("source_server_id", flexibleServerId.ID()); err != nil { - return fmt.Errorf("setting `source_server_id`: %+v", err) - } + id := virtualendpoints.NewVirtualEndpointID(sourceServerId.SubscriptionId, sourceServerId.ResourceGroupName, sourceServerId.FlexibleServerName, virtualEndpoint.Name) + + locks.ByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + defer locks.UnlockByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + + // This API can be a bit flaky if the same named resource is created/destroyed quickly + // usually waiting a minute or two before redeploying is enough to resolve the conflict + if err = client.CreateThenPoll(ctx, id, virtualendpoints.VirtualEndpointResource{ + Name: &virtualEndpoint.Name, + Properties: &virtualendpoints.VirtualEndpointResourceProperties{ + EndpointType: (*virtualendpoints.VirtualEndpointType)(&virtualEndpoint.Type), + Members: &[]string{replicaServerId.FlexibleServerName}, + }, + }); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) - resp, err := client.Get(ctx, *id) - if err != nil { - if response.WasNotFound(resp.HttpResponse) { - log.Printf("[INFO] Postgresql Flexible Server Endpoint %q does not exist - removing from state", d.Id()) - d.SetId("") return nil - } - return fmt.Errorf("retrieving %s: %+v", id, err) + }, } +} + +func (r PostgresqlFlexibleServerVirtualEndpointResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Postgres.VirtualEndpointClient - if model := resp.Model; model != nil && model.Properties != nil { - // Model.Properties.Members should be a tuple => [source_server, replication_server] - if resp.Model.Properties.Members != nil { - replicateServerId := servers.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroupName, (*resp.Model.Properties.Members)[1]) - if err := d.Set("replica_server_id", replicateServerId.ID()); err != nil { - return fmt.Errorf("setting `replica_server_id`: %+v", err) + id, err := virtualendpoints.ParseVirtualEndpointID(metadata.ResourceData.Id()) + if err != nil { + return err } - } else { - // if members list is nil, this is an endpoint that was previously deleted - log.Printf("[INFO] Postgresql Flexible Server Endpoint %q was previously deleted - removing from state", d.Id()) - d.SetId("") - return nil - } - } - return nil -} + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[INFO] Postgresql Flexible Server Endpoint %q does not exist - removing from state", metadata.ResourceData.Id()) + return metadata.MarkAsGone(id) + } + return fmt.Errorf("retrieving %s: %+v", id, err) + } -func resourcePostgresqlFlexibleServerVirtualEndpointUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Postgres.VirtualEndpointClient - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() + virtualEndpoint := PostgresqlFlexibleServerVirtualEndpointModel{ + SourceServerId: virtualendpoints.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroupName, id.FlexibleServerName).ID(), + } - id, err := virtualendpoints.ParseVirtualEndpointID(d.Id()) - if err != nil { - return err + if model := resp.Model; model != nil && model.Properties != nil { + // Model.Properties.Members should be a tuple => [source_server, replication_server] + if resp.Model.Properties.Members != nil && len(*resp.Model.Properties.Members) == 2 { + virtualEndpoint.ReplicaServerId = servers.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroupName, (*resp.Model.Properties.Members)[1]).ID() + } else { + // if members list is nil, this is an endpoint that was previously deleted + log.Printf("[INFO] Postgresql Flexible Server Endpoint %q was previously deleted - removing from state", id.ID()) + return metadata.MarkAsGone(id) + } + } + + return metadata.Encode(&virtualEndpoint) + }, } +} - replicaServer := d.Get("replica_server_id").(string) - virtualEndpointType := d.Get("type").(string) +func (r PostgresqlFlexibleServerVirtualEndpointResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Postgres.VirtualEndpointClient - replicaServerId, err := servers.ParseFlexibleServerID(replicaServer) - if err != nil { - return err - } + id, err := virtualendpoints.ParseVirtualEndpointID(metadata.ResourceData.Id()) + if err != nil { + return err + } - locks.ByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) - defer locks.UnlockByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + locks.ByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + defer locks.UnlockByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + + if err := DeletePostgresFlexibileServerVirtualEndpoint(ctx, client, id); err != nil { + return err + } - if err := client.UpdateThenPoll(ctx, *id, virtualendpoints.VirtualEndpointResourceForPatch{ - Properties: &virtualendpoints.VirtualEndpointResourceProperties{ - EndpointType: (*virtualendpoints.VirtualEndpointType)(&virtualEndpointType), - Members: &[]string{replicaServerId.FlexibleServerName}, + return metadata.MarkAsGone(id) // is this correct?? }, - }); err != nil { - return fmt.Errorf("updating %q: %+v", id, err) } - - return nil } -func resourcePostgresqlFlexibleServerVirtualEndpointDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Postgres.VirtualEndpointClient - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() +func (r PostgresqlFlexibleServerVirtualEndpointResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var virtualEndpoint PostgresqlFlexibleServerVirtualEndpointModel + client := metadata.Client.Postgres.VirtualEndpointClient - id, err := virtualendpoints.ParseVirtualEndpointID(d.Id()) - if err != nil { - return err - } + if err := metadata.Decode(&virtualEndpoint); err != nil { + return err + } - locks.ByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) - defer locks.UnlockByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + id, err := virtualendpoints.ParseVirtualEndpointID(metadata.ResourceData.Id()) + if err != nil { + return err + } - if err := DeletePostgresFlexibileServerVirtualEndpoint(ctx, client, id); err != nil { - return err - } + replicaServerId, err := servers.ParseFlexibleServerID(virtualEndpoint.ReplicaServerId) + if err != nil { + return err + } - return nil + locks.ByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + defer locks.UnlockByName(id.FlexibleServerName, postgresqlFlexibleServerResourceName) + + if err := client.UpdateThenPoll(ctx, *id, virtualendpoints.VirtualEndpointResourceForPatch{ + Properties: &virtualendpoints.VirtualEndpointResourceProperties{ + EndpointType: (*virtualendpoints.VirtualEndpointType)(&virtualEndpoint.Type), + Members: &[]string{replicaServerId.FlexibleServerName}, + }, + }); err != nil { + return fmt.Errorf("updating %q: %+v", id, err) + } + + return nil + }, + } } // exposed so we can access from tests diff --git a/internal/services/postgres/registration.go b/internal/services/postgres/registration.go index 20e104f59612..cad8f4e49dcf 100644 --- a/internal/services/postgres/registration.go +++ b/internal/services/postgres/registration.go @@ -10,7 +10,10 @@ import ( type Registration struct{} -var _ sdk.UntypedServiceRegistrationWithAGitHubLabel = Registration{} +var ( + _ sdk.TypedServiceRegistrationWithAGitHubLabel = Registration{} + _ sdk.UntypedServiceRegistrationWithAGitHubLabel = Registration{} +) func (r Registration) AssociatedGitHubLabel() string { return "service/postgresql" @@ -51,6 +54,15 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { "azurerm_postgresql_flexible_server_configuration": resourcePostgresqlFlexibleServerConfiguration(), "azurerm_postgresql_flexible_server_database": resourcePostgresqlFlexibleServerDatabase(), "azurerm_postgresql_flexible_server_active_directory_administrator": resourcePostgresqlFlexibleServerAdministrator(), - "azurerm_postgresql_flexible_server_virtual_endpoint": resourcePostgresqlFlexibleServerVirtualEndpoint(), } } + +func (r Registration) Resources() []sdk.Resource { + return []sdk.Resource{ + PostgresqlFlexibleServerVirtualEndpointResource{}, + } +} + +func (r Registration) DataSources() []sdk.DataSource { + return []sdk.DataSource{} +}