From f394a542e65ac4094bcb59fafa89474dae8224f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Jul 2025 11:50:17 +0000 Subject: [PATCH 1/8] Initial plan From 99bb02a003b478a51e980b58b29f1bc5ebf70815 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:03:56 +0000 Subject: [PATCH 2/8] Add solution field support to Kibana space resource and data source Co-authored-by: tobio <444668+tobio@users.noreply.github.com> --- internal/kibana/space.go | 13 ++++++++++ internal/kibana/space_test.go | 24 +++++++++++++++++++ internal/kibana/spaces/models.go | 1 + internal/kibana/spaces/read.go | 1 + internal/kibana/spaces/schema.go | 4 ++++ .../go-kibana-rest/kbapi/api.kibana_spaces.go | 1 + .../kbapi/api.kibana_spaces_test.go | 1 + 7 files changed, 45 insertions(+) diff --git a/internal/kibana/space.go b/internal/kibana/space.go index 55ea8f7c8..fd1b0fd6f 100644 --- a/internal/kibana/space.go +++ b/internal/kibana/space.go @@ -61,6 +61,12 @@ func ResourceSpace() *schema.Resource { Optional: true, ValidateFunc: validation.StringMatch(regexp.MustCompile("^data:image/"), "must be a valid data-URL encoded image"), }, + "solution": { + Description: "The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`.", + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"security", "oblt", "es", "classic"}, false), + }, } return &schema.Resource{ @@ -120,6 +126,10 @@ func resourceSpaceUpsert(ctx context.Context, d *schema.ResourceData, meta inter space.ImageURL = imageUrl.(string) } + if solution, ok := d.GetOk("solution"); ok { + space.Solution = solution.(string) + } + var spaceResponse *kbapi.KibanaSpace if d.IsNewResource() { @@ -182,6 +192,9 @@ func resourceSpaceRead(ctx context.Context, d *schema.ResourceData, meta interfa if err := d.Set("color", space.Color); err != nil { return diag.FromErr(err) } + if err := d.Set("solution", space.Solution); err != nil { + return diag.FromErr(err) + } return diags } diff --git a/internal/kibana/space_test.go b/internal/kibana/space_test.go index 9a53286f0..9141b12cb 100644 --- a/internal/kibana/space_test.go +++ b/internal/kibana/space_test.go @@ -39,6 +39,15 @@ func TestAccResourceSpace(t *testing.T) { resource.TestCheckResourceAttrSet("elasticstack_kibana_space.test_space", "image_url"), ), }, + { + Config: testAccResourceSpaceWithSolution(spaceId), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_kibana_space.test_space", "space_id", spaceId), + resource.TestCheckResourceAttr("elasticstack_kibana_space.test_space", "name", fmt.Sprintf("Solution %s", spaceId)), + resource.TestCheckResourceAttr("elasticstack_kibana_space.test_space", "description", "Test Space with Solution"), + resource.TestCheckResourceAttr("elasticstack_kibana_space.test_space", "solution", "security"), + ), + }, { Config: testAccResourceSpaceCreate(spaceId), Check: resource.ComposeTestCheckFunc( @@ -83,6 +92,21 @@ resource "elasticstack_kibana_space" "test_space" { `, id, fmt.Sprintf("Updated %s", id)) } +func testAccResourceSpaceWithSolution(id string) string { + return fmt.Sprintf(` +provider "elasticstack" { + kibana {} +} + +resource "elasticstack_kibana_space" "test_space" { + space_id = "%s" + name = "%s" + description = "Test Space with Solution" + solution = "security" +} + `, id, fmt.Sprintf("Solution %s", id)) +} + func checkResourceSpaceDestroy(s *terraform.State) error { client, err := clients.NewAcceptanceTestingClient() if err != nil { diff --git a/internal/kibana/spaces/models.go b/internal/kibana/spaces/models.go index e7187566f..4503ddf95 100644 --- a/internal/kibana/spaces/models.go +++ b/internal/kibana/spaces/models.go @@ -17,4 +17,5 @@ type model struct { Initials types.String `tfsdk:"initials"` Color types.String `tfsdk:"color"` ImageUrl types.String `tfsdk:"image_url"` + Solution types.String `tfsdk:"solution"` } diff --git a/internal/kibana/spaces/read.go b/internal/kibana/spaces/read.go index ee7879a81..beaca5772 100644 --- a/internal/kibana/spaces/read.go +++ b/internal/kibana/spaces/read.go @@ -27,6 +27,7 @@ func (d *dataSource) Read(ctx context.Context, req datasource.ReadRequest, resp Initials: types.StringValue(space.Initials), Color: types.StringValue(space.Color), ImageUrl: types.StringValue(space.ImageURL), + Solution: types.StringValue(space.Solution), } disabledFeatures, diags := types.ListValueFrom(ctx, types.StringType, space.DisabledFeatures) diff --git a/internal/kibana/spaces/schema.go b/internal/kibana/spaces/schema.go index bb08c3958..701396f5c 100644 --- a/internal/kibana/spaces/schema.go +++ b/internal/kibana/spaces/schema.go @@ -51,6 +51,10 @@ func (d *dataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp Description: "The data-URL encoded image to display in the space avatar.", Optional: true, }, + "solution": schema.StringAttribute{ + Description: "The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`.", + Optional: true, + }, }, }, }, diff --git a/libs/go-kibana-rest/kbapi/api.kibana_spaces.go b/libs/go-kibana-rest/kbapi/api.kibana_spaces.go index 02d9d6374..9b1e7a9c7 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_spaces.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_spaces.go @@ -23,6 +23,7 @@ type KibanaSpace struct { Initials string `json:"initials,omitempty"` Color string `json:"color,omitempty"` ImageURL string `json:"imageUrl,omitempty"` + Solution string `json:"solution,omitempty"` } // KibanaSpaces is the list of KibanaSpace object 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..a60997bbe 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_spaces_test.go @@ -22,6 +22,7 @@ func (s *KBAPITestSuite) TestKibanaSpaces() { ID: "test", Name: "test", Description: "My test", + Solution: "security", } kibanaSpace, err = s.KibanaSpaces.Create(kibanaSpace) assert.NoError(s.T(), err) From 0a8ad8000ec1f21f306e290f6ee2a4e32a5dc401 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:06:53 +0000 Subject: [PATCH 3/8] Update documentation and changelog for solution field support Co-authored-by: tobio <444668+tobio@users.noreply.github.com> --- CHANGELOG.md | 1 + docs/data-sources/kibana_spaces.md | 1 + docs/resources/kibana_space.md | 2 ++ 3 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91197a939..c91c0a715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [Unreleased] +- Add support for `solution` field in `elasticstack_kibana_space` resource and data source ([#1102](https://github.com/elastic/terraform-provider-elasticstack/issues/1102)) - Add support for `timeslice_metric_indicator` in `elasticstack_kibana_slo` ([#1195](https://github.com/elastic/terraform-provider-elasticstack/pull/1195)) - Add `elasticstack_elasticsearch_ingest_processor_reroute` data source ([#678](https://github.com/elastic/terraform-provider-elasticstack/issues/678)) - Add support for `supports_agentless` to `elasticstack_fleet_agent_policy` ([#1197](https://github.com/elastic/terraform-provider-elasticstack/pull/1197)) diff --git a/docs/data-sources/kibana_spaces.md b/docs/data-sources/kibana_spaces.md index 4bb1d0120..e56002e12 100644 --- a/docs/data-sources/kibana_spaces.md +++ b/docs/data-sources/kibana_spaces.md @@ -43,6 +43,7 @@ Optional: - `description` (String) The description for the space. - `disabled_features` (List of String) The list of disabled features for the space. To get a list of available feature IDs, use the Features API (https://www.elastic.co/guide/en/kibana/master/features-api-get.html). - `image_url` (String) The data-URL encoded image to display in the space avatar. +- `solution` (String) The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`. Read-Only: diff --git a/docs/resources/kibana_space.md b/docs/resources/kibana_space.md index 8dbca8e03..3ab4bd5cf 100644 --- a/docs/resources/kibana_space.md +++ b/docs/resources/kibana_space.md @@ -23,6 +23,7 @@ resource "elasticstack_kibana_space" "example" { description = "A fresh space for testing visualisations" disabled_features = ["ingestManager", "enterpriseSearch"] initials = "ts" + solution = "security" } ``` @@ -41,6 +42,7 @@ resource "elasticstack_kibana_space" "example" { - `disabled_features` (Set of String) The list of disabled features for the space. To get a list of available feature IDs, use the Features API (https://www.elastic.co/guide/en/kibana/master/features-api-get.html). - `image_url` (String) The data-URL encoded image to display in the space avatar. - `initials` (String) The initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters. +- `solution` (String) The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`. ### Read-Only From 33887bf8db9f5ed95eff312964e6dd721bfba100 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Jul 2025 22:00:30 +0000 Subject: [PATCH 4/8] Add version checking for solution field in Kibana space resource Co-authored-by: tobio <444668+tobio@users.noreply.github.com> --- internal/kibana/space.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/kibana/space.go b/internal/kibana/space.go index fd1b0fd6f..9a861070e 100644 --- a/internal/kibana/space.go +++ b/internal/kibana/space.go @@ -6,11 +6,14 @@ import ( "github.com/disaster37/go-kibana-rest/v8/kbapi" "github.com/elastic/terraform-provider-elasticstack/internal/clients" + "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +var SpaceSolutionMinVersion = version.Must(version.NewVersion("8.18.0")) + func ResourceSpace() *schema.Resource { apikeySchema := map[string]*schema.Schema{ "id": { @@ -96,6 +99,18 @@ func resourceSpaceUpsert(ctx context.Context, d *schema.ResourceData, meta inter return diag.FromErr(err) } + // Check version compatibility for solution field + if solution, ok := d.GetOk("solution"); ok && solution.(string) != "" { + serverVersion, diags := client.ServerVersion(ctx) + if diags.HasError() { + return diags + } + + if !serverVersion.GreaterThanOrEqual(SpaceSolutionMinVersion) { + return diag.Errorf("solution field is not supported in this version of the Elastic Stack. Solution field requires %s or higher", SpaceSolutionMinVersion) + } + } + space := kbapi.KibanaSpace{ ID: d.Get("space_id").(string), Name: d.Get("name").(string), From d501f186ed0e5e3e0b928443856a8a07a92ca4ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Jul 2025 22:09:43 +0000 Subject: [PATCH 5/8] Add version 8.18.3 to test matrix and SkipFunc for solution field tests Co-authored-by: tobio <444668+tobio@users.noreply.github.com> --- .github/workflows/test.yml | 1 + internal/kibana/space_test.go | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fd1ccfc82..19d46ce3c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -126,6 +126,7 @@ jobs: - '8.15.5' - '8.16.2' - '8.17.0' + - '8.18.3' - '9.0.0-SNAPSHOT' steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 diff --git a/internal/kibana/space_test.go b/internal/kibana/space_test.go index 9141b12cb..2f3a2cb51 100644 --- a/internal/kibana/space_test.go +++ b/internal/kibana/space_test.go @@ -6,6 +6,8 @@ import ( "github.com/elastic/terraform-provider-elasticstack/internal/acctest" "github.com/elastic/terraform-provider-elasticstack/internal/clients" + "github.com/elastic/terraform-provider-elasticstack/internal/kibana" + "github.com/elastic/terraform-provider-elasticstack/internal/versionutils" sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -40,7 +42,8 @@ func TestAccResourceSpace(t *testing.T) { ), }, { - Config: testAccResourceSpaceWithSolution(spaceId), + Config: testAccResourceSpaceWithSolution(spaceId), + SkipFunc: versionutils.CheckIfVersionIsUnsupported(kibana.SpaceSolutionMinVersion), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("elasticstack_kibana_space.test_space", "space_id", spaceId), resource.TestCheckResourceAttr("elasticstack_kibana_space.test_space", "name", fmt.Sprintf("Solution %s", spaceId)), From 7baf53d3b52788c3e7dcf489fee8da39fd9311e5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:20:09 +0000 Subject: [PATCH 6/8] Add Computed: true to disabled_features and solution fields in resource and data source Co-authored-by: tobio <444668+tobio@users.noreply.github.com> --- internal/kibana/space.go | 2 ++ internal/kibana/spaces/schema.go | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/kibana/space.go b/internal/kibana/space.go index 9a861070e..908ea1358 100644 --- a/internal/kibana/space.go +++ b/internal/kibana/space.go @@ -41,6 +41,7 @@ func ResourceSpace() *schema.Resource { Description: "The list of disabled features for the space. To get a list of available feature IDs, use the Features API (https://www.elastic.co/guide/en/kibana/master/features-api-get.html).", Type: schema.TypeSet, Optional: true, + Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -68,6 +69,7 @@ func ResourceSpace() *schema.Resource { Description: "The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`.", Type: schema.TypeString, Optional: true, + Computed: true, ValidateFunc: validation.StringInSlice([]string{"security", "oblt", "es", "classic"}, false), }, } diff --git a/internal/kibana/spaces/schema.go b/internal/kibana/spaces/schema.go index 701396f5c..4b45988a6 100644 --- a/internal/kibana/spaces/schema.go +++ b/internal/kibana/spaces/schema.go @@ -37,7 +37,7 @@ func (d *dataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp "disabled_features": schema.ListAttribute{ Description: "The list of disabled features for the space. To get a list of available feature IDs, use the Features API (https://www.elastic.co/guide/en/kibana/master/features-api-get.html).", ElementType: types.StringType, - Optional: true, + Computed: true, }, "initials": schema.StringAttribute{ Description: "The initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters.", @@ -53,7 +53,7 @@ func (d *dataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp }, "solution": schema.StringAttribute{ Description: "The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`.", - Optional: true, + Computed: true, }, }, }, From 8cf1bf95f0812a215851a75c5bc02956b3903314 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:33:38 +0000 Subject: [PATCH 7/8] Regenerate documentation using make docs-generate Co-authored-by: tobio <444668+tobio@users.noreply.github.com> --- docs/data-sources/kibana_spaces.md | 4 ++-- docs/resources/kibana_space.md | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/data-sources/kibana_spaces.md b/docs/data-sources/kibana_spaces.md index e56002e12..efcfdc282 100644 --- a/docs/data-sources/kibana_spaces.md +++ b/docs/data-sources/kibana_spaces.md @@ -41,12 +41,12 @@ Required: Optional: - `description` (String) The description for the space. -- `disabled_features` (List of String) The list of disabled features for the space. To get a list of available feature IDs, use the Features API (https://www.elastic.co/guide/en/kibana/master/features-api-get.html). - `image_url` (String) The data-URL encoded image to display in the space avatar. -- `solution` (String) The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`. Read-Only: - `color` (String) The hexadecimal color code used in the space avatar. By default, the color is automatically generated from the space name. +- `disabled_features` (List of String) The list of disabled features for the space. To get a list of available feature IDs, use the Features API (https://www.elastic.co/guide/en/kibana/master/features-api-get.html). - `id` (String) Internal identifier of the resource. - `initials` (String) The initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters. +- `solution` (String) The solution view for the space. Valid options are `security`, `oblt`, `es`, or `classic`. diff --git a/docs/resources/kibana_space.md b/docs/resources/kibana_space.md index 3ab4bd5cf..c8b1b30a1 100644 --- a/docs/resources/kibana_space.md +++ b/docs/resources/kibana_space.md @@ -23,7 +23,6 @@ resource "elasticstack_kibana_space" "example" { description = "A fresh space for testing visualisations" disabled_features = ["ingestManager", "enterpriseSearch"] initials = "ts" - solution = "security" } ``` From d174c2ba7d22a764aa47ae657f1003af9c0739e2 Mon Sep 17 00:00:00 2001 From: Toby Brain Date: Mon, 21 Jul 2025 22:15:30 +1000 Subject: [PATCH 8/8] Use make target for acc test services --- .github/workflows/copilot-setup-steps.yml | 59 ++--------------------- 1 file changed, 3 insertions(+), 56 deletions(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index d9b9ccac6..f63795b10 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -21,62 +21,6 @@ jobs: permissions: # If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete. contents: read - env: - ELASTICSEARCH_ENDPOINTS: "http://localhost:9200" - ELASTICSEARCH_USERNAME: "elastic" - ELASTICSEARCH_PASSWORD: password - KIBANA_ENDPOINT: "http://localhost:5601" - KIBANA_USERNAME: "elastic" - KIBANA_PASSWORD: password - KIBANA_SYSTEM_USERNAME: kibana_system - KIBANA_SYSTEM_PASSWORD: password - TF_ACC: "1" - services: - elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:9.0.3 - env: - discovery.type: single-node - xpack.security.enabled: true - xpack.security.authc.api_key.enabled: true - xpack.security.authc.token.enabled: true - xpack.watcher.enabled: true - xpack.license.self_generated.type: trial - repositories.url.allowed_urls: https://example.com/* - path.repo: /tmp - ELASTIC_PASSWORD: ${{ env.ELASTICSEARCH_PASSWORD }} - ports: - - 9200:9200 - options: --health-cmd="curl http://localhost:9200/_cluster/health" --health-interval=10s --health-timeout=5s --health-retries=10 - kibana: - image: docker.elastic.co/kibana/kibana:9.0.3 - env: - SERVER_NAME: kibana - ELASTICSEARCH_HOSTS: http://elasticsearch:9200 - ELASTICSEARCH_USERNAME: ${{ env.KIBANA_SYSTEM_USERNAME }} - ELASTICSEARCH_PASSWORD: ${{ env.KIBANA_SYSTEM_PASSWORD }} - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY: a7a6311933d3503b89bc2dbc36572c33a6c10925682e591bffcab6911c06786d - # LOGGING_ROOT_LEVEL: debug - ports: - - 5601:5601 - options: --health-cmd="curl http://localhost:5601/api/status" --health-interval=10s --health-timeout=5s --health-retries=10 - fleet: - image: docker.elastic.co/elastic-agent/elastic-agent:9.0.3 - env: - SERVER_NAME: fleet - FLEET_ENROLL: "1" - FLEET_URL: https://fleet:8220 - FLEET_INSECURE: "true" - FLEET_SERVER_ENABLE: "1" - FLEET_SERVER_POLICY_ID: fleet-server - FLEET_SERVER_ELASTICSEARCH_HOST: http://elasticsearch:9200 - FLEET_SERVER_ELASTICSEARCH_INSECURE: "true" - FLEET_SERVER_INSECURE_HTTP: "true" - KIBANA_HOST: http://kibana:5601 - KIBANA_FLEET_SETUP: "1" - KIBANA_FLEET_PASSWORD: ${{ env.ELASTICSEARCH_PASSWORD }} - ports: - - 8220:8220 - options: --restart="unless-stopped" steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -88,6 +32,9 @@ jobs: with: terraform_wrapper: false + - name: Setup Elastic Stack + run: make docker-fleet + - name: Get dependencies run: make setup