diff --git a/deploy/scripts/advanced_state_management.sh b/deploy/scripts/advanced_state_management.sh index b924194474..e1e078ddf1 100755 --- a/deploy/scripts/advanced_state_management.sh +++ b/deploy/scripts/advanced_state_management.sh @@ -13,6 +13,10 @@ script_directory="$(dirname "${full_script_path}")" #call stack has full scriptname when using source source "${script_directory}/deploy_utils.sh" +#helper files +source "${script_directory}/helpers/script_helpers.sh" + + function showhelp { echo "" echo "##################################################################################################################" @@ -125,7 +129,7 @@ if [ -z "$parameterfile" ]; then exit 2 #No such file or directory fi -if [ ! -n "${type}" ] +if [ -z "${type}" ] then printf -v val %-40.40s "$type" echo "#########################################################################################" @@ -143,45 +147,38 @@ then exit 64 #script usage wrong fi +# Check that the exports ARM_SUBSCRIPTION_ID and DEPLOYMENT_REPO_PATH are defined +validate_exports +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code +fi -# Checking for valid az session -az account show > stdout.az 2>&1 -temp=$(grep "az login" stdout.az) -if [ -n "${temp}" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Please login using az login $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - if [ -f stdout.az ] - then - rm stdout.az - fi - exit 67 #addressee unknown -else - if [ -f stdout.az ] - then - rm stdout.az - fi - +# Check that Terraform and Azure CLI is installed +validate_dependencies +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi -account_set=0 +# Check that parameter files have environment and location defined +validate_key_parameters "$parameterfile_name" +if [ 0 != $return_code ]; then + exit $return_code +fi -cloudIDUsed=$(az account show | grep "cloudShellID") -if [ ! -z "${cloudIDUsed}" ]; -then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Please login using your credentials or service principal credentials! $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 67 #addressee unknown +if valid_region_name ${region} ; then + # Convert the region to the correct code + get_region_code ${region} +else + echo "Invalid region: $region" + exit 2 fi +account_set=0 + +automation_config_directory=~/.sap_deployment_automation/ +generic_config_information="${automation_config_directory}"config +system_config_information="${automation_config_directory}""${environment}""${region_code}" az_res=$(az resource show --ids "${resourceID}") @@ -199,15 +196,28 @@ if [ 0 != $return_value ] ; then exit $return_value fi -if [ ! -z "${subscription_id}" ] +if [ -n "${subscription_id}" ] then - $(az account set --sub "${subscription_id}") - account_set=1 + az account set --sub "${subscription_id}" +else + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" + + subscription_id=$STATE_SUBSCRIPTION + + if [ -n "${subscription_id}" ] + then + read -p "Subscription ID containing Terraform state storage account:" subscription_id + fi + az account set --sub "${subscription_id}" fi +load_config_vars "${system_config_information}" "tfstate_resource_id" -tfstate_resource_id=$(az resource list --name "${storage_account_name}" --resource-type Microsoft.Storage/storageAccounts | jq --raw-output '.[0].id') -fail_if_null tfstate_resource_id +if [ -z "${tfstate_resource_id}" ] +then + tfstate_resource_id=$(az resource list --name "${storage_account_name}" --resource-type Microsoft.Storage/storageAccounts | jq --raw-output '.[0].id') + fail_if_null tfstate_resource_id +fi resource_group_name=$(echo $tfstate_resource_id | cut -d/ -f5 | tr -d \" | xargs) directory=$(pwd)/.terraform @@ -242,9 +252,7 @@ fi terraform -chdir=${module_dir} state list > resources.lst -shorter_name=$(echo ${moduleID} | cut -d[ -f1) -tf_resource=$(grep ${shorter_name} resources.lst) -echo $tf_resource +tf_resource=$(grep ${moduleID} resources.lst) if [ -n "${tf_resource}" ]; then echo "#########################################################################################" diff --git a/deploy/scripts/configure_deployer.sh b/deploy/scripts/configure_deployer.sh index aacd99a15a..fecd0ab147 100755 --- a/deploy/scripts/configure_deployer.sh +++ b/deploy/scripts/configure_deployer.sh @@ -55,7 +55,7 @@ set -o pipefail # if [ ! -n "${TF_VERSION}" ]; then - TF_VERSION="0.14.8" + TF_VERSION="1.0.11" fi @@ -260,6 +260,7 @@ required_pkgs=( lsb-release gnupg sshpass + dos2unix ) cli_pkgs=( @@ -328,6 +329,8 @@ fi curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash > /dev/null +/usr/bin/az extension add --name storage-blob-preview > /dev/null + # Ensure our package metadata cache is up to date pkg_mgr_refresh diff --git a/deploy/scripts/deploy_utils.sh b/deploy/scripts/deploy_utils.sh index 56fb84eeec..da33de3a67 100755 --- a/deploy/scripts/deploy_utils.sh +++ b/deploy/scripts/deploy_utils.sh @@ -16,37 +16,40 @@ function save_config_var() { function save_config_vars() { local var_file="${1}" var_name - + if [[ ! -f "${var_file}" ]]; then + return + fi + shift # shift params 1 place to remove var_file value from front of list - + for var_name; do # iterate over function params sed -i -e "" -e /${var_name}/d "${var_file}" echo "${var_name}=${!var_name}" >>"${var_file}" - + done } function load_config_vars() { local var_file="${1}" var_name var_value - + shift # shift params 1 place to remove var_file value from front of list - + # We don't assign values to variables if they aren't found in the var_file # so there is nothing to do if the specified var_file doesn't exist if [[ ! -f "${var_file}" ]]; then return fi - + for var_name; do # iterate over function params # NOTE: Should we care if we fail to retrieve a value from the file? var_value="$(grep -m1 "^${var_name}=" "${var_file}" | cut -d'=' -f2 | tr -d '"')" - + # NOTE: this continue means we skip setting an empty value for a variable # whose value is empty in the var_file... [[ -z "${var_value}" ]] && continue # switch to compound command `[[` instead of `[` - + typeset -g "${var_name}" # declare the specified variable as global - + eval "${var_name}='${var_value}'" # set the variable in global context done } @@ -55,7 +58,7 @@ function init() { local automation_config_directory="${1}" local generic_config_information="${2}" local app_config_information="${3}" - + if [ ! -d "${automation_config_directory}" ]; then # No configuration directory exists mkdir "${automation_config_directory}" @@ -69,7 +72,7 @@ function init() { # Store ARM Subscription info in ~/.sap_deployment_automation save_config_var "ARM_SUBSCRIPTION_ID" "${app_config_information}" fi - + else touch "${generic_config_information}" touch "${app_config_information}" @@ -84,47 +87,50 @@ function init() { load_config_vars "${app_config_information}" "ARM_SUBSCRIPTION_ID" fi fi - + } function error_msg { echo "Error!!! ${@}" } + function fail_if_null { local var_name="${1}" - + # return immeditaely if no action required if [ "${!var_name}" != "null" ]; then return fi - + shift 1 - + if (($# > 0)); then error_msg "${@}" else error_msg "Got a null value for '${var_name}'" fi - + exit 1 } function get_and_store_sa_details { local REMOTE_STATE_SA="${1}" local config_file_name="${2}" - + + echo "Trying to find the storage account ${REMOTE_STATE_SA}" + save_config_vars "${config_file_name}" REMOTE_STATE_SA tfstate_resource_id=$(az resource list --name "${REMOTE_STATE_SA}" --resource-type Microsoft.Storage/storageAccounts | jq --raw-output '.[0].id') fail_if_null tfstate_resource_id - STATE_SUBSCRIPTION=$(echo $tfstate_resource_id | cut -d/ -f3 | tr -d \" | xargs) - REMOTE_STATE_RG=$(echo $tfstate_resource_id | cut -d/ -f5 | tr -d \" | xargs) - + export STATE_SUBSCRIPTION=$(echo $tfstate_resource_id | cut -d/ -f3 | tr -d \" | xargs) + export REMOTE_STATE_RG=$(echo $tfstate_resource_id | cut -d/ -f5 | tr -d \" | xargs) + save_config_vars "${config_file_name}" \ - REMOTE_STATE_RG \ - tfstate_resource_id \ - STATE_SUBSCRIPTION - + REMOTE_STATE_RG \ + tfstate_resource_id \ + STATE_SUBSCRIPTION + echo "Found the storage account ${REMOTE_STATE_SA}" } # /*---------------------------------------------------------------------------8 @@ -161,8 +167,9 @@ function checkforEnvVar() { fi } -# Check if we are running in CloudShell, we have the following three environment -# variables: POWERSHELL_DISTRIBUTION_CHANNEL, AZURE_HTTP_USER_AGENT, and + +# Check if we are running in CloudShell, we have the following three environment +# variables: POWERSHELL_DISTRIBUTION_CHANNEL, AZURE_HTTP_USER_AGENT, and # AZUREPS_HOST_ENVIRONMENT. We will use the first one to determine if we are # running in CloudShell. # Default values for these variables are: @@ -185,34 +192,34 @@ function set_azure_cloud_environment() { #Description # Find the cloud environment where we are executing. # This is included for future use. - + echo -e "\t\t[set_azure_cloud_environment]: Identifying the executing cloud environment" - + # set the azure cloud environment variables local azure_cloud_environment='' - + unset AZURE_ENVIRONMENT - + # check the azure environment in which we are running AZURE_ENVIRONMENT=$(az cloud show --query name --output tsv) - + if [ -n "${AZURE_ENVIRONMENT}" ]; then - + case $AZURE_ENVIRONMENT in - AzureCloud) - azure_cloud_environment='public' + AzureCloud) + azure_cloud_environment='public' ;; - AzureUSGovernment) - azure_cloud_environment='usgov' + AzureUSGovernment) + azure_cloud_environment='usgov' ;; - AzureChinaCloud) - azure_cloud_environment='china' + AzureChinaCloud) + azure_cloud_environment='china' ;; - AzureGermanCloud) - azure_cloud_environment='german' + AzureGermanCloud) + azure_cloud_environment='german' ;; esac - + export AZURE_ENVIRONMENT=${azure_cloud_environment} echo -e "\t\t[set_azure_cloud_environment]: Azure cloud environment: ${azure_cloud_environment}" else @@ -224,11 +231,11 @@ function is_running_in_azureCloudShell() { #Description # Check if we are running in Azure Cloud Shell azureCloudShellIsSetup=1 # default value is false - + echo -e "\t\t[is_running_in_azureCloudShell]: Identifying if we are running in Azure Cloud Shell" cloudShellCheck=$(checkIfCloudShell) - if [[ (($cloudShellCheck == 0)) ]]; then + if [[ (($cloudShellCheck == 0)) ]]; then echo -e "\t\t[is_running_in_azureCloudShell]: Identified we are running in Azure Cloud Shell" echo -e "\t\t[is_running_in_azureCloudShell]: Checking if we have a valid login in Azure Cloud Shell" cloudIDUsed=$(az account show | grep "cloudShellID") @@ -242,7 +249,7 @@ function is_running_in_azureCloudShell() { echo "#########################################################################################" echo "" azureCloudShellIsSetup=67 #addressee unknown - else + else echo -e "\t\t[is_running_in_azureCloudShell]: We have a valid login in Azure Cloud Shell" azureCloudShellIsSetup=0 #we are good to go fi @@ -250,12 +257,12 @@ function is_running_in_azureCloudShell() { echo -e "\t\t[is_running_in_azureCloudShell]: We are not running Azure Cloud Shell" azureCloudShellIsSetup=1 #set return to further logic fi - + return $azureCloudShellIsSetup } function set_executing_user_environment_variables() { - + local az_exec_user_type local az_exec_user_name local az_user_name @@ -263,31 +270,31 @@ function set_executing_user_environment_variables() { local az_subscription_id local az_tenant_id local az_client_id - local az_client_secret + local az_client_secret az_client_secret="$1" echo -e "\t[set_executing_user_environment_variables]: Identifying the executing user and client" - + set_azure_cloud_environment - + az_exec_user_type=$(az account show | jq -r .user.type) az_exec_user_name=$(az account show -o json | jq -r .user.name) az_tenant_id=$(az account show -o json | jq -r .tenantId) - + echo -e "\t\t[set_executing_user_environment_variables]: User type: "${az_exec_user_type}"" - + # if you are executing as user, we do not want to set any exports to run Terraform # else, if you are executing as service principal, we need to export the ARM variables if [ "${az_exec_user_type}" == "user" ]; then # if you are executing as user, we do not want to set any exports for terraform echo -e "\t[set_executing_user_environment_variables]: Identified login type as 'user'" - + unset_executing_user_environment_variables - + az_user_obj_id=$(az ad signed-in-user show --query objectId -o tsv) az_user_name=$(az ad signed-in-user show --query userPrincipalName -o tsv) - + # this is the user object id but exporeted as client_id to make it easier to use in TF export TF_VAR_arm_client_id=${az_user_obj_id} @@ -298,62 +305,62 @@ function set_executing_user_environment_variables() { #when logged in as a service principal or MSI, username is clientID az_client_id=$(az account show --query user.name -o tsv) az_subscription_id=$(az account show --query id -o tsv) - + echo -e "\t\t[set_executing_user_environment_variables]: client id: "${az_client_id}"" - + #do we need to get details of the service principal? if [ "${az_client_id}" == "null" ]; then echo -e "\t[set_executing_user_environment_variables]: unable to identify the executing user and client" return 65 #/* data format error */ fi - + case "${az_client_id}" in - "systemAssignedIdentity") - echo -e "\t[set_executing_user_environment_variables]: logged in using '${az_exec_user_type}'" - echo -e "\t[set_executing_user_environment_variables]: Nothing to do" + "systemAssignedIdentity") + echo -e "\t[set_executing_user_environment_variables]: logged in using '${az_exec_user_type}'" + echo -e "\t[set_executing_user_environment_variables]: Nothing to do" ;; - "userAssignedIdentity") - echo -e "\t[set_executing_user_environment_variables]: logged in using User Assigned Identity: '${az_exec_user_type}'" - echo -e "\t[set_executing_user_environment_variables]: Nothing to do" + "userAssignedIdentity") + echo -e "\t[set_executing_user_environment_variables]: logged in using User Assigned Identity: '${az_exec_user_type}'" + echo -e "\t[set_executing_user_environment_variables]: Nothing to do" ;; - *) - if is_valid_guid "${az_exec_user_name}"; then - - az_user_obj_id=$(az ad sp show --id "${az_exec_user_name}" --query objectId -o tsv) - az_user_name=$(az ad sp show --id "${az_exec_user_name}" --query displayName -o tsv) - - echo -e "\t[set_executing_user_environment_variables]: Identified login type as 'service principal'" - echo -e "\t[set_executing_user_environment_variables]: Initializing state with SPN named: ${az_user_name}" - - if [ -z "$az_client_secret" ]; then - #do not output the secret to screen - stty -echo - read -ers -p " -> Kindly provide SPN Password: " az_client_secret; echo "********" - stty echo + *) + if is_valid_guid "${az_exec_user_name}"; then + + az_user_obj_id=$(az ad sp show --id "${az_exec_user_name}" --query objectId -o tsv) + az_user_name=$(az ad sp show --id "${az_exec_user_name}" --query displayName -o tsv) + + echo -e "\t[set_executing_user_environment_variables]: Identified login type as 'service principal'" + echo -e "\t[set_executing_user_environment_variables]: Initializing state with SPN named: ${az_user_name}" + + if [ -z "$az_client_secret" ]; then + #do not output the secret to screen + stty -echo + read -ers -p " -> Kindly provide SPN Password: " az_client_secret; echo "********" + stty echo + fi + + #export the environment variables + + ARM_SUBSCRIPTION_ID=${az_subscription_id} + ARM_TENANT_ID=${az_tenant_id} + ARM_CLIENT_ID=${az_exec_user_name} + if [ "none" != "$az_client_secret" ]; then + + ARM_CLIENT_SECRET=${az_client_secret} + fi + + echo -e "\t[set_executing_user_environment_variables]: exporting environment variables" + export ARM_SUBSCRIPTION_ID + export ARM_TENANT_ID + export ARM_CLIENT_ID + export ARM_CLIENT_SECRET + + else + echo -e "\t[set_executing_user_environment_variables]: unable to identify the executing user and client" fi - - #export the environment variables - - ARM_SUBSCRIPTION_ID=${az_subscription_id} - ARM_TENANT_ID=${az_tenant_id} - ARM_CLIENT_ID=${az_exec_user_name} - if [ "none" != "$az_client_secret" ]; then - - ARM_CLIENT_SECRET=${az_client_secret} - fi - - echo -e "\t[set_executing_user_environment_variables]: exporting environment variables" - export ARM_SUBSCRIPTION_ID - export ARM_TENANT_ID - export ARM_CLIENT_ID - export ARM_CLIENT_SECRET - - else - echo -e "\t[set_executing_user_environment_variables]: unable to identify the executing user and client" - fi ;; esac - + fi } @@ -364,47 +371,13 @@ function unset_executing_user_environment_variables() { unset ARM_TENANT_ID unset ARM_CLIENT_ID unset ARM_CLIENT_SECRET - + } # print the script name and function being called function print_script_name_and_function() { echo -e "\t[$(basename "")]: $(basename "$0") $1" } -# -# Input validation routines -# - -# An environment value must be a string that is at most 5 characters -# long, made up of uppercase letters and numbers, and must start with -# an uppercase letter. -function valid_environment() { - [[ "${environment}" =~ ^[[:upper:]][[:upper:][:digit:]]{1,4}$ ]] -} - -# A region name must be a valid Azure lowercase region name, made -# up of lowercase latters optionally followed by numbers. -# NOTE: If we have the list of possible regions in a file somewhere -# we can validate it is one of the entries in that list. -function valid_region_name() { - [[ "${region}" =~ ^[[:lower:]]+[[:digit:]]?$ ]] -} - -# A region code must be a valid , made -# up of 4 uppercase latters -# NOTE: If we have the list of possible regions in a file somewhere -# we can validate it is one of the entries in that list. -function valid_region_code() { - [[ "${region_code}" =~ ^[[:upper:]][[:upper:][:digit:]]{1,3}$ ]] -} - - -#print the function name being executed -#printf maybe instead of echo -#printf "%s\n" "${FUNCNAME[@]}" -#check the AZURE_HTTP_USER_AGENT=cloud-shell/1.0 to identify the cloud shell -#update template to user the following user http://localhost:50342/oauth2/token - function get_region_code() { region_lower=$(echo "${region}" | tr [:upper:] [:lower:] ) case "${region_lower}" in @@ -412,7 +385,6 @@ function get_region_code() { "australiacentral2") export region_code="AUC2" ;; "australiaeast") export region_code="AUEA" ;; "australiasoutheast") export region_code="AUSE" ;; - "australiacentral2") export region_code="AUC2" ;; "brazilsouth") export region_code="BRSO" ;; "brazilsoutheast") export region_code="BRSE" ;; "brazilus") export region_code="BRUS" ;; @@ -453,6 +425,63 @@ function get_region_code() { "westus") export region_code="WEUS" ;; "westus2") export region_code="WUS2" ;; *) export region_code="UNKN" ;; - -esac -} \ No newline at end of file + + esac +} + +# +# Input validation routines +# + +# An environment value must be a string that is at most 5 characters +# long, made up of uppercase letters and numbers, and must start with +# an uppercase letter. +function valid_environment() { + if [[ "${environment}" =~ "^[A-Za-z0-9]{1,10}$" ]]; then + return 1 + else + return 0 + fi +} + +# A region name must be a valid Azure lowercase region name, made +# up of lowercase latters optionally followed by numbers. +# NOTE: If we have the list of possible regions in a file somewhere +# we can validate it is one of the entries in that list. +function valid_region_name() { + if [[ "${region}" =~ "^[A-Za-z0-9]$" ]]; then + return 1 + else + return 0 + fi +} + +# A region code must be a valid , made +# up of 4 uppercase latters +# NOTE: If we have the list of possible regions in a file somewhere +# we can validate it is one of the entries in that list. +function valid_region_code() { + if [[ "${region_code}" =~ "^[A-Z0-9]{1,4}$" ]]; then + return 1 + else + return 0 + fi +} + +# An Keyvault name value must be made up of letters and numbers +# an uppercase letter. +function valid_kv_name() { + if [[ "${keyvault}" =~ "^[A-Za-z0-9]{1,10}$" ]]; then + return 1 + else + return 0 + fi +} + + +#print the function name being executed +#printf maybe instead of echo +#printf "%s\n" "${FUNCNAME[@]}" +#check the AZURE_HTTP_USER_AGENT=cloud-shell/1.0 to identify the cloud shell +#update template to user the following user http://localhost:50342/oauth2/token + diff --git a/deploy/scripts/helpers/script_helpers.sh b/deploy/scripts/helpers/script_helpers.sh new file mode 100755 index 0000000000..c683cd6aef --- /dev/null +++ b/deploy/scripts/helpers/script_helpers.sh @@ -0,0 +1,424 @@ +#!/bin/bash +#colors for terminal +boldreduscore="\e[1;4;31m" +boldred="\e[1;31m" +cyan="\e[1;36m" +resetformatting="\e[0m" + +function control_plane_showhelp { + echo "" + echo "#################################################################################################################" + echo "# #" + echo "# #" + echo "# This file contains the logic to prepare an Azure region to support the SAP Deployment Automation by #" + echo "# preparing the deployer and the library. #" + echo "# The script experts the following exports: #" + echo "# #" + echo "# ARM_SUBSCRIPTION_ID to specify which subscription to deploy to #" + echo "# DEPLOYMENT_REPO_PATH the path to the folder containing the cloned sap-automation #" + echo "# #" + echo "# The script is to be run from a parent folder to the folders containing the json parameter files for #" + echo "# the deployer and the library and the environment. #" + echo "# #" + echo "# The script will persist the parameters needed between the executions in the #" + echo "# ~/.sap_deployment_automation folder #" + echo "# #" + echo "# #" + echo "# Usage: prepare_region.sh #" + echo "# -d or --deployer_parameter_file deployer parameter file #" + echo "# -l or --library_parameter_file library parameter file #" + echo "# #" + echo "# Optional parameters #" + echo "# -s or --subscription subscription #" + echo "# -c or --spn_id SPN application id #" + echo "# -p or --spn_secret SPN password #" + echo "# -t or --tenant_id SPN Tenant id #" + echo "# -f or --force Clean up the local Terraform files. #" + echo "# -i or --auto-approve Silent install #" + echo "# -h or --help Help #" + echo "# #" + echo "# Example: #" + echo "# #" + echo "# DEPLOYMENT_REPO_PATH/scripts/prepare_region.sh \ #" + echo "# --deployer_parameter_file DEPLOYER/MGMT-WEEU-DEP00-INFRASTRUCTURE/MGMT-WEEU-DEP00-INFRASTRUCTURE.json \ #" + echo "# --library_parameter_file LIBRARY/MGMT-WEEU-SAP_LIBRARY/MGMT-WEEU-SAP_LIBRARY.json \ #" + echo "# #" + echo "# Example: #" + echo "# #" + echo "# DEPLOYMENT_REPO_PATH/scripts/prepare_region.sh \ #" + echo "# --deployer_parameter_file DEPLOYER/PROD-WEEU-DEP00-INFRASTRUCTURE/PROD-WEEU-DEP00-INFRASTRUCTURE.json \ #" + echo "# --library_parameter_file LIBRARY/PROD-WEEU-SAP_LIBRARY/PROD-WEEU-SAP_LIBRARY.json \ #" + echo "# --subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ #" + echo "# --spn_id yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy \ #" + echo "# --spn_secret ************************ \ #" + echo "# --tenant_id zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz \ #" + echo "# --auto-approve #" + echo "# #" + echo "#################################################################################################################" +} + +function control_plane_missing { + printf -v val '%-40s' "$missing_value" + echo "" + echo "#########################################################################################" + echo "# #" + echo "# Missing : ${val} #" + echo "# #" + echo "# Usage: prepare_region.sh #" + echo "# -d or --deployer_parameter_file deployer parameter file #" + echo "# -l or --library_parameter_file library parameter file #" + echo "# #" + echo "# Optional parameters #" + echo "# -s or --subscription subscription #" + echo "# -c or --spn_id SPN application id #" + echo "# -p or --spn_secret SPN password #" + echo "# -t or --tenant_id SPN Tenant id #" + echo "# -f or --force Clean up the local Terraform files. #" + echo "# -i or --auto-approve Silent install #" + echo "# -h or --help Help #" + echo "# #" + echo "#########################################################################################" + +} + +function workload_zone_showhelp { + echo "" + echo "#########################################################################################" + echo "# #" + echo "# #" + echo "# This file contains the logic to deploy the workload infrastructure to Azure #" + echo "# #" + echo "# The script experts the following exports: #" + echo "# #" + echo "# DEPLOYMENT_REPO_PATH the path to the folder containing the cloned sap-automation repo #" + echo "# #" + echo "# The script is to be run from the folder containing the json parameter file #" + echo "# #" + echo "# The script will persist the parameters needed between the executions in the #" + echo "# ~/.sap_deployment_automation folder #" + echo "# #" + echo "# Usage: install_workloadzone.sh #" + echo "# -p or --parameterfile deployer parameter file #" + echo "# #" + echo "# Optional parameters #" + echo "# -d or --deployer_tfstate_key Deployer terraform state file name #" + echo "# -e or --deployer_environment Deployer environment, i.e. MGMT #" + echo "# -s or --subscription subscription #" + echo "# -k or --state_subscription subscription for statefile #" + echo "# -c or --spn_id SPN application id #" + echo "# -p or --spn_secret SPN password #" + echo "# -t or --tenant_id SPN Tenant id #" + echo "# -f or --force Clean up the local Terraform files. #" + echo "# -i or --auto-approve Silent install #" + echo "# -h or --help Help #" + echo "# #" + echo "# Example: #" + echo "# #" + echo "# [REPO-ROOT]deploy/scripts/install_workloadzone.sh \ #" + echo "# --parameterfile PROD-WEEU-SAP01-INFRASTRUCTURE #" + echo "# #" + echo "# Example: #" + echo "# #" + echo "# [REPO-ROOT]deploy/scripts/install_workloadzone.sh \ #" + echo "# --parameterfile PROD-WEEU-SAP01-INFRASTRUCTURE \ #" + echo "# --deployer_environment MGMT \ #" + echo "# --subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ #" + echo "# --spn_id yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy \ #" + echo "# --spn_secret ************************ \ #" + echo "# --spn_secret yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy \ #" + echo "# --tenant_id zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz \ #" + echo "# --auto-approve #" + echo "#########################################################################################" +} + +function workload_zone_missing { + printf -v val %-.40s "$option" + echo "" + echo "" + echo "#########################################################################################" + echo "# #" + echo "# Missing environment variables: ${option}!!! #" + echo "# #" + echo "# Please export the folloing variables: #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# #" + echo "# Usage: install_workloadzone.sh #" + echo "# -p or --parameterfile deployer parameter file #" + echo "# #" + echo "# Optional parameters #" + echo "# -d or deployer_tfstate_key Deployer terraform state file name #" + echo "# -e or deployer_environment Deployer environment, i.e. MGMT #" + echo "# -k or --state_subscription subscription of keyvault with SPN details #" + echo "# -v or --keyvault Name of Azure keyvault with SPN details #" + echo "# -s or --subscription subscription #" + echo "# -c or --spn_id SPN application id #" + echo "# -o or --storageaccountname Storage account for terraform state files #" + echo "# -n or --spn_secret SPN password #" + echo "# -t or --tenant_id SPN Tenant id #" + echo "# -f or --force Clean up the local Terraform files. #" + echo "# -i or --auto-approve Silent install #" + echo "# -h or --help Help #" + echo "#########################################################################################" +} + +function showhelp { + echo "" + echo "#########################################################################################" + echo "# #" + echo "# #" + echo "# This file contains the logic to deploy the different systems #" + echo "# The script experts the following exports: #" + echo "# #" + echo "# ARM_SUBSCRIPTION_ID to specify which subscription to deploy to #" + echo "# DEPLOYMENT_REPO_PATH the path to the folder containing the cloned sap-automation #" + echo "# #" + echo "# The script will persist the parameters needed between the executions in the #" + echo "# ~/.sap_deployment_automation folder #" + echo "# #" + echo "# #" + echo "# Usage: installer.sh #" + echo "# -p or --parameterfile parameter file #" + echo "# -t or --type type of system to remove #" + echo "# valid options: #" + echo "# sap_deployer #" + echo "# sap_library #" + echo "# sap_landscape #" + echo "# sap_system #" + echo "# #" + echo "# Optional parameters #" + echo "# #" + echo "# -o or --storageaccountname Storage account name for state file #" + echo "# -s or --state_subscription Subscription for tfstate storage account #" + echo "# -i or --auto-approve Silent install #" + echo "# -h or --help Show help #" + echo "# #" + echo "# Example: #" + echo "# #" + echo "# [REPO-ROOT]deploy/scripts/installer.sh \ #" + echo "# --parameterfile DEV-WEEU-SAP01-X00 \ #" + echo "# --type sap_system #" + echo "# --auto-approve #" + echo "# #" + echo "#########################################################################################" + return 0 +} + +function missing { + printf -v val %-.40s "$option" + echo "" + echo "" + echo "#########################################################################################" + echo "# #" + echo "# Missing environment variables: ${option}!!! #" + echo "# #" + echo "# Please export the folloing variables: #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" + echo "# REMOTE_STATE_RG (resource group name for storage account containing state files) #" + echo "# REMOTE_STATE_SA (storage account for state file) #" + echo "# #" + echo "#########################################################################################" + return 0 +} + + +function validate_exports { + if [ -z "$DEPLOYMENT_REPO_PATH" ]; then + echo "" + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Missing environment variables (DEPLOYMENT_REPO_PATH)!!! $resetformatting #" + echo "# #" + echo "# Please export the folloing variables: #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" + echo "# #" + echo "#########################################################################################" + return 65 #data format error + fi + + if [ -z "$ARM_SUBSCRIPTION_ID" ]; then + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Missing environment variables (ARM_SUBSCRIPTION_ID)!!! $resetformatting #" + echo "# #" + echo "# Please export the folloing variables: #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" + echo "# #" + echo "#########################################################################################" + return 65 #data format error + fi + + return 0 +} + +function showhelp { + echo "" + echo "#########################################################################################" + echo "# #" + echo "# #" + echo "# This file contains the logic to deploy the different systems #" + echo "# The script experts the following exports: #" + echo "# #" + echo "# ARM_SUBSCRIPTION_ID to specify which subscription to deploy to #" + echo "# DEPLOYMENT_REPO_PATH the path to the folder containing the cloned sap-automation #" + echo "# #" + echo "# The script will persist the parameters needed between the executions in the #" + echo "# ~/.sap_deployment_automation folder #" + echo "# #" + echo "# #" + echo "# Usage: installer.sh #" + echo "# -p or --parameterfile parameter file #" + echo "# -t or --type type of system to remove #" + echo "# valid options: #" + echo "# sap_deployer #" + echo "# sap_library #" + echo "# sap_landscape #" + echo "# sap_system #" + echo "# #" + echo "# Optional parameters #" + echo "# #" + echo "# -o or --storageaccountname Storage account name for state file #" + echo "# -s or --state_subscription Subscription for tfstate storage account #" + echo "# -i or --auto-approve Silent install #" + echo "# -h or --help Show help #" + echo "# #" + echo "# Example: #" + echo "# #" + echo "# [REPO-ROOT]deploy/scripts/installer.sh \ #" + echo "# --parameterfile DEV-WEEU-SAP01-X00 \ #" + echo "# --type sap_system #" + echo "# --auto-approve #" + echo "# #" + echo "#########################################################################################" +} + +function missing { + printf -v val %-.40s "$option" + echo "" + echo "" + echo "#########################################################################################" + echo "# #" + echo "# Missing environment variables: ${option}!!! #" + echo "# #" + echo "# Please export the folloing variables: #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" + echo "# REMOTE_STATE_RG (resource group name for storage account containing state files) #" + echo "# REMOTE_STATE_SA (storage account for state file) #" + echo "# #" + echo "#########################################################################################" +} + + + +function validate_dependencies { + # Check terraform + tf=$(terraform -version | grep Terraform) + if [ -z "$tf" ]; then + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldreduscore Please install Terraform $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + return 2 #No such file or directory + fi + # Set Terraform Plug in cache + if [ ! -d "$HOME/.terraform.d/plugin-cache" ] + then + mkdir -p "$HOME/.terraform.d/plugin-cache" + fi + export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" + + + az --version >stdout.az 2>&1 + az=$(grep "azure-cli" stdout.az) + if [ -z "${az}" ]; then + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldreduscore Please install the Azure CLI $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + return 2 #No such file or directory + fi + # Checking for valid az session + temp=$(grep "az login" stdout.az) + if [ -n "${temp}" ]; then + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Please login using az login! $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + if [ -f stdout.az ]; then + rm stdout.az + fi + exit 67 #addressee unknown + fi + cloudIDUsed=$(az account show | grep "cloudShellID") + if [ -n "${cloudIDUsed}" ]; + then + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Please login using your credentials or service principal credentials! $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + exit 67 #addressee unknown + fi + + return 0 +} + +function validate_key_parameters { + echo "Validating $1" + ext=$(echo $1 | cut -d. -f2) + + # Helper variables + if [ "${ext}" == json ]; then + export environment=$(jq --raw-output .infrastructure.environment $1) + export region=$(jq --raw-output .infrastructure.region $1) + else + load_config_vars $1 "environment" + environment=$(echo ${environment} | xargs) + load_config_vars $1 "location" + region=$(echo ${location} | xargs) + fi + + if [ -z "${environment}" ]; then + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Incorrect parameter file. $resetformatting #" + echo "# #" + echo "# The file must contain the environment attribute!! #" + echo "# #" + echo "#########################################################################################" + echo "" + return 64 #script usage wrong + fi + + if [ -z "${region}" ]; then + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Incorrect parameter file. $resetformatting #" + echo "# #" + echo "# The file must contain the region/location attribute!! #" + echo "# #" + echo "#########################################################################################" + echo "" + return 64 #script usage wrong + fi + + return 0 +} + + diff --git a/deploy/scripts/install_deployer.sh b/deploy/scripts/install_deployer.sh index ecf9d84ef8..425cc44652 100755 --- a/deploy/scripts/install_deployer.sh +++ b/deploy/scripts/install_deployer.sh @@ -15,6 +15,9 @@ script_directory="$(dirname "${full_script_path}")" #call stack has full scriptname when using source source "${script_directory}/deploy_utils.sh" +#helper files +source "${script_directory}/helpers/script_helpers.sh" + #Internal helper functions function showhelp { echo "" @@ -72,6 +75,8 @@ deployment_system=sap_deployer param_dirname=$(dirname "${parameterfile}") +echo "Parameter file: "${parameterfile}"" + if [ ! -f "${parameterfile}" ] then printf -v val %-40.40s "$parameterfile" @@ -84,7 +89,7 @@ then exit 2 #No such file or directory fi -if [ $param_dirname != '.' ]; then +if [ "$param_dirname" != '.' ]; then echo "" echo "#########################################################################################" echo "# #" @@ -95,17 +100,11 @@ if [ $param_dirname != '.' ]; then fi -ext=$(echo ${parameterfile} | cut -d. -f2) - -# Helper variables -if [ "${ext}" == json ]; then - environment=$(jq --raw-output .infrastructure.environment "${parameterfile}") - region=$(jq --raw-output .infrastructure.region "${parameterfile}") -else - - load_config_vars "${param_dirname}"/"${parameterfile}" "environment" - load_config_vars "${param_dirname}"/"${parameterfile}" "location" - region=$(echo ${location} | xargs) +# Check that parameter files have environment and location defined +validate_key_parameters "$parameterfile" +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi # Convert the region to the correct code @@ -114,32 +113,6 @@ get_region_code $region key=$(echo "${parameterfile}" | cut -d. -f1) -if [ ! -n "${environment}" ] -then - echo "#########################################################################################" - echo "# #" - echo "# Incorrect parameter file. #" - echo "# #" - echo "# The file needs to contain the infrastructure.environment attribute!! #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 64 -fi - -if [ ! -n "${region}" ] -then - echo "#########################################################################################" - echo "# #" - echo "# Incorrect parameter file. #" - echo "# #" - echo "# The file needs to contain the infrastructure.region attribute!! #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 64 -fi - #Persisting the parameters across executions automation_config_directory=~/.sap_deployment_automation/ generic_config_information="${automation_config_directory}"config @@ -153,53 +126,11 @@ param_dirname=$(pwd) init "${automation_config_directory}" "${generic_config_information}" "${deployer_config_information}" var_file="${param_dirname}"/"${parameterfile}" - -if [ ! -n "${DEPLOYMENT_REPO_PATH}" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo "# Missing environment variables (DEPLOYMENT_REPO_PATH)!!! #" - echo "# #" - echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" - echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" - echo "# #" - echo "#########################################################################################" - exit 4 -else - if [ $config_stored == false ] - then - save_config_var "DEPLOYMENT_REPO_PATH" "${generic_config_information}" - fi -fi - -templen=$(echo "${ARM_SUBSCRIPTION_ID}" | wc -c) -# Subscription length is 37 -if [ 37 != $templen ] -then - arm_config_stored=false -fi - -if [ ! -n "$ARM_SUBSCRIPTION_ID" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo "# Missing environment variables (ARM_SUBSCRIPTION_ID)!!! #" - echo "# #" - echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" - echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" - echo "# #" - echo "#########################################################################################" - exit 3 -else - if [ $arm_config_stored == false ] - then - echo "Storing the configuration" - save_config_var "ARM_SUBSCRIPTION_ID" "${deployer_config_information}" - STATE_SUBSCRIPTION=$ARM_SUBSCRIPTION_ID - save_config_var "STATE_SUBSCRIPTION" "${deployer_config_information}" - fi +# Check that the exports ARM_SUBSCRIPTION_ID and DEPLOYMENT_REPO_PATH are defined +validate_exports +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi terraform_module_directory="${DEPLOYMENT_REPO_PATH}"/deploy/terraform/bootstrap/"${deployment_system}"/ @@ -208,13 +139,12 @@ export TF_DATA_DIR="${param_dirname}"/.terraform ok_to_proceed=false new_deployment=false -if [ ! -d "$HOME/.terraform.d/plugin-cache" ] -then - mkdir -p "$HOME/.terraform.d/plugin-cache" +# Check that Terraform and Azure CLI is installed +validate_dependencies +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi -export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" - - if [ ! -d ./.terraform/ ]; then echo "#########################################################################################" diff --git a/deploy/scripts/install_library.sh b/deploy/scripts/install_library.sh index 45061d05ec..e60a5b9920 100755 --- a/deploy/scripts/install_library.sh +++ b/deploy/scripts/install_library.sh @@ -420,11 +420,9 @@ then temp=$(echo "${REMOTE_STATE_RG}" | grep "Backend reinitialization required") if [ -z "${temp}" ] then - echo "save" save_config_var "REMOTE_STATE_RG" "${library_config_information}" return_value=0 fi fi - exit $return_value diff --git a/deploy/scripts/install_workloadzone.sh b/deploy/scripts/install_workloadzone.sh index 22b019ba25..5849518d21 100755 --- a/deploy/scripts/install_workloadzone.sh +++ b/deploy/scripts/install_workloadzone.sh @@ -109,6 +109,9 @@ get_region_code "$region" private_link_used=$(grep "use_private_endpoint=" "${param_dirname}"/"${parameterfile}" | cut -d'=' -f2 | tr -d '"') key=$(echo "${workload_file_parametername}" | cut -d. -f1) +landscape_tfstate_key=${key}.terraform.tfstate + + #Persisting the parameters across executions @@ -620,6 +623,8 @@ then unset TF_DATA_DIR exit $return_value fi + +ok_to_proceed=0 if [ 0 == $return_value ] ; then echo "" echo "#########################################################################################" @@ -648,13 +653,8 @@ if [ 0 == $return_value ] ; then workloadkeyvault=$(terraform -chdir="${terraform_module_directory}" output workloadzone_kv_name | tr -d \") save_config_var "workloadkeyvault" "${workload_config_information}" - - workloadkeyvault=$(terraform -chdir="${terraform_module_directory}" output workloadzone_kv_name | tr -d \") - save_config_var "workloadkeyvault" "${workload_config_information}" - - - unset TF_DATA_DIR - exit $return_value + save_config_vars "landscape_tfstate_key" "${workload_config_information}" + ok_to_proceed=0 fi if [ 2 == $return_value ] ; then @@ -679,21 +679,18 @@ if [ 2 == $return_value ] ; then read -p "Do you want to continue with the deployment Y/N?" ans answer=${ans^^} if [ $answer == 'Y' ]; then - ok_to_proceed=true + ok_to_proceed=1 else unset TF_DATA_DIR exit 0 fi else - ok_to_proceed=true + ok_to_proceed=1 fi fi -if [ $ok_to_proceed ]; then - - rm plan_output.log - +if [ 1 == $ok_to_proceed ]; then echo "" echo "#########################################################################################" echo "# #" @@ -703,18 +700,15 @@ if [ $ok_to_proceed ]; then echo "" terraform -chdir="${terraform_module_directory}" apply ${approve} -var-file=${var_file} $tfstate_parameter $landscape_tfstate_key_parameter $deployer_tfstate_key_parameter + return_value=$? fi -return_value=0 -landscape_tfstate_key=${key}.terraform.tfstate save_config_var "landscape_tfstate_key" "${workload_config_information}" - if [ 0 == $return_value ] ; then - + save_config_vars "landscape_tfstate_key" "${workload_config_information}" workloadkeyvault=$(terraform -chdir="${terraform_module_directory}" output workloadzone_kv_name | tr -d \") - return_value=-1 temp=$(echo "${workloadkeyvault}" | grep "Warning") if [ -z "${temp}" ] then @@ -733,14 +727,9 @@ if [ 0 == $return_value ] ; then echo "" save_config_var "workloadkeyvault" "${workload_config_information}" - return_value=0 - else - return_value=-1 fi fi unset TF_DATA_DIR - exit $return_value - if [ "$private_link_used" == "true" ]; then echo "#########################################################################################" @@ -757,6 +746,22 @@ if [ 0 == $return_value ] ; then fi +now=$(date) +cat < "${workload_config_information}".md +# Workload Zone Deployment # + +Date : "${now}" + +## Configuration details ## + +| Item | Name | +| ----------------------- | -------------------- | +| Environment | $environment | +| Location | $region | +| Keyvault Name | ${workloadkeyvault} | + +EOF + unset TF_DATA_DIR exit $return_value diff --git a/deploy/scripts/installer.sh b/deploy/scripts/installer.sh index e033643f89..cc40034bb4 100755 --- a/deploy/scripts/installer.sh +++ b/deploy/scripts/installer.sh @@ -14,63 +14,8 @@ script_directory="$(dirname "${full_script_path}")" #call stack has full scriptname when using source source "${script_directory}/deploy_utils.sh" -function showhelp { - echo "" - echo "#########################################################################################" - echo "# #" - echo "# #" - echo "# This file contains the logic to deploy the different systems #" - echo "# The script experts the following exports: #" - echo "# #" - echo "# ARM_SUBSCRIPTION_ID to specify which subscription to deploy to #" - echo "# DEPLOYMENT_REPO_PATH the path to the folder containing the cloned sap-automation #" - echo "# #" - echo "# The script will persist the parameters needed between the executions in the #" - echo "# ~/.sap_deployment_automation folder #" - echo "# #" - echo "# #" - echo "# Usage: installer.sh #" - echo "# -p or --parameterfile parameter file #" - echo "# -t or --type type of system to remove #" - echo "# valid options: #" - echo "# sap_deployer #" - echo "# sap_library #" - echo "# sap_landscape #" - echo "# sap_system #" - echo "# #" - echo "# Optional parameters #" - echo "# #" - echo "# -o or --storageaccountname Storage account name for state file #" - echo "# -i or --auto-approve Silent install #" - echo "# -h or --help Show help #" - echo "# #" - echo "# Example: #" - echo "# #" - echo "# [REPO-ROOT]deploy/scripts/installer.sh \ #" - echo "# --parameterfile DEV-WEEU-SAP01-X00 \ #" - echo "# --type sap_system #" - echo "# --auto-approve #" - echo "# #" - echo "#########################################################################################" -} - -function missing { - printf -v val %-.40s "$option" - echo "" - echo "" - echo "#########################################################################################" - echo "# #" - echo "# Missing environment variables: ${option}!!! #" - echo "# #" - echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" - echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" - echo "# REMOTE_STATE_RG (resource group name for storage account containing state files) #" - echo "# REMOTE_STATE_SA (storage account for state file) #" - echo "# #" - echo "#########################################################################################" -} - +#helper files +source "${script_directory}/helpers/script_helpers.sh" force=0 @@ -105,18 +50,12 @@ tfstate_resource_id="" tfstate_parameter="" deployer_tfstate_key_parameter="" -deployer_tfstate_key_exists=false landscape_tfstate_key_parameter="" landscape_tfstate_key_exists=false parameterfile_name=$(basename "${parameterfile}") param_dirname=$(dirname "${parameterfile}") -echo $STATE_SUBSCRIPTION -echo $deployer_tfstate_key -echo $landscape_tfstate_key - - if [ "${param_dirname}" != '.' ]; then echo "" echo "#########################################################################################" @@ -139,7 +78,7 @@ then exit 2 #No such file or directory fi -if [ ! -n "${deployment_system}" ] +if [ -z "${deployment_system}" ] then printf -v val %-40.40s "$deployment_system" echo "#########################################################################################" @@ -157,50 +96,33 @@ then exit 64 #script usage wrong fi - - - -ext=$(echo ${parameterfile_name} | cut -d. -f2) - -# Helper variables -if [ "${ext}" == json ]; then - environment=$(jq --raw-output .infrastructure.environment "${parameterfile}") - region=$(jq --raw-output .infrastructure.region "${parameterfile}") -else - load_config_vars "${param_dirname}"/"${parameterfile}" "environment" - load_config_vars "${param_dirname}"/"${parameterfile}" "location" - region=$(echo ${location} | xargs) +# Check that the exports ARM_SUBSCRIPTION_ID and DEPLOYMENT_REPO_PATH are defined +validate_exports +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi -if [ ! -n "${environment}" ] -then - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Incorrect parameter file. $resetformatting #" - echo "# #" - echo "# The file needs to contain the infrastructure.environment attribute!! #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 65 #data format error +# Check that Terraform and Azure CLI is installed +validate_dependencies +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi -if [ ! -n "${region}" ] -then - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Incorrect parameter file. $resetformatting #" - echo "# #" - echo "# The file needs to contain the infrastructure.region attribute!! #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 65 #data format error +# Check that parameter files have environment and location defined +validate_key_parameters "$parameterfile_name" +if [ 0 != $return_code ]; then + exit $return_code fi - -# Convert the region to the correct code -get_region_code $region +if valid_region_name ${region} ; then + # Convert the region to the correct code + get_region_code ${region} +else + echo "Invalid region: $region" + exit 2 +fi key=$(echo "${parameterfile_name}" | cut -d. -f1) @@ -210,6 +132,10 @@ automation_config_directory=~/.sap_deployment_automation/ generic_config_information="${automation_config_directory}"config system_config_information="${automation_config_directory}""${environment}""${region_code}" +echo "Configuration file: $system_config_information" +echo "Deployment region: $region" +echo "Deployment region code: $region_code" + deployer_tfstate_key_parameter='' landscape_tfstate_key_parameter='' @@ -222,13 +148,6 @@ fi echo "Parallelism count $parallelism" -#Plugins -if [ ! -d "$HOME/.terraform.d/plugin-cache" ] -then - mkdir -p "$HOME/.terraform.d/plugin-cache" -fi -export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" - param_dirname=$(pwd) init "${automation_config_directory}" "${generic_config_information}" "${system_config_information}" @@ -248,122 +167,100 @@ fi if [ -z "$REMOTE_STATE_SA" ]; then + echo "Loading the State file information" load_config_vars "${system_config_information}" "REMOTE_STATE_SA" + load_config_vars "${system_config_information}" "REMOTE_STATE_RG" + load_config_vars "${system_config_information}" "tfstate_resource_id" + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" else save_config_vars "${system_config_information}" REMOTE_STATE_SA fi -load_config_vars "${system_config_information}" "REMOTE_STATE_RG" -load_config_vars "${system_config_information}" "tfstate_resource_id" +echo "Terraform state file storage: $REMOTE_STATE_SA" +echo "Terraform state subscription: $STATE_SUBSCRIPTION" if [ -z "$deployer_tfstate_key" ]; then - load_config_vars "${system_config_information}" "deployer_tfstate_key" + load_config_vars "${system_config_information}" "deployer_tfstate_key" else - save_config_vars "${system_config_information}" deployer_tfstate_key + save_config_vars "${system_config_information}" deployer_tfstate_key fi if [ -z "$landscape_tfstate_key" ]; then - load_config_vars "${system_config_information}" "landscape_tfstate_key" + load_config_vars "${system_config_information}" "landscape_tfstate_key" else - save_config_vars "${system_config_information}" landscape_tfstate_key + save_config_vars "${system_config_information}" landscape_tfstate_key fi if [ -z "$STATE_SUBSCRIPTION" ]; then - load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" else echo "Saving the state subscription" - if is_valid_guid "STATE_SUBSCRIPTION" ; then - save_config_var "STATE_SUBSCRIPTION" "${workload_config_information}" + if is_valid_guid "$STATE_SUBSCRIPTION" ; then + save_config_var "STATE_SUBSCRIPTION" "${system_config_information}" else printf -v val %-40.40s "$STATE_SUBSCRIPTION" echo "#########################################################################################" echo "# #" - echo -e "#The provided state_subscription is not valid:$boldred ${val} $resetformatting#" + echo -e "# The provided state_subscription is not valid:$boldred ${val}$resetformatting#" echo "# #" echo "#########################################################################################" exit 65 fi - + fi -echo "Terraform storage " "${REMOTE_STATE_SA}" +account_set=0 -if [ ! -n "${DEPLOYMENT_REPO_PATH}" ]; then - option="DEPLOYMENT_REPO_PATH" - missing - exit 1 -fi +#setting the user environment variables +set_executing_user_environment_variables "none" -# Checking for valid az session -az account show > stdout.az 2>&1 -temp=$(grep "az login" stdout.az) -if [ -n "${temp}" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Please login using az login $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - if [ -f stdout.az ] - then - rm stdout.az - fi - exit 67 #addressee unknown -else - if [ -f stdout.az ] - then - rm stdout.az +if [ -n "${subscription}" ]; then + if is_valid_guid "${subscription}" ; then + echo "Valid subscription format" + else + printf -v val %-40.40s "$subscription" + echo "#########################################################################################" + echo "# #" + echo -e "# The provided subscription is not valid:$boldred ${val} $resetformatting# " + echo "# #" + echo "#########################################################################################" + exit 65 fi - + export ARM_SUBSCRIPTION_ID="${subscription}" fi -account_set=0 - -cloudIDUsed=$(az account show | grep "cloudShellID") -if [ ! -z "${cloudIDUsed}" ]; -then +if [ -n "$STATE_SUBSCRIPTION" ]; +then echo "" echo "#########################################################################################" echo "# #" - echo -e "# $boldred Please login using your credentials or service principal credentials! $resetformatting #" + echo -e "# $cyan Changing the subscription to: $STATE_SUBSCRIPTION $resetformatting #" echo "# #" echo "#########################################################################################" echo "" - exit 67 #addressee unknown + az account set --sub "${STATE_SUBSCRIPTION}" fi -#setting the user environment variables -set_executing_user_environment_variables "none" - +load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" +load_config_vars "${system_config_information}" "REMOTE_STATE_RG" +load_config_vars "${system_config_information}" "tfstate_resource_id" -if [ ! -z "${STATE_SUBSCRIPTION}" ] -then - $(az account set --sub "${STATE_SUBSCRIPTION}") - account_set=1 -fi -if [ ! -n "${REMOTE_STATE_SA}" ]; then - read -p "Terraform state storage account name:" REMOTE_STATE_SA - - get_and_store_sa_details ${REMOTE_STATE_SA} "${system_config_information}" - load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" - load_config_vars "${system_config_information}" "REMOTE_STATE_RG" - load_config_vars "${system_config_information}" "tfstate_resource_id" - - if [ ! -z "${STATE_SUBSCRIPTION}" ] - then - if [ $account_set == 0 ] - then - $(az account set --sub "${STATE_SUBSCRIPTION}") - account_set=1 - fi +if [ -z "${REMOTE_STATE_SA}" ]; then + if [ 1 != $ado ]; then + read -p "Terraform state storage account name:" REMOTE_STATE_SA + + get_and_store_sa_details "${REMOTE_STATE_SA}" "${system_config_information}" + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" + load_config_vars "${system_config_information}" "REMOTE_STATE_RG" + load_config_vars "${system_config_information}" "tfstate_resource_id" fi fi +echo "Terraform state storage " "${REMOTE_STATE_SA}" if [ -z "${REMOTE_STATE_SA}" ]; then option="REMOTE_STATE_SA" @@ -372,33 +269,24 @@ if [ -z "${REMOTE_STATE_SA}" ]; then fi if [ -z "${REMOTE_STATE_RG}" ]; then - get_and_store_sa_details ${REMOTE_STATE_SA} "${system_config_information}" + get_and_store_sa_details "${REMOTE_STATE_SA}" "${system_config_information}" + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" + load_config_vars "${system_config_information}" "REMOTE_STATE_RG" + load_config_vars "${system_config_information}" "tfstate_resource_id" +fi + +if [ -z "${tfstate_resource_id}" ]; then + get_and_store_sa_details "${REMOTE_STATE_SA}" "${system_config_information}" load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" load_config_vars "${system_config_information}" "REMOTE_STATE_RG" load_config_vars "${system_config_information}" "tfstate_resource_id" - - if [ ! -z "${STATE_SUBSCRIPTION}" ] - then - if [ $account_set == 0 ] - then - $(az account set --sub "${STATE_SUBSCRIPTION}") - account_set=1 - fi - - fi fi +tfstate_parameter=" -var tfstate_resource_id=${tfstate_resource_id}" + if [ "${deployment_system}" != sap_deployer ] then - if [ ! -n "${tfstate_resource_id}" ]; then - get_and_store_sa_details ${REMOTE_STATE_SA} "${system_config_information}" - load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" - load_config_vars "${system_config_information}" "REMOTE_STATE_RG" - load_config_vars "${system_config_information}" "tfstate_resource_id" - - fi - tfstate_parameter=" -var tfstate_resource_id=${tfstate_resource_id}" if [ -z "${deployer_tfstate_key}" ]; then deployer_tfstate_key_parameter=" " @@ -422,10 +310,23 @@ then landscape_tfstate_key_parameter=" -var landscape_tfstate_key=${landscape_tfstate_key}" landscape_tfstate_key_exists=true else - read -p "Workload terraform statefile name :" landscape_tfstate_key - landscape_tfstate_key_parameter=" -var landscape_tfstate_key=${landscape_tfstate_key}" - save_config_var "landscape_tfstate_key" "${system_config_information}" - landscape_tfstate_key_exists=true + if [ 1 != $ado ]; then + read -p "Workload terraform statefile name :" landscape_tfstate_key + landscape_tfstate_key_parameter=" -var landscape_tfstate_key=${landscape_tfstate_key}" + save_config_var "landscape_tfstate_key" "${system_config_information}" + landscape_tfstate_key_exists=true + else + export last_error="Workload terraform statefile name is missing" + echo "#########################################################################################" + echo "# #" + echo -e "# $boldred Workload terraform statefile name is missing $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + unset TF_DATA_DIR + exit 1 + + fi fi else landscape_tfstate_key_parameter="" @@ -453,24 +354,21 @@ then fi ok_to_proceed=false -new_deployment=false -check_output=0 - -if [ $account_set == 0 ] -then - $(az account set --sub "${STATE_SUBSCRIPTION}") - account_set=1 -fi +echo "subscription_id=${STATE_SUBSCRIPTION}" +echo "resource_group_name=${REMOTE_STATE_RG}" +echo "storage_account_name=${REMOTE_STATE_SA}" # This is used to tell Terraform if this is a new deployment or an update deployment_parameter="" # This is used to tell Terraform the version information from the state file version_parameter="" + +check_output=0 if [ ! -d ./.terraform/ ]; then deployment_parameter=" -var deployment=new " - + terraform -chdir="${terraform_module_directory}" init -upgrade=true \ --backend-config "subscription_id=${STATE_SUBSCRIPTION}" \ --backend-config "resource_group_name=${REMOTE_STATE_RG}" \ @@ -478,10 +376,10 @@ then --backend-config "container_name=tfstate" \ --backend-config "key=${key}.terraform.tfstate" return_value=$? - + else temp=$(grep "\"type\": \"local\"" .terraform/terraform.tfstate) - if [ ! -z "${temp}" ] + if [ -n "${temp}" ] then terraform -chdir="${terraform_module_directory}" init -upgrade=true -force-copy \ --backend-config "subscription_id=${STATE_SUBSCRIPTION}" \ @@ -511,7 +409,6 @@ else fi fi - if [ 0 != $return_value ] then echo "#########################################################################################" @@ -520,17 +417,13 @@ then echo "# #" echo "#########################################################################################" echo "" - exit $return_value + exit $return_value fi - if [ 1 == $check_output ] then - terraform -chdir=$terraform_module_directory refresh -var-file=${var_file} ${tfstate_parameter} ${landscape_tfstate_key_parameter} ${deployer_tfstate_key_parameter} ${extra_vars} - outputs=$(terraform -chdir="${terraform_module_directory}" output ) if echo "${outputs}" | grep "No outputs"; then ok_to_proceed=true - new_deployment=true echo "#########################################################################################" echo "# #" echo -e "# $cyan New deployment $resetformatting #" @@ -547,12 +440,14 @@ then echo "# #" echo "#########################################################################################" echo "" + allParams=$(printf " -var-file=%s %s %s %s %s %s %s" "${var_file}" "${extra_vars}" "${tfstate_parameter}" "${landscape_tfstate_key_parameter}" "${deployer_tfstate_key_parameter}" "${deployment_parameter}" "${version_parameter}" ) + terraform -chdir="${terraform_module_directory}" refresh $allParams deployment_parameter=" " deployed_using_version=$(terraform -chdir="${terraform_module_directory}" output automation_version | tr -d \") - if [ ! -n "${deployed_using_version}" ]; then + if [ -z "${deployed_using_version}" ]; then echo "" echo "#########################################################################################" echo "# #" @@ -563,12 +458,11 @@ then echo "# Please inspect the output of Terraform plan carefully before proceeding #" echo "# #" echo "#########################################################################################" - + if [ 1 == $ado ] ; then - unset TF_DATA_DIR - exit 1 + unset TF_DATA_DIR + exit 1 fi - read -p "Do you want to continue Y/N?" ans answer=${ans^^} if [ $answer == 'Y' ]; then @@ -580,7 +474,7 @@ then else version_parameter=" -var terraform_template_version=${deployed_using_version} " - printf -v val %-.20s "$deployed_using_version" + printf -v val %-.20s "$deployed_using_version" echo "" echo "#########################################################################################" echo "# #" @@ -615,15 +509,10 @@ then echo "" echo "#########################################################################################" echo "# #" - echo -e "# $boldreduscoreErrors during the plan phase$resetformatting #" + echo -e "# $boldreduscore Errors during the plan phase$resetformatting #" echo "# #" echo "#########################################################################################" echo "" - if [ -f plan_output.log ] - then - cat plan_output.log - rm plan_output.log - fi unset TF_DATA_DIR exit $return_value fi @@ -640,19 +529,16 @@ if [ 0 == $return_value ] ; then then rm plan_output.log fi - + if [ "${deployment_system}" == sap_deployer ] then deployer_public_ip_address=$(terraform -chdir="${terraform_module_directory}" output deployer_public_ip_address | tr -d \") keyvault=$(terraform -chdir="${terraform_module_directory}" output deployer_kv_user_name | tr -d \") - sshsecret=$(terraform -chdir="${terraform_module_directory}" output deployer_private_key_secret_name | tr -d \") - save_config_var "keyvault" "${system_config_information}" - save_config_var "deployer_public_ip_address" "${system_config_information}" - save_config_var "sshsecret" "${system_config_information}" + save_config_var "deployer_public_ip_address" "${system_config_information}" fi - + if [ "${deployment_system}" == sap_landscape ] then if [ $landscape_tfstate_key_exists == false ] @@ -661,21 +547,21 @@ if [ 0 == $return_value ] ; then landscape_tfstate_key fi fi - + if [ "${deployment_system}" == sap_library ] then tfstate_resource_id=$(terraform -chdir="${terraform_module_directory}" output tfstate_resource_id| tr -d \") - STATE_SUBSCRIPTION=$(echo $tfstate_resource_id | cut -d/ -f3 | tr -d \" | xargs) - - az account set --sub $STATE_SUBSCRIPTION - + STATE_SUBSCRIPTION=$(echo "$tfstate_resource_id" | cut -d/ -f3 | tr -d \" | xargs) + + az account set --sub "${STATE_SUBSCRIPTION}" + REMOTE_STATE_SA=$(terraform -chdir="${terraform_module_directory}" output remote_state_storage_account_name| tr -d \") - get_and_store_sa_details ${REMOTE_STATE_SA} "${system_config_information}" + get_and_store_sa_details "${REMOTE_STATE_SA}" "${system_config_information}" fi - + unset TF_DATA_DIR exit $return_value fi @@ -683,7 +569,7 @@ if [ 2 == $return_value ] ; then fatal_errors=0 # HANA VM test=$(grep vm_dbnode plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -698,7 +584,7 @@ if [ 2 == $return_value ] ; then fi # HANA VM disks test=$(grep azurerm_managed_disk.data_disk plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -711,10 +597,10 @@ if [ 2 == $return_value ] ; then echo "" fatal_errors=1 fi - + # AnyDB server test=$(grep dbserver plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -729,7 +615,7 @@ if [ 2 == $return_value ] ; then fi # AnyDB disks test=$(grep azurerm_managed_disk.disks plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -742,10 +628,10 @@ if [ 2 == $return_value ] ; then echo "" fatal_errors=1 fi - + # App server test=$(grep virtual_machine.app plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -760,7 +646,7 @@ if [ 2 == $return_value ] ; then fi # App server disks test=$(grep azurerm_managed_disk.app plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -773,10 +659,10 @@ if [ 2 == $return_value ] ; then echo "" fatal_errors=1 fi - + # SCS server test=$(grep virtual_machine.scs plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -789,10 +675,10 @@ if [ 2 == $return_value ] ; then echo "" fatal_errors=1 fi - + # SCS server disks test=$(grep azurerm_managed_disk.scs plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -805,10 +691,10 @@ if [ 2 == $return_value ] ; then echo "" fatal_errors=1 fi - + # Web server test=$(grep virtual_machine.web plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -823,7 +709,7 @@ if [ 2 == $return_value ] ; then fi # Web dispatcher server disks test=$(grep azurerm_managed_disk.web plan_output.log | grep -m1 replaced) - if [ ! -z "${test}" ] ; then + if [ -n "${test}" ] ; then echo "" echo "#########################################################################################" echo "# #" @@ -836,9 +722,9 @@ if [ 2 == $return_value ] ; then echo "" fatal_errors=1 fi - + if [ $fatal_errors == 1 ] ; then - + echo "" echo "#########################################################################################" echo "# #" @@ -852,9 +738,9 @@ if [ 2 == $return_value ] ; then unset TF_DATA_DIR exit 1 fi - + if [ 1 == $force ]; then - ok_to_proceed=true + ok_to_proceed=true else read -p "Do you want to continue with the deployment Y/N?" ans answer=${ans^^} @@ -865,7 +751,7 @@ if [ 2 == $return_value ] ; then exit 1 fi fi - + fi else ok_to_proceed=true @@ -879,7 +765,7 @@ if [ $ok_to_proceed ]; then fi if [ -f plan_output.log ] then - rm plan_output.log + rm plan_output.log fi echo "" @@ -890,9 +776,9 @@ if [ $ok_to_proceed ]; then echo "#########################################################################################" echo "" - allParams=$(printf " -var-file=%s %s %s %s %s %s %s" "${var_file}" "${extra_vars}" "${tfstate_parameter}" "${landscape_tfstate_key_parameter}" "${deployer_tfstate_key_parameter}" "${deployment_parameter}" "${version_parameter}" ) + allParams=$(printf " -var-file=%s %s %s %s %s %s %s %s " "${var_file}" "${extra_vars}" "${tfstate_parameter}" "${landscape_tfstate_key_parameter}" "${deployer_tfstate_key_parameter}" "${deployment_parameter}" "${version_parameter} "${approve}"" ) - terraform -chdir="${terraform_module_directory}" apply -parallelism=$parallelism ${approve} $allParams 2>error.log + terraform -chdir="${terraform_module_directory}" apply -parallelism="${parallelism}" $allParams 2>error.log return_value=$? if [ 0 != $return_value ] ; then @@ -916,11 +802,9 @@ if [ "${deployment_system}" == sap_deployer ] then deployer_public_ip_address=$(terraform -chdir="${terraform_module_directory}" output deployer_public_ip_address | tr -d \") keyvault=$(terraform -chdir="${terraform_module_directory}" output deployer_kv_user_name | tr -d \") - sshsecret=$(terraform -chdir="${terraform_module_directory}" output deployer_private_key_secret_name | tr -d \") - + save_config_var "keyvault" "${system_config_information}" - save_config_var "deployer_public_ip_address" "${system_config_information}" - save_config_var "sshsecret" "${system_config_information}" + save_config_var "deployer_public_ip_address" "${system_config_information}" fi @@ -932,15 +816,9 @@ fi if [ "${deployment_system}" == sap_library ] then - - tfstate_resource_id=$(terraform -chdir="${terraform_module_directory}" output tfstate_resource_id| tr -d \") - STATE_SUBSCRIPTION=$(echo $tfstate_resource_id | cut -d/ -f3 | tr -d \" | xargs) - - az account set --sub $STATE_SUBSCRIPTION - REMOTE_STATE_SA=$(terraform -chdir="${terraform_module_directory}" output remote_state_storage_account_name| tr -d \") - get_and_store_sa_details ${REMOTE_STATE_SA} "${system_config_information}" + get_and_store_sa_details "${REMOTE_STATE_SA}" "${system_config_information}" fi diff --git a/deploy/scripts/persist_environment_variables.sh b/deploy/scripts/persist_environment_variables.sh new file mode 100644 index 0000000000..c3a3afc47b --- /dev/null +++ b/deploy/scripts/persist_environment_variables.sh @@ -0,0 +1,50 @@ +tf_bin=$(which terraform) +ansible_bin=$(which ansible) +# Ensure that the user's account is logged in to Azure with specified creds +az login --identity --output none +'echo ${USER} account ready for use with Azure SAP Automated Deployment' + +# +# Create /etc/profile.d script to setup environment for future interactive sessions +# +echo '# Configure environment settings for deployer interactive sessions' | sudo tee /etc/profile.d/deploy_server.sh + +echo export ARM_SUBSCRIPTION_ID=${subscription_id} | sudo tee -a /etc/profile.d/deploy_server.sh +echo export DEPLOYMENT_REPO_PATH=$HOME/Azure_SAP_Automated_Deployment/sap-automation | sudo tee -a /etc/profile.d/deploy_server.sh + +echo export "PATH=${ansible_bin}:${tf_bin}:"'${PATH}':$HOME/Azure_SAP_Automated_Deployment/sap-automation/deploy/scripts:$HOME/Azure_SAP_Automated_Deployment/sap-automation/deploy/ansible | sudo tee -a /etc/profile.d/deploy_server.sh + + +# Set env for ansible +echo export ANSIBLE_HOST_KEY_CHECKING=False | sudo tee -a /etc/profile.d/deploy_server.sh +echo export ANSIBLE_COLLECTIONS_PATHS=${ansible_collections} | sudo tee -a /etc/profile.d/deploy_server.sh + +# Set env for MSI +echo export ARM_USE_MSI=true | sudo tee -a /etc/profile.d/deploy_server.sh + +az login --identity 2>error.log || : + +if [ ! -f error.log ]; then + az account show > az.json + client_id=$(jq --raw-output .id az.json) + tenant_id=$(jq --raw-output .tenantId az.json) + rm az.json +else + client_id='' + tenant_id='' + +fi + +if [ ! -n "${client_id}" ]; then + export ARM_CLIENT_ID=${client_id} + echo export ARM_CLIENT_ID=${client_id} | sudo tee -a /etc/profile.d/deploy_server.sh +fi + +if [ ! -n "${tenant_id}" ]; then + export ARM_TENANT_ID=${tenant_id} + echo export ARM_TENANT_ID=${tenant_id} | sudo tee -a /etc/profile.d/deploy_server.sh +fi + +# Ensure that the user's account is logged in to Azure with specified creds +echo az login --identity --output none | sudo tee -a /etc/profile.d/deploy_server.sh +echo 'echo ${USER} account ready for use with Azure SAP Automated Deployment' | sudo tee -a /etc/profile.d/deploy_server.sh diff --git a/deploy/scripts/prepare_region.sh b/deploy/scripts/prepare_region.sh index 9915b9d214..291c8ca6b3 100755 --- a/deploy/scripts/prepare_region.sh +++ b/deploy/scripts/prepare_region.sh @@ -1,21 +1,5 @@ #!/bin/bash -#error codes include those from /usr/include/sysexits.h - -#colors for terminal -boldreduscore="\e[1;4;31m" -boldred="\e[1;31m" -cyan="\e[1;36m" -resetformatting="\e[0m" - -#External helper functions -#. "$(dirname "${BASH_SOURCE[0]}")/deploy_utils.sh" -full_script_path="$(realpath "${BASH_SOURCE[0]}")" -script_directory="$(dirname "${full_script_path}")" - -#call stack has full scriptname when using source -source "${script_directory}/deploy_utils.sh" - ################################################################################################ # # # This file contains the logic to deploy the environment to support SAP workloads. # @@ -32,90 +16,33 @@ source "${script_directory}/deploy_utils.sh" # # ################################################################################################ -function showhelp { - echo "" - echo "#################################################################################################################" - echo "# #" - echo "# #" - echo "# This file contains the logic to prepare an Azure region to support the SAP Deployment Automation by #" - echo "# preparing the deployer and the library. #" - echo "# The script experts the following exports: #" - echo "# #" - echo "# ARM_SUBSCRIPTION_ID to specify which subscription to deploy to #" - echo "# DEPLOYMENT_REPO_PATH the path to the folder containing the cloned sap-automation #" - echo "# #" - echo "# The script is to be run from a parent folder to the folders containing the json parameter files for #" - echo "# the deployer and the library and the environment. #" - echo "# #" - echo "# The script will persist the parameters needed between the executions in the #" - echo "# ~/.sap_deployment_automation folder #" - echo "# #" - echo "# #" - echo "# Usage: prepare_region.sh #" - echo "# -d or --deployer_parameter_file deployer parameter file #" - echo "# -l or --library_parameter_file library parameter file #" - echo "# #" - echo "# Optional parameters #" - echo "# -s or --subscription subscription #" - echo "# -c or --spn_id SPN application id #" - echo "# -p or --spn_secret SPN password #" - echo "# -t or --tenant_id SPN Tenant id #" - echo "# -f or --force Clean up the local Terraform files. #" - echo "# -i or --auto-approve Silent install #" - echo "# -h or --help Help #" - echo "# #" - echo "# Example: #" - echo "# #" - echo "# DEPLOYMENT_REPO_PATH/scripts/prepare_region.sh \ #" - echo "# --deployer_parameter_file DEPLOYER/MGMT-WEEU-DEP00-INFRASTRUCTURE/MGMT-WEEU-DEP00-INFRASTRUCTURE.json \ #" - echo "# --library_parameter_file LIBRARY/MGMT-WEEU-SAP_LIBRARY/MGMT-WEEU-SAP_LIBRARY.json \ #" - echo "# #" - echo "# Example: #" - echo "# #" - echo "# DEPLOYMENT_REPO_PATH/scripts/prepare_region.sh \ #" - echo "# --deployer_parameter_file DEPLOYER/PROD-WEEU-DEP00-INFRASTRUCTURE/PROD-WEEU-DEP00-INFRASTRUCTURE.json \ #" - echo "# --library_parameter_file LIBRARY/PROD-WEEU-SAP_LIBRARY/PROD-WEEU-SAP_LIBRARY.json \ #" - echo "# --subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ #" - echo "# --spn_id yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy \ #" - echo "# --spn_secret ************************ \ #" - echo "# --tenant_id zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz \ #" - echo "# --auto-approve #" - echo "# #" - echo "#################################################################################################################" -} - -function missing { - printf -v val '%-40s' "$missing_value" - echo "" - echo "#########################################################################################" - echo "# #" - echo "# Missing : ${val} #" - echo "# #" - echo "# Usage: prepare_region.sh #" - echo "# -d or --deployer_parameter_file deployer parameter file #" - echo "# -l or --library_parameter_file library parameter file #" - echo "# #" - echo "# Optional parameters #" - echo "# -s or --subscription subscription #" - echo "# -c or --spn_id SPN application id #" - echo "# -p or --spn_secret SPN password #" - echo "# -t or --tenant_id SPN Tenant id #" - echo "# -f or --force Clean up the local Terraform files. #" - echo "# -i or --auto-approve Silent install #" - echo "# -h or --help Help #" - echo "# #" - echo "#########################################################################################" - -} +#error codes include those from /usr/include/sysexits.h + +#colors for terminal +boldreduscore="\e[1;4;31m" +boldred="\e[1;31m" +cyan="\e[1;36m" +resetformatting="\e[0m" + +#External helper functions +#. "$(dirname "${BASH_SOURCE[0]}")/deploy_utils.sh" +full_script_path="$(realpath "${BASH_SOURCE[0]}")" +script_directory="$(dirname "${full_script_path}")" + +#call stack has full scriptname when using source +source "${script_directory}/deploy_utils.sh" + +#helper files +source "${script_directory}/helpers/script_helpers.sh" force=0 recover=0 -INPUT_ARGUMENTS=$(getopt -n prepare_region -o d:l:s:c:p:t:a:ifohr --longoptions deployer_parameter_file:,library_parameter_file:,subscription:,spn_id:,spn_secret:,tenant_id:,storageaccountname:,auto-approve,force,only_deployer,help,recover -- "$@") +INPUT_ARGUMENTS=$(getopt -n prepare_region -o d:l:s:c:p:t:a:ifohrv --longoptions deployer_parameter_file:,library_parameter_file:,subscription:,spn_id:,spn_secret:,tenant_id:,storageaccountname:,auto-approve,force,only_deployer,help,recover,ado -- "$@") VALID_ARGUMENTS=$? if [ "$VALID_ARGUMENTS" != "0" ]; then - showhelp + control_plane_showhelp fi eval set -- "$INPUT_ARGUMENTS" @@ -129,111 +56,59 @@ do -p | --spn_secret) spn_secret="$2" ; shift 2 ;; -t | --tenant_id) tenant_id="$2" ; shift 2 ;; -a | --storageaccountname) REMOTE_STATE_SA="$2" ; shift 2 ;; + -v | --ado) ado_flag="--ado" ; shift ;; -f | --force) force=1 ; shift ;; -o | --only_deployer) only_deployer=1 ; shift ;; -r | --recover) recover=1 ; shift ;; -i | --auto-approve) approve="--auto-approve" ; shift ;; - -h | --help) showhelp + -h | --help) control_plane_showhelp exit 3 ; shift ;; --) shift; break ;; esac done -this_ip=$(curl ipinfo.io/ip) - +this_ip=$(curl -s ipinfo.io/ip) >/dev/null 2>&1 root_dirname=$(pwd) -if [ ! -z "$approve" ]; then +if [ -n "$approve" ]; then approveparam=" -i" fi -if [ -z "$deployer_parameter_file" ]; then - missing_value='deployer parameter file' - missing +if [ ! -f "$deployer_parameter_file" ]; then + export missing_value='deployer parameter file' + control_plane_missing exit 2 #No such file or directory fi -if [ -z "$library_parameter_file" ]; then - missing_value='library parameter file' - missing +if [ ! -f "$library_parameter_file" ]; then + export missing_value='library parameter file' + control_plane_missing exit 2 #No such file or directory fi -# Check terraform -tf=$(terraform -version | grep Terraform) -if [ ! -n "$tf" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldreduscore Please install Terraform $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 2 #No such file or directory +# Check that Terraform and Azure CLI is installed +validate_dependencies +return_code=$? +if [ 0 != $return_code ]; then + echo "validate_dependencies returned $return_code" + exit $return_code fi -az --version >stdout.az 2>&1 -az=$(grep "azure-cli" stdout.az) -if [ ! -n "${az}" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldreduscore Please install the Azure CLI $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 2 #No such file or directory -fi - -ext=$(echo ${deployer_parameter_file} | cut -d. -f2) - -# Helper variables -if [ "${ext}" == json ]; then - environment=$(jq --raw-output .infrastructure.environment "${deployer_parameter_file}") - region=$(jq --raw-output .infrastructure.region "${deployer_parameter_file}") -else - load_config_vars "${root_dirname}"/"${deployer_parameter_file}" "environment" - load_config_vars "${root_dirname}"/"${deployer_parameter_file}" "location" - region=$(echo ${location} | xargs) - -fi - -if [ ! -n "${environment}" ]; then - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Incorrect parameter file. $resetformatting #" - echo "# #" - echo "# The file must contain the environment attribute!! #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 64 #script usage wrong -fi - -if [ ! -n "${region}" ]; then - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Incorrect parameter file. $resetformatting #" - echo "# #" - echo "# The file must contain the region/location attribute!! #" - echo "# #" - echo "#########################################################################################" - echo "" - exit 64 #script usage wrong +# Check that parameter files have environment and location defined +validate_key_parameters "$deployer_parameter_file" +if [ 0 != $return_code ]; then + exit $return_code fi # Convert the region to the correct code -get_region_code $region +get_region_code "$region" + +echo "Region code for deployment: $region_code" automation_config_directory=~/.sap_deployment_automation generic_config_information="${automation_config_directory}"/config deployer_config_information="${automation_config_directory}"/"${environment}""${region_code}" -#Plugins -if [ ! -d "$HOME/.terraform.d/plugin-cache" ]; then - mkdir -p "$HOME/.terraform.d/plugin-cache" -fi -export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" if [ $force == 1 ]; then if [ -f "${deployer_config_information}" ]; then @@ -244,49 +119,15 @@ fi init "${automation_config_directory}" "${generic_config_information}" "${deployer_config_information}" -if [ ! -z "${subscription}" ]; then +if [ -n "${subscription}" ]; then ARM_SUBSCRIPTION_ID="${subscription}" export ARM_SUBSCRIPTION_ID=$subscription fi - -if [ ! -n "$DEPLOYMENT_REPO_PATH" ]; then - echo "" - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Missing environment variables (DEPLOYMENT_REPO_PATH)!!! $resetformatting #" - echo "# #" - echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" - echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" - echo "# #" - echo "#########################################################################################" - exit 65 #data format error -fi - -templen=$(echo "${ARM_SUBSCRIPTION_ID}" | wc -c) -# Subscription length is 37 -if [ 37 != $templen ]; then - arm_config_stored=0 -fi - -if [ ! -n "$ARM_SUBSCRIPTION_ID" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Missing environment variables (ARM_SUBSCRIPTION_ID)!!! $resetformatting #" - echo "# #" - echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" - echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" - echo "# #" - echo "#########################################################################################" - exit 65 #data format error -else - if [ "${arm_config_stored}" != 0 ]; then - echo "Storing the configuration" - save_config_var "ARM_SUBSCRIPTION_ID" "${deployer_config_information}" - fi +# Check that the exports ARM_SUBSCRIPTION_ID and DEPLOYMENT_REPO_PATH are defined +validate_exports +return_code=$? +if [ 0 != $return_code ]; then + exit $return_code fi deployer_dirname=$(dirname "${deployer_parameter_file}") @@ -297,60 +138,41 @@ library_file_parametername=$(basename "${library_parameter_file}") relative_path="${root_dirname}"/"${deployer_dirname}" export TF_DATA_DIR="${relative_path}"/.terraform -# Checking for valid az session - -if [ ! -d "$HOME/.terraform.d/plugin-cache" ] -then - mkdir -p "$HOME/.terraform.d/plugin-cache" -fi -export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" - -temp=$(grep "az login" stdout.az) -if [ -n "${temp}" ]; then - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $boldred Please login using az login! $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - if [ -f stdout.az ]; then - rm stdout.az - fi - exit 67 #addressee unknown -else - if [ -f stdout.az ]; then - rm stdout.az - fi - - if [ ! -z "${subscription}" ]; then - echo "Setting the subscription" - az account set --sub "${subscription}" - export ARM_SUBSCRIPTION_ID="${subscription}" - fi - -fi step=0 +echo "#########################################################################################" +echo "# #" +echo -e "# $cyan Starting the control plane deployment $resetformatting #" +echo "# #" +echo "#########################################################################################" -cloudIDUsed=$(az account show | grep "cloudShellID") -if [ ! -z "${cloudIDUsed}" ]; -then +#setting the user environment variables +if [ -n "${subscription}" ]; then + if is_valid_guid "$subscription"; then + echo "" + else + printf -v val %-40.40s "$subscription" + echo "#########################################################################################" + echo "# #" + echo -e "# The provided subscription is not valid:$boldred ${val} $resetformatting# " + echo "# #" + echo "#########################################################################################" + exit 65 + fi echo "" echo "#########################################################################################" echo "# #" - echo -e "# $boldred Please login using your credentials or service principal credentials! $resetformatting #" + echo -e "# $cyan Changing the subscription to: $subscription $resetformatting #" echo "# #" echo "#########################################################################################" echo "" - exit 67 #addressee unknown + az account set --sub "${subscription}" + export ARM_SUBSCRIPTION_ID="${subscription}" fi -#setting the user environment variables - if [ 3 == $step ]; then - spn_secret="none" + spn_secret="none" fi set_executing_user_environment_variables "${spn_secret}" @@ -379,41 +201,40 @@ if [ 0 == $step ]; then echo "#########################################################################################" echo "" - allParams=$(printf " -p %s %s" "${deployer_file_parametername}" "${approveparam}") + allParams=$(printf " --parameterfile %s %s" "${deployer_file_parametername}" "${approveparam}") + + echo $allParams cd "${deployer_dirname}" || exit - + if [ $force == 1 ]; then rm -Rf .terraform terraform.tfstate* fi - + "${DEPLOYMENT_REPO_PATH}"/deploy/scripts/install_deployer.sh $allParams - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 != $return_code ]; then + exit $return_code fi - + #Persist the parameters - if [ ! -z "$subscription" ]; then + if [ -n "$subscription" ]; then save_config_var "subscription" "${deployer_config_information}" - kvsubscription=$subscription - save_config_var "kvsubscription" "${deployer_config_information}" + export STATE_SUBSCRIPTION=$subscription + save_config_var "STATE_SUBSCRIPTION" "${deployer_config_information}" fi - if [ ! -z "$client_id" ]; then + if [ -n "$client_id" ]; then save_config_var "client_id" "${deployer_config_information}" fi - if [ ! -z "$tenant_id" ]; then + if [ -n "$tenant_id" ]; then save_config_var "tenant_id" "${deployer_config_information}" fi - if [ $force == 1 ]; then - rm -Rf .terraform terraform.tfstate* - fi - - step=1 + export step=1 save_config_var "step" "${deployer_config_information}" - + cd "$root_dirname" || exit echo "#########################################################################################" @@ -423,57 +244,59 @@ if [ 0 == $step ]; then echo "#########################################################################################" echo "" - ssh_timeout_s=10 - load_config_vars "${deployer_config_information}" "sshsecret" load_config_vars "${deployer_config_information}" "keyvault" load_config_vars "${deployer_config_information}" "deployer_public_ip_address" - - if [ "$this_ip" != "$deployer_public_ip_address" ] ; then - # Only run this when not on deployer - if [ ! -z ${sshsecret} ] - then - echo "#########################################################################################" - echo "# #" - echo -e "# $cyan Collecting secrets from KV $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - - temp_file=$(mktemp) - ppk=$(az keyvault secret show --vault-name "${keyvault}" --name "${sshsecret}" | jq -r .value) - echo "${ppk}" > "${temp_file}" - chmod 600 "${temp_file}" - - remote_deployer_dir="$HOME/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$deployer_parameter_file") - remote_library_dir="$HOME/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$library_parameter_file") - remote_config_dir="$HOME/.sap_deployment_automation" - - ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_deployer_dir}"/.terraform - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$deployer_parameter_file" azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/. - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/.terraform/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/.terraform/terraform.tfstate - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/terraform.tfstate - - ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" " mkdir -p ${remote_library_dir}"/.terraform - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$library_parameter_file" azureadm@"${deployer_public_ip_address}":"$remote_library_dir"/. - - ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_config_dir}" - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "${deployer_config_information}" azureadm@"${deployer_public_ip_address}":"${remote_config_dir}"/. - - rm "${temp_file}" + + if [ -n "${deployer_public_ip_address}" ]; then + if [ "$this_ip" != "$deployer_public_ip_address" ]; then + # Only run this when not on deployer + if [ -n "${sshsecret}" ] + then + echo "#########################################################################################" + echo "# #" + echo -e "# $cyan Collecting secrets from KV $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + + temp_file=$(mktemp) + ppk=$(az keyvault secret show --vault-name "${keyvault}" --name "${sshsecret}" | jq -r .value) + echo "${ppk}" > "${temp_file}" + chmod 600 "${temp_file}" + + remote_deployer_dir="$HOME/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$deployer_parameter_file") + remote_library_dir="$HOME/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$library_parameter_file") + remote_config_dir="$HOME/.sap_deployment_automation" + + ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_deployer_dir}"/.terraform 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$deployer_parameter_file" azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/. 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/.terraform/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/.terraform/terraform.tfstate 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/terraform.tfstate 2> /dev/null + + ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" " mkdir -p ${remote_library_dir}"/.terraform 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$library_parameter_file" azureadm@"${deployer_public_ip_address}":"$remote_library_dir"/. 2> /dev/null + + ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_config_dir}" 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 "${deployer_config_information}" azureadm@"${deployer_public_ip_address}":"${remote_config_dir}"/. 2> /dev/null + + rm "${temp_file}" + fi fi + + else + echo "" + echo "#########################################################################################" + echo "# #" + echo -e "# $cyan Deployer is bootstrapped $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" fi - -else - echo "" - echo "#########################################################################################" - echo "# #" - echo -e "# $cyan Deployer is bootstrapped $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" fi +cd "$root_dirname" || exit + if [ 1 = "${only_deployer:-}" ]; then load_config_vars "${deployer_config_information}" deployer_public_ip_address echo "" @@ -485,7 +308,7 @@ if [ 1 = "${only_deployer:-}" ]; then printf -v secretname4 '%-40s' "${environment}"-tenant-id printf -v deployerpara '%-40s' "-d ${deployer_parameter_file}" printf -v librarypara '%-40s' "-l ${library_parameter_file}" - + echo "" echo "#########################################################################################" echo "# #" @@ -504,7 +327,7 @@ if [ 1 = "${only_deployer:-}" ]; then echo "# #" echo "#########################################################################################" echo "" - + step=6 save_config_var "step" "${deployer_config_information}" exit 0 @@ -519,43 +342,46 @@ if [ 1 == $step ]; then echo "# #" echo "#########################################################################################" echo "" - - if [ ! -n "$keyvault" ]; then + + if [ -z "$keyvault" ]; then read -r -p "Deployer keyvault name: " keyvault fi access_error=$(az keyvault secret list --vault "$keyvault" --only-show-errors | grep "The user, group or application") - if [ ! -n "${access_error}" ]; then + if [ -z "${access_error}" ]; then save_config_var "client_id" "${deployer_config_information}" save_config_var "tenant_id" "${deployer_config_information}" - + if [ -n "$spn_secret" ]; then allParams=$(printf " -e %s -r %s -v %s --spn_secret %s " "${environment}" "${region_code}" "${keyvault}" "${spn_secret}") "${DEPLOYMENT_REPO_PATH}"/deploy/scripts/set_secrets.sh $allParams - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 != $return_code ]; then + exit $return_code fi else read -p "Do you want to specify the SPN Details Y/N?" ans answer=${ans^^} if [ "$answer" == 'Y' ]; then allParams=$(printf " -e %s -r %s -v %s " "${environment}" "${region_code}" "${keyvault}" ) - + #$allParams as an array (); array math can be done in shell, allowing dynamic parameter lists to be created #"${allParams[@]}" - quotes all elements of the array - + "${DEPLOYMENT_REPO_PATH}"/deploy/scripts/set_secrets.sh $allParams - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 == $return_code ]; then + exit $return_code fi fi fi if [ -f post_deployment.sh ]; then ./post_deployment.sh - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 != $return_code ]; then + exit $return_code fi fi cd "${curdir}" || exit @@ -570,7 +396,7 @@ if [ 1 == $step ]; then echo "# #" echo "#########################################################################################" exit 65 - + fi fi unset TF_DATA_DIR @@ -599,11 +425,13 @@ if [ 2 == $step ]; then allParams=$(printf " -p %s -d %s %s" "${library_file_parametername}" "${relative_path}" "${approveparam}") "${DEPLOYMENT_REPO_PATH}"/deploy/scripts/install_library.sh $allParams - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 != $return_code ]; then + exit $return_code fi + cd "${curdir}" || exit - step=3 + export step=3 save_config_var "step" "${deployer_config_information}" else echo "" @@ -636,14 +464,16 @@ if [ 3 == $step ]; then if [ -f post_deployment.sh ]; then rm post_deployment.sh fi - allParams=$(printf " --parameterfile %s --storageaccountname %s --type sap_deployer %s" "${deployer_file_parametername}" "${REMOTE_STATE_SA}" "${approveparam}") + allParams=$(printf " --parameterfile %s --storageaccountname %s --type sap_deployer %s %s " "${deployer_file_parametername}" "${REMOTE_STATE_SA}" "${approveparam}" "${ado_flag}" ) "${DEPLOYMENT_REPO_PATH}"/deploy/scripts/installer.sh $allParams - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 != $return_code ]; then + exit $return_code fi + cd "${curdir}" || exit - step=4 + export step=4 save_config_var "step" "${deployer_config_information}" fi @@ -656,7 +486,7 @@ load_config_vars "${deployer_config_information}" "REMOTE_STATE_SA" if [ 4 == $step ]; then echo "" - + echo "#########################################################################################" echo "# #" echo -e "# $cyan Migrating the library state $resetformatting #" @@ -665,15 +495,16 @@ if [ 4 == $step ]; then echo "" cd "${library_dirname}" || exit - allParams=$(printf " --parameterfile %s --storageaccountname %s --type sap_library %s" "${library_file_parametername}" "${REMOTE_STATE_SA}" "${approveparam}") + allParams=$(printf " --parameterfile %s --storageaccountname %s --type sap_library %s %s" "${library_file_parametername}" "${REMOTE_STATE_SA}" "${approveparam}" "${ado_flag}") "${DEPLOYMENT_REPO_PATH}"/deploy/scripts/installer.sh $allParams - if (($? > 0)); then - exit $? + return_code=$? + if [ 0 != $return_code ]; then + exit $return_code fi - + cd "$root_dirname" || exit - + step=5 save_config_var "step" "${deployer_config_information}" fi @@ -685,20 +516,45 @@ echo "" echo "#########################################################################################" echo "# #" echo -e "# $cyan Please save these values: $resetformatting #" -echo "# - Key Vault: "${kvname}" #" -echo "# - Deployer IP: "${dep_ip}" #" -echo "# - Storage Account: "${REMOTE_STATE_SA}" #" +echo "# - Key Vault: ${kvname} #" +echo "# - Deployer IP: ${dep_ip} #" +echo "# - Storage Account: ${storage_account} #" echo "# #" echo "#########################################################################################" -if [ 5 == $step ]; then - end=`date -u -d "180 days" '+%Y-%m-%dT%H:%MZ'` +now=$(date) +cat < "${deployer_config_information}".md +# Control Plane Deployment # - sas=?$(az storage container generate-sas --permissions r --account-name ${REMOTE_STATE_SA} --name sapbits --https-only --expiry $end -o tsv) +Date : "${now}" - # az keyvault secret set --vault-name "${keyvault}" --name "sapbits-sas-token" --value "${sas}" +## Configuration details ## +| Item | Name | +| ----------------------- | -------------------- | +| Environment | $environment | +| Location | $region | +| Keyvault Name | ${kvname} | +| Deployer IP | ${dep_ip} | +| Terraform state | ${storage_account} | + +EOF + +cat "${deployer_config_information}".md +export deployer_keyvault="${keyvault}" +export deployer_ip="${deployer_public_ip_address}" +export terraform_state_storage_account="${REMOTE_STATE_SA}" + +if [ 5 == $step ]; then + + key=$(az keyvault secret show --vault-name "${keyvault}" --name "sapbits-access-key" | jq -r .value) + end=$(date -u -d "180 days" '+%Y-%m-%dT%H:%MZ') + + sas=$(az storage container generate-sas --permissions rl --account-name ${REMOTE_STATE_SA} --name 'sapbits' --https-only --expiry $end -o tsv --account-key "${key}") + + az keyvault secret set --vault-name "${keyvault}" --name "sapbits-sas-token" --value "?${sas}" + step=6 save_config_var "step" "${deployer_config_information}" fi @@ -706,46 +562,50 @@ fi if [ 6 == $step ]; then cd "${curdir}" || exit - ssh_timeout_s=10 - load_config_vars "${deployer_config_information}" "sshsecret" load_config_vars "${deployer_config_information}" "keyvault" - if [ "$this_ip" != "${dep_ip}" ] ; then + load_config_vars "${deployer_config_information}" "deployer_public_ip_address" + if [ "$this_ip" != "$deployer_public_ip_address" ] ; then # Only run this when not on deployer - echo "#########################################################################################" - echo "# #" - echo -e "# $cyan Copying the parameterfiles $resetformatting #" - echo "# #" - echo "#########################################################################################" - echo "" - - printf "%s\n" "Collecting secrets from KV" - temp_file=$(mktemp) - ppk=$(az keyvault secret show --vault-name "${keyvault}" --name "${sshsecret}" | jq -r .value) - echo "${ppk}" > "${temp_file}" - chmod 600 "${temp_file}" - remote_deployer_dir="/home/azureadm/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$deployer_parameter_file") - remote_library_dir="/home/azureadm/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$library_parameter_file") - remote_config_dir="/home/azureadm/.sap_deployment_automation" - - ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_deployer_dir}"/.terraform - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$deployer_parameter_file" azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/. - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/.terraform/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/.terraform/terraform.tfstate - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/terraform.tfstate - - ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" " mkdir -p ${remote_library_dir}"/.terraform - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$(dirname "$deployer_parameter_file")"/.terraform/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/. - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "$library_parameter_file" azureadm@"${deployer_public_ip_address}":"$remote_library_dir"/. - - ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_config_dir}" - scp -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=120 "${deployer_config_information}" azureadm@"${deployer_public_ip_address}":"${remote_config_dir}"/. - - rm "${temp_file}" + echo "#########################################################################################" + echo "# #" + echo -e "# $cyan Copying the parameterfiles $resetformatting #" + echo "# #" + echo "#########################################################################################" + echo "" + + if [ -n "${sshsecret}" ]; then + step=3 + save_config_var "step" "${deployer_config_information}" + printf "%s\n" "Collecting secrets from KV" + temp_file=$(mktemp) + ppk=$(az keyvault secret show --vault-name "${keyvault}" --name "${sshsecret}" | jq -r .value) + echo "${ppk}" > "${temp_file}" + chmod 600 "${temp_file}" + + remote_deployer_dir="/home/azureadm/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$deployer_parameter_file") + remote_library_dir="/home/azureadm/Azure_SAP_Automated_Deployment/WORKSPACES/"$(dirname "$library_parameter_file") + remote_config_dir="/home/azureadm/.sap_deployment_automation" + + ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_deployer_dir}"/.terraform 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 -p "$deployer_parameter_file" azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/. 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 -p "$(dirname "$deployer_parameter_file")"/.terraform/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/.terraform/terraform.tfstate 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 -p "$(dirname "$deployer_parameter_file")"/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/terraform.tfstate 2> /dev/null + + ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" " mkdir -p ${remote_library_dir}"/.terraform 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 -p "$(dirname "$deployer_parameter_file")"/.terraform/terraform.tfstate azureadm@"${deployer_public_ip_address}":"${remote_deployer_dir}"/. 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 -p "$library_parameter_file" azureadm@"${deployer_public_ip_address}":"$remote_library_dir"/. 2> /dev/null + + ssh -i "${temp_file}" -o StrictHostKeyChecking=no -o ConnectTimeout=10 azureadm@"${deployer_public_ip_address}" "mkdir -p ${remote_config_dir}" 2> /dev/null + scp -i "${temp_file}" -q -o StrictHostKeyChecking=no -o ConnectTimeout=120 -p "${deployer_config_information}" azureadm@"${deployer_public_ip_address}":"${remote_config_dir}"/. 2> /dev/null + rm "${temp_file}" + fi fi - step=3 - save_config_var "step" ${deployer_config_information} fi +step=3 +save_config_var "step" ${deployer_config_information} + unset TF_DATA_DIR exit 0 diff --git a/deploy/scripts/remove_region.sh b/deploy/scripts/remove_region.sh index e4771ba528..1558648848 100755 --- a/deploy/scripts/remove_region.sh +++ b/deploy/scripts/remove_region.sh @@ -81,7 +81,7 @@ function missing { force=0 -INPUT_ARGUMENTS=$(getopt -n remove_region -o d:l:s:b:r:h --longoptions deployer_parameter_file:,library_parameter_file:,subscription:,resource_group:,storage_account:,help -- "$@") +INPUT_ARGUMENTS=$(getopt -n remove_region -o d:l:s:b:r:iha --longoptions deployer_parameter_file:,library_parameter_file:,subscription:,resource_group:,storage_account,auto-approve,ado,help -- "$@") VALID_ARGUMENTS=$? if [ "$VALID_ARGUMENTS" != "0" ]; then @@ -97,15 +97,17 @@ do -s | --subscription) subscription="$2" ; shift 2 ;; -b | --storage_account) storage_account="$2" ; shift 2 ;; -r | --resource_group) resource_group="$2" ; shift 2 ;; + -a | --ado) ado=1 ; shift ;; + -i | --auto-approve) approve="--auto-approve" ; shift ;; -h | --help) showhelp exit 3 ; shift ;; --) shift; break ;; esac done - -if [ ! -z "$approve" ]; then - approveparam=" -i" +approveparam="" +if [ 1 == ado ]; then + approveparam=" --auto-approve" fi if [ -z "$deployer_parameter_file" ]; then @@ -223,7 +225,7 @@ if [ ! -n "$DEPLOYMENT_REPO_PATH" ]; then echo "# Missing environment variables (DEPLOYMENT_REPO_PATH)!!! #" echo "# #" echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" echo "# #" echo "#########################################################################################" @@ -288,7 +290,7 @@ then echo "" echo "#########################################################################################" echo "# #" - echo -e "# $boldred Please login using your credentials or service principal credentials! $resetformatting #" + echo "# Please login using your credentials or service principal credentials! #" echo "# #" echo "#########################################################################################" echo "" @@ -299,7 +301,7 @@ fi curdir=$(pwd) #we know that we have a valid az session so let us set the environment variables -set_executing_user_environment_variables +set_executing_user_environment_variables "none" # Deployer @@ -321,11 +323,7 @@ if [ -z "${storage_account}" ]; then if [ ! -z "${STATE_SUBSCRIPTION}" ] then subscription="${STATE_SUBSCRIPTION}" - if [ $account_set==0 ] - then - $(az account set --sub "${STATE_SUBSCRIPTION}") - account_set=1 - fi + $(az account set --sub "${STATE_SUBSCRIPTION}") fi @@ -405,7 +403,6 @@ then echo "#########################################################################################" echo "" - terraform -chdir="${terraform_module_directory}" init -upgrade=true -reconfigure \ --backend-config "subscription_id=${subscription}" \ --backend-config "resource_group_name=${resource_group}" \ @@ -435,9 +432,7 @@ fi var_file="${param_dirname}"/"${library_file_parametername}" -allParams=$(printf " -var-file=%s -var deployer_statefile_foldername=%s %s" "${var_file}" "${relative_path}" "${extra_vars}" ) - -echo $allParams +allParams=$(printf " -var-file=%s -var deployer_statefile_foldername=%s %s %s " "${var_file}" "${relative_path}" "${extra_vars}" "${approveparam}" ) echo "" echo "#########################################################################################" @@ -447,7 +442,13 @@ echo "# echo "#########################################################################################" echo "" -terraform -chdir="${terraform_module_directory}" destroy $allParams +terraform -chdir="${terraform_module_directory}" destroy $allParams +return_value=$? + +if [ 0 != $return_value ] +then + exit $return_value +fi cd "${curdir}" || exit @@ -465,7 +466,7 @@ if [ -f terraform.tfvars ]; then fi var_file="${param_dirname}"/"${deployer_file_parametername}" -allParams=$(printf " -var-file=%s %s" "${var_file}" "${extra_vars}" ) +allParams=$(printf " -var-file=%s %s %s " "${var_file}" "${extra_vars}" "${approveparam}" ) echo "" echo "#########################################################################################" @@ -476,10 +477,10 @@ echo "########################################################################## echo "" terraform -chdir="${terraform_module_directory}" destroy $allParams +return_value=$? cd "${curdir}" || exit - unset TF_DATA_DIR step=0 @@ -487,4 +488,4 @@ save_config_var "step" "${deployer_config_information}" rm "${deployer_config_information}" -exit 0 +exit $return_value diff --git a/deploy/scripts/remover.sh b/deploy/scripts/remover.sh index 33a5a26ee7..6d203806a0 100755 --- a/deploy/scripts/remover.sh +++ b/deploy/scripts/remover.sh @@ -20,12 +20,13 @@ function showhelp { echo "" echo "#########################################################################################" + echo "# #" echo -e "# $boldreduscore !Warning!: This script will remove deployed systems $resetformatting #" echo "# #" echo "# This file contains the logic to remove the different systems #" echo "# The script expects the following exports: #" echo "# #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" echo "# REMOTE_STATE_RG (resource group name for storage account containing state files) #" echo "# REMOTE_STATE_SA (storage account for state file) #" @@ -35,8 +36,8 @@ function showhelp { echo "# #" echo "# #" echo "# Usage: remover.sh #" - echo "# -p or --parameterfile parameter file #" - echo "# -t or --type type of system to remove #" + echo "# -p or --parameterfile parameter file #" + echo "# -t or --type type of system to remove #" echo "# valid options: #" echo "# sap_deployer #" echo "# sap_library #" @@ -44,6 +45,11 @@ function showhelp { echo "# sap_system #" echo "# -h or --help Show help #" echo "# #" + echo "# Optional parameters #" + echo "# #" + echo "# -o or --storageaccountname Storage account name for state file #" + echo "# -s or --state_subscription Subscription for tfstate storage account #" + echo "# #" echo "# Example: #" echo "# #" echo "# [REPO-ROOT]deploy/scripts/remover.sh \ #" @@ -62,14 +68,14 @@ function missing { echo "# Missing environment variables: ${option}!!! #" echo "# #" echo "# Please export the folloing variables: #" - echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" + echo "# DEPLOYMENT_REPO_PATH (path to the repo folder (sap-automation)) #" echo "# ARM_SUBSCRIPTION_ID (subscription containing the state file storage account) #" echo "# #" echo "#########################################################################################" } #process inputs - may need to check the option i for auto approve as it is not used -INPUT_ARGUMENTS=$(getopt -n validate -o p:t:hi --longoptions type:,parameterfile:,auto-approve,help -- "$@") +INPUT_ARGUMENTS=$(getopt -n remover -o p:o:t:s:hi --longoptions type:,parameterfile:,storageaccountname:,state_subscription:,auto-approve,help -- "$@") VALID_ARGUMENTS=$? if [ "$VALID_ARGUMENTS" != "0" ]; then @@ -81,6 +87,8 @@ while : do case "$1" in -p | --parameterfile) parameterfile="$2" ; shift 2 ;; + -o | --storageaccountname) REMOTE_STATE_SA="$2" ; shift 2 ;; + -s | --state_subscription) STATE_SUBSCRIPTION="$2" ; shift 2 ;; -t | --type) deployment_system="$2" ; shift 2 ;; -i | --auto-approve) approve="--auto-approve" ; shift ;; -h | --help) showhelp @@ -198,13 +206,22 @@ export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" init "${automation_config_directory}" "${generic_config_information}" "${system_config_information}" var_file="${parameterfile_dirname}"/"${parameterfile}" +if [ -z "$REMOTE_STATE_SA" ]; +then + load_config_vars "${system_config_information}" "REMOTE_STATE_SA" + load_config_vars "${system_config_information}" "REMOTE_STATE_RG" + load_config_vars "${system_config_information}" "tfstate_resource_id" + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" +else + save_config_vars "${system_config_information}" REMOTE_STATE_SA + get_and_store_sa_details ${REMOTE_STATE_SA} "${system_config_information}" + load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" + load_config_vars "${system_config_information}" "REMOTE_STATE_RG" + load_config_vars "${system_config_information}" "tfstate_resource_id" +fi -load_config_vars "${system_config_information}" "REMOTE_STATE_SA" -load_config_vars "${system_config_information}" "REMOTE_STATE_RG" -load_config_vars "${system_config_information}" "tfstate_resource_id" load_config_vars "${system_config_information}" "deployer_tfstate_key" load_config_vars "${system_config_information}" "landscape_tfstate_key" -load_config_vars "${system_config_information}" "STATE_SUBSCRIPTION" load_config_vars "${system_config_information}" "ARM_SUBSCRIPTION_ID" deployer_tfstate_key_parameter='' @@ -353,7 +370,7 @@ elif [ "$deployment_system" == "sap_library" ]; then $landscape_tfstate_key_parameter \ $deployer_tfstate_key_parameter - terraform -chdir="${terraform_bootstrap_directory}" destroy -var-file="${var_file}" \ + terraform -chdir="${terraform_bootstrap_directory}" destroy -var-file="${var_file}" ${approve} \ $landscape_tfstate_key_parameter \ $deployer_tfstate_key_parameter else @@ -363,7 +380,7 @@ else $deployer_tfstate_key_parameter echo -e "#$cyan processing $deployment_system removal as defined in $parameterfile_name $resetformatting" - terraform -chdir="${terraform_module_directory}" destroy -var-file="${var_file}" \ + terraform -chdir="${terraform_module_directory}" destroy -var-file="${var_file}" ${approve} \ $tfstate_parameter \ $landscape_tfstate_key_parameter \ $deployer_tfstate_key_parameter diff --git a/deploy/scripts/set_secrets.sh b/deploy/scripts/set_secrets.sh index ad3da56341..204cb02962 100755 --- a/deploy/scripts/set_secrets.sh +++ b/deploy/scripts/set_secrets.sh @@ -121,11 +121,11 @@ fi # exit 65 #/* data format error */ # fi -if ! valid_region_code "${region_code}"; then - echo "The 'region' must be a non-empty string composed of 4 uppercase letters!" - showhelp - exit 65 #/* data format error */ -fi +# if ! valid_region_code "${region_code}"; then +# echo "The 'region' must be a non-empty string composed of 4 uppercase letters!" +# showhelp +# exit 65 #/* data format error */ +# fi automation_config_directory=~/.sap_deployment_automation environment_config_information="${automation_config_directory}"/"${environment}""${region_code}" @@ -148,16 +148,40 @@ fi if [ -z "$keyvault" ]; then load_config_vars "${environment_config_information}" "keyvault" - if [ ! -n "$keyvault" ]; then + if [ -z "$keyvault" ]; then read -r -p "Keyvault name: " keyvault fi + if valid_kv_name "$keyvault" ; then + echo "Valid keyvault name format specified" + else + printf -v val %-40.40s "$keyvault" + echo "#########################################################################################" + echo "# #" + echo -e "# The provided keyvault is not valid:$boldred ${val} $resetformatting #" + echo "# #" + echo "#########################################################################################" + exit 65 + fi + fi -if [ -z "$client_id" ]; then +if [ -z "${client_id}" ]; then load_config_vars "${environment_config_information}" "client_id" if [ -z "$client_id" ]; then read -r -p "SPN App ID: " client_id fi +else + if is_valid_guid "${client_id}" ; then + echo "Valid client_id specified" + else + printf -v val %-40.40s "$client_id" + echo "#########################################################################################" + echo "# #" + echo -e "# The provided client_id is not valid:$boldred ${val} $resetformatting #" + echo "# #" + echo "#########################################################################################" + exit 65 + fi fi if [ ! -n "$client_secret" ]; then @@ -171,10 +195,34 @@ if [ -z "${tenant_id}" ]; then if [ ! -n "${tenant_id}" ]; then read -r -p "SPN Tenant ID: " tenant_id fi +else + if is_valid_guid "${tenant_id}" ; then + echo "Valid tenant_id specified" + else + printf -v val %-40.40s "$tenant_id" + echo "#########################################################################################" + echo "# #" + echo -e "# The provided tenant_id is not valid:$boldred ${val} $resetformatting #" + echo "# #" + echo "#########################################################################################" + exit 65 + fi fi -if [ -z "$subscription" ]; then +if [ -z "${subscription}" ]; then read -r -p "SPN Subscription: " subscription +else + if is_valid_guid "${subscription}" ; then + echo "Valid subscription specified" + else + printf -v val %-40.40s "$subscription" + echo "#########################################################################################" + echo "# #" + echo -e "# The provided subscription is not valid:$boldred ${val} $resetformatting #" + echo "# #" + echo "#########################################################################################" + exit 65 + fi fi if [ -z "${keyvault}" ]; then diff --git a/deploy/scripts/setup_ado.sh b/deploy/scripts/setup_ado.sh index 67bebcf93f..fadc9dd7cc 100755 --- a/deploy/scripts/setup_ado.sh +++ b/deploy/scripts/setup_ado.sh @@ -1,91 +1,14 @@ #!/bin/bash -function SetupAuthentication { - if [ ! -n "${ORGANIZATION1}" ] ;then +# https://github.com/Microsoft/azure-pipelines-agent/releases - read -p "Please provide the Azure DevOps ORGANIZATION name? " ORGANIZATION - export ORGANIZATION="${ORGANIZATION}" - echo "ORGANIZATION="${ORGANIZATION}>>/etc/environment - fi + mkdir -p ~/agent; cd $_ - if [ ! -n "${PROJECT1}" ] ;then + wget https://vstsagentpackage.azureedge.net/agent/2.196.1/vsts-agent-linux-x64-2.196.1.tar.gz agent.tar.gz - read -p "Please provide the Azure DevOps PROJECT name? " PROJECT - export PROJECT="${PROJECT}" - echo "PROJECT="${PROJECT}>>/etc/environment - fi + tar zxvf agent.tar.gz - if [ ! -n "${REPONAME1}" ] ;then - - read -p "Please provide the Azure DevOps repo name? " REPONAME - export REPONAME="${REPONAME}" - echo "REPONAME="${REPONAME}>>/etc/environment - fi - - - if [ ! -n "${PAT1}" ] ;then - - read -p "Please provide your Azure DevOps PAT? " PAT - export PAT="${PAT}" - B64_PAT=$(printf "%s"":$PAT" | base64) - export B64_PAT="${B64_PAT}" - echo "B64_PAT="${B64_PAT}>>/etc/environment - echo "PAT="${PAT}>>/etc/environment - fi - -} - -read -p "Register the environment variables? Y/N " ans -answer=${ans^^} -if [ $answer == 'Y' ]; then - SetupAuthentication -fi - - -read -p "Clone the repo? Y/N " ans -answer=${ans^^} -if [ $answer == 'Y' ]; then - - echo "Cloning the repo" - - DIRECTORY="WORKSPACES" - - cd /home/azureadm/Azure_SAP_Automated_Deployment || exit - - - if [[ -d "$DIRECTORY" ]]; then - echo "$DIRECTORY exists on your filesystem." - - mv $DIRECTORY ${DIRECTORY}2 - - git -c http.extraHeader="Authorization: Basic ${B64_PAT}" clone https://dev.azure.com/$ORGANIZATION/$PROJECT/_git/$REPONAME $DIRECTORY - - cp -r ${DIRECTORY}2 $DIRECTORY - - rm -r ${DIRECTORY}2 - - fi - -fi - - -read -p "Make the VM the Azure DevOps agent? Y/N " ans -answer=${ans^^} -if [ $answer == 'Y' ]; then - - mkdir -p /home/azureadm/agent; cd $_ - - wget https://vstsagentpackage.azureedge.net/agent/2.190.0/vsts-agent-linux-x64-2.190.0.tar.gz - - tar zxvf vsts-agent-linux-x64-2.190.0.tar.gz - - ./config.sh -fi - -read -p "Start the agent agent? Y/N " ans -answer=${ans^^} -if [ $answer == 'Y' ]; then + ./config.sh sudo ./svc.sh install azureadm sudo ./svc.sh start -fi diff --git a/deploy/scripts/update_sas_token.sh b/deploy/scripts/update_sas_token.sh index 87efd073bb..df97fcde99 100755 --- a/deploy/scripts/update_sas_token.sh +++ b/deploy/scripts/update_sas_token.sh @@ -1,10 +1,17 @@ # This is the SAP library’s storage account for sap binaries if [ ! -n "${SAP_LIBRARY_TF}" ] ;then - read -p "Please provide the saplib state storage account from SAP_LIBRARY? " saplib + read -p "Please provide the saplib storage account name (SAP_LIBRARY)? " saplib else saplib="${SAP_LIBRARY_TF}" fi +if [ ! -n "${AZURE_STORAGE_KEY}" ] ;then + read -p "Please provide the saplib storage account account key (SAP_LIBRARY)? " key +else + key="${AZURE_STORAGE_KEY}" +fi + + # This is the deployer keyvault if [ ! -n "${SAP_KV_TF}" ] ;then read -p "Please provide the Deployer keyvault name? " kv_name @@ -12,8 +19,9 @@ else kv_name="${SAP_KV_TF}" fi + end=`date -u -d "90 days" '+%Y-%m-%dT%H:%MZ'` -sas=?$(az storage container generate-sas --permissions r --account-name $saplib --name sapbits --https-only --expiry $end -o tsv) +sas=?$(az storage container generate-sas --permissions r --account-name $saplib --name sapbits --https-only --expiry $end -o tsv --account-key "${key}") az keyvault secret set --vault-name $kv_name --name "sapbits-sas-token" --value "${sas}" diff --git a/deploy/terraform/bootstrap/sap_deployer/output.tf b/deploy/terraform/bootstrap/sap_deployer/output.tf index 63f182e580..a53b09a283 100644 --- a/deploy/terraform/bootstrap/sap_deployer/output.tf +++ b/deploy/terraform/bootstrap/sap_deployer/output.tf @@ -10,7 +10,7 @@ output "deployer_id" { } output "vnet_mgmt_id" { - value = module.sap_deployer.vnet_mgmt.id + value = module.sap_deployer.vnet_mgmt_id } output "subnet_mgmt_id" { diff --git a/deploy/terraform/bootstrap/sap_library/imports.tf b/deploy/terraform/bootstrap/sap_library/imports.tf index 4121de5987..486eca6fac 100644 --- a/deploy/terraform/bootstrap/sap_library/imports.tf +++ b/deploy/terraform/bootstrap/sap_library/imports.tf @@ -12,7 +12,6 @@ data "terraform_remote_state" "deployer" { } data "azurerm_key_vault_secret" "subscription_id" { - count = var.use_deployer ? 1 : 0 provider = azurerm.deployer name = format("%s-subscription-id", upper(local.infrastructure.environment)) key_vault_id = local.spn_key_vault_arm_id diff --git a/deploy/terraform/bootstrap/sap_library/variables_local.tf b/deploy/terraform/bootstrap/sap_library/variables_local.tf index 383775c4a2..907c4e2a7d 100644 --- a/deploy/terraform/bootstrap/sap_library/variables_local.tf +++ b/deploy/terraform/bootstrap/sap_library/variables_local.tf @@ -8,7 +8,7 @@ locals { spn_key_vault_arm_id = coalesce(local.key_vault.kv_spn_id, try(data.terraform_remote_state.deployer[0].outputs.deployer_kv_user_arm_id, "")) spn = { - subscription_id = var.use_deployer ? data.azurerm_key_vault_secret.subscription_id[0].value : null, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, client_id = var.use_deployer ? data.azurerm_key_vault_secret.client_id[0].value : null, client_secret = var.use_deployer ? data.azurerm_key_vault_secret.client_secret[0].value : null, tenant_id = var.use_deployer ? data.azurerm_key_vault_secret.tenant_id[0].value : null @@ -21,7 +21,7 @@ spn = { } account = { - subscription_id = local.spn.subscription_id, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, tenant_id = data.azurerm_client_config.current.tenant_id, object_id = data.azurerm_client_config.current.object_id } diff --git a/deploy/terraform/run/sap_deployer/output.tf b/deploy/terraform/run/sap_deployer/output.tf index 4be090d6a1..bad6715969 100644 --- a/deploy/terraform/run/sap_deployer/output.tf +++ b/deploy/terraform/run/sap_deployer/output.tf @@ -10,7 +10,7 @@ output "deployer_id" { } output "vnet_mgmt_id" { - value = module.sap_deployer.vnet_mgmt.id + value = module.sap_deployer.vnet_mgmt_id } output "subnet_mgmt_id" { diff --git a/deploy/terraform/run/sap_deployer/tfvar_variables.tf b/deploy/terraform/run/sap_deployer/tfvar_variables.tf index 55d9af9966..1182d00fcf 100644 --- a/deploy/terraform/run/sap_deployer/tfvar_variables.tf +++ b/deploy/terraform/run/sap_deployer/tfvar_variables.tf @@ -7,7 +7,6 @@ This block describes the variable for the infrastructure block in the json file variable "environment" { type = string description = "This is the environment name of the deployer" - default = "" } variable "codename" { @@ -17,7 +16,6 @@ variable "codename" { variable "location" { type = string - default = "" } variable "resourcegroup_name" { diff --git a/deploy/terraform/run/sap_landscape/imports.tf b/deploy/terraform/run/sap_landscape/imports.tf index 1e8662c313..50f0541dcf 100644 --- a/deploy/terraform/run/sap_landscape/imports.tf +++ b/deploy/terraform/run/sap_landscape/imports.tf @@ -22,7 +22,6 @@ data "terraform_remote_state" "deployer" { data "azurerm_key_vault_secret" "subscription_id" { provider = azurerm.deployer - count = var.use_spn ? 1 : 0 name = format("%s-subscription-id", local.environment) key_vault_id = local.spn_key_vault_arm_id } diff --git a/deploy/terraform/run/sap_landscape/module.tf b/deploy/terraform/run/sap_landscape/module.tf index 68ba4b7b6f..6ab98aef6e 100644 --- a/deploy/terraform/run/sap_landscape/module.tf +++ b/deploy/terraform/run/sap_landscape/module.tf @@ -16,8 +16,8 @@ module "sap_landscape" { service_principal = var.use_spn ? local.service_principal : local.account key_vault = local.key_vault deployer_tfstate = try(data.terraform_remote_state.deployer[0].outputs, []) - diagnostics_storage_account = var.diagnostics_storage_account - witness_storage_account = var.witness_storage_account + diagnostics_storage_account = local.diagnostics_storage_account + witness_storage_account = local.witness_storage_account use_deployer = length(var.deployer_tfstate_key) > 0 ANF_settings = local.ANF_settings create_spn = local.options.create_fencing_spn diff --git a/deploy/terraform/run/sap_landscape/output.tf b/deploy/terraform/run/sap_landscape/output.tf index 597c905027..507f00dc51 100644 --- a/deploy/terraform/run/sap_landscape/output.tf +++ b/deploy/terraform/run/sap_landscape/output.tf @@ -1,5 +1,5 @@ output "vnet_sap_arm_id" { - value = try(module.sap_landscape.vnet_sap[0].id, "") + value = module.sap_landscape.vnet_sap_id } output "landscape_key_vault_user_arm_id" { @@ -118,7 +118,10 @@ output "dns_resource_group_name" { value = length(var.dns_resource_group_name) > 0 ? var.dns_resource_group_name : local.saplib_resource_group_name } - output "spn_kv_id" { value = local.spn_key_vault_arm_id } + +output "subnet_mgmt_id" { + value = module.sap_landscape.subnet_mgmt_id +} \ No newline at end of file diff --git a/deploy/terraform/run/sap_landscape/variables_local.tf b/deploy/terraform/run/sap_landscape/variables_local.tf index 385d396bd6..888350ae25 100644 --- a/deploy/terraform/run/sap_landscape/variables_local.tf +++ b/deploy/terraform/run/sap_landscape/variables_local.tf @@ -80,7 +80,7 @@ locals { spn = { - subscription_id = var.use_spn ? data.azurerm_key_vault_secret.subscription_id[0].value : null, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, client_id = var.use_spn ? data.azurerm_key_vault_secret.client_id[0].value : null, client_secret = var.use_spn ? data.azurerm_key_vault_secret.client_secret[0].value : null, tenant_id = var.use_spn ? data.azurerm_key_vault_secret.tenant_id[0].value : null @@ -93,7 +93,7 @@ locals { } account = { - subscription_id = local.spn.subscription_id, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, tenant_id = data.azurerm_client_config.current.tenant_id, object_id = data.azurerm_client_config.current.object_id } diff --git a/deploy/terraform/run/sap_library/imports.tf b/deploy/terraform/run/sap_library/imports.tf index acc168777a..30ad4ece85 100644 --- a/deploy/terraform/run/sap_library/imports.tf +++ b/deploy/terraform/run/sap_library/imports.tf @@ -16,7 +16,6 @@ data "terraform_remote_state" "deployer" { } data "azurerm_key_vault_secret" "subscription_id" { - count = var.use_deployer ? 1 : 0 provider = azurerm.deployer name = format("%s-subscription-id", upper(local.infrastructure.environment)) key_vault_id = local.spn_key_vault_arm_id diff --git a/deploy/terraform/run/sap_library/variables_local.tf b/deploy/terraform/run/sap_library/variables_local.tf index 86b8723c7d..f1ac67096d 100644 --- a/deploy/terraform/run/sap_library/variables_local.tf +++ b/deploy/terraform/run/sap_library/variables_local.tf @@ -30,7 +30,7 @@ locals { deployer_tfstate_key = length(var.deployer_tfstate_key) > 0 ? var.deployer_tfstate_key : format("%s%s", local.deployer_rg_name, ".terraform.tfstate") spn = { - subscription_id = var.use_deployer ? data.azurerm_key_vault_secret.subscription_id[0].value : null, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, client_id = var.use_deployer ? data.azurerm_key_vault_secret.client_id[0].value : null, client_secret = var.use_deployer ? data.azurerm_key_vault_secret.client_secret[0].value : null, tenant_id = var.use_deployer ? data.azurerm_key_vault_secret.tenant_id[0].value : null @@ -43,7 +43,7 @@ locals { } account = { - subscription_id = local.spn.subscription_id, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, tenant_id = data.azurerm_client_config.current.tenant_id, object_id = data.azurerm_client_config.current.object_id } diff --git a/deploy/terraform/run/sap_system/imports.tf b/deploy/terraform/run/sap_system/imports.tf index 02b9fc5174..f87a47668f 100644 --- a/deploy/terraform/run/sap_system/imports.tf +++ b/deploy/terraform/run/sap_system/imports.tf @@ -33,7 +33,6 @@ data "terraform_remote_state" "landscape" { data "azurerm_key_vault_secret" "subscription_id" { provider = azurerm.deployer - count = var.use_spn ? 1 : 0 name = format("%s-subscription-id", local.environment) key_vault_id = local.spn_key_vault_arm_id } diff --git a/deploy/terraform/run/sap_system/module.tf b/deploy/terraform/run/sap_system/module.tf index 8def429b42..358c39c204 100644 --- a/deploy/terraform/run/sap_system/module.tf +++ b/deploy/terraform/run/sap_system/module.tf @@ -5,27 +5,30 @@ module "sap_namegenerator" { - source = "../../terraform-units/modules/sap_namegenerator" - environment = local.infrastructure.environment - location = local.infrastructure.region - codename = lower(try(local.infrastructure.codename, "")) - random_id = module.common_infrastructure.random_id - sap_vnet_name = local.vnet_logical_name - sap_sid = local.sap_sid - db_sid = local.db_sid - app_ostype = try(local.application.os.os_type, "LINUX") - anchor_ostype = upper(try(local.anchor_vms.os.os_type, "LINUX")) - db_ostype = try(local.databases[0].os.os_type, "LINUX") - db_server_count = var.database_server_count - app_server_count = try(local.application.application_server_count, 0) - web_server_count = try(local.application.webdispatcher_count, 0) - scs_server_count = local.application.scs_high_availability ? 2 * local.application.scs_server_count : local.application.scs_server_count - app_zones = [] - scs_zones = try(local.application.scs_zones, []) - web_zones = try(local.application.web_zones, []) - db_zones = try(local.databases[0].zones, []) - resource_offset = try(var.options.resource_offset, 0) - custom_prefix = var.custom_prefix + source = "../../terraform-units/modules/sap_namegenerator" + environment = local.infrastructure.environment + location = local.infrastructure.region + codename = lower(try(local.infrastructure.codename, "")) + random_id = module.common_infrastructure.random_id + sap_vnet_name = local.vnet_logical_name + sap_sid = local.sap_sid + db_sid = local.db_sid + app_ostype = try(local.application.os.os_type, "LINUX") + anchor_ostype = upper(try(local.anchor_vms.os.os_type, "LINUX")) + db_ostype = try(local.databases[0].os.os_type, "LINUX") + db_server_count = var.database_server_count + app_server_count = try(local.application.application_server_count, 0) + web_server_count = try(local.application.webdispatcher_count, 0) + scs_server_count = local.application.scs_high_availability ? 2 * local.application.scs_server_count : local.application.scs_server_count + app_zones = [] + scs_zones = try(local.application.scs_zones, []) + web_zones = try(local.application.web_zones, []) + db_zones = try(local.databases[0].zones, []) + resource_offset = try(var.options.resource_offset, 0) + custom_prefix = var.custom_prefix + database_high_availability = local.databases[0].high_availability + scs_high_availability = local.application.scs_high_availability + use_zonal_markers = var.use_zonal_markers } module "common_infrastructure" { @@ -53,7 +56,7 @@ module "common_infrastructure" { anf_transport_volume_size = var.anf_transport_volume_size anf_sapmnt_volume_size = var.anf_sapmnt_volume_size use_ANF = var.use_ANF - custom_prefix = var.custom_prefix + custom_prefix = var.use_prefix ? var.custom_prefix : " " } # // Create HANA database nodes @@ -64,8 +67,10 @@ module "hdb_node" { azurerm.deployer = azurerm.deployer } depends_on = [module.common_infrastructure] - order_deployment = local.db_zonal_deployment ? ( - module.app_tier.scs_vm_ids[0] + order_deployment = local.enable_db_deployment ? ( + local.db_zonal_deployment ? ( + module.app_tier.scs_vm_ids[0] + ) : (null) ) : (null) databases = local.databases infrastructure = local.infrastructure @@ -108,11 +113,12 @@ module "app_tier" { azurerm.main = azurerm azurerm.deployer = azurerm.deployer } - order_deployment = local.db_zonal_deployment ? ( - "") : ( - coalesce(try(module.hdb_node.hdb_vms[0], ""), try(module.anydb_node.anydb_vms[0], "")) - ) - + order_deployment = local.enable_db_deployment ? ( + local.db_zonal_deployment ? ( + "") : ( + coalesce(try(module.hdb_node.hdb_vms[0], ""), try(module.anydb_node.anydb_vms[0], "")) + ) + ) : (null) application = local.application infrastructure = local.infrastructure options = local.options @@ -147,8 +153,10 @@ module "anydb_node" { azurerm.deployer = azurerm.deployer } depends_on = [module.common_infrastructure] - order_deployment = local.db_zonal_deployment ? ( - module.app_tier.scs_vm_ids[0] + order_deployment = local.enable_db_deployment ? ( + local.db_zonal_deployment ? ( + module.app_tier.scs_vm_ids[0] + ) : (null) ) : (null) databases = local.databases infrastructure = local.infrastructure @@ -180,6 +188,7 @@ module "anydb_node" { 0) : ( local.databases[0].high_availability ? 2 * var.database_server_count : var.database_server_count ) + use_observer = var.use_observer } # // Generate output files module "output_files" { @@ -229,5 +238,6 @@ module "output_files" { platform = upper(try(local.databases[0].platform, "HANA")) db_auth_type = try(local.databases[0].authentication.type, "key") tfstate_resource_id = var.tfstate_resource_id + install_path = module.common_infrastructure.install_path } diff --git a/deploy/terraform/run/sap_system/tfvar_variables.tf b/deploy/terraform/run/sap_system/tfvar_variables.tf index a2b34524a0..553f8239a0 100644 --- a/deploy/terraform/run/sap_system/tfvar_variables.tf +++ b/deploy/terraform/run/sap_system/tfvar_variables.tf @@ -20,6 +20,10 @@ variable "custom_prefix" { default = "" } +variable "use_prefix" { + default = true +} + variable "location" { type = string @@ -46,15 +50,6 @@ variable "proximityplacementgroup_arm_ids" { default = [] } - - - -/* - -This block describes the variables for the VNet block in the json file - -*/ - variable "network_logical_name" { default = "" } @@ -194,6 +189,11 @@ variable "anchor_vm_nic_ips" { variable "anchor_vm_accelerated_networking" { default = true } + + +variable "use_observer" { + default = true +} /* This block describes the variables for the key_vault section block in the json file */ @@ -388,6 +388,10 @@ variable "application_server_no_avset" { default = false } +variable "application_server_vm_avset_arm_ids" { + default = [] +} + variable "application_server_no_ppg" { default = false } diff --git a/deploy/terraform/run/sap_system/transform.tf b/deploy/terraform/run/sap_system/transform.tf index 7250086242..6392c0e987 100644 --- a/deploy/terraform/run/sap_system/transform.tf +++ b/deploy/terraform/run/sap_system/transform.tf @@ -76,8 +76,8 @@ locals { high_availability = var.database_high_availability || try(var.databases[0].high_availability, false) use_DHCP = var.database_vm_use_DHCP || try(var.databases[0].use_DHCP, false) - platform = try(coalesce(var.database_platform, try(var.databases[0].platform, "HANA")), "") - size = try(coalesce(var.database_size, try(var.databases[0].size, "")), "") + platform = coalesce(var.database_platform, try(var.databases[0].platform, "")) + size = coalesce(var.database_size, try(var.databases[0].size, "")) use_ANF = var.database_HANA_use_ANF_scaleout_scenario || try(var.databases[0].use_ANF, false) dual_nics = var.database_dual_nics || try(var.databases[0].dual_nics, false) @@ -121,6 +121,7 @@ locals { app_sku = try(coalesce(var.application_server_sku, var.application.app_sku), "") app_no_ppg = var.application_server_no_ppg || try(var.application.app_no_ppg, false) app_no_avset = var.application_server_no_avset || try(var.application.app_no_avset, false) + avset_arm_ids = var.application_server_vm_avset_arm_ids scs_server_count = max(var.scs_server_count, try(var.application.scs_server_count, 1)) scs_high_availability = var.scs_high_availability || try(var.application.scs_high_availability, false) diff --git a/deploy/terraform/run/sap_system/variables_local.tf b/deploy/terraform/run/sap_system/variables_local.tf index 823c783fe4..8300aec8a7 100644 --- a/deploy/terraform/run/sap_system/variables_local.tf +++ b/deploy/terraform/run/sap_system/variables_local.tf @@ -64,7 +64,11 @@ variable "terraform_template_version" { variable "license_type" { description = "Specifies the license type for the OS" default = "" +} +variable "use_zonal_markers" { + type = bool + default = true } locals { @@ -98,6 +102,12 @@ locals { anydb_sid = (length(local.anydb-databases) > 0) ? try(local.anydb-databases[0].instance.sid, lower(substr(local.anydb_platform, 0, 3))) : lower(substr(local.anydb_platform, 0, 3)) db_sid = length(local.hana-databases) > 0 ? local.hanadb_sid : local.anydb_sid sap_sid = upper(try(local.application.sid, local.db_sid)) + + enable_db_deployment = ( + length(local.hana-databases) > 0 + || length(local.anydb-databases) > 0 + ) + db_zonal_deployment = length(try(local.databases[0].zones, [])) > 0 // Locate the tfstate storage account @@ -116,7 +126,7 @@ locals { deployer_subscription_id = length(local.spn_key_vault_arm_id) > 0 ? split("/", local.spn_key_vault_arm_id)[2] : "" spn = { - subscription_id = var.use_spn ? data.azurerm_key_vault_secret.subscription_id[0].value : null, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, client_id = var.use_spn ? data.azurerm_key_vault_secret.client_id[0].value : null, client_secret = var.use_spn ? data.azurerm_key_vault_secret.client_secret[0].value : null, tenant_id = var.use_spn ? data.azurerm_key_vault_secret.tenant_id[0].value : null @@ -129,7 +139,7 @@ locals { } account = { - subscription_id = local.spn.subscription_id, + subscription_id = data.azurerm_key_vault_secret.subscription_id.value, tenant_id = data.azurerm_client_config.current.tenant_id, object_id = data.azurerm_client_config.current.object_id } diff --git a/deploy/terraform/terraform-units/modules/sap_deployer/nsg-mgmt.tf b/deploy/terraform/terraform-units/modules/sap_deployer/nsg-mgmt.tf index ea95d7e25f..d222532b8d 100644 --- a/deploy/terraform/terraform-units/modules/sap_deployer/nsg-mgmt.tf +++ b/deploy/terraform/terraform-units/modules/sap_deployer/nsg-mgmt.tf @@ -48,7 +48,7 @@ resource "azurerm_network_security_rule" "nsr_ssh" { source_port_range = "*" destination_port_range = 22 source_address_prefixes = local.sub_mgmt_nsg_allowed_ips - destination_address_prefixes = local.sub_mgmt_deployed.address_prefixes + destination_address_prefixes = local.sub_mgmt_deployed_prefixes } // Add RDP network security rule @@ -68,7 +68,7 @@ resource "azurerm_network_security_rule" "nsr_rdp" { source_port_range = "*" destination_port_range = 3389 source_address_prefixes = local.sub_mgmt_nsg_allowed_ips - destination_address_prefixes = local.sub_mgmt_deployed.address_prefixes + destination_address_prefixes = local.sub_mgmt_deployed_prefixes } // Add WinRM network security rule @@ -88,5 +88,5 @@ resource "azurerm_network_security_rule" "nsr_winrm" { source_port_range = "*" destination_port_ranges = [5985, 5986] source_address_prefixes = local.sub_mgmt_nsg_allowed_ips - destination_address_prefixes = local.sub_mgmt_deployed.address_prefixes + destination_address_prefixes = local.sub_mgmt_deployed_prefixes } diff --git a/deploy/terraform/terraform-units/modules/sap_deployer/output.tf b/deploy/terraform/terraform-units/modules/sap_deployer/output.tf index ec7a70d16e..0695b1d630 100644 --- a/deploy/terraform/terraform-units/modules/sap_deployer/output.tf +++ b/deploy/terraform/terraform-units/modules/sap_deployer/output.tf @@ -15,13 +15,13 @@ output "deployer_id" { } // Details of management vnet that is deployed/imported -output "vnet_mgmt" { - value = local.vnet_mgmt_exists ? data.azurerm_virtual_network.vnet_mgmt[0] : azurerm_virtual_network.vnet_mgmt[0] +output "vnet_mgmt_id" { + value = local.vnet_mgmt_exists ? data.azurerm_virtual_network.vnet_mgmt[0].id : azurerm_virtual_network.vnet_mgmt[0].id } // Details of management subnet that is deployed/imported -output "subnet_mgmt" { - value = local.sub_mgmt_exists ? data.azurerm_subnet.subnet_mgmt[0] : azurerm_subnet.subnet_mgmt[0] +output "subnet_mgmt_id" { + value = local.sub_mgmt_exists ? data.azurerm_subnet.subnet_mgmt[0].id : azurerm_subnet.subnet_mgmt[0].id } // Details of the management vnet NSG that is deployed/imported @@ -96,7 +96,3 @@ output "firewall_ip" { output "firewall_id" { value = var.firewall_deployment ? azurerm_firewall.firewall[0].id : "" } - -output "subnet_mgmt_id" { - value = local.sub_mgmt_exists ? data.azurerm_subnet.subnet_mgmt[0].id : azurerm_subnet.subnet_mgmt[0].id -} diff --git a/deploy/terraform/terraform-units/modules/sap_deployer/templates/configure_deployer.sh.tmpl b/deploy/terraform/terraform-units/modules/sap_deployer/templates/configure_deployer.sh.tmpl index d37d0ff819..b4dd1128af 100644 --- a/deploy/terraform/terraform-units/modules/sap_deployer/templates/configure_deployer.sh.tmpl +++ b/deploy/terraform/terraform-units/modules/sap_deployer/templates/configure_deployer.sh.tmpl @@ -255,6 +255,7 @@ required_pkgs=( lsb-release gnupg sshpass + dos2unix ) cli_pkgs=( @@ -327,6 +328,11 @@ fi curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash > /dev/null +/usr/bin/az extension add --name storage-blob-preview > /dev/null + +# Fail if any command exits with a non-zero exit status +set -o errexit + # Ensure our package metadata cache is up to date pkg_mgr_refresh diff --git a/deploy/terraform/terraform-units/modules/sap_deployer/variables_local.tf b/deploy/terraform/terraform-units/modules/sap_deployer/variables_local.tf index c4c869981c..c941200b26 100644 --- a/deploy/terraform/terraform-units/modules/sap_deployer/variables_local.tf +++ b/deploy/terraform/terraform-units/modules/sap_deployer/variables_local.tf @@ -95,7 +95,7 @@ locals { sub_mgmt_prefix = local.sub_mgmt_exists ? "" : try(local.sub_mgmt.prefix, "") - sub_mgmt_deployed = local.sub_mgmt_exists ? data.azurerm_subnet.subnet_mgmt[0] : azurerm_subnet.subnet_mgmt[0] + sub_mgmt_deployed_prefixes = local.sub_mgmt_exists ? data.azurerm_subnet.subnet_mgmt[0].address_prefixes : azurerm_subnet.subnet_mgmt[0].address_prefixes // Management NSG sub_mgmt_nsg = try(local.sub_mgmt.nsg, {}) diff --git a/deploy/terraform/terraform-units/modules/sap_deployer/vm-deployer.tf b/deploy/terraform/terraform-units/modules/sap_deployer/vm-deployer.tf index 7d0338ac0e..cfac20d22a 100644 --- a/deploy/terraform/terraform-units/modules/sap_deployer/vm-deployer.tf +++ b/deploy/terraform/terraform-units/modules/sap_deployer/vm-deployer.tf @@ -32,7 +32,7 @@ resource "azurerm_network_interface" "deployer" { "") : ( length(var.deployer.private_ip_address) > 0 ? ( var.deployer.private_ip_address) : ( - cidrhost(local.sub_mgmt_deployed.address_prefixes[0], 4) + cidrhost(local.sub_mgmt_deployed_prefixes[0], 4) ) ) private_ip_address_allocation = var.deployer.use_DHCP ? "Dynamic" : "Static" diff --git a/deploy/terraform/terraform-units/modules/sap_landscape/outputs.tf b/deploy/terraform/terraform-units/modules/sap_landscape/outputs.tf index 93925da811..be1362ca7c 100644 --- a/deploy/terraform/terraform-units/modules/sap_landscape/outputs.tf +++ b/deploy/terraform/terraform-units/modules/sap_landscape/outputs.tf @@ -1,9 +1,5 @@ -output "resource_group" { - value = local.rg_exists ? data.azurerm_resource_group.resource_group : azurerm_resource_group.resource_group -} - -output "vnet_sap" { - value = local.vnet_sap_exists ? data.azurerm_virtual_network.vnet_sap : azurerm_virtual_network.vnet_sap +output "vnet_sap_id" { + value = local.vnet_sap_exists ? data.azurerm_virtual_network.vnet_sap[0].id : azurerm_virtual_network.vnet_sap[0].id } output "random_id" { @@ -180,3 +176,7 @@ output "ANF_pool_settings" { use_ANF = false } } + +output "subnet_mgmt_id" { + value = try(var.deployer_tfstate.subnet_mgmt.id, "") +} \ No newline at end of file diff --git a/deploy/terraform/terraform-units/modules/sap_landscape/subnets.tf b/deploy/terraform/terraform-units/modules/sap_landscape/subnets.tf index 41ee94a28b..851f576a87 100644 --- a/deploy/terraform/terraform-units/modules/sap_landscape/subnets.tf +++ b/deploy/terraform/terraform-units/modules/sap_landscape/subnets.tf @@ -21,6 +21,10 @@ resource "azurerm_subnet" "db" { resource_group_name = local.vnet_sap_exists ? data.azurerm_virtual_network.vnet_sap[0].resource_group_name : azurerm_virtual_network.vnet_sap[0].resource_group_name virtual_network_name = local.vnet_sap_exists ? data.azurerm_virtual_network.vnet_sap[0].name : azurerm_virtual_network.vnet_sap[0].name address_prefixes = [local.sub_db_prefix] + + enforce_private_link_endpoint_network_policies = true + enforce_private_link_service_network_policies = false + service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"] } // Creates app subnet of SAP VNET @@ -34,7 +38,7 @@ resource "azurerm_subnet" "app" { enforce_private_link_endpoint_network_policies = true enforce_private_link_service_network_policies = false - service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"] + service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"] } // Creates web subnet of SAP VNET @@ -45,6 +49,10 @@ resource "azurerm_subnet" "web" { resource_group_name = local.vnet_sap_exists ? data.azurerm_virtual_network.vnet_sap[0].resource_group_name : azurerm_virtual_network.vnet_sap[0].resource_group_name virtual_network_name = local.vnet_sap_exists ? data.azurerm_virtual_network.vnet_sap[0].name : azurerm_virtual_network.vnet_sap[0].name address_prefixes = [local.sub_web_prefix] + + enforce_private_link_endpoint_network_policies = true + enforce_private_link_service_network_policies = false + service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"] } // Creates anf subnet of SAP VNET diff --git a/deploy/terraform/terraform-units/modules/sap_library/storage_accounts.tf b/deploy/terraform/terraform-units/modules/sap_library/storage_accounts.tf index 2d15e6e309..b033548b6c 100644 --- a/deploy/terraform/terraform-units/modules/sap_library/storage_accounts.tf +++ b/deploy/terraform/terraform-units/modules/sap_library/storage_accounts.tf @@ -22,7 +22,7 @@ resource "azurerm_storage_account" "storage_tfstate" { account_tier = local.sa_tfstate_account_tier account_kind = local.sa_tfstate_account_kind enable_https_traffic_only = local.sa_tfstate_enable_secure_transfer - allow_blob_public_access = true + allow_blob_public_access = false blob_properties { delete_retention_policy { days = 7 @@ -111,7 +111,7 @@ resource "azurerm_storage_account" "storage_sapbits" { account_kind = local.sa_sapbits_account_kind enable_https_traffic_only = local.sa_sapbits_enable_secure_transfer // To support all access levels 'Blob' 'Private' and 'Container' - allow_blob_public_access = true + allow_blob_public_access = false // TODO: soft delete for file share network_rules { @@ -189,28 +189,3 @@ resource "azurerm_key_vault_secret" "sapbits_location_base_path" { key_vault_id = local.deployer_kv_user_arm_id } -data "azurerm_storage_account_blob_container_sas" "saplib" { - connection_string = local.sa_sapbits_exists ? data.azurerm_storage_account.storage_sapbits[0].primary_connection_string : azurerm_storage_account.storage_sapbits[0].primary_connection_string - container_name = local.resource_suffixes.sapbits - https_only = true - start = format("%s-01-01", formatdate("YYYY", timestamp())) - expiry = format("%s-12-31", formatdate("YYYY", timeadd(timestamp(), "8760h"))) - permissions { - read = true - add = false - create = false - write = false - delete = false - list = true - } - -} - -resource "azurerm_key_vault_secret" "saplibrary_sas_token" { - provider = azurerm.deployer - count = length(local.deployer_kv_user_arm_id) > 0 ? 1 : 0 - name = "sapbits-sas-token" - value = format("%s", data.azurerm_storage_account_blob_container_sas.saplib.sas) - key_vault_id = local.deployer_kv_user_arm_id -} - diff --git a/deploy/terraform/terraform-units/modules/sap_namegenerator/output.tf b/deploy/terraform/terraform-units/modules/sap_namegenerator/output.tf index b8491d55a2..4b09f0bcae 100644 --- a/deploy/terraform/terraform-units/modules/sap_namegenerator/output.tf +++ b/deploy/terraform/terraform-units/modules/sap_namegenerator/output.tf @@ -44,13 +44,13 @@ output "naming" { ANCHOR_COMPUTERNAME = local.anchor_computer_names ANCHOR_SECONDARY_DNSNAME = local.anchor_secondary_dnsnames ANCHOR_VMNAME = local.anchor_vm_names - ANYDB_COMPUTERNAME = concat(local.anydb_computer_names, local.anydb_computer_names_ha) + ANYDB_COMPUTERNAME = var.database_high_availability ? concat(local.anydb_computer_names, local.anydb_computer_names_ha) : local.anydb_computer_names ANYDB_SECONDARY_DNSNAME = concat(local.anydb_secondary_dnsnames, local.anydb_secondary_dnsnames_ha) - ANYDB_VMNAME = concat(local.anydb_vm_names, local.anydb_vm_names_ha) + ANYDB_VMNAME = var.database_high_availability ? concat(local.anydb_vm_names, local.anydb_vm_names_ha) : local.anydb_vm_names DEPLOYER = local.deployer_vm_names - HANA_COMPUTERNAME = concat(local.hana_computer_names, local.hana_computer_names_ha) - HANA_SECONDARY_DNSNAME = concat(local.hana_secondary_dnsnames, local.hana_secondary_dnsnames_ha) - HANA_VMNAME = concat(local.hana_server_vm_names, local.hana_server_vm_names_ha) + HANA_COMPUTERNAME = var.database_high_availability ? concat(local.hana_computer_names, local.hana_computer_names_ha) : local.hana_computer_names + HANA_SECONDARY_DNSNAME = var.database_high_availability ? concat(local.hana_secondary_dnsnames, local.hana_secondary_dnsnames_ha) : local.hana_secondary_dnsnames + HANA_VMNAME = var.database_high_availability ? concat(local.hana_server_vm_names, local.hana_server_vm_names_ha) : local.hana_server_vm_names ISCSI_COMPUTERNAME = local.iscsi_server_names OBSERVER_COMPUTERNAME = local.observer_computer_names OBSERVER_VMNAME = local.observer_vm_names diff --git a/deploy/terraform/terraform-units/modules/sap_namegenerator/variables_local.tf b/deploy/terraform/terraform-units/modules/sap_namegenerator/variables_local.tf index 17d4542933..0866f704ae 100644 --- a/deploy/terraform/terraform-units/modules/sap_namegenerator/variables_local.tf +++ b/deploy/terraform/terraform-units/modules/sap_namegenerator/variables_local.tf @@ -108,6 +108,21 @@ variable "resource_offset" { default = 0 } +variable "database_high_availability" { + type = bool + default = false +} + +variable "scs_high_availability" { + type = bool + default = false +} + +variable "use_zonal_markers" { + type = bool + default = true +} + //Todo: Add to documentation variable "sapautomation_name_limits" { description = "Name length for automation resources" @@ -287,6 +302,7 @@ variable "resource_suffixes" { "sdu_rg" = "" "tfstate" = "tfstate" "transport_volume" = "transport" + "install_volume" = "install" "vm" = "" "vnet" = "-vnet" "vnet_rg" = "-INFRASTRUCTURE" diff --git a/deploy/terraform/terraform-units/modules/sap_namegenerator/vm.tf b/deploy/terraform/terraform-units/modules/sap_namegenerator/vm.tf index 8e40fc14ec..2900e2ab9b 100644 --- a/deploy/terraform/terraform-units/modules/sap_namegenerator/vm.tf +++ b/deploy/terraform/terraform-units/modules/sap_namegenerator/vm.tf @@ -21,18 +21,18 @@ locals { ] anydb_computer_names_ha = [for idx in range(var.db_server_count) : - format("%sdb%02dl%d%s", lower(var.sap_sid), idx + var.resource_offset, 1, local.random_id_vm_verified) + format("%sdb%02dl%d%s", lower(var.sap_sid), idx + var.resource_offset, 1, local.random_id_vm_verified) ] anydb_vm_names = [for idx in range(var.db_server_count) : - length(var.db_zones) > 0 ? ( + length(var.db_zones) > 0 && var.use_zonal_markers ? ( format("%sdb%sz%s%s%02dl%d%s", lower(var.sap_sid), local.separator, var.db_zones[idx % max(length(var.db_zones), 1)], local.separator, idx + var.resource_offset, 0, local.random_id_vm_verified)) : ( format("%sdb%02dl%d%s", lower(var.sap_sid), idx + var.resource_offset, 0, local.random_id_vm_verified) ) ] anydb_vm_names_ha = [for idx in range(var.db_server_count) : - length(var.db_zones) > 0 ? ( + length(var.db_zones) > 0 && var.use_zonal_markers ? ( format("%sdb%sz%s%s%02dl%d%s", lower(var.sap_sid), local.separator, var.db_zones[idx % max(length(var.db_zones), 1)], local.separator, idx + var.resource_offset, 1, local.random_id_vm_verified)) : ( format("%sdb%02dl%d%s", lower(var.sap_sid), idx + var.resource_offset, 1, local.random_id_vm_verified) ) @@ -43,7 +43,7 @@ locals { ] app_server_vm_names = [for idx in range(var.app_server_count) : - length(var.app_zones) > 0 ? ( + length(var.app_zones) > 0 && var.use_zonal_markers ? ( format("%sapp%sz%s%s%02d%s%s", lower(var.sap_sid), local.separator, var.app_zones[idx % max(length(var.app_zones), 1)], local.separator, idx + var.resource_offset, local.app_oscode, local.random_id_vm_verified)) : ( format("%sapp%02d%s%s", lower(var.sap_sid), idx + var.resource_offset, local.app_oscode, local.random_id_vm_verified) ) @@ -62,14 +62,14 @@ locals { ] hana_server_vm_names = [for idx in range(var.db_server_count) : - length(var.db_zones) > 0 ? ( + length(var.db_zones) > 0 && var.use_zonal_markers ? ( format("%sd%s%sz%s%s%02dl%d%s", lower(var.sap_sid), lower(var.db_sid), local.separator, var.db_zones[idx % max(length(var.db_zones), 1)], local.separator, idx + var.resource_offset, 0, local.random_id_vm_verified)) : ( format("%sd%s%02dl%d%s", lower(var.sap_sid), lower(var.db_sid), idx + var.resource_offset, 0, local.random_id_vm_verified) ) ] hana_server_vm_names_ha = [for idx in range(var.db_server_count) : - length(var.db_zones) > 0 ? ( + length(var.db_zones) > 0 && var.use_zonal_markers ? ( format("%sd%s%sz%s%s%02dl%d%s", lower(var.sap_sid), lower(var.db_sid), local.separator, var.db_zones[idx % max(length(var.db_zones), 1)], local.separator, idx + var.resource_offset, 1, local.random_id_vm_verified)) : ( format("%sd%s%02dl%d%s", lower(var.sap_sid), lower(var.db_sid), idx + var.resource_offset, 1, local.random_id_vm_verified) ) @@ -80,7 +80,7 @@ locals { ] scs_server_vm_names = [for idx in range(var.scs_server_count) : - length(var.scs_zones) > 0 ? ( + length(var.scs_zones) > 0 && var.use_zonal_markers ? ( format("%sscs%sz%s%s%02d%s%s", lower(var.sap_sid), local.separator, var.scs_zones[idx % max(length(var.scs_zones), 1)], local.separator, idx + var.resource_offset, local.app_oscode, local.random_id_vm_verified)) : ( format("%sscs%02d%s%s", lower(var.sap_sid), idx + var.resource_offset, local.app_oscode, local.random_id_vm_verified) ) @@ -91,17 +91,17 @@ locals { ] web_server_vm_names = [for idx in range(var.web_server_count) : - length(var.web_zones) > 0 ? ( + length(var.web_zones) > 0 && var.use_zonal_markers ? ( format("%sweb%sz%s%s%02d%s%s", lower(var.sap_sid), local.separator, var.web_zones[idx % max(length(var.web_zones), 1)], local.separator, idx + var.resource_offset, local.app_oscode, local.random_id_vm_verified)) : ( format("%sweb%02d%s%s", lower(var.sap_sid), idx + var.resource_offset, local.app_oscode, local.random_id_vm_verified) ) ] - observer_computer_names = [for idx in range(length(local.zones)) : + observer_computer_names = [for idx in range(max(length(local.zones), 1)) : format("%sobserver%02d%s%s", lower(var.sap_sid), idx + var.resource_offset, local.db_oscode, local.random_id_vm_verified) ] - observer_vm_names = [for idx in range(length(local.zones)) : + observer_vm_names = [for idx in range(max(length(local.zones), 1)) : local.zonal_deployment ? ( format("%sobserver_z%s_%02d%s%s", lower(var.sap_sid), local.zones[idx % length(local.zones)], idx + var.resource_offset, local.db_oscode, local.random_id_vm_verified)) : ( format("%sobserver%02d%s%s", lower(var.sap_sid), idx + var.resource_offset, local.db_oscode, local.random_id_vm_verified) diff --git a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/infrastructure.tf b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/infrastructure.tf index 3119240fad..205413434b 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/infrastructure.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/infrastructure.tf @@ -77,7 +77,13 @@ resource "azurerm_availability_set" "anydb" { resource_group_name = var.resource_group[0].name platform_update_domain_count = 20 platform_fault_domain_count = local.faultdomain_count - proximity_placement_group_id = local.zonal_deployment ? var.ppg[count.index % length(local.zones)].id : var.ppg[0].id + proximity_placement_group_id = local.zonal_deployment ? ( + null) : ( + local.no_ppg ? ( + null) : ( + var.ppg[0].id + ) + ) managed = true } diff --git a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/variables_local.tf b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/variables_local.tf index b426c7c833..e3eff235bc 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/variables_local.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/variables_local.tf @@ -98,11 +98,17 @@ variable "database_server_count" { default = 1 } -variable "order_deployment" { +variable "order_deployment" { description = "psuedo condition for ordering deployment" default = "" } +variable "use_observer" { +} + + + + locals { // Imports database sizing information @@ -165,7 +171,7 @@ locals { enable_deployment = (length(local.anydb_databases) > 0) ? true : false anydb = local.enable_deployment ? local.anydb_databases[0] : null - anydb_platform = local.enable_deployment ? try(local.anydb.platform, "NONE") : "NONE" + anydb_platform = local.enable_deployment ? upper(try(local.anydb.platform, "NONE")) : "NONE" // Enable deployment based on length of local.anydb_databases // If custom image is used, we do not overwrite os reference with default value @@ -178,14 +184,14 @@ locals { db_sizing = local.enable_deployment ? lookup(local.sizes.db, local.anydb_size).storage : [] db_size = local.enable_deployment ? lookup(local.sizes.db, local.anydb_size).compute : {} - anydb_sku = try(local.db_size.vm_size, "Standard_E4s_v3") + anydb_sku = try(local.db_size.vm_size, "Standard_E16_v3") - anydb_fs = try(local.anydb.filesystem, "xfs") - anydb_ha = try(local.anydb.high_availability, false) + anydb_ha = try(local.anydb.high_availability, false) + db_sid = try(local.anydb.instance.sid, lower(substr(local.anydb_platform, 0, 3))) + loadbalancer = try(local.anydb.loadbalancer, {}) - db_sid = lower(substr(local.anydb_platform, 0, 3)) - loadbalancer = try(local.anydb.loadbalancer, {}) - enable_db_lb_deployment = var.database_server_count > 0 && (var.use_loadbalancers_for_standalone_deployments || var.database_server_count > 1) + # Oracle deployments do not need a load balancer + enable_db_lb_deployment = var.database_server_count > 0 && (var.use_loadbalancers_for_standalone_deployments || var.database_server_count > 1) && local.anydb_platform != "ORACLE" && local.anydb_platform != "NONE" anydb_cred = try(local.anydb.credentials, {}) @@ -246,7 +252,9 @@ locals { //Observer VM observer = try(local.anydb.observer, {}) - deploy_observer = upper(local.anydb_platform) == "ORACLE" && local.anydb_ha + + #If using an existing VM for observer set use_observer to false in .tfvars + deploy_observer = var.use_observer ? upper(local.anydb_platform) == "ORACLE" && local.anydb_ha : false observer_size = "Standard_D4s_v3" observer_authentication = local.authentication observer_custom_image = local.anydb_custom_image @@ -395,7 +403,10 @@ locals { zonal_deployment = local.db_zone_count > 0 || local.enable_ultradisk ? true : false //If we deploy more than one server in zone put them in an availability set - use_avset = var.database_server_count > 0 && try(!local.anydb.no_avset, false) ? !local.zonal_deployment || (var.database_server_count != local.db_zone_count) : false + use_avset = local.zonal_deployment ? ( + false) : ( + var.database_server_count > 0 && try(!local.anydb.no_avset, false) + ) full_observer_names = flatten([for vm in var.naming.virtualmachine_names.OBSERVER_VMNAME : format("%s%s%s%s", local.prefix, var.naming.separator, vm, local.resource_suffixes.vm)] diff --git a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-anydb.tf b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-anydb.tf index 8fa7c5bb0c..3d5275dac9 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-anydb.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-anydb.tf @@ -112,7 +112,8 @@ resource "azurerm_linux_virtual_machine" "dbserver" { azurerm_availability_set.anydb[count.index % max(local.db_zone_count, 1)].id ) ) : null - zone = local.use_avset ? null : local.zones[count.index % max(local.db_zone_count, 1)] + + zone = local.zonal_deployment ? local.zones[count.index % max(local.db_zone_count, 1)] : null network_interface_ids = local.anydb_dual_nics ? ( var.options.legacy_nic_order ? ( @@ -198,7 +199,8 @@ resource "azurerm_windows_virtual_machine" "dbserver" { azurerm_availability_set.anydb[count.index % max(local.db_zone_count, 1)].id ) ) : null - zone = local.use_avset ? null : local.zones[count.index % max(local.db_zone_count, 1)] + + zone = local.zonal_deployment ? local.zones[count.index % max(local.db_zone_count, 1)] : null network_interface_ids = local.anydb_dual_nics ? ( var.options.legacy_nic_order ? ( @@ -258,8 +260,7 @@ resource "azurerm_managed_disk" "disks" { disk_iops_read_write = "UltraSSD_LRS" == local.anydb_disks[count.index].storage_account_type ? local.anydb_disks[count.index].disk_iops_read_write : null disk_mbps_read_write = "UltraSSD_LRS" == local.anydb_disks[count.index].storage_account_type ? local.anydb_disks[count.index].disk_mbps_read_write : null - - zones = !local.use_avset ? ( + zones = local.zonal_deployment ? ( upper(local.anydb_ostype) == "LINUX" ? ( [azurerm_linux_virtual_machine.dbserver[local.anydb_disks[count.index].vm_index].zone]) : ( [azurerm_windows_virtual_machine.dbserver[local.anydb_disks[count.index].vm_index].zone] diff --git a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-observer.tf b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-observer.tf index 842a26a1ae..78e19c4891 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-observer.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/anydb_node/vm-observer.tf @@ -2,7 +2,7 @@ # Create observer VM resource "azurerm_network_interface" "observer" { provider = azurerm.main - count = local.deploy_observer ? length(local.zones) : 0 + count = local.deploy_observer ? 1 : 0 name = format("%s%s%s%s", local.prefix, var.naming.separator, var.naming.virtualmachine_names.OBSERVER_VMNAME[count.index], local.resource_suffixes.nic) resource_group_name = var.resource_group[0].name location = var.resource_group[0].location @@ -26,7 +26,7 @@ resource "azurerm_network_interface" "observer" { resource "azurerm_linux_virtual_machine" "observer" { provider = azurerm.main depends_on = [var.anchor_vm] - count = local.deploy_observer && upper(local.anydb_ostype) == "LINUX" ? length(local.zones) : 0 + count = local.deploy_observer && upper(local.anydb_ostype) == "LINUX" ? 1 : 0 resource_group_name = var.resource_group[0].name location = var.resource_group[0].location name = format("%s%s%s%s", local.prefix, var.naming.separator, var.naming.virtualmachine_names.OBSERVER_VMNAME[count.index], local.resource_suffixes.vm) @@ -44,18 +44,7 @@ resource "azurerm_linux_virtual_machine" "observer" { } } - //If more than one servers are deployed into a single zone put them in an availability set and not a zone - proximity_placement_group_id = local.zonal_deployment ? var.ppg[count.index % max(local.db_zone_count, 1)].id : var.ppg[0].id - //If more than one servers are deployed into a single zone put them in an availability set and not a zone - availability_set_id = local.zonal_deployment ? ( - var.database_server_count == local.db_zone_count ? null : azurerm_availability_set.anydb[count.index % max(local.db_zone_count, 1)].id) : ( - azurerm_availability_set.anydb[0].id - ) - - zone = local.zonal_deployment ? ( - var.database_server_count == local.db_zone_count ? local.zones[count.index % max(local.db_zone_count, 1)] : null) : ( - null - ) + zone = local.zonal_deployment ? local.zones[count.index % max(local.db_zone_count, 1)] : null network_interface_ids = [ azurerm_network_interface.observer[count.index].id @@ -95,24 +84,13 @@ resource "azurerm_linux_virtual_machine" "observer" { # Create the Windows Application VM(s) resource "azurerm_windows_virtual_machine" "observer" { provider = azurerm.main - count = local.deploy_observer && upper(local.anydb_ostype) == "WINDOWS" ? length(local.zones) : 0 + count = local.deploy_observer && upper(local.anydb_ostype) == "WINDOWS" ? 1 : 0 name = format("%s%s%s%s", local.prefix, var.naming.separator, var.naming.virtualmachine_names.OBSERVER_VMNAME[count.index], local.resource_suffixes.vm) computer_name = var.naming.virtualmachine_names.OBSERVER_COMPUTERNAME[count.index] resource_group_name = var.resource_group[0].name location = var.resource_group[0].location - //If more than one servers are deployed into a single zone put them in an availability set and not a zone - proximity_placement_group_id = local.zonal_deployment ? var.ppg[count.index % max(local.db_zone_count, 1)].id : var.ppg[0].id - //If more than one servers are deployed into a single zone put them in an availability set and not a zone - availability_set_id = local.zonal_deployment ? ( - var.database_server_count == local.db_zone_count ? null : azurerm_availability_set.anydb[count.index % max(local.db_zone_count, 1)].id) : ( - azurerm_availability_set.anydb[0].id - ) - - zone = local.zonal_deployment ? ( - var.database_server_count == local.db_zone_count ? local.zones[count.index % max(local.db_zone_count, 1)] : null) : ( - null - ) + zone = local.zonal_deployment ? local.zones[count.index % max(local.db_zone_count, 1)] : null network_interface_ids = [ azurerm_network_interface.observer[count.index].id ] diff --git a/deploy/terraform/terraform-units/modules/sap_system/app_tier/infrastructure.tf b/deploy/terraform/terraform-units/modules/sap_system/app_tier/infrastructure.tf index f73ca06808..1788717a7d 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/app_tier/infrastructure.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/app_tier/infrastructure.tf @@ -192,7 +192,7 @@ resource "azurerm_availability_set" "scs" { # Create the Application Availability Set resource "azurerm_availability_set" "app" { provider = azurerm.main - count = local.enable_deployment && local.use_app_avset ? max(length(local.app_zones), 1) : 0 + count = local.enable_deployment && local.use_app_avset && length(var.application.avset_arm_ids) == 0 ? max(length(local.app_zones), 1) : 0 name = format("%s%s%s", local.prefix, var.naming.separator, var.naming.app_avset_names[count.index]) location = var.resource_group[0].location resource_group_name = var.resource_group[0].name diff --git a/deploy/terraform/terraform-units/modules/sap_system/app_tier/variables_local.tf b/deploy/terraform/terraform-units/modules/sap_system/app_tier/variables_local.tf index 07c4fe0a17..f609ff2223 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/app_tier/variables_local.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/app_tier/variables_local.tf @@ -402,14 +402,14 @@ locals { { name = format("%s%s%s", local.prefix, var.naming.separator, local.resource_suffixes.scs_clst_feip) subnet_id = local.enable_deployment ? (local.sub_app_exists ? data.azurerm_subnet.subnet_sap_app[0].id : azurerm_subnet.subnet_sap_app[0].id) : "" - private_ip_address = var.application.use_DHCP || ! local.enable_scs_lb_deployment ? (null) : (try(local.scs_lb_ips[0], cidrhost(local.sub_app_prefix, 2 + local.ip_offsets.scs_lb))) + private_ip_address = var.application.use_DHCP ? (null) : (try(local.scs_lb_ips[0], cidrhost(local.sub_app_prefix, 2 + local.ip_offsets.scs_lb))) private_ip_address_allocation = var.application.use_DHCP ? "Dynamic" : "Static" }, { name = format("%s%s%s", local.prefix, var.naming.separator, local.resource_suffixes.scs_fs_feip) subnet_id = local.enable_deployment ? (local.sub_app_exists ? data.azurerm_subnet.subnet_sap_app[0].id : azurerm_subnet.subnet_sap_app[0].id) : "" - private_ip_address = var.application.use_DHCP || ! local.enable_scs_lb_deployment ? (null) : (try(local.scs_lb_ips[0], cidrhost(local.sub_app_prefix, 3 + local.ip_offsets.scs_lb))) + private_ip_address = var.application.use_DHCP ? (null) : (try(local.scs_lb_ips[0], cidrhost(local.sub_app_prefix, 3 + local.ip_offsets.scs_lb))) private_ip_address_allocation = var.application.use_DHCP ? "Dynamic" : "Static" } ] @@ -419,13 +419,13 @@ locals { { name = format("%s%s%s", local.prefix, var.naming.separator, local.resource_suffixes.scs_alb_feip) subnet_id = local.enable_deployment ? (local.sub_app_exists ? data.azurerm_subnet.subnet_sap_app[0].id : azurerm_subnet.subnet_sap_app[0].id) : "" - private_ip_address = var.application.use_DHCP || ! local.enable_scs_lb_deployment ? (null) : (try(local.scs_lb_ips[0], cidrhost(local.sub_app_prefix, 0 + local.ip_offsets.scs_lb))) + private_ip_address = var.application.use_DHCP ? (null) : (try(local.scs_lb_ips[0], cidrhost(local.sub_app_prefix, 0 + local.ip_offsets.scs_lb))) private_ip_address_allocation = var.application.use_DHCP ? "Dynamic" : "Static" }, { name = format("%s%s%s", local.prefix, var.naming.separator, local.resource_suffixes.scs_ers_feip) subnet_id = local.enable_deployment ? (local.sub_app_exists ? data.azurerm_subnet.subnet_sap_app[0].id : azurerm_subnet.subnet_sap_app[0].id) : "" - private_ip_address = var.application.use_DHCP || ! local.enable_scs_lb_deployment ? (null) : (try(local.scs_lb_ips[1], cidrhost(local.sub_app_prefix, 1 + local.ip_offsets.scs_lb))) + private_ip_address = var.application.use_DHCP ? (null) : (try(local.scs_lb_ips[1], cidrhost(local.sub_app_prefix, 1 + local.ip_offsets.scs_lb))) private_ip_address_allocation = var.application.use_DHCP ? "Dynamic" : "Static" }, ] diff --git a/deploy/terraform/terraform-units/modules/sap_system/app_tier/vm-app.tf b/deploy/terraform/terraform-units/modules/sap_system/app_tier/vm-app.tf index 91f30d9a79..f7c65f0334 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/app_tier/vm-app.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/app_tier/vm-app.tf @@ -73,7 +73,13 @@ resource "azurerm_linux_virtual_machine" "app" { ) //If more than one servers are deployed into a single zone put them in an availability set and not a zone - availability_set_id = local.use_app_avset ? azurerm_availability_set.app[count.index % max(local.app_zone_count, 1)].id : null + availability_set_id = local.use_app_avset ? ( + length(var.application.avset_arm_ids) > 0 ? ( + var.application.avset_arm_ids[count.index % max(local.app_zone_count, 1)]) : ( + azurerm_availability_set.app[count.index % max(local.app_zone_count, 1)].id + )) : ( + null + ) //If length of zones > 1 distribute servers evenly across zones zone = local.use_app_avset ? null : try(local.app_zones[count.index % max(local.app_zone_count, 1)], null) @@ -167,7 +173,13 @@ resource "azurerm_windows_virtual_machine" "app" { ) //If more than one servers are deployed into a single zone put them in an availability set and not a zone - availability_set_id = local.use_app_avset ? azurerm_availability_set.app[count.index % max(local.app_zone_count, 1)].id : null + availability_set_id = local.use_app_avset ? ( + length(var.application.avset_arm_ids) > 0 ? ( + var.application.avset_arm_ids[count.index % max(local.app_zone_count, 1)]) : ( + azurerm_availability_set.app[count.index % max(local.app_zone_count, 1)].id + )) : ( + null + ) //If length of zones > 1 distribute servers evenly across zones zone = local.use_app_avset ? null : local.app_zones[count.index % max(local.app_zone_count, 1)] diff --git a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/key_vault_sap_system.tf b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/key_vault_sap_system.tf index 52dd71ec4c..3d5cfd2722 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/key_vault_sap_system.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/key_vault_sap_system.tf @@ -148,7 +148,7 @@ resource "azurerm_key_vault_secret" "auth_password" { provider = azurerm.main count = local.enable_sid_deployment && local.use_local_credentials ? 1 : 0 name = format("%s-password", local.prefix) - value = var.authentication.password + value = local.sid_auth_password key_vault_id = azurerm_key_vault.sid_kv_user[0].id } diff --git a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/outputs.tf b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/outputs.tf index 324796ae2c..5ae4932f9d 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/outputs.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/outputs.tf @@ -1,5 +1,8 @@ output "anchor_vm" { - value = local.anchor_ostype == "LINUX" ? azurerm_linux_virtual_machine.anchor : azurerm_windows_virtual_machine.anchor + value = local.deploy_anchor ? ( + local.anchor_ostype == "LINUX" ? (azurerm_linux_virtual_machine.anchor[0].id) : (azurerm_windows_virtual_machine.anchor[0].id)) : ( + "" + ) } output "resource_group" { @@ -30,7 +33,11 @@ output "admin_subnet" { } output "db_subnet" { - value = local.sub_db_exists ? data.azurerm_subnet.db[0] : azurerm_subnet.db[0] + value = local.enable_db_deployment ? ( + local.sub_db_exists ? data.azurerm_subnet.db[0] : azurerm_subnet.db[0]) : ( + null + ) + #local.sub_db_exists ? data.azurerm_subnet.db[0] : azurerm_subnet.db[0] } output "network_location" { @@ -85,7 +92,7 @@ output "route_table_id" { } output "firewall_id" { - value = try(var.deployer_tfstate.firewall_id, "") + value = try(var.deployer_tfstate.firewall_id, "") } output "db_asg_id" { @@ -108,6 +115,6 @@ output "saptransport_path" { value = local.ANF_pool_settings.use_ANF ? format("%s:/%s", azurerm_netapp_volume.transport[0].mount_ip_addresses[0], azurerm_netapp_volume.transport[0].volume_path) : "" } -# output "shared_path" { -# value = local.ANF_pool_settings.use_ANF ? format("%s:/%s",azurerm_netapp_volume.shared[0].mount_ip_addresses[0]) : "" -# } \ No newline at end of file +output "install_path" { + value = local.deploy_afs ? try(format("%s:/%s/%s", split("/", replace(azurerm_storage_share.install[0].url, "https://", ""))[0], azurerm_storage_account.install[0].name, azurerm_storage_share.install[0].name), "") : "" +} diff --git a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/storage_accounts.tf b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/storage_accounts.tf new file mode 100644 index 0000000000..843c192ca5 --- /dev/null +++ b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/storage_accounts.tf @@ -0,0 +1,26 @@ +resource "azurerm_storage_account" "install" { + count = local.deploy_afs ? 1 : 0 + name = replace(lower(format("%s%s", local.prefix, local.resource_suffixes.install_volume)), "/[^a-z0-9]/", "") + resource_group_name = local.rg_exists ? data.azurerm_resource_group.resource_group[0].name : azurerm_resource_group.resource_group[0].name + location = var.infrastructure.region + account_tier = "Premium" + account_replication_type = "ZRS" + account_kind = "FileStorage" + enable_https_traffic_only = false + + + network_rules { + default_action = "Deny" + virtual_network_subnet_ids = compact([var.landscape_tfstate.app_subnet_id, var.landscape_tfstate.db_subnet_id, try(var.landscape_tfstate.web_subnet_id, ""), try(var.landscape_tfstate.subnet_mgmt_id, "")]) + bypass = ["AzureServices", "Logging", "Metrics"] + } +} + +resource "azurerm_storage_share" "install" { + count = local.deploy_afs ? 1 : 0 + name = format("%s", local.resource_suffixes.install_volume) + storage_account_name = azurerm_storage_account.install[0].name + enabled_protocol = "NFS" + + quota = 128 +} diff --git a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/variables_local.tf b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/variables_local.tf index e8ba136e98..0ccb054bfa 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/variables_local.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/common_infrastructure/variables_local.tf @@ -205,7 +205,7 @@ locals { //If the db uses ultra disks ensure that the anchore sets the ultradisk flag but only for the zones that will contain db servers enable_anchor_ultra = [ for zone in local.zones : - contains(local.db_list[0].zones, zone) ? local.enable_ultradisk : false + try(contains(local.db_list[0].zones, zone) ? local.enable_ultradisk : false, false) ] anchor_custom_image = length(try(var.infrastructure.anchor_vms.os.source_image_id, "")) > 0 @@ -350,7 +350,7 @@ locals { sid_auth_password = coalesce( try(var.authentication.password, ""), - try(data.azurerm_key_vault_secret.sid_password[0].value, local.use_local_credentials ? random_password.password[0].result : "") + try(data.azurerm_key_vault_secret.sid_password[0].value, random_password.password[0].result) ) sid_public_key = local.use_local_credentials ? ( @@ -373,6 +373,8 @@ locals { { use_ANF = false } ) + deploy_afs = false + } locals { diff --git a/deploy/terraform/terraform-units/modules/sap_system/hdb_node/infrastructure.tf b/deploy/terraform/terraform-units/modules/sap_system/hdb_node/infrastructure.tf index 36e29b3d2f..9c2a11ca8f 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/hdb_node/infrastructure.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/hdb_node/infrastructure.tf @@ -6,7 +6,13 @@ resource "azurerm_availability_set" "hdb" { resource_group_name = var.resource_group[0].name platform_update_domain_count = 20 platform_fault_domain_count = local.faultdomain_count - proximity_placement_group_id = local.zonal_deployment ? var.ppg[count.index % length(local.zones)].id : var.ppg[0].id + proximity_placement_group_id = local.zonal_deployment ? ( + null) : ( + local.no_ppg ? ( + null) : ( + var.ppg[0].id + ) + ) managed = true } diff --git a/deploy/terraform/terraform-units/modules/sap_system/output_files/ansible_inventory.tmpl b/deploy/terraform/terraform-units/modules/sap_system/output_files/ansible_inventory.tmpl index e23fed8cd1..efeaf96e3a 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/output_files/ansible_inventory.tmpl +++ b/deploy/terraform/terraform-units/modules/sap_system/output_files/ansible_inventory.tmpl @@ -1,106 +1,81 @@ -[iscsi] -%{~ for ip_iscsi in ips_iscsi } -%{~ if iscsi.authentication.type == "key" } -${ip_iscsi} ansible_connection=ssh ansible_user=${iscsi.authentication.username} -%{~ endif } -%{~ if iscsi.authentication.type == "password" } -${ip_iscsi} ansible_connection=ssh ansible_user=${iscsi.authentication.username} ansible_ssh_pass=${iscsi.authentication.password} ansible_become_pass=${iscsi.authentication.password} -%{~ endif } +${sid}_DB: + hosts: +%{~ for idx,ips_dbnode in ips_dbnodes } + ${dbnodes[idx]}: + ansible_host : ${ips_dbnode} + ansible_user : ${ansible_user} + ansible_connection : ${dbconnection} + connection_type : ${dbconnectiontype} %{~ endfor } + vars: + node_tier : ${platform} + supported_tiers : [${db_supported_tiers}] -[all_linux_servers] -%{~ for ip_dbnode_admin in ips_dbnodes_admin } -%{~ if dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.type == "key" } -${ip_dbnode_admin} ansible_connection=ssh ansible_user=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.username} -%{~ endif } -%{~ if dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.type == "password" } -${ip_dbnode_admin} ansible_connection=ssh ansible_user=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.username} ansible_ssh_pass=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.password} ansible_become_pass=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.password} -%{~ endif } -%{~ endfor } -%{~ for ip_scs in ips_scs } -${ip_scs} ansible_connection=ssh ansible_user=${application.authentication.username} -%{~ endfor } -%{ for ip_app in ips_app } -${ip_app} ansible_connection=ssh ansible_user=${application.authentication.username} -%{~ endfor } -%{ for ip_web in ips_web } -${ip_web} ansible_connection=ssh ansible_user=${application.authentication.username} +${sid}_SCS: + hosts: +%{~ for idx,ip_scs in ips_scs } + ${scsservers[idx]}: + ansible_host : ${ip_scs} + ansible_user : ${ansible_user} + ansible_connection : ${scsconnection} + connection_type : ${scsconnectiontype} %{~ endfor } + vars: + node_tier : scs + supported_tiers : [${scs_supported_tiers}] -[hanadbnodes] -%{~ for ip_dbnode_admin in ips_dbnodes_admin } -%{~ if dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.type == "key" } -${ip_dbnode_admin} ansible_connection=ssh ansible_user=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.username} -%{~ endif } -%{~ if dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.type == "password" } -${ip_dbnode_admin} ansible_connection=ssh ansible_user=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.username} ansible_ssh_pass=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.password} ansible_become_pass=${dbnodes[index(ips_dbnodes_admin, ip_dbnode_admin)].authentication.password} -%{~ endif } +${sid}_ERS: + hosts: +%{~ for idx,ip_ers in ips_ers } + ${ersservers[idx]}: + ansible_host : ${ip_ers} + ansible_user : ${ansible_user} + ansible_connection : ${ersconnection} + connection_type : ${ersconnectiontype} %{~ endfor } + vars: + node_tier : ers + supported_tiers : [ers] -[scs] -%{~ for ip_scs in ips_scs } -${ip_scs} ansible_connection=ssh ansible_user=${application.authentication.username} -%{~ if application.authentication.type == "password" } -${ip_scs} ansible_connection=ssh ansible_user=${application.authentication.username} ansible_ssh_pass=${application.authentication.password} ansible_become_pass=${application.authentication.password} -%{~ endif } -%{~ endfor } -[app] -%{~ for ip_app in ips_app } -${ip_app} ansible_connection=ssh ansible_user=${application.authentication.username} -%{~ if application.authentication.type == "password" } -${ip_app} ansible_connection=ssh ansible_user=${application.authentication.username} ansible_ssh_pass=${application.authentication.password} ansible_become_pass=${application.authentication.password} -%{~ endif } -%{~ endfor } +${sid}_PAS: + hosts: +%{~ for idx,ip_pas in ips_pas } + ${passervers[idx]}: + ansible_host : ${ip_pas} + ansible_user : ${ansible_user} + ansible_connection : ${scsconnection} + connection_type : ${scsconnectiontype} -[web] -%{~ for ip_web in ips_web } -${ip_web} ansible_connection=ssh ansible_user=${application.authentication.username} -%{~ if application.authentication.type == "password" } -${ip_web} ansible_connection=ssh ansible_user=${application.authentication.username} ansible_ssh_pass=${application.authentication.password} ansible_become_pass=${application.authentication.password} -%{~ endif } %{~ endfor } + vars: + node_tier : pas + supported_tiers : [pas] -[ase] -%{~ for ips_anydbnode in ips_anydbnodes } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].platform == "ASE" } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.type == "key" } -${ips_anydbnode} ansible_connection=ssh ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} -%{~ endif } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.type == "password" } -${ips_anydbnode} ansible_connection=ssh ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} ansible_ssh_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} ansible_become_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} -%{~ endif } -%{~ endif } -%{~ endfor } +${sid}_APP: + hosts: +%{~ for idx,ip_app in ips_app } + ${appservers[idx]}: + ansible_host : ${ip_app} + ansible_user : ${ansible_user} + ansible_connection : ${appconnection} + connection_type : ${appconnectiontype} -[oracle] -%{~ for ips_anydbnode in ips_anydbnodes } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].platform == "ORACLE" } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.type == "key" } -${ips_anydbnode} ansible_connection=ssh ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} -%{~ endif } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.type == "password" } -${ips_anydbnode} ansible_connection=ssh ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} ansible_ssh_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} ansible_become_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} -%{~ endif } -%{~ endif } %{~ endfor } + vars: + node_tier : app + supported_tiers : [app] -[db2] -%{~ for ips_anydbnode in ips_anydbnodes } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].platform == "DB2" } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.type == "key" } -${ips_anydbnode} ansible_connection=ssh ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} -%{~ endif } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.type == "password" } -${ips_anydbnode} ansible_connection=ssh ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} ansible_ssh_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} ansible_become_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} -%{~ endif } -%{~ endif } -%{~ endfor } +${sid}_WEB: + hosts: +%{~ for idx,ip_web in ips_web } + ${webservers[idx]}: + ansible_host : ${ip_web} + ansible_user : ${ansible_user} + ansible_connection : ${webconnection} + connection_type : ${webconnectiontype} -[sqlserver] -%{~ for ips_anydbnode in ips_anydbnodes } -%{~ if anydbnodes[index(ips_anydbnodes, ips_anydbnode)].platform == "SQLSERVER" } -${ips_anydbnode} ansible_connection=winrm ansible_user=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.username} ansible_ssh_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} ansible_become_pass=${anydbnodes[index(ips_anydbnodes, ips_anydbnode)].authentication.password} -%{~ endif } %{~ endfor } - + vars: + node_tier : web + supported_tiers : [web] diff --git a/deploy/terraform/terraform-units/modules/sap_system/output_files/inventory.tf b/deploy/terraform/terraform-units/modules/sap_system/output_files/inventory.tf index d1cb1bc34c..524a792901 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/output_files/inventory.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/output_files/inventory.tf @@ -1,5 +1,5 @@ resource "local_file" "ansible_inventory_new_yml" { - content = templatefile(format("%s%s", path.module, "/ansible_inventory_new.yml.tmpl"), { + content = templatefile(format("%s%s", path.module, "/ansible_inventory.tmpl"), { ips_dbnodes = var.database_admin_ips, dbnodes = var.platform == "HANA" ? var.naming.virtualmachine_names.HANA_COMPUTERNAME : var.naming.virtualmachine_names.ANYDB_COMPUTERNAME ips_scs = length(local.ips_scs) > 0 ? ( @@ -43,21 +43,23 @@ resource "local_file" "ansible_inventory_new_yml" { )) : ( [] ), - webservers = length(local.ips_web) > 0 ? var.naming.virtualmachine_names.WEB_COMPUTERNAME : [], - prefix = var.naming.prefix.SDU, - separator = var.naming.separator, - platform = lower(var.platform) - dbconnection = var.platform == "SQLSERVER" ? "winrm" : "ssh" - scsconnection = upper(var.app_tier_os_types["scs"]) == "LINUX" ? "ssh" : "winrm" - ersconnection = upper(var.app_tier_os_types["scs"]) == "LINUX" ? "ssh" : "winrm" - appconnection = upper(var.app_tier_os_types["app"]) == "LINUX" ? "ssh" : "winrm" - webconnection = upper(var.app_tier_os_types["web"]) == "LINUX" ? "ssh" : "winrm" - appconnectiontype = try(var.authentication_type, "key") - webconnectiontype = try(var.authentication_type, "key") - scsconnectiontype = try(var.authentication_type, "key") - ersconnectiontype = try(var.authentication_type, "key") - dbconnectiontype = try(var.db_auth_type, "key") - ansible_user = var.ansible_user + webservers = length(local.ips_web) > 0 ? var.naming.virtualmachine_names.WEB_COMPUTERNAME : [], + prefix = var.naming.prefix.SDU, + separator = var.naming.separator, + platform = lower(var.platform) + dbconnection = var.platform == "SQLSERVER" ? "winrm" : "ssh" + scsconnection = upper(var.app_tier_os_types["scs"]) == "LINUX" ? "ssh" : "winrm" + ersconnection = upper(var.app_tier_os_types["scs"]) == "LINUX" ? "ssh" : "winrm" + appconnection = upper(var.app_tier_os_types["app"]) == "LINUX" ? "ssh" : "winrm" + webconnection = upper(var.app_tier_os_types["web"]) == "LINUX" ? "ssh" : "winrm" + appconnectiontype = try(var.authentication_type, "key") + webconnectiontype = try(var.authentication_type, "key") + scsconnectiontype = try(var.authentication_type, "key") + ersconnectiontype = try(var.authentication_type, "key") + dbconnectiontype = try(var.db_auth_type, "key") + ansible_user = var.ansible_user + db_supported_tiers = local.db_supported_tiers + scs_supported_tiers = local.scs_supported_tiers } ) filename = format("%s/%s_hosts.yaml", path.cwd, var.sap_sid) @@ -90,6 +92,7 @@ resource "local_file" "sap-parameters_yml" { platform = var.platform scs_instance_number = var.scs_instance_number ers_instance_number = var.ers_instance_number + install_path = var.install_path } ) @@ -98,8 +101,24 @@ resource "local_file" "sap-parameters_yml" { directory_permission = "0770" } +resource "local_file" "sap_inventory_md" { + content = templatefile(format("%s/sap_application.tmpl", path.module), { + sid = var.sap_sid, + db_sid = var.db_sid + kv_name = local.kv_name, + scs_lb_ip = length(var.scs_lb_ip) > 0 ? var.scs_lb_ip : try(local.ips_scs[0], "") + platform = lower(var.platform) + kv_pwd_secret = format("%s-%s-sap-password", local.secret_prefix, var.sap_sid) + } + ) + filename = format("%s/%s.md", path.cwd, var.sap_sid) + file_permission = "0660" + directory_permission = "0770" +} + resource "azurerm_storage_blob" "hosts_yaml" { + count = 0 provider = azurerm.deployer name = format("%s_hosts.yaml", length(trimspace(var.naming.prefix.SDU)) > 0 ? trimspace(var.naming.prefix.SDU) : var.sap_sid) storage_account_name = local.tfstate_storage_account_name @@ -112,6 +131,7 @@ resource "azurerm_storage_blob" "sap_parameters_yaml" { depends_on = [ local_file.sap-parameters_yml ] + count = 0 provider = azurerm.deployer name = format("%s_sap-parameters.yaml", length(trimspace(var.naming.prefix.SDU)) > 0 ? trimspace(var.naming.prefix.SDU) : var.sap_sid) storage_account_name = local.tfstate_storage_account_name diff --git a/deploy/terraform/terraform-units/modules/sap_system/output_files/sap-parameters.yml.tmpl b/deploy/terraform/terraform-units/modules/sap_system/output_files/sap-parameters.yml.tmpl index 6084428c6e..9b408405f4 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/output_files/sap-parameters.yml.tmpl +++ b/deploy/terraform/terraform-units/modules/sap_system/output_files/sap-parameters.yml.tmpl @@ -60,6 +60,8 @@ db_high_availability: ${db_ha} # db_lb_ip is the IP address of the load balancer in from of the database virtual machines db_lb_ip: ${db_lb_ip} +# usr_sap_install_mountpoint: ${install_path} + ############################################################################# # # # ANF # diff --git a/deploy/terraform/terraform-units/modules/sap_system/output_files/sap_application.tmpl b/deploy/terraform/terraform-units/modules/sap_system/output_files/sap_application.tmpl new file mode 100644 index 0000000000..40c040ec56 --- /dev/null +++ b/deploy/terraform/terraform-units/modules/sap_system/output_files/sap_application.tmpl @@ -0,0 +1,19 @@ +# SAP System Deployment + + +| Setting | Value | +| ---------------- | ------------------------------- | +| SID | ${sid} | +| Database | ${platform} | +| DB SID | ${db_sid} | +| SCS Server IP | ${scs_lb_ip} | + +## Access credentials + +| Setting | Value | +| ---------------- | ------------------------------- | +| Keyvault | ${kv_name} | +| Secret | ${kv_pwd_secret} | + + + diff --git a/deploy/terraform/terraform-units/modules/sap_system/output_files/variables_local.tf b/deploy/terraform/terraform-units/modules/sap_system/output_files/variables_local.tf index 90aa37f9e3..09d6a0440d 100644 --- a/deploy/terraform/terraform-units/modules/sap_system/output_files/variables_local.tf +++ b/deploy/terraform/terraform-units/modules/sap_system/output_files/variables_local.tf @@ -170,6 +170,9 @@ variable "db_auth_type" { } +variable "install_path" { + default = "" +} locals { @@ -206,6 +209,11 @@ locals { secret_prefix = var.use_local_credentials ? var.naming.prefix.SDU : var.naming.prefix.VNET dns_label = try(var.landscape_tfstate.dns_label, "") + app_server_count = length(var.nics_app) + scs_server_count = length(var.nics_scs) + app_tier = (local.app_server_count + local.scs_server_count) > 0 + db_supported_tiers = local.app_tier ? lower(var.platform) : format("%s, scs, pas",lower(var.platform)) + scs_supported_tiers = local.app_server_count > 0 ? "scs" : "scs, pas" }