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 1 commit
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,
}
}
164 changes: 164 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,164 @@
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"
"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: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use ValidateResourceIDPriorToImport here.


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)

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

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

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
}
148 changes: 148 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,148 @@
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 SqlFirewallRuleResource struct{}

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

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

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

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 TestAccSqlFirewallRule_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_firewall_rule", "test")
r := SqlFirewallRuleResource{}

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 SqlFirewallRuleResource) 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 (SqlFirewallRuleResource) 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 SqlFirewallRuleResource) 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 SqlFirewallRuleResource) 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 SqlFirewallRuleResource) 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))
}
1 change: 1 addition & 0 deletions azurerm/internal/services/mssql/mssql_server_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/go-azure-helpers/response"
"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/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
Expand Down
Loading