From 198bc442007c7873b9f81d370268f193f0348aef Mon Sep 17 00:00:00 2001 From: afreyermuth98 Date: Wed, 27 Dec 2023 17:15:59 +0100 Subject: [PATCH 1/2] :sparkles: disable_provenance for grafana_contact_point --- .../resource_alerting_contact_point.go | 23 ++++++- .../resource_alerting_contact_point_test.go | 64 +++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/internal/resources/grafana/resource_alerting_contact_point.go b/internal/resources/grafana/resource_alerting_contact_point.go index 172c89ea0..e67c0b39b 100644 --- a/internal/resources/grafana/resource_alerting_contact_point.go +++ b/internal/resources/grafana/resource_alerting_contact_point.go @@ -70,6 +70,13 @@ This resource requires Grafana 9.1.0 or later. Required: true, Description: "The name of the contact point.", }, + "disable_provenance": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, // Can't modify provenance on contact points + Description: "Allow modifying the contact point from other sources than Terraform or the Grafana API.", + }, }, } @@ -166,6 +173,10 @@ func updateContactPoint(ctx context.Context, data *schema.ResourceData, meta int if uid = p.tfState["uid"].(string); uid != "" { // If the contact point already has a UID, update it. params := provisioning.NewPutContactpointParams().WithUID(uid).WithBody(p.gfState) + if data.Get("disable_provenance").(bool) { + disabled := "disabled" + params.SetXDisableProvenance(&disabled) + } if _, err := client.Provisioning.PutContactpoint(params); err != nil { return diag.FromErr(err) } @@ -174,7 +185,12 @@ func updateContactPoint(ctx context.Context, data *schema.ResourceData, meta int // Retry if the API returns 500 because it may be that the alertmanager is not ready in the org yet. // The alertmanager is provisioned asynchronously when the org is created. err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError { - resp, err := client.Provisioning.PostContactpoints(provisioning.NewPostContactpointsParams().WithBody(p.gfState)) + params := provisioning.NewPostContactpointsParams().WithBody(p.gfState) + if data.Get("disable_provenance").(bool) { + disabled := "disabled" + params.SetXDisableProvenance(&disabled) + } + resp, err := client.Provisioning.PostContactpoints(params) if orgID > 1 && err != nil && err.(*runtime.APIError).IsCode(500) { return retry.RetryableError(err) } else if err != nil { @@ -285,8 +301,12 @@ func unpackPointConfig(n notifier, data interface{}, name string) *models.Embedd func packContactPoints(ps []*models.EmbeddedContactPoint, data *schema.ResourceData) error { pointsPerNotifier := map[notifier][]interface{}{} + disableProvenance := true for _, p := range ps { data.Set("name", p.Name) + if p.Provenance != "" { + disableProvenance = false + } for _, n := range notifiers { if *p.Type == n.meta().typeStr { @@ -299,6 +319,7 @@ func packContactPoints(ps []*models.EmbeddedContactPoint, data *schema.ResourceD } } } + data.Set("disable_provenance", disableProvenance) for n, pts := range pointsPerNotifier { data.Set(n.meta().field, pts) diff --git a/internal/resources/grafana/resource_alerting_contact_point_test.go b/internal/resources/grafana/resource_alerting_contact_point_test.go index 0059c22e0..0adc36325 100644 --- a/internal/resources/grafana/resource_alerting_contact_point_test.go +++ b/internal/resources/grafana/resource_alerting_contact_point_test.go @@ -510,6 +510,58 @@ func TestAccContactPoint_empty(t *testing.T) { }) } +func TestAccContactPoint_disableProvenance(t *testing.T) { + testutils.CheckOSSTestsEnabled(t, ">=9.1.0") + + var points models.ContactPoints + name := acctest.RandString(10) + + resource.ParallelTest(t, resource.TestCase{ + ProviderFactories: testutils.ProviderFactories, + CheckDestroy: alertingContactPointCheckExists.destroyed(&points, nil), + Steps: []resource.TestStep{ + // Create + { + Config: testContactPointDisableProvenance(name, false), + Check: resource.ComposeTestCheckFunc( + checkAlertingContactPointExistsWithLength("grafana_contact_point.my_contact_point", &points, 1), + resource.TestCheckResourceAttr("grafana_contact_point.my_contact_point", "name", name), + resource.TestCheckResourceAttr("grafana_contact_point.my_contact_point", "disable_provenance", "false"), + ), + }, + // Import (tests that disable_provenance is fetched from API) + { + ResourceName: "grafana_contact_point.my_contact_point", + ImportState: true, + ImportStateId: name, + ImportStateVerify: true, + }, + // Disable provenance + { + Config: testContactPointDisableProvenance(name, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("grafana_contact_point.my_contact_point", "name", name), + resource.TestCheckResourceAttr("grafana_contact_point.my_contact_point", "disable_provenance", "true"), + ), + }, + // Import (tests that disable_provenance is fetched from API) + { + ResourceName: "grafana_contact_point.my_contact_point", + ImportState: true, + ImportStateVerify: true, + }, + // Re-enable provenance + { + Config: testContactPointDisableProvenance(name, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("grafana_contact_point.my_contact_point", "name", name), + resource.TestCheckResourceAttr("grafana_contact_point.my_contact_point", "disable_provenance", "false"), + ), + }, + }, + }) +} + func checkAlertingContactPointExistsWithLength(rn string, v *models.ContactPoints, expectedLength int) resource.TestCheckFunc { return resource.ComposeTestCheckFunc( alertingContactPointCheckExists.exists(rn, v), @@ -526,6 +578,18 @@ func checkAlertingContactPointExistsWithLength(rn string, v *models.ContactPoint ) } +func testContactPointDisableProvenance(name string, disableProvenance bool) string { + return fmt.Sprintf(` + resource "grafana_contact_point" "my_contact_point" { + name = "%s" + disable_provenance = %t + email { + addresses = [ "hello@example.com" ] + } + } + `, name, disableProvenance) +} + func testAccContactPointInOrg(name string) string { return fmt.Sprintf(` resource "grafana_organization" "test" { From e5cff960563769a100489e53f2436e9278ac64ac Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Thu, 25 Jan 2024 10:20:40 -0500 Subject: [PATCH 2/2] Use a const for provenance disabled string --- docs/resources/contact_point.md | 1 + .../resources/grafana/resource_alerting_contact_point.go | 8 ++++---- .../grafana/resource_alerting_message_template.go | 3 +-- .../grafana/resource_alerting_notification_policy.go | 3 +-- .../resources/grafana/resource_alerting_rule_group.go | 3 +-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/resources/contact_point.md b/docs/resources/contact_point.md index ddcfd047a..12162e5af 100644 --- a/docs/resources/contact_point.md +++ b/docs/resources/contact_point.md @@ -44,6 +44,7 @@ resource "grafana_contact_point" "my_contact_point" { - `alertmanager` (Block Set) A contact point that sends notifications to other Alertmanager instances. (see [below for nested schema](#nestedblock--alertmanager)) - `dingding` (Block Set) A contact point that sends notifications to DingDing. (see [below for nested schema](#nestedblock--dingding)) +- `disable_provenance` (Boolean) Allow modifying the contact point from other sources than Terraform or the Grafana API. Defaults to `false`. - `discord` (Block Set) A contact point that sends notifications as Discord messages (see [below for nested schema](#nestedblock--discord)) - `email` (Block Set) A contact point that sends notifications to an email address. (see [below for nested schema](#nestedblock--email)) - `googlechat` (Block Set) A contact point that sends notifications to Google Chat. (see [below for nested schema](#nestedblock--googlechat)) diff --git a/internal/resources/grafana/resource_alerting_contact_point.go b/internal/resources/grafana/resource_alerting_contact_point.go index e67c0b39b..c448e0495 100644 --- a/internal/resources/grafana/resource_alerting_contact_point.go +++ b/internal/resources/grafana/resource_alerting_contact_point.go @@ -18,6 +18,8 @@ import ( "github.com/grafana/terraform-provider-grafana/internal/common" ) +var provenanceDisabled = "disabled" + var notifiers = []notifier{ alertmanagerNotifier{}, dingDingNotifier{}, @@ -174,8 +176,7 @@ func updateContactPoint(ctx context.Context, data *schema.ResourceData, meta int // If the contact point already has a UID, update it. params := provisioning.NewPutContactpointParams().WithUID(uid).WithBody(p.gfState) if data.Get("disable_provenance").(bool) { - disabled := "disabled" - params.SetXDisableProvenance(&disabled) + params.SetXDisableProvenance(&provenanceDisabled) } if _, err := client.Provisioning.PutContactpoint(params); err != nil { return diag.FromErr(err) @@ -187,8 +188,7 @@ func updateContactPoint(ctx context.Context, data *schema.ResourceData, meta int err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError { params := provisioning.NewPostContactpointsParams().WithBody(p.gfState) if data.Get("disable_provenance").(bool) { - disabled := "disabled" - params.SetXDisableProvenance(&disabled) + params.SetXDisableProvenance(&provenanceDisabled) } resp, err := client.Provisioning.PostContactpoints(params) if orgID > 1 && err != nil && err.(*runtime.APIError).IsCode(500) { diff --git a/internal/resources/grafana/resource_alerting_message_template.go b/internal/resources/grafana/resource_alerting_message_template.go index 90bfa307a..4938936de 100644 --- a/internal/resources/grafana/resource_alerting_message_template.go +++ b/internal/resources/grafana/resource_alerting_message_template.go @@ -92,8 +92,7 @@ func putMessageTemplate(ctx context.Context, data *schema.ResourceData, meta int Template: content, }) if v, ok := data.GetOk("disable_provenance"); ok && v.(bool) { - disabled := "disabled" - params.SetXDisableProvenance(&disabled) + params.SetXDisableProvenance(&provenanceDisabled) } if _, err := client.Provisioning.PutTemplate(params); err != nil { if orgID > 1 && err.(*runtime.APIError).IsCode(500) { diff --git a/internal/resources/grafana/resource_alerting_notification_policy.go b/internal/resources/grafana/resource_alerting_notification_policy.go index 9c304a1e4..ba92304a9 100644 --- a/internal/resources/grafana/resource_alerting_notification_policy.go +++ b/internal/resources/grafana/resource_alerting_notification_policy.go @@ -207,8 +207,7 @@ func putNotificationPolicy(ctx context.Context, data *schema.ResourceData, meta putParams := provisioning.NewPutPolicyTreeParams().WithBody(npt) if data.Get("disable_provenance").(bool) { - disabled := "disabled" - putParams.SetXDisableProvenance(&disabled) + putParams.SetXDisableProvenance(&provenanceDisabled) } err = retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError { diff --git a/internal/resources/grafana/resource_alerting_rule_group.go b/internal/resources/grafana/resource_alerting_rule_group.go index a731ceb26..e3bc8cba1 100644 --- a/internal/resources/grafana/resource_alerting_rule_group.go +++ b/internal/resources/grafana/resource_alerting_rule_group.go @@ -259,8 +259,7 @@ func putAlertRuleGroup(ctx context.Context, data *schema.ResourceData, meta inte }) if data.Get("disable_provenance").(bool) { - disableProvenance := "disabled" // This can be any non-empty string. - putParams.SetXDisableProvenance(&disableProvenance) + putParams.SetXDisableProvenance(&provenanceDisabled) } resp, err := client.Provisioning.PutAlertRuleGroup(putParams)