From 93fd90cf03e0795ff2b70243cd1bdddc615a63a7 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Tue, 8 Dec 2020 07:58:28 +0100 Subject: [PATCH 01/21] r/eventgrid_topic: managed identity --- .../services/eventgrid/eventgrid_topic.go | 111 ++++++++++++++++++ .../eventgrid/eventgrid_topic_resource.go | 13 ++ 2 files changed, 124 insertions(+) create mode 100644 azurerm/internal/services/eventgrid/eventgrid_topic.go diff --git a/azurerm/internal/services/eventgrid/eventgrid_topic.go b/azurerm/internal/services/eventgrid/eventgrid_topic.go new file mode 100644 index 000000000000..89bafcb4b31a --- /dev/null +++ b/azurerm/internal/services/eventgrid/eventgrid_topic.go @@ -0,0 +1,111 @@ +package eventgrid + +import ( + "fmt" + + "github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute" + "github.com/Azure/azure-sdk-for-go/services/preview/eventgrid/mgmt/2020-04-01-preview/eventgrid" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func EventGridTopicIdentitySchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(eventgrid.IdentityTypeNone), + string(eventgrid.IdentityTypeSystemAssigned), + }, false), + }, + + "identity_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "principal_id": { + Type: schema.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + } +} + +func expandEventGridTopicIdentity(input []interface{}) (*eventgrid.IdentityInfo, error) { + if len(input) == 0 { + // TODO: Does this want to be this, or nil? + return &compute.VirtualMachineIdentity{ + Type: compute.ResourceIdentityTypeNone, + }, nil + } + + raw := input[0].(map[string]interface{}) + + identity := eventgrid.IdentityInfo{ + Type: eventgrid.IdentityType(raw["type"].(string)), + } + + identityIdsRaw := raw["identity_ids"].(*schema.Set).List() + identityIds := make(map[string]*eventgrid.UserIdentityProperties) + for _, v := range identityIdsRaw { + identityIds[v.(string)] = &eventgrid.UserIdentityProperties{} + } + + if len(identityIds) > 0 { + if identity.Type != eventgrid.IdentityTypeUserAssigned && identity.Type != eventgrid.IdentityTypeSystemAssignedUserAssigned { + return nil, fmt.Errorf("`identity_ids` can only be specified when `type` includes `UserAssigned`") + } + + identity.UserAssignedIdentities = identityIds + } + + return &identity, nil +} + +func flattenEventGridTopicIdentity(input *eventgrid.IdentityInfo) []interface{} { + if input == nil || input.Type == eventgrid.IdentityTypeNone { + return []interface{}{} + } + + identityIds := make([]string, 0) + if input.UserAssignedIdentities != nil { + for k := range input.UserAssignedIdentities { + identityIds = append(identityIds, k) + } + } + + principalID := "" + if input.PrincipalID != nil { + principalID = *input.PrincipalID + } + + tenantID := "" + if input.TenantID != nil { + tenantID = *input.TenantID + } + + return []interface{}{ + map[string]interface{}{ + "type": string(input.Type), + "identity_ids": identityIds, + "principal_id": principalID, + "tenant_id": tenantID, + }, + } +} diff --git a/internal/services/eventgrid/eventgrid_topic_resource.go b/internal/services/eventgrid/eventgrid_topic_resource.go index 74cac67d7fca..60a6110d3314 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource.go +++ b/internal/services/eventgrid/eventgrid_topic_resource.go @@ -55,6 +55,8 @@ func resourceEventGridTopic() *pluginsdk.Resource { "resource_group_name": azure.SchemaResourceGroupName(), + "identity": EventGridTopicIdentitySchema(), + "input_schema": { Type: pluginsdk.TypeString, Optional: true, @@ -193,8 +195,15 @@ func resourceEventGridTopicCreateUpdate(d *pluginsdk.ResourceData, meta interfac InboundIPRules: expandInboundIPRules(d), } + identityRaw := d.Get("identity").([]interface{}) + identity, err := expandEventGridTopicIdentity(identityRaw) + if err != nil { + return fmt.Errorf("expanding `identity`: %+v", err) + } + properties := eventgrid.Topic{ Location: &location, + Identity: &identity, TopicProperties: topicProperties, Tags: tags.Expand(t), } @@ -290,6 +299,10 @@ func resourceEventGridTopicRead(d *pluginsdk.ResourceData, meta interface{}) err d.Set("endpoint", props.Endpoint) } + if err := d.Set("identity", flattenEventGridTopicIdentity(resp.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + d.Set("primary_access_key", keys.Key1) d.Set("secondary_access_key", keys.Key2) From c9ab57518bd8ffe4e125e827869f1cbd351fa12e Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Tue, 8 Dec 2020 09:01:14 +0100 Subject: [PATCH 02/21] fixes --- azurerm/internal/services/eventgrid/eventgrid_topic.go | 5 ++--- internal/services/eventgrid/eventgrid_topic_resource.go | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/eventgrid/eventgrid_topic.go b/azurerm/internal/services/eventgrid/eventgrid_topic.go index 89bafcb4b31a..ef3e7f168bca 100644 --- a/azurerm/internal/services/eventgrid/eventgrid_topic.go +++ b/azurerm/internal/services/eventgrid/eventgrid_topic.go @@ -3,7 +3,6 @@ package eventgrid import ( "fmt" - "github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute" "github.com/Azure/azure-sdk-for-go/services/preview/eventgrid/mgmt/2020-04-01-preview/eventgrid" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" @@ -50,8 +49,8 @@ func EventGridTopicIdentitySchema() *schema.Schema { func expandEventGridTopicIdentity(input []interface{}) (*eventgrid.IdentityInfo, error) { if len(input) == 0 { // TODO: Does this want to be this, or nil? - return &compute.VirtualMachineIdentity{ - Type: compute.ResourceIdentityTypeNone, + return &eventgrid.IdentityInfo{ + Type: eventgrid.IdentityTypeNone, }, nil } diff --git a/internal/services/eventgrid/eventgrid_topic_resource.go b/internal/services/eventgrid/eventgrid_topic_resource.go index 60a6110d3314..9543fca8d9cf 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource.go +++ b/internal/services/eventgrid/eventgrid_topic_resource.go @@ -203,7 +203,7 @@ func resourceEventGridTopicCreateUpdate(d *pluginsdk.ResourceData, meta interfac properties := eventgrid.Topic{ Location: &location, - Identity: &identity, + Identity: identity, TopicProperties: topicProperties, Tags: tags.Expand(t), } From 39f6ab146f956496af60ac1a5df674a9c9cfbe69 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Thu, 17 Dec 2020 06:42:44 +0100 Subject: [PATCH 03/21] identity acc tests --- .../eventgrid_topic_resource_test.go | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/internal/services/eventgrid/eventgrid_topic_resource_test.go b/internal/services/eventgrid/eventgrid_topic_resource_test.go index 3768e4db94bb..1f04faed77d2 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource_test.go +++ b/internal/services/eventgrid/eventgrid_topic_resource_test.go @@ -5,11 +5,12 @@ import ( "fmt" "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "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/services/eventgrid/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" ) @@ -111,7 +112,26 @@ func TestAccEventGridTopic_inboundIPRules(t *testing.T) { }) } -func (EventGridTopicResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { +func TestAccEventGridTopic_basicWithIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_topic", "test") + r := EventGridTopicResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basicWithIdentity(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.%").HasValue("1"), + check.That(data.ResourceName).Key("identity.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.principal_id").Exists(), + check.That(data.ResourceName).Key("identity.tenant_id").Exists(), + ), + }, + data.ImportStep(), + }) +} + +func (EventGridTopicResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.TopicID(state.ID) if err != nil { return nil, err @@ -241,3 +261,28 @@ resource "azurerm_eventgrid_topic" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } + +func (EventGridTopicResource) basicWithIdentity(data acceptance.TestData) string { + // currently only supported in "West Central US" & "West US 2" + location := "westus2" + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_eventgrid_topic" "test" { + name = "acctesteg-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, location, data.RandomInteger) +} From 390f87d1462e7a6a67c5821baf4fffbd99a74db9 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Thu, 17 Dec 2020 08:25:56 +0100 Subject: [PATCH 04/21] add identity to eventgrid domain --- .../services/eventgrid/eventgrid_topic.go | 110 ------------------ internal/services/eventgrid/eventgrid.go | 109 ++++++++++++++++- .../eventgrid/eventgrid_domain_resource.go | 16 ++- .../eventgrid_domain_resource_test.go | 47 +++++++- .../eventgrid/eventgrid_topic_resource.go | 6 +- .../eventgrid_topic_resource_test.go | 16 +-- 6 files changed, 175 insertions(+), 129 deletions(-) delete mode 100644 azurerm/internal/services/eventgrid/eventgrid_topic.go diff --git a/azurerm/internal/services/eventgrid/eventgrid_topic.go b/azurerm/internal/services/eventgrid/eventgrid_topic.go deleted file mode 100644 index ef3e7f168bca..000000000000 --- a/azurerm/internal/services/eventgrid/eventgrid_topic.go +++ /dev/null @@ -1,110 +0,0 @@ -package eventgrid - -import ( - "fmt" - - "github.com/Azure/azure-sdk-for-go/services/preview/eventgrid/mgmt/2020-04-01-preview/eventgrid" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" -) - -func EventGridTopicIdentitySchema() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(eventgrid.IdentityTypeNone), - string(eventgrid.IdentityTypeSystemAssigned), - }, false), - }, - - "identity_ids": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - - "principal_id": { - Type: schema.TypeString, - Computed: true, - }, - - "tenant_id": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - } -} - -func expandEventGridTopicIdentity(input []interface{}) (*eventgrid.IdentityInfo, error) { - if len(input) == 0 { - // TODO: Does this want to be this, or nil? - return &eventgrid.IdentityInfo{ - Type: eventgrid.IdentityTypeNone, - }, nil - } - - raw := input[0].(map[string]interface{}) - - identity := eventgrid.IdentityInfo{ - Type: eventgrid.IdentityType(raw["type"].(string)), - } - - identityIdsRaw := raw["identity_ids"].(*schema.Set).List() - identityIds := make(map[string]*eventgrid.UserIdentityProperties) - for _, v := range identityIdsRaw { - identityIds[v.(string)] = &eventgrid.UserIdentityProperties{} - } - - if len(identityIds) > 0 { - if identity.Type != eventgrid.IdentityTypeUserAssigned && identity.Type != eventgrid.IdentityTypeSystemAssignedUserAssigned { - return nil, fmt.Errorf("`identity_ids` can only be specified when `type` includes `UserAssigned`") - } - - identity.UserAssignedIdentities = identityIds - } - - return &identity, nil -} - -func flattenEventGridTopicIdentity(input *eventgrid.IdentityInfo) []interface{} { - if input == nil || input.Type == eventgrid.IdentityTypeNone { - return []interface{}{} - } - - identityIds := make([]string, 0) - if input.UserAssignedIdentities != nil { - for k := range input.UserAssignedIdentities { - identityIds = append(identityIds, k) - } - } - - principalID := "" - if input.PrincipalID != nil { - principalID = *input.PrincipalID - } - - tenantID := "" - if input.TenantID != nil { - tenantID = *input.TenantID - } - - return []interface{}{ - map[string]interface{}{ - "type": string(input.Type), - "identity_ids": identityIds, - "principal_id": principalID, - "tenant_id": tenantID, - }, - } -} diff --git a/internal/services/eventgrid/eventgrid.go b/internal/services/eventgrid/eventgrid.go index de200aa6df20..a32fa564b70b 100644 --- a/internal/services/eventgrid/eventgrid.go +++ b/internal/services/eventgrid/eventgrid.go @@ -1,15 +1,56 @@ package eventgrid import ( + "fmt" + "github.com/Azure/azure-sdk-for-go/services/preview/eventgrid/mgmt/2020-10-15-preview/eventgrid" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/utils" ) -func eventSubscriptionPublicNetworkAccessEnabled() *pluginsdk.Schema { - return &pluginsdk.Schema{ - Type: pluginsdk.TypeBool, +func IdentitySchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(eventgrid.IdentityTypeNone), + string(eventgrid.IdentityTypeSystemAssigned), + }, false), + }, + + "identity_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "principal_id": { + Type: schema.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + } +} + +func eventSubscriptionPublicNetworkAccessEnabled() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeBool, Optional: true, Default: true, } @@ -93,3 +134,65 @@ func flattenInboundIPRules(in *[]eventgrid.InboundIPRule) []interface{} { } return rules } + +func expandIdentity(input []interface{}) (*eventgrid.IdentityInfo, error) { + if len(input) == 0 { + return &eventgrid.IdentityInfo{ + Type: eventgrid.IdentityTypeNone, + }, nil + } + + raw := input[0].(map[string]interface{}) + + identity := eventgrid.IdentityInfo{ + Type: eventgrid.IdentityType(raw["type"].(string)), + } + + identityIdsRaw := raw["identity_ids"].(*schema.Set).List() + identityIds := make(map[string]*eventgrid.UserIdentityProperties) + for _, v := range identityIdsRaw { + identityIds[v.(string)] = &eventgrid.UserIdentityProperties{} + } + + if len(identityIds) > 0 { + if identity.Type != eventgrid.IdentityTypeUserAssigned && identity.Type != eventgrid.IdentityTypeSystemAssignedUserAssigned { + return nil, fmt.Errorf("`identity_ids` can only be specified when `type` includes `UserAssigned`") + } + + identity.UserAssignedIdentities = identityIds + } + + return &identity, nil +} + +func flattenIdentity(input *eventgrid.IdentityInfo) []interface{} { + if input == nil || input.Type == eventgrid.IdentityTypeNone { + return []interface{}{} + } + + identityIds := make([]string, 0) + if input.UserAssignedIdentities != nil { + for k := range input.UserAssignedIdentities { + identityIds = append(identityIds, k) + } + } + + principalID := "" + if input.PrincipalID != nil { + principalID = *input.PrincipalID + } + + tenantID := "" + if input.TenantID != nil { + tenantID = *input.TenantID + } + + return []interface{}{ + map[string]interface{}{ + "type": string(input.Type), + "identity_ids": identityIds, + "principal_id": principalID, + "tenant_id": tenantID, + }, + } +} diff --git a/internal/services/eventgrid/eventgrid_domain_resource.go b/internal/services/eventgrid/eventgrid_domain_resource.go index e8682934bfa9..664f3fc7f0f7 100644 --- a/internal/services/eventgrid/eventgrid_domain_resource.go +++ b/internal/services/eventgrid/eventgrid_domain_resource.go @@ -55,7 +55,7 @@ func resourceEventGridDomain() *pluginsdk.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - "tags": tags.Schema(), + "identity": IdentitySchema(), "input_schema": { Type: pluginsdk.TypeString, @@ -158,6 +158,8 @@ func resourceEventGridDomain() *pluginsdk.Resource { Computed: true, Sensitive: true, }, + + "tags": tags.Schema(), }, } } @@ -186,6 +188,12 @@ func resourceEventGridDomainCreateUpdate(d *pluginsdk.ResourceData, meta interfa location := azure.NormalizeLocation(d.Get("location").(string)) t := d.Get("tags").(map[string]interface{}) + identityRaw := d.Get("identity").([]interface{}) + identity, err := expandIdentity(identityRaw) + if err != nil { + return fmt.Errorf("expanding `identity`: %+v", err) + } + domainProperties := &eventgrid.DomainProperties{ InputSchemaMapping: expandAzureRmEventgridDomainInputMapping(d), InputSchema: eventgrid.InputSchema(d.Get("input_schema").(string)), @@ -195,6 +203,7 @@ func resourceEventGridDomainCreateUpdate(d *pluginsdk.ResourceData, meta interfa domain := eventgrid.Domain{ Location: &location, + Identity: identity, DomainProperties: domainProperties, Tags: tags.Expand(t), } @@ -286,6 +295,11 @@ func resourceEventGridDomainRead(d *pluginsdk.ResourceData, meta interface{}) er if err != nil { return fmt.Errorf("retrieving Shared Access Keys for EventGrid Domain %q: %+v", id.Name, err) } + + if err := d.Set("identity", flattenIdentity(resp.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + d.Set("primary_access_key", keys.Key1) d.Set("secondary_access_key", keys.Key2) diff --git a/internal/services/eventgrid/eventgrid_domain_resource_test.go b/internal/services/eventgrid/eventgrid_domain_resource_test.go index bb5c077a082b..59dc9691951c 100644 --- a/internal/services/eventgrid/eventgrid_domain_resource_test.go +++ b/internal/services/eventgrid/eventgrid_domain_resource_test.go @@ -5,11 +5,12 @@ import ( "fmt" "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "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/services/eventgrid/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" ) @@ -108,7 +109,26 @@ func TestAccEventGridDomain_inboundIPRules(t *testing.T) { }) } -func (EventGridDomainResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { +func TestAccEventGridDomain_basicWithIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") + r := EventGridDomainResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basicWithIdentity(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), + check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), + ), + }, + data.ImportStep(), + }) +} + +func (EventGridDomainResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.DomainID(state.ID) if err != nil { return nil, err @@ -238,3 +258,26 @@ resource "azurerm_eventgrid_domain" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } + +func (EventGridDomainResource) basicWithIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_eventgrid_domain" "test" { + name = "acctesteg-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/internal/services/eventgrid/eventgrid_topic_resource.go b/internal/services/eventgrid/eventgrid_topic_resource.go index 9543fca8d9cf..af8e1924f7e6 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource.go +++ b/internal/services/eventgrid/eventgrid_topic_resource.go @@ -55,7 +55,7 @@ func resourceEventGridTopic() *pluginsdk.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - "identity": EventGridTopicIdentitySchema(), + "identity": IdentitySchema(), "input_schema": { Type: pluginsdk.TypeString, @@ -196,7 +196,7 @@ func resourceEventGridTopicCreateUpdate(d *pluginsdk.ResourceData, meta interfac } identityRaw := d.Get("identity").([]interface{}) - identity, err := expandEventGridTopicIdentity(identityRaw) + identity, err := expandIdentity(identityRaw) if err != nil { return fmt.Errorf("expanding `identity`: %+v", err) } @@ -299,7 +299,7 @@ func resourceEventGridTopicRead(d *pluginsdk.ResourceData, meta interface{}) err d.Set("endpoint", props.Endpoint) } - if err := d.Set("identity", flattenEventGridTopicIdentity(resp.Identity)); err != nil { + if err := d.Set("identity", flattenIdentity(resp.Identity)); err != nil { return fmt.Errorf("setting `identity`: %+v", err) } diff --git a/internal/services/eventgrid/eventgrid_topic_resource_test.go b/internal/services/eventgrid/eventgrid_topic_resource_test.go index 1f04faed77d2..44392d851aab 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource_test.go +++ b/internal/services/eventgrid/eventgrid_topic_resource_test.go @@ -121,10 +121,10 @@ func TestAccEventGridTopic_basicWithIdentity(t *testing.T) { Config: r.basicWithIdentity(data), Check: resource.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), - check.That(data.ResourceName).Key("identity.%").HasValue("1"), - check.That(data.ResourceName).Key("identity.type").HasValue("SystemAssigned"), - check.That(data.ResourceName).Key("identity.principal_id").Exists(), - check.That(data.ResourceName).Key("identity.tenant_id").Exists(), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), + check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), ), }, data.ImportStep(), @@ -207,8 +207,6 @@ resource "azurerm_eventgrid_topic" "test" { } func (EventGridTopicResource) basicWithTags(data acceptance.TestData) string { - // currently only supported in "West Central US" & "West US 2" - location := "westus2" return fmt.Sprintf(` provider "azurerm" { features {} @@ -228,7 +226,7 @@ resource "azurerm_eventgrid_topic" "test" { "foo" = "bar" } } -`, data.RandomInteger, location, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } func (EventGridTopicResource) inboundIPRules(data acceptance.TestData) string { @@ -263,8 +261,6 @@ resource "azurerm_eventgrid_topic" "test" { } func (EventGridTopicResource) basicWithIdentity(data acceptance.TestData) string { - // currently only supported in "West Central US" & "West US 2" - location := "westus2" return fmt.Sprintf(` provider "azurerm" { features {} @@ -284,5 +280,5 @@ resource "azurerm_eventgrid_topic" "test" { type = "SystemAssigned" } } -`, data.RandomInteger, location, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } From 6addeb5bcc3fda7bcfc9989e5462891b13ad607c Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Thu, 17 Dec 2020 08:37:17 +0100 Subject: [PATCH 05/21] docs --- website/docs/r/eventgrid_domain.html.markdown | 10 ++++++++++ website/docs/r/eventgrid_topic.html.markdown | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/website/docs/r/eventgrid_domain.html.markdown b/website/docs/r/eventgrid_domain.html.markdown index db76a4261323..cb7c8c630dfc 100644 --- a/website/docs/r/eventgrid_domain.html.markdown +++ b/website/docs/r/eventgrid_domain.html.markdown @@ -40,6 +40,8 @@ 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. +* `identity` - (Optional) An `identity` block as defined below. + * `input_schema` - (Optional) Specifies the schema in which incoming events will be published to this domain. Allowed values are `CloudEventSchemaV1_0`, `CustomEventSchema`, or `EventGridSchema`. Defaults to `eventgridschema`. Changing this forces a new resource to be created. * `input_mapping_fields` - (Optional) A `input_mapping_fields` block as defined below. @@ -54,6 +56,14 @@ The following arguments are supported: --- +A `identity` block exports the following: + +~> **Note:** Currently only type `SystemAssigned` identity is supported. + +* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. + +--- + A `input_mapping_fields` supports the following: * `id` - (Optional) Specifies the id of the EventGrid Event to associate with the domain. Changing this forces a new resource to be created. diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index dc86f5f965a2..17eabf33fb9c 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -42,6 +42,8 @@ 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. +* `identity` - (Optional) An `identity` block as defined below. + * `input_schema` - (Optional) Specifies the schema in which incoming events will be published to this domain. Allowed values are `CloudEventSchemaV1_0`, `CustomEventSchema`, or `EventGridSchema`. Defaults to `EventGridSchema`. Changing this forces a new resource to be created. * `input_mapping_fields` - (Optional) A `input_mapping_fields` block as defined below. @@ -56,6 +58,14 @@ The following arguments are supported: --- +A `identity` block exports the following: + +~> **Note:** Currently only type `SystemAssigned` identity is supported. + +* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. + +--- + A `input_mapping_fields` supports the following: * `id` - (Optional) Specifies the id of the EventGrid Event to associate with the domain. Changing this forces a new resource to be created. From 16208143a8f93fbbf0669ba6eacf059c288d645b Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Wed, 11 Aug 2021 13:36:00 +0200 Subject: [PATCH 06/21] fix: check if input is nil --- internal/services/eventgrid/eventgrid.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/eventgrid/eventgrid.go b/internal/services/eventgrid/eventgrid.go index a32fa564b70b..fa7fdb9e0cab 100644 --- a/internal/services/eventgrid/eventgrid.go +++ b/internal/services/eventgrid/eventgrid.go @@ -136,7 +136,7 @@ func flattenInboundIPRules(in *[]eventgrid.InboundIPRule) []interface{} { } func expandIdentity(input []interface{}) (*eventgrid.IdentityInfo, error) { - if len(input) == 0 { + if len(input) == 0 || input[0] == nil { return &eventgrid.IdentityInfo{ Type: eventgrid.IdentityTypeNone, }, nil From 10cf9bef2a2eaf4296c71335aef174f256dcaa02 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Wed, 11 Aug 2021 14:03:32 +0200 Subject: [PATCH 07/21] fix: documentation --- website/docs/r/eventgrid_domain.html.markdown | 24 +++++++++++++++---- website/docs/r/eventgrid_topic.html.markdown | 24 +++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/website/docs/r/eventgrid_domain.html.markdown b/website/docs/r/eventgrid_domain.html.markdown index cb7c8c630dfc..b394f06cfedf 100644 --- a/website/docs/r/eventgrid_domain.html.markdown +++ b/website/docs/r/eventgrid_domain.html.markdown @@ -56,11 +56,13 @@ The following arguments are supported: --- -A `identity` block exports the following: +A `identity` block supports the following: -~> **Note:** Currently only type `SystemAssigned` identity is supported. +* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Managed Identity for you), `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field, and `SystemAssigned, UserAssigned` which assigns both a system managed identity as well as the specified user assigned identities. -* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. +~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Domain has been created. More details are available below. + +* `identity_ids` - (Optional) Specifies a list of user managed identity ids to be assigned. Required if `type` is `UserAssigned`. --- @@ -108,9 +110,23 @@ The following attributes are exported: * `secondary_access_key` - The Secondary Shared Access Key associated with the EventGrid Domain. -## Timeouts +* `identity` - An `identity` block as defined below, which contains the Managed Service Identity information for this Event Grid Domain. +--- + +A `identity` block exports the following: +* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. + +* `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. + +* `tenant_id` - Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. + +* `identity_ids` - A list of IDs for User Assigned Managed Identity resources to be assigned. + +--- + +## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 17eabf33fb9c..3df421a31f24 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -58,11 +58,13 @@ The following arguments are supported: --- -A `identity` block exports the following: +A `identity` block supports the following: -~> **Note:** Currently only type `SystemAssigned` identity is supported. +* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Managed Identity for you), `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field, and `SystemAssigned, UserAssigned` which assigns both a system managed identity as well as the specified user assigned identities. -* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. +~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Domain has been created. More details are available below. + +* `identity_ids` - (Optional) Specifies a list of user managed identity ids to be assigned. Required if `type` is `UserAssigned`. --- @@ -110,9 +112,23 @@ The following attributes are exported: * `secondary_access_key` - The Secondary Shared Access Key associated with the EventGrid Topic. -## Timeouts +* `identity` - An `identity` block as defined below, which contains the Managed Service Identity information for this Event Grid Domain. +--- + +A `identity` block exports the following: +* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. + +* `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. + +* `tenant_id` - Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. + +* `identity_ids` - A list of IDs for User Assigned Managed Identity resources to be assigned. + +--- + +## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: From 3105b2fdeaadac3592336e017b5e40400e06c9f3 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Wed, 11 Aug 2021 14:16:57 +0200 Subject: [PATCH 08/21] fix: add tests for identity_ids --- .../eventgrid_domain_resource_test.go | 119 ++++++++++++++++-- 1 file changed, 112 insertions(+), 7 deletions(-) diff --git a/internal/services/eventgrid/eventgrid_domain_resource_test.go b/internal/services/eventgrid/eventgrid_domain_resource_test.go index 59dc9691951c..1e7e453837ca 100644 --- a/internal/services/eventgrid/eventgrid_domain_resource_test.go +++ b/internal/services/eventgrid/eventgrid_domain_resource_test.go @@ -109,17 +109,58 @@ func TestAccEventGridDomain_inboundIPRules(t *testing.T) { }) } -func TestAccEventGridDomain_basicWithIdentity(t *testing.T) { +func TestAccEventGridDomain_basicWithSystemManagedIdentity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") r := EventGridDomainResource{} data.ResourceTest(t, r, []resource.TestStep{ { - Config: r.basicWithIdentity(data), + Config: r.basicWithSystemManagedIdentity(data), Check: resource.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), + check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), + ), + }, + data.ImportStep(), + }) +} + +func TestAccEventGridDomain_basicWithUserAssignedManagedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") + r := EventGridDomainResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basicWithUserAssignedManagedIdentity(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("UserAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids").IsSet(), + check.That(data.ResourceName).Key("identity.0.principal_id").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.tenant_id").IsEmpty(), + ), + }, + data.ImportStep(), + }) +} + +func TestAccEventGridDomain_basicWithSystemAndUserAssignedManagedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") + r := EventGridDomainResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basicWithSystemAndUserAssignedManagedIdentity(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned, UserAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids").IsSet(), check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), ), @@ -259,19 +300,19 @@ resource "azurerm_eventgrid_domain" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func (EventGridDomainResource) basicWithIdentity(data acceptance.TestData) string { +func (EventGridDomainResource) basicWithSystemManagedIdentity(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { features {} } resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" + name = "acctestRG-%[1]d" + location = "%[2]s" } resource "azurerm_eventgrid_domain" "test" { - name = "acctesteg-%d" + name = "acctesteg-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name @@ -279,5 +320,69 @@ resource "azurerm_eventgrid_domain" "test" { type = "SystemAssigned" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary) +} + +func (EventGridDomainResource) basicWithUserAssignedManagedIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_user_assigned_identity" "test" { + name = "acctesteg-%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +resource "azurerm_eventgrid_domain" "test" { + name = "acctesteg-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + identity { + type = "UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id + ] + } +} +`, data.RandomInteger, data.Locations.Primary) +} + +func (EventGridDomainResource) basicWithSystemAndUserAssignedManagedIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_user_assigned_identity" "test" { + name = "acctesteg-%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +resource "azurerm_eventgrid_domain" "test" { + name = "acctesteg-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + identity { + type = "SystemAssigned, UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id + ] + } +} +`, data.RandomInteger, data.Locations.Primary) } From d6ebf28a913f640794ab8cdd8deefa36393284f6 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Wed, 11 Aug 2021 14:55:38 +0200 Subject: [PATCH 09/21] fix: PR notes --- internal/services/eventgrid/eventgrid.go | 1 + .../eventgrid_domain_resource_test.go | 56 +--------------- .../eventgrid_topic_resource_test.go | 67 +++++++++++++++++-- website/docs/r/eventgrid_domain.html.markdown | 2 +- website/docs/r/eventgrid_topic.html.markdown | 2 +- 5 files changed, 65 insertions(+), 63 deletions(-) diff --git a/internal/services/eventgrid/eventgrid.go b/internal/services/eventgrid/eventgrid.go index fa7fdb9e0cab..57fb4275686e 100644 --- a/internal/services/eventgrid/eventgrid.go +++ b/internal/services/eventgrid/eventgrid.go @@ -23,6 +23,7 @@ func IdentitySchema() *schema.Schema { ValidateFunc: validation.StringInSlice([]string{ string(eventgrid.IdentityTypeNone), string(eventgrid.IdentityTypeSystemAssigned), + string(eventgrid.IdentityTypeUserAssigned), }, false), }, diff --git a/internal/services/eventgrid/eventgrid_domain_resource_test.go b/internal/services/eventgrid/eventgrid_domain_resource_test.go index 1e7e453837ca..13f47a378d23 100644 --- a/internal/services/eventgrid/eventgrid_domain_resource_test.go +++ b/internal/services/eventgrid/eventgrid_domain_resource_test.go @@ -120,7 +120,7 @@ func TestAccEventGridDomain_basicWithSystemManagedIdentity(t *testing.T) { check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), - check.That(data.ResourceName).Key("identity.0.identity_ids").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("0"), check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), ), @@ -140,7 +140,7 @@ func TestAccEventGridDomain_basicWithUserAssignedManagedIdentity(t *testing.T) { check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("UserAssigned"), - check.That(data.ResourceName).Key("identity.0.identity_ids").IsSet(), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.principal_id").IsEmpty(), check.That(data.ResourceName).Key("identity.0.tenant_id").IsEmpty(), ), @@ -149,26 +149,6 @@ func TestAccEventGridDomain_basicWithUserAssignedManagedIdentity(t *testing.T) { }) } -func TestAccEventGridDomain_basicWithSystemAndUserAssignedManagedIdentity(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") - r := EventGridDomainResource{} - - data.ResourceTest(t, r, []resource.TestStep{ - { - Config: r.basicWithSystemAndUserAssignedManagedIdentity(data), - Check: resource.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - check.That(data.ResourceName).Key("identity.#").HasValue("1"), - check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned, UserAssigned"), - check.That(data.ResourceName).Key("identity.0.identity_ids").IsSet(), - check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), - check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), - ), - }, - data.ImportStep(), - }) -} - func (EventGridDomainResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.DomainID(state.ID) if err != nil { @@ -354,35 +334,3 @@ resource "azurerm_eventgrid_domain" "test" { } `, data.RandomInteger, data.Locations.Primary) } - -func (EventGridDomainResource) basicWithSystemAndUserAssignedManagedIdentity(data acceptance.TestData) string { - return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%[1]d" - location = "%[2]s" -} - -resource "azurerm_user_assigned_identity" "test" { - name = "acctesteg-%[1]d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location -} - -resource "azurerm_eventgrid_domain" "test" { - name = "acctesteg-%[1]d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - - identity { - type = "SystemAssigned, UserAssigned" - identity_ids = [ - azurerm_user_assigned_identity.test.id - ] - } -} -`, data.RandomInteger, data.Locations.Primary) -} diff --git a/internal/services/eventgrid/eventgrid_topic_resource_test.go b/internal/services/eventgrid/eventgrid_topic_resource_test.go index 44392d851aab..d98f840ceaf6 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource_test.go +++ b/internal/services/eventgrid/eventgrid_topic_resource_test.go @@ -112,17 +112,18 @@ func TestAccEventGridTopic_inboundIPRules(t *testing.T) { }) } -func TestAccEventGridTopic_basicWithIdentity(t *testing.T) { +func TestAccEventGridTopic_basicWithSystemManagedIdentity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_eventgrid_topic", "test") r := EventGridTopicResource{} data.ResourceTest(t, r, []resource.TestStep{ { - Config: r.basicWithIdentity(data), + Config: r.basicWithSystemManagedIdentity(data), Check: resource.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("0"), check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), ), @@ -131,6 +132,26 @@ func TestAccEventGridTopic_basicWithIdentity(t *testing.T) { }) } +func TestAccEventGridTopic_basicWithUserAssignedManagedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_topic", "test") + r := EventGridTopicResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.basicWithUserAssignedManagedIdentity(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("UserAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.principal_id").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.tenant_id").IsEmpty(), + ), + }, + data.ImportStep(), + }) +} + func (EventGridTopicResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.TopicID(state.ID) if err != nil { @@ -260,19 +281,19 @@ resource "azurerm_eventgrid_topic" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func (EventGridTopicResource) basicWithIdentity(data acceptance.TestData) string { +func (EventGridTopicResource) basicWithSystemManagedIdentity(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { features {} } resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" + name = "acctestRG-%[1]d" + location = "%[2]s" } resource "azurerm_eventgrid_topic" "test" { - name = "acctesteg-%d" + name = "acctesteg-%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name @@ -280,5 +301,37 @@ resource "azurerm_eventgrid_topic" "test" { type = "SystemAssigned" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary) +} + +func (EventGridTopicResource) basicWithUserAssignedManagedIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_user_assigned_identity" "test" { + name = "acctesteg-%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +resource "azurerm_eventgrid_topic" "test" { + name = "acctesteg-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + identity { + type = "UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id + ] + } +} +`, data.RandomInteger, data.Locations.Primary) } diff --git a/website/docs/r/eventgrid_domain.html.markdown b/website/docs/r/eventgrid_domain.html.markdown index b394f06cfedf..84e05eb13e11 100644 --- a/website/docs/r/eventgrid_domain.html.markdown +++ b/website/docs/r/eventgrid_domain.html.markdown @@ -58,7 +58,7 @@ The following arguments are supported: A `identity` block supports the following: -* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Managed Identity for you), `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field, and `SystemAssigned, UserAssigned` which assigns both a system managed identity as well as the specified user assigned identities. +* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Principal for you) or `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field. ~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Domain has been created. More details are available below. diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 3df421a31f24..5bb747492d34 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -60,7 +60,7 @@ The following arguments are supported: A `identity` block supports the following: -* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Managed Identity for you), `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field, and `SystemAssigned, UserAssigned` which assigns both a system managed identity as well as the specified user assigned identities. +* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Principal for you) or `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field. ~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Domain has been created. More details are available below. From 48ecb5c701f618db8d6c8f4ce39286c0c4769958 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Wed, 11 Aug 2021 15:08:17 +0200 Subject: [PATCH 10/21] fix: refactor identity assignment --- .../eventgrid/eventgrid_domain_resource.go | 16 ++++++++------ .../eventgrid/eventgrid_topic_resource.go | 22 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/internal/services/eventgrid/eventgrid_domain_resource.go b/internal/services/eventgrid/eventgrid_domain_resource.go index 664f3fc7f0f7..59b1839f7007 100644 --- a/internal/services/eventgrid/eventgrid_domain_resource.go +++ b/internal/services/eventgrid/eventgrid_domain_resource.go @@ -188,12 +188,6 @@ func resourceEventGridDomainCreateUpdate(d *pluginsdk.ResourceData, meta interfa location := azure.NormalizeLocation(d.Get("location").(string)) t := d.Get("tags").(map[string]interface{}) - identityRaw := d.Get("identity").([]interface{}) - identity, err := expandIdentity(identityRaw) - if err != nil { - return fmt.Errorf("expanding `identity`: %+v", err) - } - domainProperties := &eventgrid.DomainProperties{ InputSchemaMapping: expandAzureRmEventgridDomainInputMapping(d), InputSchema: eventgrid.InputSchema(d.Get("input_schema").(string)), @@ -203,11 +197,19 @@ func resourceEventGridDomainCreateUpdate(d *pluginsdk.ResourceData, meta interfa domain := eventgrid.Domain{ Location: &location, - Identity: identity, DomainProperties: domainProperties, Tags: tags.Expand(t), } + if v, ok := d.GetOk("identity"); ok { + identityRaw := v.([]interface{}) + identity, err := expandIdentity(identityRaw) + if err != nil { + return fmt.Errorf("expanding `identity`: %+v", err) + } + domain.Identity = identity + } + log.Printf("[INFO] preparing arguments for AzureRM EventGrid Domain creation with Properties: %+v", domain) future, err := client.CreateOrUpdate(ctx, resourceGroup, name, domain) diff --git a/internal/services/eventgrid/eventgrid_topic_resource.go b/internal/services/eventgrid/eventgrid_topic_resource.go index af8e1924f7e6..2e651533cef8 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource.go +++ b/internal/services/eventgrid/eventgrid_topic_resource.go @@ -195,22 +195,24 @@ func resourceEventGridTopicCreateUpdate(d *pluginsdk.ResourceData, meta interfac InboundIPRules: expandInboundIPRules(d), } - identityRaw := d.Get("identity").([]interface{}) - identity, err := expandIdentity(identityRaw) - if err != nil { - return fmt.Errorf("expanding `identity`: %+v", err) - } - - properties := eventgrid.Topic{ + topic := eventgrid.Topic{ Location: &location, - Identity: identity, TopicProperties: topicProperties, Tags: tags.Expand(t), } - log.Printf("[INFO] preparing arguments for AzureRM EventGrid Topic creation with Properties: %+v.", properties) + if v, ok := d.GetOk("identity"); ok { + identityRaw := v.([]interface{}) + identity, err := expandIdentity(identityRaw) + if err != nil { + return fmt.Errorf("expanding `identity`: %+v", err) + } + topic.Identity = identity + } + + log.Printf("[INFO] preparing arguments for AzureRM EventGrid Topic creation with Properties: %+v.", topic) - future, err := client.CreateOrUpdate(ctx, resourceGroup, name, properties) + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, topic) if err != nil { return err } From 3ca99ec01d3ba8c68d2613031c3f613bdb784dc4 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:27:25 +0200 Subject: [PATCH 11/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 5bb747492d34..ca925ec8290a 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -122,7 +122,7 @@ A `identity` block exports the following: * `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. -* `tenant_id` - Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. +* `tenant_id` - Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Event Grid Topic. * `identity_ids` - A list of IDs for User Assigned Managed Identity resources to be assigned. From e9a772ab46c9f0f241326203ad64c0e78fd5dbb4 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:27:45 +0200 Subject: [PATCH 12/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index ca925ec8290a..7ba8514aa55d 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -60,7 +60,7 @@ The following arguments are supported: A `identity` block supports the following: -* `type` - Specifies the identity type of Event Grid Domain. Possible values are `SystemAssigned` (where Azure will generate a Principal for you) or `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field. +* `type` - Specifies the identity type of Event Grid Topic. Possible values are `SystemAssigned` (where Azure will generate a Principal for you) or `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field. ~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Domain has been created. More details are available below. From 09492572e0ae56531a44e93300823deb4b455a89 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:27:55 +0200 Subject: [PATCH 13/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 7ba8514aa55d..8f09e80a8c8d 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -62,7 +62,7 @@ A `identity` block supports the following: * `type` - Specifies the identity type of Event Grid Topic. Possible values are `SystemAssigned` (where Azure will generate a Principal for you) or `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field. -~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Domain has been created. More details are available below. +~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid Topic has been created. More details are available below. * `identity_ids` - (Optional) Specifies a list of user managed identity ids to be assigned. Required if `type` is `UserAssigned`. From d3b873e908c52cff41bddf5bb47ec58bb2277d02 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:28:05 +0200 Subject: [PATCH 14/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 8f09e80a8c8d..6cca6b531984 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -112,7 +112,7 @@ The following attributes are exported: * `secondary_access_key` - The Secondary Shared Access Key associated with the EventGrid Topic. -* `identity` - An `identity` block as defined below, which contains the Managed Service Identity information for this Event Grid Domain. +* `identity` - An `identity` block as defined below, which contains the Managed Service Identity information for this Event Grid Topic. --- From e1501c90bb0ae4542bd44b78d29888da7cff54e1 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:28:20 +0200 Subject: [PATCH 15/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 6cca6b531984..a86b676e689f 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -116,7 +116,7 @@ The following attributes are exported: --- -A `identity` block exports the following: +A `identity` block supports the following: * `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. From d24da41467ef82d40a04fa7a63179509350fd378 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:28:35 +0200 Subject: [PATCH 16/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index a86b676e689f..3fca92b5486f 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -118,7 +118,7 @@ The following attributes are exported: A `identity` block supports the following: -* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Domain. +* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Topic. * `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. From e7341b4255f8f45e2e85fde22adc41081f881451 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Fri, 3 Sep 2021 13:28:49 +0200 Subject: [PATCH 17/21] Update website/docs/r/eventgrid_topic.html.markdown Co-authored-by: stephybun --- website/docs/r/eventgrid_topic.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/eventgrid_topic.html.markdown b/website/docs/r/eventgrid_topic.html.markdown index 3fca92b5486f..c2838d74a509 100644 --- a/website/docs/r/eventgrid_topic.html.markdown +++ b/website/docs/r/eventgrid_topic.html.markdown @@ -120,7 +120,7 @@ A `identity` block supports the following: * `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid Topic. -* `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid Domain. +* `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid Topic. * `tenant_id` - Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Event Grid Topic. From 5d003a6590deff5ddfbbf6989584ac3d849c4791 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Mon, 6 Sep 2021 09:33:58 +0200 Subject: [PATCH 18/21] fix: rename conflicting identity functions --- internal/services/eventgrid/event_subscription.go | 4 ++-- .../eventgrid/eventgrid_event_subscription_resource.go | 8 ++++---- .../eventgrid_system_topic_event_subscription_resource.go | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/services/eventgrid/event_subscription.go b/internal/services/eventgrid/event_subscription.go index 7fcefacba5f9..7da48980d919 100644 --- a/internal/services/eventgrid/event_subscription.go +++ b/internal/services/eventgrid/event_subscription.go @@ -1121,7 +1121,7 @@ func expandEventGridEventSubscriptionRetryPolicy(d *pluginsdk.ResourceData) *eve return nil } -func expandIdentity(input []interface{}) *eventgrid.EventSubscriptionIdentity { +func expandEventGridEventSubscriptionIdentity(input []interface{}) *eventgrid.EventSubscriptionIdentity { if len(input) == 0 || input[0] == nil { return &eventgrid.EventSubscriptionIdentity{ Type: eventgrid.EventSubscriptionIdentityType("None"), @@ -1483,7 +1483,7 @@ func flattenKey(inputKey *string) map[string]interface{} { } } -func flattenIdentity(input *eventgrid.EventSubscriptionIdentity) []interface{} { +func flattenEventGridEventSubscriptionIdentity(input *eventgrid.EventSubscriptionIdentity) []interface{} { if input == nil || string(input.Type) == "None" { return []interface{}{} } diff --git a/internal/services/eventgrid/eventgrid_event_subscription_resource.go b/internal/services/eventgrid/eventgrid_event_subscription_resource.go index 8511e138a7c2..7628cc0434f3 100644 --- a/internal/services/eventgrid/eventgrid_event_subscription_resource.go +++ b/internal/services/eventgrid/eventgrid_event_subscription_resource.go @@ -203,7 +203,7 @@ func resourceEventGridEventSubscriptionCreateUpdate(d *pluginsdk.ResourceData, m if v, ok := d.GetOk("delivery_identity"); ok { deliveryIdentityRaw := v.([]interface{}) - deliveryIdentity := expandIdentity(deliveryIdentityRaw) + deliveryIdentity := expandEventGridEventSubscriptionIdentity(deliveryIdentityRaw) eventSubscriptionProperties.DeliveryWithResourceIdentity = &eventgrid.DeliveryWithResourceIdentity{ Identity: deliveryIdentity, Destination: destination, @@ -217,7 +217,7 @@ func resourceEventGridEventSubscriptionCreateUpdate(d *pluginsdk.ResourceData, m return fmt.Errorf("`dead_letter_identity`: `storage_blob_dead_letter_destination` must be specified") } deadLetterIdentityRaw := v.([]interface{}) - deadLetterIdentity := expandIdentity(deadLetterIdentityRaw) + deadLetterIdentity := expandEventGridEventSubscriptionIdentity(deadLetterIdentityRaw) eventSubscriptionProperties.DeadLetterWithResourceIdentity = &eventgrid.DeadLetterWithResourceIdentity{ Identity: deadLetterIdentity, DeadLetterDestination: deadLetterDestination, @@ -289,7 +289,7 @@ func resourceEventGridEventSubscriptionRead(d *pluginsdk.ResourceData, meta inte deliveryIdentityFlattened := make([]interface{}, 0) if deliveryIdentity := props.DeliveryWithResourceIdentity; deliveryIdentity != nil { destination = deliveryIdentity.Destination - deliveryIdentityFlattened = flattenIdentity(deliveryIdentity.Identity) + deliveryIdentityFlattened = flattenEventGridEventSubscriptionIdentity(deliveryIdentity.Identity) } if err := d.Set("delivery_identity", deliveryIdentityFlattened); err != nil { return fmt.Errorf("setting `delivery_identity` for EventGrid Event Subscription %q (Scope %q): %s", id.Name, id.Scope, err) @@ -347,7 +347,7 @@ func resourceEventGridEventSubscriptionRead(d *pluginsdk.ResourceData, meta inte deadLetterIdentityFlattened := make([]interface{}, 0) if deadLetterIdentity := props.DeadLetterWithResourceIdentity; deadLetterIdentity != nil { deadLetterDestination = deadLetterIdentity.DeadLetterDestination - deadLetterIdentityFlattened = flattenIdentity(deadLetterIdentity.Identity) + deadLetterIdentityFlattened = flattenEventGridEventSubscriptionIdentity(deadLetterIdentity.Identity) } if err := d.Set("dead_letter_identity", deadLetterIdentityFlattened); err != nil { return fmt.Errorf("setting `dead_letter_identity` for EventGrid Event Subscription %q (Scope %q): %s", id.Name, id.Scope, err) diff --git a/internal/services/eventgrid/eventgrid_system_topic_event_subscription_resource.go b/internal/services/eventgrid/eventgrid_system_topic_event_subscription_resource.go index 0e0d799ff8f7..3c1016c434fb 100644 --- a/internal/services/eventgrid/eventgrid_system_topic_event_subscription_resource.go +++ b/internal/services/eventgrid/eventgrid_system_topic_event_subscription_resource.go @@ -182,7 +182,7 @@ func resourceEventGridSystemTopicEventSubscriptionCreateUpdate(d *pluginsdk.Reso if v, ok := d.GetOk("delivery_identity"); ok { deliveryIdentityRaw := v.([]interface{}) - deliveryIdentity := expandIdentity(deliveryIdentityRaw) + deliveryIdentity := expandEventGridEventSubscriptionIdentity(deliveryIdentityRaw) eventSubscriptionProperties.DeliveryWithResourceIdentity = &eventgrid.DeliveryWithResourceIdentity{ Identity: deliveryIdentity, Destination: destination, @@ -196,7 +196,7 @@ func resourceEventGridSystemTopicEventSubscriptionCreateUpdate(d *pluginsdk.Reso return fmt.Errorf("`dead_letter_identity`: `storage_blob_dead_letter_destination` must be specified") } deadLetterIdentityRaw := v.([]interface{}) - deadLetterIdentity := expandIdentity(deadLetterIdentityRaw) + deadLetterIdentity := expandEventGridEventSubscriptionIdentity(deadLetterIdentityRaw) eventSubscriptionProperties.DeadLetterWithResourceIdentity = &eventgrid.DeadLetterWithResourceIdentity{ Identity: deadLetterIdentity, DeadLetterDestination: deadLetterDestination, @@ -269,7 +269,7 @@ func resourceEventGridSystemTopicEventSubscriptionRead(d *pluginsdk.ResourceData deliveryIdentityFlattened := make([]interface{}, 0) if deliveryIdentity := props.DeliveryWithResourceIdentity; deliveryIdentity != nil { destination = deliveryIdentity.Destination - deliveryIdentityFlattened = flattenIdentity(deliveryIdentity.Identity) + deliveryIdentityFlattened = flattenEventGridEventSubscriptionIdentity(deliveryIdentity.Identity) } if err := d.Set("delivery_identity", deliveryIdentityFlattened); err != nil { return fmt.Errorf("setting `delivery_identity` for EventGrid System Topic Event Subscription %q (System Topic %q): %s", id.Name, id.SystemTopic, err) @@ -319,7 +319,7 @@ func resourceEventGridSystemTopicEventSubscriptionRead(d *pluginsdk.ResourceData deadLetterIdentityFlattened := make([]interface{}, 0) if deadLetterIdentity := props.DeadLetterWithResourceIdentity; deadLetterIdentity != nil { deadLetterDestination = deadLetterIdentity.DeadLetterDestination - deadLetterIdentityFlattened = flattenIdentity(deadLetterIdentity.Identity) + deadLetterIdentityFlattened = flattenEventGridEventSubscriptionIdentity(deadLetterIdentity.Identity) } if err := d.Set("dead_letter_identity", deadLetterIdentityFlattened); err != nil { return fmt.Errorf("setting `dead_letter_identity` for EventGrid System Topic Event Subscription %q (Scope %q): %s", id.Name, id.SystemTopic, err) From 11ba381c56c9cbd6a38fe70c75722268084a4a1b Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Mon, 6 Sep 2021 10:08:52 +0200 Subject: [PATCH 19/21] fix: update tests to use acceptance module --- .../services/eventgrid/eventgrid_domain_resource_test.go | 9 ++++----- .../services/eventgrid/eventgrid_topic_resource_test.go | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/internal/services/eventgrid/eventgrid_domain_resource_test.go b/internal/services/eventgrid/eventgrid_domain_resource_test.go index 698169d61d3f..9651b0637bb2 100644 --- a/internal/services/eventgrid/eventgrid_domain_resource_test.go +++ b/internal/services/eventgrid/eventgrid_domain_resource_test.go @@ -5,7 +5,6 @@ import ( "fmt" "testing" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" @@ -113,10 +112,10 @@ func TestAccEventGridDomain_basicWithSystemManagedIdentity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") r := EventGridDomainResource{} - data.ResourceTest(t, r, []resource.TestStep{ + data.ResourceTest(t, r, []acceptance.TestStep{ { Config: r.basicWithSystemManagedIdentity(data), - Check: resource.ComposeTestCheckFunc( + Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), @@ -133,10 +132,10 @@ func TestAccEventGridDomain_basicWithUserAssignedManagedIdentity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test") r := EventGridDomainResource{} - data.ResourceTest(t, r, []resource.TestStep{ + data.ResourceTest(t, r, []acceptance.TestStep{ { Config: r.basicWithUserAssignedManagedIdentity(data), - Check: resource.ComposeTestCheckFunc( + Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("UserAssigned"), diff --git a/internal/services/eventgrid/eventgrid_topic_resource_test.go b/internal/services/eventgrid/eventgrid_topic_resource_test.go index d98f840ceaf6..5397ad314161 100644 --- a/internal/services/eventgrid/eventgrid_topic_resource_test.go +++ b/internal/services/eventgrid/eventgrid_topic_resource_test.go @@ -5,7 +5,6 @@ import ( "fmt" "testing" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" @@ -116,10 +115,10 @@ func TestAccEventGridTopic_basicWithSystemManagedIdentity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_eventgrid_topic", "test") r := EventGridTopicResource{} - data.ResourceTest(t, r, []resource.TestStep{ + data.ResourceTest(t, r, []acceptance.TestStep{ { Config: r.basicWithSystemManagedIdentity(data), - Check: resource.ComposeTestCheckFunc( + Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), @@ -136,10 +135,10 @@ func TestAccEventGridTopic_basicWithUserAssignedManagedIdentity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_eventgrid_topic", "test") r := EventGridTopicResource{} - data.ResourceTest(t, r, []resource.TestStep{ + data.ResourceTest(t, r, []acceptance.TestStep{ { Config: r.basicWithUserAssignedManagedIdentity(data), - Check: resource.ComposeTestCheckFunc( + Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.#").HasValue("1"), check.That(data.ResourceName).Key("identity.0.type").HasValue("UserAssigned"), From 02d4dc1af48aba8b6bec4e354163c43e428fd5b6 Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Mon, 6 Sep 2021 10:09:19 +0200 Subject: [PATCH 20/21] feat: added identity support to system topic --- .../eventgrid_system_topic_resource.go | 29 ++++- .../eventgrid_system_topic_resource_test.go | 115 ++++++++++++++++++ .../r/eventgrid_system_topic.html.markdown | 28 +++++ 3 files changed, 166 insertions(+), 6 deletions(-) diff --git a/internal/services/eventgrid/eventgrid_system_topic_resource.go b/internal/services/eventgrid/eventgrid_system_topic_resource.go index a9c4d592b2be..b8ba87f162a9 100644 --- a/internal/services/eventgrid/eventgrid_system_topic_resource.go +++ b/internal/services/eventgrid/eventgrid_system_topic_resource.go @@ -55,6 +55,8 @@ func resourceEventGridSystemTopic() *pluginsdk.Resource { "resource_group_name": azure.SchemaResourceGroupName(), + "identity": IdentitySchema(), + "source_arm_resource_id": { Type: pluginsdk.TypeString, Required: true, @@ -105,13 +107,24 @@ func resourceEventGridSystemTopicCreateUpdate(d *pluginsdk.ResourceData, meta in location := azure.NormalizeLocation(d.Get("location").(string)) t := d.Get("tags").(map[string]interface{}) + systemTopicProperties := &eventgrid.SystemTopicProperties{ + Source: &source, + TopicType: &topicType, + } + systemTopic := eventgrid.SystemTopic{ - Location: &location, - SystemTopicProperties: &eventgrid.SystemTopicProperties{ - Source: &source, - TopicType: &topicType, - }, - Tags: tags.Expand(t), + Location: &location, + SystemTopicProperties: systemTopicProperties, + Tags: tags.Expand(t), + } + + if v, ok := d.GetOk("identity"); ok { + identityRaw := v.([]interface{}) + identity, err := expandIdentity(identityRaw) + if err != nil { + return fmt.Errorf("expanding `identity`: %+v", err) + } + systemTopic.Identity = identity } log.Printf("[INFO] preparing arguments for AzureRM Event Grid System Topic creation with Properties: %+v.", systemTopic) @@ -171,6 +184,10 @@ func resourceEventGridSystemTopicRead(d *pluginsdk.ResourceData, meta interface{ d.Set("metric_arm_resource_id", props.MetricResourceID) } + if err := d.Set("identity", flattenIdentity(resp.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + return tags.FlattenAndSet(d, resp.Tags) } diff --git a/internal/services/eventgrid/eventgrid_system_topic_resource_test.go b/internal/services/eventgrid/eventgrid_system_topic_resource_test.go index 54383729eb0b..0dff5c4b806a 100644 --- a/internal/services/eventgrid/eventgrid_system_topic_resource_test.go +++ b/internal/services/eventgrid/eventgrid_system_topic_resource_test.go @@ -90,6 +90,46 @@ func TestAccEventGridSystemTopic_complete(t *testing.T) { }) } +func TestAccEventGridSystemTopic_basicWithSystemManagedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_system_topic", "test") + r := EventGridSystemTopicResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicWithSystemManagedIdentity(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("0"), + check.That(data.ResourceName).Key("identity.0.principal_id").Exists(), + check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(), + ), + }, + data.ImportStep(), + }) +} + +func TestAccEventGridSystemTopic_basicWithUserAssignedManagedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_eventgrid_system_topic", "test") + r := EventGridSystemTopicResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicWithUserAssignedManagedIdentity(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("UserAssigned"), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.principal_id").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.tenant_id").IsEmpty(), + ), + }, + data.ImportStep(), + }) +} + func (EventGridSystemTopicResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.SystemTopicID(state.ID) if err != nil { @@ -206,3 +246,78 @@ resource "azurerm_eventgrid_system_topic" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(10)) } + +func (EventGridSystemTopicResource) basicWithSystemManagedIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestegst%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_eventgrid_system_topic" "test" { + name = "acctesteg-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + source_arm_resource_id = azurerm_storage_account.test.id + topic_type = "Microsoft.Storage.StorageAccounts" + + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, data.Locations.Primary) +} + +func (EventGridSystemTopicResource) basicWithUserAssignedManagedIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestegst%[1]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 = "acctesteg-%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +resource "azurerm_eventgrid_system_topic" "test" { + name = "acctesteg-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + source_arm_resource_id = azurerm_storage_account.test.id + topic_type = "Microsoft.Storage.StorageAccounts" + + identity { + type = "UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id + ] + } +} +`, data.RandomInteger, data.Locations.Primary) +} diff --git a/website/docs/r/eventgrid_system_topic.html.markdown b/website/docs/r/eventgrid_system_topic.html.markdown index 849de22671ed..5175714254a9 100644 --- a/website/docs/r/eventgrid_system_topic.html.markdown +++ b/website/docs/r/eventgrid_system_topic.html.markdown @@ -49,6 +49,8 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the Resource Group where the Event Grid System Topic should exist. Changing this forces a new Event Grid System Topic to be created. +* `identity` - (Optional) An `identity` block as defined below. + * `source_arm_resource_id` - (Required) The ID of the Event Grid System Topic ARM Source. Changing this forces a new Event Grid System Topic to be created. * `topic_type` - (Required) The Topic Type of the Event Grid System Topic. Possible values are: `Microsoft.AppConfiguration.ConfigurationStores`, `Microsoft.Communication.CommunicationServices` @@ -58,6 +60,16 @@ The following arguments are supported: --- +A `identity` block supports the following: + +* `type` - Specifies the identity type of Event Grid System Topic. Possible values are `SystemAssigned` (where Azure will generate a Principal for you) or `UserAssigned` where you can specify the User Assigned Managed Identity IDs in the `identity_ids` field. + +~> **NOTE:** When `type` is set to `SystemAssigned`, The assigned `principal_id` and `tenant_id` can be retrieved after the Event Grid System Topic has been created. More details are available below. + +* `identity_ids` - (Optional) Specifies a list of user managed identity ids to be assigned. Required if `type` is `UserAssigned`. + +--- + * `tags` - (Optional) A mapping of tags which should be assigned to the Event Grid System Topic. ## Attributes Reference @@ -66,8 +78,24 @@ In addition to the Arguments listed above - the following Attributes are exporte * `id` - The ID of the Event Grid System Topic. +* `identity` - An `identity` block as defined below, which contains the Managed Service Identity information for this Event Grid System Topic. + * `metric_arm_resource_id` - The Metric ARM Resource ID of the Event Grid System Topic. +--- + +A `identity` block supports the following: + +* `type` - Specifies the type of Managed Service Identity that is configured on this Event Grid System Topic. + +* `principal_id` - Specifies the Principal ID of the System Assigned Managed Service Identity that is configured on this Event Grid System Topic. + +* `tenant_id` - Specifies the Tenant ID of the System Assigned Managed Service Identity that is configured on this Event Grid System Topic. + +* `identity_ids` - A list of IDs for User Assigned Managed Identity resources to be assigned. + +--- + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: From e9e897731e83f871d9684b7f71d8fb2baaefa76c Mon Sep 17 00:00:00 2001 From: Jochen Rauschenbusch Date: Mon, 6 Sep 2021 10:46:39 +0200 Subject: [PATCH 21/21] fix: system topic tests --- .../eventgrid_system_topic_resource_test.go | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/internal/services/eventgrid/eventgrid_system_topic_resource_test.go b/internal/services/eventgrid/eventgrid_system_topic_resource_test.go index 0dff5c4b806a..9e8d3362f9a7 100644 --- a/internal/services/eventgrid/eventgrid_system_topic_resource_test.go +++ b/internal/services/eventgrid/eventgrid_system_topic_resource_test.go @@ -151,12 +151,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-eg-%d" - location = "%s" + name = "acctestRG-%[1]d" + location = "%[2]s" } resource "azurerm_storage_account" "test" { - name = "acctestegst%d" + name = "acctestegst%[3]d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location account_tier = "Standard" @@ -164,13 +164,13 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_eventgrid_system_topic" "test" { - name = "acctestEGST%d" + name = "acctestEGST%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name source_arm_resource_id = azurerm_storage_account.test.id topic_type = "Microsoft.Storage.StorageAccounts" } -`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(12), data.RandomIntOfLength(10)) +`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(12)) } func (r EventGridSystemTopicResource) requiresImport(data acceptance.TestData) string { @@ -194,12 +194,12 @@ provider "azurerm" { } resource "azurerm_resource_group" "test" { - name = "acctestRG-eg-%d" - location = "%s" + name = "acctestRG-%[1]d" + location = "%[2]s" } resource "azurerm_storage_account" "test" { - name = "acctestegst%d" + name = "acctestegst%[3]d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location account_tier = "Standard" @@ -207,7 +207,7 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_eventgrid_system_topic" "test" { - name = "acctestEGST%d" + name = "acctestEGST%[1]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name source_arm_resource_id = azurerm_storage_account.test.id @@ -217,7 +217,7 @@ resource "azurerm_eventgrid_system_topic" "test" { "Foo" = "Bar" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(12), data.RandomIntOfLength(10)) +`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(12)) } func (EventGridSystemTopicResource) policyStates(data acceptance.TestData) string { @@ -229,12 +229,12 @@ provider "azurerm" { data "azurerm_subscription" "current" {} resource "azurerm_resource_group" "test" { - name = "acctestRG-eg-%d" - location = "%s" + name = "acctestRG-%[1]d" + location = "%[2]s" } resource "azurerm_eventgrid_system_topic" "test" { - name = "acctestEGST%d" + name = "acctestEGST%[1]d" location = "Global" resource_group_name = azurerm_resource_group.test.name source_arm_resource_id = format("/subscriptions/%%s", data.azurerm_subscription.current.subscription_id) @@ -259,7 +259,7 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_storage_account" "test" { - name = "acctestegst%[1]d" + name = "acctestegst%[3]d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location account_tier = "Standard" @@ -277,7 +277,7 @@ resource "azurerm_eventgrid_system_topic" "test" { type = "SystemAssigned" } } -`, data.RandomInteger, data.Locations.Primary) +`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(12)) } func (EventGridSystemTopicResource) basicWithUserAssignedManagedIdentity(data acceptance.TestData) string { @@ -292,7 +292,7 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_storage_account" "test" { - name = "acctestegst%[1]d" + name = "acctestegst%[3]d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location account_tier = "Standard" @@ -319,5 +319,5 @@ resource "azurerm_eventgrid_system_topic" "test" { ] } } -`, data.RandomInteger, data.Locations.Primary) +`, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(12)) }