Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tests #10

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,7 @@ github/
*.ovpn

*.zip


state
.cache
10 changes: 9 additions & 1 deletion src/providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ provider "aws" {

# Profile is deprecated in favor of terraform_role_arn. When profiles are not in use, terraform_profile_name is null.
profile = module.iam_roles.terraform_profile_name

default_tags {
tags = var.default_tags
}
dynamic "assume_role" {
# module.iam_roles.terraform_role_arn may be null, in which case do not assume a role.
for_each = compact([module.iam_roles.terraform_role_arn])
Expand All @@ -17,3 +19,9 @@ module "iam_roles" {
source = "../account-map/modules/iam-roles"
context = module.this.context
}

variable "default_tags" {
type = map(string)
description = "A map of tags to add to every resource"
default = {}
}
4 changes: 4 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
state/
.cache
test/test-suite.json
.atmos
151 changes: 151 additions & 0 deletions test/component_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package test

import (
"fmt"
"strings"
"testing"

awssdk "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/cloudposse/test-helpers/pkg/atmos"
helper "github.com/cloudposse/test-helpers/pkg/atmos/aws-component-helper"
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestComponent(t *testing.T) {
awsRegion := "us-east-2"

fixture := helper.NewFixture(t, "../", awsRegion, "test/fixtures")

defer fixture.TearDown()
fixture.SetUp(&atmos.Options{})

fixture.Suite("default", func(t *testing.T, suite *helper.Suite) {
suite.Test(t, "two-private-subnets", func(t *testing.T, atm *helper.Atmos) {
inputs := map[string]interface{}{
"name": "vpc-terraform",
"availability_zones": []string{"a", "b"},
"public_subnets_enabled": false,
"nat_gateway_enabled": false,
"nat_instance_enabled": false,
"subnet_type_tag_key": "eg.cptest.co/subnet/type",
"max_subnet_count": 3,
"vpc_flow_logs_enabled": false,
"ipv4_primary_cidr_block": "172.16.0.0/16",
}

defer atm.GetAndDestroy("vpc/private", "default-test", inputs)
component := atm.GetAndDeploy("vpc/private", "default-test", inputs)

vpcId := atm.Output(component, "vpc_id")
require.True(t, strings.HasPrefix(vpcId, "vpc-"))

vpc := aws.GetVpcById(t, vpcId, awsRegion)

assert.Equal(t, vpc.Name, fmt.Sprintf("eg-default-ue2-test-vpc-terraform-%s", component.RandomIdentifier))
assert.Equal(t, *vpc.CidrAssociations[0], "172.16.0.0/16")
assert.Equal(t, *vpc.CidrBlock, "172.16.0.0/16")
assert.Nil(t, vpc.Ipv6CidrAssociations)
assert.Equal(t, vpc.Tags["Environment"], "ue2")
assert.Equal(t, vpc.Tags["Namespace"], "eg")
assert.Equal(t, vpc.Tags["Stage"], "test")
assert.Equal(t, vpc.Tags["Tenant"], "default")

subnets := vpc.Subnets
require.Equal(t, 2, len(subnets))

public_subnet_ids := atm.OutputList(component, "public_subnet_ids")
assert.Empty(t, public_subnet_ids)

public_subnet_cidrs := atm.OutputList(component, "public_subnet_cidrs")
assert.Empty(t, public_subnet_cidrs)

private_subnet_ids := atm.OutputList(component, "private_subnet_ids")
assert.Equal(t, 2, len(private_subnet_ids))

assert.Contains(t, private_subnet_ids, subnets[0].Id)
assert.Contains(t, private_subnet_ids, subnets[1].Id)

assert.False(t, aws.IsPublicSubnet(t, subnets[0].Id, awsRegion))
assert.False(t, aws.IsPublicSubnet(t, subnets[1].Id, awsRegion))

nats, err := GetNatsByVpcIdE(t, vpcId, awsRegion)
assert.NoError(t, err)
assert.Equal(t, 0, len(nats))
})

suite.Test(t, "public-private-subnets", func(t *testing.T, atm *helper.Atmos) {
inputs := map[string]interface{}{
"name": "vpc-terraform",
"availability_zones": []string{"b", "c"},
"public_subnets_enabled": true,
"nat_gateway_enabled": true,
"nat_instance_enabled": false,
"subnet_type_tag_key": "eg.cptest.co/subnet/type",
"max_nats": 1,
"max_subnet_count": 3,
"vpc_flow_logs_enabled": false,
"ipv4_primary_cidr_block": "172.16.0.0/16",
}

defer atm.GetAndDestroy("vpc/public", "default-test", inputs)
component := atm.GetAndDeploy("vpc/public", "default-test", inputs)

vpcId := atm.Output(component, "vpc_id")
require.True(t, strings.HasPrefix(vpcId, "vpc-"))

vpc := aws.GetVpcById(t, vpcId, awsRegion)

assert.Equal(t, vpc.Name, fmt.Sprintf("eg-default-ue2-test-vpc-terraform-%s", component.RandomIdentifier))
assert.Equal(t, *vpc.CidrAssociations[0], "172.16.0.0/16")
assert.Equal(t, *vpc.CidrBlock, "172.16.0.0/16")
assert.Nil(t, vpc.Ipv6CidrAssociations)
assert.Equal(t, vpc.Tags["Environment"], "ue2")
assert.Equal(t, vpc.Tags["Namespace"], "eg")
assert.Equal(t, vpc.Tags["Stage"], "test")
assert.Equal(t, vpc.Tags["Tenant"], "default")

subnets := vpc.Subnets
require.Equal(t, 4, len(subnets))

public_subnet_ids := atm.OutputList(component, "public_subnet_ids")
assert.Equal(t, 2, len(public_subnet_ids))

public_subnet_cidrs := atm.OutputList(component, "public_subnet_cidrs")
assert.Equal(t, 2, len(public_subnet_cidrs))

private_subnet_ids := atm.OutputList(component, "private_subnet_ids")
assert.Equal(t, 2, len(private_subnet_ids))

private_subnet_cidrs := atm.OutputList(component, "private_subnet_cidrs")
assert.Equal(t, 2, len(private_subnet_cidrs))

assert.False(t, aws.IsPublicSubnet(t, private_subnet_ids[0], awsRegion))
assert.False(t, aws.IsPublicSubnet(t, private_subnet_ids[1], awsRegion))

assert.True(t, aws.IsPublicSubnet(t, public_subnet_ids[0], awsRegion))
assert.True(t, aws.IsPublicSubnet(t, public_subnet_ids[1], awsRegion))

nats, err := GetNatsByVpcIdE(t, vpcId, awsRegion)
assert.NoError(t, err)
assert.Equal(t, 1, len(nats))
})

})
}

func GetNatsByVpcIdE(t *testing.T, vpcId string, awsRegion string) ([]*ec2.NatGateway, error) {
client, err := aws.NewEc2ClientE(t, awsRegion)
if err != nil {
return nil, err
}

filter := ec2.Filter{Name: awssdk.String("vpc-id"), Values: []*string{&vpcId}}
response, err := client.DescribeNatGateways(&ec2.DescribeNatGatewaysInput{Filter: []*ec2.Filter{&filter}})
if err != nil {
return nil, err
}
return response.NatGateways, nil
}
87 changes: 87 additions & 0 deletions test/fixtures/atmos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# 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

commands:
- name: "test-components"
description: "List the Atmos virtual components configured for testing"
steps:
- >
atmos describe stacks --format json --sections=component,metadata --components=component -s sandbox
| jq '.[] | .components.terraform | to_entries |
map(select(.value.component == "component" and (.value.metadata.type != "abstract" or .value.metadata.type == null)))
| .[].key'
6 changes: 6 additions & 0 deletions test/fixtures/components/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*
# Module directory
# Note that the leading "**/" appears necessary for Docker even if not for Git
!assert*
!assert*/*.tf

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: {}
17 changes: 17 additions & 0 deletions test/fixtures/stacks/catalog/usecase/private.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
components:
terraform:
vpc/private:
metadata:
component: vpc
vars:
name: "vpc-terraform"
availability_zones:
- "a"
- "b"
public_subnets_enabled: false
nat_gateway_enabled: false
nat_instance_enabled: false
subnet_type_tag_key: "eg.cptest.co/subnet/type"
max_subnet_count: 3
vpc_flow_logs_enabled: false
ipv4_primary_cidr_block: "172.16.0.0/16"
18 changes: 18 additions & 0 deletions test/fixtures/stacks/catalog/usecase/public.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
components:
terraform:
vpc/public:
metadata:
component: vpc
vars:
name: "vpc-terraform"
availability_zones:
- "b"
- "c"
public_subnets_enabled: true
max_nats: 1
nat_gateway_enabled: true
nat_instance_enabled: false
subnet_type_tag_key: "eg.cptest.co/subnet/type"
max_subnet_count: 3
vpc_flow_logs_enabled: false
ipv4_primary_cidr_block: "172.16.0.0/16"
28 changes: 28 additions & 0 deletions test/fixtures/stacks/catalog/usecase/with_flowlogs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# @TODO: Add example of how to use the vpc with flow logs
components:
terraform:
vpc-flow-logs-bucket:
metadata:
component: vpc-flow-logs-bucket
vars:
name: "vpc-flow-logs-bucket"
noncurrent_version_expiration_days: 180
noncurrent_version_transition_days: 30
standard_transition_days: 60
glacier_transition_days: 180
expiration_days: 365

vpc/with_flowlogs:
metadata:
component: vpc
vars:
name: "vpc-terraform"
availability_zones:
- "a"
public_subnets_enabled: false
nat_gateway_enabled: false
nat_instance_enabled: false
subnet_type_tag_key: "eg.cptest.co/subnet/type"
max_subnet_count: 3
vpc_flow_logs_enabled: false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Verify vpc_flow_logs_enabled setting.

The vpc_flow_logs_enabled is set to false which seems contradictory to the purpose of this fixture file (testing VPC with flow logs). Consider setting this to true to properly test the flow logs functionality.

-        vpc_flow_logs_enabled: false
+        vpc_flow_logs_enabled: true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
vpc_flow_logs_enabled: false
vpc_flow_logs_enabled: true

ipv4_primary_cidr_block: "172.16.0.0/16"
Loading
Loading