Skip to content

Commit d1d877e

Browse files
Added tests (#16)
* Added tests * Added tests helpers * Added tests helpers * Pin version * Update test/component_test.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update test/component_test.go --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 2580402 commit d1d877e

File tree

15 files changed

+811
-5
lines changed

15 files changed

+811
-5
lines changed

src/remote-state.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module "cloudtrail_bucket" {
22
source = "cloudposse/stack-config/yaml//modules/remote-state"
3-
version = "1.5.0"
3+
version = "1.8.0"
44

55
component = var.cloudtrail_bucket_component_name
66
environment = var.cloudtrail_bucket_environment_name
@@ -11,7 +11,7 @@ module "cloudtrail_bucket" {
1111

1212
module "account_map" {
1313
source = "cloudposse/stack-config/yaml//modules/remote-state"
14-
version = "1.5.0"
14+
version = "1.8.0"
1515

1616
component = "account-map"
1717
tenant = module.iam_roles.global_tenant_name

test/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
state/
2+
.cache
3+
test/test-suite.json
4+
.atmos
5+
test_suite.yaml

test/component_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package test
2+
3+
import (
4+
"context"
5+
"strings"
6+
"testing"
7+
8+
"github.com/aws/aws-sdk-go-v2/service/cloudtrail"
9+
"github.com/cloudposse/test-helpers/pkg/atmos"
10+
helper "github.com/cloudposse/test-helpers/pkg/atmos/component-helper"
11+
awshelper "github.com/cloudposse/test-helpers/pkg/aws"
12+
"github.com/gruntwork-io/terratest/modules/aws"
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
type ComponentSuite struct {
17+
helper.TestSuite
18+
}
19+
20+
func (s *ComponentSuite) TestBasic() {
21+
const component = "cloudtrail/basic"
22+
const stack = "default-test"
23+
const awsRegion = "us-east-2"
24+
25+
defer s.DestroyAtmosComponent(s.T(), component, stack, nil)
26+
options, _ := s.DeployAtmosComponent(s.T(), component, stack, nil)
27+
assert.NotNil(s.T(), options)
28+
29+
cloudtrailBucketOptions := s.GetAtmosOptions("cloudtrail-bucket", stack, nil)
30+
bucketName := atmos.Output(s.T(), cloudtrailBucketOptions, "cloudtrail_bucket_id")
31+
defer aws.EmptyS3Bucket(s.T(), awsRegion, bucketName)
32+
33+
cloudtrailID := atmos.Output(s.T(), options, "cloudtrail_id")
34+
35+
client := awshelper.NewCloudTrailClient(s.T(), awsRegion)
36+
trails, err := client.DescribeTrails(context.Background(), &cloudtrail.DescribeTrailsInput{
37+
TrailNameList: []string{cloudtrailID},
38+
})
39+
assert.NoError(s.T(), err)
40+
trail := trails.TrailList[0]
41+
42+
cloudtrailArn := atmos.Output(s.T(), options, "cloudtrail_arn")
43+
assert.Equal(s.T(), cloudtrailArn, *trail.TrailARN)
44+
45+
cloudtrailLogsLogGroupArn := atmos.Output(s.T(), options, "cloudtrail_logs_log_group_arn")
46+
assert.True(s.T(), strings.HasPrefix(*trail.CloudWatchLogsLogGroupArn, cloudtrailLogsLogGroupArn))
47+
48+
cloudtrailLogsLogGroupName := atmos.Output(s.T(), options, "cloudtrail_logs_log_group_name")
49+
assert.True(s.T(), strings.HasSuffix(cloudtrailLogsLogGroupArn, cloudtrailLogsLogGroupName))
50+
51+
cloudtrailLogsRoleArn := atmos.Output(s.T(), options, "cloudtrail_logs_role_arn")
52+
assert.Equal(s.T(), cloudtrailLogsRoleArn, *trail.CloudWatchLogsRoleArn)
53+
54+
cloudtrailLogsRoleName := atmos.Output(s.T(), options, "cloudtrail_logs_role_name")
55+
assert.True(s.T(), strings.HasSuffix(cloudtrailLogsRoleArn, cloudtrailLogsRoleName))
56+
57+
cloudtrailHomeRegion := atmos.Output(s.T(), options, "cloudtrail_home_region")
58+
assert.Equal(s.T(), "us-east-2", cloudtrailHomeRegion)
59+
assert.Equal(s.T(), *trail.HomeRegion, cloudtrailHomeRegion)
60+
61+
assert.False(s.T(), *trail.IsOrganizationTrail)
62+
63+
s.DriftTest(component, stack, nil)
64+
}
65+
66+
func (s *ComponentSuite) TestOrgLevel() {
67+
const component = "cloudtrail/org-level"
68+
const stack = "default-test"
69+
const awsRegion = "us-east-2"
70+
71+
s.T().Skip("Skipping org-level test because it's not supported due to Service Policy limitations")
72+
defer s.DestroyAtmosComponent(s.T(), component, stack, nil)
73+
options, _ := s.DeployAtmosComponent(s.T(), component, stack, nil)
74+
assert.NotNil(s.T(), options)
75+
76+
cloudtrailBucketOptions := s.GetAtmosOptions("cloudtrail-bucket", stack, nil)
77+
bucketName := atmos.Output(s.T(), cloudtrailBucketOptions, "cloudtrail_bucket_id")
78+
defer aws.EmptyS3Bucket(s.T(), awsRegion, bucketName)
79+
80+
cloudtrailID := atmos.Output(s.T(), options, "cloudtrail_id")
81+
82+
client := awshelper.NewCloudTrailClient(s.T(), awsRegion)
83+
trails, err := client.DescribeTrails(context.Background(), &cloudtrail.DescribeTrailsInput{
84+
TrailNameList: []string{cloudtrailID},
85+
})
86+
assert.NoError(s.T(), err)
87+
trail := trails.TrailList[0]
88+
89+
cloudtrailArn := atmos.Output(s.T(), options, "cloudtrail_arn")
90+
assert.Equal(s.T(), cloudtrailArn, *trail.TrailARN)
91+
92+
cloudtrailLogsLogGroupArn := atmos.Output(s.T(), options, "cloudtrail_logs_log_group_arn")
93+
assert.True(s.T(), strings.HasPrefix(*trail.CloudWatchLogsLogGroupArn, cloudtrailLogsLogGroupArn))
94+
95+
cloudtrailLogsLogGroupName := atmos.Output(s.T(), options, "cloudtrail_logs_log_group_name")
96+
assert.True(s.T(), strings.HasSuffix(cloudtrailLogsLogGroupArn, cloudtrailLogsLogGroupName))
97+
98+
cloudtrailLogsRoleArn := atmos.Output(s.T(), options, "cloudtrail_logs_role_arn")
99+
assert.Equal(s.T(), cloudtrailLogsRoleArn, *trail.CloudWatchLogsRoleArn)
100+
101+
cloudtrailLogsRoleName := atmos.Output(s.T(), options, "cloudtrail_logs_role_name")
102+
assert.True(s.T(), strings.HasSuffix(cloudtrailLogsRoleArn, cloudtrailLogsRoleName))
103+
104+
cloudtrailHomeRegion := atmos.Output(s.T(), options, "cloudtrail_home_region")
105+
assert.Equal(s.T(), "us-east-2", cloudtrailHomeRegion)
106+
assert.Equal(s.T(), *trail.HomeRegion, cloudtrailHomeRegion)
107+
108+
assert.True(s.T(), *trail.IsOrganizationTrail)
109+
110+
s.DriftTest(component, stack, nil)
111+
}
112+
113+
func (s *ComponentSuite) TestEnabledFlag() {
114+
const component = "cloudtrail/disabled"
115+
const stack = "default-test"
116+
117+
s.VerifyEnabledFlag(component, stack, nil)
118+
}
119+
120+
func TestRunSuite(t *testing.T) {
121+
suite := new(ComponentSuite)
122+
123+
suite.AddDependency(t, "cloudtrail-bucket", "default-test", nil)
124+
helper.Run(t, suite)
125+
}

test/fixtures/atmos.yaml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# CLI config is loaded from the following locations (from lowest to highest priority):
2+
# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows)
3+
# home dir (~/.atmos)
4+
# current directory
5+
# ENV vars
6+
# Command-line arguments
7+
#
8+
# It supports POSIX-style Globs for file names/paths (double-star `**` is supported)
9+
# https://en.wikipedia.org/wiki/Glob_(programming)
10+
11+
# Base path for components, stacks and workflows configurations.
12+
# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument.
13+
# Supports both absolute and relative paths.
14+
# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path`
15+
# are independent settings (supporting both absolute and relative paths).
16+
# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path`
17+
# are considered paths relative to `base_path`.
18+
base_path: ""
19+
20+
components:
21+
terraform:
22+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument
23+
# Supports both absolute and relative paths
24+
base_path: "components/terraform"
25+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var
26+
apply_auto_approve: true
27+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument
28+
deploy_run_init: true
29+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument
30+
init_run_reconfigure: true
31+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument
32+
auto_generate_backend_file: true
33+
34+
stacks:
35+
# Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments
36+
# Supports both absolute and relative paths
37+
base_path: "stacks"
38+
# Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string)
39+
# Since we are distinguishing stacks based on namespace, and namespace is not part
40+
# of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile
41+
included_paths:
42+
- "orgs/**/*"
43+
44+
# Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string)
45+
excluded_paths:
46+
- "**/_defaults.yaml"
47+
48+
# Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var
49+
name_pattern: "{tenant}-{stage}"
50+
51+
workflows:
52+
# Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments
53+
# Supports both absolute and relative paths
54+
base_path: "stacks/workflows"
55+
56+
# https://github.com/cloudposse/atmos/releases/tag/v1.33.0
57+
logs:
58+
file: "/dev/stdout"
59+
# Supported log levels: Trace, Debug, Info, Warning, Off
60+
level: Info
61+
62+
settings:
63+
# Can also be set using 'ATMOS_SETTINGS_LIST_MERGE_STRATEGY' environment variable, or '--settings-list-merge-strategy' command-line argument
64+
list_merge_strategy: replace
65+
66+
# `Go` templates in Atmos manifests
67+
# https://atmos.tools/core-concepts/stacks/templating
68+
# https://pkg.go.dev/text/template
69+
templates:
70+
settings:
71+
enabled: true
72+
# https://masterminds.github.io/sprig
73+
sprig:
74+
enabled: true
75+
# https://docs.gomplate.ca
76+
gomplate:
77+
enabled: true
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
components:
2+
terraform:
3+
account-map:
4+
metadata:
5+
terraform_workspace: core-gbl-root
6+
vars:
7+
tenant: core
8+
environment: gbl
9+
stage: root
10+
11+
# This remote state is only for Cloud Posse internal use.
12+
# It references the Cloud Posse test organizations actual infrastructure.
13+
# remote_state_backend:
14+
# s3:
15+
# bucket: cptest-core-ue2-root-tfstate-core
16+
# dynamodb_table: cptest-core-ue2-root-tfstate-core-lock
17+
# role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-core-ro
18+
# encrypt: true
19+
# key: terraform.tfstate
20+
# acl: bucket-owner-full-control
21+
# region: us-east-2
22+
23+
remote_state_backend_type: static
24+
remote_state_backend:
25+
# This static backend is used for tests that only need to use the account map iam-roles module
26+
# to find the role to assume for Terraform operations. It is configured to use whatever
27+
# the current user's role is, but the environment variable `TEST_ACCOUNT_ID` must be set to
28+
# the account ID of the account that the user is currently assuming a role in.
29+
#
30+
# For some components, this backend is missing important data, and those components
31+
# will need that data added to the backend configuration in order to work properly.
32+
static:
33+
account_info_map: {}
34+
all_accounts: []
35+
aws_partition: aws
36+
full_account_map: {}
37+
iam_role_arn_templates: {}
38+
non_eks_accounts: []
39+
profiles_enabled: false
40+
root_account_aws_name: root
41+
terraform_access_map: {}
42+
terraform_dynamic_role_enabled: false
43+
terraform_role_name_map:
44+
apply: terraform
45+
plan: planner
46+
terraform_roles: {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
components:
2+
terraform:
3+
cloudtrail-bucket:
4+
metadata:
5+
component: cloudtrail-bucket
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
components:
2+
terraform:
3+
cloudtrail/basic:
4+
metadata:
5+
component: target
6+
vars:
7+
enabled: true
8+
cloudtrail_bucket_environment_name: "ue2"
9+
cloudtrail_bucket_stage_name: "test"
10+
cloudwatch_logs_retention_in_days: 1
11+
is_organization_trail: false
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
components:
2+
terraform:
3+
cloudtrail/disabled:
4+
metadata:
5+
component: target
6+
vars:
7+
enabled: false
8+
cloudtrail_bucket_environment_name: "ue2"
9+
cloudtrail_bucket_stage_name: "test"
10+
cloudwatch_logs_retention_in_days: 1
11+
is_organization_trail: false
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
components:
2+
terraform:
3+
cloudtrail/org-level:
4+
metadata:
5+
component: target
6+
vars:
7+
enabled: true
8+
cloudtrail_bucket_environment_name: "ue2"
9+
cloudtrail_bucket_stage_name: "test"
10+
cloudwatch_logs_retention_in_days: 1
11+
is_organization_trail: true
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import:
2+
- catalog/account-map
3+
4+
terraform:
5+
backend_type: local
6+
backend:
7+
local:
8+
path: '{{ getenv "COMPONENT_HELPER_STATE_DIR" | default "../../../state" }}/{{ .component }}/terraform.tfstate'
9+
workspace_dir: '{{ getenv "COMPONENT_HELPER_STATE_DIR" | default "../../../state" }}/{{ .component }}/'
10+
vars:
11+
namespace: eg
12+
tenant: default
13+
environment: ue2
14+
region: us-east-2
15+
stage: test
16+
label_order:
17+
- namespace
18+
- tenant
19+
- environment
20+
- stage
21+
- name
22+
- attributes
23+
descriptor_formats:
24+
account_name:
25+
format: "%v-%v"
26+
labels:
27+
- tenant
28+
- stage
29+
stack:
30+
format: "%v-%v-%v"
31+
labels:
32+
- tenant
33+
- environment
34+
- stage
35+
36+
components:
37+
terraform:
38+
account-map:
39+
remote_state_backend:
40+
static:
41+
account_info_map:
42+
default-test:
43+
account_email_format: aws+cptest-%[email protected]
44+
eks: true
45+
id: '{{ getenv "TEST_ACCOUNT_ID" | default "<TEST_ACCOUNT_ID>" }}'
46+
ou: default
47+
parent_ou: none
48+
stage: test
49+
tags:
50+
eks: false
51+
tenant: default
52+
all_accounts:
53+
- default-test
54+
artifacts_account_account_name: default-test
55+
audit_account_account_name: default-test
56+
dns_account_account_name: default-test
57+
eks_accounts:
58+
- default-test
59+
full_account_map:
60+
default-test: '{{ getenv "TEST_ACCOUNT_ID" | default "<TEST_ACCOUNT_ID>" }}'
61+
iam_role_arn_templates:
62+
default-test: 'arn:aws:iam::{{ getenv "TEST_ACCOUNT_ID" | default "<TEST_ACCOUNT_ID>" }}:role/tester-%s'
63+
identity_account_account_name: default-test
64+
root_account_account_name: default-test
65+
terraform_roles:
66+
default-test: ''
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import:
2+
- orgs/default/test/_defaults
3+
- catalog/cloudtrail-bucket
4+
- catalog/usecase/basic
5+
- catalog/usecase/org-level
6+
- catalog/usecase/disabled

0 commit comments

Comments
 (0)