Skip to content

Commit

Permalink
Added support for annotations field in google_secret_manager_secret r…
Browse files Browse the repository at this point in the history
…esource (#8500)

* Added support for annotations field in google_secret_manager_secret resource

* Adjusted white spaces in Secret.yaml

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician committed Aug 3, 2023
1 parent 3675547 commit 0b7d5f0
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/8500.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
secretmanager: added `annotations` field to `google_secret_manager_secret` resource
```
49 changes: 49 additions & 0 deletions google/resource_secret_manager_secret_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,55 @@ resource "google_secret_manager_secret" "secret-basic" {
`, context)
}

func TestAccSecretManagerSecret_secretWithAnnotationsExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckSecretManagerSecretDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccSecretManagerSecret_secretWithAnnotationsExample(context),
},
{
ResourceName: "google_secret_manager_secret.secret-with-annotations",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ttl", "secret_id"},
},
},
})
}

func testAccSecretManagerSecret_secretWithAnnotationsExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_secret_manager_secret" "secret-with-annotations" {
secret_id = "secret%{random_suffix}"
labels = {
label = "my-label"
}
annotations = {
key1 = "someval"
key2 = "someval2"
key3 = "someval3"
key4 = "someval4"
key5 = "someval5"
}
replication {
automatic = true
}
}
`, context)
}

func testAccCheckSecretManagerSecretDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
Expand Down
90 changes: 90 additions & 0 deletions google/resource_secret_manager_secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,49 @@ func TestAccSecretManagerSecret_cmek(t *testing.T) {
})
}

func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckSecretManagerSecretDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccSecretManagerSecret_annotationsBasic(context),
},
{
ResourceName: "google_secret_manager_secret.secret-with-annotations",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ttl"},
},
{
Config: testAccSecretManagerSecret_annotationsUpdate(context),
},
{
ResourceName: "google_secret_manager_secret.secret-with-annotations",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ttl"},
},
{
Config: testAccSecretManagerSecret_annotationsBasic(context),
},
{
ResourceName: "google_secret_manager_secret.secret-with-annotations",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ttl"},
},
},
})
}

func testAccSecretManagerSecret_basic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_secret_manager_secret" "secret-basic" {
Expand Down Expand Up @@ -128,3 +171,50 @@ resource "google_secret_manager_secret" "secret-basic" {
}
`, context)
}

