package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestVPCModule(t *testing.T) {
t.Parallel()
awsRegion := "us-east-1"
terraformOptions := &terraform.Options{
TerraformDir: "../../modules/vpc",
Vars: map[string]interface{}{
"name": "test-vpc",
"cidr_block": "10.100.0.0/16",
"availability_zones": []string{"us-east-1a", "us-east-1b"},
"environment": "test",
},
EnvVars: map[string]string{
"AWS_DEFAULT_REGION": awsRegion,
},
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
vpcID := terraform.Output(t, terraformOptions, "vpc_id")
require.NotEmpty(t, vpcID, "VPC ID should not be empty")
vpc := aws.GetVpcById(t, vpcID, awsRegion)
assert.Equal(t, "10.100.0.0/16", aws.GetCidrBlockOfVpc(t, vpc))
publicSubnetIDs := terraform.OutputList(t, terraformOptions, "public_subnet_ids")
privateSubnetIDs := terraform.OutputList(t, terraformOptions, "private_subnet_ids")
assert.Len(t, publicSubnetIDs, 2, "Should have 2 public subnets")
assert.Len(t, privateSubnetIDs, 2, "Should have 2 private subnets")
tags := aws.GetTagsForVpc(t, vpcID, awsRegion)
assert.Equal(t, "test", tags["Environment"])
assert.Equal(t, "test-vpc", tags["Name"])
}
func TestRDSModuleWithRetry(t *testing.T) {
t.Parallel()
opts := &terraform.Options{
TerraformDir: "../../modules/rds",
Vars: map[string]interface{}{
"instance_class": "db.t3.micro",
"engine_version": "15.4",
"multi_az": false,
},
RetryableTerraformErrors: map[string]string{
".*timeout.*": "Transient timeout; retrying",
},
MaxRetries: 3,
TimeBetweenRetries: 10 * time.Second,
}
defer terraform.Destroy(t, opts)
terraform.InitAndApply(t, opts)
endpoint := terraform.Output(t, opts, "endpoint")
assert.Contains(t, endpoint, ".rds.amazonaws.com")
}
# policies/terraform/required_tags.rego
package terraform.required_tags
import future.keywords.in
required_tags := {"Environment", "Team", "CostCenter"}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
resource.change.actions[_] in ["create", "update"]
missing := required_tags - {k | resource.change.after.tags[k]}
count(missing) > 0
msg := sprintf(
"EC2 instance '%s' is missing required tags: %v",
[resource.address, missing]
)
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.actions[_] in ["create", "update"]
not resource.change.after.tags["CostCenter"]
msg := sprintf("S3 bucket '%s' must have a CostCenter tag", [resource.address])
}