-
Notifications
You must be signed in to change notification settings - Fork 123
Add export saved objects data source #1293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
cefa6d6
cf35903
1f3ad75
1973635
bd4292f
18ab254
3c5465d
cdb7a0a
cbc1daf
b2da721
4821a00
1847e83
0ee452b
82d6299
4bfc5cc
c8b8af0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 - 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-dfe54cc87208" | ||
| } | ||
| ]) | ||
| } | ||
|
|
||
| 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) Generated ID for the export. |
| 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-dfe54cc87208" | ||
| } | ||
| ]) | ||
| } | ||
|
|
||
| output "saved_objects" { | ||
| value = data.elasticstack_kibana_export_saved_objects.example.exported_objects | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package export_saved_objects_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 | ||
| } | ||
| ]) | ||
| } | ||
| ` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package export_saved_objects | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| "github.com/elastic/terraform-provider-elasticstack/internal/clients" | ||
| "github.com/hashicorp/terraform-plugin-framework/datasource" | ||
| ) | ||
|
|
||
| // Ensure the implementation satisfies the expected interfaces. | ||
| var ( | ||
| _ datasource.DataSource = &dataSource{} | ||
| _ datasource.DataSourceWithConfigure = &dataSource{} | ||
| ) | ||
|
|
||
| // NewDataSource is a helper function to simplify the provider implementation. | ||
| func NewDataSource() datasource.DataSource { | ||
| return &dataSource{} | ||
| } | ||
|
|
||
| // dataSource is the data source implementation. | ||
| type dataSource struct { | ||
| client *clients.ApiClient | ||
| } | ||
|
|
||
| // Metadata returns the data source type name. | ||
| func (d *dataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { | ||
| resp.TypeName = req.ProviderTypeName + "_kibana_export_saved_objects" | ||
| } | ||
|
|
||
| // Configure adds the provider configured client to the data source. | ||
| func (d *dataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { | ||
| // Add a nil check when handling ProviderData because Terraform | ||
| // sets that data after it calls the ConfigureProvider RPC. | ||
| if req.ProviderData == nil { | ||
| return | ||
| } | ||
|
|
||
| client, diags := clients.ConvertProviderData(req.ProviderData) | ||
| resp.Diagnostics.Append(diags...) | ||
| if resp.Diagnostics.HasError() { | ||
| return | ||
| } | ||
|
|
||
| d.client = client | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,117 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package export_saved_objects | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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-framework/datasource" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/hashicorp/terraform-plugin-framework/types" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read refreshes the Terraform state with the latest data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (d *dataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var config dataSourceModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| diags := req.Config.Get(ctx, &config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resp.Diagnostics.Append(diags...) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if resp.Diagnostics.HasError() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Get Kibana client | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| oapiClient, err := d.client.GetKibanaOapiClient() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resp.Diagnostics.AddError("unable to get Kibana client", err.Error()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Set default space_id if not provided | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spaceId := "default" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !config.SpaceID.IsNull() && !config.SpaceID.IsUnknown() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spaceId = config.SpaceID.ValueString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Parse objects JSON | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var objectsList kbapi.PostSavedObjectsExportJSONBodyHasReference1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| objectsJSON := config.Objects.ValueString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var rawObjects []map[string]interface{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := json.Unmarshal([]byte(objectsJSON), &rawObjects); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resp.Diagnostics.AddError("Invalid objects JSON", fmt.Sprintf("Error parsing objects JSON: %v", err)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, obj := range rawObjects { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id, ok := obj["id"].(string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resp.Diagnostics.AddError("Invalid object", "Object missing 'id' field") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| objType, ok := obj["type"].(string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resp.Diagnostics.AddError("Invalid object", "Object missing 'type' field") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| objectsList = append(objectsList, struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Id string `json:"id"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Type string `json:"type"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Id: id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Type: objType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var objectsList kbapi.PostSavedObjectsExportJSONBodyHasReference1 | |
| objectsJSON := config.Objects.ValueString() | |
| var rawObjects []map[string]interface{} | |
| if err := json.Unmarshal([]byte(objectsJSON), &rawObjects); err != nil { | |
| resp.Diagnostics.AddError("Invalid objects JSON", fmt.Sprintf("Error parsing objects JSON: %v", err)) | |
| return | |
| } | |
| for _, obj := range rawObjects { | |
| id, ok := obj["id"].(string) | |
| if !ok { | |
| resp.Diagnostics.AddError("Invalid object", "Object missing 'id' field") | |
| return | |
| } | |
| objType, ok := obj["type"].(string) | |
| if !ok { | |
| resp.Diagnostics.AddError("Invalid object", "Object missing 'type' field") | |
| return | |
| } | |
| objectsList = append(objectsList, struct { | |
| Id string `json:"id"` | |
| Type string `json:"type"` | |
| }{ | |
| Id: id, | |
| Type: objType, | |
| }) | |
| } | |
| objectsList := utils.ListTypeToSlice(ctx, config.Objects, path.Root("objects"), &resp.Diagnostics, func(item objectModel, meta utils.ListMeta) struct { | |
| Id string `json:"id"` | |
| Type string `json:"type"` | |
| } { | |
| return struct { | |
| Id string `json:"id"` | |
| Type string `json:"type"` | |
| }{ | |
| Id: item.ID.ValueString(), | |
| Type: item.Type.ValueString(), | |
| } | |
| }) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,52 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| package export_saved_objects | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/hashicorp/terraform-plugin-framework/datasource" | ||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/hashicorp/terraform-plugin-framework/types" | ||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Schema defines the schema for the data source. | ||||||||||||||||||||||||||||||||||||||||||||||||
| func (d *dataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| resp.Schema = schema.Schema{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| Description: "Export Kibana saved objects. This data source allows you to export saved objects from Kibana and store the result in the Terraform state.", | ||||||||||||||||||||||||||||||||||||||||||||||||
| Attributes: map[string]schema.Attribute{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| "id": schema.StringAttribute{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| Description: "Generated ID for the export.", | ||||||||||||||||||||||||||||||||||||||||||||||||
| Computed: true, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "space_id": schema.StringAttribute{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| Description: "An identifier for the space. If space_id is not provided, the default space is used.", | ||||||||||||||||||||||||||||||||||||||||||||||||
| Optional: true, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "objects": schema.StringAttribute{ | ||||||||||||||||||||||||||||||||||||||||||||||||
| Description: "JSON-encoded list of objects to export. Each object should have 'type' and 'id' fields.", | ||||||||||||||||||||||||||||||||||||||||||||||||
| Required: true, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
| "objects": schema.StringAttribute{ | |
| Description: "JSON-encoded list of objects to export. Each object should have 'type' and 'id' fields.", | |
| Required: true, | |
| }, | |
| "objects": schema.ListNestedAttribute{ | |
| Description: "List of objects to export.", | |
| Required: true, | |
| Validators: []validator.List{ | |
| listvalidator.SizeAtLeast(1), | |
| }, | |
| NestedObject: schema.NestedAttributeObject{ | |
| Attributes: map[string]schema.Attribute{ | |
| "type": schema.StringAttribute{ | |
| Description: "The type of the saved object.", | |
| Required: true, | |
| }, | |
| "id": schema.StringAttribute{ | |
| Description: "The ID of the saved object.", | |
| Required: true, | |
| }, | |
| }, | |
| }, | |
| }, |
We can make this much simpler for users by fully defining the input schema here.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Objects types.String `tfsdk:"objects"` | |
| Objects types.List `tfsdk:"objects"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming the schema change above
| } | |
| } | |
| type objectModel struct { | |
| Type types.String `tfsdk:"type"` | |
| ID types.String `tfsdk:"id"` | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.