Skip to content

Instantly share code, notes, and snippets.

@mmarseglia
Created September 12, 2018 15:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmarseglia/97e643b9f39d62621285e960ee7da6db to your computer and use it in GitHub Desktop.
Save mmarseglia/97e643b9f39d62621285e960ee7da6db to your computer and use it in GitHub Desktop.
Terraform Makefile
APP_NAME = ${TF_VAR_app_name}
REGION = ${TF_VAR_region}
KEY = 'terraform.state'
PROFILE = ${TF_VAR_profile}
AWS_ACCOUNT = ${TF_VAR_aws_account}
BUCKET = "${APP_NAME}-${AWS_ACCOUNT}"
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
.PHONY: help
help: ## This help message.
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.PHONY: clean
clean: ## Clean up local after a terraform init, plan or run.
rm -rf terraform/.terraform terraform/*.tfstate output.json inspec.json bucket
.PHONY: all
all: plan apply test output
.PHONY: backend
backend: bucket ## Initialize terraform backend
@cd terraform; \
terraform init \
--backend-config="bucket=$(BUCKET)" \
--backend-config="region=$(REGION)" \
--backend-config="key=$(KEY)" \
--backend-config="profile=$(PROFILE)"
bucket: ## Attempts to create or verify the S3 bucket is available as a backend
@aws --profile $(PROFILE) s3 ls $(BUCKET) && echo $(BUCKET) > bucket || aws --profile $(PROFILE) s3 mb s3://$(BUCKET); \
if [ $$? -ne 0 ]; then \
echo "Bucket $(BUCKET) exists and we don't own it or your credentials are incorrect."; \
exit 1; \
fi;
.PHONY: validate
validate: terraform/*.tf ## Runs `terraform validate` against all the .tf files
@cd terraform; \
for i in $$(find . -type f -name "*.tf" -prune -o -name '.terraform' -exec dirname {} \;); do \
terraform validate "$$i"; \
if [ $$? -ne 0 ]; then \
echo "Failed Terraform file validation on file $${i}"; \
echo; \
exit 1; \
fi; \
done
.PHONY: update
update:
@cd terraform; \
terraform get -update=true 1>/dev/null
plan: backend update validate ## Display all the changes that Terraform is going to make.
@cd terraform && \
terraform plan \
-input=false
plan-target: backend update validate ## Shows what a plan looks like for applying a specific resource
@tput setaf 3; tput bold; echo -n "[INFO] "; tput sgr0; echo "Example to type for the following question: module.rds.aws_route53_record.rds-master"
@read -p "PLAN target: " DATA &&\
terraform plan \
-input=true \
-target=$$DATA
plan-destroy: backend update validate ## Creates a destruction plan.
@terraform plan \
-input=false \
-destroy
show: backend ## Show terraform resources.
@cd terraform; \
terraform show -module-depth=-1
graph: ## Output the `dot` graph of all the built Terraform resources
@rm -f graph.png
@terraform graph -draw-cycles -module-depth=-1 | dot -Tpng > graph.png
@shotwell graph.png
apply: ## Apply builds/changes resources. You should ALWAYS run a plan first.
@cd terraform && \
terraform apply \
-input=true \
-refresh=true \
-auto-approve
apply-target: backend update ## Apply a specific resource and any chained resources.
@tput setaf 3; tput bold; echo -n "[INFO] "; tput sgr0; echo "Specifically APPLY a piece of Terraform data."
@tput setaf 3; tput bold; echo -n "[INFO] "; tput sgr0; echo "Example to type for the following question: module.rds.aws_route53_record.rds-master"
@tput setaf 1; tput bold; echo -n "[DANGER] "; tput sgr0; echo "You are about to apply a new state."
@tput setaf 1; tput bold; echo -n "[DANGER] "; tput sgr0; echo "This has the potential to break your infrastructure."
@read -p "APPLY target: " DATA &&\
terraform apply \
-input=true \
-refresh=true \
-target=$$DATA
.PHONY: output
output: output.json ## Generate all output files.
output.json: terraform/outputs.tf apply ## Display all outputs from the remote state file and save as JSON.
@cd terraform && \
if [ -n $(MODULE) ]; then\
terraform output -json > ../output.json;\
else\
terraform output -module=$(MODULE);\
fi
taint: backend update ## Taint a resource for destruction upon next `apply`
@echo "Tainting involves specifying a module and a resource"
@read -p "Module: " MODULE && \
read -p "Resource: " RESOURCE && \
terraform taint \
-module=$$MODULE $$RESOURCE
@echo "You will now want to run a plan to see what changes will take place"
destroy: backend update ## Destroys everything. There is a prompt before destruction.
@cd terraform && \
terraform destroy
destroy-target: backend update ## Destroy a specific resource. Caution though, this destroys chained resources.
@echo "Specifically destroy a piece of Terraform data."
@echo
@echo "Example to type for the following question: module.rds.aws_route53_record.rds-master"
@echo
@read -p "Destroy target: " DATA &&\
terraform destroy \
-target=$$DATA
.PHONY: test
test: inspec.json ## Run all tests.
inspec.json: output ## Run inspec tests and output results as JSON.
@inspec exec test \
-t aws://us-east-1/$(APP_NAME) \
--reporter json \
json:/$(ROOT_DIR)/inspec.json%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment