Skip to content

Commit 78a7837

Browse files
committed
Fix tests
1 parent a0c6336 commit 78a7837

File tree

8 files changed

+564
-76
lines changed

8 files changed

+564
-76
lines changed

docs/resources/elasticsearch_security_role.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ Required:
135135

136136
Optional:
137137

138-
- `field_security` (Attributes List) The document fields that the owners of the role have read access to. (see [below for nested schema](#nestedatt--remote_indices--field_security))
138+
- `field_security` (Block List) The document fields that the owners of the role have read access to. (see [below for nested schema](#nestedblock--remote_indices--field_security))
139139
- `query` (String) A search query that defines the documents the owners of the role have read access to.
140140

141-
<a id="nestedatt--remote_indices--field_security"></a>
141+
<a id="nestedblock--remote_indices--field_security"></a>
142142
### Nested Schema for `remote_indices.field_security`
143143

144144
Optional:

internal/elasticsearch/security/role/acc_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ func TestAccResourceSecurityRole(t *testing.T) {
4646
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "run_as.#"),
4747
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "global"),
4848
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "applications.#"),
49-
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "indices.0.allow_restricted_indices"),
5049
),
5150
},
5251
{
@@ -75,7 +74,6 @@ func TestAccResourceSecurityRole(t *testing.T) {
7574
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "run_as.#"),
7675
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "global"),
7776
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "applications.#"),
78-
resource.TestCheckNoResourceAttr("elasticstack_elasticsearch_security_role.test", "indices.0.allow_restricted_indices"),
7977
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "remote_indices.*.clusters.*", "test-cluster2"),
8078
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_security_role.test", "remote_indices.*.names.*", "sample2"),
8179
),

internal/elasticsearch/security/role/models.go

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,6 @@ import (
1313
"github.com/hashicorp/terraform-plugin-framework/types"
1414
)
1515

16-
var (
17-
applicationAttrTypes = map[string]attr.Type{
18-
"application": types.StringType,
19-
"privileges": types.SetType{ElemType: types.StringType},
20-
"resources": types.SetType{ElemType: types.StringType},
21-
}
22-
23-
fieldSecurityAttrTypes = map[string]attr.Type{
24-
"grant": types.SetType{ElemType: types.StringType},
25-
"except": types.SetType{ElemType: types.StringType},
26-
}
27-
28-
indexPermsAttrTypes = map[string]attr.Type{
29-
"field_security": types.ListType{ElemType: types.ObjectType{AttrTypes: fieldSecurityAttrTypes}},
30-
"names": types.SetType{ElemType: types.StringType},
31-
"privileges": types.SetType{ElemType: types.StringType},
32-
"query": jsontypes.NormalizedType{},
33-
"allow_restricted_indices": types.BoolType,
34-
}
35-
36-
remoteIndexPermsAttrTypes = map[string]attr.Type{
37-
"clusters": types.SetType{ElemType: types.StringType},
38-
"field_security": types.ListType{ElemType: types.ObjectType{AttrTypes: fieldSecurityAttrTypes}},
39-
"query": jsontypes.NormalizedType{},
40-
"names": types.SetType{ElemType: types.StringType},
41-
"privileges": types.SetType{ElemType: types.StringType},
42-
}
43-
)
44-
4516
type RoleData struct {
4617
Id types.String `tfsdk:"id"`
4718
ElasticsearchConnection types.List `tfsdk:"elasticsearch_connection"`
@@ -329,7 +300,7 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
329300
return diags
330301
}
331302

