Skip to content

Commit aeb99cf

Browse files
DrFaust92jrhouston
andauthored
Add immutable field to kubernetes_secret (#1280)
Co-authored-by: John Houston <[email protected]>
1 parent f0aaaa0 commit aeb99cf

File tree

6 files changed

+215
-58
lines changed

6 files changed

+215
-58
lines changed

kubernetes/data_source_kubernetes_secret.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ func dataSourceKubernetesSecret() *schema.Resource {
3131
Description: "Type of secret",
3232
Computed: true,
3333
},
34+
"immutable": {
35+
Type: schema.TypeBool,
36+
Description: "Ensures that data stored in the Secret cannot be updated (only object metadata can be modified).",
37+
Computed: true,
38+
},
3439
},
3540
}
3641
}

kubernetes/data_source_kubernetes_secret_test.go

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,36 @@ import (
1010

1111
func TestAccKubernetesDataSourceSecret_basic(t *testing.T) {
1212
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
13+
resourceName := "kubernetes_secret.test"
14+
datasourceName := "data.kubernetes_secret.test"
1315

1416
resource.Test(t, resource.TestCase{
1517
PreCheck: func() { testAccPreCheck(t) },
1618
ProviderFactories: testAccProviderFactories,
1719
Steps: []resource.TestStep{
1820
{
1921
Config: testAccKubernetesDataSourceSecretConfig_basic(name),
20-
Check: resource.ComposeAggregateTestCheckFunc(
21-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", name),
22-
resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"),
23-
resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"),
24-
resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"),
25-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "2"),
26-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationOne", "one"),
27-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationTwo", "two"),
28-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelOne", "one"),
29-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelTwo", "two"),
30-
resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelThree", "three"),
31-
resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "2"),
32-
resource.TestCheckResourceAttr("kubernetes_secret.test", "data.one", "first"),
33-
resource.TestCheckResourceAttr("kubernetes_secret.test", "data.two", "second"),
34-
resource.TestCheckResourceAttr("kubernetes_secret.test", "type", "Opaque"),
35-
resource.TestCheckResourceAttr("kubernetes_secret.test", "binary_data.raw", "UmF3IGRhdGEgc2hvdWxkIGNvbWUgYmFjayBhcyBpcyBpbiB0aGUgcG9k"),
36-
),
3722
},
3823
{
3924
Config: testAccKubernetesDataSourceSecretConfig_basic(name) +
4025
testAccKubernetesDataSourceSecretConfig_read(),
4126
Check: resource.ComposeAggregateTestCheckFunc(
42-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.name", name),
43-
resource.TestCheckResourceAttrSet("data.kubernetes_secret.test", "metadata.0.generation"),
44-
resource.TestCheckResourceAttrSet("data.kubernetes_secret.test", "metadata.0.resource_version"),
45-
resource.TestCheckResourceAttrSet("data.kubernetes_secret.test", "metadata.0.uid"),
46-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.annotations.%", "2"),
47-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.annotations.TestAnnotationOne", "one"),
48-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.annotations.TestAnnotationTwo", "two"),
49-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.labels.TestLabelOne", "one"),
50-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.labels.TestLabelTwo", "two"),
51-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "metadata.0.labels.TestLabelThree", "three"),
52-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "data.%", "2"),
53-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "data.one", "first"),
54-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "data.two", "second"),
55-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "type", "Opaque"),
56-
resource.TestCheckResourceAttr("data.kubernetes_secret.test", "binary_data.raw", "UmF3IGRhdGEgc2hvdWxkIGNvbWUgYmFjayBhcyBpcyBpbiB0aGUgcG9k"),
27+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.name", resourceName, "metadata.0.name"),
28+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.generation", resourceName, "metadata.0.generation"),
29+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.resource_version", resourceName, "metadata.0.resource_version"),
30+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.uid", resourceName, "metadata.0.uid"),
31+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.annotations.%", resourceName, "metadata.0.annotations.%"),
32+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.annotations.TestAnnotationOne", resourceName, "metadata.0.annotations.TestAnnotationOne"),
33+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.annotations.TestAnnotationTwo", resourceName, "metadata.0.annotations.TestAnnotationTwo"),
34+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.labels.TestLabelOne", resourceName, "metadata.0.labels.TestLabelOne"),
35+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.labels.TestLabelTwo", resourceName, "metadata.0.labels.TestLabelTwo"),
36+
resource.TestCheckResourceAttrPair(datasourceName, "metadata.0.labels.TestLabelThree", resourceName, "metadata.0.labels.TestLabelThree"),
37+
resource.TestCheckResourceAttrPair(datasourceName, "data.%", resourceName, "data.%"),
38+
resource.TestCheckResourceAttrPair(datasourceName, "data.one", resourceName, "data.one"),
39+
resource.TestCheckResourceAttrPair(datasourceName, "data.two", resourceName, "data.two"),
40+
resource.TestCheckResourceAttrPair(datasourceName, "type", resourceName, "type"),
41+
resource.TestCheckResourceAttrPair(datasourceName, "immutable", resourceName, "immutable"),
42+
resource.TestCheckResourceAttrPair(datasourceName, "binary_data.raw", resourceName, "binary_data.raw"),
5743
),
5844
},
5945
},
@@ -92,7 +78,7 @@ func testAccKubernetesDataSourceSecretConfig_basic(name string) string {
9278
func testAccKubernetesDataSourceSecretConfig_read() string {
9379
return fmt.Sprintf(`data "kubernetes_secret" "test" {
9480
metadata {
95-
name = "${kubernetes_secret.test.metadata.0.name}"
81+
name = kubernetes_secret.test.metadata.0.name
9682
}
9783
9884
binary_data = {

kubernetes/resource_kubernetes_secret.go

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,29 @@ func resourceKubernetesSecret() *schema.Resource {
2222
Importer: &schema.ResourceImporter{
2323
StateContext: schema.ImportStatePassthroughContext,
2424
},
25+
CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error {
26+
if diff.Id() == "" {
27+
return nil
28+
}
29+
30+
// ForceNew if immutable has been set to true
31+
// and there are any changes to data, binary_data, or immutable
32+
immutable, _ := diff.GetChange("immutable")
33+
if immutable.(bool) {
34+
immutableFields := []string{
35+
"data",
36+
"binary_data",
37+
"immutable",
38+
}
39+
for _, f := range immutableFields {
40+
if diff.HasChange(f) {
41+
diff.ForceNew(f)
42+
}
43+
}
44+
}
45+
46+
return nil
47+
},
2548

2649
Schema: map[string]*schema.Schema{
2750
"metadata": namespacedMetadataSchema("secret", true),
@@ -38,10 +61,15 @@ func resourceKubernetesSecret() *schema.Resource {
3861
Sensitive: true,
3962
Description: "A map of the secret data in base64 encoding. Use this for binary data.",
4063
},
64+
"immutable": {
65+
Type: schema.TypeBool,
66+
Optional: true,
67+
Description: "Ensures that data stored in the Secret cannot be updated (only object metadata can be modified).",
68+
},
4169
"type": {
4270
Type: schema.TypeString,
4371
Description: "Type of secret",
44-
Default: "Opaque",
72+
Default: string(api.SecretTypeOpaque),
4573
Optional: true,
4674
ForceNew: true,
4775
},
@@ -81,6 +109,10 @@ func resourceKubernetesSecretCreate(ctx context.Context, d *schema.ResourceData,
81109
secret.Type = api.SecretType(v.(string))
82110
}
83111

112+
if v, ok := d.GetOkExists("immutable"); ok {
113+
secret.Immutable = ptrToBool(v.(bool))
114+
}
115+
84116
log.Printf("[INFO] Creating new secret: %#v", secret)
85117
out, err := conn.CoreV1().Secrets(metadata.Namespace).Create(ctx, &secret, metav1.CreateOptions{})
86118
if err != nil {
@@ -139,6 +171,8 @@ func resourceKubernetesSecretRead(ctx context.Context, d *schema.ResourceData, m
139171
}
140172
d.Set("data", flattenByteMapToStringMap(secret.Data))
141173
d.Set("type", secret.Type)
174+
d.Set("immutable", secret.Immutable)
175+
142176
return nil
143177
}
144178

@@ -156,12 +190,14 @@ func resourceKubernetesSecretUpdate(ctx context.Context, d *schema.ResourceData,
156190
ops := patchMetadata("metadata.0.", "/metadata/", d)
157191

158192
newData := map[string]interface{}{}
193+
updateData := false
159194
if d.HasChange("data") {
160195
_, new := d.GetChange("data")
161196
new = base64EncodeStringMap(new.(map[string]interface{}))
162197
for k, v := range new.(map[string]interface{}) {
163198
newData[k] = v
164199
}
200+
updateData = true
165201
} else if v, ok := d.GetOk("data"); ok {
166202
for k, vv := range base64EncodeStringMap(v.(map[string]interface{})) {
167203
newData[k] = vv
@@ -172,16 +208,26 @@ func resourceKubernetesSecretUpdate(ctx context.Context, d *schema.ResourceData,
172208
for k, v := range new.(map[string]interface{}) {
173209
newData[k] = v
174210
}
211+
updateData = true
175212
} else if v, ok := d.GetOk("binary_data"); ok {
176213
for k, vv := range v.(map[string]interface{}) {
177214
newData[k] = vv
178215
}
179216
}
180217

181-
ops = append(ops, &AddOperation{
182-
Path: "/data",
183-
Value: newData,
184-
})
218+
if updateData {
219+
ops = append(ops, &AddOperation{
220+
Path: "/data",
221+
Value: newData,
222+
})
223+
}
224+
225+
if d.HasChange("immutable") {
226+
ops = append(ops, &ReplaceOperation{
227+
Path: "/immutable",
228+
Value: ptrToBool(d.Get("immutable").(bool)),
229+
})
230+
}
185231

186232
data, err := ops.MarshalJSON()
187233
if err != nil {

0 commit comments

Comments
 (0)