diff --git a/.changelog/2616.txt b/.changelog/2616.txt new file mode 100644 index 0000000000..65800ea206 --- /dev/null +++ b/.changelog/2616.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +Added support for the `binary_data` field in the `kubernetes_config_map_v1_data` resource. +``` \ No newline at end of file diff --git a/docs/resources/config_map_v1_data.md b/docs/resources/config_map_v1_data.md index 6b21810e79..3a6709d42f 100644 --- a/docs/resources/config_map_v1_data.md +++ b/docs/resources/config_map_v1_data.md @@ -18,7 +18,7 @@ This resource allows Terraform to manage data within a pre-existing ConfigMap. T - `metadata` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--metadata)) ### Optional - +- `binary_data` (Map of String) BinaryData contains the binary data. Each key must consist of alphanumeric characters, '-', '_' or '.'. BinaryData can contain byte sequences that are not in the UTF-8 range. The keys stored in BinaryData must not overlap with the ones in the Data field, this is enforced during validation process. Using this field will require 1.10+ apiserver and kubelet. This field only accepts base64-encoded payloads that will be decoded/encoded before being sent/received to/from the apiserver. - `field_manager` (String) Set the name of the field manager for the specified labels. - `force` (Boolean) Force overwriting data that is managed outside of Terraform. @@ -50,6 +50,9 @@ resource "kubernetes_config_map_v1_data" "example" { data = { "owner" = "myteam" } + binary_data = { + "logo.png" = "HxShiC0rp..." + } } ``` diff --git a/kubernetes/resource_kubernetes_config_map_v1_data.go b/kubernetes/resource_kubernetes_config_map_v1_data.go index 7b450ead19..f17d8ce54c 100644 --- a/kubernetes/resource_kubernetes_config_map_v1_data.go +++ b/kubernetes/resource_kubernetes_config_map_v1_data.go @@ -49,9 +49,17 @@ func resourceKubernetesConfigMapV1Data() *schema.Resource { }, }, "data": { - Type: schema.TypeMap, - Description: "The data we want to add to the ConfigMap.", - Required: true, + Type: schema.TypeMap, + Description: "The data we want to add to the ConfigMap.", + AtLeastOneOf: []string{"data", "binary_data"}, + Optional: true, + }, + "binary_data": { + Type: schema.TypeMap, + Description: "BinaryData contains the binary data. Each key must consist of alphanumeric characters, '-', '_' or '.'. BinaryData can contain byte sequences that are not in the UTF-8 range. The keys stored in BinaryData must not overlap with the ones in the Data field, this is enforced during validation process. Using this field will require 1.10+ apiserver and kubelet. This field only accepts base64-encoded payloads that will be decoded/encoded before being sent/received to/from the apiserver.", + Optional: true, + AtLeastOneOf: []string{"data", "binary_data"}, + ValidateFunc: validateBase64EncodedMap, }, "force": { Type: schema.TypeBool, @@ -120,6 +128,7 @@ func resourceKubernetesConfigMapV1DataRead(ctx context.Context, d *schema.Resour } d.Set("data", data) + d.Set("binary_data", flattenByteMapToBase64Map(res.BinaryData)) return nil } @@ -169,6 +178,7 @@ func resourceKubernetesConfigMapV1DataUpdate(ctx context.Context, d *schema.Reso // craft the patch to update the data data := d.Get("data") + binaryData := expandBase64MapToByteMap(d.Get("binary_data").(map[string]interface{})) if d.Id() == "" { // if we're deleting then just we just patch // with an empty data map @@ -181,7 +191,8 @@ func resourceKubernetesConfigMapV1DataUpdate(ctx context.Context, d *schema.Reso "name": name, "namespace": namespace, }, - "data": data, + "data": data, + "binaryData": binaryData, } patch := unstructured.Unstructured{} patch.Object = patchobj diff --git a/kubernetes/resource_kubernetes_config_map_v1_data_test.go b/kubernetes/resource_kubernetes_config_map_v1_data_test.go index c17a2827dd..b50d099aba 100644 --- a/kubernetes/resource_kubernetes_config_map_v1_data_test.go +++ b/kubernetes/resource_kubernetes_config_map_v1_data_test.go @@ -5,6 +5,8 @@ package kubernetes import ( "fmt" + "os" + "path/filepath" "regexp" "testing" @@ -88,6 +90,53 @@ func TestAccKubernetesConfigMapV1Data_validation(t *testing.T) { }) } +func TestAccKubernetesConfigMapV1Data_binaryData(t *testing.T) { + name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + resourceName := "kubernetes_config_map_v1_data.test" + baseDir := "." + cwd, _ := os.Getwd() + if filepath.Base(cwd) != "kubernetes" { // running from test binary + baseDir = "kubernetes" + } + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + createConfigMap(name, "default") + }, + IDRefreshName: resourceName, + IDRefreshIgnore: []string{"metadata.0.resource_version"}, + ProviderFactories: testAccProviderFactories, + CheckDestroy: func(s *terraform.State) error { + return destroyConfigMap(name, "default") + }, + Steps: []resource.TestStep{ + + { + Config: testAccKubernetesConfigMapV1Data_binaryData(name, baseDir), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "data.%", "1"), + resource.TestCheckResourceAttr(resourceName, "data.text", "initial data"), + resource.TestCheckResourceAttr(resourceName, "binary_data.%", "1"), + resource.TestCheckResourceAttrSet(resourceName, "binary_data.binary1"), + ), + }, + + { + Config: testAccKubernetesConfigMapV1Data_binaryDataUpdated(name, baseDir), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "data.%", "1"), + resource.TestCheckResourceAttr(resourceName, "data.text", "updated data"), + resource.TestCheckResourceAttr(resourceName, "binary_data.%", "3"), + resource.TestCheckResourceAttrSet(resourceName, "binary_data.binary1"), + resource.TestCheckResourceAttrSet(resourceName, "binary_data.binary2"), + resource.TestCheckResourceAttr(resourceName, "binary_data.inline_binary", "UmF3IGlubGluZSBkYXRh"), + ), + }, + }, + }) +} + func testAccKubernetesConfigMapV1Data_empty(name string) string { return fmt.Sprintf(`resource "kubernetes_config_map_v1_data" "test" { metadata { @@ -126,3 +175,43 @@ func testAccKubernetesConfigMapV1Data_modified(name string) string { } `, name) } + +func testAccKubernetesConfigMapV1Data_binaryData(name string, baseDir string) string { + return fmt.Sprintf(`resource "kubernetes_config_map_v1_data" "test" { + metadata { + name = %q + } + + data = { + "text" = "initial data" + } + + binary_data = { + "binary1" = "${filebase64("%s/test-fixtures/binary.data")}" + } + + field_manager = "tftest" +} +`, name, baseDir) +} + +func testAccKubernetesConfigMapV1Data_binaryDataUpdated(name string, baseDir string) string { + return fmt.Sprintf(`resource "kubernetes_config_map_v1_data" "test" { + metadata { + name = %q + } + + data = { + "text" = "updated data" + } + + binary_data = { + "binary1" = "${filebase64("%s/test-fixtures/binary.data")}" + "binary2" = "${filebase64("%s/test-fixtures/binary2.data")}" + "inline_binary" = "${base64encode("Raw inline data")}" + } + + field_manager = "tftest" +} +`, name, baseDir, baseDir) +}