func testAccSecretManagerSecret_annotationsBasic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_secret_manager_secret" "secret-with-annotations" {
secret_id = "tf-test-secret-%{random_suffix}"
labels = {
label = "my-label"
}
annotations = {
key1 = "someval"
key2 = "someval2"
key3 = "someval3"
key4 = "someval4"
key5 = "someval5"
}
replication {
automatic = true
}
}
`, context)
}

func testAccSecretManagerSecret_annotationsUpdate(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_secret_manager_secret" "secret-with-annotations" {
secret_id = "tf-test-secret-%{random_suffix}"
labels = {
label = "my-label"
}
annotations = {
key1 = "someval"
key2update = "someval2"
key3 = "someval3update"
key4update = "someval4update"
}
replication {
automatic = true
}
}
`, context)
}
53 changes: 53 additions & 0 deletions google/services/secretmanager/resource_secret_manager_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,25 @@ after the Secret has been created.`,
ForceNew: true,
Description: `This must be unique within the project.`,
},
"annotations": {
Type: schema.TypeMap,
Optional: true,
Description: `Custom metadata about the secret.
Annotations are distinct from various forms of labels. Annotations exist to allow
client tools to store their own state information without requiring a database.
Annotation keys must be between 1 and 63 characters long, have a UTF-8 encoding of
maximum 128 bytes, begin and end with an alphanumeric character ([a-z0-9A-Z]), and
may have dashes (-), underscores (_), dots (.), and alphanumerics in between these
symbols.
The total size of annotation keys and values must be less than 16KiB.
An object containing a list of "key": value pairs. Example:
{ "name": "wrench", "mass": "1.3kg", "count": "3" }.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"expire_time": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -226,6 +245,12 @@ func resourceSecretManagerSecretCreate(d *schema.ResourceData, meta interface{})
} else if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
annotationsProp, err := expandSecretManagerSecretAnnotations(d.Get("annotations"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("annotations"); !tpgresource.IsEmptyValue(reflect.ValueOf(annotationsProp)) && (ok || !reflect.DeepEqual(v, annotationsProp)) {
obj["annotations"] = annotationsProp
}
replicationProp, err := expandSecretManagerSecretReplication(d.Get("replication"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -353,6 +378,9 @@ func resourceSecretManagerSecretRead(d *schema.ResourceData, meta interface{}) e
if err := d.Set("labels", flattenSecretManagerSecretLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Secret: %s", err)
}
if err := d.Set("annotations", flattenSecretManagerSecretAnnotations(res["annotations"], d, config)); err != nil {
return fmt.Errorf("Error reading Secret: %s", err)
}
if err := d.Set("replication", flattenSecretManagerSecretReplication(res["replication"], d, config)); err != nil {
return fmt.Errorf("Error reading Secret: %s", err)
}
Expand Down Expand Up @@ -391,6 +419,12 @@ func resourceSecretManagerSecretUpdate(d *schema.ResourceData, meta interface{})
} else if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
annotationsProp, err := expandSecretManagerSecretAnnotations(d.Get("annotations"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("annotations"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, annotationsProp)) {
obj["annotations"] = annotationsProp
}
topicsProp, err := expandSecretManagerSecretTopics(d.Get("topics"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -422,6 +456,10 @@ func resourceSecretManagerSecretUpdate(d *schema.ResourceData, meta interface{})
updateMask = append(updateMask, "labels")
}

if d.HasChange("annotations") {
updateMask = append(updateMask, "annotations")
}

if d.HasChange("topics") {
updateMask = append(updateMask, "topics")
}
Expand Down Expand Up @@ -541,6 +579,10 @@ func flattenSecretManagerSecretLabels(v interface{}, d *schema.ResourceData, con
return v
}

func flattenSecretManagerSecretAnnotations(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenSecretManagerSecretReplication(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
Expand Down Expand Up @@ -673,6 +715,17 @@ func expandSecretManagerSecretLabels(v interface{}, d tpgresource.TerraformResou
return m, nil
}

func expandSecretManagerSecretAnnotations(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}

func expandSecretManagerSecretReplication(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
Expand Down
42 changes: 42 additions & 0 deletions website/docs/r/secret_manager_secret.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,35 @@ resource "google_secret_manager_secret" "secret-basic" {
}
}
```
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_working_dir=secret_with_annotations&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
</a>
</div>
## Example Usage - Secret With Annotations


```hcl
resource "google_secret_manager_secret" "secret-with-annotations" {
secret_id = "secret"
labels = {
label = "my-label"
}
annotations = {
key1 = "someval"
key2 = "someval2"
key3 = "someval3"
key4 = "someval4"
key5 = "someval5"
}
replication {
automatic = true
}
}
```

## Argument Reference

Expand Down Expand Up @@ -123,6 +152,19 @@ The following arguments are supported:
An object containing a list of "key": value pairs. Example:
{ "name": "wrench", "mass": "1.3kg", "count": "3" }.

* `annotations` -
(Optional)
Custom metadata about the secret.
Annotations are distinct from various forms of labels. Annotations exist to allow
client tools to store their own state information without requiring a database.
Annotation keys must be between 1 and 63 characters long, have a UTF-8 encoding of
maximum 128 bytes, begin and end with an alphanumeric character ([a-z0-9A-Z]), and
may have dashes (-), underscores (_), dots (.), and alphanumerics in between these
symbols.
The total size of annotation keys and values must be less than 16KiB.
An object containing a list of "key": value pairs. Example:
{ "name": "wrench", "mass": "1.3kg", "count": "3" }.

* `topics` -
(Optional)
A list of up to 10 Pub/Sub topics to which messages are published when control plane operations are called on the secret or its versions.
Expand Down

0 comments on commit 0b7d5f0

Please sign in to comment.