Skip to content

Commit a85e5b9

Browse files
authored
Add binary_data attribute to kubernetes_secret (#1228)
* Add binary_data attribute to kubernetes_secret * Make data a computed field
1 parent f9aeea9 commit a85e5b9

File tree

4 files changed

+143
-54
lines changed

4 files changed

+143
-54
lines changed

kubernetes/resource_kubernetes_secret.go

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,15 @@ func resourceKubernetesSecret() *schema.Resource {
2929
Type: schema.TypeMap,
3030
Description: "A map of the secret data.",
3131
Optional: true,
32+
Computed: true,
3233
Sensitive: true,
3334
},
35+
"binary_data": {
36+
Type: schema.TypeMap,
37+
Optional: true,
38+
Sensitive: true,
39+
Description: "A map of the secret data in base64 encoding. Use this for binary data.",
40+
},
3441
"type": {
3542
Type: schema.TypeString,
3643
Description: "Type of secret",
@@ -51,7 +58,23 @@ func resourceKubernetesSecretCreate(ctx context.Context, d *schema.ResourceData,
5158
metadata := expandMetadata(d.Get("metadata").([]interface{}))
5259
secret := api.Secret{
5360
ObjectMeta: metadata,
54-
Data: expandStringMapToByteMap(d.Get("data").(map[string]interface{})),
61+
}
62+
63+
if v, ok := d.GetOk("data"); ok {
64+
m := map[string]string{}
65+
for k, v := range v.(map[string]interface{}) {
66+
vv := v.(string)
67+
m[k] = vv
68+
}
69+
secret.StringData = m
70+
}
71+
72+
if v, ok := d.GetOk("binary_data"); ok {
73+
m, err := base64DecodeStringMap(v.(map[string]interface{}))
74+
if err != nil {
75+
return diag.FromErr(err)
76+
}
77+
secret.Data = m
5578
}
5679

5780
if v, ok := d.GetOk("type"); ok {
@@ -101,9 +124,21 @@ func resourceKubernetesSecretRead(ctx context.Context, d *schema.ResourceData, m
101124
return diag.FromErr(err)
102125
}
103126

127+
binaryDataKeys := []string{}
128+
if v, ok := d.GetOk("binary_data"); ok {
129+
binaryData := map[string][]byte{}
130+
for k := range v.(map[string]interface{}) {
131+
binaryData[k] = secret.Data[k]
132+
binaryDataKeys = append(binaryDataKeys, k)
133+
}
134+
d.Set("binary_data", base64EncodeByteMap(binaryData))
135+
}
136+
137+
for _, k := range binaryDataKeys {
138+
delete(secret.Data, k)
139+
}
104140
d.Set("data", flattenByteMapToStringMap(secret.Data))
105141
d.Set("type", secret.Type)
106-
107142
return nil
108143
}
109144

@@ -119,17 +154,35 @@ func resourceKubernetesSecretUpdate(ctx context.Context, d *schema.ResourceData,
119154
}
120155

121156
ops := patchMetadata("metadata.0.", "/metadata/", d)
122-
if d.HasChange("data") {
123-
oldV, newV := d.GetChange("data")
124157

125-
oldV = base64EncodeStringMap(oldV.(map[string]interface{}))
126-
newV = base64EncodeStringMap(newV.(map[string]interface{}))
127-
128-
diffOps := diffStringMap("/data/", oldV.(map[string]interface{}), newV.(map[string]interface{}))
129-
130-
ops = append(ops, diffOps...)
158+
newData := map[string]interface{}{}
159+
if d.HasChange("data") {
160+
_, new := d.GetChange("data")
161+
new = base64EncodeStringMap(new.(map[string]interface{}))
162+
for k, v := range new.(map[string]interface{}) {
163+
newData[k] = v
164+
}
165+
} else if v, ok := d.GetOk("data"); ok {
166+
for k, vv := range base64EncodeStringMap(v.(map[string]interface{})) {
167+
newData[k] = vv
168+
}
169+
}
170+
if d.HasChange("binary_data") {
171+
_, new := d.GetChange("binary_data")
172+
for k, v := range new.(map[string]interface{}) {
173+
newData[k] = v
174+
}
175+
} else if v, ok := d.GetOk("binary_data"); ok {
176+
for k, vv := range v.(map[string]interface{}) {
177+
newData[k] = vv
178+
}
131179
}
132180

181+
ops = append(ops, &AddOperation{
182+
Path: "/data",
183+
Value: newData,
184+
})
185+
133186
data, err := ops.MarshalJSON()
134187
if err != nil {
135188
return diag.Errorf("Failed to marshal update operations: %s", err)

kubernetes/resource_kubernetes_secret_test.go

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -194,38 +194,41 @@ func TestAccKubernetesSecret_generatedName(t *testing.T) {
194194
})
195195
}
196196

197-
// Disabled - this test loads binary data from a file and passes it through configuration
198-
// which is no longer supported in TF 0.12.
199-
// Instead, the resource attribute should be adapted to transport base64 encoded
200-
// data and decode it when constructing the API object for client-go.
201-
//
202-
// func TestAccKubernetesSecret_binaryData(t *testing.T) {
203-
// var conf api.Secret
204-
// prefix := "tf-acc-test-gen-"
205-
//
206-
// resource.Test(t, resource.TestCase{
207-
// PreCheck: func() { testAccPreCheck(t) },
208-
// IDRefreshName: "kubernetes_secret.test",
209-
// ProviderFactories: testAccProviderFactories,
210-
// CheckDestroy: testAccCheckKubernetesSecretDestroy,
211-
// Steps: []resource.TestStep{
212-
// {
213-
// Config: testAccKubernetesSecretConfig_binaryData(prefix),
214-
// Check: resource.ComposeAggregateTestCheckFunc(
215-
// testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf),
216-
// resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "1"),
217-
// ),
218-
// },
219-
// {
220-
// Config: testAccKubernetesSecretConfig_binaryData2(prefix),
221-
// Check: resource.ComposeAggregateTestCheckFunc(
222-
// testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf),
223-
// resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "2"),
224-
// ),
225-
// },
226-
// },
227-
// })
228-
// }
197+
func TestAccKubernetesSecret_binaryData(t *testing.T) {
198+
var conf api.Secret
199+
prefix := "tf-acc-test-gen-"
200+
201+
resource.Test(t, resource.TestCase{
202+
PreCheck: func() { testAccPreCheck(t) },
203+
IDRefreshName: "kubernetes_secret.test",
204+
ProviderFactories: testAccProviderFactories,
205+
CheckDestroy: testAccCheckKubernetesSecretDestroy,
206+
Steps: []resource.TestStep{
207+
{
208+
Config: testAccKubernetesSecretConfig_binaryData(prefix),
209+
Check: resource.ComposeAggregateTestCheckFunc(
210+
testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf),
211+
resource.TestCheckResourceAttr("kubernetes_secret.test", "binary_data.%", "1"),
212+
),
213+
},
214+
{
215+
Config: testAccKubernetesSecretConfig_binaryData2(prefix),
216+
Check: resource.ComposeAggregateTestCheckFunc(
217+
testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf),
218+
resource.TestCheckResourceAttr("kubernetes_secret.test", "binary_data.%", "2"),
219+
),
220+
},
221+
{
222+
Config: testAccKubernetesSecretConfig_binaryDataCombined(prefix),
223+
Check: resource.ComposeAggregateTestCheckFunc(
224+
testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf),
225+
resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "2"),
226+
resource.TestCheckResourceAttr("kubernetes_secret.test", "binary_data.%", "2"),
227+
),
228+
},
229+
},
230+
})
231+
}
229232

