Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## [Unreleased]

- Add `elasticstack_kibana_export_saved_objects` data source ([#1293](https://github.com/elastic/terraform-provider-elasticstack/pull/1293))
- Create `elasticstack_kibana_maintenance_window` resource. ([#1224](https://github.com/elastic/terraform-provider-elasticstack/pull/1224))
- Add support for `solution` field in `elasticstack_kibana_space` resource and data source ([#1102](https://github.com/elastic/terraform-provider-elasticstack/issues/1102))
- Add `slo_id` validation to `elasticstack_kibana_slo` ([#1221](https://github.com/elastic/terraform-provider-elasticstack/pull/1221))
Expand Down
54 changes: 54 additions & 0 deletions docs/data-sources/kibana_export_saved_objects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "elasticstack_kibana_export_saved_objects Data Source - terraform-provider-elasticstack"
subcategory: ""
description: |-
Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.
---

# elasticstack_kibana_export_saved_objects (Data Source)

Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.

## Example Usage

```terraform
provider "elasticstack" {
elasticsearch {}
kibana {}
}

data "elasticstack_kibana_export_saved_objects" "example" {
space_id = "default"
exclude_export_details = true
include_references_deep = true
objects = jsonencode([
{
"type" : "dashboard",
"id" : "7c5f07ee-7e41-4d50-ae1f-dfe54cc87209"
}
])
}

output "saved_objects" {
value = data.elasticstack_kibana_export_saved_objects.example.exported_objects
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `objects` (String) JSON-encoded list of objects to export. Each object should have 'type' and 'id' fields.

### Optional

- `exclude_export_details` (Boolean) Do not add export details. Defaults to true.
- `include_references_deep` (Boolean) Include references to other saved objects recursively. Defaults to true.
- `space_id` (String) An identifier for the space. If space_id is not provided, the default space is used.

### Read-Only

- `exported_objects` (String) The exported objects in NDJSON format.
- `id` (String) Identifier for the data source.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
provider "elasticstack" {
elasticsearch {}
kibana {}
}

data "elasticstack_kibana_export_saved_objects" "example" {
space_id = "default"
exclude_export_details = true
include_references_deep = true
objects = jsonencode([
{
"type" : "dashboard",
"id" : "7c5f07ee-7e41-4d50-ae1f-dfe54cc87209"
}
])
}

output "saved_objects" {
value = data.elasticstack_kibana_export_saved_objects.example.exported_objects
}
146 changes: 146 additions & 0 deletions internal/kibana/export_saved_object_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package kibana

import (
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Schema defines the schema for the data source.
func DataSourceExportSavedObjects() *schema.Resource {
var savedObjectSchema = map[string]*schema.Schema{
"id": {
Description: "Identifier for the data source.",
Type: schema.TypeString,
Computed: true,
},
"space_id": {
Description: "An identifier for the space. If space_id is not provided, the default space is used.",
Type: schema.TypeString,
Optional: true,
},
"objects": {
Description: "JSON-encoded list of objects to export. Each object should have 'type' and 'id' fields.",
Type: schema.TypeString,
Required: true,
},
"exclude_export_details": {
Description: "Do not add export details. Defaults to true.",
Type: schema.TypeBool,
Optional: true,
},
"include_references_deep": {
Description: "Include references to other saved objects recursively. Defaults to true.",
Type: schema.TypeBool,
Optional: true,
},
"exported_objects": {
Description: "The exported objects in NDJSON format.",
Type: schema.TypeString,
Computed: true,
},
}
return &schema.Resource{
Description: "Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.",
ReadContext: datasourceExportSavedObjectRead,
Schema: savedObjectSchema,
}
}

func datasourceExportSavedObjectRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
oapiClient, err := client.GetKibanaOapiClient()
if err != nil {
return diag.FromErr(err)
}

spaceId := d.Get("space_id").(string)
if spaceId == "" {
spaceId = "default"
}

var objectsList kbapi.PostSavedObjectsExportJSONBodyHasReference1
objectsJSON := d.Get("objects").(string)

var rawObjects []map[string]interface{}
if err := json.Unmarshal([]byte(objectsJSON), &rawObjects); err != nil {
return diag.Errorf("Invalid objects JSON: %v", err)
}

for _, obj := range rawObjects {
id, ok := obj["id"].(string)
if !ok {
return diag.Errorf("Object missing 'id' field")
}
objType, ok := obj["type"].(string)
if !ok {
return diag.Errorf("Object missing 'type' field")
}
objectsList = append(objectsList, struct {
Id string `json:"id"`
Type string `json:"type"`
}{
Id: id,
Type: objType,
})
}

excludeExportDetails := true
if val, ok := d.GetOk("exclude_export_details"); ok {
excludeExportDetails = val.(bool)
}

includeReferencesDeep := true
if val, ok := d.GetOk("include_references_deep"); ok {
includeReferencesDeep = val.(bool)
}

body := kbapi.PostSavedObjectsExportJSONRequestBody{
ExcludeExportDetails: &excludeExportDetails,
IncludeReferencesDeep: &includeReferencesDeep,
Objects: &objectsList,
}

resp, err := oapiClient.API.PostSavedObjectsExportWithResponse(ctx, body)
if err != nil {
return diag.Errorf("unable to export saved objects: [%v]", err)
}

if resp.StatusCode() != http.StatusOK {
return diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Error,
Summary: fmt.Sprintf("Unexpected status code from server: got HTTP %d", resp.StatusCode()),
Detail: string(resp.Body),
},
}
}

// Set the results
compositeID := &clients.CompositeId{ClusterId: spaceId, ResourceId: "export"}
d.SetId(compositeID.String())

if err := d.Set("exported_objects", string(resp.Body)); err != nil {
return diag.FromErr(err)
}
if err := d.Set("space_id", spaceId); err != nil {
return diag.FromErr(err)
}
if err := d.Set("exclude_export_details", excludeExportDetails); err != nil {
return diag.FromErr(err)
}
if err := d.Set("include_references_deep", includeReferencesDeep); err != nil {
return diag.FromErr(err)
}

return nil
}
54 changes: 54 additions & 0 deletions internal/kibana/export_saved_object_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package kibana_test

import (
"testing"

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAccDataSourceKibanaExportSavedObjects(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: acctest.Providers,
Steps: []resource.TestStep{
{
Config: testAccDataSourceKibanaExportSavedObjectsConfig,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.elasticstack_kibana_export_saved_objects.test", "id"),
resource.TestCheckResourceAttrSet("data.elasticstack_kibana_export_saved_objects.test", "exported_objects"),
resource.TestCheckResourceAttr("data.elasticstack_kibana_export_saved_objects.test", "space_id", "default"),
resource.TestCheckResourceAttr("data.elasticstack_kibana_export_saved_objects.test", "exclude_export_details", "true"),
resource.TestCheckResourceAttr("data.elasticstack_kibana_export_saved_objects.test", "include_references_deep", "true"),
),
},
},
})
}

const testAccDataSourceKibanaExportSavedObjectsConfig = `
provider "elasticstack" {
elasticsearch {}
kibana {}
}

resource "elasticstack_kibana_action_connector" "test" {
name = "test-export-connector"
connector_type_id = ".slack"
secrets = jsonencode({
webhookUrl = "https://example.com"
})
}

data "elasticstack_kibana_export_saved_objects" "test" {
space_id = "default"
exclude_export_details = true
include_references_deep = true
objects = jsonencode([
{
"type": "action",
"id": elasticstack_kibana_action_connector.test.connector_id
}
])
}
`
5 changes: 3 additions & 2 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ func New(version string) *schema.Provider {
"elasticstack_elasticsearch_snapshot_repository": cluster.DataSourceSnapshotRespository(),
"elasticstack_elasticsearch_info": cluster.DataSourceClusterInfo(),

"elasticstack_kibana_action_connector": kibana.DataSourceConnector(),
"elasticstack_kibana_security_role": kibana.DataSourceRole(),
"elasticstack_kibana_action_connector": kibana.DataSourceConnector(),
"elasticstack_kibana_export_saved_objects": kibana.DataSourceExportSavedObjects(),
"elasticstack_kibana_security_role": kibana.DataSourceRole(),
},
ResourcesMap: map[string]*schema.Resource{
"elasticstack_elasticsearch_cluster_settings": cluster.ResourceSettings(),
Expand Down