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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
- Migrate `elasticstack_kibana_action_connector` to the Terraform plugin framework ([#1269](https://github.com/elastic/terraform-provider-elasticstack/pull/1269))
- Migrate `elasticstack_elasticsearch_security_role_mapping` resource and data source to Terraform Plugin Framework ([#1279](https://github.com/elastic/terraform-provider-elasticstack/pull/1279))
- Add support for `inactivity_timeout` in `elasticstack_fleet_agent_policy` ([#641](https://github.com/elastic/terraform-provider-elasticstack/issues/641))
- [Refactor] Regenerate the SLO client using the current OpenAPI spec ([#1303](https://github.com/elastic/terraform-provider-elasticstack/pull/1303))
- Add support for `data_view_id` in the `elasticstack_kibana_slo` resource ([#1305](https://github.com/elastic/terraform-provider-elasticstack/pull/1305))

## [0.11.17] - 2025-07-21

Expand Down
4 changes: 4 additions & 0 deletions docs/resources/kibana_slo.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ Required:

Optional:

- `data_view_id` (String) Optional data view id to use for this indicator.
- `filter` (String)
- `timestamp_field` (String)

Expand Down Expand Up @@ -366,6 +367,7 @@ Required:

Optional:

- `data_view_id` (String) Optional data view id to use for this indicator.
- `filter` (String)
- `good` (String)
- `timestamp_field` (String)
Expand All @@ -383,6 +385,7 @@ Required:

Optional:

- `data_view_id` (String) Optional data view id to use for this indicator.
- `filter` (String)
- `timestamp_field` (String)

Expand Down Expand Up @@ -453,6 +456,7 @@ Required:

Optional:

- `data_view_id` (String) Optional data view id to use for this indicator.
- `filter` (String)

<a id="nestedblock--timeslice_metric_indicator--metric"></a>
Expand Down
16 changes: 12 additions & 4 deletions internal/clients/kibana/slo.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ func GetSlo(ctx context.Context, apiClient *clients.ApiClient, id, spaceID strin
return nil, nil
}
if err != nil {
return nil, diag.FromErr(err)
diags := diag.FromErr(err)
diags = append(diags, utils.CheckHttpError(res, "unable to create slo with id "+id)...)
return nil, diags
}

defer res.Body.Close()
Expand All @@ -46,7 +48,9 @@ func DeleteSlo(ctx context.Context, apiClient *clients.ApiClient, sloId string,
req := client.DeleteSloOp(ctxWithAuth, sloId, spaceId).KbnXsrf("true")
res, err := req.Execute()
if err != nil && res == nil {
return diag.FromErr(err)
diags := diag.FromErr(err)
diags = append(diags, utils.CheckHttpError(res, "unable to create slo with id "+sloId)...)
return diags
}

defer res.Body.Close()
Expand Down Expand Up @@ -80,7 +84,9 @@ func UpdateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo,
_, res, err := req.Execute()

if err != nil {
return nil, diag.FromErr(err)
diags := diag.FromErr(err)
diags = append(diags, utils.CheckHttpError(res, "unable to create slo with id "+s.SloID)...)
return nil, diags
}

defer res.Body.Close()
Expand Down Expand Up @@ -122,7 +128,9 @@ func CreateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo,
req := client.CreateSloOp(ctxWithAuth, s.SpaceID).KbnXsrf("true").CreateSloRequest(reqModel)
sloRes, res, err := req.Execute()
if err != nil {
return nil, diag.FromErr(err)
diags := diag.FromErr(err)
diags = append(diags, utils.CheckHttpError(res, "unable to create slo with id "+s.SloID)...)
return nil, diags
}
defer res.Body.Close()

Expand Down
82 changes: 72 additions & 10 deletions internal/kibana/slo.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var SLOSupportsMultipleGroupByMinVersion = version.Must(version.NewVersion("8.14.0"))
var (
SLOSupportsMultipleGroupByMinVersion = version.Must(version.NewVersion("8.14.0"))
SLOSupportsDataViewIDMinVersion = version.Must(version.NewVersion("8.15.0"))
)

func ResourceSlo() *schema.Resource {
return &schema.Resource{
Expand Down Expand Up @@ -114,6 +117,11 @@ func getSchema() map[string]*schema.Schema {
Type: schema.TypeString,
Required: true,
},
"data_view_id": {
Type: schema.TypeString,
Optional: true,
Description: "Optional data view id to use for this indicator.",
},
"filter": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -215,6 +223,11 @@ func getSchema() map[string]*schema.Schema {
Type: schema.TypeString,
Required: true,
},
"data_view_id": {
Type: schema.TypeString,
Optional: true,
Description: "Optional data view id to use for this indicator.",
},
"filter": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -375,6 +388,11 @@ func getSchema() map[string]*schema.Schema {
Type: schema.TypeString,
Required: true,
},
"data_view_id": {
Type: schema.TypeString,
Optional: true,
Description: "Optional data view id to use for this indicator.",
},
"filter": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -408,6 +426,11 @@ func getSchema() map[string]*schema.Schema {
Type: schema.TypeString,
Required: true,
},
"data_view_id": {
Type: schema.TypeString,
Optional: true,
Description: "Optional data view id to use for this indicator.",
},
"timestamp_field": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -609,7 +632,8 @@ func getSloFromResourceData(d *schema.ResourceData) (models.Slo, diag.Diagnostic
IndicatorPropertiesCustomKql: &slo.IndicatorPropertiesCustomKql{
Type: indicatorAddressToType[indicatorType],
Params: slo.IndicatorPropertiesCustomKqlParams{
Index: d.Get(indicatorType + ".0.index").(string),
Index: d.Get(indicatorType + ".0.index").(string),
DataViewId: getOrNil[string](indicatorType+".0.data_view_id", d),
Filter: transformOrNil[slo.KqlWithFilters](
indicatorType+".0.filter", d,
func(v interface{}) slo.KqlWithFilters {
Expand Down Expand Up @@ -666,6 +690,7 @@ func getSloFromResourceData(d *schema.ResourceData) (models.Slo, diag.Diagnostic
Params: slo.IndicatorPropertiesHistogramParams{
Filter: getOrNil[string](indicatorType+".0.filter", d),
Index: d.Get(indicatorType + ".0.index").(string),
DataViewId: getOrNil[string](indicatorType+".0.data_view_id", d),
TimestampField: d.Get(indicatorType + ".0.timestamp_field").(string),
Good: slo.IndicatorPropertiesHistogramParamsGood{
Field: d.Get(indicatorType + ".0.good.0.field").(string),
Expand Down Expand Up @@ -714,6 +739,7 @@ func getSloFromResourceData(d *schema.ResourceData) (models.Slo, diag.Diagnostic
Params: slo.IndicatorPropertiesCustomMetricParams{
Filter: getOrNil[string](indicatorType+".0.filter", d),
Index: d.Get(indicatorType + ".0.index").(string),
DataViewId: getOrNil[string](indicatorType+".0.data_view_id", d),
TimestampField: d.Get(indicatorType + ".0.timestamp_field").(string),
Good: slo.IndicatorPropertiesCustomMetricParamsGood{
Equation: d.Get(indicatorType + ".0.good.0.equation").(string),
Expand Down Expand Up @@ -769,6 +795,7 @@ func getSloFromResourceData(d *schema.ResourceData) (models.Slo, diag.Diagnostic
Type: indicatorAddressToType[indicatorType],
Params: slo.IndicatorPropertiesTimesliceMetricParams{
Index: params["index"].(string),
DataViewId: getOrNil[string]("timeslice_metric_indicator.0.data_view_id", d),
TimestampField: params["timestamp_field"].(string),
Filter: getOrNil[string]("timeslice_metric_indicator.0.filter", d),
Metric: slo.IndicatorPropertiesTimesliceMetricParamsMetric{
Expand Down Expand Up @@ -850,6 +877,16 @@ func resourceSloCreate(ctx context.Context, d *schema.ResourceData, meta interfa
return diags
}

// Version check for data_view_id support
if !serverVersion.GreaterThanOrEqual(SLOSupportsDataViewIDMinVersion) {
// Check all indicator types that support data_view_id
for _, indicatorType := range []string{"metric_custom_indicator", "histogram_custom_indicator", "kql_custom_indicator", "timeslice_metric_indicator"} {
if v, ok := d.GetOk(indicatorType + ".0.data_view_id"); ok && v != "" {
return diag.Errorf("data_view_id is not supported for %s on Elastic Stack versions < %s", indicatorType, SLOSupportsDataViewIDMinVersion)
}
}
}

supportsMultipleGroupBy := serverVersion.GreaterThanOrEqual(SLOSupportsMultipleGroupByMinVersion)
if len(slo.GroupBy) > 1 && !supportsMultipleGroupBy {
return diag.Errorf("multiple group_by fields are not supported in this version of the Elastic Stack. Multiple group_by fields requires %s", SLOSupportsMultipleGroupByMinVersion)
Expand Down Expand Up @@ -882,6 +919,15 @@ func resourceSloUpdate(ctx context.Context, d *schema.ResourceData, meta interfa
return diags
}

// Version check for data_view_id support
if !serverVersion.GreaterThanOrEqual(SLOSupportsDataViewIDMinVersion) {
for _, indicatorType := range []string{"metric_custom_indicator", "histogram_custom_indicator", "kql_custom_indicator", "timeslice_metric_indicator"} {
if v, ok := d.GetOk(indicatorType + ".0.data_view_id"); ok && v != "" {
return diag.Errorf("data_view_id is not supported for %s on Elastic Stack versions < %s", indicatorType, SLOSupportsDataViewIDMinVersion)
}
}
}

supportsMultipleGroupBy := serverVersion.GreaterThanOrEqual(SLOSupportsMultipleGroupByMinVersion)
if len(slo.GroupBy) > 1 && !supportsMultipleGroupBy {
return diag.Errorf("multiple group_by fields are not supported in this version of the Elastic Stack. Multiple group_by fields requires %s", SLOSupportsMultipleGroupByMinVersion)
Expand Down Expand Up @@ -950,13 +996,17 @@ func resourceSloRead(ctx context.Context, d *schema.ResourceData, meta interface
case s.Indicator.IndicatorPropertiesCustomKql != nil:
indicatorAddress = indicatorTypeToAddress[s.Indicator.IndicatorPropertiesCustomKql.Type]
params := s.Indicator.IndicatorPropertiesCustomKql.Params
indicator = append(indicator, map[string]interface{}{
indicatorMap := map[string]interface{}{
"index": params.Index,
"filter": params.Filter.String,
"good": params.Good.String,
"total": params.Total.String,
"timestamp_field": params.TimestampField,
})
}
if params.DataViewId != nil {
indicatorMap["data_view_id"] = *params.DataViewId
}
indicator = append(indicator, indicatorMap)

case s.Indicator.IndicatorPropertiesHistogram != nil:
indicatorAddress = indicatorTypeToAddress[s.Indicator.IndicatorPropertiesHistogram.Type]
Expand All @@ -975,13 +1025,17 @@ func resourceSloRead(ctx context.Context, d *schema.ResourceData, meta interface
"from": params.Total.From,
"to": params.Total.To,
}}
indicator = append(indicator, map[string]interface{}{
indicatorMap := map[string]interface{}{
"index": params.Index,
"filter": params.Filter,
"timestamp_field": params.TimestampField,
"good": good,
"total": total,
})
}
if params.DataViewId != nil {
indicatorMap["data_view_id"] = *params.DataViewId
}
indicator = append(indicator, indicatorMap)

case s.Indicator.IndicatorPropertiesCustomMetric != nil:
indicatorAddress = indicatorTypeToAddress[s.Indicator.IndicatorPropertiesCustomMetric.Type]
Expand Down Expand Up @@ -1012,13 +1066,17 @@ func resourceSloRead(ctx context.Context, d *schema.ResourceData, meta interface
"equation": params.Total.Equation,
"metrics": totalMetrics,
}}
indicator = append(indicator, map[string]interface{}{
indicatorMap := map[string]interface{}{
"index": params.Index,
"filter": params.Filter,
"timestamp_field": params.TimestampField,
"good": good,
"total": total,
})
}
if params.DataViewId != nil {
indicatorMap["data_view_id"] = *params.DataViewId
}
indicator = append(indicator, indicatorMap)

case s.Indicator.IndicatorPropertiesTimesliceMetric != nil:
indicatorAddress = indicatorTypeToAddress[s.Indicator.IndicatorPropertiesTimesliceMetric.Type]
Expand Down Expand Up @@ -1049,12 +1107,16 @@ func resourceSloRead(ctx context.Context, d *schema.ResourceData, meta interface
"comparator": params.Metric.Comparator,
"threshold": params.Metric.Threshold,
}
indicator = append(indicator, map[string]interface{}{
indicatorMap := map[string]interface{}{
"index": params.Index,
"timestamp_field": params.TimestampField,
"filter": params.Filter,
"metric": []interface{}{metricBlock},
})
}
if params.DataViewId != nil {
indicatorMap["data_view_id"] = *params.DataViewId
}
indicator = append(indicator, indicatorMap)

default:
return diag.Errorf("indicator not set")
Expand Down
Loading
Loading