Skip to content

Commit b38ec22

Browse files
biscout42tobio
andauthored
synthetics icmp and browser monitors support (#772)
* feat: add icmp and browser synthetic monitors implements #610 --------- Co-authored-by: Toby Brain <[email protected]>
1 parent 92f3019 commit b38ec22

File tree

9 files changed

+949
-29
lines changed

9 files changed

+949
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- Add the `Frequency` field to the Create Rule API ([#753](https://github.com/elastic/terraform-provider-elasticstack/pull/753))
1010
- Prevent a provider panic when the repository referenced in an `elasticstack_elasticsearch_snapshot_repository` does not exist ([#758](https://github.com/elastic/terraform-provider-elasticstack/pull/758))
1111
- Add support for `remote_indicies` to `elasticstack_elasticsearch_security_api_key` (#766)[https://github.com/elastic/terraform-provider-elasticstack/pull/766]
12+
- Add support for `icmp` and `browser` monitor types to `elasticstack_kibana_synthetics_monitor` resource (#772)[https://github.com/elastic/terraform-provider-elasticstack/pull/772]
1213

1314
## [0.11.6] - 2024-08-20
1415

docs/resources/kibana_synthetics_monitor.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ See [API docs](https://www.elastic.co/guide/en/kibana/current/add-monitor-api.ht
1414
## Supported monitor types
1515
* `http`
1616
* `tcp`
17+
* `icmp`
18+
* `browser`
1719

1820
**NOTE:** Due-to nature of partial update API, reset values to defaults is not supported.
1921
In case you would like to reset an optional monitor value, please set it explicitly or delete and create new monitor.
@@ -65,8 +67,10 @@ resource "elasticstack_kibana_synthetics_monitor" "my_monitor" {
6567
### Optional
6668

6769
- `alert` (Attributes) Alert configuration. Default: `{ status: { enabled: true }, tls: { enabled: true } }`. (see [below for nested schema](#nestedatt--alert))
70+
- `browser` (Attributes) Browser Monitor specific fields (see [below for nested schema](#nestedatt--browser))
6871
- `enabled` (Boolean) Whether the monitor is enabled. Default: `true`
6972
- `http` (Attributes) HTTP Monitor specific fields (see [below for nested schema](#nestedatt--http))
73+
- `icmp` (Attributes) ICMP Monitor specific fields (see [below for nested schema](#nestedatt--icmp))
7074
- `locations` (List of String) Where to deploy the monitor. Monitors can be deployed in multiple locations so that you can detect differences in availability and response times across those locations.
7175
- `params` (String) Monitor parameters. Raw JSON object, use `jsonencode` function to represent JSON
7276
- `private_locations` (List of String) These Private Locations refer to locations hosted and managed by you, whereas locations are hosted by Elastic. You can specify a Private Location using the location’s name.
@@ -107,6 +111,21 @@ Optional:
107111

108112

109113

114+
<a id="nestedatt--browser"></a>
115+
### Nested Schema for `browser`
116+
117+
Required:
118+
119+
- `inline_script` (String) The inline script.
120+
121+
Optional:
122+
123+
- `ignore_https_errors` (Boolean) Whether to ignore HTTPS errors.
124+
- `playwright_options` (String) Playwright options.. Raw JSON object, use `jsonencode` function to represent JSON
125+
- `screenshots` (String) Controls the behavior of the screenshots feature.
126+
- `synthetics_args` (List of String) Synthetics agent CLI arguments.
127+
128+
110129
<a id="nestedatt--http"></a>
111130
### Nested Schema for `http`
112131

@@ -130,6 +149,18 @@ Optional:
130149
- `username` (String) The username for authenticating with the server. The credentials are passed with the request.
131150

132151

152+
<a id="nestedatt--icmp"></a>
153+
### Nested Schema for `icmp`
154+
155+
Required:
156+
157+
- `host` (String) Host to ping; it can be an IP address or a hostname.
158+
159+
Optional:
160+
161+
- `wait` (Number) Wait time in seconds. Default: `1`
162+
163+
133164
<a id="nestedatt--tcp"></a>
134165
### Nested Schema for `tcp`
135166

@@ -157,4 +188,4 @@ terraform import elasticstack_kibana_synthetics_monitor.my_monitor <space id>/<m
157188
**NOTE:** Not all monitor fields are supported during the import due-to API limitation.
158189
Full field support could be implemented after this [kibana issue](https://github.com/elastic/kibana/issues/189906) is resolved.
159190

160-
Currently not supported fields during the import: `params`, `retest_on_failure`, `http.proxy_header`, `http.username`, `http.password`, `http.check`, `http.response`, `tcp.check_send`, `tcp.check_receive`
191+
Currently not supported fields during the import: `params`, `retest_on_failure`, `http.proxy_header`, `http.username`, `http.password`, `http.check`, `http.response`, `tcp.check_send`, `tcp.check_receive` and monitor type `browser`

internal/kibana/synthetics/acc_test.go

Lines changed: 263 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ resource "elasticstack_kibana_synthetics_monitor" "%s" {
3939
url = "http://localhost:5601"
4040
ssl_verification_mode = "full"
4141
ssl_supported_protocols = ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
42-
max_redirects = 10
4342
mode = "any"
4443
ipv4 = true
4544
ipv6 = false
@@ -165,7 +164,108 @@ resource "elasticstack_kibana_synthetics_monitor" "%s" {
165164
check_receive = "World Updated"
166165
}
167166
}
167+
`
168+
169+
icmpMonitorConfig = `
168170
171+
resource "elasticstack_kibana_synthetics_monitor" "%s" {
172+
name = "TestIcmpMonitorResource - %s"
173+
space_id = "testacc"
174+
schedule = 5
175+
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
176+
enabled = true
177+
tags = ["a", "b"]
178+
alert = {
179+
status = {
180+
enabled = true
181+
}
182+
tls = {
183+
enabled = true
184+
}
185+
}
186+
service_name = "test apm service"
187+
timeout = 30
188+
icmp = {
189+
host = "localhost"
190+
}
191+
}
192+
`
193+
194+
icmpMonitorUpdated = `
195+
resource "elasticstack_kibana_synthetics_monitor" "%s" {
196+
name = "TestIcmpMonitorResource Updated - %s"
197+
space_id = "testacc"
198+
schedule = 10
199+
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
200+
enabled = false
201+
tags = ["c", "d", "e"]
202+
alert = {
203+
status = {
204+
enabled = true
205+
}
206+
tls = {
207+
enabled = false
208+
}
209+
}
210+
service_name = "test apm service"
211+
timeout = 30
212+
icmp = {
213+
host = "google.com"
214+
wait = 10
215+
}
216+
}
217+
`
218+
browserMonitorConfig = `
219+
220+
resource "elasticstack_kibana_synthetics_monitor" "%s" {
221+
name = "TestBrowserMonitorResource - %s"
222+
space_id = "testacc"
223+
schedule = 5
224+
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
225+
enabled = true
226+
tags = ["a", "b"]
227+
alert = {
228+
status = {
229+
enabled = true
230+
}
231+
tls = {
232+
enabled = true
233+
}
234+
}
235+
service_name = "test apm service"
236+
timeout = 30
237+
browser = {
238+
inline_script = "step('Go to https://google.com.co', () => page.goto('https://www.google.com'))"
239+
}
240+
}
241+
`
242+
243+
browserMonitorUpdated = `
244+
resource "elasticstack_kibana_synthetics_monitor" "%s" {
245+
name = "TestBrowserMonitorResource Updated - %s"
246+
space_id = "testacc"
247+
schedule = 10
248+
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
249+
enabled = false
250+
tags = ["c", "d", "e"]
251+
alert = {
252+
status = {
253+
enabled = true
254+
}
255+
tls = {
256+
enabled = false
257+
}
258+
}
259+
service_name = "test apm service"
260+
timeout = 30
261+
browser = {
262+
inline_script = "step('Go to https://google.de', () => page.goto('https://www.google.de'))"
263+
synthetics_args = ["--no-sandbox", "--disable-setuid-sandbox"]
264+
screenshots = "off"
265+
ignore_https_errors = true
266+
playwright_options = jsonencode({"httpCredentials":{"password":"test","username":"test"},"ignoreHTTPSErrors":false})
267+
}
268+
}
169269
`
170270
)
171271

@@ -205,7 +305,7 @@ func TestSyntheticMonitorHTTPResource(t *testing.T) {
205305
resource.TestCheckResourceAttr(httpMonitorId, "http.ssl_supported_protocols.0", "TLSv1.0"),
206306
resource.TestCheckResourceAttr(httpMonitorId, "http.ssl_supported_protocols.1", "TLSv1.1"),
207307
resource.TestCheckResourceAttr(httpMonitorId, "http.ssl_supported_protocols.2", "TLSv1.2"),
208-
resource.TestCheckResourceAttr(httpMonitorId, "http.max_redirects", "10"),
308+
resource.TestCheckResourceAttr(httpMonitorId, "http.max_redirects", "0"),
209309
resource.TestCheckResourceAttr(httpMonitorId, "http.mode", "any"),
210310
resource.TestCheckResourceAttr(httpMonitorId, "http.ipv4", "true"),
211311
resource.TestCheckResourceAttr(httpMonitorId, "http.ipv6", "false"),
@@ -251,6 +351,8 @@ func TestSyntheticMonitorHTTPResource(t *testing.T) {
251351
resource.TestCheckResourceAttr(httpMonitorId, "http.ipv6", "true"),
252352
resource.TestCheckResourceAttr(httpMonitorId, "http.proxy_url", "http://localhost"),
253353
resource.TestCheckNoResourceAttr(httpMonitorId, "tcp"),
354+
resource.TestCheckNoResourceAttr(httpMonitorId, "browser"),
355+
resource.TestCheckNoResourceAttr(httpMonitorId, "icmp"),
254356
//check for merge attributes
255357
resource.TestCheckResourceAttr(httpMonitorId, "http.proxy_header", `{"header-name":"header-value-updated"}`),
256358
resource.TestCheckResourceAttr(httpMonitorId, "http.username", "testupdated"),
@@ -343,6 +445,8 @@ func TestSyntheticMonitorTCPResource(t *testing.T) {
343445
resource.TestCheckResourceAttr(tcpMonitorId, "tcp.proxy_url", "http://localhost"),
344446
resource.TestCheckResourceAttr(tcpMonitorId, "tcp.proxy_use_local_resolver", "false"),
345447
resource.TestCheckNoResourceAttr(tcpMonitorId, "http"),
448+
resource.TestCheckNoResourceAttr(tcpMonitorId, "browser"),
449+
resource.TestCheckNoResourceAttr(tcpMonitorId, "icmp"),
346450
//check for merge attributes
347451
resource.TestCheckResourceAttr(tcpMonitorId, "tcp.check_send", "Hello Updated"),
348452
resource.TestCheckResourceAttr(tcpMonitorId, "tcp.check_receive", "World Updated"),
@@ -354,6 +458,163 @@ func TestSyntheticMonitorTCPResource(t *testing.T) {
354458
})
355459
}
356460

461+
func TestSyntheticMonitorICMPResource(t *testing.T) {
462+
463+
name := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum)
464+
id := "icmp-monitor"
465+
icmpMonitorId, config := testMonitorConfig(id, icmpMonitorConfig, name)
466+
_, configUpdated := testMonitorConfig(id, icmpMonitorUpdated, name)
467+
468+
resource.Test(t, resource.TestCase{
469+
PreCheck: func() { acctest.PreCheck(t) },
470+
ProtoV6ProviderFactories: acctest.Providers,
471+
Steps: []resource.TestStep{
472+
473+
// Create and Read icmp monitor
474+
{
475+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion),
476+
Config: config,
477+
Check: resource.ComposeAggregateTestCheckFunc(
478+
resource.TestCheckResourceAttrSet(icmpMonitorId, "id"),
479+
resource.TestCheckResourceAttr(icmpMonitorId, "name", "TestIcmpMonitorResource - "+name),
480+
resource.TestCheckResourceAttr(icmpMonitorId, "space_id", "testacc"),
481+
resource.TestCheckResourceAttr(icmpMonitorId, "schedule", "5"),
482+
resource.TestCheckResourceAttr(icmpMonitorId, "private_locations.#", "1"),
483+
resource.TestCheckResourceAttrSet(icmpMonitorId, "private_locations.0"),
484+
resource.TestCheckResourceAttr(icmpMonitorId, "enabled", "true"),
485+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.#", "2"),
486+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.0", "a"),
487+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.1", "b"),
488+
resource.TestCheckResourceAttr(icmpMonitorId, "alert.status.enabled", "true"),
489+
resource.TestCheckResourceAttr(icmpMonitorId, "alert.tls.enabled", "true"),
490+
resource.TestCheckResourceAttr(icmpMonitorId, "service_name", "test apm service"),
491+
resource.TestCheckResourceAttr(icmpMonitorId, "timeout", "30"),
492+
resource.TestCheckResourceAttr(icmpMonitorId, "icmp.host", "localhost"),
493+
),
494+
},
495+
// ImportState testing
496+
{
497+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion),
498+
ResourceName: icmpMonitorId,
499+
ImportState: true,
500+
ImportStateVerify: true,
501+
Config: config,
502+
},
503+
// Update and Read icmp monitor
504+
{
505+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion),
506+
ResourceName: icmpMonitorId,
507+
Config: configUpdated,
508+
Check: resource.ComposeAggregateTestCheckFunc(
509+
resource.TestCheckResourceAttrSet(icmpMonitorId, "id"),
510+
resource.TestCheckResourceAttr(icmpMonitorId, "name", "TestIcmpMonitorResource Updated - "+name),
511+
resource.TestCheckResourceAttr(icmpMonitorId, "space_id", "testacc"),
512+
resource.TestCheckResourceAttr(icmpMonitorId, "schedule", "10"),
513+
resource.TestCheckResourceAttr(icmpMonitorId, "private_locations.#", "1"),
514+
resource.TestCheckResourceAttrSet(icmpMonitorId, "private_locations.0"),
515+
resource.TestCheckResourceAttr(icmpMonitorId, "enabled", "false"),
516+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.#", "3"),
517+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.0", "c"),
518+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.1", "d"),
519+
resource.TestCheckResourceAttr(icmpMonitorId, "tags.2", "e"),
520+
resource.TestCheckResourceAttr(icmpMonitorId, "alert.status.enabled", "true"),
521+
resource.TestCheckResourceAttr(icmpMonitorId, "alert.tls.enabled", "false"),
522+
resource.TestCheckResourceAttr(icmpMonitorId, "service_name", "test apm service"),
523+
resource.TestCheckResourceAttr(icmpMonitorId, "timeout", "30"),
524+
resource.TestCheckResourceAttr(icmpMonitorId, "icmp.host", "google.com"),
525+
resource.TestCheckResourceAttr(icmpMonitorId, "icmp.wait", "10"),
526+
resource.TestCheckNoResourceAttr(icmpMonitorId, "http"),
527+
resource.TestCheckNoResourceAttr(icmpMonitorId, "browser"),
528+
resource.TestCheckNoResourceAttr(icmpMonitorId, "tcp"),
529+
),
530+
},
531+
// Delete testing automatically occurs in TestCase
532+
533+
},
534+
})
535+
}
536+
537+
func TestSyntheticMonitorBrowserResource(t *testing.T) {
538+
539+
name := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum)
540+
id := "browser-monitor"
541+
browserMonitorId, config := testMonitorConfig(id, browserMonitorConfig, name)
542+
_, configUpdated := testMonitorConfig(id, browserMonitorUpdated, name)
543+
544+
resource.Test(t, resource.TestCase{
545+
PreCheck: func() { acctest.PreCheck(t) },
546+
ProtoV6ProviderFactories: acctest.Providers,
547+
Steps: []resource.TestStep{
548+
549+
// Create and Read browser monitor
550+
{
551+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion),
552+
Config: config,
553+
Check: resource.ComposeAggregateTestCheckFunc(
554+
resource.TestCheckResourceAttrSet(browserMonitorId, "id"),
555+
resource.TestCheckResourceAttr(browserMonitorId, "name", "TestBrowserMonitorResource - "+name),
556+
resource.TestCheckResourceAttr(browserMonitorId, "space_id", "testacc"),
557+
resource.TestCheckResourceAttr(browserMonitorId, "schedule", "5"),
558+
resource.TestCheckResourceAttr(browserMonitorId, "private_locations.#", "1"),
559+
resource.TestCheckResourceAttrSet(browserMonitorId, "private_locations.0"),
560+
resource.TestCheckResourceAttr(browserMonitorId, "enabled", "true"),
561+
resource.TestCheckResourceAttr(browserMonitorId, "tags.#", "2"),
562+
resource.TestCheckResourceAttr(browserMonitorId, "tags.0", "a"),
563+
resource.TestCheckResourceAttr(browserMonitorId, "tags.1", "b"),
564+
resource.TestCheckResourceAttr(browserMonitorId, "alert.status.enabled", "true"),
565+
resource.TestCheckResourceAttr(browserMonitorId, "alert.tls.enabled", "true"),
566+
resource.TestCheckResourceAttr(browserMonitorId, "service_name", "test apm service"),
567+
resource.TestCheckResourceAttr(browserMonitorId, "timeout", "30"),
568+
resource.TestCheckResourceAttr(browserMonitorId, "browser.inline_script", "step('Go to https://google.com.co', () => page.goto('https://www.google.com'))"),
569+
),
570+
},
571+
// ImportState testing - kibana doesn't return required parameter inline_script for browser monitor, so import state is not supported till the fix
572+
/* {
573+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion),
574+
ResourceName: browserMonitorId,
575+
ImportState: true,
576+
ImportStateVerify: true,
577+
Config: config,
578+
},
579+
*/ // Update and Read browser monitor
580+
{
581+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion),
582+
ResourceName: browserMonitorId,
583+
Config: configUpdated,
584+
Check: resource.ComposeAggregateTestCheckFunc(
585+
resource.TestCheckResourceAttrSet(browserMonitorId, "id"),
586+
resource.TestCheckResourceAttr(browserMonitorId, "name", "TestBrowserMonitorResource Updated - "+name),
587+
resource.TestCheckResourceAttr(browserMonitorId, "space_id", "testacc"),
588+
resource.TestCheckResourceAttr(browserMonitorId, "schedule", "10"),
589+
resource.TestCheckResourceAttr(browserMonitorId, "private_locations.#", "1"),
590+
resource.TestCheckResourceAttrSet(browserMonitorId, "private_locations.0"),
591+
resource.TestCheckResourceAttr(browserMonitorId, "enabled", "false"),
592+
resource.TestCheckResourceAttr(browserMonitorId, "tags.#", "3"),
593+
resource.TestCheckResourceAttr(browserMonitorId, "tags.0", "c"),
594+
resource.TestCheckResourceAttr(browserMonitorId, "tags.1", "d"),
595+
resource.TestCheckResourceAttr(browserMonitorId, "tags.2", "e"),
596+
resource.TestCheckResourceAttr(browserMonitorId, "alert.status.enabled", "true"),
597+
resource.TestCheckResourceAttr(browserMonitorId, "alert.tls.enabled", "false"),
598+
resource.TestCheckResourceAttr(browserMonitorId, "service_name", "test apm service"),
599+
resource.TestCheckResourceAttr(browserMonitorId, "timeout", "30"),
600+
resource.TestCheckResourceAttr(browserMonitorId, "browser.inline_script", "step('Go to https://google.de', () => page.goto('https://www.google.de'))"),
601+
resource.TestCheckResourceAttr(browserMonitorId, "browser.synthetics_args.#", "2"),
602+
resource.TestCheckResourceAttr(browserMonitorId, "browser.synthetics_args.0", "--no-sandbox"),
603+
resource.TestCheckResourceAttr(browserMonitorId, "browser.synthetics_args.1", "--disable-setuid-sandbox"),
604+
resource.TestCheckResourceAttr(browserMonitorId, "browser.screenshots", "off"),
605+
resource.TestCheckResourceAttr(browserMonitorId, "browser.ignore_https_errors", "true"),
606+
resource.TestCheckResourceAttr(browserMonitorId, "browser.playwright_options", `{"httpCredentials":{"password":"test","username":"test"},"ignoreHTTPSErrors":false}`),
607+
resource.TestCheckNoResourceAttr(browserMonitorId, "http"),
608+
resource.TestCheckNoResourceAttr(browserMonitorId, "icmp"),
609+
resource.TestCheckNoResourceAttr(browserMonitorId, "tcp"),
610+
),
611+
},
612+
// Delete testing automatically occurs in TestCase
613+
614+
},
615+
})
616+
}
617+
357618
func testMonitorConfig(id, cfg, name string) (string, string) {
358619

359620
resourceId := "elasticstack_kibana_synthetics_monitor." + id

internal/kibana/synthetics/resource.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ func (r *Resource) ConfigValidators(ctx context.Context) []resource.ConfigValida
5555
resourcevalidator.ExactlyOneOf(
5656
path.MatchRoot("http"),
5757
path.MatchRoot("tcp"),
58-
// other monitor config types: icmp, browser
58+
path.MatchRoot("icmp"),
59+
path.MatchRoot("browser"),
5960
),
6061
resourcevalidator.AtLeastOneOf(
6162
path.MatchRoot("locations"),

0 commit comments

Comments
 (0)