From 1a000b569eddb9677ec2f8647ceb811005dcfa8e Mon Sep 17 00:00:00 2001 From: Catriona Date: Thu, 15 Dec 2022 14:18:36 +0000 Subject: [PATCH 1/6] add recoverableDatabaseId --- 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 | 27 ++++ .../sql_pool_recoverable_database_id.go | 23 ++++ .../sql_pool_recoverable_database_id_test.go | 88 ++++++++++++ 7 files changed, 347 insertions(+) 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..65fd8fb4e5f4 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, ), }, @@ -164,6 +166,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() @@ -243,6 +246,17 @@ func resourceSynapseSqlPoolCreate(d *pluginsdk.ResourceData, meta interface{}) e } } + /* geoBackupParams := synapse.GeoBackupPolicy{ + Response: autorest.Response{}, + GeoBackupPolicyProperties: &synapse.GeoBackupPolicyProperties{ + State: synapse.GeoBackupPolicyStateEnabled, + }, + } + + if _, err := geoBackUpClient.CreateOrUpdate(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, geoBackupParams); err != nil { + return err + }*/ + d.SetId(id.ID()) return resourceSynapseSqlPoolRead(d, meta) } @@ -348,6 +362,19 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err } if props := resp.SQLPoolResourceProperties; props != nil { d.Set("collation", props.Collation) + + if props.RecoverableDatabaseID != nil { + recoverableDatabaseId := *props.RecoverableDatabaseID + if recoverableDatabaseId != "" { + id, err := parse.SqlPoolRecoverableDatabaseID(*props.RecoverableDatabaseID) + recoverableDatabaseId = id.ID() + if err != nil { + return err + } + } + d.Set("recoverable_database_id", recoverableDatabaseId) + } + } if props := transparentDataEncryption.TransparentDataEncryptionProperties; props != nil { d.Set("data_encrypted", props.Status == synapse.TransparentDataEncryptionStatusEnabled) 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) + } + } +} From c10ca854b93e8e8053ec1b86844d6892798e42ab Mon Sep 17 00:00:00 2001 From: Catriona Date: Thu, 15 Dec 2022 17:10:03 +0000 Subject: [PATCH 2/6] add recoverableDatabaseId --- internal/services/synapse/synapse_sql_pool_resource.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/services/synapse/synapse_sql_pool_resource.go b/internal/services/synapse/synapse_sql_pool_resource.go index 65fd8fb4e5f4..b9927c420871 100644 --- a/internal/services/synapse/synapse_sql_pool_resource.go +++ b/internal/services/synapse/synapse_sql_pool_resource.go @@ -363,8 +363,9 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err if props := resp.SQLPoolResourceProperties; props != nil { d.Set("collation", props.Collation) + recoverableDatabaseId := "" if props.RecoverableDatabaseID != nil { - recoverableDatabaseId := *props.RecoverableDatabaseID + recoverableDatabaseId = *props.RecoverableDatabaseID if recoverableDatabaseId != "" { id, err := parse.SqlPoolRecoverableDatabaseID(*props.RecoverableDatabaseID) recoverableDatabaseId = id.ID() @@ -372,9 +373,8 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err return err } } - d.Set("recoverable_database_id", recoverableDatabaseId) } - + d.Set("recoverable_database_id", recoverableDatabaseId) } if props := transparentDataEncryption.TransparentDataEncryptionProperties; props != nil { d.Set("data_encrypted", props.Status == synapse.TransparentDataEncryptionStatusEnabled) From 50ee6ceff92295b8de101795a0166d3b95563232 Mon Sep 17 00:00:00 2001 From: Catriona Date: Fri, 16 Dec 2022 17:28:05 +0000 Subject: [PATCH 3/6] set recovery_database_id and add geo_backup_policy_enabled property --- .../synapse/synapse_sql_pool_resource.go | 70 ++++++++++++++----- .../synapse/synapse_sql_pool_resource_test.go | 70 +++++++++++++++++++ 2 files changed, 122 insertions(+), 18 deletions(-) diff --git a/internal/services/synapse/synapse_sql_pool_resource.go b/internal/services/synapse/synapse_sql_pool_resource.go index b9927c420871..2eff8fdbf710 100644 --- a/internal/services/synapse/synapse_sql_pool_resource.go +++ b/internal/services/synapse/synapse_sql_pool_resource.go @@ -157,6 +157,12 @@ func resourceSynapseSqlPool() *pluginsdk.Resource { Optional: true, }, + "geo_backup_policy_enabled": { + Type: pluginsdk.TypeBool, + Default: true, + Optional: true, + }, + "tags": tags.Schema(), }, } @@ -166,7 +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 + geoBackUpClient := meta.(*clients.Client).Synapse.SqlPoolGeoBackupPoliciesClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -246,16 +252,17 @@ func resourceSynapseSqlPoolCreate(d *pluginsdk.ResourceData, meta interface{}) e } } - /* geoBackupParams := synapse.GeoBackupPolicy{ - Response: autorest.Response{}, + if !d.Get("geo_backup_policy_enabled").(bool) { + geoBackupParams := synapse.GeoBackupPolicy{ GeoBackupPolicyProperties: &synapse.GeoBackupPolicyProperties{ - State: synapse.GeoBackupPolicyStateEnabled, + State: synapse.GeoBackupPolicyStateDisabled, }, } if _, err := geoBackUpClient.CreateOrUpdate(ctx, id.ResourceGroup, id.WorkspaceName, id.Name, geoBackupParams); err != nil { - return err - }*/ + return fmt.Errorf("setting `geo_backup_policy_enabled`: %+v", err) + } + } d.SetId(id.ID()) return resourceSynapseSqlPoolRead(d, meta) @@ -264,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() @@ -288,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{ @@ -330,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() @@ -351,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() @@ -364,20 +394,24 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err d.Set("collation", props.Collation) recoverableDatabaseId := "" - if props.RecoverableDatabaseID != nil { - recoverableDatabaseId = *props.RecoverableDatabaseID - if recoverableDatabaseId != "" { - id, err := parse.SqlPoolRecoverableDatabaseID(*props.RecoverableDatabaseID) - recoverableDatabaseId = id.ID() - if err != nil { - return err - } + if props.RecoverableDatabaseID != nil && *props.RecoverableDatabaseID != "" { + id, err := parse.SqlPoolRecoverableDatabaseID(*props.RecoverableDatabaseID) + if err != nil { + return err } + recoverableDatabaseId = id.ID() } - d.Set("recoverable_database_id", recoverableDatabaseId) + d.Set("recovery_database_id", recoverableDatabaseId) } - 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 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) +} From 943a1d565cd1d5648acfc7afef2fefb62ac6878b Mon Sep 17 00:00:00 2001 From: Catriona Date: Wed, 4 Jan 2023 12:57:25 +0000 Subject: [PATCH 4/6] simplify error message --- internal/services/synapse/synapse_sql_pool_resource.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/services/synapse/synapse_sql_pool_resource.go b/internal/services/synapse/synapse_sql_pool_resource.go index 2eff8fdbf710..b352ad572cd5 100644 --- a/internal/services/synapse/synapse_sql_pool_resource.go +++ b/internal/services/synapse/synapse_sql_pool_resource.go @@ -432,11 +432,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 } From b76e78bc03bdc171600e763aebc5c5cca4c60152 Mon Sep 17 00:00:00 2001 From: Catriona Date: Fri, 13 Jan 2023 14:57:43 +0000 Subject: [PATCH 5/6] remove recovery_database_id from read and add docs --- .../services/synapse/synapse_sql_pool_resource.go | 12 +----------- website/docs/r/synapse_sql_pool.html.markdown | 2 ++ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/internal/services/synapse/synapse_sql_pool_resource.go b/internal/services/synapse/synapse_sql_pool_resource.go index b352ad572cd5..534fde4594b5 100644 --- a/internal/services/synapse/synapse_sql_pool_resource.go +++ b/internal/services/synapse/synapse_sql_pool_resource.go @@ -194,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) @@ -392,16 +392,6 @@ func resourceSynapseSqlPoolRead(d *pluginsdk.ResourceData, meta interface{}) err } if props := resp.SQLPoolResourceProperties; props != nil { d.Set("collation", props.Collation) - - recoverableDatabaseId := "" - if props.RecoverableDatabaseID != nil && *props.RecoverableDatabaseID != "" { - id, err := parse.SqlPoolRecoverableDatabaseID(*props.RecoverableDatabaseID) - if err != nil { - return err - } - recoverableDatabaseId = id.ID() - } - d.Set("recovery_database_id", recoverableDatabaseId) } geoBackupEnabled := true diff --git a/website/docs/r/synapse_sql_pool.html.markdown b/website/docs/r/synapse_sql_pool.html.markdown index a5d620e11acf..115ec196cbfd 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`. +* `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. --- From fc1a237df95b0236dc19cebfcc274d76326f1b0f Mon Sep 17 00:00:00 2001 From: Catriona Date: Fri, 13 Jan 2023 15:14:11 +0000 Subject: [PATCH 6/6] docs --- website/docs/r/synapse_sql_pool.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/synapse_sql_pool.html.markdown b/website/docs/r/synapse_sql_pool.html.markdown index 115ec196cbfd..7ccbed1bd8d2 100644 --- a/website/docs/r/synapse_sql_pool.html.markdown +++ b/website/docs/r/synapse_sql_pool.html.markdown @@ -67,7 +67,7 @@ The following arguments are supported: * `collation` - (Optional) The name of the collation to use with this pool, only applicable when `create_mode` is set to `Default`. Azure default is `SQL_LATIN1_GENERAL_CP1_CI_AS`. Changing this forces a new resource to be created. -* `data_encrypted` - (Optional) Is transparent data encryption enabled? Defaults to `false`. +* `data_encrypted` - (Optional) Is transparent data encryption enabled? * `recovery_database_id` - (Optional) The ID of the Synapse SQL Pool or SQL Database which is to back up, only applicable when `create_mode` is set to `Recovery`. Changing this forces a new Synapse SQL Pool to be created.