From 871ac976172284b51639bfe5d19667d280f81173 Mon Sep 17 00:00:00 2001 From: dwalasek <138129050+dwalasek@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:27:08 +0200 Subject: [PATCH] detector: fix an issue with deleting all teams/tags/authorized users/teas=ms (#489) * detector: fix an issue with deleting all teams/tags/authorized users/authorized teams from detector object To remove teams/tags/authorized users/authorize from detector resource, the API client must send an empty array. Sending any of these fields missing (null) has no effect --- CHANGELOG.md | 5 ++ go.mod | 2 +- go.sum | 4 +- signalfx/resource_signalfx_detector.go | 19 +++--- signalfx/resource_signalfx_detector_test.go | 76 ++++++++++++++++++++- 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 081cc3dd..8e736505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Unreleased +## 9.1.5 + +BUGFIXES: +* Fix an issue with removing all teams/tags/authorized users/authorized teams from detector resource [#489](https://github.com/splunk-terraform/terraform-provider-signalfx/pull/489) + ## 9.1.4 IMPROVEMENTS: diff --git a/go.mod b/go.mod index b8a28ba5..f4cecbac 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0 github.com/mitchellh/go-homedir v1.1.0 - github.com/signalfx/signalfx-go v1.36.0 + github.com/signalfx/signalfx-go v1.37.0 github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index a0b2decd..48d16b16 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/signalfx/signalfx-go v1.36.0 h1:btfNrjb/MWAku7Ibj5BUamArVkyV9XI/fYqA0ytLdEo= -github.com/signalfx/signalfx-go v1.36.0/go.mod h1:aVrA69k02raBhDtIL1l+KBu+H5eEmS5b0IFbqgKh7eg= +github.com/signalfx/signalfx-go v1.37.0 h1:AtCvcW9VGoVUnCVcoHLbRD5QUsMpy1SnViJN+jKGBU8= +github.com/signalfx/signalfx-go v1.37.0/go.mod h1:aVrA69k02raBhDtIL1l+KBu+H5eEmS5b0IFbqgKh7eg= github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/signalfx/resource_signalfx_detector.go b/signalfx/resource_signalfx_detector.go index 728986f9..1e7c6e39 100644 --- a/signalfx/resource_signalfx_detector.go +++ b/signalfx/resource_signalfx_detector.go @@ -306,7 +306,7 @@ func getPayloadDetector(d *schema.ResourceData) (*detector.CreateUpdateDetectorR maxDelay := int32(d.Get("max_delay").(int) * 1000) minDelay := int32(d.Get("min_delay").(int) * 1000) - var tags []string + tags := []string{} if val, ok := d.GetOk("tags"); ok { for _, tag := range val.(*schema.Set).List() { tags = append(tags, tag.(string)) @@ -326,32 +326,33 @@ func getPayloadDetector(d *schema.ResourceData) (*detector.CreateUpdateDetectorR Tags: tags, } + authorizedTeams := []string{} if val, ok := d.GetOk("authorized_writer_teams"); ok { - var teams []string tfValues := val.(*schema.Set).List() for _, v := range tfValues { - teams = append(teams, v.(string)) + authorizedTeams = append(authorizedTeams, v.(string)) } - cudr.AuthorizedWriters.Teams = teams } + cudr.AuthorizedWriters.Teams = authorizedTeams + + authorizedUsers := []string{} if val, ok := d.GetOk("authorized_writer_users"); ok { - var users []string tfValues := val.(*schema.Set).List() for _, v := range tfValues { - users = append(users, v.(string)) + authorizedUsers = append(authorizedUsers, v.(string)) } - cudr.AuthorizedWriters.Users = users } + cudr.AuthorizedWriters.Users = authorizedUsers cudr.VisualizationOptions = getVisualizationOptionsDetector(d) + teams := []string{} if val, ok := d.GetOk("teams"); ok { - teams := []string{} for _, t := range val.(*schema.Set).List() { teams = append(teams, t.(string)) } - cudr.Teams = teams } + cudr.Teams = teams return cudr, nil } diff --git a/signalfx/resource_signalfx_detector_test.go b/signalfx/resource_signalfx_detector_test.go index e3461588..3e0b458e 100644 --- a/signalfx/resource_signalfx_detector_test.go +++ b/signalfx/resource_signalfx_detector_test.go @@ -65,7 +65,7 @@ func TestValidateSeverityNotAllowed(t *testing.T) { const newDetectorConfig = ` resource "signalfx_team" "detectorTeam" { - name = "Super Cool Team" + name = "Splunk Team" description = "Detector Team" notifications_critical = [ "Email,test@example.com" ] @@ -123,6 +123,7 @@ resource "signalfx_detector" "application_delay" { show_event_lines = true disable_sampling = true time_range = 3600 + tags = ["tag-1","tag-2","tag-3"] program_text = <<-EOF signal = data('app.delay2').max().publish('app delay') @@ -153,6 +154,39 @@ resource "signalfx_detector" "application_delay" { } ` +const secondUpdatedDetectorConfig = ` +resource "signalfx_detector" "application_delay" { + name = "max average delay UPDATED" + description = "your application is slowER" + max_delay = 60 + min_delay = 30 + timezone = "Europe/Paris" + + show_data_markers = true + show_event_lines = true + disable_sampling = true + time_range = 3600 + + program_text = <<-EOF + signal = data('app.delay2').max().publish('app delay') + detect(when(signal > 60, '5m')).publish('Processing old messages 5m') + EOF + rule { + description = "NEW maximum > 60 for 5m" + severity = "Warning" + detect_label = "Processing old messages 5m" + notifications = ["Email,foo-alerts@example.com"] + runbook_url = "https://www.example.com" + tip = "reboot it" + } + viz_options { + label = "app delay" + color = "orange" + value_unit = "Second" + } +} +` + const invalidProgramTextConfig = ` resource "signalfx_detector" "high_cpu_utilization" { name = "CPU utilization is high" @@ -279,7 +313,10 @@ func TestAccCreateUpdateDetector(t *testing.T) { resource.TestCheckResourceAttr("signalfx_detector.application_delay", "name", "max average delay UPDATED"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "description", "your application is slowER"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "timezone", "Europe/Paris"), - resource.TestCheckResourceAttr("signalfx_detector.application_delay", "tags.#", "0"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "tags.#", "3"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "tags.0", "tag-1"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "tags.1", "tag-2"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "tags.2", "tag-3"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "teams.#", "0"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "max_delay", "60"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "min_delay", "30"), @@ -316,6 +353,39 @@ func TestAccCreateUpdateDetector(t *testing.T) { resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.runbook_url", "https://www.example.com"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.severity", "Critical"), resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.tip", ""), + + // Force sleep before refresh at the end of test execution + waitBeforeTestStepPlanRefresh, + ), + }, + // Subsequent Update + { + Config: secondUpdatedDetectorConfig, + Check: resource.ComposeTestCheckFunc( + waitBeforeTestStepPlanRefresh, + testAccCheckDetectorResourceExists, + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "name", "max average delay UPDATED"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "description", "your application is slowER"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "timezone", "Europe/Paris"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "tags.#", "0"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "teams.#", "0"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "max_delay", "60"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "min_delay", "30"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", + "time_range", "3600"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "program_text", "signal = data('app.delay2').max().publish('app delay')\ndetect(when(signal > 60, '5m')).publish('Processing old messages 5m')\n"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "show_data_markers", "true"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "show_event_lines", "true"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "disable_sampling", "true"), + + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.#", "1"), + + // Rule #1 + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.description", "NEW maximum > 60 for 5m"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.notifications.0", "Email,foo-alerts@example.com"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.severity", "Warning"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.runbook_url", "https://www.example.com"), + resource.TestCheckResourceAttr("signalfx_detector.application_delay", "rule.0.tip", "reboot it"), ), }, }, @@ -326,7 +396,7 @@ func waitBeforeTestStepPlanRefresh(s *terraform.State) error { // Gives time to the API to properly update info before read them again // required to make the acceptance tests always passing, see: // https://github.com/splunk-terraform/terraform-provider-signalfx/pull/306#issuecomment-870417521 - time.Sleep(1 * time.Second) + time.Sleep(30 * time.Second) return nil }