Skip to content

Commit 2f93ca5

Browse files
committed
WIP
1 parent 7666df1 commit 2f93ca5

File tree

9 files changed

+351
-81
lines changed

9 files changed

+351
-81
lines changed

generated/slo-spec.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,14 @@ components:
13891389
$ref: '#/components/schemas/objective'
13901390
settings:
13911391
$ref: '#/components/schemas/settings'
1392+
groupBy:
1393+
description: optional group by field to use to generate an SLO per distinct value
1394+
oneOf:
1395+
- type: string
1396+
- type: array
1397+
items:
1398+
type: string
1399+
example: some.field
13921400
tags:
13931401
description: List of tags
13941402
type: array

generated/slo/api/openapi.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,8 @@ components:
13491349
$ref: '#/components/schemas/objective'
13501350
settings:
13511351
$ref: '#/components/schemas/settings'
1352+
groupBy:
1353+
$ref: '#/components/schemas/slo_response_groupBy'
13521354
tags:
13531355
description: List of tags
13541356
items:

generated/slo/docs/UpdateSloRequest.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Name | Type | Description | Notes
1111
**BudgetingMethod** | Pointer to [**BudgetingMethod**](BudgetingMethod.md) | | [optional]
1212
**Objective** | Pointer to [**Objective**](Objective.md) | | [optional]
1313
**Settings** | Pointer to [**Settings**](Settings.md) | | [optional]
14+
**GroupBy** | Pointer to [**SloResponseGroupBy**](SloResponseGroupBy.md) | | [optional]
1415
**Tags** | Pointer to **[]string** | List of tags | [optional]
1516

1617
## Methods
@@ -207,6 +208,31 @@ SetSettings sets Settings field to given value.
207208

208209
HasSettings returns a boolean if a field has been set.
209210

211+
### GetGroupBy
212+
213+
`func (o *UpdateSloRequest) GetGroupBy() SloResponseGroupBy`
214+
215+
GetGroupBy returns the GroupBy field if non-nil, zero value otherwise.
216+
217+
### GetGroupByOk
218+
219+
`func (o *UpdateSloRequest) GetGroupByOk() (*SloResponseGroupBy, bool)`
220+
221+
GetGroupByOk returns a tuple with the GroupBy field if it's non-nil, zero value otherwise
222+
and a boolean to check if the value has been set.
223+
224+
### SetGroupBy
225+
226+
`func (o *UpdateSloRequest) SetGroupBy(v SloResponseGroupBy)`
227+
228+
SetGroupBy sets GroupBy field to given value.
229+
230+
### HasGroupBy
231+
232+
`func (o *UpdateSloRequest) HasGroupBy() bool`
233+
234+
HasGroupBy returns a boolean if a field has been set.
235+
210236
### GetTags
211237

212238
`func (o *UpdateSloRequest) GetTags() []string`

generated/slo/model_slo_response_group_by.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

generated/slo/model_update_slo_request.go

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/clients/kibana/slo.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func DeleteSlo(ctx context.Context, apiClient *clients.ApiClient, sloId string,
5353
return utils.CheckHttpError(res, "Unabled to delete slo with ID "+string(sloId))
5454
}
5555

56-
func UpdateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo) (*models.Slo, diag.Diagnostics) {
56+
func UpdateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo, supportsGroupByList bool) (*models.Slo, diag.Diagnostics) {
5757
client, err := apiClient.GetSloClient()
5858
if err != nil {
5959
return nil, diag.FromErr(err)
@@ -72,6 +72,7 @@ func UpdateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo)
7272
BudgetingMethod: (*slo.BudgetingMethod)(&s.BudgetingMethod),
7373
Objective: &s.Objective,
7474
Settings: s.Settings,
75+
GroupBy: transformGroupBy(s.GroupBy, supportsGroupByList),
7576
Tags: s.Tags,
7677
}
7778

@@ -90,7 +91,7 @@ func UpdateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo)
9091
return sloResponseToModel(s.SpaceID, slo), diag.Diagnostics{}
9192
}
9293

