Skip to content

Commit

Permalink
including #24054
Browse files Browse the repository at this point in the history
* Initial Check-in...

* Checking-in progress...

* Address PR comments...

* Add test cases and expose in data source...

* Fix data source and tests...

* mod tidy for elasticpools...

* Upgrade elaticpool to 2023-02-01-preview...

* Fix lint errors?

* Expose enclave_type for ElasticPool...

* Fix lint errors...

* Fix lint error...

* Lint error take 3...

* Move enclave sku validation to custom diff...

* Update test cases for enclave type...

* Fix lint errors...

* Fix test cases...

* Fix auditing policy import test...

* Address PR comments...
  • Loading branch information
WodansSon authored Dec 7, 2023
1 parent b40cc20 commit c23011e
Show file tree
Hide file tree
Showing 34 changed files with 1,792 additions and 362 deletions.
48 changes: 23 additions & 25 deletions internal/services/mssql/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/backupshorttermretentionpolicies"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/databases"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/databasesecurityalertpolicies"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/elasticpools"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/geobackuppolicies"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/longtermretentionpolicies"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/replicationlinks"
Expand All @@ -32,8 +33,7 @@ type Client struct {
DatabaseSecurityAlertPoliciesClient *databasesecurityalertpolicies.DatabaseSecurityAlertPoliciesClient
DatabaseVulnerabilityAssessmentRuleBaselinesClient *sql.DatabaseVulnerabilityAssessmentRuleBaselinesClient
DatabasesClient *databases.DatabasesClient
LegacyDatabasesClient *sql.DatabasesClient
ElasticPoolsClient *sql.ElasticPoolsClient
ElasticPoolsClient *elasticpools.ElasticPoolsClient
EncryptionProtectorClient *sql.EncryptionProtectorsClient
FailoverGroupsClient *sql.FailoverGroupsClient
FirewallRulesClient *sql.FirewallRulesClient
Expand Down Expand Up @@ -88,12 +88,11 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
}
o.Configure(databasesClient.Client, o.Authorizers.ResourceManager)

// NOTE: Remove once Azure Bug 2805551 ReplicationLink API ListByDatabase missed subsubcriptionId in partnerDatabaseId in response body has been released
legacyDatabasesClient := sql.NewDatabasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&legacyDatabasesClient.Client, o.ResourceManagerAuthorizer)

elasticPoolsClient := sql.NewElasticPoolsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&elasticPoolsClient.Client, o.ResourceManagerAuthorizer)
elasticPoolsClient, err := elasticpools.NewElasticPoolsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building ElasticPools Client: %+v", err)
}
o.Configure(elasticPoolsClient.Client, o.Authorizers.ResourceManager)

encryptionProtectorClient := sql.NewEncryptionProtectorsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&encryptionProtectorClient.Client, o.ResourceManagerAuthorizer)
Expand Down Expand Up @@ -211,32 +210,31 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
// Clients using the Track1 SDK which need to be gradually switched over to `hashicorp/go-azure-sdk`
DatabaseExtendedBlobAuditingPoliciesClient: &databaseExtendedBlobAuditingPoliciesClient,
DatabaseVulnerabilityAssessmentRuleBaselinesClient: &databaseVulnerabilityAssessmentRuleBaselinesClient,
ElasticPoolsClient: &elasticPoolsClient,
EncryptionProtectorClient: &encryptionProtectorClient,
FailoverGroupsClient: &failoverGroupsClient,
FirewallRulesClient: &firewallRulesClient,
JobAgentsClient: &jobAgentsClient,
JobCredentialsClient: &jobCredentialsClient,
OutboundFirewallRulesClient: &outboundFirewallRulesClient,
ServerDNSAliasClient: &serverDNSAliasClient,
ServerDevOpsAuditSettingsClient: &serverDevOpsAuditSettingsClient,
ServerExtendedBlobAuditingPoliciesClient: &serverExtendedBlobAuditingPoliciesClient,
ServerKeysClient: &serverKeysClient,
ServerVulnerabilityAssessmentsClient: &serverVulnerabilityAssessmentsClient,
VirtualMachinesAvailabilityGroupListenersClient: &virtualMachinesAvailabilityGroupListenersClient,
VirtualMachinesClient: &virtualMachinesClient,
VirtualMachineGroupsClient: &virtualMachineGroupsClient,
VirtualNetworkRulesClient: &virtualNetworkRulesClient,
EncryptionProtectorClient: &encryptionProtectorClient,
FailoverGroupsClient: &failoverGroupsClient,
FirewallRulesClient: &firewallRulesClient,
JobAgentsClient: &jobAgentsClient,
JobCredentialsClient: &jobCredentialsClient,
OutboundFirewallRulesClient: &outboundFirewallRulesClient,
ServerDNSAliasClient: &serverDNSAliasClient,
ServerDevOpsAuditSettingsClient: &serverDevOpsAuditSettingsClient,
ServerExtendedBlobAuditingPoliciesClient: &serverExtendedBlobAuditingPoliciesClient,
ServerKeysClient: &serverKeysClient,
ServerVulnerabilityAssessmentsClient: &serverVulnerabilityAssessmentsClient,
VirtualMachinesAvailabilityGroupListenersClient: &virtualMachinesAvailabilityGroupListenersClient,
VirtualMachinesClient: &virtualMachinesClient,
VirtualMachineGroupsClient: &virtualMachineGroupsClient,
VirtualNetworkRulesClient: &virtualNetworkRulesClient,

