Skip to content

Instantly share code, notes, and snippets.

@mike-zipit
Last active July 20, 2018 19:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mike-zipit/fa936438c1edbb5f26ba68eec1cffaf8 to your computer and use it in GitHub Desktop.
Save mike-zipit/fa936438c1edbb5f26ba68eec1cffaf8 to your computer and use it in GitHub Desktop.
Geodesic food for thought

OK, fundamentally this script does 3 things:

  • It is bash + jq, already built into geodsic so can be included in /usr/local/binif we include terraform-docs in the build
  • It creates output-modules.tf which outputs all the input modules into the state
  • It creates README.md with your input/outputs for this module (for reference), but also gives you the module input/outputs you are using in this directory as reference

I started noticing I'm re-outputing module outputs to the state that I need later -- needs to be automated I also noticed I need to look up module inputs for the modules I'm using -- why not grab them and put them in the readme?

Bonus

Now it tells you when you're modules are out of date with the latest tags on github (or tries to)

screenshot

Generic VPC

Purpose

Execution

This module will typically be imported as /conf/vpc. If you are developing in this module, then you need to run init-terraform as follows:

TF_BUCKET_PREFIX=vpc init-terraform

Module vpc Inputs and Outputs

Inputs

Name Description Type Default Required
app_name string - yes
availability_zones list - yes
aws_account string - yes
aws_account_id string - yes
aws_profile string - yes
aws_region string - yes
cidr_block Base CIDR block which is divided into subnet CIDR blocks (e.g. 10.0.0.0/16) string 10.0.0.0/16 no
exposed_cidrs list - yes
github_organization string - yes
github_team string - yes
igw_id Internet Gateway ID that is used as a default route when creating public subnets (e.g. igw-9c26a123) string `` no
key_name string - yes
keypair_file_path string - yes
name string vpc no
namespace string global no
nat_images map <map> no
route53_domain string - yes
route53_zone string - yes
stage string default no
tags map <map> no

Outputs

Name Description
vpc_bastion_instance_id
vpc_bastion_label_attributes
vpc_bastion_label_id
vpc_bastion_label_name
vpc_bastion_label_namespace
vpc_bastion_label_stage
vpc_bastion_label_tags Merge input tags with our tags.nNote: Name has a special meaning in AWS and we need to disamgiuate it by using the computed idn
vpc_bastion_private_ip
vpc_bastion_public_ip
vpc_bastion_role
vpc_bastion_security_group_id
vpc_bastion_ssh_user
vpc_cloudtrail_cloudtrail_arn
vpc_cloudtrail_cloudtrail_home_region
vpc_cloudtrail_cloudtrail_id
vpc_cloudtrail_s3_bucket_bucket_arn
vpc_cloudtrail_s3_bucket_bucket_domain_name
vpc_cloudtrail_s3_bucket_bucket_id
vpc_cloudtrail_s3_bucket_bucket_prefix
vpc_private_subnets_az_ngw_ids
vpc_private_subnets_az_route_table_ids
vpc_private_subnets_az_subnet_ids
vpc_public_subnets_az_ngw_ids
vpc_public_subnets_az_route_table_ids
vpc_public_subnets_az_subnet_ids
vpc_vpc_igw_id The ID of the Internet Gateway
vpc_vpc_ipv6_cidr_block The IPv6 CIDR block
vpc_vpc_vpc_cidr_block The CIDR block of the VPC
vpc_vpc_vpc_default_network_acl_id The ID of the network ACL created by default on VPC creation
vpc_vpc_vpc_default_route_table_id The ID of the route table created by default on VPC creation
vpc_vpc_vpc_default_security_group_id The ID of the security group created by default on VPC creation
vpc_vpc_vpc_id The ID of the VPC
vpc_vpc_vpc_ipv6_association_id The association ID for the IPv6 CIDR block
vpc_vpc_vpc_main_route_table_id The ID of the main route table associated with this VPC.

