diff --git a/internal/services/digitaltwins/digital_twins_endpoint_eventgrid_resource.go b/internal/services/digitaltwins/digital_twins_endpoint_eventgrid_resource.go index 88be6b263cfa8..75758bd8f0b66 100644 --- a/internal/services/digitaltwins/digital_twins_endpoint_eventgrid_resource.go +++ b/internal/services/digitaltwins/digital_twins_endpoint_eventgrid_resource.go @@ -18,7 +18,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) func resourceDigitalTwinsEndpointEventGrid() *pluginsdk.Resource { @@ -114,10 +113,10 @@ func resourceDigitalTwinsEndpointEventGridCreateUpdate(d *pluginsdk.ResourceData payload := endpoints.DigitalTwinsEndpointResource{ Properties: &endpoints.EventGrid{ AuthenticationType: pointer.To(endpoints.AuthenticationTypeKeyBased), - TopicEndpoint: utils.String(d.Get("eventgrid_topic_endpoint").(string)), - AccessKey1: utils.String(d.Get("eventgrid_topic_primary_access_key").(string)), - AccessKey2: utils.String(d.Get("eventgrid_topic_secondary_access_key").(string)), - DeadLetterSecret: utils.String(d.Get("dead_letter_storage_secret").(string)), + TopicEndpoint: d.Get("eventgrid_topic_endpoint").(string), + AccessKey1: d.Get("eventgrid_topic_primary_access_key").(string), + AccessKey2: pointer.To(d.Get("eventgrid_topic_secondary_access_key").(string)), + DeadLetterSecret: pointer.To(d.Get("dead_letter_storage_secret").(string)), }, } diff --git a/internal/services/digitaltwins/digital_twins_instance_resource.go b/internal/services/digitaltwins/digital_twins_instance_resource.go index 3a797c1485452..8780ec3fdbc55 100644 --- a/internal/services/digitaltwins/digital_twins_instance_resource.go +++ b/internal/services/digitaltwins/digital_twins_instance_resource.go @@ -57,7 +57,7 @@ func resourceDigitalTwinsInstance() *pluginsdk.Resource { Computed: true, }, - "identity": commonschema.SystemAssignedIdentityOptional(), + "identity": commonschema.SystemAssignedUserAssignedIdentityOptional(), "tags": commonschema.Tags(), }, @@ -81,7 +81,7 @@ func resourceDigitalTwinsInstanceCreate(d *pluginsdk.ResourceData, meta interfac return tf.ImportAsExistsError("azurerm_digital_twins_instance", id.ID()) } - expandedIdentity, err := identity.ExpandSystemAssigned(d.Get("identity").([]interface{})) + expandedIdentity, err := identity.ExpandLegacySystemAndUserAssignedMap(d.Get("identity").([]interface{})) if err != nil { return fmt.Errorf("expanding `identity`: %+v", err) } @@ -130,7 +130,11 @@ func resourceDigitalTwinsInstanceRead(d *pluginsdk.ResourceData, meta interface{ d.Set("host_name", props.HostName) } - if err := d.Set("identity", identity.FlattenSystemAssigned(model.Identity)); err != nil { + flattenedIdentity, err := identity.FlattenLegacySystemAndUserAssignedMap(model.Identity) + if err != nil { + return fmt.Errorf("flattening `identity`: %+v", err) + } + if err := d.Set("identity", flattenedIdentity); err != nil { return fmt.Errorf("setting `identity`: %+v", err) } @@ -155,7 +159,7 @@ func resourceDigitalTwinsInstanceUpdate(d *pluginsdk.ResourceData, meta interfac props := digitaltwinsinstance.DigitalTwinsPatchDescription{} if d.HasChange("identity") { - expandedIdentity, err := identity.ExpandSystemAssigned(d.Get("identity").([]interface{})) + expandedIdentity, err := identity.ExpandLegacySystemAndUserAssignedMap(d.Get("identity").([]interface{})) if err != nil { return fmt.Errorf("expanding `identity`: %+v", err) } diff --git a/internal/services/digitaltwins/digital_twins_instance_resource_test.go b/internal/services/digitaltwins/digital_twins_instance_resource_test.go index 4b9a8fdc6ae22..5105289be8592 100644 --- a/internal/services/digitaltwins/digital_twins_instance_resource_test.go +++ b/internal/services/digitaltwins/digital_twins_instance_resource_test.go @@ -102,12 +102,12 @@ func TestAccDigitalTwinsInstance_update(t *testing.T) { }) } -func TestAccDigitalTwinsInstance_identity(t *testing.T) { +func TestAccDigitalTwinsInstance_identitySystemAssigned(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_digital_twins_instance", "test") r := DigitalTwinsInstanceResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.basicWithIdentity(data), + Config: r.basicWithIdentitySystemAssigned(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.0.principal_id").IsUUID(), @@ -125,7 +125,7 @@ func TestAccDigitalTwinsInstance_identity(t *testing.T) { }, data.ImportStep(), { - Config: r.basicWithIdentity(data), + Config: r.basicWithIdentitySystemAssigned(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("identity.0.principal_id").IsUUID(), @@ -136,6 +136,40 @@ func TestAccDigitalTwinsInstance_identity(t *testing.T) { }) } +func TestAccDigitalTwinsInstance_identityUserAssigned(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_digital_twins_instance", "test") + r := DigitalTwinsInstanceResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicWithIdentityUserAssigned(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.0.principal_id").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.tenant_id").IsEmpty(), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.0.principal_id").DoesNotExist(), + check.That(data.ResourceName).Key("identity.0.tenant_id").DoesNotExist(), + ), + }, + data.ImportStep(), + { + Config: r.basicWithIdentityUserAssigned(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.0.principal_id").IsEmpty(), + check.That(data.ResourceName).Key("identity.0.tenant_id").IsEmpty(), + ), + }, + data.ImportStep(), + }) +} + func (DigitalTwinsInstanceResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := digitaltwinsinstance.ParseDigitalTwinsInstanceID(state.ID) if err != nil { @@ -219,7 +253,7 @@ resource "azurerm_digital_twins_instance" "test" { `, r.template(data), data.RandomInteger) } -func (r DigitalTwinsInstanceResource) basicWithIdentity(data acceptance.TestData) string { +func (r DigitalTwinsInstanceResource) basicWithIdentitySystemAssigned(data acceptance.TestData) string { return fmt.Sprintf(` %s @@ -233,3 +267,27 @@ resource "azurerm_digital_twins_instance" "test" { } `, r.template(data), data.RandomInteger) } + +func (r DigitalTwinsInstanceResource) basicWithIdentityUserAssigned(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_user_assigned_identity" "test" { + name = "acctest%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} + +resource "azurerm_digital_twins_instance" "test" { + name = "acctest-DT-%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + identity { + type = "UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id + ] + } +} +`, r.template(data), data.RandomInteger) +} diff --git a/internal/services/digitaltwins/digital_twins_time_series_database_connection_resource.go b/internal/services/digitaltwins/digital_twins_time_series_database_connection_resource.go index 8a0684a2845aa..6cf238975128a 100644 --- a/internal/services/digitaltwins/digital_twins_time_series_database_connection_resource.go +++ b/internal/services/digitaltwins/digital_twins_time_series_database_connection_resource.go @@ -253,7 +253,7 @@ func (m TimeSeriesDatabaseConnectionResource) Delete() sdk.ResourceFunc { } client := meta.Client.DigitalTwins.TimeSeriesDatabaseConnectionsClient - if err = client.DeleteThenPoll(ctx, *id); err != nil { + if err = client.DeleteThenPoll(ctx, *id, timeseriesdatabaseconnections.DefaultDeleteOperationOptions()); err != nil { return fmt.Errorf("deleting %s: %+v", id, err) } return nil diff --git a/website/docs/r/digital_twins_instance.html.markdown b/website/docs/r/digital_twins_instance.html.markdown index 4350299e14905..92b045cf0b61e 100644 --- a/website/docs/r/digital_twins_instance.html.markdown +++ b/website/docs/r/digital_twins_instance.html.markdown @@ -42,7 +42,7 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the Resource Group where the Digital Twins instance should exist. Changing this forces a new Digital Twins instance to be created. * `location` - (Required) The Azure Region where the Digital Twins instance should exist. Changing this forces a new Digital Twins instance to be created. -* + * `identity` - (Optional) An `identity` block as defined below. * `tags` - (Optional) A mapping of tags which should be assigned to the Digital Twins instance. @@ -51,7 +51,11 @@ The following arguments are supported: An `identity` block supports the following: -* `type` - (Required) The type of Managed Service Identity that is configured on this Digital Twins instance. The only possible value is `SystemAssigned`. +* `type` - (Required) Specifies the type of Managed Service Identity that should be configured on this Digital Twins instance. Possible values are `SystemAssigned`, `UserAssigned`, `SystemAssigned, UserAssigned` (to enable both). + +* `identity_ids` - (Optional) A list of User Assigned Managed Identity IDs to be assigned to this Digital Twins instance. + +~> **NOTE:** This is required when `type` is set to `UserAssigned` or `SystemAssigned, UserAssigned`. ## Attributes Reference @@ -61,6 +65,16 @@ In addition to the Arguments listed above - the following Attributes are exporte * `host_name` - The API endpoint to work with this Digital Twins instance. +* `identity` - An `identity` block as defined below. + +--- + +An `identity` block exports the following: + +* `principal_id` - The Principal ID associated with this Managed Service Identity. + +* `tenant_id` - The Tenant ID associated with this Managed Service Identity. + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: