Skip to content

Commit dcdc1eb

Browse files
authored
Fix dataview namespaces regression (#1011)
* Fix dataview namespace inconsistencies * cl * update test
1 parent fd45c4c commit dcdc1eb

File tree

6 files changed

+115
-6
lines changed

6 files changed

+115
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- Fix a provider crash when interacting with elasticstack_kibana_data_view resources created with 0.11.0. ([#979](https://github.com/elastic/terraform-provider-elasticstack/pull/979))
44
- Add `max_primary_shard_docs` condition to ILM rollover ([#845](https://github.com/elastic/terraform-provider-elasticstack/pull/845))
55
- Add missing entries to `data_view.field_formats.params` ([#1001](https://github.com/elastic/terraform-provider-elasticstack/pull/1001))
6+
- Fix namespaces inconsistency when creating elasticstack_kibana_data_view resources ([#1011](https://github.com/elastic/terraform-provider-elasticstack/pull/1011))
67

78
## [0.11.13] - 2025-01-09
89

@@ -19,6 +20,7 @@
1920
- Support multiple group by fields in SLOs ([#870](https://github.com/elastic/terraform-provider-elasticstack/pull/878)). This changes to type of the `group_by` attribute of the `elasticstack_kibana_slo` resource from a String to a list of Strings. Any existing SLO defintions will need to update `group_by = "field"` to `group_by = ["field"]`.
2021

2122
### Changes
23+
2224
- Handle NPE in integration policy secrets ([#946](https://github.com/elastic/terraform-provider-elasticstack/pull/946))
2325
- Use the auto-generated OAS schema from elastic/kibana for the Fleet API. ([#834](https://github.com/elastic/terraform-provider-elasticstack/issues/834))
2426
- Support description in `elasticstack_elasticsearch_security_role` data sources. ([#884](https://github.com/elastic/terraform-provider-elasticstack/pull/884))

internal/kibana/data_view/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (r *DataViewResource) Create(ctx context.Context, req resource.CreateReques
3535
return
3636
}
3737

38-
diags = planModel.populateFromAPI(ctx, dataView)
38+
diags = planModel.populateFromAPI(ctx, dataView, spaceID)
3939
resp.Diagnostics.Append(diags...)
4040
if resp.Diagnostics.HasError() {
4141
return

internal/kibana/data_view/models.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/hashicorp/terraform-plugin-framework/types"
1313
)
1414

15-
func (model *dataViewModel) populateFromAPI(ctx context.Context, data *kbapi.DataViewsDataViewResponseObject) diag.Diagnostics {
15+
func (model *dataViewModel) populateFromAPI(ctx context.Context, data *kbapi.DataViewsDataViewResponseObject, spaceID string) diag.Diagnostics {
1616
if data == nil {
1717
return nil
1818
}
@@ -60,10 +60,15 @@ func (model *dataViewModel) populateFromAPI(ctx context.Context, data *kbapi.Dat
6060

6161
// Keep the original ordering if equal but unordered
6262
// The API response is ordered by name.
63-
if len(existing) == len(incoming) {
63+
// Additionally, allow for the response containing an extra namespace that is the current SpaceID
64+
// If the SpaceID is not included in the `namespaces` field, when trying to GET the object it will 404
65+
if (len(existing) == len(incoming)) || (len(existing) == len(incoming)-1) {
6466
useExisting := true
6567
for _, ns := range existing {
6668
if !slices.Contains(incoming, ns) {
69+
if ns == spaceID {
70+
continue
71+
}
6772
useExisting = false
6873
break
6974
}

internal/kibana/data_view/models_test.go

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,115 @@ func TestPopulateFromAPI(t *testing.T) {
100100
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
101101
},
102102
},
103+
{
104+
// When sending no value, the response from Kibana is ["default"]
105+
name: "handleNamespaces_null_default",
106+
existingModel: dataViewModel{
107+
ID: types.StringValue("default/id"),
108+
SpaceID: types.StringValue("default"),
109+
DataView: utils.ObjectValueFrom(ctx, &innerModel{
110+
ID: types.StringValue("id"),
111+
Namespaces: utils.ListValueFrom[string](ctx, nil, types.StringType, path.Root("data_view").AtName("namespaces"), &diags),
112+
SourceFilters: types.ListNull(types.StringType),
113+
FieldAttributes: types.MapNull(getFieldAttrElemType()),
114+
RuntimeFieldMap: types.MapNull(getRuntimeFieldMapElemType()),
115+
FieldFormats: types.MapNull(getFieldFormatElemType()),
116+
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
117+
},
118+
response: kbapi.DataViewsDataViewResponseObject{
119+
DataView: &kbapi.DataViewsDataViewResponseObjectInner{
120+
Id: utils.Pointer("id"),
121+
Namespaces: &[]string{"default"},
122+
},
123+
},
124+
expectedModel: dataViewModel{
125+
ID: types.StringValue("default/id"),
126+
SpaceID: types.StringValue("default"),
127+
DataView: utils.ObjectValueFrom(ctx, &innerModel{
128+
ID: types.StringValue("id"),
129+
Namespaces: utils.ListValueFrom[string](ctx, nil, types.StringType, path.Root("data_view").AtName("namespaces"), &diags),
130+
SourceFilters: types.ListNull(types.StringType),
131+
FieldAttributes: types.MapNull(getFieldAttrElemType()),
132+
RuntimeFieldMap: types.MapNull(getRuntimeFieldMapElemType()),
133+
FieldFormats: types.MapNull(getFieldFormatElemType()),
134+
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
135+
},
136+
},
137+
{
138+
// When sending the SpaceID as the namespace, the response from Kibana should be the same
139+
name: "handleNamespaces_populated_default",
140+
existingModel: dataViewModel{
141+
ID: types.StringValue("space_id/dataview_id"),
142+
SpaceID: types.StringValue("space_id"),
143+
DataView: utils.ObjectValueFrom(ctx, &innerModel{
144+
ID: types.StringValue("dataview_id"),
145+
Namespaces: utils.ListValueFrom(ctx, []string{"space_id"}, types.StringType, path.Root("data_view").AtName("namespaces"), &diags),
146+
SourceFilters: types.ListNull(types.StringType),
147+
FieldAttributes: types.MapNull(getFieldAttrElemType()),
148+
RuntimeFieldMap: types.MapNull(getRuntimeFieldMapElemType()),
149+
FieldFormats: types.MapNull(getFieldFormatElemType()),
150+
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
151+
},
152+
response: kbapi.DataViewsDataViewResponseObject{
153+
DataView: &kbapi.DataViewsDataViewResponseObjectInner{
154+
Id: utils.Pointer("dataview_id"),
155+
Namespaces: &[]string{"space_id"},
156+
},
157+
},
158+
expectedModel: dataViewModel{
159+
ID: types.StringValue("space_id/dataview_id"),
160+
SpaceID: types.StringValue("space_id"),
161+
DataView: utils.ObjectValueFrom(ctx, &innerModel{
162+
ID: types.StringValue("dataview_id"),
163+
Namespaces: utils.ListValueFrom(ctx, []string{"space_id"}, types.StringType, path.Root("data_view").AtName("namespaces"), &diags),
164+
SourceFilters: types.ListNull(types.StringType),
165+
FieldAttributes: types.MapNull(getFieldAttrElemType()),
166+
RuntimeFieldMap: types.MapNull(getRuntimeFieldMapElemType()),
167+
FieldFormats: types.MapNull(getFieldFormatElemType()),
168+
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
169+
},
170+
},
171+
{
172+
// When sending a populated list, the response from Kibana should be the same list
173+
name: "handleNamespaces_populated_default",
174+
existingModel: dataViewModel{
175+
ID: types.StringValue("test/placeholder"),
176+
SpaceID: types.StringValue("test"),
177+
DataView: utils.ObjectValueFrom(ctx, &innerModel{
178+
ID: types.StringValue("placeholder"),
179+
Namespaces: utils.ListValueFrom(ctx, []string{"ns1", "ns2"}, types.StringType, path.Root("data_view").AtName("namespaces"), &diags),
180+
SourceFilters: types.ListNull(types.StringType),
181+
FieldAttributes: types.MapNull(getFieldAttrElemType()),
182+
RuntimeFieldMap: types.MapNull(getRuntimeFieldMapElemType()),
183+
FieldFormats: types.MapNull(getFieldFormatElemType()),
184+
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
185+
},
186+
response: kbapi.DataViewsDataViewResponseObject{
187+
DataView: &kbapi.DataViewsDataViewResponseObjectInner{
188+
Id: utils.Pointer("placeholder"),
189+
Namespaces: &[]string{"test", "ns1", "ns2"},
190+
},
191+
},
192+
expectedModel: dataViewModel{
193+
ID: types.StringValue("test/placeholder"),
194+
SpaceID: types.StringValue("test"),
195+
DataView: utils.ObjectValueFrom(ctx, &innerModel{
196+
ID: types.StringValue("placeholder"),
197+
Namespaces: utils.ListValueFrom(ctx, []string{"ns1", "ns2"}, types.StringType, path.Root("data_view").AtName("namespaces"), &diags),
198+
SourceFilters: types.ListNull(types.StringType),
199+
FieldAttributes: types.MapNull(getFieldAttrElemType()),
200+
RuntimeFieldMap: types.MapNull(getRuntimeFieldMapElemType()),
201+
FieldFormats: types.MapNull(getFieldFormatElemType()),
202+
}, getDataViewAttrTypes(), path.Root("data_view"), &diags),
203+
},
204+
},
103205
}
104206

105207
require.Empty(t, diags)
106208

107209
for _, tt := range tests {
108210
t.Run(tt.name, func(t *testing.T) {
109-
diags := tt.existingModel.populateFromAPI(ctx, &tt.response)
211+
diags := tt.existingModel.populateFromAPI(ctx, &tt.response, tt.existingModel.SpaceID.ValueString())
110212

111213
require.Equal(t, tt.expectedModel, tt.existingModel)
112214
require.Empty(t, diags)

internal/kibana/data_view/read.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (r *DataViewResource) Read(ctx context.Context, req resource.ReadRequest, r
3434
return
3535
}
3636

37-
diags = stateModel.populateFromAPI(ctx, dataView)
37+
diags = stateModel.populateFromAPI(ctx, dataView, spaceID)
3838
resp.Diagnostics.Append(diags...)
3939
if resp.Diagnostics.HasError() {
4040
return

internal/kibana/data_view/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (r *DataViewResource) Update(ctx context.Context, req resource.UpdateReques
3535
return
3636
}
3737

38-
diags = planModel.populateFromAPI(ctx, dataView)
38+
diags = planModel.populateFromAPI(ctx, dataView, spaceID)
3939
resp.Diagnostics.Append(diags...)
4040
if resp.Diagnostics.HasError() {
4141
return

0 commit comments

Comments
 (0)