AppSpec 'hooks' section - AWS CodeDeploy (original) (raw)

The content in the 'hooks' section of the AppSpec file varies, depending on the compute platform for your deployment. The 'hooks' section for an EC2/On-Premises deployment contains mappings that link deployment lifecycle event hooks to one or more scripts. The 'hooks' section for a Lambda or an Amazon ECS deployment specifies Lambda validation functions to run during a deployment lifecycle event. If an event hook is not present, no operation is executed for that event. This section is required only if you are running scripts or Lambda validation functions as part of the deployment.

Topics

AppSpec 'hooks' section for an Amazon ECS deployment

Topics

List of lifecycle event hooks for an Amazon ECS deployment

An AWS Lambda hook is one Lambda function specified with a string on a new line after the name of the lifecycle event. Each hook is executed once per deployment. Following are descriptions of the lifecycle events where you can run a hook during an Amazon ECS deployment.

For more information, see What happens during an Amazon ECS deployment and Tutorial: Deploy an Amazon ECS service with a validation test.

Run order of hooks in an Amazon ECS deployment.

In an Amazon ECS deployment, event hooks run in the following order:

The order of event hooks in an Amazon ECS deployment.

Note

The Start, Install, TestTraffic, AllowTraffic, and End events in the deployment cannot be scripted, which is why they appear in gray in this diagram.

Structure of 'hooks' section

The following are examples of the structure of the 'hooks' section.

Using YAML:

Hooks:
  - BeforeInstall: "BeforeInstallHookFunctionName"
  - AfterInstall: "AfterInstallHookFunctionName"
  - AfterAllowTestTraffic: "AfterAllowTestTrafficHookFunctionName"
  - BeforeAllowTraffic: "BeforeAllowTrafficHookFunctionName"
  - AfterAllowTraffic: "AfterAllowTrafficHookFunctionName"

Using JSON:

"Hooks": [
        {
            "BeforeInstall": "BeforeInstallHookFunctionName"
        },
        {
            "AfterInstall": "AfterInstallHookFunctionName"
        },
        {
            "AfterAllowTestTraffic": "AfterAllowTestTrafficHookFunctionName"
        },
        {
            "BeforeAllowTraffic": "BeforeAllowTrafficHookFunctionName"
        },
        {
            "AfterAllowTraffic": "AfterAllowTrafficHookFunctionName"
        }
    ]
}

Sample Lambda 'hooks' function

Use the 'hooks' section to specify a Lambda function that CodeDeploy can call to validate an Amazon ECS deployment. You can use the same function or a different one for the BeforeInstall, AfterInstall,AfterAllowTestTraffic, BeforeAllowTraffic, andAfterAllowTraffic deployment lifecycle events. Following completion of the validation tests, the Lambda AfterAllowTraffic function calls back CodeDeploy and delivers a result of Succeeded or Failed.

Important

The deployment is considered to have failed if CodeDeploy is not notified by the Lambda validation function within one hour.

Before invoking a Lambda hook function, the server must be notified of the deployment ID and the lifecycle event hook execution ID using theputLifecycleEventHookExecutionStatus command.

The following is a sample Lambda hook function written in Node.js.

'use strict';

const aws = require('aws-sdk');
const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'});

exports.handler = (event, context, callback) => {
    //Read the DeploymentId from the event payload.
    var deploymentId = event.DeploymentId;

    //Read the LifecycleEventHookExecutionId from the event payload
    var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;

    /*
     Enter validation tests here.
    */

    // Prepare the validation test results with the deploymentId and
    // the lifecycleEventHookExecutionId for CodeDeploy.
    var params = {
        deploymentId: deploymentId,
        lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
        status: 'Succeeded' // status can be 'Succeeded' or 'Failed'
    };
    
    // Pass CodeDeploy the prepared validation test results.
    codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
        if (err) {
            // Validation failed.
            callback('Validation test failed');
        } else {
            // Validation succeeded.
            callback(null, 'Validation test succeeded');
        }
    });
};

AppSpec 'hooks' section for an AWS Lambda deployment

Topics

List of lifecycle event hooks for an AWS Lambda deployment

An AWS Lambda hook is one Lambda function specified with a string on a new line after the name of the lifecycle event. Each hook is executed once per deployment. Here are descriptions of the hooks available for use in your AppSpec file.

Run order of hooks in a Lambda function version deployment

In a serverless Lambda function version deployment, event hooks run in the following order:

The order of event hooks in a Lambda deployment.

Note

The Start, AllowTraffic, and End events in the deployment cannot be scripted, which is why they appear in gray in this diagram.

