Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_mssql_database/azurerm_mssql_elasticpool - add support for enclave_type field #24054

Merged
merged 19 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading