Skip to content

Commit 3e17377

Browse files
authored
impl framework data_source.fleet_enrollment_tokens (#778)
* remove usage of isReady, add check to ConvertProviderData instead * impl fw data_source.enrollment_tokens * make fmt * make docs-generate * undo rename of struct * tinkering * remove duplicate schema
1 parent 9d8c7bd commit 3e17377

File tree

27 files changed

+448
-229
lines changed

27 files changed

+448
-229
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- 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))
1212
- Add support for `remote_indicies` to `elasticstack_elasticsearch_security_api_key` (#766)[https://github.com/elastic/terraform-provider-elasticstack/pull/766]
1313
- Add support for `icmp` and `browser` monitor types to `elasticstack_kibana_synthetics_monitor` resource (#772)[https://github.com/elastic/terraform-provider-elasticstack/pull/772]
14+
- Migrate `elasticstack_fleet_enrollment_tokens` to terraform-plugin-framework ([#778](https://github.com/elastic/terraform-provider-elasticstack/pull/778))
1415

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

docs/data-sources/fleet_enrollment_tokens.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ data "elasticstack_fleet_enrollment_tokens" "test" {
3232
### Read-Only
3333

3434
- `id` (String) The ID of this resource.
35-
- `tokens` (List of Object) A list of enrollment tokens. (see [below for nested schema](#nestedatt--tokens))
35+
- `tokens` (Attributes List) A list of enrollment tokens. (see [below for nested schema](#nestedatt--tokens))
3636

3737
<a id="nestedatt--tokens"></a>
3838
### Nested Schema for `tokens`
3939

4040
Read-Only:
4141

42-
- `active` (Boolean)
43-
- `api_key` (String)
44-
- `api_key_id` (String)
45-
- `created_at` (String)
46-
- `key_id` (String)
47-
- `name` (String)
48-
- `policy_id` (String)
42+
- `active` (Boolean) Indicates if the enrollment token is active.
43+
- `api_key` (String, Sensitive) The API key.
44+
- `api_key_id` (String) The API key identifier.
45+
- `created_at` (String) The time at which the enrollment token was created.
46+
- `key_id` (String) The unique identifier of the enrollment token.
47+
- `name` (String) The name of the enrollment token.
48+
- `policy_id` (String) The identifier of the associated agent policy.

internal/clients/api_client.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ func ConvertProviderData(providerData any) (*ApiClient, fwdiags.Diagnostics) {
154154

155155
return nil, diags
156156
}
157+
if client == nil {
158+
diags.AddError(
159+
"Unconfigured Client",
160+
"Expected configured client. Please report this issue to the provider developers.",
161+
)
162+
}
157163
return client, diags
158164
}
159165

internal/clients/fleet/fleet.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99

1010
fleetapi "github.com/elastic/terraform-provider-elasticstack/generated/fleet"
11+
fwdiag "github.com/hashicorp/terraform-plugin-framework/diag"
1112
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1213
)
1314

@@ -16,20 +17,20 @@ var (
1617
)
1718

1819
// AllEnrollmentTokens reads all enrollment tokens from the API.
19-
func AllEnrollmentTokens(ctx context.Context, client *Client) ([]fleetapi.EnrollmentApiKey, diag.Diagnostics) {
20+
func AllEnrollmentTokens(ctx context.Context, client *Client) ([]fleetapi.EnrollmentApiKey, fwdiag.Diagnostics) {
2021
resp, err := client.API.GetEnrollmentApiKeysWithResponse(ctx)
2122
if err != nil {
22-
return nil, diag.FromErr(err)
23+
return nil, fromErr(err)
2324
}
2425

2526
if resp.StatusCode() == http.StatusOK {
2627
return resp.JSON200.Items, nil
2728
}
28-
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
29+
return nil, reportUnknownErrorFw(resp.StatusCode(), resp.Body)
2930
}
3031

3132
// GetEnrollmentTokensByPolicy Get enrollment tokens by given policy ID
32-
func GetEnrollmentTokensByPolicy(ctx context.Context, client *Client, policyID string) ([]fleetapi.EnrollmentApiKey, diag.Diagnostics) {
33+
func GetEnrollmentTokensByPolicy(ctx context.Context, client *Client, policyID string) ([]fleetapi.EnrollmentApiKey, fwdiag.Diagnostics) {
3334
resp, err := client.API.GetEnrollmentApiKeysWithResponse(ctx, func(ctx context.Context, req *http.Request) error {
3435
q := req.URL.Query()
3536
q.Set("kuery", "policy_id:"+policyID)
@@ -38,13 +39,13 @@ func GetEnrollmentTokensByPolicy(ctx context.Context, client *Client, policyID s
3839
return nil
3940
})
4041
if err != nil {
41-
return nil, diag.FromErr(err)
42+
return nil, fromErr(err)
4243
}
4344

4445
if resp.StatusCode() == http.StatusOK {
4546
return resp.JSON200.Items, nil
4647
}
47-
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
48+
return nil, reportUnknownErrorFw(resp.StatusCode(), resp.Body)
4849
}
4950

5051
// ReadAgentPolicy reads a specific agent policy from the API.
@@ -416,6 +417,16 @@ func AllPackages(ctx context.Context, client *Client, prerelease bool) ([]fleeta
416417
}
417418
}
418419

420+
// fromErr recreates the sdkdiag.FromErr functionality.
421+
func fromErr(err error) fwdiag.Diagnostics {
422+
if err == nil {
423+
return nil
424+
}
425+
return fwdiag.Diagnostics{
426+
fwdiag.NewErrorDiagnostic(err.Error(), ""),
427+
}
428+
}
429+
419430
func reportUnknownError(statusCode int, body []byte) diag.Diagnostics {
420431
return diag.Diagnostics{
421432
diag.Diagnostic{
@@ -425,3 +436,12 @@ func reportUnknownError(statusCode int, body []byte) diag.Diagnostics {
425436
},
426437
}
427438
}
439+
440+
func reportUnknownErrorFw(statusCode int, body []byte) fwdiag.Diagnostics {
441+
return fwdiag.Diagnostics{
442+
fwdiag.NewErrorDiagnostic(
443+
fmt.Sprintf("Unexpected status code from server: got HTTP %d", statusCode),
444+
string(body),
445+
),
446+
}
447+
}

internal/elasticsearch/index/index/create.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ import (
1616
var includeTypeNameMinUnsupportedVersion = version.Must(version.NewVersion("8.0.0"))
1717

1818
func (r Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
19-
if !r.resourceReady(&resp.Diagnostics) {
20-
return
21-
}
22-
2319
var planModel tfModel
2420
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
2521
if resp.Diagnostics.HasError() {

internal/elasticsearch/index/index/delete.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import (
1010
)
1111

1212
func (r *Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
13-
if !r.resourceReady(&resp.Diagnostics) {
14-
return
15-
}
16-
1713
var model tfModel
1814
resp.Diagnostics.Append(req.State.Get(ctx, &model)...)
1915
if resp.Diagnostics.HasError() {

internal/elasticsearch/index/index/read.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import (
1010
)
1111

1212
func (r *Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
13-
if !r.resourceReady(&resp.Diagnostics) {
14-
return
15-
}
16-
1713
var stateModel tfModel
1814
resp.Diagnostics.Append(req.State.Get(ctx, &stateModel)...)
1915
if resp.Diagnostics.HasError() {

internal/elasticsearch/index/index/resource.go

Lines changed: 0 additions & 13 deletions
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
)
@@ -18,18 +17,6 @@ type Resource struct {
1817
client *clients.ApiClient
1918
}
2019

21-
func (r *Resource) resourceReady(dg *diag.Diagnostics) bool {
22-
if r.client == nil {
23-
dg.AddError(
24-
"Unconfigured Client",
25-
"Expected configured client. Please report this issue to the provider developers.",
26-
)
27-
28-
return false
29-
}
30-
return true
31-
}
32-
3320
func (r *Resource) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
3421
client, diags := clients.ConvertProviderData(request.ProviderData)
3522
response.Diagnostics.Append(diags...)

internal/elasticsearch/index/index/update.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ import (
1515
)
1616

1717
func (r *Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
18-
if !r.resourceReady(&resp.Diagnostics) {
19-
return
20-
}
21-
2218
var planModel tfModel
2319
var stateModel tfModel
2420
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package enrollment_tokens
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource"
9+
)
10+
11+
var (
12+
_ datasource.DataSource = &enrollmentTokensDataSource{}
13+
_ datasource.DataSourceWithConfigure = &enrollmentTokensDataSource{}
14+
)
15+
16+
// NewDataSource is a helper function to simplify the provider implementation.
17+
func NewDataSource() datasource.DataSource {
18+
return &enrollmentTokensDataSource{}
19+
}
20+
21+
type enrollmentTokensDataSource struct {
22+
client *clients.ApiClient
23+
}
24+
25+
func (d *enrollmentTokensDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
26+
resp.TypeName = fmt.Sprintf("%s_%s", req.ProviderTypeName, "fleet_enrollment_tokens")
27+
}
28+
29+
func (d *enrollmentTokensDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
30+
client, diags := clients.ConvertProviderData(req.ProviderData)
31+
resp.Diagnostics.Append(diags...)
32+
d.client = client
33+
}

internal/fleet/enrollment_tokens_data_source_test.go renamed to internal/fleet/enrollment_tokens/data_source_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
package fleet_test
1+
package enrollment_tokens_test
22

33
import (
4+
"context"
5+
"fmt"
46
"testing"
57

68
"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
9+
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
10+
"github.com/elastic/terraform-provider-elasticstack/internal/clients/fleet"
11+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
712
"github.com/elastic/terraform-provider-elasticstack/internal/versionutils"
813
"github.com/hashicorp/go-version"
914
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1016
)
1117

1218
var minVersionEnrollmentTokens = version.Must(version.NewVersion("8.6.0"))
@@ -46,3 +52,29 @@ data "elasticstack_fleet_enrollment_tokens" "test" {
4652
policy_id = elasticstack_fleet_agent_policy.test.policy_id
4753
}
4854
`
55+
56+
func checkResourceAgentPolicyDestroy(s *terraform.State) error {
57+
client, err := clients.NewAcceptanceTestingClient()
58+
if err != nil {
59+
return err
60+
}
61+
62+
for _, rs := range s.RootModule().Resources {
63+
if rs.Type != "elasticstack_fleet_agent_policy" {
64+
continue
65+
}
66+
67+
fleetClient, err := client.GetFleetClient()
68+
if err != nil {
69+
return err
70+
}
71+
policy, diags := fleet.ReadAgentPolicy(context.Background(), fleetClient, rs.Primary.ID)
72+
if diags.HasError() {
73+
return utils.SdkDiagsAsError(diags)
74+
}
75+
if policy != nil {
76+
return fmt.Errorf("agent policy id=%v still exists, but it should have been removed", rs.Primary.ID)
77+
}
78+
}
79+
return nil
80+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package enrollment_tokens
2+
3+
import (
4+
"context"
5+
6+
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"
10+
"github.com/hashicorp/terraform-plugin-framework/types"
11+
)
12+
13+
type enrollmentTokensModel struct {
14+
ID types.String `tfsdk:"id"`
15+
PolicyID types.String `tfsdk:"policy_id"`
16+
Tokens types.List `tfsdk:"tokens"` //> enrollmentTokenModel
17+
}
18+
19+
type enrollmentTokenModel struct {
20+
KeyID types.String `tfsdk:"key_id"`
21+
ApiKey types.String `tfsdk:"api_key"`
22+
ApiKeyID types.String `tfsdk:"api_key_id"`
23+
CreatedAt types.String `tfsdk:"created_at"`
24+
Name types.String `tfsdk:"name"`
25+
Active types.Bool `tfsdk:"active"`
26+
PolicyID types.String `tfsdk:"policy_id"`
27+
}
28+
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
32+
}
33+
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+
}
44+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package enrollment_tokens
2+
3+
import (
4+
"context"
5+
6+
fleetapi "github.com/elastic/terraform-provider-elasticstack/generated/fleet"
7+
"github.com/elastic/terraform-provider-elasticstack/internal/clients/fleet"
8+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
9+
"github.com/hashicorp/terraform-plugin-framework/datasource"
10+
"github.com/hashicorp/terraform-plugin-framework/types"
11+
)
12+
13+
func (d *enrollmentTokensDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
14+
var model enrollmentTokensModel
15+
16+
diags := req.Config.Get(ctx, &model)
17+
resp.Diagnostics.Append(diags...)
18+
if resp.Diagnostics.HasError() {
19+
return
20+
}
21+
22+
client, err := d.client.GetFleetClient()
23+
if err != nil {
24+
resp.Diagnostics.AddError(err.Error(), "")
25+
return
26+
}
27+
28+
var tokens []fleetapi.EnrollmentApiKey
29+
policyID := model.PolicyID.ValueString()
30+
if policyID == "" {
31+
tokens, diags = fleet.AllEnrollmentTokens(ctx, client)
32+
} else {
33+
tokens, diags = fleet.GetEnrollmentTokensByPolicy(ctx, client, policyID)
34+
}
35+
resp.Diagnostics.Append(diags...)
36+
if resp.Diagnostics.HasError() {
37+
return
38+
}
39+
40+
if policyID != "" {
41+
model.ID = types.StringValue(policyID)
42+
} else {
43+
hash, err := utils.StringToHash(client.URL)
44+
if err != nil {
45+
resp.Diagnostics.AddError(err.Error(), "")
46+
return
47+
}
48+
model.ID = types.StringPointerValue(hash)
49+
}
50+
51+
diags = model.populateFromAPI(ctx, tokens)
52+
resp.Diagnostics.Append(diags...)
53+
if resp.Diagnostics.HasError() {
54+
return
55+
}
56+
57+
diags = resp.State.Set(ctx, model)
58+
resp.Diagnostics.Append(diags...)
59+
}

0 commit comments

Comments
 (0)