Module bastion_label Inputs and Outputs:

Inputs

Name Description Type Default Required
attributes Additional attributes (e.g. policy or role) list <list> no
delimiter Delimiter to be used between name, namespace, stage, etc. string - no
enabled Set to false to prevent the module from creating any resources string true no
name string - yes
namespace string - yes
stage string - yes
tags Additional tags (e.g. map('BusinessUnit,XYZ) map <map> no

Outputs

Name Description
attributes
id
name
namespace
stage
tags Merge input tags with our tags. Note: Name has a special meaning in AWS and we need to disamgiuate it by using the computed id

Module bastion Inputs and Outputs:

Inputs

Name Description Type Default Required
ami string ami-efd0428f no
instance_type string t2.micro no
key_name string `` no
name string bastion no
namespace string global no
security_groups list - yes
ssh_user string ubuntu no
stage string default no
subnets list <list> no
user_data list <list> no
user_data_file string user_data.sh no
vpc_id string `` no
zone_id string `` no

Outputs

Name Description
instance_id
private_ip
public_ip
role
security_group_id
ssh_user

Module cloudtrail Inputs and Outputs:

Inputs

Name Description Type Default Required
attributes Additional attributes (e.g. logs) list <list> no
delimiter Delimiter to be used between namespace, stage, name and attributes string - no
enable_log_file_validation Specifies whether log file integrity validation is enabled. Creates signed digest for validated contents of logs string true no
enable_logging Enable logging for the trail string true no
include_global_service_events Specifies whether the trail is publishing events from global services such as IAM to the log files string false no
is_multi_region_trail Specifies whether the trail is created in the current region or in all regions string false no
name Name (e.g. app or cluster) string - yes
namespace Namespace (e.g. cp or cloudposse) string - yes
s3_bucket_name S3 bucket name for CloudTrail logs string - yes
stage Stage (e.g. prod, dev, staging) string - yes
tags Additional tags (e.g. map('BusinessUnit,XYZ`) map <map> no

Outputs

Name Description
cloudtrail_arn
cloudtrail_home_region
cloudtrail_id

Module cloudtrail_s3_bucket Inputs and Outputs:

Inputs

Name Description Type Default Required
acl Canned ACL to apply to the S3 bucket string log-delivery-write no
attributes Additional attributes (e.g. logs) list <list> no
delimiter Delimiter to be used between namespace, stage, name and attributes string - no
force_destroy A boolean that indicates the bucket can be destroyed even if it contains objects. These objects are not recoverable string false no
name Name (e.g. app or cluster) string - yes
namespace Namespace (e.g. cp or cloudposse) string - yes
prefix The S3 bucket prefix for the AWSLogs string lb no
region AWS Region for S3 bucket string us-east-1 no
stage Stage (e.g. prod, dev, staging) string - yes
tags Additional tags (e.g. map(BusinessUnit,XYZ) map <map> no

Outputs

Name Description
bucket_arn
bucket_domain_name
bucket_id
bucket_prefix

Module vpc Inputs and Outputs:

Inputs

Name Description Type Default Required
attributes Additional attributes (e.g. 1) list <list> no
cidr_block CIDR for the VPC string 10.0.0.0/16 no
delimiter Delimiter to be used between namespace, stage, name and attributes string - no
enable_classiclink A boolean flag to enable/disable ClassicLink for the VPC string false no
enable_classiclink_dns_support A boolean flag to enable/disable ClassicLink DNS Support for the VPC string false no
enable_dns_hostnames A boolean flag to enable/disable DNS hostnames in the VPC string true no
enable_dns_support A boolean flag to enable/disable DNS support in the VPC string true no
instance_tenancy A tenancy option for instances launched into the VPC string default no
name Name (e.g. app or cluster) string - yes
namespace Namespace (e.g. cp or cloudposse) string - yes
stage Stage (e.g. prod, dev, staging) string - yes
tags Additional tags (e.g. map(BusinessUnit,XYZ) map <map> no

Outputs

Name Description
igw_id The ID of the Internet Gateway
ipv6_cidr_block The IPv6 CIDR block
vpc_cidr_block The CIDR block of the VPC
vpc_default_network_acl_id The ID of the network ACL created by default on VPC creation
vpc_default_route_table_id The ID of the route table created by default on VPC creation
vpc_default_security_group_id The ID of the security group created by default on VPC creation
vpc_id The ID of the VPC
vpc_ipv6_association_id The association ID for the IPv6 CIDR block
vpc_main_route_table_id The ID of the main route table associated with this VPC.

Module public_subnets Inputs and Outputs:

Inputs

Name Description Type Default Required
attributes Additional attributes (e.g. policy or role) list <list> no
availability_zones List of Availability Zones (e.g. ['us-east-1a', 'us-east-1b', 'us-east-1c']) list <list> no
az_ngw_count Count of items in the az_ngw_ids map. Needs to be explicitly provided since Terraform currently can't use dynamic count on computed resources from different modules. hashicorp/terraform#10857 string 0 no
az_ngw_ids Only for private subnets. Map of AZ names to NAT Gateway IDs that are used as default routes when creating private subnets map <map> no
cidr_block Base CIDR block which is divided into subnet CIDR blocks (e.g. 10.0.0.0/16) string - yes
delimiter Delimiter to be used between namespace, stage, name and attributes string - no
enabled Set to false to prevent the module from creating any resources string true no
igw_id Internet Gateway ID that is used as a default route when creating public subnets (e.g. igw-9c26a123) string `` no
max_subnets Maximum number of subnets that can be created. The variable is used for CIDR blocks calculation string 6 no
name Application or solution name string - yes
namespace Namespace (e.g. cp or cloudposse) string - yes
nat_gateway_enabled Flag to enable/disable NAT Gateways creation in public subnets string true no
private_network_acl_egress Egress network ACL rules list <list> no
private_network_acl_id Network ACL ID that is added to the private subnets. If empty, a new ACL will be created string `` no
private_network_acl_ingress Egress network ACL rules list <list> no
public_network_acl_egress Egress network ACL rules list <list> no
public_network_acl_id Network ACL ID that is added to the public subnets. If empty, a new ACL will be created string `` no
public_network_acl_ingress Egress network ACL rules list <list> no
stage Stage (e.g. prod, dev, staging) string - yes
tags Additional tags (e.g. map(BusinessUnit,XYZ) map <map> no
type Type of subnets to create (private or public) string private no
vpc_id VPC ID string - yes

Outputs

Name Description
az_ngw_ids
az_route_table_ids
az_subnet_ids

Module private_subnets Inputs and Outputs:

Inputs

Name Description Type Default Required
attributes Additional attributes (e.g. policy or role) list <list> no
availability_zones List of Availability Zones (e.g. ['us-east-1a', 'us-east-1b', 'us-east-1c']) list <list> no
az_ngw_count Count of items in the az_ngw_ids map. Needs to be explicitly provided since Terraform currently can't use dynamic count on computed resources from different modules. hashicorp/terraform#10857 string 0 no
az_ngw_ids Only for private subnets. Map of AZ names to NAT Gateway IDs that are used as default routes when creating private subnets map <map> no
cidr_block Base CIDR block which is divided into subnet CIDR blocks (e.g. 10.0.0.0/16) string - yes
delimiter Delimiter to be used between namespace, stage, name and attributes string - no
enabled Set to false to prevent the module from creating any resources string true no
igw_id Internet Gateway ID that is used as a default route when creating public subnets (e.g. igw-9c26a123) string `` no
max_subnets Maximum number of subnets that can be created. The variable is used for CIDR blocks calculation string 6 no
name Application or solution name string - yes
namespace Namespace (e.g. cp or cloudposse) string - yes
nat_gateway_enabled Flag to enable/disable NAT Gateways creation in public subnets string true no
private_network_acl_egress Egress network ACL rules list <list> no
private_network_acl_id Network ACL ID that is added to the private subnets. If empty, a new ACL will be created string `` no
private_network_acl_ingress Egress network ACL rules list <list> no
public_network_acl_egress Egress network ACL rules list <list> no
public_network_acl_id Network ACL ID that is added to the public subnets. If empty, a new ACL will be created string `` no
public_network_acl_ingress Egress network ACL rules list <list> no
stage Stage (e.g. prod, dev, staging) string - yes
tags Additional tags (e.g. map(BusinessUnit,XYZ) map <map> no
type Type of subnets to create (private or public) string private no
vpc_id VPC ID string - yes

Outputs

Name Description
az_ngw_ids
az_route_table_ids
az_subnet_ids

#!/usr/bin/env bash
# ##################################################
# Purpose: Create README.md from ${HEADER}/${FOOTER} and build output-${GEOMODULE}.tf from included modules
#
version="1.0.4"
#
# HISTORY:
#
# * 19-Jun-2018 - v1.0.4 - Fixing logic bug determining if on the right tag
#
# ##################################################
GEOMODULE=$(basename $(pwd))
GEOMODULE=${GEOMODULE//-/_}
GOUT=output-${GEOMODULE}.tf
HEADER=.header.local.md
FOOTER=.footer.local.md
function mainScript() {
TFDOC=$(which terraform-docs_linux_amd64)
if [ "${TFDOC}" == "" ]; then
TFDOC=$(which terraform-docs)
if [ "${TFDOC}" == "" ]; then
error "You need a binary of terraform-docs in your path"
die
fi
fi
if [ ! -d .terraform ]; then
die "You must init the local directory using ${bold}init-terraform${reset} first"
fi
RM1=$(mktemp)
RM2=$(mktemp)
rm -rf ${GOUT}
touch ${GOUT}
cat .terraform/modules/modules.json | jq -rc '.Modules[] | select(.Key | test("^[^|]*$"))' | while read JSON; do
DIR="$(echo "${JSON}" | jq -r .Dir)"
KEY="$(echo "${JSON}" | jq -r .Key | sed 's/^1\.//' | sed 's/;.*$//')"
SOURCE="$(echo "${JSON}" | jq -r .Source)"
# debug "JSON=${JSON}"
if [[ "${SOURCE}" == *"cloudposse/terraform-terraform-label.git"* ]]; then
debug "Ignoring module ${KEY} (${SOURCE})"
continue
fi
if [[ "${SOURCE}" == *"cloudposse/terraform-null-label.git"* ]]; then
debug "Ignoring module ${KEY} (${SOURCE})"
continue
fi
if [ ! -d ${DIR} ]; then
continue
fi
debug "Processing ${bold}${DIR}${reset}, terraform module ${bold}${KEY}${reset}"
debug "Source=${SOURCE}"
REPO=$(echo "${SOURCE}" | sed -r "s/^.*github.com\/((\/\w+)*\/)?([\w\-\.]*[^#? \t]+)?(\?[a-z]+=)?(.*)?(#[\w\-]+)?$/\3/")
TAG=$(echo "${SOURCE}" | sed -r "s/^.*github.com\/((\/\w+)*\/)?([\w\-\.]*[^#? \t]+)?(\?[a-z]+=)?(.*)?(#[\w\-]+)?$/\5/")
if [ "${cache[${REPO}]}" != "" ]; then
LATEST="${cache[${REPO}]}"
else
LATEST=$(curl --silent "https://api.github.com/repos/${REPO/.git/}/tags?${GITHUB_ACCESS_TOKEN}" | jq -r '.[0]?.name')
cache[${REPO}]="${LATEST}"
fi
debug "REPO=${REPO} TAG=${TAG} and latest=${LATEST}"
if [ "${LATEST}" == "" ]; then
notice "Repo ${REPO} does not appear to use tags. Please suggest they tag their revisions for repeatability"
elif [ "${TAG}" == "master" ]; then
warning "You should NOT be referencing master. We recommend using ${REPO}?refs=tags/${LATEST} instead"
elif [ "${TAG}" == "${LATEST}" ]; then
debug "You are using what appears to be the latest version (${LATEST})"
elif [ "${TAG}" == "tags/${LATEST}" ]; then
debug "You are using what appears to be the latest version (${LATEST})"
else
notice "NOTE: The latest tag for ${REPO} is ${LATEST} (you are using ${TAG})"
fi
echo "### Module \`${KEY}\` Inputs and Outputs: " >> ${RM1}
if ${readme}; then
debug "Using ${TFDOC} to get the documentation for ${bold}${KEY}${reset} and adding it to README.md"
${TFDOC} md ${DIR} >> ${RM1}
fi
break >> ${RM1}
if ${output}; then
debug "Now using ${TFDOC} to get the outputs of for module ${bold}${KEY}${reset} and create our ${bold}${GOUT}${reset} file"
${TFDOC} json ${DIR} | jq -rc ".Outputs[]? " | while read OUTPUT; do
NAME=$(echo "${OUTPUT}" | jq -r .Name)
DESC=$(echo "${OUTPUT}" | jq -r .Description?)
NEW_KEY=$(echo "${GEOMODULE}_${KEY}_${NAME}" | sed "s/${GEOMODULE}_\(${GEOMODULE}_\)*/${GEOMODULE}_/g")
info "Variable ${bold}${NAME}${reset} from ${bold}${KEY}${reset} be output as ${bold}${NEW_KEY}${reset}"
cat <<EOF >> ${GOUT}
output "${NEW_KEY}" {
value = "\${module.${KEY}.${NAME}}"
description = "${DESC}"
}
EOF
done
fi
done
if ${readme}; then
if [ -f README.md -a ! -f ${HEADER} ]; then
seek_confirmation "Warning -- this overwrites ${bold}README.md${reset} -- break now or suffer the consequences (I'm warning you because you don't have a ${HEADER} file)"
if ! is_confirmed; then
die
fi
fi
rm README.md -f
touch README.md
if [ -f ${HEADER} ]; then
debug "You have a ${HEADER}, adding that to ${bold}README.md${reset}"
cat ${HEADER} > README.md
fi
echo "# Module \`${GEOMODULE}\` Inputs and Outputs" >> README.md
debug "Running terraform-docs to build your documentation for this directory"
${TFDOC} md . >> README.md
break >> README.md
cat ${RM1} >> README.md
if [ -f ${FOOTER} ]; then
cat ${FOOTER} >> README.md
fi
notice "${bold}README.md${reset} created"
fi
if ${output}; then
notice "${bold}${GOUT}${reset} created"
fi
echo " "
}
function break {
echo " "
echo "---"
echo " "
}
# Options and Usage
# -----------------------------------
function usage() {
echo -n "${scriptName} [OPTION]...
Fundamentally this script can do 2 things:
- It creates ${bold}output-modules.tf${reset} which outputs all the input modules into the state
- It creates ${bold}README.md${reset} with your input/outputs for this module (for reference), but also gives you the module input/outputs you are using in this directory as reference
${bold}Options:${reset}
--no-readme Don't build the ${bold}README.md${reset} file
--no-output-modules Don't build the ${bold}output-modules.tf${reset} file
-p, --prefix Define the prefix to use instead of '${bold}${GEOMODULE}${reset}' -- used in the ${bold}output-modules.tf${reset} file as the module prefix
-o, --output-name Define the name for the output modules (currently ${bold}output-modules.tf${reset})
-l, --log-level Set the display logging level (default=${bold}notice${reset}. Valid values are debug|info|notice
-d, --debug Set logging level to debug (shortcut)
-n, --notice Set logging level to notice (shortcut)
-h, --help Display this help and exit
--version Output version information and exit
NOTES:
* If you have ${HEADER} and/or ${FOOTER} in this directory, those will be prepended/appended to the README.md
* If ${bold}WILL${reset} a github API rate limit trying to get the latest releases (null comes back for versions). Create your own authentication by setting:
export GITHUB_ACCESS_TOKEN=access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
"
}
function process_user_options() {
# Print help if no arguments were passed.
# Uncomment to force arguments when invoking the script
# -------------------------------------
#[[ $# -eq 0 ]] && set -- "--help"
# Set Flags
quiet=true
printLog=false
logLevel=info
force=false
strict=false
debug=false
readme=true
output=true
args=()
# Read the options and set stuff
while [[ ${1} = -?* ]]; do
case ${1} in
--no-readme) readme=false; notice "Not building ${bold}README.md${reset}" ;;
--no-output-modules) output=false notice "Not building ${bold}${GOUT}${reset}" ;;
-h|--help) usage >&2; safeExit ;;
--version) echo "$(basename ${0}) ${version}"; safeExit ;;
-p|--prefix) shift; GEOMODULE=${1}; GOUT=output-${GEOMODULE}.tf; notice "Changing the prefix to ${bold}${GEOMODULE}${reset}" ;;
-o|--output-name) shift; GOUT=${1}; notice "Changing the output modules name to ${bold}${GOUT}${reset}" ;;
-l|--log-level) shift; logLevel=${1}; shift; ;;
-d|--debug) shift; logLevel=debug; shift; ;;
-n|--notice) shift; logLevel=notice; shift; ;;
--endopts) shift; break ;;
*) usage; die "invalid option: '${1}'." ;;
esac
shift
done
# Store the remaining part as arguments.
args+=("$@")
}
###
### ----------------------[ No editing normally below here ]----------------------
###
# Define log levels
# ----------------------
declare -A logLevels=(["debug"]=0 ["info"]=1 ["notice"]=2)
declare -A cache=()
# Set Base Variables
# ----------------------
scriptName=$(basename "${0}")
# Logging
# -----------------------------------
# Log is only used when the '-l' flag is set.
logFile="/tmp/${scriptBasename}.log"
function trapCleanup() {
echo ""
# Delete temp files, if any
if [ -d "${tmpDir}" ] ; then
rm -r "${tmpDir}"
fi
die "Exit trapped. In function: '${FUNCNAME[*]}'"
}
function safeExit() {
# Delete temp files, if any
if [ -d "${tmpDir}" ] ; then
rm -r "${tmpDir}"
fi
trap - INT TERM EXIT
exit
}
# Set Colors
bold=$(tput bold)
reset=$'\e[0m'
purple=$'\e[1;35m'
red=$'\e[1;31m'
green=$'\e[1;32m'
tan=$'\e[1;36m'
blue=$'\e[1;34m'
underline=$(tput sgr 0 1)
# Set Temp Directory
tmpDir="/tmp/${scriptName}.${RANDOM}.${RANDOM}.${RANDOM}.$"
(umask 077 && mkdir "${tmpDir}") || {
die "Could not create temporary directory! Exiting."
}
# Logging & Feedback
# -----------------------------------------------------
function _alert() {
case ${1} in
debug|notice|info)
[[ ${logLevels[${1}]} ]] || return 1
#check if level is enough
(( ${logLevels[${1}]} < ${logLevels[$logLevel]} )) && return 2
;;
esac
case ${1} in
error) local color="${bold}${red}"; ;;
warning) local color="${red}"; ;;
success) local color="${green}"; ;;
debug) local color="${purple}"; ;;
header) local color="${bold}${tan}"; ;;
input) local color="${bold}"; ;;
notice) local color="${green}"; ;;
info) local color=""; ;;
esac
# Don't use colors on pipes or non-recognized terminals
if [[ "${TERM}" != "xterm"* ]] || [ -t 1 ]; then color=""; reset=""; fi
echo " "
echo -e "$(date +"%r") ${color}$(printf "[%7s]" "${1}") ${_message}${reset}\\n";
# Print to Logfile
if ${printLog} && [ "${1}" != "input" ]; then
color=""; reset="" # Don't use colors in logs
echo -e "$(date +"%m-%d-%Y %r") $(printf "[%7s]" "${1}") ${_message}" >> "${logFile}";
fi
}
function die () { local _message="${*} Exiting."; quiet=false; echo -e "$(_alert error)"; safeExit;}
function error () { local _message="${*}"; echo -en "$(_alert error)"; }
function warning () { local _message="${*}"; echo -en "$(_alert warning)"; }
function notice () { local _message="${*}"; echo -en "$(_alert notice)"; }
function info () { local _message="${*}"; echo -en "$(_alert info)"; }
function debug () { local _message="${*}"; echo -en "$(_alert debug)"; }
function success () { local _message="${*}"; echo -en "$(_alert success)"; }
function input() { local _message="${*}"; echo -n "$(_alert input)"; }
function header() { local _message="== ${*} == "; echo -e "$(_alert header)"; }
function verbose() { if ${verbose}; then debug "$@"; fi }
# SEEKING CONFIRMATION
# ------------------------------------------------------
function seek_confirmation() {
# echo ""
input "$@"
if "${force}"; then
notice "Forcing confirmation with '--force' flag set"
else
read -p " (y/n) " -n 1
echo ""
fi
}
function is_confirmed() {
if "${force}"; then
return 0
else
if [[ "${REPLY}" =~ ^[Yy]$ ]]; then
return 0
fi
return 1
fi
}
function is_not_confirmed() {
if "${force}"; then
return 1
else
if [[ "${REPLY}" =~ ^[Nn]$ ]]; then
return 0
fi
return 1
fi
}
# Iterate over options breaking -ab into -a -b when needed and --foo=bar into
# --foo bar
optstring=h
unset options
while (($#)); do
case ${1} in
# If option is of type -ab
-[!-]?*)
# Loop over each character starting with the second
for ((i=1; i < ${#1}; i++)); do
c=${1:i:1}
# Add current char to options
options+=("-$c")
# If option takes a required argument, and it's not the last char make
# the rest of the string its argument
if [[ $optstring = *"$c:"* && ${1:i+1} ]]; then
options+=("${1:i+1}")
break
fi
done
;;
# If option is of type --foo=bar
--?*=*) options+=("${1%%=*}" "${1#*=}") ;;
# add --endopts for --
--) options+=(--endopts) ;;
# Otherwise, nothing special
*) options+=("${1}") ;;
esac
shift
done
set -- "${options[@]}"
unset options
process_user_options $@
# Trap bad exits with your cleanup function
trap trapCleanup EXIT INT TERM
# Set IFS to preferred implementation
IFS=$' \n\t'
# Exit on error. Append '||true' when you run the script if you expect an error.
set -o errexit
# Run in debug mode, if set
if ${debug}; then set -x ; fi
# Exit on empty variable
if ${strict}; then set -o nounset ; fi
# Bash will remember & return the highest exitcode in a chain of pipes.
# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`, for example.
set -o pipefail
# Run your script
mainScript
# Exit cleanly
safeExit
output "vpc_bastion_label_attributes" {
value = "module.bastion_label.attributes"
description = ""
}
output "vpc_bastion_label_id" {
value = "module.bastion_label.id"
description = ""
}
output "vpc_bastion_label_name" {
value = "module.bastion_label.name"
description = ""
}
output "vpc_bastion_label_namespace" {
value = "module.bastion_label.namespace"
description = ""
}
output "vpc_bastion_label_stage" {
value = "module.bastion_label.stage"
description = ""
}
output "vpc_bastion_label_tags" {
value = "module.bastion_label.tags"
description = "Merge input tags with our tags.nNote: `Name` has a special meaning in AWS and we need to disamgiuate it by using the computed `id`n"
}
output "vpc_bastion_instance_id" {
value = "module.bastion.instance_id"
description = ""
}
output "vpc_bastion_private_ip" {
value = "module.bastion.private_ip"
description = ""
}
output "vpc_bastion_public_ip" {
value = "module.bastion.public_ip"
description = ""
}
output "vpc_bastion_role" {
value = "module.bastion.role"
description = ""
}
output "vpc_bastion_security_group_id" {
value = "module.bastion.security_group_id"
description = ""
}
output "vpc_bastion_ssh_user" {
value = "module.bastion.ssh_user"
description = ""
}
output "vpc_cloudtrail_cloudtrail_arn" {
value = "module.cloudtrail.cloudtrail_arn"
description = ""
}
output "vpc_cloudtrail_cloudtrail_home_region" {
value = "module.cloudtrail.cloudtrail_home_region"
description = ""
}
output "vpc_cloudtrail_cloudtrail_id" {
value = "module.cloudtrail.cloudtrail_id"
description = ""
}
output "vpc_cloudtrail_s3_bucket_bucket_arn" {
value = "module.cloudtrail_s3_bucket.bucket_arn"
description = ""
}
output "vpc_cloudtrail_s3_bucket_bucket_domain_name" {
value = "module.cloudtrail_s3_bucket.bucket_domain_name"
description = ""
}
output "vpc_cloudtrail_s3_bucket_bucket_id" {
value = "module.cloudtrail_s3_bucket.bucket_id"
description = ""
}
output "vpc_cloudtrail_s3_bucket_bucket_prefix" {
value = "module.cloudtrail_s3_bucket.bucket_prefix"
description = ""
}
output "vpc_vpc_igw_id" {
value = "module.vpc.igw_id"
description = "The ID of the Internet Gateway"
}
output "vpc_vpc_ipv6_cidr_block" {
value = "module.vpc.ipv6_cidr_block"
description = "The IPv6 CIDR block"
}
output "vpc_vpc_vpc_cidr_block" {
value = "module.vpc.vpc_cidr_block"
description = "The CIDR block of the VPC"
}
output "vpc_vpc_vpc_default_network_acl_id" {
value = "module.vpc.vpc_default_network_acl_id"
description = "The ID of the network ACL created by default on VPC creation"
}
output "vpc_vpc_vpc_default_route_table_id" {
value = "module.vpc.vpc_default_route_table_id"
description = "The ID of the route table created by default on VPC creation"
}
output "vpc_vpc_vpc_default_security_group_id" {
value = "module.vpc.vpc_default_security_group_id"
description = "The ID of the security group created by default on VPC creation"
}
output "vpc_vpc_vpc_id" {
value = "module.vpc.vpc_id"
description = "The ID of the VPC"
}
output "vpc_vpc_vpc_ipv6_association_id" {
value = "module.vpc.vpc_ipv6_association_id"
description = "The association ID for the IPv6 CIDR block"
}
output "vpc_vpc_vpc_main_route_table_id" {
value = "module.vpc.vpc_main_route_table_id"
description = "The ID of the main route table associated with this VPC."
}
output "vpc_public_subnets_az_ngw_ids" {
value = "module.public_subnets.az_ngw_ids"
description = ""
}
output "vpc_public_subnets_az_route_table_ids" {
value = "module.public_subnets.az_route_table_ids"
description = ""
}
output "vpc_public_subnets_az_subnet_ids" {
value = "module.public_subnets.az_subnet_ids"
description = ""
}
output "vpc_private_subnets_az_ngw_ids" {
value = "module.private_subnets.az_ngw_ids"
description = ""
}
output "vpc_private_subnets_az_route_table_ids" {
value = "module.private_subnets.az_route_table_ids"
description = ""
}
output "vpc_private_subnets_az_subnet_ids" {
value = "module.private_subnets.az_subnet_ids"
description = ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment