Skip to content

AEM – Automation — Package Deployment

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:

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.

SKYDEVOPS -- AEM Replication Agents on Author
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
  1. 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:toolscurl76bincurl.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:toolscurl76bincurl.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

Shashi View All

A passionate devops and automation engineer

Leave a comment