diff --git a/internal/services/cosmos/client/client.go b/internal/services/cosmos/client/client.go index 569ddde19ce8..a2da051bd050 100644 --- a/internal/services/cosmos/client/client.go +++ b/internal/services/cosmos/client/client.go @@ -19,29 +19,28 @@ import ( ) type Client struct { + ClustersClient *clusters.ClustersClient + ConfigurationsClient *configurations.ConfigurationsClient + CosmosDBClient *cosmosdb.CosmosDBClient + FirewallRulesClient *firewallrules.FirewallRulesClient + ManagedCassandraClient *managedcassandras.ManagedCassandrasClient + MongoRBACClient *mongorbacs.MongorbacsClient + RolesClient *roles.RolesClient + SqlDedicatedGatewayClient *sqldedicatedgateway.SqlDedicatedGatewayClient + + // Track 1 CassandraClient *documentdb.CassandraResourcesClient - ClustersClient *clusters.ClustersClient - ConfigurationsClient *configurations.ConfigurationsClient - CosmosDBClient *cosmosdb.CosmosDBClient DatabaseClient *documentdb.DatabaseAccountsClient - FirewallRulesClient *firewallrules.FirewallRulesClient GremlinClient *documentdb.GremlinResourcesClient - ManagedCassandraClient *managedcassandras.ManagedCassandrasClient MongoDbClient *documentdb.MongoDBResourcesClient - MongoRBACClient *mongorbacs.MongorbacsClient NotebookWorkspaceClient *documentdb.NotebookWorkspacesClient RestorableDatabaseAccountsClient *documentdb.RestorableDatabaseAccountsClient - RolesClient *roles.RolesClient - SqlDedicatedGatewayClient *sqldedicatedgateway.SqlDedicatedGatewayClient SqlClient *documentdb.SQLResourcesClient SqlResourceClient *documentdb.SQLResourcesClient TableClient *documentdb.TableResourcesClient } func NewClient(o *common.ClientOptions) (*Client, error) { - cassandraClient := documentdb.NewCassandraResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&cassandraClient.Client, o.ResourceManagerAuthorizer) - managedCassandraClient, err := managedcassandras.NewManagedCassandrasClientWithBaseURI(o.Environment.ResourceManager) if err != nil { return nil, fmt.Errorf("building Managed Cassandra client: %+v", err) @@ -66,33 +65,18 @@ func NewClient(o *common.ClientOptions) (*Client, error) { } o.Configure(cosmosdbClient.Client, o.Authorizers.ResourceManager) - databaseClient := documentdb.NewDatabaseAccountsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&databaseClient.Client, o.ResourceManagerAuthorizer) - firewallRulesClient, err := firewallrules.NewFirewallRulesClientWithBaseURI(o.Environment.ResourceManager) if err != nil { return nil, fmt.Errorf("building FirewallRules client: %+v", err) } o.Configure(firewallRulesClient.Client, o.Authorizers.ResourceManager) - gremlinClient := documentdb.NewGremlinResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&gremlinClient.Client, o.ResourceManagerAuthorizer) - - mongoDbClient := documentdb.NewMongoDBResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&mongoDbClient.Client, o.ResourceManagerAuthorizer) - mongorbacsClient, err := mongorbacs.NewMongorbacsClientWithBaseURI(o.Environment.ResourceManager) if err != nil { return nil, fmt.Errorf("building Mongorbacs client: %+v", err) } o.Configure(mongorbacsClient.Client, o.Authorizers.ResourceManager) - notebookWorkspaceClient := documentdb.NewNotebookWorkspacesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(¬ebookWorkspaceClient.Client, o.ResourceManagerAuthorizer) - - restorableDatabaseAccountsClient := documentdb.NewRestorableDatabaseAccountsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&restorableDatabaseAccountsClient.Client, o.ResourceManagerAuthorizer) - rolesClient, err := roles.NewRolesClientWithBaseURI(o.Environment.ResourceManager) if err != nil { return nil, fmt.Errorf("building Roles client: %+v", err) @@ -105,6 +89,25 @@ func NewClient(o *common.ClientOptions) (*Client, error) { } o.Configure(sqlDedicatedGatewayClient.Client, o.Authorizers.ResourceManager) + // Track 1 + cassandraClient := documentdb.NewCassandraResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&cassandraClient.Client, o.ResourceManagerAuthorizer) + + databaseClient := documentdb.NewDatabaseAccountsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&databaseClient.Client, o.ResourceManagerAuthorizer) + + gremlinClient := documentdb.NewGremlinResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&gremlinClient.Client, o.ResourceManagerAuthorizer) + + mongoDbClient := documentdb.NewMongoDBResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&mongoDbClient.Client, o.ResourceManagerAuthorizer) + + notebookWorkspaceClient := documentdb.NewNotebookWorkspacesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(¬ebookWorkspaceClient.Client, o.ResourceManagerAuthorizer) + + restorableDatabaseAccountsClient := documentdb.NewRestorableDatabaseAccountsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&restorableDatabaseAccountsClient.Client, o.ResourceManagerAuthorizer) + sqlClient := documentdb.NewSQLResourcesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&sqlClient.Client, o.ResourceManagerAuthorizer) @@ -115,20 +118,22 @@ func NewClient(o *common.ClientOptions) (*Client, error) { o.ConfigureClient(&tableClient.Client, o.ResourceManagerAuthorizer) return &Client{ + ManagedCassandraClient: managedCassandraClient, + ClustersClient: clustersClient, + ConfigurationsClient: configurationsClient, + CosmosDBClient: cosmosdbClient, + FirewallRulesClient: firewallRulesClient, + MongoRBACClient: mongorbacsClient, + RolesClient: rolesClient, + SqlDedicatedGatewayClient: sqlDedicatedGatewayClient, + + // Track 1 CassandraClient: &cassandraClient, - ManagedCassandraClient: managedCassandraClient, - ClustersClient: clustersClient, - ConfigurationsClient: configurationsClient, - CosmosDBClient: cosmosdbClient, DatabaseClient: &databaseClient, - FirewallRulesClient: firewallRulesClient, GremlinClient: &gremlinClient, MongoDbClient: &mongoDbClient, - MongoRBACClient: mongorbacsClient, NotebookWorkspaceClient: ¬ebookWorkspaceClient, RestorableDatabaseAccountsClient: &restorableDatabaseAccountsClient, - RolesClient: rolesClient, - SqlDedicatedGatewayClient: sqlDedicatedGatewayClient, SqlClient: &sqlClient, SqlResourceClient: &sqlResourceClient, TableClient: &tableClient, diff --git a/internal/services/cosmos/cosmosdb.go b/internal/services/cosmos/cosmosdb.go new file mode 100644 index 000000000000..ebd41d9fc627 --- /dev/null +++ b/internal/services/cosmos/cosmosdb.go @@ -0,0 +1,15 @@ +package cosmos + +import "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2021-10-15/documentdb" // nolint: staticcheck + +func isServerlessCapacityMode(accResp documentdb.DatabaseAccountGetResults) bool { + if props := accResp.DatabaseAccountGetProperties; props != nil && props.Capabilities != nil { + for _, v := range *props.Capabilities { + if v.Name != nil && *v.Name == "EnableServerless" { + return true + } + } + } + + return false +} diff --git a/internal/services/cosmos/cosmosdb_account_resource.go b/internal/services/cosmos/cosmosdb_account_resource.go index e0f084f9b0b8..00e6a4347718 100644 --- a/internal/services/cosmos/cosmosdb_account_resource.go +++ b/internal/services/cosmos/cosmosdb_account_resource.go @@ -14,11 +14,11 @@ import ( "strings" "time" - "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2021-10-15/documentdb" // nolint: staticcheck "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" + "github.com/hashicorp/go-azure-helpers/resourcemanager/keyvault" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" "github.com/hashicorp/go-azure-sdk/resource-manager/cosmosdb/2024-08-15/cosmosdb" @@ -26,15 +26,12 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/customermanagedkeys" "github.com/hashicorp/terraform-provider-azurerm/internal/features" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/services/cosmos/common" "github.com/hashicorp/terraform-provider-azurerm/internal/services/cosmos/migration" "github.com/hashicorp/terraform-provider-azurerm/internal/services/cosmos/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/cosmos/validate" - keyVaultSuppress "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/suppress" - keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" - managedHsmValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/managedhsm/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" @@ -342,20 +339,10 @@ func resourceCosmosDbAccount() *pluginsdk.Resource { }, "key_vault_key_id": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - DiffSuppressFunc: keyVaultSuppress.DiffSuppressIgnoreKeyVaultKeyVersion, - ValidateFunc: keyVaultValidate.VersionlessNestedItemId, - ConflictsWith: []string{"managed_hsm_key_id"}, - }, - - "managed_hsm_key_id": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: managedHsmValidate.ManagedHSMDataPlaneVersionlessKeyID, - ConflictsWith: []string{"key_vault_key_id"}, + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: keyvault.ValidateNestedItemID(keyvault.VersionTypeVersionless, keyvault.NestedItemTypeKey), }, "consistency_policy": { @@ -784,6 +771,49 @@ func resourceCosmosDbAccount() *pluginsdk.Resource { Default: string(cosmosdb.MinimalTlsVersionTlsOneTwo), ValidateFunc: validation.StringInSlice(cosmosdb.PossibleValuesForMinimalTlsVersion(), false), } + + resource.Schema["managed_hsm_key_id"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + Optional: true, + DiffSuppressOnRefresh: true, + DiffSuppressFunc: func(_, oldValue, newValue string, d *schema.ResourceData) bool { + if newValue == "" { + // If using `key_vault_key_id`, `managed_hsm_key_id` will also be set + // ignore diff if the 2 are equal. + raw := d.GetRawConfig().AsValueMap()["key_vault_key_id"] + if raw.IsKnown() && !raw.IsNull() { + return raw.AsString() == oldValue + } + } + + return false + }, + ForceNew: true, + ValidateFunc: keyvault.ValidateNestedItemID(keyvault.VersionTypeVersionless, keyvault.NestedItemTypeKey), + ConflictsWith: []string{"key_vault_key_id"}, + Deprecated: "`managed_hsm_key_id` has been deprecated in favour of `key_vault_key_id` and will be removed in v5.0 of the AzureRM provider", + } + + resource.Schema["key_vault_key_id"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: keyvault.ValidateNestedItemID(keyvault.VersionTypeVersionless, keyvault.NestedItemTypeKey), + DiffSuppressOnRefresh: true, + DiffSuppressFunc: func(_, oldValue, newValue string, d *schema.ResourceData) bool { + if newValue == "" { + // If using `managed_hsm_key_id`, `key_vault_key_id` will also be set + // ignore diff if the 2 are equal. + raw := d.GetRawConfig().AsValueMap()["managed_hsm_key_id"] + if raw.IsKnown() && !raw.IsNull() { + return raw.AsString() == oldValue + } + } + + return false + }, + ConflictsWith: []string{"managed_hsm_key_id"}, + } } return resource @@ -791,69 +821,37 @@ func resourceCosmosDbAccount() *pluginsdk.Resource { func resourceCosmosDbAccountCreate(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Cosmos.CosmosDBClient - databaseClient := meta.(*clients.Client).Cosmos.DatabaseClient - accountClient := meta.(*clients.Client).Account - subscriptionId := accountClient.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() - log.Printf("[INFO] Preparing arguments for AzureRM Cosmos DB Account creation") - id := cosmosdb.NewDatabaseAccountID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) - - if d.IsNewResource() { - existing, err := client.DatabaseAccountsGet(ctx, id) - if err != nil { - if !response.WasNotFound(existing.HttpResponse) { - return fmt.Errorf("checking for presence of existing %s: %s", id, err) - } - } + id := cosmosdb.NewDatabaseAccountID(meta.(*clients.Client).Account.SubscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + existing, err := client.DatabaseAccountsGet(ctx, id) + if err != nil { if !response.WasNotFound(existing.HttpResponse) { - return tf.ImportAsExistsError("azurerm_cosmosdb_account", id.ID()) + return fmt.Errorf("checking for presence of existing %s: %s", id, err) } } - location := location.Normalize(d.Get("location").(string)) - t := d.Get("tags").(map[string]interface{}) - kind := d.Get("kind").(string) - offerType := d.Get("offer_type").(string) - - ipRangeFilter := common.CosmosDBIpRangeFilterToIpRules(*utils.ExpandStringSlice(d.Get("ip_range_filter").(*pluginsdk.Set).List())) - isVirtualNetworkFilterEnabled := d.Get("is_virtual_network_filter_enabled").(bool) - - enableFreeTier := d.Get("free_tier_enabled").(bool) - enableAutomaticFailover := d.Get("automatic_failover_enabled").(bool) - enableMultipleWriteLocations := d.Get("multiple_write_locations_enabled").(bool) - - partitionMergeEnabled := d.Get("partition_merge_enabled").(bool) - burstCapacityEnabled := d.Get("burst_capacity_enabled").(bool) - enableAnalyticalStorage := d.Get("analytical_storage_enabled").(bool) - disableLocalAuthentication := d.Get("local_authentication_disabled").(bool) + if !response.WasNotFound(existing.HttpResponse) { + return tf.ImportAsExistsError("azurerm_cosmosdb_account", id.ID()) + } - r, err := databaseClient.CheckNameExists(ctx, id.DatabaseAccountName) - if err != nil { - // TODO: remove when https://github.com/Azure/azure-sdk-for-go/issues/9891 is fixed - if !utils.ResponseWasStatusCode(r, http.StatusInternalServerError) { - return fmt.Errorf("checking if CosmosDB Account %s: %+v", id, err) - } - } else { - if !utils.ResponseWasNotFound(r) { - return fmt.Errorf("CosmosDB Account %s already exists, please import the resource via terraform import", id.DatabaseAccountName) + databaseAccountNameID := cosmosdb.NewDatabaseAccountNameID(id.DatabaseAccountName) + dbCheckNameResp, err := client.DatabaseAccountsCheckNameExists(ctx, databaseAccountNameID) + if !response.WasNotFound(dbCheckNameResp.HttpResponse) { + if err != nil { + // TODO: remove when https://github.com/Azure/azure-sdk-for-go/issues/9891 is fixed + if !response.WasStatusCode(dbCheckNameResp.HttpResponse, http.StatusInternalServerError) { + return fmt.Errorf("checking whether the CosmosDB Account name (`%s`) is available: %+v", id.DatabaseAccountName, err) + } } + return fmt.Errorf("a CosmosDB Account with the chosen name (`%s`) already exists, please specify a different name", id.DatabaseAccountName) } geoLocations, err := expandAzureRmCosmosDBAccountGeoLocations(d) if err != nil { - return fmt.Errorf("expanding %s geo locations: %+v", id, err) - } - - publicNetworkAccess := cosmosdb.PublicNetworkAccessEnabled - if enabled := d.Get("public_network_access_enabled").(bool); !enabled { - publicNetworkAccess = cosmosdb.PublicNetworkAccessDisabled - } - - networkByPass := cosmosdb.NetworkAclBypassNone - if d.Get("network_acl_bypass_for_azure_services").(bool) { - networkByPass = cosmosdb.NetworkAclBypassAzureServices + return fmt.Errorf("expanding `geo_location`: %+v", err) } expandedIdentity, err := identity.ExpandLegacySystemAndUserAssignedMap(d.Get("identity").([]interface{})) @@ -861,38 +859,35 @@ func resourceCosmosDbAccountCreate(d *pluginsdk.ResourceData, meta interface{}) return fmt.Errorf("expanding `identity`: %+v", err) } - capabilities := expandAzureRmCosmosDBAccountCapabilities(d) - account := cosmosdb.DatabaseAccountCreateUpdateParameters{ - Location: pointer.To(location), - Kind: pointer.To(cosmosdb.DatabaseAccountKind(kind)), + Location: pointer.To(location.Normalize(d.Get("location").(string))), + Kind: pointer.ToEnum[cosmosdb.DatabaseAccountKind](d.Get("kind").(string)), Identity: expandedIdentity, Properties: cosmosdb.DatabaseAccountCreateUpdateProperties{ - DatabaseAccountOfferType: cosmosdb.DatabaseAccountOfferType(offerType), - IPRules: ipRangeFilter, - IsVirtualNetworkFilterEnabled: pointer.To(isVirtualNetworkFilterEnabled), - EnableFreeTier: pointer.To(enableFreeTier), - EnableAutomaticFailover: pointer.To(enableAutomaticFailover), + DatabaseAccountOfferType: cosmosdb.DatabaseAccountOfferType(d.Get("offer_type").(string)), + IPRules: common.CosmosDBIpRangeFilterToIpRules(*utils.ExpandStringSlice(d.Get("ip_range_filter").(*pluginsdk.Set).List())), + IsVirtualNetworkFilterEnabled: pointer.To(d.Get("is_virtual_network_filter_enabled").(bool)), + EnableFreeTier: pointer.To(d.Get("free_tier_enabled").(bool)), + EnableAutomaticFailover: pointer.To(d.Get("automatic_failover_enabled").(bool)), ConsistencyPolicy: expandAzureRmCosmosDBAccountConsistencyPolicy(d), Locations: geoLocations, - Capabilities: capabilities, + Capabilities: expandAzureRmCosmosDBAccountCapabilities(d), MinimalTlsVersion: pointer.To(cosmosdb.MinimalTlsVersion(d.Get("minimal_tls_version").(string))), VirtualNetworkRules: expandAzureRmCosmosDBAccountVirtualNetworkRules(d), - EnableMultipleWriteLocations: pointer.To(enableMultipleWriteLocations), - EnablePartitionMerge: pointer.To(partitionMergeEnabled), - EnableBurstCapacity: pointer.To(burstCapacityEnabled), - PublicNetworkAccess: pointer.To(publicNetworkAccess), - EnableAnalyticalStorage: pointer.To(enableAnalyticalStorage), + EnableMultipleWriteLocations: pointer.To(d.Get("multiple_write_locations_enabled").(bool)), + EnablePartitionMerge: pointer.To(d.Get("partition_merge_enabled").(bool)), + EnableBurstCapacity: pointer.To(d.Get("burst_capacity_enabled").(bool)), + PublicNetworkAccess: expandCosmosdbAccountPublicNetworkAccess(d.Get("public_network_access_enabled").(bool)), + EnableAnalyticalStorage: pointer.To(d.Get("analytical_storage_enabled").(bool)), Cors: common.ExpandCosmosCorsRule(d.Get("cors_rule").([]interface{})), DisableKeyBasedMetadataWriteAccess: pointer.To(!d.Get("access_key_metadata_writes_enabled").(bool)), - NetworkAclBypass: pointer.To(networkByPass), + NetworkAclBypass: expandCosmosdbAccountNetworkBypass(d.Get("network_acl_bypass_for_azure_services").(bool)), NetworkAclBypassResourceIds: utils.ExpandStringSlice(d.Get("network_acl_bypass_ids").([]interface{})), - DisableLocalAuth: pointer.To(disableLocalAuthentication), + DisableLocalAuth: pointer.To(d.Get("local_authentication_disabled").(bool)), }, - Tags: tags.Expand(t), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } - // These values may not have changed but they need to be in the update params... if v, ok := d.GetOk("default_identity_type"); ok { account.Properties.DefaultIdentity = pointer.To(v.(string)) } @@ -931,9 +926,22 @@ func resourceCosmosDbAccountCreate(d *pluginsdk.ResourceData, meta interface{}) return fmt.Errorf("`create_mode` only works when `backup.type` is `Continuous`") } - if key, err := customermanagedkeys.ExpandKeyVaultOrManagedHSMKey(d, customermanagedkeys.VersionTypeAny, accountClient.Environment.KeyVault, accountClient.Environment.ManagedHSM); err != nil { - return fmt.Errorf("parse key vault key id: %+v", err) - } else if key != nil { + var key *keyvault.NestedItemID + if !features.FivePointOh() && setInConfig(d, "managed_hsm_key_id") { + keyId, err := keyvault.ParseNestedItemID(d.Get("managed_hsm_key_id").(string), keyvault.VersionTypeAny, keyvault.NestedItemTypeKey) + if err != nil { + return err + } + key = keyId + } else if v, ok := d.GetOk("key_vault_key_id"); ok && setInConfig(d, "key_vault_key_id") { + keyId, err := keyvault.ParseNestedItemID(v.(string), keyvault.VersionTypeAny, keyvault.NestedItemTypeKey) + if err != nil { + return err + } + key = keyId + } + + if key != nil { account.Properties.KeyVaultKeyUri = pointer.To(key.ID()) } @@ -941,14 +949,14 @@ func resourceCosmosDbAccountCreate(d *pluginsdk.ResourceData, meta interface{}) consistencyPolicy := account.Properties.ConsistencyPolicy if len(geoLocations) > 1 && consistencyPolicy != nil && consistencyPolicy.DefaultConsistencyLevel == cosmosdb.DefaultConsistencyLevelBoundedStaleness { if msp := consistencyPolicy.MaxStalenessPrefix; msp != nil && pointer.From(msp) < 100000 { - return fmt.Errorf("max_staleness_prefix (%d) must be greater then 100000 when more then one geo_location is used", *msp) + return fmt.Errorf("max_staleness_prefix (%d) must be greater than 100000 when more then one geo_location is used", *msp) } if mis := consistencyPolicy.MaxIntervalInSeconds; mis != nil && pointer.From(mis) < 300 { - return fmt.Errorf("max_interval_in_seconds (%d) must be greater then 300 (5min) when more then one geo_location is used", *mis) + return fmt.Errorf("max_interval_in_seconds (%d) must be greater than 300 (5 minutes) when more then one geo_location is used", *mis) } } - err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, id, account, d) + err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, id, account) if err != nil { return fmt.Errorf("creating %s: %+v", id, err) } @@ -956,7 +964,7 @@ func resourceCosmosDbAccountCreate(d *pluginsdk.ResourceData, meta interface{}) // NOTE: this is to work around the issue here: https://github.com/Azure/azure-rest-api-specs/issues/27596 // Once the above issue is resolved we shouldn't need this check and update anymore if d.Get("create_mode").(string) == string(cosmosdb.CreateModeRestore) { - err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, id, account, d) + err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, id, account) if err != nil { return fmt.Errorf("updating %s: %+v", id, err) } @@ -969,54 +977,48 @@ func resourceCosmosDbAccountCreate(d *pluginsdk.ResourceData, meta interface{}) func resourceCosmosDbAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Cosmos.CosmosDBClient - apiEnvs := meta.(*clients.Client).Account.Environment - // subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - log.Printf("[INFO] Preparing arguments for AzureRM Cosmos DB Account update") - id, err := cosmosdb.ParseDatabaseAccountID(d.Id()) if err != nil { return err } - // get existing locations (if exists) existing, err := client.DatabaseAccountsGet(ctx, *id) if err != nil { - return fmt.Errorf("making Read request on %s: %s", id, err) + return fmt.Errorf("retrieving %s: %s", id, err) } if existing.Model == nil { - return fmt.Errorf("retrieving %s: properties were nil", id) + return fmt.Errorf("retrieving %s: model was nil", id) } + if existing.Model.Properties == nil { + return fmt.Errorf("retrieving %s: properties was nil", id) + } + props := existing.Model.Properties + configLocations, err := expandAzureRmCosmosDBAccountGeoLocations(d) if err != nil { - return fmt.Errorf("expanding %s geo locations: %+v", id, err) + return fmt.Errorf("expanding `geo_location`: %w", err) } // Normalize Locations... cosmosLocations := make([]cosmosdb.Location, 0) cosmosLocationsMap := map[string]cosmosdb.Location{} - if existing.Model.Properties.Locations != nil { - for _, l := range *existing.Model.Properties.Locations { - loc := cosmosdb.Location{ - Id: l.Id, - LocationName: l.LocationName, - FailoverPriority: l.FailoverPriority, - IsZoneRedundant: l.IsZoneRedundant, - } - - cosmosLocations = append(cosmosLocations, loc) - cosmosLocationsMap[location.Normalize(*loc.LocationName)] = loc + for _, l := range pointer.From(existing.Model.Properties.Locations) { + loc := cosmosdb.Location{ + Id: l.Id, + LocationName: l.LocationName, + FailoverPriority: l.FailoverPriority, + IsZoneRedundant: l.IsZoneRedundant, } - } - var capabilities *[]cosmosdb.Capability - if existing.Model.Properties.Capabilities != nil { - capabilities = existing.Model.Properties.Capabilities + cosmosLocations = append(cosmosLocations, loc) + cosmosLocationsMap[location.NormalizeNilable(loc.LocationName)] = loc } // backup must be updated independently @@ -1047,314 +1049,243 @@ func resourceCosmosDbAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) } } - updateRequired := false - if props := existing.Model.Properties; props != nil { - location := location.Normalize(pointer.From(existing.Model.Location)) - offerType := d.Get("offer_type").(string) - t := tags.Expand(d.Get("tags").(map[string]interface{})) - kind := cosmosdb.DatabaseAccountKind(d.Get("kind").(string)) - isVirtualNetworkFilterEnabled := pointer.To(d.Get("is_virtual_network_filter_enabled").(bool)) - enableAnalyticalStorage := pointer.To(d.Get("analytical_storage_enabled").(bool)) - disableLocalAuthentication := pointer.To(d.Get("local_authentication_disabled").(bool)) - enableAutomaticFailover := pointer.To(d.Get("automatic_failover_enabled").(bool)) - - networkByPass := cosmosdb.NetworkAclBypassNone - if d.Get("network_acl_bypass_for_azure_services").(bool) { - networkByPass = cosmosdb.NetworkAclBypassAzureServices - } - - ipRangeFilter := common.CosmosDBIpRangeFilterToIpRules(*utils.ExpandStringSlice(d.Get("ip_range_filter").(*pluginsdk.Set).List())) - - publicNetworkAccess := cosmosdb.PublicNetworkAccessEnabled - if enabled := d.Get("public_network_access_enabled").(bool); !enabled { - publicNetworkAccess = cosmosdb.PublicNetworkAccessDisabled - } - - // NOTE: these fields are expanded directly into the - // 'DatabaseAccountCreateUpdateParameters' below or - // are included in the 'DatabaseAccountCreateUpdateParameters' - // later, however we need to know if they changed or not... - if d.HasChanges("consistency_policy", "virtual_network_rule", "cors_rule", "access_key_metadata_writes_enabled", - "network_acl_bypass_for_azure_services", "network_acl_bypass_ids", "analytical_storage", - "capacity", "create_mode", "restore", "key_vault_key_id", "managed_hsm_key_id", "mongo_server_version", - "public_network_access_enabled", "ip_range_filter", "offer_type", "is_virtual_network_filter_enabled", - "kind", "tags", "automatic_failover_enabled", "analytical_storage_enabled", - "local_authentication_disabled", "partition_merge_enabled", "minimal_tls_version", "burst_capacity_enabled") { - updateRequired = true - } - - // Incident : #383341730 - // Azure Bug: #2209567 'Updating identities and default identity at the same time fails silently' - // - // The 'Identity' field should only ever be sent once to the endpoint, except for updates and removal. If the - // 'Identity' field is included in the update call with the 'DefaultIdentity' it will silently fail - // per the bug noted above (e.g. Azure Bug #2209567). - // - // In the update scenario where the end-user would like to update their 'Identity' and their 'DefaultIdentity' - // fields at the same time both of these operations need to happen atomically in separate PUT/PATCH calls - // to the service else you will hit the bug mentioned above. You need to update the 'Identity' field - // first then update the 'DefaultIdentity' in totally different PUT/PATCH calls where you have to drop - // the 'Identity' field on the floor when updating the 'DefaultIdentity' field. - // - // NOTE : If the 'Identity' field has not changed in the resource, do not send it in the payload. - // this workaround can be removed once the service team fixes the above mentioned bug. - // - // ADDITIONAL: You cannot update properties and add/remove replication locations or update the enabling of - // multiple write locations at the same time. So you must update any changed properties - // first, then address the replication locations and/or updating/enabling of - // multiple write locations. - - account := cosmosdb.DatabaseAccountCreateUpdateParameters{ - Location: pointer.To(location), - Kind: pointer.To(kind), - Properties: cosmosdb.DatabaseAccountCreateUpdateProperties{ - DatabaseAccountOfferType: cosmosdb.DatabaseAccountOfferType(offerType), - IPRules: ipRangeFilter, - IsVirtualNetworkFilterEnabled: isVirtualNetworkFilterEnabled, - EnableFreeTier: existing.Model.Properties.EnableFreeTier, - EnableAutomaticFailover: enableAutomaticFailover, - MinimalTlsVersion: pointer.To(cosmosdb.MinimalTlsVersion(d.Get("minimal_tls_version").(string))), - Capabilities: capabilities, - ConsistencyPolicy: expandAzureRmCosmosDBAccountConsistencyPolicy(d), - Locations: cosmosLocations, - VirtualNetworkRules: expandAzureRmCosmosDBAccountVirtualNetworkRules(d), - EnableMultipleWriteLocations: props.EnableMultipleWriteLocations, - PublicNetworkAccess: pointer.To(publicNetworkAccess), - EnableAnalyticalStorage: enableAnalyticalStorage, - Cors: common.ExpandCosmosCorsRule(d.Get("cors_rule").([]interface{})), - DisableKeyBasedMetadataWriteAccess: pointer.To(!d.Get("access_key_metadata_writes_enabled").(bool)), - NetworkAclBypass: pointer.To(networkByPass), - NetworkAclBypassResourceIds: utils.ExpandStringSlice(d.Get("network_acl_bypass_ids").([]interface{})), - DisableLocalAuth: disableLocalAuthentication, - BackupPolicy: backup, - EnablePartitionMerge: pointer.To(d.Get("partition_merge_enabled").(bool)), - EnableBurstCapacity: pointer.To(d.Get("burst_capacity_enabled").(bool)), - }, - Tags: t, - } + // NOTE: these fields are expanded directly into the + // 'DatabaseAccountCreateUpdateParameters' below or + // are included in the 'DatabaseAccountCreateUpdateParameters' + // later, however we need to know if they changed or not... + updateRequired := d.HasChanges("consistency_policy", "virtual_network_rule", "cors_rule", "access_key_metadata_writes_enabled", + "network_acl_bypass_for_azure_services", "network_acl_bypass_ids", "analytical_storage", + "capacity", "restore", "mongo_server_version", + "public_network_access_enabled", "ip_range_filter", "offer_type", "is_virtual_network_filter_enabled", + "tags", "automatic_failover_enabled", "analytical_storage_enabled", + "local_authentication_disabled", "partition_merge_enabled", "minimal_tls_version", "burst_capacity_enabled") + + // Incident : #383341730 + // Azure Bug: #2209567 'Updating identities and default identity at the same time fails silently' + // + // The 'Identity' field should only ever be sent once to the endpoint, except for updates and removal. If the + // 'Identity' field is included in the update call with the 'DefaultIdentity' it will silently fail + // per the bug noted above (e.g. Azure Bug #2209567). + // + // In the update scenario where the end-user would like to update their 'Identity' and their 'DefaultIdentity' + // fields at the same time both of these operations need to happen atomically in separate PUT/PATCH calls + // to the service else you will hit the bug mentioned above. You need to update the 'Identity' field + // first then update the 'DefaultIdentity' in totally different PUT/PATCH calls where you have to drop + // the 'Identity' field on the floor when updating the 'DefaultIdentity' field. + // + // NOTE : If the 'Identity' field has not changed in the resource, do not send it in the payload. + // this workaround can be removed once the service team fixes the above mentioned bug. + // + // ADDITIONAL: You cannot update properties and add/remove replication locations or update the enabling of + // multiple write locations at the same time. So you must update any changed properties + // first, then address the replication locations and/or updating/enabling of + // multiple write locations. - if key, err := customermanagedkeys.ExpandKeyVaultOrManagedHSMKey(d, customermanagedkeys.VersionTypeAny, apiEnvs.KeyVault, apiEnvs.ManagedHSM); err != nil { - return err - } else if key != nil { - account.Properties.KeyVaultKeyUri = pointer.To(key.ID()) - } + account := cosmosdb.DatabaseAccountCreateUpdateParameters{ + Location: pointer.To(location.NormalizeNilable(existing.Model.Location)), + Kind: pointer.To(cosmosdb.DatabaseAccountKind(d.Get("kind").(string))), + Properties: cosmosdb.DatabaseAccountCreateUpdateProperties{ + DatabaseAccountOfferType: cosmosdb.DatabaseAccountOfferType(d.Get("offer_type").(string)), + IPRules: common.CosmosDBIpRangeFilterToIpRules(*utils.ExpandStringSlice(d.Get("ip_range_filter").(*pluginsdk.Set).List())), + IsVirtualNetworkFilterEnabled: pointer.To(d.Get("is_virtual_network_filter_enabled").(bool)), + EnableFreeTier: existing.Model.Properties.EnableFreeTier, + EnableAutomaticFailover: pointer.To(d.Get("automatic_failover_enabled").(bool)), + MinimalTlsVersion: pointer.To(cosmosdb.MinimalTlsVersion(d.Get("minimal_tls_version").(string))), + Capabilities: existing.Model.Properties.Capabilities, + ConsistencyPolicy: expandAzureRmCosmosDBAccountConsistencyPolicy(d), + KeyVaultKeyUri: existing.Model.Properties.KeyVaultKeyUri, + Locations: cosmosLocations, + VirtualNetworkRules: expandAzureRmCosmosDBAccountVirtualNetworkRules(d), + EnableMultipleWriteLocations: props.EnableMultipleWriteLocations, + PublicNetworkAccess: expandCosmosdbAccountPublicNetworkAccess(d.Get("public_network_access_enabled").(bool)), + EnableAnalyticalStorage: pointer.To(d.Get("analytical_storage_enabled").(bool)), + Cors: common.ExpandCosmosCorsRule(d.Get("cors_rule").([]interface{})), + DisableKeyBasedMetadataWriteAccess: pointer.To(!d.Get("access_key_metadata_writes_enabled").(bool)), + NetworkAclBypass: expandCosmosdbAccountNetworkBypass(d.Get("network_acl_bypass_for_azure_services").(bool)), + NetworkAclBypassResourceIds: utils.ExpandStringSlice(d.Get("network_acl_bypass_ids").([]interface{})), + DisableLocalAuth: pointer.To(d.Get("local_authentication_disabled").(bool)), + BackupPolicy: backup, + EnablePartitionMerge: pointer.To(d.Get("partition_merge_enabled").(bool)), + EnableBurstCapacity: pointer.To(d.Get("burst_capacity_enabled").(bool)), + }, + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } - // 'default_identity_type' will always have a value since it now has a default value of "FirstPartyIdentity" per the API documentation. - // I do not include 'DefaultIdentity' and 'Identity' in the 'accountProps' intentionally, these operations need to be - // performed mutually exclusive from each other in an atomic fashion, else you will hit the service teams bug... - updateDefaultIdentity := false - if d.HasChange("default_identity_type") { - updateDefaultIdentity = true - } + // 'default_identity_type' will always have a value since it now has a default value of "FirstPartyIdentity" per the API documentation. + // I do not include 'DefaultIdentity' and 'Identity' in the 'accountProps' intentionally, these operations need to be + // performed mutually exclusive from each other in an atomic fashion, else you will hit the service teams bug... + updateDefaultIdentity := d.HasChange("default_identity_type") - // adding 'DefaultIdentity' to avoid causing it to fallback - // to "FirstPartyIdentity" on update(s), issue #22466 - if v, ok := d.GetOk("default_identity_type"); ok { - account.Properties.DefaultIdentity = pointer.To(v.(string)) - } + // adding 'DefaultIdentity' to avoid causing it to fallback + // to "FirstPartyIdentity" on update(s), issue #22466 + if v, ok := d.GetOk("default_identity_type"); ok { + account.Properties.DefaultIdentity = pointer.To(v.(string)) + } - // we need the following in the accountProps even if they have not changed... - if v, ok := d.GetOk("analytical_storage"); ok { - account.Properties.AnalyticalStorageConfiguration = expandCosmosDBAccountAnalyticalStorageConfiguration(v.([]interface{})) - } + // we need the following in the accountProps even if they have not changed... + if v, ok := d.GetOk("analytical_storage"); ok { + account.Properties.AnalyticalStorageConfiguration = expandCosmosDBAccountAnalyticalStorageConfiguration(v.([]interface{})) + } - if v, ok := d.GetOk("capacity"); ok { - account.Properties.Capacity = expandCosmosDBAccountCapacity(v.([]interface{})) - } + if v, ok := d.GetOk("capacity"); ok { + account.Properties.Capacity = expandCosmosDBAccountCapacity(v.([]interface{})) + } - var createMode string - if v, ok := d.GetOk("create_mode"); ok { - createMode = v.(string) - account.Properties.CreateMode = pointer.To(cosmosdb.CreateMode(createMode)) + var createMode string + if v, ok := d.GetOk("create_mode"); ok { + createMode = v.(string) + account.Properties.CreateMode = pointer.To(cosmosdb.CreateMode(createMode)) + } + + if v, ok := d.GetOk("restore"); ok { + account.Properties.RestoreParameters = expandCosmosdbAccountRestoreParameters(v.([]interface{})) + } + + if !pluginsdk.IsExplicitlyNullInConfig(d, "mongo_server_version") { + account.Properties.ApiProperties = &cosmosdb.ApiProperties{ + ServerVersion: pointer.To(cosmosdb.ServerVersion(d.Get("mongo_server_version").(string))), } + } - if v, ok := d.GetOk("restore"); ok { - account.Properties.RestoreParameters = expandCosmosdbAccountRestoreParameters(v.([]interface{})) + // Only do this update if a value has changed above... + if updateRequired { + if err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) } + } - if !pluginsdk.IsExplicitlyNullInConfig(d, "mongo_server_version") { - account.Properties.ApiProperties = &cosmosdb.ApiProperties{ - ServerVersion: pointer.To(cosmosdb.ServerVersion(d.Get("mongo_server_version").(string))), - } + // Update the following properties independently after the initial CreateOrUpdate... + if d.HasChange("multiple_write_locations_enabled") { + account.Properties.EnableMultipleWriteLocations = pointer.To(d.Get("multiple_write_locations_enabled").(bool)) + + // Update the database... + if err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account); err != nil { + return fmt.Errorf("updating %q EnableMultipleWriteLocations: %+v", id, err) } + } - // Only do this update if a value has changed above... - if updateRequired { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'DatabaseAccountCreateUpdateParameters'") + // determine if any locations have been renamed/priority reordered and remove them + updateLocations := false + for _, configLoc := range configLocations { + if cosmosLoc, ok := cosmosLocationsMap[pointer.From(configLoc.LocationName)]; ok { + // is the location in the config also in the database with the same 'FailoverPriority'? + if pointer.From(configLoc.FailoverPriority) != pointer.From(cosmosLoc.FailoverPriority) { + // The Failover Priority has been changed in the config... + if pointer.From(configLoc.FailoverPriority) == 0 { + return fmt.Errorf("cannot change the failover priority of %q location %q to %d", id, pointer.From(configLoc.LocationName), pointer.From(configLoc.FailoverPriority)) + } - // Update the database... - if err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account, d); err != nil { - return fmt.Errorf("updating %s: %+v", id, err) + // since the Locations FailoverPriority changed remove it from the map because + // we have to update the Location in the database. The Locations + // left in the map after this loop are the Locations that are + // the same in the database and in the config file... + delete(cosmosLocationsMap, pointer.From(configLoc.LocationName)) + updateLocations = true } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Update 'DatabaseAccountCreateUpdateParameters' [NO CHANGE]") } + } - // Update the following properties independently after the initial CreateOrUpdate... - if d.HasChange("multiple_write_locations_enabled") { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'EnableMultipleWriteLocations'") + if updateLocations { + locationsUnchanged := make([]cosmosdb.Location, 0, len(cosmosLocationsMap)) + for _, value := range cosmosLocationsMap { + locationsUnchanged = append(locationsUnchanged, value) + } - enableMultipleWriteLocations := pointer.To(d.Get("multiple_write_locations_enabled").(bool)) - if props.EnableMultipleWriteLocations != enableMultipleWriteLocations { - account.Properties.EnableMultipleWriteLocations = enableMultipleWriteLocations + account.Properties.Locations = locationsUnchanged - // Update the database... - if err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account, d); err != nil { - return fmt.Errorf("updating %q EnableMultipleWriteLocations: %+v", id, err) - } - } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Updating 'EnableMultipleWriteLocations' [NO CHANGE]") - } - - // determine if any locations have been renamed/priority reordered and remove them - updateLocations := false - for _, configLoc := range configLocations { - if cosmosLoc, ok := cosmosLocationsMap[pointer.From(configLoc.LocationName)]; ok { - // is the location in the config also in the database with the same 'FailoverPriority'? - if pointer.From(configLoc.FailoverPriority) != pointer.From(cosmosLoc.FailoverPriority) { - // The Failover Priority has been changed in the config... - if pointer.From(configLoc.FailoverPriority) == 0 { - return fmt.Errorf("cannot change the failover priority of %q location %q to %d", id, pointer.From(configLoc.LocationName), pointer.From(configLoc.FailoverPriority)) - } + // Update the database... + if err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account); err != nil { + return fmt.Errorf("removing %q renamed `locations`: %+v", id, err) + } + } - // since the Locations FailoverPriority changed remove it from the map because - // we have to update the Location in the database. The Locations - // left in the map after this loop are the Locations that are - // the same in the database and in the config file... - delete(cosmosLocationsMap, pointer.From(configLoc.LocationName)) - updateLocations = true - } - } + if d.HasChanges("geo_location") { + account.Properties.Locations = configLocations + + // Update the database locations... + err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account) + if err != nil { + return fmt.Errorf("updating %q `locations`: %+v", id, err) } + } - if updateLocations { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Removing renamed 'Locations'") - locationsUnchanged := make([]cosmosdb.Location, 0, len(cosmosLocationsMap)) - for _, value := range cosmosLocationsMap { - locationsUnchanged = append(locationsUnchanged, value) - } + // Update Identity and Default Identity... + identityChanged := false + if d.HasChange("identity") { + identityChanged = true - account.Properties.Locations = locationsUnchanged + // Looks like you have to always remove all the identities first before you can + // reassign/modify them, else it will append any new/changed identities + // resulting in a diff... + log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Setting 'Identity' to 'None'") - // Update the database... - if err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account, d); err != nil { - return fmt.Errorf("removing %q renamed `locations`: %+v", id, err) - } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Removing renamed 'Locations' [NO CHANGE]") + // can't set this back to account, because that will hit the bug... + identityVal := cosmosdb.DatabaseAccountUpdateParameters{ + Identity: pointer.To(identity.LegacySystemAndUserAssignedMap{ + Type: identity.TypeNone, + }), } - if d.HasChanges("geo_location") { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'Locations'") - // add any new/renamed locations - account.Properties.Locations = configLocations - - // Update the database locations... - err = resourceCosmosDbAccountApiCreateOrUpdate(client, ctx, *id, account, d) - if err != nil { - return fmt.Errorf("updating %q `locations`: %+v", id, err) - } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Updating 'Locations' [NO CHANGE]") + // Update the database 'Identity' to 'None'... + err = resourceCosmosDbAccountApiUpdate(client, ctx, *id, identityVal) + if err != nil { + return fmt.Errorf("updating 'identity' %q: %+v", id, err) } - // Update Identity and Default Identity... - identityChanged := false expandedIdentity, err := identity.ExpandLegacySystemAndUserAssignedMap(d.Get("identity").([]interface{})) if err != nil { return fmt.Errorf("expanding `identity`: %+v", err) } - if d.HasChange("identity") { - identityChanged = true - - // Looks like you have to always remove all the identities first before you can - // reassign/modify them, else it will append any new/changed identities - // resulting in a diff... - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Setting 'Identity' to 'None'") - - // can't set this back to account, because that will hit the bug... + // If the Identity was removed from the configuration file it will be set as type None + // so we can skip setting the Identity if it is going to be set to None... + if expandedIdentity.Type != identity.TypeNone { identityVal := cosmosdb.DatabaseAccountUpdateParameters{ - Identity: pointer.To(identity.LegacySystemAndUserAssignedMap{ - Type: identity.TypeNone, - }), + Identity: expandedIdentity, } - // Update the database 'Identity' to 'None'... - err = resourceCosmosDbAccountApiUpdate(client, ctx, *id, identityVal, d) + // Update the database... + err = resourceCosmosDbAccountApiUpdate(client, ctx, *id, identityVal) if err != nil { - return fmt.Errorf("updating 'identity' %q: %+v", id, err) + return fmt.Errorf("updating `identity` for %s: %+v", id, err) } + } + } - // If the Identity was removed from the configuration file it will be set as type None - // so we can skip setting the Identity if it is going to be set to None... - if expandedIdentity.Type != identity.TypeNone { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'Identity' to %q", expandedIdentity.Type) - - identityVal := cosmosdb.DatabaseAccountUpdateParameters{ - Identity: expandedIdentity, - } - - // Update the database... - err = resourceCosmosDbAccountApiUpdate(client, ctx, *id, identityVal, d) - if err != nil { - return fmt.Errorf("updating 'identity' %q: %+v", id, err) - } - } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Updating 'Identity' [NO CHANGE]") - } - - // NOTE: updateDefaultIdentity now has a default value of 'FirstPartyIdentity'... This value now gets - // triggered if the default value does not match the value in Azure... - // - // NOTE: When you change the 'Identity', the 'DefaultIdentity' will be set to 'undefined', so if you change - // the identity you must also update the 'DefaultIdentity' as well... - if updateDefaultIdentity || identityChanged { - // This will now return the default of 'FirstPartyIdentity' if it - // is not set in the config, which is correct. - configDefaultIdentity := d.Get("default_identity_type").(string) - if identityChanged { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'DefaultIdentity' to %q because the 'Identity' was changed to %q", configDefaultIdentity, expandedIdentity.Type) - } else { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'DefaultIdentity' to %q because 'default_identity_type' was changed", configDefaultIdentity) - } + // NOTE: updateDefaultIdentity now has a default value of 'FirstPartyIdentity'... This value now gets + // triggered if the default value does not match the value in Azure... + // + // NOTE: When you change the 'Identity', the 'DefaultIdentity' will be set to 'undefined', so if you change + // the identity you must also update the 'DefaultIdentity' as well... + if updateDefaultIdentity || identityChanged { + // This will now return the default of 'FirstPartyIdentity' if it + // is not set in the config, which is correct. - // PATCH instead of PUT... - defaultIdentity := cosmosdb.DatabaseAccountUpdateParameters{ - Properties: &cosmosdb.DatabaseAccountUpdateProperties{ - DefaultIdentity: pointer.To(configDefaultIdentity), - }, - } + // PATCH instead of PUT... + defaultIdentity := cosmosdb.DatabaseAccountUpdateParameters{ + Properties: &cosmosdb.DatabaseAccountUpdateProperties{ + DefaultIdentity: pointer.To(d.Get("default_identity_type").(string)), + }, + } - // Update the database... - err = resourceCosmosDbAccountApiUpdate(client, ctx, *id, defaultIdentity, d) - if err != nil { - return fmt.Errorf("updating 'default_identity_type' %q: %+v", id, err) - } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Updating 'DefaultIdentity' [NO CHANGE]") + // Update the database... + err = resourceCosmosDbAccountApiUpdate(client, ctx, *id, defaultIdentity) + if err != nil { + return fmt.Errorf("updating `default_identity_type` for %s: %+v", id, err) } } if existing.Model.Properties.Capabilities != nil { if d.HasChange("capabilities") { - log.Printf("[INFO] Updating AzureRM Cosmos DB Account: Updating 'Capabilities'") - - newCapabilities := expandAzureRmCosmosDBAccountCapabilities(d) updateParameters := cosmosdb.DatabaseAccountUpdateParameters{ Properties: &cosmosdb.DatabaseAccountUpdateProperties{ - Capabilities: newCapabilities, + Capabilities: expandAzureRmCosmosDBAccountCapabilities(d), }, } - // Update Database 'capabilities'... if err := client.DatabaseAccountsUpdateThenPoll(ctx, *id, updateParameters); err != nil { - return fmt.Errorf("updating CosmosDB Account %q (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("updating `capabilities` for %s: %+v", id, err) } - } else { - log.Printf("[INFO] [SKIP] AzureRM Cosmos DB Account: Updating 'Capabilities' [NO CHANGE]") } } @@ -1363,6 +1294,7 @@ func resourceCosmosDbAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) func resourceCosmosDbAccountRead(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Cosmos.CosmosDBClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -1378,202 +1310,183 @@ func resourceCosmosDbAccountRead(d *pluginsdk.ResourceData, meta interface{}) er return nil } - return fmt.Errorf("retrieving CosmosDB Account %q (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } d.Set("name", id.DatabaseAccountName) d.Set("resource_group_name", id.ResourceGroupName) - d.Set("location", location.NormalizeNilable(existing.Model.Location)) - d.Set("kind", pointer.From(existing.Model.Kind)) - identity, err := identity.FlattenLegacySystemAndUserAssignedMap(existing.Model.Identity) - if err != nil { - return fmt.Errorf("flattening `identity`: %+v", err) - } + if model := existing.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + d.Set("kind", pointer.From(model.Kind)) + d.Set("tags", model.Tags) - if err := d.Set("identity", identity); err != nil { - return fmt.Errorf("setting `identity`: %+v", err) - } - - if props := existing.Model.Properties; props != nil { - d.Set("offer_type", pointer.From(props.DatabaseAccountOfferType)) + flattenedIdentity, err := identity.FlattenLegacySystemAndUserAssignedMap(model.Identity) + if err != nil { + return fmt.Errorf("flattening `identity`: %+v", err) + } - d.Set("ip_range_filter", common.CosmosDBIpRulesToIpRangeFilter(props.IPRules)) + if err := d.Set("identity", flattenedIdentity); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } - d.Set("endpoint", props.DocumentEndpoint) + if props := model.Properties; props != nil { + d.Set("offer_type", pointer.From(props.DatabaseAccountOfferType)) + d.Set("ip_range_filter", common.CosmosDBIpRulesToIpRangeFilter(props.IPRules)) + d.Set("endpoint", props.DocumentEndpoint) + d.Set("free_tier_enabled", props.EnableFreeTier) + d.Set("analytical_storage_enabled", props.EnableAnalyticalStorage) + d.Set("public_network_access_enabled", pointer.From(props.PublicNetworkAccess) == cosmosdb.PublicNetworkAccessEnabled) - d.Set("free_tier_enabled", props.EnableFreeTier) - d.Set("analytical_storage_enabled", props.EnableAnalyticalStorage) - d.Set("public_network_access_enabled", pointer.From(props.PublicNetworkAccess) == cosmosdb.PublicNetworkAccessEnabled) - if props.DefaultIdentity == nil || *props.DefaultIdentity != "" { - d.Set("default_identity_type", props.DefaultIdentity) - } else { d.Set("default_identity_type", "FirstPartyIdentity") - } - d.Set("minimal_tls_version", pointer.From(props.MinimalTlsVersion)) - d.Set("create_mode", pointer.From(props.CreateMode)) - d.Set("partition_merge_enabled", pointer.From(props.EnablePartitionMerge)) - d.Set("burst_capacity_enabled", pointer.From(props.EnableBurstCapacity)) + if pointer.From(props.DefaultIdentity) != "" { + d.Set("default_identity_type", props.DefaultIdentity) + } - if v := props.IsVirtualNetworkFilterEnabled; v != nil { - d.Set("is_virtual_network_filter_enabled", props.IsVirtualNetworkFilterEnabled) - } + d.Set("minimal_tls_version", pointer.From(props.MinimalTlsVersion)) + d.Set("create_mode", pointer.From(props.CreateMode)) + d.Set("partition_merge_enabled", pointer.From(props.EnablePartitionMerge)) + d.Set("burst_capacity_enabled", pointer.From(props.EnableBurstCapacity)) + d.Set("is_virtual_network_filter_enabled", pointer.From(props.IsVirtualNetworkFilterEnabled)) + d.Set("automatic_failover_enabled", pointer.From(props.EnableAutomaticFailover)) + d.Set("multiple_write_locations_enabled", pointer.From(props.EnableMultipleWriteLocations)) - if v := props.EnableAutomaticFailover; v != nil { - d.Set("automatic_failover_enabled", props.EnableAutomaticFailover) - } + if v := props.KeyVaultKeyUri; v != nil { + key, err := keyvault.ParseNestedItemID(*v, keyvault.VersionTypeAny, keyvault.NestedItemTypeKey) + if err != nil { + return err + } - if v := props.KeyVaultKeyUri; v != nil { - envs := meta.(*clients.Client).Account.Environment - if key, err := customermanagedkeys.FlattenKeyVaultOrManagedHSMID(*v, envs.ManagedHSM); err != nil { - return fmt.Errorf("flatten key vault uri: %+v", err) - } else if key.IsSet() { - if key.KeyVaultKeyId != nil { - d.Set("key_vault_key_id", key.KeyVaultKeyId.ID()) - } else { - d.Set("managed_hsm_key_id", key.ManagedHSMKeyID()) + d.Set("key_vault_key_id", key.VersionlessID()) + if !features.FivePointOh() && key.IsManagedHSM() { + d.Set("managed_hsm_key_id", key.VersionlessID()) } } - } - if v := existing.Model.Properties.EnableMultipleWriteLocations; v != nil { - d.Set("multiple_write_locations_enabled", props.EnableMultipleWriteLocations) - } + if err := d.Set("analytical_storage", flattenCosmosDBAccountAnalyticalStorageConfiguration(props.AnalyticalStorageConfiguration)); err != nil { + return fmt.Errorf("setting `analytical_storage`: %+v", err) + } - if err := d.Set("analytical_storage", flattenCosmosDBAccountAnalyticalStorageConfiguration(props.AnalyticalStorageConfiguration)); err != nil { - return fmt.Errorf("setting `analytical_storage`: %+v", err) - } + if err := d.Set("capacity", flattenCosmosDBAccountCapacity(props.Capacity)); err != nil { + return fmt.Errorf("setting `capacity`: %+v", err) + } - if err := d.Set("capacity", flattenCosmosDBAccountCapacity(props.Capacity)); err != nil { - return fmt.Errorf("setting `capacity`: %+v", err) - } + if err := d.Set("restore", flattenCosmosdbAccountRestoreParameters(props.RestoreParameters)); err != nil { + return fmt.Errorf("setting `restore`: %+v", err) + } - if err := d.Set("restore", flattenCosmosdbAccountRestoreParameters(props.RestoreParameters)); err != nil { - return fmt.Errorf("setting `restore`: %+v", err) - } + if err = d.Set("consistency_policy", flattenAzureRmCosmosDBAccountConsistencyPolicy(props.ConsistencyPolicy)); err != nil { + return fmt.Errorf("setting `consistency_policy`: %+v", err) + } - if err = d.Set("consistency_policy", flattenAzureRmCosmosDBAccountConsistencyPolicy(props.ConsistencyPolicy)); err != nil { - return fmt.Errorf("setting CosmosDB Account %q `consistency_policy` (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err) - } + if err = d.Set("geo_location", flattenAzureRmCosmosDBAccountGeoLocations(props)); err != nil { + return fmt.Errorf("setting `geo_location`: %+v", err) + } - if err = d.Set("geo_location", flattenAzureRmCosmosDBAccountGeoLocations(props)); err != nil { - return fmt.Errorf("setting `geo_location`: %+v", err) - } + if err = d.Set("capabilities", flattenAzureRmCosmosDBAccountCapabilities(props.Capabilities)); err != nil { + return fmt.Errorf("setting `capabilities`: %+v", err) + } - if err = d.Set("capabilities", flattenAzureRmCosmosDBAccountCapabilities(props.Capabilities)); err != nil { - return fmt.Errorf("setting `capabilities`: %+v", err) - } + if err = d.Set("virtual_network_rule", flattenAzureRmCosmosDBAccountVirtualNetworkRules(props.VirtualNetworkRules)); err != nil { + return fmt.Errorf("setting `virtual_network_rule`: %+v", err) + } - if err = d.Set("virtual_network_rule", flattenAzureRmCosmosDBAccountVirtualNetworkRules(props.VirtualNetworkRules)); err != nil { - return fmt.Errorf("setting `virtual_network_rule`: %+v", err) - } + accessKeyMetadataWritesEnabled := true + if v := props.DisableKeyBasedMetadataWriteAccess; v != nil { + accessKeyMetadataWritesEnabled = !*v + } + d.Set("access_key_metadata_writes_enabled", accessKeyMetadataWritesEnabled) - d.Set("access_key_metadata_writes_enabled", !*props.DisableKeyBasedMetadataWriteAccess) - if apiProps := props.ApiProperties; apiProps != nil { - d.Set("mongo_server_version", pointer.From(apiProps.ServerVersion)) - } - d.Set("network_acl_bypass_for_azure_services", pointer.From(props.NetworkAclBypass) == cosmosdb.NetworkAclBypassAzureServices) - d.Set("network_acl_bypass_ids", utils.FlattenStringSlice(props.NetworkAclBypassResourceIds)) + if apiProps := props.ApiProperties; apiProps != nil { + d.Set("mongo_server_version", pointer.From(apiProps.ServerVersion)) + } - if v := existing.Model.Properties.DisableLocalAuth; v != nil { - d.Set("local_authentication_disabled", props.DisableLocalAuth) - } + d.Set("network_acl_bypass_for_azure_services", pointer.From(props.NetworkAclBypass) == cosmosdb.NetworkAclBypassAzureServices) + d.Set("network_acl_bypass_ids", utils.FlattenStringSlice(props.NetworkAclBypassResourceIds)) + d.Set("local_authentication_disabled", pointer.From(props.DisableLocalAuth)) - policy, err := flattenCosmosdbAccountBackup(props.BackupPolicy) - if err != nil { - return err - } + policy, err := flattenCosmosdbAccountBackup(props.BackupPolicy) + if err != nil { + return fmt.Errorf("flattening `backup`: %w", err) + } - if err = d.Set("backup", policy); err != nil { - return fmt.Errorf("setting `backup`: %+v", err) - } + if err = d.Set("backup", policy); err != nil { + return fmt.Errorf("setting `backup`: %+v", err) + } - d.Set("cors_rule", common.FlattenCosmosCorsRule(props.Cors)) - } + d.Set("cors_rule", common.FlattenCosmosCorsRule(props.Cors)) - readEndpoints := make([]string, 0) - if p := existing.Model.Properties.ReadLocations; p != nil { - for _, l := range *p { - if l.DocumentEndpoint == nil { - continue + if err := d.Set("read_endpoints", flattenCosmosdbAccountReadWriteEndpoints(props.Locations)); err != nil { + return fmt.Errorf("setting `read_endpoints`: %s", err) } - readEndpoints = append(readEndpoints, *l.DocumentEndpoint) - } - } - if err := d.Set("read_endpoints", readEndpoints); err != nil { - return fmt.Errorf("setting `read_endpoints`: %s", err) - } - - writeEndpoints := make([]string, 0) - if p := existing.Model.Properties.WriteLocations; p != nil { - for _, l := range *p { - if l.DocumentEndpoint == nil { - continue + if err := d.Set("write_endpoints", flattenCosmosdbAccountReadWriteEndpoints(props.WriteLocations)); err != nil { + return fmt.Errorf("setting `write_endpoints`: %s", err) } - writeEndpoints = append(writeEndpoints, *l.DocumentEndpoint) - } - } - if err := d.Set("write_endpoints", writeEndpoints); err != nil { - return fmt.Errorf("setting `write_endpoints`: %s", err) - } + // ListKeys returns a data structure containing a DatabaseAccountListReadOnlyKeysResult pointer + // implying that it also returns the read only keys, however this appears to not be the case + keys, err := client.DatabaseAccountsListKeys(ctx, *id) + if err != nil { + if response.WasNotFound(keys.HttpResponse) { + log.Printf("[DEBUG] Keys were not found for CosmosDB Account %q (Resource Group %q) - removing from state!", id.DatabaseAccountName, id.ResourceGroupName) + d.SetId("") + return nil + } - // ListKeys returns a data structure containing a DatabaseAccountListReadOnlyKeysResult pointer - // implying that it also returns the read only keys, however this appears to not be the case - keys, err := client.DatabaseAccountsListKeys(ctx, *id) - if err != nil { - if response.WasNotFound(keys.HttpResponse) { - log.Printf("[DEBUG] Keys were not found for CosmosDB Account %q (Resource Group %q) - removing from state!", id.DatabaseAccountName, id.ResourceGroupName) - d.SetId("") - return nil - } + return fmt.Errorf("listing keys for %s: %w", id, err) + } - return fmt.Errorf("[ERROR] Unable to List Write keys for CosmosDB Account %s: %s", id.DatabaseAccountName, err) - } - d.Set("primary_key", keys.Model.PrimaryMasterKey) - d.Set("secondary_key", keys.Model.SecondaryMasterKey) + if keys.Model != nil { + d.Set("primary_key", keys.Model.PrimaryMasterKey) + d.Set("secondary_key", keys.Model.SecondaryMasterKey) + } - readonlyKeys, err := client.DatabaseAccountsListReadOnlyKeys(ctx, *id) - if err != nil { - if response.WasNotFound(keys.HttpResponse) { - log.Printf("[DEBUG] Read Only Keys were not found for CosmosDB Account %q (Resource Group %q) - removing from state!", id.DatabaseAccountName, id.ResourceGroupName) - d.SetId("") - return nil - } + readonlyKeys, err := client.DatabaseAccountsListReadOnlyKeys(ctx, *id) + if err != nil { + if response.WasNotFound(keys.HttpResponse) { + log.Printf("[DEBUG] Read Only Keys were not found for CosmosDB Account %q (Resource Group %q) - removing from state!", id.DatabaseAccountName, id.ResourceGroupName) + d.SetId("") + return nil + } - return fmt.Errorf("[ERROR] Unable to List read-only keys for CosmosDB Account %s: %s", id.DatabaseAccountName, err) - } - d.Set("primary_readonly_key", readonlyKeys.Model.PrimaryReadonlyMasterKey) - d.Set("secondary_readonly_key", readonlyKeys.Model.SecondaryReadonlyMasterKey) + return fmt.Errorf("listing read-only keys for %s: %w", id, err) + } + if readonlyKeys.Model != nil { + d.Set("primary_readonly_key", readonlyKeys.Model.PrimaryReadonlyMasterKey) + d.Set("secondary_readonly_key", readonlyKeys.Model.SecondaryReadonlyMasterKey) + } - connStringResp, err := client.DatabaseAccountsListConnectionStrings(ctx, *id) - if err != nil { - if response.WasNotFound(keys.HttpResponse) { - log.Printf("[DEBUG] Connection Strings were not found for CosmosDB Account %q (Resource Group %q) - removing from state!", id.ResourceGroupName, id.ResourceGroupName) - d.SetId("") - return nil - } + connStringResp, err := client.DatabaseAccountsListConnectionStrings(ctx, *id) + if err != nil { + if response.WasNotFound(keys.HttpResponse) { + log.Printf("[DEBUG] Connection Strings were not found for CosmosDB Account %q (Resource Group %q) - removing from state!", id.ResourceGroupName, id.ResourceGroupName) + d.SetId("") + return nil + } - return fmt.Errorf("[ERROR] Unable to List connection strings for CosmosDB Account %s: %s", id.DatabaseAccountName, err) - } + return fmt.Errorf("listing connection strings for %s: %w", id, err) + } - var connStrings []string - if connStringResp.Model.ConnectionStrings != nil { - connStrings = make([]string, len(*connStringResp.Model.ConnectionStrings)) - for i, v := range *connStringResp.Model.ConnectionStrings { - connStrings[i] = *v.ConnectionString - if propertyName, propertyExists := connStringPropertyMap[*v.Description]; propertyExists { - d.Set(propertyName, v.ConnectionString) // lintignore:R001 + var connStrings []string + if connStringResp.Model.ConnectionStrings != nil { + connStrings = make([]string, len(*connStringResp.Model.ConnectionStrings)) + for i, v := range *connStringResp.Model.ConnectionStrings { + connStrings[i] = *v.ConnectionString + if propertyName, propertyExists := connStringPropertyMap[*v.Description]; propertyExists { + d.Set(propertyName, v.ConnectionString) // lintignore:R001 + } + } } } } - return tags.FlattenAndSet(d, existing.Model.Tags) + return nil } func resourceCosmosDbAccountDelete(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Cosmos.CosmosDBClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() @@ -1583,7 +1496,7 @@ func resourceCosmosDbAccountDelete(d *pluginsdk.ResourceData, meta interface{}) } if err := client.DatabaseAccountsDeleteThenPoll(ctx, *id); err != nil { - return fmt.Errorf("deleting CosmosDB Account %q (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("deleting %s: %+v", id, err) } // the SDK now will return a `WasNotFound` response even when still deleting @@ -1606,15 +1519,15 @@ func resourceCosmosDbAccountDelete(d *pluginsdk.ResourceData, meta interface{}) } if _, err = stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for CosmosDB Account %q (Resource Group %q) to be deleted: %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("waiting for %s to be deleted: %+v", id, err) } return nil } -func resourceCosmosDbAccountApiUpdate(client *cosmosdb.CosmosDBClient, ctx context.Context, id cosmosdb.DatabaseAccountId, account cosmosdb.DatabaseAccountUpdateParameters, d *pluginsdk.ResourceData) error { +func resourceCosmosDbAccountApiUpdate(client *cosmosdb.CosmosDBClient, ctx context.Context, id cosmosdb.DatabaseAccountId, account cosmosdb.DatabaseAccountUpdateParameters) error { if err := client.DatabaseAccountsUpdateThenPoll(ctx, id, account); err != nil { - return fmt.Errorf("updating CosmosDB Account %q (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("updating %s: %+v", id, err) } stateConf := &pluginsdk.StateChangeConf{ @@ -1625,7 +1538,7 @@ func resourceCosmosDbAccountApiUpdate(client *cosmosdb.CosmosDBClient, ctx conte Refresh: func() (interface{}, string, error) { resp, err2 := client.DatabaseAccountsGet(ctx, id) if err2 != nil || resp.HttpResponse == nil || resp.HttpResponse.StatusCode == http.StatusNotFound { - return nil, "", fmt.Errorf("reading CosmosDB Account %q after update (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err2) + return nil, "", fmt.Errorf("retrieving %s: %+v", id, err2) } status := "Succeeded" @@ -1633,18 +1546,22 @@ func resourceCosmosDbAccountApiUpdate(client *cosmosdb.CosmosDBClient, ctx conte }, } - stateConf.Timeout = d.Timeout(pluginsdk.TimeoutUpdate) + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("internal-error: context had no deadline") + } + stateConf.Timeout = time.Until(deadline) if _, err := stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for the CosmosDB Account %q (Resource Group %q) to update: %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("waiting for %s to update: %+v", id, err) } return nil } -func resourceCosmosDbAccountApiCreateOrUpdate(client *cosmosdb.CosmosDBClient, ctx context.Context, id cosmosdb.DatabaseAccountId, account cosmosdb.DatabaseAccountCreateUpdateParameters, d *pluginsdk.ResourceData) error { +func resourceCosmosDbAccountApiCreateOrUpdate(client *cosmosdb.CosmosDBClient, ctx context.Context, id cosmosdb.DatabaseAccountId, account cosmosdb.DatabaseAccountCreateUpdateParameters) error { if err := client.DatabaseAccountsCreateOrUpdateThenPoll(ctx, id, account); err != nil { - return fmt.Errorf("creating/updating CosmosDB Account %q (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("creating/updating %s: %+v", id, err) } // if a replication location is added or removed it can take some time to provision @@ -1656,7 +1573,7 @@ func resourceCosmosDbAccountApiCreateOrUpdate(client *cosmosdb.CosmosDBClient, c Refresh: func() (interface{}, string, error) { resp, err2 := client.DatabaseAccountsGet(ctx, id) if err2 != nil || resp.HttpResponse == nil || resp.HttpResponse.StatusCode == http.StatusNotFound { - return nil, "", fmt.Errorf("reading CosmosDB Account %q after create/update (Resource Group %q): %+v", id.DatabaseAccountName, id.ResourceGroupName, err2) + return nil, "", fmt.Errorf("retrieving %s: %+v", id, err2) } status := "Succeeded" if props := resp.Model.Properties; props != nil { @@ -1692,14 +1609,14 @@ func resourceCosmosDbAccountApiCreateOrUpdate(client *cosmosdb.CosmosDBClient, c }, } - if d.IsNewResource() { - stateConf.Timeout = d.Timeout(pluginsdk.TimeoutCreate) - } else { - stateConf.Timeout = d.Timeout(pluginsdk.TimeoutUpdate) + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("internal-error: context had no deadline") } + stateConf.Timeout = time.Until(deadline) if _, err := stateConf.WaitForStateContext(ctx); err != nil { - return fmt.Errorf("waiting for the CosmosDB Account %q (Resource Group %q) to provision: %+v", id.DatabaseAccountName, id.ResourceGroupName, err) + return fmt.Errorf("waiting for %s to provision: %+v", id, err) } return nil @@ -1864,18 +1781,6 @@ func findZoneRedundant(locations *[]cosmosdb.Location, id string) bool { return false } -func isServerlessCapacityMode(accResp documentdb.DatabaseAccountGetResults) bool { - if props := accResp.DatabaseAccountGetProperties; props != nil && props.Capabilities != nil { - for _, v := range *props.Capabilities { - if v.Name != nil && *v.Name == "EnableServerless" { - return true - } - } - } - - return false -} - func flattenAzureRmCosmosDBAccountCapabilities(capabilities *[]cosmosdb.Capability) *pluginsdk.Set { s := pluginsdk.Set{ F: resourceAzureRMCosmosDBAccountCapabilitiesHash, @@ -1983,12 +1888,16 @@ func expandCosmosdbAccountBackup(input []interface{}, backupHasChange bool, crea return nil, fmt.Errorf("`tier` can not be set when `type` in `backup` is `Periodic`") } - // Mirror the behavior of the old SDK... periodicModeBackupPolicy := cosmosdb.PeriodicModeBackupPolicy{ - PeriodicModeProperties: &cosmosdb.PeriodicModeProperties{ - BackupIntervalInMinutes: pointer.To(int64(attr["interval_in_minutes"].(int))), - BackupRetentionIntervalInHours: pointer.To(int64(attr["retention_in_hours"].(int))), - }, + PeriodicModeProperties: &cosmosdb.PeriodicModeProperties{}, + } + + if v := attr["interval_in_minutes"].(int); v != 0 { + periodicModeBackupPolicy.PeriodicModeProperties.BackupIntervalInMinutes = pointer.To(int64(v)) + } + + if v := attr["retention_in_hours"].(int); v != 0 { + periodicModeBackupPolicy.PeriodicModeProperties.BackupRetentionIntervalInHours = pointer.To(int64(v)) } if v := attr["storage_redundancy"].(string); v != "" { @@ -2220,6 +2129,36 @@ func flattenCosmosdbAccountGremlinDatabasesToRestore(input *[]cosmosdb.GremlinDa return results } +func expandCosmosdbAccountNetworkBypass(input bool) *cosmosdb.NetworkAclBypass { + if input { + return pointer.To(cosmosdb.NetworkAclBypassAzureServices) + } + return pointer.To(cosmosdb.NetworkAclBypassNone) +} + +func expandCosmosdbAccountPublicNetworkAccess(input bool) *cosmosdb.PublicNetworkAccess { + if input { + return pointer.To(cosmosdb.PublicNetworkAccessEnabled) + } + return pointer.To(cosmosdb.PublicNetworkAccessDisabled) +} + +func flattenCosmosdbAccountReadWriteEndpoints(input *[]cosmosdb.Location) []string { + result := make([]string, 0) + if input == nil { + return result + } + + for _, l := range *input { + if l.DocumentEndpoint == nil { + continue + } + result = append(result, *l.DocumentEndpoint) + } + + return result +} + func checkCapabilitiesCanBeUpdated(kind string, oldCapabilities *[]cosmosdb.Capability, newCapabilities *[]cosmosdb.Capability) bool { // The feedback from service team : capabilities that can be added to an existing account canBeAddedCaps := []string{ @@ -2309,3 +2248,15 @@ func prepareCapabilities(capabilities interface{}) *[]cosmosdb.Capability { } return &output } + +func setInConfig(d *pluginsdk.ResourceData, address string) bool { + // remove function in 5.0 + if features.FivePointOh() { + // No need to check RawConfig in 5.0 as `key_vault_key_id` is no longer computed + // so the existing `GetOk` check will suffice + return true + } + + raw, diags := d.GetRawConfigAt(sdk.ConstructCtyPath(address)) + return !diags.HasError() && !raw.IsNull() +} diff --git a/internal/services/cosmos/cosmosdb_account_resource_test.go b/internal/services/cosmos/cosmosdb_account_resource_test.go index b37cc78027f8..281b9e489802 100644 --- a/internal/services/cosmos/cosmosdb_account_resource_test.go +++ b/internal/services/cosmos/cosmosdb_account_resource_test.go @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/services/cosmos/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" ) @@ -119,7 +120,8 @@ func TestAccCosmosDBAccount_keyVaultUri(t *testing.T) { ), }, data.ImportStep(), - }) + }, + ) } func TestAccCosmosDBAccount_ManagedHSMUri(t *testing.T) { @@ -131,15 +133,33 @@ func TestAccCosmosDBAccount_ManagedHSMUri(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_cosmosdb_account", "test") r := CosmosDBAccountResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ + // Due to the additional test steps, these UUIDs need to be consistent + // can be moved back into the config func in 5.x + raName1, _ := uuid.GenerateUUID() + raName2, _ := uuid.GenerateUUID() + raName3, _ := uuid.GenerateUUID() + uuids := []string{raName1, raName2, raName3} + + steps := []acceptance.TestStep{ { - Config: r.managedHSMKey(data), + Config: r.managedHSMKey(data, uuids, "managed_hsm_key_id"), Check: acceptance.ComposeAggregateTestCheckFunc( checkAccCosmosDBAccount_basic(data, cosmosdb.DefaultConsistencyLevelStrong, 1), ), }, data.ImportStep(), - }) + } + + if !features.FivePointOh() { + // remove cmkArgument parameter from `managedHSMKey` post 5.x + steps = append(steps, acceptance.TestStep{ + // Tests migration path from `managed_hsm_key_id` to `key_vault_key_id` without replacing resource + Config: r.managedHSMKey(data, uuids, "key_vault_key_id"), + }, + ) + } + + data.ResourceTest(t, r, steps) } func TestAccCosmosDBAccount_customerManagedKeyWithIdentity(t *testing.T) { @@ -1440,7 +1460,7 @@ func TestAccCosmosDBAccount_withoutMaxAgeInSeconds(t *testing.T) { }) } -func (t CosmosDBAccountResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { +func (r CosmosDBAccountResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.DatabaseAccountID(state.ID) if err != nil { return nil, err @@ -1461,19 +1481,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -1481,7 +1501,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) basicMongoDB(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -1491,12 +1511,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -1507,7 +1527,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -1515,7 +1535,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func (r CosmosDBAccountResource) requiresImport(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -1547,22 +1567,22 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" - partition_merge_enabled = %t + kind = "%[3]s" + partition_merge_enabled = %[4]t consistency_policy { - consistency_level = "%s" - max_interval_in_seconds = %d - max_staleness_prefix = %d + consistency_level = "%[5]s" + max_interval_in_seconds = %[6]d + max_staleness_prefix = %[7]d } geo_location { @@ -1570,7 +1590,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), partitionMergeEnabled, string(consistency), interval, staleness) +`, data.RandomInteger, data.Locations.Primary, string(kind), partitionMergeEnabled, string(consistency), interval, staleness) } func (CosmosDBAccountResource) consistencyMongoDB(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel, interval, staleness int) string { @@ -1580,12 +1600,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -1596,9 +1616,9 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" - max_interval_in_seconds = %d - max_staleness_prefix = %d + consistency_level = "%[3]s" + max_interval_in_seconds = %[4]d + max_staleness_prefix = %[5]d } geo_location { @@ -1606,7 +1626,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency), interval, staleness) +`, data.RandomInteger, data.Locations.Primary, string(consistency), interval, staleness) } func (CosmosDBAccountResource) completePreReqs(data acceptance.TestData) string { @@ -1834,16 +1854,16 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" multiple_write_locations_enabled = true @@ -1859,12 +1879,12 @@ resource "azurerm_cosmosdb_account" "test" { } geo_location { - location = "%s" + location = "%[4]s" failover_priority = 1 zone_redundant = true } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), data.Locations.Secondary) +`, data.RandomInteger, data.Locations.Primary, string(kind), data.Locations.Secondary) } func (CosmosDBAccountResource) zoneRedundantMongoDB(data acceptance.TestData) string { @@ -1874,12 +1894,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -1903,12 +1923,12 @@ resource "azurerm_cosmosdb_account" "test" { } geo_location { - location = "%s" + location = "%[3]s" failover_priority = 1 zone_redundant = true } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Secondary) +`, data.RandomInteger, data.Locations.Primary, data.Locations.Secondary) } func (r CosmosDBAccountResource) completeUpdated(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2198,11 +2218,11 @@ func (r CosmosDBAccountResource) basicWithResources(data acceptance.TestData, ki %[1]s resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" capabilities { name = "AllowSelfServeUpgradeToMongo36" @@ -2217,7 +2237,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -2233,7 +2253,7 @@ func (r CosmosDBAccountResource) basicWithResourcesMongoDB(data acceptance.TestD %[1]s resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -2260,7 +2280,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -2283,29 +2303,29 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { consistency_level = "Strong" } - %s + %[4]s geo_location { location = azurerm_resource_group.test.location failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), capeTf) +`, data.RandomInteger, data.Locations.Primary, string(kind), capeTf) } func (CosmosDBAccountResource) geoLocationUpdate(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2315,19 +2335,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -2336,11 +2356,11 @@ resource "azurerm_cosmosdb_account" "test" { } geo_location { - location = "%s" + location = "%[5]s" failover_priority = 1 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency), data.Locations.Secondary) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency), data.Locations.Secondary) } func (CosmosDBAccountResource) zoneRedundantMongoDBUpdate(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2353,12 +2373,12 @@ variable "geo_location" { })) default = [ { - location = "%s" + location = "%[1]s" failover_priority = 0 zone_redundant = false }, { - location = "%s" + location = "%[2]s" failover_priority = 1 zone_redundant = true } @@ -2370,12 +2390,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[3]d" + location = "%[1]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[3]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -2389,7 +2409,7 @@ resource "azurerm_cosmosdb_account" "test" { automatic_failover_enabled = true consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } dynamic "geo_location" { @@ -2401,7 +2421,7 @@ resource "azurerm_cosmosdb_account" "test" { } } } -`, data.Locations.Primary, data.Locations.Secondary, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.Locations.Primary, data.Locations.Secondary, data.RandomInteger, string(consistency)) } func (CosmosDBAccountResource) vNetFiltersPreReqs(data acceptance.TestData) string { @@ -2492,21 +2512,21 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" free_tier_enabled = true consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -2514,7 +2534,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) analyticalStorage(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel, enableAnalyticalStorage bool) string { @@ -2524,21 +2544,21 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" - analytical_storage_enabled = %t + analytical_storage_enabled = %[4]t consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -2546,7 +2566,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), enableAnalyticalStorage, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), enableAnalyticalStorage, string(consistency)) } func (CosmosDBAccountResource) mongoAnalyticalStorage(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2556,12 +2576,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -2570,7 +2590,7 @@ resource "azurerm_cosmosdb_account" "test" { analytical_storage_enabled = true consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } capabilities { @@ -2582,7 +2602,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func checkAccCosmosDBAccount_basic(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel, locationCount int) acceptance.TestCheckFunc { @@ -2619,16 +2639,16 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" public_network_access_enabled = true capabilities { @@ -2636,7 +2656,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -2644,7 +2664,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) key_vault_uri(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2661,8 +2681,8 @@ provider "azurerm" { provider "azuread" {} resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } data "azuread_service_principal" "cosmosdb" { @@ -2672,7 +2692,7 @@ data "azuread_service_principal" "cosmosdb" { data "azurerm_client_config" "current" {} resource "azurerm_key_vault" "test" { - name = "acctestkv-%s" + name = "acctestkv-%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name tenant_id = data.azurerm_client_config.current.tenant_id @@ -2726,7 +2746,7 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" + name = "key-%[3]s" key_vault_id = azurerm_key_vault.test.id key_type = "RSA" key_size = 2048 @@ -2742,11 +2762,11 @@ resource "azurerm_key_vault_key" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[4]s" key_vault_key_id = azurerm_key_vault_key.test.versionless_id capabilities { @@ -2754,7 +2774,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -2762,7 +2782,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, string(kind), string(consistency)) } func (CosmosDBAccountResource) keyVaultKeyUriWithSystemAssignedIdentity(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2779,8 +2799,8 @@ provider "azurerm" { provider "azuread" {} resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } data "azurerm_client_config" "current" {} @@ -2796,7 +2816,7 @@ resource "azurerm_user_assigned_identity" "test" { } resource "azurerm_key_vault" "test" { - name = "acctestkv-%s" + name = "acctestkv-%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name tenant_id = data.azurerm_client_config.current.tenant_id @@ -2872,7 +2892,7 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" + name = "key-%[3]s" key_vault_id = azurerm_key_vault.test.id key_type = "RSA" key_size = 2048 @@ -2888,11 +2908,11 @@ resource "azurerm_key_vault_key" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[4]s" key_vault_key_id = azurerm_key_vault_key.test.versionless_id capabilities { @@ -2900,7 +2920,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -2912,7 +2932,7 @@ resource "azurerm_cosmosdb_account" "test" { type = "SystemAssigned" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, string(kind), string(consistency)) } func (CosmosDBAccountResource) keyVaultKeyUriWithSystemAssignedAndUserAssignedIdentity(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -2929,8 +2949,8 @@ provider "azurerm" { provider "azuread" {} resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } data "azurerm_client_config" "current" {} @@ -2946,7 +2966,7 @@ resource "azurerm_user_assigned_identity" "test" { } resource "azurerm_key_vault" "test" { - name = "acctestkv-%s" + name = "acctestkv-%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name tenant_id = data.azurerm_client_config.current.tenant_id @@ -3022,7 +3042,7 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" + name = "key-%[3]s" key_vault_id = azurerm_key_vault.test.id key_type = "RSA" key_size = 2048 @@ -3038,11 +3058,11 @@ resource "azurerm_key_vault_key" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[4]s" key_vault_key_id = azurerm_key_vault_key.test.versionless_id capabilities { @@ -3050,7 +3070,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -3065,7 +3085,7 @@ resource "azurerm_cosmosdb_account" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, string(kind), string(consistency)) } func (CosmosDBAccountResource) keyVaultKeyUriWithUserAssignedIdentity(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3082,8 +3102,8 @@ provider "azurerm" { provider "azuread" {} resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } data "azurerm_client_config" "current" {} @@ -3099,7 +3119,7 @@ resource "azurerm_user_assigned_identity" "test" { } resource "azurerm_key_vault" "test" { - name = "acctestkv-%s" + name = "acctestkv-%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name tenant_id = data.azurerm_client_config.current.tenant_id @@ -3175,7 +3195,7 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" + name = "key-%[3]s" key_vault_id = azurerm_key_vault.test.id key_type = "RSA" key_size = 2048 @@ -3191,11 +3211,11 @@ resource "azurerm_key_vault_key" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[4]s" key_vault_key_id = azurerm_key_vault_key.test.versionless_id capabilities { @@ -3203,7 +3223,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -3218,15 +3238,11 @@ resource "azurerm_cosmosdb_account" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, string(kind), string(consistency)) } -func (CosmosDBAccountResource) managedHSMKey(data acceptance.TestData) string { +func (CosmosDBAccountResource) managedHSMKey(data acceptance.TestData, uuids []string, cmkArgument string) string { // Purge Protection must be enabled to configure Managed HSM Key: https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-customer-managed-keys-mhsm#configure-your-azure-managed-hsm-key-vault - // hsmTemplate := customermanagedkeys.ManagedHSMKeyTempalte(data.RandomInteger, data.RandomString, enablePurgeProtection, []string{"data.azuread_service_principal.cosmosdb.id"}) - raName1, _ := uuid.GenerateUUID() - raName2, _ := uuid.GenerateUUID() - raName3, _ := uuid.GenerateUUID() return fmt.Sprintf(` provider "azurerm" { features {} @@ -3390,7 +3406,7 @@ resource "azurerm_cosmosdb_account" "test" { resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" kind = "MongoDB" - managed_hsm_key_id = azurerm_key_vault_managed_hardware_security_module_key.test.id + %[6]s = azurerm_key_vault_managed_hardware_security_module_key.test.id capabilities { name = "EnableMongo" @@ -3411,10 +3427,8 @@ resource "azurerm_cosmosdb_account" "test" { azurerm_user_assigned_identity.test.id ] } - - // depends_on = [azurerm_key_vault_managed_hardware_security_module_role_assignment.racosmos] } -`, data.RandomInteger, data.Locations.Primary, raName1, raName2, raName3) +`, data.RandomInteger, data.Locations.Primary, uuids[0], uuids[1], uuids[2], cmkArgument) } func (CosmosDBAccountResource) systemAssignedUserAssignedIdentity(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3424,8 +3438,8 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_user_assigned_identity" "test" { @@ -3435,7 +3449,7 @@ resource "azurerm_user_assigned_identity" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -3446,7 +3460,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -3461,7 +3475,7 @@ resource "azurerm_cosmosdb_account" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func (CosmosDBAccountResource) multipleUserAssignedIdentity(data acceptance.TestData, identityResource string) string { @@ -3471,8 +3485,8 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_user_assigned_identity" "test" { @@ -3488,13 +3502,13 @@ resource "azurerm_user_assigned_identity" "test2" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" kind = "MongoDB" - default_identity_type = join("=", ["UserAssignedIdentity", %[4]s]) + default_identity_type = join("=", ["UserAssignedIdentity", %[3]s]) capabilities { name = "EnableMongo" @@ -3513,12 +3527,12 @@ resource "azurerm_cosmosdb_account" "test" { identity { type = "UserAssigned" - identity_ids = [%[4]s] + identity_ids = [%[3]s] } depends_on = [azurerm_user_assigned_identity.test, azurerm_user_assigned_identity.test2] } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, identityResource) +`, data.RandomInteger, data.Locations.Primary, identityResource) } func (CosmosDBAccountResource) multipleUserAssignedIdentityBaseState(data acceptance.TestData) string { @@ -3528,8 +3542,8 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_user_assigned_identity" "test" { @@ -3545,7 +3559,7 @@ resource "azurerm_user_assigned_identity" "test2" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -3568,7 +3582,7 @@ resource "azurerm_cosmosdb_account" "test" { depends_on = [azurerm_user_assigned_identity.test, azurerm_user_assigned_identity.test2] } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary) } func (CosmosDBAccountResource) basicWithBackupPeriodic(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3578,19 +3592,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3605,7 +3619,7 @@ resource "azurerm_cosmosdb_account" "test" { storage_redundancy = "Geo" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) storageRedundancyUndefined(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3615,19 +3629,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3641,7 +3655,7 @@ resource "azurerm_cosmosdb_account" "test" { retention_in_hours = 10 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) basicWithBackupPeriodicUpdate(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3651,19 +3665,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3678,7 +3692,7 @@ resource "azurerm_cosmosdb_account" "test" { storage_redundancy = "Local" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) basicWithBackupContinuous(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel, tier cosmosdb.ContinuousTier) string { @@ -3688,19 +3702,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3710,10 +3724,10 @@ resource "azurerm_cosmosdb_account" "test" { backup { type = "Continuous" - tier = "%s" + tier = "%[5]s" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency), string(tier)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency), string(tier)) } func (CosmosDBAccountResource) basicWithBackupContinuousUpdate(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3723,21 +3737,21 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" is_virtual_network_filter_enabled = true consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3749,7 +3763,7 @@ resource "azurerm_cosmosdb_account" "test" { type = "Continuous" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) basicWithNetworkBypassTemplate(data acceptance.TestData) string { @@ -3794,17 +3808,17 @@ resource "azurerm_synapse_workspace" "test" { func (r CosmosDBAccountResource) basicWithNetworkBypass(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { return fmt.Sprintf(` -%s +%[1]s resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3820,17 +3834,17 @@ resource "azurerm_cosmosdb_account" "test" { func (r CosmosDBAccountResource) basicWithoutNetworkBypass(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { return fmt.Sprintf(` -%s +%[1]s resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -3849,12 +3863,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -3862,7 +3876,7 @@ resource "azurerm_cosmosdb_account" "test" { mongo_server_version = "3.2" consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -3870,7 +3884,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func (CosmosDBAccountResource) updateMongoDBVersionCapabilities(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3880,12 +3894,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -3897,7 +3911,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -3909,7 +3923,7 @@ resource "azurerm_cosmosdb_account" "test" { name = "EnableMongo16MBDocumentSupport" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func (CosmosDBAccountResource) basicMongoDBVersion36(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3919,12 +3933,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -3932,7 +3946,7 @@ resource "azurerm_cosmosdb_account" "test" { mongo_server_version = "3.6" consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -3940,7 +3954,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func (CosmosDBAccountResource) basicMongoDBVersion40(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -3950,12 +3964,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -3987,7 +4001,7 @@ resource "azurerm_cosmosdb_account" "test" { } consistency_policy { - consistency_level = "%s" + consistency_level = "%[3]s" } geo_location { @@ -3995,7 +4009,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(consistency)) } func (CosmosDBAccountResource) basicMongoDBVersion(data acceptance.TestData, consistency cosmosdb.DefaultConsistencyLevel, version string) string { @@ -4005,24 +4019,24 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" kind = "MongoDB" - mongo_server_version = "%s" + mongo_server_version = "%[3]s" capabilities { name = "EnableMongo" } consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -4030,7 +4044,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, version, string(consistency)) } func (CosmosDBAccountResource) basicWithLocalAuthenticationDisabled(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4040,19 +4054,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -4062,7 +4076,7 @@ resource "azurerm_cosmosdb_account" "test" { local_authentication_disabled = true } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) basicWithBurstCapacityEnabled(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4072,19 +4086,19 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -4094,7 +4108,7 @@ resource "azurerm_cosmosdb_account" "test" { burst_capacity_enabled = true } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) updateAnalyticalStorage(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, schemaType cosmosdb.AnalyticalStorageSchemaType, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4104,24 +4118,24 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" analytical_storage_enabled = false analytical_storage { - schema_type = "%s" + schema_type = "%[4]s" } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -4129,7 +4143,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(schemaType), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(schemaType), string(consistency)) } func (CosmosDBAccountResource) updateCapacity(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, totalThroughputLimit int, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4139,24 +4153,24 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" analytical_storage_enabled = false capacity { - total_throughput_limit = %d + total_throughput_limit = %[4]d } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -4164,7 +4178,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), totalThroughputLimit, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), totalThroughputLimit, string(consistency)) } func (CosmosDBAccountResource) defaultIdentity(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, defaultIdentity string, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4174,20 +4188,20 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" - default_identity_type = "%s" + kind = "%[3]s" + default_identity_type = "%[4]s" consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -4195,7 +4209,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), defaultIdentity, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), defaultIdentity, string(consistency)) } func (CosmosDBAccountResource) updateDefaultIdentity(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, defaultIdentity string, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4205,24 +4219,24 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" - default_identity_type = %s + kind = "%[3]s" + default_identity_type = %[4]s identity { type = "SystemAssigned" } consistency_policy { - consistency_level = "%s" + consistency_level = "%[5]s" } geo_location { @@ -4230,7 +4244,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), defaultIdentity, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), defaultIdentity, string(consistency)) } func (CosmosDBAccountResource) updateDefaultIdentityUserAssigned(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, defaultIdentity string, consistency cosmosdb.DefaultConsistencyLevel, identityType string) string { @@ -4240,8 +4254,8 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_user_assigned_identity" "test" { @@ -4251,20 +4265,20 @@ resource "azurerm_user_assigned_identity" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" - default_identity_type = %s + kind = "%[3]s" + default_identity_type = %[4]s identity { - type = "%s" + type = "%[5]s" identity_ids = [azurerm_user_assigned_identity.test.id] } consistency_policy { - consistency_level = "%s" + consistency_level = "%[6]s" } geo_location { @@ -4272,7 +4286,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), defaultIdentity, identityType, string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), defaultIdentity, identityType, string(consistency)) } func (CosmosDBAccountResource) defaultCreateMode(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4282,20 +4296,20 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" create_mode = "Default" consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } backup { @@ -4307,7 +4321,7 @@ resource "azurerm_cosmosdb_account" "test" { failover_priority = 0 } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) restoreCreateMode(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4317,12 +4331,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test1" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -4348,13 +4362,13 @@ resource "azurerm_cosmosdb_account" "test1" { } resource "azurerm_cosmosdb_mongo_database" "test" { - name = "acctest-mongodb-%d" + name = "acctest-mongodb-%[1]d" resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name account_name = azurerm_cosmosdb_account.test1.name } resource "azurerm_cosmosdb_mongo_collection" "test" { - name = "acctest-mongodb-coll-%d" + name = "acctest-mongodb-coll-%[1]d" resource_group_name = azurerm_cosmosdb_mongo_database.test.resource_group_name account_name = azurerm_cosmosdb_mongo_database.test.account_name database_name = azurerm_cosmosdb_mongo_database.test.name @@ -4379,18 +4393,18 @@ data "azurerm_cosmosdb_restorable_database_accounts" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca2-%d" + name = "acctest-ca2-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" capabilities { name = "EnableMongo" } consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -4421,7 +4435,7 @@ resource "azurerm_cosmosdb_account" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) tablesToRestore(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4431,12 +4445,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test1" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -4461,13 +4475,13 @@ resource "azurerm_cosmosdb_account" "test1" { } resource "azurerm_cosmosdb_table" "test" { - name = "acctest-sqltable-%d" + name = "acctest-sqltable-%[1]d" resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name account_name = azurerm_cosmosdb_account.test1.name } resource "azurerm_cosmosdb_table" "test2" { - name = "acctest-sqltable2-%d" + name = "acctest-sqltable2-%[1]d" resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name account_name = azurerm_cosmosdb_account.test1.name @@ -4482,18 +4496,18 @@ data "azurerm_cosmosdb_restorable_database_accounts" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca2-%d" + name = "acctest-ca2-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" capabilities { name = "EnableTable" } consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -4520,7 +4534,7 @@ resource "azurerm_cosmosdb_account" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (CosmosDBAccountResource) gremlinDatabasesToRestore(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string { @@ -4530,12 +4544,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-cosmos-%d" - location = "%s" + name = "acctestRG-cosmos-%[1]d" + location = "%[2]s" } resource "azurerm_cosmosdb_account" "test1" { - name = "acctest-ca-%d" + name = "acctest-ca-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" @@ -4560,13 +4574,13 @@ resource "azurerm_cosmosdb_account" "test1" { } resource "azurerm_cosmosdb_gremlin_database" "test" { - name = "acctest-gremlindb-%d" + name = "acctest-gremlindb-%[1]d" resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name account_name = azurerm_cosmosdb_account.test1.name } resource "azurerm_cosmosdb_gremlin_graph" "test" { - name = "acctest-CGRPC-%d" + name = "acctest-CGRPC-%[1]d" resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name account_name = azurerm_cosmosdb_account.test1.name database_name = azurerm_cosmosdb_gremlin_database.test.name @@ -4575,7 +4589,7 @@ resource "azurerm_cosmosdb_gremlin_graph" "test" { } resource "azurerm_cosmosdb_gremlin_graph" "test2" { - name = "acctest-CGRPC2-%d" + name = "acctest-CGRPC2-%[1]d" resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name account_name = azurerm_cosmosdb_account.test1.name database_name = azurerm_cosmosdb_gremlin_database.test.name @@ -4593,18 +4607,18 @@ data "azurerm_cosmosdb_restorable_database_accounts" "test" { } resource "azurerm_cosmosdb_account" "test" { - name = "acctest-ca2-%d" + name = "acctest-ca2-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name offer_type = "Standard" - kind = "%s" + kind = "%[3]s" capabilities { name = "EnableGremlin" } consistency_policy { - consistency_level = "%s" + consistency_level = "%[4]s" } geo_location { @@ -4635,7 +4649,7 @@ resource "azurerm_cosmosdb_account" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, string(kind), string(consistency)) +`, data.RandomInteger, data.Locations.Primary, string(kind), string(consistency)) } func (r CosmosDBAccountResource) ipRangeFilters(data acceptance.TestData) string { diff --git a/internal/services/cosmos/cosmosdb_cassandra_datacenter_resource.go b/internal/services/cosmos/cosmosdb_cassandra_datacenter_resource.go index 9346821aea2a..84c749c7556b 100644 --- a/internal/services/cosmos/cosmosdb_cassandra_datacenter_resource.go +++ b/internal/services/cosmos/cosmosdb_cassandra_datacenter_resource.go @@ -13,11 +13,11 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/keyvault" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" "github.com/hashicorp/go-azure-sdk/resource-manager/cosmosdb/2023-04-15/managedcassandras" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" @@ -69,7 +69,7 @@ func resourceCassandraDatacenter() *pluginsdk.Resource { "backup_storage_customer_key_uri": { Type: pluginsdk.TypeString, Optional: true, - ValidateFunc: keyVaultValidate.NestedItemId, + ValidateFunc: keyvault.ValidateNestedItemID(keyvault.VersionTypeVersioned, keyvault.NestedItemTypeKey), }, "base64_encoded_yaml_fragment": { @@ -88,7 +88,7 @@ func resourceCassandraDatacenter() *pluginsdk.Resource { "managed_disk_customer_key_uri": { Type: pluginsdk.TypeString, Optional: true, - ValidateFunc: keyVaultValidate.NestedItemId, + ValidateFunc: keyvault.ValidateNestedItemID(keyvault.VersionTypeVersioned, keyvault.NestedItemTypeKey), }, "node_count": { diff --git a/website/docs/5.0-upgrade-guide.html.markdown b/website/docs/5.0-upgrade-guide.html.markdown index 7aa05c61b0a6..ce3b26612b5c 100644 --- a/website/docs/5.0-upgrade-guide.html.markdown +++ b/website/docs/5.0-upgrade-guide.html.markdown @@ -329,6 +329,7 @@ Please follow the format in the example below for listing breaking changes in re ### `azurerm_cosmosdb_account` +* The deprecated `managed_hsm_key_id` property has been removed in favour of the `key_vault_key_id` property. * The `minimal_tls_version` property no longer accepts `Tls` or `Tls11` as a value. ### `azurerm_container_app_environment` diff --git a/website/docs/r/cosmosdb_account.html.markdown b/website/docs/r/cosmosdb_account.html.markdown index 8ae45f5e03de..817eccedb79b 100644 --- a/website/docs/r/cosmosdb_account.html.markdown +++ b/website/docs/r/cosmosdb_account.html.markdown @@ -154,7 +154,7 @@ The following arguments are supported: * `burst_capacity_enabled` - (Optional) Enable burst capacity for this Cosmos DB account. Defaults to `false`. -* `public_network_access_enabled` - (Optional) Whether or not public network access is allowed for this CosmosDB account. Defaults to `true`. +* `public_network_access_enabled` - (Optional) Whether public network access is allowed for this CosmosDB account. Defaults to `true`. * `capabilities` - (Optional) The capabilities which should be enabled for this Cosmos DB account. Value is a `capabilities` block as defined below. @@ -162,15 +162,7 @@ The following arguments are supported: * `key_vault_key_id` - (Optional) A versionless Key Vault Key ID for CMK encryption. Changing this forces a new resource to be created. -~> **Note:** When referencing an `azurerm_key_vault_key` resource, use `versionless_id` instead of `id` - -~> **Note:** In order to use a `Custom Key` from Key Vault for encryption you must grant Azure Cosmos DB Service access to your key vault. For instructions on how to configure your Key Vault correctly please refer to the [product documentation](https://docs.microsoft.com/azure/cosmos-db/how-to-setup-cmk#add-an-access-policy-to-your-azure-key-vault-instance) - -* `managed_hsm_key_id` - (Optional) A versionless Managed HSM Key ID for CMK encryption. Changing this forces a new resource to be created. - -~> **Note:** When referencing an `azurerm_key_vault_managed_hardware_security_module_key` resource, use `id` instead of `versioned_id` - -~> **Note:** In order to use a `Custom Key` from Managed HSM for encryption you must grant Azure Cosmos DB Service access to your Managed HSM. For instructions on how to configure your Key Vault correctly please refer to the [product documentation](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-customer-managed-keys-mhsm) +~> **Note:** In order to use a `Custom Key` from a Key Vault or Managed HSM Vault for encryption, you must grant Azure Cosmos DB Service access to your key vault. For instructions on how to configure your Key Vault correctly please refer to the [product documentation](https://docs.microsoft.com/azure/cosmos-db/how-to-setup-cmk#add-an-access-policy-to-your-azure-key-vault-instance) * `virtual_network_rule` - (Optional) Specifies a `virtual_network_rule` block as defined below, used to define which subnets are allowed to access this CosmosDB account.