From 48a2dd24773f723c7a5f2942be1b966c8df6335f Mon Sep 17 00:00:00 2001 From: catriona-m <86247157+catriona-m@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:23:04 +0000 Subject: [PATCH] `azurerm_synapse_sql_pool` - add support for `geo_backup_policy_enabled` and fix `recovery_database_id` (#20010) * add recoverableDatabaseId * add recoverableDatabaseId * set recovery_database_id and add geo_backup_policy_enabled property * simplify error message * remove recovery_database_id from read and add docs * docs --- internal/services/synapse/client/client.go | 5 + .../parse/sql_pool_recoverable_database.go | 75 ++++++++++ .../sql_pool_recoverable_database_test.go | 128 ++++++++++++++++++ internal/services/synapse/resourceids.go | 1 + .../synapse/synapse_sql_pool_resource.go | 63 ++++++++- .../synapse/synapse_sql_pool_resource_test.go | 70 ++++++++++ .../sql_pool_recoverable_database_id.go | 23 ++++ .../sql_pool_recoverable_database_id_test.go | 88 ++++++++++++ website/docs/r/synapse_sql_pool.html.markdown | 2 + 9 files changed, 449 insertions(+), 6 deletions(-) create mode 100644 internal/services/synapse/parse/sql_pool_recoverable_database.go create mode 100644 internal/services/synapse/parse/sql_pool_recoverable_database_test.go create mode 100644 internal/services/synapse/validate/sql_pool_recoverable_database_id.go create mode 100644 internal/services/synapse/validate/sql_pool_recoverable_database_id_test.go diff --git a/internal/services/synapse/client/client.go b/internal/services/synapse/client/client.go index 36990c7058d7..c824f16726c9 100644 --- a/internal/services/synapse/client/client.go +++ b/internal/services/synapse/client/client.go @@ -20,6 +20,7 @@ type Client struct { SparkPoolClient *synapse.BigDataPoolsClient SqlPoolClient *synapse.SQLPoolsClient SqlPoolExtendedBlobAuditingPoliciesClient *synapse.ExtendedSQLPoolBlobAuditingPoliciesClient + SqlPoolGeoBackupPoliciesClient *synapse.SQLPoolGeoBackupPoliciesClient SqlPoolSecurityAlertPolicyClient *synapse.SQLPoolSecurityAlertPoliciesClient SqlPoolTransparentDataEncryptionClient *synapse.SQLPoolTransparentDataEncryptionsClient SqlPoolVulnerabilityAssessmentsClient *synapse.SQLPoolVulnerabilityAssessmentsClient @@ -63,6 +64,9 @@ func NewClient(o *common.ClientOptions) *Client { sqlPoolExtendedBlobAuditingPoliciesClient := synapse.NewExtendedSQLPoolBlobAuditingPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&sqlPoolExtendedBlobAuditingPoliciesClient.Client, o.ResourceManagerAuthorizer) + sqlPoolGeoBackupPoliciesClient := synapse.NewSQLPoolGeoBackupPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&sqlPoolGeoBackupPoliciesClient.Client, o.ResourceManagerAuthorizer) + sqlPoolSecurityAlertPolicyClient := synapse.NewSQLPoolSecurityAlertPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&sqlPoolSecurityAlertPolicyClient.Client, o.ResourceManagerAuthorizer) @@ -111,6 +115,7 @@ func NewClient(o *common.ClientOptions) *Client { SparkPoolClient: &sparkPoolClient, SqlPoolClient: &sqlPoolClient, SqlPoolExtendedBlobAuditingPoliciesClient: &sqlPoolExtendedBlobAuditingPoliciesClient, + SqlPoolGeoBackupPoliciesClient: &sqlPoolGeoBackupPoliciesClient, SqlPoolSecurityAlertPolicyClient: &sqlPoolSecurityAlertPolicyClient, SqlPoolTransparentDataEncryptionClient: &sqlPoolTransparentDataEncryptionClient, SqlPoolVulnerabilityAssessmentsClient: &sqlPoolVulnerabilityAssessmentsClient, diff --git a/internal/services/synapse/parse/sql_pool_recoverable_database.go b/internal/services/synapse/parse/sql_pool_recoverable_database.go new file mode 100644 index 000000000000..45b7fac43350 --- /dev/null +++ b/internal/services/synapse/parse/sql_pool_recoverable_database.go @@ -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 SqlPoolRecoverableDatabaseId struct { + SubscriptionId string + ResourceGroup string + WorkspaceName string + RecoverableDatabaseName string +} + +func NewSqlPoolRecoverableDatabaseID(subscriptionId, resourceGroup, workspaceName, recoverableDatabaseName string) SqlPoolRecoverableDatabaseId { + return SqlPoolRecoverableDatabaseId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + WorkspaceName: workspaceName, + RecoverableDatabaseName: recoverableDatabaseName, + } +} + +func (id SqlPoolRecoverableDatabaseId) String() string { + segments := []string{ + fmt.Sprintf("Recoverable Database Name %q", id.RecoverableDatabaseName), + fmt.Sprintf("Workspace Name %q", id.WorkspaceName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Sql Pool Recoverable Database", segmentsStr) +} + +func (id SqlPoolRecoverableDatabaseId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Synapse/workspaces/%s/recoverableDatabases/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.WorkspaceName, id.RecoverableDatabaseName) +} + +// SqlPoolRecoverableDatabaseID parses a SqlPoolRecoverableDatabase ID into an SqlPoolRecoverableDatabaseId struct +func SqlPoolRecoverableDatabaseID(input string) (*SqlPoolRecoverableDatabaseId, error) { + id, err := resourceids.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := SqlPoolRecoverableDatabaseId{ + 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.WorkspaceName, err = id.PopSegment("workspaces"); err != nil { + return nil, err + } + if resourceId.RecoverableDatabaseName, err = id.PopSegment("recoverableDatabases"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/internal/services/synapse/parse/sql_pool_recoverable_database_test.go b/internal/services/synapse/parse/sql_pool_recoverable_database_test.go new file mode 100644 index 000000000000..270988615ef5 --- /dev/null +++ b/internal/services/synapse/parse/sql_pool_recoverable_database_test.go @@ -0,0 +1,128 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.Id = SqlPoolRecoverableDatabaseId{} + +func TestSqlPoolRecoverableDatabaseIDFormatter(t *testing.T) { + actual := NewSqlPoolRecoverableDatabaseID("12345678-1234-9876-4563-123456789012", "resGroup1", "workspace1", "database").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/recoverableDatabases/database" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestSqlPoolRecoverableDatabaseID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *SqlPoolRecoverableDatabaseId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Error: true, + }, + + { + // missing WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/", + Error: true, + }, + + { + // missing value for WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/", + Error: true, + }, + + { + // missing RecoverableDatabaseName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/", + Error: true, + }, + + { + // missing value for RecoverableDatabaseName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/recoverableDatabases/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/recoverableDatabases/database", + Expected: &SqlPoolRecoverableDatabaseId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "resGroup1", + WorkspaceName: "workspace1", + RecoverableDatabaseName: "database", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.SYNAPSE/WORKSPACES/WORKSPACE1/RECOVERABLEDATABASES/DATABASE", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := SqlPoolRecoverableDatabaseID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.WorkspaceName != v.Expected.WorkspaceName { + t.Fatalf("Expected %q but got %q for WorkspaceName", v.Expected.WorkspaceName, actual.WorkspaceName) + } + if actual.RecoverableDatabaseName != v.Expected.RecoverableDatabaseName { + t.Fatalf("Expected %q but got %q for RecoverableDatabaseName", v.Expected.RecoverableDatabaseName, actual.RecoverableDatabaseName) + } + } +} diff --git a/internal/services/synapse/resourceids.go b/internal/services/synapse/resourceids.go index d8df796954a3..7b45e6784ca4 100644 --- a/internal/services/synapse/resourceids.go +++ b/internal/services/synapse/resourceids.go @@ -9,6 +9,7 @@ package synapse //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SparkPool -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/bigDataPools/bigDataPool1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SqlPool -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/sqlPools/sqlPool1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SqlPoolExtendedAuditingPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/sqlPools/sqlPool1/extendedAuditingSettings/default +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SqlPoolRecoverableDatabase -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/recoverableDatabases/database //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SqlPoolSecurityAlertPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/sqlPools/sqlPool1/securityAlertPolicies/Default //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SqlPoolVulnerabilityAssessment -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/sqlPools/sqlPool1/vulnerabilityAssessments/default //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=SqlPoolWorkloadClassifier -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/sqlPools/sqlPool1/workloadGroups/workloadGroup1/workloadClassifiers/workloadClassifier1 diff --git a/internal/services/synapse/synapse_sql_pool_resource.go b/internal/services/synapse/synapse_sql_pool_resource.go index a4046c4cf42b..534fde4594b5 100644 --- a/internal/services/synapse/synapse_sql_pool_resource.go +++ b/internal/services/synapse/synapse_sql_pool_resource.go @@ -118,7 +118,9 @@ func resourceSynapseSqlPool() *pluginsdk.Resource { ConflictsWith: []string{"restore"}, ValidateFunc: validation.Any( validate.SqlPoolID, + validate.SqlPoolRecoverableDatabaseID, mssqlValidate.DatabaseID, + mssqlValidate.RecoverableDatabaseID, ), }, @@ -155,6 +157,12 @@ func resourceSynapseSqlPool() *pluginsdk.Resource { Optional: true, }, + "geo_backup_policy_enabled": { + Type: pluginsdk.TypeBool, + Default: true, + Optional: true, + }, + "tags": tags.Schema(), }, } @@ -164,6 +172,7 @@ func resourceSynapseSqlPoolCreate(d *pluginsdk.ResourceData, meta interface{}) e sqlClient := meta.(*clients.Client).Synapse.SqlPoolClient sqlPTDEClient := meta.(*clients.Client).Synapse.SqlPoolTransparentDataEncryptionClient workspaceClient := meta.(*clients.Client).Synapse.WorkspaceClient + geoBackUpClient := meta.(*clients.Client).Synapse.SqlPoolGeoBackupPoliciesClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -185,7 +194,7 @@ func resourceSynapseSqlPoolCreate(d *pluginsdk.ResourceData, meta interface{}) e workspace, err := workspaceClient.Get(ctx, workspaceId.ResourceGroup, workspaceId.Name) if err != nil { - return fmt.Errorf("retrieving Synapse Workspace %q (Resource Group %q): %+v", workspaceId.Name, workspaceId.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", workspaceId, err) } mode := d.Get("create_mode").(string) @@ -243,6 +252,18 @@ func resourceSynapseSqlPoolCreate(d *pluginsdk.ResourceData, meta interface{}) e } } + if !d.Get("geo_backup_policy_enabled").(bool) { + geoBackupParams := synapse.GeoBackupPolicy{ + GeoBackupPolicyProperties: &synapse.GeoBackupPolicyProperties{ + State: synapse.GeoBackupPolicyStateDisabled, + }, + } + + if _, err := geoBackUpClient.CreateOrUpdate(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, geoBackupParams); err != nil { + return fmt.Errorf("setting `geo_backup_policy_enabled`: %+v", err) + } + } + d.SetId(id.ID()) return resourceSynapseSqlPoolRead(d, meta) } @@ -250,6 +271,7 @@ func resourceSynapseSqlPoolCreate(d *pluginsdk.ResourceData, meta interface{}) e func resourceSynapseSqlPoolUpdate(d *pluginsdk.ResourceData, meta interface{}) error { sqlClient := meta.(*clients.Client).Synapse.SqlPoolClient sqlPTDEClient := meta.(*clients.Client).Synapse.SqlPoolTransparentDataEncryptionClient + geoBackUpClient := meta.(*clients.Client).Synapse.SqlPoolGeoBackupPoliciesClient ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -274,6 +296,22 @@ func resourceSynapseSqlPoolUpdate(d *pluginsdk.ResourceData, meta interface{}) e } } + if d.HasChange("geo_backup_policy_enabled") { + state := synapse.GeoBackupPolicyStateEnabled + if !d.Get("geo_backup_policy_enabled").(bool) { + state = synapse.GeoBackupPolicyStateDisabled + } + + geoBackupParams := synapse.GeoBackupPolicy{ + GeoBackupPolicyProperties: &synapse.GeoBackupPolicyProperties{ + State: state, + }, + } + if _, err := geoBackUpClient.CreateOrUpdate(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, geoBackupParams); err != nil { + return fmt.Errorf("updating `geo_backup_policy_enabled`: %+v", err) + } + } + if d.HasChanges("sku_name", "tags") { sqlPoolInfo := synapse.SQLPoolPatchInfo{ Sku: &synapse.Sku{ @@ -316,6 +354,7 @@ func resourceSynapseSqlPoolUpdate(d *pluginsdk.ResourceData, meta interface{}) e func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) error { sqlClient := meta.(*clients.Client).Synapse.SqlPoolClient sqlPTDEClient := meta.(*clients.Client).Synapse.SqlPoolTransparentDataEncryptionClient + geoBackUpClient := meta.(*clients.Client).Synapse.SqlPoolGeoBackupPoliciesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -337,7 +376,12 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err transparentDataEncryption, err := sqlPTDEClient.Get(ctx, id.ResourceGroup, id.WorkspaceName, id.Name) if err != nil { - return fmt.Errorf("retrieving Transparent Data Encryption settings of Synapse SqlPool %q (Workspace %q / Resource Group %q): %+v", id.Name, id.WorkspaceName, id.ResourceGroup, err) + return fmt.Errorf("retrieving Transparent Data Encryption settings of %s: %+v", *id, err) + } + + geoBackupPolicy, err := geoBackUpClient.Get(ctx, id.ResourceGroup, id.WorkspaceName, id.Name) + if err != nil { + return fmt.Errorf("retrieving Geo Backup Policy of %s: %+v", *id, err) } workspaceId := parse.NewWorkspaceID(id.SubscriptionId, id.ResourceGroup, id.WorkspaceName).ID() @@ -349,8 +393,15 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err if props := resp.SQLPoolResourceProperties; props != nil { d.Set("collation", props.Collation) } - if props := transparentDataEncryption.TransparentDataEncryptionProperties; props != nil { - d.Set("data_encrypted", props.Status == synapse.TransparentDataEncryptionStatusEnabled) + + geoBackupEnabled := true + if geoBackupProps := geoBackupPolicy.GeoBackupPolicyProperties; geoBackupProps != nil { + geoBackupEnabled = geoBackupProps.State == synapse.GeoBackupPolicyStateEnabled + } + d.Set("geo_backup_policy_enabled", geoBackupEnabled) + + if tdeProps := transparentDataEncryption.TransparentDataEncryptionProperties; tdeProps != nil { + d.Set("data_encrypted", tdeProps.Status == synapse.TransparentDataEncryptionStatusEnabled) } // whole "restore" block is not returned. to avoid conflict, so set it from the old state @@ -371,11 +422,11 @@ func resourceSynapseSqlPoolDelete(d *pluginsdk.ResourceData, meta interface{}) e future, err := sqlClient.Delete(ctx, id.ResourceGroup, id.WorkspaceName, id.Name) if err != nil { - return fmt.Errorf("deleting Synapse Sql Pool %q (Workspace %q / Resource Group %q): %+v", id.Name, id.WorkspaceName, id.ResourceGroup, err) + return fmt.Errorf("deleting %s: %+v", *id, err) } if err = future.WaitForCompletionRef(ctx, sqlClient.Client); err != nil { - return fmt.Errorf("waiting for deletion of Synapse Sql Pool %q (Workspace %q / Resource Group %q): %+v", id.Name, id.WorkspaceName, id.ResourceGroup, err) + return fmt.Errorf("waiting for deletion of %s: %+v", *id, err) } return nil } diff --git a/internal/services/synapse/synapse_sql_pool_resource_test.go b/internal/services/synapse/synapse_sql_pool_resource_test.go index 089f410d5355..fbbe373fdd48 100644 --- a/internal/services/synapse/synapse_sql_pool_resource_test.go +++ b/internal/services/synapse/synapse_sql_pool_resource_test.go @@ -104,6 +104,38 @@ func TestAccSynapseSqlPool_update(t *testing.T) { }) } +func TestAccSynapseSqlPool_geoBackupPolicy(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_synapse_sql_pool", "test") + r := SynapseSqlPoolResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.geoBackupDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("geo_backup_policy_enabled").HasValue("false"), + ), + }, + data.ImportStep(), + { + Config: r.geoBackupEnabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("geo_backup_policy_enabled").HasValue("true"), + ), + }, + data.ImportStep(), + { + Config: r.geoBackupDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("geo_backup_policy_enabled").HasValue("false"), + ), + }, + data.ImportStep(), + }) +} + func (r SynapseSqlPoolResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.SqlPoolID(state.ID) if err != nil { @@ -229,3 +261,41 @@ resource "azurerm_synapse_workspace" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) } + +func (r SynapseSqlPoolResource) geoBackupDisabled(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_synapse_sql_pool" "test" { + name = "acctestSP%s" + synapse_workspace_id = azurerm_synapse_workspace.test.id + sku_name = "DW100c" + create_mode = "Default" + geo_backup_policy_enabled = false +} +`, template, data.RandomString) +} + +func (r SynapseSqlPoolResource) geoBackupEnabled(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_synapse_sql_pool" "test" { + name = "acctestSP%s" + synapse_workspace_id = azurerm_synapse_workspace.test.id + sku_name = "DW100c" + create_mode = "Default" + geo_backup_policy_enabled = true +} +`, template, data.RandomString) +} diff --git a/internal/services/synapse/validate/sql_pool_recoverable_database_id.go b/internal/services/synapse/validate/sql_pool_recoverable_database_id.go new file mode 100644 index 000000000000..eb15671980c3 --- /dev/null +++ b/internal/services/synapse/validate/sql_pool_recoverable_database_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/hashicorp/terraform-provider-azurerm/internal/services/synapse/parse" +) + +func SqlPoolRecoverableDatabaseID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := parse.SqlPoolRecoverableDatabaseID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/synapse/validate/sql_pool_recoverable_database_id_test.go b/internal/services/synapse/validate/sql_pool_recoverable_database_id_test.go new file mode 100644 index 000000000000..437e0fe70177 --- /dev/null +++ b/internal/services/synapse/validate/sql_pool_recoverable_database_id_test.go @@ -0,0 +1,88 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestSqlPoolRecoverableDatabaseID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Valid: false, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Valid: false, + }, + + { + // missing WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/", + Valid: false, + }, + + { + // missing value for WorkspaceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/", + Valid: false, + }, + + { + // missing RecoverableDatabaseName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/", + Valid: false, + }, + + { + // missing value for RecoverableDatabaseName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/recoverableDatabases/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Synapse/workspaces/workspace1/recoverableDatabases/database", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.SYNAPSE/WORKSPACES/WORKSPACE1/RECOVERABLEDATABASES/DATABASE", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := SqlPoolRecoverableDatabaseID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/website/docs/r/synapse_sql_pool.html.markdown b/website/docs/r/synapse_sql_pool.html.markdown index 710f9f8d6637..a6bd16603368 100644 --- a/website/docs/r/synapse_sql_pool.html.markdown +++ b/website/docs/r/synapse_sql_pool.html.markdown @@ -73,6 +73,8 @@ The following arguments are supported: * `restore` - (Optional) A `restore` block as defined below. only applicable when `create_mode` is set to `PointInTimeRestore`. Changing this forces a new resource to be created. +* `geo_backup_policy_enabled` - (Optional) Is geo-backup policy enabled? Defaults to `true`. + * `tags` - (Optional) A mapping of tags which should be assigned to the Synapse SQL Pool. ---