Skip to content

Commit

Permalink
Fix: var.enabled for Parameter Read, Testing Suite Overhaul (#33)
Browse files Browse the repository at this point in the history
Co-authored-by: cloudpossebot <[email protected]>
  • Loading branch information
korenyoni and cloudpossebot authored Oct 18, 2021
1 parent 712156c commit 7ab272c
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 24 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ This example creates a new `String` parameter called `/cp/prod/app/database/mast

```hcl
module "store_write" {
source = "git::https://github.com/cloudposse/terraform-aws-ssm-parameter-store?ref=master"
source = "cloudposse/ssm-parameter-store/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
parameter_write = [
{
Expand All @@ -131,7 +133,10 @@ This example reads a value from the parameter store with the name `/cp/prod/app/

```hcl
module "store_read" {
source = "git::https://github.com/cloudposse/terraform-aws-ssm-parameter-store?ref=master"
source = "cloudposse/ssm-parameter-store/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
parameter_read = ["/cp/prod/app/database/master_password"]
}
```
Expand Down Expand Up @@ -367,8 +372,8 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply
### Contributors

<!-- markdownlint-disable -->
| [![Erik Osterman][osterman_avatar]][osterman_homepage]<br/>[Erik Osterman][osterman_homepage] | [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]<br/>[Andriy Knysh][aknysh_homepage] | [![Jamie Nelson][Jamie-BitFlight_avatar]][Jamie-BitFlight_homepage]<br/>[Jamie Nelson][Jamie-BitFlight_homepage] | [![Matt Gowie][Gowiem_avatar]][Gowiem_homepage]<br/>[Matt Gowie][Gowiem_homepage] |
|---|---|---|---|
| [![Erik Osterman][osterman_avatar]][osterman_homepage]<br/>[Erik Osterman][osterman_homepage] | [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]<br/>[Andriy Knysh][aknysh_homepage] | [![Jamie Nelson][Jamie-BitFlight_avatar]][Jamie-BitFlight_homepage]<br/>[Jamie Nelson][Jamie-BitFlight_homepage] | [![Matt Gowie][Gowiem_avatar]][Gowiem_homepage]<br/>[Matt Gowie][Gowiem_homepage] | [![Yonatan Koren][korenyoni_avatar]][korenyoni_homepage]<br/>[Yonatan Koren][korenyoni_homepage] |
|---|---|---|---|---|
<!-- markdownlint-restore -->

[osterman_homepage]: https://github.com/osterman
Expand All @@ -379,6 +384,8 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply
[Jamie-BitFlight_avatar]: https://img.cloudposse.com/150x150/https://github.com/Jamie-BitFlight.png
[Gowiem_homepage]: https://github.com/Gowiem
[Gowiem_avatar]: https://img.cloudposse.com/150x150/https://github.com/Gowiem.png
[korenyoni_homepage]: https://github.com/korenyoni
[korenyoni_avatar]: https://img.cloudposse.com/150x150/https://github.com/korenyoni.png

[![README Footer][readme_footer_img]][readme_footer_link]
[![Beacon][beacon]][website]
Expand Down
11 changes: 9 additions & 2 deletions README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ usage: |2-
```hcl
module "store_write" {
source = "git::https://github.com/cloudposse/terraform-aws-ssm-parameter-store?ref=master"
source = "cloudposse/ssm-parameter-store/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
parameter_write = [
{
Expand All @@ -71,7 +73,10 @@ usage: |2-
```hcl
module "store_read" {
source = "git::https://github.com/cloudposse/terraform-aws-ssm-parameter-store?ref=master"
source = "cloudposse/ssm-parameter-store/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
parameter_read = ["/cp/prod/app/database/master_password"]
}
```
Expand All @@ -88,3 +93,5 @@ contributors:
github: "Jamie-BitFlight"
- name: "Matt Gowie"
github: "Gowiem"
- name: "Yonatan Koren"
github: "korenyoni"
4 changes: 4 additions & 0 deletions examples/complete/fixtures.us-east-2.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ parameter_write = [
description = "Company name"
}
]

//parameter_read= [
// "/production/test/master/preexisting_key_${rand_id}"
//]
16 changes: 15 additions & 1 deletion examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ provider "aws" {

module "kms_key" {
source = "cloudposse/kms-key/aws"
version = "0.9.0"
version = "0.11.0"
description = "terraform-aws-ssm-parameter-store test KMS key"
deletion_window_in_days = 10
enable_key_rotation = true
Expand All @@ -16,7 +16,21 @@ module "kms_key" {
module "store" {
source = "../../"
parameter_write = var.parameter_write
parameter_read = var.parameter_read
kms_arn = module.kms_key.key_arn

context = module.this.context

depends_on = [
aws_ssm_parameter.preexisting_parameter
]
}

# This resource is used to test var.parameter_read in both enabled and disabled contexts.
# The value is hardcoded because it is referenced in examples_complete_test.go
resource "aws_ssm_parameter" "preexisting_parameter" {
count = length(var.parameter_read)
name = element(var.parameter_read, count.index)
type = "SecureString"
value = "preexisting_value"
}
6 changes: 6 additions & 0 deletions examples/complete/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ variable "parameter_write" {
type = list(map(string))
description = "List of maps with the parameter values to write to SSM Parameter Store"
}

variable "parameter_read" {
type = list(string)
description = "List of parameters to read from SSM. These must already exist otherwise an error is returned. Can be used with `parameter_write` as long as the parameters are different."
default = []
}
9 changes: 5 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
locals {
parameter_write = module.this.enabled ? { for e in var.parameter_write : e.name => merge(var.parameter_write_defaults, e) } : {}
enabled = module.this.enabled
parameter_write = local.enabled ? { for e in var.parameter_write : e.name => merge(var.parameter_write_defaults, e) } : {}
parameter_read = local.enabled ? var.parameter_read : []
}

data "aws_ssm_parameter" "read" {
count = module.this.enabled ? length(var.parameter_read) : 0
name = element(var.parameter_read, count.index)
count = length(local.parameter_read)
name = element(local.parameter_read, count.index)
}

resource "aws_ssm_parameter" "default" {
Expand All @@ -19,5 +21,4 @@ resource "aws_ssm_parameter" "default" {
overwrite = each.value.overwrite
allowed_pattern = each.value.allowed_pattern
tags = var.tags

}
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Splitting and joining, and then compacting a list to get a normalised list
locals {
name_list = compact(concat(keys(local.parameter_write), var.parameter_read))
name_list = compact(concat(keys(local.parameter_write), local.parameter_read))

value_list = compact(
concat(
Expand Down
103 changes: 91 additions & 12 deletions test/src/examples_complete_test.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,122 @@
package test

import (
"strings"
"fmt"
"math/rand"
"strconv"
"testing"
"time"

"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)

const preExistingKeyFormat = "/production/test/master/preexisting_key_%s"

// Test the Terraform module in examples/complete using Terratest.
func TestExamplesComplete(t *testing.T) {
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: "../../examples/complete",
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: []string{"fixtures.us-east-2.tfvars"},
}

terraform.Init(t, terraformOptions)
// Run tests in parallel
t.Run("Disabled", testExamplesCompleteDisabled)
t.Run("Enabled", testExamplesCompleteEnabled)
}

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

attributes := []string{strconv.Itoa(rand.Intn(100000))}
preExistingKeyName := fmt.Sprintf(preExistingKeyFormat, attributes[0])

terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: "../../examples/complete",
Upgrade: true,
EnvVars: map[string]string{
"TF_CLI_ARGS": "-state=terraform-disabled-test.tfstate",
},
// Variables to pass to our Terraform code using -var-file options
VarFiles: []string{"fixtures.us-east-2.tfvars"},
Vars: map[string]interface{}{
"enabled": false,
"attributes": attributes,
"parameter_read": []string{
preExistingKeyName,
},
},
}

// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)
// This will run `terraform apply` and fail the test if there are any errors
terraform.Apply(t, terraformOptions)

// Run `terraform output` to get the value of an output variable
output := terraform.Output(t, terraformOptions, "map")
output := terraform.OutputMap(t, terraformOptions, "map")
assert.Equal(t, len(output), 0, "There should be no outputs when the module is disabled.")
}

key1Result := strings.Contains(output, "/production/test/master/company")
value1Result := strings.Contains(output, "Amazon")
key2Result := strings.Contains(output, "/production/test/master/users")
value2Result := strings.Contains(output, "John,Todd")
func testExamplesCompleteEnabled(t *testing.T) {
t.Parallel()

rand.Seed(time.Now().UnixNano() + 1) // give a slightly different seed than the other parallel test
attributes := []string{strconv.Itoa(rand.Intn(100000))}
preExistingKeyName := fmt.Sprintf(preExistingKeyFormat, attributes[0])

terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: "../../examples/complete",
Upgrade: true,
EnvVars: map[string]string{
"TF_CLI_ARGS": "-state=terraform-enabled-test.tfstate",
},
// Variables to pass to our Terraform code using -var-file options
VarFiles: []string{"fixtures.us-east-2.tfvars"},
Vars: map[string]interface{}{
"attributes": attributes,
"parameter_read": []string{
preExistingKeyName,
},
},
}

// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// This will run `terraform apply` and fail the test if there are any errors
terraform.Apply(t, terraformOptions)

// Run `terraform output` to get the value of an output variable
output := terraform.OutputMap(t, terraformOptions, "map")

// Expected values for created parameters
key1 := "/production/test/master/company"
value1 := "Amazon"
key2 := "/production/test/master/users"
value2 := "John,Todd"

// Expected values for preexisting parameters
key3 := preExistingKeyName
value3 := "preexisting_value"

// Verify we're getting back the outputs we expect
assert.True(t, key1Result, "The 'map' output should contain the /production/test/master/company key")
assert.True(t, value1Result, "The /production/test/master/company key's value should be 'Amazon'")
containsErrorMessageFormat := "The 'map' output should contain the %s key"
equalsErrorMessageFormat := "The %s's value should be '%s'"

assert.Contains(t, output, key1, fmt.Sprintf(containsErrorMessageFormat, key1))
assert.Equal(t, value1 ,output[key1], fmt.Sprintf(equalsErrorMessageFormat, key1, value1))

assert.Contains(t, output, key2, fmt.Sprintf(containsErrorMessageFormat, key2))
assert.Equal(t, value2 ,output[key2], fmt.Sprintf(equalsErrorMessageFormat, key2, value2))

assert.True(t, key2Result, "The 'map' output should contain the /production/test/master/users key")
assert.True(t, value2Result, "The /production/test/master/users key's value should be 'John,Todd'")
assert.Contains(t, output, key3, fmt.Sprintf(containsErrorMessageFormat, key3))
assert.Equal(t, value3 ,output[key3], fmt.Sprintf(equalsErrorMessageFormat, key3, value3))
}

0 comments on commit 7ab272c

Please sign in to comment.