January 4, 2021
Estimated Post Reading Time ~

Automation of Package Deployment in AEM

SYNOPSIS:

Following is the guide to Download, Install, Replicate AEM Package and Flush the Dispatcher Cache. The Job can be achieved in several different ways, and there is always room for improvement. In this tutorial we shall download the package from lower environments and install the downloaded package to a different environment.

This Tutorial is an advancement to the following blog AEM-Download,Install,Replicate.

Tools Used:

  • Powershell
  • cURL
  • Windows 10 Enterprise
  • Jenkins

Prerequisites:
ACS Commons Package, make sure the package is available on the Author instance where the package is being installed, Script utilizes the acs commons dispatcher flush component to trigger the dispatcher flush agent under the Replication — agents on author.
Compatibility — Check package compatibility with the following at Compatibility chart and Download the respective package
Download — Package can be downloaded from Download–ACS Commons 3.19.0
ACS Commons Installation Guide
Jenkins Plugins used

  1. Parameterized Build Plugin
  2. Cloudbees Credentials Plugin
  3. Credentials Binding Plugin
  4. Powershell Plugin

Guide:
STEP-01: Agents on Author — Target Host

Configuring the Dispatcher flush agent of the Target Host machine, and ACS Commons dispatcher flush component on Target Host.
Replication Agents on Author
  1. Go to the miscadmin URL
  2. From the left sidebar menu select Replication
  3. Under the Replication, select Agents on Author
  4. From the Main Menu, Double-Click Dispatcher Flush Agent
Dispatcher Flush Agent
  1. Go to Dispatcher Flush Agent URL
  2. Click Edit, to configure Dispatcher
Dispatcher Flush Settings TAB
  1. Go to SETTINGS tab
  2. Name the Dispatcher flush Agent
  3. Enable Flush Agent
Dispatcher Flush Agent — Transport TAB
  1. Go to Transport TAB
  2. Add the URI for the Dispatcher instance
Dispatcher Flush Agent — Triggers TAB
  1. Go to the Triggers TAB
  2. Enable the on/off time Boundary value for page
  3. Finally Save all settings by clicking OK.
STEP – 02: ACS Commons — Dispatcher Flush
Using the acs commons package, we shall trigger the dispatcher flush agent and the path to flush using dispatcher flush agent
ACS Commons — Dispatcher Flush
  1. Go to acs commons dispatcher flush url
  2. Select Acs Commons from the left sidebar
  3. Select Dispatcher Flush under ACS Commons
  4. Click New on the main dispatcher flush page
Dispatcher Flush Agent — Template
  1. Add Title to the agent
  2. Select the dispatcher flush Template
  3. Finally, Click create
ACS Commons — Custom Dispatcher Flush
  1. Select the newly created flush agent ‘sd-disp-flush’
  2. Double Click on the Flush agent to configure
Flush Agent — Configuration
  1. Verify the Name of the Agent
  2. This is the Dispatcher Flush Agent from Agents on Author (from previous step)
  3. Click on EDIT, to configure the flush agent
Cache Flush Method
Select whether to delete or invalidate cache
Paths to flush
  1. Click on Add Item, to add path to be flushed
  2. Select the appropriate path to form the list
  3. Repeat step-2 to add additional paths
  4. When done adding paths, click OK to save configuration
STEP-03: Powershell Script For Automation
  1. Declaring required Parameters and variables
param( [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CURLEXE = "C:\tools\curl76\bin\curl.exe", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$AEMENV = "PROD", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$packageName = "$ENV:Enter_Package_Name", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CQ_USER = "$ENV:SDUsernameUAT", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CQ_PASSD = "$ENV:SDPasswordUAT", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CQ_PASSI = "$ENV:SDpasswordPRD", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$HOSTNAMED = "192.168.2.7", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$HOSTNAMEI = "192.168.2.9", [parameter(Mandatory=$False,ValueFromPipeline=$False)][Int]$AEMPORTD = 4502, [parameter(Mandatory=$False,ValueFromPipeline=$False)][Int]$AEMPORTI = 4502, [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$packURL = "http://${HOSTNAMED}:${AEMPORTD}/crx/packmgr/list.jsp", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$packData = (cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSD}" "${packURL}" 2>$null), [parameter(Mandatory=$False,ValueFromPipeline=$False)]$psData = ( $packData | ConvertFrom-JSON ), [parameter(Mandatory=$False,ValueFromPipeline=$False)][String[]]$packDName = @(($psData.results | ? { $_.Name -eq "$packageName"}).downloadName), [parameter(Mandatory=$False,ValueFromPipeline=$False)][String[]]$GroupData = @(($psData.results | ? { $_.Name -eq "$packageName" }).group), [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$GroupName = ($GroupData[($GroupData.length)-1]), [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$PKGNAME = $packDName[($packDName.length)-1], [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$PKGPATH = "${PKGNAME}", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$ValidationURL = "http://${HOSTNAMEI}:${AEMPORTI}/crx/packmgr/index.jsp#/etc/packages/${GroupName}/${PKGNAME}", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$DCURL = "http://${HOSTNAMED}:${AEMPORTD}/etc/packages/${GroupName}/${PKGNAME}", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$ICURL = "http://${HOSTNAMEI}:${AEMPORTI}/crx/packmgr/service.jsp", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$RCURL = "http://${HOSTNAMEI}:${AEMPORTI}/crx/packmgr/service/script.html/etc/packages/${GroupName}/${PKGNAME}?cmd=replicate", [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$DFLUSH = "http://${HOSTNAMEI}:${AEMPORTI}/etc/acs-commons/dispatcher-flush/sd-disp-flush/_jcr_content/configuration.flush.html" )

2. Function Block — Begin{}
Begin {
        # Stopping the job if it encounters error 
        $ErrorActionPreference  = 'Stop'
        $ScriptName       =   $MyInvocation.MyCommand.Name
        # Clear-Host
        Write-Host -F Green  " "
        Write-Host -F Green  "****************************************************************" 
        Write-Host -F Green  "Starting $AEMENV Deploy Process at [$([DateTime]::Now)]."  
        Write-Host -F Green  "***************************************************************" 
        Write-Host -F Green  " " 
        Write-Host -F Green  "Script Name:                  $ScriptName"
        Write-Host -F Green  "Environment:                  $AEMENV"
        Write-Host -F Green  "Download Host Details:        $HOSTNAMED, $AEMPORTD"
        Write-Host -F Green  "Install Host Details:         $HOSTNAMEI, $AEMPORTI"
        Write-Host -F Green  "Package Name:                 $PKGNAME"
        Write-Host -F Green  "Package Group:                $GroupName"
        Write-Host -F Green  " " 
        Write-Host -F Green  "**************************************************************" 
        Write-Host -F Green  " "
    }

Custom Code to Check if Group Name contains spaces  and replace them with HTML URL encoding — PROCESS{} Block

if ($GroupName -like "* *") {

    $DCURL  =   ($DCURL).Replace(' ','%20')

    $ICURL  =   ($ICURL).Replace(' ','%20')

    $RCURL  =   ($RCURL).Replace(' ','%20')

    $DFLUSH =   ($DFLUSH).Replace(' ','%20')

    $ValidationURL =    ($ValidationURL).Replace(' ','%20')

}

Custom code block to check if the Installation Host is using http or https and based on that change the URL

if ($AEMPORTI -eq '5443') {

    $ICURL  =   ($ICURL).Replace('http','https')

    $RCURL  =   ($RCURL).Replace('http','https')

    $DFLUSH =   ($DFLUSH).Replace('http','https')

    $ValidationURL = ($ValidationURL).Replace('http','https')

}

Custom code to Download the package

# Downlaod Package --BEGIN

Write-Host " "

Write-Host -F Green ">>>> Downloading Package $PKGNAME from $HOSTNAMED"

Write-Host -F Green " "

cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSD}" "${DCURL}" --Output "${PKGPATH}"

if ($?) {

    $DwnEC = "True"

    Write-Host -F Green " "

    Write-Host -F Green ">>>> Package Downlaod Complete"

    Write-Host -F Green " "

}else {

    Write-Host -F Green " "

    Write-Host -F RED ">>>> Package Downlaod Failed"

    Write-Host -F Green " "

}

Custom code to upload and install the downloaded package, the upload and installation will only commence if the package download is successful.

# Download package --END

if ($DwnEC -eq "True") {

    # Installing the Package --BEGIN

    Write-Host -F Green " "

    Write-Host -F Green ">>>> Installing $PKGNAME Package on $HOSTNAMEI"

    Write-Host -F Green " "

    if ($AEMPORTI -eq 5443) {

        cmd.exe /c $CURLEXE -ku "${CQ_USER}:${CQ_PASSD}" -F file=@"${PKGPATH}" -F name="${packageName}" -F force=true -F install=true "${ICURL}" | Out-Null

    }else {

        cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSD}" -F file=@"${PKGPATH}" -F name="${packageName}" -F force=true -F install=true "${ICURL}" | Out-Null

    }

    if ($?) {

        $INSTEC = "True"

        Write-Host -F Green " "

        Write-Host -F Green ">>>> Package Installation Complete"

        Write-Host -F Green " "

    }else {

        Write-Host -F Green " "

        Write-Host -F RED ">>>> Package Installation Failed"

        Write-Host -F Green " "

    }

    # Package Installation --END

}

Following is the entire script to download the package, upload and install, replicate the package and finally clear the dispatcher cache

param(

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CURLEXE          =   "C:\tools\curl76\bin\curl.exe",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$AEMENV           =   "PROD",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$packageName      =   "$ENV:Enter_Package_Name",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CQ_USER          =   "$ENV:SDUsernameUAT",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CQ_PASSD         =   "$ENV:SDPasswordUAT",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$CQ_PASSI         =   "$ENV:SDpasswordPRD",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$HOSTNAMED        =   "192.168.2.7",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$HOSTNAMEI        =   "192.168.2.9",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][Int]$AEMPORTD            =   4502,

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][Int]$AEMPORTI            =   4502,

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$packURL          =   "http://${HOSTNAMED}:${AEMPORTD}/crx/packmgr/list.jsp",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$packData         =   (cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSD}" "${packURL}" 2>$null),

     [parameter(Mandatory=$False,ValueFromPipeline=$False)]$psData                   =   ( $packData | ConvertFrom-JSON ),

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String[]]$packDName      =   @(($psData.results | ? { $_.Name -eq "$packageName"}).downloadName),

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String[]]$GroupData      =   @(($psData.results | ? { $_.Name -eq "$packageName" }).group),

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$GroupName        =   ($GroupData[($GroupData.length)-1]),

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$PKGNAME          =   $packDName[($packDName.length)-1],

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$PKGPATH          =   "${PKGNAME}",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$ValidationURL    =   "http://${HOSTNAMEI}:${AEMPORTI}/crx/packmgr/index.jsp#/etc/packages/${GroupName}/${PKGNAME}",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$DCURL            =   "http://${HOSTNAMED}:${AEMPORTD}/etc/packages/${GroupName}/${PKGNAME}",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$ICURL            =   "http://${HOSTNAMEI}:${AEMPORTI}/crx/packmgr/service.jsp",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$RCURL            =   "http://${HOSTNAMEI}:${AEMPORTI}/crx/packmgr/service/script.html/etc/packages/${GroupName}/${PKGNAME}?cmd=replicate",

     [parameter(Mandatory=$False,ValueFromPipeline=$False)][String]$DFLUSH           =   "http://${HOSTNAMEI}:${AEMPORTI}/etc/acs-commons/dispatcher-flush/sd-disp-flush/_jcr_content/configuration.flush.html"

)


