Skip to content

Commit 56ab9c5

Browse files
committed
tinkering
1 parent 971a9a6 commit 56ab9c5

File tree

8 files changed

+237
-25
lines changed

8 files changed

+237
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Prevent a provider panic when the repository referenced in an `elasticstack_elasticsearch_snapshot_repository` does not exist ([#758](https://github.com/elastic/terraform-provider-elasticstack/pull/758))
1111
- Add support for `remote_indicies` to `elasticstack_elasticsearch_security_api_key` (#766)[https://github.com/elastic/terraform-provider-elasticstack/pull/766]
1212
- Add support for `icmp` and `browser` monitor types to `elasticstack_kibana_synthetics_monitor` resource (#772)[https://github.com/elastic/terraform-provider-elasticstack/pull/772]
13+
- Migrate `elasticstack_fleet_enrollment_tokens` to terraform-plugin-framework ([#778](https://github.com/elastic/terraform-provider-elasticstack/pull/778))
1314

1415
## [0.11.6] - 2024-08-20
1516

internal/elasticsearch/index/index/resource.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55

66
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
7-
"github.com/hashicorp/terraform-plugin-framework/diag"
87
"github.com/hashicorp/terraform-plugin-framework/path"
98
"github.com/hashicorp/terraform-plugin-framework/resource"
109
)
Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package enrollment_tokens
22

33
import (
4+
"context"
5+
46
fleetapi "github.com/elastic/terraform-provider-elasticstack/generated/fleet"
7+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
8+
"github.com/hashicorp/terraform-plugin-framework/diag"
9+
"github.com/hashicorp/terraform-plugin-framework/path"
510
"github.com/hashicorp/terraform-plugin-framework/types"
611
)
712

813
type enrollmentTokensModel struct {
9-
ID types.String `tfsdk:"id"`
10-
PolicyID types.String `tfsdk:"policy_id"`
11-
Tokens []enrollmentTokenModel `tfsdk:"tokens"`
14+
ID types.String `tfsdk:"id"`
15+
PolicyID types.String `tfsdk:"policy_id"`
16+
Tokens types.List `tfsdk:"tokens"` //> enrollmentTokenModel
1217
}
1318

1419
type enrollmentTokenModel struct {
@@ -21,21 +26,19 @@ type enrollmentTokenModel struct {
2126
PolicyID types.String `tfsdk:"policy_id"`
2227
}
2328

24-
func (model *enrollmentTokensModel) populateFromAPI(data []fleetapi.EnrollmentApiKey) {
25-
model.Tokens = make([]enrollmentTokenModel, 0, len(data))
26-
for _, token := range data {
27-
itemModel := enrollmentTokenModel{}
28-
itemModel.populateFromAPI(token)
29-
model.Tokens = append(model.Tokens, itemModel)
30-
}
29+
func (model *enrollmentTokensModel) populateFromAPI(ctx context.Context, data []fleetapi.EnrollmentApiKey) (diags diag.Diagnostics) {
30+
model.Tokens = utils.SliceToListType(ctx, data, getTokenType(), path.Root("tokens"), diags, newEnrollmentTokenModel)
31+
return
3132
}
3233

33-
func (model *enrollmentTokenModel) populateFromAPI(data fleetapi.EnrollmentApiKey) {
34-
model.KeyID = types.StringValue(data.Id)
35-
model.Active = types.BoolValue(data.Active)
36-
model.ApiKey = types.StringValue(data.ApiKey)
37-
model.ApiKeyID = types.StringValue(data.ApiKeyId)
38-
model.CreatedAt = types.StringValue(data.CreatedAt)
39-
model.Name = types.StringPointerValue(data.Name)
40-
model.PolicyID = types.StringPointerValue(data.PolicyId)
34+
func newEnrollmentTokenModel(data fleetapi.EnrollmentApiKey) enrollmentTokenModel {
35+
return enrollmentTokenModel{
36+
KeyID: types.StringValue(data.Id),
37+
Active: types.BoolValue(data.Active),
38+
ApiKey: types.StringValue(data.ApiKey),
39+
ApiKeyID: types.StringValue(data.ApiKeyId),
40+
CreatedAt: types.StringValue(data.CreatedAt),
41+
Name: types.StringPointerValue(data.Name),
42+
PolicyID: types.StringPointerValue(data.PolicyId),
43+
}
4144
}

internal/fleet/enrollment_tokens/read.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ func (d *enrollmentTokensDataSource) Read(ctx context.Context, req datasource.Re
4848
model.ID = types.StringPointerValue(hash)
4949
}
5050

51-
model.populateFromAPI(tokens)
51+
diags = model.populateFromAPI(ctx, tokens)
52+
resp.Diagnostics.Append(diags...)
53+
if resp.Diagnostics.HasError() {
54+
return
55+
}
5256

5357
diags = resp.State.Set(ctx, model)
5458
resp.Diagnostics.Append(diags...)

internal/fleet/enrollment_tokens/schema.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package enrollment_tokens
33
import (
44
"context"
55

6+
"github.com/hashicorp/terraform-plugin-framework/attr"
67
"github.com/hashicorp/terraform-plugin-framework/datasource"
78
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
89
)
@@ -57,3 +58,60 @@ func (d *enrollmentTokensDataSource) Schema(ctx context.Context, req datasource.
5758
},
5859
}
5960
}
61+
62+
func getSchema() *schema.Schema {
63+
return &schema.Schema{
64+
Description: "Retrieves Elasticsearch API keys used to enroll Elastic Agents in Fleet. See: https://www.elastic.co/guide/en/fleet/current/fleet-enrollment-tokens.html",
65+
Attributes: map[string]schema.Attribute{
66+
"id": schema.StringAttribute{
67+
Description: "The ID of this resource.",
68+
Computed: true,
69+
},
70+
"policy_id": schema.StringAttribute{
71+
Description: "The identifier of the target agent policy. When provided, only the enrollment tokens associated with this agent policy will be selected. Omit this value to select all enrollment tokens.",
72+
Optional: true,
73+
},
74+
"tokens": schema.ListNestedAttribute{
75+
Description: "A list of enrollment tokens.",
76+
Computed: true,
77+
NestedObject: schema.NestedAttributeObject{
78+
Attributes: map[string]schema.Attribute{
79+
"key_id": schema.StringAttribute{
80+
Description: "The unique identifier of the enrollment token.",
81+
Computed: true,
82+
},
83+
"api_key": schema.StringAttribute{
84+
Description: "The API key.",
85+
Computed: true,
86+
Sensitive: true,
87+
},
88+
"api_key_id": schema.StringAttribute{
89+
Description: "The API key identifier.",
90+
Computed: true,
91+
},
92+
"created_at": schema.StringAttribute{
93+
Description: "The time at which the enrollment token was created.",
94+
Computed: true,
95+
},
96+
"name": schema.StringAttribute{
97+
Description: "The name of the enrollment token.",
98+
Computed: true,
99+
},
100+
"active": schema.BoolAttribute{
101+
Description: "Indicates if the enrollment token is active.",
102+
Computed: true,
103+
},
104+
"policy_id": schema.StringAttribute{
105+
Description: "The identifier of the associated agent policy.",
106+
Computed: true,
107+
},
108+
},
109+
},
110+
},
111+
},
112+
}
113+
}
114+
115+
func getTokenType() attr.Type {
116+
return getSchema().Attributes["tokens"].GetType().(attr.TypeWithElementType).ElementType()
117+
}

internal/utils/tfsdk.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package utils
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-framework/attr"
7+
"github.com/hashicorp/terraform-plugin-framework/diag"
8+
"github.com/hashicorp/terraform-plugin-framework/path"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
)
11+
12+
// SliceToListType converts a tfsdk naive []T1 into an types.List of []T2.
13+
// This handles both structs and simple types to attr.Values.
14+
func SliceToListType[T1 any, T2 any](ctx context.Context, value []T1, elemType attr.Type, path path.Path, diags diag.Diagnostics, iteratee func(item T1) T2) types.List {
15+
if value == nil {
16+
return types.ListNull(elemType)
17+
}
18+
19+
elems := TransformSlice(value, iteratee)
20+
list, nd := types.ListValueFrom(ctx, elemType, elems)
21+
diags.Append(ConvertToAttrDiags(nd, path)...)
22+
23+
return list
24+
}
25+
26+
// TransformSlice converts []T1 to []T2 via the iteratee.
27+
func TransformSlice[T1 any, T2 any](value []T1, iteratee func(item T1) T2) []T2 {
28+
if value == nil {
29+
return nil
30+
}
31+
32+
elems := make([]T2, len(value))
33+
for i, v := range value {
34+
elems[i] = iteratee(v)
35+
}
36+
37+
return elems
38+
}

internal/utils/tfsdk_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package utils_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
8+
"github.com/hashicorp/terraform-plugin-framework/attr"
9+
"github.com/hashicorp/terraform-plugin-framework/diag"
10+
"github.com/hashicorp/terraform-plugin-framework/path"
11+
"github.com/hashicorp/terraform-plugin-framework/types"
12+
)
13+
14+
func TestSliceToListType(t *testing.T) {
15+
t.Parallel()
16+
17+
type Type1 struct {
18+
ID string `json:"id"`
19+
}
20+
type Type2 struct {
21+
ID types.String `tfsdk:"id"`
22+
}
23+
elemType := types.ObjectType{
24+
AttrTypes: map[string]attr.Type{
25+
"id": types.StringType,
26+
},
27+
}
28+
t1_t2 := func(item any) any {
29+
i := item.(Type1)
30+
return Type2{
31+
ID: types.StringValue(i.ID),
32+
}
33+
}
34+
toString := func(item any) any {
35+
return types.StringValue(item.(string))
36+
}
37+
38+
tests := []struct {
39+
name string
40+
input []any
41+
want types.List
42+
elemType attr.Type
43+
iter func(any) any
44+
}{
45+
{
46+
name: "converts nil",
47+
input: nil,
48+
want: types.ListNull(elemType),
49+
elemType: elemType,
50+
iter: t1_t2,
51+
},
52+
{
53+
name: "converts empty",
54+
input: []any{},
55+
want: types.ListValueMust(elemType, []attr.Value{}),
56+
elemType: elemType,
57+
iter: t1_t2,
58+
},
59+
{
60+
name: "converts struct",
61+
input: []any{
62+
Type1{ID: "id1"},
63+
Type1{ID: "id2"},
64+
Type1{ID: "id3"},
65+
},
66+
want: types.ListValueMust(elemType, []attr.Value{
67+
types.ObjectValueMust(elemType.AttrTypes, map[string]attr.Value{"id": types.StringValue("id1")}),
68+
types.ObjectValueMust(elemType.AttrTypes, map[string]attr.Value{"id": types.StringValue("id2")}),
69+
types.ObjectValueMust(elemType.AttrTypes, map[string]attr.Value{"id": types.StringValue("id3")}),
70+
}),
71+
elemType: elemType,
72+
iter: t1_t2,
73+
},
74+
{
75+
name: "convert strings",
76+
input: []any{"val1", "val2", "val3"},
77+
want: types.ListValueMust(types.StringType, []attr.Value{
78+
types.StringValue("val1"),
79+
types.StringValue("val2"),
80+
types.StringValue("val3"),
81+
}),
82+
elemType: types.StringType,
83+
iter: toString,
84+
},
85+
}
86+
87+
ctx := context.Background()
88+
89+
for _, tt := range tests {
90+
t.Run(tt.name, func(t *testing.T) {
91+
var diags diag.Diagnostics
92+
got := utils.SliceToListType(ctx, tt.input, tt.elemType, path.Empty(), diags, tt.iter)
93+
if !got.Equal(tt.want) {
94+
t.Errorf("SliceToListType() = %v, want %v", got, tt.want)
95+
}
96+
for _, d := range diags.Errors() {
97+
t.Errorf("SlicetoListType() diagnostic: %s: %s", d.Summary(), d.Detail())
98+
}
99+
})
100+
}
101+
}

internal/utils/utils.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import (
1313

1414
"github.com/elastic/go-elasticsearch/v7/esapi"
1515
providerSchema "github.com/elastic/terraform-provider-elasticstack/internal/schema"
16+
"github.com/hashicorp/terraform-plugin-framework/diag"
1617
fwdiag "github.com/hashicorp/terraform-plugin-framework/diag"
18+
"github.com/hashicorp/terraform-plugin-framework/path"
1719
"github.com/hashicorp/terraform-plugin-log/tflog"
1820
sdkdiag "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1921
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -254,11 +256,17 @@ func SdkDiagsAsError(diags sdkdiag.Diagnostics) error {
254256
return nil
255257
}
256258

257-
func FwDiagsAsError(diags fwdiag.Diagnostics) error {
258-
for _, diag := range diags {
259-
if diag.Severity() == fwdiag.SeverityError {
260-
return fmt.Errorf("%s: %s", diag.Summary(), diag.Detail())
259+
// ConvertToAttrDiags wraps an existing collection of diagnostics with an attribute path.
260+
func ConvertToAttrDiags(diags fwdiag.Diagnostics, path path.Path) fwdiag.Diagnostics {
261+
var nd fwdiag.Diagnostics
262+
for _, d := range diags {
263+
if d.Severity() == fwdiag.SeverityError {
264+
nd.AddAttributeError(path, d.Summary(), d.Detail())
265+
} else if d.Severity() == diag.SeverityWarning {
266+
nd.AddAttributeWarning(path, d.Summary(), d.Detail())
267+
} else {
268+
nd.Append(d)
261269
}
262270
}
263-
return nil
271+
return nd
264272
}

0 commit comments

Comments
 (0)