230233
func testAccCheckSecretData(m *api.Secret, expected map[string]string) resource.TestCheckFunc {
231234
return func(s *terraform.State) error {
@@ -382,6 +385,8 @@ func testAccKubernetesSecretConfig_noData(name string) string {
382385
metadata {
383386
name = "%s"
384387
}
388+
389+
data = {}
385390
}
386391
`, name)
387392
}
@@ -422,11 +427,8 @@ func testAccKubernetesSecretConfig_binaryData(prefix string) string {
422427
generate_name = "%s"
423428
}
424429
425-
data = {
426-
one = <<EOF
427-
"${filebase64("./test-fixtures/binary.data")}"
428-
EOF
429-
430+
binary_data = {
431+
one = filebase64("./test-fixtures/binary.data")
430432
}
431433
}
432434
`, prefix)
@@ -438,15 +440,28 @@ func testAccKubernetesSecretConfig_binaryData2(prefix string) string {
438440
generate_name = "%s"
439441
}
440442
441-
data = {
442-
one = <<EOF
443-
"${filebase64("./test-fixtures/binary2.data")}"
444-
EOF
443+
binary_data = {
444+
one = filebase64("./test-fixtures/binary.data")
445+
two = filebase64("./test-fixtures/binary2.data")
446+
}
447+
}
448+
`, prefix)
449+
}
450+
451+
func testAccKubernetesSecretConfig_binaryDataCombined(prefix string) string {
452+
return fmt.Sprintf(`resource "kubernetes_secret" "test" {
453+
metadata {
454+
generate_name = "%s"
455+
}
445456
446-
two = <<EOF
447-
"${filebase64("./test-fixtures/binary.data")}"
448-
EOF
457+
data = {
458+
"HOST" = "127.0.0.1"
459+
"PORT" = "80"
460+
}
449461
462+
binary_data = {
463+
one = filebase64("./test-fixtures/binary.data")
464+
two = filebase64("./test-fixtures/binary2.data")
450465
}
451466
}
452467
`, prefix)

kubernetes/structures.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,26 @@ func base64EncodeStringMap(m map[string]interface{}) map[string]interface{} {
218218
return result
219219
}
220220

221+
func base64EncodeByteMap(m map[string][]byte) map[string]interface{} {
222+
result := map[string]interface{}{}
223+
for k, v := range m {
224+
result[k] = base64.StdEncoding.EncodeToString(v)
225+
}
226+
return result
227+
}
228+
229+
func base64DecodeStringMap(m map[string]interface{}) (map[string][]byte, error) {
230+
mm := map[string][]byte{}
231+
for k, v := range m {
232+
d, err := base64.StdEncoding.DecodeString(v.(string))
233+
if err != nil {
234+
return nil, err
235+
}
236+
mm[k] = []byte(d)
237+
}
238+
return mm, nil
239+
}
240+
221241
func flattenResourceList(l api.ResourceList) map[string]string {
222242
m := make(map[string]string)
223243
for k, v := range l {

website/docs/r/secret.html.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ resource "kubernetes_secret" "example" {
9999
The following arguments are supported:
100100

101101
* `data` - (Optional) A map of the secret data.
102+
* `binary_data` - (Optional) A map base64 encoded map of the secret data.
102103
* `metadata` - (Required) Standard secret's metadata. For more info see [Kubernetes reference](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata)
103104
* `type` - (Optional) The secret type. Defaults to `Opaque`. For more info see [Kubernetes reference](https://github.com/kubernetes/community/blob/c7151dd8dd7e487e96e5ce34c6a416bb3b037609/contributors/design-proposals/auth/secrets.md#proposed-design)
104105

0 commit comments

Comments
 (0)