diff --git a/README.md b/README.md index 5e4915ab..766286dc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Cloud Posse][logo]](https://cpco.io/homepage) -# terraform-aws-dynamic-subnets [![Build Status](https://travis-ci.org/cloudposse/terraform-aws-dynamic-subnets.svg?branch=master)](https://travis-ci.org/cloudposse/terraform-aws-dynamic-subnets) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-dynamic-subnets.svg)](https://github.com/cloudposse/terraform-aws-dynamic-subnets/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) +# terraform-aws-dynamic-subnets [![Codefresh Build Status](https://g.codefresh.io/api/badges/pipeline/cloudposse/cloudposse%2Fterraform-aws-dynamic-subnets%2Ftest?type=cf-1)](https://g.codefresh.io/public/accounts/cloudposse/pipelines/cloudposse/terraform-aws-dynamic-subnets/test) [![Build Status](https://travis-ci.org/cloudposse/terraform-aws-dynamic-subnets.svg?branch=master)](https://travis-ci.org/cloudposse/terraform-aws-dynamic-subnets) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-dynamic-subnets.svg)](https://github.com/cloudposse/terraform-aws-dynamic-subnets/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) Terraform module to provision public and private [`subnets`](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) in an existing [`VPC`](https://aws.amazon.com/vpc) @@ -53,6 +53,9 @@ Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest re ```hcl module "subnets" { source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" + providers = { + aws = "aws" + } namespace = "cp" stage = "prod" name = "app" @@ -64,6 +67,8 @@ module "subnets" { } ``` +Learn about [using providers](https://www.terraform.io/docs/configuration-0-11/modules.html#providers-within-modules) with terraform modules. + @@ -174,7 +179,6 @@ Available targets: | private_network_acl_id | Network ACL ID that will be added to private subnets. If empty, a new ACL will be created | string | `` | no | | public_network_acl_id | Network ACL ID that will be added to public subnets. If empty, a new ACL will be created | string | `` | no | | regex_replace_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. By default only hyphens, letters and digits are allowed, all other chars are removed | string | `/[^a-zA-Z0-9-]/` | no | -| region | AWS Region (e.g. `us-east-1`) | string | - | yes | | stage | Stage, e.g. 'prod', 'staging', 'dev', or 'test' | string | `` | no | | subnet_type_tag_key | Key for subnet type tag to provide information about the type of subnets, e.g. `cpco.io/subnet/type=private` or `cpco.io/subnet/type=public` | string | `cpco.io/subnet/type` | no | | subnet_type_tag_value_format | This is using the format interpolation symbols to allow the value of the subnet_type_tag_key to be modified. | string | `%s` | no | diff --git a/README.yaml b/README.yaml index 92a98123..b7f076de 100644 --- a/README.yaml +++ b/README.yaml @@ -32,6 +32,9 @@ github_repo: cloudposse/terraform-aws-dynamic-subnets # Badges to display badges: + - name: "Codefresh Build Status" + image: "https://g.codefresh.io/api/badges/pipeline/cloudposse/cloudposse%2Fterraform-aws-dynamic-subnets%2Ftest?type=cf-1" + url: "https://g.codefresh.io/public/accounts/cloudposse/pipelines/cloudposse/terraform-aws-dynamic-subnets/test" - name: "Build Status" image: "https://travis-ci.org/cloudposse/terraform-aws-dynamic-subnets.svg?branch=master" url: "https://travis-ci.org/cloudposse/terraform-aws-dynamic-subnets" @@ -68,6 +71,9 @@ usage: |- ```hcl module "subnets" { source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" + providers = { + aws = "aws" + } namespace = "cp" stage = "prod" name = "app" @@ -79,6 +85,8 @@ usage: |- } ``` + Learn about [using providers](https://www.terraform.io/docs/configuration-0-11/modules.html#providers-within-modules) with terraform modules. + include: - "docs/design.md" - "docs/targets.md" @@ -102,3 +110,4 @@ contributors: github: "ivan-pinatti" - name: "Oscar Sullivan" github: "osulli" + diff --git a/codefresh/test.yml b/codefresh/test.yml new file mode 100644 index 00000000..60f6a2a3 --- /dev/null +++ b/codefresh/test.yml @@ -0,0 +1,73 @@ +version: '1.0' + +stages: +- Prepare +- Test + +steps: + wait: + title: Wait + stage: Prepare + image: codefresh/cli:latest + commands: + - codefresh get builds --pipeline=${{CF_REPO_NAME}} --status running --limit 1000 -o json | jq --arg id ${{CF_BUILD_ID}} -ser 'flatten|.[-1].id==$id' + retry: + maxAttempts: 10 + delay: 20 + exponentialFactor: 1.1 + + main_clone: + title: "Clone repository" + type: git-clone + stage: Prepare + description: "Initialize" + repo: ${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} + git: CF-default + revision: ${{CF_REVISION}} + + clean_init: + title: Prepare build-harness and test-harness + image: ${{TEST_IMAGE}} + stage: Prepare + commands: + - cf_export PATH="/usr/local/terraform/0.11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + - make init + - git -C build-harness checkout master + - make -C test/ clean init TEST_HARNESS_BRANCH=master + - make -C test/src clean init + - find test/src -name '*.tf' -delete + + test: + type: "parallel" + title: "Run tests" + description: "Run all tests in parallel" + stage: Test + steps: + test_readme_lint: + title: "Test README.md updated" + stage: "Test" + image: ${{TEST_IMAGE}} + description: Test "readme/lint" + commands: + - make readme/lint + + test_module: + title: Test module with bats + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/ module + + test_examples_complete: + title: Test "examples/complete" with bats + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/ examples/complete + + test_examples_complete_terratest: + title: Test "examples/complete" with terratest + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/src diff --git a/docs/terraform.md b/docs/terraform.md index 46462fff..777caae7 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -21,7 +21,6 @@ | private_network_acl_id | Network ACL ID that will be added to private subnets. If empty, a new ACL will be created | string | `` | no | | public_network_acl_id | Network ACL ID that will be added to public subnets. If empty, a new ACL will be created | string | `` | no | | regex_replace_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. By default only hyphens, letters and digits are allowed, all other chars are removed | string | `/[^a-zA-Z0-9-]/` | no | -| region | AWS Region (e.g. `us-east-1`) | string | - | yes | | stage | Stage, e.g. 'prod', 'staging', 'dev', or 'test' | string | `` | no | | subnet_type_tag_key | Key for subnet type tag to provide information about the type of subnets, e.g. `cpco.io/subnet/type=private` or `cpco.io/subnet/type=public` | string | `cpco.io/subnet/type` | no | | subnet_type_tag_value_format | This is using the format interpolation symbols to allow the value of the subnet_type_tag_key to be modified. | string | `%s` | no | diff --git a/examples/complete/fixtures.us-west-1.tfvars b/examples/complete/fixtures.us-west-1.tfvars new file mode 100644 index 00000000..97d8ae92 --- /dev/null +++ b/examples/complete/fixtures.us-west-1.tfvars @@ -0,0 +1,11 @@ +max_availability_zones = 2 + +region = "us-west-1" + +availability_zones = ["us-west-1b", "us-west-1c"] + +namespace = "eg" + +name = "vpc" + +stage = "test" diff --git a/examples/complete/main.tf b/examples/complete/main.tf new file mode 100644 index 00000000..15569cdf --- /dev/null +++ b/examples/complete/main.tf @@ -0,0 +1,29 @@ +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.3.4" + + providers = { + aws = "aws" + } + + namespace = "${var.namespace}" + stage = "${var.stage}" + name = "${var.name}" + cidr_block = "172.16.0.0/16" +} + +module "subnets" { + source = "../../" + + providers = { + aws = "aws" + } + + availability_zones = "${var.availability_zones}" + namespace = "${var.namespace}" + stage = "${var.stage}" + name = "${var.name}" + vpc_id = "${module.vpc.vpc_id}" + igw_id = "${module.vpc.igw_id}" + cidr_block = "${module.vpc.vpc_cidr_block}" + nat_gateway_enabled = "true" +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf new file mode 100644 index 00000000..eca8e5a6 --- /dev/null +++ b/examples/complete/outputs.tf @@ -0,0 +1,7 @@ +output "public_subnet_cidrs" { + value = "${module.subnets.public_subnet_cidrs}" +} + +output "private_subnet_cidrs" { + value = "${module.subnets.private_subnet_cidrs}" +} diff --git a/examples/complete/provider.tf b/examples/complete/provider.tf new file mode 100644 index 00000000..0977ba55 --- /dev/null +++ b/examples/complete/provider.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "${var.region}" +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf new file mode 100644 index 00000000..40c30e3a --- /dev/null +++ b/examples/complete/variables.tf @@ -0,0 +1,13 @@ +variable "max_availability_zones" {} + +variable "region" {} + +variable "availability_zones" { + type = "list" +} + +variable "namespace" {} + +variable "name" {} + +variable "stage" {} diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf new file mode 100644 index 00000000..1d62e4f6 --- /dev/null +++ b/examples/complete/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = "~> 0.11.7" +} diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 00000000..442804a2 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +.test-harness diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 00000000..1a141686 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,43 @@ +TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git +TEST_HARNESS_BRANCH ?= master +TEST_HARNESS_PATH = $(realpath .test-harness) +BATS_ARGS ?= --tap +BATS_LOG ?= test.log + +# Define a macro to run the tests +define RUN_TESTS +@echo "Running tests in $(1)" +@cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS))) +endef + +default: all + +-include Makefile.* + +## Provision the test-harnesss +.test-harness: + git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@ + +## Initialize the tests +init: .test-harness + +## Install all dependencies (OS specific) +deps:: + @exit 0 + +## Clean up the test harness +clean: + [ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH) + +## Run all tests +all: module examples/complete + +## Run basic sanity checks against the module itself +module: export TESTS ?= installed lint get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions +module: deps + $(call RUN_TESTS, ../) + +## Run tests against example +examples/complete: export TESTS ?= installed lint get-modules get-plugins validate +examples/complete: deps + $(call RUN_TESTS, ../$@) diff --git a/test/Makefile.alpine b/test/Makefile.alpine new file mode 100644 index 00000000..7925b186 --- /dev/null +++ b/test/Makefile.alpine @@ -0,0 +1,5 @@ +ifneq (,$(wildcard /sbin/apk)) +## Install all dependencies for alpine +deps:: init + @apk add --update terraform-docs@cloudposse json2hcl@cloudposse +endif diff --git a/test/src/.gitignore b/test/src/.gitignore new file mode 100644 index 00000000..31b0219e --- /dev/null +++ b/test/src/.gitignore @@ -0,0 +1,2 @@ +.gopath +vendor/ diff --git a/test/src/Gopkg.lock b/test/src/Gopkg.lock new file mode 100644 index 00000000..87bb6bd6 --- /dev/null +++ b/test/src/Gopkg.lock @@ -0,0 +1,92 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:75d6042fc66aebc974cc49b0c6c7cc3b9adb5f8130fbfa0dbec0820d990afa25" + name = "github.com/gruntwork-io/terratest" + packages = [ + "modules/collections", + "modules/customerrors", + "modules/files", + "modules/logger", + "modules/retry", + "modules/shell", + "modules/ssh", + "modules/terraform", + ] + pruneopts = "UT" + revision = "892abb2c35878d0808101bbfe6559e931dc2d354" + version = "v0.16.0" + +[[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + pruneopts = "UT" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + digest = "1:5da8ce674952566deae4dbc23d07c85caafc6cfa815b0b3e03e41979cedb8750" + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + ] + pruneopts = "UT" + revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" + version = "v1.3.0" + +[[projects]] + branch = "master" + digest = "1:831470c2758c8b733941144f2803a0ccad0632c5a767415b777ebd296b5f463e" + name = "golang.org/x/crypto" + packages = [ + "curve25519", + "ed25519", + "ed25519/internal/edwards25519", + "internal/chacha20", + "internal/subtle", + "poly1305", + "ssh", + "ssh/agent", + ] + pruneopts = "UT" + revision = "22d7a77e9e5f409e934ed268692e56707cd169e5" + +[[projects]] + branch = "master" + digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70" + name = "golang.org/x/net" + packages = ["context"] + pruneopts = "UT" + revision = "f3200d17e092c607f615320ecaad13d87ad9a2b3" + +[[projects]] + branch = "master" + digest = "1:181f3fd33e620b958b5ab77da177cf775cdcccd7db82963607875fbd09ae995e" + name = "golang.org/x/sys" + packages = [ + "cpu", + "unix", + ] + pruneopts = "UT" + revision = "9cd6430ef91e39e1a0ec0470cf1321a33ef1b887" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/gruntwork-io/terratest/modules/terraform", + "github.com/stretchr/testify/assert", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/test/src/Gopkg.toml b/test/src/Gopkg.toml new file mode 100644 index 00000000..995bac57 --- /dev/null +++ b/test/src/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[prune] + go-tests = true + unused-packages = true diff --git a/test/src/Makefile b/test/src/Makefile new file mode 100644 index 00000000..3a342e36 --- /dev/null +++ b/test/src/Makefile @@ -0,0 +1,50 @@ +PACKAGE = terraform-aws-dynamic-subnets +GOEXE ?= /usr/bin/go +GOPATH = $(CURDIR)/.gopath +GOBIN = $(GOPATH)/bin +BASE = $(GOPATH)/src/$(PACKAGE) +PATH := $(PATH):$(GOBIN) + +export TF_DATA_DIR ?= $(CURDIR)/.terraform +export TF_CLI_ARGS_init ?= -get-plugins=true +export GOPATH + +.PHONY: all +## Default target +all: test + +ifneq (,$(wildcard /sbin/apk)) +## Install go, if not installed +$(GOEXE): + apk add --update go +endif + +ifeq ($(shell uname -s),Linux) +## Install all `dep`, if not installed +$(GOBIN)/dep: + @mkdir -p $(GOBIN) + @curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh +endif + +## Prepare the GOPATH +$(BASE): $(GOEXE) + @mkdir -p $(dir $@) + @ln -sf $(CURDIR) $@ + +## Download vendor dependencies to vendor/ +$(BASE)/vendor: $(BASE) $(GOBIN)/dep + cd $(BASE) && dep ensure + +.PHONY : init +## Initialize tests +init: $(BASE)/vendor + +.PHONY : test +## Run tests +test: init + cd $(BASE) && go test -v -timeout 30m -run TestExamplesComplete + +.PHONY : clean +## Clean up files +clean: + rm -rf .gopath/ vendor/ $(TF_DATA_DIR) diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go new file mode 100644 index 00000000..baf93432 --- /dev/null +++ b/test/src/examples_complete_test.go @@ -0,0 +1,41 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +// Test the Terraform module in examples/complete using Terratest. +func TestExamplesComplete(t *testing.T) { + t.Parallel() + + 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-west-1.tfvars"}, + } + + // 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) + + // Run `terraform output` to get the value of an output variable + privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs") + + expectedPrivateSubnetCidrs := []string{"172.16.0.0/18", "172.16.64.0/18"} + // Verify we're getting back the outputs we expect + assert.Equal(t, expectedPrivateSubnetCidrs, privateSubnetCidrs) + + // Run `terraform output` to get the value of an output variable + publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs") + + expectedPublicSubnetCidrs := []string{"172.16.128.0/18", "172.16.192.0/18"} + // Verify we're getting back the outputs we expect + assert.Equal(t, expectedPublicSubnetCidrs, publicSubnetCidrs) +} diff --git a/variables.tf b/variables.tf index 73a9241b..eeedbac5 100644 --- a/variables.tf +++ b/variables.tf @@ -9,11 +9,6 @@ variable "subnet_type_tag_value_format" { type = "string" } -variable "region" { - type = "string" - description = "AWS Region (e.g. `us-east-1`)" -} - variable "max_subnet_count" { default = 0 description = "Sets the maximum amount of subnets to deploy. 0 will deploy a subnet for every provided availablility zone (in `availability_zones` variable) within the region"