@@ -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+
1720func 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
444491func 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