Skip to content

Commit

Permalink
New Resource: `azurerm_mysql_flexible_server_active_directory_adminis…
Browse files Browse the repository at this point in the history
…trator` (#21786)
  • Loading branch information
neil-yechenwei authored May 23, 2023
1 parent fc5483e commit d292453
Show file tree
Hide file tree
Showing 24 changed files with 1,576 additions and 1 deletion.
1 change: 1 addition & 0 deletions internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration {
mobilenetwork.Registration{},
mssql.Registration{},
mssqlmanagedinstance.Registration{},
mysql.Registration{},
network.Registration{},
netapp.Registration{},
nginx.Registration{},
Expand Down
6 changes: 6 additions & 0 deletions internal/services/mysql/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2021-05-01/mysqlflexibleservers" // nolint: staticcheck
"github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2021-05-01/serverfailover"
"github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2021-05-01/servers"
"github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2022-01-01/azureadadministrators"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

type Client struct {
AzureADAdministratorsClient *azureadadministrators.AzureADAdministratorsClient
ConfigurationsClient *mysql.ConfigurationsClient
DatabasesClient *mysql.DatabasesClient
FirewallRulesClient *mysql.FirewallRulesClient
Expand All @@ -25,6 +27,9 @@ type Client struct {
}

func NewClient(o *common.ClientOptions) *Client {
azureADAdministratorsClient := azureadadministrators.NewAzureADAdministratorsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&azureADAdministratorsClient.Client, o.ResourceManagerAuthorizer)

ConfigurationsClient := mysql.NewConfigurationsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&ConfigurationsClient.Client, o.ResourceManagerAuthorizer)

Expand Down Expand Up @@ -65,6 +70,7 @@ func NewClient(o *common.ClientOptions) *Client {
o.ConfigureClient(&serverAdministratorsClient.Client, o.ResourceManagerAuthorizer)

return &Client{
AzureADAdministratorsClient: &azureADAdministratorsClient,
ConfigurationsClient: &ConfigurationsClient,
DatabasesClient: &DatabasesClient,
FirewallRulesClient: &FirewallRulesClient,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
package mysql

import (
"context"
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2022-01-01/azureadadministrators"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

type MySQLFlexibleServerAdministratorModel struct {
ServerId string `tfschema:"server_id"`
IdentityId string `tfschema:"identity_id"`
Login string `tfschema:"login"`
ObjectId string `tfschema:"object_id"`
TenantId string `tfschema:"tenant_id"`
}

type MySQLFlexibleServerAdministratorResource struct{}

var _ sdk.ResourceWithUpdate = MySQLFlexibleServerAdministratorResource{}

func (r MySQLFlexibleServerAdministratorResource) ResourceType() string {
return "azurerm_mysql_flexible_server_active_directory_administrator"
}

func (r MySQLFlexibleServerAdministratorResource) ModelObject() interface{} {
return &MySQLFlexibleServerAdministratorModel{}
}

func (r MySQLFlexibleServerAdministratorResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.FlexibleServerAzureActiveDirectoryAdministratorID
}

func (r MySQLFlexibleServerAdministratorResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"server_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: azureadadministrators.ValidateFlexibleServerID,
},

"identity_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: commonids.ValidateUserAssignedIdentityID,
},

"login": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"object_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.IsUUID,
},

"tenant_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.IsUUID,
},
}
}

func (r MySQLFlexibleServerAdministratorResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{}
}

func (r MySQLFlexibleServerAdministratorResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var model MySQLFlexibleServerAdministratorModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

client := metadata.Client.MySQL.AzureADAdministratorsClient
flexibleServerId, err := azureadadministrators.ParseFlexibleServerID(model.ServerId)
if err != nil {
return err
}

existing, err := client.Get(ctx, *flexibleServerId)
if err != nil && !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for existing %s: %+v", flexibleServerId, err)
}

if !response.WasNotFound(existing.HttpResponse) {
return metadata.ResourceRequiresImport(r.ResourceType(), flexibleServerId)
}

