From 6606714f7c042c039ad1b992ca1818ed425c0d2a Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 15 Nov 2024 12:56:21 -0500 Subject: [PATCH 1/5] SM Checks: Select probes automatically Crossplane doesn't have datasources, so we have to specify probe IDs manually This will allow us to specify a number of probes to be selected randomly --- .../syntheticmonitoring/resource_check.go | 67 +++++++++++-- .../resource_check_test.go | 95 +++++++++++++++++++ 2 files changed, 155 insertions(+), 7 deletions(-) diff --git a/internal/resources/syntheticmonitoring/resource_check.go b/internal/resources/syntheticmonitoring/resource_check.go index 243b83dbf..3a64f0247 100644 --- a/internal/resources/syntheticmonitoring/resource_check.go +++ b/internal/resources/syntheticmonitoring/resource_check.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math/rand/v2" "strconv" "strings" @@ -22,7 +23,6 @@ const ( ) var ( - // Set variables for schemas used in multiple fields and/or used to transform // API client types back to schemas. @@ -761,11 +761,22 @@ multiple checks for a single endpoint to check different capabilities. "probes": { Description: "List of probe location IDs where this target will be checked from.", Type: schema.TypeSet, - Required: true, + Optional: true, + Computed: true, Elem: &schema.Schema{ Type: schema.TypeInt, }, }, + "select_probes_count": { + Description: `Number of probes to use for this check. +On creation and updates, an attempt will be made to use a selection of geographically dispersed probes. +On imports, the current selection of probes will be used, and a diff will be generated if the number of probes is different. +To select specific probes, use the "probes" attribute. +`, + Type: schema.TypeInt, + Optional: true, + ConflictsWith: []string{"probes"}, + }, "labels": { Description: "Custom labels to be included with collected metrics and logs. " + "The maximum number of labels that can be specified per check is 5. " + @@ -816,7 +827,7 @@ func listChecks(ctx context.Context, client *common.Client, data any) ([]string, } func resourceCheckCreate(ctx context.Context, d *schema.ResourceData, c *smapi.Client) diag.Diagnostics { - chk, err := makeCheck(d) + chk, err := makeCheck(ctx, c, d) if err != nil { return diag.FromErr(err) } @@ -1153,7 +1164,7 @@ func resourceCheckRead(ctx context.Context, d *schema.ResourceData, c *smapi.Cli } func resourceCheckUpdate(ctx context.Context, d *schema.ResourceData, c *smapi.Client) diag.Diagnostics { - chk, err := makeCheck(d) + chk, err := makeCheck(ctx, c, d) if err != nil { return diag.FromErr(err) } @@ -1175,15 +1186,52 @@ func resourceCheckDelete(ctx context.Context, d *schema.ResourceData, c *smapi.C // makeCheck populates an instance of sm.Check. We need this for create and // update calls with the SM API client. -func makeCheck(d *schema.ResourceData) (*sm.Check, error) { +func makeCheck(ctx context.Context, c *smapi.Client, d *schema.ResourceData) (*sm.Check, error) { var id int64 if d.Id() != "" { id, _ = strconv.ParseInt(d.Id(), 10, 64) } var probes []int64 - for _, p := range d.Get("probes").(*schema.Set).List() { - probes = append(probes, int64(p.(int))) + if probeCount := d.Get("select_probes_count").(int); probeCount > 0 { + smProbes, err := c.ListProbes(ctx) + if err != nil { + return nil, fmt.Errorf("failed to list probes: %w", err) + } + byRegion := make(map[string][]int64) + for _, p := range smProbes { + if !p.Deprecated { + byRegion[p.Region] = append(byRegion[p.Region], p.Id) + } + } + // Shuffle lists so the provider doesn't always pick the same probes. + for _, probes := range byRegion { + rand.Shuffle(len(probes), func(i, j int) { + probes[i], probes[j] = probes[j], probes[i] + }) + } + // Add probes from each region until we have enough. + for len(probes) < probeCount { + for region, regionProbes := range byRegion { + if len(regionProbes) == 0 { + delete(byRegion, region) + continue + } + if len(probes) >= probeCount { + break + } + probes = append(probes, regionProbes[0]) + byRegion[region] = regionProbes[1:] + break + } + if len(byRegion) == 0 { + return nil, fmt.Errorf("not enough probes available, requested: %d, available: %d", probeCount, len(probes)) + } + } + } else { + for _, p := range d.Get("probes").(*schema.Set).List() { + probes = append(probes, int64(p.(int))) + } } var labels []sm.Label @@ -1608,5 +1656,10 @@ func resourceCheckCustomizeDiff(ctx context.Context, diff *schema.ResourceDiff, return fmt.Errorf("exactly one check setting must be defined, got %d", count) } + // If the user changed `select_probes_count`, the probes list will be rebuilt. + if diff.HasChange("select_probes_count") { + diff.SetNewComputed("probes") + } + return nil } diff --git a/internal/resources/syntheticmonitoring/resource_check_test.go b/internal/resources/syntheticmonitoring/resource_check_test.go index c0a186b10..e16a270d5 100644 --- a/internal/resources/syntheticmonitoring/resource_check_test.go +++ b/internal/resources/syntheticmonitoring/resource_check_test.go @@ -2,6 +2,7 @@ package syntheticmonitoring_test import ( "context" + "fmt" "os" "path/filepath" "regexp" @@ -151,6 +152,84 @@ func TestAccResourceCheck_http(t *testing.T) { }) } +func TestAccResourceCheck_selectProbes(t *testing.T) { + testutils.CheckCloudInstanceTestsEnabled(t) + + // Inject random job names to avoid conflicts with other tests + jobName := acctest.RandomWithPrefix("sm-random") + + resource.ParallelTest(t, resource.TestCase{ + ProtoV5ProviderFactories: testutils.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + // There aren't 10000 probes, so this should fail + Config: testAccResourceCheck_randomProbes(jobName, 10000), + ExpectError: regexp.MustCompile(`.*not enough probes available, requested: 10000, available: \d+.*`), + }, + { + Config: testAccResourceCheck_randomProbes(jobName, 5), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("grafana_synthetic_monitoring_check.http", "id"), + resource.TestCheckResourceAttrSet("grafana_synthetic_monitoring_check.http", "tenant_id"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "job", jobName), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "target", "https://"+jobName+".com"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "probes.#", "5"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "select_probes_count", "5"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "labels.foo", "bar"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.ip_version", "V4"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.method", "GET"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.no_follow_redirects", "false"), + ), + }, + // Increase the number of probes + { + Config: testAccResourceCheck_randomProbes(jobName, 7), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("grafana_synthetic_monitoring_check.http", "id"), + resource.TestCheckResourceAttrSet("grafana_synthetic_monitoring_check.http", "tenant_id"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "job", jobName), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "target", "https://"+jobName+".com"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "probes.#", "7"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "select_probes_count", "7"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "labels.foo", "bar"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.ip_version", "V4"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.method", "GET"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.no_follow_redirects", "false"), + ), + }, + // Decrease the number of probes + { + Config: testAccResourceCheck_randomProbes(jobName, 3), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("grafana_synthetic_monitoring_check.http", "id"), + resource.TestCheckResourceAttrSet("grafana_synthetic_monitoring_check.http", "tenant_id"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "job", jobName), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "target", "https://"+jobName+".com"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "probes.#", "3"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "select_probes_count", "3"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "labels.foo", "bar"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.ip_version", "V4"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.method", "GET"), + resource.TestCheckResourceAttr("grafana_synthetic_monitoring_check.http", "settings.0.http.0.no_follow_redirects", "false"), + ), + }, + + // Importing should also work, the diff will be against the number of probes in the check + { + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.http", + ImportStateVerifyIgnore: []string{"select_probes_count"}, + }, + // Should be an empty plan + { + Config: testAccResourceCheck_randomProbes(jobName, 3), + PlanOnly: true, + }, + }, + }) +} + func TestAccResourceCheck_ping(t *testing.T) { testutils.CheckCloudInstanceTestsEnabled(t) @@ -560,6 +639,22 @@ func TestAccResourceCheck_multiple(t *testing.T) { }) } +func testAccResourceCheck_randomProbes(name string, count int) string { + return fmt.Sprintf(` +resource "grafana_synthetic_monitoring_check" "http" { + job = "%s" + target = "https://%s.com" + enabled = false + select_probes_count = %d + labels = { + foo = "bar" + } + settings { + http {} + } +}`, name, name, count) +} + const testAccResourceCheck_noSettings = ` data "grafana_synthetic_monitoring_probes" "main" {} From 9bff450ca1a94ce378ef7c1a4e0a46e43f0989fa Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 15 Nov 2024 12:59:25 -0500 Subject: [PATCH 2/5] make docs --- docs/resources/synthetic_monitoring_check.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/resources/synthetic_monitoring_check.md b/docs/resources/synthetic_monitoring_check.md index 3b1e5a54b..e366bbbe8 100644 --- a/docs/resources/synthetic_monitoring_check.md +++ b/docs/resources/synthetic_monitoring_check.md @@ -414,7 +414,6 @@ resource "grafana_synthetic_monitoring_check" "traceroute" { ### Required - `job` (String) Name used for job label. -- `probes` (Set of Number) List of probe location IDs where this target will be checked from. - `settings` (Block Set, Min: 1, Max: 1) Check settings. Should contain exactly one nested block. (see [below for nested schema](#nestedblock--settings)) - `target` (String) Hostname to ping. @@ -425,6 +424,11 @@ resource "grafana_synthetic_monitoring_check" "traceroute" { - `enabled` (Boolean) Whether to enable the check. Defaults to `true`. - `frequency` (Number) How often the check runs in milliseconds (the value is not truly a "frequency" but a "period"). The minimum acceptable value is 1 second (1000 ms), and the maximum is 1 hour (3600000 ms). Defaults to `60000`. - `labels` (Map of String) Custom labels to be included with collected metrics and logs. The maximum number of labels that can be specified per check is 5. These are applied, along with the probe-specific labels, to the outgoing metrics. The names and values of the labels cannot be empty, and the maximum length is 32 bytes. +- `probes` (Set of Number) List of probe location IDs where this target will be checked from. +- `select_probes_count` (Number) Number of probes to use for this check. +On creation and updates, an attempt will be made to use a selection of geographically dispersed probes. +On imports, the current selection of probes will be used, and a diff will be generated if the number of probes is different. +To select specific probes, use the "probes" attribute. - `timeout` (Number) Specifies the maximum running time for the check in milliseconds. The minimum acceptable value is 1 second (1000 ms), and the maximum 10 seconds (10000 ms). Defaults to `3000`. ### Read-Only From fb325a7f8bb0e5a806f91de044d27738558473d9 Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 15 Nov 2024 13:10:06 -0500 Subject: [PATCH 3/5] Simplify basic examples by auto-selecting probes Make switching attribute work --- docs/resources/synthetic_monitoring_check.md | 100 ++++++------------ .../dns_basic.tf | 12 +-- .../grpc_basic.tf | 12 +-- .../http_basic.tf | 12 +-- .../multihttp_basic.tf | 12 +-- .../ping_basic.tf | 12 +-- .../scripted_basic.tf | 12 +-- .../tcp_basic.tf | 12 +-- .../traceroute_basic.tf | 16 ++- .../syntheticmonitoring/resource_check.go | 4 +- .../resource_check_test.go | 56 +++++----- 11 files changed, 102 insertions(+), 158 deletions(-) diff --git a/docs/resources/synthetic_monitoring_check.md b/docs/resources/synthetic_monitoring_check.md index e366bbbe8..fd5ee6de5 100644 --- a/docs/resources/synthetic_monitoring_check.md +++ b/docs/resources/synthetic_monitoring_check.md @@ -26,15 +26,11 @@ multiple checks for a single endpoint to check different capabilities. ### DNS Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "dns" { - job = "DNS Defaults" - target = "grafana.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "DNS Defaults" + target = "grafana.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } @@ -103,15 +99,11 @@ resource "grafana_synthetic_monitoring_check" "dns" { ### HTTP Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "http" { - job = "HTTP Defaults" - target = "https://grafana.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "HTTP Defaults" + target = "https://grafana.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } @@ -223,15 +215,11 @@ EOS ### Ping Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "ping" { - job = "Ping Defaults" - target = "grafana.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "Ping Defaults" + target = "grafana.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } @@ -270,15 +258,11 @@ resource "grafana_synthetic_monitoring_check" "ping" { ### TCP Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "tcp" { - job = "TCP Defaults" - target = "grafana.com:80" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "TCP Defaults" + target = "grafana.com:80" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } @@ -360,17 +344,13 @@ EOS ### Traceroute Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "traceroute" { - job = "Traceroute defaults" - target = "grafana.com" - enabled = false - frequency = 120000 - timeout = 30000 - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "Traceroute defaults" + target = "grafana.com" + enabled = false + frequency = 120000 + timeout = 30000 + select_probes_count = 1 labels = { foo = "bar" } @@ -748,15 +728,11 @@ Optional: ### MultiHTTP Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "multihttp" { - job = "multihttp basic" - target = "https://www.grafana-dev.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Amsterdam, - ] + job = "multihttp basic" + target = "https://www.grafana-dev.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } @@ -864,15 +840,11 @@ resource "grafana_synthetic_monitoring_check" "multihttp" { ### Scripted Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "scripted" { - job = "Validate homepage" - target = "https://grafana.com/" - enabled = true - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Paris, - ] + job = "Validate homepage" + target = "https://grafana.com/" + enabled = true + select_probes_count = 1 labels = { environment = "production" } @@ -889,15 +861,11 @@ resource "grafana_synthetic_monitoring_check" "scripted" { ### gRPC Health Check Basic ```terraform -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "grpc" { - job = "gRPC Defaults" - target = "host.docker.internal:50051" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "gRPC Defaults" + target = "host.docker.internal:50051" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/dns_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/dns_basic.tf index 7a87c39f3..f7786c7f9 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/dns_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/dns_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "dns" { - job = "DNS Defaults" - target = "grafana.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "DNS Defaults" + target = "grafana.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/grpc_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/grpc_basic.tf index 5b28bd2ec..bb12bdaa4 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/grpc_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/grpc_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "grpc" { - job = "gRPC Defaults" - target = "host.docker.internal:50051" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "gRPC Defaults" + target = "host.docker.internal:50051" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/http_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/http_basic.tf index f772e8f7d..bf816f7a8 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/http_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/http_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "http" { - job = "HTTP Defaults" - target = "https://grafana.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "HTTP Defaults" + target = "https://grafana.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/multihttp_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/multihttp_basic.tf index 467b47501..4a11b8d2a 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/multihttp_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/multihttp_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "multihttp" { - job = "multihttp basic" - target = "https://www.grafana-dev.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Amsterdam, - ] + job = "multihttp basic" + target = "https://www.grafana-dev.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/ping_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/ping_basic.tf index 31c039028..937987a23 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/ping_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/ping_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "ping" { - job = "Ping Defaults" - target = "grafana.com" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "Ping Defaults" + target = "grafana.com" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/scripted_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/scripted_basic.tf index 0faaf9e44..b27855eee 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/scripted_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/scripted_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "scripted" { - job = "Validate homepage" - target = "https://grafana.com/" - enabled = true - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Paris, - ] + job = "Validate homepage" + target = "https://grafana.com/" + enabled = true + select_probes_count = 1 labels = { environment = "production" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/tcp_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/tcp_basic.tf index 4c6e263f3..cec37c455 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/tcp_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/tcp_basic.tf @@ -1,12 +1,8 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "tcp" { - job = "TCP Defaults" - target = "grafana.com:80" - enabled = false - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "TCP Defaults" + target = "grafana.com:80" + enabled = false + select_probes_count = 1 labels = { foo = "bar" } diff --git a/examples/resources/grafana_synthetic_monitoring_check/traceroute_basic.tf b/examples/resources/grafana_synthetic_monitoring_check/traceroute_basic.tf index e2c64794f..17eb31a09 100644 --- a/examples/resources/grafana_synthetic_monitoring_check/traceroute_basic.tf +++ b/examples/resources/grafana_synthetic_monitoring_check/traceroute_basic.tf @@ -1,14 +1,10 @@ -data "grafana_synthetic_monitoring_probes" "main" {} - resource "grafana_synthetic_monitoring_check" "traceroute" { - job = "Traceroute defaults" - target = "grafana.com" - enabled = false - frequency = 120000 - timeout = 30000 - probes = [ - data.grafana_synthetic_monitoring_probes.main.probes.Atlanta, - ] + job = "Traceroute defaults" + target = "grafana.com" + enabled = false + frequency = 120000 + timeout = 30000 + select_probes_count = 1 labels = { foo = "bar" } diff --git a/internal/resources/syntheticmonitoring/resource_check.go b/internal/resources/syntheticmonitoring/resource_check.go index 3a64f0247..df2d3ff59 100644 --- a/internal/resources/syntheticmonitoring/resource_check.go +++ b/internal/resources/syntheticmonitoring/resource_check.go @@ -1193,7 +1193,7 @@ func makeCheck(ctx context.Context, c *smapi.Client, d *schema.ResourceData) (*s } var probes []int64 - if probeCount := d.Get("select_probes_count").(int); probeCount > 0 { + if probeCount := d.Get("select_probes_count").(int); probeCount > 0 && !d.HasChange("probes") { smProbes, err := c.ListProbes(ctx) if err != nil { return nil, fmt.Errorf("failed to list probes: %w", err) @@ -1657,7 +1657,7 @@ func resourceCheckCustomizeDiff(ctx context.Context, diff *schema.ResourceDiff, } // If the user changed `select_probes_count`, the probes list will be rebuilt. - if diff.HasChange("select_probes_count") { + if diff.HasChange("select_probes_count") && !diff.HasChange("probes") { diff.SetNewComputed("probes") } diff --git a/internal/resources/syntheticmonitoring/resource_check_test.go b/internal/resources/syntheticmonitoring/resource_check_test.go index e16a270d5..7e91c0538 100644 --- a/internal/resources/syntheticmonitoring/resource_check_test.go +++ b/internal/resources/syntheticmonitoring/resource_check_test.go @@ -75,9 +75,10 @@ func TestAccResourceCheck_dns(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.dns", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.dns", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -144,9 +145,10 @@ func TestAccResourceCheck_http(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.http", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.http", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -272,9 +274,10 @@ func TestAccResourceCheck_ping(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.ping", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.ping", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -328,9 +331,10 @@ func TestAccResourceCheck_tcp(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.tcp", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.tcp", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -380,9 +384,10 @@ func TestAccResourceCheck_traceroute(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.traceroute", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.traceroute", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -470,9 +475,10 @@ func TestAccResourceCheck_multihttp(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.multihttp", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.multihttp", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -510,9 +516,10 @@ func TestAccResourceCheck_scripted(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.scripted", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.scripted", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) @@ -561,9 +568,10 @@ func TestAccResourceCheck_grpc(t *testing.T) { ), }, { - ImportState: true, - ImportStateVerify: true, - ResourceName: "grafana_synthetic_monitoring_check.grpc", + ImportState: true, + ImportStateVerify: true, + ResourceName: "grafana_synthetic_monitoring_check.grpc", + ImportStateVerifyIgnore: []string{"select_probes_count"}, }, }, }) From 471ca07cf7c93cb922170246e5417112e70bbf0f Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 15 Nov 2024 13:20:07 -0500 Subject: [PATCH 4/5] Fix generate test --- pkg/generate/generate_test.go | 2 +- .../generate/sm-check/resources.tf.tmpl | 37 +++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/pkg/generate/generate_test.go b/pkg/generate/generate_test.go index e41c893b9..edd875730 100644 --- a/pkg/generate/generate_test.go +++ b/pkg/generate/generate_test.go @@ -361,7 +361,7 @@ func TestAccGenerate_SMCheck(t *testing.T) { var smCheckID string tc := generateTestCase{ name: "sm-check", - config: testutils.TestAccExampleWithReplace(t, "resources/grafana_synthetic_monitoring_check/http_basic.tf", map[string]string{ + config: testutils.TestAccExampleWithReplace(t, "resources/grafana_synthetic_monitoring_check/http_complex.tf", map[string]string{ `"HTTP Defaults"`: strconv.Quote(randomString), }), stateCheck: func(s *terraform.State) error { diff --git a/pkg/generate/testdata/generate/sm-check/resources.tf.tmpl b/pkg/generate/testdata/generate/sm-check/resources.tf.tmpl index 05655e84e..43bfe9808 100644 --- a/pkg/generate/testdata/generate/sm-check/resources.tf.tmpl +++ b/pkg/generate/testdata/generate/sm-check/resources.tf.tmpl @@ -11,16 +11,39 @@ resource "grafana_synthetic_monitoring_check" "{{ .Job }}" { labels = { foo = "bar" } - probes = [7] - target = "https://grafana.com" + probes = [8, 22] + target = "https://grafana.org" timeout = 3000 settings { http { - fail_if_not_ssl = false - fail_if_ssl = false - ip_version = "V4" - method = "GET" - no_follow_redirects = false + bearer_token = "asdfjkl;" + body = "and spirit" + cache_busting_query_param_name = "pineapple" + fail_if_body_matches_regexp = [".*bad stuff.*"] + fail_if_body_not_matches_regexp = [".*good stuff.*"] + fail_if_not_ssl = true + fail_if_ssl = true + headers = ["Content-Type: multipart/form-data; boundary=something"] + ip_version = "V6" + method = "TRACE" + no_follow_redirects = true + proxy_url = "https://almost-there" + valid_http_versions = ["HTTP/1.0", "HTTP/1.1", "HTTP/2.0"] + valid_status_codes = [200, 201] + basic_auth { + password = "sesame" + username = "open" + } + fail_if_header_matches_regexp { + allow_missing = true + header = "Content-Type" + regexp = "application/soap*" + } + tls_config { + client_cert = "-----BEGIN CERTIFICATE-----\nMIIEljCCAn4CCQCKJPUQQxeO0zANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJT\nRTAeFw0yMTA1MjkxOTIyNTdaFw0yNDAzMTgxOTIyNTdaMA0xCzAJBgNVBAYTAlNF\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnmbazDNUT0rSI4BpGZK+\n0AJ+9FDkIYWJUtRLJoxw8CF+AobMFploYA2L2Myt80cTA1w8FrewjC8qlqdnrPWr\nh1ely2zsUljgi1/niH0ndjFzliL7UkinXQiAsTtYOrOQmzyd/o5PNdu7dz0m7stD\nBN/Sz5TlXZnA1/eJbqV/kqMau6b1MaBx8SbRfUG9+cSmUobFJwuktDrPuwJhcEkl\niDmhEqu1GuZzmKvzPacLTVia1vSlmCTCu89NiHI8iGiiLtqNrapup7f8j5m3a3SL\na+vXhplFj2piNl7Nc0dfuVgtEliTI+qUL2/+4A7gzRWZpHy21/LxMMXmBhdJW9En\nFWkev97VZLgb5TR3+qpSWmXcodjPy4dibvwsOMpdd+Q4AYulwvlDw5idRPVgGvk7\nqq03+w9ppZ5Fugws9k2CD9F/75JX2mCbRpkuPe8XXZ7bqrMaQgQMLOrs68HuiiCk\nFTklglq4DMKxnf/Y/T/MgIa9Q1o28YSevh6A7FnfPGARj2H2T4rToi+bC1Vf7qNB\nZ18bDpz99tRUTbyiRUSBMWLCGhU6c4HAqUrfrkpperOKFBQ3i38a79838oFdXHBW\n6rx1t5cC3XwtEoUyeBKAygez8G1LDXbN3607MxVhAjhHKtPkYvuBfysSNU6JrR0z\nUV1IURJANt2UMuKgSEkG/IMCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAcipMhp/w\nyzfPy61faVAw9SPaMNRlnW9FCDC3N9CGOjo2knjXpObPzyzsJiUURTjrA9eFMpRA\ne2Rgn2j+nvm2XdLAlC4Kh8jqv/wCL0X6BTQMdN5aOhXdSiXtpXOMvXYY/dQ4ebRZ\nXeRCVWQD79JbV6/uyx0nCV3FVcU7L1P4UjxroefVr0soLPMirgxHmOxLnkoVgdcB\ntqufP5kJx9CIeJXPx3QQsk1XfEtxtUvuw4ZaZkQnNUqvGl7V+AZpur5Eqfv3zBi8\nQxxL7qGkARNssNWH2Ju+tqpM/UZRnjlFrDR4SXUgT0coTduBalUY6qHkciHmRpiP\ntf3SgpDeiCSOV2iVFGdaR1mz3muWoAYWFstcWN3a3HjjVugIi23yLN8Gv8CNeoH4\nprulinFCLrFgAh8SLAF8mOAZanT06LH8jOIFYrdUxH+ZeRBR0rLoFjUF+JB7UKD9\n5TA+B4EBzQ1tMbGFU1DX79MjAejq0IV0Nzq+GMfBvLHxEf4+Oz8nqhDXQcJ6TdtY\nl3Lyw5zBvOL80SBK+Mr0UP7d9U3VXgbGHCYVJU6Ot1TwiGwahtWALRALA3TWeGkq\n7kyD1H+nm+9lfKhuyBRQnRGBVyze2lAp7oxwshJuhBwEXosXFxq1Cy6QhPN77r6N\nvuhxvtppolNnyOgGxwG4zquqq2V5/+vKjKY=\n-----END CERTIFICATE-----\n" + insecure_skip_verify = false + server_name = "grafana.org" + } } } } From 78166ffe2c1a885e062b4bc7e75ad83efd3dd362 Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 15 Nov 2024 13:35:20 -0500 Subject: [PATCH 5/5] Simpler iteration --- internal/resources/syntheticmonitoring/resource_check.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/resources/syntheticmonitoring/resource_check.go b/internal/resources/syntheticmonitoring/resource_check.go index df2d3ff59..6f6bf9620 100644 --- a/internal/resources/syntheticmonitoring/resource_check.go +++ b/internal/resources/syntheticmonitoring/resource_check.go @@ -1213,16 +1213,14 @@ func makeCheck(ctx context.Context, c *smapi.Client, d *schema.ResourceData) (*s // Add probes from each region until we have enough. for len(probes) < probeCount { for region, regionProbes := range byRegion { - if len(regionProbes) == 0 { - delete(byRegion, region) - continue - } if len(probes) >= probeCount { break } probes = append(probes, regionProbes[0]) byRegion[region] = regionProbes[1:] - break + if len(byRegion[region]) == 0 { + delete(byRegion, region) + } } if len(byRegion) == 0 { return nil, fmt.Errorf("not enough probes available, requested: %d, available: %d", probeCount, len(probes))