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

mssql: add resources azurerm_mssql_firewall_rule and azurerm_mssql_virtual_network_rule #10954

Merged
merged 4 commits into from
Mar 18, 2021
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
2 changes: 1 addition & 1 deletion .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ var services = mapOf(
"maps" to "Maps",
"mariadb" to "MariaDB",
"media" to "Media",
"mssql" to "Microsoft SQL Server / SQL Azure",
"mssql" to "Microsoft SQL Server / Azure SQL",
"mixedreality" to "Mixed Reality",
"monitor" to "Monitor",
"mysql" to "MySQL",
Expand Down
19 changes: 15 additions & 4 deletions azurerm/internal/services/mssql/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@ package client
import (
"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql"
"github.com/Azure/azure-sdk-for-go/services/preview/sqlvirtualmachine/mgmt/2017-03-01-preview/sqlvirtualmachine"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

type Client struct {
BackupLongTermRetentionPoliciesClient *sql.BackupLongTermRetentionPoliciesClient
BackupShortTermRetentionPoliciesClient *sql.BackupShortTermRetentionPoliciesClient
DatabasesClient *sql.DatabasesClient
DatabaseExtendedBlobAuditingPoliciesClient *sql.ExtendedDatabaseBlobAuditingPoliciesClient
DatabaseThreatDetectionPoliciesClient *sql.DatabaseThreatDetectionPoliciesClient
ElasticPoolsClient *sql.ElasticPoolsClient
DatabaseVulnerabilityAssessmentRuleBaselinesClient *sql.DatabaseVulnerabilityAssessmentRuleBaselinesClient
DatabasesClient *sql.DatabasesClient
ElasticPoolsClient *sql.ElasticPoolsClient
FirewallRulesClient *sql.FirewallRulesClient
RestorableDroppedDatabasesClient *sql.RestorableDroppedDatabasesClient
ServerAzureADAdministratorsClient *sql.ServerAzureADAdministratorsClient
ServersClient *sql.ServersClient
ServerExtendedBlobAuditingPoliciesClient *sql.ExtendedServerBlobAuditingPoliciesClient
ServerConnectionPoliciesClient *sql.ServerConnectionPoliciesClient
ServerExtendedBlobAuditingPoliciesClient *sql.ExtendedServerBlobAuditingPoliciesClient
ServerSecurityAlertPoliciesClient *sql.ServerSecurityAlertPoliciesClient
ServerVulnerabilityAssessmentsClient *sql.ServerVulnerabilityAssessmentsClient
ServersClient *sql.ServersClient
VirtualMachinesClient *sqlvirtualmachine.SQLVirtualMachinesClient
VirtualNetworkRulesClient *sql.VirtualNetworkRulesClient
}

func NewClient(o *common.ClientOptions) *Client {
Expand All @@ -46,6 +49,9 @@ func NewClient(o *common.ClientOptions) *Client {
elasticPoolsClient := sql.NewElasticPoolsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&elasticPoolsClient.Client, o.ResourceManagerAuthorizer)

firewallRulesClient := sql.NewFirewallRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&firewallRulesClient.Client, o.ResourceManagerAuthorizer)

restorableDroppedDatabasesClient := sql.NewRestorableDroppedDatabasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&restorableDroppedDatabasesClient.Client, o.ResourceManagerAuthorizer)

Expand All @@ -70,6 +76,9 @@ func NewClient(o *common.ClientOptions) *Client {
sqlVirtualMachinesClient := sqlvirtualmachine.NewSQLVirtualMachinesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&sqlVirtualMachinesClient.Client, o.ResourceManagerAuthorizer)

sqlVirtualNetworkRulesClient := sql.NewVirtualNetworkRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&sqlVirtualNetworkRulesClient.Client, o.ResourceManagerAuthorizer)

return &Client{
BackupLongTermRetentionPoliciesClient: &BackupLongTermRetentionPoliciesClient,
BackupShortTermRetentionPoliciesClient: &BackupShortTermRetentionPoliciesClient,
Expand All @@ -78,6 +87,7 @@ func NewClient(o *common.ClientOptions) *Client {
DatabaseThreatDetectionPoliciesClient: &databaseThreatDetectionPoliciesClient,
DatabaseVulnerabilityAssessmentRuleBaselinesClient: &databaseVulnerabilityAssessmentRuleBaselinesClient,
ElasticPoolsClient: &elasticPoolsClient,
FirewallRulesClient: &firewallRulesClient,
RestorableDroppedDatabasesClient: &restorableDroppedDatabasesClient,
ServerAzureADAdministratorsClient: &serverAzureADAdministratorsClient,
ServersClient: &serversClient,
Expand All @@ -86,5 +96,6 @@ func NewClient(o *common.ClientOptions) *Client {
ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient,
ServerVulnerabilityAssessmentsClient: &serverVulnerabilityAssessmentsClient,
VirtualMachinesClient: &sqlVirtualMachinesClient,
VirtualNetworkRulesClient: &sqlVirtualNetworkRulesClient,
}
}
165 changes: 165 additions & 0 deletions azurerm/internal/services/mssql/mssql_firewall_rule_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package mssql

import (
"fmt"
"log"
"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/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/sql/parse"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceMsSqlFirewallRule() *schema.Resource {
return &schema.Resource{
Create: resourceMsSqlFirewallRuleCreateUpdate,
Read: resourceMsSqlFirewallRuleRead,
Update: resourceMsSqlFirewallRuleCreateUpdate,
Delete: resourceMsSqlFirewallRuleDelete,

Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := parse.FirewallRuleID(id)
return err
}),

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

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

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

"start_ip_address": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.All(
validation.IsIPAddress,
validation.StringIsNotEmpty,
),
},

"end_ip_address": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.All(
validation.IsIPAddress,
validation.StringIsNotEmpty,
),
},
},
}
}

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