properties := azureadadministrators.AzureADAdministrator{
Properties: &azureadadministrators.AdministratorProperties{
AdministratorType: pointer.To(azureadadministrators.AdministratorTypeActiveDirectory),
IdentityResourceId: pointer.To(model.IdentityId),
Login: pointer.To(model.Login),
Sid: pointer.To(model.ObjectId),
TenantId: pointer.To(model.TenantId),
},
}

if err := client.CreateOrUpdateThenPoll(ctx, *flexibleServerId, properties); err != nil {
return fmt.Errorf("creating %s: %+v", flexibleServerId, err)
}

id := parse.NewFlexibleServerAzureActiveDirectoryAdministratorID(flexibleServerId.SubscriptionId, flexibleServerId.ResourceGroupName, flexibleServerId.FlexibleServerName, string(azureadadministrators.AdministratorTypeActiveDirectory))

metadata.SetID(id)
return nil
},
}
}

func (r MySQLFlexibleServerAdministratorResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MySQL.AzureADAdministratorsClient

id, err := parse.FlexibleServerAzureActiveDirectoryAdministratorID(metadata.ResourceData.Id())
if err != nil {
return err
}

var model MySQLFlexibleServerAdministratorModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

flexibleServerId := azureadadministrators.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroup, id.FlexibleServerName)

resp, err := client.Get(ctx, flexibleServerId)
if err != nil {
return fmt.Errorf("retrieving %s: %+v", *id, err)
}

properties := resp.Model
if properties == nil {
return fmt.Errorf("retrieving %s: properties was nil", id)
}

if metadata.ResourceData.HasChange("identity_id") {
properties.Properties.IdentityResourceId = pointer.To(model.IdentityId)
}

if metadata.ResourceData.HasChange("login") {
properties.Properties.Login = pointer.To(model.Login)
}

if metadata.ResourceData.HasChange("object_id") {
properties.Properties.Sid = pointer.To(model.ObjectId)
}

if metadata.ResourceData.HasChange("tenant_id") {
properties.Properties.TenantId = pointer.To(model.TenantId)
}

if err := client.CreateOrUpdateThenPoll(ctx, flexibleServerId, *properties); err != nil {
return fmt.Errorf("updating %s: %+v", *id, err)
}

return nil
},
}
}

func (r MySQLFlexibleServerAdministratorResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MySQL.AzureADAdministratorsClient

id, err := parse.FlexibleServerAzureActiveDirectoryAdministratorID(metadata.ResourceData.Id())
if err != nil {
return err
}

flexibleServerId := azureadadministrators.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroup, id.FlexibleServerName)

resp, err := client.Get(ctx, flexibleServerId)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(id)
}

return fmt.Errorf("retrieving %s: %+v", *id, err)
}

state := MySQLFlexibleServerAdministratorModel{
ServerId: flexibleServerId.ID(),
}

if model := resp.Model; model != nil {
if properties := model.Properties; properties != nil {
identity, err := commonids.ParseUserAssignedIdentityIDInsensitively(*properties.IdentityResourceId)
if err != nil {
return err
}

state.IdentityId = identity.ID()
state.Login = pointer.From(properties.Login)
state.ObjectId = pointer.From(properties.Sid)
state.TenantId = pointer.From(properties.TenantId)
}
}

return metadata.Encode(&state)
},
}
}

func (r MySQLFlexibleServerAdministratorResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MySQL.AzureADAdministratorsClient

id, err := parse.FlexibleServerAzureActiveDirectoryAdministratorID(metadata.ResourceData.Id())
if err != nil {
return err
}

flexibleServerId := azureadadministrators.NewFlexibleServerID(id.SubscriptionId, id.ResourceGroup, id.FlexibleServerName)

if err := client.DeleteThenPoll(ctx, flexibleServerId); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}

return nil
},
}
}
Loading

0 comments on commit d292453

Please sign in to comment.