// Legacy Clients
LegacyDatabasesClient: &legacyDatabasesClient,
LegacyServerSecurityAlertPoliciesClient: &legacyServerSecurityAlertPoliciesClient,
LegacyReplicationLinksClient: &legacyReplicationLinksClient,

// 2023-02-01-preview Clients
BackupShortTermRetentionPoliciesClient: backupShortTermRetentionPoliciesClient,
DatabasesClient: databasesClient,
DatabaseSecurityAlertPoliciesClient: databaseSecurityAlertPoliciesClient,
ElasticPoolsClient: elasticPoolsClient,
GeoBackupPoliciesClient: geoBackupPoliciesClient,
LongTermRetentionPoliciesClient: longTermRetentionPoliciesClient,
ReplicationLinksClient: replicationLinksClient,
Expand Down
31 changes: 21 additions & 10 deletions internal/services/mssql/helper/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ import (
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-06-01/resources" // nolint: staticcheck
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-helpers/resourcemanager/location"
"github.com/hashicorp/go-azure-sdk/resource-manager/sql/2023-02-01-preview/databases"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/parse"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

// FindDatabaseReplicationPartners looks for partner databases having one of the specified replication roles, by
// reading any replication links then attempting to discover and match the corresponding server/database resources for
// the other end of the link.
func FindDatabaseReplicationPartners(ctx context.Context, databasesClient *sql.DatabasesClient, replicationLinksClient *sql.ReplicationLinksClient, resourcesClient *resources.Client, id commonids.SqlDatabaseId, rolesToFind []sql.ReplicationRole) ([]sql.Database, error) {
var partnerDatabases []sql.Database
func FindDatabaseReplicationPartners(ctx context.Context, databasesClient *databases.DatabasesClient, replicationLinksClient *sql.ReplicationLinksClient, resourcesClient *resources.Client, id commonids.SqlDatabaseId, primaryEnclaveType databases.AlwaysEncryptedEnclaveType, rolesToFind []sql.ReplicationRole) ([]databases.Database, error) {
var partnerDatabases []databases.Database

matchesRole := func(role sql.ReplicationRole) bool {
for _, r := range rolesToFind {
Expand All @@ -35,6 +36,7 @@ func FindDatabaseReplicationPartners(ctx context.Context, databasesClient *sql.D
if err != nil {
return nil, fmt.Errorf("reading Replication Links for %s: %+v", id, err)
}

if linksIterator.Response().IsEmpty() {
return nil, fmt.Errorf("reading Replication Links for %s: response was empty", id)
}
Expand All @@ -44,6 +46,7 @@ func FindDatabaseReplicationPartners(ctx context.Context, databasesClient *sql.D
log.Printf("[INFO] Replication Link Properties was nil for %s", id)
continue
}

if linkProps.PartnerLocation == nil || linkProps.PartnerServer == nil || linkProps.PartnerDatabase == nil {
log.Printf("[INFO] Replication Link Properties was invalid for %s", id)
continue
Expand Down Expand Up @@ -93,17 +96,25 @@ func FindDatabaseReplicationPartners(ctx context.Context, databasesClient *sql.D
// If the database has a replication link for the specified role, we'll consider it a partner of this database if the location is the same as expected partner
if matchesRole(linkPropsPossiblePartner.Role) {
partnerDatabaseId := commonids.NewSqlDatabaseID(partnerServerId.SubscriptionId, partnerServerId.ResourceGroup, partnerServerId.Name, *linkProps.PartnerDatabase)
partnerDatabase, err := databasesClient.Get(ctx, partnerDatabaseId.ResourceGroupName, partnerDatabaseId.ServerName, partnerDatabaseId.DatabaseName)
partnerDatabase, err := databasesClient.Get(ctx, partnerDatabaseId, databases.DefaultGetOperationOptions())
if err != nil {
return nil, fmt.Errorf("retrieving Partner %s: %+v", partnerDatabaseId, err)
}
if location.NormalizeNilable(partnerDatabase.Location) != location.Normalize(*linkProps.PartnerLocation) {
log.Printf("[INFO] Mismatch of possible Partner Database based on location (%s vs %s) for %s", location.NormalizeNilable(partnerDatabase.Location), location.Normalize(*linkProps.PartnerLocation), id)
continue
}
if partnerDatabase.ID != nil {
log.Printf("[INFO] Found Partner %s", partnerDatabaseId)
partnerDatabases = append(partnerDatabases, partnerDatabase)

if partnerDatabase := partnerDatabase.Model; partnerDatabase != nil {
if location.Normalize(partnerDatabase.Location) != location.Normalize(*linkProps.PartnerLocation) {
log.Printf("[INFO] Mismatch of possible Partner Database based on location (%s vs %s) for %s", location.Normalize(partnerDatabase.Location), location.Normalize(*linkProps.PartnerLocation), id)
continue
}

if partnerDatabase.Id != nil && partnerDatabase.Properties != nil && partnerDatabase.Properties.PreferredEnclaveType != nil {
if primaryEnclaveType == *partnerDatabase.Properties.PreferredEnclaveType {
log.Printf("[INFO] Found Partner %s", partnerDatabaseId)
partnerDatabases = append(partnerDatabases, *partnerDatabase)
} else {
log.Printf("[INFO] Mismatch of possible Partner Database based on enclave type (%s vs %s) for %s", string(primaryEnclaveType), string(*partnerDatabase.Properties.PreferredEnclaveType), id)
}
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion internal/services/mssql/helper/elasticpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ func MSSQLElasticPoolValidateSKU(diff *pluginsdk.ResourceDiff) error {
maxSizeGb := diff.Get("max_size_gb")
minCapacity := diff.Get("per_database_settings.0.min_capacity")
maxCapacity := diff.Get("per_database_settings.0.max_capacity")
enclaveType := diff.Get("enclave_type")

s := sku{
Name: name.(string),
Expand Down Expand Up @@ -279,7 +280,12 @@ func MSSQLElasticPoolValidateSKU(diff *pluginsdk.ResourceDiff) error {
return fmt.Errorf("mismatch between SKU name '%s' and family '%s', expected '%s'", s.Name, s.Family, getFamilyFromName(s))
}

// get max GB and do validation based on SKU type
// Validate if 'enclave_type' is valid for this SKU type
if enclaveType != "" && strings.Contains(strings.ToLower(s.Name), "_dc") {
return fmt.Errorf("virtualization based security (VBS) enclaves are not supported for the %q sku", s.Name)
}

// Get max GB and do validation based on SKU type
if s.SkuType == DTU {
s.MaxAllowedGB = getDTUMaxGB[strings.ToLower(s.Tier)][s.Capacity]
return doDTUSKUValidation(s)
Expand Down
11 changes: 11 additions & 0 deletions internal/services/mssql/mssql_database_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ func dataSourceMsSqlDatabase() *pluginsdk.Resource {
Computed: true,
},

"enclave_type": {
Type: pluginsdk.TypeString,
Computed: true,
},

"tags": commonschema.TagsDataSource(),
},
}
Expand Down Expand Up @@ -138,6 +143,12 @@ func dataSourceMsSqlDatabaseRead(d *pluginsdk.ResourceData, meta interface{}) er
}
d.Set("read_scale", readScale == databases.DatabaseReadScaleEnabled)

enclaveType := ""
if props.PreferredEnclaveType != nil && *props.PreferredEnclaveType != databases.AlwaysEncryptedEnclaveTypeDefault {
enclaveType = string(*props.PreferredEnclaveType)
}
d.Set("enclave_type", enclaveType)

storageAccountType := string(databases.BackupStorageRedundancyGeo)
if props.CurrentBackupStorageRedundancy != nil {
storageAccountType = string(pointer.From(props.CurrentBackupStorageRedundancy))
Expand Down
2 changes: 2 additions & 0 deletions internal/services/mssql/mssql_database_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestAccDataSourceMsSqlDatabase_basic(t *testing.T) {
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("name").HasValue(fmt.Sprintf("acctest-db-%d", data.RandomInteger)),
check.That(data.ResourceName).Key("server_id").Exists(),
check.That(data.ResourceName).Key("enclave_type").IsEmpty(),
),
},
})
Expand All @@ -42,6 +43,7 @@ func TestAccDataSourceMsSqlDatabase_complete(t *testing.T) {
check.That(data.ResourceName).Key("sku_name").HasValue("GP_Gen5_2"),
check.That(data.ResourceName).Key("tags.%").HasValue("1"),
check.That(data.ResourceName).Key("tags.ENV").HasValue("Test"),
check.That(data.ResourceName).Key("enclave_type").HasValue("VBS"),
),
},
})
Expand Down
Loading

0 comments on commit c23011e

Please sign in to comment.