Skip to content

Commit

Permalink
add mssql dns alias resource support, fix hashicorp#11276
Browse files Browse the repository at this point in the history
  • Loading branch information
wuxu committed May 20, 2022
1 parent e0cc6a4 commit 8282dec
Show file tree
Hide file tree
Showing 11 changed files with 653 additions and 0 deletions.
14 changes: 14 additions & 0 deletions helpers/validate/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,17 @@ func LowerCasedString(i interface{}, k string) ([]string, []error) {

return nil, nil
}

// NotEmptyString validates that the string is not empty
func NotEmptyString(i interface{}, k string) ([]string, []error) {
v, ok := i.(string)
if !ok {
return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
}

if strings.TrimSpace(v) == "" {
return nil, []error{fmt.Errorf("%q must not be empty", k)}
}

return nil, nil
}
5 changes: 5 additions & 0 deletions internal/services/mssql/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Client struct {
ServerAzureADAdministratorsClient *sql.ServerAzureADAdministratorsClient
ServerAzureADOnlyAuthenticationsClient *sql.ServerAzureADOnlyAuthenticationsClient
ServerConnectionPoliciesClient *sql.ServerConnectionPoliciesClient
ServerDNSAliasClient *sql.ServerDNSAliasesClient
ServerExtendedBlobAuditingPoliciesClient *sql.ExtendedServerBlobAuditingPoliciesClient
ServerKeysClient *sql.ServerKeysClient
ServerSecurityAlertPoliciesClient *sql.ServerSecurityAlertPoliciesClient
Expand Down Expand Up @@ -118,6 +119,9 @@ func NewClient(o *common.ClientOptions) *Client {
serverConnectionPoliciesClient := sql.NewServerConnectionPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&serverConnectionPoliciesClient.Client, o.ResourceManagerAuthorizer)

serverDNSAliasClient := sql.NewServerDNSAliasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&serverDNSAliasClient.Client, o.ResourceManagerAuthorizer)

serverExtendedBlobAuditingPoliciesClient := sql.NewExtendedServerBlobAuditingPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&serverExtendedBlobAuditingPoliciesClient.Client, o.ResourceManagerAuthorizer)

Expand Down Expand Up @@ -168,6 +172,7 @@ func NewClient(o *common.ClientOptions) *Client {
ServerAzureADAdministratorsClient: &serverAzureADAdministratorsClient,
ServerAzureADOnlyAuthenticationsClient: &serverAzureADOnlyAuthenticationsClient,
ServerConnectionPoliciesClient: &serverConnectionPoliciesClient,
ServerDNSAliasClient: &serverDNSAliasClient,
ServerExtendedBlobAuditingPoliciesClient: &serverExtendedBlobAuditingPoliciesClient,
ServerKeysClient: &serverKeysClient,
ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient,
Expand Down
140 changes: 140 additions & 0 deletions internal/services/mssql/mssql_server_dns_alias_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package mssql

import (
"context"
"fmt"
"time"

validate2 "github.com/hashicorp/terraform-provider-azurerm/helpers/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type ServerDNSAliasModel struct {
MsSQLServerId string `tfschema:"mssql_server_id"`
Name string `tfschema:"name"`
DNSRecord string `tfschema:"dns_record"`
}

type ServerDNSAliasResource struct{}

var _ sdk.Resource = (*ServerDNSAliasResource)(nil)

func (m ServerDNSAliasResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"mssql_server_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.ServerID,
},

"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate2.NotEmptyString,
},
}
}

func (m ServerDNSAliasResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"dns_record": {
Type: pluginsdk.TypeString,
Computed: true,
},
}
}

func (m ServerDNSAliasResource) ModelObject() interface{} {
return &ServerDNSAliasModel{}
}

func (m ServerDNSAliasResource) ResourceType() string {
return "azurerm_mssql_server_dns_alias"
}

func (m ServerDNSAliasResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var alias ServerDNSAliasModel
if err := metadata.Decode(&alias); err != nil {
return err
}
serverID, err := parse.ServerID(alias.MsSQLServerId)
if err != nil {
return err
}
client := metadata.Client.MSSQL.ServerDNSAliasClient
id := parse.NewServerDNSAliasID(serverID.SubscriptionId, serverID.ResourceGroup, serverID.Name, alias.Name)
existing, err := client.Get(ctx, id.ResourceGroup, id.ServerName, id.DnsAliaseName)
if !utils.ResponseWasNotFound(existing.Response) {
if err != nil {
return fmt.Errorf("retreiving %s: %v", id, err)
}
return metadata.ResourceRequiresImport(m.ResourceType(), id)
}
future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.ServerName, id.DnsAliaseName)
if err != nil {
return fmt.Errorf("creating %s: %v", id, err)
}
if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for creation of %s: %v", id, err)
}
metadata.SetID(id)
return nil
},
}
}

