From 5b86cc63e18f1185bed3d91ea058968932a389ed Mon Sep 17 00:00:00 2001 From: ms-henglu Date: Wed, 30 Jun 2021 10:36:07 +0800 Subject: [PATCH 1/4] `azurerm_cognitive_account` supports `identity` `storage` `disable_local_auth` `fqdns` `public_network_access_enabled` and `restrict_outbound_network_access` --- .../cognitive/cognitive_account_resource.go | 265 +++++++++++++++++- .../cognitive_account_resource_test.go | 198 +++++++++++++ .../docs/r/cognitive_account.html.markdown | 30 ++ 3 files changed, 481 insertions(+), 12 deletions(-) diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource.go b/azurerm/internal/services/cognitive/cognitive_account_resource.go index 6028cf6f9df8..954f52ab11cd 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource.go @@ -15,8 +15,11 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cognitive/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cognitive/validate" + msiparse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/msi/parse" + msiValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/msi/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" networkParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/parse" + storageValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/set" @@ -104,6 +107,69 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, false), }, + "custom_subdomain_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "disable_local_auth": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "fqdns": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + + "identity": { + Type: pluginsdk.TypeList, + Optional: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "type": { + Type: pluginsdk.TypeString, + Optional: true, + Default: string(cognitiveservices.ResourceIdentityTypeNone), + ValidateFunc: validation.StringInSlice([]string{ + string(cognitiveservices.ResourceIdentityTypeNone), + string(cognitiveservices.ResourceIdentityTypeSystemAssigned), + string(cognitiveservices.ResourceIdentityTypeUserAssigned), + string(cognitiveservices.ResourceIdentityTypeSystemAssignedUserAssigned), + }, false), + }, + + "principal_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "identity_ids": { + Type: pluginsdk.TypeSet, + Optional: true, + MinItems: 1, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: msiValidate.UserAssignedIdentityID, + }, + }, + }, + }, + }, + "qna_runtime_endpoint": { Type: pluginsdk.TypeString, Optional: true, @@ -146,11 +212,36 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, }, - "custom_subdomain_name": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, + "public_network_access_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "restrict_outbound_network_access": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "storage": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "resource_id": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: storageValidate.StorageAccountID, + }, + + "identity_client_id": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.IsUUID, + }, + }, + }, }, "tags": tags.Schema(), @@ -218,19 +309,35 @@ func resourceCognitiveAccountCreate(d *pluginsdk.ResourceData, meta interface{}) locks.MultipleByName(&virtualNetworkNames, network.VirtualNetworkResourceName) defer locks.UnlockMultipleByName(&virtualNetworkNames, network.VirtualNetworkResourceName) + publicNetworkAccess := cognitiveservices.PublicNetworkAccessEnabled + if !d.Get("public_network_access_enabled").(bool) { + publicNetworkAccess = cognitiveservices.PublicNetworkAccessDisabled + } props := cognitiveservices.Account{ Kind: utils.String(kind), Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), Sku: sku, Properties: &cognitiveservices.AccountProperties{ - APIProperties: &cognitiveservices.APIProperties{}, - NetworkAcls: networkAcls, - CustomSubDomainName: utils.String(d.Get("custom_subdomain_name").(string)), + APIProperties: &cognitiveservices.APIProperties{}, + NetworkAcls: networkAcls, + CustomSubDomainName: utils.String(d.Get("custom_subdomain_name").(string)), + AllowedFqdnList: utils.ExpandStringSlice(d.Get("fqdns").([]interface{})), + PublicNetworkAccess: publicNetworkAccess, + UserOwnedStorage: expandCognitiveAccountStorage(d.Get("storage").([]interface{})), + RestrictOutboundNetworkAccess: utils.Bool(d.Get("restrict_outbound_network_access").(bool)), + DisableLocalAuth: utils.Bool(d.Get("disable_local_auth").(bool)), }, Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } + identityRaw := d.Get("identity").([]interface{}) + identity, err := expandCognitiveAccountIdentity(identityRaw) + if err != nil { + return fmt.Errorf("Error expanding `identity`: %+v", err) + } + props.Identity = identity + if kind == "QnAMaker" { if v, ok := d.GetOk("qna_runtime_endpoint"); ok && v != "" { props.Properties.APIProperties.QnaRuntimeEndpoint = utils.String(v.(string)) @@ -291,15 +398,31 @@ func resourceCognitiveAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) locks.MultipleByName(&virtualNetworkNames, network.VirtualNetworkResourceName) defer locks.UnlockMultipleByName(&virtualNetworkNames, network.VirtualNetworkResourceName) + publicNetworkAccess := cognitiveservices.PublicNetworkAccessEnabled + if !d.Get("public_network_access_enabled").(bool) { + publicNetworkAccess = cognitiveservices.PublicNetworkAccessDisabled + } + props := cognitiveservices.Account{ Sku: sku, Properties: &cognitiveservices.AccountProperties{ - APIProperties: &cognitiveservices.APIProperties{}, - NetworkAcls: networkAcls, - CustomSubDomainName: utils.String(d.Get("custom_subdomain_name").(string)), + APIProperties: &cognitiveservices.APIProperties{}, + NetworkAcls: networkAcls, + CustomSubDomainName: utils.String(d.Get("custom_subdomain_name").(string)), + AllowedFqdnList: utils.ExpandStringSlice(d.Get("fqdns").([]interface{})), + PublicNetworkAccess: publicNetworkAccess, + UserOwnedStorage: expandCognitiveAccountStorage(d.Get("storage").([]interface{})), + RestrictOutboundNetworkAccess: utils.Bool(d.Get("restrict_outbound_network_access").(bool)), + DisableLocalAuth: utils.Bool(d.Get("disable_local_auth").(bool)), }, Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } + identityRaw := d.Get("identity").([]interface{}) + identity, err := expandCognitiveAccountIdentity(identityRaw) + if err != nil { + return fmt.Errorf("Error expanding `identity`: %+v", err) + } + props.Identity = identity if kind := d.Get("kind"); kind == "QnAMaker" { if v, ok := d.GetOk("qna_runtime_endpoint"); ok && v != "" { @@ -363,6 +486,12 @@ func resourceCognitiveAccountRead(d *pluginsdk.ResourceData, meta interface{}) e d.Set("sku_name", sku.Name) } + identity, err := flattenCognitiveAccountIdentity(resp.Identity) + if err != nil { + return err + } + d.Set("identity", identity) + if props := resp.Properties; props != nil { if apiProps := props.APIProperties; apiProps != nil { d.Set("qna_runtime_endpoint", apiProps.QnaRuntimeEndpoint) @@ -370,7 +499,18 @@ func resourceCognitiveAccountRead(d *pluginsdk.ResourceData, meta interface{}) e d.Set("endpoint", props.Endpoint) d.Set("custom_subdomain_name", props.CustomSubDomainName) if err := d.Set("network_acls", flattenCognitiveAccountNetworkAcls(props.NetworkAcls)); err != nil { - return fmt.Errorf("setting `network_acls` for Cognitive Account %q: %+v", *resp.Name, err) + return fmt.Errorf("setting `network_acls` for Cognitive Account %q: %+v", id, err) + } + d.Set("fqdns", utils.FlattenStringSlice(props.AllowedFqdnList)) + d.Set("public_network_access_enabled", props.PublicNetworkAccess == cognitiveservices.PublicNetworkAccessEnabled) + if err := d.Set("storage", flattenCognitiveAccountStorage(props.UserOwnedStorage)); err != nil { + return fmt.Errorf("setting `storages` for Cognitive Account %q: %+v", id, err) + } + if props.RestrictOutboundNetworkAccess != nil { + d.Set("restrict_outbound_network_access", *props.RestrictOutboundNetworkAccess) + } + if props.DisableLocalAuth != nil { + d.Set("disable_local_auth", *props.DisableLocalAuth) } } @@ -492,6 +632,58 @@ func expandCognitiveAccountNetworkAcls(input []interface{}) (*cognitiveservices. return &ruleSet, subnetIds } +func expandCognitiveAccountStorage(input []interface{}) *[]cognitiveservices.UserOwnedStorage { + if len(input) == 0 { + return nil + } + results := make([]cognitiveservices.UserOwnedStorage, 0) + for _, v := range input { + value := v.(map[string]interface{}) + results = append(results, cognitiveservices.UserOwnedStorage{ + ResourceID: utils.String(value["resource_id"].(string)), + IdentityClientID: utils.String(value["identity_client_id"].(string)), + }) + } + return &results +} + +func expandCognitiveAccountIdentity(vs []interface{}) (*cognitiveservices.Identity, error) { + if len(vs) == 0 { + return &cognitiveservices.Identity{ + Type: cognitiveservices.ResourceIdentityTypeNone, + }, nil + } + + v := vs[0].(map[string]interface{}) + managedServiceIdentity := cognitiveservices.Identity{ + Type: cognitiveservices.ResourceIdentityType(v["type"].(string)), + } + + var identityIdSet []interface{} + if identityIds, ok := v["identity_ids"]; ok { + identityIdSet = identityIds.(*pluginsdk.Set).List() + } + + // If type contains `UserAssigned`, `identity_ids` must be specified and have at least 1 element + if managedServiceIdentity.Type == cognitiveservices.ResourceIdentityTypeUserAssigned || managedServiceIdentity.Type == cognitiveservices.ResourceIdentityTypeSystemAssignedUserAssigned { + if len(identityIdSet) == 0 { + return nil, fmt.Errorf("`identity_ids` must have at least 1 element when `type` includes `UserAssigned`") + } + + userAssignedIdentities := make(map[string]*cognitiveservices.UserAssignedIdentity) + for _, id := range identityIdSet { + userAssignedIdentities[id.(string)] = &cognitiveservices.UserAssignedIdentity{} + } + + managedServiceIdentity.UserAssignedIdentities = userAssignedIdentities + } else if len(identityIdSet) > 0 { + // If type does _not_ contain `UserAssigned` (i.e. is set to `SystemAssigned` or defaulted to `None`), `identity_ids` is not allowed + return nil, fmt.Errorf("`identity_ids` can only be specified when `type` includes `UserAssigned`; but `type` is currently %q", managedServiceIdentity.Type) + } + + return &managedServiceIdentity, nil +} + func flattenCognitiveAccountNetworkAcls(input *cognitiveservices.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{} @@ -532,3 +724,52 @@ func flattenCognitiveAccountNetworkAcls(input *cognitiveservices.NetworkRuleSet) }, } } + +func flattenCognitiveAccountStorage(input *[]cognitiveservices.UserOwnedStorage) []interface{} { + if input == nil { + return []interface{}{} + } + results := make([]interface{}, 0) + for _, v := range *input { + value := make(map[string]interface{}) + if v.ResourceID != nil { + value["resource_id"] = *v.ResourceID + } + if v.IdentityClientID != nil { + value["identity_client_id"] = *v.IdentityClientID + } + results = append(results, value) + } + return results +} + +func flattenCognitiveAccountIdentity(identity *cognitiveservices.Identity) ([]interface{}, error) { + if identity == nil || identity.Type == cognitiveservices.ResourceIdentityTypeNone { + return make([]interface{}, 0), nil + } + + result := make(map[string]interface{}) + result["type"] = string(identity.Type) + + if identity.PrincipalID != nil { + result["principal_id"] = *identity.PrincipalID + } + + if identity.TenantID != nil { + result["tenant_id"] = *identity.TenantID + } + + identityIds := make([]interface{}, 0) + if identity.UserAssignedIdentities != nil { + for key := range identity.UserAssignedIdentities { + parsedId, err := msiparse.UserAssignedIdentityID(key) + if err != nil { + return nil, err + } + identityIds = append(identityIds, parsedId.ID()) + } + result["identity_ids"] = pluginsdk.NewSet(pluginsdk.HashString, identityIds) + } + + return []interface{}{result}, nil +} diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go index 3d8516d05ff7..c89e55a350d4 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go @@ -6,6 +6,7 @@ import ( "regexp" "testing" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" @@ -55,6 +56,23 @@ func TestAccCognitiveAccount_speechServices(t *testing.T) { }) } +func TestAccCognitiveAccount_speechServicesWithStorage(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_cognitive_account", "test") + r := CognitiveAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.speechServicesWithStorage(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("primary_access_key").Exists(), + check.That(data.ResourceName).Key("secondary_access_key").Exists(), + ), + }, + data.ImportStep(), + }) +} + func TestAccCognitiveAccount_requiresImport(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_cognitive_account", "test") r := CognitiveAccountResource{} @@ -218,6 +236,46 @@ func TestAccCognitiveAccount_networkAcls(t *testing.T) { }) } +func TestAccCognitiveAccount_identity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_cognitive_account", "test") + r := CognitiveAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.identitySystemAssignedUserAssigned(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.0.principal_id").MatchesRegex(validate.UUIDRegExp), + check.That(data.ResourceName).Key("identity.0.tenant_id").MatchesRegex(validate.UUIDRegExp), + ), + }, + data.ImportStep(), + { + Config: r.identityUserAssigned(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.identitySystemAssigned(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.0.principal_id").MatchesRegex(validate.UUIDRegExp), + check.That(data.ResourceName).Key("identity.0.tenant_id").MatchesRegex(validate.UUIDRegExp), + ), + }, + data.ImportStep(), + }) +} + func (t CognitiveAccountResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.AccountID(state.ID) if err != nil { @@ -253,6 +311,96 @@ resource "azurerm_cognitive_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } +func (CognitiveAccountResource) identitySystemAssigned(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-cognitive-%d" + location = "%s" +} + +resource "azurerm_cognitive_account" "test" { + name = "acctestcogacc-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + kind = "Face" + sku_name = "S0" + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} + +func (CognitiveAccountResource) identityUserAssigned(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-cognitive-%d" + location = "%s" +} + +resource "azurerm_user_assigned_identity" "test" { + name = "acctestUAI-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_cognitive_account" "test" { + name = "acctestcogacc-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + kind = "Face" + sku_name = "S0" + identity { + type = "UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id, + ] + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func (CognitiveAccountResource) identitySystemAssignedUserAssigned(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-cognitive-%d" + location = "%s" +} + +resource "azurerm_user_assigned_identity" "test" { + name = "acctestUAI-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_cognitive_account" "test" { + name = "acctestcogacc-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + kind = "Face" + sku_name = "S0" + identity { + type = "SystemAssigned, UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id, + ] + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + func (CognitiveAccountResource) speechServices(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { @@ -274,6 +422,51 @@ resource "azurerm_cognitive_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } +func (CognitiveAccountResource) speechServicesWithStorage(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-cognitive-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestrg%d" + resource_group_name = azurerm_resource_group.test.name + + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_user_assigned_identity" "test" { + name = "acctest-identity-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +resource "azurerm_cognitive_account" "test" { + name = "acctestcogacc-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + kind = "SpeechServices" + sku_name = "S0" + + identity { + type = "SystemAssigned" + } + + storage { + resource_id = azurerm_storage_account.test.id + identity_client_id = azurerm_user_assigned_identity.test.client_id + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(8), data.RandomInteger, data.RandomInteger) +} + func (CognitiveAccountResource) requiresImport(data acceptance.TestData) string { template := CognitiveAccountResource{}.basic(data) return fmt.Sprintf(` @@ -307,6 +500,11 @@ resource "azurerm_cognitive_account" "test" { kind = "Face" sku_name = "S0" + fqdns = ["foo.com", "bar.com"] + public_network_access_enabled = false + restrict_outbound_network_access = true + disable_local_auth = true + tags = { Acceptance = "Test" } diff --git a/website/docs/r/cognitive_account.html.markdown b/website/docs/r/cognitive_account.html.markdown index f38c08a4ab0e..1704f2e55e17 100644 --- a/website/docs/r/cognitive_account.html.markdown +++ b/website/docs/r/cognitive_account.html.markdown @@ -56,6 +56,18 @@ The following arguments are supported: * `custom_subdomain_name` - (Optional) The subdomain name used for token-based authentication. Changing this forces a new resource to be created. +* `disable_local_auth` - (Optional) Whether local authentication methods is disabled for the Cognitive Account. Defaults to `false`. + +* `fqdns` - (Optional) List of FQDNs allowed for the Cognitive Account. + +* `identity` - (Optional) An `identity` block is documented below. + +* `public_network_access_enabled` - (Optional) Whether public network access is allowed for the Cognitive Account. Defaults to `true`. + +* `restrict_outbound_network_access` - (Optional) Whether outbound network access is restricted for the Cognitive Account. Defaults to `false`. + +* `storage` - (Optional) An `identity` block is documented below. + * `tags` - (Optional) A mapping of tags to assign to the resource. --- @@ -68,6 +80,24 @@ A `network_acls` block supports the following: * `virtual_network_subnet_ids` - (Optional) One or more Subnet ID's which should be able to access this Cognitive Account. +--- + +A `identity` block supports the following: + +* `type` - (Required) Specifies the type of Managed Service Identity that should be configured on the Cognitive Account. Possible values are `SystemAssigned`, `UserAssigned`, `SystemAssigned, UserAssigned` (to enable both). + +* `identity_ids` - (Optional) A list of IDs for User Assigned Managed Identity resources to be assigned. + +~> **NOTE:** This is required when `type` is set to `UserAssigned` or `SystemAssigned, UserAssigned`. + +--- + +A `storage` block supports the following: + +* `resource_id` - (Required) Full resource id of a Microsoft.Storage resource. + +* `identity_client_id` - (Optional) The client ID of the managed identity associated with the storage resource. + ## Attributes Reference The following attributes are exported: From 889b7b4079888ee759d066868da2a29dd17ca4fd Mon Sep 17 00:00:00 2001 From: ms-henglu Date: Tue, 6 Jul 2021 16:24:42 +0800 Subject: [PATCH 2/4] support --- .../cognitive/cognitive_account_resource.go | 104 +++++++++++++++--- .../cognitive_account_resource_test.go | 39 +++++++ .../docs/r/cognitive_account.html.markdown | 10 +- 3 files changed, 134 insertions(+), 19 deletions(-) diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource.go b/azurerm/internal/services/cognitive/cognitive_account_resource.go index 954f52ab11cd..2cdf4530a3a4 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource.go @@ -86,6 +86,7 @@ func resourceCognitiveAccount() *pluginsdk.Resource { "ImmersiveReader", "LUIS", "LUIS.Authoring", + "MetricsAdvisor", "Personalizer", "QnAMaker", "Recommendations", @@ -107,6 +108,20 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, false), }, + "aad_client_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "aad_tenant_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "custom_subdomain_name": { Type: pluginsdk.TypeString, Optional: true, @@ -244,6 +259,20 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, }, + "super_user": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "website_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "tags": tags.Schema(), "endpoint": { @@ -314,12 +343,17 @@ func resourceCognitiveAccountCreate(d *pluginsdk.ResourceData, meta interface{}) publicNetworkAccess = cognitiveservices.PublicNetworkAccessDisabled } + apiProps, err := expandCognitiveAccountAPIProperties(d) + if err != nil { + return err + } + props := cognitiveservices.Account{ Kind: utils.String(kind), Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), Sku: sku, Properties: &cognitiveservices.AccountProperties{ - APIProperties: &cognitiveservices.APIProperties{}, + APIProperties: apiProps, NetworkAcls: networkAcls, CustomSubDomainName: utils.String(d.Get("custom_subdomain_name").(string)), AllowedFqdnList: utils.ExpandStringSlice(d.Get("fqdns").([]interface{})), @@ -338,14 +372,6 @@ func resourceCognitiveAccountCreate(d *pluginsdk.ResourceData, meta interface{}) } props.Identity = identity - if kind == "QnAMaker" { - if v, ok := d.GetOk("qna_runtime_endpoint"); ok && v != "" { - props.Properties.APIProperties.QnaRuntimeEndpoint = utils.String(v.(string)) - } else { - return fmt.Errorf("the QnAMaker runtime endpoint `qna_runtime_endpoint` is required when kind is set to `QnAMaker`") - } - } - if _, err := client.Create(ctx, id.ResourceGroup, id.Name, props); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } @@ -403,10 +429,15 @@ func resourceCognitiveAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) publicNetworkAccess = cognitiveservices.PublicNetworkAccessDisabled } + apiProps, err := expandCognitiveAccountAPIProperties(d) + if err != nil { + return err + } + props := cognitiveservices.Account{ Sku: sku, Properties: &cognitiveservices.AccountProperties{ - APIProperties: &cognitiveservices.APIProperties{}, + APIProperties: apiProps, NetworkAcls: networkAcls, CustomSubDomainName: utils.String(d.Get("custom_subdomain_name").(string)), AllowedFqdnList: utils.ExpandStringSlice(d.Get("fqdns").([]interface{})), @@ -424,14 +455,6 @@ func resourceCognitiveAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) } props.Identity = identity - if kind := d.Get("kind"); kind == "QnAMaker" { - if v, ok := d.GetOk("qna_runtime_endpoint"); ok && v != "" { - props.Properties.APIProperties.QnaRuntimeEndpoint = utils.String(v.(string)) - } else { - return fmt.Errorf("the QnAMaker runtime endpoint `qna_runtime_endpoint` is required when kind is set to `QnAMaker`") - } - } - if _, err = client.Update(ctx, id.ResourceGroup, id.Name, props); err != nil { return fmt.Errorf("updating %s: %+v", *id, err) } @@ -495,6 +518,10 @@ func resourceCognitiveAccountRead(d *pluginsdk.ResourceData, meta interface{}) e if props := resp.Properties; props != nil { if apiProps := props.APIProperties; apiProps != nil { d.Set("qna_runtime_endpoint", apiProps.QnaRuntimeEndpoint) + d.Set("aad_client_id", apiProps.AadClientID) + d.Set("aad_tenant_id", apiProps.AadTenantID) + d.Set("super_user", apiProps.SuperUser) + d.Set("website_name", apiProps.WebsiteName) } d.Set("endpoint", props.Endpoint) d.Set("custom_subdomain_name", props.CustomSubDomainName) @@ -684,6 +711,47 @@ func expandCognitiveAccountIdentity(vs []interface{}) (*cognitiveservices.Identi return &managedServiceIdentity, nil } +func expandCognitiveAccountAPIProperties(d *pluginsdk.ResourceData) (*cognitiveservices.APIProperties, error) { + props := cognitiveservices.APIProperties{} + kind := d.Get("kind") + if kind == "QnAMaker" { + if v, ok := d.GetOk("qna_runtime_endpoint"); ok && v != "" { + props.QnaRuntimeEndpoint = utils.String(v.(string)) + } else { + return nil, fmt.Errorf("the QnAMaker runtime endpoint `qna_runtime_endpoint` is required when kind is set to `QnAMaker`") + } + } + if v, ok := d.GetOk("aad_client_id"); ok { + if kind == "MetricsAdvisor" { + props.AadClientID = utils.String(v.(string)) + } else { + return nil, fmt.Errorf("aad_client_id can only used set when kind is set to `MetricsAdvisor`") + } + } + if v, ok := d.GetOk("aad_tenant_id"); ok { + if kind == "MetricsAdvisor" { + props.AadTenantID = utils.String(v.(string)) + } else { + return nil, fmt.Errorf("aad_tenant_id can only used set when kind is set to `MetricsAdvisor`") + } + } + if v, ok := d.GetOk("super_user"); ok { + if kind == "MetricsAdvisor" { + props.SuperUser = utils.String(v.(string)) + } else { + return nil, fmt.Errorf("super_user can only used set when kind is set to `MetricsAdvisor`") + } + } + if v, ok := d.GetOk("website_name"); ok { + if kind == "MetricsAdvisor" { + props.WebsiteName = utils.String(v.(string)) + } else { + return nil, fmt.Errorf("website_name can only used set when kind is set to `MetricsAdvisor`") + } + } + return &props, nil +} + func flattenCognitiveAccountNetworkAcls(input *cognitiveservices.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{} diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go index c89e55a350d4..05b5c309f1a3 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go @@ -276,6 +276,21 @@ func TestAccCognitiveAccount_identity(t *testing.T) { }) } +func TestAccCognitiveAccount_metricsAdvisor(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_cognitive_account", "test") + r := CognitiveAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.metricsAdvisor(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func (t CognitiveAccountResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.AccountID(state.ID) if err != nil { @@ -576,6 +591,30 @@ resource "azurerm_cognitive_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } +func (CognitiveAccountResource) metricsAdvisor(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} +resource "azurerm_resource_group" "test" { + name = "acctestRG-cognitive-%d" + location = "%s" +} +resource "azurerm_cognitive_account" "test" { + name = "acctestcogacc-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + kind = "MetricsAdvisor" + sku_name = "S0" + custom_subdomain_name = "acctestcogacc-%d" + aad_client_id = "310d7b2e-d1d1-4b87-9807-5b885b290c00" + aad_tenant_id = "72f988bf-86f1-41af-91ab-2d7cd011db47" + super_user = "mock_user1" + website_name = "mock_name2" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + func (CognitiveAccountResource) withMultipleCognitiveAccounts(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/cognitive_account.html.markdown b/website/docs/r/cognitive_account.html.markdown index 1704f2e55e17..fcfbf2eae4e5 100644 --- a/website/docs/r/cognitive_account.html.markdown +++ b/website/docs/r/cognitive_account.html.markdown @@ -44,10 +44,14 @@ The following arguments are supported: * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `kind` - (Required) Specifies the type of Cognitive Service Account that should be created. Possible values are `Academic`, `AnomalyDetector`, `Bing.Autosuggest`, `Bing.Autosuggest.v7`, `Bing.CustomSearch`, `Bing.Search`, `Bing.Search.v7`, `Bing.Speech`, `Bing.SpellCheck`, `Bing.SpellCheck.v7`, `CognitiveServices`, `ComputerVision`, `ContentModerator`, `CustomSpeech`, `CustomVision.Prediction`, `CustomVision.Training`, `Emotion`, `Face`,`FormRecognizer`, `ImmersiveReader`, `LUIS`, `LUIS.Authoring`, `Personalizer`, `QnAMaker`, `Recommendations`, `SpeakerRecognition`, `Speech`, `SpeechServices`, `SpeechTranslation`, `TextAnalytics`, `TextTranslation` and `WebLM`. Changing this forces a new resource to be created. +* `kind` - (Required) Specifies the type of Cognitive Service Account that should be created. Possible values are `Academic`, `AnomalyDetector`, `Bing.Autosuggest`, `Bing.Autosuggest.v7`, `Bing.CustomSearch`, `Bing.Search`, `Bing.Search.v7`, `Bing.Speech`, `Bing.SpellCheck`, `Bing.SpellCheck.v7`, `CognitiveServices`, `ComputerVision`, `ContentModerator`, `CustomSpeech`, `CustomVision.Prediction`, `CustomVision.Training`, `Emotion`, `Face`,`FormRecognizer`, `ImmersiveReader`, `LUIS`, `LUIS.Authoring`, `MetricsAdvisor`, `Personalizer`, `QnAMaker`, `Recommendations`, `SpeakerRecognition`, `Speech`, `SpeechServices`, `SpeechTranslation`, `TextAnalytics`, `TextTranslation` and `WebLM`. Changing this forces a new resource to be created. * `sku_name` - (Required) Specifies the SKU Name for this Cognitive Service Account. Possible values are `F0`, `F1`, `S`, `S0`, `S1`, `S2`, `S3`, `S4`, `S5`, `S6`, `P0`, `P1`, and `P2`. +* `aad_client_id` - (Optional) The Azure AD Client ID (Application ID). This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. + +* `aad_tenant_id` - (Optional) The Azure AD Tenant ID. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. + * `qna_runtime_endpoint` - (Optional) A URL to link a QnAMaker cognitive account to a QnA runtime. -> **NOTE:** This URL is mandatory if the `kind` is set to `QnAMaker`. @@ -68,6 +72,10 @@ The following arguments are supported: * `storage` - (Optional) An `identity` block is documented below. +* `super_user` - (Optional) The super user of Metrics Advisor. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. + +* `website_name` - (Optional) The website name of Metrics Advisor. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. + * `tags` - (Optional) A mapping of tags to assign to the resource. --- From 31bc84cfb05034cdbc6dc47e4a030fdca2f35821 Mon Sep 17 00:00:00 2001 From: henglu Date: Wed, 7 Jul 2021 11:08:49 +0800 Subject: [PATCH 3/4] rename fields --- .../cognitive/cognitive_account_resource.go | 122 +++++++++--------- .../cognitive_account_resource_test.go | 30 ++--- .../docs/r/cognitive_account.html.markdown | 34 ++--- 3 files changed, 93 insertions(+), 93 deletions(-) diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource.go b/azurerm/internal/services/cognitive/cognitive_account_resource.go index 2cdf4530a3a4..c84ce8131a5f 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource.go @@ -108,20 +108,6 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, false), }, - "aad_client_id": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "aad_tenant_id": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "custom_subdomain_name": { Type: pluginsdk.TypeString, Optional: true, @@ -129,12 +115,6 @@ func resourceCognitiveAccount() *pluginsdk.Resource { ValidateFunc: validation.StringIsNotEmpty, }, - "disable_local_auth": { - Type: pluginsdk.TypeBool, - Optional: true, - Default: false, - }, - "fqdns": { Type: pluginsdk.TypeList, Optional: true, @@ -185,10 +165,38 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, }, - "qna_runtime_endpoint": { + "local_auth_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "metrics_advisor_aad_client_id": { Type: pluginsdk.TypeString, Optional: true, - ValidateFunc: validation.IsURLWithHTTPorHTTPS, + ForceNew: true, + ValidateFunc: validation.IsUUID, + }, + + "metrics_advisor_aad_tenant_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IsUUID, + }, + + "metrics_advisor_super_user_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "metrics_advisor_website_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, }, "network_acls": { @@ -227,16 +235,22 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, }, - "public_network_access_enabled": { + "outbound_network_access_restrited": { Type: pluginsdk.TypeBool, Optional: true, - Default: true, + Default: false, }, - "restrict_outbound_network_access": { + "public_network_access_enabled": { Type: pluginsdk.TypeBool, Optional: true, - Default: false, + Default: true, + }, + + "qna_runtime_endpoint": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.IsURLWithHTTPorHTTPS, }, "storage": { @@ -244,7 +258,7 @@ func resourceCognitiveAccount() *pluginsdk.Resource { Optional: true, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "resource_id": { + "storage_account_id": { Type: pluginsdk.TypeString, Required: true, ValidateFunc: storageValidate.StorageAccountID, @@ -259,20 +273,6 @@ func resourceCognitiveAccount() *pluginsdk.Resource { }, }, - "super_user": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "website_name": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "tags": tags.Schema(), "endpoint": { @@ -359,8 +359,8 @@ func resourceCognitiveAccountCreate(d *pluginsdk.ResourceData, meta interface{}) AllowedFqdnList: utils.ExpandStringSlice(d.Get("fqdns").([]interface{})), PublicNetworkAccess: publicNetworkAccess, UserOwnedStorage: expandCognitiveAccountStorage(d.Get("storage").([]interface{})), - RestrictOutboundNetworkAccess: utils.Bool(d.Get("restrict_outbound_network_access").(bool)), - DisableLocalAuth: utils.Bool(d.Get("disable_local_auth").(bool)), + RestrictOutboundNetworkAccess: utils.Bool(d.Get("outbound_network_access_restrited").(bool)), + DisableLocalAuth: utils.Bool(!d.Get("local_auth_enabled").(bool)), }, Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } @@ -443,8 +443,8 @@ func resourceCognitiveAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) AllowedFqdnList: utils.ExpandStringSlice(d.Get("fqdns").([]interface{})), PublicNetworkAccess: publicNetworkAccess, UserOwnedStorage: expandCognitiveAccountStorage(d.Get("storage").([]interface{})), - RestrictOutboundNetworkAccess: utils.Bool(d.Get("restrict_outbound_network_access").(bool)), - DisableLocalAuth: utils.Bool(d.Get("disable_local_auth").(bool)), + RestrictOutboundNetworkAccess: utils.Bool(d.Get("outbound_network_access_restrited").(bool)), + DisableLocalAuth: utils.Bool(!d.Get("local_auth_enabled").(bool)), }, Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } @@ -518,10 +518,10 @@ func resourceCognitiveAccountRead(d *pluginsdk.ResourceData, meta interface{}) e if props := resp.Properties; props != nil { if apiProps := props.APIProperties; apiProps != nil { d.Set("qna_runtime_endpoint", apiProps.QnaRuntimeEndpoint) - d.Set("aad_client_id", apiProps.AadClientID) - d.Set("aad_tenant_id", apiProps.AadTenantID) - d.Set("super_user", apiProps.SuperUser) - d.Set("website_name", apiProps.WebsiteName) + d.Set("metrics_advisor_aad_client_id", apiProps.AadClientID) + d.Set("metrics_advisor_aad_tenant_id", apiProps.AadTenantID) + d.Set("metrics_advisor_super_user_name", apiProps.SuperUser) + d.Set("metrics_advisor_website_name", apiProps.WebsiteName) } d.Set("endpoint", props.Endpoint) d.Set("custom_subdomain_name", props.CustomSubDomainName) @@ -534,10 +534,10 @@ func resourceCognitiveAccountRead(d *pluginsdk.ResourceData, meta interface{}) e return fmt.Errorf("setting `storages` for Cognitive Account %q: %+v", id, err) } if props.RestrictOutboundNetworkAccess != nil { - d.Set("restrict_outbound_network_access", *props.RestrictOutboundNetworkAccess) + d.Set("outbound_network_access_restrited", *props.RestrictOutboundNetworkAccess) } if props.DisableLocalAuth != nil { - d.Set("disable_local_auth", *props.DisableLocalAuth) + d.Set("local_auth_enabled", !*props.DisableLocalAuth) } } @@ -667,7 +667,7 @@ func expandCognitiveAccountStorage(input []interface{}) *[]cognitiveservices.Use for _, v := range input { value := v.(map[string]interface{}) results = append(results, cognitiveservices.UserOwnedStorage{ - ResourceID: utils.String(value["resource_id"].(string)), + ResourceID: utils.String(value["storage_account_id"].(string)), IdentityClientID: utils.String(value["identity_client_id"].(string)), }) } @@ -721,32 +721,32 @@ func expandCognitiveAccountAPIProperties(d *pluginsdk.ResourceData) (*cognitives return nil, fmt.Errorf("the QnAMaker runtime endpoint `qna_runtime_endpoint` is required when kind is set to `QnAMaker`") } } - if v, ok := d.GetOk("aad_client_id"); ok { + if v, ok := d.GetOk("metrics_advisor_aad_client_id"); ok { if kind == "MetricsAdvisor" { props.AadClientID = utils.String(v.(string)) } else { - return nil, fmt.Errorf("aad_client_id can only used set when kind is set to `MetricsAdvisor`") + return nil, fmt.Errorf("metrics_advisor_aad_client_id can only used set when kind is set to `MetricsAdvisor`") } } - if v, ok := d.GetOk("aad_tenant_id"); ok { + if v, ok := d.GetOk("metrics_advisor_aad_tenant_id"); ok { if kind == "MetricsAdvisor" { props.AadTenantID = utils.String(v.(string)) } else { - return nil, fmt.Errorf("aad_tenant_id can only used set when kind is set to `MetricsAdvisor`") + return nil, fmt.Errorf("metrics_advisor_aad_tenant_id can only used set when kind is set to `MetricsAdvisor`") } } - if v, ok := d.GetOk("super_user"); ok { + if v, ok := d.GetOk("metrics_advisor_super_user_name"); ok { if kind == "MetricsAdvisor" { props.SuperUser = utils.String(v.(string)) } else { - return nil, fmt.Errorf("super_user can only used set when kind is set to `MetricsAdvisor`") + return nil, fmt.Errorf("metrics_advisor_super_user_name can only used set when kind is set to `MetricsAdvisor`") } } - if v, ok := d.GetOk("website_name"); ok { + if v, ok := d.GetOk("metrics_advisor_website_name"); ok { if kind == "MetricsAdvisor" { props.WebsiteName = utils.String(v.(string)) } else { - return nil, fmt.Errorf("website_name can only used set when kind is set to `MetricsAdvisor`") + return nil, fmt.Errorf("metrics_advisor_website_name can only used set when kind is set to `MetricsAdvisor`") } } return &props, nil @@ -801,7 +801,7 @@ func flattenCognitiveAccountStorage(input *[]cognitiveservices.UserOwnedStorage) for _, v := range *input { value := make(map[string]interface{}) if v.ResourceID != nil { - value["resource_id"] = *v.ResourceID + value["storage_account_id"] = *v.ResourceID } if v.IdentityClientID != nil { value["identity_client_id"] = *v.IdentityClientID diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go index 05b5c309f1a3..a2d43b49793e 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go @@ -475,7 +475,7 @@ resource "azurerm_cognitive_account" "test" { } storage { - resource_id = azurerm_storage_account.test.id + storage_account_id = azurerm_storage_account.test.id identity_client_id = azurerm_user_assigned_identity.test.client_id } } @@ -515,10 +515,10 @@ resource "azurerm_cognitive_account" "test" { kind = "Face" sku_name = "S0" - fqdns = ["foo.com", "bar.com"] - public_network_access_enabled = false - restrict_outbound_network_access = true - disable_local_auth = true + fqdns = ["foo.com", "bar.com"] + public_network_access_enabled = false + outbound_network_access_restrited = true + local_auth_enabled = false tags = { Acceptance = "Test" @@ -601,16 +601,16 @@ resource "azurerm_resource_group" "test" { location = "%s" } resource "azurerm_cognitive_account" "test" { - name = "acctestcogacc-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - kind = "MetricsAdvisor" - sku_name = "S0" - custom_subdomain_name = "acctestcogacc-%d" - aad_client_id = "310d7b2e-d1d1-4b87-9807-5b885b290c00" - aad_tenant_id = "72f988bf-86f1-41af-91ab-2d7cd011db47" - super_user = "mock_user1" - website_name = "mock_name2" + name = "acctestcogacc-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + kind = "MetricsAdvisor" + sku_name = "S0" + custom_subdomain_name = "acctestcogacc-%d" + metrics_advisor_aad_client_id = "310d7b2e-d1d1-4b87-9807-5b885b290c00" + metrics_advisor_aad_tenant_id = "72f988bf-86f1-41af-91ab-2d7cd011db47" + metrics_advisor_super_user_name = "mock_user1" + metrics_advisor_website_name = "mock_name2" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } diff --git a/website/docs/r/cognitive_account.html.markdown b/website/docs/r/cognitive_account.html.markdown index fcfbf2eae4e5..bde8d073e114 100644 --- a/website/docs/r/cognitive_account.html.markdown +++ b/website/docs/r/cognitive_account.html.markdown @@ -48,33 +48,33 @@ The following arguments are supported: * `sku_name` - (Required) Specifies the SKU Name for this Cognitive Service Account. Possible values are `F0`, `F1`, `S`, `S0`, `S1`, `S2`, `S3`, `S4`, `S5`, `S6`, `P0`, `P1`, and `P2`. -* `aad_client_id` - (Optional) The Azure AD Client ID (Application ID). This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. +* `custom_subdomain_name` - (Optional) The subdomain name used for token-based authentication. Changing this forces a new resource to be created. -* `aad_tenant_id` - (Optional) The Azure AD Tenant ID. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. - -* `qna_runtime_endpoint` - (Optional) A URL to link a QnAMaker cognitive account to a QnA runtime. +* `fqdns` - (Optional) List of FQDNs allowed for the Cognitive Account. --> **NOTE:** This URL is mandatory if the `kind` is set to `QnAMaker`. +* `identity` - (Optional) An `identity` block is documented below. -* `network_acls` - (Optional) A `network_acls` block as defined below. +* `local_auth_enabled` - (Optional) Whether local authentication methods is enabled for the Cognitive Account. Defaults to `true`. -* `custom_subdomain_name` - (Optional) The subdomain name used for token-based authentication. Changing this forces a new resource to be created. +* `metrics_advisor_aad_client_id` - (Optional) The Azure AD Client ID (Application ID). This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. -* `disable_local_auth` - (Optional) Whether local authentication methods is disabled for the Cognitive Account. Defaults to `false`. +* `metrics_advisor_aad_tenant_id` - (Optional) The Azure AD Tenant ID. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. -* `fqdns` - (Optional) List of FQDNs allowed for the Cognitive Account. - -* `identity` - (Optional) An `identity` block is documented below. +* `metrics_advisor_super_user_name` - (Optional) The super user of Metrics Advisor. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. -* `public_network_access_enabled` - (Optional) Whether public network access is allowed for the Cognitive Account. Defaults to `true`. +* `metrics_advisor_website_name` - (Optional) The website name of Metrics Advisor. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. -* `restrict_outbound_network_access` - (Optional) Whether outbound network access is restricted for the Cognitive Account. Defaults to `false`. +-> **NOTE:** This URL is mandatory if the `kind` is set to `QnAMaker`. -* `storage` - (Optional) An `identity` block is documented below. +* `network_acls` - (Optional) A `network_acls` block as defined below. -* `super_user` - (Optional) The super user of Metrics Advisor. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. +* `outbound_network_access_restrited` - (Optional) Whether outbound network access is restricted for the Cognitive Account. Defaults to `false`. -* `website_name` - (Optional) The website name of Metrics Advisor. This attribute is only set when kind is `MetricsAdvisor`. Changing this forces a new resource to be created. +* `public_network_access_enabled` - (Optional) Whether public network access is allowed for the Cognitive Account. Defaults to `true`. + +* `qna_runtime_endpoint` - (Optional) A URL to link a QnAMaker cognitive account to a QnA runtime. + +* `storage` - (Optional) An `identity` block is documented below. * `tags` - (Optional) A mapping of tags to assign to the resource. @@ -102,7 +102,7 @@ A `identity` block supports the following: A `storage` block supports the following: -* `resource_id` - (Required) Full resource id of a Microsoft.Storage resource. +* `storage_account_id` - (Required) Full resource id of a Microsoft.Storage resource. * `identity_client_id` - (Optional) The client ID of the managed identity associated with the storage resource. From 86ad13711b264fde3729ed2cc611d230e8772dfb Mon Sep 17 00:00:00 2001 From: henglu Date: Fri, 9 Jul 2021 09:43:37 +0800 Subject: [PATCH 4/4] update test location --- .../services/cognitive/cognitive_account_resource_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go index a2d43b49793e..207d32be38e9 100644 --- a/azurerm/internal/services/cognitive/cognitive_account_resource_test.go +++ b/azurerm/internal/services/cognitive/cognitive_account_resource_test.go @@ -434,7 +434,7 @@ resource "azurerm_cognitive_account" "test" { kind = "SpeechServices" sku_name = "S0" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Secondary, data.RandomInteger) } func (CognitiveAccountResource) speechServicesWithStorage(data acceptance.TestData) string { @@ -479,7 +479,7 @@ resource "azurerm_cognitive_account" "test" { identity_client_id = azurerm_user_assigned_identity.test.client_id } } -`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(8), data.RandomInteger, data.RandomInteger) +`, data.RandomInteger, data.Locations.Secondary, data.RandomIntOfLength(8), data.RandomInteger, data.RandomInteger) } func (CognitiveAccountResource) requiresImport(data acceptance.TestData) string { @@ -546,7 +546,7 @@ resource "azurerm_cognitive_account" "test" { qna_runtime_endpoint = "%s" sku_name = "S0" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, url) +`, data.RandomInteger, "West US", data.RandomInteger, url) // QnAMaker only available in West US } func (CognitiveAccountResource) qnaRuntimeEndpointUnspecified(data acceptance.TestData) string { @@ -567,7 +567,7 @@ resource "azurerm_cognitive_account" "test" { kind = "QnAMaker" sku_name = "S0" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, "West US", data.RandomInteger) // QnAMaker only available in West US } func (CognitiveAccountResource) cognitiveServices(data acceptance.TestData) string {