Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New resource/data source: azurerm_mssql_database #6083

Merged
merged 35 commits into from
Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions azurerm/helpers/validate/float.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package validate

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

// FloatInSlice returns a SchemaValidateFunc which tests if the provided value
// is of type float64 and matches the value of an element in the valid slice
func FloatInSlice(valid []float64) schema.SchemaValidateFunc {
return func(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(float64)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %s to be float", i))
return warnings, errors
}

for _, validFloat := range valid {
if v == validFloat {
return warnings, errors
}
}

errors = append(errors, fmt.Errorf("expected %s to be one of %v, got %f", k, valid, v))
return warnings, errors
}
}
50 changes: 50 additions & 0 deletions azurerm/helpers/validate/float_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package validate

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func TestValidateFloatInSlice(t *testing.T) {
cases := map[string]struct {
Value interface{}
ValidateFunc schema.SchemaValidateFunc
ExpectValidationErrors bool
}{
"accept valid value": {
Value: 1.5,
ValidateFunc: FloatInSlice([]float64{1.0, 1.5, 2.0}),
ExpectValidationErrors: false,
},
"accept valid negative value ": {
Value: -1.0,
ValidateFunc: FloatInSlice([]float64{-1.0, 2.0}),
ExpectValidationErrors: false,
},
"accept zero": {
Value: 0.0,
ValidateFunc: FloatInSlice([]float64{0.0, 2.0}),
ExpectValidationErrors: false,
},
"reject out of range value": {
Value: -1.0,
ValidateFunc: FloatInSlice([]float64{0.0, 2.0}),
ExpectValidationErrors: true,
},
"reject incorrectly typed value": {
Value: 1,
ValidateFunc: FloatInSlice([]float64{0, 1, 2}),
ExpectValidationErrors: true,
},
}

for tn, tc := range cases {
_, errors := tc.ValidateFunc(tc.Value, tn)
if len(errors) > 0 && !tc.ExpectValidationErrors {
t.Errorf("%s: unexpected errors %s", tn, errors)
} else if len(errors) == 0 && tc.ExpectValidationErrors {
t.Errorf("%s: expected errors but got none", tn)
}
}
}
14 changes: 12 additions & 2 deletions azurerm/internal/services/mssql/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ import (
)

type Client struct {
DatabasesClient *sql.DatabasesClient
ElasticPoolsClient *sql.ElasticPoolsClient
DatabaseVulnerabilityAssessmentRuleBaselinesClient *sql.DatabaseVulnerabilityAssessmentRuleBaselinesClient
ServersClient *sql.ServersClient
ServerSecurityAlertPoliciesClient *sql.ServerSecurityAlertPoliciesClient
ServerVulnerabilityAssessmentsClient *sql.ServerVulnerabilityAssessmentsClient
}

func NewClient(o *common.ClientOptions) *Client {
DatabasesClient := sql.NewDatabasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&DatabasesClient.Client, o.ResourceManagerAuthorizer)

ElasticPoolsClient := sql.NewElasticPoolsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&ElasticPoolsClient.Client, o.ResourceManagerAuthorizer)

Expand All @@ -22,13 +27,18 @@ func NewClient(o *common.ClientOptions) *Client {
ServerSecurityAlertPoliciesClient := sql.NewServerSecurityAlertPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&ServerSecurityAlertPoliciesClient.Client, o.ResourceManagerAuthorizer)

ServersClient := sql.NewServersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&ServersClient.Client, o.ResourceManagerAuthorizer)

ServerVulnerabilityAssessmentsClient := sql.NewServerVulnerabilityAssessmentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&ServerVulnerabilityAssessmentsClient.Client, o.ResourceManagerAuthorizer)

return &Client{
DatabasesClient: &DatabasesClient,
ElasticPoolsClient: &ElasticPoolsClient,
DatabaseVulnerabilityAssessmentRuleBaselinesClient: &DatabaseVulnerabilityAssessmentRuleBaselinesClient,
ServerSecurityAlertPoliciesClient: &ServerSecurityAlertPoliciesClient,
ServerVulnerabilityAssessmentsClient: &ServerVulnerabilityAssessmentsClient,
ServersClient: &ServersClient,
ServerSecurityAlertPoliciesClient: &ServerSecurityAlertPoliciesClient,
ServerVulnerabilityAssessmentsClient: &ServerVulnerabilityAssessmentsClient,
}
}
129 changes: 129 additions & 0 deletions azurerm/internal/services/mssql/data_source_mssql_database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package mssql