func (m ServerDNSAliasResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
id, err := parse.ServerDNSAliasID(metadata.ResourceData.Id())
if err != nil {
return err
}
client := metadata.Client.MSSQL.ServerDNSAliasClient
alias, err := client.Get(ctx, id.ResourceGroup, id.ServerName, id.DnsAliaseName)
if err != nil {
return err
}
state := ServerDNSAliasModel{
Name: id.DnsAliaseName,
MsSQLServerId: parse.NewServerID(id.SubscriptionId, id.ResourceGroup, id.ServerName).ID(),
}
if prop := alias.ServerDNSAliasProperties; prop != nil {
state.DNSRecord = utils.NormalizeNilableString(prop.AzureDNSRecord)
}
return metadata.Encode(&state)
},
}
}

func (m ServerDNSAliasResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
id, err := parse.ServerDNSAliasID(metadata.ResourceData.Id())
if err != nil {
return err
}
metadata.Logger.Infof("deleting %s", id)
client := metadata.Client.MSSQL.ServerDNSAliasClient
if _, err = client.Delete(ctx, id.ResourceGroup, id.ServerName, id.DnsAliaseName); err != nil {
return fmt.Errorf("deleting %s: %v", id, err)
}
return nil
},
}
}

func (m ServerDNSAliasResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.ServerDNSAliasID
}
108 changes: 108 additions & 0 deletions internal/services/mssql/mssql_server_dns_alias_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package mssql_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/parse"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type ServerDNSAliasResource struct{}

func TestAccServerDNSAlias_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_server_dns_alias", "test")
r := ServerDNSAliasResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccServerDNSAlias_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_server_dns_alias", "test")
r := ServerDNSAliasResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.RequiresImportErrorStep(r.requiresImport),
})
}

func (r ServerDNSAliasResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := parse.ServerDNSAliasID(state.ID)
if err != nil {
return nil, err
}

resp, err := client.MSSQL.ServerDNSAliasClient.Get(ctx, id.ResourceGroup, id.ServerName, id.DnsAliaseName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return utils.Bool(false), nil
}
return nil, fmt.Errorf("retreiving %s: %v", id, err)
}
if utils.ResponseWasNotFound(resp.Response) {
return utils.Bool(false), nil
}
return utils.Bool(true), nil
}

// Configs

func (r ServerDNSAliasResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-appServerDNSAlias-%[1]d"
location = "%[2]s"
}
resource "azurerm_mssql_server" "sql" {
administrator_login = "umtacc"
administrator_login_password = "random81jdpwd_$#fs"
location = azurerm_resource_group.test.location
name = "acctestrg-sql-sever-%[1]d"
resource_group_name = azurerm_resource_group.test.name
version = "12.0"
}
resource "azurerm_mssql_server_dns_alias" "test" {
mssql_server_id = azurerm_mssql_server.sql.id
name = "acctest-dns-alias-%[1]d"
}
`, data.RandomInteger, data.Locations.Primary)
}

func (r ServerDNSAliasResource) requiresImport(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_mssql_server_dns_alias" "import" {
name = azurerm_mssql_server_dns_alias.test.name
mssql_server_id = azurerm_mssql_server_dns_alias.test.mssql_server_id
}
`, r.basic(data))
}
75 changes: 75 additions & 0 deletions internal/services/mssql/parse/server_dns_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"fmt"
"strings"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

type ServerDNSAliasId struct {
SubscriptionId string
ResourceGroup string
ServerName string
DnsAliaseName string
}

func NewServerDNSAliasID(subscriptionId, resourceGroup, serverName, dnsAliaseName string) ServerDNSAliasId {
return ServerDNSAliasId{
SubscriptionId: subscriptionId,
ResourceGroup: resourceGroup,
ServerName: serverName,
DnsAliaseName: dnsAliaseName,
}
}

func (id ServerDNSAliasId) String() string {
segments := []string{
fmt.Sprintf("Dns Aliase Name %q", id.DnsAliaseName),
fmt.Sprintf("Server Name %q", id.ServerName),
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Server D N S Alias", segmentsStr)
}

func (id ServerDNSAliasId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Sql/servers/%s/dnsAliases/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.ServerName, id.DnsAliaseName)
}

// ServerDNSAliasID parses a ServerDNSAlias ID into an ServerDNSAliasId struct
func ServerDNSAliasID(input string) (*ServerDNSAliasId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := ServerDNSAliasId{
SubscriptionId: id.SubscriptionID,
ResourceGroup: id.ResourceGroup,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

if resourceId.ResourceGroup == "" {
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
}

if resourceId.ServerName, err = id.PopSegment("servers"); err != nil {
return nil, err
}
if resourceId.DnsAliaseName, err = id.PopSegment("dnsAliases"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
Loading

0 comments on commit 8282dec

Please sign in to comment.