diff --git a/docs/resources/kibana_default_data_view.md b/docs/resources/kibana_default_data_view.md new file mode 100644 index 000000000..92bc132a4 --- /dev/null +++ b/docs/resources/kibana_default_data_view.md @@ -0,0 +1,49 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "elasticstack_kibana_default_data_view Resource - terraform-provider-elasticstack" +subcategory: "Kibana" +description: |- + Manages the default Kibana data view. See the Kibana Data Views API documentation https://www.elastic.co/docs/api/doc/kibana/v8/operation/operation-setdefaultdatailviewdefault for more information. +--- + +# elasticstack_kibana_default_data_view (Resource) + +Manages the default Kibana data view. See the [Kibana Data Views API documentation](https://www.elastic.co/docs/api/doc/kibana/v8/operation/operation-setdefaultdatailviewdefault) for more information. + +## Example Usage + +```terraform +resource "elasticstack_elasticsearch_index" "my_index" { + name = "my-index-000001" + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "my_data_view" { + data_view = { + title = "my-index-*" + name = "My Index Data View" + } + + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_default_data_view" "default" { + data_view_id = elasticstack_kibana_data_view.my_data_view.data_view.id + force = true + skip_delete = false +} +``` + + +## Schema + +### Optional + +- `data_view_id` (String) The data view identifier to set as default. NOTE: The API does not validate whether it is a valid identifier. Leave this unset (or explicitly `null`) to unset the default data view. +- `force` (Boolean) Update an existing default data view identifier. If set to false and a default data view already exists, the operation will fail. +- `skip_delete` (Boolean) If set to true, the default data view will not be unset when the resource is destroyed. The existing default data view will remain unchanged. +- `space_id` (String) The Kibana space ID to set the default data view in. Defaults to `default`. + +### Read-Only + +- `id` (String) Internal identifier of the resource. diff --git a/examples/resources/elasticstack_kibana_default_data_view/resource.tf b/examples/resources/elasticstack_kibana_default_data_view/resource.tf new file mode 100644 index 000000000..8b8f3fd8c --- /dev/null +++ b/examples/resources/elasticstack_kibana_default_data_view/resource.tf @@ -0,0 +1,19 @@ +resource "elasticstack_elasticsearch_index" "my_index" { + name = "my-index-000001" + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "my_data_view" { + data_view = { + title = "my-index-*" + name = "My Index Data View" + } + + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_default_data_view" "default" { + data_view_id = elasticstack_kibana_data_view.my_data_view.data_view.id + force = true + skip_delete = false +} diff --git a/generated/kbapi/kibana.gen.go b/generated/kbapi/kibana.gen.go index a23628e88..b6ec5a016 100644 --- a/generated/kbapi/kibana.gen.go +++ b/generated/kbapi/kibana.gen.go @@ -25912,15 +25912,6 @@ type UpdateRuntimeFieldDefaultJSONBody struct { RuntimeField map[string]interface{} `json:"runtimeField"` } -// SetDefaultDatailViewDefaultJSONBody defines parameters for SetDefaultDatailViewDefault. -type SetDefaultDatailViewDefaultJSONBody struct { - // DataViewId The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view. - DataViewId *string `json:"data_view_id,omitempty"` - - // Force Update an existing default data view identifier. - Force *bool `json:"force,omitempty"` -} - // DeleteRuleParams defines parameters for DeleteRule. type DeleteRuleParams struct { // Id The rule's `id` value. @@ -41426,6 +41417,15 @@ type PutActionsConnectorIdJSONBody struct { Secrets *UpdateConnectorSecrets `json:"secrets,omitempty"` } +// SetDefaultDatailViewDefaultJSONBody defines parameters for SetDefaultDatailViewDefault. +type SetDefaultDatailViewDefaultJSONBody struct { + // DataViewId The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view. + DataViewId *string `json:"data_view_id,omitempty"` + + // Force Update an existing default data view identifier. + Force *bool `json:"force,omitempty"` +} + // PostMaintenanceWindowJSONBody defines parameters for PostMaintenanceWindow. type PostMaintenanceWindowJSONBody struct { // Enabled Whether the current maintenance window is enabled. Disabled maintenance windows do not suppress notifications. @@ -41696,9 +41696,6 @@ type CreateUpdateRuntimeFieldDefaultJSONRequestBody CreateUpdateRuntimeFieldDefa // UpdateRuntimeFieldDefaultJSONRequestBody defines body for UpdateRuntimeFieldDefault for application/json ContentType. type UpdateRuntimeFieldDefaultJSONRequestBody UpdateRuntimeFieldDefaultJSONBody -// SetDefaultDatailViewDefaultJSONRequestBody defines body for SetDefaultDatailViewDefault for application/json ContentType. -type SetDefaultDatailViewDefaultJSONRequestBody SetDefaultDatailViewDefaultJSONBody - // SwapDataViewsDefaultJSONRequestBody defines body for SwapDataViewsDefault for application/json ContentType. type SwapDataViewsDefaultJSONRequestBody = DataViewsSwapDataViewRequestObject @@ -42287,6 +42284,9 @@ type CreateDataViewDefaultwJSONRequestBody = DataViewsCreateDataViewRequestObjec // UpdateDataViewDefaultJSONRequestBody defines body for UpdateDataViewDefault for application/json ContentType. type UpdateDataViewDefaultJSONRequestBody = DataViewsUpdateDataViewRequestObject +// SetDefaultDatailViewDefaultJSONRequestBody defines body for SetDefaultDatailViewDefault for application/json ContentType. +type SetDefaultDatailViewDefaultJSONRequestBody SetDefaultDatailViewDefaultJSONBody + // PostMaintenanceWindowJSONRequestBody defines body for PostMaintenanceWindow for application/json ContentType. type PostMaintenanceWindowJSONRequestBody PostMaintenanceWindowJSONBody @@ -54769,7 +54769,7 @@ func (t SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item) AsSLO // FromSLOsTimesliceMetricBasicMetricWithField overwrites any union data inside the SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item as the provided SLOsTimesliceMetricBasicMetricWithField func (t *SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item) FromSLOsTimesliceMetricBasicMetricWithField(v SLOsTimesliceMetricBasicMetricWithField) error { - v.Aggregation = "cardinality" + v.Aggregation = "last_value" b, err := json.Marshal(v) t.union = b return err @@ -54777,7 +54777,7 @@ func (t *SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item) From // MergeSLOsTimesliceMetricBasicMetricWithField performs a merge with any union data inside the SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item, using the provided SLOsTimesliceMetricBasicMetricWithField func (t *SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item) MergeSLOsTimesliceMetricBasicMetricWithField(v SLOsTimesliceMetricBasicMetricWithField) error { - v.Aggregation = "cardinality" + v.Aggregation = "last_value" b, err := json.Marshal(v) if err != nil { return err @@ -54858,10 +54858,10 @@ func (t SLOsIndicatorPropertiesTimesliceMetric_Params_Metric_Metrics_Item) Value return nil, err } switch discriminator { - case "cardinality": - return t.AsSLOsTimesliceMetricBasicMetricWithField() case "doc_count": return t.AsSLOsTimesliceMetricDocCountMetric() + case "last_value": + return t.AsSLOsTimesliceMetricBasicMetricWithField() case "percentile": return t.AsSLOsTimesliceMetricPercentileMetric() default: @@ -68122,14 +68122,6 @@ type ClientInterface interface { UpdateRuntimeFieldDefault(ctx context.Context, viewId DataViewsViewId, fieldName DataViewsFieldName, body UpdateRuntimeFieldDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetDefaultDataViewDefault request - GetDefaultDataViewDefault(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // SetDefaultDatailViewDefaultWithBody request with any body - SetDefaultDatailViewDefaultWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - SetDefaultDatailViewDefault(ctx context.Context, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // SwapDataViewsDefaultWithBody request with any body SwapDataViewsDefaultWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -69694,6 +69686,14 @@ type ClientInterface interface { UpdateDataViewDefault(ctx context.Context, spaceId SpaceId, viewId DataViewsViewId, body UpdateDataViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetDefaultDataViewDefault request + GetDefaultDataViewDefault(ctx context.Context, spaceId SpaceId, reqEditors ...RequestEditorFn) (*http.Response, error) + + // SetDefaultDatailViewDefaultWithBody request with any body + SetDefaultDatailViewDefaultWithBody(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + SetDefaultDatailViewDefault(ctx context.Context, spaceId SpaceId, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // PostMaintenanceWindowWithBody request with any body PostMaintenanceWindowWithBody(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -71368,42 +71368,6 @@ func (c *Client) UpdateRuntimeFieldDefault(ctx context.Context, viewId DataViews return c.Client.Do(req) } -func (c *Client) GetDefaultDataViewDefault(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetDefaultDataViewDefaultRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) SetDefaultDatailViewDefaultWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewSetDefaultDatailViewDefaultRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) SetDefaultDatailViewDefault(ctx context.Context, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewSetDefaultDatailViewDefaultRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - func (c *Client) SwapDataViewsDefaultWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewSwapDataViewsDefaultRequestWithBody(c.Server, contentType, body) if err != nil { @@ -78412,6 +78376,42 @@ func (c *Client) UpdateDataViewDefault(ctx context.Context, spaceId SpaceId, vie return c.Client.Do(req) } +func (c *Client) GetDefaultDataViewDefault(ctx context.Context, spaceId SpaceId, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetDefaultDataViewDefaultRequest(c.Server, spaceId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) SetDefaultDatailViewDefaultWithBody(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewSetDefaultDatailViewDefaultRequestWithBody(c.Server, spaceId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) SetDefaultDatailViewDefault(ctx context.Context, spaceId SpaceId, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewSetDefaultDatailViewDefaultRequest(c.Server, spaceId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) PostMaintenanceWindowWithBody(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewPostMaintenanceWindowRequestWithBody(c.Server, spaceId, contentType, body) if err != nil { @@ -83896,73 +83896,6 @@ func NewUpdateRuntimeFieldDefaultRequestWithBody(server string, viewId DataViews return req, nil } -// NewGetDefaultDataViewDefaultRequest generates requests for GetDefaultDataViewDefault -func NewGetDefaultDataViewDefaultRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/data_views/default") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewSetDefaultDatailViewDefaultRequest calls the generic SetDefaultDatailViewDefault builder with application/json body -func NewSetDefaultDatailViewDefaultRequest(server string, body SetDefaultDatailViewDefaultJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewSetDefaultDatailViewDefaultRequestWithBody(server, "application/json", bodyReader) -} - -// NewSetDefaultDatailViewDefaultRequestWithBody generates requests for SetDefaultDatailViewDefault with any type of body -func NewSetDefaultDatailViewDefaultRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/data_views/default") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - // NewSwapDataViewsDefaultRequest calls the generic SwapDataViewsDefault builder with application/json body func NewSwapDataViewsDefaultRequest(server string, body SwapDataViewsDefaultJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -104936,6 +104869,87 @@ func NewUpdateDataViewDefaultRequestWithBody(server string, spaceId SpaceId, vie return req, nil } +// NewGetDefaultDataViewDefaultRequest generates requests for GetDefaultDataViewDefault +func NewGetDefaultDataViewDefaultRequest(server string, spaceId SpaceId) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "spaceId", runtime.ParamLocationPath, spaceId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/s/%s/api/data_views/default", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewSetDefaultDatailViewDefaultRequest calls the generic SetDefaultDatailViewDefault builder with application/json body +func NewSetDefaultDatailViewDefaultRequest(server string, spaceId SpaceId, body SetDefaultDatailViewDefaultJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewSetDefaultDatailViewDefaultRequestWithBody(server, spaceId, "application/json", bodyReader) +} + +// NewSetDefaultDatailViewDefaultRequestWithBody generates requests for SetDefaultDatailViewDefault with any type of body +func NewSetDefaultDatailViewDefaultRequestWithBody(server string, spaceId SpaceId, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "spaceId", runtime.ParamLocationPath, spaceId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/s/%s/api/data_views/default", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewPostMaintenanceWindowRequest calls the generic PostMaintenanceWindow builder with application/json body func NewPostMaintenanceWindowRequest(server string, spaceId SpaceId, body PostMaintenanceWindowJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -106325,14 +106339,6 @@ type ClientWithResponsesInterface interface { UpdateRuntimeFieldDefaultWithResponse(ctx context.Context, viewId DataViewsViewId, fieldName DataViewsFieldName, body UpdateRuntimeFieldDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateRuntimeFieldDefaultResponse, error) - // GetDefaultDataViewDefaultWithResponse request - GetDefaultDataViewDefaultWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetDefaultDataViewDefaultResponse, error) - - // SetDefaultDatailViewDefaultWithBodyWithResponse request with any body - SetDefaultDatailViewDefaultWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) - - SetDefaultDatailViewDefaultWithResponse(ctx context.Context, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) - // SwapDataViewsDefaultWithBodyWithResponse request with any body SwapDataViewsDefaultWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SwapDataViewsDefaultResponse, error) @@ -107897,6 +107903,14 @@ type ClientWithResponsesInterface interface { UpdateDataViewDefaultWithResponse(ctx context.Context, spaceId SpaceId, viewId DataViewsViewId, body UpdateDataViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDataViewDefaultResponse, error) + // GetDefaultDataViewDefaultWithResponse request + GetDefaultDataViewDefaultWithResponse(ctx context.Context, spaceId SpaceId, reqEditors ...RequestEditorFn) (*GetDefaultDataViewDefaultResponse, error) + + // SetDefaultDatailViewDefaultWithBodyWithResponse request with any body + SetDefaultDatailViewDefaultWithBodyWithResponse(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) + + SetDefaultDatailViewDefaultWithResponse(ctx context.Context, spaceId SpaceId, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) + // PostMaintenanceWindowWithBodyWithResponse request with any body PostMaintenanceWindowWithBodyWithResponse(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostMaintenanceWindowResponse, error) @@ -112113,56 +112127,6 @@ func (r UpdateRuntimeFieldDefaultResponse) StatusCode() int { return 0 } -type GetDefaultDataViewDefaultResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - DataViewId *string `json:"data_view_id,omitempty"` - } - JSON400 *DataViews400Response -} - -// Status returns HTTPResponse.Status -func (r GetDefaultDataViewDefaultResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetDefaultDataViewDefaultResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type SetDefaultDatailViewDefaultResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - Acknowledged *bool `json:"acknowledged,omitempty"` - } - JSON400 *DataViews400Response -} - -// Status returns HTTPResponse.Status -func (r SetDefaultDatailViewDefaultResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r SetDefaultDatailViewDefaultResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - type SwapDataViewsDefaultResponse struct { Body []byte HTTPResponse *http.Response @@ -125839,6 +125803,56 @@ func (r UpdateDataViewDefaultResponse) StatusCode() int { return 0 } +type GetDefaultDataViewDefaultResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + DataViewId *string `json:"data_view_id,omitempty"` + } + JSON400 *DataViews400Response +} + +// Status returns HTTPResponse.Status +func (r GetDefaultDataViewDefaultResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetDefaultDataViewDefaultResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type SetDefaultDatailViewDefaultResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Acknowledged *bool `json:"acknowledged,omitempty"` + } + JSON400 *DataViews400Response +} + +// Status returns HTTPResponse.Status +func (r SetDefaultDatailViewDefaultResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r SetDefaultDatailViewDefaultResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type PostMaintenanceWindowResponse struct { Body []byte HTTPResponse *http.Response @@ -127616,32 +127630,6 @@ func (c *ClientWithResponses) UpdateRuntimeFieldDefaultWithResponse(ctx context. return ParseUpdateRuntimeFieldDefaultResponse(rsp) } -// GetDefaultDataViewDefaultWithResponse request returning *GetDefaultDataViewDefaultResponse -func (c *ClientWithResponses) GetDefaultDataViewDefaultWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetDefaultDataViewDefaultResponse, error) { - rsp, err := c.GetDefaultDataViewDefault(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetDefaultDataViewDefaultResponse(rsp) -} - -// SetDefaultDatailViewDefaultWithBodyWithResponse request with arbitrary body returning *SetDefaultDatailViewDefaultResponse -func (c *ClientWithResponses) SetDefaultDatailViewDefaultWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) { - rsp, err := c.SetDefaultDatailViewDefaultWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseSetDefaultDatailViewDefaultResponse(rsp) -} - -func (c *ClientWithResponses) SetDefaultDatailViewDefaultWithResponse(ctx context.Context, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) { - rsp, err := c.SetDefaultDatailViewDefault(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseSetDefaultDatailViewDefaultResponse(rsp) -} - // SwapDataViewsDefaultWithBodyWithResponse request with arbitrary body returning *SwapDataViewsDefaultResponse func (c *ClientWithResponses) SwapDataViewsDefaultWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SwapDataViewsDefaultResponse, error) { rsp, err := c.SwapDataViewsDefaultWithBody(ctx, contentType, body, reqEditors...) @@ -132710,6 +132698,32 @@ func (c *ClientWithResponses) UpdateDataViewDefaultWithResponse(ctx context.Cont return ParseUpdateDataViewDefaultResponse(rsp) } +// GetDefaultDataViewDefaultWithResponse request returning *GetDefaultDataViewDefaultResponse +func (c *ClientWithResponses) GetDefaultDataViewDefaultWithResponse(ctx context.Context, spaceId SpaceId, reqEditors ...RequestEditorFn) (*GetDefaultDataViewDefaultResponse, error) { + rsp, err := c.GetDefaultDataViewDefault(ctx, spaceId, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetDefaultDataViewDefaultResponse(rsp) +} + +// SetDefaultDatailViewDefaultWithBodyWithResponse request with arbitrary body returning *SetDefaultDatailViewDefaultResponse +func (c *ClientWithResponses) SetDefaultDatailViewDefaultWithBodyWithResponse(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) { + rsp, err := c.SetDefaultDatailViewDefaultWithBody(ctx, spaceId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseSetDefaultDatailViewDefaultResponse(rsp) +} + +func (c *ClientWithResponses) SetDefaultDatailViewDefaultWithResponse(ctx context.Context, spaceId SpaceId, body SetDefaultDatailViewDefaultJSONRequestBody, reqEditors ...RequestEditorFn) (*SetDefaultDatailViewDefaultResponse, error) { + rsp, err := c.SetDefaultDatailViewDefault(ctx, spaceId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseSetDefaultDatailViewDefaultResponse(rsp) +} + // PostMaintenanceWindowWithBodyWithResponse request with arbitrary body returning *PostMaintenanceWindowResponse func (c *ClientWithResponses) PostMaintenanceWindowWithBodyWithResponse(ctx context.Context, spaceId SpaceId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostMaintenanceWindowResponse, error) { rsp, err := c.PostMaintenanceWindowWithBody(ctx, spaceId, contentType, body, reqEditors...) @@ -137632,76 +137646,6 @@ func ParseUpdateRuntimeFieldDefaultResponse(rsp *http.Response) (*UpdateRuntimeF return response, nil } -// ParseGetDefaultDataViewDefaultResponse parses an HTTP response from a GetDefaultDataViewDefaultWithResponse call -func ParseGetDefaultDataViewDefaultResponse(rsp *http.Response) (*GetDefaultDataViewDefaultResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetDefaultDataViewDefaultResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - DataViewId *string `json:"data_view_id,omitempty"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest DataViews400Response - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - } - - return response, nil -} - -// ParseSetDefaultDatailViewDefaultResponse parses an HTTP response from a SetDefaultDatailViewDefaultWithResponse call -func ParseSetDefaultDatailViewDefaultResponse(rsp *http.Response) (*SetDefaultDatailViewDefaultResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &SetDefaultDatailViewDefaultResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Acknowledged *bool `json:"acknowledged,omitempty"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest DataViews400Response - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - } - - return response, nil -} - // ParseSwapDataViewsDefaultResponse parses an HTTP response from a SwapDataViewsDefaultWithResponse call func ParseSwapDataViewsDefaultResponse(rsp *http.Response) (*SwapDataViewsDefaultResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -153316,6 +153260,76 @@ func ParseUpdateDataViewDefaultResponse(rsp *http.Response) (*UpdateDataViewDefa return response, nil } +// ParseGetDefaultDataViewDefaultResponse parses an HTTP response from a GetDefaultDataViewDefaultWithResponse call +func ParseGetDefaultDataViewDefaultResponse(rsp *http.Response) (*GetDefaultDataViewDefaultResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetDefaultDataViewDefaultResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + DataViewId *string `json:"data_view_id,omitempty"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest DataViews400Response + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + + return response, nil +} + +// ParseSetDefaultDatailViewDefaultResponse parses an HTTP response from a SetDefaultDatailViewDefaultWithResponse call +func ParseSetDefaultDatailViewDefaultResponse(rsp *http.Response) (*SetDefaultDatailViewDefaultResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &SetDefaultDatailViewDefaultResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Acknowledged *bool `json:"acknowledged,omitempty"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest DataViews400Response + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + + return response, nil +} + // ParsePostMaintenanceWindowResponse parses an HTTP response from a PostMaintenanceWindowWithResponse call func ParsePostMaintenanceWindowResponse(rsp *http.Response) (*PostMaintenanceWindowResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/generated/kbapi/transform_schema.go b/generated/kbapi/transform_schema.go index 962151838..1e6a3e237 100644 --- a/generated/kbapi/transform_schema.go +++ b/generated/kbapi/transform_schema.go @@ -690,6 +690,7 @@ func transformKibanaPaths(schema *Schema) { "/api/maintenance_window/{id}", "/api/actions/connector/{id}", "/api/actions/connectors", + "/api/data_views/default", } // Add a spaceId parameter if not already present diff --git a/internal/clients/kibana_oapi/data_views.go b/internal/clients/kibana_oapi/data_views.go index 1126a73cc..00aca6f13 100644 --- a/internal/clients/kibana_oapi/data_views.go +++ b/internal/clients/kibana_oapi/data_views.go @@ -87,3 +87,36 @@ func DeleteDataView(ctx context.Context, client *Client, spaceID string, viewID return reportUnknownError(resp.StatusCode(), resp.Body) } } + +// GetDefaultDataView reads the default data view from the API. +func GetDefaultDataView(ctx context.Context, client *Client, spaceID string) (*string, diag.Diagnostics) { + resp, err := client.API.GetDefaultDataViewDefaultWithResponse(ctx, spaceID) + if err != nil { + return nil, diagutil.FrameworkDiagFromError(err) + } + + switch resp.StatusCode() { + case http.StatusOK: + if resp.JSON200 != nil && resp.JSON200.DataViewId != nil && *resp.JSON200.DataViewId != "" { + return resp.JSON200.DataViewId, nil + } + return nil, nil + default: + return nil, reportUnknownError(resp.StatusCode(), resp.Body) + } +} + +// SetDefaultDataView sets the default data view. +func SetDefaultDataView(ctx context.Context, client *Client, spaceID string, req kbapi.SetDefaultDatailViewDefaultJSONRequestBody) diag.Diagnostics { + resp, err := client.API.SetDefaultDatailViewDefaultWithResponse(ctx, spaceID, req) + if err != nil { + return diagutil.FrameworkDiagFromError(err) + } + + switch resp.StatusCode() { + case http.StatusOK: + return nil + default: + return reportUnknownError(resp.StatusCode(), resp.Body) + } +} diff --git a/internal/kibana/default_data_view/acc_test.go b/internal/kibana/default_data_view/acc_test.go new file mode 100644 index 000000000..1ccb316b6 --- /dev/null +++ b/internal/kibana/default_data_view/acc_test.go @@ -0,0 +1,129 @@ +package default_data_view_test + +import ( + "embed" + "testing" + + "github.com/elastic/terraform-provider-elasticstack/internal/acctest" + "github.com/elastic/terraform-provider-elasticstack/internal/versionutils" + "github.com/hashicorp/go-version" + "github.com/hashicorp/terraform-plugin-testing/config" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +//go:embed test_data/*.tf +var testDataFS embed.FS + +var minDataViewAPISupport = version.Must(version.NewVersion("8.1.0")) + +// loadTestData reads and returns the content of a test data file +func loadTestData(filename string) string { + data, err := testDataFS.ReadFile("test_data/" + filename) + if err != nil { + panic("Failed to load test data file: " + filename + " - " + err.Error()) + } + return string(data) +} + +func TestAccResourceDefaultDataView(t *testing.T) { + indexName1 := "my-index-" + sdkacctest.RandStringFromCharSet(4, sdkacctest.CharSetAlphaNum) + indexName2 := "my-other-index-" + sdkacctest.RandStringFromCharSet(4, sdkacctest.CharSetAlphaNum) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.Providers, + Steps: []resource.TestStep{ + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minDataViewAPISupport), + Config: loadTestData("basic.tf"), + ConfigVariables: config.Variables{ + "index_name": config.StringVariable(indexName1), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "id", "default"), + resource.TestCheckResourceAttrSet("elasticstack_kibana_default_data_view.test", "data_view_id"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "force", "true"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "skip_delete", "false"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "space_id", "default"), + ), + }, + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minDataViewAPISupport), + Config: loadTestData("update.tf"), + ConfigVariables: config.Variables{ + "index_name1": config.StringVariable(indexName1), + "index_name2": config.StringVariable(indexName2), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "id", "default"), + resource.TestCheckResourceAttrSet("elasticstack_kibana_default_data_view.test", "data_view_id"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "space_id", "default"), + ), + }, + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minDataViewAPISupport), + Config: loadTestData("unset.tf"), + ConfigVariables: config.Variables{ + "index_name1": config.StringVariable(indexName1), + "index_name2": config.StringVariable(indexName2), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "id", "default"), + resource.TestCheckNoResourceAttr("elasticstack_kibana_default_data_view.test", "data_view_id"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "space_id", "default"), + ), + }, + }, + }) +} + +func TestAccResourceDefaultDataViewWithSkipDelete(t *testing.T) { + indexName := "my-index-" + sdkacctest.RandStringFromCharSet(4, sdkacctest.CharSetAlphaNum) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.Providers, + Steps: []resource.TestStep{ + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minDataViewAPISupport), + Config: loadTestData("skip_delete.tf"), + ConfigVariables: config.Variables{ + "index_name": config.StringVariable(indexName), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "id", "default"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "skip_delete", "true"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "space_id", "default"), + ), + }, + }, + }) +} + +func TestAccResourceDefaultDataViewWithCustomSpace(t *testing.T) { + indexName := "my-index-" + sdkacctest.RandStringFromCharSet(4, sdkacctest.CharSetAlphaNum) + spaceID := "test-space-" + sdkacctest.RandStringFromCharSet(6, sdkacctest.CharSetAlphaNum) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.Providers, + Steps: []resource.TestStep{ + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minDataViewAPISupport), + Config: loadTestData("custom_space.tf"), + ConfigVariables: config.Variables{ + "index_name": config.StringVariable(indexName), + "space_id": config.StringVariable(spaceID), + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "id", spaceID), + resource.TestCheckResourceAttrSet("elasticstack_kibana_default_data_view.test", "data_view_id"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "force", "true"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "skip_delete", "false"), + resource.TestCheckResourceAttr("elasticstack_kibana_default_data_view.test", "space_id", spaceID), + ), + }, + }, + }) +} diff --git a/internal/kibana/default_data_view/create.go b/internal/kibana/default_data_view/create.go new file mode 100644 index 000000000..2f04767a3 --- /dev/null +++ b/internal/kibana/default_data_view/create.go @@ -0,0 +1,51 @@ +package default_data_view + +import ( + "context" + + "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" + "github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana_oapi" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func (r *DefaultDataViewResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + resp.Diagnostics.Append(r.setDefaultDataView(ctx, req.Plan, &resp.State)...) +} + +// setDefaultDataView is a helper method that contains the core logic for setting the default data view. +func (r *DefaultDataViewResource) setDefaultDataView(ctx context.Context, plan tfsdk.Plan, state *tfsdk.State) diag.Diagnostics { + var model defaultDataViewModel + diags := plan.Get(ctx, &model) + if diags.HasError() { + return diags + } + + client, err := r.client.GetKibanaOapiClient() + if err != nil { + diags.AddError("unable to get kibana client", err.Error()) + return diags + } + + dataViewID := model.DataViewID.ValueStringPointer() + force := model.Force.ValueBool() + spaceID := model.SpaceID.ValueString() + setReq := kbapi.SetDefaultDatailViewDefaultJSONRequestBody{ + DataViewId: dataViewID, + Force: &force, + } + + apiDiags := kibana_oapi.SetDefaultDataView(ctx, client, spaceID, setReq) + diags.Append(apiDiags...) + if diags.HasError() { + return diags + } + + // Use the space_id as the resource ID + model.ID = types.StringValue(spaceID) + + diags = state.Set(ctx, model) + return diags +} diff --git a/internal/kibana/default_data_view/delete.go b/internal/kibana/default_data_view/delete.go new file mode 100644 index 000000000..bc32c0ebd --- /dev/null +++ b/internal/kibana/default_data_view/delete.go @@ -0,0 +1,40 @@ +package default_data_view + +import ( + "context" + + "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" + "github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana_oapi" + "github.com/elastic/terraform-provider-elasticstack/internal/utils" + "github.com/hashicorp/terraform-plugin-framework/resource" +) + +func (r *DefaultDataViewResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state defaultDataViewModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + // If skip_delete is true, leave the default data view unchanged + if state.SkipDelete.ValueBool() { + return + } + + client, err := r.client.GetKibanaOapiClient() + if err != nil { + resp.Diagnostics.AddError("unable to get kibana client", err.Error()) + return + } + + spaceID := state.SpaceID.ValueString() + + // Unset the default data view by setting it to null + setReq := kbapi.SetDefaultDatailViewDefaultJSONRequestBody{ + Force: utils.Pointer(true), + } + + diags = kibana_oapi.SetDefaultDataView(ctx, client, spaceID, setReq) + resp.Diagnostics.Append(diags...) +} diff --git a/internal/kibana/default_data_view/models.go b/internal/kibana/default_data_view/models.go new file mode 100644 index 000000000..f1dc34c65 --- /dev/null +++ b/internal/kibana/default_data_view/models.go @@ -0,0 +1,13 @@ +package default_data_view + +import ( + "github.com/hashicorp/terraform-plugin-framework/types" +) + +type defaultDataViewModel struct { + ID types.String `tfsdk:"id"` + DataViewID types.String `tfsdk:"data_view_id"` + Force types.Bool `tfsdk:"force"` + SkipDelete types.Bool `tfsdk:"skip_delete"` + SpaceID types.String `tfsdk:"space_id"` +} diff --git a/internal/kibana/default_data_view/read.go b/internal/kibana/default_data_view/read.go new file mode 100644 index 000000000..2ebbdd2cf --- /dev/null +++ b/internal/kibana/default_data_view/read.go @@ -0,0 +1,40 @@ +package default_data_view + +import ( + "context" + + "github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana_oapi" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func (r *DefaultDataViewResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state defaultDataViewModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + client, err := r.client.GetKibanaOapiClient() + if err != nil { + resp.Diagnostics.AddError("unable to get kibana client", err.Error()) + return + } + + spaceID := state.SpaceID.ValueString() + defaultDataViewID, diags := kibana_oapi.GetDefaultDataView(ctx, client, spaceID) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + // Update state with current default data view + state.DataViewID = types.StringPointerValue(defaultDataViewID) + + // Use the space_id as the resource ID + state.ID = types.StringValue(spaceID) + + diags = resp.State.Set(ctx, state) + resp.Diagnostics.Append(diags...) +} diff --git a/internal/kibana/default_data_view/resource.go b/internal/kibana/default_data_view/resource.go new file mode 100644 index 000000000..dd5d262a0 --- /dev/null +++ b/internal/kibana/default_data_view/resource.go @@ -0,0 +1,33 @@ +package default_data_view + +import ( + "context" + "fmt" + + "github.com/elastic/terraform-provider-elasticstack/internal/clients" + "github.com/hashicorp/terraform-plugin-framework/resource" +) + +var ( + _ resource.Resource = &DefaultDataViewResource{} + _ resource.ResourceWithConfigure = &DefaultDataViewResource{} +) + +// NewResource is a helper function to simplify the provider implementation. +func NewResource() resource.Resource { + return &DefaultDataViewResource{} +} + +type DefaultDataViewResource struct { + client *clients.ApiClient +} + +func (r *DefaultDataViewResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + client, diags := clients.ConvertProviderData(req.ProviderData) + resp.Diagnostics.Append(diags...) + r.client = client +} + +func (r *DefaultDataViewResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = fmt.Sprintf("%s_%s", req.ProviderTypeName, "kibana_default_data_view") +} diff --git a/internal/kibana/default_data_view/schema.go b/internal/kibana/default_data_view/schema.go new file mode 100644 index 000000000..c7603f80c --- /dev/null +++ b/internal/kibana/default_data_view/schema.go @@ -0,0 +1,59 @@ +package default_data_view + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +func (r *DefaultDataViewResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = getSchema() +} + +func getSchema() schema.Schema { + return schema.Schema{ + MarkdownDescription: "Manages the default Kibana data view. See the [Kibana Data Views API documentation](https://www.elastic.co/docs/api/doc/kibana/v8/operation/operation-setdefaultdatailviewdefault) for more information.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Internal identifier of the resource.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "data_view_id": schema.StringAttribute{ + MarkdownDescription: "The data view identifier to set as default. NOTE: The API does not validate whether it is a valid identifier. Leave this unset (or explicitly `null`) to unset the default data view.", + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + }, + }, + "force": schema.BoolAttribute{ + MarkdownDescription: "Update an existing default data view identifier. If set to false and a default data view already exists, the operation will fail.", + Optional: true, + }, + "skip_delete": schema.BoolAttribute{ + MarkdownDescription: "If set to true, the default data view will not be unset when the resource is destroyed. The existing default data view will remain unchanged.", + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, + "space_id": schema.StringAttribute{ + MarkdownDescription: "The Kibana space ID to set the default data view in. Defaults to `default`.", + Optional: true, + Computed: true, + Default: stringdefault.StaticString("default"), + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + }, + } +} diff --git a/internal/kibana/default_data_view/test_data/basic.tf b/internal/kibana/default_data_view/test_data/basic.tf new file mode 100644 index 000000000..1f3ab00dc --- /dev/null +++ b/internal/kibana/default_data_view/test_data/basic.tf @@ -0,0 +1,26 @@ +variable "index_name" { + description = "The name of the Elasticsearch index" + type = string +} + +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_elasticsearch_index" "my_index" { + name = var.index_name + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "dv" { + data_view = { + title = "${var.index_name}*" + } + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_default_data_view" "test" { + data_view_id = elasticstack_kibana_data_view.dv.data_view.id + force = true +} \ No newline at end of file diff --git a/internal/kibana/default_data_view/test_data/custom_space.tf b/internal/kibana/default_data_view/test_data/custom_space.tf new file mode 100644 index 000000000..10878d9e3 --- /dev/null +++ b/internal/kibana/default_data_view/test_data/custom_space.tf @@ -0,0 +1,39 @@ +variable "index_name" { + description = "The name of the Elasticsearch index" + type = string +} + +variable "space_id" { + description = "The ID of the Kibana space" + type = string +} + +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_kibana_space" "test_space" { + space_id = var.space_id + name = "Test Space ${var.space_id}" + description = "Test space for default data view" +} + +resource "elasticstack_elasticsearch_index" "my_index" { + name = var.index_name + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "dv" { + space_id = elasticstack_kibana_space.test_space.space_id + data_view = { + title = "${var.index_name}*" + } + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_default_data_view" "test" { + space_id = elasticstack_kibana_space.test_space.space_id + data_view_id = elasticstack_kibana_data_view.dv.data_view.id + force = true +} \ No newline at end of file diff --git a/internal/kibana/default_data_view/test_data/skip_delete.tf b/internal/kibana/default_data_view/test_data/skip_delete.tf new file mode 100644 index 000000000..9f7fba451 --- /dev/null +++ b/internal/kibana/default_data_view/test_data/skip_delete.tf @@ -0,0 +1,27 @@ +variable "index_name" { + description = "The name of the Elasticsearch index" + type = string +} + +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_elasticsearch_index" "my_index" { + name = var.index_name + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "dv" { + data_view = { + title = "${var.index_name}*" + } + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_default_data_view" "test" { + data_view_id = elasticstack_kibana_data_view.dv.data_view.id + force = true + skip_delete = true +} \ No newline at end of file diff --git a/internal/kibana/default_data_view/test_data/unset.tf b/internal/kibana/default_data_view/test_data/unset.tf new file mode 100644 index 000000000..3f469ded0 --- /dev/null +++ b/internal/kibana/default_data_view/test_data/unset.tf @@ -0,0 +1,42 @@ +variable "index_name1" { + description = "The name of the first Elasticsearch index" + type = string +} + +variable "index_name2" { + description = "The name of the second Elasticsearch index" + type = string +} + +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_elasticsearch_index" "my_index" { + name = var.index_name1 + deletion_protection = false +} + +resource "elasticstack_elasticsearch_index" "my_other_index" { + name = var.index_name2 + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "dv" { + data_view = { + title = "${var.index_name1}*" + } + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_data_view" "dv2" { + data_view = { + title = "${var.index_name2}*" + } + depends_on = [elasticstack_elasticsearch_index.my_other_index] +} + +resource "elasticstack_kibana_default_data_view" "test" { + force = true +} \ No newline at end of file diff --git a/internal/kibana/default_data_view/test_data/update.tf b/internal/kibana/default_data_view/test_data/update.tf new file mode 100644 index 000000000..53cd380a4 --- /dev/null +++ b/internal/kibana/default_data_view/test_data/update.tf @@ -0,0 +1,43 @@ +variable "index_name1" { + description = "The name of the first Elasticsearch index" + type = string +} + +variable "index_name2" { + description = "The name of the second Elasticsearch index" + type = string +} + +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_elasticsearch_index" "my_index" { + name = var.index_name1 + deletion_protection = false +} + +resource "elasticstack_elasticsearch_index" "my_other_index" { + name = var.index_name2 + deletion_protection = false +} + +resource "elasticstack_kibana_data_view" "dv" { + data_view = { + title = "${var.index_name1}*" + } + depends_on = [elasticstack_elasticsearch_index.my_index] +} + +resource "elasticstack_kibana_data_view" "dv2" { + data_view = { + title = "${var.index_name2}*" + } + depends_on = [elasticstack_elasticsearch_index.my_other_index] +} + +resource "elasticstack_kibana_default_data_view" "test" { + data_view_id = elasticstack_kibana_data_view.dv2.data_view.id + force = true +} \ No newline at end of file diff --git a/internal/kibana/default_data_view/update.go b/internal/kibana/default_data_view/update.go new file mode 100644 index 000000000..49d327384 --- /dev/null +++ b/internal/kibana/default_data_view/update.go @@ -0,0 +1,11 @@ +package default_data_view + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource" +) + +func (r *DefaultDataViewResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.Append(r.setDefaultDataView(ctx, req.Plan, &resp.State)...) +} diff --git a/provider/plugin_framework.go b/provider/plugin_framework.go index 47a51ea2c..5c95d3792 100644 --- a/provider/plugin_framework.go +++ b/provider/plugin_framework.go @@ -23,6 +23,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/internal/fleet/server_host" "github.com/elastic/terraform-provider-elasticstack/internal/kibana/connectors" "github.com/elastic/terraform-provider-elasticstack/internal/kibana/data_view" + "github.com/elastic/terraform-provider-elasticstack/internal/kibana/default_data_view" "github.com/elastic/terraform-provider-elasticstack/internal/kibana/export_saved_objects" "github.com/elastic/terraform-provider-elasticstack/internal/kibana/import_saved_objects" "github.com/elastic/terraform-provider-elasticstack/internal/kibana/maintenance_window" @@ -104,6 +105,7 @@ func (p *Provider) Resources(ctx context.Context) []func() resource.Resource { agent_configuration.NewAgentConfigurationResource, func() resource.Resource { return &import_saved_objects.Resource{} }, data_view.NewResource, + default_data_view.NewResource, func() resource.Resource { return ¶meter.Resource{} }, func() resource.Resource { return &private_location.Resource{} }, func() resource.Resource { return &index.Resource{} },