Skip to content

Commit ab66f7a

Browse files
fix: filter cm fields not already present in resource (#319)
This would fix a lot of the inconsistent state issues which we see, where if we don't specify the exact keys that the API returns, the provider fails horribly. This also simplifies the config from a user perspective, since they don't have to specify every single key that the API returns. This means that from a TF perspective, the config becomes minimal in most cases. This relies on the fact that when we submit requests to the ApplyConfig endpoint, that only the cm fields specified are set; any other field that needs to be present in the data model relies on the API to set the correct defaults. Fixes #143
1 parent 9240b06 commit ab66f7a

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

akp/types/configmap.go

+38
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,44 @@ import (
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414
)
1515

16+
func ToFilteredConfigMapTFModel(ctx context.Context, diagnostics *diag.Diagnostics, data *structpb.Struct, oldCM tftypes.Map) tftypes.Map {
17+
if data == nil || len(data.AsMap()) == 0 {
18+
if !oldCM.IsUnknown() && (oldCM.IsNull() || len(oldCM.Elements()) == 0) {
19+
return oldCM
20+
}
21+
}
22+
23+
oldMap := make(map[string]interface{}, len(oldCM.Elements()))
24+
for k, v := range oldCM.Elements() {
25+
oldMap[k] = v
26+
}
27+
28+
m := data.AsMap()
29+
30+
// Only include values which are a part of the original resource map. The reason for doing so is that the API returns
31+
// a lot of fields which can cause TF to have an inconsistent state. We rely on the backend being able to do the right
32+
// thing in regard to PATCH requests; we don't actually need to have all the fields which the API returns in the state.
33+
for k := range oldMap {
34+
if v, ok := m[k]; ok {
35+
switch t := v.(type) {
36+
case string:
37+
sortedValue, err := sortJSONString(t)
38+
if err != nil {
39+
diagnostics.AddError("Client Error", fmt.Sprintf("Unable to sort JSON keys for key %s. %s", k, err))
40+
return tftypes.MapNull(tftypes.StringType)
41+
}
42+
oldMap[k] = sortedValue
43+
default:
44+
oldMap[k] = v
45+
}
46+
}
47+
}
48+
49+
newData, diag := tftypes.MapValueFrom(ctx, tftypes.StringType, &oldMap)
50+
diagnostics.Append(diag...)
51+
return newData
52+
}
53+
1654
func ToConfigMapTFModel(ctx context.Context, diagnostics *diag.Diagnostics, data *structpb.Struct, oldCM tftypes.Map) tftypes.Map {
1755
if data == nil || len(data.AsMap()) == 0 {
1856
if !oldCM.IsUnknown() && (oldCM.IsNull() || len(oldCM.Elements()) == 0) {

akp/types/instance.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (i *Instance) Update(ctx context.Context, diagnostics *diag.Diagnostics, ex
7070
argoCD.Spec.InstanceSpec.Fqdn = &fqdn
7171
}
7272
i.ArgoCD.Update(ctx, diagnostics, argoCD)
73-
i.ArgoCDConfigMap = ToConfigMapTFModel(ctx, diagnostics, exportResp.ArgocdConfigmap, i.ArgoCDConfigMap)
73+
i.ArgoCDConfigMap = ToFilteredConfigMapTFModel(ctx, diagnostics, exportResp.ArgocdConfigmap, i.ArgoCDConfigMap)
7474
i.ArgoCDRBACConfigMap = ToConfigMapTFModel(ctx, diagnostics, exportResp.ArgocdRbacConfigmap, i.ArgoCDRBACConfigMap)
7575
i.NotificationsConfigMap = ToConfigMapTFModel(ctx, diagnostics, exportResp.NotificationsConfigmap, i.NotificationsConfigMap)
7676
i.ImageUpdaterConfigMap = ToConfigMapTFModel(ctx, diagnostics, exportResp.ImageUpdaterConfigmap, i.ImageUpdaterConfigMap)

docs/resources/instance.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,12 @@ resource "akp_instance" "example" {
148148
}
149149
}
150150
argocd_cm = {
151-
# When configuring the `argocd_cm`, make sure to specify the following keys (from "admin.enabled", to "users.anonymous.enabled") since those keys are added by Akuity Platform by default.
152-
# If they are not defined, you may see inconsistent results and errors from the provider.
153-
# Feel free to customize the values based on your usage, but the keys themselves must be specified.
154-
# Note that "admin.enabled" cannot be set to true independently, and an "accounts.admin" key is required, like the "accounts.alice" key below, once you add that, remove the "admin.enabled" key.
155-
"admin.enabled" = false
151+
# When configuring `argocd_cm`, there is generally no need to set all of these keys. If you do not set a key, the API will set suitable default values.
152+
# Please note that the API will disallow the setting of any key which isn't a known configuration option in `argocd-cm`.
153+
#
154+
# NOTE:
155+
# `admin.enabled` can be set to `false` to disable the admin login.
156+
# To enable the admin account, set `accounts.admin: "login"`, and to disable the admin login, set `admin.enabled: false`. They are mutually exclusive.
156157
"exec.enabled" = true
157158
"ga.anonymizeusers" = false
158159
"helm.enabled" = true

examples/resources/akp_instance/resource.tf

+6-5
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ resource "akp_instance" "example" {
4646
}
4747
}
4848
argocd_cm = {
49-
# When configuring the `argocd_cm`, make sure to specify the following keys (from "admin.enabled", to "users.anonymous.enabled") since those keys are added by Akuity Platform by default.
50-
# If they are not defined, you may see inconsistent results and errors from the provider.
51-
# Feel free to customize the values based on your usage, but the keys themselves must be specified.
52-
# Note that "admin.enabled" cannot be set to true independently, and an "accounts.admin" key is required, like the "accounts.alice" key below, once you add that, remove the "admin.enabled" key.
53-
"admin.enabled" = false
49+
# When configuring `argocd_cm`, there is generally no need to set all of these keys. If you do not set a key, the API will set suitable default values.
50+
# Please note that the API will disallow the setting of any key which isn't a known configuration option in `argocd-cm`.
51+
#
52+
# NOTE:
53+
# `admin.enabled` can be set to `false` to disable the admin login.
54+
# To enable the admin account, set `accounts.admin: "login"`, and to disable the admin login, set `admin.enabled: false`. They are mutually exclusive.
5455
"exec.enabled" = true
5556
"ga.anonymizeusers" = false
5657
"helm.enabled" = true

0 commit comments

Comments
 (0)