-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: Implements tags
and labels
as MapAttribute in advanced_cluster
schema v2
#2996
Changes from all commits
623161a
214906b
8fd6649
99cde29
fdc1bf0
3653edc
241f8b0
360c86e
e150067
86314a9
bf19829
c3aceeb
1198109
0067508
35900d4
f24f8dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,9 +30,9 @@ type ExtraAPIInfo struct { | |
func NewTFModel(ctx context.Context, input *admin.ClusterDescription20240805, timeout timeouts.Value, diags *diag.Diagnostics, apiInfo ExtraAPIInfo) *TFModel { | ||
biConnector := NewBiConnectorConfigObjType(ctx, input.BiConnector, diags) | ||
connectionStrings := NewConnectionStringsObjType(ctx, input.ConnectionStrings, diags) | ||
labels := NewLabelsObjType(ctx, input.Labels, diags) | ||
labels := NewLabelsObjType(ctx, diags, input.Labels) | ||
replicationSpecs := NewReplicationSpecsObjType(ctx, input.ReplicationSpecs, diags, &apiInfo) | ||
tags := NewTagsObjType(ctx, input.Tags, diags) | ||
tags := NewTagsObjType(ctx, diags, input.Tags) | ||
pinnedFCV := NewPinnedFCVObjType(ctx, input, diags) | ||
if diags.HasError() { | ||
return nil | ||
|
@@ -100,22 +100,19 @@ func NewConnectionStringsObjType(ctx context.Context, input *admin.ClusterConnec | |
return objType | ||
} | ||
|
||
func NewLabelsObjType(ctx context.Context, input *[]admin.ComponentLabel, diags *diag.Diagnostics) types.Set { | ||
if input == nil { | ||
return types.SetNull(LabelsObjType) | ||
} | ||
tfModels := make([]TFLabelsModel, 0, len(*input)) | ||
for _, item := range *input { | ||
key := conversion.SafeValue(item.Key) | ||
value := conversion.SafeValue(item.Value) | ||
if key == LegacyIgnoredLabelKey { | ||
continue | ||
func NewLabelsObjType(ctx context.Context, diags *diag.Diagnostics, input *[]admin.ComponentLabel) types.Map { | ||
elms := make(map[string]string) | ||
if input != nil { | ||
for _, item := range *input { | ||
key := item.GetKey() | ||
value := item.GetValue() | ||
if key == LegacyIgnoredLabelKey { | ||
continue | ||
} | ||
elms[key] = value | ||
} | ||
tfModels = append(tfModels, TFLabelsModel{Key: types.StringValue(key), Value: types.StringValue(value)}) | ||
} | ||
setType, diagsLocal := types.SetValueFrom(ctx, LabelsObjType, tfModels) | ||
diags.Append(diagsLocal...) | ||
return setType | ||
return conversion.ToTFMapOfString(ctx, diags, &elms) | ||
} | ||
|
||
func NewReplicationSpecsObjType(ctx context.Context, input *[]admin.ReplicationSpec20240805, diags *diag.Diagnostics, apiInfo *ExtraAPIInfo) types.List { | ||
|
@@ -235,21 +232,14 @@ func convertReplicationSpecsLegacy(ctx context.Context, input *[]admin.Replicati | |
return &tfModels | ||
} | ||
|
||
func NewTagsObjType(ctx context.Context, input *[]admin.ResourceTag, diags *diag.Diagnostics) types.Set { | ||
if input == nil { | ||
// API Response not consistent, even when not set in POST/PATCH `[]` is returned instead of null | ||
return types.SetValueMust(TagsObjType, nil) | ||
} | ||
tfModels := make([]TFTagsModel, len(*input)) | ||
for i, item := range *input { | ||
tfModels[i] = TFTagsModel{ | ||
Key: types.StringValue(item.Key), | ||
Value: types.StringValue(item.Value), | ||
func NewTagsObjType(ctx context.Context, diags *diag.Diagnostics, input *[]admin.ResourceTag) types.Map { | ||
elms := make(map[string]string) | ||
if input != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice refactor! |
||
for _, item := range *input { | ||
elms[item.GetKey()] = item.GetValue() | ||
} | ||
} | ||
setType, diagsLocal := types.SetValueFrom(ctx, TagsObjType, tfModels) | ||
diags.Append(diagsLocal...) | ||
return setType | ||
return conversion.ToTFMapOfString(ctx, diags, &elms) | ||
} | ||
|
||
func NewPrivateEndpointObjType(ctx context.Context, input *[]admin.ClusterDescriptionConnectionStringsPrivateEndpoint, diags *diag.Diagnostics) types.List { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,11 @@ func setStateResponse(ctx context.Context, diags *diag.Diagnostics, stateIn *tfp | |
return | ||
} | ||
setOptionalModelAttrs(ctx, stateObj, model) | ||
|
||
// Set tags and labels to null instead of empty so there is no plan change if there are no tags or labels when Read is called. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you had to learn this the hard way? If you do nothing they are set to empty map? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ha ha, exactly |
||
model.Tags = types.MapNull(types.StringType) | ||
model.Labels = types.MapNull(types.StringType) | ||
|
||
diags.Append(stateOut.Set(ctx, model)...) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,18 @@ func overrideAttributesWithPrevStateValue(modelIn, modelOut *TFModel) { | |
if retainBackups != nil && !modelIn.RetainBackupsEnabled.Equal(modelOut.RetainBackupsEnabled) { | ||
modelOut.RetainBackupsEnabled = types.BoolPointerValue(retainBackups) | ||
} | ||
overrideMapStringWithPrevStateValue(&modelIn.Labels, &modelOut.Labels) | ||
overrideMapStringWithPrevStateValue(&modelIn.Tags, &modelOut.Tags) | ||
} | ||
func overrideMapStringWithPrevStateValue(mapIn, mapOut *types.Map) { | ||
Comment on lines
+25
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see for cases of the empty lists/map we sometimes go for setting nil directly (example) or in cases like this one support defining the empty map in the config. I would assess what is the drawback UX wise if we dont have this logic to avoid relying on previous state is not ideal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. discussed offline |
||
if mapIn == nil || mapOut == nil || len(mapOut.Elements()) > 0 { | ||
return | ||
} | ||
if mapIn.IsNull() { | ||
*mapOut = types.MapNull(types.StringType) | ||
} else { | ||
*mapOut = types.MapValueMust(types.StringType, nil) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice usage of |
||
} | ||
} | ||
|
||
func findNumShardsUpdates(ctx context.Context, state, plan *TFModel, diags *diag.Diagnostics) map[string]int64 { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @EspenAlbert for the tips for checking maps