From c5572e789a8cb3abce36a36029bb58813cbce797 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 15:46:21 +0200 Subject: [PATCH 01/10] fix: use `namespace` and `space_id` in synthetics separately --- libs/go-kibana-rest/docker-compose.yml | 4 +- .../kbapi/api.kibana_synthetics.go | 38 +++++++++---------- .../kbapi/api.kibana_synthetics_test.go | 26 +++++++------ 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/libs/go-kibana-rest/docker-compose.yml b/libs/go-kibana-rest/docker-compose.yml index 80a792946..515a53e3c 100644 --- a/libs/go-kibana-rest/docker-compose.yml +++ b/libs/go-kibana-rest/docker-compose.yml @@ -11,7 +11,7 @@ services: ports: - "9200:9200/tcp" set-kibana-password: - image: docker.elastic.co/kibana/kibana:9.1.2@sha256:dea5d20df42e6833966deceadb10ecdbf85970b704d17b0abfc3b485622c1a08 + image: docker.elastic.co/kibana/kibana:9.0.3@sha256:c4c00a485fbc3619d8373f3bc74e9dd5b5a34380ef50442be4366e8fb57cd50a restart: on-failure links: - elasticsearch @@ -22,7 +22,7 @@ services: elasticsearch: condition: service_started kibana: - image: docker.elastic.co/kibana/kibana:9.1.2@sha256:dea5d20df42e6833966deceadb10ecdbf85970b704d17b0abfc3b485622c1a08 + image: docker.elastic.co/kibana/kibana:9.0.3@sha256:c4c00a485fbc3619d8373f3bc74e9dd5b5a34380ef50442be4366e8fb57cd50a environment: SERVER_NAME: kibana ELASTICSEARCH_HOSTS: http://es:9200 diff --git a/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go b/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go index 99bde4939..6389d699f 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go @@ -326,13 +326,13 @@ func (f BrowserMonitorFields) APIRequest(config SyntheticsMonitorConfig) interfa } } -type KibanaSyntheticsMonitorAdd func(ctx context.Context, config SyntheticsMonitorConfig, fields MonitorFields, namespace string) (*SyntheticsMonitor, error) +type KibanaSyntheticsMonitorAdd func(ctx context.Context, config SyntheticsMonitorConfig, fields MonitorFields, space string) (*SyntheticsMonitor, error) -type KibanaSyntheticsMonitorUpdate func(ctx context.Context, id MonitorID, config SyntheticsMonitorConfig, fields MonitorFields, namespace string) (*SyntheticsMonitor, error) +type KibanaSyntheticsMonitorUpdate func(ctx context.Context, id MonitorID, config SyntheticsMonitorConfig, fields MonitorFields, space string) (*SyntheticsMonitor, error) -type KibanaSyntheticsMonitorGet func(ctx context.Context, id MonitorID, namespace string) (*SyntheticsMonitor, error) +type KibanaSyntheticsMonitorGet func(ctx context.Context, id MonitorID, space string) (*SyntheticsMonitor, error) -type KibanaSyntheticsMonitorDelete func(ctx context.Context, namespace string, ids ...MonitorID) ([]MonitorDeleteStatus, error) +type KibanaSyntheticsMonitorDelete func(ctx context.Context, space string, ids ...MonitorID) ([]MonitorDeleteStatus, error) type KibanaSyntheticsPrivateLocationCreate func(ctx context.Context, pLoc PrivateLocationConfig) (*PrivateLocation, error) @@ -390,8 +390,8 @@ func newKibanaSyntheticsPrivateLocationDeleteFunc(c *resty.Client) KibanaSynthet } func newKibanaSyntheticsMonitorGetFunc(c *resty.Client) KibanaSyntheticsMonitorGet { - return func(ctx context.Context, id MonitorID, namespace string) (*SyntheticsMonitor, error) { - path := basePathWithId(namespace, monitorsSuffix, id) + return func(ctx context.Context, id MonitorID, space string) (*SyntheticsMonitor, error) { + path := basePathWithId(space, monitorsSuffix, id) log.Debugf("URL to get monitor: %s", path) resp, err := c.R().SetContext(ctx).Get(path) @@ -403,8 +403,8 @@ func newKibanaSyntheticsMonitorGetFunc(c *resty.Client) KibanaSyntheticsMonitorG } func newKibanaSyntheticsMonitorDeleteFunc(c *resty.Client) KibanaSyntheticsMonitorDelete { - return func(ctx context.Context, namespace string, ids ...MonitorID) ([]MonitorDeleteStatus, error) { - path := basePath(namespace, monitorsSuffix) + return func(ctx context.Context, space string, ids ...MonitorID) ([]MonitorDeleteStatus, error) { + path := basePath(space, monitorsSuffix) log.Debugf("URL to delete monitors: %s", path) resp, err := c.R().SetContext(ctx).SetBody(map[string]interface{}{ @@ -420,9 +420,9 @@ func newKibanaSyntheticsMonitorDeleteFunc(c *resty.Client) KibanaSyntheticsMonit } func newKibanaSyntheticsMonitorUpdateFunc(c *resty.Client) KibanaSyntheticsMonitorUpdate { - return func(ctx context.Context, id MonitorID, config SyntheticsMonitorConfig, fields MonitorFields, namespace string) (*SyntheticsMonitor, error) { + return func(ctx context.Context, id MonitorID, config SyntheticsMonitorConfig, fields MonitorFields, space string) (*SyntheticsMonitor, error) { - path := basePathWithId(namespace, monitorsSuffix, id) + path := basePathWithId(space, monitorsSuffix, id) log.Debugf("URL to update monitor: %s", path) data := fields.APIRequest(config) resp, err := c.R().SetContext(ctx).SetBody(data).Put(path) @@ -434,9 +434,9 @@ func newKibanaSyntheticsMonitorUpdateFunc(c *resty.Client) KibanaSyntheticsMonit } func newKibanaSyntheticsMonitorAddFunc(c *resty.Client) KibanaSyntheticsMonitorAdd { - return func(ctx context.Context, config SyntheticsMonitorConfig, fields MonitorFields, namespace string) (*SyntheticsMonitor, error) { + return func(ctx context.Context, config SyntheticsMonitorConfig, fields MonitorFields, space string) (*SyntheticsMonitor, error) { - path := basePath(namespace, monitorsSuffix) + path := basePath(space, monitorsSuffix) log.Debugf("URL to create monitor: %s", path) data := fields.APIRequest(config) resp, err := c.R().SetContext(ctx).SetBody(data).Post(path) @@ -510,18 +510,18 @@ func handleKibanaError(err error, resp *resty.Response) error { return nil } -func basePathWithId(namespace, suffix string, id any) string { - return fmt.Sprintf("%s/%s", basePath(namespace, suffix), id) +func basePathWithId(space, suffix string, id any) string { + return fmt.Sprintf("%s/%s", basePath(space, suffix), id) } -func basePath(namespace, suffix string) string { - return namespaceBasesPath(namespace, basePathKibanaSynthetics, suffix) +func basePath(space, suffix string) string { + return spaceBasesPath(space, basePathKibanaSynthetics, suffix) } -func namespaceBasesPath(namespace, basePath, suffix string) string { - if namespace == "" || namespace == "default" { +func spaceBasesPath(space, basePath, suffix string) string { + if space == "" || space == "default" { return fmt.Sprintf("%s%s", basePath, suffix) } - return fmt.Sprintf("/s/%s%s%s", namespace, basePath, suffix) + return fmt.Sprintf("/s/%s%s%s", space, basePath, suffix) } diff --git a/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go b/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go index ac6d6fbc5..1c48454a6 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "testing" "github.com/go-resty/resty/v2" @@ -12,22 +13,22 @@ import ( ) var ( - spaces = []string{"", "default", "testacc"} + spaces = []string{"", "default", "testacc", "sample-with-dash"} ) -func testWithPolicy(t *testing.T, client *resty.Client, namespace string, f func(policyId string)) { +func testWithPolicy(t *testing.T, client *resty.Client, space_id string, f func(policyId string)) { policyName := uuid.New().String() - path := namespaceBasesPath(namespace, "/api/fleet", "/agent_policies") + path := spaceBasesPath(space_id, "/api/fleet", "/agent_policies") - if namespace == "" { - namespace = "default" + if space_id == "" { + space_id = "default" } policyResponse, err := client.R().SetBody(map[string]interface{}{ "name": fmt.Sprintf("Test synthetics monitor policy %s", policyName), "description": "test policy for synthetics API", - "namespace": namespace, + "namespace": strings.Replace(space_id, "-", "_", -1), "monitoring_enabled": []string{"logs", "metrics"}, }).Post(path) assert.NoError(t, err) @@ -64,6 +65,7 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsMonitorAPI() { for _, n := range spaces { testUuid := uuid.New().String() space := n + namespace := strings.Replace(n, "-", "_", -1) syntheticsAPI := s.API.KibanaSynthetics testWithPolicy(s.T(), s.client, space, func(policyId string) { @@ -138,7 +140,7 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsMonitorAPI() { }, APMServiceName: "APMServiceName", TimeoutSeconds: 42, - Namespace: space, + Namespace: namespace, Params: map[string]interface{}{ "param1": "some-params", "my_url": "http://localhost:8080", @@ -212,7 +214,7 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsMonitorAPI() { }, APMServiceName: "APMServiceName", TimeoutSeconds: 42, - Namespace: space, + Namespace: namespace, Params: map[string]interface{}{ "param1": "some-params", "my_url": "http://localhost:8080", @@ -280,7 +282,7 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsMonitorAPI() { }, APMServiceName: "APMServiceName", TimeoutSeconds: 42, - Namespace: space, + Namespace: namespace, Params: map[string]interface{}{ "param1": "some-params", "my_url": "http://localhost:8080", @@ -338,7 +340,7 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsMonitorAPI() { }, APMServiceName: "APMServiceName", TimeoutSeconds: 42, - Namespace: space, + Namespace: namespace, Params: map[string]interface{}{ "param1": "some-params", "my_url": "http://localhost:8080", @@ -424,11 +426,11 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsPrivateLocationAPI() { for _, n := range spaces { testUuid := uuid.New().String() - namespace := n + space_id := n pAPI := s.API.KibanaSynthetics.PrivateLocation s.Run(fmt.Sprintf("TestKibanaSyntheticsPrivateLocationAPI - %s", n), func() { - testWithPolicy(s.T(), s.client, namespace, func(policyId string) { + testWithPolicy(s.T(), s.client, space_id, func(policyId string) { cfg := PrivateLocationConfig{ Label: fmt.Sprintf("TestKibanaSyntheticsPrivateLocationAPI-%s", testUuid), From 5239fc1c159029b6005967ebedc3d770de85d546 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 15:57:51 +0200 Subject: [PATCH 02/10] remove dashboard API, related to https://github.com/elastic/kibana/issues/41439 --- libs/go-kibana-rest/kbapi/api._.go | 11 -- .../kbapi/api.kibana_dashboard.go | 114 ------------------ .../kbapi/api.kibana_dashboard_test.go | 46 ------- 3 files changed, 171 deletions(-) delete mode 100644 libs/go-kibana-rest/kbapi/api.kibana_dashboard.go delete mode 100644 libs/go-kibana-rest/kbapi/api.kibana_dashboard_test.go diff --git a/libs/go-kibana-rest/kbapi/api._.go b/libs/go-kibana-rest/kbapi/api._.go index 5d8c4fe30..cce4657e0 100644 --- a/libs/go-kibana-rest/kbapi/api._.go +++ b/libs/go-kibana-rest/kbapi/api._.go @@ -8,7 +8,6 @@ import ( type API struct { KibanaSpaces *KibanaSpacesAPI KibanaRoleManagement *KibanaRoleManagementAPI - KibanaDashboard *KibanaDashboardAPI KibanaSavedObject *KibanaSavedObjectAPI KibanaStatus *KibanaStatusAPI KibanaLogstashPipeline *KibanaLogstashPipelineAPI @@ -34,12 +33,6 @@ type KibanaRoleManagementAPI struct { Delete KibanaRoleManagementDelete } -// KibanaDashboardAPI handle the dashboard API -type KibanaDashboardAPI struct { - Export KibanaDashboardExport - Import KibanaDashboardImport -} - // KibanaSavedObjectAPI handle the saved object API type KibanaSavedObjectAPI struct { Get KibanaSavedObjectGet @@ -92,10 +85,6 @@ func New(c *resty.Client) *API { CreateOrUpdate: newKibanaRoleManagementCreateOrUpdateFunc(c), Delete: newKibanaRoleManagementDeleteFunc(c), }, - KibanaDashboard: &KibanaDashboardAPI{ - Export: newKibanaDashboardExportFunc(c), - Import: newKibanaDashboardImportFunc(c), - }, KibanaSavedObject: &KibanaSavedObjectAPI{ Get: newKibanaSavedObjectGetFunc(c), Find: newKibanaSavedObjectFindFunc(c), diff --git a/libs/go-kibana-rest/kbapi/api.kibana_dashboard.go b/libs/go-kibana-rest/kbapi/api.kibana_dashboard.go deleted file mode 100644 index 69be75594..000000000 --- a/libs/go-kibana-rest/kbapi/api.kibana_dashboard.go +++ /dev/null @@ -1,114 +0,0 @@ -package kbapi - -import ( - "encoding/json" - "fmt" - "github.com/go-resty/resty/v2" - log "github.com/sirupsen/logrus" - "strings" -) - -const ( - basePathKibanaDashboard = "/api/kibana/dashboards" // Base URL to access on Kibana dashboard -) - -// KibanaDashboardExport permit to export dashboard -type KibanaDashboardExport func(listID []string, kibanaSpace string) (map[string]interface{}, error) - -// KibanaDashboardImport permit to import dashboard -type KibanaDashboardImport func(data map[string]interface{}, listExcludeType []string, force bool, kibanaSpace string) error - -// newKibanaDashboardExportFunc permit to export Kibana dashboard by its names -func newKibanaDashboardExportFunc(c *resty.Client) KibanaDashboardExport { - return func(listID []string, kibanaSpace string) (map[string]interface{}, error) { - - if len(listID) == 0 { - return nil, NewAPIError(600, "You must provide on or more dashboard ID") - } - log.Debug("listID: ", listID) - log.Debug("kibanaSpace: ", kibanaSpace) - - var path string - if kibanaSpace == "" || kibanaSpace == "default" { - path = fmt.Sprintf("%s/export", basePathKibanaDashboard) - } else { - path = fmt.Sprintf("/s/%s%s/export", kibanaSpace, basePathKibanaDashboard) - } - - log.Debugf("Url to export: %s", path) - - query := fmt.Sprintf("dashboard=%s", strings.Join(listID, ",")) - resp, err := c.R().SetQueryString(query).Get(path) - if err != nil { - return nil, err - } - log.Debug("Response: ", resp) - if resp.StatusCode() >= 300 { - if resp.StatusCode() == 404 { - return nil, nil - } - return nil, NewAPIError(resp.StatusCode(), resp.Status()) - - } - var data map[string]interface{} - err = json.Unmarshal(resp.Body(), &data) - if err != nil { - return nil, err - } - log.Debug("Data: ", data) - - return data, nil - } - -} - -// newKibanaDashboardImportFunc permit to import kibana dashboard -func newKibanaDashboardImportFunc(c *resty.Client) KibanaDashboardImport { - return func(data map[string]interface{}, listExcludeType []string, force bool, kibanaSpace string) error { - - if data == nil { - return NewAPIError(600, "You must provide one or more dashboard to import") - } - log.Debug("data: ", data) - log.Debug("List type to exclude: ", listExcludeType) - log.Debug("Force import: ", force) - log.Debug("KibanaSpace: ", kibanaSpace) - - var path string - if kibanaSpace == "" || kibanaSpace == "default" { - path = fmt.Sprintf("%s/import", basePathKibanaDashboard) - } else { - path = fmt.Sprintf("/s/%s%s/import", kibanaSpace, basePathKibanaDashboard) - } - - log.Debugf("URL to import %s", path) - - request := c.R().SetQueryString(fmt.Sprintf("force=%t", force)) - if len(listExcludeType) > 0 { - request = request.SetQueryString(fmt.Sprintf("exclude=%s", strings.Join(listExcludeType, ","))) - } - jsonData, err := json.Marshal(data) - if err != nil { - return err - } - resp, err := request.SetBody(jsonData).Post(path) - if err != nil { - return err - } - log.Debug("Response: ", resp) - if resp.StatusCode() >= 300 { - return NewAPIError(resp.StatusCode(), resp.Status()) - } - var dataResponse map[string]interface{} - err = json.Unmarshal(resp.Body(), &dataResponse) - if err != nil { - return err - } - log.Debug("Data response: ", dataResponse) - - // Need to manage error returned in response - - return nil - } - -} diff --git a/libs/go-kibana-rest/kbapi/api.kibana_dashboard_test.go b/libs/go-kibana-rest/kbapi/api.kibana_dashboard_test.go deleted file mode 100644 index 93150c668..000000000 --- a/libs/go-kibana-rest/kbapi/api.kibana_dashboard_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package kbapi - -import ( - "encoding/json" - "os" - - "github.com/stretchr/testify/assert" -) - -func (s *KBAPITestSuite) TestKibanaDashboard() { - - // Import dashboard from fixtures - b, err := os.ReadFile("../fixtures/kibana-dashboard.json") - if err != nil { - panic(err) - } - data := make(map[string]interface{}) - if err = json.Unmarshal(b, &data); err != nil { - panic(err) - } - err = s.API.KibanaDashboard.Import(data, nil, true, "default") - assert.NoError(s.T(), err) - - // Export dashboard - data, err = s.API.KibanaDashboard.Export([]string{"edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b"}, "default") - assert.NoError(s.T(), err) - assert.NotNil(s.T(), data) - - // Import dashboard from fixtures in specific space - b, err = os.ReadFile("../fixtures/kibana-dashboard.json") - if err != nil { - panic(err) - } - data = make(map[string]interface{}) - if err = json.Unmarshal(b, &data); err != nil { - panic(err) - } - err = s.API.KibanaDashboard.Import(data, nil, true, "testacc") - assert.NoError(s.T(), err) - - // Export dashboard from specific space - data, err = s.API.KibanaDashboard.Export([]string{"edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b"}, "testacc") - assert.NoError(s.T(), err) - assert.NotNil(s.T(), data) - -} From 5d0d6f6b97293a7af7a09d511a61fb8f26946aed Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 16:06:39 +0200 Subject: [PATCH 03/10] adjust spaces test --- libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go b/libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go index 77d34a1d8..c7a4f9a26 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go @@ -42,7 +42,7 @@ func (s *KBAPITestSuite) TestKibanaSpaces() { Objects: []KibanaSpaceObjectParameter{ { Type: "config", - ID: "8.17.0", + ID: "9.0.3", }, }, } From d78118d7396c6c491a47b6efb06986a490059c0c Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 16:36:14 +0200 Subject: [PATCH 04/10] update schema --- internal/kibana/synthetics/create.go | 9 ++++---- internal/kibana/synthetics/read.go | 9 ++++---- internal/kibana/synthetics/schema.go | 21 +++++++++++++----- internal/kibana/synthetics/schema_test.go | 26 ++++++++++++++++++----- internal/kibana/synthetics/update.go | 9 ++++---- 5 files changed, 52 insertions(+), 22 deletions(-) diff --git a/internal/kibana/synthetics/create.go b/internal/kibana/synthetics/create.go index 830b9aa73..2aacea31a 100644 --- a/internal/kibana/synthetics/create.go +++ b/internal/kibana/synthetics/create.go @@ -3,6 +3,7 @@ package synthetics import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -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 diff --git a/internal/kibana/synthetics/read.go b/internal/kibana/synthetics/read.go index e7a13db7f..8d13887fd 100644 --- a/internal/kibana/synthetics/read.go +++ b/internal/kibana/synthetics/read.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/disaster37/go-kibana-rest/v8/kbapi" "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -28,9 +29,9 @@ 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 { @@ -38,11 +39,11 @@ func (r *Resource) Read(ctx context.Context, request resource.ReadRequest, respo 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 diff --git a/internal/kibana/synthetics/schema.go b/internal/kibana/synthetics/schema.go index e77fce16e..74dd8a8b9 100644 --- a/internal/kibana/synthetics/schema.go +++ b/internal/kibana/synthetics/schema.go @@ -99,6 +99,7 @@ type tfModelV0 struct { ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` SpaceID types.String `tfsdk:"space_id"` + Namespace types.String `tfsdk:"namespace"` Schedule types.Int64 `tfsdk:"schedule"` Locations []types.String `tfsdk:"locations"` PrivateLocations []types.String `tfsdk:"private_locations"` @@ -143,7 +144,16 @@ func monitorConfigSchema() schema.Schema { MarkdownDescription: "The monitor’s name.", }, "space_id": schema.StringAttribute{ - MarkdownDescription: "The namespace field should be lowercase and not contain spaces. The namespace must not include any of the following characters: *, \\, /, ?, \", <, >, |, whitespace, ,, #, :, or -. Default: `default`", + MarkdownDescription: "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.", + Optional: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + stringplanmodifier.RequiresReplace(), + }, + Computed: true, + }, + "namespace": schema.StringAttribute{ + MarkdownDescription: "Fleet namespace. The `namespace` field should be lowercase and not contain spaces. The namespace must not include any of the following characters: *, \\, /, ?, \", <, >, |, whitespace, ,, #, :, or -. Default: `default`", Optional: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), @@ -566,7 +576,7 @@ func stringToInt64(v string) (int64, error) { return res, err } -func (v *tfModelV0) toModelV0(ctx context.Context, api *kbapi.SyntheticsMonitor) (*tfModelV0, diag.Diagnostics) { +func (v *tfModelV0) toModelV0(ctx context.Context, api *kbapi.SyntheticsMonitor, space string) (*tfModelV0, diag.Diagnostics) { var schedule int64 var err error dg := diag.Diagnostics{} @@ -640,7 +650,7 @@ func (v *tfModelV0) toModelV0(ctx context.Context, api *kbapi.SyntheticsMonitor) } resourceID := clients.CompositeId{ - ClusterId: api.Namespace, + ClusterId: space, ResourceId: string(api.Id), } @@ -652,7 +662,8 @@ func (v *tfModelV0) toModelV0(ctx context.Context, api *kbapi.SyntheticsMonitor) return &tfModelV0{ ID: types.StringValue(resourceID.String()), Name: types.StringValue(api.Name), - SpaceID: types.StringValue(api.Namespace), + SpaceID: types.StringValue(space), + Namespace: types.StringValue(api.Namespace), Schedule: types.Int64Value(schedule), Locations: v.Locations, PrivateLocations: StringSliceValue(privateLocLabels), @@ -883,7 +894,7 @@ func (v *tfModelV0) toSyntheticsMonitorConfig(ctx context.Context) (*kbapi.Synth Alert: toTFAlertConfig(ctx, v.Alert), APMServiceName: v.APMServiceName.ValueString(), TimeoutSeconds: int(v.TimeoutSeconds.ValueInt64()), - Namespace: v.SpaceID.ValueString(), + Namespace: v.Namespace.ValueString(), Params: params, RetestOnFailure: v.RetestOnFailure.ValueBoolPointer(), }, diag.Diagnostics{} //dg diff --git a/internal/kibana/synthetics/schema_test.go b/internal/kibana/synthetics/schema_test.go index 1711530bf..e5c5bb60a 100644 --- a/internal/kibana/synthetics/schema_test.go +++ b/internal/kibana/synthetics/schema_test.go @@ -3,9 +3,10 @@ package synthetics import ( "context" "encoding/json" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "testing" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/disaster37/go-kibana-rest/v8/kbapi" "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" "github.com/hashicorp/terraform-plugin-framework/attr" @@ -49,6 +50,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -83,6 +85,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -111,6 +114,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -130,6 +134,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -191,6 +196,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("default/test-id-http"), Name: types.StringValue("test-name-http"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default"), Schedule: types.Int64Value(5), Locations: []types.String{types.StringValue("us_east")}, PrivateLocations: []types.String{types.StringValue("test private location")}, @@ -229,7 +235,7 @@ func TestToModelV0(t *testing.T) { input: kbapi.SyntheticsMonitor{ Id: "test-id-tcp", Name: "test-name-tcp", - Namespace: "default", + Namespace: "default-2", Enabled: tBool, Alert: &kbapi.MonitorAlertConfig{Status: &kbapi.SyntheticsStatusConfig{Enabled: tBool}}, Schedule: &kbapi.MonitorScheduleConfig{Number: "5", Unit: "m"}, @@ -261,6 +267,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("default/test-id-tcp"), Name: types.StringValue("test-name-tcp"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default-2"), Schedule: types.Int64Value(5), Locations: nil, PrivateLocations: []types.String{types.StringValue("test private location")}, @@ -320,6 +327,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("default/test-id-icmp"), Name: types.StringValue("test-name-icmp"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default"), Schedule: types.Int64Value(5), Locations: nil, PrivateLocations: []types.String{types.StringValue("test private location")}, @@ -375,6 +383,7 @@ func TestToModelV0(t *testing.T) { ID: types.StringValue("default/test-id-browser"), Name: types.StringValue("test-name-browser"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default"), Schedule: types.Int64Value(5), Locations: nil, PrivateLocations: []types.String{types.StringValue("test private location")}, @@ -398,7 +407,7 @@ func TestToModelV0(t *testing.T) { for _, tt := range testcases { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() - model, diag := tt.expected.toModelV0(ctx, &tt.input) + model, diag := tt.expected.toModelV0(ctx, &tt.input, tt.expected.SpaceID.ValueString()) assert.False(t, diag.HasError()) assert.Equal(t, &tt.expected, model) }) @@ -457,6 +466,7 @@ func TestToKibanaAPIRequest(t *testing.T) { ID: types.StringValue("test-id-http"), Name: types.StringValue("test-name-http"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default-3"), Schedule: types.Int64Value(5), Locations: []types.String{types.StringValue("us_east")}, PrivateLocations: []types.String{types.StringValue("test private location")}, @@ -500,7 +510,7 @@ func TestToKibanaAPIRequest(t *testing.T) { Tags: []string{"tag1", "tag2"}, Alert: &kbapi.MonitorAlertConfig{Status: &kbapi.SyntheticsStatusConfig{Enabled: tBool}, Tls: &kbapi.SyntheticsStatusConfig{Enabled: fBool}}, APMServiceName: "test-service-http", - Namespace: "default", + Namespace: "default-3", TimeoutSeconds: 30, Params: kbapi.JsonObject{"param1": "value1"}, }, @@ -533,6 +543,7 @@ func TestToKibanaAPIRequest(t *testing.T) { ID: types.StringValue("test-id-tcp"), Name: types.StringValue("test-name-tcp"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default"), Schedule: types.Int64Value(5), Locations: []types.String{types.StringValue("us_east")}, PrivateLocations: nil, @@ -597,6 +608,7 @@ func TestToKibanaAPIRequest(t *testing.T) { ID: types.StringValue("test-id-icmp"), Name: types.StringValue("test-name-icmp"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default"), Schedule: types.Int64Value(5), Locations: []types.String{types.StringValue("us_east")}, PrivateLocations: nil, @@ -637,6 +649,7 @@ func TestToKibanaAPIRequest(t *testing.T) { ID: types.StringValue("test-id-browser"), Name: types.StringValue("test-name-browser"), SpaceID: types.StringValue("default"), + Namespace: types.StringValue("default"), Schedule: types.Int64Value(5), Locations: []types.String{types.StringValue("us_east")}, PrivateLocations: nil, @@ -722,6 +735,7 @@ func TestToModelV0MergeAttributes(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -767,6 +781,7 @@ func TestToModelV0MergeAttributes(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -801,6 +816,7 @@ func TestToModelV0MergeAttributes(t *testing.T) { ID: types.StringValue("/"), Name: types.StringValue(""), SpaceID: types.StringValue(""), + Namespace: types.StringValue(""), Schedule: types.Int64Value(0), APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), @@ -816,7 +832,7 @@ func TestToModelV0MergeAttributes(t *testing.T) { for _, tt := range testcases { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() - actual, diag := tt.state.toModelV0(ctx, &tt.input) + actual, diag := tt.state.toModelV0(ctx, &tt.input, tt.state.SpaceID.ValueString()) assert.False(t, diag.HasError()) assert.NotNil(t, actual) assert.Equal(t, &tt.expected, actual) diff --git a/internal/kibana/synthetics/update.go b/internal/kibana/synthetics/update.go index c7544622b..3902615b3 100644 --- a/internal/kibana/synthetics/update.go +++ b/internal/kibana/synthetics/update.go @@ -3,6 +3,7 @@ package synthetics import ( "context" "fmt" + "github.com/disaster37/go-kibana-rest/v8/kbapi" "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -33,14 +34,14 @@ func (r *Resource) Update(ctx context.Context, request resource.UpdateRequest, r return } - namespace := plan.SpaceID.ValueString() - result, err := kibanaClient.KibanaSynthetics.Monitor.Update(ctx, kbapi.MonitorID(monitorId.ResourceId), input.config, input.fields, namespace) + spaceId := plan.SpaceID.ValueString() + result, err := kibanaClient.KibanaSynthetics.Monitor.Update(ctx, kbapi.MonitorID(monitorId.ResourceId), input.config, input.fields, spaceId) if err != nil { - response.Diagnostics.AddError(fmt.Sprintf("Failed to update Kibana monitor `%s`, namespace %s", input.config.Name, namespace), err.Error()) + response.Diagnostics.AddError(fmt.Sprintf("Failed to update 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 From d0ba09bbb2f97f7e03d8207aa33db15d56f48dcf Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 16:40:32 +0200 Subject: [PATCH 05/10] use golang 1.24 for mod and toolchain --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index 8ab4e1cd9..f50057681 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/elastic/terraform-provider-elasticstack go 1.24.0 -toolchain go1.25.0 - require ( github.com/disaster37/go-kibana-rest/v8 v8.5.0 github.com/elastic/elastic-transport-go/v8 v8.7.0 From 34d5ddf7303b58f437a7c3dd09d073f1dc5ec986 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 16:41:44 +0200 Subject: [PATCH 06/10] update docs --- docs/resources/kibana_synthetics_monitor.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/resources/kibana_synthetics_monitor.md b/docs/resources/kibana_synthetics_monitor.md index fabdec368..a532f915b 100644 --- a/docs/resources/kibana_synthetics_monitor.md +++ b/docs/resources/kibana_synthetics_monitor.md @@ -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) Fleet namespace. 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` From 797db0b56b55b41c298b7f7a01a04b2d6a216d4a Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 17:28:00 +0200 Subject: [PATCH 07/10] fix `TestSyntheticMonitorHTTPResource` test --- internal/kibana/synthetics/acc_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/kibana/synthetics/acc_test.go b/internal/kibana/synthetics/acc_test.go index dca2ed096..089cc58b5 100644 --- a/internal/kibana/synthetics/acc_test.go +++ b/internal/kibana/synthetics/acc_test.go @@ -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 @@ -363,7 +364,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"), @@ -376,7 +378,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"), @@ -405,6 +408,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"), @@ -446,6 +450,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"), From b2a937822c276f036f4096d27906ca2e65fac14d Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 17:39:14 +0200 Subject: [PATCH 08/10] fix tests --- internal/kibana/synthetics/acc_test.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/internal/kibana/synthetics/acc_test.go b/internal/kibana/synthetics/acc_test.go index 089cc58b5..346fafbcd 100644 --- a/internal/kibana/synthetics/acc_test.go +++ b/internal/kibana/synthetics/acc_test.go @@ -165,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 @@ -231,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 @@ -280,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 @@ -514,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"), @@ -528,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"), @@ -557,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"), @@ -595,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"), @@ -648,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"), @@ -663,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"), @@ -694,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"), @@ -740,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"), @@ -754,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"), @@ -785,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"), From 886306f160d2ab6d6b8f4d9d360d1de6632570c7 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Tue, 19 Aug 2025 17:57:07 +0200 Subject: [PATCH 09/10] chage log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e418e54..6771aee18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) +- Fix `namespace` usage in synthetic monitors. Separate Kibana `space_id` the monitor is saved in from the `namespace`, the data stream namespace for Fleet. ([#1247](https://github.com/elastic/terraform-provider-elasticstack/pull/1247)) ## [0.11.17] - 2025-07-21 From c8acce6b2e800d46110ccc2fdc245b41dd34db83 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Wed, 20 Aug 2025 07:40:38 +0200 Subject: [PATCH 10/10] revert toolchain to 1.25 --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index f50057681..8ab4e1cd9 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/elastic/terraform-provider-elasticstack go 1.24.0 +toolchain go1.25.0 + require ( github.com/disaster37/go-kibana-rest/v8 v8.5.0 github.com/elastic/elastic-transport-go/v8 v8.7.0