Structure of 'hooks' section

The following are examples of the structure of the 'hooks' section.

Using YAML:

hooks:
   - BeforeAllowTraffic: BeforeAllowTrafficHookFunctionName
   - AfterAllowTraffic: AfterAllowTrafficHookFunctionName

Using JSON:

"hooks": [{
    "BeforeAllowTraffic": "BeforeAllowTrafficHookFunctionName"
    },
    {
    "AfterAllowTraffic": "AfterAllowTrafficHookFunctionName"
}]

Sample Lambda 'hooks' function

Use the 'hooks' section to specify a Lambda function that CodeDeploy can call to validate a Lambda deployment. You can use the same function or a different one for theBeforeAllowTraffic and AfterAllowTraffic deployment lifecycle events. Following completion of the validation tests, the Lambda validation function calls back CodeDeploy and delivers a result of Succeeded orFailed.

Important

The deployment is considered to have failed if CodeDeploy is not notified by the Lambda validation function within one hour.

Before invoking a Lambda hook function, the server must be notified of the deployment ID and the lifecycle event hook execution ID using theputLifecycleEventHookExecutionStatus command.

The following is a sample Lambda hook function written in Node.js.

'use strict';

const aws = require('aws-sdk');
const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'});

exports.handler = (event, context, callback) => {
    //Read the DeploymentId from the event payload.
    var deploymentId = event.DeploymentId;

    //Read the LifecycleEventHookExecutionId from the event payload
    var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;

    /*
     Enter validation tests here.
    */

    // Prepare the validation test results with the deploymentId and
    // the lifecycleEventHookExecutionId for CodeDeploy.
    var params = {
        deploymentId: deploymentId,
        lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
        status: 'Succeeded' // status can be 'Succeeded' or 'Failed'
    };
    
    // Pass CodeDeploy the prepared validation test results.
    codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
        if (err) {
            // Validation failed.
            callback('Validation test failed');
        } else {
            // Validation succeeded.
            callback(null, 'Validation test succeeded');
        }
    });
};

AppSpec 'hooks' section for an EC2/On-Premises deployment

Topics

List of lifecycle event hooks

An EC2/On-Premises deployment hook is executed once per deployment to an instance. You can specify one or more scripts to run in a hook. Each hook for a lifecycle event is specified with a string on a separate line. Here are descriptions of the hooks available for use in your AppSpec file.

For information about which lifecycle event hooks are valid for which deployment and rollback types, see Lifecycle event hook availability.

Note

An AppSpec file does not exist on an instance before you deploy to it. For this reason, the ApplicationStop hook does not run the first time you deploy to the instance. You can use the ApplicationStop hook the second time you deploy to an instance.
To determine the location of the last successfully deployed application revision, the CodeDeploy agent looks up the location listed in the`deployment-group-id`_last_successful_install file. This file is located in:
/opt/codedeploy-agent/deployment-root/deployment-instructions folder on Amazon Linux, Ubuntu Server, and RHEL Amazon EC2 instances.
C:\ProgramData\Amazon\CodeDeploy\deployment-instructions folder on Windows Server Amazon EC2 instances.
To troubleshoot a deployment that fails during the ApplicationStop deployment lifecycle event, see Troubleshooting a failed ApplicationStop, BeforeBlockTraffic, or AfterBlockTraffic deployment lifecycle event.

Lifecycle event hook availability

The following table lists the lifecycle event hooks available for each deployment and rollback scenario.

Lifecycle event name Auto Scaling launch deployment¹ Auto Scaling termination deployment¹ In-place deployment² Blue/green deployment: Original instances Blue/green deployment: Replacement instances Blue/green deployment rollback: Original instances Blue/green deployment rollback: Replacement instances
ApplicationStop
DownloadBundle³
BeforeInstall
Install³
AfterInstall
ApplicationStart
ValidateService
BeforeBlockTraffic
BlockTraffic³
AfterBlockTraffic
BeforeAllowTraffic
AllowTraffic³
AfterAllowTraffic
¹ For information about Amazon EC2 Auto Scaling deployments, see How Amazon EC2 Auto Scaling works with CodeDeploy. ² Also applies to the rollback of an in-place deployment. ³ Reserved for CodeDeploy operations. Cannot be used to run scripts.

Run order of hooks in a deployment

Auto Scaling launch deployments

During an Auto Scaling launch deployment, CodeDeploy runs event hooks in the following order.

For more information about Auto Scaling launch deployments, see How Amazon EC2 Auto Scaling works with CodeDeploy.

The order of event hooks during an Auto Scaling launch deployment.

Note

