Skip to content

Commit

Permalink
update to new format
Browse files Browse the repository at this point in the history
  • Loading branch information
bruceharrison1984 committed Jul 31, 2024
1 parent ecb3882 commit f544df8
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit f544df8

Please sign in to comment.