From c564099428c18c939031faa2e924aad3d794d23d Mon Sep 17 00:00:00 2001 From: confusdcodr Date: Wed, 21 Aug 2019 12:26:13 -0400 Subject: [PATCH] Module initialization --- .bumpversion.cfg | 6 ++ .dependabot/config.yml | 7 ++ .editorconfig | 23 ++++++ .gitignore | 12 ++++ .travis.yml | 58 ++++++++++++++++ CHANGELOG.md | 15 ++++ Makefile | 123 +++++++++++++++++++++++++++++++++ README.md | 13 ++++ _docs/MAIN.md | 3 + main.tf | 58 ++++++++++++++++ outputs.tf | 1 + tests/example_testcase/main.tf | 7 ++ tests/module_test.go | 49 +++++++++++++ variables.tf | 23 ++++++ 14 files changed, 398 insertions(+) create mode 100644 .bumpversion.cfg create mode 100644 .dependabot/config.yml create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 Makefile create mode 100644 README.md create mode 100644 _docs/MAIN.md create mode 100644 main.tf create mode 100644 outputs.tf create mode 100644 tests/example_testcase/main.tf create mode 100644 tests/module_test.go create mode 100644 variables.tf diff --git a/.bumpversion.cfg b/.bumpversion.cfg new file mode 100644 index 0000000..ee11dd6 --- /dev/null +++ b/.bumpversion.cfg @@ -0,0 +1,6 @@ +[bumpversion] +current_version = 0.0.0 +commit = True +message = Bumps version to {new_version} +tag = False +tag_name = {new_version} diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 0000000..ab6dbbc --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,7 @@ +version: 1 + +update_configs: + + - package_manager: "terraform" + directory: "/" + update_schedule: "daily" diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9c61d05 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +# see http://editorconfig.org +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 +charset = utf-8 + +[*.md] +trim_trailing_whitespace = false + +[*.py] +indent_size = 4 + +[Makefile] +indent_style = tab +indent_size = 1 + +[LICENSE] +indent_size = none diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9abe890 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Local .terraform directories +.terraform/ + +# .tfstate files +*.tfstate +*.tfstate.* + +# .tfvars files +*.tfvars + +# ignore this file +!tfmodule-template.tf diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9b2d7fb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,58 @@ +dist: xenial + +language: node_js + +node_js: + - "8" + +stages: + - lint + - deploy + +jobs: + include: + - stage: lint + name: EditorConfig Syntax Verification + install: + - npm install -g eclint + - eclint --version + script: eclint check + - stage: lint + name: Shell Script Syntax Verification + script: make sh/lint + - stage: lint + name: JSON Lint/Format Verification + script: make json/lint + - stage: lint + name: Terraform Lint/Format Verification + install: + - make terraform/install + - make terraform-docs/install + script: + - make terraform/lint + - make docs/lint + - stage: deploy + if: branch = master AND type = push AND repo = plus3it/terraform-aws-tardigrade-vpc-endpoints + before_script: + - | + PRIOR_VERSION=$(git describe --abbrev=0 --tags) + RELEASE_VERSION=$(grep current_version $TRAVIS_BUILD_DIR/.bumpversion.cfg | sed 's/^.*= //' ) + RELEASE_BODY="* [terraform-aws-tardigrade-vpc-endpoints v$RELEASE_VERSION CHANGELOG](https://github.com/plus3it/terraform-aws-tardigrade-vpc-endpoints/blob/$RELEASE_VERSION/CHANGELOG.md)" + export PRIOR_VERSION RELEASE_VERSION RELEASE_BODY + script: skip + before_deploy: + - | + (set -x; git tag -a $RELEASE_VERSION -m $RELEASE_VERSION) + deploy: + provider: releases + api_key: + secure: + name: $RELEASE_VERSION + body: $RELEASE_BODY + tag_name: $RELEASE_VERSION + target_commitish: $TRAVIS_COMMIT + draft: false + on: + branch: master + repo: plus3it/terraform-aws-tardigrade-vpc-endpoints + condition: '"$PRIOR_VERSION" != "$RELEASE_VERSION"' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a9c9bad --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +## terraform-aws-tardigrade-vpc-endpoints Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). + +### 0.0.0 + +**Commit Delta**: N/A + +**Released**: 2019.08.21 + +**Summary**: + +* Initial release! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1d88840 --- /dev/null +++ b/Makefile @@ -0,0 +1,123 @@ +ARCH ?= amd64 +OS ?= $(shell uname -s | tr '[:upper:]' '[:lower:']) +CURL ?= curl --fail -sSL +XARGS ?= xargs -I {} +BIN_DIR ?= ${HOME}/bin +TMP ?= /tmp +FIND_EXCLUDES ?= -not \( -name .terraform -prune \) -not \( -name .terragrunt-cache -prune \) + +PATH := $(BIN_DIR):${PATH} + +MAKEFLAGS += --no-print-directory +SHELL := bash +.SHELLFLAGS := -eu -o pipefail -c + +.PHONY: guard/% %/install %/lint + +GITHUB_ACCESS_TOKEN ?= 4224d33b8569bec8473980bb1bdb982639426a92 +# Macro to return the download url for a github release +# For latest release, use version=latest +# To pin a release, use version=tags/ +# $(call parse_github_download_url,owner,repo,version,asset select query) +parse_github_download_url = $(CURL) https://api.github.com/repos/$(1)/$(2)/releases/$(3)?access_token=$(GITHUB_ACCESS_TOKEN) | jq --raw-output '.assets[] | select($(4)) | .browser_download_url' + +# Macro to download a github binary release +# $(call download_github_release,file,owner,repo,version,asset select query) +download_github_release = $(CURL) -o $(1) $(shell $(call parse_github_download_url,$(2),$(3),$(4),$(5))) + +# Macro to download a hashicorp archive release +# $(call download_hashicorp_release,file,app,version) +download_hashicorp_release = $(CURL) -o $(1) https://releases.hashicorp.com/$(2)/$(3)/$(2)_$(3)_$(OS)_$(ARCH).zip + +guard/env/%: + @ _="$(or $($*),$(error Make/environment variable '$*' not present))" + +guard/program/%: + @ which $* > /dev/null || $(MAKE) $*/install + +$(BIN_DIR): + @ echo "[make]: Creating directory '$@'..." + mkdir -p $@ + +install/gh-release/%: guard/env/FILENAME guard/env/OWNER guard/env/REPO guard/env/VERSION guard/env/QUERY +install/gh-release/%: + @ echo "[$@]: Installing $*..." + $(call download_github_release,$(FILENAME),$(OWNER),$(REPO),$(VERSION),$(QUERY)) + chmod +x $(FILENAME) + $* --version + @ echo "[$@]: Completed successfully!" + +zip/install: + @ echo "[$@]: Installing $(@D)..." + apt-get install zip -y + @ echo "[$@]: Completed successfully!" + +terraform/install: TERRAFORM_VERSION_LATEST := $(CURL) https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version' | sed 's/^v//' +terraform/install: TERRAFORM_VERSION ?= $(shell $(TERRAFORM_VERSION_LATEST)) +terraform/install: | $(BIN_DIR) guard/program/jq + @ echo "[$@]: Installing $(@D)..." + $(call download_hashicorp_release,$(@D).zip,$(@D),$(TERRAFORM_VERSION)) + unzip $(@D).zip && rm -f $(@D).zip && chmod +x $(@D) + mv $(@D) "$(BIN_DIR)" + $(@D) --version + @ echo "[$@]: Completed successfully!" + +terraform-docs/install: TFDOCS_VERSION ?= latest +terraform-docs/install: | $(BIN_DIR) guard/program/jq + @ $(MAKE) install/gh-release/$(@D) FILENAME="$(BIN_DIR)/$(@D)" OWNER=segmentio REPO=$(@D) VERSION=$(TFDOCS_VERSION) QUERY='.name | endswith("$(OS)-$(ARCH)")' + +jq/install: JQ_VERSION ?= latest +jq/install: | $(BIN_DIR) + @ $(MAKE) install/gh-release/$(@D) FILENAME="$(BIN_DIR)/$(@D)" OWNER=stedolan REPO=$(@D) VERSION=$(JQ_VERSION) QUERY='.name | endswith("$(OS)64")' + +shellcheck/install: SHELLCHECK_VERSION ?= latest +shellcheck/install: SHELLCHECK_URL ?= https://storage.googleapis.com/shellcheck/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz +shellcheck/install: $(BIN_DIR) guard/program/xz + $(CURL) $(SHELLCHECK_URL) | tar -xJv + mv $(@D)-*/$(@D) $(BIN_DIR) + rm -rf $(@D)-* + $(@D) --version + +terraform/lint: | guard/program/terraform + @ echo "[$@]: Linting Terraform files..." + terraform fmt -check=true -diff=true + @ echo "[$@]: Terraform files PASSED lint test!" + +sh/%: FIND_SH := find . $(FIND_EXCLUDES) -name '*.sh' -type f -print0 +sh/lint: | guard/program/shellcheck + @ echo "[$@]: Linting shell scripts..." + $(FIND_SH) | $(XARGS) shellcheck {} + @ echo "[$@]: Shell scripts PASSED lint test!" + +json/%: FIND_JSON := find . $(FIND_EXCLUDES) -name '*.json' -type f +json/lint: | guard/program/jq + @ echo "[$@]: Linting JSON files..." + $(FIND_JSON) | $(XARGS) bash -c 'cmp {} <(jq --indent 4 -S . {}) || (echo "[{}]: Failed JSON Lint Test"; exit 1)' + @ echo "[$@]: JSON files PASSED lint test!" + +json/format: | guard/program/jq + @ echo "[$@]: Formatting JSON files..." + $(FIND_JSON) | $(XARGS) bash -c 'echo "$$(jq --indent 4 -S . "{}")" > "{}"' + @ echo "[$@]: Successfully formatted JSON files!" + +docs/%: README_PARTS := _docs/MAIN.md <(echo) <(terraform-docs markdown table .) +docs/%: README_FILE ?= README.md + +docs/lint: | guard/program/terraform-docs + @ echo "[$@]: Linting documentation files.." + diff $(README_FILE) <(cat $(README_PARTS)) + @ echo "[$@]: Documentation files PASSED lint test!" + +docs/generate: | guard/program/terraform-docs + @ echo "[$@]: Creating documentation files.." + cat $(README_PARTS) > $(README_FILE) + @ echo "[$@]: Documentation files creation complete!" + +dep/install: guard/program/curl + curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh + +terratest/install: | guard/program/go guard/program/dep + cd tests && dep ensure + +terratest/test: | guard/program/go guard/program/dep + cd tests && go test -timeout 20m diff --git a/README.md b/README.md new file mode 100644 index 0000000..ae7cc46 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# terraform-aws-tardigrade-vpc-endpoints + +Terraform module to create VPC Endpoints + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| create\_vpc\_endpoints | toggle to create vpc endpoints | string | `"false"` | no | +| subnet\_ids | target subnet ids | list | `` | no | +| tags | A map of tags to add to the VPC endpoint SG | map | `` | no | +| vpc\_endpoint\_interfaces | List of aws api endpoints that are used to create VPC Interface endpoints. See https://docs.aws.amazon.com/general/latest/gr/rande.html for full list. | list | `` | no | + diff --git a/_docs/MAIN.md b/_docs/MAIN.md new file mode 100644 index 0000000..5523b92 --- /dev/null +++ b/_docs/MAIN.md @@ -0,0 +1,3 @@ +# terraform-aws-tardigrade-vpc-endpoints + +Terraform module to create VPC Endpoints diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..0cbfc5f --- /dev/null +++ b/main.tf @@ -0,0 +1,58 @@ +data "aws_subnet" "selected" { + count = "${var.create_vpc_endpoints ? 1 : 0}" + + id = "${var.subnet_ids[0]}" +} + +data "aws_vpc" "selected" { + count = "${var.create_vpc_endpoints ? 1 : 0}" + + id = "${local.vpc_id}" +} + +locals { + vpc_id = "${join("", data.aws_subnet.selected.*.vpc_id)}" + vpc_cidr = "${join("", data.aws_vpc.selected.*.cidr_block)}" +} + +resource "aws_security_group" "this" { + count = "${var.create_vpc_endpoints ? 1 : 0}" + + description = "VPC Interface Endpoints - Allow inbound from ${local.vpc_id} and allow all outbound" + vpc_id = "${local.vpc_id}" + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["${local.vpc_cidr}"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = "${var.tags}" +} + +resource "aws_vpc_endpoint" "interface_services" { + count = "${var.create_vpc_endpoints ? length(var.vpc_endpoint_interfaces) : 0}" + + vpc_id = "${local.vpc_id}" + service_name = "${var.vpc_endpoint_interfaces[count.index]}" + vpc_endpoint_type = "Interface" + auto_accept = true + + subnet_ids = [ + "${var.subnet_ids}", + ] + + security_group_ids = [ + "${aws_security_group.this.id}", + ] + + private_dns_enabled = true # https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html#vpce-private-dns +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/outputs.tf @@ -0,0 +1 @@ + diff --git a/tests/example_testcase/main.tf b/tests/example_testcase/main.tf new file mode 100644 index 0000000..dbe7f9d --- /dev/null +++ b/tests/example_testcase/main.tf @@ -0,0 +1,7 @@ +terraform { + required_version = "~> 0.11.0" +} + +module "example" { + source = "../../" +} diff --git a/tests/module_test.go b/tests/module_test.go new file mode 100644 index 0000000..d3905e0 --- /dev/null +++ b/tests/module_test.go @@ -0,0 +1,49 @@ +package testing + +import ( + "io/ioutil" + "log" + "os" + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestModule(t *testing.T) { + files, err := ioutil.ReadDir("./") + + if err != nil { + log.Fatal(err) + } + + for _, f := range files { + // look for directories with test cases in it + if f.IsDir() && f.Name() != "vendor" { + investigateDirectory(t, f) + } + } +} + +func investigateDirectory(t *testing.T, directory os.FileInfo) { + // check if a prereq directory exists + prereqDir := directory.Name() + "/prereq/" + if _, err := os.Stat(prereqDir); err == nil { + prereqOptions := createTerraformOptions(prereqDir) + defer terraform.Destroy(t, prereqOptions) + terraform.InitAndApply(t, prereqOptions) + } + + // run terraform code for test case + terraformOptions := createTerraformOptions(directory.Name()) + defer terraform.Destroy(t, terraformOptions) + terraform.InitAndApply(t, terraformOptions) +} + +func createTerraformOptions(directory string) *terraform.Options { + terraformOptions := &terraform.Options{ + TerraformDir: directory, + NoColor: true, + } + + return terraformOptions +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..78ddecd --- /dev/null +++ b/variables.tf @@ -0,0 +1,23 @@ +variable "create_vpc_endpoints" { + type = "string" + description = "toggle to create vpc endpoints" + default = false +} + +variable "subnet_ids" { + type = "list" + description = "target subnet ids" + default = [] +} + +variable "vpc_endpoint_interfaces" { + type = "list" + description = "List of aws api endpoints that are used to create VPC Interface endpoints. See https://docs.aws.amazon.com/general/latest/gr/rande.html for full list." + default = [] +} + +variable "tags" { + description = "A map of tags to add to the VPC endpoint SG" + type = "map" + default = {} +}