deploy/pipelines/07-sap-cal-installation.yaml (240 lines of code) (raw):

# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. --- # /*---------------------------------------------------------------------------8 # | | # | This pipeline performs the software installation | # | and must run on a self hosted deployment agent | # | due to long run time. | # | | # +------------------------------------4--------------------------------------*/ parameters: - name: sap_system_configuration_name displayName: "SAP System configuration name, use the following syntax: ENV-LOCA-VNET-SID" type: string default: DEV-WEEU-SAP01-X00 - name: environment displayName: Workload Environment (DEV, QUA, PRD, ...) type: string default: DEV - name: sap_cal_product_name displayName: SAP CAL Product Name type: string - name: extra_params displayName: Extra Parameters type: string default: "" - name: base_os_configuration displayName: Core Operating System Configuration type: boolean default: true - name: sap_os_configuration displayName: SAP Operating System Configuration type: boolean default: true - name: sapcal_integration displayName: SAP CAL Integration type: boolean default: false # 20220929 MKD - ACSS Registration <BEGIN> - name: acss_registration displayName: Register System in ACSS type: boolean default: true - name: acss_environment displayName: ACSS Prod/NonProd type: string values: - NonProd - Prod - name: acss_sap_product displayName: System Type type: string values: - S4HANA - ECC - Other # 20220929 MKD - ACSS Registration <END> - name: sap_automation_repo_path displayName: The local path on the agent where the sap_automation repo can be found type: string - name: config_repo_path displayName: The local path on the agent where the config repo can be found type: string stages: - stage: Preparation_for_Ansible condition: and(not(failed()), not(canceled())) variables: - template: variables/07-sap-cal-installation-variables.yaml parameters: environment: ${{ parameters.environment }} displayName: OS Configuration and SAP Installation jobs: - job: Installation_step displayName: OS Configuration and SAP Installation timeoutInMinutes: 0 workspace: clean: all steps: - template: templates\download.yaml parameters: getLatestFromBranch: true - task: PostBuildCleanup@4 - bash: | #!/bin/bash # Exit immediately if a command exits with a non-zero status. set -e green="\e[1;32m" ; reset="\e[0m" ; boldred="\e[1;31m" if [[ ! -f /etc/profile.d/deploy_server.sh ]]; then echo -e "$green --- Install dos2unix ---$reset" sudo apt-get -qq install dos2unix fi echo -e "$green--- Convert config file to UX format ---$reset" echo -e "$green--- Update .sap_deployment_automation/config as DEPLOYMENT_REPO_PATH can change on devops agent ---$reset" export HOME=${CONFIG_REPO_PATH}/$(Deployment_Configuration_Path) cd $HOME echo -e "$green--- Configure devops CLI extension ---$reset" az config set extension.use_dynamic_install=yes_without_prompt --output none az extension add --name azure-devops --output none az devops configure --defaults organization=$(System.CollectionUri) project='$(System.TeamProject)' --output none echo -e "$green--- Validations ---$reset" ENVIRONMENT=$(echo ${SAP_SYSTEM_CONFIGURATION_NAME} | awk -F'-' '{print $1}' | xargs) ; echo Environment $ENVIRONMENT LOCATION=$(echo ${SAP_SYSTEM_CONFIGURATION_NAME} | awk -F'-' '{print $2}' | xargs) ; echo Location $LOCATION NETWORK=$(echo ${SAP_SYSTEM_CONFIGURATION_NAME} | awk -F'-' '{print $3}' | xargs) ; echo Virtual network logical name $NETWORK SID=$(echo ${SAP_SYSTEM_CONFIGURATION_NAME} | awk -F'-' '{print $4}' | xargs) ; echo SID $SID environment_file_name=$HOME/.sap_deployment_automation/$ENVIRONMENT$LOCATION$NETWORK ; echo configuration_file $environment_file_name params_file=$HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/sap-parameters.yaml ; echo sap_parameters_file $params_file if [ "azure pipelines" = "$(this_agent)" ]; then echo "##vso[task.logissue type=error]Please use a self hosted agent for this playbook. Define it in the SDAF-${ENVIRONMENT} variable group using the 'POOL' variable." exit 2 fi if [ ! -f $environment_file_name ]; then echo -e "$boldred--- $environment_file_name was not found ---$reset" echo "##vso[task.logissue type=error]Workload zone configuration file $environment_file_name was not found." exit 2 fi if [ ! -f $params_file ]; then echo -e "$boldred--- $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/sap-parameters.yaml was not found ---$reset" echo "##vso[task.logissue type=error]File $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/sap-parameters.yaml was not found." exit 2 else dos2unix -q $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/sap-parameters.yaml fi if [ ! -n ${SID} ]; then echo "##vso[task.logissue type=error]SID was not found in ${SAP_SYSTEM_CONFIGURATION_NAME}." exit 2 fi if [ ! -f $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/${SID}_hosts.yaml ]; then echo -e "$boldred--- $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/${SID}_hosts.yaml was not found ---$reset" echo "##vso[task.logissue type=error]File $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/${SID}_hosts.yaml was not found." exit 2 fi dos2unix -q $HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}/${SID}_hosts.yaml export VARIABLE_GROUP_ID=$(az pipelines variable-group list --query "[?name=='$(variable_group)'].id | [0]") echo '$(variable_group) id: ' $VARIABLE_GROUP_ID if [ -z ${VARIABLE_GROUP_ID} ]; then echo "##vso[task.logissue type=error]Variable group $(variable_group) could not be found." exit 2 fi echo "##vso[build.updatebuildnumber]Deploying ${SAP_SYSTEM_CONFIGURATION_NAME} using SAP CAL" echo "##vso[task.setvariable variable=SID;isOutput=true]${SID}" echo "##vso[task.setvariable variable=SAP_PARAMETERS;isOutput=true]sap-parameters.yaml" echo "##vso[task.setvariable variable=FOLDER;isOutput=true]$HOME/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME}" echo "##vso[task.setvariable variable=HOSTS;isOutput=true]${SID}_hosts.yaml" echo -e "$green--- Get Files from the DevOps Repository ---$reset" cd ${CONFIG_REPO_PATH}/$(Deployment_Configuration_Path)/SYSTEM/${SAP_SYSTEM_CONFIGURATION_NAME} sap_params_updated=0 fqdn="$(grep -m1 "$sap_fqdn:" sap-parameters.yaml | cut -d':' -f2- | tr -d ' ' | tr -d '"')" if [ -z $fqdn ] ; then sed -i 's|sap_fqdn:.*|sap_fqdn: '"$(sap_fqdn)"'|' sap-parameters.yaml fi if [[ -n "${sapcalProductName}" ]]; then echo -e "$green--- Add SAP CAL Product Name $sapcalProductName to sap-parameters.yaml ---$reset" sed -i 's|sap_cal_product_name:.*|sap_cal_product_name: '"$sapcalProductName"'|' sap-parameters.yaml fi echo -e "$green--- Get connection details ---$reset" mkdir -p artifacts az_var=$(az pipelines variable-group variable list --group-id ${VARIABLE_GROUP_ID} --query "${NETWORK}"Workload_Key_Vault.value --output tsv) if [ -z ${az_var} ]; then export workload_key_vault=$(cat "${environment_file_name}" | grep workloadkeyvault | awk -F'=' '{print $2}' | xargs) ; echo 'Workload Key Vault' ${workload_key_vault} else export workload_key_vault=${az_var} ; echo 'Workload Key Vault' ${workload_key_vault} ; fi az_var=$(az pipelines variable-group variable list --group-id ${VARIABLE_GROUP_ID} --query "${NETWORK}"Workload_Secret_Prefix.value --output tsv) if [ -z ${az_var} ]; then export workload_prefix=$(cat "${environment_file_name}" | grep workload_zone_prefix | awk -F'=' '{print $2}' | xargs) ; echo 'Workload Prefix' ${workload_prefix} else export workload_prefix=${az_var} ; echo 'Workload Prefix' ${workload_prefix}; fi az_var=$(az pipelines variable-group variable list --group-id ${VARIABLE_GROUP_ID} --query Terraform_Remote_Storage_Subscription.value --output tsv) if [ -z ${az_var} ]; then export control_plane_subscription=$(cat "${environment_file_name}" | grep STATE_SUBSCRIPTION | awk -F'=' '{print $2}' | xargs) ; echo 'Control Plane Subscription' ${control_plane_subscription} else export control_plane_subscription=${az_var} ; echo 'Control Plane Subscription' ${control_plane_subscription} fi if [[ $EXTRA_PARAMETERS = "'$(EXTRA_PARAMETERS)'" ]]; then new_parameters=$PIPELINE_EXTRA_PARAMETERS else echo "##vso[task.logissue type=warning]Extra parameters were provided - '$EXTRA_PARAMETERS'" new_parameters="$EXTRA_PARAMETERS $PIPELINE_EXTRA_PARAMETERS" fi echo "##vso[task.setvariable variable=SSH_KEY_NAME;isOutput=true]${workload_prefix}-sid-sshkey" echo "##vso[task.setvariable variable=VAULT_NAME;isOutput=true]$workload_key_vault" echo "##vso[task.setvariable variable=PASSWORD_KEY_NAME;isOutput=true]${workload_prefix}-sid-password" echo "##vso[task.setvariable variable=USERNAME_KEY_NAME;isOutput=true]${workload_prefix}-sid-username" echo "##vso[task.setvariable variable=NEW_PARAMETERS;isOutput=true]${new_parameters}" echo "##vso[task.setvariable variable=CP_SUBSCRIPTION;isOutput=true]${control_plane_subscription}" echo -e "$green--- az login ---$reset" # If the deployer_file exists we run on a deployer configured by the framework instead of a azdo hosted one deployer_file=/etc/profile.d/deploy_server.sh if [ "$USE_MSI" = "true" ]; then echo "Using MSI" source /etc/profile.d/deploy_server.sh az account set --subscription $control_plane_subscription else if [ ! -n $AZURE_CLIENT_ID ]; then echo "##vso[task.logissue type=error]Variable ARM_CLIENT_ID was not defined." exit 2 fi if [ ! -n $AZURE_CLIENT_SECRET ]; then echo "##vso[task.logissue type=error]Variable ARM_CLIENT_SECRET was not defined." exit 2 fi if [ ! -n $AZURE_TENANT_ID ]; then echo "##vso[task.logissue type=error]Variable ARM_TENANT_ID was not defined." exit 2 fi az login --service-principal --username $AZURE_CLIENT_ID --password=${AZURE_CLIENT_SECRET} --tenant $AZURE_TENANT_ID --output none return_code=$? if [ 0 != $return_code ]; then echo -e "$boldred--- Login failed ---$reset" echo "##vso[task.logissue type=error]az login failed." exit $return_code fi az account set --subscription $control_plane_subscription fi return_code=$? if [ 0 != $return_code ]; then echo -e "$boldred--- Login failed ---$reset" echo "##vso[task.logissue type=error]az login failed." exit $return_code fi az_var=$(az pipelines variable-group variable list --group-id ${VARIABLE_GROUP_ID} --query "Deployer_Key_Vault.value" | tr -d \") if [ -n ${az_var} ]; then kv_name=${az_var}; echo "Key Vault="$kv_name else kv_name=$(cat .sap_deployment_automation/$(environment_code)$(location_code) | grep keyvault |awk -F'=' '{print $2}'); echo "Key Vault="$kv_name fi echo "##vso[task.setvariable variable=KV_NAME;isOutput=true]$kv_name" if [ "your S User" == "${SUsername}" ]; then echo "##vso[task.logissue type=error]Please define the S-Username variable." exit 2 fi if [ "your S user password" == "${SPassword}" ]; then echo "##vso[task.logissue type=error]Please define the S-Password variable." exit 2 fi echo -e "$green--- Set S-Username and S-Password in the key_vault if not yet there ---$reset" export SUsernamefromVault=$(az keyvault secret list --vault-name "${kv_name}" --subscription "${ARM_SUBSCRIPTION_ID}" --query "[].{Name:name} | [? contains(Name,'S-Username')] | [0]" -o tsv) if [ $SUsernamefromVault == $SUsername ]; then echo -e "$green--- $SUsername present in keyvault. In case of download errors check that user and password are correct ---$reset" echo "##vso[task.setvariable variable=SUSERNAME;isOutput=true]$SUsernamefromVault" else echo -e "$green--- Setting the S username in key vault ---$reset" az keyvault secret set --name "S-Username" --vault-name $kv_name --value="${SUsername}" --subscription "${ARM_SUBSCRIPTION_ID}" --expires "$(date -d '+1 year' -u +%Y-%m-%dT%H:%M:%SZ)" --output none echo "##vso[task.setvariable variable=SUSERNAME;isOutput=true]$SUsername" fi export SPasswordfromVault=$(az keyvault secret list --vault-name "${kv_name}" --subscription "${ARM_SUBSCRIPTION_ID}" --query "[].{Name:name} | [? contains(Name,'S-Password')] | [0]" -o tsv) if [ ${SPassword} == $SPasswordfromVault ]; then echo "##vso[task.setvariable variable=SPASSWORD;isOutput=true]${SPasswordfromVault}" echo -e "$green--- Password present in keyvault. In case of download errors check that user and password are correct ---$reset" else echo -e "$green--- Setting the S user name password in key vault ---$reset" az keyvault secret set --name "S-Password" --vault-name $kv_name --value "${SPassword}" --subscription "${ARM_SUBSCRIPTION_ID}" --expires "$(date -d '+1 year' -u +%Y-%m-%dT%H:%M:%SZ)" --output none echo "##vso[task.setvariable variable=SPASSWORD;isOutput=true]${SPassword}" fi az keyvault secret show --name ${workload_prefix}-sid-sshkey --vault-name $workload_key_vault --subscription $AZURE_SUBSCRIPTION_ID --query value -o tsv > artifacts/${SAP_SYSTEM_CONFIGURATION_NAME}_sshkey cp sap-parameters.yaml artifacts/. cp ${SID}_hosts.yaml artifacts/. 2> >(while read line; do (>&2 echo "STDERROR: $line"); done) name: Preparation displayName: Preparation for Ansible env: SCRIPT_PATH: $${{ parameters.sap_automation_repo_path }}/deploy/pipelines/templates/*.sh SYSTEM_ACCESSTOKEN: $(System.AccessToken) AZURE_DEVOPS_EXT_PAT: $(System.AccessToken) ANSIBLE_HOST_KEY_CHECKING: false AZURE_CLIENT_ID: $(ARM_CLIENT_ID) AZURE_CLIENT_SECRET: $(ARM_CLIENT_SECRET) AZURE_TENANT_ID: $(ARM_TENANT_ID) AZURE_SUBSCRIPTION_ID: $(Terraform_Remote_Storage_Subscription) ANSIBLE_COLLECTIONS_PATH: /opt/ansible/collections CONFIG_REPO_PATH: ${{ parameters.config_repo_path }} SAP_SYSTEM_CONFIGURATION_NAME: ${{ parameters.sap_system_configuration_name }} EXTRA_PARAMETERS: $(EXTRA_PARAMETERS) PIPELINE_EXTRA_PARAMETERS: ${{ parameters.extra_params }} USE_MSI: $(USE_MSI) SUsername: $(S-Username) SPassword: $(S-Password) sapcalProductName: ${{ parameters.sap_cal_product_name }} - template: templates\run-ansible.yaml parameters: displayName: "Parameter validation" ansibleFilePath: ${{ parameters.sap_automation_repo_path }}/deploy/ansible/playbook_00_validate_parameters.yaml secretName: "$(Preparation.SSH_KEY_NAME)" passwordSecretName: "$(Preparation.PASSWORD_KEY_NAME)" userNameSecretName: "$(Preparation.USERNAME_KEY_NAME)" vaultName: $(Preparation.VAULT_NAME) parametersFolder: $(Preparation.FOLDER) sapParams: "${{ parameters.config_repo_path }}/$(Deployment_Configuration_Path)/SYSTEM/${{ parameters.sap_system_configuration_name }}/artifacts/$(Preparation.SAP_PARAMETERS)" sidHosts: $(Preparation.HOSTS) extraParams: "$(Preparation.NEW_PARAMETERS)" azureClientId: $(ARM_CLIENT_ID) azureClientSecret: $(ARM_CLIENT_SECRET) azureTenantId: $(ARM_TENANT_ID) azureSubscriptionId: $(ARM_SUBSCRIPTION_ID) USE_MSI: $(USE_MSI) - ${{ if eq(parameters.base_os_configuration, true) }}: - template: templates\run-ansible.yaml parameters: displayName: "Operating System Configuration" ansibleFilePath: ${{ parameters.sap_automation_repo_path }}/deploy/ansible/playbook_01_os_base_config.yaml secretName: "$(Preparation.SSH_KEY_NAME)" passwordSecretName: "$(Preparation.PASSWORD_KEY_NAME)" userNameSecretName: "$(Preparation.USERNAME_KEY_NAME)" vaultName: $(Preparation.VAULT_NAME) parametersFolder: $(Preparation.FOLDER) sapParams: "${{ parameters.config_repo_path }}/$(Deployment_Configuration_Path)/SYSTEM/${{ parameters.sap_system_configuration_name }}/artifacts/$(Preparation.SAP_PARAMETERS)" sidHosts: $(Preparation.HOSTS) extraParams: "$(Preparation.NEW_PARAMETERS)" azureClientId: $(ARM_CLIENT_ID) azureClientSecret: $(ARM_CLIENT_SECRET) azureTenantId: $(ARM_TENANT_ID) azureSubscriptionId: $(ARM_SUBSCRIPTION_ID) USE_MSI: $(USE_MSI) - ${{ if eq(parameters.sap_os_configuration, true) }}: - template: templates\run-ansible.yaml parameters: displayName: "SAP Specific Operating System Configuration" ansibleFilePath: ${{ parameters.sap_automation_repo_path }}/deploy/ansible/playbook_02_os_sap_specific_config.yaml secretName: "$(Preparation.SSH_KEY_NAME)" passwordSecretName: "$(Preparation.PASSWORD_KEY_NAME)" userNameSecretName: "$(Preparation.USERNAME_KEY_NAME)" vaultName: $(Preparation.VAULT_NAME) parametersFolder: $(Preparation.FOLDER) sapParams: "${{ parameters.config_repo_path }}/$(Deployment_Configuration_Path)/SYSTEM/${{ parameters.sap_system_configuration_name }}/artifacts/$(Preparation.SAP_PARAMETERS)" sidHosts: $(Preparation.HOSTS) extraParams: "$(Preparation.NEW_PARAMETERS)" azureClientId: $(ARM_CLIENT_ID) azureClientSecret: $(ARM_CLIENT_SECRET) azureTenantId: $(ARM_TENANT_ID) azureSubscriptionId: $(ARM_SUBSCRIPTION_ID) USE_MSI: $(USE_MSI) - ${{ if eq(parameters.sapcal_integration, true) }}: - template: templates\run-ansible.yaml parameters: displayName: "SAPCAL Integration" ansibleFilePath: ${{ parameters.sap_automation_repo_path }}/deploy/ansible/playbook_sapcal_integration.yaml secretName: "$(Preparation.SSH_KEY_NAME)" passwordSecretName: "$(Preparation.PASSWORD_KEY_NAME)" userNameSecretName: "$(Preparation.USERNAME_KEY_NAME)" vaultName: $(Preparation.VAULT_NAME) parametersFolder: $(Preparation.FOLDER) sapParams: "${{ parameters.config_repo_path }}/$(Deployment_Configuration_Path)/SYSTEM/${{ parameters.sap_system_configuration_name }}/artifacts/$(Preparation.SAP_PARAMETERS)" sidHosts: $(Preparation.HOSTS) extraParams: "$(Preparation.NEW_PARAMETERS)" azureClientId: $(ARM_CLIENT_ID) azureClientSecret: $(ARM_CLIENT_SECRET) azureTenantId: $(ARM_TENANT_ID) azureSubscriptionId: $(ARM_SUBSCRIPTION_ID) sapcalProductName: ${{ parameters.sap_cal_product_name }} USE_MSI: $(USE_MSI) - template: templates\collect-calapi-file.yaml parameters: filePath: ${{ parameters.config_repo_path }}/$(Deployment_Configuration_Path)/SYSTEM/${{ parameters.sap_system_configuration_name }}