Function SDProdDeploy {

    Begin {

        # Stopping the job if it encounters error 

        $ErrorActionPreference  = 'Stop'

        $ScriptName       =   $MyInvocation.MyCommand.Name

        # Clear-Host

        Write-Host -F Green  " "

        Write-Host -F Green  "***************************************************************" 

        Write-Host -F Green  "Starting $AEMENV Deploy Process at [$([DateTime]::Now)]."  

        Write-Host -F Green  "*************************************************************" 

        Write-Host -F Green  " " 

        Write-Host -F Green  "Script Name:                  $ScriptName"

        Write-Host -F Green  "Environment:                  $AEMENV"

        Write-Host -F Green  "Download Host Details:        $HOSTNAMED, $AEMPORTD"

        Write-Host -F Green  "Install Host Details:         $HOSTNAMEI, $AEMPORTI"

        Write-Host -F Green  "Package Name:                 $PKGNAME"

        Write-Host -F Green  "Package Group:                $GroupName"

        Write-Host -F Green  " " 

        Write-Host -F Green  "**************************************************************" 

        Write-Host -F Green  " "

    }

    Process {

        if ($packDName -ne $null) {


            # Check if group name contains spaces

            if ($GroupName -like "* *") {

                $DCURL  =   ($DCURL).Replace(' ','%20')

                $ICURL  =   ($ICURL).Replace(' ','%20')

                $RCURL  =   ($RCURL).Replace(' ','%20')

                $DFLUSH =   ($DFLUSH).Replace(' ','%20')

                $ValidationURL =    ($ValidationURL).Replace(' ','%20')

            }

            if ($AEMPORTI -eq '5443') {

                $ICURL  =   ($ICURL).Replace('http','https')

                $RCURL  =   ($RCURL).Replace('http','https')

                $DFLUSH =   ($DFLUSH).Replace('http','https')

                $ValidationURL = ($ValidationURL).Replace('http','https')

            }

            # Downlaod Package --BEGIN

            Write-Host " "

            Write-Host -F Green ">>>> Downloading Package $PKGNAME from $HOSTNAMED"

            Write-Host -F Green " "

            cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSD}" "${DCURL}" --Output "${PKGPATH}"

            if ($?) {

                $DwnEC = "True"

                Write-Host -F Green " "

                Write-Host -F Green ">>>> Package Downlaod Complete"

                Write-Host -F Green " "

            }else {

                Write-Host -F Green " "

                Write-Host -F RED ">>>> Package Downlaod Failed"

                Write-Host -F Green " "

            }

            # Download package --END

            if ($DwnEC -eq "True") {

                # Installing the Package --BEGIN

                Write-Host -F Green " "

                Write-Host -F Green ">>>> Installing $PKGNAME Package on $HOSTNAMEI"

                Write-Host -F Green " "

                if ($AEMPORTI -eq 5443) {

                    cmd.exe /c $CURLEXE -ku "${CQ_USER}:${CQ_PASSD}" -F file=@"${PKGPATH}" -F name="${packageName}" -F force=true -F install=true "${ICURL}" | Out-Null

                }else {

                    cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSD}" -F file=@"${PKGPATH}" -F name="${packageName}" -F force=true -F install=true "${ICURL}" | Out-Null

                }

                if ($?) {

                    $INSTEC = "True"

                    Write-Host -F Green " "

                    Write-Host -F Green ">>>> Package Installation Complete"

                    Write-Host -F Green " "

                }else {

                    Write-Host -F Green " "

                    Write-Host -F RED ">>>> Package Installation Failed"

                    Write-Host -F Green " "

                }

                # Package Installation --END

            }

            if ($INSTEC -eq "True") {

                # Replicate Package --BEGIN

                Write-Host -F Green " "

                Write-Host -F Green ">>>> Replicating Package $PKGNAME on $HOSTNAMEI"

                Write-Host -F Green " "

                if ($AEMPORTI -eq 5443) {

                    cmd.exe /c $CURLEXE -ku "${CQ_USER}:${CQ_PASSI}" -X POST $RCURL | Out-Null

                }else {

                    cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSI}" -X POST $RCURL | Out-Null

                }

                if ($?) {

                    $REPEC = "True"

                    Write-Host -F Green " "

                    Write-Host -F Green ">>>> Package Replication Complete"

                    Write-Host -F Green " "

                }else {

                    Write-Host -F Green " "

                    Write-Host -F RED ">>>> Package Replication Failed"

                    Write-Host -F Green " "

                }

                # Package Replication --END

            }

            if ($REPEC -eq "True") {

                # Flush Dispatcher using ACS Commons --BEGIN

                Write-Host -F Green " "

                Write-Host -F Green ">>>> Flushing Dispatcher Cache"

                Write-Host -F Green " "

                if ($AEMPORTI -eq 5443) {

                    cmd.exe /c $CURLEXE -ku "${CQ_USER}:${CQ_PASSI}" -X POST $DFLUSH | Out-Null

                }else {

                    cmd.exe /c $CURLEXE -u "${CQ_USER}:${CQ_PASSI}" -X POST $DFLUSH | Out-Null

                }

                if ($?) {

                    Write-Host -F Green " "

                    Write-Host -F Green ">>>> Dispatcher Flush Complete"

                    Write-Host -F Green " "

                }else {

                    Write-Host -F Green " "

                    Write-Host -F RED ">>>> Dispatcher Flush Failed"

                    Write-Host -F Green " "

                }

            }

        }else {

            Write-Host -F Red ">>>>"   Package Name: ($packageName).toupper()   "-- Not Found."

        }

    }

   End {

     If ($?) {

       Write-Host -F Green ""

       Write-Host -F Green ">>>> Verification URL"

       Write-Host -F Green "Install Host URL: $ValidationURL"

       Write-Host -F Green ""

       Write-Host -F Green "**************************************************************"

       Write-Host -F Green "Finished processing at [$([DateTime]::Now)]."

       Write-Host -F Green "*************************************************************"

       Write-Host -F Green ""

     }

  }

}

