Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Add `slo_id` validation to `elasticstack_kibana_slo` ([#1221](https://github.com/elastic/terraform-provider-elasticstack/pull/1221))
- Add `ignore_missing_component_templates` to `elasticstack_elasticsearch_index_template` ([#1206](https://github.com/elastic/terraform-provider-elasticstack/pull/1206))
- Prevent provider panic when a script exists in state, but not in Elasticsearch ([#1218](https://github.com/elastic/terraform-provider-elasticstack/pull/1218))
- Add `namespace` attribute to `elasticstack_kibana_synthetics_monitor` resource to support setting data stream namespace independently from `space_id` ([#1247](https://github.com/elastic/terraform-provider-elasticstack/pull/1247))

## [0.11.17] - 2025-07-21

Expand Down
3 changes: 2 additions & 1 deletion docs/resources/kibana_synthetics_monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,13 @@ resource "elasticstack_kibana_synthetics_monitor" "my_monitor" {
- `http` (Attributes) HTTP Monitor specific fields (see [below for nested schema](#nestedatt--http))
- `icmp` (Attributes) ICMP Monitor specific fields (see [below for nested schema](#nestedatt--icmp))
- `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.
- `namespace` (String) The data stream namespace. Note: if you change its value, kibana creates new datastream. A user needs permissions for new/old datastream in update case to be able to see full monitor history. The `namespace` field should be lowercase and not contain spaces. The namespace must not include any of the following characters: *, \, /, ?, ", <, >, |, whitespace, ,, #, :, or -. Default: `default`
- `params` (String) Monitor parameters. Raw JSON object, use `jsonencode` function to represent JSON
- `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.
- `retest_on_failure` (Boolean) Enable or disable retesting when a monitor fails. By default, monitors are automatically retested if the monitor goes from "up" to "down". If the result of the retest is also "down", an error will be created, and if configured, an alert sent. Then the monitor will resume running according to the defined schedule. Using retest_on_failure can reduce noise related to transient problems. Default: `true`.
- `schedule` (Number) The monitor’s schedule in minutes. Supported values are 1, 3, 5, 10, 15, 30, 60, 120 and 240.
- `service_name` (String) The APM service name.
- `space_id` (String) The namespace field should be lowercase and not contain spaces. The namespace must not include any of the following characters: *, \, /, ?, ", <, >, |, whitespace, ,, #, :, or -. Default: `default`
- `space_id` (String) Kibana space. The space ID that is part of the Kibana URL when inside the space. Space IDs are limited to lowercase alphanumeric, underscore, and hyphen characters (a-z, 0-9, _, and -). You are cannot change the ID with the update operation.
- `tags` (List of String) An array of tags.
- `tcp` (Attributes) TCP Monitor specific fields (see [below for nested schema](#nestedatt--tcp))
- `timeout` (Number) The monitor timeout in seconds, monitor will fail if it doesn’t complete within this time. Default: `16`
Expand Down
30 changes: 24 additions & 6 deletions internal/kibana/synthetics/acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ resource "elasticstack_kibana_synthetics_monitor" "%s" {
resource "elasticstack_kibana_synthetics_monitor" "%s" {
name = "TestHttpMonitorResource - %s"
space_id = "testacc"
namespace = "test_namespace"
schedule = 5
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
enabled = true
Expand Down Expand Up @@ -164,6 +165,7 @@ resource "elasticstack_kibana_synthetics_monitor" "%s" {
resource "elasticstack_kibana_synthetics_monitor" "%s" {
name = "TestTcpMonitorResource - %s"
space_id = "testacc"
namespace = "testacc_test"
schedule = 5
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
enabled = true
Expand Down Expand Up @@ -230,6 +232,7 @@ resource "elasticstack_kibana_synthetics_monitor" "%s" {
resource "elasticstack_kibana_synthetics_monitor" "%s" {
name = "TestIcmpMonitorResource - %s"
space_id = "testacc"
namespace = "testacc_namespace"
schedule = 5
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
enabled = true
Expand Down Expand Up @@ -279,6 +282,7 @@ resource "elasticstack_kibana_synthetics_monitor" "%s" {
resource "elasticstack_kibana_synthetics_monitor" "%s" {
name = "TestBrowserMonitorResource - %s"
space_id = "testacc"
namespace = "testacc_ns"
schedule = 5
private_locations = [elasticstack_kibana_synthetics_private_location.%s.label]
enabled = true
Expand Down Expand Up @@ -363,7 +367,8 @@ func TestSyntheticMonitorHTTPResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(bmMonitorId, "id"),
resource.TestCheckResourceAttr(bmMonitorId, "name", "TestHttpMonitorResource - "+bmName),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", ""),
resource.TestCheckResourceAttr(bmMonitorId, "namespace", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.status.enabled", "true"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.tls.enabled", "true"),
resource.TestCheckResourceAttr(bmMonitorId, "http.url", "http://localhost:5601"),
Expand All @@ -376,7 +381,8 @@ func TestSyntheticMonitorHTTPResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(sslHttpMonitorId, "id"),
resource.TestCheckResourceAttr(sslHttpMonitorId, "name", "TestHttpMonitorResource - "+sslName),
resource.TestCheckResourceAttr(sslHttpMonitorId, "space_id", "default"),
resource.TestCheckResourceAttr(sslHttpMonitorId, "space_id", ""),
resource.TestCheckResourceAttr(sslHttpMonitorId, "namespace", "default"),
resource.TestCheckResourceAttr(sslHttpMonitorId, "http.url", "http://localhost:5601"),
resource.TestCheckResourceAttr(sslHttpMonitorId, "http.ssl_verification_mode", "full"),
resource.TestCheckResourceAttr(sslHttpMonitorId, "http.ssl_supported_protocols.#", "1"),
Expand Down Expand Up @@ -405,6 +411,7 @@ func TestSyntheticMonitorHTTPResource(t *testing.T) {
resource.TestCheckResourceAttrSet(httpMonitorId, "id"),
resource.TestCheckResourceAttr(httpMonitorId, "name", "TestHttpMonitorResource - "+name),
resource.TestCheckResourceAttr(httpMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(httpMonitorId, "namespace", "test_namespace"),
resource.TestCheckResourceAttr(httpMonitorId, "schedule", "5"),
resource.TestCheckResourceAttr(httpMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(httpMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -446,6 +453,7 @@ func TestSyntheticMonitorHTTPResource(t *testing.T) {
resource.TestCheckResourceAttrSet(httpMonitorId, "id"),
resource.TestCheckResourceAttr(httpMonitorId, "name", "TestHttpMonitorResource Updated - "+name),
resource.TestCheckResourceAttr(httpMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(httpMonitorId, "namespace", "test_namespace"),
resource.TestCheckResourceAttr(httpMonitorId, "schedule", "10"),
resource.TestCheckResourceAttr(httpMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(httpMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -509,7 +517,8 @@ func TestSyntheticMonitorTCPResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(bmMonitorId, "id"),
resource.TestCheckResourceAttr(bmMonitorId, "name", "TestTcpMonitorResource - "+bmName),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", ""),
resource.TestCheckResourceAttr(bmMonitorId, "namespace", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "tcp.host", "http://localhost:5601"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.status.enabled", "true"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.tls.enabled", "true"),
Expand All @@ -523,7 +532,8 @@ func TestSyntheticMonitorTCPResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(sslTcpMonitorId, "id"),
resource.TestCheckResourceAttr(sslTcpMonitorId, "name", "TestHttpMonitorResource - "+sslName),
resource.TestCheckResourceAttr(sslTcpMonitorId, "space_id", "default"),
resource.TestCheckResourceAttr(sslTcpMonitorId, "space_id", ""),
resource.TestCheckResourceAttr(sslTcpMonitorId, "namespace", "default"),
resource.TestCheckResourceAttr(sslTcpMonitorId, "tcp.host", "http://localhost:5601"),
resource.TestCheckResourceAttr(sslTcpMonitorId, "tcp.ssl_verification_mode", "full"),
resource.TestCheckResourceAttr(sslTcpMonitorId, "tcp.ssl_supported_protocols.#", "1"),
Expand Down Expand Up @@ -552,6 +562,7 @@ func TestSyntheticMonitorTCPResource(t *testing.T) {
resource.TestCheckResourceAttrSet(tcpMonitorId, "id"),
resource.TestCheckResourceAttr(tcpMonitorId, "name", "TestTcpMonitorResource - "+name),
resource.TestCheckResourceAttr(tcpMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(tcpMonitorId, "namespace", "testacc_test"),
resource.TestCheckResourceAttr(tcpMonitorId, "schedule", "5"),
resource.TestCheckResourceAttr(tcpMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(tcpMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -590,6 +601,7 @@ func TestSyntheticMonitorTCPResource(t *testing.T) {
resource.TestCheckResourceAttrSet(tcpMonitorId, "id"),
resource.TestCheckResourceAttr(tcpMonitorId, "name", "TestTcpMonitorResource Updated - "+name),
resource.TestCheckResourceAttr(tcpMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(tcpMonitorId, "namespace", "testacc_test"),
resource.TestCheckResourceAttr(tcpMonitorId, "schedule", "10"),
resource.TestCheckResourceAttr(tcpMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(tcpMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -643,7 +655,8 @@ func TestSyntheticMonitorICMPResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(bmMonitorId, "id"),
resource.TestCheckResourceAttr(bmMonitorId, "name", "TestIcmpMonitorResource - "+bmName),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", ""),
resource.TestCheckResourceAttr(bmMonitorId, "namespace", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "icmp.host", "localhost"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.status.enabled", "true"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.tls.enabled", "true"),
Expand All @@ -658,6 +671,7 @@ func TestSyntheticMonitorICMPResource(t *testing.T) {
resource.TestCheckResourceAttrSet(icmpMonitorId, "id"),
resource.TestCheckResourceAttr(icmpMonitorId, "name", "TestIcmpMonitorResource - "+name),
resource.TestCheckResourceAttr(icmpMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(icmpMonitorId, "namespace", "testacc_namespace"),
resource.TestCheckResourceAttr(icmpMonitorId, "schedule", "5"),
resource.TestCheckResourceAttr(icmpMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(icmpMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -689,6 +703,7 @@ func TestSyntheticMonitorICMPResource(t *testing.T) {
resource.TestCheckResourceAttrSet(icmpMonitorId, "id"),
resource.TestCheckResourceAttr(icmpMonitorId, "name", "TestIcmpMonitorResource Updated - "+name),
resource.TestCheckResourceAttr(icmpMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(icmpMonitorId, "namespace", "testacc_namespace"),
resource.TestCheckResourceAttr(icmpMonitorId, "schedule", "10"),
resource.TestCheckResourceAttr(icmpMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(icmpMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -735,7 +750,8 @@ func TestSyntheticMonitorBrowserResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(bmMonitorId, "id"),
resource.TestCheckResourceAttr(bmMonitorId, "name", "TestBrowserMonitorResource - "+bmName),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "space_id", ""),
resource.TestCheckResourceAttr(bmMonitorId, "namespace", "default"),
resource.TestCheckResourceAttr(bmMonitorId, "browser.inline_script", "step('Go to https://google.com.co', () => page.goto('https://www.google.com'))"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.status.enabled", "true"),
resource.TestCheckResourceAttr(bmMonitorId, "alert.tls.enabled", "true"),
Expand All @@ -749,6 +765,7 @@ func TestSyntheticMonitorBrowserResource(t *testing.T) {
resource.TestCheckResourceAttrSet(browserMonitorId, "id"),
resource.TestCheckResourceAttr(browserMonitorId, "name", "TestBrowserMonitorResource - "+name),
resource.TestCheckResourceAttr(browserMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(browserMonitorId, "namespace", "testacc_ns"),
resource.TestCheckResourceAttr(browserMonitorId, "schedule", "5"),
resource.TestCheckResourceAttr(browserMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(browserMonitorId, "private_locations.0"),
Expand Down Expand Up @@ -780,6 +797,7 @@ func TestSyntheticMonitorBrowserResource(t *testing.T) {
resource.TestCheckResourceAttrSet(browserMonitorId, "id"),
resource.TestCheckResourceAttr(browserMonitorId, "name", "TestBrowserMonitorResource Updated - "+name),
resource.TestCheckResourceAttr(browserMonitorId, "space_id", "testacc"),
resource.TestCheckResourceAttr(browserMonitorId, "namespace", "testacc_ns"),
resource.TestCheckResourceAttr(browserMonitorId, "schedule", "10"),
resource.TestCheckResourceAttr(browserMonitorId, "private_locations.#", "1"),
resource.TestCheckResourceAttrSet(browserMonitorId, "private_locations.0"),
Expand Down
9 changes: 5 additions & 4 deletions internal/kibana/synthetics/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package synthetics
import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/resource"
)

Expand All @@ -26,14 +27,14 @@ func (r *Resource) Create(ctx context.Context, request resource.CreateRequest, r
return
}

namespace := plan.SpaceID.ValueString()
result, err := kibanaClient.KibanaSynthetics.Monitor.Add(ctx, input.config, input.fields, namespace)
spaceId := plan.SpaceID.ValueString()
result, err := kibanaClient.KibanaSynthetics.Monitor.Add(ctx, input.config, input.fields, spaceId)
if err != nil {
response.Diagnostics.AddError(fmt.Sprintf("Failed to create Kibana monitor `%s`, namespace %s", input.config.Name, namespace), err.Error())
response.Diagnostics.AddError(fmt.Sprintf("Failed to create Kibana monitor `%s`, space %s", input.config.Name, spaceId), err.Error())
return
}

plan, diags = plan.toModelV0(ctx, result)
plan, diags = plan.toModelV0(ctx, result, spaceId)
response.Diagnostics.Append(diags...)
if response.Diagnostics.HasError() {
return
Expand Down
9 changes: 5 additions & 4 deletions internal/kibana/synthetics/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"

"github.com/disaster37/go-kibana-rest/v8/kbapi"
"github.com/hashicorp/terraform-plugin-framework/resource"
)
Expand All @@ -28,21 +29,21 @@ func (r *Resource) Read(ctx context.Context, request resource.ReadRequest, respo
return
}

namespace := compositeId.ClusterId
spaceId := compositeId.ClusterId
monitorId := kbapi.MonitorID(compositeId.ResourceId)
result, err := kibanaClient.KibanaSynthetics.Monitor.Get(ctx, monitorId, namespace)
result, err := kibanaClient.KibanaSynthetics.Monitor.Get(ctx, monitorId, spaceId)
if err != nil {
var apiError *kbapi.APIError
if errors.As(err, &apiError) && apiError.Code == 404 {
response.State.RemoveResource(ctx)
return
}

response.Diagnostics.AddError(fmt.Sprintf("Failed to get monitor `%s`, namespace %s", monitorId, namespace), err.Error())
response.Diagnostics.AddError(fmt.Sprintf("Failed to get monitor `%s`, space %s", monitorId, spaceId), err.Error())
return
}

state, diags = state.toModelV0(ctx, result)
state, diags = state.toModelV0(ctx, result, spaceId)
response.Diagnostics.Append(diags...)
if response.Diagnostics.HasError() {
return
Expand Down
Loading
Loading