332-
appObj, d := types.ObjectValue(applicationAttrTypes, map[string]attr.Value{
303+
appObj, d := types.ObjectValue(getApplicationAttrTypes(), map[string]attr.Value{
333304
"application": types.StringValue(app.Name),
334305
"privileges": privSet,
335306
"resources": resSet,
@@ -342,14 +313,14 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
342313
appElements[i] = appObj
343314
}
344315

345-
appSet, d := types.SetValue(types.ObjectType{AttrTypes: applicationAttrTypes}, appElements)
316+
appSet, d := types.SetValue(types.ObjectType{AttrTypes: getApplicationAttrTypes()}, appElements)
346317
diags.Append(d...)
347318
if diags.HasError() {
348319
return diags
349320
}
350321
data.Applications = appSet
351322
} else {
352-
data.Applications = types.SetNull(types.ObjectType{AttrTypes: applicationAttrTypes})
323+
data.Applications = types.SetNull(types.ObjectType{AttrTypes: getApplicationAttrTypes()})
353324
}
354325

355326
// Cluster
@@ -420,7 +391,7 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
420391
return diags
421392
}
422393

423-
fieldSecObj, d := types.ObjectValue(fieldSecurityAttrTypes, map[string]attr.Value{
394+
fieldSecObj, d := types.ObjectValue(getFieldSecurityAttrTypes(), map[string]attr.Value{
424395
"grant": grantSet,
425396
"except": exceptSet,
426397
})
@@ -429,16 +400,16 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
429400
return diags
430401
}
431402

432-
fieldSecList, d = types.ListValue(types.ObjectType{AttrTypes: fieldSecurityAttrTypes}, []attr.Value{fieldSecObj})
403+
fieldSecList, d = types.ListValue(types.ObjectType{AttrTypes: getFieldSecurityAttrTypes()}, []attr.Value{fieldSecObj})
433404
diags.Append(d...)
434405
if diags.HasError() {
435406
return diags
436407
}
437408
} else {
438-
fieldSecList = types.ListNull(types.ObjectType{AttrTypes: fieldSecurityAttrTypes})
409+
fieldSecList = types.ListNull(types.ObjectType{AttrTypes: getFieldSecurityAttrTypes()})
439410
}
440411

441-
indexObj, d := types.ObjectValue(indexPermsAttrTypes, map[string]attr.Value{
412+
indexObj, d := types.ObjectValue(getIndexPermsAttrTypes(), map[string]attr.Value{
442413
"field_security": fieldSecList,
443414
"names": namesSet,
444415
"privileges": privSet,
@@ -453,14 +424,14 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
453424
indicesElements[i] = indexObj
454425
}
455426

456-
indicesSet, d := types.SetValue(types.ObjectType{AttrTypes: indexPermsAttrTypes}, indicesElements)
427+
indicesSet, d := types.SetValue(types.ObjectType{AttrTypes: getIndexPermsAttrTypes()}, indicesElements)
457428
diags.Append(d...)
458429
if diags.HasError() {
459430
return diags
460431
}
461432
data.Indices = indicesSet
462433
} else {
463-
data.Indices = types.SetNull(types.ObjectType{AttrTypes: indexPermsAttrTypes})
434+
data.Indices = types.SetNull(types.ObjectType{AttrTypes: getIndexPermsAttrTypes()})
464435
}
465436

466437
// Remote Indices
@@ -494,19 +465,19 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
494465

495466
var fieldSecList types.List
496467
if remoteIndex.FieldSecurity != nil {
497-
grantSet, d := types.SetValueFrom(ctx, types.StringType, remoteIndex.FieldSecurity.Grant)
468+
grantSet, d := types.SetValueFrom(ctx, types.StringType, utils.NonNilSlice(remoteIndex.FieldSecurity.Grant))
498469
diags.Append(d...)
499470
if diags.HasError() {
500471
return diags
501472
}
502473

503-
exceptSet, d := types.SetValueFrom(ctx, types.StringType, remoteIndex.FieldSecurity.Except)
474+
exceptSet, d := types.SetValueFrom(ctx, types.StringType, utils.NonNilSlice(remoteIndex.FieldSecurity.Except))
504475
diags.Append(d...)
505476
if diags.HasError() {
506477
return diags
507478
}
508479

509-
fieldSecObj, d := types.ObjectValue(fieldSecurityAttrTypes, map[string]attr.Value{
480+
fieldSecObj, d := types.ObjectValue(getRemoteFieldSecurityAttrTypes(), map[string]attr.Value{
510481
"grant": grantSet,
511482
"except": exceptSet,
512483
})
@@ -515,16 +486,16 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
515486
return diags
516487
}
517488

518-
fieldSecList, d = types.ListValue(types.ObjectType{AttrTypes: fieldSecurityAttrTypes}, []attr.Value{fieldSecObj})
489+
fieldSecList, d = types.ListValue(types.ObjectType{AttrTypes: getRemoteFieldSecurityAttrTypes()}, []attr.Value{fieldSecObj})
519490
diags.Append(d...)
520491
if diags.HasError() {
521492
return diags
522493
}
523494
} else {
524-
fieldSecList = types.ListNull(types.ObjectType{AttrTypes: fieldSecurityAttrTypes})
495+
fieldSecList = types.ListNull(types.ObjectType{AttrTypes: getRemoteFieldSecurityAttrTypes()})
525496
}
526497

527-
remoteIndexObj, d := types.ObjectValue(remoteIndexPermsAttrTypes, map[string]attr.Value{
498+
remoteIndexObj, d := types.ObjectValue(getRemoteIndexPermsAttrTypes(), map[string]attr.Value{
528499
"clusters": clustersSet,
529500
"field_security": fieldSecList,
530501
"query": queryVal,
@@ -539,14 +510,14 @@ func (data *RoleData) fromAPIModel(ctx context.Context, role *models.Role) diag.
539510
remoteIndicesElements[i] = remoteIndexObj
540511
}
541512

542-
remoteIndicesSet, d := types.SetValue(types.ObjectType{AttrTypes: remoteIndexPermsAttrTypes}, remoteIndicesElements)
513+
remoteIndicesSet, d := types.SetValue(types.ObjectType{AttrTypes: getRemoteIndexPermsAttrTypes()}, remoteIndicesElements)
543514
diags.Append(d...)
544515
if diags.HasError() {
545516
return diags
546517
}
547518
data.RemoteIndices = remoteIndicesSet
548519
} else {
549-
data.RemoteIndices = types.SetNull(types.ObjectType{AttrTypes: remoteIndexPermsAttrTypes})
520+
data.RemoteIndices = types.SetNull(types.ObjectType{AttrTypes: getRemoteIndexPermsAttrTypes()})
550521
}
551522

552523
// Metadata

internal/elasticsearch/security/role/read.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
88
"github.com/elastic/terraform-provider-elasticstack/internal/clients/elasticsearch"
99
"github.com/elastic/terraform-provider-elasticstack/internal/diagutil"
10+
"github.com/hashicorp/terraform-plugin-framework/diag"
1011
"github.com/hashicorp/terraform-plugin-framework/resource"
1112
"github.com/hashicorp/terraform-plugin-framework/types"
1213
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -19,39 +20,53 @@ func (r *roleResource) Read(ctx context.Context, req resource.ReadRequest, resp
1920
return
2021
}
2122

22-
compId, diags := clients.CompositeIdFromStrFw(data.Id.ValueString())
23+
readData, diags := r.read(ctx, data)
2324
resp.Diagnostics.Append(diags...)
2425
if resp.Diagnostics.HasError() {
2526
return
2627
}
28+
29+
if readData == nil {
30+
resp.State.RemoveResource(ctx)
31+
return
32+
}
33+
34+
resp.Diagnostics.Append(req.State.Set(ctx, readData)...)
35+
}
36+
37+
func (r *roleResource) read(ctx context.Context, data RoleData) (*RoleData, diag.Diagnostics) {
38+
compId, diags := clients.CompositeIdFromStrFw(data.Id.ValueString())
39+
diags.Append(diags...)
40+
if diags.HasError() {
41+
return nil, diags
42+
}
2743
roleId := compId.ResourceId
2844

2945
client, diags := clients.MaybeNewApiClientFromFrameworkResource(ctx, data.ElasticsearchConnection, r.client)
30-
resp.Diagnostics.Append(diags...)
31-
if resp.Diagnostics.HasError() {
32-
return
46+
diags.Append(diags...)
47+
if diags.HasError() {
48+
return nil, diags
3349
}
3450

3551
role, sdkDiags := elasticsearch.GetRole(ctx, client, roleId)
36-
resp.Diagnostics.Append(diagutil.FrameworkDiagsFromSDK(sdkDiags)...)
37-
if resp.Diagnostics.HasError() {
38-
return
52+
diags.Append(diagutil.FrameworkDiagsFromSDK(sdkDiags)...)
53+
if diags.HasError() {
54+
return nil, diags
3955
}
4056

4157
if role == nil {
42-
tflog.Warn(ctx, fmt.Sprintf(`Role "%s" not found, removing from state`, roleId))
43-
resp.State.RemoveResource(ctx)
44-
return
58+
tflog.Warn(ctx, fmt.Sprintf(`Role "%s" not found`, roleId))
59+
return nil, diags
4560
}
4661

4762
// Convert from API model
48-
resp.Diagnostics.Append(data.fromAPIModel(ctx, role)...)
49-
if resp.Diagnostics.HasError() {
50-
return
63+
diags.Append(data.fromAPIModel(ctx, role)...)
64+
if diags.HasError() {
65+
return nil, diags
5166
}
5267

5368
// Set the name to the roleId we extracted to ensure consistency
5469
data.Name = types.StringValue(roleId)
5570

56-
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
71+
return &data, diags
5772
}

internal/elasticsearch/security/role/resource.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@ package role
22

33
import (
44
"context"
5+
"encoding/json"
56

67
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
8+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
79
"github.com/hashicorp/terraform-plugin-framework/path"
810
"github.com/hashicorp/terraform-plugin-framework/resource"
11+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
912
)
1013

1114
// Ensure provider defined types fully satisfy framework interfaces
1215
var _ resource.Resource = &roleResource{}
1316
var _ resource.ResourceWithConfigure = &roleResource{}
1417
var _ resource.ResourceWithImportState = &roleResource{}
18+
var _ resource.ResourceWithUpgradeState = &roleResource{}
1519

1620
func NewRoleResource() resource.Resource {
1721
return &roleResource{}
@@ -34,3 +38,70 @@ func (r *roleResource) Configure(_ context.Context, req resource.ConfigureReques
3438
func (r *roleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
3539
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
3640
}
41+
42+
func (r *roleResource) UpgradeState(_ context.Context) map[int64]resource.StateUpgrader {
43+
return map[int64]resource.StateUpgrader{
44+
0: {
45+
PriorSchema: utils.Pointer(GetSchema(0)),
46+
StateUpgrader: v0ToV1,
47+
},
48+
}
49+
}
50+
51+
func v0ToV1(ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse) {
52+
var priorState map[string]interface{}
53+
err := json.Unmarshal(req.RawState.JSON, &priorState)
54+
if err != nil {
55+
resp.Diagnostics.AddError("State Upgrade Error", "Could not unmarshal prior state: "+err.Error())
56+
return
57+
}
58+
59+
if priorState["global"] == "" {
60+
delete(priorState, "global")
61+
}
62+
63+
if priorState["metadata"] == "" {
64+
delete(priorState, "metadata")
65+
}
66+
67+
indices, ok := priorState["indices"]
68+
if ok {
69+
indicesSlice, ok := indices.([]interface{})
70+
if ok {
71+
for i, index := range indicesSlice {
72+
indexMap, ok := index.(map[string]interface{})
73+
if ok {
74+
if indexMap["query"] == "" {
75+
delete(indexMap, "query")
76+
}
77+
indicesSlice[i] = indexMap
78+
}
79+
}
80+
}
81+
}
82+
83+
remoteIndices, ok := priorState["remote_indices"]
84+
if ok {
85+
remoteIndicesSlice, ok := remoteIndices.([]interface{})
86+
if ok {
87+
for i, remoteIndex := range remoteIndicesSlice {
88+
remoteIndexMap, ok := remoteIndex.(map[string]interface{})
89+
if ok {
90+
if remoteIndexMap["query"] == "" {
91+
delete(remoteIndexMap, "query")
92+
}
93+
remoteIndicesSlice[i] = remoteIndexMap
94+
}
95+
}
96+
}
97+
}
98+
99+
stateJSON, err := json.Marshal(priorState)
100+
if err != nil {
101+
resp.Diagnostics.AddError("State Upgrade Error", "Could not marshal new state: "+err.Error())
102+
return
103+
}
104+
resp.DynamicValue = &tfprotov6.DynamicValue{
105+
JSON: stateJSON,
106+
}
107+
}

0 commit comments

Comments
 (0)