import (
"fmt"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceArmMsSqlDatabase() *schema.Resource {
return &schema.Resource{
Read: dataSourceArmMsSqlDatabaseRead,

Timeouts: &schema.ResourceTimeout{
Read: schema.DefaultTimeout(5 * time.Minute),
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: azure.ValidateMsSqlDatabaseName,
},

"server_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.MsSqlServerID,
},

"collation": {
Type: schema.TypeString,
Computed: true,
},

"elastic_pool_id": {
Type: schema.TypeString,
Computed: true,
},

"license_type": {
Type: schema.TypeString,
Computed: true,
},

"max_size_gb": {
Type: schema.TypeInt,
Computed: true,
},

"read_replica_count": {
Type: schema.TypeInt,
Computed: true,
},

"read_scale": {
Type: schema.TypeBool,
Computed: true,
},

"sku_name": {
Type: schema.TypeString,
Computed: true,
},

"zone_redundant": {
Type: schema.TypeBool,
Computed: true,
},

"tags": tags.SchemaDataSource(),
},
}
}

func dataSourceArmMsSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).MSSQL.DatabasesClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

name := d.Get("name").(string)
mssqlServerId := d.Get("server_id").(string)
serverId, err := parse.MsSqlServerID(mssqlServerId)
if err != nil {
return err
}

resp, err := client.Get(ctx, serverId.ResourceGroup, serverId.Name, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Database %q (Resource Group %q, SQL Server %q) was not found", name, serverId.ResourceGroup, serverId.Name)
}

return fmt.Errorf("Failure in making Read request on AzureRM Database %s (Resource Group %q, SQL Server %q): %+v", name, serverId.ResourceGroup, serverId.Name, err)
}

if id := resp.ID; id != nil {
d.SetId(*resp.ID)
}
d.Set("name", name)
d.Set("server_id", mssqlServerId)

if props := resp.DatabaseProperties; props != nil {
d.Set("collation", props.Collation)
d.Set("elastic_pool_id", props.ElasticPoolID)
d.Set("license_type", props.LicenseType)
if props.MaxSizeBytes != nil {
d.Set("max_size_gb", int32((*props.MaxSizeBytes)/int64(1073741824)))
}
d.Set("read_replica_count", props.ReadReplicaCount)
if props.ReadScale == sql.DatabaseReadScaleEnabled {
d.Set("read_scale", true)
} else if props.ReadScale == sql.DatabaseReadScaleDisabled {
d.Set("read_scale", false)
}
d.Set("sku_name", props.CurrentServiceObjectiveName)
d.Set("zone_redundant", props.ZoneRedundant)
}

return tags.FlattenAndSet(d, resp.Tags)
}
95 changes: 95 additions & 0 deletions azurerm/internal/services/mssql/parse/mssql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package parse

import (
"fmt"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type MsSqlDatabaseId struct {
Name string
MsSqlServer string
ResourceGroup string
}

type MsSqlServerId struct {
Name string
ResourceGroup string
}

type MsSqlElasticPoolId struct {
Name string
MsSqlServer string
ResourceGroup string
}

func MsSqlDatabaseID(input string) (*MsSqlDatabaseId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("Unable to parse MsSql Database ID %q: %+v", input, err)
}

database := MsSqlDatabaseId{
ResourceGroup: id.ResourceGroup,
}

if database.MsSqlServer, err = id.PopSegment("servers"); err != nil {
return nil, err
}

if database.Name, err = id.PopSegment("databases"); err != nil {
return nil, err
}

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

return &database, nil
}

func MsSqlServerID(input string) (*MsSqlServerId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("Unable to parse MsSql Server ID %q: %+v", input, err)
}

server := MsSqlServerId{
ResourceGroup: id.ResourceGroup,
}

if server.Name, err = id.PopSegment("servers"); err != nil {
return nil, err
}

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

return &server, nil
}

func MSSqlElasticPoolID(input string) (*MsSqlElasticPoolId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("Unable to parse MsSql Elastic Pool ID %q: %+v", input, err)
}

elasticPool := MsSqlElasticPoolId{
ResourceGroup: id.ResourceGroup,
}

if elasticPool.MsSqlServer, err = id.PopSegment("servers"); err != nil {
return nil, err
}

if elasticPool.Name, err = id.PopSegment("elasticPools"); err != nil {
return nil, err
}

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

return &elasticPool, nil
}
Loading