diff --git a/.env b/.env index a2f232d4..9393d903 100644 --- a/.env +++ b/.env @@ -1,14 +1,15 @@ -versionAzureCli=2.29.0 +versionAzureCli=2.30.0 versionKubectl=1.22.1 versionGit=1:2.30.2-1ubuntu1 -versionTflint=0.33.0 -versionTflintazrs=0.13.2 -versionVault=1.8.4 +versionTflint=0.33.1 +versionTflintazrs=0.14.0 +versionVault=1.9.0 versionJq=1.6-2.1ubuntu1 versionDockerCompose=1.29.2 -versionTfsec=0.58.14 +versionTfsec=0.61.3 versionTerraformDocs=0.16.0 versionAnsible=2.10.7-1 -versionPacker=1.7.6 -versionCheckov=2.0.489 +versionPacker=1.7.8 +versionCheckov=2.0.604 versionMssqlTools=17.7.1.1 +extensionsAzureCli=resource-graph diff --git a/.env.terraform b/.env.terraform index 0469ecd4..be319cd0 100644 --- a/.env.terraform +++ b/.env.terraform @@ -1,5 +1,5 @@ 0.13.7 0.14.11 0.15.5 -1.0.7 -1.0.9 +1.0.11 +1.1.0-rc1 diff --git a/.vscode/settings.json b/.vscode/settings.json index ef6628e4..4823cbc4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "files.eol": "\n", - "terminal.integrated.defaultProfile.linux": "caf (rover on docker)", + "terminal.integrated.defaultProfile.linux": "caf (zsh)", "editor.tabSize": 2, "terminal.integrated.scrollback": 32000, "terminal.integrated.profiles.linux": { @@ -8,6 +8,10 @@ "path": "docker-compose", "args": ["-f", "rover_on_ssh_host.yml", "run", "-e", "ROVER_RUNNER=true", "--rm", "-w", "/tf/caf" ,"rover", "/usr/bin/zsh"], "overrideName": true + }, + "caf (zsh)": { + "path": "zsh", + "overrideName": true } } } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b9ffc165..5092c6b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ########################################################### # base tools and dependencies ########################################################### -FROM ubuntu:21.04 as base +FROM --platform=linux/amd64 ubuntu:21.04 as base SHELL ["/bin/bash", "-c"] @@ -11,7 +11,6 @@ ARG versionAzureCli \ versionVault \ versionKubectl \ versionTflint \ - versionGit \ versionJq \ versionDockerCompose \ versionTfsec \ @@ -21,6 +20,7 @@ ARG versionAzureCli \ versionMssqlTools \ versionTerraformDocs \ versionTflintazrs \ + extensionsAzureCli \ SSH_PASSWD ARG USERNAME=vscode @@ -34,7 +34,6 @@ ENV SSH_PASSWD=${SSH_PASSWD} \ versionKubectl=${versionKubectl} \ versionTflint=${versionTflint} \ versionJq=${versionJq} \ - versionGit=${versionGit} \ versionDockerCompose=${versionDockerCompose} \ versionTfsec=${versionTfsec} \ versionAnsible=${versionAnsible} \ @@ -43,6 +42,7 @@ ENV SSH_PASSWD=${SSH_PASSWD} \ versionMssqlTools=${versionMssqlTools} \ versionTerraformDocs=${versionTerraformDocs} \ versionTflintazrs=${versionTflintazrs} \ + extensionsAzureCli=${extensionsAzureCli} \ PATH="${PATH}:/opt/mssql-tools/bin:/home/vscode/.local/lib/shellspec/bin:/home/vscode/go/bin" \ TF_DATA_DIR="/home/${USERNAME}/.terraform.cache" \ TF_PLUGIN_CACHE_DIR="/home/${USERNAME}/.terraform.cache/plugin-cache" \ @@ -63,6 +63,7 @@ RUN apt-get update && \ curl \ ca-certificates \ apt-transport-https \ + git \ gettext \ software-properties-common \ unzip \ @@ -97,17 +98,17 @@ RUN curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > # Add Microsoft repository # curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/msprod.list && \ - curl https://packages.microsoft.com/config/ubuntu/21.04/prod.list >> /etc/apt/sources.list.d/msprod.list && \ + #curl https://packages.microsoft.com/config/ubuntu/21.04/prod.list >> /etc/apt/sources.list.d/msprod.list && \ # # Add Docker repository # curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor > /etc/apt/trusted.gpg.d/docker-archive-keyring.gpg && \ - echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu hirsute stable" > /etc/apt/sources.list.d/docker.list && \ + echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" > /etc/apt/sources.list.d/docker.list && \ # # Add Terraform repository # curl -fsSL https://apt.releases.hashicorp.com/gpg | gpg --dearmor > /etc/apt/trusted.gpg.d/hashicorp-archive-keyring.gpg && \ - echo "deb [arch=amd64] https://apt.releases.hashicorp.com hirsute main" > /etc/apt/sources.list.d/hashicorp.list && \ + echo "deb [arch=amd64] https://apt.releases.hashicorp.com focal main" > /etc/apt/sources.list.d/hashicorp.list && \ # # Kubernetes repo # @@ -150,7 +151,7 @@ RUN echo "Installing docker-compose ${versionDockerCompose}..." && \ tar -zxf /tmp/terraform-docs.tar.gz --directory=/usr/bin && \ chmod +x /usr/bin/terraform-docs && \ # - # Install baash completions for git + # Install bash completions for git # echo "Installing bash completions for git" && \ mkdir -p /etc/bash_completion.d/ && \ @@ -179,6 +180,7 @@ RUN apt-get install -y python3-pip && \ # Install Azure-cli # pip3 install azure-cli==${versionAzureCli} && \ + az config set extension.use_dynamic_install=yes_without_prompt && \ # # Install checkov # @@ -187,11 +189,19 @@ RUN apt-get install -y python3-pip && \ # # Install pywinrm # - pip3 install pywinrm && \ + pip3 install pywinrm # # Clean-up # - pip3 cache purge + #pip3 cache purge + + # + # ################# Install Azure CLI extensions ################### + # + # Provide a comma separated list of Azure CLI extensions to add. + # +RUN ext=(${extensionsAzureCli//,/ }); for i in "${ext[@]}"; do az extension add --name "$i"; done + # # ################ Install apt packages ################## # @@ -212,25 +222,13 @@ RUN echo "Installing Vault ${versionVault}..." && \ rm /tmp/vault.zip RUN apt-get install -y --no-install-recommends \ - docker-ce-cli - -RUN apt-get install -y --no-install-recommends \ - golang - -RUN apt-get install -y --no-install-recommends \ - git=${versionGit} - -RUN apt-get install -y --no-install-recommends \ - ansible=${versionAnsible} - -RUN apt-get install -y --no-install-recommends \ - openssh-server - -RUN apt-get install -y --no-install-recommends \ - fonts-powerline - -RUN apt-get install -y --no-install-recommends \ - jq=${versionJq} + docker-ce-cli \ + golang \ + git \ + ansible \ + openssh-server \ + fonts-powerline \ + jq RUN apt-get install -y --no-install-recommends \ powershell && \ @@ -240,8 +238,8 @@ RUN apt-get install -y --no-install-recommends \ RUN echo "Installing shellspec..." && \ curl -fsSL https://git.io/shellspec | sh -s -- --yes -RUN echo "Installing caflint..." && \ - go install github.com/aztfmod/caflint@latest +# RUN echo "Installing caflint..." && \ +# go install github.com/aztfmod/caflint@latest RUN echo "Installing Tflint Ruleset ${versionTflintazrs} for Azure..." && \ curl -sSL -o /tmp/tflint-ruleset-azurerm.zip https://github.com/terraform-linters/tflint-ruleset-azurerm/releases/download/v${versionTflintazrs}/tflint-ruleset-azurerm_linux_amd64.zip 2>&1 && \ @@ -303,7 +301,7 @@ RUN mkdir -p /tf/caf \ -COPY ./scripts/rover.sh ./scripts/tfstate_azurerm.sh ./scripts/functions.sh ./scripts/parse_command.sh ./scripts/banner.sh ./scripts/clone.sh ./scripts/walkthrough.sh ./scripts/sshd.sh ./scripts/backend.hcl.tf ./scripts/ci.sh ./scripts/cd.sh ./scripts/task.sh ./scripts/symphony_yaml.sh ./scripts/test_runner.sh ./ +COPY ./scripts/rover.sh ./scripts/tfstate.sh ./scripts/functions.sh ./scripts/parse_command.sh ./scripts/banner.sh ./scripts/clone.sh ./scripts/walkthrough.sh ./scripts/sshd.sh ./scripts/backend.hcl.tf ./scripts/backend.azurerm.tf ./scripts/ci.sh ./scripts/cd.sh ./scripts/task.sh ./scripts/symphony_yaml.sh ./scripts/test_runner.sh ./ COPY ./scripts/ci_tasks/* ./ci_tasks/ COPY ./scripts/lib/* ./lib/ # diff --git a/rover_on_ssh_host.yml b/rover_on_ssh_host.yml index bf116e63..163dc0fb 100644 --- a/rover_on_ssh_host.yml +++ b/rover_on_ssh_host.yml @@ -11,7 +11,7 @@ version: '3.7' services: rover: - image: aztfmod/rover:1.0.4-2108.1802 + image: aztfmod/rover:1.0.9-2111.0103 user: vscode diff --git a/scripts/backend.azurerm.tf b/scripts/backend.azurerm.tf new file mode 100644 index 00000000..5d026b23 --- /dev/null +++ b/scripts/backend.azurerm.tf @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/scripts/functions.sh b/scripts/functions.sh index 65599069..d01544f9 100644 --- a/scripts/functions.sh +++ b/scripts/functions.sh @@ -341,8 +341,7 @@ function login_as_launchpad { echo "" echo "Getting launchpad coordinates from subscription: ${TF_VAR_tfstate_subscription_id}" - export keyvault=$(az keyvault list --subscription ${TF_VAR_tfstate_subscription_id} --query "[?tags.tfstate=='${TF_VAR_level}' && tags.environment=='${TF_VAR_environment}']" -o json | jq -r .[0].name) - + keyvault=$(az graph query -q "Resources | where type == 'microsoft.keyvault/vaults' and ((tags.environment == '${TF_VAR_environment}' and tags.tfstate == '${TF_VAR_level}') or (tags.caf_environment == '${TF_VAR_environment}' and tags.caf_tfstate == '${TF_VAR_level}')) | project name" --query "data[0].name" -o tsv) echo " - keyvault_name: ${keyvault}" stg=$(az storage account show --ids ${id} -o json) @@ -365,22 +364,6 @@ function login_as_launchpad { export TF_VAR_tfstate_key=${TF_VAR_tf_name} - if [ ${caf_command} == "landingzone" ]; then - - if [ ${impersonate} = true ]; then - export SECRET_PREFIX=$(az keyvault secret show --subscription ${TF_VAR_tfstate_subscription_id} -n launchpad-secret-prefix --vault-name ${keyvault} -o json | jq -r .value) && echo " - Name: ${SECRET_PREFIX}" - echo "Set terraform provider context to Azure AD application launchpad " - export ARM_CLIENT_ID=$(az keyvault secret show --subscription ${TF_VAR_tfstate_subscription_id} -n ${SECRET_PREFIX}-client-id --vault-name ${keyvault} -o json | jq -r .value) && echo " - client id: ${ARM_CLIENT_ID}" - export ARM_CLIENT_SECRET=$(az keyvault secret show --subscription ${TF_VAR_tfstate_subscription_id} -n ${SECRET_PREFIX}-client-secret --vault-name ${keyvault} -o json | jq -r .value) - export ARM_TENANT_ID=$(az keyvault secret show --subscription ${TF_VAR_tfstate_subscription_id} -n ${SECRET_PREFIX}-tenant-id --vault-name ${keyvault} -o json | jq -r .value) && echo " - tenant id: ${ARM_TENANT_ID}" - export TF_VAR_logged_aad_app_objectId=$(az ad sp show --id ${ARM_CLIENT_ID} --query objectId -o tsv) && echo " - Set logged in aad app object id from keyvault: ${TF_VAR_logged_aad_app_objectId}" - - echo "Impersonating with the azure session with the launchpad service principal to deploy the landingzone" - az login --service-principal -u ${ARM_CLIENT_ID} -p ${ARM_CLIENT_SECRET} --tenant ${ARM_TENANT_ID} - fi - - fi - } function deploy_landingzone { diff --git a/scripts/rover.sh b/scripts/rover.sh index f4d41560..c5b54837 100755 --- a/scripts/rover.sh +++ b/scripts/rover.sh @@ -7,7 +7,7 @@ source /tf/rover/lib/logger.sh source /tf/rover/clone.sh source /tf/rover/walkthrough.sh -source /tf/rover/tfstate_azurerm.sh +source /tf/rover/tfstate.sh source /tf/rover/functions.sh source /tf/rover/parse_command.sh source /tf/rover/banner.sh @@ -30,13 +30,14 @@ export TF_CACHE_FOLDER=${TF_DATA_DIR:=$(echo ~)} export ARM_SNAPSHOT=${ARM_SNAPSHOT:="true"} export ARM_USE_AZUREAD=${ARM_USE_AZUREAD:="true"} export ARM_STORAGE_USE_AZUREAD=${ARM_STORAGE_USE_AZUREAD:="true"} -export impersonate=${impersonate:=false} export skip_permission_check=${skip_permission_check:=false} export symphony_run_all_tasks=true export debug_mode=${debug_mode:="false"} export devops=${devops:="false"} export log_folder_path=${log_folderpath:=~/.terraform.logs} export TF_IN_AUTOMATION="true" #Overriden in logger if log-severity is passed in. +export TF_backend_type=${TF_backend_type:="azurerm"} +export TFC_hostname=${TFC_hostname:="app.terraform.io"} unset PARAMS @@ -161,7 +162,17 @@ while (( "$#" )); do ;; -tfc|--tfc) shift 1 - export caf_command="tfc" + export TF_backend_type="tfc" + ;; + -tfc_organization|--tfc_organization) + export TFC_organization="${2}" + export TF_backend_type="tfc" + shift 2 + ;; + -tfc_hostname|--tfc_hostname) + export TFC_hostname="${2}" + export TF_backend_type="tfc" + shift 2 ;; -t|--tenant) export tenant=$(parameter_value --tenant ${2}) @@ -209,16 +220,13 @@ while (( "$#" )); do export TF_VAR_level=$(parameter_value '-level' ${2}) shift 2 ;; - --impersonate) - export impersonate=true - shift 1 - ;; -skip-permission-check) export skip_permission_check=true shift 1 ;; -var-folder) expand_tfvars_folder $(parameter_value '-var-folder' ${2}) + export TF_var_folder="${2}" var_folder_set=true shift 2 ;; @@ -290,6 +298,7 @@ if [ "${caf_command}" != "walkthrough" ]; then echo "level (current) : '$(echo ${TF_VAR_level})'" echo "environment : '$(echo ${TF_VAR_environment})'" echo "workspace : '$(echo ${TF_VAR_workspace})'" + echo "terraform backend type : '$(echo ${TF_backend_type})'" echo "tfstate : '$(echo ${TF_VAR_tf_name})'" echo "tfstate subscription id : '$(echo ${TF_VAR_tfstate_subscription_id})'" echo "target subscription : '$(echo ${target_subscription_name})'" @@ -314,3 +323,5 @@ export terraform_version=$(terraform --version | head -1 | cut -d ' ' -f 2) process_actions clean_up_variables + +exit ${RETURN_CODE} \ No newline at end of file diff --git a/scripts/tfstate_azurerm.sh b/scripts/tfstate.sh similarity index 77% rename from scripts/tfstate_azurerm.sh rename to scripts/tfstate.sh index 078f065a..8c48f3d6 100644 --- a/scripts/tfstate_azurerm.sh +++ b/scripts/tfstate.sh @@ -1,3 +1,67 @@ +function tfstate_cleanup { + + sudo rm -f -- ${landingzone_name}/backend.*.tf || true + sudo rm -rf -- "${landingzone_name}/backend.hcl" || true + rm -rf -- "${landingzone_name}/caf.auto.tfvars" || true + rm -rf -- "${TF_DATA_DIR}/terraform.tfstate" || true + +} + +function tfstate_configure { + + case "${TF_backend_type}" in + azurerm) + echo "@calling tfstate_configure -- azurerm" + cp -f /tf/rover/backend.azurerm.tf ${landingzone_name}/backend.azurerm.tf + ;; + tfc) + echo "@calling tfstate_configure -- tfc" + sudo cp -f /tf/rover/backend.hcl.tf ${landingzone_name}/backend.hcl.tf + + sudo rm -rf -- "${landingzone_name}/caf.auto.tfvars" || true + for filename in ${TF_var_folder}/*.tfvars; do + command="cat ${filename} >> ${landingzone_name}/caf.auto.tfvars && printf '\n' >> ${landingzone_name}/caf.auto.tfvars" + echo ${command} + sudo bash -c "${command}" + done + + terraform fmt ${landingzone_name}/caf.auto.tfvars + + cat << EOF > ${landingzone_name}/backend.hcl +workspaces { name = "${TF_VAR_workspace}" } +hostname = "${TFC_hostname}" +organization = "${TFC_organization}" +EOF + + + ;; + *) + tfstate_cleanup + error ${LINENO} "Error backend type not yet supported: ${TF_backend_type}" 3001 + ;; + esac + +} + +function terraform_init_remote { + echo "@calling terraform_init_remote" + + case "${TF_backend_type}" in + azurerm) + echo "@calling terraform_init_remote -- azurerm" + terraform_init_remote_azurerm + ;; + tfc) + echo "@calling terraform_init_remote -- tfc" + terraform_init_remote_tfc + ;; + *) + error ${LINENO} "Error backend type not yet supported: ${TF_backend_type}" 3002 + ;; + esac + +} + function initialize_state { echo "@calling initialize_state" @@ -11,9 +75,7 @@ function initialize_state { echo "Installing launchpad from ${landingzone_name}" cd ${landingzone_name} - sudo rm -f -- ${landingzone_name}/backend.azurerm.tf - - rm -f -- "${TF_DATA_DIR}/terraform.tfstate" + tfstate_cleanup export TF_VAR_tf_name=${TF_VAR_tf_name:="$(basename $(pwd)).tfstate"} export TF_VAR_tf_plan=${TF_VAR_tf_plan:="$(basename $(pwd)).tfplan"} @@ -26,13 +88,13 @@ function initialize_state { echo "Terraform version 0.15 or greater" terraform -chdir=${landingzone_name} \ init \ - -upgrade=true + -upgrade=true | grep -P '^- (?=Downloading|Using|Finding|Installing)|^[^-]' ;; *) terraform init \ -get-plugins=true \ -upgrade=true \ - ${landingzone_name} + ${landingzone_name} | grep -P '^- (?=Downloading|Using|Finding|Installing)|^[^-]' ;; esac @@ -62,7 +124,7 @@ function initialize_state { ;; esac - rm -rf backend.azurerm.tf || true + tfstate_cleanup cd "${current_path}" @@ -135,15 +197,13 @@ function deploy_from_remote_state { echo 'Connecting to the launchpad' cd ${landingzone_name} - if [ -f "backend.azurerm" ]; then - sudo cp backend.azurerm backend.azurerm.tf - fi + tfstate_configure login_as_launchpad deploy_landingzone - rm -rf backend.azurerm.tf + tfstate_cleanup cd "${current_path}" } @@ -163,7 +223,7 @@ function destroy_from_remote_state { # Cleanup previous deployments rm -rf "${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}" - rm -rf "${TF_DATA_DIR}/tfstates/terraform.tfstate" + tfstate_cleanup mkdir -p "${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}" @@ -203,11 +263,12 @@ function destroy_from_remote_state { cd "${current_path}" } -function terraform_init_remote { +function terraform_init_remote_azurerm { case ${terraform_version} in *"15"* | *"1."*) - echo "Terraform version 0.15 or greater" + echo "Terraform version ${terraform_version}" + echo "Running Terraform init..." terraform -chdir=${landingzone_name} \ init \ -reconfigure \ @@ -217,7 +278,7 @@ function terraform_init_remote { -backend-config resource_group_name=${TF_VAR_tfstate_resource_group_name} \ -backend-config container_name=${TF_VAR_workspace} \ -backend-config key=${TF_VAR_tf_name} \ - -backend-config subscription_id=${TF_VAR_tfstate_subscription_id} + -backend-config subscription_id=${TF_VAR_tfstate_subscription_id} | grep -P '^- (?=Downloading|Using|Finding|Installing)|^[^-]' ;; *) terraform init \ @@ -230,9 +291,31 @@ function terraform_init_remote { -backend-config container_name=${TF_VAR_workspace} \ -backend-config key=${TF_VAR_tf_name} \ -backend-config subscription_id=${TF_VAR_tfstate_subscription_id} \ - ${landingzone_name} + ${landingzone_name} | grep -P '^- (?=Downloading|Using|Finding|Installing)|^[^-]' ;; esac + + RETURN_CODE=$? + if [ $RETURN_CODE != 0 ]; then + error ${LINENO} "Error running terraform init (azurerm) " $RETURN_CODE + fi +} + +function terraform_init_remote_tfc { + + echo "@calling terraform_init_remote_tfc" + + terraform -chdir=${landingzone_name} \ + init \ + -backend=true \ + -upgrade \ + -reconfigure \ + -backend-config=${landingzone_name}/backend.hcl + + RETURN_CODE=$? + if [ $RETURN_CODE != 0 ]; then + error ${LINENO} "Error running terraform init (tfc) " $RETURN_CODE + fi } function plan { @@ -253,30 +336,51 @@ function plan { if [ "$tf_no_color" == "true" ]; then colorFlag="-no-color" fi - case ${terraform_version} in - *"15"* | *"1."*) - echo "Terraform version 0.15 or greater" + + echo "Running Terraforn plan..." + + case "${TF_backend_type}" in + azurerm) + echo "@calling terraform_plan -- azurerm" + case ${terraform_version} in + *"15"* | *"1."*) + terraform -chdir=${landingzone_name} \ + plan ${plan_command} \ + -refresh=true \ + -detailed-exitcode \ + -lock=false \ + -state="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_name}" \ + -out="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" | tee ${tf_output_file} + ;; + *) + terraform plan ${plan_command} \ + -refresh=true \ + -state="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_name}" \ + -out="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" $PWD | tee ${tf_output_file} + ;; + esac + ;; + tfc) + echo "@calling terraform_plan -- tfc" terraform -chdir=${landingzone_name} \ - plan ${plan_command} \ + plan \ -refresh=true \ -detailed-exitcode \ -lock=false \ - -state="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_name}" \ - -out="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" | tee ${tf_output_file} + -state="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_name}" | tee ${tf_output_file} ;; *) - terraform plan ${plan_command} \ - -refresh=true \ - -state="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_name}" \ - -out="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" $PWD | tee ${tf_output_file} + error ${LINENO} "Error backend type not yet supported: ${TF_backend_type}" 3003 ;; esac RETURN_CODE=${PIPESTATUS[0]} && echo "Terraform plan return code: ${RETURN_CODE}" if [ ! -z ${tf_plan_file} ]; then - echo "Copying plan file to ${tf_plan_file}" - cp "${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" "${tf_plan_file}" + if [ -f "${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" ]; then + echo "Copying plan file to ${tf_plan_file}" + cp "${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" "${tf_plan_file}" + fi fi case "${RETURN_CODE}" in @@ -300,11 +404,11 @@ function apply { echo 'running terraform apply' rm -f $STDERR_FILE - if [ -z ${tf_plan_file} ]; then + if [[ -z ${tf_plan_file} ]] && [ "${TF_backend_type}" == "azurerm" ]; then echo "Plan not provided with -p or --plan so calling terraform plan" plan - tf_plan_file="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" + local tf_plan_file="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" fi echo "Running Terraform apply with plan ${tf_plan_file}" @@ -383,23 +487,20 @@ function destroy { echo " -TF_VAR_tf_name: ${TF_VAR_tf_name}" echo "terraform destroy parameters: -chdir=${landingzone_name} apply -refresh=false $(parse_command_destroy_with_plan ${tf_command}) ${tf_approve} ${tf_plan_file}" - rm -f "${TF_DATA_DIR}/terraform.tfstate" - sudo rm -f ${landingzone_name}/backend.azurerm.tf + tfstate_cleanup if [ "$1" == "remote" ]; then - if [ -e backend.azurerm ]; then - sudo cp -f backend.azurerm backend.azurerm.tf - fi + tfstate_configure echo 'running terraform destroy remote' - terraform_init_remote + terraform_init_remote_azurerm if [ -z ${tf_plan_file} ]; then echo "Plan not provided with -p or --plan so calling terraform plan" plan "-destroy" - tf_plan_file="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" + local tf_plan_file="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" fi RETURN_CODE=$? && echo "Line ${LINENO} - Terraform init return code ${RETURN_CODE}" @@ -444,14 +545,14 @@ function destroy { terraform -chdir=${landingzone_name} \ init \ -reconfigure=true \ - -upgrade=true + -upgrade=true | grep -P '^- (?=Downloading|Using|Finding|Installing)|^[^-]' ;; *) terraform init \ -reconfigure=true \ -get-plugins=true \ -upgrade=true \ - ${landingzone_name} + ${landingzone_name} | grep -P '^- (?=Downloading|Using|Finding|Installing)|^[^-]' ;; esac @@ -461,7 +562,7 @@ function destroy { echo "Plan not provided with -p or --plan so calling terraform plan" plan "-destroy" - tf_plan_file="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" + local tf_plan_file="${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_plan}" fi echo "using tfstate from ${TF_DATA_DIR}/tfstates/${TF_VAR_level}/${TF_VAR_workspace}/${TF_VAR_tf_name}"