#!/usr/bin/env bash # Setup Terraform Backend Storage Account # Creates storage account, container, and updates .env file set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../lib/init.sh" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Load .env via dotenv (RPC CR/LF trim). Fallback: raw source. if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then # shellcheck disable=SC1090 source "$SCRIPT_DIR/../lib/deployment/dotenv.sh" load_deployment_env --repo-root "${PROJECT_ROOT:-$REPO_ROOT}" elif [[ -n "${PROJECT_ROOT:-}" && -f "$PROJECT_ROOT/.env" ]]; then set -a # shellcheck disable=SC1090 source "$PROJECT_ROOT/.env" set +a elif [[ -n "${REPO_ROOT:-}" && -f "$REPO_ROOT/.env" ]]; then set -a # shellcheck disable=SC1090 source "$REPO_ROOT/.env" set +a fi log() { log_success "[✓] $1" } error() { log_error "[✗] $1" exit 1 } warn() { log_warn "[!] $1" } info() { log_info "[i] $1" } section() { echo log_info "=== $1 ===" } section "Terraform Backend Storage Setup" # Check Azure authentication if ! az account show &> /dev/null; then error "Not logged in to Azure. Run: az login" fi log "Azure authentication verified" # Load existing .env if present if [ -f "$PROJECT_ROOT/.env" ]; then source "$PROJECT_ROOT/.env" log ".env file loaded" fi # Get subscription and location SUBSCRIPTION_ID=$(az account show --query id -o tsv) LOCATION="${AZURE_LOCATION:-westeurope}" RESOURCE_GROUP="${ARM_RESOURCE_GROUP_NAME:-tfstate-rg}" info "Subscription: $SUBSCRIPTION_ID" info "Location: $LOCATION" info "Resource Group: $RESOURCE_GROUP" # Create resource group if it doesn't exist section "Resource Group" if az group show --name "$RESOURCE_GROUP" &> /dev/null; then log "Resource group exists: $RESOURCE_GROUP" else info "Creating resource group: $RESOURCE_GROUP" az group create \ --name "$RESOURCE_GROUP" \ --location "$LOCATION" \ --output none log "Resource group created" fi # Generate storage account name (must be globally unique, 3-24 chars, lowercase alphanumeric) STORAGE_ACCOUNT_NAME="${ARM_STORAGE_ACCOUNT_NAME:-}" if [ -z "$STORAGE_ACCOUNT_NAME" ] || [[ "$STORAGE_ACCOUNT_NAME" == *""* ]]; then # Generate unique name: tfstate + 8 random chars RANDOM_SUFFIX=$(openssl rand -hex 4) STORAGE_ACCOUNT_NAME="tfstate${RANDOM_SUFFIX}" info "Generated storage account name: $STORAGE_ACCOUNT_NAME" else info "Using existing storage account name: $STORAGE_ACCOUNT_NAME" fi # Check if storage account exists section "Storage Account" if az storage account show --name "$STORAGE_ACCOUNT_NAME" --resource-group "$RESOURCE_GROUP" &> /dev/null; then log "Storage account exists: $STORAGE_ACCOUNT_NAME" else info "Creating storage account: $STORAGE_ACCOUNT_NAME" az storage account create \ --name "$STORAGE_ACCOUNT_NAME" \ --resource-group "$RESOURCE_GROUP" \ --location "$LOCATION" \ --sku Standard_LRS \ --kind StorageV2 \ --allow-blob-public-access false \ --min-tls-version TLS1_2 \ --output none if [ $? -eq 0 ]; then log "Storage account created" else error "Failed to create storage account. Name might not be unique. Try again." fi fi # Get storage account key section "Storage Account Key" ACCESS_KEY=$(az storage account keys list \ --resource-group "$RESOURCE_GROUP" \ --account-name "$STORAGE_ACCOUNT_NAME" \ --query "[0].value" -o tsv) if [ -z "$ACCESS_KEY" ]; then error "Failed to retrieve storage account key" fi log "Storage account key retrieved" # Create container CONTAINER_NAME="${ARM_CONTAINER_NAME:-tfstate}" section "Storage Container" if az storage container show \ --name "$CONTAINER_NAME" \ --account-name "$STORAGE_ACCOUNT_NAME" \ --account-key "$ACCESS_KEY" \ &> /dev/null; then log "Container exists: $CONTAINER_NAME" else info "Creating container: $CONTAINER_NAME" az storage container create \ --name "$CONTAINER_NAME" \ --account-name "$STORAGE_ACCOUNT_NAME" \ --account-key "$ACCESS_KEY" \ --public-access off \ --output none log "Container created" fi # Update .env file section "Updating .env file" ENV_FILE="$PROJECT_ROOT/.env" # Backup existing .env if [ -f "$ENV_FILE" ]; then cp "$ENV_FILE" "${ENV_FILE}.backup.$(date +%Y%m%d_%H%M%S)" log "Backed up existing .env file" fi # Update or add backend variables if grep -q "^ARM_STORAGE_ACCOUNT_NAME=" "$ENV_FILE" 2>/dev/null; then sed -i "s|^ARM_STORAGE_ACCOUNT_NAME=.*|ARM_STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME|" "$ENV_FILE" else echo "ARM_STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME" >> "$ENV_FILE" fi if grep -q "^ARM_CONTAINER_NAME=" "$ENV_FILE" 2>/dev/null; then sed -i "s|^ARM_CONTAINER_NAME=.*|ARM_CONTAINER_NAME=$CONTAINER_NAME|" "$ENV_FILE" else echo "ARM_CONTAINER_NAME=$CONTAINER_NAME" >> "$ENV_FILE" fi if grep -q "^ARM_RESOURCE_GROUP_NAME=" "$ENV_FILE" 2>/dev/null; then sed -i "s|^ARM_RESOURCE_GROUP_NAME=.*|ARM_RESOURCE_GROUP_NAME=$RESOURCE_GROUP|" "$ENV_FILE" else echo "ARM_RESOURCE_GROUP_NAME=$RESOURCE_GROUP" >> "$ENV_FILE" fi if grep -q "^ARM_ACCESS_KEY=" "$ENV_FILE" 2>/dev/null; then sed -i "s|^ARM_ACCESS_KEY=.*|ARM_ACCESS_KEY=$ACCESS_KEY|" "$ENV_FILE" else echo "ARM_ACCESS_KEY=$ACCESS_KEY" >> "$ENV_FILE" fi log ".env file updated with backend configuration" section "Summary" info "Storage Account: $STORAGE_ACCOUNT_NAME" info "Container: $CONTAINER_NAME" info "Resource Group: $RESOURCE_GROUP" info "Location: $LOCATION" log "Backend configuration complete!" info "Next step: Run terraform init" info " cd terraform" info " terraform init"