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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Prevent a provider panic when an `elasticstack_elasticsearch_template` or `elasticstack_elasticsearch_component_template` includes an empty `template` (`template {}`) block. ([#598](https://github.com/elastic/terraform-provider-elasticstack/pull/598))
- Prevent `elasticstack_kibana_space` to attempt the space recreation if `initials` and `color` are not provided. ([#606](https://github.com/elastic/terraform-provider-elasticstack/pull/606))
- Prevent a provider panic in `elasticstack_kibana_data_view` when a `field_format` does not include a `pattern`. ([#619](https://github.com/elastic/terraform-provider-elasticstack/pull/619/files))
- Fixed a bug where the `id` attribute for `elasticstack_kibana_slo` resources was ignored by renaming the attribute to `slo_id`. ([#622](https://github.com/elastic/terraform-provider-elasticstack/pull/622))

### Added

Expand Down
6 changes: 5 additions & 1 deletion docs/resources/kibana_slo.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,17 @@ resource "elasticstack_kibana_slo" "custom_metric" {
- `apm_latency_indicator` (Block List, Max: 1) (see [below for nested schema](#nestedblock--apm_latency_indicator))
- `group_by` (String) Optional group by field to use to generate an SLO per distinct value.
- `histogram_custom_indicator` (Block List, Max: 1) (see [below for nested schema](#nestedblock--histogram_custom_indicator))
- `id` (String) An ID (8 and 36 characters). If omitted, a UUIDv1 will be generated server-side.
- `kql_custom_indicator` (Block List, Max: 1) (see [below for nested schema](#nestedblock--kql_custom_indicator))
- `metric_custom_indicator` (Block List, Max: 1) (see [below for nested schema](#nestedblock--metric_custom_indicator))
- `settings` (Block List, Max: 1) The default settings should be sufficient for most users, but if needed, these properties can be overwritten. (see [below for nested schema](#nestedblock--settings))
- `slo_id` (String) An ID (8 and 36 characters). If omitted, a UUIDv1 will be generated server-side.
- `space_id` (String) An identifier for the space. If space_id is not provided, the default space is used.
- `tags` (List of String) The tags for the SLO.

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--objective"></a>
### Nested Schema for `objective`

Expand Down
2 changes: 1 addition & 1 deletion generated/slo/.openapi-generator/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.0.0-beta
7.0.1
12 changes: 12 additions & 0 deletions generated/slo/api_slo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion generated/slo/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions internal/clients/kibana/slo.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ func UpdateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo)
Tags: s.Tags,
}

req := client.UpdateSloOp(ctxWithAuth, s.SpaceID, s.ID).KbnXsrf("true").UpdateSloRequest(reqModel)
req := client.UpdateSloOp(ctxWithAuth, s.SpaceID, s.SloID).KbnXsrf("true").UpdateSloRequest(reqModel)
slo, res, err := req.Execute()

if err != nil {
return nil, diag.FromErr(err)
}

defer res.Body.Close()
if diags := utils.CheckHttpError(res, "unable to update slo with id "+s.ID); diags.HasError() {
if diags := utils.CheckHttpError(res, "unable to update slo with id "+s.SloID); diags.HasError() {
return nil, diags
}

Expand Down Expand Up @@ -112,18 +112,24 @@ func CreateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo)
GroupBy: s.GroupBy,
Tags: s.Tags,
}

// Explicitly set SLO object id if provided, otherwise we'll use the autogenerated ID from the Kibana API response
if s.SloID != "" {
reqModel.Id = &s.SloID
}

req := client.CreateSloOp(ctxWithAuth, s.SpaceID).KbnXsrf("true").CreateSloRequest(reqModel)
sloRes, res, err := req.Execute()
if err != nil {
return nil, diag.FromErr(err)
}
defer res.Body.Close()

if diags := utils.CheckHttpError(res, "unable to create slo with id "+s.ID); diags.HasError() {
if diags := utils.CheckHttpError(res, "unable to create slo with id "+s.SloID); diags.HasError() {
return nil, diags
}

s.ID = sloRes.Id
s.SloID = sloRes.Id

return &s, diag.Diagnostics{}
}
Expand Down Expand Up @@ -162,7 +168,7 @@ func sloResponseToModel(spaceID string, res *slo.SloResponse) *models.Slo {
}

return &models.Slo{
ID: res.Id,
SloID: res.Id,
SpaceID: spaceID,
Name: res.Name,
Description: res.Description,
Expand Down
8 changes: 6 additions & 2 deletions internal/clients/kibana/slo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ func Test_sloResponseToModel(t *testing.T) {
tests := []struct {
name string
spaceId string
sloId string
sloResponse *slo.SloResponse
expectedModel *models.Slo
}{
{
name: "should return a model with the correct values",
spaceId: "space-id",
sloId: "slo-id",
sloResponse: &slo.SloResponse{
Id: "slo-id",
Name: "slo-name",
Expand Down Expand Up @@ -50,7 +52,7 @@ func Test_sloResponseToModel(t *testing.T) {
UpdatedAt: "2023-08-11T00:05:36.567Z",
},
expectedModel: &models.Slo{
ID: "slo-id",
SloID: "slo-id",
Name: "slo-name",
Description: "slo-description",
Indicator: slo.SloResponseIndicator{
Expand Down Expand Up @@ -81,6 +83,7 @@ func Test_sloResponseToModel(t *testing.T) {
{
name: "should return tags if available",
spaceId: "space-id",
sloId: "slo-id",
sloResponse: &slo.SloResponse{
Id: "slo-id",
Name: "slo-name",
Expand Down Expand Up @@ -112,7 +115,7 @@ func Test_sloResponseToModel(t *testing.T) {
UpdatedAt: "2023-08-11T00:05:36.567Z",
},
expectedModel: &models.Slo{
ID: "slo-id",
SloID: "slo-id",
Name: "slo-name",
Description: "slo-description",
Indicator: slo.SloResponseIndicator{
Expand Down Expand Up @@ -144,6 +147,7 @@ func Test_sloResponseToModel(t *testing.T) {
{
name: "nil response should return a nil model",
spaceId: "space-id",
sloId: "slo-id",
sloResponse: nil,
expectedModel: nil,
},
Expand Down
25 changes: 12 additions & 13 deletions internal/kibana/slo.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ func ResourceSlo() *schema.Resource {
}

sloSchema := map[string]*schema.Schema{
"id": {
"slo_id": {
Description: "An ID (8 and 36 characters). If omitted, a UUIDv1 will be generated server-side.",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ForceNew: true,
},
"name": {
Description: "The name of the SLO.",
Expand Down Expand Up @@ -617,6 +617,11 @@ func getSloFromResourceData(d *schema.ResourceData) (models.Slo, diag.Diagnostic
GroupBy: getOrNilString("group_by", d),
}

// Explicitly set SLO object id if provided, otherwise we'll use the autogenerated ID from the Kibana API response
if sloID := getOrNilString("slo_id", d); sloID != nil && *sloID != "" {
slo.SloID = *sloID
}

if tags, ok := d.GetOk("tags"); ok {
for _, t := range tags.([]interface{}) {
slo.Tags = append(slo.Tags, t.(string))
Expand All @@ -643,8 +648,8 @@ func resourceSloCreate(ctx context.Context, d *schema.ResourceData, meta interfa
return diags
}

id := &clients.CompositeId{ClusterId: slo.SpaceID, ResourceId: res.ID}
d.SetId(id.String())
compositeID := &clients.CompositeId{ClusterId: slo.SpaceID, ResourceId: res.SloID}
d.SetId(compositeID.String())

return resourceSloRead(ctx, d, meta)
}
Expand All @@ -660,20 +665,14 @@ func resourceSloUpdate(ctx context.Context, d *schema.ResourceData, meta interfa
return diags
}

compId, diags := clients.CompositeIdFromStr(d.Id())
if diags.HasError() {
return diags
}
slo.ID = compId.ResourceId

res, diags := kibana.UpdateSlo(ctx, client, slo)

if diags.HasError() {
return diags
}

id := &clients.CompositeId{ClusterId: slo.SpaceID, ResourceId: res.ID}
d.SetId(id.String())
compositeID := &clients.CompositeId{ClusterId: slo.SpaceID, ResourceId: res.SloID}
d.SetId(compositeID.String())

return resourceSloRead(ctx, d, meta)
}
Expand Down Expand Up @@ -844,7 +843,7 @@ func resourceSloRead(ctx context.Context, d *schema.ResourceData, meta interface
}
}

if err := d.Set("id", s.ID); err != nil {
if err := d.Set("slo_id", s.SloID); err != nil {
return diag.FromErr(err)
}
if err := d.Set("space_id", s.SpaceID); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions internal/kibana/slo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func TestAccResourceSlo(t *testing.T) {
Config: getSLOConfig(sloName, "apm_latency_indicator", false, []string{}, ""),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_kibana_slo.test_slo", "name", sloName),
resource.TestCheckResourceAttr("elasticstack_kibana_slo.test_slo", "slo_id", "fully-sick-slo"),
resource.TestCheckResourceAttr("elasticstack_kibana_slo.test_slo", "description", "fully sick SLO"),
resource.TestCheckResourceAttr("elasticstack_kibana_slo.test_slo", "apm_latency_indicator.0.environment", "production"),
resource.TestCheckResourceAttr("elasticstack_kibana_slo.test_slo", "apm_latency_indicator.0.service", "my-service"),
Expand Down Expand Up @@ -292,6 +293,7 @@ func getSLOConfig(name string, indicatorType string, settingsEnabled bool, tags

resource "elasticstack_kibana_slo" "test_slo" {
name = "%s"
slo_id = "fully-sick-slo"
description = "fully sick SLO"

%s
Expand Down
2 changes: 1 addition & 1 deletion internal/models/slo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
)

type Slo struct {
ID string
SloID string
Name string
Description string
Indicator slo.SloResponseIndicator
Expand Down