Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_new_relic_monitor - Support identity #26115

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions internal/services/newrelic/new_relic_monitor_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
Comment on lines +274 to +276
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't how the Type field in Identity is usually handled which would imply a bug, this should also be raised as an issue on the Rest API specs repo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created a issue to track this problem: Azure/azure-rest-api-specs#29257

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future: can we also update the API Definition to expose the Identity field correctly too? We've spent a considerable amount of time standardising the behaviours (and methods) for the Identity types, so we should lean on them where possible - as such I've opened hashicorp/pandora#4171 which'll allow this.


if err := client.CreateOrUpdateThenPoll(ctx, id, *properties); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
},
}
}
51 changes: 51 additions & 0 deletions internal/services/newrelic/new_relic_monitor_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 := "[email protected]"
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 {
Expand Down Expand Up @@ -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)
}
40 changes: 40 additions & 0 deletions website/docs/r/new_relic_monitor.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ resource "azurerm_new_relic_monitor" "example" {
last_name = "User"
phone_number = "+12313803556"
}

identity {
type = "SystemAssigned"
}
}
```

Expand All @@ -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.
Expand Down Expand Up @@ -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:
Expand Down
Loading