diff --git a/azurerm/helpers/azure/mssql.go b/azurerm/helpers/azure/mssql.go index 188bd78fdd8e..de9e37befe34 100644 --- a/azurerm/helpers/azure/mssql.go +++ b/azurerm/helpers/azure/mssql.go @@ -24,6 +24,14 @@ func ValidateMsSqlDatabaseName(i interface{}, k string) (_ []string, errors []er return nil, errors } +func ValidateMsSqlFailoverGroupName(i interface{}, k string) (_ []string, errors []error) { + if m, regexErrs := validate.RegExHelper(i, k, `^[0-9a-z]([-0-9a-z]{0,61}[0-9a-z])?$`); !m { + errors = append(regexErrs, fmt.Errorf("%q can contain only lowercase letters, numbers, and '-', but can't start or end with '-'.", k)) + } + + return nil, errors +} + //Following characters and any control characters are not allowed for resource name '%,&,\\\\,?,/'.\" //The name can not end with characters: '. ' //TODO: unsure about length, was able to deploy one at 120 diff --git a/azurerm/internal/services/mssql/client.go b/azurerm/internal/services/mssql/client.go index 7dcf7ddaa3a4..cd330d84ffc4 100644 --- a/azurerm/internal/services/mssql/client.go +++ b/azurerm/internal/services/mssql/client.go @@ -13,6 +13,7 @@ func BuildClient(o *common.ClientOptions) *Client { ElasticPoolsClient := sql.NewElasticPoolsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ElasticPoolsClient.Client, o.ResourceManagerAuthorizer) + return &Client{ ElasticPoolsClient: &ElasticPoolsClient, } diff --git a/azurerm/internal/services/sql/client.go b/azurerm/internal/services/sql/client.go index db2b93ac5f66..36c05bfd530a 100644 --- a/azurerm/internal/services/sql/client.go +++ b/azurerm/internal/services/sql/client.go @@ -10,6 +10,7 @@ type Client struct { DatabaseThreatDetectionPoliciesClient *sql.DatabaseThreatDetectionPoliciesClient ElasticPoolsClient *sql.ElasticPoolsClient FirewallRulesClient *sql.FirewallRulesClient + FailoverGroupsClient *sql.FailoverGroupsClient ServersClient *sql.ServersClient ServerAzureADAdministratorsClient *sql.ServerAzureADAdministratorsClient VirtualNetworkRulesClient *sql.VirtualNetworkRulesClient @@ -27,6 +28,9 @@ func BuildClient(o *common.ClientOptions) *Client { ElasticPoolsClient := sql.NewElasticPoolsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ElasticPoolsClient.Client, o.ResourceManagerAuthorizer) + FailoverGroupsClient := sql.NewFailoverGroupsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&FailoverGroupsClient.Client, o.ResourceManagerAuthorizer) + FirewallRulesClient := sql.NewFirewallRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&FirewallRulesClient.Client, o.ResourceManagerAuthorizer) @@ -43,6 +47,7 @@ func BuildClient(o *common.ClientOptions) *Client { DatabasesClient: &DatabasesClient, DatabaseThreatDetectionPoliciesClient: &DatabaseThreatDetectionPoliciesClient, ElasticPoolsClient: &ElasticPoolsClient, + FailoverGroupsClient: &FailoverGroupsClient, FirewallRulesClient: &FirewallRulesClient, ServersClient: &ServersClient, ServerAzureADAdministratorsClient: &ServerAzureADAdministratorsClient, diff --git a/azurerm/provider.go b/azurerm/provider.go index 656f10c15c87..41d0a474c8f6 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -360,6 +360,7 @@ func Provider() terraform.ResourceProvider { "azurerm_sql_active_directory_administrator": resourceArmSqlAdministrator(), "azurerm_sql_database": resourceArmSqlDatabase(), "azurerm_sql_elasticpool": resourceArmSqlElasticPool(), + "azurerm_sql_failover_group": resourceArmSqlFailoverGroup(), "azurerm_sql_firewall_rule": resourceArmSqlFirewallRule(), "azurerm_sql_server": resourceArmSqlServer(), "azurerm_sql_virtual_network_rule": resourceArmSqlVirtualNetworkRule(), diff --git a/azurerm/resource_arm_sql_failover_group.go b/azurerm/resource_arm_sql_failover_group.go new file mode 100644 index 000000000000..9085f8223da9 --- /dev/null +++ b/azurerm/resource_arm_sql_failover_group.go @@ -0,0 +1,361 @@ +package azurerm + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func resourceArmSqlFailoverGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceArmSqlFailoverGroupCreateUpdate, + Read: resourceArmSqlFailoverGroupRead, + Update: resourceArmSqlFailoverGroupCreateUpdate, + Delete: resourceArmSqlFailoverGroupDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateMsSqlFailoverGroupName, + }, + + "location": azure.SchemaLocationForDataSource(), + + "resource_group_name": azure.SchemaResourceGroupName(), + + "server_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateMsSqlServerName, + }, + + "databases": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + }, + + "partner_servers": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "location": azure.SchemaLocationForDataSource(), + + "role": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "readonly_endpoint_failover_policy": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sql.ReadOnlyEndpointFailoverPolicyDisabled), + string(sql.ReadOnlyEndpointFailoverPolicyEnabled), + }, false), + }, + }, + }, + }, + + "read_write_endpoint_failover_policy": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sql.Automatic), + string(sql.Manual), + }, false), + }, + "grace_minutes": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + + "role": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmSqlFailoverGroupCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).sql.FailoverGroupsClient + ctx := meta.(*ArmClient).StopContext + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + serverName := d.Get("server_name").(string) + + if requireResourcesToBeImported && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, serverName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing SQL Failover Group %q (Resource Group %q, Server %q): %+v", name, resourceGroup, serverName, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_sql_failover_group", *existing.ID) + } + } + + tags := d.Get("tags").(map[string]interface{}) + + properties := sql.FailoverGroup{ + FailoverGroupProperties: &sql.FailoverGroupProperties{ + ReadOnlyEndpoint: expandSqlFailoverGroupReadOnlyPolicy(d), + ReadWriteEndpoint: expandSqlFailoverGroupReadWritePolicy(d), + PartnerServers: expandSqlFailoverGroupPartnerServers(d), + }, + Tags: expandTags(tags), + } + + if r, ok := d.Get("databases").(*schema.Set); ok && r.Len() > 0 { + var databases []string + for _, v := range r.List() { + s := v.(string) + databases = append(databases, s) + } + + properties.Databases = &databases + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, serverName, name, properties) + if err != nil { + return fmt.Errorf("Error issuing create/update request for SQL Failover Group %q (Resource Group %q, Server %q): %+v", name, resourceGroup, serverName, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on create/update future for SQL Failover Group %q (Resource Group %q, Server %q): %+v", name, resourceGroup, serverName, err) + } + + resp, err := client.Get(ctx, resourceGroup, serverName, name) + if err != nil { + return fmt.Errorf("Error issuing get request for SQL Failover Group %q (Resource Group %q, Server %q): %+v", name, resourceGroup, serverName, err) + } + + d.SetId(*resp.ID) + + return resourceArmSqlFailoverGroupRead(d, meta) +} + +func resourceArmSqlFailoverGroupRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).sql.FailoverGroupsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resourceGroup := id.ResourceGroup + serverName := id.Path["servers"] + name := id.Path["failoverGroups"] + + resp, err := client.Get(ctx, resourceGroup, serverName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error making Read request for SQL Failover Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resourceGroup) + d.Set("server_name", serverName) + + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if props := resp.FailoverGroupProperties; props != nil { + if err := d.Set("read_write_endpoint_failover_policy", flattenSqlFailoverGroupReadWritePolicy(props.ReadWriteEndpoint)); err != nil { + return fmt.Errorf("Error setting `read_write_endpoint_failover_policy`: %+v", err) + } + + if err := d.Set("readonly_endpoint_failover_policy", flattenSqlFailoverGroupReadOnlyPolicy(props.ReadOnlyEndpoint)); err != nil { + return fmt.Errorf("Error setting `read_only_endpoint_failover_policy`: %+v", err) + } + + if props.Databases != nil { + d.Set("databases", set.FromStringSlice(*props.Databases)) + } + d.Set("role", string(props.ReplicationRole)) + + if err := d.Set("partner_servers", flattenSqlFailoverGroupPartnerServers(props.PartnerServers)); err != nil { + return fmt.Errorf("Error setting `partner_servers`: %+v", err) + } + } + + flattenAndSetTags(d, resp.Tags) + + return nil +} + +func resourceArmSqlFailoverGroupDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).sql.FailoverGroupsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resourceGroup := id.ResourceGroup + serverName := id.Path["servers"] + name := id.Path["failoverGroups"] + + future, err := client.Delete(ctx, resourceGroup, serverName, name) + if err != nil { + return fmt.Errorf("Error deleting SQL Failover Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error deleting SQL Failover Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + return err +} + +func expandSqlFailoverGroupReadWritePolicy(d *schema.ResourceData) *sql.FailoverGroupReadWriteEndpoint { + vs := d.Get("read_write_endpoint_failover_policy").([]interface{}) + v := vs[0].(map[string]interface{}) + + mode := sql.ReadWriteEndpointFailoverPolicy(v["mode"].(string)) + graceMins := int32(v["grace_minutes"].(int)) + + policy := &sql.FailoverGroupReadWriteEndpoint{ + FailoverPolicy: mode, + } + + if mode != sql.Manual { + policy.FailoverWithDataLossGracePeriodMinutes = utils.Int32(graceMins) + } + + return policy +} + +func flattenSqlFailoverGroupReadWritePolicy(input *sql.FailoverGroupReadWriteEndpoint) []interface{} { + if input == nil { + return []interface{}{} + } + + policy := make(map[string]interface{}) + + policy["mode"] = string(input.FailoverPolicy) + + if input.FailoverWithDataLossGracePeriodMinutes != nil { + policy["grace_minutes"] = *input.FailoverWithDataLossGracePeriodMinutes + } + return []interface{}{policy} +} + +func expandSqlFailoverGroupReadOnlyPolicy(d *schema.ResourceData) *sql.FailoverGroupReadOnlyEndpoint { + vs := d.Get("readonly_endpoint_failover_policy").([]interface{}) + if len(vs) == 0 { + return nil + } + + v := vs[0].(map[string]interface{}) + mode := sql.ReadOnlyEndpointFailoverPolicy(v["mode"].(string)) + + return &sql.FailoverGroupReadOnlyEndpoint{ + FailoverPolicy: mode, + } +} + +func flattenSqlFailoverGroupReadOnlyPolicy(input *sql.FailoverGroupReadOnlyEndpoint) []interface{} { + if input == nil { + return []interface{}{} + } + + policy := make(map[string]interface{}) + policy["mode"] = string(input.FailoverPolicy) + + return []interface{}{policy} +} + +func expandSqlFailoverGroupPartnerServers(d *schema.ResourceData) *[]sql.PartnerInfo { + servers := d.Get("partner_servers").([]interface{}) + partners := make([]sql.PartnerInfo, 0) + + for _, server := range servers { + info := server.(map[string]interface{}) + + id := info["id"].(string) + partners = append(partners, sql.PartnerInfo{ + ID: &id, + }) + } + + return &partners +} + +func flattenSqlFailoverGroupPartnerServers(input *[]sql.PartnerInfo) []map[string]interface{} { + result := make([]map[string]interface{}, 0) + + if input != nil { + for _, server := range *input { + info := make(map[string]interface{}) + + if v := server.ID; v != nil { + info["id"] = *v + } + if v := server.Location; v != nil { + info["location"] = *v + } + info["role"] = string(server.ReplicationRole) + + result = append(result, info) + } + } + return result +} diff --git a/azurerm/resource_arm_sql_failover_group_test.go b/azurerm/resource_arm_sql_failover_group_test.go new file mode 100644 index 000000000000..8443da9e9c74 --- /dev/null +++ b/azurerm/resource_arm_sql_failover_group_test.go @@ -0,0 +1,385 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMSqlFailoverGroup_basic(t *testing.T) { + resourceName := "azurerm_sql_failover_group.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSqlFailoverGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSqlFailoverGroup_basic(ri, testLocation(), testAltLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlFailoverGroupExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSqlFailoverGroup_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skiiping since resources aren't required to be imported") + return + } + resourceName := "azurerm_sql_failover_group.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSqlFailoverGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSqlFailoverGroup_basic(ri, testLocation(), testAltLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlFailoverGroupExists(resourceName), + ), + }, + { + Config: testAccAzureRMSqlFailoverGroup_requiresImport(ri, testLocation(), testAltLocation()), + ExpectError: testRequiresImportError("azurerm_sql_failover_group"), + }, + }, + }) +} + +func TestAccAzureRMSqlFailoverGroup_disappears(t *testing.T) { + resourceName := "azurerm_sql_failover_group.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSqlFailoverGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSqlFailoverGroup_basic(ri, testLocation(), testAltLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlFailoverGroupExists(resourceName), + testCheckAzureRMSqlFailoverGroupDisappears(resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAzureRMSqlFailoverGroup_withTags(t *testing.T) { + resourceName := "azurerm_sql_failover_group.test" + ri := tf.AccRandTimeInt() + location := testLocation() + altLocation := testAltLocation() + preConfig := testAccAzureRMSqlFailoverGroup_withTags(ri, location, altLocation) + postConfig := testAccAzureRMSqlFailoverGroup_withTagsUpdate(ri, location, altLocation) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSqlFailoverGroupDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlFailoverGroupExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlFailoverGroupExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + ), + }, + }, + }) +} + +func testCheckAzureRMSqlFailoverGroupExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serverName := rs.Primary.Attributes["server_name"] + name := rs.Primary.Attributes["name"] + + client := testAccProvider.Meta().(*ArmClient).sql.FailoverGroupsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := client.Get(ctx, resourceGroup, serverName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("SQL Failover Group %q (server %q / resource group %q) was not found", name, serverName, resourceGroup) + } + + return err + } + + return nil + } +} + +func testCheckAzureRMSqlFailoverGroupDisappears(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serverName := rs.Primary.Attributes["server_name"] + name := rs.Primary.Attributes["name"] + + client := testAccProvider.Meta().(*ArmClient).sql.FailoverGroupsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + future, err := client.Delete(ctx, resourceGroup, serverName, name) + if err != nil { + return fmt.Errorf("Bad: Delete on sqlFailoverGroupsClient: %+v", err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error deleting SQL Failover Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + return nil + } +} + +func testCheckAzureRMSqlFailoverGroupDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_sql_failover_group" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serverName := rs.Primary.Attributes["server_name"] + + client := testAccProvider.Meta().(*ArmClient).sql.FailoverGroupsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := client.Get(ctx, resourceGroup, serverName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("SQL Failover Group %q (server %q / resource group %q) still exists: %+v", name, serverName, resourceGroup, resp) + } + + return nil +} + +func testAccAzureRMSqlFailoverGroup_basic(rInt int, location, altlocation string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_sql_server" "test_primary" { + name = "acctestmssql%[1]d-primary" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_server" "test_secondary" { + name = "acctestmssql%[1]d-secondary" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "%[3]s" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_database" "test" { + name = "acctestdb%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test_primary.name}" + location = "${azurerm_resource_group.test.location}" + edition = "Standard" + collation = "SQL_Latin1_General_CP1_CI_AS" + max_size_bytes = "1073741824" + requested_service_objective_name = "S0" +} + +resource "azurerm_sql_failover_group" "test" { + name = "acctestsfg%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test_primary.name}" + databases = ["${azurerm_sql_database.test.id}"] + + partner_servers { + id = "${azurerm_sql_server.test_secondary.id}" + } + + read_write_endpoint_failover_policy { + mode = "Automatic" + grace_minutes = 60 + } +} +`, rInt, location, altlocation) +} + +func testAccAzureRMSqlFailoverGroup_requiresImport(rInt int, location, altlocation string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_sql_failover_group" "import" { + name = "${azurerm_sql_failover_group.test.name}" + resource_group_name = "${azurerm_sql_failover_group.test.resource_group_name}" + server_name = "${azurerm_sql_failover_group.test.server_name}" + databases = "${azurerm_sql_failover_group.test.databases}" + + partner_servers { + id = "${azurerm_sql_failover_group.test.partner_servers.0.id}" + } + + read_write_endpoint_failover_policy { + mode = "${azurerm_sql_failover_group.test.read_write_endpoint_failover_policy.0.mode}" + grace_minutes = "${azurerm_sql_failover_group.test.read_write_endpoint_failover_policy.0.grace_minutes}" + } + } +`, testAccAzureRMSqlFailoverGroup_basic(rInt, location, altlocation)) +} + +func testAccAzureRMSqlFailoverGroup_withTags(rInt int, location, altlocation string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_sql_server" "test_primary" { + name = "acctestmssql%[1]d-primary" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_server" "test_secondary" { + name = "acctestmssql%[1]d-secondary" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "%[3]s" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_database" "test" { + name = "acctestdb%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test_primary.name}" + location = "${azurerm_resource_group.test.location}" + edition = "Standard" + collation = "SQL_Latin1_General_CP1_CI_AS" + max_size_bytes = "1073741824" + requested_service_objective_name = "S0" +} + +resource "azurerm_sql_failover_group" "test" { + name = "acctestsfg%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test_primary.name}" + databases = ["${azurerm_sql_database.test.id}"] + + partner_servers { + id = "${azurerm_sql_server.test_secondary.id}" + } + read_write_endpoint_failover_policy { + mode = "Automatic" + grace_minutes = 60 + } + tags = { + environment = "staging" + database = "test" + } +} +`, rInt, location, altlocation) +} + +func testAccAzureRMSqlFailoverGroup_withTagsUpdate(rInt int, location, altlocation string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_sql_server" "test_primary" { + name = "acctestmssql%[1]d-primary" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_server" "test_secondary" { + name = "acctestmssql%[1]d-secondary" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "%[3]s" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_database" "test" { + name = "acctestdb%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test_primary.name}" + location = "${azurerm_resource_group.test.location}" + edition = "Standard" + collation = "SQL_Latin1_General_CP1_CI_AS" + max_size_bytes = "1073741824" + requested_service_objective_name = "S0" +} + +resource "azurerm_sql_failover_group" "test" { + name = "acctestsfg%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test_primary.name}" + databases = ["${azurerm_sql_database.test.id}"] + + partner_servers { + id = "${azurerm_sql_server.test_secondary.id}" + } + read_write_endpoint_failover_policy { + mode = "Automatic" + grace_minutes = 60 + } + tags = { + environment = "production" + } +} +`, rInt, location, altlocation) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 885644d65f76..6e23f38dd35d 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -817,6 +817,10 @@ azurerm_mssql_elasticpool +