The Start, DownloadBundle, Install, AllowTraffic, and End events in the deployment cannot be scripted, which is why they appear in gray in this diagram. However, you can edit the 'files' section of the AppSpec file to specify what's installed during the Install event.

Auto Scaling termination deployments

During an Auto Scaling termination deployment, CodeDeploy runs event hooks in the following order.

For more information about Auto Scaling termination deployments, see Enabling termination deployments during Auto Scaling scale-in events.

The order of event hooks during an Auto Scaling termination deployment.

Note

The Start, BlockTraffic, and End events in the deployment cannot be scripted, which is why they appear in gray in this diagram.

In-place deployments

In an in-place deployment, including the rollback of an in-place deployment, event hooks are run in the following order:

Note

For in-place deployments, the six hooks related to blocking and allowing traffic apply only if you specify a Classic Load Balancer, Application Load Balancer, or Network Load Balancer from Elastic Load Balancing in the deployment group.

The order of event hooks during the rollback of an in-place deployment.

Note

The Start, DownloadBundle, Install, and End events in the deployment cannot be scripted, which is why they appear in gray in this diagram. However, you can edit the 'files' section of the AppSpec file to specify what's installed during the Install event.

Blue/green deployments

In a blue/green deployment, event hooks are run in the following order:

The order of event hooks in a blue/green deployment.

Note

The Start, DownloadBundle, Install, BlockTraffic, AllowTraffic, and End events in the deployment cannot be scripted, which is why they appear in gray in this diagram. However, you can edit the 'files' section of the AppSpec file to specify what's installed during the Install event.

Structure of 'hooks' section

The 'hooks' section has the following structure:

hooks:
   deployment-lifecycle-event-name:
     - location: script-location
       timeout: timeout-in-seconds
       runas: user-name

You can include the following elements in a hook entry after the deployment lifecycle event name:

location

Required. The location in the bundle of the script file for the revision. The location of scripts you specify in the hooks section is relative to the root of the application revision bundle. For more information, see Plan a revision for CodeDeploy.

timeout

Optional. The number of seconds to allow the script to execute before it is considered to have failed. The default is 3600 seconds (1 hour).

Note

3600 seconds (1 hour) is the maximum amount of time allowed for script execution for each deployment lifecycle event. If scripts exceed this limit, the deployment stops and the deployment to the instance fails. Make sure the total number of seconds specified in timeout for all scripts in each deployment lifecycle event does not exceed this limit.

runas

Optional. The user to impersonate when running the script. By default, this is the CodeDeploy agent running on the instance. CodeDeploy does not store passwords, so the user cannot be impersonated if the runas user needs a password. This element applies to Amazon Linux and Ubuntu Server instances only.

Referencing files in your hook scripts

If you are hooking up a script to a CodeDeploy lifecycle event as described in AppSpec 'hooks' section, and you want to reference a file (for example, helper.sh) in your script, then you will need to specify helper.sh using:

Using absolute paths

To reference a file using its absolute path, you can either:

Deployment archive location

During the DownloadBundle lifecycle event, the CodeDeploy agent extracts the revision for the deployment to a directory that has the following format:

`root-directory`/`deployment-group-id`/`deployment-id`/deployment-archive

The root-directory portion of the path is always set to either the default shown in the following table, or is controlled by the:root_dir configuration setting. For more information about configuration settings, see CodeDeploy agent configuration reference.

Agent platform Default root directory
Linux – all rpm distributions /opt/codedeploy-agent/deployment-root
Ubuntu Server – all deb distributions /opt/codedeploy-agent/deployment-root
Windows Server %ProgramData%\Amazon\CodeDeploy

From your hook scripts, you could access the current deployment archive using the the root directory path and the DEPLOYMENT_ID andDEPLOYMENT_GROUP_ID environment variables. For more information about variables you can use, see Environment variable availability for hooks.

For example, here is how you could access a data.json file that resides at the root of your revision on Linux:

#!/bin/bash

rootDirectory="/opt/codedeploy-agent/deployment-root" # note: this will be different if you
                                                      # customize the :root_dir configuration
dataFile="$rootDirectory/$DEPLOYMENT_GROUP_ID/$DEPLOYMENT_ID/deployment-archive/data.json"
data=$(cat dataFile)

