diff --git a/internal/services/newrelic/new_relic_monitor_resource.go b/internal/services/newrelic/new_relic_monitor_resource.go index 86429c359957..d45a4fbd410e 100644 --- a/internal/services/newrelic/new_relic_monitor_resource.go +++ b/internal/services/newrelic/new_relic_monitor_resource.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" "github.com/hashicorp/go-azure-sdk/resource-manager/newrelic/2022-07-01/monitors" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" @@ -193,6 +194,8 @@ func (r NewRelicMonitorResource) Arguments() map[string]*pluginsdk.Schema { ValidateFunc: validation.StringIsNotEmpty, }, + "identity": commonschema.SystemAssignedIdentityOptionalForceNew(), + "ingestion_key": { Type: pluginsdk.TypeString, Optional: true, @@ -265,6 +268,13 @@ func (r NewRelicMonitorResource) Create() sdk.ResourceFunc { }, } + identityValue := expandSystemAssigned(metadata.ResourceData.Get("identity").([]interface{})) + + // Currently the API does not accept `None` type: https://github.com/Azure/azure-rest-api-specs/issues/29257 + if identityValue.Type != identity.TypeNone { + properties.Identity = identityValue + } + if err := client.CreateOrUpdateThenPoll(ctx, id, *properties); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } @@ -309,6 +319,10 @@ func (r NewRelicMonitorResource) Read() sdk.ResourceFunc { if model := resp.Model; model != nil { state.Location = location.Normalize(model.Location) + if err := metadata.ResourceData.Set("identity", flattenSystemAssigned(model.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + properties := &model.Properties if properties.AccountCreationSource != nil { state.AccountCreationSource = *properties.AccountCreationSource @@ -520,3 +534,34 @@ func flattenUserInfoModel(input *monitors.UserInfo) []UserInfoModel { return append(outputList, output) } + +// Currently the API only supports `SystemAssigned` type: https://github.com/Azure/azure-rest-api-specs/issues/29256 +func expandSystemAssigned(input []interface{}) *identity.SystemAndUserAssignedMap { + if len(input) == 0 || input[0] == nil { + return &identity.SystemAndUserAssignedMap{ + Type: identity.TypeNone, + } + } + + return &identity.SystemAndUserAssignedMap{ + Type: identity.TypeSystemAssigned, + } +} + +func flattenSystemAssigned(input *identity.SystemAndUserAssignedMap) []interface{} { + if input == nil { + return []interface{}{} + } + + if input.Type == identity.TypeNone { + return []interface{}{} + } + + return []interface{}{ + map[string]interface{}{ + "type": input.Type, + "principal_id": input.PrincipalId, + "tenant_id": input.TenantId, + }, + } +} diff --git a/internal/services/newrelic/new_relic_monitor_resource_test.go b/internal/services/newrelic/new_relic_monitor_resource_test.go index 23846d5164df..18e8a8380c5b 100644 --- a/internal/services/newrelic/new_relic_monitor_resource_test.go +++ b/internal/services/newrelic/new_relic_monitor_resource_test.go @@ -83,6 +83,21 @@ func TestAccNewRelicMonitor_complete(t *testing.T) { }) } +func TestAccNewRelicMonitor_identity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_new_relic_monitor", "test") + r := NewRelicMonitorResource{} + effectiveDate := time.Now().Add(time.Hour * 7).Format(time.RFC3339) + email := "fdfc9282-8817-442f-9f32-605ab174b610@example.com" + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.identity(data, effectiveDate, email), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + }) +} + func (r NewRelicMonitorResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := monitors.ParseMonitorID(state.ID) if err != nil { @@ -187,3 +202,39 @@ resource "azurerm_new_relic_monitor" "test" { } `, template, data.RandomInteger, effectiveDate, email, accountId, orgId) } + +func (r NewRelicMonitorResource) identity(data acceptance.TestData, effectiveDate string, email string) string { + template := r.template(data) + return fmt.Sprintf(` + %s +resource "azurerm_new_relic_monitor" "test" { + name = "acctest-nrm-%d" + resource_group_name = azurerm_resource_group.test.name + location = "%s" + plan { + effective_date = "%s" + } + user { + email = "%s" + first_name = "first" + last_name = "last" + phone_number = "123456" + } + identity { + type = "SystemAssigned" + } +} + +data "azurerm_subscription" "primary" {} + +data "azurerm_role_definition" "test" { + name = "Monitoring Reader" +} + +resource "azurerm_role_assignment" "test" { + scope = data.azurerm_subscription.primary.id + role_definition_id = "${data.azurerm_subscription.primary.id}${data.azurerm_role_definition.test.id}" + principal_id = azurerm_new_relic_monitor.test.identity[0].principal_id +} +`, template, data.RandomInteger, data.Locations.Primary, effectiveDate, email) +} diff --git a/website/docs/r/new_relic_monitor.html.markdown b/website/docs/r/new_relic_monitor.html.markdown index e2fc47984db2..9d68f5bce1be 100644 --- a/website/docs/r/new_relic_monitor.html.markdown +++ b/website/docs/r/new_relic_monitor.html.markdown @@ -33,6 +33,10 @@ resource "azurerm_new_relic_monitor" "example" { last_name = "User" phone_number = "+12313803556" } + + identity { + type = "SystemAssigned" + } } ``` @@ -56,6 +60,8 @@ The following arguments are supported: -> **NOTE:** The value of `account_id` must come from an Azure Native New Relic Monitor instance of another different subscription. +* `identity` - (Optional) An `identity` block as defined below. Changing this forces a new Azure Native New Relic Monitor to be created. + * `ingestion_key` - (Optional) Specifies the ingestion key of account. Changing this forces a new Azure Native New Relic Monitor to be created. * `organization_id` - (Optional) Specifies the organization id. Changing this forces a new Azure Native New Relic Monitor to be created. @@ -90,12 +96,46 @@ A `user` block supports the following: * `phone_number` - (Required) Specifies the contact phone number. Changing this forces a new Azure Native New Relic Monitor to be created. +--- + +An `identity` block supports the following: + +* `type` - (Required) Specifies the identity type of the Azure Native New Relic Monitor. The only possible value is `SystemAssigned`. Changing this forces a new Azure Native New Relic Monitor to be created. + ## Attributes Reference In addition to the Arguments listed above - the following Attributes are exported: * `id` - The ID of the Azure Native New Relic Monitor. +--- + +An `identity` block exports the following: + +* `principal_id` - The Principal ID for the Service Principal associated with the Identity of this Azure Native New Relic Monitor. + +* `tenant_id` - The Tenant ID for the Service Principal associated with the Identity of this Azure Native New Relic Monitor. + +## Role Assignment + +To enable metrics flow, perform role assignment on the identity created above. `Monitoring reader(43d0d8ad-25c7-4714-9337-8ba259a9fe05)` role is required . + +### Role assignment on the monitor created + +```hcl +data "azurerm_subscription" "primary" {} + +data "azurerm_role_definition" "monitoring_reader" { + name = "Monitoring Reader" +} + +resource "azurerm_role_assignment" "example" { + scope = data.azurerm_subscription.primary.id + role_definition_id = "${data.azurerm_subscription.primary.id}${data.azurerm_role_definition.monitoring_reader.id}" + principal_id = azurerm_new_relic_monitor.example.identity[0].principal_id +} +``` + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: