Skip to content

Commit

Permalink
Added tests (#18)
Browse files Browse the repository at this point in the history
* Added tests

* Added tests

* Added tests

* Pin version
  • Loading branch information
goruha authored Feb 20, 2025
1 parent fd43f26 commit 6a862f2
Show file tree
Hide file tree
Showing 17 changed files with 851 additions and 9 deletions.
8 changes: 4 additions & 4 deletions src/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,28 @@ module "ssm_parameter_store" {
parameter_write = [
{
description = "SES AWS access key ID"
name = "/ses/ses_access_key_id"
name = format("%s/%s", var.ssm_prefix, "ses_access_key_id")
overwrite = true
type = "String"
value = module.ses.access_key_id
},
{
description = "SES user IAM secret for usage with SES API"
name = "/ses/ses_secret_access_key"
name = format("%s/%s", var.ssm_prefix, "ses_secret_access_key")
overwrite = true
type = "SecureString"
value = module.ses.secret_access_key
},
{
description = "SES IAM user name"
name = "/ses/ses_user_name"
name = format("%s/%s", var.ssm_prefix, "ses_user_name")
overwrite = true
type = "String"
value = module.ses.user_name
},
{
description = "SES SMTP password"
name = "/ses/ses_smtp_password"
name = format("%s/%s", var.ssm_prefix, "ses_smtp_password")
overwrite = true
type = "SecureString"
value = module.ses.ses_smtp_password
Expand Down
4 changes: 2 additions & 2 deletions src/remote-state.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module "dns_gbl_delegated" {
source = "cloudposse/stack-config/yaml//modules/remote-state"
version = "1.5.0"
version = "1.8.0"

component = "dns-delegated"
environment = "gbl"
environment = coalesce(var.dns_delegated_environment_name, module.iam_roles.global_environment_name)

context = module.this.context
}
13 changes: 13 additions & 0 deletions src/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,16 @@ variable "domain_template" {
type = string
description = "The `format()` string to use to generate the base domain name for sending and receiving email with Amazon SES, `format(var.domain_template, var.tenant, var.environment, var.stage)"
}

variable "dns_delegated_environment_name" {
type = string
default = null
description = "`dns-delegated` component environment name"
}

variable "ssm_prefix" {
type = string
default = "/ses"
sensitive = false
description = "The prefix to use for the SSM parameters"
}
5 changes: 5 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
state/
.cache
test/test-suite.json
.atmos
test_suite.yaml
119 changes: 119 additions & 0 deletions test/component_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package test

import (
"context"
"fmt"
"strings"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/service/sesv2"
"github.com/aws/aws-sdk-go-v2/service/sesv2/types"
"github.com/cloudposse/test-helpers/pkg/atmos"
helper "github.com/cloudposse/test-helpers/pkg/atmos/component-helper"
awshelper "github.com/cloudposse/test-helpers/pkg/aws"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/stretchr/testify/assert"
)

type ComponentSuite struct {
helper.TestSuite
}

func (s *ComponentSuite) TestBasic() {
const component = "ses/basic"
const stack = "default-test"
const awsRegion = "us-east-2"

dnsDelegatedOptions := s.GetAtmosOptions("dns-delegated", stack, nil)
domain := atmos.Output(s.T(), dnsDelegatedOptions, "default_domain_name")

hostnamePrefix := strings.ToLower(random.UniqueId())
inputs := map[string]interface{}{
"domain_template": hostnamePrefix + "-%[3]v.%[2]v.%[1]v." + domain,
"ssm_prefix": fmt.Sprintf("/ses/%s", hostnamePrefix),
}
defer s.DestroyAtmosComponent(s.T(), component, stack, &inputs)
options, _ := s.DeployAtmosComponent(s.T(), component, stack, &inputs)
assert.NotNil(s.T(), options)

smtpPassword := atmos.Output(s.T(), options, "smtp_password")
assert.NotEmpty(s.T(), smtpPassword)

smtpUser := atmos.Output(s.T(), options, "smtp_user")
assert.NotEmpty(s.T(), smtpUser)

userUniqueId := atmos.Output(s.T(), options, "user_unique_id")
assert.NotEmpty(s.T(), userUniqueId)

userArn := atmos.Output(s.T(), options, "user_arn")
assert.NotEmpty(s.T(), userArn)

randomContentMessage := strings.ToLower(random.UniqueId())
identityDomain := fmt.Sprintf("%s-test.ue2.default.%s", hostnamePrefix, domain)
senderEmail := fmt.Sprintf("test@%s", identityDomain)
client := awshelper.NewSESV2Client(s.T(), awsRegion)

var identityState string
var attempt int
for strings.ToLower(identityState) != "success" && attempt <= 60 {
identities, err := client.GetEmailIdentity(context.Background(), &sesv2.GetEmailIdentityInput{
EmailIdentity: &identityDomain,
})
assert.NoError(s.T(), err)

identityState = string(identities.VerificationStatus)
time.Sleep(2 * time.Second)
attempt++
}
assert.Equal(s.T(), "SUCCESS", identityState)

_, err := client.SendEmail(context.Background(), &sesv2.SendEmailInput{
Content: &types.EmailContent{
Raw: &types.RawMessage{
Data: []byte(fmt.Sprintf("Test email %s", randomContentMessage)),
},
},
Destination: &types.Destination{
ToAddresses: []string{"success@simulator.amazonses.com"},
},
FromEmailAddress: &senderEmail,
})
assert.NoError(s.T(), err)

s.DriftTest(component, stack, &inputs)
}

func (s *ComponentSuite) TestEnabledFlag() {
const component = "ses/disabled"
const stack = "default-test"
const awsRegion = "us-east-2"

dnsDelegatedOptions := s.GetAtmosOptions("dns-delegated", stack, nil)
domain := atmos.Output(s.T(), dnsDelegatedOptions, "default_domain_name")

hostnamePrefix := strings.ToLower(random.UniqueId())
inputs := map[string]interface{}{
"domain_template": hostnamePrefix + "-%[3]v.%[2]v.%[1]v." + domain,
"ssm_prefix": fmt.Sprintf("/ses/%s", hostnamePrefix),
}

s.VerifyEnabledFlag(component, stack, &inputs)
}


func TestRunSuite(t *testing.T) {
suite := new(ComponentSuite)

subdomain := strings.ToLower(random.UniqueId())
inputs := map[string]interface{}{
"zone_config": []map[string]interface{}{
{
"subdomain": subdomain,
"zone_name": "components.cptest.test-automation.app",
},
},
}
suite.AddDependency(t, "dns-delegated", "default-test", &inputs)
helper.Run(t, suite)
}
77 changes: 77 additions & 0 deletions test/fixtures/atmos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# CLI config is loaded from the following locations (from lowest to highest priority):
# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows)
# home dir (~/.atmos)
# current directory
# ENV vars
# Command-line arguments
#
# It supports POSIX-style Globs for file names/paths (double-star `**` is supported)
# https://en.wikipedia.org/wiki/Glob_(programming)

# Base path for components, stacks and workflows configurations.
# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument.
# Supports both absolute and relative paths.
# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path`
# are independent settings (supporting both absolute and relative paths).
# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path`
# are considered paths relative to `base_path`.
base_path: ""

components:
terraform:
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument
# Supports both absolute and relative paths
base_path: "components/terraform"
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var
apply_auto_approve: true
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument
deploy_run_init: true
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument
init_run_reconfigure: true
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument
auto_generate_backend_file: true

stacks:
# Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments
# Supports both absolute and relative paths
base_path: "stacks"
# Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string)
# Since we are distinguishing stacks based on namespace, and namespace is not part
# of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile
included_paths:
- "orgs/**/*"

# Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string)
excluded_paths:
- "**/_defaults.yaml"

# Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var
name_pattern: "{tenant}-{stage}"

workflows:
# Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments
# Supports both absolute and relative paths
base_path: "stacks/workflows"

# https://github.com/cloudposse/atmos/releases/tag/v1.33.0
logs:
file: "/dev/stdout"
# Supported log levels: Trace, Debug, Info, Warning, Off
level: Info

settings:
# Can also be set using 'ATMOS_SETTINGS_LIST_MERGE_STRATEGY' environment variable, or '--settings-list-merge-strategy' command-line argument
list_merge_strategy: replace

# `Go` templates in Atmos manifests
# https://atmos.tools/core-concepts/stacks/templating
# https://pkg.go.dev/text/template
templates:
settings:
enabled: true
# https://masterminds.github.io/sprig
sprig:
enabled: true
# https://docs.gomplate.ca
gomplate:
enabled: true
46 changes: 46 additions & 0 deletions test/fixtures/stacks/catalog/account-map.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
components:
terraform:
account-map:
metadata:
terraform_workspace: core-gbl-root
vars:
tenant: core
environment: gbl
stage: root

# This remote state is only for Cloud Posse internal use.
# It references the Cloud Posse test organizations actual infrastructure.
# remote_state_backend:
# s3:
# bucket: cptest-core-ue2-root-tfstate-core
# dynamodb_table: cptest-core-ue2-root-tfstate-core-lock
# role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-core-ro
# encrypt: true
# key: terraform.tfstate
# acl: bucket-owner-full-control
# region: us-east-2

remote_state_backend_type: static
remote_state_backend:
# This static backend is used for tests that only need to use the account map iam-roles module
# to find the role to assume for Terraform operations. It is configured to use whatever
# the current user's role is, but the environment variable `TEST_ACCOUNT_ID` must be set to
# the account ID of the account that the user is currently assuming a role in.
#
# For some components, this backend is missing important data, and those components
# will need that data added to the backend configuration in order to work properly.
static:
account_info_map: {}
all_accounts: []
aws_partition: aws
full_account_map: {}
iam_role_arn_templates: {}
non_eks_accounts: []
profiles_enabled: false
root_account_aws_name: root
terraform_access_map: {}
terraform_dynamic_role_enabled: false
terraform_role_name_map:
apply: terraform
plan: planner
terraform_roles: {}
10 changes: 10 additions & 0 deletions test/fixtures/stacks/catalog/dns-delegated.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
components:
terraform:
dns-delegated:
metadata:
component: dns-delegated
vars:
zone_config:
- subdomain: test
zone_name: example.net
request_acm_certificate: true
9 changes: 9 additions & 0 deletions test/fixtures/stacks/catalog/dns-primary.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
components:
terraform:
dns-primary:
metadata:
component: dns-primary
vars:
domain_names:
- example.net
record_config: []
17 changes: 17 additions & 0 deletions test/fixtures/stacks/catalog/usecase/basic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
components:
terraform:
ses/basic:
metadata:
component: target
vars:
enabled: true
name: ses
ses_verify_domain: true
ses_verify_dkim: true
dns_delegated_environment_name: ue2
# {environment}.{stage}.{tenant}.acme.org
domain_template: "%s[2]s.%[3]s.%[1]s.acme.org"
# use this when `account-map` is deployed in a separate `tenant`
tags:
Team: sre
Service: ses
17 changes: 17 additions & 0 deletions test/fixtures/stacks/catalog/usecase/disabled.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
components:
terraform:
ses/disabled:
metadata:
component: target
vars:
enabled: false
name: ses
ses_verify_domain: true
ses_verify_dkim: true
dns_delegated_environment_name: ue2
# {environment}.{stage}.{tenant}.acme.org
domain_template: "%s[2]s.%[3]s.%[1]s.acme.org"
# use this when `account-map` is deployed in a separate `tenant`
tags:
Team: sre
Service: ses
Loading

0 comments on commit 6a862f2

Please sign in to comment.