#! /usr/bin/env bash set -euo pipefail vault_args=() temp_vault_pass_file="" usage() { cat <<'EOF' Usage: ./setup [--no-ansible] [--no-terraform|--ansible-only] [--] [terraform ] Defaults: - Runs Terraform (plan/apply) in terraform/ - Generates Ansible inventory from Terraform outputs - Runs Ansible playbooks Options: --no-ansible Run Terraform only (no Ansible). --no-terraform Skip Terraform; requires existing inventory/hosts.yml. --ansible-only Alias for --no-terraform. --help Show this help. Terraform passthrough: ./setup -- terraform [args] ./setup -- [args] EOF } cleanup() { if [[ -n "${temp_vault_pass_file}" ]] && [[ -f "${temp_vault_pass_file}" ]]; then rm -f "${temp_vault_pass_file}" fi } trap cleanup EXIT ansible_extra_args=() terraform_apply_args=() terraform_passthrough=() run_ansible=true run_terraform=true if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then usage exit 0 fi if [[ "${1:-}" == "--no-ansible" ]]; then run_ansible=false shift fi if [[ "${1:-}" == "--no-terraform" ]] || [[ "${1:-}" == "--ansible-only" ]]; then run_terraform=false shift fi if [[ "${1:-}" == "--" ]]; then shift if [[ "${1:-}" == "terraform" ]]; then shift terraform_passthrough=("$@") else case "${1:-}" in output|state|workspace|providers|version|validate|fmt|taint|untaint|graph|show|console|import) terraform_passthrough=("$@") ;; *) terraform_apply_args=("$@") ;; esac fi fi if [[ -f ".env" ]]; then set -a source .env set +a fi if [[ "${run_terraform}" == "true" ]]; then if ! command -v terraform >/dev/null 2>&1; then echo "terraform is required (install terraform or run with --no-terraform)" >&2 exit 2 fi fi if [[ "${run_ansible}" == "true" ]]; then if ! command -v ansible-playbook >/dev/null 2>&1; then echo "ansible-playbook is required (install ansible or run with --no-ansible)" >&2 exit 2 fi fi if [[ -f "secrets/vault.yml" ]]; then if ! command -v ansible-vault >/dev/null 2>&1; then echo "ansible-vault is required to read secrets/vault.yml" >&2 exit 2 fi if [[ -f "secrets/.vault_pass" ]]; then vault_args+=(--vault-password-file "secrets/.vault_pass") elif [[ -f ".vault_pass" ]]; then vault_args+=(--vault-password-file ".vault_pass") else read -rsp "Vault password: " vault_password echo temp_vault_pass_file=$(mktemp) chmod 600 "${temp_vault_pass_file}" printf '%s' "${vault_password}" > "${temp_vault_pass_file}" unset vault_password vault_args+=(--vault-password-file "${temp_vault_pass_file}") fi if (( ${#vault_args[@]} )); then vault_plain=$(ansible-vault view secrets/vault.yml "${vault_args[@]}") else vault_plain=$(ansible-vault view secrets/vault.yml) fi while IFS= read -r line; do [[ -z "${line}" ]] && continue [[ "${line}" == "---" ]] && continue [[ "${line}" != TF_VAR_*:* ]] && [[ "${line}" != CF_DNS_API_TOKEN:* ]] && [[ "${line}" != CF_ZONE_API_TOKEN:* ]] && [[ "${line}" != S3_ACCESS_KEY_ID:* ]] && [[ "${line}" != S3_SECRET_ACCESS_KEY:* ]] && continue key="${line%%:*}" value="${line#*:}" value="${value# }" [[ -z "${value}" ]] && continue escaped=$(printf '%q' "${value}") eval "export ${key}=${escaped}" done <<< "${vault_plain}" if [[ -z "${TF_VAR_cloudflare_api_token:-}" ]] && [[ -n "${CF_DNS_API_TOKEN:-}" ]]; then export TF_VAR_cloudflare_api_token="${CF_DNS_API_TOKEN}" fi if [[ -z "${TF_VAR_cloudflare_zone_id:-}" ]] && [[ -n "${CF_ZONE_API_TOKEN:-}" ]]; then export TF_VAR_cloudflare_zone_id="${CF_ZONE_API_TOKEN}" fi fi if [[ "${run_terraform}" == "true" ]]; then terraform -chdir=terraform init if (( ${#terraform_passthrough[@]} )); then terraform -chdir=terraform "${terraform_passthrough[@]}" exit 0 fi if (( ${#terraform_apply_args[@]} )); then terraform -chdir=terraform apply "${terraform_apply_args[@]}" else terraform -chdir=terraform plan -out=tfplan terraform -chdir=terraform apply tfplan fi rm -f terraform/tfplan web_ipv4=$(terraform -chdir=terraform output -raw web_ip) web_ipv6=$(terraform -chdir=terraform output -raw web_ipv6) services_ipv4=$(terraform -chdir=terraform output -raw services_ip) ssh_user=${TF_VAR_user:-ansible} mkdir -p inventory/host_vars cat > inventory/hosts.yml < inventory/host_vars/web.yml <&2 exit 2 fi fi if [[ "${run_ansible}" == "true" ]]; then if [[ -n "${vault_args+x}" ]] && (( ${#vault_args[@]} )); then ansible_extra_args=("${vault_args[@]}") fi ansible-playbook playbooks/services.yml ${ansible_extra_args[@]+"${ansible_extra_args[@]}"} ansible-playbook playbooks/web.yml ${ansible_extra_args[@]+"${ansible_extra_args[@]}"} fi