Skip to content

Commit ecc0e89

Browse files
authored
Add export saved objects data source (#1293)
* feat: add export saved objects data source Closes #688 * fix: docs generation * chore: Update changelog * fix: add data-view to saved object test * test: Use working connector tests * fix: Use terraform-plugin-framework * fix: Update docs * fix: update docs * fix docs with new generate * fix docs * fix docs * fix: Update schema * fix: Update docs * fix: docs update
1 parent 6456336 commit ecc0e89

File tree

8 files changed

+359
-0
lines changed

8 files changed

+359
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## [Unreleased]
22

3+
- Add `elasticstack_kibana_export_saved_objects` data source ([#1293](https://github.com/elastic/terraform-provider-elasticstack/pull/1293))
34
- Create `elasticstack_kibana_maintenance_window` resource. ([#1224](https://github.com/elastic/terraform-provider-elasticstack/pull/1224))
45
- Add support for `solution` field in `elasticstack_kibana_space` resource and data source ([#1102](https://github.com/elastic/terraform-provider-elasticstack/issues/1102))
56
- Add `slo_id` validation to `elasticstack_kibana_slo` ([#1221](https://github.com/elastic/terraform-provider-elasticstack/pull/1221))
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
---
3+
# generated by https://github.com/hashicorp/terraform-plugin-docs
4+
page_title: "elasticstack_kibana_export_saved_objects Data Source - terraform-provider-elasticstack"
5+
subcategory: "Kibana"
6+
description: |-
7+
Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.
8+
---
9+
10+
# elasticstack_kibana_export_saved_objects (Data Source)
11+
12+
Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.
13+
14+
## Example Usage
15+
16+
```terraform
17+
provider "elasticstack" {
18+
elasticsearch {}
19+
kibana {}
20+
}
21+
22+
data "elasticstack_kibana_export_saved_objects" "example" {
23+
exclude_export_details = true
24+
include_references_deep = true
25+
objects = [
26+
{
27+
type = "dashboard",
28+
id = "7c5f07ee-7e41-4d50-ae1f-dfe54cc87209"
29+
}
30+
]
31+
}
32+
33+
output "saved_objects" {
34+
value = data.elasticstack_kibana_export_saved_objects.example.exported_objects
35+
}
36+
```
37+
38+
<!-- schema generated by tfplugindocs -->
39+
## Schema
40+
41+
### Required
42+
43+
- `objects` (Attributes List) List of objects to export. (see [below for nested schema](#nestedatt--objects))
44+
45+
### Optional
46+
47+
- `exclude_export_details` (Boolean) Do not add export details. Defaults to true.
48+
- `include_references_deep` (Boolean) Include references to other saved objects recursively. Defaults to true.
49+
- `space_id` (String) An identifier for the space. If space_id is not provided, the default space is used.
50+
51+
### Read-Only
52+
53+
- `exported_objects` (String) The exported objects in NDJSON format.
54+
- `id` (String) Generated ID for the export.
55+
56+
<a id="nestedatt--objects"></a>
57+
### Nested Schema for `objects`
58+
59+
Required:
60+
61+
- `id` (String) The ID of the saved object.
62+
- `type` (String) The type of the saved object.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
provider "elasticstack" {
2+
elasticsearch {}
3+
kibana {}
4+
}
5+
6+
data "elasticstack_kibana_export_saved_objects" "example" {
7+
exclude_export_details = true
8+
include_references_deep = true
9+
objects = [
10+
{
11+
type = "dashboard",
12+
id = "7c5f07ee-7e41-4d50-ae1f-dfe54cc87209"
13+
}
14+
]
15+
}
16+
17+
output "saved_objects" {
18+
value = data.elasticstack_kibana_export_saved_objects.example.exported_objects
19+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package export_saved_objects_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
7+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
8+
)
9+
10+
func TestAccDataSourceKibanaExportSavedObjects(t *testing.T) {
11+
resource.Test(t, resource.TestCase{
12+
PreCheck: func() { acctest.PreCheck(t) },
13+
ProtoV6ProviderFactories: acctest.Providers,
14+
Steps: []resource.TestStep{
15+
{
16+
Config: testAccDataSourceKibanaExportSavedObjectsConfig,
17+
Check: resource.ComposeAggregateTestCheckFunc(
18+
resource.TestCheckResourceAttrSet("data.elasticstack_kibana_export_saved_objects.test", "id"),
19+
resource.TestCheckResourceAttrSet("data.elasticstack_kibana_export_saved_objects.test", "exported_objects"),
20+
resource.TestCheckResourceAttr("data.elasticstack_kibana_export_saved_objects.test", "space_id", "default"),
21+
resource.TestCheckResourceAttr("data.elasticstack_kibana_export_saved_objects.test", "exclude_export_details", "true"),
22+
resource.TestCheckResourceAttr("data.elasticstack_kibana_export_saved_objects.test", "include_references_deep", "true"),
23+
),
24+
},
25+
},
26+
})
27+
}
28+
29+
const testAccDataSourceKibanaExportSavedObjectsConfig = `
30+
provider "elasticstack" {
31+
elasticsearch {}
32+
kibana {}
33+
}
34+
35+
resource "elasticstack_kibana_action_connector" "test" {
36+
name = "test-export-connector"
37+
connector_type_id = ".slack"
38+
secrets = jsonencode({
39+
webhookUrl = "https://example.com"
40+
})
41+
}
42+
43+
data "elasticstack_kibana_export_saved_objects" "test" {
44+
space_id = "default"
45+
exclude_export_details = true
46+
include_references_deep = true
47+
objects = [
48+
{
49+
type = "action",
50+
id = elasticstack_kibana_action_connector.test.connector_id
51+
}
52+
]
53+
}
54+
`
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package export_saved_objects
2+
3+
import (
4+
"context"
5+
6+
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
)
9+
10+
// Ensure the implementation satisfies the expected interfaces.
11+
var (
12+
_ datasource.DataSource = &dataSource{}
13+
_ datasource.DataSourceWithConfigure = &dataSource{}
14+
)
15+
16+
// NewDataSource is a helper function to simplify the provider implementation.
17+
func NewDataSource() datasource.DataSource {
18+
return &dataSource{}
19+
}
20+
21+
// dataSource is the data source implementation.
22+
type dataSource struct {
23+
client *clients.ApiClient
24+
}
25+
26+
// Metadata returns the data source type name.
27+
func (d *dataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
28+
resp.TypeName = req.ProviderTypeName + "_kibana_export_saved_objects"
29+
}
30+
31+
// Configure adds the provider configured client to the data source.
32+
func (d *dataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
33+
// Add a nil check when handling ProviderData because Terraform
34+
// sets that data after it calls the ConfigureProvider RPC.
35+
if req.ProviderData == nil {
36+
return
37+
}
38+
39+
client, diags := clients.ConvertProviderData(req.ProviderData)
40+
resp.Diagnostics.Append(diags...)
41+
if resp.Diagnostics.HasError() {
42+
return
43+
}
44+
45+
d.client = client
46+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package export_saved_objects
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
9+
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
10+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
11+
"github.com/hashicorp/terraform-plugin-framework/datasource"
12+
"github.com/hashicorp/terraform-plugin-framework/path"
13+
"github.com/hashicorp/terraform-plugin-framework/types"
14+
)
15+
16+
// Read refreshes the Terraform state with the latest data.
17+
func (d *dataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
18+
var config dataSourceModel
19+
20+
// Read configuration
21+
diags := req.Config.Get(ctx, &config)
22+
resp.Diagnostics.Append(diags...)
23+
if resp.Diagnostics.HasError() {
24+
return
25+
}
26+
27+
// Get Kibana client
28+
oapiClient, err := d.client.GetKibanaOapiClient()
29+
if err != nil {
30+
resp.Diagnostics.AddError("unable to get Kibana client", err.Error())
31+
return
32+
}
33+
34+
// Set default space_id if not provided
35+
spaceId := "default"
36+
if !config.SpaceID.IsNull() && !config.SpaceID.IsUnknown() {
37+
spaceId = config.SpaceID.ValueString()
38+
}
39+
40+
objectsList := utils.ListTypeToSlice(ctx, config.Objects, path.Root("objects"), &resp.Diagnostics, func(item objectModel, meta utils.ListMeta) struct {
41+
Id string `json:"id"`
42+
Type string `json:"type"`
43+
} {
44+
return struct {
45+
Id string `json:"id"`
46+
Type string `json:"type"`
47+
}{
48+
Id: item.ID.ValueString(),
49+
Type: item.Type.ValueString(),
50+
}
51+
})
52+
53+
// Set default values for boolean options
54+
excludeExportDetails := true
55+
if !config.ExcludeExportDetails.IsNull() && !config.ExcludeExportDetails.IsUnknown() {
56+
excludeExportDetails = config.ExcludeExportDetails.ValueBool()
57+
}
58+
59+
includeReferencesDeep := true
60+
if !config.IncludeReferencesDeep.IsNull() && !config.IncludeReferencesDeep.IsUnknown() {
61+
includeReferencesDeep = config.IncludeReferencesDeep.ValueBool()
62+
}
63+
64+
// Create request body
65+
body := kbapi.PostSavedObjectsExportJSONRequestBody{
66+
ExcludeExportDetails: &excludeExportDetails,
67+
IncludeReferencesDeep: &includeReferencesDeep,
68+
Objects: &objectsList,
69+
}
70+
71+
// Make the API call
72+
apiResp, err := oapiClient.API.PostSavedObjectsExportWithResponse(ctx, body)
73+
if err != nil {
74+
resp.Diagnostics.AddError("API call failed", fmt.Sprintf("Unable to export saved objects: %v", err))
75+
return
76+
}
77+
78+
if apiResp.StatusCode() != http.StatusOK {
79+
resp.Diagnostics.AddError(
80+
"Unexpected API response",
81+
fmt.Sprintf("Unexpected status code from server: got HTTP %d, response: %s", apiResp.StatusCode(), string(apiResp.Body)),
82+
)
83+
return
84+
}
85+
86+
// Create composite ID for state tracking
87+
compositeID := &clients.CompositeId{ClusterId: spaceId, ResourceId: "export"}
88+
89+
// Set the state
90+
var state dataSourceModel
91+
state.ID = types.StringValue(compositeID.String())
92+
state.SpaceID = types.StringValue(spaceId)
93+
state.Objects = config.Objects
94+
state.ExcludeExportDetails = types.BoolValue(excludeExportDetails)
95+
state.IncludeReferencesDeep = types.BoolValue(includeReferencesDeep)
96+
state.ExportedObjects = types.StringValue(string(apiResp.Body))
97+
98+
// Set state
99+
diags = resp.State.Set(ctx, &state)
100+
resp.Diagnostics.Append(diags...)
101+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package export_saved_objects
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
9+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
10+
"github.com/hashicorp/terraform-plugin-framework/types"
11+
)
12+
13+
// Schema defines the schema for the data source.
14+
func (d *dataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
15+
resp.Schema = schema.Schema{
16+
Description: "Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.",
17+
Attributes: map[string]schema.Attribute{
18+
"id": schema.StringAttribute{
19+
Description: "Generated ID for the export.",
20+
Computed: true,
21+
},
22+
"space_id": schema.StringAttribute{
23+
Description: "An identifier for the space. If space_id is not provided, the default space is used.",
24+
Optional: true,
25+
},
26+
"objects": schema.ListNestedAttribute{
27+
Description: "List of objects to export.",
28+
Required: true,
29+
Validators: []validator.List{
30+
listvalidator.SizeAtLeast(1),
31+
},
32+
NestedObject: schema.NestedAttributeObject{
33+
Attributes: map[string]schema.Attribute{
34+
"type": schema.StringAttribute{
35+
Description: "The type of the saved object.",
36+
Required: true,
37+
},
38+
"id": schema.StringAttribute{
39+
Description: "The ID of the saved object.",
40+
Required: true,
41+
},
42+
},
43+
},
44+
},
45+
"exclude_export_details": schema.BoolAttribute{
46+
Description: "Do not add export details. Defaults to true.",
47+
Optional: true,
48+
},
49+
"include_references_deep": schema.BoolAttribute{
50+
Description: "Include references to other saved objects recursively. Defaults to true.",
51+
Optional: true,
52+
},
53+
"exported_objects": schema.StringAttribute{
54+
Description: "The exported objects in NDJSON format.",
55+
Computed: true,
56+
},
57+
},
58+
}
59+
}
60+
61+
type objectModel struct {
62+
Type types.String `tfsdk:"type"`
63+
ID types.String `tfsdk:"id"`
64+
}
65+
66+
// dataSourceModel maps the data source schema data.
67+
type dataSourceModel struct {
68+
ID types.String `tfsdk:"id"`
69+
SpaceID types.String `tfsdk:"space_id"`
70+
Objects types.List `tfsdk:"objects"`
71+
ExcludeExportDetails types.Bool `tfsdk:"exclude_export_details"`
72+
IncludeReferencesDeep types.Bool `tfsdk:"include_references_deep"`
73+
ExportedObjects types.String `tfsdk:"exported_objects"`
74+
}

provider/plugin_framework.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/elastic/terraform-provider-elasticstack/internal/fleet/server_host"
2424
"github.com/elastic/terraform-provider-elasticstack/internal/kibana/connectors"
2525
"github.com/elastic/terraform-provider-elasticstack/internal/kibana/data_view"
26+
"github.com/elastic/terraform-provider-elasticstack/internal/kibana/export_saved_objects"
2627
"github.com/elastic/terraform-provider-elasticstack/internal/kibana/import_saved_objects"
2728
"github.com/elastic/terraform-provider-elasticstack/internal/kibana/maintenance_window"
2829
"github.com/elastic/terraform-provider-elasticstack/internal/kibana/spaces"
@@ -89,6 +90,7 @@ func (p *Provider) DataSources(ctx context.Context) []func() datasource.DataSour
8990
return []func() datasource.DataSource{
9091
indices.NewDataSource,
9192
spaces.NewDataSource,
93+
export_saved_objects.NewDataSource,
9294
enrollment_tokens.NewDataSource,
9395
integration_ds.NewDataSource,
9496
enrich.NewEnrichPolicyDataSource,

0 commit comments

Comments
 (0)