As another example, here is how you could access a data.json file that resides at the root of your revision using Powershell on Windows:

                                                    # customize the :root_dir configuration <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>a</mi><mi>t</mi><mi>a</mi><mi>F</mi><mi>i</mi><mi>l</mi><mi>e</mi><mo>=</mo><mi mathvariant="normal">&quot;</mi></mrow><annotation encoding="application/x-tex">dataFile=&quot;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">&quot;</span></span></span></span>rootDirectory\$env:DEPLOYMENT_GROUP_ID\$env:DEPLOYMENT_ID\deployment-archive\data.json" <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>a</mi><mi>t</mi><mi>a</mi><mo>=</mo><mo stretchy="false">(</mo><mi>G</mi><mi>e</mi><mi>t</mi><mo>−</mo><mi>C</mi><mi>o</mi><mi>n</mi><mi>t</mi><mi>e</mi><mi>n</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">data=(Get-Content </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mord mathnormal">e</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span></span></span></span>dataFile)

Using relative paths

To reference a file using its relative path, you'll need to know the CodeDeploy agent's working directory. File paths are relative to this directory.

The following table shows the working directory for each supported platform of the CodeDeploy agent.

Agent platform Process management method Working directory for lifecycle event scripts
Linux – all rpm distributions systemd (default) /
init.d – Learn more /opt/codedeploy-agent
Ubuntu Server – all debian distributions all /opt/codedeploy-agent
Windows Server not applicable C:\Windows\System32

Environment variable availability for hooks

During each deployment lifecycle event, hook scripts can access the following environment variables:

APPLICATION_NAME

The name of the application in CodeDeploy that is part of the current deployment (for example, WordPress_App).

DEPLOYMENT_ID

The ID CodeDeploy has assigned to the current deployment (for example,d-AB1CDEF23).

DEPLOYMENT_GROUP_NAME

The name of the deployment group in CodeDeploy that is part of the current deployment (for example, WordPress_DepGroup).

DEPLOYMENT_GROUP_ID

The ID of the deployment group in CodeDeploy that is part of the current deployment (for example, b1a2189b-dd90-4ef5-8f40-4c1c5EXAMPLE).

LIFECYCLE_EVENT

The name of the current deployment lifecycle event (for example,AfterInstall).

These environment variables are local to each deployment lifecycle event.

There are additional environment variables available to hook scripts depending on the source of the deployment bundle:

Bundle from Amazon S3

Bundle from GitHub

The following script changes the listening port on an Apache HTTP server to 9090 instead of 80 if the value of DEPLOYMENT_GROUP_NAME is equal to Staging. This script must be invoked during theBeforeInstall deployment lifecycle event:

if [ "$DEPLOYMENT_GROUP_NAME" == "Staging" ]
then
    sed -i -e 's/Listen 80/Listen 9090/g' /etc/httpd/conf/httpd.conf
fi

The following script example changes the verbosity level of messages recorded in its error log from warning to debug if the value of the DEPLOYMENT_GROUP_NAME environment variable is equal toStaging. This script must be invoked during theBeforeInstall deployment lifecycle event:

if [ "$DEPLOYMENT_GROUP_NAME" == "Staging" ]
then
    sed -i -e 's/LogLevel warn/LogLevel debug/g' /etc/httpd/conf/httpd.conf
fi

The following script example replaces the text in the specified webpage with text that displays the value of these environment variables. This script must be invoked during the AfterInstall deployment lifecycle event:

#!/usr/bin/python

import os
 
strToSearch="<h2>This application was deployed using CodeDeploy.</h2>"
strToReplace="<h2>This page for "+os.environ['APPLICATION_NAME']+" application and "+os.environ['DEPLOYMENT_GROUP_NAME']+" deployment group with "+os.environ['DEPLOYMENT_GROUP_ID']+" deployment group ID was generated by a "+os.environ['LIFECYCLE_EVENT']+" script during "+os.environ['DEPLOYMENT_ID']+" deployment.</h2>"
 
fp=open("/var/www/html/index.html","r")
buffer=fp.read()
fp.close()
 
fp=open("/var/www/html/index.html","w")
fp.write(buffer.replace(strToSearch,strToReplace))
fp.close()

Hooks example

Here is an example of a hooks entry that specifies two hooks for the AfterInstall lifecycle event:

hooks:
   AfterInstall:
     - location: Scripts/RunResourceTests.sh
       timeout: 180
     - location: Scripts/PostDeploy.sh
       timeout: 180

The Scripts/RunResourceTests.sh script runs during theAfterInstall stage of the deployment process. The deployment is unsuccessful if it takes the script more than 180 seconds (3 minutes) to run.

The location of scripts you specify in the 'hooks' section is relative to the root of the application revision bundle. In the preceding example, a file namedRunResourceTests.sh is in a directory named Scripts. The Scripts directory is at the root level of the bundle. For more information, see Plan a revision for CodeDeploy.