SDProdDeploy


STEP-04: Automating the Package deployment using Jenkins and Powershell
Following is the process, where package name is given as input to the build job on Jenkins. Then based on the package name, script will parse through AEM [Download Host], if found, will gather DownloadName, Groupname of the package.
Project Description
  1. Go to General TAB
  2. Add the project description
Housekeeping
  1. Select the House keeping strategy for the project
  2. Mention the number of days to keep the builds
  3. Mention max number of builds to keep
Extensible Choice Parameter
We shall use the extensible choice parameter, if not already install, got to plugin manager and install the plugin, see prerequisites
  1. Select the Extensible choice parameter
  2. Name of the Variable in the Script
  3. Describe the Variable
  4. Select the Textarea Choice parameter
  5. Add the choices as shown in the above figure
  6. Select the option, which would be displayed as the default choice
  7. Enable Editable option, to manually add package name, if package is not listed on the list
  8. Parameter to display all of selected choices
Bindings — AEM username and password
Use the credentials bindings parameter to enter the credentials for AEM instances
  1. Enable bindings by selecting Use secrets option under Build Environment
  2. Binding parameter
  3. Use the separated option
  4. Declare username variable
  5. Declare password variable
  6. Choose the credentials from credentials list to assign them to above variables
Build — Windows Powershell
Select Build Step
Add windows powershell from the list
Add the powershell script from STEP-03
Post-Build Action — Clean Workspace
Clean up the workspace after building the project
Building Project
  1. Select “Build with Parameters“
  2. click on the Textarea, Can manually enter package name here if not in list
  3. Select the desired package from the list
B
Build Output
  1. Console output of the Build
  2. Describes the Environment, AEM hosts, Port numbers, Package name and Group
  3. Information about the package being downloaded
  4. Information about the package being uploaded and installed
  5. Information about the package being Replicated
  6. Information about the flushing dispatcher cache
  7. Link/URL to the deployed AEM instance to verify the Deployment
  8. Workspace cleanup
Source:
https://skydevops.co.in/2019/02/17/aem-automation-package-deployment/


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.