serverId, err := parse.ServerID(d.Get("server_id").(string))
if err != nil {
return fmt.Errorf("parsing server ID %q: %+v", d.Get("server_id"), err)
}

id := parse.NewFirewallRuleID(serverId.SubscriptionId, serverId.ResourceGroup, serverId.Name, d.Get("name").(string))

if d.IsNewResource() {
existing, err := client.Get(ctx, id.ResourceGroup, id.ServerName, id.Name)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("checking for presence of existing MSSQL %s: %+v", id.String(), err)
}
}

if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError("azurerm_mssql_firewall_rule", id.ID())
}
}

parameters := sql.FirewallRule{
FirewallRuleProperties: &sql.FirewallRuleProperties{
StartIPAddress: utils.String(d.Get("start_ip_address").(string)),
EndIPAddress: utils.String(d.Get("end_ip_address").(string)),
},
}

if _, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.ServerName, id.Name, parameters); err != nil {
return fmt.Errorf("creating MSSQL %s: %+v", id.String(), err)
}

d.SetId(id.ID())

return resourceMsSqlFirewallRuleRead(d, meta)
}

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

id, err := parse.FirewallRuleID(d.Id())
if err != nil {
return fmt.Errorf("parsing ID %q: %+v", d.Id(), err)
}

resp, err := client.Get(ctx, id.ResourceGroup, id.ServerName, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[INFO] MSSQL %s was not found - removing from state", id.String())
d.SetId("")
return nil
}

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

d.Set("name", id.Name)

d.Set("start_ip_address", resp.StartIPAddress)
d.Set("end_ip_address", resp.EndIPAddress)

serverId := parse.NewServerID(id.SubscriptionId, id.ResourceGroup, id.ServerName)
d.Set("server_id", serverId.ID())

return nil
}

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

id, err := parse.FirewallRuleID(d.Id())
if err != nil {
return fmt.Errorf("parsing ID %q: %+v", d.Id(), err)
}

resp, err := client.Delete(ctx, id.ResourceGroup, id.ServerName, id.Name)
if err != nil {
if !utils.ResponseWasNotFound(resp) {
return fmt.Errorf("deleting MSSQL %s: %+v", id.String(), err)
}
}

return nil
}
147 changes: 147 additions & 0 deletions azurerm/internal/services/mssql/mssql_firewall_rule_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package mssql_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check"
"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/utils"
)

type MsSqlFirewallRuleResource struct{}

func TestAccMsSqlFirewallRule_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_firewall_rule", "test")
r := MsSqlFirewallRuleResource{}

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

func TestAccMsSqlFirewallRule_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_firewall_rule", "test")
r := MsSqlFirewallRuleResource{}

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

func TestAccMsSqlFirewallRule_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_firewall_rule", "test")
r := MsSqlFirewallRuleResource{}

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

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

resp, err := client.MSSQL.FirewallRulesClient.Get(ctx, id.ResourceGroup, id.ServerName, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return utils.Bool(false), nil
}
return nil, fmt.Errorf("retrieving MSSQL %s: %+v", id.String(), err)
}

return utils.Bool(true), nil
}

func (MsSqlFirewallRuleResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%[1]d"
location = "%[2]s"
}

resource "azurerm_mssql_server" "test" {
name = "acctestsqlserver%[1]d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
version = "12.0"
administrator_login = "msincredible"
administrator_login_password = "P@55W0rD!!%[3]s"
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func (r MsSqlFirewallRuleResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s

resource "azurerm_mssql_firewall_rule" "test" {
name = "acctestsqlserver%[2]d"
server_id = azurerm_mssql_server.test.id
start_ip_address = "0.0.0.0"
end_ip_address = "255.255.255.255"
}
`, r.template(data), data.RandomInteger)
}

func (r MsSqlFirewallRuleResource) updated(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s

resource "azurerm_mssql_firewall_rule" "test" {
name = "acctestsqlserver%[2]d"
server_id = azurerm_mssql_server.test.id
start_ip_address = "10.0.17.62"
end_ip_address = "10.0.17.64"
}
`, r.template(data), data.RandomInteger)
}

func (r MsSqlFirewallRuleResource) requiresImport(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s

resource "azurerm_mssql_firewall_rule" "import" {
name = azurerm_mssql_firewall_rule.test.name
server_id = azurerm_mssql_firewall_rule.test.server_id
start_ip_address = azurerm_mssql_firewall_rule.test.start_ip_address
end_ip_address = azurerm_mssql_firewall_rule.test.end_ip_address
}
`, r.basic(data))
}
Loading