93-
func CreateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo) (*models.Slo, diag.Diagnostics) {
94+
func CreateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo, supportsGroupByList bool) (*models.Slo, diag.Diagnostics) {
9495
client, err := apiClient.GetSloClient()
9596
if err != nil {
9697
return nil, diag.FromErr(err)
@@ -109,7 +110,7 @@ func CreateSlo(ctx context.Context, apiClient *clients.ApiClient, s models.Slo)
109110
BudgetingMethod: slo.BudgetingMethod(s.BudgetingMethod),
110111
Objective: s.Objective,
111112
Settings: s.Settings,
112-
GroupBy: transformGroupBy(s.GroupBy),
113+
GroupBy: transformGroupBy(s.GroupBy, supportsGroupByList),
113114
Tags: s.Tags,
114115
}
115116

@@ -177,14 +178,33 @@ func sloResponseToModel(spaceID string, res *slo.SloResponse) *models.Slo {
177178
TimeWindow: res.TimeWindow,
178179
Objective: res.Objective,
179180
Settings: &res.Settings,
181+
GroupBy: transformGroupByFromResponse(res.GroupBy),
180182
Tags: res.Tags,
181183
}
182184
}
183185

184-
func transformGroupBy(groupBy *string) *slo.SloResponseGroupBy {
186+
func transformGroupBy(groupBy []string, supportsGroupByList bool) *slo.SloResponseGroupBy {
185187
if groupBy == nil {
186188
return nil
187189
}
188190

189-
return &slo.SloResponseGroupBy{String: groupBy}
191+
if !supportsGroupByList && len(groupBy) > 0 {
192+
return &slo.SloResponseGroupBy{
193+
String: &groupBy[0],
194+
}
195+
}
196+
197+
return &slo.SloResponseGroupBy{ArrayOfString: &groupBy}
198+
}
199+
200+
func transformGroupByFromResponse(groupBy slo.SloResponseGroupBy) []string {
201+
if groupBy.String != nil {
202+
return []string{*groupBy.String}
203+
}
204+
205+
if groupBy.ArrayOfString == nil {
206+
return nil
207+
}
208+
209+
return *groupBy.ArrayOfString
190210
}

internal/kibana/slo.go

Lines changed: 93 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,77 @@ import (
99
"github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana"
1010
"github.com/elastic/terraform-provider-elasticstack/internal/models"
1111
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
12+
"github.com/hashicorp/go-version"
1213
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1314
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1415
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1516
)
1617

18+
var SLOSupportsMultipleGroupByMinVersion = version.Must(version.NewVersion("8.14.0"))
19+
1720
func ResourceSlo() *schema.Resource {
21+
return &schema.Resource{
22+
Description: "Creates an SLO.",
23+
24+
CreateContext: resourceSloCreate,
25+
UpdateContext: resourceSloUpdate,
26+
ReadContext: resourceSloRead,
27+
DeleteContext: resourceSloDelete,
28+
29+
Importer: &schema.ResourceImporter{
30+
StateContext: schema.ImportStatePassthroughContext,
31+
},
32+
33+
Schema: getSchema(),
34+
SchemaVersion: 1,
35+
StateUpgraders: []schema.StateUpgrader{
36+
{
37+
Version: 0,
38+
Type: getResourceSchemaV0().CoreConfigSchema().ImpliedType(),
39+
Upgrade: func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
40+
groupBy, ok := rawState["group_by"]
41+
if !ok {
42+
return rawState, nil
43+
}
44+
45+
groupByStr, ok := groupBy.(string)
46+
if !ok {
47+
return rawState, nil
48+
}
49+
50+
if len(groupByStr) == 0 {
51+
return rawState, nil
52+
}
53+
54+
rawState["group_by"] = []string{groupByStr}
55+
return rawState, nil
56+
},
57+
},
58+
},
59+
}
60+
}
61+
62+
func getResourceSchemaV0() *schema.Resource {
63+
s := getSchema()
64+
s["group_by"] = &schema.Schema{
65+
Description: "Optional group by field to use to generate an SLO per distinct value.",
66+
Type: schema.TypeString,
67+
Optional: true,
68+
ForceNew: false,
69+
}
70+
71+
return &schema.Resource{
72+
Schema: s,
73+
}
74+
}
75+
76+
func getSchema() map[string]*schema.Schema {
1877
var indicatorAddresses []string
1978
for i := range indicatorAddressToType {
2079
indicatorAddresses = append(indicatorAddresses, i)
2180
}
2281

23-
sloSchema := map[string]*schema.Schema{
82+
return map[string]*schema.Schema{
2483
"slo_id": {
2584
Description: "An ID (8 and 36 characters). If omitted, a UUIDv1 will be generated server-side.",
2685
Type: schema.TypeString,
@@ -409,10 +468,13 @@ func ResourceSlo() *schema.Resource {
409468
ForceNew: true,
410469
},
411470
"group_by": {
412-
Description: "Optional group by field to use to generate an SLO per distinct value.",
413-
Type: schema.TypeString,
471+
Description: "Optional group by fields to use to generate an SLO per distinct value.",
472+
Type: schema.TypeList,
414473
Optional: true,
415474
ForceNew: false,
475+
Elem: &schema.Schema{
476+
Type: schema.TypeString,
477+
},
416478
},
417479
"tags": {
418480
Description: "The tags for the SLO.",
@@ -424,21 +486,6 @@ func ResourceSlo() *schema.Resource {
424486
},
425487
},
426488
}
427-
428-
return &schema.Resource{
429-
Description: "Creates an SLO.",
430-
431-
CreateContext: resourceSloCreate,
432-
UpdateContext: resourceSloUpdate,
433-
ReadContext: resourceSloRead,
434-
DeleteContext: resourceSloDelete,
435-
436-
Importer: &schema.ResourceImporter{
437-
StateContext: schema.ImportStatePassthroughContext,
438-
},
439-
440-
Schema: sloSchema,
441-
}
442489
}
443490

444491
func getOrNilString(path string, d *schema.ResourceData) *string {
@@ -614,14 +661,19 @@ func getSloFromResourceData(d *schema.ResourceData) (models.Slo, diag.Diagnostic
614661
Objective: objective,
615662
Settings: &settings,
616663
SpaceID: d.Get("space_id").(string),
617-
GroupBy: getOrNilString("group_by", d),
618664
}
619665

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

671+
if groupBy, ok := d.GetOk("group_by"); ok {
672+
for _, g := range groupBy.([]interface{}) {
673+
slo.GroupBy = append(slo.GroupBy, g.(string))
674+
}
675+
}
676+
625677
if tags, ok := d.GetOk("tags"); ok {
626678
for _, t := range tags.([]interface{}) {
627679
slo.Tags = append(slo.Tags, t.(string))
@@ -642,8 +694,17 @@ func resourceSloCreate(ctx context.Context, d *schema.ResourceData, meta interfa
642694
return diags
643695
}
644696

645-
res, diags := kibana.CreateSlo(ctx, client, slo)
697+
serverVersion, diags := client.ServerVersion(ctx)
698+
if diags.HasError() {
699+
return diags
700+
}
701+
702+
supportsMultipleGroupBy := serverVersion.GreaterThanOrEqual(SLOSupportsMultipleGroupByMinVersion)
703+
if len(slo.GroupBy) > 1 && !supportsMultipleGroupBy {
704+
return diag.Errorf("multiple group_by fields are not supported in this version of the Elastic Stack. Multiple group_by fields requires %s", SLOSupportsMultipleGroupByMinVersion)
705+
}
646706

707+
res, diags := kibana.CreateSlo(ctx, client, slo, supportsMultipleGroupBy)
647708
if diags.HasError() {
648709
return diags
649710
}
@@ -665,8 +726,17 @@ func resourceSloUpdate(ctx context.Context, d *schema.ResourceData, meta interfa
665726
return diags
666727
}
667728

668-
res, diags := kibana.UpdateSlo(ctx, client, slo)
729+
serverVersion, diags := client.ServerVersion(ctx)
730+
if diags.HasError() {
731+
return diags
732+
}
669733

734+
supportsMultipleGroupBy := serverVersion.GreaterThanOrEqual(SLOSupportsMultipleGroupByMinVersion)
735+
if len(slo.GroupBy) > 1 && !supportsMultipleGroupBy {
736+
return diag.Errorf("multiple group_by fields are not supported in this version of the Elastic Stack. Multiple group_by fields requires %s", SLOSupportsMultipleGroupByMinVersion)
737+
}
738+
739+
res, diags := kibana.UpdateSlo(ctx, client, slo, supportsMultipleGroupBy)
670740
if diags.HasError() {
671741
return diags
672742
}
@@ -837,10 +907,8 @@ func resourceSloRead(ctx context.Context, d *schema.ResourceData, meta interface
837907
return diag.FromErr(err)
838908
}
839909

840-
if s.GroupBy != nil {
841-
if err := d.Set("group_by", s.GroupBy); err != nil {
842-
return diag.FromErr(err)
843-
}
910+
if err := d.Set("group_by", s.GroupBy); err != nil {
911+
return diag.FromErr(err)
844912
}
845913

846914
if err := d.Set("slo_id", s.SloID); err != nil {

0 commit comments

Comments
 (0)