

• The AWS Systems Manager CloudWatch Dashboard will no longer be available after April 30, 2026. Customers can continue to use Amazon CloudWatch console to view, create, and manage their Amazon CloudWatch dashboards, just as they do today. For more information, see [Amazon CloudWatch Dashboard documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html). 

# AWS Systems Manager Automation
<a name="systems-manager-automation"></a>

Automation, a tool in AWS Systems Manager, simplifies common maintenance, deployment, and remediation tasks for AWS services like Amazon Elastic Compute Cloud (Amazon EC2), Amazon Relational Database Service (Amazon RDS), Amazon Redshift, Amazon Simple Storage Service (Amazon S3), and many more. To get started with Automation, open the [Systems Manager console](https://console.aws.amazon.com/systems-manager/automation). In the navigation pane, choose **Automation**. 

Automation helps you to build automated solutions to deploy, configure, and manage AWS resources at scale. With Automation, you have granular control over the concurrency of your automations. This means you can specify how many resources to target concurrently, and how many errors can occur before an automation is stopped. 

To help you get started with Automation, AWS develops and maintains several pre-defined runbooks. Depending on your use case, you can use these pre-defined runbooks that perform a variety of tasks, or create your own custom runbooks that might better suit your needs. To monitor the progress and status of your automations, you can use the Systems Manager Automation console, or your preferred command line tool. Automation also integrates with Amazon EventBridge to help you build event-driven architecture at scale.

**Note**  
For customers who are new to Systems Manager Automation as of August 14, 2025, the Automation free tier is not available. For customers already using Automation, the free tier of service ends on December 31, 2025. For information about current service costs, see [AWS Systems Manager pricing](https://aws.amazon.com/systems-manager/pricing/).

## How can Automation benefit my organization?
<a name="automation-benefits"></a>

Automation offers these benefits:
+ **Scripting support in runbook content**

  Using the `aws:executeScript` action, you can run custom Python and PowerShell functions directly from your runbooks. This provides you greater flexibility in creating your custom runbooks because you can complete various tasks that other Automation actions don't support. You also have greater control over the logic of the runbook. For an example of how this action can be used and how it can help to improve an existing automated solution, see [Authoring Automation runbooks](automation-authoring-runbooks.md).
+  **Run automations across multiple AWS accounts and AWS Regions from a centralized location** 

  Administrators can run automations on resources across multiple accounts and Regions from the Systems Manager console.
+  **Enhanced operations security** 

  Administrators have a centralized place to grant and revoke access to runbooks. Using only AWS Identity and Access Management (IAM) policies, you can control which individual users or groups in your organization can use Automation and which runbooks they can access.
+  **Automate common IT tasks** 

  Automating common tasks can help improve operational efficiency, enforce organizational standards, and reduce operator errors. For example, you can use the `AWS-UpdateCloudFormationStackWithApproval` runbook to update resources that were deployed by using an AWS CloudFormation template. The update applies a new template. You can configure the Automation to request approval by one or more users before the update begins.
+  **Safely perform disruptive tasks in bulk** 

  Automation includes features, like rate controls, that allow you to control the deployment of an automation across your fleet by specifying a concurrency value and an error threshold. For more information about working with rate controls, see [Run automated operations at scale](running-automations-scale.md).
+ **Streamline complex tasks**

  Automation provides pre-defined runbooks that streamline complex and time-consuming tasks such as creating golden Amazon Machine Images (AMIs). For example, you can use the `AWS-UpdateLinuxAmi` and `AWS-UpdateWindowsAmi` runbooks to create golden AMIs from a source AMI. Using these runbooks, you can run custom scripts before and after updates are applied. You can also include or exclude specific software packages from being installed. For examples of how to use these runbooks, see [Tutorials](automation-tutorials.md).
+ **Define constraints for inputs**

  You can define constraints in custom runbooks to limit the values that Automation will accept for a particular input parameter. For example, `allowedPattern` will only accept values for an input parameter that match the regular expression you define. If you specify `allowedValues` for an input parameter, only the values you've specified in the runbook are accepted.
+  **Log automation action output to Amazon CloudWatch Logs** 

  To meet operational or security requirements in your organization, you might need to provide a record of the scripts run during a runbook. With CloudWatch Logs, you can monitor, store, and access log files from various AWS services. You can send output from the `aws:executeScript` action to a CloudWatch Logs log group for debugging and troubleshooting purposes. Log data can be sent to your log group with or without AWS KMS encryption using your KMS key. For more information, see [Logging Automation action output with CloudWatch Logs](automation-action-logging.md).
+  **Amazon EventBridge integration** 

  Automation is supported as a *target* type in Amazon EventBridge rules. This means you can trigger runbooks by using events. For more information, see [Monitoring Systems Manager events with Amazon EventBridge](monitoring-eventbridge-events.md) and [Reference: Amazon EventBridge event patterns and types for Systems Manager](reference-eventbridge-events.md).
+ **Share organizational best practices**

  You can define best practices for resource management, operations tasks, and more in runbooks that you share across accounts and Regions.

## Who should use Automation?
<a name="automation-who"></a>
+ Any AWS customer who wants to improve their operational efficiency at scale, reduce errors associated with manual intervention, and reduce time to resolution of common issues.
+ Infrastructure experts who want to automate deployment and configuration tasks.
+ Administrators who want to reliably resolve common issues, improve troubleshooting efficiency, and reduce repetitive operations.
+ Users who want to automate a task they normally perform manually.

## What is an automation?
<a name="what-is-an-automation"></a>

An *automation* consists of all of the tasks that are defined in a runbook, and are performed by the Automation service. Automation uses the following components to run automations.


****  

| Concept | Details | 
| --- | --- | 
|  Automation runbook  |  A Systems Manager Automation runbook defines the automation (the actions that Systems Manager performs on your managed nodes and AWS resources). Automation includes several pre-defined runbooks that you can use to perform common tasks like restarting one or more Amazon EC2 instances or creating an Amazon Machine Image (AMI). You can create your own runbooks as well. Runbooks use YAML or JSON, and they include steps and parameters that you specify. Steps run in sequential order. For more information, see [Creating your own runbooks](automation-documents.md). Runbooks are Systems Manager documents of type `Automation`, as opposed to `Command`, `Policy`, `Session` documents. Runbooks support schema version 0.3. Command documents use schema version 1.2, 2.0, or 2.2. Policy documents use schema version 2.0 or later.  | 
|  Automation action  |  The automation defined in a runbook includes one or more steps. Each step is associated with a particular action. The action determines the inputs, behavior, and outputs of the step. Steps are defined in the `mainSteps` section of your runbook. Automation supports 20 distinct action types. For more information, see the [Systems Manager Automation actions reference](automation-actions.md).  | 
|  Automation quota  |  Each AWS account can run 100 automations simultaneously. This includes child automations (automations that are started by another automation), and rate control automations. If you attempt to run more automations than this, Systems Manager adds the additional automations to a queue and displays a status of Pending. This quota can be adjusted using adaptive concurrency. For more information, see [Allowing Automation to adapt to your concurrency needs](adaptive-concurrency.md).For more information about running automations, see [Run an automated operation powered by Systems Manager Automation](running-simple-automations.md).  | 
|  Automation queue quota  |  If you attempt to run more automations than the concurrent automation limit, subsequent automations are added to a queue. Each AWS account can queue 5,000 automations. When an automation is complete (or reaches a terminal state), the first automation in the queue is started.  | 
|  Rate control automation quota  |  Each AWS account can run 25 rate control automations simultaneously. If you attempt to run more rate control automations than the concurrent rate control automation limit, Systems Manager adds the subsequent rate control automations to a queue and displays a status of Pending. For more information about running rate control automations, see [Run automated operations at scale](running-automations-scale.md).  | 
|  Rate control automation queue quota  |  If you attempt to run more automations than the concurrent rate control automation limit, subsequent automations are added to a queue. Each AWS account can queue 1,000 rate control automations. When an automation is complete (or reaches a terminal state), the first automation in the queue is started.  | 

**Topics**
+ [How can Automation benefit my organization?](#automation-benefits)
+ [Who should use Automation?](#automation-who)
+ [What is an automation?](#what-is-an-automation)
+ [Setting up Automation](automation-setup.md)
+ [Run an automated operation powered by Systems Manager Automation](running-simple-automations.md)
+ [Rerunning automation executions](automation-rerun-executions.md)
+ [Run an automation that requires approvals](running-automations-require-approvals.md)
+ [Run automated operations at scale](running-automations-scale.md)
+ [Running automations in multiple AWS Regions and accounts](running-automations-multiple-accounts-regions.md)
+ [Run automations based on EventBridge events](running-automations-event-bridge.md)
+ [Run an automation step by step](automation-working-executing-manually.md)
+ [Scheduling automations with State Manager associations](scheduling-automations-state-manager-associations.md)
+ [Schedule automations with maintenance windows](scheduling-automations-maintenance-windows.md)
+ [Systems Manager Automation actions reference](automation-actions.md)
+ [Creating your own runbooks](automation-documents.md)
+ [Systems Manager Automation Runbook Reference](automation-documents-reference.md)
+ [Tutorials](automation-tutorials.md)
+ [Learn about statuses returned by Systems Manager Automation](automation-statuses.md)
+ [Troubleshooting Systems Manager Automation](automation-troubleshooting.md)

# Setting up Automation
<a name="automation-setup"></a>

To set up Automation, a tool in AWS Systems Manager, you must verify user access to the Automation service and situationally configure roles so that the service can perform actions on your resources. We also recommend that you opt in to the adaptive concurrency mode in your Automation preferences. Adaptive concurrency automatically scales your automation quota to meet your needs. For more information, see [Allowing Automation to adapt to your concurrency needs](adaptive-concurrency.md).

To ensure proper access to AWS Systems Manager Automation, review the following user and service role requirements.

## Verifying user access for runbooks
<a name="automation-setup-user-access"></a>

Verify that you have permission to use runbooks. If your user, group, or role is assigned administrator permissions, then you have access to Systems Manager Automation. If you don't have administrator permissions, then an administrator must give you permission by assigning the `AmazonSSMFullAccess` managed policy, or a policy that provides comparable permissions, to your user, group, or role.

**Important**  
The IAM policy `AmazonSSMFullAccess` grants permissions to Systems Manager actions. However, some runbooks require permissions to other services, such as the runbook `AWS-ReleaseElasticIP`, which requires IAM permissions for `ec2:ReleaseAddress`. Therefore, you must review the actions taken in a runbook to ensure your user, group, or role is assigned the necessary permissions to perform the actions included in the runbook.

## Configuring a service role (assume role) access for automations
<a name="automation-setup-configure-role"></a>

Automations can be initiated under the context of a service role (or *assume role*). This allows the service to perform actions on your behalf. If you don't specify an assume role, Automation uses the context of the user who invoked the automation.

However, the following situations require that you specify a service role for Automation:
+ When you want to restrict a user's permissions on a resource, but you want the user to run an automation that requires elevated permissions. In this scenario, you can create a service role with elevated permissions and allow the user to run the automation.
+ When you create a Systems Manager State Manager association that runs a runbook.
+ When you have operations that you expect to run longer than 12 hours.
+ When you're running a runbook not owned by Amazon that uses the `aws:executeScript` action to call an AWS API operation or to act on an AWS resource. For information, see [Permissions for using runbooks](automation-document-script-considerations.md#script-permissions).

If you need to create a service role for Automation, you can use one of the following methods.

**Topics**
+ [Verifying user access for runbooks](#automation-setup-user-access)
+ [Configuring a service role (assume role) access for automations](#automation-setup-configure-role)
+ [Create service roles for Automation by using CloudFormation](automation-setup-cloudformation.md)
+ [Create the service roles for Automation using the console](automation-setup-iam.md)
+ [Setting up identity based policies examples](automation-setup-identity-based-policies.md)
+ [Allowing Automation to adapt to your concurrency needs](adaptive-concurrency.md)
+ [Configuring automatic retry for throttled operations](automation-throttling-retry.md)
+ [Implement change controls for Automation](automation-change-calendar-integration.md)

# Create service roles for Automation by using CloudFormation
<a name="automation-setup-cloudformation"></a>

You can create a service role for Automation, a tool in AWS Systems Manager, from an AWS CloudFormation template. After you create the service role, you can specify the service role in runbooks using the parameter `AutomationAssumeRole`.

## Create the service role using CloudFormation
<a name="create-iam-service-role"></a>

Use the following procedure to create the required AWS Identity and Access Management (IAM) role for Systems Manager Automation by using CloudFormation.

**To create the required IAM role**

1. Download and unzip the [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationServiceRole.zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationServiceRole.zip) file. This file includes the `AWS-SystemsManager-AutomationServiceRole.yaml` CloudFormation template file.

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create Stack**.

1. In the **Specify template** section, choose **Upload a template file**.

1. Choose **Browse**, and then choose the `AWS-SystemsManager-AutomationServiceRole.yaml` CloudFormation template file.

1. Choose **Next**.

1. On the **Specify stack details** page, in the **Stack name** field, enter a name. 

1. On the **Configure stack options** page, you don’t need to make any selections. Choose **Next**.

1. On the **Review** page, scroll down and choose the **I acknowledge that CloudFormation might create IAM resources** option.

1. Choose **Create**.

CloudFormation shows the **CREATE\$1IN\$1PROGRESS** status for approximately three minutes. The status changes to **CREATE\$1COMPLETE** after the stack is created and your roles are ready to use.

**Important**  
If you run an automation workflow that invokes other services by using an AWS Identity and Access Management (IAM) service role, be aware that the service role must be configured with permission to invoke those services. This requirement applies to all AWS Automation runbooks (`AWS-*` runbooks) such as the `AWS-ConfigureS3BucketLogging`, `AWS-CreateDynamoDBBackup`, and `AWS-RestartEC2Instance` runbooks, to name a few. This requirement also applies to any custom Automation runbooks you create that invoke other AWS services by using actions that call other services. For example, if you use the `aws:executeAwsApi`, `aws:createStack`, or `aws:copyImage` actions, configure the service role with permission to invoke those services. You can give permissions to other AWS services by adding an IAM inline policy to the role. For more information, see [(Optional) Add an Automation inline policy or customer managed policy to invoke other AWS services](automation-setup-iam.md#add-inline-policy).

## Copy role information for Automation
<a name="copy-iam-role-info"></a>

Use the following procedure to copy information about the Automation service role from the CloudFormation console. You must specify these roles when you use a runbook.

**Note**  
You don't need to copy role information using this procedure if you run the `AWS-UpdateLinuxAmi` or `AWS-UpdateWindowsAmi` runbooks. These runbooks already have the required roles specified as default values. The roles specified in these runbooks use IAM managed policies. 

**To copy the role names**

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Select the Automation **Stack name** you created in the previous procedure.

1. Choose the **Resources** tab.

1. Choose the **Physical ID** link for **AutomationServiceRole**. The IAM console opens to a summary of the Automation service role.

1. Copy the Amazon Resource Name (ARN) next to **Role ARN**. The ARN is similar to the following: `arn:aws:iam::12345678:role/AutomationServiceRole`

1. Paste the ARN into a text file to use later.

You have finished configuring the service role for Automation. You can now use the Automation service role ARN in your runbooks.

# Create the service roles for Automation using the console
<a name="automation-setup-iam"></a>

If you need to create a service role for Automation, a tool in AWS Systems Manager, complete the following tasks. For more information about when a service role is required for Automation, see [Setting up Automation](automation-setup.md).

**Topics**
+ [Task 1: Create a service role for Automation](#create-service-role)
+ [Task 2: Attach the iam:PassRole policy to your Automation role](#attach-passrole-policy)

## Task 1: Create a service role for Automation
<a name="create-service-role"></a>

Use the following procedure to create a service role (or *assume role*) for Systems Manager Automation.

**Note**  
You can also use this role in runbooks, such as the `AWS-CreateManagedLinuxInstance` runbook. Using this role, or the Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) role, in runbooks allows Automation to perform actions in your environment, such as launch new instances and perform actions on your behalf.

**To create an IAM role and allow Automation to assume it**

1. Open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).

1. In the navigation pane, choose **Roles**, and then choose **Create role**.

1. Under **Select type of trusted entity**, choose **AWS service**.

1. In the **Choose a use case** section, choose **Systems Manager**, and then choose **Next: Permissions**.

1. On the **Attached permissions policy** page, search for the **AmazonSSMAutomationRole** policy, choose it, and then choose **Next: Review**. 

1. On the **Review** page, enter a name in the **Role name** box, and then enter a description.

1. Choose **Create role**. The system returns you to the **Roles** page.

1. On the **Roles** page, choose the role you just created to open the **Summary** page. Note the **Role Name** and **Role ARN**. You will specify the role ARN when you attach the **iam:PassRole** policy to your IAM account in the next procedure. You can also specify the role name and the ARN in runbooks.

**Note**  
The `AmazonSSMAutomationRole` policy assigns the Automation role permission to a subset of AWS Lambda functions within your account. These functions begin with "Automation". If you plan to use Automation with Lambda functions, the Lambda ARN must use the following format:  
`"arn:aws:lambda:*:*:function:Automation*"`  
If you have existing Lambda functions whose ARNs don't use this format, then you must also attach an additional Lambda policy to your automation role, such as the **AWSLambdaRole** policy. The additional policy or role must provide broader access to Lambda functions within the AWS account.

After creating your service role, we recommend editing the trust policy to help prevent the cross-service confused deputy problem. The *confused deputy problem* is a security issue where an entity that doesn't have permission to perform an action can coerce a more-privileged entity to perform the action. In AWS, cross-service impersonation can result in the confused deputy problem. Cross-service impersonation can occur when one service (the *calling service*) calls another service (the *called service*). The calling service can be manipulated to use its permissions to act on another customer's resources in a way it should not otherwise have permission to access. To prevent this, AWS provides tools that help you protect your data for all services with service principals that have been given access to resources in your account. 

We recommend using the [https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn) and [https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourceaccount](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourceaccount) global condition context keys in resource policies to limit the permissions that Automation gives another service to the resource. If the `aws:SourceArn` value doesn't contain the account ID, such as an Amazon S3 bucket ARN, you must use both global condition context keys to limit permissions. If you use both global condition context keys and the `aws:SourceArn` value contains the account ID, the `aws:SourceAccount` value and the account in the `aws:SourceArn` value must use the same account ID when used in the same policy statement. Use `aws:SourceArn` if you want only one resource to be associated with the cross-service access. Use `aws:SourceAccount` if you want to allow any resource in that account to be associated with the cross-service use. The value of `aws:SourceArn` must be the ARN for automation executions. If you don't know the full ARN of the resource or if you're specifying multiple resources, use the `aws:SourceArn` global context condition key with wildcards (`*`) for the unknown portions of the ARN. For example, `arn:aws:ssm:*:123456789012:automation-execution/*`. 

The following example shows how you can use the `aws:SourceArn` and `aws:SourceAccount` global condition context keys for Automation to prevent the confused deputy problem.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "ssm.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:ssm:*:123456789012:automation-execution/*"
        }
      }
    }
  ]
}
```

------

**To modify the role's trust policy**

1. Open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).

1. In the navigation pane, choose **Roles**.

1. In the list of roles in your account, choose the name of your Automation service role.

1. Choose the **Trust relationships** tab, and then choose **Edit trust relationship**.

1. Edit the trust policy using the `aws:SourceArn` and `aws:SourceAccount` global condition context keys for Automation to prevent the confused deputy problem.

1. Choose **Update Trust Policy** to save your changes.

### (Optional) Add an Automation inline policy or customer managed policy to invoke other AWS services
<a name="add-inline-policy"></a>

If you run an automation that invokes other AWS services by using an IAM service role, the service role must be configured with permission to invoke those services. This requirement applies to all AWS Automation runbooks (`AWS-*` runbooks) such as the `AWS-ConfigureS3BucketLogging`, `AWS-CreateDynamoDBBackup`, and `AWS-RestartEC2Instance` runbooks, to name a few. This requirement also applies to any custom runbooks you create that invoke other AWS services by using actions that call other services. For example, if you use the `aws:executeAwsApi`, `aws:CreateStack`, or `aws:copyImage` actions, to name a few, then you must configure the service role with permission to invoke those services. You can give permissions to other AWS services by adding an IAM inline policy or customer managed policy to the role. 

**To embed an inline policy for a service role (IAM console)**

1. Sign in to the AWS Management Console and open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).

1. In the navigation pane, choose **Roles**.

1. In the list, choose the name of the role that you want to edit.

1. Choose the **Permissions** tab.

1. In the **Add permissions** dropdown, choose **Attach policies** or **Create inline policy**.

1. If you choose **Attach policies**, select the check box next to the policy you want to add and choose **Add permissions**.

1. If you choose **Create inline policy**, choose the **JSON** tab.

1. Enter a JSON Policy document for the AWS services you want to invoke. Here are two example JSON Policy documents.

   **Amazon S3 PutObject and GetObject Example**

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "s3:PutObject",
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*"
           }
       ]
   }
   ```

------

   **Amazon EC2 CreateSnapshot and DescribeSnapShots Example**

------
#### [ JSON ]

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement":[
         {
            "Effect":"Allow",
            "Action":"ec2:CreateSnapshot",
            "Resource":"*"
         },
         {
            "Effect":"Allow",
            "Action":"ec2:DescribeSnapshots",
            "Resource":"*"
         }
      ]
   }
   ```

------

   For details about the IAM policy language, see [IAM JSON Policy Reference](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) in the *IAM User Guide*.

1. When you're finished, choose **Review policy**. The [Policy Validator](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_policy-validator.html) reports any syntax errors.

1. On the **Review policy** page, enter a **Name** for the policy that you're creating. Review the policy **Summary** to see the permissions that are granted by your policy. Then choose **Create policy** to save your work.

1. After you create an inline policy, it's automatically embedded in your role.

## Task 2: Attach the iam:PassRole policy to your Automation role
<a name="attach-passrole-policy"></a>

Use the following procedure to attach the `iam:PassRole` policy to your Automation service role. This allows the Automation service to pass the role to other services or Systems Manager tools when running automations.

**To attach the iam:PassRole policy to your Automation role**

1. In the **Summary** page for the role you just created, choose the **Permissions** tab.

1. Choose **Add inline policy**.

1. On the **Create policy** page, choose the **Visual editor** tab.

1. Choose **Service**, and then choose **IAM**.

1. Choose **Select actions**.

1. In the **Filter actions** text box, type **PassRole**, and then choose the **PassRole** option.

1. Choose **Resources**. Verify that **Specific** is selected, and then choose **Add ARN**.

1. In the **Specify ARN for role** field, paste the Automation role ARN that you copied at the end of Task 1. The system populates the **Account** and **Role name with path** fields.
**Note**  
If you want the Automation service role to attach an IAM instance profile role to an EC2 instance, then you must add the ARN of the IAM instance profile role. This allows the Automation service role to pass the IAM instance profile role to the target EC2 instance.

1. Choose **Add**.

1. Choose **Review policy**.

1. On the **Review Policy** page, enter a name and then choose **Create Policy**.

# Setting up identity based policies examples
<a name="automation-setup-identity-based-policies"></a>

The following sections provide example IAM identity-based policies for AWS Systems Manager Automation service. For more information about how to create an IAM identity-based policy using these example JSON Policy documents, see [Creating IAM policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html#access_policies_create-json-editor) in the *IAM User Guide*.

**Note**  
All examples contain fictitious account IDs. The account ID shouldn't be specified in the Amazon Resource Name (ARN) for AWS owned public documents.

 **Examples** 
+  [Example 1: Allow a user to run an automation document and view the automation execution](#automation-setup-identity-based-policies-example-1) 
+  [Example 2: Allow a user to run a specific version of an automation document](#automation-setup-identity-based-policies-example-2) 
+  [Example 3: Allow a user to execute automation documents with a specific tag](#automation-setup-identity-based-policies-example-3) 
+  [Example 4: Allow a user to run an automation document when a specific tag parameter is provided for the automation execution](#automation-setup-identity-based-policies-example-4) 

## Example 1: Allow a user to run an automation document and view the automation execution
<a name="automation-setup-identity-based-policies-example-1"></a>

The following example IAM policy allows a user to do the following:
+ Run the automation document specified in the policy. The name of the document is determined by the following entry.

  ```
  arn:aws:ssm:*:111122223333:document/{{DocumentName}}
  ```
+ Stop and send signals to an automation execution.
+ View details about the automation execution after it has been started.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": "ssm:StartAutomationExecution",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:111122223333:document/{{DocumentName}}",
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ]
        },
        {
            "Action": [
                "ssm:StopAutomationExecution",
                "ssm:GetAutomationExecution",
                "ssm:DescribeAutomationExecutions",
                "ssm:DescribeAutomationStepExecutions",
                "ssm:SendAutomationSignal"
            ],
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ],
            "Effect": "Allow"
        }
    ]
}
```

------

## Example 2: Allow a user to run a specific version of an automation document
<a name="automation-setup-identity-based-policies-example-2"></a>

The following example IAM policy allows a user to run a specific version of an automation document:
+ The name of the automation document is determined by the following entry.

  ```
  arn:aws:ssm:*:111122223333:document/{{DocumentName}}
  ```
+ The version of the automation document is determined by the following entry.

  ```
  "ssm:DocumentVersion": "5"
  ```

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": "ssm:StartAutomationExecution",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:111122223333:document/{{DocumentName}}"
            ],
            "Condition": {
                "ForAnyValue:StringEquals": {
                   "ssm:DocumentVersion": ["5"]
                }
            }
        },
        {
            "Action": [
                "ssm:StartAutomationExecution"
            ],
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "ssm:StopAutomationExecution",
                "ssm:GetAutomationExecution",
                "ssm:DescribeAutomationExecutions",
                "ssm:DescribeAutomationStepExecutions",
                "ssm:SendAutomationSignal"
            ],
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ],
            "Effect": "Allow"
        }
    ]
}
```

------

## Example 3: Allow a user to execute automation documents with a specific tag
<a name="automation-setup-identity-based-policies-example-3"></a>

The following example IAM policy allows a user to run any automation document that has a specific tag:
+ The name of the automation document is determined by the following entry.

  ```
  arn:aws:ssm:*:111122223333:document/{{DocumentName}}
  ```
+ The tag of the automation document is determined by the following entry.

  ```
  "ssm:DocumentVersion": "5"
  ```

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": "ssm:StartAutomationExecution",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:111122223333:document/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/stage": "production"
                }
            }
        },
        {
            "Action": [
                "ssm:StartAutomationExecution"
            ],
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "ssm:StopAutomationExecution",
                "ssm:GetAutomationExecution",
                "ssm:DescribeAutomationExecutions",
                "ssm:DescribeAutomationStepExecutions",
                "ssm:SendAutomationSignal"
            ],
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ],
            "Effect": "Allow"
        }
    ]
}
```

------

## Example 4: Allow a user to run an automation document when a specific tag parameter is provided for the automation execution
<a name="automation-setup-identity-based-policies-example-4"></a>

The following example IAM policy grants permissions to a user to run automation documents when a specific tag parameter is provided for the automation execution:
+ Run the automation document specified in the policy. The name of the document is determined by the following entry.

  ```
  arn:aws:ssm:*:111122223333:document/{{DocumentName}}
  ```
+ Must provide a specific tag parameter for the automation execution. The tag parameter for the automation execution resource is determined by the following entry.

  ```
  "aws:ResourceTag/stage": "production"
  ```
+ Stop and send signals to automation executions that have the specified tag.
+ View details about the automation executions that have the specified tag.
+ Add the specified tag to SSM resources.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": "ssm:StartAutomationExecution",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:111122223333:document/{{DocumentName}}"
            ]
        },
        {
            "Action": [
                "ssm:StartAutomationExecution",
                "ssm:StopAutomationExecution",
                "ssm:GetAutomationExecution",
                "ssm:DescribeAutomationExecutions",
                "ssm:DescribeAutomationStepExecutions",
                "ssm:SendAutomationSignal"
            ],
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ],
            "Effect": "Allow",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/environment": "beta"
                }
            }
        },
        {
            "Action": "ssm:AddTagsToResource",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:111122223333:automation-execution/*"
            ]
        }
    ]
}
```

------

# Allowing Automation to adapt to your concurrency needs
<a name="adaptive-concurrency"></a>

By default, Automation allows you to run up to 100 concurrent automations at a time. Automation also provides an optional setting that you can use to adjust your concurrency automation quota automatically. With this setting, your concurrency automation quota can accommodate up to 500 concurrent automations, depending on available resources. 

**Note**  
If your automation calls API operations, adaptively scaling to your targets can result in throttling exceptions. If recurring throttling exceptions occur when running automations with adaptive concurrency turned on, you might have to request quota increases for the API operation if available.

**To turn on adaptive concurrency using the AWS Management Console**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the **Preferences** tab, and then choose **Edit**.

1. Select the check box next to **Enable adaptive concurrency**.

1. Choose **Save**.

**To turn on adaptive concurrency using the command line**
+ Open the AWS CLI or Tools for Windows PowerShell and run the following command to turn on adaptive concurrency for your account in the requesting Region.

------
#### [ Linux & macOS ]

  ```
  aws ssm update-service-setting \
      --setting-id /ssm/automation/enable-adaptive-concurrency \
      --setting-value True
  ```

------
#### [ Windows ]

  ```
  aws ssm update-service-setting ^
      --setting-id /ssm/automation/enable-adaptive-concurrency ^
      --setting-value True
  ```

------
#### [ PowerShell ]

  ```
  Update-SSMServiceSetting `
      -SettingId "/ssm/automation/enable-adaptive-concurrency" `
      -SettingValue "True"
  ```

------

# Configuring automatic retry for throttled operations
<a name="automation-throttling-retry"></a>

There is a limit on the number of concurrent automation executions that can run in each account. Attempting to run several automations concurrently in an account can lead to throttling issues. You can use the automatic throttling retry capability to configure retry behavior for throttled automation steps.

Automatic throttling retry for automation actions provides a more resilient execution environment for high-scale operations. The throttling retry capability supports all [automation actions](automation-actions.md) except for `aws:executeScript`.

The throttling retry setting works in addition to the existing `maxAttempts` step property. When both are configured, the system first attempts throttling retries within the specified time limit, then applies the `maxAttempts` setting if the step continues to fail.

**To configure throttling retry using the AWS Management Console**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the **Preferences** tab, and then choose **Edit**.

1. In the **Throttling retry time limit** field, enter a value between 0 and 3600 seconds. This specifies the maximum time that the system retries a step that is throttled.

1. Choose **Save**.

**To configure throttling retry using the command line**
+ Open the AWS CLI or Tools for Windows PowerShell and run the following command to configure throttling retry for your account in the requesting Region.

------
#### [ Linux & macOS ]

  ```
  aws ssm update-service-setting \
      --setting-id /ssm/automation/throttled-retry-time-limit \
      --setting-value 3600
  ```

------
#### [ Windows ]

  ```
  aws ssm update-service-setting ^
      --setting-id /ssm/automation/throttled-retry-time-limit ^
      --setting-value 3600
  ```

------
#### [ PowerShell ]

  ```
  Update-SSMServiceSetting `
      -SettingId "/ssm/automation/throttled-retry-time-limit" `
      -SettingValue "3600"
  ```

------

# Implement change controls for Automation
<a name="automation-change-calendar-integration"></a>

By default, Automation allows you to use runbooks without date and time constraints. By integrating Automation with Change Calendar, you can implement change controls to all automations in your AWS account. With this setting, AWS Identity and Access Management (IAM) principals in your account can only run automations during the time periods allowed by your change calendar. To learn more about working with Change Calendar, see [Working with Change Calendar](systems-manager-change-calendar-working.md).

**To turn on change controls (console)**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the **Preferences** tab, and then choose **Edit**.

1. Select the check box next to **Turn on Change Calendar integration**.

1. In the **Choose a change calendar** dropdown list, choose the change calendar that you want Automation to follow.

1. Choose **Save**.

# Run an automated operation powered by Systems Manager Automation
<a name="running-simple-automations"></a>

When you run an automation, by default, the automation runs in the context of the user who initiated the automation. This means, for example, if your user has administrator permissions, then the automation runs with administrator permissions and full access to the resources being configured by the automation. As a security best practice, we recommend that you run automation by using an IAM service role that is known in this case as an *assume* role that is configured with the AmazonSSMAutomationRole managed policy. You might need to add additional IAM policies to your assume role to use various runbooks. Using an IAM service role to run automation is called *delegated administration*.

When you use a service role, the automation is allowed to run against the AWS resources, but the user who ran the automation has restricted access (or no access) to those resources. For example, you can configure a service role and use it with Automation to restart one or more Amazon Elastic Compute Cloud (Amazon EC2) instances. Automation is a tool in AWS Systems Manager. The automation restarts the instances, but the service role doesn't give the user permission to access those instances.

You can specify a service role at runtime when you run an automation, or you can create custom runbooks and specify the service role directly in the runbook. If you specify a service role, either at runtime or in a runbook, then the service runs in the context of the specified service role. If you don't specify a service role, then the system creates a temporary session in the context of the user and runs the automation.

**Note**  
You must specify a service role for automation that you expect to run longer than 12 hours. If you start a long-running automation in the context of a user, the user's temporary session expires after 12 hours.

Delegated administration ensures elevated security and control of your AWS resources. It also allows an enhanced auditing experience because actions are being performed against your resources by a central service role instead of multiple IAM accounts.

**Before you begin**  
Before you complete the following procedures, you must create the IAM service role and configure a trust relationship for Automation, a tool in AWS Systems Manager. For more information, see [Task 1: Create a service role for Automation](automation-setup-iam.md#create-service-role).

The following procedures describe how to use the Systems Manager console or your preferred command line tool to run a simple automation.

## Running a simple automation (console)
<a name="simple-console"></a>

The following procedure describes how to use the Systems Manager console to run a simple automation.

**To run a simple automation**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Automation document** list, choose a runbook. Choose one or more options in the **Document categories** pane to filter SSM documents according to their purpose. To view a runbook that you own, choose the **Owned by me** tab. To view a runbook that is shared with your account, choose the **Shared with me** tab. To view all runbooks, choose the **All documents** tab.
**Note**  
You can view information about a runbook by choosing the runbook name.

1. In the **Document details** section, verify that **Document version** is set to the version that you want to run. The system includes the following version options: 
   + **Default version at runtime** – Choose this option if the Automation runbook is updated periodically and a new default version is assigned.
   + **Latest version at runtime** – Choose this option if the Automation runbook is updated periodically, and you want to run the version that was most recently updated.
   + **1 (Default)** – Choose this option to run the first version of the document, which is the default.

1. Choose **Next**.

1. In the **Execution Mode** section, choose **Simple execution**.

1. In the **Input parameters** section, specify the required inputs. Optionally, you can choose an IAM service role from the **AutomationAssumeRole** list.

1. (Optional) Choose a CloudWatch alarm to apply to your automation for monitoring. To attach a CloudWatch alarm to your automation, the IAM principal that starts the automation must have permission for the `iam:createServiceLinkedRole` action. For more information about CloudWatch alarms, see [Using Amazon CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html). Note that if your alarm activates, the automation is stopped. If you use AWS CloudTrail, you will see the API call in your trail. 

1. Choose **Execute**. 

The console displays the status of the automation. If the automation fails to run, see [Troubleshooting Systems Manager Automation](automation-troubleshooting.md).

After an automation execution completes, you can rerun the execution with the same or modified parameters. For more information, see [Rerunning automation executions](automation-rerun-executions.md).

## Running a simple automation (command line)
<a name="simple-cli"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows) or AWS Tools for PowerShell to run a simple automation.

**To run a simple automation**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Run the following command to start a simple automation. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name runbook name \
       --parameters runbook parameters
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name runbook name ^
       --parameters runbook parameters
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
     -DocumentName runbook name `
     -Parameter runbook parameters
   ```

------

   Here is an example using the runbook `AWS-RestartEC2Instance` to restart the specified EC2 instance.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name "AWS-RestartEC2Instance" \
       --parameters "InstanceId=i-02573cafcfEXAMPLE"
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name "AWS-RestartEC2Instance" ^
       --parameters "InstanceId=i-02573cafcfEXAMPLE"
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
     -DocumentName AWS-RestartEC2Instance `
     -Parameter @{"InstanceId"="i-02573cafcfEXAMPLE"}
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
       "AutomationExecutionId": "4105a4fc-f944-11e6-9d32-0123456789ab"
   }
   ```

------
#### [ Windows ]

   ```
   {
       "AutomationExecutionId": "4105a4fc-f944-11e6-9d32-0123456789ab"
   }
   ```

------
#### [ PowerShell ]

   ```
   4105a4fc-f944-11e6-9d32-0123456789ab
   ```

------

1. Run the following command to retrieve the status of the automation.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-automation-executions \
       --filter "Key=ExecutionId,Values=4105a4fc-f944-11e6-9d32-0123456789ab"
   ```

------
#### [ Windows ]

   ```
   aws ssm describe-automation-executions ^
       --filter "Key=ExecutionId,Values=4105a4fc-f944-11e6-9d32-0123456789ab"
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMAutomationExecutionList | `
     Where {$_.AutomationExecutionId -eq "4105a4fc-f944-11e6-9d32-0123456789ab"}
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
       "AutomationExecutionMetadataList": [
           {
               "AutomationExecutionStatus": "InProgress",
               "CurrentStepName": "stopInstances",
               "Outputs": {},
               "DocumentName": "AWS-RestartEC2Instance",
               "AutomationExecutionId": "4105a4fc-f944-11e6-9d32-0123456789ab",
               "DocumentVersion": "1",
               "ResolvedTargets": {
                   "ParameterValues": [],
                   "Truncated": false
               },
               "AutomationType": "Local",
               "Mode": "Auto",
               "ExecutionStartTime": 1564600648.159,
               "CurrentAction": "aws:changeInstanceState",
               "ExecutedBy": "arn:aws:sts::123456789012:assumed-role/Administrator/Admin",
               "LogFile": "",
               "Targets": []
           }
       ]
   }
   ```

------
#### [ Windows ]

   ```
   {
       "AutomationExecutionMetadataList": [
           {
               "AutomationExecutionStatus": "InProgress",
               "CurrentStepName": "stopInstances",
               "Outputs": {},
               "DocumentName": "AWS-RestartEC2Instance",
               "AutomationExecutionId": "4105a4fc-f944-11e6-9d32-0123456789ab",
               "DocumentVersion": "1",
               "ResolvedTargets": {
                   "ParameterValues": [],
                   "Truncated": false
               },
               "AutomationType": "Local",
               "Mode": "Auto",
               "ExecutionStartTime": 1564600648.159,
               "CurrentAction": "aws:changeInstanceState",
               "ExecutedBy": "arn:aws:sts::123456789012:assumed-role/Administrator/Admin",
               "LogFile": "",
               "Targets": []
           }
       ]
   }
   ```

------
#### [ PowerShell ]

   ```
   AutomationExecutionId       : 4105a4fc-f944-11e6-9d32-0123456789ab
   AutomationExecutionStatus   : InProgress
   AutomationType              : Local
   CurrentAction               : aws:changeInstanceState
   CurrentStepName             : startInstances
   DocumentName                : AWS-RestartEC2Instance
   DocumentVersion             : 1
   ExecutedBy                  : arn:aws:sts::123456789012:assumed-role/Administrator/Admin
   ExecutionEndTime            : 1/1/0001 12:00:00 AM
   ExecutionStartTime          : 7/31/2019 7:17:28 PM
   FailureMessage              : 
   LogFile                     : 
   MaxConcurrency              : 
   MaxErrors                   : 
   Mode                        : Auto
   Outputs                     : {}
   ParentAutomationExecutionId : 
   ResolvedTargets             : Amazon.SimpleSystemsManagement.Model.ResolvedTargets
   Target                      : 
   TargetMaps                  : {}
   TargetParameterName         : 
   Targets                     : {}
   ```

------

# Rerunning automation executions
<a name="automation-rerun-executions"></a>

You can rerun AWS Systems Manager automation executions to repeat tasks with either identical or modified parameters. The rerun capability allows you to efficiently replicate automation executions without manually recreating automation configurations, reducing operational overhead and potential configuration errors.

When you rerun an automation execution, Systems Manager preserves the original runbook parameters, Amazon CloudWatch alarms, and tags from the previous execution. The system creates a new execution with a new execution ID and updated timestamps. You can rerun any type of automation execution, including simple executions, rate control executions, cross-account and cross-region executions, and manual executions.

## Rerun an automation execution (console)
<a name="rerun-console"></a>

The following procedures describe how to use the Systems Manager console to rerun an automation execution.

**To rerun an automation execution from the Automation home page**

Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. In the executions list, select the execution that you want to rerun.

1. Choose **Rerun execution**.

1. On the **Execute automation document** page, review the pre-populated parameters, execution mode, and target configuration from the original execution.

1. (Optional) Modify any parameters, targets, or other settings as needed for your rerun.

1. Choose **Execute** to start the rerun with a new execution ID.

**To rerun an automation execution from the execution details page**

Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the execution ID of the automation that you want to rerun.

1. On the execution details page, choose **Rerun execution**.

1. On the **Execute automation document** page, review the pre-populated parameters, execution mode, and target configuration from the original execution.

1. (Optional) Modify any parameters, targets, or other settings as needed for your rerun.

1. Choose **Execute** to start the rerun with a new execution ID.

**To copy an automation execution to a new execution**

Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the execution ID of the automation that you want to copy.

1. On the execution details page, choose **Actions**, and then choose **Copy to new**.

1. On the **Execute automation document** page, review the pre-populated parameters, execution mode, and target configuration from the original execution.

1. (Optional) Modify any parameters, targets, or other settings as needed for your new execution.

1. Choose **Execute** to start the new execution.

# Run an automation that requires approvals
<a name="running-automations-require-approvals"></a>

The following procedures describe how to use the AWS Systems Manager console and AWS Command Line Interface (AWS CLI) to run an automation with approvals using simple execution. The automation uses the automation action `aws:approve`, which temporarily pauses the automation until the designated principals either approve or deny the action. The automation runs in the context of the current user. This means that you don't need to configure additional IAM permissions as long as you have permission to use the runbook, and any actions called by the runbook. If you have administrator permissions in IAM, then you already have permission to use this runbook.

**Before you begin**  
In addition to the standard inputs required by the runbook, the `aws:approve` action requires the following two parameters: 
+ A list of approvers. The list of approvers must contain at least one approver in the form of a user name or a user ARN. If multiple approvers are provided, a corresponding minimum approval count must also be specified within the runbook. 
+ An Amazon Simple Notification Service (Amazon SNS) topic ARN. The Amazon SNS topic name must start with `Automation`.

This procedure assumes that you have already created an Amazon SNS topic, which is required to deliver the approval request. For information, see [Create a Topic](https://docs.aws.amazon.com/sns/latest/dg/sns-getting-started.html#CreateTopic) in the *Amazon Simple Notification Service Developer Guide*.

## Running an automation with approvers (console)
<a name="approval-console"></a>

**To run an automation with approvers**

The following procedure describes how to use the Systems Manager console to run an automation with approvers.

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Automation document** list, choose a runbook. Choose one or more options in the **Document categories** pane to filter SSM documents according to their purpose. To view a runbook that you own, choose the **Owned by me** tab. To view a runbook that is shared with your account, choose the **Shared with me** tab. To view all runbooks, choose the **All documents** tab.
**Note**  
You can view information about a runbook by choosing the runbook name.

1. In the **Document details** section, verify that **Document version** is set to the version that you want to run. The system includes the following version options: 
   + **Default version at runtime** – Choose this option if the Automation runbook is updated periodically and a new default version is assigned.
   + **Latest version at runtime** – Choose this option if the Automation runbook is updated periodically, and you want to run the version that was most recently updated.
   + **1 (Default)** – Choose this option to run the first version of the document, which is the default.

1. Choose **Next**.

1. On the **Execute automation document** page, choose **Simple execution**.

1. In the **Input parameters** section, specify the required input parameters.

   For example, if you chose the `AWS-StartEC2InstanceWithApproval` runbook, then you must specify or choose instance IDs for the **InstanceId** parameter. 

1. In the **Approvers** section, specify the user names or user ARNs of approvers for the automation action.

1. In the **SNSTopicARN** section, specify the SNS topic ARN to use for sending approval notification. The SNS topic name must start with **Automation**.

1. Optionally, you can choose an IAM service role from the **AutomationAssumeRole** list. If you're targeting more than 100 accounts and Regions, you must specify the `AWS-SystemsManager-AutomationAdministrationRole`.

1. Choose **Execute automation**. 

The specified approver receives an Amazon SNS notification with details to approve or reject the automation. This approval action is valid for 7 days from the date of issue and can be issued using the Systems Manager console or the AWS Command Line Interface (AWS CLI).

If you chose to approve the automation, the automation continues to run the steps included in the specified runbook. The console displays the status of the automation. If the automation fails to run, see [Troubleshooting Systems Manager Automation](automation-troubleshooting.md).

**To approve or deny an automation**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then select the automation that was run in the previous procedure.

1. Choose **Actions** and then choose **Approve/Deny**.

1. Choose to **Approve** or **Deny** and optionally provide a comment.

1. Choose **Submit**.

## Running an automation with approvers (command line)
<a name="approval-cli"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows) or AWS Tools for PowerShell to run an automation with approvers.

**To run an automation with approvers**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Run the following command to run an automation with approvers. Replace each *example resource placeholder* with your own information. In the document name section, specify a runbook that includes the automation action, `aws:approve`.

   For `Approvers`, specify the user names or user ARNs of approvers for the action. For `SNSTopic`, specify the SNS topic ARN to use to send approval notification. The Amazon SNS topic name must start with `Automation`.
**Note**  
The specific names of the parameter values for approvers and the SNS topic depend on the values specified within the runbook you choose. 

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name "AWS-StartEC2InstanceWithApproval" \
       --parameters "InstanceId=i-02573cafcfEXAMPLE,Approvers=arn:aws:iam::123456789012:role/Administrator,SNSTopicArn=arn:aws:sns:region:123456789012:AutomationApproval"
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name "AWS-StartEC2InstanceWithApproval" ^
       --parameters "InstanceId=i-02573cafcfEXAMPLE,Approvers=arn:aws:iam::123456789012:role/Administrator,SNSTopicArn=arn:aws:sns:region:123456789012:AutomationApproval"
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
       -DocumentName AWS-StartEC2InstanceWithApproval `
       -Parameters @{
           "InstanceId"="i-02573cafcfEXAMPLE"
           "Approvers"="arn:aws:iam::123456789012:role/Administrator"
           "SNSTopicArn"="arn:aws:sns:region:123456789012:AutomationApproval"
       }
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
       "AutomationExecutionId": "df325c6d-b1b1-4aa0-8003-6cb7338213c6"
   }
   ```

------
#### [ Windows ]

   ```
   {
       "AutomationExecutionId": "df325c6d-b1b1-4aa0-8003-6cb7338213c6"
   }
   ```

------
#### [ PowerShell ]

   ```
   df325c6d-b1b1-4aa0-8003-6cb7338213c6
   ```

------

**To approve an automation**
+ Run the following command to approve an automation. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

  ```
  aws ssm send-automation-signal \
      --automation-execution-id "df325c6d-b1b1-4aa0-8003-6cb7338213c6" \
      --signal-type "Approve" \
      --payload "Comment=your comments"
  ```

------
#### [ Windows ]

  ```
  aws ssm send-automation-signal ^
      --automation-execution-id "df325c6d-b1b1-4aa0-8003-6cb7338213c6" ^
      --signal-type "Approve" ^
      --payload "Comment=your comments"
  ```

------
#### [ PowerShell ]

  ```
  Send-SSMAutomationSignal `
      -AutomationExecutionId df325c6d-b1b1-4aa0-8003-6cb7338213c6 `
      -SignalType Approve `
      -Payload @{"Comment"="your comments"}
  ```

------

  There is no output if the command succeeds.

**To deny an automation**
+ Run the following command to deny an automation. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

  ```
  aws ssm send-automation-signal \
      --automation-execution-id "df325c6d-b1b1-4aa0-8003-6cb7338213c6" \
      --signal-type "Deny" \
      --payload "Comment=your comments"
  ```

------
#### [ Windows ]

  ```
  aws ssm send-automation-signal ^
      --automation-execution-id "df325c6d-b1b1-4aa0-8003-6cb7338213c6" ^
      --signal-type "Deny" ^
      --payload "Comment=your comments"
  ```

------
#### [ PowerShell ]

  ```
  Send-SSMAutomationSignal `
      -AutomationExecutionId df325c6d-b1b1-4aa0-8003-6cb7338213c6 `
      -SignalType Deny `
      -Payload @{"Comment"="your comments"}
  ```

------

  There is no output if the command succeeds.

# Run automated operations at scale
<a name="running-automations-scale"></a>

With AWS Systems Manager Automation, you can run automations on a fleet of AWS resources by using *targets*. Additionally, you can control the deployment of the automation across your fleet by specifying a concurrency value and an error threshold. The concurrency and error threshold features are collectively called *rate controls*. The concurrency value determines how many resources are allowed to run the automation simultaneously. Automation also provides an adaptive concurrency mode you can opt in to. Adaptive concurrency automatically scales your automation quota from 100 concurrently running automations up to 500. An error threshold determines how many automations are allowed to fail before Systems Manager stops sending the automation to other resources.

For more information about concurrency and error thresholds, see [Control automations at scale](running-automations-scale-controls.md). For more information about targets, see [Mapping targets for an automation](running-automations-map-targets.md).

The following procedures show you how to turn on adaptive concurrency, and how to run an automation with targets and rate controls by using the Systems Manager console and AWS Command Line Interface (AWS CLI).

## Running an automation with targets and rate controls (console)
<a name="scale-console"></a>

The following procedure describes how to use the Systems Manager console to run an automation with targets and rate controls.

**To run an automation with targets and rate controls**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Automation document** list, choose a runbook. Choose one or more options in the **Document categories** pane to filter SSM documents according to their purpose. To view a runbook that you own, choose the **Owned by me** tab. To view a runbook that is shared with your account, choose the **Shared with me** tab. To view all runbooks, choose the **All documents** tab.
**Note**  
You can view information about a runbook by choosing the runbook name.

1. In the **Document details** section, verify that **Document version** is set to the version that you want to run. The system includes the following version options: 
   + **Default version at runtime** – Choose this option if the Automation runbook is updated periodically and a new default version is assigned.
   + **Latest version at runtime** – Choose this option if the Automation runbook is updated periodically, and you want to run the version that was most recently updated.
   + **1 (Default)** – Choose this option to run the first version of the document, which is the default.

1. Choose **Next**.

1. In the **Execution Mode** section, choose **Rate Control**. You must use this mode or **Multi-account and Region** if you want to use targets and rate controls.

1. In the **Targets** section, choose how you want to target the AWS resources where you want to run the Automation. These options are required.

   1. Use the **Parameter** list to choose a parameter. The items in the **Parameter** list are determined by the parameters in the Automation runbook that you selected at the start of this procedure. By choosing a parameter you define the type of resource on which the Automation workflow runs. 

   1. Use the **Targets** list to choose how you want to target resources.

      1. If you chose to target resources by using parameter values, then enter the parameter value for the parameter you chose in the **Input parameters** section.

      1. If you chose to target resources by using AWS Resource Groups, then choose the name of the group from the **Resource Group** list.

      1. If you chose to target resources by using tags, then enter the tag key and (optionally) the tag value in the fields provided. Choose **Add**.

      1. If you want to run an Automation runbook on all instances in the current AWS account and AWS Region, then choose **All instances**.

1. In the **Input parameters** section, specify the required inputs. Optionally, you can choose an IAM service role from the **AutomationAssumeRole** list.
**Note**  
You might not need to choose some of the options in the **Input parameters** section. This is because you targeted resources by using tags or a resource group. For example, if you chose the `AWS-RestartEC2Instance` runbook, then you don't need to specify or choose instance IDs in the **Input parameters** section. The Automation execution locates the instances to restart by using the tags or resource group you specified.

1. Use the options in the **Rate control** section to restrict the number of AWS resources that can run the Automation within each account-Region pair. 

   In the **Concurrency** section, choose an option: 
   + Choose **targets** to enter an absolute number of targets that can run the Automation workflow simultaneously.
   + Choose **percentage** to enter a percentage of the target set that can run the Automation workflow simultaneously.

1. In the **Error threshold** section, choose an option:
   + Choose **errors** to enter an absolute number of errors allowed before Automation stops sending the workflow to other resources.
   + Choose **percentage** to enter a percentage of errors allowed before Automation stops sending the workflow to other resources.

1. (Optional) Choose a CloudWatch alarm to apply to your automation for monitoring. To attach a CloudWatch alarm to your automation, the IAM principal that starts the automation must have permission for the `iam:createServiceLinkedRole` action. For more information about CloudWatch alarms, see [Using Amazon CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html). Note that if your alarm activates, the automation is stopped. If you use AWS CloudTrail, you will see the API call in your trail.

1. Choose **Execute**. 

To view automations started by your rate control automation, in the navigation pane, choose Automation, and then select **Show child automations**.

After an automation execution completes, you can rerun the execution with the same or modified parameters. For more information, see [Rerunning automation executions](automation-rerun-executions.md).

## Running an automation with targets and rate controls (command line)
<a name="scale-cli"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows) or AWS Tools for PowerShell to run an automation with targets and rate controls.

**To run an automation with targets and rate controls**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Run the following command to view a list of documents.

------
#### [ Linux & macOS ]

   ```
   aws ssm list-documents
   ```

------
#### [ Windows ]

   ```
   aws ssm list-documents
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMDocumentList
   ```

------

   Note the name of the runbook that you want to use.

1. Run the following command to view details about the runbook. Replace the *runbook name* with the name of the runbook whose details you want to view. Also, note a parameter name (for example, `InstanceId`) that you want to use for the `--target-parameter-name` option. This parameter determines the type of resource on which the automation runs.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-document \
       --name runbook name
   ```

------
#### [ Windows ]

   ```
   aws ssm describe-document ^
       --name runbook name
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMDocumentDescription `
       -Name runbook name
   ```

------

1. Create a command that uses the targets and rate control options you want to run. Replace each *example resource placeholder* with your own information.

   *Targeting using tags*

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name runbook name \
       --targets Key=tag:key name,Values=value \
       --target-parameter-name parameter name \
       --parameters "input parameter name=input parameter value,input parameter 2 name=input parameter 2 value" \
       --max-concurrency 10 \
       --max-errors 25%
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name runbook name ^
       --targets Key=tag:key name,Values=value ^
       --target-parameter-name parameter name ^
       --parameters "input parameter name=input parameter value,input parameter 2 name=input parameter 2 value" ^
       --max-concurrency 10 ^
       --max-errors 25%
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "tag:key name"
   $Targets.Values = "value"
   
   Start-SSMAutomationExecution `
       DocumentName "runbook name" `
       -Targets $Targets `
       -TargetParameterName "parameter name" `
       -Parameter @{"input parameter name"="input parameter value";"input parameter 2 name"="input parameter 2 value"} `
       -MaxConcurrency "10" `
       -MaxError "25%"
   ```

------

   *Targeting using parameter values*

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name runbook name \
       --targets Key=ParameterValues,Values=value,value 2,value 3 \
       --target-parameter-name parameter name \
       --parameters "input parameter name=input parameter value" \
       --max-concurrency 10 \
       --max-errors 25%
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name runbook name ^
       --targets Key=ParameterValues,Values=value,value 2,value 3 ^
       --target-parameter-name parameter name ^
       --parameters "input parameter name=input parameter value" ^
       --max-concurrency 10 ^
       --max-errors 25%
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "ParameterValues"
   $Targets.Values = "value","value 2","value 3"
   
   Start-SSMAutomationExecution `
       -DocumentName "runbook name" `
       -Targets $Targets `
       -TargetParameterName "parameter name" `
       -Parameter @{"input parameter name"="input parameter value"} `
       -MaxConcurrency "10" `
       -MaxError "25%"
   ```

------

   *Targeting using AWS Resource Groups*

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name runbook name \
       --targets Key=ResourceGroup,Values=Resource group nname \
       --target-parameter-name parameter name \
       --parameters "input parameter name=input parameter value" \
       --max-concurrency 10 \
       --max-errors 25%
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name runbook name ^
       --targets Key=ResourceGroup,Values=Resource group name ^
       --target-parameter-name parameter name ^
       --parameters "input parameter name=input parameter value" ^
       --max-concurrency 10 ^
       --max-errors 25%
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "ResourceGroup"
   $Targets.Values = "Resource group name"
   
   Start-SSMAutomationExecution `
       -DocumentName "runbook name" `
       -Targets $Targets `
       -TargetParameterName "parameter name" `
       -Parameter @{"input parameter name"="input parameter value"} `
       -MaxConcurrency "10" `
       -MaxError "25%"
   ```

------

   *Targeting all Amazon EC2 instances in the current AWS account and AWS Region*

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name runbook name \
       --targets "Key=AWS::EC2::Instance,Values=*"  \
       --target-parameter-name instanceId \
       --parameters "input parameter name=input parameter value" \
       --max-concurrency 10 \
       --max-errors 25%
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name runbook name ^
       --targets Key=AWS::EC2::Instance,Values=* ^
       --target-parameter-name instanceId ^
       --parameters "input parameter name=input parameter value" ^
       --max-concurrency 10 ^
       --max-errors 25%
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "AWS::EC2::Instance"
   $Targets.Values = "*"
   
   Start-SSMAutomationExecution `
       -DocumentName "runbook name" `
       -Targets $Targets `
       -TargetParameterName "instanceId" `
       -Parameter @{"input parameter name"="input parameter value"} `
       -MaxConcurrency "10" `
       -MaxError "25%"
   ```

------

   The command returns an execution ID. Copy this ID to the clipboard. You can use this ID to view the status of the automation.

------
#### [ Linux & macOS ]

   ```
   {
       "AutomationExecutionId": "a4a3c0e9-7efd-462a-8594-01234EXAMPLE"
   }
   ```

------
#### [ Windows ]

   ```
   {
       "AutomationExecutionId": "a4a3c0e9-7efd-462a-8594-01234EXAMPLE"
   }
   ```

------
#### [ PowerShell ]

   ```
   a4a3c0e9-7efd-462a-8594-01234EXAMPLE
   ```

------

1. Run the following command to view the automation. Replace each *automation execution ID* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-automation-executions \
       --filter Key=ExecutionId,Values=automation execution ID
   ```

------
#### [ Windows ]

   ```
   aws ssm describe-automation-executions ^
       --filter Key=ExecutionId,Values=automation execution ID
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMAutomationExecutionList | `
       Where {$_.AutomationExecutionId -eq "automation execution ID"}
   ```

------

1. To view details about the automation progress, run the following command. Replace each *automation execution ID* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm get-automation-execution \
       --automation-execution-id automation execution ID
   ```

------
#### [ Windows ]

   ```
   aws ssm get-automation-execution ^
       --automation-execution-id automation execution ID
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMAutomationExecution `
       -AutomationExecutionId automation execution ID
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
       "AutomationExecution": {
           "StepExecutionsTruncated": false,
           "AutomationExecutionStatus": "Success",
           "MaxConcurrency": "1",
           "Parameters": {},
           "MaxErrors": "1",
           "Outputs": {},
           "DocumentName": "AWS-StopEC2Instance",
           "AutomationExecutionId": "a4a3c0e9-7efd-462a-8594-01234EXAMPLE",
           "ResolvedTargets": {
               "ParameterValues": [
                   "i-02573cafcfEXAMPLE"
               ],
               "Truncated": false
           },
           "ExecutionEndTime": 1564681619.915,
           "Targets": [
               {
                   "Values": [
                       "DEV"
                   ],
                   "Key": "tag:ENV"
               }
           ],
           "DocumentVersion": "1",
           "ExecutionStartTime": 1564681576.09,
           "ExecutedBy": "arn:aws:sts::123456789012:assumed-role/Administrator/Admin",
           "StepExecutions": [
               {
                   "Inputs": {
                       "InstanceId": "i-02573cafcfEXAMPLE"
                   },
                   "Outputs": {},
                   "StepName": "i-02573cafcfEXAMPLE",
                   "ExecutionEndTime": 1564681619.093,
                   "StepExecutionId": "86c7b811-3896-4b78-b897-01234EXAMPLE",
                   "ExecutionStartTime": 1564681576.836,
                   "Action": "aws:executeAutomation",
                   "StepStatus": "Success"
               }
           ],
           "TargetParameterName": "InstanceId",
           "Mode": "Auto"
       }
   }
   ```

------
#### [ Windows ]

   ```
   {
       "AutomationExecution": {
           "StepExecutionsTruncated": false,
           "AutomationExecutionStatus": "Success",
           "MaxConcurrency": "1",
           "Parameters": {},
           "MaxErrors": "1",
           "Outputs": {},
           "DocumentName": "AWS-StopEC2Instance",
           "AutomationExecutionId": "a4a3c0e9-7efd-462a-8594-01234EXAMPLE",
           "ResolvedTargets": {
               "ParameterValues": [
                   "i-02573cafcfEXAMPLE"
               ],
               "Truncated": false
           },
           "ExecutionEndTime": 1564681619.915,
           "Targets": [
               {
                   "Values": [
                       "DEV"
                   ],
                   "Key": "tag:ENV"
               }
           ],
           "DocumentVersion": "1",
           "ExecutionStartTime": 1564681576.09,
           "ExecutedBy": "arn:aws:sts::123456789012:assumed-role/Administrator/Admin",
           "StepExecutions": [
               {
                   "Inputs": {
                       "InstanceId": "i-02573cafcfEXAMPLE"
                   },
                   "Outputs": {},
                   "StepName": "i-02573cafcfEXAMPLE",
                   "ExecutionEndTime": 1564681619.093,
                   "StepExecutionId": "86c7b811-3896-4b78-b897-01234EXAMPLE",
                   "ExecutionStartTime": 1564681576.836,
                   "Action": "aws:executeAutomation",
                   "StepStatus": "Success"
               }
           ],
           "TargetParameterName": "InstanceId",
           "Mode": "Auto"
       }
   }
   ```

------
#### [ PowerShell ]

   ```
   AutomationExecutionId       : a4a3c0e9-7efd-462a-8594-01234EXAMPLE
   AutomationExecutionStatus   : Success
   CurrentAction               : 
   CurrentStepName             : 
   DocumentName                : AWS-StopEC2Instance
   DocumentVersion             : 1
   ExecutedBy                  : arn:aws:sts::123456789012:assumed-role/Administrator/Admin
   ExecutionEndTime            : 8/1/2019 5:46:59 PM
   ExecutionStartTime          : 8/1/2019 5:46:16 PM
   FailureMessage              : 
   MaxConcurrency              : 1
   MaxErrors                   : 1
   Mode                        : Auto
   Outputs                     : {}
   Parameters                  : {}
   ParentAutomationExecutionId : 
   ProgressCounters            : 
   ResolvedTargets             : Amazon.SimpleSystemsManagement.Model.ResolvedTargets
   StepExecutions              : {i-02573cafcfEXAMPLE}
   StepExecutionsTruncated     : False
   Target                      : 
   TargetLocations             : {}
   TargetMaps                  : {}
   TargetParameterName         : InstanceId
   Targets                     : {tag:Name}
   ```

------
**Note**  
You can also monitor the status of the automation in the console. In the **Automation executions** list, choose the automation you just ran and then choose the **Execution steps** tab. This tab shows the status of the automation actions.

# Mapping targets for an automation
<a name="running-automations-map-targets"></a>

Use the `Targets` parameter to quickly define which resources are targeted by an automation. For example, if you want to run an automation that restarts your managed instances, then instead of manually selecting dozens of instance IDs in the console or typing them in a command, you can target instances by specifying Amazon Elastic Compute Cloud (Amazon EC2) tags with the `Targets` parameter.

When you run an automation that uses a target, AWS Systems Manager creates a child automation for each target. For example, if you target Amazon Elastic Block Store (Amazon EBS) volumes by specifying tags, and those tags resolve to 100 Amazon EBS volumes, then Systems Manager creates 100 child automations. The parent automation is complete when all child automations reach a final state.

**Note**  
Any `input parameters` that you specify at runtime (either in the **Input parameters** section of the console or by using the `parameters` option from the command line) are automatically processed by all child automations.

You can target resources for an automation by using tags, Resource Groups,and parameter values. Additionally, you can use the `TargetMaps` option to target multiple parameter values from the command line or a file. The following section describes each of these targeting options in more detail.

## Targeting a tag
<a name="target-tags"></a>

You can specify a single tag as the target of an automation. Many AWS resources support tags, including Amazon Elastic Compute Cloud (Amazon EC2) and Amazon Relational Database Service (Amazon RDS) instances, Amazon Elastic Block Store (Amazon EBS) volumes and snapshots, Resource Groups,and Amazon Simple Storage Service (Amazon S3) buckets, to name a few. You can quickly run automation on your AWS resources by targeting a tag. A tag is a key-value pair, such as Operating\$1System:Linux or Department:Finance. If you assign a specific name to a resource, then you can also use the word "Name" as a key, and the name of the resource as the value.

When you specify a tag as the target for an automation, you also specify a target parameter. The target parameter uses the `TargetParameterName` option. By choosing a target parameter, you define the type of resource on which the automation runs. The target parameter you specify with the tag must be a valid parameter defined in the runbook. For example, if you want to target dozens of EC2 instances by using tags, then choose the `InstanceId` target parameter. By choosing this parameter, you define *instances* as the resource type for the automation. When creating a custom runbook you must specify the **Target type** as `/AWS::EC2::Instance` to ensure only instances are used. Otherwise, all resources with the same tag will be targeted. When targeting instances with a tag, terminated instances might be included.

The following screenshot uses the `AWS-DetachEBSVolume` runbook. The logical target parameter is `VolumeId`.

![\[Using a tag as a target for a Systems Manager Automation\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/automation-rate-control-tags-1-new.png)


The `AWS-DetachEBSVolume` runbook also includes a special property called **Target type**, which is set to `/AWS::EC2::Volume`. This means that if the tag-key pair `Finance:TestEnv` returns different types of resources (for example, EC2 instances, Amazon EBS volumes, Amazon EBS snapshots) then only Amazon EBS volumes will be used.

**Important**  
Target parameter names are case sensitive. If you run automations by using either the AWS Command Line Interface (AWS CLI) or AWS Tools for Windows PowerShell, then you must enter the target parameter name exactly as it's defined in the runbook. If you don't, the system returns an `InvalidAutomationExecutionParametersException` error. You can use the [DescribeDocument](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_DescribeDocument.html) API operation to see information about the available target parameters in a specific runbook. Following is an example AWS CLI command that provides information about the `AWS-DeleteSnapshot` document.  

```
aws ssm describe-document \
    --name AWS-DeleteSnapshot
```

Here are some example AWS CLI commands that target resources by using a tag.

**Example 1: Targeting a tag using a key-value pair to restart Amazon EC2 instances**

This example restarts all Amazon EC2 instances that are tagged with a key of *Department* and a value of *HumanResources*. The target parameter uses the *InstanceId* parameter from the runbook. The example uses an additional parameter to run the automation by using an Automation service role (also called an *assume role*).

```
aws ssm start-automation-execution \
    --document-name AWS-RestartEC2Instance \
    --targets Key=tag:Department,Values=HumanResources \
    --target-parameter-name InstanceId \
    --parameters "AutomationAssumeRole=arn:aws:iam::111122223333:role/AutomationServiceRole"
```

**Example 2: Targeting a tag using a key-value pair to delete Amazon EBS snapshots**

The following example uses the `AWS-DeleteSnapshot` runbook to delete all snapshots with a key of *Name* and a value of *January2018Backups*. The target parameter uses the *VolumeId* parameter.

```
aws ssm start-automation-execution \
    --document-name AWS-DeleteSnapshot \
    --targets Key=tag:Name,Values=January2018Backups \
    --target-parameter-name VolumeId
```

## Targeting AWS Resource Groups
<a name="target-resource-groups"></a>

You can specify a single AWS resource group as the target of an automation. Systems Manager creates a child automation for every object in the target Resource Group.

For example, say that one of your Resource Groups is named PatchedAMIs. This Resource Group includes a list of 25 Windows Amazon Machine Images (AMIs) that are routinely patched. If you run an automation that uses the `AWS-CreateManagedWindowsInstance` runbook and target this Resource Group, then Systems Manager creates a child automation for each of the 25 AMIs. This means, that by targeting the PatchedAMIs Resource Group, the automation creates 25 instances from a list of patched AMIs. The parent automation is complete when all child automations complete processing or reach a final state.

The following AWS CLI command applies to the PatchAMIs Resource Group example. The command takes the *AmiId* parameter for the `--target-parameter-name` option. The command doesn't include an additional parameter defining which type of instance to create from each AMI. The `AWS-CreateManagedWindowsInstance` runbook defaults to the t2.medium instance type, so this command would create 25 t2.medium Amazon EC2 instances for Windows Server.

```
aws ssm start-automation-execution \
    --document-name AWS-CreateManagedWindowsInstance \
    --targets Key=ResourceGroup,Values=PatchedAMIs  \
    --target-parameter-name AmiId
```

The following console example uses a Resource Group called t2-micro-instances.

![\[Targeting an AWS resource group with a Systems Manager automation\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/automation-rate-control-resource-groups-new.png)


## Targeting parameter values
<a name="target-parameter-values"></a>

You can also target a parameter value. You enter `ParameterValues` as the key and then enter the specific resource value where you want the automation to run. If you specify multiple values, Systems Manager runs a child automation on each value specified.

For example, say that your runbook includes an **InstanceID** parameter. If you target the values of the **InstanceID** parameter when you run the Automation, then Systems Manager runs a child automation for each instance ID value specified. The parent automation is complete when the automation finishes running each specified instance, or if the automation fails. You can target a maximum of 50 parameter values.

The following example uses the `AWS-CreateImage` runbook. The target parameter name specified is *InstanceId*. The key uses *ParameterValues*. The values are two Amazon EC2 instance IDs. This command creates an automation for each instance, which produces an AMI from each instance. 

```
aws ssm start-automation-execution 
    --document-name AWS-CreateImage \
    --target-parameter-name InstanceId \
    --targets Key=ParameterValues,Values=i-02573cafcfEXAMPLE,i-0471e04240EXAMPLE
```

**Note**  
`AutomationAssumeRole` isn't a valid parameter. Don’t choose this item when running automation that target a parameter value.

### Targeting parameter value maps
<a name="target-maps"></a>

The `TargetMaps` option expands your ability to target `ParameterValues`. You can enter an array of parameter values by using `TargetMaps` at the command line. You can specify a maximum of 50 parameter values at the command line. If you want to run commands that specify more than 50 parameter values, then you can enter the values in a JSON file. You can then call the file from the command line.

**Note**  
The `TargetMaps` option isn't supported in the console.

Use the following format to specify multiple parameter values by using the `TargetMaps` option in a command. Replace each *example resource placeholder* with your own information.

```
aws ssm start-automation-execution \
    --document-name runbook name \
    --target-maps “parameter=value, parameter 2=value, parameter 3=value”  “parameter 4=value, parameter 5=value, parameter 6=value”
```

If you want to enter more than 50 parameter values for the `TargetMaps` option, then specify the values in a file by using the following JSON format. Using a JSON file also improves readability when providing multiple parameter values.

```
[

    {“parameter”: "value", “parameter 2”: "value", “parameter 3”: "value"},

    {“parameter 4”: "value", “parameter 5”: "value", "parameter 6": "value"}

]
```

Save the file with a .json file extension. You can call the file by using the following command. Replace each *example resource placeholder* with your own information.

```
aws ssm start-automation-execution \
    --document-name runbook name \
    –-parameters input parameters \
    --target-maps path to file/file name.json
```

You can also download the file from an Amazon Simple Storage Service (Amazon S3) bucket, as long as you have permission to read data from the bucket. Use the following command format. Replace each *example resource placeholder* with your own information.

```
aws ssm start-automation-execution \
    --document-name runbook name \
    --target-maps http://amzn-s3-demo-bucket.s3.amazonaws.com/file_name.json
```

Here is an example scenario to help you understand the `TargetMaps` option. In this scenario, a user wants to create Amazon EC2 instances of different types from different AMIs. To perform this task, the user creates a runbook named AMI\$1Testing. This runbook defines two input parameters: `instanceType` and `imageId`. 

```
{
  "description": "AMI Testing",
  "schemaVersion": "0.3",
  "assumeRole": "{{assumeRole}}",
  "parameters": {
    "assumeRole": {
      "type": "String",
      "description": "Role under which to run the automation",
      "default": ""
    },
    "instanceType": {
      "type": "String",
      "description": "Type of EC2 Instance to launch for this test"
    },
    "imageId": {
      "type": "String",
      "description": "Source AMI id from which to run instance"
    }
  },
  "mainSteps": [
    {
      "name": "runInstances",
      "action": "aws:runInstances",
      "maxAttempts": 1,
      "onFailure": "Abort",
      "inputs": {
        "ImageId": "{{imageId}}",
        "InstanceType": "{{instanceType}}",
        "MinInstanceCount": 1,
        "MaxInstanceCount": 1
      }
    }
  ],
  "outputs": [
    "runInstances.InstanceIds"
  ]
}
```

The user then specifies the following target parameter values in a file named `AMI_instance_types.json`.

```
[
  {
    "instanceType" : ["t2.micro"],     
    "imageId" : ["ami-b70554c8"]     
  },
  {
    "instanceType" : ["t2.small"],     
    "imageId" : ["ami-b70554c8"]     
  },
  {
    "instanceType" : ["t2.medium"],     
    "imageId" : ["ami-cfe4b2b0"]     
  },
  {
    "instanceType" : ["t2.medium"],     
    "imageId" : ["ami-cfe4b2b0"]     
  },
  {
    "instanceType" : ["t2.medium"],     
    "imageId" : ["ami-cfe4b2b0"]     
  }
]
```

The user can run the automation and create the five EC2 instances defined in `AMI_instance_types.json` by running the following command.

```
aws ssm start-automation-execution \
    --document-name AMI_Testing \
    --target-parameter-name imageId \
    --target-maps file:///home/TestUser/workspace/runinstances/AMI_instance_types.json
```

## Targeting all Amazon EC2 instances
<a name="target-all-instances"></a>

You can run an automation on all Amazon EC2 instances in the current AWS account and AWS Region by choosing **All instances** in the **Targets** list. For example, if you want to restart all Amazon EC2 instances your AWS account and the current AWS Region, you can choose the `AWS-RestartEC2Instance` runbook and then choose **All instances** from the **Targets** list.

![\[Targeting all Amazon EC2 instances for a runbook\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/automation-rate-control-target-all-instances.png)


After you choose **All instances**, Systems Manager populates the **Instance** field with an asterisk (\$1) and makes the field unavailable for changes (the field is grayed out). Systems Manager also makes the **InstanceId** field in the **Input parameters** field unavailable for changes. Making these fields unavailable for changes is expected behavior if you choose to target all instances.

# Control automations at scale
<a name="running-automations-scale-controls"></a>

You can control the deployment of an automation across a fleet of AWS resources by specifying a concurrency value and an error threshold. Concurrency and error threshold are collectively called *rate controls*.

**Concurrency**  
Use Concurrency to specify how many resources are allowed to run an automation simultaneously. Concurrency helps to limit the impact or downtime on your resources when processing an automation. You can specify either an absolute number of resources, for example 20, or a percentage of the target set, for example 10%.

The queueing system delivers the automation to a single resource and waits until the initial invocation is complete before sending the automation to two more resources. The system exponentially sends the automation to more resources until the concurrency value is met.

**Error thresholds**  
Use an error threshold to specify how many automations are allowed to fail before AWS Systems Manager stops sending the automation to other resources. You can specify either an absolute number of errors, for example 10, or a percentage of the target set, for example 10%.

If you specify an absolute number of 3 errors, for example, the system stops running the automation when the fourth error is received. If you specify 0, then the system stops running the automation on additional targets after the first error result is returned.

If you send an automation to, for example, 50 instances and set the error threshold to 10%, then the system stops sending the command to additional instances when the fifth error is received. Invocations that are already running an automation when an error threshold is reached are allowed to be completed, but some of these automations might fail as well. If you need to ensure that there won’t be more errors than the number specified for the error threshold, then set the **Concurrency** value to 1 so that automations proceed one at a time. 

# Running automations in multiple AWS Regions and accounts
<a name="running-automations-multiple-accounts-regions"></a>

You can run AWS Systems Manager automations across multiple AWS Regions and AWS accounts or AWS Organizations organizational units (OUs) from a central account. Automation is a tool in AWS Systems Manager. Running automations in multiple Regions and accounts or OUs reduces the time required to administer your AWS resources while enhancing the security of your computing environment.

For example, you can do the following by using automation runbooks:
+ Implement patching and security updates centrally.
+ Remediate compliance drift on VPC configurations or Amazon S3 bucket policies.
+ Manage resources, such as Amazon Elastic Compute Cloud (Amazon EC2) EC2 instances, at scale.

The following diagram shows an example of a user who is running the `AWS-RestartEC2Instances` runbook in multiple Regions and accounts from a central account. The automation locates the instances by using the specified tags in the targeted Regions and accounts.

![\[Illustration showing Systems Manager Automation running in multiple Regions and multiple accounts.\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/automation-multi-region-and-multi-account.png)


**Choose a central account for Automation**  
If you want to run automations across OUs, the central account must have permissions to list all of the accounts in the OUs. This is only possible from a delegated administrator account, or the management account of the organization. We recommend that you follow AWS Organizations best practices and use a delegated administrator account. For more information about AWS Organizations best practices, see [Best practices for the management account](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_best-practices_mgmt-acct.html) in the *AWS Organizations User Guide*. To create a delegated administrator account for Systems Manager, you can use the `register-delegated-administrator` command with the AWS CLI as shown in the following example.

```
aws organizations register-delegated-administrator \
    --account-id delegated admin account ID \
    --service-principal ssm.amazonaws.com
```

If you want to run automations across multiple accounts that are not managed by AWS Organizations, we recommend creating a dedicated account for automation management. Running all cross-account automations from a dedicated account simplifies IAM permissions management, troubleshooting efforts, and creates a layer of separation between operations and administration. This approach is also recommended if you use AWS Organizations, but only want to target individual accounts and not OUs.

**How running automations works**  
Running automations across multiple Regions and accounts or OUs works as follows:

1. Sign in to the account that you want to configure as the Automation central account.

1. Use the [Setting up management account permissions for multi-Region and multi-account automation](#setup-management-account-iam-roles) procedure in this topic to create the following IAM roles:
   + `AWS-SystemsManager-AutomationAdministrationRole` - This role gives the user permission to run automations in multiple accounts and OUs.
   + `AWS-SystemsManager-AutomationExecutionRole` - This role gives the user permission to run automations in the targeted accounts.

1. Choose the runbook, Regions, and accounts or OUs where you want to run the automation.
**Note**  
Be sure that the target OU contains the desired accounts. If you choose a custom runbook, the runbook must be shared with all of the target accounts. For information about sharing runbooks, see [Sharing SSM documents](documents-ssm-sharing.md). For information about using shared runbooks, see [Using shared SSM documents](documents-ssm-sharing.md#using-shared-documents).

1. Run the automation.

1. Use the [GetAutomationExecution](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetAutomationExecution.html), [DescribeAutomationStepExecutions](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_DescribeAutomationStepExecutions.html), and [DescribeAutomationExecutions](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_DescribeAutomationExecutions.html) API operations from the AWS Systems Manager console or the AWS CLI to monitor automation progress. The output of the steps for the automation in your primary account will be the `AutomationExecutionId` of the child automations. To view the output of the child automations created in your target accounts, be sure to specify the appropriate account, Region, and `AutomationExecutionId` in your request.

## Setting up management account permissions for multi-Region and multi-account automation
<a name="setup-management-account-iam-roles"></a>

Use the following procedure to create the required IAM roles for Systems Manager Automation multi-Region and multi-account automation by using AWS CloudFormation. This procedure describes how to create the `AWS-SystemsManager-AutomationAdministrationRole` role. You only need to create this role in the Automation central account. This procedure also describes how to create the `AWS-SystemsManager-AutomationExecutionRole` role. You must create this role in *every* account that you want to target to run multi-Region and multi-account automations. We recommend using CloudFormation StackSets to create the `AWS-SystemsManager-AutomationExecutionRole` role in the accounts you want to target to run multi-Region and multi-account automations.

**To create the required IAM administration role for multi-Region and multi-account automations by using CloudFormation**

1. Download and unzip the [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationAdministrationRole.zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationAdministrationRole.zip).

   -or-

   If your accounts are managed by AWS Organizations [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationAdministrationRole (org).zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationAdministrationRole (org).zip).

   These files contain the `AWS-SystemsManager-AutomationAdministrationRole.yaml` and `AWS-SystemsManager-AutomationAdministrationRole (org).yaml` CloudFormation template files, respectively.

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create stack**.

1. In the **Specify template** section, choose **Upload a template**.

1. Choose **Choose file**, and then choose the `AWS-SystemsManager-AutomationAdministrationRole.yaml` or `AWS-SystemsManager-AutomationAdministrationRole (org).yaml` CloudFormation template file, depending on your selection in step 1.

1. Choose **Next**.

1. On the **Specify stack details** page, in the **Stack name** field, enter a name. 

1. Choose **Next**.

1. On the **Configure stack options** page, enter values for any options you want to use. Choose **Next**.

1. On the **Review** page, scroll down and choose the **I acknowledge that CloudFormation might create IAM resources with custom names** option.

1. Choose **Create stack**.

CloudFormation shows the **CREATE\$1IN\$1PROGRESS** status for approximately three minutes. The status changes to **CREATE\$1COMPLETE**.

You must repeat the following procedure in *every* account that you want to target to run multi-Region and multi-account automations.

**To create the required IAM automation role for multi-Region and multi-account automations by using CloudFormation**

1. Download the [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationExecutionRole.zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationExecutionRole.zip).

   -or

   If your accounts are managed by AWS Organizations [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationExecutionRole (org).zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWS-SystemsManager-AutomationExecutionRole (org).zip).

   These files contains the `AWS-SystemsManager-AutomationExecutionRole.yaml` and `AWS-SystemsManager-AutomationExecutionRole (org).yaml`CloudFormation template files, respectively.

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create stack**.

1. In the **Specify template** section, choose **Upload a template**.

1. Choose **Choose file**, and then choose the `AWS-SystemsManager-AutomationExecutionRole.yaml` or `AWS-SystemsManager-AutomationExecutionRole (org).yaml` CloudFormation template file, depending on your selection in step 1.

1. Choose **Next**.

1. On the **Specify stack details** page, in the **Stack name** field, enter a name. 

1. In the **Parameters** section, in the **AdminAccountId** field, enter the ID for the Automation central account.

1. If you are setting up this role for an AWS Organizations environment, there is another field in the section called **OrganizationID**. Enter the ID of your AWS organization.

1. Choose **Next**.

1. On the **Configure stack options** page, enter values for any options you want to use. Choose **Next**.

1. On the **Review** page, scroll down and choose the **I acknowledge that CloudFormation might create IAM resources with custom names** option.

1. Choose **Create stack**.

CloudFormation shows the **CREATE\$1IN\$1PROGRESS** status for approximately three minutes. The status changes to **CREATE\$1COMPLETE**.

## Run an automation in multiple Regions and accounts (console)
<a name="multiple-console"></a>

The following procedure describes how to use the Systems Manager console to run an automation in multiple Regions and accounts from the Automation management account.

**Before you begin**  
Before you complete the following procedure, note the following information:
+ The user or role you use to run a multi-Region or multi-account automation must have the `iam:PassRole` permission for the `AWS-SystemsManager-AutomationAdministrationRole` role.
+ AWS account IDs or OUs where you want to run the automation.
+ [Regions supported by Systems Manager](https://docs.aws.amazon.com/general/latest/gr/ssm.html#ssm_region) where you want to run the automation.
+ The tag key and the tag value, or the name of the resource group, where you want to run the automation.

**To run an automation in multiple Regions and accounts**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Automation document** list, choose a runbook. Choose one or more options in the **Document categories** pane to filter SSM documents according to their purpose. To view a runbook that you own, choose the **Owned by me** tab. To view a runbook that is shared with your account, choose the **Shared with me** tab. To view all runbooks, choose the **All documents** tab.
**Note**  
You can view information about a runbook by choosing the runbook name.

1. In the **Document details** section, verify that **Document version** is set to the version that you want to run. The system includes the following version options: 
   + **Default version at runtime** – Choose this option if the Automation runbook is updated periodically and a new default version is assigned.
   + **Latest version at runtime** – Choose this option if the Automation runbook is updated periodically, and you want to run the version that was most recently updated.
   + **1 (Default)** – Choose this option to run the first version of the document, which is the default.

1. Choose **Next**.

1. On the **Execute automation document** page, choose **Multi-account and Region**.

1. In the **Target accounts and Regions** section, use the **Accounts, organizational units (OUs), and roots** field to specify the different AWS accounts or AWS organizational units (OUs) where you want to run the automation. Separate multiple accounts or OUs with a comma. 

   1. (Optional) Select the **Include child OUs** checkbox to include all child organizational units within the specified OUs.

   1. (Optional) In the **Exclude accounts and organizational units (OUs)** field, enter a comma-separated list of account IDs and OU IDs that you want to exclude from the expanded entities entered above.

1. Use the **Regions** list to choose one or more Regions where you want to run the automation.

1. Use the **Multi-Region and account rate control** options to restrict the automation to a limited number of accounts running in a limited number of Regions. These options don't restrict the number of AWS resources that can run the automations. 

   1. In the **Location (account-Region pair) concurrency** section, choose an option to restrict the number of automations that can run in multiple accounts and Regions at the same time. For example, if you choose to run an automation in five (5) AWS accounts, which are located in four (4) AWS Regions, then Systems Manager runs automations in a total of 20 account-Region pairs. You can use this option to specify an absolute number, such as **2**, so that the automation only runs in two account-Region pairs at the same time. Or you can specify a percentage of the account-Region pairs that can run at the same time. For example, with 20 account-Region pairs, if you specify 20%, then the automation simultaneously runs in a maximum of five (5) account-Region pairs. 
      + Choose **targets** to enter an absolute number of account-Region pairs that can run the automation simultaneously.
      + Choose **percent** to enter a percentage of the total number of account-Region pairs that can run the automation simultaneously.

   1. In the **Error threshold** section, choose an option:
      + Choose **errors** to enter an absolute number of errors allowed before Automation stops sending the automation to other resources.
      + Choose **percent** to enter a percentage of errors allowed before Automation stops sending the automation to other resources.

1. In the **Targets** section, choose how you want to target the AWS resources where you want to run the Automation. These options are required.

   1. Use the **Parameter** list to choose a parameter. The items in the **Parameter** list are determined by the parameters in the Automation runbook that you selected at the start of this procedure. By choosing a parameter you define the type of resource on which the Automation workflow runs. 

   1. Use the **Targets** list to choose how you want to target resources.

      1. If you chose to target resources by using parameter values, then enter the parameter value for the parameter you chose in the **Input parameters** section.

      1. If you chose to target resources by using AWS Resource Groups, then choose the name of the group from the **Resource Group** list.

      1. If you chose to target resources by using tags, then enter the tag key and (optionally) the tag value in the fields provided. Choose **Add**.

      1. If you want to run an Automation runbook on all instances in the current AWS account and AWS Region, then choose **All instances**.

1. In the **Input parameters** section, specify the required inputs. Choose the `AWS-SystemsManager-AutomationAdministrationRole` IAM service role from the **AutomationAssumeRole** list.
**Note**  
You might not need to choose some of the options in the **Input parameters** section. This is because you targeted resources in multiple Regions and accounts by using tags or a resource group. For example, if you chose the `AWS-RestartEC2Instance` runbook, then you don't need to specify or choose instance IDs in the **Input parameters** section. The automation locates the instances to restart by using the tags you specified. 

1. (Optional) Choose a CloudWatch alarm to apply to your automation for monitoring. To attach a CloudWatch alarm to your automation, the IAM principal that starts the automation must have permission for the `iam:createServiceLinkedRole` action. For more information about CloudWatch alarms, see [Using Amazon CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html). Note that if your alarm activates, the automation is cancelled and any `OnCancel` steps you have defined run. If you use AWS CloudTrail, you will see the API call in your trail.

1. Use the options in the **Rate control** section to restrict the number of AWS resources that can run the Automation within each account-Region pair. 

   In the **Concurrency** section, choose an option: 
   + Choose **targets** to enter an absolute number of targets that can run the Automation workflow simultaneously.
   + Choose **percentage** to enter a percentage of the target set that can run the Automation workflow simultaneously.

1. In the **Error threshold** section, choose an option:
   + Choose **errors** to enter an absolute number of errors allowed before Automation stops sending the workflow to other resources.
   + Choose **percentage** to enter a percentage of errors allowed before Automation stops sending the workflow to other resources.

1. Choose **Execute**.

After an automation execution completes, you can rerun the execution with the same or modified parameters. For more information, see [Rerunning automation executions](automation-rerun-executions.md).

## Run an automation in multiple Regions and accounts (command line)
<a name="multiple-cli"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows) or AWS Tools for PowerShell to run an automation in multiple Regions and accounts from the Automation management account.

**Before you begin**  
Before you complete the following procedure, note the following information:
+ AWS account IDs or OUs where you want to run the automation.
+ [Regions supported by Systems Manager](https://docs.aws.amazon.com/general/latest/gr/ssm.html#ssm_region) where you want to run the automation.
+ The tag key and the tag value, or the name of the resource group, where you want to run the automation.

**To run an automation in multiple Regions and accounts**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Use the following format to create a command to run an automation in multiple Regions and accounts. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
           --document-name runbook name \
           --parameters AutomationAssumeRole=arn:aws:iam::management account ID:role/AWS-SystemsManager-AutomationAdministrationRole \
           --target-parameter-name parameter name \
           --targets Key=tag key,Values=value \
           --target-locations Accounts=account ID,account ID 2,Regions=Region,Region 2,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
           --document-name runbook name ^
           --parameters AutomationAssumeRole=arn:aws:iam::management account ID:role/AWS-SystemsManager-AutomationAdministrationRole ^
           --target-parameter-name parameter name ^
           --targets Key=tag key,Values=value ^
           --target-locations Accounts=account ID,account ID 2,Regions=Region,Region 2,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
       $Targets.Key = "tag key"
       $Targets.Values = "value"
       
       Start-SSMAutomationExecution `
           -DocumentName "runbook name" `
           -Parameter @{
           "AutomationAssumeRole"="arn:aws:iam::management account ID:role/AWS-SystemsManager-AutomationAdministrationRole" } `
           -TargetParameterName "parameter name" `
           -Target $Targets `
           -TargetLocation @{
           "Accounts"="account ID","account ID 2";
           "Regions"="Region","Region 2";
           "ExecutionRoleName"="AWS-SystemsManager-AutomationExecutionRole" }
   ```

------

**Examples: Running an automation in multiple Regions and accounts**  
The following are examples demonstrating how to use the AWS CLI and PowerShell to run automations in multiple accounts and Regions with a single command.

   **Example 1**: This example restarts EC2 instances in three Regions across an entire AWS Organizations organization. This is achieved by targeting the root ID of the organization, and including child OUs.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
           --document-name "AWS-RestartEC2Instance" \
           --target-parameter-name InstanceId \
           --targets '[{"Key":"AWS::EC2::Instance","Values":["*"]}]' \
           --target-locations '[{
               "Accounts": ["r-example"],
               "IncludeChildOrganizationUnits": true,
               "Regions": ["us-east-1", "us-east-2", "us-west-2"]
           }]'
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution \
           --document-name "AWS-RestartEC2Instance" ^
           --target-parameter-name InstanceId ^
           --targets '[{"Key":"AWS::EC2::Instance","Values":["*"]}]' ^
           --target-locations '[{
               "Accounts": ["r-example"],
               "IncludeChildOrganizationUnits": true,
               "Regions": ["us-east-1", "us-east-2", "us-west-2"]
           }]'
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
           -DocumentName "AWS-RestartEC2Instance" `
           -TargetParameterName "InstanceId" `
           -Targets '[{"Key":"AWS::EC2::Instance","Values":["*"]}]'
           -TargetLocation @{
               "Accounts"="r-example";
               "Regions"="us-east-1", "us-east-2", "us-west-2";
               "IncludeChildOrganizationUnits"=true}
   ```

------

   **Example 2**: This example restarts specific EC2 instances in different accounts and Regions.
**Note**  
The `TargetLocationMaxConcurrency` option is available using the AWS CLI and AWS SDKs.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
           --document-name "AWS-RestartEC2Instance" \
           --target-parameter-name InstanceId \
           --target-locations '[{
               "Accounts": ["123456789012"],
               "Targets": [{
                   "Key":"ParameterValues",
                   "Values":["i-02573cafcfEXAMPLE", "i-0471e04240EXAMPLE"]
               }],
               "TargetLocationMaxConcurrency": "100%",
               "Regions": ["us-east-1"]
           }, {
               "Accounts": ["987654321098"],
               "Targets": [{
                   "Key":"ParameterValues",
                   "Values":["i-07782c72faEXAMPLE"]
               }],
               "TargetLocationMaxConcurrency": "100%",
               "Regions": ["us-east-2"]
           }]'
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
           --document-name "AWS-RestartEC2Instance" ^
           --target-parameter-name InstanceId ^
           --target-locations '[{
               "Accounts": ["123456789012"],
               "Targets": [{
                   "Key":"ParameterValues",
                   "Values":["i-02573cafcfEXAMPLE", "i-0471e04240EXAMPLE"]
               }],
               "TargetLocationMaxConcurrency": "100%",
               "Regions": ["us-east-1"]
           }, {
               "Accounts": ["987654321098"],
               "Targets": [{
                   "Key":"ParameterValues",
                   "Values":["i-07782c72faEXAMPLE"]
               }],
               "TargetLocationMaxConcurrency": "100%",
               "Regions": ["us-east-2"]
           }]'
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
           -DocumentName "AWS-RestartEC2Instance" `
           -TargetParameterName "InstanceId" `
           -Targets '[{"Key":"AWS::EC2::Instance","Values":["*"]}]'
           -TargetLocation @({
               "Accounts"="123456789012",
               "Targets"= @{
                   "Key":"ParameterValues",
                   "Values":["i-02573cafcfEXAMPLE", "i-0471e04240EXAMPLE"]
               },
               "TargetLocationMaxConcurrency"="100%",
               "Regions"=["us-east-1"]
           }, {
               "Accounts"="987654321098",
               "Targets": @{
                   "Key":"ParameterValues",
                   "Values":["i-07782c72faEXAMPLE"]
               },
               "TargetLocationMaxConcurrency": "100%",
               "Regions"=["us-east-2"]
           })
   ```

------

   **Example 3**: This example demonstrates specifying multiple AWS accounts and Regions where the automation should run using the `--target-locations-url` option. The value for this option must be a JSON file in a publicly accessible [presigned Amazon S3 URL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html).
**Note**  
`--target-locations-url` is available when using the AWS CLI and AWS SDKs.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name "MyCustomAutomationRunbook" \
       --target-locations-url "https://amzn-s3-demo-bucket.s3.amazonaws.com/target-locations.json"
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name "MyCustomAutomationRunbook" ^
       --target-locations-url "https://amzn-s3-demo-bucket.s3.amazonaws.com/target-locations.json"
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
       -DocumentName "MyCustomAutomationRunbook" `
       -TargetLocationsUrl "https://amzn-s3-demo-bucket.s3.amazonaws.com/target-locations.json"
   ```

------

   Sample content for the JSON file:

   ```
   [
   { 
            "Accounts": [ "123456789012", "987654321098", "456789123012" ],
            "ExcludeAccounts": [ "111222333444", "999888444666" ],
            "ExecutionRoleName": "MyAutomationExecutionRole",
            "IncludeChildOrganizationUnits": true,
            "Regions": [ "us-east-1", "us-west-2", "ap-south-1", "ap-northeast-1" ],
            "Targets": ["Key": "AWS::EC2::Instance", "Values": ["i-2"]],
            "TargetLocationMaxConcurrency": "50%",
            "TargetLocationMaxErrors": "10",
            "TargetsMaxConcurrency": "20",
            "TargetsMaxErrors": "12"
    }
   ]
   ```

   **Example 4**: This example restarts EC2 instances in the `123456789012` and `987654321098` accounts, which are located in the `us-east-2` and `us-west-1` Regions. The instances must be tagged with the tag key-pair value `Env-PROD`.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
           --document-name AWS-RestartEC2Instance \
           --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole \
           --target-parameter-name InstanceId \
           --targets Key=tag:Env,Values=PROD \
           --target-locations Accounts=123456789012,987654321098,Regions=us-east-2,us-west-1,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
           --document-name AWS-RestartEC2Instance ^
           --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole ^
           --target-parameter-name InstanceId ^
           --targets Key=tag:Env,Values=PROD ^
           --target-locations Accounts=123456789012,987654321098,Regions=us-east-2,us-west-1,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
       $Targets.Key = "tag:Env"
       $Targets.Values = "PROD"
       
       Start-SSMAutomationExecution `
           -DocumentName "AWS-RestartEC2Instance" `
           -Parameter @{
           "AutomationAssumeRole"="arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole" } `
           -TargetParameterName "InstanceId" `
           -Target $Targets `
           -TargetLocation @{
           "Accounts"="123456789012","987654321098";
           "Regions"="us-east-2","us-west-1";
           "ExecutionRoleName"="AWS-SystemsManager-AutomationExecutionRole" }
   ```

------

   **Example 5**: This example restarts EC2 instances in the `123456789012` and `987654321098` accounts, which are located in the `eu-central-1` Region. The instances must be members of the `prod-instances` AWS resource group.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
           --document-name AWS-RestartEC2Instance \
           --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole \
           --target-parameter-name InstanceId \
           --targets Key=ResourceGroup,Values=prod-instances \
           --target-locations Accounts=123456789012,987654321098,Regions=eu-central-1,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
           --document-name AWS-RestartEC2Instance ^
           --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole ^
           --target-parameter-name InstanceId ^
           --targets Key=ResourceGroup,Values=prod-instances ^
           --target-locations Accounts=123456789012,987654321098,Regions=eu-central-1,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
       $Targets.Key = "ResourceGroup"
       $Targets.Values = "prod-instances"
       
       Start-SSMAutomationExecution `
           -DocumentName "AWS-RestartEC2Instance" `
           -Parameter @{
           "AutomationAssumeRole"="arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole" } `
           -TargetParameterName "InstanceId" `
           -Target $Targets `
           -TargetLocation @{
           "Accounts"="123456789012","987654321098";
           "Regions"="eu-central-1";
           "ExecutionRoleName"="AWS-SystemsManager-AutomationExecutionRole" }
   ```

------

   **Example 6**: This example restarts EC2 instances in the `ou-1a2b3c-4d5e6c` AWS organizational unit (OU). The instances are located in the `us-west-1` and `us-west-2` Regions. The instances must be members of the `WebServices` AWS resource group.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
           --document-name AWS-RestartEC2Instance \
           --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole \
           --target-parameter-name InstanceId \
           --targets Key=ResourceGroup,Values=WebServices \
           --target-locations Accounts=ou-1a2b3c-4d5e6c,Regions=us-west-1,us-west-2,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
           --document-name AWS-RestartEC2Instance ^
           --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole ^
           --target-parameter-name InstanceId ^
           --targets Key=ResourceGroup,Values=WebServices ^
           --target-locations Accounts=ou-1a2b3c-4d5e6c,Regions=us-west-1,us-west-2,ExecutionRoleName=AWS-SystemsManager-AutomationExecutionRole
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
       $Targets.Key = "ResourceGroup"
       $Targets.Values = "WebServices"
       
       Start-SSMAutomationExecution `
           -DocumentName "AWS-RestartEC2Instance" `
           -Parameter @{
           "AutomationAssumeRole"="arn:aws:iam::123456789012:role/AWS-SystemsManager-AutomationAdministrationRole" } `
           -TargetParameterName "InstanceId" `
           -Target $Targets `
           -TargetLocation @{
           "Accounts"="ou-1a2b3c-4d5e6c";
           "Regions"="us-west-1";
           "ExecutionRoleName"="AWS-SystemsManager-AutomationExecutionRole" }
   ```

------

   The system returns information similar to the following.

------
#### [ Linux & macOS ]

   ```
   {
           "AutomationExecutionId": "4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE"
       }
   ```

------
#### [ Windows ]

   ```
   {
           "AutomationExecutionId": "4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE"
       }
   ```

------
#### [ PowerShell ]

   ```
   4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE
   ```

------

1. Run the following command to view details for the automation. Replace *automation execution ID* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-automation-executions \
           --filters Key=ExecutionId,Values=automation execution ID
   ```

------
#### [ Windows ]

   ```
   aws ssm describe-automation-executions ^
           --filters Key=ExecutionId,Values=automation execution ID
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMAutomationExecutionList | `
           Where {$_.AutomationExecutionId -eq "automation execution ID"}
   ```

------

1. Run the following command to view details about the automation progress.

------
#### [ Linux & macOS ]

   ```
   aws ssm get-automation-execution \
           --automation-execution-id 4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE
   ```

------
#### [ Windows ]

   ```
   aws ssm get-automation-execution ^
           --automation-execution-id 4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMAutomationExecution `
           -AutomationExecutionId a4a3c0e9-7efd-462a-8594-01234EXAMPLE
   ```

------
**Note**  
You can also monitor the status of the automation in the console. In the **Automation executions** list, choose the automation you just ran and then choose the **Execution steps** tab. This tab shows the status of the automation actions.

**More info**  
[Centralized multi-account and multi-Region patching with AWS Systems Manager Automation](https://aws.amazon.com/blogs/mt/centralized-multi-account-and-multi-region-patching-with-aws-systems-manager-automation/)

# Run automations based on EventBridge events
<a name="running-automations-event-bridge"></a>

You can start an automation by specifying a runbook as the target of an Amazon EventBridge event. You can start automations according to a schedule, or when a specific AWS system event occurs. For example, let's say you create a runbook named *BootStrapInstances* that installs software on an instance when an instance starts. To specify the *BootStrapInstances* runbook (and corresponding automation) as a target of an EventBridge event, you first create a new EventBridge rule. (Here's an example rule: **Service name**: EC2, **Event Type**: EC2 Instance State-change Notification, **Specific state(s)**: running, **Any instance**.) Then you use the following procedures to specify the *BootStrapInstances* runbook as the target of the event using the EventBridge console and AWS Command Line Interface (AWS CLI). When a new instance starts, the system runs the automation and installs software.

For information about creating runbooks, see [Creating your own runbooks](automation-documents.md).

## Creating an EventBridge event that uses a runbook (console)
<a name="automation-cwe-target-console"></a>

Use the following procedure to configure a runbook as the target of a EventBridge event.

**To configure a runbook as a target of a EventBridge event rule**

1. Open the Amazon EventBridge console at [https://console.aws.amazon.com/events/](https://console.aws.amazon.com/events/).

1. In the navigation pane, choose **Rules**.

1. Choose **Create rule**.

1. Enter a name and description for the rule.

   A rule can't have the same name as another rule in the same Region and on the same event bus.

1. For **Event bus**, choose the event bus that you want to associate with this rule. If you want this rule to respond to matching events that come from your own AWS account, select **default**. When an AWS service in your account emits an event, it always goes to your account’s default event bus.

1. Choose how the rule is triggered.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/running-automations-event-bridge.html)

1. Choose **Next**.

1. For **Target types**, choose **AWS service**.

1. For **Select a target**, choose **Systems Manager Automation**. 

1. For **Document**, choose a runbook to use when your target is invoked.

1. In the **Configure automation parameter(s)** section, either keep the default parameter values (if available) or enter your own values. 
**Note**  
To create a target, you must specify a value for each required parameter. If you don't, the system creates the rule, but the rule won't run.

1. For many target types, EventBridge needs permissions to send events to the target. In these cases, EventBridge can create the IAM role needed for your rule to run. Do one of the following:
   + To create an IAM role automatically, choose **Create a new role for this specific resource**.
   + To use an IAM role that you created earlier, choose **Use existing role** and select the existing role from the dropdown. Note that you might need to update the trust policy for your IAM role to include EventBridge. The following is an example:

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Sid": "",
               "Effect": "Allow",
               "Principal": {
                   "Service": [
                       "events.amazonaws.com",
                       "ssm.amazonaws.com"
                   ]
               },
               "Action": "sts:AssumeRole"
           }
       ]
   }
   ```

------

1. Choose **Next**.

1. (Optional) Enter one or more tags for the rule. For more information, see [Tagging Your Amazon EventBridge Resources](https://docs.aws.amazon.com/eventbridge/latest/userguide/eventbridge-tagging.html) in the *Amazon EventBridge User Guide*.

1. Choose **Next**.

1. Review the details of the rule and choose **Create rule**.

## Create an EventBridge event that uses a runbook (command line)
<a name="automation-cwe-target-commandline"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows) or AWS Tools for PowerShell to create an EventBridge event rule and configure a runbook as the target.

**To configure a runbook as a target of an EventBridge event rule**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Create a command to specify a new EventBridge event rule. Replace each *example resource placeholder* with your own information.

   *Triggers based on a schedule*

------
#### [ Linux & macOS ]

   ```
   aws events put-rule \
   --name "rule name" \
   --schedule-expression "cron or rate expression"
   ```

------
#### [ Windows ]

   ```
   aws events put-rule ^
   --name "rule name" ^
   --schedule-expression "cron or rate expression"
   ```

------
#### [ PowerShell ]

   ```
   Write-CWERule `
   -Name "rule name" `
   -ScheduleExpression "cron or rate expression"
   ```

------

   The following example creates an EventBridge event rule that starts every day at 9:00 AM (UTC).

------
#### [ Linux & macOS ]

   ```
   aws events put-rule \
   --name "DailyAutomationRule" \
   --schedule-expression "cron(0 9 * * ? *)"
   ```

------
#### [ Windows ]

   ```
   aws events put-rule ^
   --name "DailyAutomationRule" ^
   --schedule-expression "cron(0 9 * * ? *)"
   ```

------
#### [ PowerShell ]

   ```
   Write-CWERule `
   -Name "DailyAutomationRule" `
   -ScheduleExpression "cron(0 9 * * ? *)"
   ```

------

   *Triggers based on an event*

------
#### [ Linux & macOS ]

   ```
   aws events put-rule \
   --name "rule name" \
   --event-pattern "{\"source\":[\"aws.service\"],\"detail-type\":[\"service event detail type\"]}"
   ```

------
#### [ Windows ]

   ```
   aws events put-rule ^
   --name "rule name" ^
   --event-pattern "{\"source\":[\"aws.service\"],\"detail-type\":[\"service event detail type\"]}"
   ```

------
#### [ PowerShell ]

   ```
   Write-CWERule `
   -Name "rule name" `
   -EventPattern '{"source":["aws.service"],"detail-type":["service event detail type"]}'
   ```

------

   The following example creates an EventBridge event rule that starts when any EC2 instance in the Region changes state.

------
#### [ Linux & macOS ]

   ```
   aws events put-rule \
   --name "EC2InstanceStateChanges" \
   --event-pattern "{\"source\":[\"aws.ec2\"],\"detail-type\":[\"EC2 Instance State-change Notification\"]}"
   ```

------
#### [ Windows ]

   ```
   aws events put-rule ^
   --name "EC2InstanceStateChanges" ^
   --event-pattern "{\"source\":[\"aws.ec2\"],\"detail-type\":[\"EC2 Instance State-change Notification\"]}"
   ```

------
#### [ PowerShell ]

   ```
   Write-CWERule `
   -Name "EC2InstanceStateChanges" `
   -EventPattern '{"source":["aws.ec2"],"detail-type":["EC2 Instance State-change Notification"]}'
   ```

------

   The command returns details for the new EventBridge rule similar to the following.

------
#### [ Linux & macOS ]

   ```
   {
   "RuleArn": "arn:aws:events:us-east-1:123456789012:rule/automationrule"
   }
   ```

------
#### [ Windows ]

   ```
   {
   "RuleArn": "arn:aws:events:us-east-1:123456789012:rule/automationrule"
   }
   ```

------
#### [ PowerShell ]

   ```
   arn:aws:events:us-east-1:123456789012:rule/EC2InstanceStateChanges
   ```

------

1. Create a command to specify a runbook as a target of the EventBridge event rule you created in step 2. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws events put-targets \
   --rule rule name \
   --targets '{"Arn": " arn:aws:ssm:region:account ID:automation-definition/runbook name","Input":"{\"Message\":[\"{\\\"Key\\\":\\\"key name\\\",\\\"Values\\\":[\\\"value\\\"]}\"]}","Id": "target ID","RoleArn": "arn:aws:iam::123456789012:role/service-role/EventBridge service role"}'
   ```

------
#### [ Windows ]

   ```
   aws events put-targets ^
   --rule rule name ^
   --targets '{"Arn": "arn:aws:ssm:region:account ID:automation-definition/runbook name","Input":"{\"Message\":[\"{\\\"Key\\\":\\\"key name\\\",\\\"Values\\\":[\\\"value\\\"]}\"]}","Id": "target ID","RoleArn": "arn:aws:iam::123456789012:role/service-role/EventBridge service role"}'
   ```

------
#### [ PowerShell ]

   ```
   $Target = New-Object Amazon.CloudWatchEvents.Model.Target
   $Target.Id = "target ID"
   $Target.Arn = "arn:aws:ssm:region:account ID:automation-definition/runbook name"
   $Target.RoleArn = "arn:aws:iam::123456789012:role/service-role/EventBridge service role"
   $Target.Input = '{"input parameter":["value"],"AutomationAssumeRole":["arn:aws:iam::123456789012:role/AutomationServiceRole"]}'
   
   Write-CWETarget `
   -Rule "rule name" `
   -Target $Target
   ```

------

   The following example creates an EventBridge event target that starts the specified instance ID using the runbook `AWS-StartEC2Instance`.

------
#### [ Linux & macOS ]

   ```
   aws events put-targets \
   --rule DailyAutomationRule \
   --targets '{"Arn": "arn:aws:ssm:region:*:automation-definition/AWS-StartEC2Instance","Input":"{\"InstanceId\":[\"i-02573cafcfEXAMPLE\"],\"AutomationAssumeRole\":[\"arn:aws:iam::123456789012:role/AutomationServiceRole\"]}","Id": "Target1","RoleArn": "arn:aws:iam::123456789012:role/service-role/AWS_Events_Invoke_Start_Automation_Execution_1213609520"}'
   ```

------
#### [ Windows ]

   ```
   aws events put-targets ^
   --rule DailyAutomationRule ^
   --targets '{"Arn": "arn:aws:ssm:region:*:automation-definition/AWS-StartEC2Instance","Input":"{\"InstanceId\":[\"i-02573cafcfEXAMPLE\"],\"AutomationAssumeRole\":[\"arn:aws:iam::123456789012:role/AutomationServiceRole\"]}","Id": "Target1","RoleArn": "arn:aws:iam::123456789012:role/service-role/AWS_Events_Invoke_Start_Automation_Execution_1213609520"}'
   ```

------
#### [ PowerShell ]

   ```
   $Target = New-Object Amazon.CloudWatchEvents.Model.Target
   $Target.Id = "Target1"
   $Target.Arn = "arn:aws:ssm:region:*:automation-definition/AWS-StartEC2Instance"
   $Target.RoleArn = "arn:aws:iam::123456789012:role/service-role/AWS_Events_Invoke_Start_Automation_Execution_1213609520"
   $Target.Input = '{"InstanceId":["i-02573cafcfEXAMPLE"],"AutomationAssumeRole":["arn:aws:iam::123456789012:role/AutomationServiceRole"]}'
   
   Write-CWETarget `
   -Rule "DailyAutomationRule" `
   -Target $Target
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
   "FailedEntries": [],
   "FailedEntryCount": 0
   }
   ```

------
#### [ Windows ]

   ```
   {
   "FailedEntries": [],
   "FailedEntryCount": 0
   }
   ```

------
#### [ PowerShell ]

   There is no output if the command succeeds for PowerShell.

------

# Run an automation step by step
<a name="automation-working-executing-manually"></a>

The following procedures describe how to use the AWS Systems Manager console and AWS Command Line Interface (AWS CLI) to run an automation using the manual execution mode. By using the manual execution mode, the automation starts in a *Waiting* status and pauses in the *Waiting* status between each step. This allows you to control when the automation proceeds, which is useful if you need to review the result of a step before continuing.

The automation runs in the context of the current user. This means that you don't need to configure additional IAM permissions as long as you have permission to use the runbook, and any actions called by the runbook. If you have administrator permissions in IAM, then you already have permission to run this automation.

## Running an automation step by step (console)
<a name="automation-working-executing-manually-console"></a>

The following procedure shows how to use the Systems Manager console to manually run an automation step by step.

**To run an automation step by step**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Automation document** list, choose a runbook. Choose one or more options in the **Document categories** pane to filter SSM documents according to their purpose. To view a runbook that you own, choose the **Owned by me** tab. To view a runbook that is shared with your account, choose the **Shared with me** tab. To view all runbooks, choose the **All documents** tab.
**Note**  
You can view information about a runbook by choosing the runbook name.

1. In the **Document details** section, verify that **Document version** is set to the version that you want to run. The system includes the following version options: 
   + **Default version at runtime** – Choose this option if the Automation runbook is updated periodically and a new default version is assigned.
   + **Latest version at runtime** – Choose this option if the Automation runbook is updated periodically, and you want to run the version that was most recently updated.
   + **1 (Default)** – Choose this option to run the first version of the document, which is the default.

1. Choose **Next**.

1. In the **Execution Mode** section, choose **Manual execution**.

1. In the **Input parameters** section, specify the required inputs. Optionally, you can choose an IAM service role from the **AutomationAssumeRole** list.

1. Choose **Execute**. 

1. Choose **Execute this step** when you're ready to start the first step of the automation. The automation proceeds with step one and pauses before running any subsequent steps specified in the runbook you chose in step 3 of this procedure. If the runbook has multiple steps, you must select **Execute this step** for each step for the automation to proceed. Each time you choose **Execute this step** the action runs.
**Note**  
The console displays the status of the automation. If the automation fails to run a step, see [Troubleshooting Systems Manager Automation](automation-troubleshooting.md).

1. After you complete all steps specified in the runbook, choose **Complete and view results** to finish the automation and view the results.

After an automation execution completes, you can rerun the execution with the same or modified parameters. For more information, see [Rerunning automation executions](automation-rerun-executions.md).

## Running an automation step by step (command line)
<a name="automation-working-executing-manually-commandline"></a>

The following procedure describes how to use the AWS CLI (on Linux, macOS, or Windows) or AWS Tools for PowerShell to manually run an automation step by step.

**To run an automation step by step**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Run the following command to start a manual automation. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name runbook name \
       --mode Interactive \
       --parameters runbook parameters
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name runbook name ^
       --mode Interactive ^
       --parameters runbook parameters
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
       -DocumentName runbook name `
       -Mode Interactive `
       -Parameter runbook parameters
   ```

------

   Here is an example using the runbook `AWS-RestartEC2Instance` to restart the specified EC2 instance.

------
#### [ Linux & macOS ]

   ```
   aws ssm start-automation-execution \
       --document-name "AWS-RestartEC2Instance" \
       --mode Interactive \
       --parameters "InstanceId=i-02573cafcfEXAMPLE"
   ```

------
#### [ Windows ]

   ```
   aws ssm start-automation-execution ^
       --document-name "AWS-RestartEC2Instance" ^
       --mode Interactive ^
       --parameters "InstanceId=i-02573cafcfEXAMPLE"
   ```

------
#### [ PowerShell ]

   ```
   Start-SSMAutomationExecution `
       -DocumentName AWS-RestartEC2Instance `
       -Mode Interactive 
       -Parameter @{"InstanceId"="i-02573cafcfEXAMPLE"}
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
       "AutomationExecutionId": "ba9cd881-1b36-4d31-a698-0123456789ab"
   }
   ```

------
#### [ Windows ]

   ```
   {
       "AutomationExecutionId": "ba9cd881-1b36-4d31-a698-0123456789ab"
   }
   ```

------
#### [ PowerShell ]

   ```
   ba9cd881-1b36-4d31-a698-0123456789ab
   ```

------

1. Run the following command when you're ready to start the first step of the automation. Replace each *example resource placeholder* with your own information. The automation proceeds with step one and pauses before running any subsequent steps specified in the runbook you chose in step 1 of this procedure. If the runbook has multiple steps, you must run the following command for each step for the automation to proceed.

------
#### [ Linux & macOS ]

   ```
   aws ssm send-automation-signal \
       --automation-execution-id ba9cd881-1b36-4d31-a698-0123456789ab \
       --signal-type StartStep \
       --payload StepName="stopInstances"
   ```

------
#### [ Windows ]

   ```
   aws ssm send-automation-signal ^
       --automation-execution-id ba9cd881-1b36-4d31-a698-0123456789ab ^
       --signal-type StartStep ^
       --payload StepName="stopInstances"
   ```

------
#### [ PowerShell ]

   ```
   Send-SSMAutomationSignal `
       -AutomationExecutionId ba9cd881-1b36-4d31-a698-0123456789ab `
       -SignalType StartStep 
       -Payload @{"StepName"="stopInstances"}
   ```

------

   There is no output if the command succeeds.

1. Run the following command to retrieve the status of each step execution in the automation.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-automation-step-executions \
       --automation-execution-id ba9cd881-1b36-4d31-a698-0123456789ab
   ```

------
#### [ Windows ]

   ```
   aws ssm describe-automation-step-executions ^
       --automation-execution-id ba9cd881-1b36-4d31-a698-0123456789ab
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMAutomationStepExecution `
       -AutomationExecutionId ba9cd881-1b36-4d31-a698-0123456789ab
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
       "StepExecutions": [
           {
               "StepName": "stopInstances",
               "Action": "aws:changeInstanceState",
               "ExecutionStartTime": 1557167178.42,
               "ExecutionEndTime": 1557167220.617,
               "StepStatus": "Success",
               "Inputs": {
                   "DesiredState": "\"stopped\"",
                   "InstanceIds": "[\"i-02573cafcfEXAMPLE\"]"
               },
               "Outputs": {
                   "InstanceStates": [
                       "stopped"
                   ]
               },
               "StepExecutionId": "654243ba-71e3-4771-b04f-0123456789ab",
               "OverriddenParameters": {},
               "ValidNextSteps": [
                   "startInstances"
               ]
           },
           {
               "StepName": "startInstances",
               "Action": "aws:changeInstanceState",
               "ExecutionStartTime": 1557167273.754,
               "ExecutionEndTime": 1557167480.73,
               "StepStatus": "Success",
               "Inputs": {
                   "DesiredState": "\"running\"",
                   "InstanceIds": "[\"i-02573cafcfEXAMPLE\"]"
               },
               "Outputs": {
                   "InstanceStates": [
                       "running"
                   ]
               },
               "StepExecutionId": "8a4a1e0d-dc3e-4039-a599-0123456789ab",
               "OverriddenParameters": {}
           }
       ]
   }
   ```

------
#### [ Windows ]

   ```
   {
       "StepExecutions": [
           {
               "StepName": "stopInstances",
               "Action": "aws:changeInstanceState",
               "ExecutionStartTime": 1557167178.42,
               "ExecutionEndTime": 1557167220.617,
               "StepStatus": "Success",
               "Inputs": {
                   "DesiredState": "\"stopped\"",
                   "InstanceIds": "[\"i-02573cafcfEXAMPLE\"]"
               },
               "Outputs": {
                   "InstanceStates": [
                       "stopped"
                   ]
               },
               "StepExecutionId": "654243ba-71e3-4771-b04f-0123456789ab",
               "OverriddenParameters": {},
               "ValidNextSteps": [
                   "startInstances"
               ]
           },
           {
               "StepName": "startInstances",
               "Action": "aws:changeInstanceState",
               "ExecutionStartTime": 1557167273.754,
               "ExecutionEndTime": 1557167480.73,
               "StepStatus": "Success",
               "Inputs": {
                   "DesiredState": "\"running\"",
                   "InstanceIds": "[\"i-02573cafcfEXAMPLE\"]"
               },
               "Outputs": {
                   "InstanceStates": [
                       "running"
                   ]
               },
               "StepExecutionId": "8a4a1e0d-dc3e-4039-a599-0123456789ab",
               "OverriddenParameters": {}
           }
       ]
   }
   ```

------
#### [ PowerShell ]

   ```
   Action: aws:changeInstanceState
   ExecutionEndTime     : 5/6/2019 19:45:46
   ExecutionStartTime   : 5/6/2019 19:45:03
   FailureDetails       : 
   FailureMessage       : 
   Inputs               : {[DesiredState, "stopped"], [InstanceIds, ["i-02573cafcfEXAMPLE"]]}
   IsCritical           : False
   IsEnd                : False
   MaxAttempts          : 0
   NextStep             : 
   OnFailure            : 
   Outputs              : {[InstanceStates, Amazon.Runtime.Internal.Util.AlwaysSendList`1[System.String]]}
   OverriddenParameters : {}
   Response             : 
   ResponseCode         : 
   StepExecutionId      : 8fcc9641-24b7-40b3-a9be-0123456789ab
   StepName             : stopInstances
   StepStatus           : Success
   TimeoutSeconds       : 0
   ValidNextSteps       : {startInstances}
   ```

------

1. Run the following command to complete the automation after all steps specified within the chosen runbook have finished. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm stop-automation-execution \
       --automation-execution-id ba9cd881-1b36-4d31-a698-0123456789ab \
       --type Complete
   ```

------
#### [ Windows ]

   ```
   aws ssm stop-automation-execution ^
       --automation-execution-id ba9cd881-1b36-4d31-a698-0123456789ab ^
       --type Complete
   ```

------
#### [ PowerShell ]

   ```
   Stop-SSMAutomationExecution `
       -AutomationExecutionId ba9cd881-1b36-4d31-a698-0123456789ab `
       -Type Complete
   ```

------

   There is no output if the command succeeds.

# Scheduling automations with State Manager associations
<a name="scheduling-automations-state-manager-associations"></a>

You can start an automation by creating a State Manager association with a runbook. State Manager is a tool in AWS Systems Manager. By creating a State Manager association with a runbook, you can target different types of AWS resources. For example, you can create associations that enforce a desired state on an AWS resource, including the following:
+ Attach a Systems Manager role to Amazon Elastic Compute Cloud (Amazon EC2) instances to make them *managed instances*.
+ Enforce desired ingress and egress rules for a security group.
+ Create or delete Amazon DynamoDB backups.
+ Create or delete Amazon Elastic Block Store (Amazon EBS) snapshots.
+ Turn off read and write permissions on Amazon Simple Storage Service (Amazon S3) buckets.
+ Start, restart, or stop managed instances and Amazon Relational Database Service (Amazon RDS) instances.
+ Apply patches to Linux, macOS, and Window AMIs.

Use the following procedures to create a State Manager association that runs an automation using the AWS Systems Manager console and AWS Command Line Interface (AWS CLI). For general information about associations and information about creating an association that uses an SSM `Command` document or `Policy` document, see [Creating associations](state-manager-associations-creating.md).

**Before you begin**  
Be aware of the following important details before you run an automation by using State Manager:
+ Before you can create an association that uses a runbook, verify that you configured permissions for Automation, a tool in AWS Systems Manager. For more information, see [Setting up Automation](automation-setup.md).
+ State Manager associations that use runbooks contribute to the maximum number of concurrently running automations in your AWS account. You can have a maximum of 100 concurrent automations running. For information, see [Systems Manager service quotas](https://docs.aws.amazon.com/general/latest/gr/ssm.html#limits_ssm) in the *Amazon Web Services General Reference*.
+ When running an automation, State Manager does not log the API operations initiated by the automation in AWS CloudTrail.
+ Systems Manager automatically creates a service-linked role so that State Manager has permission to call Systems Manager Automation API operations. If you want, you can create the service-linked role yourself by running the following command from the AWS CLI or AWS Tools for PowerShell.

------
#### [ Linux & macOS ]

  ```
  aws iam create-service-linked-role \
  --aws-service-name ssm.amazonaws.com
  ```

------
#### [ Windows ]

  ```
  aws iam create-service-linked-role ^
  --aws-service-name ssm.amazonaws.com
  ```

------
#### [ PowerShell ]

  ```
  New-IAMServiceLinkedRole `
  -AWSServiceName ssm.amazonaws.com
  ```

------

  For more information about service-linked roles, see [Using service-linked roles for Systems Manager](using-service-linked-roles.md).

## Creating an association that runs an automation (console)
<a name="create-automation-association-console"></a>

The following procedure describes how to use the Systems Manager console to create a State Manager association that runs an automation.

**To create a State Manager association that runs an automation**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **State Manager**, and then choose **Create association**.

1. In the **Name** field, specify a name. This is optional, but recommended.

1. In the **Document** list, choose a runbook. Use the Search bar to filter on **Document type : Equal : Automation** runbooks. To view more runbooks, use the numbers to the right of the Search bar. 
**Note**  
You can view information about a runbook by choosing the runbook name.

1. Choose **Simple execution** to run the automation on one or more targets by specifying the resource ID for those targets. Choose **Rate control** to run the automation across a fleet of AWS resources by specifying a targeting option such as tags or AWS Resource Groups. You can also control the operation of the automation across your resources by specifying concurrency and error thresholds.

   If you chose **Rate control**, the **Targets** section is displayed.

1. In the **Targets** section, choose a method for targeting resources.

   1. (Required) In the **Parameter** list, choose a parameter. The items in the **Parameter** list are determined by the parameters in the runbook that you selected at the start of this procedure. By choosing a parameter, you define the type of resource on which the automation runs. 

   1. (Required) In the **Targets** list, choose a method for targeting the resources.
      + **Resource Group**: Choose the name of the group from the **Resource Group** list. For more information about targeting AWS Resource Groups in runbooks, see [Targeting AWS Resource Groups](running-automations-map-targets.md#target-resource-groups).
      + **Tags**: Enter the tag key and (optionally) the tag value in the fields provided. Choose **Add**. For more information about targeting tags in runbooks, see [Targeting a tag](running-automations-map-targets.md#target-tags).
      + **Parameter Values**: Enter values in the **Input parameters** section. If you specify multiple values, Systems Manager runs a child automation on each value specified.

        For example, say that your runbook includes an **InstanceID** parameter. If you target the values of the **InstanceID** parameter when you run the automation, then Systems Manager runs a child automation for each instance ID value specified. The parent automation is complete when the automation finishes running each specified instance, or if the automation fails. You can target a maximum of 50 parameter values. For more information about targeting parameter values in runbooks, see [Targeting parameter values](running-automations-map-targets.md#target-parameter-values).

1. In the **Input parameters** section, specify the required input parameters.

   If you chose to target resources by using tags or a resource group, then you might not need to choose some of the options in the **Input parameters** section. For example, if you chose the `AWS-RestartEC2Instance` runbook, and you chose to target instances by using tags, then you don't need to specify or choose instance IDs in the **Input parameters** section. The automation locates the instances to restart by using the tags you specified. 
**Important**  
You must specify a role ARN in the **AutomationAssumeRole** field. State Manager uses the assume role to call AWS services specified in the runbook and run Automation associations on your behalf.

1. In the **Specify schedule** section, choose **On Schedule** if you want to run the association at regular intervals. If you choose this option, then use the options provided to create the schedule using Cron or Rate expressions. For more information about Cron and Rate expressions for State Manager, see [Cron and rate expressions for associations](reference-cron-and-rate-expressions.md#reference-cron-and-rate-expressions-association). 
**Note**  
Rate expressions are the preferred scheduling mechanism for State Manager associations that use runbooks. Rate expressions allow more flexibility for running associations in the event that you reach the maximum number of concurrently running automations. With a rate schedule, Systems Manager can retry the automation shortly after receiving notification that concurrent automations have reached their maximum and have been throttled.

   Choose **No schedule** if you want to run the association one time. 

1. (Optional) In the **Rate Control** section, choose **Concurrency** and **Error threshold** options to control the automation deployment across your AWS resources.

   1. In the **Concurrency** section, choose an option: 
      + Choose **targets** to enter an absolute number of targets that can run the automation simultaneously.
      + Choose **percentage** to enter a percentage of the target set that can run the automation simultaneously.

   1. In the **Error threshold** section, choose an option:
      + Choose **errors** to enter an absolute number of errors allowed before Automation stops sending the automation to other resources.
      + Choose **percentage** to enter a percentage of errors allowed before Automation stops sending the automation to other resources.

   For more information about using targets and rate controls with Automation, see [Run automated operations at scale](running-automations-scale.md).

1. Choose **Create Association**. 
**Important**  
When you create an association, the association immediately runs against the specified targets. The association then runs based on the cron or rate expression you chose. If you chose **No schedule**, the association doesn't run again.

## Creating an association that runs an automation (command line)
<a name="create-automation-association-cli"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows Server) or AWS Tools for PowerShell to create a State Manager association that runs an automation.

**Before you begin**  
Before you complete the following procedure, make sure you have created an IAM service role that contains the permissions necessary to run the runbook, and configured a trust relationship for Automation, a tool in AWS Systems Manager. For more information, see [Task 1: Create a service role for Automation](automation-setup-iam.md#create-service-role).

**To create an association that runs an automation**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Run the following command to view a list of documents.

------
#### [ Linux & macOS ]

   ```
   aws ssm list-documents
   ```

------
#### [ Windows ]

   ```
   aws ssm list-documents
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMDocumentList
   ```

------

   Note the name of the runbook that you want to use for the association.

1. Run the following command to view details about the runbook. In the following command, replace *runbook name* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-document \
   --name runbook name
   ```

   Note a parameter name (for example, `InstanceId`) that you want to use for the `--automation-target-parameter-name` option. This parameter determines the type of resource on which the automation runs.

------
#### [ Windows ]

   ```
   aws ssm describe-document ^
   --name runbook name
   ```

   Note a parameter name (for example, `InstanceId`) that you want to use for the `--automation-target-parameter-name` option. This parameter determines the type of resource on which the automation runs.

------
#### [ PowerShell ]

   ```
   Get-SSMDocumentDescription `
   -Name runbook name
   ```

   Note a parameter name (for example, `InstanceId`) that you want to use for the `AutomationTargetParameterName` option. This parameter determines the type of resource on which the automation runs.

------

1. Create a command that runs an automation using a State Manager association. Replace each *example resource placeholder* with your own information.

   *Targeting using tags*

------
#### [ Linux & macOS ]

   ```
   aws ssm create-association \
   --association-name association name \
   --targets Key=tag:key name,Values=value \
   --name runbook name \
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole \
   --automation-target-parameter-name target parameter \
   --schedule "cron or rate expression"
   ```

**Note**  
If you create an association by using the AWS CLI, use the `--targets` parameter to target instances for the association. Don't use the `--instance-id` parameter. The `--instance-id` parameter is a legacy parameter. 

------
#### [ Windows ]

   ```
   aws ssm create-association ^
   --association-name association name ^
   --targets Key=tag:key name,Values=value ^
   --name runbook name ^
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole ^
   --automation-target-parameter-name target parameter ^
   --schedule "cron or rate expression"
   ```

**Note**  
If you create an association by using the AWS CLI, use the `--targets` parameter to target instances for the association. Don't use the `--instance-id` parameter. The `--instance-id` parameter is a legacy parameter. 

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "tag:key name"
   $Targets.Values = "value"
   
   New-SSMAssociation `
   -AssociationName "association name" `
   -Target $Targets `
   -Name "runbook name" `
   -Parameters @{
   "AutomationAssumeRole"="arn:aws:iam::123456789012:role/RunbookAssumeRole" } `
   -AutomationTargetParameterName "target parameter" `
   -ScheduleExpression "cron or rate expression"
   ```

**Note**  
If you create an association by using the AWS Tools for PowerShell, use the `Target` parameter to target instances for the association. Don't use the `InstanceId` parameter. The `InstanceId` parameter is a legacy parameter. 

------

   *Targeting using parameter values*

------
#### [ Linux & macOS ]

   ```
   aws ssm create-association \
   --association-name association name \
   --targets Key=ParameterValues,Values=value,value 2,value 3 \
   --name runbook name \
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole \
   --automation-target-parameter-name target parameter \
   --schedule "cron or rate expression"
   ```

------
#### [ Windows ]

   ```
   aws ssm create-association ^
   --association-name association name ^
   --targets Key=ParameterValues,Values=value,value 2,value 3 ^
   --name runbook name ^
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole ^
   --automation-target-parameter-name target parameter ^
   --schedule "cron or rate expression"
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "ParameterValues"
   $Targets.Values = "value","value 2","value 3"
   
   New-SSMAssociation `
   -AssociationName "association name" `
   -Target $Targets `
   -Name "runbook name" `
   -Parameters @{
   "AutomationAssumeRole"="arn:aws:iam::123456789012:role/RunbookAssumeRole"} `
   -AutomationTargetParameterName "target parameter" `
   -ScheduleExpression "cron or rate expression"
   ```

------

   *Targeting using AWS Resource Groups*

------
#### [ Linux & macOS ]

   ```
   aws ssm create-association \
   --association-name association name \
   --targets Key=ResourceGroup,Values=resource group name \
   --name runbook name \
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole \
   --automation-target-parameter-name target parameter \
   --schedule "cron or rate expression"
   ```

------
#### [ Windows ]

   ```
   aws ssm create-association ^
   --association-name association name ^
   --targets Key=ResourceGroup,Values=resource group name ^
   --name runbook name ^
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole ^
   --automation-target-parameter-name target parameter ^
   --schedule "cron or rate expression"
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "ResourceGroup"
   $Targets.Values = "resource group name"
   
   New-SSMAssociation `
   -AssociationName "association name" `
   -Target $Targets `
   -Name "runbook name" `
   -Parameters @{
   "AutomationAssumeRole"="arn:aws:iam::123456789012:role/RunbookAssumeRole"} `
   -AutomationTargetParameterName "target parameter" `
   -ScheduleExpression "cron or rate expression"
   ```

------

   *Targeting multiple accounts and Regions*

------
#### [ Linux & macOS ]

   ```
   aws ssm create-association \
   --association-name association name \
   --targets Key=ResourceGroup,Values=resource group name \
   --name runbook name \
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole \
   --automation-target-parameter-name target parameter \
   --schedule "cron or rate expression" \ 
   --target-locations Accounts=111122223333,444455556666,444455556666,Regions=region,region
   ```

------
#### [ Windows ]

   ```
   aws ssm create-association ^
   --association-name association name ^
   --targets Key=ResourceGroup,Values=resource group name ^
   --name runbook name ^
   --parameters AutomationAssumeRole=arn:aws:iam::123456789012:role/RunbookAssumeRole ^
   --automation-target-parameter-name target parameter ^
   --schedule "cron or rate expression" ^ 
   --target-locations Accounts=111122223333,444455556666,444455556666,Regions=region,region
   ```

------
#### [ PowerShell ]

   ```
   $Targets = New-Object Amazon.SimpleSystemsManagement.Model.Target
   $Targets.Key = "ResourceGroup"
   $Targets.Values = "resource group name"
   
   New-SSMAssociation `
   -AssociationName "association name" `
   -Target $Targets `
   -Name "runbook name" `
   -Parameters @{
   "AutomationAssumeRole"="arn:aws:iam::123456789012:role/RunbookAssumeRole"} `
   -AutomationTargetParameterName "target parameter" `
   -ScheduleExpression "cron or rate expression" `
   -TargetLocations @{
       "Accounts"=["111122223333,444455556666,444455556666"],
       "Regions"=["region,region"]
   ```

------

   The command returns details for the new association similar to the following.

------
#### [ Linux & macOS ]

   ```
   {
   "AssociationDescription": {
       "ScheduleExpression": "cron(0 7 ? * MON *)",
       "Name": "AWS-StartEC2Instance",
       "Parameters": {
           "AutomationAssumeRole": [
               "arn:aws:iam::123456789012:role/RunbookAssumeRole"
           ]
       },
       "Overview": {
           "Status": "Pending",
           "DetailedStatus": "Creating"
       },
       "AssociationId": "1450b4b7-bea2-4e4b-b340-01234EXAMPLE",
       "DocumentVersion": "$DEFAULT",
       "AutomationTargetParameterName": "InstanceId",
       "LastUpdateAssociationDate": 1564686638.498,
       "Date": 1564686638.498,
       "AssociationVersion": "1",
       "AssociationName": "CLI",
       "Targets": [
           {
               "Values": [
                   "DEV"
               ],
               "Key": "tag:ENV"
           }
       ]
   }
   }
   ```

------
#### [ Windows ]

   ```
   {
   "AssociationDescription": {
       "ScheduleExpression": "cron(0 7 ? * MON *)",
       "Name": "AWS-StartEC2Instance",
       "Parameters": {
           "AutomationAssumeRole": [
               "arn:aws:iam::123456789012:role/RunbookAssumeRole"
           ]
       },
       "Overview": {
           "Status": "Pending",
           "DetailedStatus": "Creating"
       },
       "AssociationId": "1450b4b7-bea2-4e4b-b340-01234EXAMPLE",
       "DocumentVersion": "$DEFAULT",
       "AutomationTargetParameterName": "InstanceId",
       "LastUpdateAssociationDate": 1564686638.498,
       "Date": 1564686638.498,
       "AssociationVersion": "1",
       "AssociationName": "CLI",
       "Targets": [
           {
               "Values": [
                   "DEV"
               ],
               "Key": "tag:ENV"
           }
       ]
   }
   }
   ```

------
#### [ PowerShell ]

   ```
   Name                  : AWS-StartEC2Instance
   InstanceId            : 
   Date                  : 8/1/2019 7:31:38 PM
   Status.Name           : 
   Status.Date           : 
   Status.Message        : 
   Status.AdditionalInfo :
   ```

------

**Note**  
If you use tags to create an association on one or more target instances, and then you remove the tags from an instance, that instance no longer runs the association. The instance is disassociated from the State Manager document. 

## Troubleshooting automations run by State Manager associations
<a name="troubleshooting-automation-associations"></a>

Systems Manager Automation enforces a limit of 100 concurrent automations, and 1,000 queued automations per account, per Region. If a State Manager association that uses a runbook shows a status of **Failed** and a detailed status of **AutomationExecutionLimitExceeded**, then your automation might have reached the limit. As a result, Systems Manager throttles the automations. To resolve this issue, do the following:
+ Use a different rate or cron expression for your association. For example, if the association is scheduled to run every 30 minutes, then change the expression so that it runs every hour or two.
+ Delete existing automations that have a status of **Pending**. By deleting these automations, you clear the current queue.

# Schedule automations with maintenance windows
<a name="scheduling-automations-maintenance-windows"></a>

You can start an automation by configuring a runbook as a registered task for a maintenance window. By registering the runbook as a registered task, the maintenance window runs the automation during the scheduled maintenance period. 

For example, let's say you create a runbook named `CreateAMI` that creates an Amazon Machine Image (AMI) of instances registered as targets to the maintenance window. To specify the `CreateAMI` runbook (and corresponding automation) as a registered task of a maintenance window, you first create a maintenance window and register targets. Then you use the following procedure to specify the `CreateAMI` document as a registered task within the maintenance window. When the maintenance window starts during the scheduled period, the system runs the automation and creates an AMI of the registered targets.

For information about creating Automation runbooks, see [Creating your own runbooks](automation-documents.md). Automation is a tool in AWS Systems Manager.

Use the following procedures to configure an automation as a registered task for a maintenance window using the AWS Systems Manager console, AWS Command Line Interface (AWS CLI), or AWS Tools for Windows PowerShell.

## Registering an automation task to a maintenance window (console)
<a name="register-automation-task-maintenance-window-console"></a>

The following procedure describes how to use the Systems Manager console to configure an automation as a registered task for a maintenance window.

**Before you begin**  
Before you complete the following procedure, you must create a maintenance window and register at least one target. For more information, see the following procedures: 
+ [Create a maintenance window using the console](sysman-maintenance-create-mw.md).
+ [Assign targets to a maintenance window using the console](sysman-maintenance-assign-targets.md)

**To configure an automation as a registered task for a maintenance window**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the left navigation pane, choose **Maintenance Windows**, and then choose the maintenance window you want to register an Automation task with.

1. Choose **Actions**. Then choose **Register Automation task** to run your choice of an automation on targets by using a runbook.

1. For **Name**, enter a name for the task.

1. For **Description**, enter a description.

1. For **Document**, choose the runbook that defines the tasks to run.

1. For **Document version**, choose the runbook version to use.

1. For **Task priority**, specify a priority for this task. `1` is the highest priority. Tasks in a maintenance window are scheduled in priority order; tasks that have the same priority are scheduled in parallel.

1. In the **Targets** section, if the runbook you chose is one that runs tasks on resources, identify the targets on which you want to run this automation by specifying tags or by selecting instances manually.
**Note**  
If you want to pass the resources through input parameters instead of targets, you don't need to specify a maintenance window target.  
In many cases, you don't need to explicitly specify a target for an automation task. For example, say that you're creating an Automation-type task to update an Amazon Machine Image (AMI) for Linux using the `AWS-UpdateLinuxAmi` runbook. When the task runs, the AMI is updated with the latest available Linux distribution packages and Amazon software. New instances created from the AMI already have these updates installed. Because the ID of the AMI to be updated is specified in the input parameters for the runbook, there is no need to specify a target again in the maintenance window task.

   For information about maintenance window tasks that don't require targets, see [Registering maintenance window tasks without targets](maintenance-windows-targetless-tasks.md).

1. (Optional) For **Rate control**:
**Note**  
If the task you're running doesn't specify targets, you don;t need to specify rate controls.
   + For **Concurrency**, specify either a number or a percentage of targets on which to run the automation at the same time.

     If you selected targets by choosing tag key-value pairs, and you aren't certain how many targets use the selected tags, then limit the number of automations that can run at the same time by specifying a percentage.

     When the maintenance window runs, a new automation is initiated per target. There is a limit of 100 concurrent automations per AWS account. If you specify a concurrency rate greater than 100, concurrent automations greater than 100 are automatically added to the automation queue. For information, see [Systems Manager service quotas](https://docs.aws.amazon.com/general/latest/gr/ssm.html#limits_ssm) in the *Amazon Web Services General Reference*. 
   + For **Error threshold**, specify when to stop running the automation on other targets after it fails on either a number or a percentage of targets. For example, if you specify three errors, then Systems Manager stops running automations when the fourth error is received. Targets still processing the automation might also send errors.

1. In the **Input Parameters** section, specify parameters for the runbook. For runbooks, the system auto-populates some of the values. You can keep or replace these values.
**Important**  
For runbooks, you can optionally specify an Automation Assume Role. If you don't specify a role for this parameter, then the automation assumes the maintenance window service role you choose in step 11. As such, you must ensure that the maintenance window service role you choose has the appropriate AWS Identity and Access Management (IAM) permissions to perform the actions defined within the runbook.   
For example, the service-linked role for Systems Manager doesn't have the IAM permission `ec2:CreateSnapshot`, which is required to use the runbook `AWS-CopySnapshot`. In this scenario, you must either use a custom maintenance window service role or specify an Automation assume role that has `ec2:CreateSnapshot` permissions. For information, see [Setting up Automation](automation-setup.md).

1. In the ** IAM service role** area, choose a role to provide permissions for Systems Manager to start the automation.

   To create a service role for maintenance window tasks, see [Setting up Maintenance Windows](setting-up-maintenance-windows.md).

1. Choose **Register Automation task**.

## Registering an Automation task to a maintenance window (command line)
<a name="register-automation-task-maintenance-window-cli"></a>

The following procedure describes how to use the AWS CLI (on Linux or Windows Server) or AWS Tools for PowerShell to configure an automation as a registered task for a maintenance window.

**Before you begin**  
Before you complete the following procedure, you must create a maintenance window and register at least one target. For more information, see the following procedures:
+ [Step 1: Create the maintenance window using the AWS CLI](mw-cli-tutorial-create-mw.md).
+ [Step 2: Register a target node with the maintenance window using the AWS CLI](mw-cli-tutorial-targets.md)

**To configure an automation as a registered task for a maintenance window**

1. Install and configure the AWS CLI or the AWS Tools for PowerShell, if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

1. Create a command to configure an automation as a registered task for a maintenance window. Replace each *example resource placeholder* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm register-task-with-maintenance-window \
   --window-id window ID \
   --name task name \
   --task-arn runbook name \
   --targets Key=targets,Values=value \
   --service-role-arn IAM role arn \
   --task-type AUTOMATION \
   --task-invocation-parameters task parameters \
   --priority task priority \
   --max-concurrency 10% \
   --max-errors 5
   ```

**Note**  
If you configure an automation as a registered task by using the AWS CLI, use the `--Task-Invocation-Parameters` parameter to specify parameters to pass to a task when it runs. Don't use the `--Task-Parameters` parameter. The `--Task-Parameters` parameter is a legacy parameter.  
For maintenance window tasks without a target specified, you can't supply values for `--max-errors` and `--max-concurrency`. Instead, the system inserts a placeholder value of `1`, which might be reported in the response to commands such as [https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-maintenance-window-tasks.html](https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-maintenance-window-tasks.html) and [https://docs.aws.amazon.com/cli/latest/reference/ssm/get-maintenance-window-task.html](https://docs.aws.amazon.com/cli/latest/reference/ssm/get-maintenance-window-task.html). These values don't affect the running of your task and can be ignored.  
For information about maintenance window tasks that don't require targets, see [Registering maintenance window tasks without targets](maintenance-windows-targetless-tasks.md).

------
#### [ Windows ]

   ```
   aws ssm register-task-with-maintenance-window ^
   --window-id window ID ^
   --name task name ^
   --task-arn runbook name ^
   --targets Key=targets,Values=value ^
   --service-role-arn IAM role arn ^
   --task-type AUTOMATION ^
   --task-invocation-parameters task parameters ^
   --priority task priority ^
   --max-concurrency 10% ^
   --max-errors 5
   ```

**Note**  
If you configure an automation as a registered task by using the AWS CLI, use the `--task-invocation-parameters` parameter to specify parameters to pass to a task when it runs. Don't use the `--task-parameters` parameter. The `--task-parameters` parameter is a legacy parameter.  
For maintenance window tasks without a target specified, you can't supply values for `--max-errors` and `--max-concurrency`. Instead, the system inserts a placeholder value of `1`, which might be reported in the response to commands such as [https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-maintenance-window-tasks.html](https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-maintenance-window-tasks.html) and [https://docs.aws.amazon.com/cli/latest/reference/ssm/get-maintenance-window-task.html](https://docs.aws.amazon.com/cli/latest/reference/ssm/get-maintenance-window-task.html). These values don't affect the running of your task and can be ignored.  
For information about maintenance window tasks that don't require targets, see [Registering maintenance window tasks without targets](maintenance-windows-targetless-tasks.md).

------
#### [ PowerShell ]

   ```
   Register-SSMTaskWithMaintenanceWindow `
   -WindowId window ID `
   -Name "task name" `
   -TaskArn "runbook name" `
   -Target @{ Key="targets";Values="value" } `
   -ServiceRoleArn "IAM role arn" `
   -TaskType "AUTOMATION" `
   -Automation_Parameter @{ "task parameter"="task parameter value"} `
   -Priority task priority `
   -MaxConcurrency 10% `
   -MaxError 5
   ```

**Note**  
If you configure an automation as a registered task by using the AWS Tools for PowerShell, use the `-Automation_Parameter` parameter to specify parameters to pass to a task when the task runs. Don't use the `-TaskParameters` parameter. The `-TaskParameters` parameter is a legacy parameter.  
For maintenance window tasks without a target specified, you can't supply values for `-MaxError` and `-MaxConcurrency`. Instead, the system inserts a placeholder value of 1, which might be reported in the response to commands such as `Get-SSMMaintenanceWindowTaskList` and `Get-SSMMaintenanceWindowTask`. These values don't affect the running of your task and can be ignored.  
For information about maintenance window tasks that don't require targets, see [Registering maintenance window tasks without targets](maintenance-windows-targetless-tasks.md).

------

   The following example configures an automation as a registered task to a maintenance window with priority 1. It also demonstrates omitting the `--targets`, `--max-errors`, and `--max-concurrency` options for a targetless maintenance window task. The automation uses the `AWS-StartEC2Instance` runbook and the specified Automation assume role to start EC2 instances registered as targets to the maintenance window. The maintenance window runs the automation simultaneously on 5 instances maximum at any given time. Also, the registered task stops running on more instances for a particular interval if the error count exceeds 1.

------
#### [ Linux & macOS ]

   ```
   aws ssm register-task-with-maintenance-window \
   --window-id mw-0c50858d01EXAMPLE \
   --name StartEC2Instances \
   --task-arn AWS-StartEC2Instance \
   --service-role-arn arn:aws:iam::123456789012:role/MaintenanceWindowRole \
   --task-type AUTOMATION \
   --task-invocation-parameters "{\"Automation\":{\"Parameters\":{\"InstanceId\":[\"{{TARGET_ID}}\"],\"AutomationAssumeRole\":[\"arn:aws:iam::123456789012:role/AutomationAssumeRole\"]}}}" \
   --priority 1
   ```

------
#### [ Windows ]

   ```
   aws ssm register-task-with-maintenance-window ^
   --window-id mw-0c50858d01EXAMPLE ^
   --name StartEC2Instances ^
   --task-arn AWS-StartEC2Instance ^
   --service-role-arn arn:aws:iam::123456789012:role/MaintenanceWindowRole ^
   --task-type AUTOMATION ^
   --task-invocation-parameters "{\"Automation\":{\"Parameters\":{\"InstanceId\":[\"{{TARGET_ID}}\"],\"AutomationAssumeRole\":[\"arn:aws:iam::123456789012:role/AutomationAssumeRole\"]}}}" ^
   --priority 1
   ```

------
#### [ PowerShell ]

   ```
   Register-SSMTaskWithMaintenanceWindow `
   -WindowId mw-0c50858d01EXAMPLE `
   -Name "StartEC2" `
   -TaskArn "AWS-StartEC2Instance" `
   -ServiceRoleArn "arn:aws:iam::123456789012:role/MaintenanceWindowRole" `
   -TaskType "AUTOMATION" `
   -Automation_Parameter @{ "InstanceId"="{{TARGET_ID}}";"AutomationAssumeRole"="arn:aws:iam::123456789012:role/AutomationAssumeRole" } `
   -Priority 1
   ```

------

   The command returns details for the new registered task similar to the following.

------
#### [ Linux & macOS ]

   ```
   {
   "WindowTaskId": "4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE"
   }
   ```

------
#### [ Windows ]

   ```
   {
   "WindowTaskId": "4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE"
   }
   ```

------
#### [ PowerShell ]

   ```
   4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE
   ```

------

1. To view the registered task, run the following command. Replace *maintenance windows ID* with your own information.

------
#### [ Linux & macOS ]

   ```
   aws ssm describe-maintenance-window-tasks \
   --window-id maintenance window ID
   ```

------
#### [ Windows ]

   ```
   aws ssm describe-maintenance-window-tasks ^
   --window-id maintenance window ID
   ```

------
#### [ PowerShell ]

   ```
   Get-SSMMaintenanceWindowTaskList `
   -WindowId maintenance window ID
   ```

------

   The system returns information like the following.

------
#### [ Linux & macOS ]

   ```
   {
   "Tasks": [
       {
           "ServiceRoleArn": "arn:aws:iam::123456789012:role/MaintenanceWindowRole",
           "MaxErrors": "1",
           "TaskArn": "AWS-StartEC2Instance",
           "MaxConcurrency": "1",
           "WindowTaskId": "4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE",
           "TaskParameters": {},
           "Priority": 1,
           "WindowId": "mw-0c50858d01EXAMPLE",
           "Type": "AUTOMATION",
           "Targets": [
           ],
           "Name": "StartEC2"
       }
   ]
   }
   ```

------
#### [ Windows ]

   ```
   {
   "Tasks": [
       {
           "ServiceRoleArn": "arn:aws:iam::123456789012:role/MaintenanceWindowRole",
           "MaxErrors": "1",
           "TaskArn": "AWS-StartEC2Instance",
           "MaxConcurrency": "1",
           "WindowTaskId": "4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE",
           "TaskParameters": {},
           "Priority": 1,
           "WindowId": "mw-0c50858d01EXAMPLE",
           "Type": "AUTOMATION",
           "Targets": [
           ],
           "Name": "StartEC2"
       }
   ]
   }
   ```

------
#### [ PowerShell ]

   ```
   Description    : 
   LoggingInfo    : 
   MaxConcurrency : 5
   MaxErrors      : 1
   Name           : StartEC2
   Priority       : 1
   ServiceRoleArn : arn:aws:iam::123456789012:role/MaintenanceWindowRole
   Targets        : {}
   TaskArn        : AWS-StartEC2Instance
   TaskParameters : {}
   Type           : AUTOMATION
   WindowId       : mw-0c50858d01EXAMPLE
   WindowTaskId   : 4f7ca192-7e9a-40fe-9192-5cb15EXAMPLE
   ```

------

# Systems Manager Automation actions reference
<a name="automation-actions"></a>

This reference describes the Automation actions that you can specify in an Automation runbook. Automation is a tool in AWS Systems Manager. These actions can't be used in other types of Systems Manager (SSM) documents. For information about plugins for other types of SSM documents, see [Command document plugin reference](documents-command-ssm-plugin-reference.md).

Systems Manager Automation runs steps defined in Automation runbooks. Each step is associated with a particular action. The action determines the inputs, behavior, and outputs of the step. Steps are defined in the `mainSteps` section of your runbook.

You don't need to specify the outputs of an action or step. The outputs are predetermined by the action associated with the step. When you specify step inputs in your runbooks, you can reference one or more outputs from an earlier step. For example, you can make the output of `aws:runInstances` available for a subsequent `aws:runCommand` action. You can also reference outputs from earlier steps in the `Output` section of the runbook. 

**Important**  
If you run an automation workflow that invokes other services by using an AWS Identity and Access Management (IAM) service role, be aware that the service role must be configured with permission to invoke those services. This requirement applies to all AWS Automation runbooks (`AWS-*` runbooks) such as the `AWS-ConfigureS3BucketLogging`, `AWS-CreateDynamoDBBackup`, and `AWS-RestartEC2Instance` runbooks, to name a few. This requirement also applies to any custom Automation runbooks you create that invoke other AWS services by using actions that call other services. For example, if you use the `aws:executeAwsApi`, `aws:createStack`, or `aws:copyImage` actions, configure the service role with permission to invoke those services. You can give permissions to other AWS services by adding an IAM inline policy to the role. For more information, see [(Optional) Add an Automation inline policy or customer managed policy to invoke other AWS services](automation-setup-iam.md#add-inline-policy).

**Topics**
+ [Properties shared by all actions](#automation-common)
+ [`aws:approve` – Pause an automation for manual approval](automation-action-approve.md)
+ [`aws:assertAwsResourceProperty` – Assert an AWS resource state or event state](automation-action-assertAwsResourceProperty.md)
+ [`aws:branch` – Run conditional automation steps](automation-action-branch.md)
+ [`aws:changeInstanceState` – Change or assert instance state](automation-action-changestate.md)
+ [`aws:copyImage` – Copy or encrypt an Amazon Machine Image](automation-action-copyimage.md)
+ [`aws:createImage` – Create an Amazon Machine Image](automation-action-create.md)
+ [`aws:createStack` – Create an CloudFormation stack](automation-action-createstack.md)
+ [`aws:createTags` – Create tags for AWS resources](automation-action-createtag.md)
+ [`aws:deleteImage` – Delete an Amazon Machine Image](automation-action-delete.md)
+ [`aws:deleteStack` – Delete an CloudFormation stack](automation-action-deletestack.md)
+ [`aws:executeAutomation` – Run another automation](automation-action-executeAutomation.md)
+ [`aws:executeAwsApi` – Call and run AWS API operations](automation-action-executeAwsApi.md)
+ [`aws:executeScript` – Run a script](automation-action-executeScript.md)
+ [`aws:executeStateMachine` – Run an AWS Step Functions state machine](automation-action-executeStateMachine.md)
+ [`aws:invokeWebhook` – Invoke an Automation webhook integration](invoke-webhook.md)
+ [`aws:invokeLambdaFunction` – Invoke an AWS Lambda function](automation-action-lamb.md)
+ [`aws:loop` – Iterate over steps in an automation](automation-action-loop.md)
+ [`aws:pause` – Pause an automation](automation-action-pause.md)
+ [`aws:runCommand` – Run a command on a managed instance](automation-action-runcommand.md)
+ [`aws:runInstances` – Launch an Amazon EC2 instance](automation-action-runinstance.md)
+ [`aws:sleep` – Delay an automation](automation-action-sleep.md)
+ [`aws:updateVariable` – Updates a value for a runbook variable](automation-action-update-variable.md)
+ [`aws:waitForAwsResourceProperty` – Wait on an AWS resource property](automation-action-waitForAwsResourceProperty.md)
+ [Automation system variables](automation-variables.md)

## Properties shared by all actions
<a name="automation-common"></a>

Common properties are parameters or options that are found in all actions. Some options define behavior for a step, such as how long to wait for a step to complete and what to do if the step fails. The following properties are common to all actions.

[description](#descriptProp)  
Information you provide to describe the purpose of a runbook or a step.  
Type: String  
Required: No

[name](#nameProp)  
An identifier that must be unique across all step names in the runbook.  
Type: String  
Allowed pattern: [a-zA-Z0-9\$1]\$1\$1  
Required: Yes

[action](#actProp)  
The name of the action the step is to run. [`aws:runCommand` – Run a command on a managed instance](automation-action-runcommand.md) is an example of an action you can specify here. This document provides detailed information about all available actions.  
Type: String  
Required: Yes

[maxAttempts](#maxProp)  
The number of times the step should be retried in case of failure. If the value is greater than 1, the step isn't considered to have failed until all retry attempts have failed. The default value is 1.  
Type: Integer  
Required: No

[timeoutSeconds](#timeProp)  
The timeout value for the step. If the timeout is reached and the value of `maxAttempts` is greater than 1, then the step isn't considered to have timed out until all retries have been attempted.  
Type: Integer  
Required: No

[onFailure](#failProp)  
Indicates whether the automation should stop, continue, or go to a different step on failure. The default value for this option is abort.  
Type: String  
Valid values: Abort \$1 Continue \$1 step:*step\$1name*  
Required: No

[onCancel](#canProp)  
Indicates which step the automation should go to in the event that a user cancels the automation. Automation runs the cancellation workflow for a maximum of two minutes.  
Type: String  
Valid values: Abort \$1 step:*step\$1name*  
Required: No  
The `onCancel` property doesn't support moving to the following actions:  
+ `aws:approve`
+ `aws:copyImage`
+ `aws:createImage`
+ `aws:createStack`
+ `aws:createTags`
+ `aws:loop`
+ `aws:pause`
+ `aws:runInstances`
+ `aws:sleep`

[isEnd](#endProp)  
This option stops an automation at the end of a specific step. The automation stops if the step failed or succeeded. The default value is false.  
Type: Boolean  
Valid values: true \$1 false  
Required: No

[nextStep](#nextProp)  
Specifies which step in an automation to process next after successfully completing a step.  
Type: String  
Required: No

[isCritical](#critProp)  
Designates a step as critical for the successful completion of the Automation. If a step with this designation fails, then Automation reports the final status of the Automation as Failed. This property is only evaluated if you explicitly define it in your step. If the `onFailure` property is set to `Continue` in a step, the value defaults to false. Otherwise, the default value for this option is true.  
Type: Boolean  
Valid values: true \$1 false  
Required: No

[inputs](#inProp)  
The properties specific to the action.  
Type: Map  
Required: Yes

### Example
<a name="automation-demo"></a>

```
---
description: "Custom Automation Example"
schemaVersion: '0.3'
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
  AutomationAssumeRole:
    type: String
    description: "(Required) The ARN of the role that allows Automation to perform
      the actions on your behalf. If no role is specified, Systems Manager Automation
      uses your IAM permissions to run this runbook."
    default: ''
  InstanceId:
      type: String
      description: "(Required) The Instance Id whose root EBS volume you want to restore the latest Snapshot."
      default: ''
mainSteps:
- name: getInstanceDetails
  action: aws:executeAwsApi
  onFailure: Abort
  inputs:
    Service: ec2
    Api: DescribeInstances
    InstanceIds:
    - "{{ InstanceId }}"
  outputs:
    - Name: availabilityZone
      Selector: "$.Reservations[0].Instances[0].Placement.AvailabilityZone"
      Type: String
    - Name: rootDeviceName
      Selector: "$.Reservations[0].Instances[0].RootDeviceName"
      Type: String
  nextStep: getRootVolumeId
- name: getRootVolumeId
  action: aws:executeAwsApi
  maxAttempts: 3
  onFailure: Abort
  inputs:
    Service: ec2
    Api: DescribeVolumes
    Filters:
    -  Name: attachment.device
       Values: ["{{ getInstanceDetails.rootDeviceName }}"]
    -  Name: attachment.instance-id
       Values: ["{{ InstanceId }}"]
  outputs:
    - Name: rootVolumeId
      Selector: "$.Volumes[0].VolumeId"
      Type: String
  nextStep: getSnapshotsByStartTime
- name: getSnapshotsByStartTime
  action: aws:executeScript
  timeoutSeconds: 45
  onFailure: Abort
  inputs:
    Runtime: python3.8
    Handler: getSnapshotsByStartTime
    InputPayload:
      rootVolumeId : "{{ getRootVolumeId.rootVolumeId }}"
    Script: |-
      def getSnapshotsByStartTime(events,context):
        import boto3

        #Initialize client
        ec2 = boto3.client('ec2')
        rootVolumeId = events['rootVolumeId']
        snapshotsQuery = ec2.describe_snapshots(
          Filters=[
            {
              "Name": "volume-id",
              "Values": [rootVolumeId]
            }
          ]
        )
        if not snapshotsQuery['Snapshots']:
          noSnapshotFoundString = "NoSnapshotFound"
          return { 'noSnapshotFound' : noSnapshotFoundString }
        else:
          jsonSnapshots = snapshotsQuery['Snapshots']
          sortedSnapshots = sorted(jsonSnapshots, key=lambda k: k['StartTime'], reverse=True)
          latestSortedSnapshotId = sortedSnapshots[0]['SnapshotId']
          return { 'latestSnapshotId' : latestSortedSnapshotId }
  outputs:
  - Name: Payload
    Selector: $.Payload
    Type: StringMap
  - Name: latestSnapshotId
    Selector: $.Payload.latestSnapshotId
    Type: String
  - Name: noSnapshotFound
    Selector: $.Payload.noSnapshotFound
    Type: String 
  nextStep: branchFromResults
- name: branchFromResults
  action: aws:branch
  onFailure: Abort
  onCancel: step:startInstance
  inputs:
    Choices:
    - NextStep: createNewRootVolumeFromSnapshot
      Not:
        Variable: "{{ getSnapshotsByStartTime.noSnapshotFound }}"
        StringEquals: "NoSnapshotFound"
  isEnd: true
- name: createNewRootVolumeFromSnapshot
  action: aws:executeAwsApi
  onFailure: Abort
  inputs:
    Service: ec2
    Api: CreateVolume
    AvailabilityZone: "{{ getInstanceDetails.availabilityZone }}"
    SnapshotId: "{{ getSnapshotsByStartTime.latestSnapshotId }}"
  outputs:
    - Name: newRootVolumeId
      Selector: "$.VolumeId"
      Type: String
  nextStep: stopInstance
- name: stopInstance
  action: aws:executeAwsApi
  onFailure: Abort
  inputs:
    Service: ec2
    Api: StopInstances
    InstanceIds:
    - "{{ InstanceId }}"
  nextStep: verifyVolumeAvailability
- name: verifyVolumeAvailability
  action: aws:waitForAwsResourceProperty
  timeoutSeconds: 120
  inputs:
    Service: ec2
    Api: DescribeVolumes
    VolumeIds:
    - "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
    PropertySelector: "$.Volumes[0].State"
    DesiredValues:
    - "available"
  nextStep: verifyInstanceStopped
- name: verifyInstanceStopped
  action: aws:waitForAwsResourceProperty
  timeoutSeconds: 120
  inputs:
    Service: ec2
    Api: DescribeInstances
    InstanceIds:
    - "{{ InstanceId }}"
    PropertySelector: "$.Reservations[0].Instances[0].State.Name"
    DesiredValues:
    - "stopped"
  nextStep: detachRootVolume
- name: detachRootVolume
  action: aws:executeAwsApi
  onFailure: Abort
  isCritical: true
  inputs:
    Service: ec2
    Api: DetachVolume
    VolumeId: "{{ getRootVolumeId.rootVolumeId }}"
  nextStep: verifyRootVolumeDetached
- name: verifyRootVolumeDetached
  action: aws:waitForAwsResourceProperty
  timeoutSeconds: 30
  inputs:
    Service: ec2
    Api: DescribeVolumes
    VolumeIds:
    - "{{ getRootVolumeId.rootVolumeId }}"
    PropertySelector: "$.Volumes[0].State"
    DesiredValues:
    - "available"
  nextStep: attachNewRootVolume
- name: attachNewRootVolume
  action: aws:executeAwsApi
  onFailure: Abort
  inputs:
    Service: ec2
    Api: AttachVolume
    Device: "{{ getInstanceDetails.rootDeviceName }}"
    InstanceId: "{{ InstanceId }}"
    VolumeId: "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
  nextStep: verifyNewRootVolumeAttached
- name: verifyNewRootVolumeAttached
  action: aws:waitForAwsResourceProperty
  timeoutSeconds: 30
  inputs:
    Service: ec2
    Api: DescribeVolumes
    VolumeIds:
    - "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
    PropertySelector: "$.Volumes[0].Attachments[0].State"
    DesiredValues:
    - "attached"
  nextStep: startInstance
- name: startInstance
  action: aws:executeAwsApi
  onFailure: Abort
  inputs:
    Service: ec2
    Api: StartInstances
    InstanceIds:
    - "{{ InstanceId }}"
```

# `aws:approve` – Pause an automation for manual approval
<a name="automation-action-approve"></a>

Temporarily pauses an automation until designated principals either approve or reject the action. After the required number of approvals is reached, the automation resumes. You can insert the approval step any place in the `mainSteps` section of your runbook. 

**Note**  
This action doesn't support multi-account and Region automations. The default timeout for this action is 7 days (604800 seconds) and the maximum value is 30 days (2592000 seconds). You can limit or extend the timeout by specifying the `timeoutSeconds` parameter for an `aws:approve` step.

In the following example, the `aws:approve` action temporarily pauses the automation until one approver either accepts or rejects the automation. Upon approval, the automation runs a simple PowerShell command. 

------
#### [ YAML ]

```
---
description: RunInstancesDemo1
schemaVersion: '0.3'
assumeRole: "{{ assumeRole }}"
parameters:
  assumeRole:
    type: String
  message:
    type: String
mainSteps:
- name: approve
  action: aws:approve
  timeoutSeconds: 1000
  onFailure: Abort
  inputs:
    NotificationArn: arn:aws:sns:us-east-2:12345678901:AutomationApproval
    Message: "{{ message }}"
    MinRequiredApprovals: 1
    Approvers:
    - arn:aws:iam::12345678901:user/AWS-User-1
- name: run
  action: aws:runCommand
  inputs:
    InstanceIds:
    - i-1a2b3c4d5e6f7g
    DocumentName: AWS-RunPowerShellScript
    Parameters:
      commands:
      - date
```

------
#### [ JSON ]

```
{
   "description":"RunInstancesDemo1",
   "schemaVersion":"0.3",
   "assumeRole":"{{ assumeRole }}",
   "parameters":{
      "assumeRole":{
         "type":"String"
      },
      "message":{
         "type":"String"
      }
   },
   "mainSteps":[
      {
         "name":"approve",
         "action":"aws:approve",
         "timeoutSeconds":1000,
         "onFailure":"Abort",
         "inputs":{
            "NotificationArn":"arn:aws:sns:us-east-2:12345678901:AutomationApproval",
            "Message":"{{ message }}",
            "MinRequiredApprovals":1,
            "Approvers":[
               "arn:aws:iam::12345678901:user/AWS-User-1"
            ]
         }
      },
      {
         "name":"run",
         "action":"aws:runCommand",
         "inputs":{
            "InstanceIds":[
               "i-1a2b3c4d5e6f7g"
            ],
            "DocumentName":"AWS-RunPowerShellScript",
            "Parameters":{
               "commands":[
                  "date"
               ]
            }
         }
      }
   ]
}
```

------

You can approve or deny Automations that are waiting for approval in the console.

**To approve or deny waiting Automations**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the option next to an Automation with a status of **Waiting**.  
![\[Accessing the Approve/Deny Automation page\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/automation-approve-action-aws.png)

1. Choose **Approve/Deny**.

1. Review the details of the Automation.

1. Choose either **Approve** or **Deny**, type an optional comment, and then choose **Submit**.

**Input example**

------
#### [ YAML ]

```
NotificationArn: arn:aws:sns:us-west-1:12345678901:Automation-ApprovalRequest
Message: Please approve this step of the Automation.
MinRequiredApprovals: 3
Approvers:
- IamUser1
- IamUser2
- arn:aws:iam::12345678901:user/IamUser3
- arn:aws:iam::12345678901:role/IamRole
```

------
#### [ JSON ]

```
{
   "NotificationArn":"arn:aws:sns:us-west-1:12345678901:Automation-ApprovalRequest",
   "Message":"Please approve this step of the Automation.",
   "MinRequiredApprovals":3,
   "Approvers":[
      "IamUser1",
      "IamUser2",
      "arn:aws:iam::12345678901:user/IamUser3",
      "arn:aws:iam::12345678901:role/IamRole"
   ]
}
```

------

NotificationArn  
The Amazon Resource Name (ARN of an Amazon Simple Notification Service (Amazon SNS) topic for Automation approvals. When you specify an `aws:approve` step in a runbook, Automation sends a message to this topic letting principals know that they must either approve or reject an Automation step. The title of the Amazon SNS topic must be prefixed with "Automation".  
Type: String  
Required: No

Message  
The information you want to include in the Amazon SNS topic when the approval request is sent. The maximum message length is 4096 characters.   
Type: String  
Required: No

MinRequiredApprovals  
The minimum number of approvals required to resume the automation. If you don't specify a value, the system defaults to one. The value for this parameter must be a positive number. The value for this parameter can't exceed the number of approvers defined by the `Approvers` parameter.   
Type: Integer  
Required: No

Approvers  
A list of AWS authenticated principals who are able to either approve or reject the action. The maximum number of approvers is 10. You can specify principals by using any of the following formats:  
+ A user name
+ A user ARN
+ An IAM role ARN
+ An IAM assume role ARN
Type: StringList  
Required: Yes

EnhancedApprovals  
This input is only used for Change Manager templates. A list of AWS authenticated principals who are able to either approve or reject the action, the type of IAM principal, and the minimum number of approvers. The following is an example:  

```
schemaVersion: "0.3"
emergencyChange: false
autoApprovable: false
mainSteps:
    - name: ApproveAction1
    action: aws:approve
    timeoutSeconds: 604800
    inputs:
        Message: Please approve this change request
        MinRequiredApprovals: 3
        EnhancedApprovals:
        Approvers:
            - approver: John Stiles
            type: IamUser
            minRequiredApprovals: 0
            - approver: Ana Carolina Silva
            type: IamUser
            minRequiredApprovals: 0
            - approver: GroupOfThree
            type: IamGroup
            minRequiredApprovals: 0
            - approver: RoleOfTen
            type: IamRole
            minRequiredApprovals: 0
```
Type: StringList  
Required: Yes

**Output**

ApprovalStatus  
The approval status of the step. The status can be one of the following: Approved, Rejected, or Waiting. Waiting means that Automation is waiting for input from approvers.  
Type: String

ApproverDecisions  
A JSON map that includes the approval decision of each approver.  
Type: MapList

# `aws:assertAwsResourceProperty` – Assert an AWS resource state or event state
<a name="automation-action-assertAwsResourceProperty"></a>

The `aws:assertAwsResourceProperty` action allows you to assert a specific resource state or event state for a specific Automation step.

**Note**  
The `aws:assertAwsResourceProperty` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

For more examples of how to use this action, see [Additional runbook examples](automation-document-examples.md).

**Input**  
Inputs are defined by the API operation that you choose. 

------
#### [ YAML ]

```
action: aws:assertAwsResourceProperty
inputs:
  Service: The official namespace of the service
  Api: The API operation or method name
  API operation inputs or parameters: A value
  PropertySelector: Response object
  DesiredValues:
  - Desired property values
```

------
#### [ JSON ]

```
{
  "action": "aws:assertAwsResourceProperty",
  "inputs": {
    "Service":"The official namespace of the service",
    "Api":"The API operation or method name",
    "API operation inputs or parameters":"A value",
    "PropertySelector": "Response object",
    "DesiredValues": [
      "Desired property values"
    ]
  }
}
```

------

Service  
The AWS service namespace that contains the API operation that you want to run. For example, the namespace for Systems Manager is `ssm`. The namespace for Amazon EC2 is `ec2`. You can view a list of supported AWS service namespaces in the [Available Services](https://docs.aws.amazon.com/cli/latest/reference/#available-services) section of the *AWS CLI Command Reference*.  
Type: String  
Required: Yes

Api  
The name of the API operation that you want to run. You can view the API operations (also called methods) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all API operations (methods) for Amazon Relational Database Service (Amazon RDS) are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html).  
Type: String  
Required: Yes

API operation inputs  
One or more API operation inputs. You can view the available inputs (also called parameters) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all methods for Amazon RDS are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html). Choose the [describe\$1db\$1instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances) method and scroll down to see the available parameters, such as **DBInstanceIdentifier**, **Name**, and **Values**. Use the following format to specify more than one input.  

```
inputs:
  Service: The official namespace of the service
  Api: The API operation name
  API input 1: A value
  API Input 2: A value
  API Input 3: A value
```

```
"inputs":{
      "Service":"The official namespace of the service",
      "Api":"The API operation name",
      "API input 1":"A value",
      "API Input 2":"A value",
      "API Input 3":"A value"
}
```
Type: Determined by chosen API operation  
Required: Yes

PropertySelector  
The JSONPath to a specific attribute in the response object. You can view the response objects by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all methods for Amazon RDS are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html). Choose the [describe\$1db\$1instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances) method and scroll down to the **Response Structure** section. **DBInstances** is listed as a response object.  
Type: String  
Required: Yes

DesiredValues  
The expected status or state on which to continue the automation. If you specify a Boolean value, you must use a capital letter such as True or False.  
Type: StringList  
Required: Yes

# `aws:branch` – Run conditional automation steps
<a name="automation-action-branch"></a>

The `aws:branch` action allows you to create a dynamic automation that evaluates different choices in a single step and then jumps to a different step in the runbook based on the results of that evaluation. 

When you specify the `aws:branch` action for a step, you specify `Choices` that the automation must evaluate. The `Choices` can be based on either a value that you specified in the `Parameters` section of the runbook, or a dynamic value generated as the output from the previous step. The automation evaluates each choice by using a Boolean expression. If the first choice is true, then the automation jumps to the step designated for that choice. If the first choice is false, the automation evaluates the next choice. The automation continues evaluating each choice until it process a true choice. The automation then jumps to the designated step for the true choice.

If none of the choices are true, the automation checks to see if the step contains a `default` value. A default value defines a step that the automation should jump to if none of the choices are true. If no `default` value is specified for the step, then the automation processes the next step in the runbook.

The `aws:branch` action supports complex choice evaluations by using a combination of `And`, `Not`, and `Or` operators. For more information about how to use `aws:branch`, including example runbooks and examples that use different operators, see [Using conditional statements in runbooks](automation-branch-condition.md).

**Input**  
Specify one or more `Choices` in a step. The `Choices` can be based on either a value that you specified in the `Parameters` section of the runbook, or a dynamic value generated as the output from the previous step. Here is a YAML sample that evaluates a parameter.

```
mainSteps:
- name: chooseOS
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runWindowsCommand
      Variable: "{{Name of a parameter defined in the Parameters section. For example: OS_name}}"
      StringEquals: windows
    - NextStep: runLinuxCommand
      Variable: "{{Name of a parameter defined in the Parameters section. For example: OS_name}}"
      StringEquals: linux
    Default:
      sleep3
```

Here is a YAML sample that evaluates output from a previous step.

```
mainSteps:
- name: chooseOS
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runPowerShellCommand
      Variable: "{{Name of a response object. For example: GetInstance.platform}}"
      StringEquals: Windows
    - NextStep: runShellCommand
      Variable: "{{Name of a response object. For example: GetInstance.platform}}"
      StringEquals: Linux
    Default:
      sleep3
```

Choices  
One or more expressions that the Automation should evaluate when determining the next step to process. Choices are evaluated by using a Boolean expression. Each choice must define the following options:  
+ **NextStep**: The next step in the runbook to process if the designated choice is true.
+ **Variable**: Specify either the name of a parameter that is defined in the `Parameters` section of the runbook. Or specify an output object from a previous step in the runbook. For more information about creating variables for `aws:branch`, see [About creating the output variable](automation-branch-condition.md#branch-action-output).
+ **Operation**: The criteria used to evaluate the choice. The `aws:branch` action supports the following operations:

**String operations**
  + StringEquals
  + EqualsIgnoreCase
  + StartsWith
  + EndsWith
  + Contains

**Numeric operations**
  + NumericEquals
  + NumericGreater
  + NumericLesser
  + NumericGreaterOrEquals
  + NumericLesser
  + NumericLesserOrEquals

**Boolean operation**
  + BooleanEquals
**Important**  
When you create a runbook, the system validates each operation in the runbook. If an operation isn't supported, the system returns an error when you try to create the runbook.

Default  
The name of a step the automation should jump to if none of the `Choices` are true.  
Type: String  
Required: No

**Note**  
The `aws:branch` action supports `And`, `Or`, and `Not` operators. For examples of `aws:branch` that use operators, see [Using conditional statements in runbooks](automation-branch-condition.md).

# `aws:changeInstanceState` – Change or assert instance state
<a name="automation-action-changestate"></a>

Changes or asserts the state of the instance.

This action can be used in assert mode (doesn't run the API to change the state but verifies the instance is in the desired state.) To use assert mode, set the `CheckStateOnly` parameter to true. This mode is useful when running the Sysprep command on Windows Server, which is an asynchronous command that can run in the background for a long time. You can ensure that the instance is stopped before you create an Amazon Machine Image (AMI).

**Note**  
The default timeout value for this action is 3600 seconds (one hour). You can limit or extend the timeout by specifying the `timeoutSeconds` parameter for an `aws:changeInstanceState` step.

**Note**  
The `aws:changeInstanceState` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**

------
#### [ YAML ]

```
name: stopMyInstance
action: aws:changeInstanceState
maxAttempts: 3
timeoutSeconds: 3600
onFailure: Abort
inputs:
  InstanceIds:
  - i-1234567890abcdef0
  CheckStateOnly: true
  DesiredState: stopped
```

------
#### [ JSON ]

```
{
    "name":"stopMyInstance",
    "action": "aws:changeInstanceState",
    "maxAttempts": 3,
    "timeoutSeconds": 3600,
    "onFailure": "Abort",
    "inputs": {
        "InstanceIds": ["i-1234567890abcdef0"],
        "CheckStateOnly": true,
        "DesiredState": "stopped"
    }
}
```

------

InstanceIds  
The IDs of the instances.  
Type: StringList  
Required: Yes

CheckStateOnly  
If false, sets the instance state to the desired state. If true, asserts the desired state using polling.  
Default: `false`  
Type: Boolean  
Required: No

DesiredState  
The desired state. When set to `running`, this action waits for the Amazon EC2 state to be `Running`, the Instance Status to be `OK`, and the System Status to be `OK` before completing.  
Type: String  
Valid values: `running` \$1 `stopped` \$1 `terminated`  
Required: Yes

Force  
If set, forces the instances to stop. The instances don't have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option isn't recommended for EC2 instances for Windows Server.  
Type: Boolean  
Required: No

AdditionalInfo  
Reserved.  
Type: String  
Required: No

**Output**  
None

# `aws:copyImage` – Copy or encrypt an Amazon Machine Image
<a name="automation-action-copyimage"></a>

Copies an Amazon Machine Image (AMI) from any AWS Region into the current Region. This action can also encrypt the new AMI.

**Note**  
The `aws:copyImage` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
This action supports most `CopyImage` parameters. For more information, see [CopyImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CopyImage.html).

The following example creates a copy of an AMI in the Seoul region (`SourceImageID`: ami-0fe10819. `SourceRegion`: ap-northeast-2). The new AMI is copied to the region where you initiated the Automation action. The copied AMI will be encrypted because the optional `Encrypted` flag is set to `true`.

------
#### [ YAML ]

```
name: createEncryptedCopy
action: aws:copyImage
maxAttempts: 3
onFailure: Abort
inputs:
  SourceImageId: ami-0fe10819
  SourceRegion: ap-northeast-2
  ImageName: Encrypted Copy of LAMP base AMI in ap-northeast-2
  Encrypted: true
```

------
#### [ JSON ]

```
{   
    "name": "createEncryptedCopy",
    "action": "aws:copyImage",
    "maxAttempts": 3,
    "onFailure": "Abort",
    "inputs": {
        "SourceImageId": "ami-0fe10819",
        "SourceRegion": "ap-northeast-2",
        "ImageName": "Encrypted Copy of LAMP base AMI in ap-northeast-2",
        "Encrypted": true
    }   
}
```

------

SourceRegion  
The region where the source AMI exists.  
Type: String  
Required: Yes

SourceImageId  
The AMI ID to copy from the source Region.  
Type: String  
Required: Yes

ImageName  
The name for the new image.  
Type: String  
Required: Yes

ImageDescription  
A description for the target image.  
Type: String  
Required: No

Encrypted  
Encrypt the target AMI.  
Type: Boolean  
Required: No

KmsKeyId  
The full Amazon Resource Name (ARN) of the AWS KMS key to use when encrypting the snapshots of an image during a copy operation. For more information, see [CopyImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/api_copyimage.html).  
Type: String  
Required: No

ClientToken  
A unique, case-sensitive identifier that you provide to ensure request idempotency. For more information, see [CopyImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/api_copyimage.html).  
Type: String  
Required: NoOutput

ImageId  
The ID of the copied image.

ImageState  
The state of the copied image.  
Valid values: `available` \$1 `pending` \$1 `failed`

# `aws:createImage` – Create an Amazon Machine Image
<a name="automation-action-create"></a>

Creates an Amazon Machine Image (AMI) from an instance that is either running, stopping, or stopped, and polls for the `ImageState` to be `available`.

**Note**  
The `aws:createImage` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
This action supports the following `CreateImage` parameters. For more information, see [CreateImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateImage.html).

------
#### [ YAML ]

```
name: createMyImage
action: aws:createImage
maxAttempts: 3
onFailure: Abort
inputs:
  InstanceId: i-1234567890abcdef0
  ImageName: AMI Created on{{global:DATE_TIME}}
  NoReboot: true
  ImageDescription: My newly created AMI
```

------
#### [ JSON ]

```
{
    "name": "createMyImage",
    "action": "aws:createImage",
    "maxAttempts": 3,
    "onFailure": "Abort",
    "inputs": {
        "InstanceId": "i-1234567890abcdef0",
        "ImageName": "AMI Created on{{global:DATE_TIME}}",
        "NoReboot": true,
        "ImageDescription": "My newly created AMI"
    }
}
```

------

InstanceId  
The ID of the instance.  
Type: String  
Required: Yes

ImageName  
The name for the image.  
Type: String  
Required: Yes

ImageDescription  
A description of the image.  
Type: String  
Required: No

NoReboot  
A Boolean literal.  
By default, Amazon Elastic Compute Cloud (Amazon EC2) attempts to shut down and reboot the instance before creating the image. If the **No Reboot** option is set to `true`, Amazon EC2 doesn't shut down the instance before creating the image. When this option is used, file system integrity on the created image can't be guaranteed.   
If you don't want the instance to run after you create an AMI from it, first use the [`aws:changeInstanceState` – Change or assert instance state](automation-action-changestate.md) action to stop the instance, and then use this `aws:createImage` action with the **NoReboot** option set to `true`.  
Type: Boolean  
Required: No

BlockDeviceMappings  
The block devices for the instance.  
Type: Map  
Required: NoOutput

ImageId  
The ID of the newly created image.  
Type: String

ImageState  
The current state of the image. If the state is available, the image is successfully registered and can be used to launch an instance.  
Type: String

# `aws:createStack` – Create an CloudFormation stack
<a name="automation-action-createstack"></a>

Creates an AWS CloudFormation stack from a template.

**Note**  
The `aws:createStack` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

For supplemental information about creating CloudFormation stacks, see [CreateStack](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html) in the *AWS CloudFormation API Reference*. 

**Input**

------
#### [ YAML ]

```
name: makeStack
action: aws:createStack
maxAttempts: 1
onFailure: Abort
inputs:
  Capabilities:
  - CAPABILITY_IAM
  StackName: myStack
  TemplateURL: http://s3.amazonaws.com/amzn-s3-demo-bucket/myStackTemplate
  TimeoutInMinutes: 5
  Parameters:
    - ParameterKey: LambdaRoleArn
      ParameterValue: "{{LambdaAssumeRole}}"
    - ParameterKey: createdResource
      ParameterValue: createdResource-{{automation:EXECUTION_ID}}
```

------
#### [ JSON ]

```
{
    "name": "makeStack",
    "action": "aws:createStack",
    "maxAttempts": 1,
    "onFailure": "Abort",
    "inputs": {
        "Capabilities": [
            "CAPABILITY_IAM"
        ],
        "StackName": "myStack",
        "TemplateURL": "http://s3.amazonaws.com/amzn-s3-demo-bucket/myStackTemplate",
        "TimeoutInMinutes": 5,
        "Parameters": [
          {
            "ParameterKey": "LambdaRoleArn",
            "ParameterValue": "{{LambdaAssumeRole}}"
          },
          {
            "ParameterKey": "createdResource",
            "ParameterValue": "createdResource-{{automation:EXECUTION_ID}}"
          }
    }
}
```

------

Capabilities  
A list of values that you specify before CloudFormation can create certain stacks. Some stack templates include resources that can affect permissions in your AWS account. For those stacks, you must explicitly acknowledge their capabilities by specifying this parameter.   
Valid values include `CAPABILITY_IAM`, `CAPABILITY_NAMED_IAM`, and `CAPABILITY_AUTO_EXPAND`.   
**CAPABILITY\$1IAM and CAPABILITY\$1NAMED\$1IAM**  
If you have IAM resources, you can specify either capability. If you have IAM resources with custom names, you must specify `CAPABILITY_NAMED_IAM`. If you don't specify this parameter, this action returns an `InsufficientCapabilities` error. The following resources require you to specify either `CAPABILITY_IAM` or `CAPABILITY_NAMED_IAM`.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-accesskey.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-accesskey.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-group.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-group.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-instanceprofile.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-instanceprofile.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-user.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-user.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-addusertogroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-addusertogroup.html)
If your stack template contains these resources, we recommend that you review all permissions associated with them and edit their permissions, if necessary.   
For more information, see [Acknowledging IAM Resources in CloudFormation Templates](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html#capabilities).   
**CAPABILITY\$1AUTO\$1EXPAND**  
Some template contain macros. Macros perform custom processing on templates; this can include simple actions like find-and-replace operations, all the way to extensive transformations of entire templates. Because of this, users typically create a change set from the processed template, so that they can review the changes resulting from the macros before actually creating the stack. If your stack template contains one or more macros, and you choose to create a stack directly from the processed template, without first reviewing the resulting changes in a change set, you must acknowledge this capability. 
For more information, see [Using AWS CloudFormation Macros to Perform Custom Processing on Templates](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-macros.html) in the *AWS CloudFormation User Guide*.  
Type: array of Strings  
Valid Values: `CAPABILITY_IAM | CAPABILITY_NAMED_IAM | CAPABILITY_AUTO_EXPAND`  
Required: No

ClientRequestToken  
A unique identifier for this CreateStack request. Specify this token if you set maxAttempts in this step to a value greater than 1. By specifying this token, CloudFormation knows that you aren't attempting to create a new stack with the same name.  
Type: String  
Required: No  
Length Constraints: Minimum length of 1. Maximum length of 128.  
Pattern: [a-zA-Z0-9][-a-zA-Z0-9]\$1

DisableRollback  
Set to `true` to turn off rollback of the stack if stack creation failed.  
Conditional: You can specify either the `DisableRollback` parameter or the `OnFailure` parameter, but not both.   
Default: `false`  
Type: Boolean  
Required: No

NotificationARNs  
The Amazon Simple Notification Service (Amazon SNS) topic ARNs for publishing stack-related events. You can find SNS topic ARNs using the Amazon SNS console, [https://console.aws.amazon.com/sns/v3/home](https://console.aws.amazon.com/sns/v3/home).   
Type: array of Strings  
Array Members: Maximum number of 5 items.  
Required: No

OnFailure  
Determines the action to take if stack creation failed. You must specify `DO_NOTHING`, `ROLLBACK`, or `DELETE`.  
Conditional: You can specify either the `OnFailure` parameter or the `DisableRollback` parameter, but not both.   
Default: `ROLLBACK`  
Type: String  
Valid Values:` DO_NOTHING | ROLLBACK | DELETE`  
Required: No

Parameters  
A list of `Parameter` structures that specify input parameters for the stack. For more information, see the [Parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_Parameter.html) data type.   
Type: array of [Parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_Parameter.html) objects   
Required: No

ResourceTypes  
The template resource types that you have permissions to work with for this create stack action. For example: `AWS::EC2::Instance`, `AWS::EC2::*`, or `Custom::MyCustomInstance`. Use the following syntax to describe template resource types.  
+ For all AWS resources:

  ```
  AWS::*
  ```
+ For all custom resources:

  ```
  Custom::*
  ```
+ For a specific custom resource:

  ```
  Custom::logical_ID
  ```
+ For all resources of a particular AWS service:

  ```
  AWS::service_name::*
  ```
+ For a specific AWS resource:

  ```
  AWS::service_name::resource_logical_ID
  ```
If the list of resource types doesn't include a resource that you're creating, the stack creation fails. By default, CloudFormation grants permissions to all resource types. IAM uses this parameter for CloudFormation-specific condition keys in IAM policies. For more information, see [Controlling Access with AWS Identity and Access Management](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html).   
Type: array of Strings  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: No

RoleARN  
The Amazon Resource Name (ARN) of an IAM role that CloudFormation assumes to create the stack. CloudFormation uses the role's credentials to make calls on your behalf. CloudFormation always uses this role for all future operations on the stack. As long as users have permission to operate on the stack, CloudFormation uses this role even if the users don't have permission to pass it. Ensure that the role grants the least amount of privileges.   
If you don't specify a value, CloudFormation uses the role that was previously associated with the stack. If no role is available, CloudFormation uses a temporary session that is generated from your user credentials.   
Type: String  
Length Constraints: Minimum length of 20. Maximum length of 2048.  
Required: No

StackName  
The name that is associated with the stack. The name must be unique in the Region in which you're creating the stack.  
A stack name can contain only alphanumeric characters (case sensitive) and hyphens. It must start with an alphabetic character and can't be longer than 128 characters. 
Type: String  
Required: Yes

StackPolicyBody  
Structure containing the stack policy body. For more information, see [Prevent Updates to Stack Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html).  
Conditional: You can specify either the `StackPolicyBody` parameter or the `StackPolicyURL` parameter, but not both.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 16384.  
Required: No

StackPolicyURL  
Location of a file containing the stack policy. The URL must point to a policy located in an S3 bucket in the same region as the stack. The maximum file size allowed for the stack policy is 16 KB.  
Conditional: You can specify either the `StackPolicyBody` parameter or the `StackPolicyURL` parameter, but not both.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1350.  
Required: No

Tags  
Key-value pairs to associate with this stack. CloudFormation also propagates these tags to the resources created in the stack. You can specify a maximum number of 10 tags.   
Type: array of [Tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_Tag.html) objects   
Required: No

TemplateBody  
Structure containing the template body with a minimum length of 1 byte and a maximum length of 51,200 bytes. For more information, see [Template Anatomy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html).   
Conditional: You can specify either the `TemplateBody` parameter or the `TemplateURL` parameter, but not both.   
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

TemplateURL  
Location of a file containing the template body. The URL must point to a template that is located in an S3 bucket. The maximum size allowed for the template is 460,800 bytes. For more information, see [Template Anatomy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html).   
Conditional: You can specify either the `TemplateBody` parameter or the `TemplateURL` parameter, but not both.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1024.  
Required: No

TimeoutInMinutes  
The amount of time that can pass before the stack status becomes `CREATE_FAILED`. If `DisableRollback` isn't set or is set to `false`, the stack will be rolled back.   
Type: Integer  
Valid Range: Minimum value of 1.  
Required: No

## Outputs
<a name="automation-action-createstack-output"></a>

StackId  
Unique identifier of the stack.  
Type: String

StackStatus  
Current status of the stack.  
Type: String  
Valid Values: `CREATE_IN_PROGRESS | CREATE_FAILED | CREATE_COMPLETE | ROLLBACK_IN_PROGRESS | ROLLBACK_FAILED | ROLLBACK_COMPLETE | DELETE_IN_PROGRESS | DELETE_FAILED | DELETE_COMPLETE | UPDATE_IN_PROGRESS | UPDATE_COMPLETE_CLEANUP_IN_PROGRESS | UPDATE_COMPLETE | UPDATE_ROLLBACK_IN_PROGRESS | UPDATE_ROLLBACK_FAILED | UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS | UPDATE_ROLLBACK_COMPLETE | REVIEW_IN_PROGRESS`  
Required: Yes

StackStatusReason  
Success or failure message associated with the stack status.  
Type: String  
Required: No  
For more information, see [CreateStack](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html).

## Security considerations
<a name="automation-action-createstack-security"></a>

Before you can use the `aws:createStack` action, you must assign the following policy to the IAM Automation assume role. For more information about the assume role, see [Task 1: Create a service role for Automation](automation-setup-iam.md#create-service-role). 

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "sqs:*",
            "cloudformation:CreateStack",
            "cloudformation:DescribeStacks"
         ],
         "Resource":"*"
      }
   ]
}
```

------

# `aws:createTags` – Create tags for AWS resources
<a name="automation-action-createtag"></a>

Creates new tags for Amazon Elastic Compute Cloud (Amazon EC2) instances or AWS Systems Manager managed instances.

**Note**  
The `aws:createTags` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
This action supports most Amazon EC2 `CreateTags` and Systems Manager `AddTagsToResource` parameters. For more information, see [CreateTags](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/api_createtags.html) and [AddTagsToResource](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/api_addtagstoresource.html).

The following example shows how to tag an Amazon Machine Image (AMI) and an instance as production resources for a particular department.

------
#### [ YAML ]

```
name: createTags
action: aws:createTags
maxAttempts: 3
onFailure: Abort
inputs:
  ResourceType: EC2
  ResourceIds:
  - ami-9a3768fa
  - i-02951acd5111a8169
  Tags:
  - Key: production
    Value: ''
  - Key: department
    Value: devops
```

------
#### [ JSON ]

```
{
    "name": "createTags",
    "action": "aws:createTags",
    "maxAttempts": 3,
    "onFailure": "Abort",
    "inputs": {
        "ResourceType": "EC2",
        "ResourceIds": [
            "ami-9a3768fa",
            "i-02951acd5111a8169"
        ],
        "Tags": [
            {
                "Key": "production",
                "Value": ""
            },
            {
                "Key": "department",
                "Value": "devops"
            }
        ]
    }
}
```

------

ResourceIds  
The IDs of the resource(s) to be tagged. If resource type isn't “EC2”, this field can contain only a single item.  
Type: String List  
Required: Yes

Tags  
The tags to associate with the resource(s).  
Type: List of Maps  
Required: Yes

ResourceType  
The type of resource(s) to be tagged. If not supplied, the default value of “EC2” is used.  
Type: String  
Required: No  
Valid Values: `EC2` \$1 `ManagedInstance` \$1 `MaintenanceWindow` \$1 `Parameter`

**Output**  
None

# `aws:deleteImage` – Delete an Amazon Machine Image
<a name="automation-action-delete"></a>

Deletes the specified Amazon Machine Image (AMI) and all related snapshots.

**Note**  
The `aws:deleteImage` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
This action supports only one parameter. For more information, see the documentation for [DeregisterImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeregisterImage.html) and [DeleteSnapshot](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteSnapshot.html).

------
#### [ YAML ]

```
name: deleteMyImage
action: aws:deleteImage
maxAttempts: 3
timeoutSeconds: 180
onFailure: Abort
inputs:
  ImageId: ami-12345678
```

------
#### [ JSON ]

```
{
    "name": "deleteMyImage",
    "action": "aws:deleteImage",
    "maxAttempts": 3,
    "timeoutSeconds": 180,
    "onFailure": "Abort",
    "inputs": {
        "ImageId": "ami-12345678"
    }
}
```

------

ImageId  
The ID of the image to be deleted.  
Type: String  
Required: Yes

**Output**  
None

# `aws:deleteStack` – Delete an CloudFormation stack
<a name="automation-action-deletestack"></a>

Deletes an AWS CloudFormation stack.

**Note**  
The `aws:deleteStack` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**

------
#### [ YAML ]

```
name: deleteStack
action: aws:deleteStack
maxAttempts: 1
onFailure: Abort
inputs:
  StackName: "{{stackName}}"
```

------
#### [ JSON ]

```
{
   "name":"deleteStack",
   "action":"aws:deleteStack",
   "maxAttempts":1,
   "onFailure":"Abort",
   "inputs":{
      "StackName":"{{stackName}}"
   }
}
```

------

ClientRequestToken  
A unique identifier for this `DeleteStack` request. Specify this token if you plan to retry requests so that CloudFormation knows that you aren't attempting to delete a stack with the same name. You can retry `DeleteStack` requests to verify that CloudFormation received them.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 128.  
Pattern: [a-zA-Z][-a-zA-Z0-9]\$1  
Required: No

RetainResources.member.N  
This input applies only to stacks that are in a `DELETE_FAILED` state. A list of logical resource IDs for the resources you want to retain. During deletion, CloudFormation deletes the stack, but doesn't delete the retained resources.  
Retaining resources is useful when you can't delete a resource, such as a non-empty S3 bucket, but you want to delete the stack.  
Type: array of strings  
Required: No

RoleARN  
The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) role that CloudFormation assumes to create the stack. CloudFormation uses the role's credentials to make calls on your behalf. CloudFormation always uses this role for all future operations on the stack. As long as users have permission to operate on the stack, CloudFormation uses this role even if the users don't have permission to pass it. Ensure that the role grants the least amount of privileges.   
If you don't specify a value, CloudFormation uses the role that was previously associated with the stack. If no role is available, CloudFormation uses a temporary session that is generated from your user credentials.   
Type: String  
Length Constraints: Minimum length of 20. Maximum length of 2048.  
Required: No

StackName  
The name or the unique stack ID that is associated with the stack.  
Type: String  
Required: Yes

## Security considerations
<a name="automation-action-deletestack-security"></a>

Before you can use the `aws:deleteStack` action, you must assign the following policy to the IAM Automation assume role. For more information about the assume role, see [Task 1: Create a service role for Automation](automation-setup-iam.md#create-service-role). 

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "sqs:*",
            "cloudformation:DeleteStack",
            "cloudformation:DescribeStacks"
         ],
         "Resource":"*"
      }
   ]
}
```

------

# `aws:executeAutomation` – Run another automation
<a name="automation-action-executeAutomation"></a>

Runs a secondary automation by calling a secondary runbook. With this action, you can create runbooks for your most common operations, and reference those runbooks during an automation. This action can simplify your runbooks by removing the need to duplicate steps across similar runbooks.

The secondary automation runs in the context of the user who initiated the primary automation. This means that the secondary automation uses the same AWS Identity and Access Management (IAM) role or user as the user who started the first automation.

**Important**  
If you specify parameters in a secondary automation that use an assume role (a role that uses the iam:passRole policy), then the user or role that initiated the primary automation must have permission to pass the assume role specified in the secondary automation. For more information about setting up an assume role for Automation, see [Create the service roles for Automation using the console](automation-setup-iam.md).

**Input**

------
#### [ YAML ]

```
name: Secondary_Automation
action: aws:executeAutomation
maxAttempts: 3
timeoutSeconds: 3600
onFailure: Abort
inputs:
  DocumentName: secondaryAutomation
  RuntimeParameters:
    instanceIds:
    - i-1234567890abcdef0
```

------
#### [ JSON ]

```
{
   "name":"Secondary_Automation",
   "action":"aws:executeAutomation",
   "maxAttempts":3,
   "timeoutSeconds":3600,
   "onFailure":"Abort",
   "inputs":{
      "DocumentName":"secondaryAutomation",
      "RuntimeParameters":{
         "instanceIds":[
            "i-1234567890abcdef0"
         ]
      }
   }
}
```

------

DocumentName  
The name of the secondary runbook to run during the step. For runbooks in the same AWS account, specify the runbook name. For runbooks shared from a different AWS account, specify the Amazon Resource Name (ARN) of the runbook. For information about using shared runbooks, see [Using shared SSM documents](documents-ssm-sharing.md#using-shared-documents).  
Type: String  
Required: Yes

DocumentVersion  
The version of the secondary runbook to run. If not specified, Automation runs the default runbook version.  
Type: String  
Required: No

MaxConcurrency  
The maximum number of targets allowed to run this task in parallel. You can specify a number, such as 10, or a percentage, such as 10%.  
Type: String  
Required: No

MaxErrors  
The number of errors that are allowed before the system stops running the automation on additional targets. You can specify either an absolute number of errors, for example 10, or a percentage of the target set, for example 10%. If you specify 3, for example, the system stops running the automation when the fourth error is received. If you specify 0, then the system stops running the automation on additional targets after the first error result is returned. If you run an automation on 50 resources and set `MaxErrors` to 10%, then the system stops running the automation on additional targets when the sixth error is received.  
Automations that are already running when the `MaxErrors` threshold is reached are allowed to complete, but some of these automations may fail as well. If you need to ensure that there won't be more failed automations than the specified `MaxErrors`, set `MaxConcurrency` to 1 so the automations proceed one at a time.  
Type: String  
Required: No

RuntimeParameters  
Required parameters for the secondary runbook. The mapping uses the following format: \$1"parameter1" : "value1", "parameter2" : "value2" \$1  
Type: Map  
Required: No

Tags  
Optional metadata that you assign to a resource. You can specify a maximum of five tags for an automation.  
Type: MapList  
Required: No

TargetLocations  
A location is a combination of AWS Regions and/or AWS accounts where you want to run the automation. A minimum number of 1 item must be specified and a maximum number of 100 items can be specified. When specifying a value for this parameter, outputs aren't returned to the parent automation. If needed, you must make subsequent calls to API operations to retrieve the output from child automations.  
Type: MapList  
Required: No

TargetMaps  
A list of key-value mappings of document parameters to target resources. Both `Targets` and `TargetMaps` can't be specified together.   
Type: MapList  
Required: No

TargetParameterName  
The name of the parameter used as the target resource for the rate-controlled automation. Required if you specify `Targets`.  
Type: String  
Required: No

Targets  
A list of key-value mappings to target resources. Required if you specify `TargetParameterName`.  
Type: MapList  
Required: NoOutput

Output  
The output generated by the secondary automation. You can reference the output by using the following format: *Secondary\$1Automation\$1Step\$1Name*.Output  
Type: StringList  
Here is an example:  

```
- name: launchNewWindowsInstance
  action: 'aws:executeAutomation'
  onFailure: Abort
  inputs:
    DocumentName: launchWindowsInstance
  nextStep: getNewInstanceRootVolume
- name: getNewInstanceRootVolume
  action: 'aws:executeAwsApi'
  onFailure: Abort
  inputs:
    Service: ec2
    Api: DescribeVolumes
    Filters:
    - Name: attachment.device
      Values:
      - /dev/sda1
    - Name: attachment.instance-id
      Values:
      - '{{launchNewWindowsInstance.Output}}'
  outputs:
  - Name: rootVolumeId
    Selector: '$.Volumes[0].VolumeId'
    Type: String
  nextStep: snapshotRootVolume
- name: snapshotRootVolume
  action: 'aws:executeAutomation'
  onFailure: Abort
  inputs:
    DocumentName: AWS-CreateSnapshot
    RuntimeParameters:
    VolumeId:
    - '{{getNewInstanceRootVolume.rootVolumeId}}'
    Description:
    - 'Initial root snapshot for {{launchNewWindowsInstance.Output}}'
```

ExecutionId  
The ID of the secondary automation.  
Type: String

Status  
The status of the secondary automation.  
Type: String

# `aws:executeAwsApi` – Call and run AWS API operations
<a name="automation-action-executeAwsApi"></a>

Calls and runs AWS API operations. Most API operations are supported, although not all API operations have been tested. Streaming API operations, such as the [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html) operation, aren't supported. If you're not sure if an API operation you want to use is a streaming operation, review the [Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) documentation for the service to determine if an API requires streaming inputs or outputs. We regularly update the Boto3 version used by this action. However, following the release of a new Boto3 version it can take up to a few weeks for changes to be reflected in this action. Each `aws:executeAwsApi` action can run up to a maximum duration of 25 seconds. For more examples of how to use this action, see [Additional runbook examples](automation-document-examples.md).

**Note**  
The `aws:executeAwsApi` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Inputs**  
Inputs are defined by the API operation that you choose. 

------
#### [ YAML ]

```
action: aws:executeAwsApi
inputs:
  Service: The official namespace of the service
  Api: The API operation or method name
  API operation inputs or parameters: A value
outputs: # These are user-specified outputs
- Name: The name for a user-specified output key
  Selector: A response object specified by using jsonpath format
  Type: The data type
```

------
#### [ JSON ]

```
{
   "action":"aws:executeAwsApi",
   "inputs":{
      "Service":"The official namespace of the service",
      "Api":"The API operation or method name",
      "API operation inputs or parameters":"A value"
   },
   "outputs":[ These are user-specified outputs
      {
         "Name":"The name for a user-specified output key",
         "Selector":"A response object specified by using JSONPath format",
         "Type":"The data type"
      }
   ]
}
```

------

Service  
The AWS service namespace that contains the API operation that you want to run. You can view a list of supported AWS service namespaces in [Available services](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) of the AWS SDK for Python (Boto3). The namespace can be found in the **Client** section. For example, the namespace for Systems Manager is `ssm`. The namespace for Amazon Elastic Compute Cloud (Amazon EC2) is `ec2`.  
Type: String  
Required: Yes

Api  
The name of the API operation that you want to run. You can view the API operations (also called methods) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all API operations (methods) for Amazon Relational Database Service (Amazon RDS) are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html).  
Type: String  
Required: Yes

API operation inputs  
One or more API operation inputs. You can view the available inputs (also called parameters) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all methods for Amazon RDS are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html). Choose the [describe\$1db\$1instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances) method and scroll down to see the available parameters, such as **DBInstanceIdentifier**, **Name**, and **Values**.  

```
inputs:
  Service: The official namespace of the service
  Api: The API operation name
  API input 1: A value
  API Input 2: A value
  API Input 3: A value
```

```
"inputs":{
      "Service":"The official namespace of the service",
      "Api":"The API operation name",
      "API input 1":"A value",
      "API Input 2":"A value",
      "API Input 3":"A value"
}
```
Type: Determined by chosen API operation  
Required: Yes

**Outputs**  
Outputs are specified by the user based on the response from the chosen API operation.

Name  
A name for the output.  
Type: String  
Required: Yes

Selector  
The JSONPath to a specific attribute in the response object. You can view the response objects by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all methods for Amazon RDS are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html). Choose the [describe\$1db\$1instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances) method and scroll down to the **Response Structure** section. **DBInstances** is listed as a response object.  
Type: Integer, Boolean, String, StringList, StringMap, or MapList  
Required: Yes

Type  
The data type for the response element.  
Type: Varies  
Required: Yes

# `aws:executeScript` – Run a script
<a name="automation-action-executeScript"></a>

Runs the Python or PowerShell script provided using the specified runtime and handler. Each `aws:executeScript` action can run up to a maximum duration of 600 seconds (10 minutes). You can limit the timeout by specifying the `timeoutSeconds` parameter for an `aws:executeScript` step.

Use return statements in your function to add outputs to your output payload. For examples of defining outputs for your `aws:executeScript` action, see [Example 2: Scripted runbook](automation-authoring-runbooks-scripted-example.md). You can also send the output from `aws:executeScript` actions in your runbooks to the Amazon CloudWatch Logs log group you specify. For more information, see [Logging Automation action output with CloudWatch Logs](automation-action-logging.md).

If you want to send output from `aws:executeScript` actions to CloudWatch Logs, or if the scripts you specify for `aws:executeScript` actions call AWS API operations, an AWS Identity and Access Management (IAM) service role (or assume role) is always required to run the runbook.

**Note**  
The `aws:executeScript` action does not support automatic throttling retry. If your script makes AWS API calls that might be throttled, you must implement your own retry logic in your script code.

The `aws:executeScript` action contains the following preinstalled PowerShell Core modules:
+ Microsoft.PowerShell.Host
+ Microsoft.PowerShell.Management
+ Microsoft.PowerShell.Security
+ Microsoft.PowerShell.Utility
+ PackageManagement
+ PowerShellGet

To use PowerShell Core modules that aren't preinstalled, your script must install the module with the `-Force` flag, as shown in the following command. The `AWSPowerShell.NetCore` module isn't supported. Replace *ModuleName* with the module you want to install.

```
Install-Module ModuleName -Force
```

To use PowerShell Core cmdlets in your script, we recommend using the `AWS.Tools` modules, as shown in the following commands. Replace each *example resource placeholder* with your own information.
+ Amazon S3 cmdlets.

  ```
  Install-Module AWS.Tools.S3 -Force
  Get-S3Bucket -BucketName amzn-s3-demo-bucket
  ```
+ Amazon EC2 cmdlets.

  ```
  Install-Module AWS.Tools.EC2 -Force
  Get-EC2InstanceStatus -InstanceId instance-id
  ```
+ Common, or service independent AWS Tools for Windows PowerShell cmdlets.

  ```
  Install-Module AWS.Tools.Common -Force
  Get-AWSRegion
  ```

If your script initializes new objects in addition to using PowerShell Core cmdlets, you must also import the module as shown in the following command.

```
Install-Module AWS.Tools.EC2 -Force
Import-Module AWS.Tools.EC2

$tag = New-Object Amazon.EC2.Model.Tag
$tag.Key = "Tag"
$tag.Value = "TagValue"

New-EC2Tag -Resource i-02573cafcfEXAMPLE -Tag $tag
```

For examples of installing and importing `AWS.Tools` modules, and using PowerShell Core cmdlets in runbooks, see [Visual design experience for Automation runbooks](automation-visual-designer.md).

**Input**  
Provide the information required to run your script. Replace each *example resource placeholder* with your own information.

**Note**  
The attachment for a Python script can be a .py file or a .zip file that contains the script. PowerShell scripts must be stored in .zip files.

------
#### [ YAML ]

```
action: "aws:executeScript"
inputs: 
 Runtime: runtime
 Handler: "functionName"
 InputPayload: 
  scriptInput: '{{parameterValue}}'
 Script: |-
   def functionName(events, context):
   ...
 Attachment: "scriptAttachment.zip"
```

------
#### [ JSON ]

```
{
    "action": "aws:executeScript",
    "inputs": {
        "Runtime": "runtime",
        "Handler": "functionName",
        "InputPayload": {
            "scriptInput": "{{parameterValue}}"
        },
        "Attachment": "scriptAttachment.zip"
    }
}
```

------

Runtime  
The runtime language to be used for running the provided script. `aws:executeScript` supports the runtimes in the following table.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/automation-action-executeScript.html)
Type: String  
Required: Yes  
For python runtimes, the environment provides 512MB of memory and 512MB of disk space. For PowerShell runtimes, the environment provides 1024MB of memory and 512MB of disk space.

Handler  
The name of your function. You must ensure the function defined in the handler has two parameters, `events` and `context`. The PowerShell runtime does not support this parameter.  
Type: String  
Required: Yes (Python) \$1 Not supported (PowerShell)

InputPayload  
A JSON or YAML object that will be passed to the first parameter of the handler. This can be used to pass input data to the script.  
Type: String  
Required: No  

```
description: Tag an instance
schemaVersion: '0.3'
assumeRole: '{{AutomationAssumeRole}}'
parameters:
    AutomationAssumeRole:
        type: String
        description: '(Required) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.'
    InstanceId:
        type: String
        description: (Required) The ID of the EC2 instance you want to tag.
mainSteps:
  - name: tagInstance
    action: 'aws:executeScript'
    inputs:
        Runtime: "python3.11"
        Handler: tagInstance
        InputPayload:
            instanceId: '{{InstanceId}}'
        Script: |-
          def tagInstance(events,context):
            import boto3

            #Initialize client
            ec2 = boto3.client('ec2')
            instanceId = events['instanceId']
            tag = {
                "Key": "Env",
                "Value": "ExamplePython"
            }
            print(f"Adding tag {tag} to instance id {instanceId}")
            ec2.create_tags(
                Resources=[instanceId],
                Tags=[tag]
            )
            return tag
    outputs:
      - Type: String
        Name: TagKey
        Selector: $.Payload.Key
outputs:
  - tagInstance.TagKey
```

```
description: Tag an instance
schemaVersion: '0.3'
assumeRole: '{{AutomationAssumeRole}}'
parameters:
  AutomationAssumeRole:
    type: String
    description: (Required) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.
  InstanceId:
    type: String
    description: (Required) The ID of the EC2 instance you want to tag.
mainSteps:
  - name: tagInstance
    action: aws:executeScript
    isEnd: true
    inputs:
      Runtime: PowerShell 7.4
      InputPayload:
        instanceId: '{{InstanceId}}'
      Script: |-
        Install-Module AWS.Tools.EC2 -Force
        Import-Module AWS.Tools.EC2

        $input = $env:InputPayload | ConvertFrom-Json

        $tag = New-Object Amazon.EC2.Model.Tag
        $tag.Key = "Env"
        $tag.Value = "ExamplePowerShell"

        Write-Information "Adding tag key: $($tag.Key) and value: $($tag.Value) to instance id $($input.instanceId)"
        New-EC2Tag -Resource $input.instanceId -Tag $tag

        return $tag
    outputs:
      - Type: String
        Name: TagKey
        Selector: $.Payload.Key
outputs:
  - tagInstance.TagKey
```

Script  
An embedded script that you want to run during the automation.  
Type: String  
Required: No (Python) \$1 Yes (PowerShell)

Attachment  
The name of a standalone script file or .zip file that can be invoked by the action. Specify the same value as the `Name` of the document attachment file you specify in the `Attachments` request parameter. For more information, see [Attachments](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_CreateDocument.html#systemsmanager-CreateDocument-request-Attachments) in the *AWS Systems Manager API Reference*. If you're providing a script using an attachment, you must also define a `files` section in the top-level elements of your runbook. For more information, see [Schema version 0.3](documents-schemas-features.md#automation-doc-syntax-examples).  
To invoke a file for Python, use the `filename.method_name` format in `Handler`.   
The attachment for a Python script can be a .py file or a .zip file that contains the script. PowerShell scripts must be stored in .zip files.
When including Python libraries in your attachment, we recommend adding an empty `__init__.py` file in each module directory. This allows you to import the modules from the library in your attachment within your script content. For example: `from library import module`  
Type: String  
Required: NoOutput

Payload  
The JSON representation of the object returned by your function. Up to 100KB is returned. If you output a list, a maximum of 100 items is returned.

## Using attachments with aws:executeScript
<a name="automation-action-executeScript-attachments"></a>

Attachments provide a powerful way to package and reuse complex scripts, multiple modules, and external dependencies with your `aws:executeScript` actions. Use attachments when you need to:
+ Package multiple Python modules or PowerShell scripts together.
+ Reuse the same script logic across multiple runbooks.
+ Include external libraries or dependencies with your scripts.
+ Keep your runbook definition clean by separating complex script logic.
+ Share script packages across teams or automation workflows.

### Attachment structure and packaging
<a name="automation-action-executeScript-attachment-structure"></a>

You can attach either single files or zip packages containing multiple files. The structure depends on your use case:

**Single file attachments**  
For simple scripts, you can attach a single `.py` file (Python) or a `.zip` file containing a single PowerShell script.

**Multi-module packages**  
For complex automation that requires multiple modules, create a zip package with the following recommended structure:

```
my-automation-package.zip
├── main.py                    # Entry point script
├── utils/
│   ├── __init__.py           # Required for Python module imports
│   ├── helper_functions.py   # Utility functions
│   └── aws_operations.py     # AWS-specific operations
├── config/
│   ├── __init__.py
│   └── settings.py           # Configuration settings
└── requirements.txt          # Optional: document dependencies
```

**Important**  
For Python packages, you must include an empty `__init__.py` file in each directory that contains Python modules. This allows you to import modules using standard Python import syntax like `from utils import helper_functions`.

**PowerShell package structure**  
PowerShell attachments must be packaged in zip files with the following structure:

```
my-powershell-package.zip
├── Main.ps1                  # Entry point script
├── Modules/
│   ├── HelperFunctions.ps1   # Utility functions
│   └── AWSOperations.ps1     # AWS-specific operations
└── Config/
    └── Settings.ps1          # Configuration settings
```

### Creating runbooks with attachments
<a name="automation-action-executeScript-attachment-workflow"></a>

Follow these steps to create runbooks that use attachments:

1. **Upload your attachment to Amazon S3**

   Upload your script file or zip package to an S3 bucket that your automation role can access. Note the S3 URI for use in the next step.

   ```
   aws s3 cp my-automation-package.zip s3://my-automation-bucket/scripts/
   ```

1. **Calculate the attachment checksum**

   Calculate the SHA-256 checksum of your attachment file for security verification:

   ```
   # Linux/macOS
   shasum -a 256 my-automation-package.zip
   
   # Windows PowerShell
   Get-FileHash -Algorithm SHA256 my-automation-package.zip
   ```

1. **Define the files section in your runbook**

   Add a `files` section at the top level of your runbook to reference your attachment:

   ```
   files:
     my-automation-package.zip:
       checksums:
         sha256: "your-calculated-checksum-here"
   ```

1. **Reference the attachment in your executeScript step**

   Use the `Attachment` parameter to reference your uploaded file:

   ```
   - name: runMyScript
     action: aws:executeScript
     inputs:
       Runtime: python3.11
       Handler: main.process_data
       Attachment: my-automation-package.zip
       InputPayload:
         inputData: "{{InputParameter}}"
   ```

## aws:executeScript attachment examples
<a name="automation-action-executeScript-examples"></a>

The following examples demonstrate different ways to use attachments with the `aws:executeScript` action.

### Example 1: Single file attachment
<a name="automation-action-executeScript-single-file-example"></a>

This example shows how to use a single Python file as an attachment to process EC2 instance data.

**Attachment file: process\$1instance.py**  
Create a Python file with the following content:

```
import boto3
import json

def process_instance_data(events, context):
    """Process EC2 instance data and return formatted results."""
    try:
        instance_id = events.get('instanceId')
        if not instance_id:
            raise ValueError("instanceId is required")
        
        ec2 = boto3.client('ec2')
        
        # Get instance details
        response = ec2.describe_instances(InstanceIds=[instance_id])
        instance = response['Reservations'][0]['Instances'][0]
        
        # Format the response
        result = {
            'instanceId': instance_id,
            'instanceType': instance['InstanceType'],
            'state': instance['State']['Name'],
            'availabilityZone': instance['Placement']['AvailabilityZone'],
            'tags': {tag['Key']: tag['Value'] for tag in instance.get('Tags', [])}
        }
        
        print(f"Successfully processed instance {instance_id}")
        return result
        
    except Exception as e:
        print(f"Error processing instance: {str(e)}")
        raise
```

**Complete runbook**  
Here's the complete runbook that uses the single file attachment:

```
description: Process EC2 instance data using single file attachment
schemaVersion: '0.3'
assumeRole: '{{AutomationAssumeRole}}'
parameters:
  AutomationAssumeRole:
    type: String
    description: (Required) IAM role for automation execution
  InstanceId:
    type: String
    description: (Required) EC2 instance ID to process

files:
  process_instance.py:
    checksums:
      sha256: "abc123def456..."

mainSteps:
  - name: processInstance
    action: aws:executeScript
    inputs:
      Runtime: python3.11
      Handler: process_instance.process_instance_data
      Attachment: process_instance.py
      InputPayload:
        instanceId: '{{InstanceId}}'
    outputs:
      - Type: StringMap
        Name: InstanceData
        Selector: $.Payload

outputs:
  - processInstance.InstanceData
```

### Example 2: Multi-module package
<a name="automation-action-executeScript-multi-module-example"></a>

This example demonstrates using a zip package containing multiple Python modules for complex S3 bucket operations.

**Package structure**  
Create a zip package with the following structure:

```
s3-operations.zip
├── main.py
├── utils/
│   ├── __init__.py
│   ├── s3_helper.py
│   └── validation.py
└── config/
    ├── __init__.py
    └── settings.py
```

**main.py (entry point)**  
The main script that orchestrates the operations:

```
from utils.s3_helper import S3Operations
from utils.validation import validate_bucket_name
from config.settings import get_default_settings

def cleanup_s3_bucket(events, context):
    """Clean up S3 bucket based on specified criteria."""
    try:
        bucket_name = events.get('bucketName')
        max_age_days = events.get('maxAgeDays', 30)
        
        # Validate inputs
        if not validate_bucket_name(bucket_name):
            raise ValueError(f"Invalid bucket name: {bucket_name}")
        
        # Initialize S3 operations
        s3_ops = S3Operations()
        settings = get_default_settings()
        
        # Perform cleanup
        deleted_objects = s3_ops.delete_old_objects(
            bucket_name, 
            max_age_days,
            settings['dry_run']
        )
        
        result = {
            'bucketName': bucket_name,
            'deletedCount': len(deleted_objects),
            'deletedObjects': deleted_objects[:10],  # Return first 10 for brevity
            'dryRun': settings['dry_run']
        }
        
        print(f"Cleanup completed for bucket {bucket_name}")
        return result
        
    except Exception as e:
        print(f"Error during S3 cleanup: {str(e)}")
        raise
```

## Troubleshooting aws:executeScript attachments
<a name="automation-action-executeScript-troubleshooting"></a>

Use the following guidance to resolve common issues with `aws:executeScript` attachments:

**Module import errors**  
If you receive import errors when using multi-module packages:
+ Ensure you have included an empty `__init__.py` file in each directory containing Python modules.
+ Verify that your import statements match the actual file and directory structure in your zip package.
+ Use relative imports (e.g., `from .utils import helper`) or absolute imports (e.g., `from utils import helper`) consistently.

**Attachment not found errors**  
If your automation fails to find the attachment:
+ Verify that the `Attachment` parameter value exactly matches the key in your `files` section.
+ Check that your S3 bucket path and file name are correct in the `files` section.
+ Ensure your automation role has `s3:GetObject` permission for the attachment S3 location.
+ Verify that the checksum in your runbook matches the actual file checksum.

**Handler function errors**  
If you receive handler-related errors:
+ For Python: Use the format `filename.function_name` in the `Handler` parameter (e.g., `main.process_data`).
+ Ensure your handler function accepts exactly two parameters: `events` and `context`.
+ For PowerShell: Do not specify a `Handler` parameter; the script runs directly.

**Script execution failures**  
If your script fails during execution:
+ Check the automation execution history for detailed error messages and stack traces.
+ Use `print()` statements (Python) or `Write-Information` (PowerShell) to add debugging output.
+ Verify that all required AWS permissions are granted to your automation role.
+ Test your script logic locally before packaging it as an attachment.

**Exit codes and error handling**  
To properly handle errors and return exit codes:
+ In Python: Use `raise Exception("error message")` to indicate script failure.
+ In PowerShell: Use `throw "error message"` or `Write-Error` to indicate failure.
+ Return structured data from your functions to provide detailed success/failure information.
+ Use try-catch blocks to handle exceptions gracefully and provide meaningful error messages.

# `aws:executeStateMachine` – Run an AWS Step Functions state machine
<a name="automation-action-executeStateMachine"></a>

Runs an AWS Step Functions state machine.

**Note**  
The `aws:executeStateMachine` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**

This action supports most parameters for the Step Functions [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) API operation.

**Required AWS Identity and Access Management (IAM) permissions**
+ `states:DescribeExecution`
+ `states:StartExecution`
+ `states:StopExecution`

------
#### [ YAML ]

```
name: executeTheStateMachine
action: aws:executeStateMachine
inputs:
  stateMachineArn: StateMachine_ARN
  input: '{"parameters":"values"}'
  name: name
```

------
#### [ JSON ]

```
{
    "name": "executeTheStateMachine",
    "action": "aws:executeStateMachine",
    "inputs": {
        "stateMachineArn": "StateMachine_ARN",
        "input": "{\"parameters\":\"values\"}",
        "name": "name"
    }
}
```

------

stateMachineArn  
The Amazon Resource Name (ARN) of the Step Functions state machine.  
Type: String  
Required: Yes

name  
The name of the execution.  
Type: String  
Required: No

input  
A string that contains the JSON input data for the execution.  
Type: String  
Required: No

**Outputs**  
The following outputs are predefined for this action.

executionArn  
The ARN of the execution.  
Type: String

input  
The string that contains the JSON input data of the execution. Length constraints apply to the payload size, and are expressed as bytes in UTF-8 encoding..  
Type: String

name  
The name of the execution.  
Type: String

output  
The JSON output data of the execution. Length constraints apply to the payload size, and are expressed as bytes in UTF-8 encoding.  
Type: String

startDate  
The date the execution is started.  
Type: String

stateMachineArn  
The ARN of the executed stated machine.  
Type: String

status  
The current status of the execution.  
Type: String

stopDate  
If the execution has already ended, the date the execution stopped.  
Type: String

# `aws:invokeWebhook` – Invoke an Automation webhook integration
<a name="invoke-webhook"></a>

Invokes the specified Automation webhook integration. For information about creating Automation integrations, see [Creating webhook integrations for Automation](creating-webhook-integrations.md).

**Note**  
The `aws:invokeWebhook` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Note**  
To use the `aws:invokeWebhook` action, your user or service role must allow the following actions:  
ssm:GetParameter
kms:Decrypt
Permission for the AWS Key Management Service (AWS KMS) `Decrypt` operation is only required if you use a customer managed key to encrypt the parameter for your integration.

**Input**  
Provide the information for the Automation integration you want to invoke.

------
#### [ YAML ]

```
action: "aws:invokeWebhook"
inputs: 
 IntegrationName: "exampleIntegration"
 Body: "Request body"
```

------
#### [ JSON ]

```
{
    "action": "aws:invokeWebhook",
    "inputs": {
        "IntegrationName": "exampleIntegration",
        "Body": "Request body"
    }
}
```

------

IntegrationName  
The name of the Automation integration. For example, `exampleIntegration`. The integration you specify must already exist.  
Type: String  
Required: Yes

Body  
The payload you want to send when your webhook integration is invoked.  
Type: String  
Required: NoOutput

Response  
The text received from the webhook provider response.

ResponseCode  
The HTTP status code received from the webhook provider response.

# `aws:invokeLambdaFunction` – Invoke an AWS Lambda function
<a name="automation-action-lamb"></a>

Invokes the specified AWS Lambda function.

**Note**  
Each `aws:invokeLambdaFunction` action can run up to a maximum duration of 300 seconds (5 minutes). You can limit the timeout by specifying the `timeoutSeconds` parameter for an `aws:invokeLambdaFunction` step.

**Note**  
The `aws:invokeLambdaFunction` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
This action supports most invoked parameters for the Lambda service. For more information, see [Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html).

------
#### [ YAML ]

```
name: invokeMyLambdaFunction
action: aws:invokeLambdaFunction
maxAttempts: 3
timeoutSeconds: 120
onFailure: Abort
inputs:
  FunctionName: MyLambdaFunction
```

------
#### [ JSON ]

```
{
    "name": "invokeMyLambdaFunction",
    "action": "aws:invokeLambdaFunction",
    "maxAttempts": 3,
    "timeoutSeconds": 120,
    "onFailure": "Abort",
    "inputs": {
        "FunctionName": "MyLambdaFunction"
    }
}
```

------

FunctionName  
The name of the Lambda function. This function must exist.  
Type: String  
Required: Yes

Qualifier  
The function version or alias name.  
Type: String  
Required: No

InvocationType  
The invocation type. The default value is `RequestResponse`.  
Type: String  
Valid values: `Event` \$1 `RequestResponse` \$1 `DryRun`  
Required: No

LogType  
If the default value is `Tail`, the invocation type must be `RequestResponse`. Lambda returns the last 4 KB of log data produced by your Lambda function, base64-encoded.  
Type: String  
Valid values: `None` \$1 `Tail`  
Required: No

ClientContext  
The client-specific information.  
Required: No

InputPayload  
A YAML or JSON object that is passed to the first parameter of the handler. You can use this input to pass data to the function. This input provides more flexibility and support than the legacy `Payload` input. If you define both `InputPayload` and `Payload` for the action, `InputPayload` takes precedence and the `Payload` value is not used.  
Type: StringMap  
Required: No

Payload  
A JSON string that's passed to the first parameter of the handler. This can be used to pass input data to the function. We recommend using `InputPayload` input for added functionality.  
Type: String  
Required: NoOutput

StatusCode  
The HTTP status code.

FunctionError  
If present, it indicates that an error occurred while executing the function. Error details are included in the response payload.

LogResult  
The base64-encoded logs for the Lambda function invocation. Logs are present only if the invocation type is `RequestResponse`, and the logs were requested.

Payload  
The JSON representation of the object returned by the Lambda function. Payload is present only if the invocation type is `RequestResponse`.

The following is a portion from the `AWS-PatchInstanceWithRollback` runbook demonstrating how to reference outputs from the `aws:invokeLambdaFunction` action.

------
#### [ YAML ]

```
- name: IdentifyRootVolume
  action: aws:invokeLambdaFunction
  inputs:
    FunctionName: "IdentifyRootVolumeLambda-{{automation:EXECUTION_ID}}"
    Payload: '{"InstanceId": "{{InstanceId}}"}'
- name: PrePatchSnapshot
  action: aws:executeAutomation
  inputs:
    DocumentName: "AWS-CreateSnapshot"
    RuntimeParameters:
      VolumeId: "{{IdentifyRootVolume.Payload}}"
      Description: "ApplyPatchBaseline restoration case contingency"
```

------
#### [ JSON ]

```
{
    "name": "IdentifyRootVolume",
    "action": "aws:invokeLambdaFunction",
    "inputs": {
      "FunctionName": "IdentifyRootVolumeLambda-{{automation:EXECUTION_ID}}",
      "Payload": "{\"InstanceId\": \"{{InstanceId}}\"}"
    }
  },
  {
    "name": "PrePatchSnapshot",
    "action": "aws:executeAutomation",
    "inputs": {
      "DocumentName": "AWS-CreateSnapshot",
      "RuntimeParameters": {
        "VolumeId": "{{IdentifyRootVolume.Payload}}",
        "Description": "ApplyPatchBaseline restoration case contingency"
      }
    }
  }
```

------

# `aws:loop` – Iterate over steps in an automation
<a name="automation-action-loop"></a>

This action iterates over a subset of steps in an automation runbook. You can choose a `do while` or `for each` style loop. To construct a `do while` loop, use the `LoopCondition` input parameter. To construct a `for each` loop, use the `Iterators` and `IteratorDataType` input parameters. When using an `aws:loop` action, only specify either the `Iterators` or `LoopCondition` input parameter. The maximum number of iterations is 100.

The `onCancel` property can only be used for steps defined within a loop. The `onCancel` property isn't supported for the `aws:loop` action. The `onFailure` property can be used for an `aws:loop` action, however it will only be used if an unexpected error occurs causing the step to fail. If you define `onFailure` properties for the steps within a loop, the `aws:loop` action inherits those properties and reacts accordingly when a failure occurs.

**Examples**  
The following are examples of how to construct the different types of loop actions.

------
#### [ do while ]

```
name: RepeatMyLambdaFunctionUntilOutputIsReturned
action: aws:loop
inputs:
    Steps:
    - name: invokeMyLambda
        action: aws:invokeLambdaFunction
        inputs:
        FunctionName: LambdaFunctionName
        outputs:
        - Name: ShouldRetry
            Selector: $.Retry
            Type: Boolean
    LoopCondition:
        Variable: "{{ invokeMyLambda.ShouldRetry }}"
        BooleanEquals: true
    MaxIterations: 3
```

------
#### [ for each ]

```
name: stopAllInstancesWithWaitTime
action: aws:loop
inputs:
    Iterators: "{{ DescribeInstancesStep.InstanceIds }}"
    IteratorDataType: "String"
    Steps:
    - name: stopOneInstance
        action: aws:changeInstanceState
        inputs:
        InstanceIds:
            - "{{stopAllInstancesWithWaitTime.CurrentIteratorValue}}"
        CheckStateOnly: false
        DesiredState: stopped
    - name: wait10Seconds
        action: aws:sleep
        inputs:
        Duration: PT10S
```

------

**Input**  
The input is as follows.

Iterators  
The list of items for the steps to iterate over. The maximum number of iterators is 100.  
Type: StringList  
Required: No

IteratorDataType  
An optional parameter to specify the data type of the `Iterators`. A value for this parameter can be provided along with the `Iterators` input parameter. If you don’t specify a value for this parameter and `Iterators`, then you must specify a value for the `LoopCondition` parameter.  
Type: String  
Valid values: Boolean \$1 Integer \$1 String \$1 StringMap  
Default: String  
Required: No

LoopCondition  
Consists of a `Variable` and an operator condition to evaluate. If you don’t specify a value for this parameter, then you must specify values for the `Iterators` and `IteratorDataType` parameters. You can use complex operator evaluations by using a combination of `And`, `Not`, and `Or` operators. The condition is evaluated after the steps in the loop complete. If the condition is `true` and the `MaxIterations` value has not been reached, the steps in the loop run again. The operator conditions are as follows:  

**String operations**
+ StringEquals
+ EqualsIgnoreCase
+ StartsWith
+ EndsWith
+ Contains

**Numeric operations**
+ NumericEquals
+ NumericGreater
+ NumericLesser
+ NumericGreaterOrEquals
+ NumericLesser
+ NumericLesserOrEquals

**Boolean operation**
+ BooleanEquals
Type: StringMap  
Required: No

MaxIterations  
The maximum number of times the steps in the loop run. Once the value specified for this input is reached, the loop stops running even if the `LoopCondition` is still `true` or if there are objects remaining in the `Iterators` parameter.  
Type: Integer  
Valid values: 1 - 100  
Required: No

Steps  
The list of steps to run in the loop. These function like a nested runbook. Within these steps you can access the current iterator value for a `for each` loop using the syntax `{{loopStepName.CurrentIteratorValue}}`. You can also access an integer value of the current iteration for both loop types using the syntax `{{loopStepName.CurrentIteration}}`.  
Type: List of steps  
Required: YesOutput

CurrentIteration  
The current loop iteration as an integer. Iteration values start at 1.  
Type: Integer

CurrentIteratorValue  
The value of the current iterator as a string. This output is only present in `for each` loops.  
Type: String

# `aws:pause` – Pause an automation
<a name="automation-action-pause"></a>

This action pauses the automation. Once paused, the automation status is *Waiting*. To continue the automation, use the [SendAutomationSignal](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_SendAutomationSignal.html) API operation with the `Resume` signal type. We recommend using the `aws:sleep` or `aws:approve` action for more granular control of your workflows.

**Note**  
The default timeout for this action is 7 days (604800 seconds) and the maximum value is 30 days (2592000 seconds). You can limit or extend the timeout by specifying the `timeoutSeconds` parameter for an `aws:pause` step.

**Input**  
The input is as follows.

------
#### [ YAML ]

```
name: pauseThis
action: aws:pause
timeoutSeconds: 1209600
inputs: {}
```

------
#### [ JSON ]

```
{
    "name": "pauseThis",
    "action": "aws:pause",
    "timeoutSeconds": "1209600",
    "inputs": {}
}
```

------Output

None  


# `aws:runCommand` – Run a command on a managed instance
<a name="automation-action-runcommand"></a>

Runs the specified commands.

**Note**  
Automation only supports *output* of one AWS Systems Manager Run Command action. A runbook can include multiple Run Command actions, but output is supported for only one action at a time.

**Input**  
This action supports most send command parameters. For more information, see [SendCommand](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_SendCommand.html).

------
#### [ YAML ]

```
- name: checkMembership
  action: 'aws:runCommand'
  inputs:
    DocumentName: AWS-RunPowerShellScript
    InstanceIds:
      - '{{InstanceIds}}'
    Parameters:
      commands:
        - (Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain
```

------
#### [ JSON ]

```
{
    "name": "checkMembership",
    "action": "aws:runCommand",
    "inputs": {
        "DocumentName": "AWS-RunPowerShellScript",
        "InstanceIds": [
            "{{InstanceIds}}"
        ],
        "Parameters": {
            "commands": [
                "(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain"
            ]
        }
    }
}
```

------

DocumentName  
If the Command type document is owned by you or AWS, specify the name of the document. If you're using a document shared with you by a different AWS account, specify the Amazon Resource Name (ARN) of the document. For more information about using shared documents, see [Using shared SSM documents](documents-ssm-sharing.md#using-shared-documents).  
Type: String  
Required: Yes

InstanceIds  
The instance IDs where you want the command to run. You can specify a maximum of 50 IDs.   
You can also use the pseudo parameter `{{RESOURCE_ID}}` in place of instance IDs to run the command on all instances in the target group. For more information about pseudo parameters, see [Using pseudo parameters when registering maintenance window tasks](maintenance-window-tasks-pseudo-parameters.md).  
Another alternative is to send commands to a fleet of instances by using the `Targets` parameter. The `Targets` parameter accepts Amazon Elastic Compute Cloud (Amazon EC2) tags. For more information about how to use the `Targets` parameter, see [Run commands at scale](send-commands-multiple.md).  
Type: StringList  
Required: No (If you don't specify InstanceIds or use the `{{RESOURCE_ID}}` pseudo parameter, then you must specify the `Targets` parameter.)

Targets  
An array of search criteria that targets instances by using a Key,Value combination that you specify. `Targets` is required if you don't provide one or more instance IDs in the call. For more information about how to use the `Targets` parameter, see [Run commands at scale](send-commands-multiple.md).  
Type: MapList (The schema of the map in the list must match the object.) For information, see [Target](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_Target.html) in the *AWS Systems Manager API Reference*.  
Required: No (If you don't specify `Targets`, then you must specify InstanceIds or use the `{{RESOURCE_ID}}` pseudo parameter.)  
Following is an example.  

```
- name: checkMembership
  action: aws:runCommand
  inputs:
    DocumentName: AWS-RunPowerShellScript
    Targets:
      - Key: tag:Stage
        Values:
          - Gamma
          - Beta
      - Key: tag-key
        Values:
          - Suite
    Parameters:
      commands:
        - (Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain
```

```
{
    "name": "checkMembership",
    "action": "aws:runCommand",
    "inputs": {
        "DocumentName": "AWS-RunPowerShellScript",
        "Targets": [                   
            {
                "Key": "tag:Stage",
                "Values": [
                    "Gamma", "Beta"
                ]
            },
            {
                "Key": "tag:Application",
                "Values": [
                    "Suite"
                ]
            }
        ],
        "Parameters": {
            "commands": [
                "(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain"
            ]
        }
    }
}
```

Parameters  
The required and optional parameters specified in the document.  
Type: Map  
Required: No

CloudWatchOutputConfig  
Configuration options for sending command output to Amazon CloudWatch Logs. For more information about sending command output to CloudWatch Logs, see [Configuring Amazon CloudWatch Logs for Run Command](sysman-rc-setting-up-cwlogs.md).  
Type: StringMap (The schema of the map must match the object. For more information, see [CloudWatchOutputConfig](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_CloudWatchOutputConfig.html) in the *AWS Systems Manager API Reference*).  
Required: No  
Following is an example.  

```
- name: checkMembership
  action: aws:runCommand
  inputs:
    DocumentName: AWS-RunPowerShellScript
    InstanceIds:
      - "{{InstanceIds}}"
    Parameters:
      commands:
        - "(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain"
    CloudWatchOutputConfig:
      CloudWatchLogGroupName: CloudWatchGroupForSSMAutomationService
      CloudWatchOutputEnabled: true
```

```
{
    "name": "checkMembership",
    "action": "aws:runCommand",
    "inputs": {
        "DocumentName": "AWS-RunPowerShellScript",
        "InstanceIds": [
            "{{InstanceIds}}"
        ],
        "Parameters": {
            "commands": [
                "(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain"
            ]
        },
        "CloudWatchOutputConfig" : { 
                "CloudWatchLogGroupName": "CloudWatchGroupForSSMAutomationService",
                "CloudWatchOutputEnabled": true
        }
    }
}
```

Comment  
User-defined information about the command.  
Type: String  
Required: No

DocumentHash  
The hash for the document.  
Type: String  
Required: No

DocumentHashType  
The type of the hash.  
Type: String  
Valid values: `Sha256` \$1 `Sha1`  
Required: No

NotificationConfig  
The configurations for sending notifications.  
Required: No

OutputS3BucketName  
The name of the S3 bucket for command output responses. Your managed node must have permissions for the S3 bucket to successfully log output.  
Type: String  
Required: No

OutputS3KeyPrefix  
The prefix.  
Type: String  
Required: No

ServiceRoleArn  
The ARN of the AWS Identity and Access Management (IAM) role.  
Type: String  
Required: No

TimeoutSeconds  
The amount of time in seconds to wait for a command to deliver to the AWS Systems Manager SSM Agent on an instance. If the command isn't received by the SSM Agent on the instance before the value specified is reached, then the status of the command changes to `Delivery Timed Out`.  
Type: Integer  
Required: No  
Valid values: 30-2592000Output

CommandId  
The ID of the command.

Status  
The status of the command.

ResponseCode  
The response code of the command. If the document you run has more than 1 step, a value isn't returned for this output.

Output  
The output of the command. If you target a tag or multiple instances with your command, no output value is returned. You can use the `GetCommandInvocation` and `ListCommandInvocations` API operations to retrieve output for individual instances.

# `aws:runInstances` – Launch an Amazon EC2 instance
<a name="automation-action-runinstance"></a>

Launches a new Amazon Elastic Compute Cloud (Amazon EC2) instance.

**Note**  
The `aws:runInstances` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
The action supports most API parameters. For more information, see the [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API documentation.

------
#### [ YAML ]

```
name: launchInstance
action: aws:runInstances
maxAttempts: 3
timeoutSeconds: 1200
onFailure: Abort
inputs:
  ImageId: ami-12345678
  InstanceType: t2.micro
  MinInstanceCount: 1
  MaxInstanceCount: 1
  IamInstanceProfileName: myRunCmdRole
  TagSpecifications:
  - ResourceType: instance
    Tags:
    - Key: LaunchedBy
      Value: SSMAutomation
    - Key: Category
      Value: HighAvailabilityFleetHost
```

------
#### [ JSON ]

```
{
   "name":"launchInstance",
   "action":"aws:runInstances",
   "maxAttempts":3,
   "timeoutSeconds":1200,
   "onFailure":"Abort",
   "inputs":{
      "ImageId":"ami-12345678",
      "InstanceType":"t2.micro",
      "MinInstanceCount":1,
      "MaxInstanceCount":1,
      "IamInstanceProfileName":"myRunCmdRole",
      "TagSpecifications":[
         {
            "ResourceType":"instance",
            "Tags":[
               {
                  "Key":"LaunchedBy",
                  "Value":"SSMAutomation"
               },
               {
                  "Key":"Category",
                  "Value":"HighAvailabilityFleetHost"
               }
            ]
         }
      ]
   }
}
```

------

AdditionalInfo  
Reserved.  
Type: String  
Required: No

BlockDeviceMappings  
The block devices for the instance.  
Type: MapList  
Required: No

ClientToken  
The identifier to ensure idempotency of the request.  
Type: String  
Required: No

DisableApiTermination  
Turns on or turns off instance API termination.  
Type: Boolean  
Required: No

EbsOptimized  
Turns on or turns off Amazon Elastic Block Store (Amazon EBS) optimization.  
Type: Boolean  
Required: No

IamInstanceProfileArn  
The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) instance profile for the instance.  
Type: String  
Required: No

IamInstanceProfileName  
The name of the IAM instance profile for the instance.  
Type: String  
Required: No

ImageId  
The ID of the Amazon Machine Image (AMI).  
Type: String  
Required: Yes

InstanceInitiatedShutdownBehavior  
Indicates whether the instance stops or terminates on system shutdown.  
Type: String  
Required: No

InstanceType  
The instance type.  
If an instance type value isn't provided, the m1.small instance type is used.
Type: String  
Required: No

KernelId  
The ID of the kernel.  
Type: String  
Required: No

KeyName  
The name of the key pair.  
Type: String  
Required: No

MaxInstanceCount  
The maximum number of instances to be launched.  
Type: String  
Required: No

MetadataOptions  
The metadata options for the instance. For more information, see [InstanceMetadataOptionsRequest](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InstanceMetadataOptionsRequest.html).  
Type: StringMap  
Required: No

MinInstanceCount  
The minimum number of instances to be launched.  
Type: String  
Required: No

Monitoring  
Turns on or turns off detailed monitoring.  
Type: Boolean  
Required: No

NetworkInterfaces  
The network interfaces.  
Type: MapList  
Required: No

Placement  
The placement for the instance.  
Type: StringMap  
Required: No

PrivateIpAddress  
The primary IPv4 address.  
Type: String  
Required: No

RamdiskId  
The ID of the RAM disk.  
Type: String  
Required: No

SecurityGroupIds  
The IDs of the security groups for the instance.  
Type: StringList  
Required: No

SecurityGroups  
The names of the security groups for the instance.  
Type: StringList  
Required: No

SubnetId  
The subnet ID.  
Type: String  
Required: No

TagSpecifications  
The tags to apply to the resources during launch. You can only tag instances and volumes at launch. The specified tags are applied to all instances or volumes that are created during launch. To tag an instance after it has been launched, use the [`aws:createTags` – Create tags for AWS resources](automation-action-createtag.md) action.  
Type: MapList (For more information, see [TagSpecification](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_TagSpecification.html).)  
Required: No

UserData  
A script provided as a string literal value. If a literal value is entered, then it must be Base64-encoded.  
Type: String  
Required: NoOutput

InstanceIds  
The IDs of the instances.

InstanceStates  
The current state of the instance.

# `aws:sleep` – Delay an automation
<a name="automation-action-sleep"></a>

Delays an automation for a specified amount of time. This action uses the International Organization for Standardization (ISO) 8601 date and time format. For more information about this date and time format, see [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html).

**Input**  
You can delay an automation for a specified duration. 

------
#### [ YAML ]

```
name: sleep
action: aws:sleep
inputs:
  Duration: PT10M
```

------
#### [ JSON ]

```
{
   "name":"sleep",
   "action":"aws:sleep",
   "inputs":{
      "Duration":"PT10M"
   }
}
```

------

You can also delay an automation until a specified date and time. If the specified date and time has passed, the action proceeds immediately. 

------
#### [ YAML ]

```
name: sleep
action: aws:sleep
inputs:
  Timestamp: '2020-01-01T01:00:00Z'
```

------
#### [ JSON ]

```
{
    "name": "sleep",
    "action": "aws:sleep",
    "inputs": {
        "Timestamp": "2020-01-01T01:00:00Z"
    }
}
```

------

**Note**  
Automation supports a maximum delay of 604799 seconds (7 days).

Duration  
An ISO 8601 duration. You can't specify a negative duration.   
Type: String  
Required: No

Timestamp  
An ISO 8601 timestamp. If you don't specify a value for this parameter, then you must specify a value for the `Duration` parameter.   
Type: String  
Required: NoOutput

None  


# `aws:updateVariable` – Updates a value for a runbook variable
<a name="automation-action-update-variable"></a>

This action updates a value for a runbook variable. The data type of the value must match the data type of the variable you want to update. Data type conversions aren't supported. The `onCancel` property isn't supported for the `aws:updateVariable` action.

**Input**  
The input is as follows.

------
#### [ YAML ]

```
name: updateStringList
action: aws:updateVariable
inputs:
    Name: variable:variable name
    Value:
    - "1"
    - "2"
```

------
#### [ JSON ]

```
{
    "name": "updateStringList",
    "action": "aws:updateVariable",
    "inputs": {
        "Name": "variable:variable name",
        "Value": ["1","2"]
    }
}
```

------

Name  
The name of the variable whose value you want to update. You must use the format `variable:variable name`  
Type: String  
Required: Yes

Value  
The new value to assign to the variable. The value must match the data type of the variable. Data type conversions aren't supported.  
Type: Boolean \$1 Integer \$1 MapList \$1 String \$1 StringList \$1 StringMap  
Required: Yes  
Constraints:  
+ MapList can contain a maximum number of 200 items.
+ Key lengths can be a minimum length of 1 and a maximum length of 50.
+ StringList can be a minimum number of 0 items and a maximum number of 50 items.
+ String lengths can be a minimum length of 1 and a maximum length of 512.Output

None  


# `aws:waitForAwsResourceProperty` – Wait on an AWS resource property
<a name="automation-action-waitForAwsResourceProperty"></a>

The `aws:waitForAwsResourceProperty` action allows your automation to wait for a specific resource state or event state before continuing the automation. For more examples of how to use this action, see [Additional runbook examples](automation-document-examples.md).

**Note**  
The default timeout value for this action is 3600 seconds (one hour). You can limit or extend the timeout by specifying the `timeoutSeconds` parameter for an `aws:waitForAwsResourceProperty` step. For more information and examples of how to use this action, see [Handling timeouts in runbooks](automation-handling-timeouts.md).

**Note**  
The `aws:waitForAwsResourceProperty` action supports automatic throttling retry. For more information, see [Configuring automatic retry for throttled operations](automation-throttling-retry.md).

**Input**  
Inputs are defined by the API operation that you choose.

------
#### [ YAML ]

```
action: aws:waitForAwsResourceProperty
inputs:
  Service: The official namespace of the service
  Api: The API operation or method name
  API operation inputs or parameters: A value
  PropertySelector: Response object
  DesiredValues:
  - Desired property value
```

------
#### [ JSON ]

```
{
  "action": "aws:waitForAwsResourceProperty",
  "inputs": {
    "Service":"The official namespace of the service",
    "Api":"The API operation or method name",
    "API operation inputs or parameters":"A value",
    "PropertySelector": "Response object",
    "DesiredValues": [
      "Desired property value"
    ]
  }
}
```

------

Service  
The AWS service namespace that contains the API operation that you want to run. For example, the namespace for AWS Systems Manager is `ssm`. The namespace for Amazon Elastic Compute Cloud (Amazon EC2) is `ec2`. You can view a list of supported AWS service namespaces in the [Available Services](https://docs.aws.amazon.com/cli/latest/reference/#available-services) section of the *AWS CLI Command Reference*.  
Type: String  
Required: Yes

Api  
The name of the API operation that you want to run. You can view the API operations (also called methods) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all API operations (methods) for Amazon Relational Database Service (Amazon RDS) are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html).  
Type: String  
Required: Yes

API operation inputs  
One or more API operation inputs. You can view the available inputs (also called parameters) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all methods for Amazon RDS are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html). Choose the [describe\$1db\$1instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances) method and scroll down to see the available parameters, such as **DBInstanceIdentifier**, **Name**, and **Values**.  

```
inputs:
  Service: The official namespace of the service
  Api: The API operation name
  API input 1: A value
  API Input 2: A value
  API Input 3: A value
```

```
"inputs":{
      "Service":"The official namespace of the service",
      "Api":"The API operation name",
      "API input 1":"A value",
      "API Input 2":"A value",
      "API Input 3":"A value"
}
```
Type: Determined by chosen API operation  
Required: Yes

PropertySelector  
The JSONPath to a specific attribute in the response object. You can view the response objects by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all methods for Amazon RDS are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html). Choose the [describe\$1db\$1instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances) method and scroll down to the **Response Structure** section. **DBInstances** is listed as a response object.  
Type: String  
Required: Yes

DesiredValues  
The expected status or state on which to continue the automation.  
Type: MapList, StringList  
Required: Yes

# Automation system variables
<a name="automation-variables"></a>

AWS Systems Manager Automation runbooks use the following variables. For an example of how these variables are used, view the JSON source of the `AWS-UpdateWindowsAmi` runbook. 

**To view the JSON source of the `AWS-UpdateWindowsAmi` runbook**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Documents**.

1. In the document list, use either the Search bar or the numbers to the right of the Search bar to choose the runbook `AWS-UpdateWindowsAmi`.

1. Choose the **Content** tab. 

**System variables**  
Automation runbooks support the following system variables.


****  

| Variable | Details | 
| --- | --- | 
|  `global:ACCOUNT_ID`  |  The AWS account ID of the user or role in which Automation runs.  | 
|  `global:DATE`  |  The date (at run time) in the format yyyy-MM-dd.  | 
|  `global:DATE_TIME`  |  The date and time (at run time) in the format yyyy-MM-dd\$1HH.mm.ss.  | 
|  `global:AWS_PARTITION`  |  The partition that the resource is in. For standard AWS Regions, the partition is `aws`. For resources in other partitions, the partition is `aws-partitionname`. For example, the partition for resources in the AWS GovCloud (US-West) Region is `aws-us-gov`.  | 
|  `global:REGION`  |  The Region that the runbook is run in. For example, us-east-2.  | 

**Automation variables**  
Automation runbooks support the following automation variables.


****  

| Variable | Details | 
| --- | --- | 
|  `automation:EXECUTION_ID`  |  The unique identifier assigned to the current automation. For example, `1a2b3c-1a2b3c-1a2b3c-1a2b3c1a2b3c1a2b3c`.  | 

**Topics**
+ [Terminology](#automation-terms)
+ [Supported scenarios](#automation-variables-support)
+ [Unsupported scenarios](#automation-variables-unsupported)

## Terminology
<a name="automation-terms"></a>

The following terms describe how variables and parameters are resolved.


****  

| Term | Definition | Example | 
| --- | --- | --- | 
|  Constant ARN  |  A valid Amazon Resource Name (ARN) without variables.  |  `arn:aws:iam::123456789012:role/roleName`  | 
|  Runbook parameter  |  A parameter defined at the runbook level (for example, `instanceId`). The parameter is used in a basic string replace. Its value is supplied at Start Execution time.  |  <pre>{ <br />   "description": "Create Image Demo",<br />   "version": "0.3",<br />   "assumeRole": "Your_Automation_Assume_Role_ARN",<br />   "parameters":{ <br />      "instanceId": { <br />         "type": "String",<br />         "description": "Instance to create image from"<br />   }<br />}</pre>  | 
|  System variable  |  A general variable substituted into the runbook when any part of the runbook is evaluated.  |  <pre>"activities": [ <br />   { <br />      "id": "copyImage",<br />      "activityType": "AWS-CopyImage",<br />      "maxAttempts": 1,<br />      "onFailure": "Continue",<br />      "inputs": { <br />         "ImageName": "{{imageName}}",<br />         "SourceImageId": "{{sourceImageId}}",<br />         "SourceRegion": "{{sourceRegion}}",<br />         "Encrypted": true,<br />         "ImageDescription": "Test CopyImage Description created on {{global:DATE}}"<br />      }<br />   }<br />]</pre>  | 
|  Automation variable  |  A variable relating to the automation substituted into the runbook when any part of the runbook is evaluated.  |  <pre>{ <br />   "name": "runFixedCmds",<br />   "action": "aws:runCommand",<br />   "maxAttempts": 1,<br />   "onFailure": "Continue",<br />   "inputs": { <br />      "DocumentName": "AWS-RunPowerShellScript",<br />      "InstanceIds": [ <br />         "{{LaunchInstance.InstanceIds}}"<br />      ],<br />      "Parameters": { <br />         "commands": [ <br />            "dir",<br />            "date",<br />            "“{{outputFormat}}” -f “left”,”right”,”{{global:DATE}}”,”{{automation:EXECUTION_ID}}”<br />         ]<br />      }<br />   }<br />}</pre>  | 
|  Systems Manager Parameter  |  A variable defined within AWS Systems Manager Parameter Store. It can't be directly referenced in step input. Permissions might be required to access the parameter.  |  <pre><br />description: Launch new Windows test instance<br />schemaVersion: '0.3'<br />assumeRole: '{{AutomationAssumeRole}}'<br />parameters:<br />  AutomationAssumeRole:<br />    type: String<br />    default: ''<br />    description: >-<br />      (Required) The ARN of the role that allows Automation to perform the<br />      actions on your behalf. If no role is specified, Systems Manager<br />      Automation uses your IAM permissions to run this runbook.<br />  LatestAmi:<br />    type: String<br />    default: >-<br />      {{ssm:/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base}}<br />    description: The latest Windows Server 2016 AMI queried from the public parameter.<br />mainSteps:<br />  - name: launchInstance<br />    action: 'aws:runInstances'<br />    maxAttempts: 3<br />    timeoutSeconds: 1200<br />    onFailure: Abort<br />    inputs:<br />      ImageId: '{{LatestAmi}}'<br />...</pre>  | 

## Supported scenarios
<a name="automation-variables-support"></a>


****  

| Scenario | Comments | Example | 
| --- | --- | --- | 
|  Constant ARN `assumeRole` at creation.  |  An authorization check is performed to verify that the calling user is permitted to pass the given `assumeRole`.  |  <pre>{<br />  "description": "Test all Automation resolvable parameters",<br />  "schemaVersion": "0.3",<br />  "assumeRole": "arn:aws:iam::123456789012:role/roleName",<br />  "parameters": { <br />  ...</pre>  | 
|  Runbook parameter supplied for `AssumeRole` when the automation is started.  |  Must be defined in the parameter list of the runbook.  |  <pre>{<br />  "description": "Test all Automation resolvable parameters",<br />  "schemaVersion": "0.3",<br />  "assumeRole": "{{dynamicARN}}",<br />  "parameters": {<br /> ...</pre>  | 
|  Value supplied for runbook parameter at start.  |  Customer supplies the value to use for a parameter. Any inputs supplied at start time need to be defined in the parameter list of the runbook.  |  <pre>...<br />"parameters": {<br />    "amiId": {<br />      "type": "String",<br />      "default": "ami-12345678",<br />      "description": "list of commands to run as part of first step"<br />    },<br />...</pre> Inputs to Start Automation Execution include : `{"amiId" : ["ami-12345678"] }`  | 
|  Systems Manager Parameter referenced within runbook content.  |  The variable exists within the customer's account, or is a publicly accessibly parameter, and the `AssumeRole` for the runbook has access to the variable. A check is performed at create time to confirm the `AssumeRole` has access. The parameter can't be directly referenced in step input.  |  <pre><br />...<br />parameters:<br />    LatestAmi:<br />    type: String<br />    default: >-<br />      {{ssm:/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base}}<br />    description: The latest Windows Server 2016 AMI queried from the public parameter.<br />mainSteps:<br />  - name: launchInstance<br />    action: 'aws:runInstances'<br />    maxAttempts: 3<br />    timeoutSeconds: 1200<br />    onFailure: Abort<br />    inputs:<br />      ImageId: '{{LatestAmi}}'<br />...</pre>  | 
|  System variable referenced within step definition  |  A system variable is substituted into the runbook when the automation is started. The value injected into the runbook is relative to when the substitution occurs. That is, the value of a time variable injected at step 1 is different from the value injected at step 3 because of the time it takes to run the steps between. System variables don't need to be set in the parameter list of the runbook.  |  <pre>...<br />  "mainSteps": [<br />    {<br />      "name": "RunSomeCommands",<br />      "action": "aws:runCommand",<br />      "maxAttempts": 1,<br />      "onFailure": "Continue",<br />      "inputs": {<br />        "DocumentName": "AWS:RunPowerShell",<br />        "InstanceIds": ["{{LaunchInstance.InstanceIds}}"],<br />        "Parameters": {<br />            "commands" : [<br />                "echo {The time is now {{global:DATE_TIME}}}"<br />            ]<br />        }<br />    }<br />}, ... </pre>  | 
|  Automation variable referenced within step definition.  |  Automation variables don't need to be set in the parameter list of the runbook. The only supported Automation variable is **automation:EXECUTION\$1ID**.  |  <pre>...<br />"mainSteps": [<br />    {<br />      "name": "invokeLambdaFunction",<br />      "action": "aws:invokeLambdaFunction",<br />      "maxAttempts": 1,<br />      "onFailure": "Continue",<br />      "inputs": {<br />        "FunctionName": "Hello-World-LambdaFunction",<br /><br />"Payload" : "{ "executionId" : "{{automation:EXECUTION_ID}}" }"<br />      }<br />    }<br />... </pre>  | 
|  Refer to output from previous step within next step definition.  |  This is parameter redirection. The output of a previous step is referenced using the syntax `{{stepName.OutputName}}`. This syntax can't be used by the customer for runbook parameters. This is resolved when the referring step runs. The parameter isn't listed in the parameters of the runbook.  |  <pre>...<br />"mainSteps": [<br />    {<br />      "name": "LaunchInstance",<br />      "action": "aws:runInstances",<br />      "maxAttempts": 1,<br />      "onFailure": "Continue",<br />      "inputs": {<br />        "ImageId": "{{amiId}}",<br />        "MinInstanceCount": 1,<br />        "MaxInstanceCount": 2<br />      }<br />    },<br />    {<br />      "name":"changeState",<br />      "action": "aws:changeInstanceState",<br />      "maxAttempts": 1,<br />      "onFailure": "Continue",<br />      "inputs": {<br />        "InstanceIds": ["{{LaunchInstance.InstanceIds}}"],<br />        "DesiredState": "terminated"<br />      }<br />    }<br /><br />... </pre>  | 

## Unsupported scenarios
<a name="automation-variables-unsupported"></a>


****  

| Scenario | Comment | Example | 
| --- | --- | --- | 
|  Systems Manager Parameter supplied for `assumeRole` at create  |  Not supported.  |  <pre>...<br /><br />{<br />  "description": "Test all Automation resolvable parameters",<br />  "schemaVersion": "0.3",<br />  "assumeRole": "{{ssm:administratorRoleARN}}",<br />  "parameters": {<br /><br />... </pre>  | 
|  Systems Manager Parameter directly referenced in step input.  |  Returns `InvalidDocumentContent` exception at create time.  |  <pre><br />...<br />mainSteps:<br />  - name: launchInstance<br />    action: 'aws:runInstances'<br />    maxAttempts: 3<br />    timeoutSeconds: 1200<br />    onFailure: Abort<br />    inputs:<br />      ImageId: '{{ssm:/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base}}'<br />...</pre>  | 
|  Variable step definition  |  The definition of a step in the runbook is constructed by variables.  |  <pre>...<br /><br />"mainSteps": [<br />    {<br />      "name": "LaunchInstance",<br />      "action": "aws:runInstances",<br />      "{{attemptModel}}": 1,<br />      "onFailure": "Continue",<br />      "inputs": {<br />        "ImageId": "ami-12345678",<br />        "MinInstanceCount": 1,<br />        "MaxInstanceCount": 2<br />      }<br /><br />...<br /><br />User supplies input : { "attemptModel" : "minAttempts" } </pre>  | 
|  Cross referencing runbook parameters  |  The user supplies an input parameter at start time, which is a reference to another parameter in the runbook.  |  <pre>...<br />"parameters": {<br />    "amiId": {<br />      "type": "String",<br />      "default": "ami-7f2e6015",<br />      "description": "list of commands to run as part of first step"<br />    },<br />    "alternateAmiId": {<br />      "type": "String",<br />      "description": "The alternate AMI to try if this first fails".<br /><br />"default" : "{{amiId}}"<br />    },<br /><br />... </pre>  | 
|  Multi-level expansion  |  The runbook defines a variable that evaluates to the name of a variable. This sits within the variable delimiters (that is *\$1\$1 \$1\$1*) and is expanded to the value of that variable/parameter.  |  <pre>...<br />  "parameters": {<br />    "firstParameter": {<br />      "type": "String",<br />      "default": "param2",<br />      "description": "The parameter to reference"<br />    },<br />    "secondParameter": {<br />      "type": "String",<br />      "default" : "echo {Hello world}",<br />      "description": "What to run"<br />    }<br />  },<br />  "mainSteps": [{<br />      "name": "runFixedCmds",<br />      "action": "aws:runCommand",<br />      "maxAttempts": 1,<br />      "onFailure": "Continue",<br />      "inputs": {<br />        "DocumentName": "AWS-RunPowerShellScript",<br /><br />"InstanceIds" : "{{LaunchInstance.InstanceIds}}",<br />        "Parameters": {<br />          "commands": [ "{{ {{firstParameter}} }}"]<br /><br />}<br /><br />...<br /><br />Note: The customer intention here would be to run a command of "echo {Hello world}" </pre>  | 
|  Referencing output from a runbook step that is a different variable type  |  The user references the output from a preceding runbook step within a subsequent step. The output is a variable type that doesn't meet the requirements of the action in the subsequent step.  |  <pre>...<br />mainSteps:<br />- name: getImageId<br />  action: aws:executeAwsApi<br />  inputs:<br />    Service: ec2<br />    Api: DescribeImages<br />    Filters:  <br />    - Name: "name"<br />      Values: <br />      - "{{ImageName}}"<br />  outputs:<br />  - Name: ImageIdList<br />    Selector: "$.Images"<br />    Type: "StringList"<br />- name: copyMyImages<br />  action: aws:copyImage<br />  maxAttempts: 3<br />  onFailure: Abort<br />  inputs:<br />    SourceImageId: {{getImageId.ImageIdList}}<br />    SourceRegion: ap-northeast-2<br />    ImageName: Encrypted Copies of LAMP base AMI in ap-northeast-2<br />    Encrypted: true <br />... <br />Note: You must provide the type required by the Automation action. <br />In this case, aws:copyImage requires a "String" type variable but the preceding step outputs a "StringList" type variable.<br />                                        </pre>  | 

# Creating your own runbooks
<a name="automation-documents"></a>

An Automation runbook defines the *actions* that Systems Manager performs on your managed instances and other AWS resources when an automation runs. Automation is a tool in AWS Systems Manager. A runbook contains one or more steps that run in sequential order. Each step is built around a single action. Output from one step can be used as input in a later step. 

The process of running these actions and their steps is called the *automation*.

Action types supported for runbooks let you automate a wide variety of operations in your AWS environment. For example, using the `executeScript` action type, you can embed a python or PowerShell script directly in your runbook. (When you create a custom runbook, you can add your script inline, or attach it from an S3 bucket or from your local machine.) You can automate management of your AWS CloudFormation resources by using the `createStack` and `deleteStack` action types. In addition, using the `executeAwsApi` action type, a step can run *any *API operation in any AWS service, including creating or deleting AWS resources, starting other processes, initiating notifications, and many more. 

For a list of all 20 supported action types for Automation, see [Systems Manager Automation actions reference](automation-actions.md).

AWS Systems Manager Automation provides several runbooks with pre-defined steps that you can use to perform common tasks like restarting one or more Amazon Elastic Compute Cloud (Amazon EC2) instances or creating an Amazon Machine Image (AMI). You can also create your own runbooks and share them with other AWS accounts, or make them public for all Automation users.

Runbooks are written using YAML or JSON. Using the **Document Builder** in the Systems Manager Automation console, however, you can create a runbook without having to author in native JSON or YAML.

**Important**  
If you run an automation workflow that invokes other services by using an AWS Identity and Access Management (IAM) service role, be aware that the service role must be configured with permission to invoke those services. This requirement applies to all AWS Automation runbooks (`AWS-*` runbooks) such as the `AWS-ConfigureS3BucketLogging`, `AWS-CreateDynamoDBBackup`, and `AWS-RestartEC2Instance` runbooks, to name a few. This requirement also applies to any custom Automation runbooks you create that invoke other AWS services by using actions that call other services. For example, if you use the `aws:executeAwsApi`, `aws:createStack`, or `aws:copyImage` actions, configure the service role with permission to invoke those services. You can give permissions to other AWS services by adding an IAM inline policy to the role. For more information, see [(Optional) Add an Automation inline policy or customer managed policy to invoke other AWS services](automation-setup-iam.md#add-inline-policy).

For information about the actions that you can specify in a runbook, see [Systems Manager Automation actions reference](automation-actions.md).

For information about using the AWS Toolkit for Visual Studio Code to create runbooks, see [Working with Systems Manager Automation documents](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/systems-manager-automation-docs.html) in the *AWS Toolkit for Visual Studio Code User Guide*.

For information about using the visual designer to create a custom runbook, see [Visual design experience for Automation runbooks](automation-visual-designer.md). 

**Contents**
+ [Visual design experience for Automation runbooks](automation-visual-designer.md)
  + [Overview of the visual design experience interface](visual-designer-interface-overview.md)
    + [Actions browser](visual-designer-interface-overview.md#visual-designer-actions)
    + [Canvas](visual-designer-interface-overview.md#visual-designer-canvas)
    + [Form](visual-designer-interface-overview.md#visual-designer-form)
    + [Keyboard shortcuts](visual-designer-interface-overview.md#visual-designer-keyboard-shortcuts)
  + [Using the visual design experience](visual-designer-use.md)
    + [Create a runbook workflow](visual-designer-use.md#visual-designer-create-runbook-workflow)
    + [Design a runbook](visual-designer-use.md#visual-designer-build)
    + [Update your runbook](visual-designer-use.md#visual-designer-update-runbook)
    + [Export your runbook](visual-designer-use.md#visual-designer-export-runbook)
  + [Configuring inputs and outputs for your actions](visual-designer-action-inputs-outputs.md)
    + [Provide input data for an action](visual-designer-action-inputs-outputs.md#providing-input)
    + [Define output data for an action](visual-designer-action-inputs-outputs.md#defining-output)
  + [Error handling with the visual design experience](visual-designer-error-handling.md)
    + [Retry action on error](visual-designer-error-handling.md#retry-actions)
    + [Timeouts](visual-designer-error-handling.md#timeout-seconds)
    + [Failed actions](visual-designer-error-handling.md#failure-actions)
    + [Canceled actions](visual-designer-error-handling.md#cancel-actions)
    + [Critical actions](visual-designer-error-handling.md#critical-actions)
    + [Ending actions](visual-designer-error-handling.md#end-actions)
  + [Tutorial: Create a runbook using the visual design experience](visual-designer-tutorial.md)
    + [Step 1: Navigate to the visual design experience](visual-designer-tutorial.md#navigate-console)
    + [Step 2: Create a workflow](visual-designer-tutorial.md#create-workflow)
    + [Step 3: Review the auto-generated code](visual-designer-tutorial.md#view-generated-code)
    + [Step 4: Run your new runbook](visual-designer-tutorial.md#use-tutorial-runbook)
    + [Step 5: Clean up](visual-designer-tutorial.md#cleanup-tutorial-runbook)
+ [Authoring Automation runbooks](automation-authoring-runbooks.md)
  + [Identify your use case](automation-authoring-runbooks.md#automation-authoring-runbooks-use-case)
  + [Set up your development environment](automation-authoring-runbooks.md#automation-authoring-runbooks-environment)
  + [Develop runbook content](automation-authoring-runbooks.md#automation-authoring-runbooks-developing-content)
  + [Example 1: Creating parent-child runbooks](automation-authoring-runbooks-parent-child-example.md)
    + [Create the child runbook](automation-authoring-runbooks-parent-child-example.md#automation-authoring-runbooks-child-runbook)
    + [Create the parent runbook](automation-authoring-runbooks-parent-child-example.md#automation-authoring-runbooks-parent-runbook)
  + [Example 2: Scripted runbook](automation-authoring-runbooks-scripted-example.md)
  + [Additional runbook examples](automation-document-examples.md)
    + [Deploy VPC architecture and Microsoft Active Directory domain controllers](automation-document-architecture-deployment-example.md)
    + [Restore a root volume from the latest snapshot](automation-document-instance-recovery-example.md)
    + [Create an AMI and cross-Region copy](automation-document-backup-maintenance-example.md)
+ [Creating input parameters that populate AWS resources](populating-input-parameters.md)
+ [Using Document Builder to create runbooks](automation-document-builder.md)
  + [Create a runbook using Document Builder](automation-document-builder.md#create-runbook)
  + [Create a runbook that runs scripts](automation-document-builder.md#create-runbook-scripts)
+ [Using scripts in runbooks](automation-document-script-considerations.md)
  + [Permissions for using runbooks](automation-document-script-considerations.md#script-permissions)
  + [Adding scripts to runbooks](automation-document-script-considerations.md#adding-scripts)
  + [Script constraints for runbooks](automation-document-script-considerations.md#script-constraints)
+ [Using conditional statements in runbooks](automation-branch-condition.md)
  + [Working with the `aws:branch` action](automation-branch-condition.md#branch-action-explained)
    + [Creating an `aws:branch` step in a runbook](automation-branch-condition.md#create-branch-action)
      + [About creating the output variable](automation-branch-condition.md#branch-action-output)
    + [Example `aws:branch` runbooks](automation-branch-condition.md#branch-runbook-examples)
    + [Creating complex branching automations with operators](automation-branch-condition.md#branch-operators)
  + [Examples of how to use conditional options](automation-branch-condition.md#conditional-examples)
+ [Using action outputs as inputs](automation-action-outputs-inputs.md)
  + [Using JSONPath in runbooks](automation-action-outputs-inputs.md#automation-action-json-path)
+ [Creating webhook integrations for Automation](creating-webhook-integrations.md)
  + [Creating integrations (console)](creating-webhook-integrations.md#creating-integrations-console)
  + [Creating integrations (command line)](creating-webhook-integrations.md#creating-integrations-commandline)
  + [Creating webhooks for integrations](creating-webhook-integrations.md#creating-webhooks)
+ [Handling timeouts in runbooks](automation-handling-timeouts.md)

# Visual design experience for Automation runbooks
<a name="automation-visual-designer"></a>

AWS Systems Manager Automation provides a low-code visual design experience that helps you create automation runbooks. The visual design experience provides a drag-and-drop interface with the option to add your own code so you can create and edit runbooks more easily. With the visual design experience, you can do the following:
+ Control conditional statements.
+ Control how input and output is filtered or transformed for each action.
+ Configure error handling.
+ Prototype new runbooks.
+ Use your prototype runbooks as the starting point for local development with the AWS Toolkit for Visual Studio Code.

When you create or edit a runbook, you can access the visual design experience from the [Automation console](https://console.aws.amazon.com/systems-manager/automation/home?region=us-east-1#/). As you create a runbook, the visual design experience validates your work and auto-generates code. You can review the generated code, or export it for local development. When you're finished, you can save your runbook, run it, and examine the results in the Systems Manager Automation console. 

**Topics**
+ [Interface overview](visual-designer-interface-overview.md)
+ [Using the visual design experience](visual-designer-use.md)
+ [Configure inputs and outputs](visual-designer-action-inputs-outputs.md)
+ [Error handling with the visual design experience](visual-designer-error-handling.md)
+ [Tutorial: Create a runbook using the visual design experience](visual-designer-tutorial.md)

# Overview of the visual design experience interface
<a name="visual-designer-interface-overview"></a>

The visual design experience for Systems Manager Automation is a low-code visual workflow designer that helps you create automation runbooks.

Get to know the visual design experience with an overview of the interface components:

![\[Visual design experience components\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_overview.png)

+ The **Actions** browser contains the **Actions**, **AWS APIs**, and **Runbooks** tabs.
+ The *canvas* is where you drag and drop actions into your workflow graph, change the order of actions, and select actions to configure or view.
+ The **Form** panel is where you can view and edit the properties of any action that you selected on the canvas. Select the **Content** toggle to view the YAML or JSON for your runbook, with the currently selected action highlighted. 

**Info** links open a panel with contextual information when you need help. These panels also include links to related topics in the Systems Manager Automation documentation. 

## Actions browser
<a name="visual-designer-actions"></a>

From the **Actions** browser, you can select actions to drag and drop into your workflow graph. You can search all actions using the search field at the top of the **Actions** browser. The **Actions** browser contains the following tabs:
+ The **Actions** tab provides a list of automation actions that you can drag and drop into your runbook's workflow graph in the canvas.
+ The **AWS APIs** tab provides a list of AWS APIs that you can drag and drop into your runbook's workflow graph in the canvas.
+ The **Runbooks** tab provides several ready-to-use, reusable runbooks as building blocks that you can use for a variety of use cases. For example, you can use runbooks to perform common remediation tasks on Amazon EC2 instances in your workflow without having to re-create the same actions.

![\[Visual design experience actions browser\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_actions_multi_view.png)


## Canvas
<a name="visual-designer-canvas"></a>

After you choose an action to add to your automation, drag it to the canvas and drop it into your workflow graph. You can also drag and drop actions to move them to different places in your runbook's workflow. If your workflow is complex, you might not be able to view all of it in the canvas panel. Use the controls at the top of the canvas to zoom in or out. To view different parts of a workflow, you can drag the workflow graph in the canvas. 

Drag an action from the **Actions** browser, and drop it into your runbook's workflow graph. A line shows where it will be placed in your workflow. To change the order of an action, you can drag it to a different place in your workflow. The new action has been added to your workflow, and its code is auto-generated.

![\[Visual design experience canvas\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_canvas.png)


## Form
<a name="visual-designer-form"></a>

After you add an action to your runbook workflow, you can configure it to meet your use case. Choose the action that you want to configure, and you will see its parameters and options in the **Form** panel. You can also see the YAML or JSON code by choosing the **Content** toggle. The code associated with the action you have selected is highlighted.

![\[Visual design experience form panel\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_form.png)


![\[Visual design experience content panel\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_content.png)


## Keyboard shortcuts
<a name="visual-designer-keyboard-shortcuts"></a>

The visual design experience supports the keyboard shortcuts shown in the following table.


| Keyboard shortcut | Function | 
| --- | --- | 
| Ctrl\$1Z | Undo the last operation. | 
| Ctrl\$1Shift\$1Z | Redo the last operation. | 
| Alt\$1C | Center the workflow in the canvas. | 
| Backspace | Remove all selected states. | 
| Delete | Remove all selected states. | 
| Ctrl\$1D | Duplicate the selected state. | 

# Using the visual design experience
<a name="visual-designer-use"></a>

Learn to create, edit and run runbook workflows using the visual design experience. After your workflow is ready, you can save it or export it. You can also use the visual design experience for rapid prototyping. 

## Create a runbook workflow
<a name="visual-designer-create-runbook-workflow"></a>

1. Sign in to the [Systems Manager Automation console](https://console.aws.amazon.com/systems-manager/automation/home?region=us-east-1#/).

1. Choose **Create runbook**.

1. In the **Name** box, enter a name for your runbook, for example, `MyNewRunbook`.

1. Next to the **Design** and **Code** toggle, select the pencil icon and enter a name for your runbook.

You can now design a workflow for your new runbook.

## Design a runbook
<a name="visual-designer-build"></a>

 To design a runbook workflow using the visual design experience, you drag an automation action from the **Actions** browser into the canvas, placing it where you want it in your runbook's workflow. You can also re-order actions in your workflow by dragging them to a different location. As you drag an action onto the canvas, a line appears wherever you can drop the action in your workflow. After an action is dropped onto the canvas, its code is auto-generated and added inside your runbook's content.

If you know the name of the action you want to add, use the search box at the top of the **Actions** browser to find the action.

After you drop an action onto the canvas, configure it using the **Form** panel on the right. This panel contains the **General**, **Inputs**, **Outputs**, and **Configuration** tabs for each automation action or API action that you place on the canvas. For example, the **General** tab consists of the following sections:
+ The **Step name** identifies the step. Specify a unique value for the step name.
+ The **Description** helps you describe what the action is doing in your runbook's workflow.

The **Inputs** tab contains fields that vary based on the action. For example, the `aws:executeScript` automation action consists of the following sections:
+ The **Runtime** is the language to use for running the provided script.
+ The **Handler** is the name of your function. You must ensure that the function defined in the handler has two parameters: `events` and `context`. The PowerShell runtime doesn't support this parameter. 
+ The **Script** is an embedded script that you want to run during the workflow.
+ (Optional) The **Attachment** is for standalone scripts or .zip files that can be invoked by the action. This parameter is required for JSON runbooks.

The **Outputs** tab helps you specify the values that you want to output from an action. You can reference output values in later actions of your workflow, or generate output from actions for logging purposes. Not all actions will have an **Outputs** tab because not all actions support outputs. For example, the `aws:pause` action doesn't support outputs. For actions that do support outputs, the **Outputs** tab consists of the following sections:
+ The **Name** is the name to be used for the output value. You can reference outputs in later actions of your workflow.
+ The **Selector** is a JSONPath expression string beginning with `"$."` that is used to select one or more components within a JSON element.
+ The **Type** is the data type for the output value. For example, a `String` or `Integer` data type.

The **Configuration** tab contains properties and options that all automation actions can use. The action consists of the following sections:
+ The **Max attempts** property is the number of times an action retries if it fails.
+ The **Timeout seconds** property specifies the timeout value for an action.
+ The **Is critical** property determines if the action failure stops the entire automation.
+ The **Next step** property determines which action the automation goes to next in the runbook.
+ The **On failure** property determines which action the automation goes to next in the runbook if the action fails.
+ The **On cancel** property determines which action the automation goes to next in the runbook if the action is canceled by a user.

To delete an action, you can use backspace, the toolbar above the canvas, or right-click and choose **Delete action**.

As your workflow grows, it might not fit in the canvas. To help make the workflow fit in the canvas, try one of the following options: 
+ Use the controls on the side panels to resize or close the panels.
+ Use the toolbar at the top of the canvas to zoom the workflow graph in or out.

## Update your runbook
<a name="visual-designer-update-runbook"></a>

You can update an existing runbook workflow by creating a new version of your runbook. Updates to your runbooks can be made by using the visual design experience, or by editing the code directly. To update an existing runbook, use the following procedure:

1. Sign in to the [Systems Manager Automation console](https://console.aws.amazon.com/systems-manager/automation/home?region=us-east-1#/).

1. Choose the runbook that you want to update.

1. Choose **Create new version**.

1. The visual design experience has two panes: A code pane and a visual workflow pane. Choose **Design** in the visual workflow pane to edit your workflow with the visual design experience. When you're done, choose **Create new version** to save your changes and exit.

1. (Optional) Use the code pane to edit the runbook content in YAML or JSON.

## Export your runbook
<a name="visual-designer-export-runbook"></a>

To export your runbook's workflow YAML or JSON code, and also a graph of your workflow, use the following procedure: 

1. Choose your runbook in the **Documents** console.

1. Choose **Create new version**.

1. In the **Actions** dropdown, choose whether you want to export the graph or runbook, and which format you prefer.

# Configuring inputs and outputs for your actions
<a name="visual-designer-action-inputs-outputs"></a>

Each automation action responds based on input that it receives. In most cases, you then pass output to the subsequent actions. In the visual design experience, you can configure an action's input and output data in the **Inputs** and **Outputs** tabs of the **Form** panel.

For detailed information about how to define and use output for automation actions, see [Using action outputs as inputs](automation-action-outputs-inputs.md). 

## Provide input data for an action
<a name="providing-input"></a>

Each automation action has one or more inputs that you must provide a value for. The value you provide for an action's input is determined by the data type and format that's accepted by the action. For example, the `aws:sleep` actions requires an ISO 8601 formatted string value for the `Duration` input.

Generally, you use actions in your runbook's workflow that return output that you want to use in subsequent actions. It's important to make sure your input values are correct to avoid errors in your runbook's workflow. Input values are also important because they determine whether the action returns the expected output. For example, when using the `aws:executeAwsApi` action, you want to make sure that you're providing the right value for the API operation.

## Define output data for an action
<a name="defining-output"></a>

Some automation actions return output after performing their defined operations. Actions that return output either have predefined outputs, or allow you to define the outputs yourself. For example, the `aws:createImage` action has predefined outputs that return an `ImageId` and `ImageState`. Comparatively, with the `aws:executeAwsApi` action, you can define the outputs you that want from the specified API operation. As a result, you can return one or more values from a single API operation to use in subsequent actions.

Defining your own outputs for an automation action requires that you specify a name of the output, the data type, and the output value. To continue using the `aws:executeAwsApi` action as an example, let's say you're calling the `DescribeInstances` API operation from Amazon EC2. In this example, you want to return, or output, the `State` of an Amazon EC2 instance and branch your runbook's workflow based on the output. You choose to name the output **InstanceState**, and use the **String** data type. 

The process to define the actual value of the output differs, depending on the action. For example, if you're using the `aws:executeScript` action, you must use `return` statements in your functions to provide data to your outputs. With other actions like `aws:executeAwsApi`, `aws:waitForAwsResourceProperty`, and `aws:assertAwsResourceProperty`, a `Selector` is required. The `Selector`, or `PropertySelector` as some actions refer to it, is a JSONPath string that is used to process the JSON response from an API operation. It's important to understand how the JSON response object from an API operation is structured so you can select the correct value for your output. Using the `DescribeInstances` API operation mentioned earlier, see the following example JSON response:

```
{
  "reservationSet": {
    "item": {
      "reservationId": "r-1234567890abcdef0",
      "ownerId": 123456789012,
      "groupSet": "",
      "instancesSet": {
        "item": {
          "instanceId": "i-1234567890abcdef0",
          "imageId": "ami-bff32ccc",
          "instanceState": {
            "code": 16,
            "name": "running"
          },
          "privateDnsName": "ip-192-168-1-88.eu-west-1.compute.internal",
          "dnsName": "ec2-54-194-252-215.eu-west-1.compute.amazonaws.com",
          "reason": "",
          "keyName": "my_keypair",
          "amiLaunchIndex": 0,
          "productCodes": "",
          "instanceType": "t2.micro",
          "launchTime": "2018-05-08T16:46:19.000Z",
          "placement": {
            "availabilityZone": "eu-west-1c",
            "groupName": "",
            "tenancy": "default"
          },
          "monitoring": {
            "state": "disabled"
          },
          "subnetId": "subnet-56f5f000",
          "vpcId": "vpc-11112222",
          "privateIpAddress": "192.168.1.88",
          "ipAddress": "54.194.252.215",
          "sourceDestCheck": true,
          "groupSet": {
            "item": {
              "groupId": "sg-e4076000",
              "groupName": "SecurityGroup1"
            }
          },
          "architecture": "x86_64",
          "rootDeviceType": "ebs",
          "rootDeviceName": "/dev/xvda",
          "blockDeviceMapping": {
            "item": {
              "deviceName": "/dev/xvda",
              "ebs": {
                "volumeId": "vol-1234567890abcdef0",
                "status": "attached",
                "attachTime": "2015-12-22T10:44:09.000Z",
                "deleteOnTermination": true
              }
            }
          },
          "virtualizationType": "hvm",
          "clientToken": "xMcwG14507example",
          "tagSet": {
            "item": {
              "key": "Name",
              "value": "Server_1"
            }
          },
          "hypervisor": "xen",
          "networkInterfaceSet": {
            "item": {
              "networkInterfaceId": "eni-551ba000",
              "subnetId": "subnet-56f5f000",
              "vpcId": "vpc-11112222",
              "description": "Primary network interface",
              "ownerId": 123456789012,
              "status": "in-use",
              "macAddress": "02:dd:2c:5e:01:69",
              "privateIpAddress": "192.168.1.88",
              "privateDnsName": "ip-192-168-1-88.eu-west-1.compute.internal",
              "sourceDestCheck": true,
              "groupSet": {
                "item": {
                  "groupId": "sg-e4076000",
                  "groupName": "SecurityGroup1"
                }
              },
              "attachment": {
                "attachmentId": "eni-attach-39697adc",
                "deviceIndex": 0,
                "status": "attached",
                "attachTime": "2018-05-08T16:46:19.000Z",
                "deleteOnTermination": true
              },
              "association": {
                "publicIp": "54.194.252.215",
                "publicDnsName": "ec2-54-194-252-215.eu-west-1.compute.amazonaws.com",
                "ipOwnerId": "amazon"
              },
              "privateIpAddressesSet": {
                "item": {
                  "privateIpAddress": "192.168.1.88",
                  "privateDnsName": "ip-192-168-1-88.eu-west-1.compute.internal",
                  "primary": true,
                  "association": {
                    "publicIp": "54.194.252.215",
                    "publicDnsName": "ec2-54-194-252-215.eu-west-1.compute.amazonaws.com",
                    "ipOwnerId": "amazon"
                  }
                }
              },
              "ipv6AddressesSet": {
                "item": {
                  "ipv6Address": "2001:db8:1234:1a2b::123"
                }
              }
            }
          },
          "iamInstanceProfile": {
            "arn": "arn:aws:iam::123456789012:instance-profile/AdminRole",
            "id": "ABCAJEDNCAA64SSD123AB"
          },
          "ebsOptimized": false,
          "cpuOptions": {
            "coreCount": 1,
            "threadsPerCore": 1
          }
        }
      }
    }
  }
}
```

In the JSON response object, the instance `State` is nested in an `Instances` object, which is nested in the `Reservations` object. To return the value of the instance `State`, use the following string for the `Selector` so the value can be used in our output: **\$1.Reservations[0].Instances[0].State.Name**.

To reference an output value in subsequent actions of your runbook's workflow, the following format is used: `{{ StepName.NameOfOutput }}`. For example, **\$1\$1 GetInstanceState.InstanceState \$1\$1**. In the visual design experience, you can choose output values to use in subsequent actions using the dropdown for the input. When using outputs in subsequent actions, the data type of the output must match the data type for the input. In this example, the `InstanceState` output is a `String`. Therefore, to use the value in a subsequent action's input, the input must accept a `String`.

# Error handling with the visual design experience
<a name="visual-designer-error-handling"></a>

By default, when an action reports an error, Automation stops the runbook's workflow entirely. This is because the default value for the `onFailure` property on all actions is `Abort`. You can configure how Automation handles errors in your runbook's workflow. Even if you have configured error handling, some errors might still cause an automation to fail. For more information, see [Troubleshooting Systems Manager Automation](automation-troubleshooting.md). In the visual design experience, you configure error handling in the **Configuration** panel.

![\[Error handling options\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_error_handling.png)


## Retry action on error
<a name="retry-actions"></a>

To retry an action in case of an error, specify a value for the **Max attempts** property. The default value is 1. If you specify a value greater than 1, the action isn't considered to have failed until all of the retry attempts have failed.

## Timeouts
<a name="timeout-seconds"></a>

You can configure a timeout for actions to set the maximum number of seconds your action can run before it fails. To configure a timeout, enter the number of seconds that your action should wait before the action fails in the **Timeout seconds** property. If the timeout is reached and the action has a value of `Max attempts` that is greater than 1, the step isn't considered to have timed out until the retries complete.

## Failed actions
<a name="failure-actions"></a>

By default, when an action fails, Automation stops the runbook's workflow entirely. You can modify this behavior by specifying an alternative value for the **On failure** property of the actions in your runbook. If you want the workflow to continue to the next step in the runbook, choose **Continue**. If you want the workflow to jump to a different subsequent step in the runbook, choose **Step** and then enter the name of the step.

## Canceled actions
<a name="cancel-actions"></a>

By default, when an action is canceled by a user, Automation stops the runbook's workflow entirely. You can modify this behavior by specifying an alternative value for the **On cancel** property of the actions in your runbook. If you want the workflow to jump to a different subsequent step in the runbook, choose **Step** and then enter the name of the step.

## Critical actions
<a name="critical-actions"></a>

You can designate an action as *critical*, meaning it determines the overall reporting status of your automation. If a step with this designation fails, Automation reports the final status as `Failed` regardless of the success of other actions. To configure an action as critical, leave the default value as **True** for the **Is critical** property.

## Ending actions
<a name="end-actions"></a>

The **Is end** property stops an automation at the end of the specified action. The default value for this property is `false`. If you configure this property for an action, the automation stops whether the action succeeds or fails. This property is most often used with `aws:branch` actions to handle unexpected or undefined input values. The following example shows a runbook that is expecting an instance state of either `running`, `stopping`, or `stopped`. If an instance is in a different state, the automation ends.

![\[Visual design experience is end example\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_is_end_example.png)


# Tutorial: Create a runbook using the visual design experience
<a name="visual-designer-tutorial"></a>

In this tutorial, you will learn the basics of working with the visual design experience provided by Systems Manager Automation. In the visual design experience, you can create a runbook that uses multiple actions. You use the drag and drop feature to arrange actions on the canvas. You also search for, select, and configure these actions. Then, you can view the auto-generated YAML code for your runbook's workflow, exit the visual design experience, run the runbook, and review the execution details.

This tutorial also shows you how to update the runbook and view the new version. At the end of the tutorial, you perform a clean-up step and delete your runbook.

After you complete this tutorial, you'll know how to use the visual design experience to create a runbook. You'll also know how to update, run, and delete your runbook.

**Note**  
Before you start this tutorial, make sure to complete [Setting up Automation](automation-setup.md).

**Topics**
+ [Step 1: Navigate to the visual design experience](#navigate-console)
+ [Step 2: Create a workflow](#create-workflow)
+ [Step 3: Review the auto-generated code](#view-generated-code)
+ [Step 4: Run your new runbook](#use-tutorial-runbook)
+ [Step 5: Clean up](#cleanup-tutorial-runbook)

## Step 1: Navigate to the visual design experience
<a name="navigate-console"></a>

1. Sign in to the [Systems Manager Automation console](https://console.aws.amazon.com/systems-manager/automation/home?region=us-east-1#/).

1. Choose **Create automation runbook**.

## Step 2: Create a workflow
<a name="create-workflow"></a>

In the visual design experience, a workflow is a graphical representation of your runbook on the canvas. You can use the visual design experience to define, configure, and examine the individual actions of your runbook.

**To create a workflow**

1. Next to the **Design** and **Code** toggle, select the pencil icon and enter a name for your runbook. For this tutorial, enter **VisualDesignExperienceTutorial**.  
![\[Visual design experience name your runbook\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_tutorial_name.png)

1. In the **Document attributes** section of the **Form** panel, expand the **Input parameters** dropdown, and select **Add a parameter**.

   1. In the **Parameter name** field, enter **InstanceId**.

   1. In the **Type** dropdown, choose **AWS::EC2::Instance**.

   1. Select the **Required** toggle.  
![\[Create a parameter for your runbook\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_actions_tutorial_parameter.png)

1. In the **AWS APIs** browser, enter **DescribeInstances** in the search bar.

1. Drag an **Amazon EC2 – DescribeInstances** action to the empty canvas.

1. For **Step name**, enter a value. For this tutorial, you can use the name **GetInstanceState**.  
![\[Choose an Amazon EC2 describe instances API action.\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_tutorial_api_action.png)

   1. Expand the **Additional inputs** dropdown, and in the **Input name** field, enter **InstanceIds**.

   1. Choose the **Inputs** tab.

   1. In the **Input value** field, choose the **InstanceId** document input. This references the value of the input parameter that you created at the beginning of the procedure. Since the **InstanceIds** input for the `DescribeInstances` action accepts `StringList` values, you must wrap the **InstanceId** input in square brackets. The YAML for the **Input value** should match the following: **['\$1\$1 InstanceId \$1\$1']**.

   1. In the **Outputs** tab, select **Add an output** and enter **InstanceState** in the **Name** field.

   1. In the **Selector** field, enter **\$1.Reservations[0].Instances[0].State.Name**.

   1. In the **Type** dropdown, choose **String**.

1. Drag a **Branch** action from the **Actions** browser, and drop it below the **`GetInstanceState`** step. 

1. For **Step name**, enter a value. For this tutorial, use the name `BranchOnInstanceState`.

   To define the branching logic, do the following:

   1. Choose the **`Branch`** state on the canvas. Then, under **Inputs** and **Choices**, select the pencil icon to edit **Rule \$11**.

   1. Choose **Add conditions**.

   1. In the **Conditions for rule \$11** dialog box, choose the **GetInstanceState.InstanceState** step output from the **Variable** dropdown.

   1. For **Operator**, choose **is equal to**.

   1. For **Value**, choose **String** from the dropdown list. Enter **stopped**.  
![\[Define a condition for a branch action.\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_tutorial_condition.png)

   1. Select **Save conditions**.

   1. Choose **Add new choice rule**.

   1. Choose **Add conditions** for **Rule \$12**.

   1. In the **Conditions for rule \$12** dialog box, choose the **GetInstanceState.InstanceState** step output from the **Variable** dropdown.

   1. For **Operator**, choose **is equal to**.

   1. For **Value**, choose **String** from the dropdown list. Enter **stopping**.

   1. Select **Save conditions**.

   1. Choose **Add new choice rule**.

   1. For **Rule \$13**, choose **Add conditions**.

   1. In the **Conditions for rule \$13** dialog box, choose the **GetInstanceState.InstanceState** step output from the **Variable** dropdown.

   1. For **Operator**, choose **is equal to**.

   1. For **Value**, choose **String** from the dropdown list. Enter **running**.

   1. Select **Save conditions**.

   1. In the **Default rule**, choose **Go to end** for the **Default step**.

1. Drag a **Change an instance state** action to the empty **Drag action here** box under the **\$1\$1 GetInstanceState.InstanceState \$1\$1 == "stopped"** condition.

   1. For the **Step name**, enter **StartInstance**.

   1. In the **Inputs** tab, under **Instance IDs**, choose the **InstanceId** document input value from the dropdown.

   1. For the **Desired state**, specify **`running`**.

1. Drag a **Wait on AWS resource** action to the empty **Drag action here** box under the **\$1\$1 GetInstanceState.InstanceState \$1\$1 == "stopping"** condition.

1. For **Step name**, enter a value. For this tutorial, use the name `WaitForInstanceStop`.

   1. For the **Service** field, choose **Amazon EC2**.

   1. For the **API** field, choose **DescribeInstances**.

   1. For the **Property selector** field, enter **\$1.Reservations[0].Instances[0].State.Name**.

   1. For the **Desired values** parameter, enter **`["stopped"]`**.

   1. In the **Configuration** tab of the **WaitForInstanceStop** action, choose **StartInstance** from the **Next step** dropdown.

1. Drag a **Run command on instances** action to the empty **Drag action here** box under the **\$1\$1 GetInstanceState.InstanceState \$1\$1 == "running"** condition.

1. For the **Step name**, enter **SayHello**.

   1. In the **Inputs** tab, enter **AWS-RunShellScript** for the **Document name** parameter.

   1. For **InstanceIds**, choose the **InstanceId** document input value from the dropdown.

   1. Expand the **Additional inputs** dropdown, and in the **Input name** dropdown, choose **Parameters**.

   1. In the **Input value** field, enter **`{"commands": "echo 'Hello World'"}`**.

1. Review the completed runbook in the canvas and select **Create runbook** to save the tutorial runbook.  
![\[Review and create the runbook.\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/visual_designer_tutorial_complete.png)

## Step 3: Review the auto-generated code
<a name="view-generated-code"></a>

As you drag and drop actions from the **Actions** browser onto the canvas, the visual design experience automatically composes the YAML or JSON content of your runbook in real-time. You can view and edit this code. To view the auto-generated code, select **Code** for the **Design** and **Code** toggle.

## Step 4: Run your new runbook
<a name="use-tutorial-runbook"></a>

After creating your runbook, you can run the automation.

**To run your new automation runbook**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Automation document** list, choose a runbook. Choose one or more options in the **Document categories** pane to filter SSM documents according to their purpose. To view a runbook that you own, choose the **Owned by me** tab. To view a runbook that is shared with your account, choose the **Shared with me** tab. To view all runbooks, choose the **All documents** tab.
**Note**  
You can view information about a runbook by choosing the runbook name.

1. In the **Document details** section, verify that **Document version** is set to the version that you want to run. The system includes the following version options: 
   + **Default version at runtime** – Choose this option if the Automation runbook is updated periodically and a new default version is assigned.
   + **Latest version at runtime** – Choose this option if the Automation runbook is updated periodically, and you want to run the version that was most recently updated.
   + **1 (Default)** – Choose this option to run the first version of the document, which is the default.

1. Choose **Next**.

1. In the **Execute automation runbook** section, choose **Simple execution**.

1. In the **Input parameters** section, specify the required inputs. Optionally, you can choose an IAM service role from the **AutomationAssumeRole** list.

1. (Optional) Choose an Amazon CloudWatch alarm to apply to your automation for monitoring. To attach a CloudWatch alarm to your automation, the IAM principal that starts the automation must have permission for the `iam:createServiceLinkedRole` action. For more information about CloudWatch alarms, see [Using Amazon CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html). If your alarm activates, the automation is stopped. If you use AWS CloudTrail, you will see the API call in your trail. 

1. Choose **Execute**. 

## Step 5: Clean up
<a name="cleanup-tutorial-runbook"></a>

**To delete your runbook**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Documents**.

1. Select the **Owned by me** tab.

1. Locate the **VisualDesignExperienceTutorial** runbook.

1. Select the button on the document card page, and then choose **Delete document** from the **Actions** dropdown.

# Authoring Automation runbooks
<a name="automation-authoring-runbooks"></a>

Each runbook in Automation, a tool in AWS Systems Manager, defines an automation. Automation runbooks define the actions that are performed during an automation. In the runbook content, you define the input parameters, outputs, and actions that Systems Manager performs on your managed instances and AWS resources. 

Automation includes several pre-defined runbooks that you can use to perform common tasks like restarting one or more Amazon Elastic Compute Cloud (Amazon EC2) instances or creating an Amazon Machine Image (AMI). However, your use cases might extend beyond the capabilities of the pre-defined runbooks. If this is the case, you can create your own runbooks and modify them to your needs.

A runbook consists of automation actions, parameters for those actions, and input parameters that you specify. A runbook's content is written in either YAML or JSON. If you're not familiar with either YAML or JSON, we recommend using the visual designer, or learning more about either markup language before attempting to author your own runbook. For more information about the visual designer, see [Visual design experience for Automation runbooks](automation-visual-designer.md).

The following sections will help you author your first runbook.

## Identify your use case
<a name="automation-authoring-runbooks-use-case"></a>

The first step in authoring a runbook is identifying your use case. For example, you scheduled the `AWS-CreateImage` runbook to run daily on all of your production Amazon EC2 instances. At the end of the month, you decide you have more images than are necessary for recovery points. Going forward, you want to automatically delete the oldest AMI of an Amazon EC2 instance when a new AMI is created. To accomplish this, you create a new runbook that does the following:

1. Runs the `aws:createImage` action and specifies the instance ID in the image description.

1. Runs the `aws:waitForAwsResourceProperty` action to poll the state of the image until it's `available`.

1. After the image state is `available`, the `aws:executeScript` action runs a custom Python script that gathers the IDs of all images associated with your Amazon EC2 instance. The script does this by filtering, using the instance ID in the image description you specified at creation. Then, the script sorts the list of image IDs based on the `creationDate` of the image and outputs the ID of the oldest AMI.

1. Lastly, the `aws:deleteImage` action runs to delete the oldest AMI using the ID from the output of the previous step.

In this scenario, you were already using the `AWS-CreateImage` runbook but found that your use case required greater flexibility. This is a common situation because there can be overlap between runbooks and automation actions. As a result, you might have to adjust which runbooks or actions you use to address your use case.

For example, the `aws:executeScript` and `aws:invokeLambdaFunction` actions both allow you to run custom scripts as part of your automation. To choose between them, you might prefer `aws:invokeLambdaFunction` because of the additional supported runtime languages. However, you might prefer `aws:executeScript` because it allows you to author your script content directly in YAML runbooks and provide script content as attachments for JSON runbooks. You might also consider `aws:executeScript` to be simpler in terms of AWS Identity and Access Management (IAM) setup. Because it uses the permissions provided in the `AutomationAssumeRole`, `aws:executeScript` doesn't require an additional AWS Lambda function execution role.

In any given scenario, one action might provide more flexibility, or added functionality, over another. Therefore, we recommend that you review the available input parameters for the runbook or action you want to use to determine which best fits your use case and preferences.

## Set up your development environment
<a name="automation-authoring-runbooks-environment"></a>

After you've identified your use case and the pre-defined runbooks or automation actions you want to use in your runbook, it's time to set up your development environment for the content of your runbook. To develop your runbook content, we recommend using the AWS Toolkit for Visual Studio Code instead of the Systems Manager Documents console. 

The Toolkit for VS Code is an open-source extension for Visual Studio Code (VS Code) that offers more features than the Systems Manager Documents console. Helpful features include schema validation for both YAML and JSON, snippets for automation action types, and auto-complete support for various options in both YAML and JSON. 

For more information about installing the Toolkit for VS Code, see [Installing the AWS Toolkit for Visual Studio Code](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html). For more information about using the Toolkit for VS Code to develop runbooks, see [Working with Systems Manager Automation documents](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/systems-manager-automation-docs.html) in the *AWS Toolkit for Visual Studio Code User Guide*.

## Develop runbook content
<a name="automation-authoring-runbooks-developing-content"></a>

With your use case identified and environment set up, you're ready to develop the content for your runbook. Your use case and preferences will largely dictate the automation actions or runbooks you use in your runbook content. Some actions support only a subset of input parameters when compared to another action that allows you to accomplish a similar task. Other actions have specific outputs, such as `aws:createImage`, where some actions allow you to define your own outputs, such as `aws:executeAwsApi`. 

If you're unsure how to use a particular action in your runbook, we recommend reviewing the corresponding entry for the action in the [Systems Manager Automation actions reference](automation-actions.md). We also recommend reviewing the content of pre-defined runbooks to see real-world examples of how these actions are used. For more examples of real-world applications of runbooks, see [Additional runbook examples](automation-document-examples.md).

To demonstrate the differences in simplicity and flexibility that runbook content provides, the following tutorials provide an example of how to patch groups of Amazon EC2 instances in stages:
+ [Example 1: Creating parent-child runbooks](automation-authoring-runbooks-parent-child-example.md) – In this example, two runbooks are used in a parent-child relationship. The parent runbook initiates a rate control automation of the child runbook. 
+ [Example 2: Scripted runbook](automation-authoring-runbooks-scripted-example.md) – This example demonstrates how you can accomplish the same tasks of Example 1 by condensing the content into a single runbook and using scripts in your runbook.

# Example 1: Creating parent-child runbooks
<a name="automation-authoring-runbooks-parent-child-example"></a>

The following example demonstrates how to create two runbooks that patch tagged groups of Amazon Elastic Compute Cloud (Amazon EC2) instances in stages. These runbooks are used in a parent-child relationship with the parent runbook used to initiate a rate control automation of the child runbook. For more information about rate control automations, see [Run automated operations at scale](running-automations-scale.md). For more information about the automation actions used in this example, see the [Systems Manager Automation actions reference](automation-actions.md).

## Create the child runbook
<a name="automation-authoring-runbooks-child-runbook"></a>

This example runbook addresses the following scenario. Emily is a Systems Engineer at AnyCompany Consultants, LLC. She needs to configure patching for groups of Amazon Elastic Compute Cloud (Amazon EC2) instances that host primary and secondary databases. Applications access these databases 24 hours a day, so one of the database instances must always be available. 

She decides that patching the instances in stages is the best approach. The primary group of database instances will be patched first, followed by the secondary group of database instances. Also, to avoid incurring additional costs by leaving instances running that were previously stopped, Emily wants the patched instances to be returned to their original state before the patching occurred. 

Emily identifies the primary and secondary groups of database instances by the tags associated with the instances. She decides to create a parent runbook that starts a rate control automation of a child runbook. By doing that, she can target the tags associated with the primary and secondary groups of database instances and manage the concurrency of the child automations. After reviewing the available Systems Manager (SSM) documents for patching, she chooses the `AWS-RunPatchBaseline` document. By using this SSM document, her colleagues can review the associated patch compliance information after the patching operation completes.

To start creating her runbook content, Emily reviews the available automation actions and begins authoring the content for the child runbook as follows:

1. First, she provides values for the schema and description of the runbook, and defines the input parameters for the child runbook.

   By using the `AutomationAssumeRole` parameter, Emily and her colleagues can use an existing IAM role that allows Automation to perform the actions in the runbook on their behalf. Emily uses the `InstanceId` parameter to determine the instance that should be patched. Optionally, the `Operation`, `RebootOption`, and `SnapshotId` parameters can be used to provide values to document parameters for `AWS-RunPatchBaseline`. To prevent invalid values from being provided to those document parameters, she defines the `allowedValues` as needed.

------
#### [ YAML ]

   ```
   schemaVersion: '0.3'
   description: 'An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.'
   assumeRole: '{{AutomationAssumeRole}}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: >-
         '(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the
         actions on your behalf. If no role is specified, Systems Manager
         Automation uses your IAM permissions to operate this runbook.'
       default: ''
     InstanceId:
       type: String
       description: >-
         '(Required) The instance you want to patch.'
     SnapshotId:
       type: String
       description: '(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.'
       default: ''
     RebootOption:
       type: String
       description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.'
       allowedValues:
         - NoReboot
         - RebootIfNeeded
       default: RebootIfNeeded
     Operation:
       type: String
       description: '(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.'
       allowedValues:
         - Install
         - Scan
       default: Install
   ```

------
#### [ JSON ]

   ```
   {
      "schemaVersion":"0.3",
      "description":"An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.",
      "assumeRole":"{{AutomationAssumeRole}}",
      "parameters":{
         "AutomationAssumeRole":{
            "type":"String",
            "description":"(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.",
            "default":""
         },
         "InstanceId":{
            "type":"String",
            "description":"(Required) The instance you want to patch."
         },
         "SnapshotId":{
            "type":"String",
            "description":"(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.",
            "default":""
         },
         "RebootOption":{
            "type":"String",
            "description":"(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.",
            "allowedValues":[
               "NoReboot",
               "RebootIfNeeded"
            ],
            "default":"RebootIfNeeded"
         },
         "Operation":{
            "type":"String",
            "description":"(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.",
            "allowedValues":[
               "Install",
               "Scan"
            ],
            "default":"Install"
         }
      }
   },
   ```

------

1. With the top-level elements defined, Emily proceeds with authoring the actions that make up the `mainSteps` of the runbook. The first step outputs the current state of the target instance specified in the `InstanceId` input parameter using the `aws:executeAwsApi` action. The output of this action is used in later actions.

------
#### [ YAML ]

   ```
   mainSteps:
     - name: getInstanceState
       action: 'aws:executeAwsApi'
       onFailure: Abort
       inputs:
         inputs:
         Service: ec2
         Api: DescribeInstances
         InstanceIds:
           - '{{InstanceId}}'
       outputs:
         - Name: instanceState
           Selector: '$.Reservations[0].Instances[0].State.Name'
           Type: String
       nextStep: branchOnInstanceState
   ```

------
#### [ JSON ]

   ```
   "mainSteps":[
         {
            "name":"getInstanceState",
            "action":"aws:executeAwsApi",
            "onFailure":"Abort",
            "inputs":{
               "inputs":null,
               "Service":"ec2",
               "Api":"DescribeInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ]
            },
            "outputs":[
               {
                  "Name":"instanceState",
                  "Selector":"$.Reservations[0].Instances[0].State.Name",
                  "Type":"String"
               }
            ],
            "nextStep":"branchOnInstanceState"
         },
   ```

------

1. Rather than manually starting and keeping track of the original state of every instance that needs to be patched, Emily uses the output from the previous action to branch the automation based on the state of the target instance. This allows the automation to run different steps depending on the conditions defined in the `aws:branch` action and improves the overall efficiency of the automation without manual intervention.

   If the instance state is already `running`, the automation proceeds with patching the instance with the `AWS-RunPatchBaseline` document using the `aws:runCommand` action.

   If the instance state is `stopping`, the automation polls for the instance to reach the `stopped` state using the `aws:waitForAwsResourceProperty` action, starts the instance using the `executeAwsApi` action, and polls for the instance to reach a `running` state before patching the instance.

   If the instance state is `stopped`, the automation starts the instance and polls for the instance to reach a `running` state before patching the instance using the same actions.

------
#### [ YAML ]

   ```
   - name: branchOnInstanceState
       action: 'aws:branch'
       onFailure: Abort
       inputs:
         Choices:
           - NextStep: startInstance
              Variable: '{{getInstanceState.instanceState}}'
              StringEquals: stopped
            - NextStep: verifyInstanceStopped
              Variable: '{{getInstanceState.instanceState}}'
              StringEquals: stopping
            - NextStep: patchInstance
              Variable: '{{getInstanceState.instanceState}}'
              StringEquals: running
       isEnd: true
     - name: startInstance
       action: 'aws:executeAwsApi'
       onFailure: Abort
       inputs:
         Service: ec2
         Api: StartInstances
         InstanceIds:
           - '{{InstanceId}}'
       nextStep: verifyInstanceRunning
     - name: verifyInstanceRunning
       action: 'aws:waitForAwsResourceProperty'
       timeoutSeconds: 120
       inputs:
         Service: ec2
         Api: DescribeInstances
         InstanceIds:
           - '{{InstanceId}}'
         PropertySelector: '$.Reservations[0].Instances[0].State.Name'
         DesiredValues:
           - running
       nextStep: patchInstance
     - name: verifyInstanceStopped
       action: 'aws:waitForAwsResourceProperty'
       timeoutSeconds: 120
       inputs:
         Service: ec2
         Api: DescribeInstances
         InstanceIds:
           - '{{InstanceId}}'
         PropertySelector: '$.Reservations[0].Instances[0].State.Name'
         DesiredValues:
           - stopped
         nextStep: startInstance
     - name: patchInstance
       action: 'aws:runCommand'
       onFailure: Abort
       timeoutSeconds: 5400
       inputs:
         DocumentName: 'AWS-RunPatchBaseline'
         InstanceIds: 
         - '{{InstanceId}}'
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
   ```

------
#### [ JSON ]

   ```
   {
            "name":"branchOnInstanceState",
            "action":"aws:branch",
            "onFailure":"Abort",
            "inputs":{
               "Choices":[
                  {
                     "NextStep":"startInstance",
                     "Variable":"{{getInstanceState.instanceState}}",
                     "StringEquals":"stopped"
                  },
                  {
                     "Or":[
                        {
                           "Variable":"{{getInstanceState.instanceState}}",
                           "StringEquals":"stopping"
                        }
                     ],
                     "NextStep":"verifyInstanceStopped"
                  },
                  {
                     "NextStep":"patchInstance",
                     "Variable":"{{getInstanceState.instanceState}}",
                     "StringEquals":"running"
                  }
               ]
            },
            "isEnd":true
         },
         {
            "name":"startInstance",
            "action":"aws:executeAwsApi",
            "onFailure":"Abort",
            "inputs":{
               "Service":"ec2",
               "Api":"StartInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ]
            },
            "nextStep":"verifyInstanceRunning"
         },
         {
            "name":"verifyInstanceRunning",
            "action":"aws:waitForAwsResourceProperty",
            "timeoutSeconds":120,
            "inputs":{
               "Service":"ec2",
               "Api":"DescribeInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ],
               "PropertySelector":"$.Reservations[0].Instances[0].State.Name",
               "DesiredValues":[
                  "running"
               ]
            },
            "nextStep":"patchInstance"
         },
         {
            "name":"verifyInstanceStopped",
            "action":"aws:waitForAwsResourceProperty",
            "timeoutSeconds":120,
            "inputs":{
               "Service":"ec2",
               "Api":"DescribeInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ],
               "PropertySelector":"$.Reservations[0].Instances[0].State.Name",
               "DesiredValues":[
                  "stopped"
               ],
               "nextStep":"startInstance"
            }
         },
         {
            "name":"patchInstance",
            "action":"aws:runCommand",
            "onFailure":"Abort",
            "timeoutSeconds":5400,
            "inputs":{
               "DocumentName":"AWS-RunPatchBaseline",
               "InstanceIds":[
                  "{{InstanceId}}"
               ],
               "Parameters":{
                  "SnapshotId":"{{SnapshotId}}",
                  "RebootOption":"{{RebootOption}}",
                  "Operation":"{{Operation}}"
               }
            }
         },
   ```

------

1. After the patching operation completes, Emily wants the automation to return the target instance to the same state it was in before the automation started. She does this by again using the output from the first action. The automation branches based on the original state of the target instance using the `aws:branch` action. If the instance was previously in any state other than `running`, the instance is stopped. Otherwise, if the instance state is `running`, the automation ends.

------
#### [ YAML ]

   ```
   - name: branchOnOriginalInstanceState
       action: 'aws:branch'
       onFailure: Abort
       inputs:
         Choices:
           - NextStep: stopInstance
             Not: 
               Variable: '{{getInstanceState.instanceState}}'
               StringEquals: running
       isEnd: true
     - name: stopInstance
       action: 'aws:executeAwsApi'
       onFailure: Abort
       inputs:
         Service: ec2
         Api: StopInstances
         InstanceIds:
           - '{{InstanceId}}'
   ```

------
#### [ JSON ]

   ```
   {
            "name":"branchOnOriginalInstanceState",
            "action":"aws:branch",
            "onFailure":"Abort",
            "inputs":{
               "Choices":[
                  {
                     "NextStep":"stopInstance",
                     "Not":{
                        "Variable":"{{getInstanceState.instanceState}}",
                        "StringEquals":"running"
                     }
                  }
               ]
            },
            "isEnd":true
         },
         {
            "name":"stopInstance",
            "action":"aws:executeAwsApi",
            "onFailure":"Abort",
            "inputs":{
               "Service":"ec2",
               "Api":"StopInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ]
            }
         }
      ]
   }
   ```

------

1. Emily reviews the completed child runbook content and creates the runbook in the same AWS account and AWS Region as the target instances. Now she's ready to continue with the creation of the parent runbook's content. The following is the completed child runbook content.

------
#### [ YAML ]

   ```
   schemaVersion: '0.3'
   description: 'An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.'
   assumeRole: '{{AutomationAssumeRole}}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: >-
         '(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the
         actions on your behalf. If no role is specified, Systems Manager
         Automation uses your IAM permissions to operate this runbook.'
       default: ''
     InstanceId:
       type: String
       description: >-
         '(Required) The instance you want to patch.'
     SnapshotId:
       type: String
       description: '(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.'
       default: ''
     RebootOption:
       type: String
       description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.'
       allowedValues:
         - NoReboot
         - RebootIfNeeded
       default: RebootIfNeeded
     Operation:
       type: String
       description: '(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.'
       allowedValues:
         - Install
         - Scan
       default: Install
   mainSteps:
     - name: getInstanceState
       action: 'aws:executeAwsApi'
       onFailure: Abort
       inputs:
         inputs:
         Service: ec2
         Api: DescribeInstances
         InstanceIds:
           - '{{InstanceId}}'
       outputs:
         - Name: instanceState
           Selector: '$.Reservations[0].Instances[0].State.Name'
           Type: String
       nextStep: branchOnInstanceState
     - name: branchOnInstanceState
       action: 'aws:branch'
       onFailure: Abort
       inputs:
         Choices:
           - NextStep: startInstance
             Variable: '{{getInstanceState.instanceState}}'
             StringEquals: stopped
           - Or:
               - Variable: '{{getInstanceState.instanceState}}'
                 StringEquals: stopping
             NextStep: verifyInstanceStopped
           - NextStep: patchInstance
             Variable: '{{getInstanceState.instanceState}}'
             StringEquals: running
       isEnd: true
     - name: startInstance
       action: 'aws:executeAwsApi'
       onFailure: Abort
       inputs:
         Service: ec2
         Api: StartInstances
         InstanceIds:
           - '{{InstanceId}}'
       nextStep: verifyInstanceRunning
     - name: verifyInstanceRunning
       action: 'aws:waitForAwsResourceProperty'
       timeoutSeconds: 120
       inputs:
         Service: ec2
         Api: DescribeInstances
         InstanceIds:
           - '{{InstanceId}}'
         PropertySelector: '$.Reservations[0].Instances[0].State.Name'
         DesiredValues:
           - running
       nextStep: patchInstance
     - name: verifyInstanceStopped
       action: 'aws:waitForAwsResourceProperty'
       timeoutSeconds: 120
       inputs:
         Service: ec2
         Api: DescribeInstances
         InstanceIds:
           - '{{InstanceId}}'
         PropertySelector: '$.Reservations[0].Instances[0].State.Name'
         DesiredValues:
           - stopped
         nextStep: startInstance
     - name: patchInstance
       action: 'aws:runCommand'
       onFailure: Abort
       timeoutSeconds: 5400
       inputs:
         DocumentName: 'AWS-RunPatchBaseline'
         InstanceIds: 
         - '{{InstanceId}}'
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
     - name: branchOnOriginalInstanceState
       action: 'aws:branch'
       onFailure: Abort
       inputs:
         Choices:
           - NextStep: stopInstance
             Not: 
               Variable: '{{getInstanceState.instanceState}}'
               StringEquals: running
       isEnd: true
     - name: stopInstance
       action: 'aws:executeAwsApi'
       onFailure: Abort
       inputs:
         Service: ec2
         Api: StopInstances
         InstanceIds:
           - '{{InstanceId}}'
   ```

------
#### [ JSON ]

   ```
   {
      "schemaVersion":"0.3",
      "description":"An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.",
      "assumeRole":"{{AutomationAssumeRole}}",
      "parameters":{
         "AutomationAssumeRole":{
            "type":"String",
            "description":"'(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.'",
            "default":""
         },
         "InstanceId":{
            "type":"String",
            "description":"'(Required) The instance you want to patch.'"
         },
         "SnapshotId":{
            "type":"String",
            "description":"(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.",
            "default":""
         },
         "RebootOption":{
            "type":"String",
            "description":"(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.",
            "allowedValues":[
               "NoReboot",
               "RebootIfNeeded"
            ],
            "default":"RebootIfNeeded"
         },
         "Operation":{
            "type":"String",
            "description":"(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.",
            "allowedValues":[
               "Install",
               "Scan"
            ],
            "default":"Install"
         }
      },
      "mainSteps":[
         {
            "name":"getInstanceState",
            "action":"aws:executeAwsApi",
            "onFailure":"Abort",
            "inputs":{
               "inputs":null,
               "Service":"ec2",
               "Api":"DescribeInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ]
            },
            "outputs":[
               {
                  "Name":"instanceState",
                  "Selector":"$.Reservations[0].Instances[0].State.Name",
                  "Type":"String"
               }
            ],
            "nextStep":"branchOnInstanceState"
         },
         {
            "name":"branchOnInstanceState",
            "action":"aws:branch",
            "onFailure":"Abort",
            "inputs":{
               "Choices":[
                  {
                     "NextStep":"startInstance",
                     "Variable":"{{getInstanceState.instanceState}}",
                     "StringEquals":"stopped"
                  },
                  {
                     "Or":[
                        {
                           "Variable":"{{getInstanceState.instanceState}}",
                           "StringEquals":"stopping"
                        }
                     ],
                     "NextStep":"verifyInstanceStopped"
                  },
                  {
                     "NextStep":"patchInstance",
                     "Variable":"{{getInstanceState.instanceState}}",
                     "StringEquals":"running"
                  }
               ]
            },
            "isEnd":true
         },
         {
            "name":"startInstance",
            "action":"aws:executeAwsApi",
            "onFailure":"Abort",
            "inputs":{
               "Service":"ec2",
               "Api":"StartInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ]
            },
            "nextStep":"verifyInstanceRunning"
         },
         {
            "name":"verifyInstanceRunning",
            "action":"aws:waitForAwsResourceProperty",
            "timeoutSeconds":120,
            "inputs":{
               "Service":"ec2",
               "Api":"DescribeInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ],
               "PropertySelector":"$.Reservations[0].Instances[0].State.Name",
               "DesiredValues":[
                  "running"
               ]
            },
            "nextStep":"patchInstance"
         },
         {
            "name":"verifyInstanceStopped",
            "action":"aws:waitForAwsResourceProperty",
            "timeoutSeconds":120,
            "inputs":{
               "Service":"ec2",
               "Api":"DescribeInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ],
               "PropertySelector":"$.Reservations[0].Instances[0].State.Name",
               "DesiredValues":[
                  "stopped"
               ],
               "nextStep":"startInstance"
            }
         },
         {
            "name":"patchInstance",
            "action":"aws:runCommand",
            "onFailure":"Abort",
            "timeoutSeconds":5400,
            "inputs":{
               "DocumentName":"AWS-RunPatchBaseline",
               "InstanceIds":[
                  "{{InstanceId}}"
               ],
               "Parameters":{
                  "SnapshotId":"{{SnapshotId}}",
                  "RebootOption":"{{RebootOption}}",
                  "Operation":"{{Operation}}"
               }
            }
         },
         {
            "name":"branchOnOriginalInstanceState",
            "action":"aws:branch",
            "onFailure":"Abort",
            "inputs":{
               "Choices":[
                  {
                     "NextStep":"stopInstance",
                     "Not":{
                        "Variable":"{{getInstanceState.instanceState}}",
                        "StringEquals":"running"
                     }
                  }
               ]
            },
            "isEnd":true
         },
         {
            "name":"stopInstance",
            "action":"aws:executeAwsApi",
            "onFailure":"Abort",
            "inputs":{
               "Service":"ec2",
               "Api":"StopInstances",
               "InstanceIds":[
                  "{{InstanceId}}"
               ]
            }
         }
      ]
   }
   ```

------

For more information about the automation actions used in this example, see the [Systems Manager Automation actions reference](automation-actions.md).

## Create the parent runbook
<a name="automation-authoring-runbooks-parent-runbook"></a>

This example runbook continues the scenario described in the previous section. Now that Emily has created the child runbook, she begins authoring the content for the parent runbook as follows:

1. First, she provides values for the schema and description of the runbook, and defines the input parameters for the parent runbook.

   By using the `AutomationAssumeRole` parameter, Emily and her colleagues can use an existing IAM role that allows Automation to perform the actions in the runbook on their behalf. Emily uses the `PatchGroupPrimaryKey` and `PatchGroupPrimaryValue` parameters to specify the tag associated with the primary group of database instances that will be patched. She uses the `PatchGroupSecondaryKey` and `PatchGroupSecondaryValue` parameters to specify the tag associated with the secondary group of database instances that will be patched.

------
#### [ YAML ]

   ```
   description: 'An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.'
   schemaVersion: '0.3'
   assumeRole: '{{AutomationAssumeRole}}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: '(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.'
       default: ''
     PatchGroupPrimaryKey:
       type: String
       description: '(Required) The key of the tag for the primary group of instances you want to patch.''
     PatchGroupPrimaryValue:
       type: String
       description: '(Required) The value of the tag for the primary group of instances you want to patch.'
     PatchGroupSecondaryKey:
       type: String
       description: '(Required) The key of the tag for the secondary group of instances you want to patch.'
     PatchGroupSecondaryValue:
       type: String
       description: '(Required) The value of the tag for the secondary group of instances you want to patch.'
   ```

------
#### [ JSON ]

   ```
   {
      "schemaVersion": "0.3",
      "description": "An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.",
      "assumeRole": "{{AutomationAssumeRole}}",
      "parameters": {
         "AutomationAssumeRole": {
            "type": "String",
            "description": "(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.",
            "default": ""
         },
         "PatchGroupPrimaryKey": {
            "type": "String",
            "description": "(Required) The key of the tag for the primary group of instances you want to patch."
         },
         "PatchGroupPrimaryValue": {
            "type": "String",
            "description": "(Required) The value of the tag for the primary group of instances you want to patch."
         },
         "PatchGroupSecondaryKey": {
            "type": "String",
            "description": "(Required) The key of the tag for the secondary group of instances you want to patch."
         },
         "PatchGroupSecondaryValue": {
            "type": "String",
            "description": "(Required) The value of the tag for the secondary group of instances you want to patch."
         }
      }
   },
   ```

------

1. With the top-level elements defined, Emily proceeds with authoring the actions that make up the `mainSteps` of the runbook. 

   The first action starts a rate control automation using the child runbook she just created that targets instances associated with the tag specified in the `PatchGroupPrimaryKey` and `PatchGroupPrimaryValue` input parameters. She uses the values provided to the input parameters to specify the key and value of the tag associated with the primary group of database instances she wants to patch.

   After the first automation completes, the second action starts another rate control automation using the child runbook that targets instances associated with the tag specified in the `PatchGroupSecondaryKey` and `PatchGroupSecondaryValue` input parameters. She uses the values provided to the input parameters to specify the key and value of the tag associated with the secondary group of database instances she wants to patch.

------
#### [ YAML ]

   ```
   mainSteps:
     - name: patchPrimaryTargets
       action: 'aws:executeAutomation'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: RunbookTutorialChildAutomation
         Targets:
           - Key: 'tag:{{PatchGroupPrimaryKey}}'
             Values:
               - '{{PatchGroupPrimaryValue}}'
         TargetParameterName: 'InstanceId'
     - name: patchSecondaryTargets
       action: 'aws:executeAutomation'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: RunbookTutorialChildAutomation
         Targets:
           - Key: 'tag:{{PatchGroupSecondaryKey}}'
             Values:
               - '{{PatchGroupSecondaryValue}}'
         TargetParameterName: 'InstanceId'
   ```

------
#### [ JSON ]

   ```
   "mainSteps":[
         {
            "name":"patchPrimaryTargets",
            "action":"aws:executeAutomation",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"RunbookTutorialChildAutomation",
               "Targets":[
                  {
                     "Key":"tag:{{PatchGroupPrimaryKey}}",
                     "Values":[
                        "{{PatchGroupPrimaryValue}}"
                     ]
                  }
               ],
               "TargetParameterName":"InstanceId"
            }
         },
         {
            "name":"patchSecondaryTargets",
            "action":"aws:executeAutomation",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"RunbookTutorialChildAutomation",
               "Targets":[
                  {
                     "Key":"tag:{{PatchGroupSecondaryKey}}",
                     "Values":[
                        "{{PatchGroupSecondaryValue}}"
                     ]
                  }
               ],
               "TargetParameterName":"InstanceId"
            }
         }
      ]
   }
   ```

------

1. Emily reviews the completed parent runbook content and creates the runbook in the same AWS account and AWS Region as the target instances. Now, she is ready to test her runbooks to make sure the automation operates as desired before implementing them into her production environment. The following is the completed parent runbook content.

------
#### [ YAML ]

   ```
   description: An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.
   schemaVersion: '0.3'
   assumeRole: '{{AutomationAssumeRole}}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: '(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.'
       default: ''
     PatchGroupPrimaryKey:
       type: String
       description: (Required) The key of the tag for the primary group of instances you want to patch.
     PatchGroupPrimaryValue:
       type: String
       description: '(Required) The value of the tag for the primary group of instances you want to patch. '
     PatchGroupSecondaryKey:
       type: String
       description: (Required) The key of the tag for the secondary group of instances you want to patch.
     PatchGroupSecondaryValue:
       type: String
       description: '(Required) The value of the tag for the secondary group of instances you want to patch.  '
   mainSteps:
     - name: patchPrimaryTargets
       action: 'aws:executeAutomation'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: RunbookTutorialChildAutomation
         Targets:
           - Key: 'tag:{{PatchGroupPrimaryKey}}'
             Values:
               - '{{PatchGroupPrimaryValue}}'
         TargetParameterName: 'InstanceId'
     - name: patchSecondaryTargets
       action: 'aws:executeAutomation'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: RunbookTutorialChildAutomation
         Targets:
           - Key: 'tag:{{PatchGroupSecondaryKey}}'
             Values:
               - '{{PatchGroupSecondaryValue}}'
         TargetParameterName: 'InstanceId'
   ```

------
#### [ JSON ]

   ```
   {
      "description":"An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.",
      "schemaVersion":"0.3",
      "assumeRole":"{{AutomationAssumeRole}}",
      "parameters":{
         "AutomationAssumeRole":{
            "type":"String",
            "description":"(Optional) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.",
            "default":""
         },
         "PatchGroupPrimaryKey":{
            "type":"String",
            "description":"(Required) The key of the tag for the primary group of instances you want to patch."
         },
         "PatchGroupPrimaryValue":{
            "type":"String",
            "description":"(Required) The value of the tag for the primary group of instances you want to patch. "
         },
         "PatchGroupSecondaryKey":{
            "type":"String",
            "description":"(Required) The key of the tag for the secondary group of instances you want to patch."
         },
         "PatchGroupSecondaryValue":{
            "type":"String",
            "description":"(Required) The value of the tag for the secondary group of instances you want to patch.  "
         }
      },
      "mainSteps":[
         {
            "name":"patchPrimaryTargets",
            "action":"aws:executeAutomation",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"RunbookTutorialChildAutomation",
               "Targets":[
                  {
                     "Key":"tag:{{PatchGroupPrimaryKey}}",
                     "Values":[
                        "{{PatchGroupPrimaryValue}}"
                     ]
                  }
               ],
               "TargetParameterName":"InstanceId"
            }
         },
         {
            "name":"patchSecondaryTargets",
            "action":"aws:executeAutomation",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"RunbookTutorialChildAutomation",
               "Targets":[
                  {
                     "Key":"tag:{{PatchGroupSecondaryKey}}",
                     "Values":[
                        "{{PatchGroupSecondaryValue}}"
                     ]
                  }
               ],
               "TargetParameterName":"InstanceId"
            }
         }
      ]
   }
   ```

------

For more information about the automation actions used in this example, see the [Systems Manager Automation actions reference](automation-actions.md).

# Example 2: Scripted runbook
<a name="automation-authoring-runbooks-scripted-example"></a>

This example runbook addresses the following scenario. Emily is a Systems Engineer at AnyCompany Consultants, LLC. She previously created two runbooks that are used in a parent-child relationship to patch groups of Amazon Elastic Compute Cloud (Amazon EC2) instances that host primary and secondary databases. Applications access these databases 24 hours a day, so one of the database instances must always be available. 

Based on this requirement, she built a solution that patches the instances in stages using the `AWS-RunPatchBaseline` Systems Manager (SSM) document. By using this SSM document, her colleagues can review the associated patch compliance information after the patching operation completes. 

The primary group of database instances are patched first, followed by the secondary group of database instances. Also, to avoid incurring additional costs by leaving instances running that were previously stopped, Emily made sure that the automation returned the patched instances to their original state before the patching occurred. Emily used tags that are associated with the primary and secondary groups of database instances to identify which instances should be patched in her desired order.

Her existing automated solution works, but she wants to improve her solution if possible. To help with the maintenance of the runbook content and to ease troubleshooting efforts, she would like to condense the automation into a single runbook and simplify the number of input parameters. Also, she would like to avoid creating multiple child automations. 

After Emily reviews the available automation actions, she determines that she can improve her solution by using the `aws:executeScript` action to run her custom Python scripts. She now begins authoring the content for the runbook as follows:

1. First, she provides values for the schema and description of the runbook, and defines the input parameters for the parent runbook.

   By using the `AutomationAssumeRole` parameter, Emily and her colleagues can use an existing IAM role that allows Automation to perform the actions in the runbook on their behalf. Unlike [Example 1](automation-authoring-runbooks-parent-child-example.md), the `AutomationAssumeRole` parameter is now required rather than optional. Because this runbook includes `aws:executeScript` actions, an AWS Identity and Access Management (IAM) service role (or assume role) is always required. This requirement is necessary because some of the Python scripts specified for the actions call AWS API operations.

   Emily uses the `PrimaryPatchGroupTag` and `SecondaryPatchGroupTag` parameters to specify the tags associated with the primary and secondary group of database instances that will be patched. To simplify the required input parameters, she decides to use `StringMap` parameters rather than using multiple `String` parameters as she used in the Example 1 runbook. Optionally, the `Operation`, `RebootOption`, and `SnapshotId` parameters can be used to provide values to document parameters for `AWS-RunPatchBaseline`. To prevent invalid values from being provided to those document parameters, she defines the `allowedValues` as needed.

------
#### [ YAML ]

   ```
   description: 'An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.'
   schemaVersion: '0.3'
   assumeRole: '{{AutomationAssumeRole}}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: '(Required) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.'
     PrimaryPatchGroupTag:
       type: StringMap
       description: '(Required) The tag for the primary group of instances you want to patch. Specify a key-value pair. Example: {"key" : "value"}'
     SecondaryPatchGroupTag:
       type: StringMap
       description: '(Required) The tag for the secondary group of instances you want to patch. Specify a key-value pair. Example: {"key" : "value"}'
     SnapshotId:
       type: String
       description: '(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.'
       default: ''
     RebootOption:
       type: String
       description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.'
       allowedValues:
         - NoReboot
         - RebootIfNeeded
       default: RebootIfNeeded
     Operation:
       type: String
       description: '(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.'
       allowedValues:
         - Install
         - Scan
       default: Install
   ```

------
#### [ JSON ]

   ```
   {
      "description":"An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.",
      "schemaVersion":"0.3",
      "assumeRole":"{{AutomationAssumeRole}}",
      "parameters":{
         "AutomationAssumeRole":{
            "type":"String",
            "description":"(Required) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook."
         },
         "PrimaryPatchGroupTag":{
            "type":"StringMap",
            "description":"(Required) The tag for the primary group of instances you want to patch. Specify a key-value pair. Example: {\"key\" : \"value\"}"
         },
         "SecondaryPatchGroupTag":{
            "type":"StringMap",
            "description":"(Required) The tag for the secondary group of instances you want to patch. Specify a key-value pair. Example: {\"key\" : \"value\"}"
         },
         "SnapshotId":{
            "type":"String",
            "description":"(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.",
            "default":""
         },
         "RebootOption":{
            "type":"String",
            "description":"(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.",
            "allowedValues":[
               "NoReboot",
               "RebootIfNeeded"
            ],
            "default":"RebootIfNeeded"
         },
         "Operation":{
            "type":"String",
            "description":"(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.",
            "allowedValues":[
               "Install",
               "Scan"
            ],
            "default":"Install"
         }
      }
   },
   ```

------

1. With the top-level elements defined, Emily proceeds with authoring the actions that make up the `mainSteps` of the runbook. The first step gathers the IDs of all instances associated with the tag specified in the `PrimaryPatchGroupTag` parameter and outputs a `StringMap` parameter containing the instance ID and the current state of the instance. The output of this action is used in later actions. 

   Note that the `script` input parameter isn't supported for JSON runbooks. JSON runbooks must provide script content using the `attachment` input parameter.

------
#### [ YAML ]

   ```
   mainSteps:
     - name: getPrimaryInstanceState
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: getInstanceStates
         InputPayload:
           primaryTag: '{{PrimaryPatchGroupTag}}'
         Script: |-
           def getInstanceStates(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             tag = events['primaryTag']
             tagKey, tagValue = list(tag.items())[0]
             instanceQuery = ec2.describe_instances(
             Filters=[
                 {
                     "Name": "tag:" + tagKey,
                     "Values": [tagValue]
                 }]
             )
             if not instanceQuery['Reservations']:
                 noInstancesForTagString = "No instances found for specified tag."
                 return({ 'noInstancesFound' : noInstancesForTagString })
             else:
                 queryResponse = instanceQuery['Reservations']
                 originalInstanceStates = {}
                 for results in queryResponse:
                     instanceSet = results['Instances']
                     for instance in instanceSet:
                         instanceId = instance['InstanceId']
                         originalInstanceStates[instanceId] = instance['State']['Name']
                 return originalInstanceStates
       outputs:
         - Name: originalInstanceStates
           Selector: $.Payload
           Type: StringMap
       nextStep: verifyPrimaryInstancesRunning
   ```

------
#### [ JSON ]

   ```
   "mainSteps":[
         {
            "name":"getPrimaryInstanceState",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"getInstanceStates",
               "InputPayload":{
                  "primaryTag":"{{PrimaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"originalInstanceStates",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               }
            ],
            "nextStep":"verifyPrimaryInstancesRunning"
         },
   ```

------

1. Emily uses the output from the previous action in another `aws:executeScript` action to verify all instances associated with the tag specified in the `PrimaryPatchGroupTag` parameter are in a `running` state.

   If the instance state is already `running` or `shutting-down`, the script continues to loop through the remaining instances.

   If the instance state is `stopping`, the script polls for the instance to reach the `stopped` state and starts the instance.

   If the instance state is `stopped`, the script starts the instance.

------
#### [ YAML ]

   ```
   - name: verifyPrimaryInstancesRunning
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: verifyInstancesRunning
         InputPayload:
           targetInstances: '{{getPrimaryInstanceState.originalInstanceStates}}'
         Script: |-
           def verifyInstancesRunning(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped':
                   print("The target instance " + instance + " is stopped. The instance will now be started.")
                   ec2.start_instances(
                       InstanceIds=[instance]
                       )
               elif instanceDict[instance] == 'stopping':
                   print("The target instance " + instance + " is stopping. Polling for instance to reach stopped state.")
                   while instanceDict[instance] != 'stopped':
                       poll = ec2.get_waiter('instance_stopped')
                       poll.wait(
                           InstanceIds=[instance]
                       )
                   ec2.start_instances(
                       InstanceIds=[instance]
                   )
               else:
                 pass
       nextStep: waitForPrimaryRunningInstances
   ```

------
#### [ JSON ]

   ```
   {
            "name":"verifyPrimaryInstancesRunning",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"verifyInstancesRunning",
               "InputPayload":{
                  "targetInstances":"{{getPrimaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"waitForPrimaryRunningInstances"
         },
   ```

------

1. Emily verifies that all instances associated with the tag specified in the `PrimaryPatchGroupTag` parameter were started or already in a `running` state. Then she uses another script to verify that all instances, including those that were started in the previous action, have reached the `running` state.

------
#### [ YAML ]

   ```
   - name: waitForPrimaryRunningInstances
       action: 'aws:executeScript'
       timeoutSeconds: 300
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: waitForRunningInstances
         InputPayload:
           targetInstances: '{{getPrimaryInstanceState.originalInstanceStates}}'
         Script: |-
           def waitForRunningInstances(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
                 poll = ec2.get_waiter('instance_running')
                 poll.wait(
                     InstanceIds=[instance]
                 )
       nextStep: returnPrimaryTagKey
   ```

------
#### [ JSON ]

   ```
   {
            "name":"waitForPrimaryRunningInstances",
            "action":"aws:executeScript",
            "timeoutSeconds":300,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"waitForRunningInstances",
               "InputPayload":{
                  "targetInstances":"{{getPrimaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"returnPrimaryTagKey"
         },
   ```

------

1. Emily uses two more scripts to return individual `String` values of the key and value of the tag specified in the `PrimaryPatchGroupTag` parameter. The values returned by these actions allows her to provide values directly to the `Targets` parameter for the `AWS-RunPatchBaseline` document. The automation then proceeds with patching the instance with the `AWS-RunPatchBaseline` document using the `aws:runCommand` action.

------
#### [ YAML ]

   ```
   - name: returnPrimaryTagKey
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           primaryTag: '{{PrimaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['primaryTag']
             tagKey = list(tag)[0]
             stringKey = "tag:" + tagKey
             return {'tagKey' : stringKey}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: primaryPatchGroupKey
           Selector: $.Payload.tagKey
           Type: String
       nextStep: returnPrimaryTagValue
     - name: returnPrimaryTagValue
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           primaryTag: '{{PrimaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['primaryTag']
             tagKey = list(tag)[0]
             tagValue = tag[tagKey]
             return {'tagValue' : tagValue}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: primaryPatchGroupValue
           Selector: $.Payload.tagValue
           Type: String
       nextStep: patchPrimaryInstances
     - name: patchPrimaryInstances
       action: 'aws:runCommand'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: AWS-RunPatchBaseline
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
         Targets:
           - Key: '{{returnPrimaryTagKey.primaryPatchGroupKey}}'
             Values:
               - '{{returnPrimaryTagValue.primaryPatchGroupValue}}'
         MaxConcurrency: 10%
         MaxErrors: 10%
       nextStep: returnPrimaryToOriginalState
   ```

------
#### [ JSON ]

   ```
   {
            "name":"returnPrimaryTagKey",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "primaryTag":"{{PrimaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"primaryPatchGroupKey",
                  "Selector":"$.Payload.tagKey",
                  "Type":"String"
               }
            ],
            "nextStep":"returnPrimaryTagValue"
         },
         {
            "name":"returnPrimaryTagValue",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "primaryTag":"{{PrimaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"primaryPatchGroupValue",
                  "Selector":"$.Payload.tagValue",
                  "Type":"String"
               }
            ],
            "nextStep":"patchPrimaryInstances"
         },
         {
            "name":"patchPrimaryInstances",
            "action":"aws:runCommand",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"AWS-RunPatchBaseline",
               "Parameters":{
                  "SnapshotId":"{{SnapshotId}}",
                  "RebootOption":"{{RebootOption}}",
                  "Operation":"{{Operation}}"
               },
               "Targets":[
                  {
                     "Key":"{{returnPrimaryTagKey.primaryPatchGroupKey}}",
                     "Values":[
                        "{{returnPrimaryTagValue.primaryPatchGroupValue}}"
                     ]
                  }
               ],
               "MaxConcurrency":"10%",
               "MaxErrors":"10%"
            },
            "nextStep":"returnPrimaryToOriginalState"
         },
   ```

------

1. After the patching operation completes, Emily wants the automation to return the target instances associated with the tag specified in the `PrimaryPatchGroupTag` parameter to the same state they were before the automation started. She does this by again using the output from the first action in a script. Based on the original state of the target instance, if the instance was previously in any state other than `running`, the instance is stopped. Otherwise, if the instance state is `running`, the script continues to loop through the remaining instances.

------
#### [ YAML ]

   ```
   - name: returnPrimaryToOriginalState
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnToOriginalState
         InputPayload:
           targetInstances: '{{getPrimaryInstanceState.originalInstanceStates}}'
         Script: |-
           def returnToOriginalState(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped' or instanceDict[instance] == 'stopping':
                   ec2.stop_instances(
                       InstanceIds=[instance]
                       )
               else:
                 pass
       nextStep: getSecondaryInstanceState
   ```

------
#### [ JSON ]

   ```
   {
            "name":"returnPrimaryToOriginalState",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnToOriginalState",
               "InputPayload":{
                  "targetInstances":"{{getPrimaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"getSecondaryInstanceState"
         },
   ```

------

1. The patching operation is completed for the instances associated with the tag specified in the `PrimaryPatchGroupTag` parameter. Now Emily duplicates all of the previous actions in her runbook content to target the instances associated with the tag specified in the `SecondaryPatchGroupTag` parameter.

------
#### [ YAML ]

   ```
   - name: getSecondaryInstanceState
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: getInstanceStates
         InputPayload:
           secondaryTag: '{{SecondaryPatchGroupTag}}'
         Script: |-
           def getInstanceStates(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             tag = events['secondaryTag']
             tagKey, tagValue = list(tag.items())[0]
             instanceQuery = ec2.describe_instances(
             Filters=[
                 {
                     "Name": "tag:" + tagKey,
                     "Values": [tagValue]
                 }]
             )
             if not instanceQuery['Reservations']:
                 noInstancesForTagString = "No instances found for specified tag."
                 return({ 'noInstancesFound' : noInstancesForTagString })
             else:
                 queryResponse = instanceQuery['Reservations']
                 originalInstanceStates = {}
                 for results in queryResponse:
                     instanceSet = results['Instances']
                     for instance in instanceSet:
                         instanceId = instance['InstanceId']
                         originalInstanceStates[instanceId] = instance['State']['Name']
                 return originalInstanceStates
       outputs:
         - Name: originalInstanceStates
           Selector: $.Payload
           Type: StringMap
       nextStep: verifySecondaryInstancesRunning
     - name: verifySecondaryInstancesRunning
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: verifyInstancesRunning
         InputPayload:
           targetInstances: '{{getSecondaryInstanceState.originalInstanceStates}}'
         Script: |-
           def verifyInstancesRunning(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped':
                   print("The target instance " + instance + " is stopped. The instance will now be started.")
                   ec2.start_instances(
                       InstanceIds=[instance]
                       )
               elif instanceDict[instance] == 'stopping':
                   print("The target instance " + instance + " is stopping. Polling for instance to reach stopped state.")
                   while instanceDict[instance] != 'stopped':
                       poll = ec2.get_waiter('instance_stopped')
                       poll.wait(
                           InstanceIds=[instance]
                       )
                   ec2.start_instances(
                       InstanceIds=[instance]
                   )
               else:
                 pass
       nextStep: waitForSecondaryRunningInstances
     - name: waitForSecondaryRunningInstances
       action: 'aws:executeScript'
       timeoutSeconds: 300
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: waitForRunningInstances
         InputPayload:
           targetInstances: '{{getSecondaryInstanceState.originalInstanceStates}}'
         Script: |-
           def waitForRunningInstances(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
                 poll = ec2.get_waiter('instance_running')
                 poll.wait(
                     InstanceIds=[instance]
                 )
       nextStep: returnSecondaryTagKey
     - name: returnSecondaryTagKey
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           secondaryTag: '{{SecondaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['secondaryTag']
             tagKey = list(tag)[0]
             stringKey = "tag:" + tagKey
             return {'tagKey' : stringKey}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: secondaryPatchGroupKey
           Selector: $.Payload.tagKey
           Type: String
       nextStep: returnSecondaryTagValue
     - name: returnSecondaryTagValue
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           secondaryTag: '{{SecondaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['secondaryTag']
             tagKey = list(tag)[0]
             tagValue = tag[tagKey]
             return {'tagValue' : tagValue}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: secondaryPatchGroupValue
           Selector: $.Payload.tagValue
           Type: String
       nextStep: patchSecondaryInstances
     - name: patchSecondaryInstances
       action: 'aws:runCommand'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: AWS-RunPatchBaseline
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
         Targets:
           - Key: '{{returnSecondaryTagKey.secondaryPatchGroupKey}}'
             Values:
             - '{{returnSecondaryTagValue.secondaryPatchGroupValue}}'
         MaxConcurrency: 10%
         MaxErrors: 10%
       nextStep: returnSecondaryToOriginalState
     - name: returnSecondaryToOriginalState
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnToOriginalState
         InputPayload:
           targetInstances: '{{getSecondaryInstanceState.originalInstanceStates}}'
         Script: |-
           def returnToOriginalState(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped' or instanceDict[instance] == 'stopping':
                   ec2.stop_instances(
                       InstanceIds=[instance]
                       )
               else:
                 pass
   ```

------
#### [ JSON ]

   ```
   {
            "name":"getSecondaryInstanceState",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"getInstanceStates",
               "InputPayload":{
                  "secondaryTag":"{{SecondaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"originalInstanceStates",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               }
            ],
            "nextStep":"verifySecondaryInstancesRunning"
         },
         {
            "name":"verifySecondaryInstancesRunning",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"verifyInstancesRunning",
               "InputPayload":{
                  "targetInstances":"{{getSecondaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"waitForSecondaryRunningInstances"
         },
         {
            "name":"waitForSecondaryRunningInstances",
            "action":"aws:executeScript",
            "timeoutSeconds":300,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"waitForRunningInstances",
               "InputPayload":{
                  "targetInstances":"{{getSecondaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"returnSecondaryTagKey"
         },
         {
            "name":"returnSecondaryTagKey",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "secondaryTag":"{{SecondaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"secondaryPatchGroupKey",
                  "Selector":"$.Payload.tagKey",
                  "Type":"String"
               }
            ],
            "nextStep":"returnSecondaryTagValue"
         },
         {
            "name":"returnSecondaryTagValue",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "secondaryTag":"{{SecondaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"secondaryPatchGroupValue",
                  "Selector":"$.Payload.tagValue",
                  "Type":"String"
               }
            ],
            "nextStep":"patchSecondaryInstances"
         },
         {
            "name":"patchSecondaryInstances",
            "action":"aws:runCommand",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"AWS-RunPatchBaseline",
               "Parameters":{
                  "SnapshotId":"{{SnapshotId}}",
                  "RebootOption":"{{RebootOption}}",
                  "Operation":"{{Operation}}"
               },
               "Targets":[
                  {
                     "Key":"{{returnSecondaryTagKey.secondaryPatchGroupKey}}",
                     "Values":[
                        "{{returnSecondaryTagValue.secondaryPatchGroupValue}}"
                     ]
                  }
               ],
               "MaxConcurrency":"10%",
               "MaxErrors":"10%"
            },
            "nextStep":"returnSecondaryToOriginalState"
         },
         {
            "name":"returnSecondaryToOriginalState",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnToOriginalState",
               "InputPayload":{
                  "targetInstances":"{{getSecondaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            }
         }
      ]
   }
   ```

------

1. Emily reviews the completed scripted runbook content and creates the runbook in the same AWS account and AWS Region as the target instances. Now she's ready to test her runbook to make sure the automation operates as desired before implementing it into her production environment. The following is the completed scripted runbook content.

------
#### [ YAML ]

   ```
   description: An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.
   schemaVersion: '0.3'
   assumeRole: '{{AutomationAssumeRole}}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: '(Required) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook.'
     PrimaryPatchGroupTag:
       type: StringMap
       description: '(Required) The tag for the primary group of instances you want to patch. Specify a key-value pair. Example: {"key" : "value"}'
     SecondaryPatchGroupTag:
       type: StringMap
       description: '(Required) The tag for the secondary group of instances you want to patch. Specify a key-value pair. Example: {"key" : "value"}'
     SnapshotId:
       type: String
       description: '(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.'
       default: ''
     RebootOption:
       type: String
       description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.'
       allowedValues:
         - NoReboot
         - RebootIfNeeded
       default: RebootIfNeeded
     Operation:
       type: String
       description: '(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.'
       allowedValues:
         - Install
         - Scan
       default: Install
   mainSteps:
     - name: getPrimaryInstanceState
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: getInstanceStates
         InputPayload:
           primaryTag: '{{PrimaryPatchGroupTag}}'
         Script: |-
           def getInstanceStates(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             tag = events['primaryTag']
             tagKey, tagValue = list(tag.items())[0]
             instanceQuery = ec2.describe_instances(
             Filters=[
                 {
                     "Name": "tag:" + tagKey,
                     "Values": [tagValue]
                 }]
             )
             if not instanceQuery['Reservations']:
                 noInstancesForTagString = "No instances found for specified tag."
                 return({ 'noInstancesFound' : noInstancesForTagString })
             else:
                 queryResponse = instanceQuery['Reservations']
                 originalInstanceStates = {}
                 for results in queryResponse:
                     instanceSet = results['Instances']
                     for instance in instanceSet:
                         instanceId = instance['InstanceId']
                         originalInstanceStates[instanceId] = instance['State']['Name']
                 return originalInstanceStates
       outputs:
         - Name: originalInstanceStates
           Selector: $.Payload
           Type: StringMap
       nextStep: verifyPrimaryInstancesRunning
     - name: verifyPrimaryInstancesRunning
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: verifyInstancesRunning
         InputPayload:
           targetInstances: '{{getPrimaryInstanceState.originalInstanceStates}}'
         Script: |-
           def verifyInstancesRunning(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped':
                   print("The target instance " + instance + " is stopped. The instance will now be started.")
                   ec2.start_instances(
                       InstanceIds=[instance]
                       )
               elif instanceDict[instance] == 'stopping':
                   print("The target instance " + instance + " is stopping. Polling for instance to reach stopped state.")
                   while instanceDict[instance] != 'stopped':
                       poll = ec2.get_waiter('instance_stopped')
                       poll.wait(
                           InstanceIds=[instance]
                       )
                   ec2.start_instances(
                       InstanceIds=[instance]
                   )
               else:
                 pass
       nextStep: waitForPrimaryRunningInstances
     - name: waitForPrimaryRunningInstances
       action: 'aws:executeScript'
       timeoutSeconds: 300
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: waitForRunningInstances
         InputPayload:
           targetInstances: '{{getPrimaryInstanceState.originalInstanceStates}}'
         Script: |-
           def waitForRunningInstances(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
                 poll = ec2.get_waiter('instance_running')
                 poll.wait(
                     InstanceIds=[instance]
                 )
       nextStep: returnPrimaryTagKey
     - name: returnPrimaryTagKey
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           primaryTag: '{{PrimaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['primaryTag']
             tagKey = list(tag)[0]
             stringKey = "tag:" + tagKey
             return {'tagKey' : stringKey}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: primaryPatchGroupKey
           Selector: $.Payload.tagKey
           Type: String
       nextStep: returnPrimaryTagValue
     - name: returnPrimaryTagValue
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           primaryTag: '{{PrimaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['primaryTag']
             tagKey = list(tag)[0]
             tagValue = tag[tagKey]
             return {'tagValue' : tagValue}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: primaryPatchGroupValue
           Selector: $.Payload.tagValue
           Type: String
       nextStep: patchPrimaryInstances
     - name: patchPrimaryInstances
       action: 'aws:runCommand'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: AWS-RunPatchBaseline
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
         Targets:
           - Key: '{{returnPrimaryTagKey.primaryPatchGroupKey}}'
             Values:
               - '{{returnPrimaryTagValue.primaryPatchGroupValue}}'
         MaxConcurrency: 10%
         MaxErrors: 10%
       nextStep: returnPrimaryToOriginalState
     - name: returnPrimaryToOriginalState
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnToOriginalState
         InputPayload:
           targetInstances: '{{getPrimaryInstanceState.originalInstanceStates}}'
         Script: |-
           def returnToOriginalState(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped' or instanceDict[instance] == 'stopping':
                   ec2.stop_instances(
                       InstanceIds=[instance]
                       )
               else:
                 pass
       nextStep: getSecondaryInstanceState
     - name: getSecondaryInstanceState
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: getInstanceStates
         InputPayload:
           secondaryTag: '{{SecondaryPatchGroupTag}}'
         Script: |-
           def getInstanceStates(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             tag = events['secondaryTag']
             tagKey, tagValue = list(tag.items())[0]
             instanceQuery = ec2.describe_instances(
             Filters=[
                 {
                     "Name": "tag:" + tagKey,
                     "Values": [tagValue]
                 }]
             )
             if not instanceQuery['Reservations']:
                 noInstancesForTagString = "No instances found for specified tag."
                 return({ 'noInstancesFound' : noInstancesForTagString })
             else:
                 queryResponse = instanceQuery['Reservations']
                 originalInstanceStates = {}
                 for results in queryResponse:
                     instanceSet = results['Instances']
                     for instance in instanceSet:
                         instanceId = instance['InstanceId']
                         originalInstanceStates[instanceId] = instance['State']['Name']
                 return originalInstanceStates
       outputs:
         - Name: originalInstanceStates
           Selector: $.Payload
           Type: StringMap
       nextStep: verifySecondaryInstancesRunning
     - name: verifySecondaryInstancesRunning
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: verifyInstancesRunning
         InputPayload:
           targetInstances: '{{getSecondaryInstanceState.originalInstanceStates}}'
         Script: |-
           def verifyInstancesRunning(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped':
                   print("The target instance " + instance + " is stopped. The instance will now be started.")
                   ec2.start_instances(
                       InstanceIds=[instance]
                       )
               elif instanceDict[instance] == 'stopping':
                   print("The target instance " + instance + " is stopping. Polling for instance to reach stopped state.")
                   while instanceDict[instance] != 'stopped':
                       poll = ec2.get_waiter('instance_stopped')
                       poll.wait(
                           InstanceIds=[instance]
                       )
                   ec2.start_instances(
                       InstanceIds=[instance]
                   )
               else:
                 pass
       nextStep: waitForSecondaryRunningInstances
     - name: waitForSecondaryRunningInstances
       action: 'aws:executeScript'
       timeoutSeconds: 300
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: waitForRunningInstances
         InputPayload:
           targetInstances: '{{getSecondaryInstanceState.originalInstanceStates}}'
         Script: |-
           def waitForRunningInstances(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
                 poll = ec2.get_waiter('instance_running')
                 poll.wait(
                     InstanceIds=[instance]
                 )
       nextStep: returnSecondaryTagKey
     - name: returnSecondaryTagKey
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           secondaryTag: '{{SecondaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['secondaryTag']
             tagKey = list(tag)[0]
             stringKey = "tag:" + tagKey
             return {'tagKey' : stringKey}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: secondaryPatchGroupKey
           Selector: $.Payload.tagKey
           Type: String
       nextStep: returnSecondaryTagValue
     - name: returnSecondaryTagValue
       action: 'aws:executeScript'
       timeoutSeconds: 120
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnTagValues
         InputPayload:
           secondaryTag: '{{SecondaryPatchGroupTag}}'
         Script: |-
           def returnTagValues(events,context):
             tag = events['secondaryTag']
             tagKey = list(tag)[0]
             tagValue = tag[tagKey]
             return {'tagValue' : tagValue}
       outputs:
         - Name: Payload
           Selector: $.Payload
           Type: StringMap
         - Name: secondaryPatchGroupValue
           Selector: $.Payload.tagValue
           Type: String
       nextStep: patchSecondaryInstances
     - name: patchSecondaryInstances
       action: 'aws:runCommand'
       onFailure: Abort
       timeoutSeconds: 7200
       inputs:
         DocumentName: AWS-RunPatchBaseline
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
         Targets:
           - Key: '{{returnSecondaryTagKey.secondaryPatchGroupKey}}'
             Values:
             - '{{returnSecondaryTagValue.secondaryPatchGroupValue}}'
         MaxConcurrency: 10%
         MaxErrors: 10%
       nextStep: returnSecondaryToOriginalState
     - name: returnSecondaryToOriginalState
       action: 'aws:executeScript'
       timeoutSeconds: 600
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: returnToOriginalState
         InputPayload:
           targetInstances: '{{getSecondaryInstanceState.originalInstanceStates}}'
         Script: |-
           def returnToOriginalState(events,context):
             import boto3
   
             #Initialize client
             ec2 = boto3.client('ec2')
             instanceDict = events['targetInstances']
             for instance in instanceDict:
               if instanceDict[instance] == 'stopped' or instanceDict[instance] == 'stopping':
                   ec2.stop_instances(
                       InstanceIds=[instance]
                       )
               else:
                 pass
   ```

------
#### [ JSON ]

   ```
   {
      "description":"An example of an Automation runbook that patches groups of Amazon EC2 instances in stages.",
      "schemaVersion":"0.3",
      "assumeRole":"{{AutomationAssumeRole}}",
      "parameters":{
         "AutomationAssumeRole":{
            "type":"String",
            "description":"(Required) The Amazon Resource Name (ARN) of the IAM role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to operate this runbook."
         },
         "PrimaryPatchGroupTag":{
            "type":"StringMap",
            "description":"(Required) The tag for the primary group of instances you want to patch. Specify a key-value pair. Example: {\"key\" : \"value\"}"
         },
         "SecondaryPatchGroupTag":{
            "type":"StringMap",
            "description":"(Required) The tag for the secondary group of instances you want to patch. Specify a key-value pair. Example: {\"key\" : \"value\"}"
         },
         "SnapshotId":{
            "type":"String",
            "description":"(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.",
            "default":""
         },
         "RebootOption":{
            "type":"String",
            "description":"(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.",
            "allowedValues":[
               "NoReboot",
               "RebootIfNeeded"
            ],
            "default":"RebootIfNeeded"
         },
         "Operation":{
            "type":"String",
            "description":"(Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.",
            "allowedValues":[
               "Install",
               "Scan"
            ],
            "default":"Install"
         }
      },
      "mainSteps":[
         {
            "name":"getPrimaryInstanceState",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"getInstanceStates",
               "InputPayload":{
                  "primaryTag":"{{PrimaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"originalInstanceStates",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               }
            ],
            "nextStep":"verifyPrimaryInstancesRunning"
         },
         {
            "name":"verifyPrimaryInstancesRunning",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"verifyInstancesRunning",
               "InputPayload":{
                  "targetInstances":"{{getPrimaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"waitForPrimaryRunningInstances"
         },
         {
            "name":"waitForPrimaryRunningInstances",
            "action":"aws:executeScript",
            "timeoutSeconds":300,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"waitForRunningInstances",
               "InputPayload":{
                  "targetInstances":"{{getPrimaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"returnPrimaryTagKey"
         },
         {
            "name":"returnPrimaryTagKey",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "primaryTag":"{{PrimaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"primaryPatchGroupKey",
                  "Selector":"$.Payload.tagKey",
                  "Type":"String"
               }
            ],
            "nextStep":"returnPrimaryTagValue"
         },
         {
            "name":"returnPrimaryTagValue",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "primaryTag":"{{PrimaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"primaryPatchGroupValue",
                  "Selector":"$.Payload.tagValue",
                  "Type":"String"
               }
            ],
            "nextStep":"patchPrimaryInstances"
         },
         {
            "name":"patchPrimaryInstances",
            "action":"aws:runCommand",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"AWS-RunPatchBaseline",
               "Parameters":{
                  "SnapshotId":"{{SnapshotId}}",
                  "RebootOption":"{{RebootOption}}",
                  "Operation":"{{Operation}}"
               },
               "Targets":[
                  {
                     "Key":"{{returnPrimaryTagKey.primaryPatchGroupKey}}",
                     "Values":[
                        "{{returnPrimaryTagValue.primaryPatchGroupValue}}"
                     ]
                  }
               ],
               "MaxConcurrency":"10%",
               "MaxErrors":"10%"
            },
            "nextStep":"returnPrimaryToOriginalState"
         },
         {
            "name":"returnPrimaryToOriginalState",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnToOriginalState",
               "InputPayload":{
                  "targetInstances":"{{getPrimaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"getSecondaryInstanceState"
         },
         {
            "name":"getSecondaryInstanceState",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"getInstanceStates",
               "InputPayload":{
                  "secondaryTag":"{{SecondaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"originalInstanceStates",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               }
            ],
            "nextStep":"verifySecondaryInstancesRunning"
         },
         {
            "name":"verifySecondaryInstancesRunning",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"verifyInstancesRunning",
               "InputPayload":{
                  "targetInstances":"{{getSecondaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"waitForSecondaryRunningInstances"
         },
         {
            "name":"waitForSecondaryRunningInstances",
            "action":"aws:executeScript",
            "timeoutSeconds":300,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"waitForRunningInstances",
               "InputPayload":{
                  "targetInstances":"{{getSecondaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            },
            "nextStep":"returnSecondaryTagKey"
         },
         {
            "name":"returnSecondaryTagKey",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "secondaryTag":"{{SecondaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"secondaryPatchGroupKey",
                  "Selector":"$.Payload.tagKey",
                  "Type":"String"
               }
            ],
            "nextStep":"returnSecondaryTagValue"
         },
         {
            "name":"returnSecondaryTagValue",
            "action":"aws:executeScript",
            "timeoutSeconds":120,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnTagValues",
               "InputPayload":{
                  "secondaryTag":"{{SecondaryPatchGroupTag}}"
               },
               "Script":"..."
            },
            "outputs":[
               {
                  "Name":"Payload",
                  "Selector":"$.Payload",
                  "Type":"StringMap"
               },
               {
                  "Name":"secondaryPatchGroupValue",
                  "Selector":"$.Payload.tagValue",
                  "Type":"String"
               }
            ],
            "nextStep":"patchSecondaryInstances"
         },
         {
            "name":"patchSecondaryInstances",
            "action":"aws:runCommand",
            "onFailure":"Abort",
            "timeoutSeconds":7200,
            "inputs":{
               "DocumentName":"AWS-RunPatchBaseline",
               "Parameters":{
                  "SnapshotId":"{{SnapshotId}}",
                  "RebootOption":"{{RebootOption}}",
                  "Operation":"{{Operation}}"
               },
               "Targets":[
                  {
                     "Key":"{{returnSecondaryTagKey.secondaryPatchGroupKey}}",
                     "Values":[
                        "{{returnSecondaryTagValue.secondaryPatchGroupValue}}"
                     ]
                  }
               ],
               "MaxConcurrency":"10%",
               "MaxErrors":"10%"
            },
            "nextStep":"returnSecondaryToOriginalState"
         },
         {
            "name":"returnSecondaryToOriginalState",
            "action":"aws:executeScript",
            "timeoutSeconds":600,
            "onFailure":"Abort",
            "inputs":{
               "Runtime":"python3.11",
               "Handler":"returnToOriginalState",
               "InputPayload":{
                  "targetInstances":"{{getSecondaryInstanceState.originalInstanceStates}}"
               },
               "Script":"..."
            }
         }
      ]
   }
   ```

------

For more information about the automation actions used in this example, see the [Systems Manager Automation actions reference](automation-actions.md).

# Additional runbook examples
<a name="automation-document-examples"></a>

The following example runbook demonstrate how you can use AWS Systems Manager automation actions to automate common deployment, troubleshooting, and maintenance tasks.

**Note**  
The example runbooks in this section are provided to demonstrate how you can create custom runbooks to support your specific operational needs. These runbooks aren't meant for use in production environments as is. However, you can customize them for your own use.

**Topics**
+ [Deploy VPC architecture and Microsoft Active Directory domain controllers](automation-document-architecture-deployment-example.md)
+ [Restore a root volume from the latest snapshot](automation-document-instance-recovery-example.md)
+ [Create an AMI and cross-Region copy](automation-document-backup-maintenance-example.md)

# Deploy VPC architecture and Microsoft Active Directory domain controllers
<a name="automation-document-architecture-deployment-example"></a>

To increase efficiency and standardize common tasks, you might choose to automate deployments. This is useful if you regularly deploy the same architecture across multiple accounts and AWS Regions. Automating architecture deployments can also reduce the potential for human error that can occur when deploying architecture manually. AWS Systems Manager Automation actions can help you accomplish this. Automation is a tool in AWS Systems Manager.

The following example AWS Systems Manager runbook performs these actions:
+ Retrieves the latest Windows Server 2016 Amazon Machine Image (AMI) using Systems Manager Parameter Store to use when launching the EC2 instances that will be configured as domain controllers. Parameter Store is a tool in AWS Systems Manager.
+ Uses the `aws:executeAwsApi` automation action to call several AWS API operations to create the VPC architecture. The domain controller instances are launched in private subnets, and connect to the internet using a NAT gateway. This allows the SSM Agent on the instances to access the requisite Systems Manager endpoints.
+ Uses the `aws:waitForAwsResourceProperty` automation action to confirm the instances launched by the previous action are `Online` for AWS Systems Manager.
+ Uses the `aws:runCommand` automation action to configure the instances launched as Microsoft Active Directory domain controllers.

------
#### [ YAML ]

```
    ---
    description: Custom Automation Deployment Example
    schemaVersion: '0.3'
    parameters:
      AutomationAssumeRole:
        type: String
        default: ''
        description: >-
          (Optional) The ARN of the role that allows Automation to perform the
          actions on your behalf. If no role is specified, Systems Manager
          Automation uses your IAM permissions to run this runbook.
    mainSteps:
      - name: getLatestWindowsAmi
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ssm
          Api: GetParameter
          Name: >-
            /aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base
        outputs:
          - Name: amiId
            Selector: $.Parameter.Value
            Type: String
        nextStep: createSSMInstanceRole
      - name: createSSMInstanceRole
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: iam
          Api: CreateRole
          AssumeRolePolicyDocument: >-
            {"Version": "2012-10-17",		 	 	 "Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]}
          RoleName: sampleSSMInstanceRole
        nextStep: attachManagedSSMPolicy
      - name: attachManagedSSMPolicy
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: iam
          Api: AttachRolePolicy
          PolicyArn: 'arn:aws:iam::aws:policy/service-role/AmazonSSMManagedInstanceCore'
          RoleName: sampleSSMInstanceRole
        nextStep: createSSMInstanceProfile
      - name: createSSMInstanceProfile
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: iam
          Api: CreateInstanceProfile
          InstanceProfileName: sampleSSMInstanceRole
        outputs:
          - Name: instanceProfileArn
            Selector: $.InstanceProfile.Arn
            Type: String
        nextStep: addSSMInstanceRoleToProfile
      - name: addSSMInstanceRoleToProfile
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: iam
          Api: AddRoleToInstanceProfile
          InstanceProfileName: sampleSSMInstanceRole
          RoleName: sampleSSMInstanceRole
        nextStep: createVpc
      - name: createVpc
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateVpc
          CidrBlock: 10.0.100.0/22
        outputs:
          - Name: vpcId
            Selector: $.Vpc.VpcId
            Type: String
        nextStep: getMainRtb
      - name: getMainRtb
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: DescribeRouteTables
          Filters:
            - Name: vpc-id
              Values:
                - '{{ createVpc.vpcId }}'
        outputs:
          - Name: mainRtbId
            Selector: '$.RouteTables[0].RouteTableId'
            Type: String
        nextStep: verifyMainRtb
      - name: verifyMainRtb
        action: aws:assertAwsResourceProperty
        onFailure: Abort
        inputs:
          Service: ec2
          Api: DescribeRouteTables
          RouteTableIds:
            - '{{ getMainRtb.mainRtbId }}'
          PropertySelector: '$.RouteTables[0].Associations[0].Main'
          DesiredValues:
            - 'True'
        nextStep: createPubSubnet
      - name: createPubSubnet
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateSubnet
          CidrBlock: 10.0.103.0/24
          AvailabilityZone: us-west-2c
          VpcId: '{{ createVpc.vpcId }}'
        outputs:
          - Name: pubSubnetId
            Selector: $.Subnet.SubnetId
            Type: String
        nextStep: createPubRtb
      - name: createPubRtb
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateRouteTable
          VpcId: '{{ createVpc.vpcId }}'
        outputs:
          - Name: pubRtbId
            Selector: $.RouteTable.RouteTableId
            Type: String
        nextStep: createIgw
      - name: createIgw
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateInternetGateway
        outputs:
          - Name: igwId
            Selector: $.InternetGateway.InternetGatewayId
            Type: String
        nextStep: attachIgw
      - name: attachIgw
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: AttachInternetGateway
          InternetGatewayId: '{{ createIgw.igwId }}'
          VpcId: '{{ createVpc.vpcId }}'
        nextStep: allocateEip
      - name: allocateEip
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: AllocateAddress
          Domain: vpc
        outputs:
          - Name: eipAllocationId
            Selector: $.AllocationId
            Type: String
        nextStep: createNatGw
      - name: createNatGw
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateNatGateway
          AllocationId: '{{ allocateEip.eipAllocationId }}'
          SubnetId: '{{ createPubSubnet.pubSubnetId }}'
        outputs:
          - Name: natGwId
            Selector: $.NatGateway.NatGatewayId
            Type: String
        nextStep: verifyNatGwAvailable
      - name: verifyNatGwAvailable
        action: aws:waitForAwsResourceProperty
        timeoutSeconds: 150
        inputs:
          Service: ec2
          Api: DescribeNatGateways
          NatGatewayIds:
            - '{{ createNatGw.natGwId }}'
          PropertySelector: '$.NatGateways[0].State'
          DesiredValues:
            - available
        nextStep: createNatRoute
      - name: createNatRoute
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateRoute
          DestinationCidrBlock: 0.0.0.0/0
          NatGatewayId: '{{ createNatGw.natGwId }}'
          RouteTableId: '{{ getMainRtb.mainRtbId }}'
        nextStep: createPubRoute
      - name: createPubRoute
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateRoute
          DestinationCidrBlock: 0.0.0.0/0
          GatewayId: '{{ createIgw.igwId }}'
          RouteTableId: '{{ createPubRtb.pubRtbId }}'
        nextStep: setPubSubAssoc
      - name: setPubSubAssoc
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: AssociateRouteTable
          RouteTableId: '{{ createPubRtb.pubRtbId }}'
          SubnetId: '{{ createPubSubnet.pubSubnetId }}'
      - name: createDhcpOptions
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateDhcpOptions
          DhcpConfigurations:
            - Key: domain-name-servers
              Values:
                - '10.0.100.50,10.0.101.50'
            - Key: domain-name
              Values:
                - sample.com
        outputs:
          - Name: dhcpOptionsId
            Selector: $.DhcpOptions.DhcpOptionsId
            Type: String
        nextStep: createDCSubnet1
      - name: createDCSubnet1
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateSubnet
          CidrBlock: 10.0.100.0/24
          AvailabilityZone: us-west-2a
          VpcId: '{{ createVpc.vpcId }}'
        outputs:
          - Name: firstSubnetId
            Selector: $.Subnet.SubnetId
            Type: String
        nextStep: createDCSubnet2
      - name: createDCSubnet2
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateSubnet
          CidrBlock: 10.0.101.0/24
          AvailabilityZone: us-west-2b
          VpcId: '{{ createVpc.vpcId }}'
        outputs:
          - Name: secondSubnetId
            Selector: $.Subnet.SubnetId
            Type: String
        nextStep: createDCSecGroup
      - name: createDCSecGroup
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: CreateSecurityGroup
          GroupName: SampleDCSecGroup
          Description: Security Group for Sample Domain Controllers
          VpcId: '{{ createVpc.vpcId }}'
        outputs:
          - Name: dcSecGroupId
            Selector: $.GroupId
            Type: String
        nextStep: authIngressDCTraffic
      - name: authIngressDCTraffic
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: AuthorizeSecurityGroupIngress
          GroupId: '{{ createDCSecGroup.dcSecGroupId }}'
          IpPermissions:
            - FromPort: -1
              IpProtocol: '-1'
              IpRanges:
                - CidrIp: 0.0.0.0/0
                  Description: Allow all traffic between Domain Controllers
        nextStep: verifyInstanceProfile
      - name: verifyInstanceProfile
        action: aws:waitForAwsResourceProperty
        maxAttempts: 5
        onFailure: Abort
        inputs:
          Service: iam
          Api: ListInstanceProfilesForRole
          RoleName: sampleSSMInstanceRole
          PropertySelector: '$.InstanceProfiles[0].Arn'
          DesiredValues:
            - '{{ createSSMInstanceProfile.instanceProfileArn }}'
        nextStep: iamEventualConsistency
      - name: iamEventualConsistency
        action: aws:sleep
        inputs:
          Duration: PT2M
        nextStep: launchDC1
      - name: launchDC1
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: RunInstances
          BlockDeviceMappings:
            - DeviceName: /dev/sda1
              Ebs:
                DeleteOnTermination: true
                VolumeSize: 50
                VolumeType: gp2
            - DeviceName: xvdf
              Ebs:
                DeleteOnTermination: true
                VolumeSize: 100
                VolumeType: gp2
          IamInstanceProfile:
            Arn: '{{ createSSMInstanceProfile.instanceProfileArn }}'
          ImageId: '{{ getLatestWindowsAmi.amiId }}'
          InstanceType: t2.micro
          MaxCount: 1
          MinCount: 1
          PrivateIpAddress: 10.0.100.50
          SecurityGroupIds:
            - '{{ createDCSecGroup.dcSecGroupId }}'
          SubnetId: '{{ createDCSubnet1.firstSubnetId }}'
          TagSpecifications:
            - ResourceType: instance
              Tags:
                - Key: Name
                  Value: SampleDC1
        outputs:
          - Name: pdcInstanceId
            Selector: '$.Instances[0].InstanceId'
            Type: String
        nextStep: launchDC2
      - name: launchDC2
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: RunInstances
          BlockDeviceMappings:
            - DeviceName: /dev/sda1
              Ebs:
                DeleteOnTermination: true
                VolumeSize: 50
                VolumeType: gp2
            - DeviceName: xvdf
              Ebs:
                DeleteOnTermination: true
                VolumeSize: 100
                VolumeType: gp2
          IamInstanceProfile:
            Arn: '{{ createSSMInstanceProfile.instanceProfileArn }}'
          ImageId: '{{ getLatestWindowsAmi.amiId }}'
          InstanceType: t2.micro
          MaxCount: 1
          MinCount: 1
          PrivateIpAddress: 10.0.101.50
          SecurityGroupIds:
            - '{{ createDCSecGroup.dcSecGroupId }}'
          SubnetId: '{{ createDCSubnet2.secondSubnetId }}'
          TagSpecifications:
            - ResourceType: instance
              Tags:
                - Key: Name
                  Value: SampleDC2
        outputs:
          - Name: adcInstanceId
            Selector: '$.Instances[0].InstanceId'
            Type: String
        nextStep: verifyDCInstanceState
      - name: verifyDCInstanceState
        action: aws:waitForAwsResourceProperty
        inputs:
          Service: ec2
          Api: DescribeInstanceStatus
          IncludeAllInstances: true
          InstanceIds:
            - '{{ launchDC1.pdcInstanceId }}'
            - '{{ launchDC2.adcInstanceId }}'
          PropertySelector: '$.InstanceStatuses..InstanceState.Name'
          DesiredValues:
            - running
        nextStep: verifyInstancesOnlineSSM
      - name: verifyInstancesOnlineSSM
        action: aws:waitForAwsResourceProperty
        timeoutSeconds: 600
        inputs:
          Service: ssm
          Api: DescribeInstanceInformation
          InstanceInformationFilterList:
            - key: InstanceIds
              valueSet:
                - '{{ launchDC1.pdcInstanceId }}'
                - '{{ launchDC2.adcInstanceId }}'
          PropertySelector: '$.InstanceInformationList..PingStatus'
          DesiredValues:
            - Online
        nextStep: installADRoles
      - name: installADRoles
        action: aws:runCommand
        inputs:
          DocumentName: AWS-RunPowerShellScript
          InstanceIds:
            - '{{ launchDC1.pdcInstanceId }}'
            - '{{ launchDC2.adcInstanceId }}'
          Parameters:
            commands: |-
              try {
                  Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools
              }
              catch {
                  Write-Error "Failed to install ADDS Role."
              }
        nextStep: setAdminPassword
      - name: setAdminPassword
        action: aws:runCommand
        inputs:
          DocumentName: AWS-RunPowerShellScript
          InstanceIds:
            - '{{ launchDC1.pdcInstanceId }}'
          Parameters:
            commands:
              - net user Administrator "sampleAdminPass123!"
        nextStep: createForest
      - name: createForest
        action: aws:runCommand
        inputs:
          DocumentName: AWS-RunPowerShellScript
          InstanceIds:
            - '{{ launchDC1.pdcInstanceId }}'
          Parameters:
            commands: |-
              $dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force
              try {
                  Install-ADDSForest -DomainName "sample.com" -DomainMode 6 -ForestMode 6 -InstallDNS -DatabasePath "D:\NTDS" -SysvolPath "D:\SYSVOL" -SafeModeAdministratorPassword $dsrmPass -Force
              }
              catch {
                  Write-Error $_
              }
              try {
                  Add-DnsServerForwarder -IPAddress "10.0.100.2"
              }
              catch {
                  Write-Error $_
              }
        nextStep: associateDhcpOptions
      - name: associateDhcpOptions
        action: aws:executeAwsApi
        onFailure: Abort
        inputs:
          Service: ec2
          Api: AssociateDhcpOptions
          DhcpOptionsId: '{{ createDhcpOptions.dhcpOptionsId }}'
          VpcId: '{{ createVpc.vpcId }}'
        nextStep: waitForADServices
      - name: waitForADServices
        action: aws:sleep
        inputs:
          Duration: PT1M
        nextStep: promoteADC
      - name: promoteADC
        action: aws:runCommand
        inputs:
          DocumentName: AWS-RunPowerShellScript
          InstanceIds:
            - '{{ launchDC2.adcInstanceId }}'
          Parameters:
            commands: |-
              ipconfig /renew
              $dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force
              $domAdminUser = "sample\Administrator"
              $domAdminPass = "sampleAdminPass123!" | ConvertTo-SecureString -asPlainText -Force
              $domAdminCred = New-Object System.Management.Automation.PSCredential($domAdminUser,$domAdminPass)
    
              try {
                  Install-ADDSDomainController -DomainName "sample.com" -InstallDNS -DatabasePath "D:\NTDS" -SysvolPath "D:\SYSVOL" -SafeModeAdministratorPassword $dsrmPass -Credential $domAdminCred -Force
              }
              catch {
                  Write-Error $_
              }
```

------
#### [ JSON ]

```
{
      "description": "Custom Automation Deployment Example",
      "schemaVersion": "0.3",
      "assumeRole": "{{ AutomationAssumeRole }}",
      "parameters": {
        "AutomationAssumeRole": {
          "type": "String",
          "description": "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to run this runbook.",
          "default": ""
        }
      },
      "mainSteps": [
        {
          "name": "getLatestWindowsAmi",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ssm",
            "Api": "GetParameter",
            "Name": "/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base"
          },
          "outputs": [
            {
              "Name": "amiId",
              "Selector": "$.Parameter.Value",
              "Type": "String"
            }
          ],
          "nextStep": "createSSMInstanceRole"
        },
        {
          "name": "createSSMInstanceRole",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "iam",
            "Api": "CreateRole",
            "AssumeRolePolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"ec2.amazonaws.com\"]},\"Action\":[\"sts:AssumeRole\"]}]}",
            "RoleName": "sampleSSMInstanceRole"
          },
          "nextStep": "attachManagedSSMPolicy"
        },
        {
          "name": "attachManagedSSMPolicy",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "iam",
            "Api": "AttachRolePolicy",
            "PolicyArn": "arn:aws:iam::aws:policy/service-role/AmazonSSMManagedInstanceCore",
            "RoleName": "sampleSSMInstanceRole"
          },
          "nextStep": "createSSMInstanceProfile"
        },
        {
          "name": "createSSMInstanceProfile",
          "action":"aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "iam",
            "Api": "CreateInstanceProfile",
            "InstanceProfileName": "sampleSSMInstanceRole"
          },
          "outputs": [
            {
              "Name": "instanceProfileArn",
              "Selector": "$.InstanceProfile.Arn",
              "Type": "String"
            }
          ],
          "nextStep": "addSSMInstanceRoleToProfile"
        },
        {
          "name": "addSSMInstanceRoleToProfile",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "iam",
            "Api": "AddRoleToInstanceProfile",
            "InstanceProfileName": "sampleSSMInstanceRole",
            "RoleName": "sampleSSMInstanceRole"
          },
          "nextStep": "createVpc"
        },
        {
          "name": "createVpc",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateVpc",
            "CidrBlock": "10.0.100.0/22"
          },
          "outputs": [
            {
              "Name": "vpcId",
              "Selector": "$.Vpc.VpcId",
              "Type": "String"
            }
          ],
          "nextStep": "getMainRtb"
        },
        {
          "name": "getMainRtb",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "DescribeRouteTables",
            "Filters": [
              {
                "Name": "vpc-id",
                "Values": ["{{ createVpc.vpcId }}"]
              }
            ]
          },
          "outputs": [
            {
              "Name": "mainRtbId",
              "Selector": "$.RouteTables[0].RouteTableId",
              "Type": "String"
            }
          ],
          "nextStep": "verifyMainRtb"
        },
        {
          "name": "verifyMainRtb",
          "action": "aws:assertAwsResourceProperty",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "DescribeRouteTables",
            "RouteTableIds": ["{{ getMainRtb.mainRtbId }}"],
            "PropertySelector": "$.RouteTables[0].Associations[0].Main",
            "DesiredValues": ["True"]
          },
          "nextStep": "createPubSubnet"
        },
        {
          "name": "createPubSubnet",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateSubnet",
            "CidrBlock": "10.0.103.0/24",
            "AvailabilityZone": "us-west-2c",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "outputs":[
            {
              "Name": "pubSubnetId",
              "Selector": "$.Subnet.SubnetId",
              "Type": "String"
            }
          ],
          "nextStep": "createPubRtb"
        },
        {
          "name": "createPubRtb",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateRouteTable",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "outputs": [
            {
              "Name": "pubRtbId",
              "Selector": "$.RouteTable.RouteTableId",
              "Type": "String"
            }
          ],
          "nextStep": "createIgw"
        },
        {
          "name": "createIgw",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateInternetGateway"
          },
          "outputs": [
            {
              "Name": "igwId",
              "Selector": "$.InternetGateway.InternetGatewayId",
              "Type": "String"
            }
          ],
          "nextStep": "attachIgw"
        },
        {
          "name": "attachIgw",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "AttachInternetGateway",
            "InternetGatewayId": "{{ createIgw.igwId }}",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "nextStep": "allocateEip"
        },
        {
          "name": "allocateEip",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "AllocateAddress",
            "Domain": "vpc"
          },
          "outputs": [
            {
              "Name": "eipAllocationId",
              "Selector": "$.AllocationId",
              "Type": "String"
            }
          ],
          "nextStep": "createNatGw"
        },
        {
          "name": "createNatGw",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateNatGateway",
            "AllocationId": "{{ allocateEip.eipAllocationId }}",
            "SubnetId": "{{ createPubSubnet.pubSubnetId }}"
          },
          "outputs":[
            {
              "Name": "natGwId",
              "Selector": "$.NatGateway.NatGatewayId",
              "Type": "String"
            }
          ],
          "nextStep": "verifyNatGwAvailable"
        },
        {
          "name": "verifyNatGwAvailable",
          "action": "aws:waitForAwsResourceProperty",
          "timeoutSeconds": 150,
          "inputs": {
            "Service": "ec2",
            "Api": "DescribeNatGateways",
            "NatGatewayIds": [
              "{{ createNatGw.natGwId }}"
            ],
            "PropertySelector": "$.NatGateways[0].State",
            "DesiredValues": [
              "available"
            ]
          },
          "nextStep": "createNatRoute"
        },
        {
          "name": "createNatRoute",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateRoute",
            "DestinationCidrBlock": "0.0.0.0/0",
            "NatGatewayId": "{{ createNatGw.natGwId }}",
            "RouteTableId": "{{ getMainRtb.mainRtbId }}"
          },
          "nextStep": "createPubRoute"
        },
        {
          "name": "createPubRoute",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateRoute",
            "DestinationCidrBlock": "0.0.0.0/0",
            "GatewayId": "{{ createIgw.igwId }}",
            "RouteTableId": "{{ createPubRtb.pubRtbId }}"
          },
          "nextStep": "setPubSubAssoc"
        },
        {
          "name": "setPubSubAssoc",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "AssociateRouteTable",
            "RouteTableId": "{{ createPubRtb.pubRtbId }}",
            "SubnetId": "{{ createPubSubnet.pubSubnetId }}"
          }
        },
        {
          "name": "createDhcpOptions",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateDhcpOptions",
            "DhcpConfigurations": [
              {
                "Key": "domain-name-servers",
                "Values": ["10.0.100.50,10.0.101.50"]
              },
              {
                "Key": "domain-name",
                "Values": ["sample.com"]
              }
            ]
          },
          "outputs": [
            {
              "Name": "dhcpOptionsId",
              "Selector": "$.DhcpOptions.DhcpOptionsId",
              "Type": "String"
            }
          ],
          "nextStep": "createDCSubnet1"
        },
        {
          "name": "createDCSubnet1",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateSubnet",
            "CidrBlock": "10.0.100.0/24",
            "AvailabilityZone": "us-west-2a",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "outputs": [
            {
              "Name": "firstSubnetId",
              "Selector": "$.Subnet.SubnetId",
              "Type": "String"
            }
          ],
          "nextStep": "createDCSubnet2"
        },
        {
          "name": "createDCSubnet2",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateSubnet",
            "CidrBlock": "10.0.101.0/24",
            "AvailabilityZone": "us-west-2b",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "outputs": [
            {
              "Name": "secondSubnetId",
              "Selector": "$.Subnet.SubnetId",
              "Type": "String"
            }
          ],
          "nextStep": "createDCSecGroup"
        },
        {
          "name": "createDCSecGroup",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "CreateSecurityGroup",
            "GroupName": "SampleDCSecGroup",
            "Description": "Security Group for Example Domain Controllers",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "outputs": [
            {
              "Name": "dcSecGroupId",
              "Selector": "$.GroupId",
              "Type": "String"
            }
          ],
          "nextStep": "authIngressDCTraffic"
        },
        {
          "name": "authIngressDCTraffic",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "AuthorizeSecurityGroupIngress",
            "GroupId": "{{ createDCSecGroup.dcSecGroupId }}",
            "IpPermissions": [
              {
                "FromPort": -1,
                "IpProtocol": "-1",
                "IpRanges": [
                  {
                    "CidrIp": "0.0.0.0/0",
                    "Description": "Allow all traffic between Domain Controllers"
                  }
                ]
              }
            ]
          },
          "nextStep": "verifyInstanceProfile"
        },
        {
          "name": "verifyInstanceProfile",
          "action": "aws:waitForAwsResourceProperty",
          "maxAttempts": 5,
          "onFailure": "Abort",
          "inputs": {
            "Service": "iam",
            "Api": "ListInstanceProfilesForRole",
            "RoleName": "sampleSSMInstanceRole",
            "PropertySelector": "$.InstanceProfiles[0].Arn",
            "DesiredValues": [
              "{{ createSSMInstanceProfile.instanceProfileArn }}"
            ]
          },
          "nextStep": "iamEventualConsistency"
        },
        {
          "name": "iamEventualConsistency",
          "action": "aws:sleep",
          "inputs": {
            "Duration": "PT2M"
          },
          "nextStep": "launchDC1"
        },
        {
          "name": "launchDC1",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "RunInstances",
            "BlockDeviceMappings": [
              {
                "DeviceName": "/dev/sda1",
                "Ebs": {
                  "DeleteOnTermination": true,
                  "VolumeSize": 50,
                  "VolumeType": "gp2"
                }
              },
              {
                "DeviceName": "xvdf",
                "Ebs": {
                  "DeleteOnTermination": true,
                  "VolumeSize": 100,
                  "VolumeType": "gp2"
                }
              }
            ],
            "IamInstanceProfile": {
              "Arn": "{{ createSSMInstanceProfile.instanceProfileArn }}"
            },
            "ImageId": "{{ getLatestWindowsAmi.amiId }}",
            "InstanceType": "t2.micro",
            "MaxCount": 1,
            "MinCount": 1,
            "PrivateIpAddress": "10.0.100.50",
            "SecurityGroupIds": [
              "{{ createDCSecGroup.dcSecGroupId }}"
            ],
            "SubnetId": "{{ createDCSubnet1.firstSubnetId }}",
            "TagSpecifications": [
              {
                "ResourceType": "instance",
                "Tags": [
                  {
                    "Key": "Name",
                    "Value": "SampleDC1"
                  }
                ]
              }
            ]
          },
          "outputs": [
            {
              "Name": "pdcInstanceId",
              "Selector": "$.Instances[0].InstanceId",
              "Type": "String"
            }
          ],
          "nextStep": "launchDC2"
        },
        {
          "name": "launchDC2",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "RunInstances",
            "BlockDeviceMappings": [
              {
                "DeviceName": "/dev/sda1",
                "Ebs": {
                  "DeleteOnTermination": true,
                  "VolumeSize": 50,
                  "VolumeType": "gp2"
                }
              },
              {
                "DeviceName": "xvdf",
                "Ebs": {
                  "DeleteOnTermination": true,
                  "VolumeSize": 100,
                  "VolumeType": "gp2"
                }
              }
            ],
            "IamInstanceProfile": {
              "Arn": "{{ createSSMInstanceProfile.instanceProfileArn }}"
            },
            "ImageId": "{{ getLatestWindowsAmi.amiId }}",
            "InstanceType": "t2.micro",
            "MaxCount": 1,
            "MinCount": 1,
            "PrivateIpAddress": "10.0.101.50",
            "SecurityGroupIds": [
              "{{ createDCSecGroup.dcSecGroupId }}"
            ],
            "SubnetId": "{{ createDCSubnet2.secondSubnetId }}",
            "TagSpecifications": [
              {
                "ResourceType": "instance",
                "Tags": [
                  {
                    "Key": "Name",
                    "Value": "SampleDC2"
                  }
                ]
              }
            ]
          },
          "outputs": [
            {
              "Name": "adcInstanceId",
              "Selector": "$.Instances[0].InstanceId",
              "Type": "String"
            }
          ],
          "nextStep": "verifyDCInstanceState"
        },
        {
          "name": "verifyDCInstanceState",
          "action": "aws:waitForAwsResourceProperty",
          "inputs": {
            "Service": "ec2",
            "Api": "DescribeInstanceStatus",
            "IncludeAllInstances": true,
            "InstanceIds": [
              "{{ launchDC1.pdcInstanceId }}",
              "{{ launchDC2.adcInstanceId }}"
            ],
            "PropertySelector": "$.InstanceStatuses[0].InstanceState.Name",
            "DesiredValues": [
              "running"
            ]
          },
          "nextStep": "verifyInstancesOnlineSSM"
        },
        {
          "name": "verifyInstancesOnlineSSM",
          "action": "aws:waitForAwsResourceProperty",
          "timeoutSeconds": 600,
          "inputs": {
            "Service": "ssm",
            "Api": "DescribeInstanceInformation",
            "InstanceInformationFilterList": [
              {
                "key": "InstanceIds",
                "valueSet": [
                  "{{ launchDC1.pdcInstanceId }}",
                  "{{ launchDC2.adcInstanceId }}"
                ]
              }
            ],
            "PropertySelector": "$.InstanceInformationList[0].PingStatus",
            "DesiredValues": [
              "Online"
            ]
          },
          "nextStep": "installADRoles"
        },
        {
          "name": "installADRoles",
          "action": "aws:runCommand",
          "inputs": {
            "DocumentName": "AWS-RunPowerShellScript",
            "InstanceIds": [
              "{{ launchDC1.pdcInstanceId }}",
              "{{ launchDC2.adcInstanceId }}"
            ],
            "Parameters": {
              "commands": [
                "try {",
                "  Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools",
                "}",
                "catch {",
                "  Write-Error \"Failed to install ADDS Role.\"",
                "}"
              ]
            }
          },
          "nextStep": "setAdminPassword"
        },
        {
          "name": "setAdminPassword",
          "action": "aws:runCommand",
          "inputs": {
            "DocumentName": "AWS-RunPowerShellScript",
            "InstanceIds": [
              "{{ launchDC1.pdcInstanceId }}"
            ],
            "Parameters": {
              "commands": [
                "net user Administrator \"sampleAdminPass123!\""
              ]
            }
          },
          "nextStep": "createForest"
        },
        {
          "name": "createForest",
          "action": "aws:runCommand",
          "inputs": {
            "DocumentName": "AWS-RunPowerShellScript",
            "InstanceIds": [
              "{{ launchDC1.pdcInstanceId }}"
            ],
            "Parameters": {
              "commands": [
                "$dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force",
                "try {",
                "   Install-ADDSForest -DomainName \"sample.com\" -DomainMode 6 -ForestMode 6 -InstallDNS -DatabasePath \"D:\\NTDS\" -SysvolPath \"D:\\SYSVOL\" -SafeModeAdministratorPassword $dsrmPass -Force",
                "}",
                "catch {",
                "   Write-Error $_",
                "}",
                "try {",
                "   Add-DnsServerForwarder -IPAddress \"10.0.100.2\"",
                "}",
                "catch {",
                "   Write-Error $_",
                "}"
              ]
            }
          },
          "nextStep": "associateDhcpOptions"
        },
        {
          "name": "associateDhcpOptions",
          "action": "aws:executeAwsApi",
          "onFailure": "Abort",
          "inputs": {
            "Service": "ec2",
            "Api": "AssociateDhcpOptions",
            "DhcpOptionsId": "{{ createDhcpOptions.dhcpOptionsId }}",
            "VpcId": "{{ createVpc.vpcId }}"
          },
          "nextStep": "waitForADServices"
        },
        {
          "name": "waitForADServices",
          "action": "aws:sleep",
          "inputs": {
            "Duration": "PT1M"
          },
          "nextStep": "promoteADC"
        },
        {
          "name": "promoteADC",
          "action": "aws:runCommand",
          "inputs": {
            "DocumentName": "AWS-RunPowerShellScript",
            "InstanceIds": [
              "{{ launchDC2.adcInstanceId }}"
            ],
            "Parameters": {
              "commands": [
                "ipconfig /renew",
                "$dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force",
                "$domAdminUser = \"sample\\Administrator\"",
                "$domAdminPass = \"sampleAdminPass123!\" | ConvertTo-SecureString -asPlainText -Force",
                "$domAdminCred = New-Object System.Management.Automation.PSCredential($domAdminUser,$domAdminPass)",
                "try {",
                "   Install-ADDSDomainController -DomainName \"sample.com\" -InstallDNS -DatabasePath \"D:\\NTDS\" -SysvolPath \"D:\\SYSVOL\" -SafeModeAdministratorPassword $dsrmPass -Credential $domAdminCred -Force",
                "}",
                "catch {",
                "   Write-Error $_",
                "}"
              ]
            }
          }
        }
      ]
    }
```

------

# Restore a root volume from the latest snapshot
<a name="automation-document-instance-recovery-example"></a>

The operating system on a root volume can become corrupted for various reasons. For example, following a patching operation, instances might fail to boot successfully due to a corrupted kernel or registry. Automating common troubleshooting tasks, like restoring a root volume from the latest snapshot taken before the patching operation, can reduce downtime and expedite your troubleshooting efforts. AWS Systems Manager Automation actions can help you accomplish this. Automation is a tool in AWS Systems Manager.

The following example AWS Systems Manager runbook performs these actions: 
+ Uses the `aws:executeAwsApi` automation action to retrieve details from the root volume of the instance.
+ Uses the `aws:executeScript` automation action to retrieve the latest snapshot for the root volume.
+ Uses the `aws:branch` automation action to continue the automation if a snapshot is found for the root volume.

------
#### [ YAML ]

```
    ---
    description: Custom Automation Troubleshooting Example
    schemaVersion: '0.3'
    assumeRole: "{{ AutomationAssumeRole }}"
    parameters:
      AutomationAssumeRole:
        type: String
        description: "(Required) The ARN of the role that allows Automation to perform
          the actions on your behalf. If no role is specified, Systems Manager Automation
          uses your IAM permissions to use this runbook."
        default: ''
      InstanceId:
          type: String
          description: "(Required) The Instance Id whose root EBS volume you want to restore the latest Snapshot."
          default: ''
    mainSteps:
    - name: getInstanceDetails
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: DescribeInstances
        InstanceIds:
        - "{{ InstanceId }}"
      outputs:
        - Name: availabilityZone
          Selector: "$.Reservations[0].Instances[0].Placement.AvailabilityZone"
          Type: String
        - Name: rootDeviceName
          Selector: "$.Reservations[0].Instances[0].RootDeviceName"
          Type: String
      nextStep: getRootVolumeId
    - name: getRootVolumeId
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: DescribeVolumes
        Filters:
        -  Name: attachment.device
           Values: ["{{ getInstanceDetails.rootDeviceName }}"]
        -  Name: attachment.instance-id
           Values: ["{{ InstanceId }}"]
      outputs:
        - Name: rootVolumeId
          Selector: "$.Volumes[0].VolumeId"
          Type: String
      nextStep: getSnapshotsByStartTime
    - name: getSnapshotsByStartTime
      action: aws:executeScript
      timeoutSeconds: 45
      onFailure: Abort
      inputs:
        Runtime: python3.11
        Handler: getSnapshotsByStartTime
        InputPayload:
          rootVolumeId : "{{ getRootVolumeId.rootVolumeId }}"
        Script: |-
          def getSnapshotsByStartTime(events,context):
            import boto3
    
            #Initialize client
            ec2 = boto3.client('ec2')
            rootVolumeId = events['rootVolumeId']
            snapshotsQuery = ec2.describe_snapshots(
              Filters=[
                {
                  "Name": "volume-id",
                  "Values": [rootVolumeId]
                }
              ]
            )
            if not snapshotsQuery['Snapshots']:
              noSnapshotFoundString = "NoSnapshotFound"
              return { 'noSnapshotFound' : noSnapshotFoundString }
            else:
              jsonSnapshots = snapshotsQuery['Snapshots']
              sortedSnapshots = sorted(jsonSnapshots, key=lambda k: k['StartTime'], reverse=True)
              latestSortedSnapshotId = sortedSnapshots[0]['SnapshotId']
              return { 'latestSnapshotId' : latestSortedSnapshotId }
      outputs:
      - Name: Payload
        Selector: $.Payload
        Type: StringMap
      - Name: latestSnapshotId
        Selector: $.Payload.latestSnapshotId
        Type: String
      - Name: noSnapshotFound
        Selector: $.Payload.noSnapshotFound
        Type: String 
      nextStep: branchFromResults
    - name: branchFromResults
      action: aws:branch
      onFailure: Abort
      inputs:
        Choices:
        - NextStep: createNewRootVolumeFromSnapshot
          Not:
            Variable: "{{ getSnapshotsByStartTime.noSnapshotFound }}"
            StringEquals: "NoSnapshotFound"
      isEnd: true
    - name: createNewRootVolumeFromSnapshot
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: CreateVolume
        AvailabilityZone: "{{ getInstanceDetails.availabilityZone }}"
        SnapshotId: "{{ getSnapshotsByStartTime.latestSnapshotId }}"
      outputs:
        - Name: newRootVolumeId
          Selector: "$.VolumeId"
          Type: String
      nextStep: stopInstance
    - name: stopInstance
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: StopInstances
        InstanceIds:
        - "{{ InstanceId }}"
      nextStep: verifyVolumeAvailability
    - name: verifyVolumeAvailability
      action: aws:waitForAwsResourceProperty
      timeoutSeconds: 120
      inputs:
        Service: ec2
        Api: DescribeVolumes
        VolumeIds:
        - "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
        PropertySelector: "$.Volumes[0].State"
        DesiredValues:
        - "available"
      nextStep: verifyInstanceStopped
    - name: verifyInstanceStopped
      action: aws:waitForAwsResourceProperty
      timeoutSeconds: 120
      inputs:
        Service: ec2
        Api: DescribeInstances
        InstanceIds:
        - "{{ InstanceId }}"
        PropertySelector: "$.Reservations[0].Instances[0].State.Name"
        DesiredValues:
        - "stopped"
      nextStep: detachRootVolume
    - name: detachRootVolume
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: DetachVolume
        VolumeId: "{{ getRootVolumeId.rootVolumeId }}"
      nextStep: verifyRootVolumeDetached
    - name: verifyRootVolumeDetached
      action: aws:waitForAwsResourceProperty
      timeoutSeconds: 30
      inputs:
        Service: ec2
        Api: DescribeVolumes
        VolumeIds:
        - "{{ getRootVolumeId.rootVolumeId }}"
        PropertySelector: "$.Volumes[0].State"
        DesiredValues:
        - "available"
      nextStep: attachNewRootVolume
    - name: attachNewRootVolume
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: AttachVolume
        Device: "{{ getInstanceDetails.rootDeviceName }}"
        InstanceId: "{{ InstanceId }}"
        VolumeId: "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
      nextStep: verifyNewRootVolumeAttached
    - name: verifyNewRootVolumeAttached
      action: aws:waitForAwsResourceProperty
      timeoutSeconds: 30
      inputs:
        Service: ec2
        Api: DescribeVolumes
        VolumeIds:
        - "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
        PropertySelector: "$.Volumes[0].Attachments[0].State"
        DesiredValues:
        - "attached"
      nextStep: startInstance
    - name: startInstance
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: StartInstances
        InstanceIds:
        - "{{ InstanceId }}"
```

------
#### [ JSON ]

```
    {
       "description": "Custom Automation Troubleshooting Example",
       "schemaVersion": "0.3",
       "assumeRole": "{{ AutomationAssumeRole }}",
       "parameters": {
          "AutomationAssumeRole": {
             "type": "String",
             "description": "(Required) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to run this runbook.",
             "default": ""
          },
          "InstanceId": {
             "type": "String",
             "description": "(Required) The Instance Id whose root EBS volume you want to restore the latest Snapshot.",
             "default": ""
          }
       },
       "mainSteps": [
          {
             "name": "getInstanceDetails",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeInstances",
                "InstanceIds": [
                   "{{ InstanceId }}"
                ]
             },
             "outputs": [
                {
                   "Name": "availabilityZone",
                   "Selector": "$.Reservations[0].Instances[0].Placement.AvailabilityZone",
                   "Type": "String"
                },
                {
                   "Name": "rootDeviceName",
                   "Selector": "$.Reservations[0].Instances[0].RootDeviceName",
                   "Type": "String"
                }
             ],
             "nextStep": "getRootVolumeId"
          },
          {
             "name": "getRootVolumeId",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeVolumes",
                "Filters": [
                   {
                      "Name": "attachment.device",
                      "Values": [
                         "{{ getInstanceDetails.rootDeviceName }}"
                      ]
                   },
                   {
                      "Name": "attachment.instance-id",
                      "Values": [
                         "{{ InstanceId }}"
                      ]
                   }
                ]
             },
             "outputs": [
                {
                   "Name": "rootVolumeId",
                   "Selector": "$.Volumes[0].VolumeId",
                   "Type": "String"
                }
             ],
             "nextStep": "getSnapshotsByStartTime"
          },
          {
             "name": "getSnapshotsByStartTime",
             "action": "aws:executeScript",
             "timeoutSeconds": 45,
             "onFailure": "Continue",
             "inputs": {
                "Runtime": "python3.11",
                "Handler": "getSnapshotsByStartTime",
                "InputPayload": {
                   "rootVolumeId": "{{ getRootVolumeId.rootVolumeId }}"
                },
                "Attachment": "getSnapshotsByStartTime.py"
             },
             "outputs": [
                {
                   "Name": "Payload",
                   "Selector": "$.Payload",
                   "Type": "StringMap"
                },
                {
                   "Name": "latestSnapshotId",
                   "Selector": "$.Payload.latestSnapshotId",
                   "Type": "String"
                },
                {
                   "Name": "noSnapshotFound",
                   "Selector": "$.Payload.noSnapshotFound",
                   "Type": "String"
                }
             ],
             "nextStep": "branchFromResults"
          },
          {
             "name": "branchFromResults",
             "action": "aws:branch",
             "onFailure": "Abort",
             "inputs": {
                "Choices": [
                   {
                      "NextStep": "createNewRootVolumeFromSnapshot",
                      "Not": {
                         "Variable": "{{ getSnapshotsByStartTime.noSnapshotFound }}",
                         "StringEquals": "NoSnapshotFound"
                      }
                   }
                ]
             },
             "isEnd": true
          },
          {
             "name": "createNewRootVolumeFromSnapshot",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "CreateVolume",
                "AvailabilityZone": "{{ getInstanceDetails.availabilityZone }}",
                "SnapshotId": "{{ getSnapshotsByStartTime.latestSnapshotId }}"
             },
             "outputs": [
                {
                   "Name": "newRootVolumeId",
                   "Selector": "$.VolumeId",
                   "Type": "String"
                }
             ],
             "nextStep": "stopInstance"
          },
          {
             "name": "stopInstance",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "StopInstances",
                "InstanceIds": [
                   "{{ InstanceId }}"
                ]
             },
             "nextStep": "verifyVolumeAvailability"
          },
          {
             "name": "verifyVolumeAvailability",
             "action": "aws:waitForAwsResourceProperty",
             "timeoutSeconds": 120,
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeVolumes",
                "VolumeIds": [
                   "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
                ],
                "PropertySelector": "$.Volumes[0].State",
                "DesiredValues": [
                   "available"
                ]
             },
             "nextStep": "verifyInstanceStopped"
          },
          {
             "name": "verifyInstanceStopped",
             "action": "aws:waitForAwsResourceProperty",
             "timeoutSeconds": 120,
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeInstances",
                "InstanceIds": [
                   "{{ InstanceId }}"
                ],
                "PropertySelector": "$.Reservations[0].Instances[0].State.Name",
                "DesiredValues": [
                   "stopped"
                ]
             },
             "nextStep": "detachRootVolume"
          },
          {
             "name": "detachRootVolume",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "DetachVolume",
                "VolumeId": "{{ getRootVolumeId.rootVolumeId }}"
             },
             "nextStep": "verifyRootVolumeDetached"
          },
          {
             "name": "verifyRootVolumeDetached",
             "action": "aws:waitForAwsResourceProperty",
             "timeoutSeconds": 30,
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeVolumes",
                "VolumeIds": [
                   "{{ getRootVolumeId.rootVolumeId }}"
                ],
                "PropertySelector": "$.Volumes[0].State",
                "DesiredValues": [
                   "available"
                ]
             },
             "nextStep": "attachNewRootVolume"
          },
          {
             "name": "attachNewRootVolume",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "AttachVolume",
                "Device": "{{ getInstanceDetails.rootDeviceName }}",
                "InstanceId": "{{ InstanceId }}",
                "VolumeId": "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
             },
             "nextStep": "verifyNewRootVolumeAttached"
          },
          {
             "name": "verifyNewRootVolumeAttached",
             "action": "aws:waitForAwsResourceProperty",
             "timeoutSeconds": 30,
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeVolumes",
                "VolumeIds": [
                   "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}"
                ],
                "PropertySelector": "$.Volumes[0].Attachments[0].State",
                "DesiredValues": [
                   "attached"
                ]
             },
             "nextStep": "startInstance"
          },
          {
             "name": "startInstance",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "StartInstances",
                "InstanceIds": [
                   "{{ InstanceId }}"
                ]
             }
          }
       ],
       "files": {
            "getSnapshotsByStartTime.py": {
                "checksums": {
                    "sha256": "sampleETagValue"
                }
            }
        }
    }
```

------

# Create an AMI and cross-Region copy
<a name="automation-document-backup-maintenance-example"></a>

Creating an Amazon Machine Image (AMI) of an instance is a common process used in backup and recovery. You might also choose to copy an AMI to another AWS Region as part of a disaster recovery architecture. Automating common maintenance tasks can reduce downtime if an issue requires failover. AWS Systems Manager Automation actions can help you accomplish this. Automation is a tool in AWS Systems Manager.

The following example AWS Systems Manager runbook performs these actions:
+ Uses the `aws:executeAwsApi` automation action to create an AMI.
+ Uses the `aws:waitForAwsResourceProperty` automation action to confirm the availability of the AMI.
+ Uses the `aws:executeScript` automation action to copy the AMI to the destination Region.

------
#### [ YAML ]

```
    ---
    description: Custom Automation Backup and Recovery Example
    schemaVersion: '0.3'
    assumeRole: "{{ AutomationAssumeRole }}"
    parameters:
      AutomationAssumeRole:
        type: String
        description: "(Required) The ARN of the role that allows Automation to perform
          the actions on your behalf. If no role is specified, Systems Manager Automation
          uses your IAM permissions to use this runbook."
        default: ''
      InstanceId:
        type: String
        description: "(Required) The ID of the EC2 instance."
        default: ''
    mainSteps:
    - name: createImage
      action: aws:executeAwsApi
      onFailure: Abort
      inputs:
        Service: ec2
        Api: CreateImage
        InstanceId: "{{ InstanceId }}"
        Name: "Automation Image for {{ InstanceId }}"
        NoReboot: false
      outputs:
        - Name: newImageId
          Selector: "$.ImageId"
          Type: String
      nextStep: verifyImageAvailability
    - name: verifyImageAvailability
      action: aws:waitForAwsResourceProperty
      timeoutSeconds: 600
      inputs:
        Service: ec2
        Api: DescribeImages
        ImageIds:
        - "{{ createImage.newImageId }}"
        PropertySelector: "$.Images[0].State"
        DesiredValues:
        - available
      nextStep: copyImage
    - name: copyImage
      action: aws:executeScript
      timeoutSeconds: 45
      onFailure: Abort
      inputs:
        Runtime: python3.11
        Handler: crossRegionImageCopy
        InputPayload:
          newImageId : "{{ createImage.newImageId }}"
        Script: |-
          def crossRegionImageCopy(events,context):
            import boto3
    
            #Initialize client
            ec2 = boto3.client('ec2', region_name='us-east-1')
            newImageId = events['newImageId']
    
            ec2.copy_image(
              Name='DR Copy for ' + newImageId,
              SourceImageId=newImageId,
              SourceRegion='us-west-2'
            )
```

------
#### [ JSON ]

```
    {
       "description": "Custom Automation Backup and Recovery Example",
       "schemaVersion": "0.3",
       "assumeRole": "{{ AutomationAssumeRole }}",
       "parameters": {
          "AutomationAssumeRole": {
             "type": "String",
             "description": "(Required) The ARN of the role that allows Automation to perform\nthe actions on your behalf. If no role is specified, Systems Manager Automation\nuses your IAM permissions to run this runbook.",
             "default": ""
          },
          "InstanceId": {
             "type": "String",
             "description": "(Required) The ID of the EC2 instance.",
             "default": ""
          }
       },
       "mainSteps": [
          {
             "name": "createImage",
             "action": "aws:executeAwsApi",
             "onFailure": "Abort",
             "inputs": {
                "Service": "ec2",
                "Api": "CreateImage",
                "InstanceId": "{{ InstanceId }}",
                "Name": "Automation Image for {{ InstanceId }}",
                "NoReboot": false
             },
             "outputs": [
                {
                   "Name": "newImageId",
                   "Selector": "$.ImageId",
                   "Type": "String"
                }
             ],
             "nextStep": "verifyImageAvailability"
          },
          {
             "name": "verifyImageAvailability",
             "action": "aws:waitForAwsResourceProperty",
             "timeoutSeconds": 600,
             "inputs": {
                "Service": "ec2",
                "Api": "DescribeImages",
                "ImageIds": [
                   "{{ createImage.newImageId }}"
                ],
                "PropertySelector": "$.Images[0].State",
                "DesiredValues": [
                   "available"
                ]
             },
             "nextStep": "copyImage"
          },
          {
             "name": "copyImage",
             "action": "aws:executeScript",
             "timeoutSeconds": 45,
             "onFailure": "Abort",
             "inputs": {
                "Runtime": "python3.11",
                "Handler": "crossRegionImageCopy",
                "InputPayload": {
                   "newImageId": "{{ createImage.newImageId }}"
                },
                "Attachment": "crossRegionImageCopy.py"
             }
          }
       ],
       "files": {
            "crossRegionImageCopy.py": {
                "checksums": {
                    "sha256": "sampleETagValue"
                }
            }
        }
    }
```

------

# Creating input parameters that populate AWS resources
<a name="populating-input-parameters"></a>

Automation, a tool in Systems Manager, populates AWS resources in the AWS Management Console that match the resource type you define for an input parameter. Resources in your AWS account that match the resource type are displayed in a dropdown list for you to choose. You can define input parameter types for Amazon Elastic Compute Cloud (Amazon EC2) instances, Amazon Simple Storage Service (Amazon S3) buckets, and AWS Identity and Access Management (IAM) roles. The supported type definitions and the regular expressions used to locate matching resources are as follows:
+ `AWS::EC2::Instance::Id` - `^m?i-([a-z0-9]{8}|[a-z0-9]{17})$`
+ `List<AWS::EC2::Instance::Id>` - `^m?i-([a-z0-9]{8}|[a-z0-9]{17})$`
+ `AWS::S3::Bucket::Name` - `^[0-9a-z][a-z0-9\\-\\.]{3,63}$`
+ `List<AWS::S3::Bucket::Name>` - `^[0-9a-z][a-z0-9\\-\\.]{3,63}$`
+ `AWS::IAM::Role::Arn` - `^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):iam::[0-9]{12}:role/.*$`
+ `List<AWS::IAM::Role::Arn>` - `^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):iam::[0-9]{12}:role/.*$`

The following is an example of input parameter types defined in runbook content.

------
#### [ YAML ]

```
description: Enables encryption on an Amazon S3 bucket
schemaVersion: '0.3'
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
  BucketName:
    type: 'AWS::S3::Bucket::Name'
    description: (Required) The name of the Amazon S3 bucket you want to encrypt.
  SSEAlgorithm:
    type: String
    description: (Optional) The server-side encryption algorithm to use for the default encryption.
    default: AES256
  AutomationAssumeRole:
    type: 'AWS::IAM::Role::Arn'
    description: (Optional) The Amazon Resource Name (ARN) of the role that allows Automation to perform the actions on your behalf.
    default: ''
mainSteps:
  - name: enableBucketEncryption
    action: 'aws:executeAwsApi'
    inputs:
      Service: s3
      Api: PutBucketEncryption
      Bucket: '{{BucketName}}'
      ServerSideEncryptionConfiguration:
        Rules:
          - ApplyServerSideEncryptionByDefault:
              SSEAlgorithm: '{{SSEAlgorithm}}'
    isEnd: true
```

------
#### [ JSON ]

```
{
   "description": "Enables encryption on an Amazon S3 bucket",
   "schemaVersion": "0.3",
   "assumeRole": "{{ AutomationAssumeRole }}",
   "parameters": {
      "BucketName": {
         "type": "AWS::S3::Bucket::Name",
         "description": "(Required) The name of the Amazon S3 bucket you want to encrypt."
      },
      "SSEAlgorithm": {
         "type": "String",
         "description": "(Optional) The server-side encryption algorithm to use for the default encryption.",
         "default": "AES256"
      },
      "AutomationAssumeRole": {
         "type": "AWS::IAM::Role::Arn",
         "description": "(Optional) The Amazon Resource Name (ARN) of the role that allows Automation to perform the actions on your behalf.",
         "default": ""
      }
   },
   "mainSteps": [
      {
         "name": "enableBucketEncryption",
         "action": "aws:executeAwsApi",
         "inputs": {
            "Service": "s3",
            "Api": "PutBucketEncryption",
            "Bucket": "{{BucketName}}",
            "ServerSideEncryptionConfiguration": {
               "Rules": [
                  {
                     "ApplyServerSideEncryptionByDefault": {
                        "SSEAlgorithm": "{{SSEAlgorithm}}"
                     }
                  }
               ]
            }
         },
         "isEnd": true
      }
   ]
}
```

------

# Using Document Builder to create runbooks
<a name="automation-document-builder"></a>

If the AWS Systems Manager public runbooks don't support all the actions you want to perform on your AWS resources, you can create your own runbooks. To create a custom runbook, you can manually create a local YAML or JSON format file with the appropriate automation actions. Alternatively, you can use Document Builder in the Systems Manager Automation console to build a custom runbook.

Using Document Builder, you can add automation actions to your custom runbook and provide the required parameters without having to use JSON or YAML syntax. After you add steps and create the runbook, the system converts the actions you've added into the YAML format that Systems Manager can use to run automation.

Runbooks support the use of Markdown, a markup language, which allows you to add wiki-style descriptions to runbooks and individual steps within the runbook. For more information about using Markdown, see [Using Markdown in AWS](https://docs.aws.amazon.com/general/latest/gr/aws-markdown.html).

## Create a runbook using Document Builder
<a name="create-runbook"></a>

**Before you begin**  
We recommend that you read about the different actions that you can use within a runbook. For more information, see [Systems Manager Automation actions reference](automation-actions.md).

**To create a runbook using Document Builder**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Documents**.

1. Choose **Create automation**.

1. For **Name**, enter a descriptive name for the runbook.

1. For **Document description**, provide the markdown style description for the runbook. You can provide instructions for using the runbook, numbered steps, or any other type of information to describe the runbook. Refer to the default text for information about formatting your content.
**Tip**  
Toggle between **Hide preview** and **Show preview** to see what your description content looks like as you compose.

1. (Optional) For **Assume role**, enter the name or ARN of a service role to perform actions on your behalf. If you don't specify a role, Automation uses the access permissions of the user who runs the automation.
**Important**  
For runbooks not owned by Amazon that use the `aws:executeScript` action, a role must be specified. For information, see [Permissions for using runbooks](automation-document-script-considerations.md#script-permissions).

1. (Optional) For **Outputs**, enter any outputs for the automation of this runbook to make available for other processes. 

   For example, if your runbook creates a new AMI, you might specify ["CreateImage.ImageId"], and then use this output to create new instances in a subsequent automation.

1. (Optional) Expand the **Input parameters** section and do the following.

   1. For **Parameter name**, enter a descriptive name for the runbook parameter you're creating.

   1. For **Type**, choose a type for the parameter, such as `String` or `MapList`.

   1. For **Required**, do one of the following: 
      + Choose **Yes** if a value for this runbook parameter must be supplied at runtime.
      + Choose **No** if the parameter isn't required, and (optional) enter a default parameter value in **Default value**.

   1. For **Description**, enter a description for the runbook parameter.
**Note**  
To add more runbook parameters, choose **Add a parameter**. To remove a runbook parameter, choose the **X** (Remove) button.

1. (Optional) Expand the **Target type** section and choose a target type to define the kinds of resources the automation can run on. For example, to use a runbook on EC2 instances, choose `/AWS::EC2::Instance`.
**Note**  
If you specify a value of '`/`', the runbook can run on all types of resources. For a list of valid resource types, see [AWS Resource Types Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) in the *AWS CloudFormation User Guide*.

1. (Optional) Expand the **Document tags** section and enter one or more tag key-value pairs to apply to the runbook. Tags make it easier to identify, organize, and search for resources.

1. In the **Step 1** section, provide the following information.
   + For **Step name**, enter a descriptive name for the first step of the automation.
   + For **Action type**, select the action type to use for this step.

     For a list and information about the available action types, see [Systems Manager Automation actions reference](automation-actions.md).
   + For **Description**, enter a description for the automation step. You can use Markdown to format your text.
   + Depending on the **Action type** selected, enter the required inputs for the action type in the **Step inputs** section. For example, if you selected the action `aws:approve`, you must specify a value for the `Approvers` property.

     For information about the step input fields, see the entry in [Systems Manager Automation actions reference](automation-actions.md) for the action type you selected. For example: [`aws:executeStateMachine` – Run an AWS Step Functions state machine](automation-action-executeStateMachine.md).
   + (Optional) For **Additional inputs**, provide any additional input values needed for your runbook. The available input types depend on the action type you selected for the step. (Note that some action types require input values.)
**Note**  
To add more inputs, choose **Add optional input**. To remove an input, choose the **X** (Remove) button.
   + (Optional) For **Outputs**, enter any outputs for this step to make available for other processes.
**Note**  
**Outputs** isn't available for all action types.
   + (Optional) Expand the **Common properties** section and specify properties for the actions that are common to all automation actions. For example, for **Timeout seconds**, you can provide a value in seconds to specify how long the step can run before it's stopped.

     For more information, see [Properties shared by all actions](automation-actions.md#automation-common).
**Note**  
To add more steps, select **Add step** and repeat the procedure for creating a step. To remove a step, choose **Remove step**.

1. Choose **Create automation** to save the runbook.

## Create a runbook that runs scripts
<a name="create-runbook-scripts"></a>

The following procedure shows how to use Document Builder in the AWS Systems Manager Automation console to create a custom runbook that runs a script.

The first step of the runbook you create runs a script to launch an Amazon Elastic Compute Cloud (Amazon EC2) instance. The second step runs another script to monitor for the instance status check to change to `ok`. Then, an overall status of `Success` is reported for the automation.

**Before you begin**  
Make sure you have completed the following steps:
+ Verify that you have administrator privileges, or that you have been granted the appropriate permissions to access Systems Manager in AWS Identity and Access Management (IAM). 

  For information, see [Verifying user access for runbooks](automation-setup.md#automation-setup-user-access).
+ Verify that you have an IAM service role for Automation (also known as an *assume role*) in your AWS account. The role is required because this walkthrough uses the `aws:executeScript` action. 

  For information about creating this role, see [Configuring a service role (assume role) access for automations](automation-setup.md#automation-setup-configure-role). 

  For information about the IAM service role requirement for running `aws:executeScript`, see [Permissions for using runbooks](automation-document-script-considerations.md#script-permissions).
+ Verify that you have permission to launch EC2 instances. 

  For information, see [IAM and Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UsingIAM.html#intro-to-iam) in the *Amazon EC2 User Guide*.

**To create a custom runbook that runs scripts using Document Builder**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Documents**.

1. Choose **Create automation**.

1. For **Name**, type this descriptive name for the runbook: **LaunchInstanceAndCheckStatus**.

1. (Optional) For **Document description**, replace the default text with a description for this runbook, using Markdown. The following is an example.

   ```
   ##Title: LaunchInstanceAndCheckState
       -----
       **Purpose**: This runbook first launches an EC2 instance using the AMI ID provided in the parameter ```imageId```. The second step of this runbook continuously checks the instance status check value for the launched instance until the status ```ok``` is returned.
       
       ##Parameters:
       -----
       Name | Type | Description | Default Value
       ------------- | ------------- | ------------- | -------------
       assumeRole | String | (Optional) The ARN of the role that allows Automation to perform the actions on your behalf. | -
       imageId  | String | (Optional) The AMI ID to use for launching the instance. The default value uses the latest Amazon Linux 2023 AMI ID available. | {{ ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64 }}
   ```

1. For **Assume role**, enter the ARN of the IAM service role for Automation (Assume role) for the automation, in the format **arn:aws:iam::111122223333:role/AutomationServiceRole**. Substitute your AWS account ID for 111122223333.

   The role you specify is used to provide the permissions needed to start the automation.
**Important**  
For runbooks not owned by Amazon that use the `aws:executeScript` action, a role must be specified. For information, see [Permissions for using runbooks](automation-document-script-considerations.md#script-permissions).

1. Expand **Input parameters** and do the following.

   1. For **Parameter name**, enter **imageId**.

   1. For **Type**, choose **String**.

   1. For **Required**, choose `No`. 

   1. For **Default value**, enter the following.

      ```
      {{ ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64 }}
      ```
**Note**  
This value launches an Amazon EC2 instance using the latest Amazon Linux 2023 Amazon Machine Image (AMI) ID. If you want to use a different AMI, replace the value with your AMI ID.

   1. For **Description**, enter the following.

      ```
      (Optional) The AMI ID to use for launching the instance. The default value uses the latest released Amazon Linux 2023 AMI ID.
      ```

1. Choose **Add a parameter** to create the second parameter, **tagValue**, and enter the following.

   1. For **Parameter name**, enter **tagValue**.

   1. For **Type**, choose **String**.

   1. For **Required**, choose `No`. 

   1. For **Default value**, enter **LaunchedBySsmAutomation**. This adds the tag key-pair value `Name:LaunchedBySsmAutomation` to the instance.

   1. For **Description**, enter the following.

      ```
      (Optional) The tag value to add to the instance. The default value is LaunchedBySsmAutomation.
      ```

1. Choose **Add a parameter** to create the third parameter, **instanceType**, and enter the following information.

   1. For **Parameter name**, enter **instanceType**.

   1. For **Type**, choose **String**.

   1. For **Required**, choose `No`. 

   1. For **Default value**, enter **t2.micro**.

   1. For **Parameter description**, enter the following.

      ```
      (Optional) The instance type to use for the instance. The default value is t2.micro.
      ```

1. Expand **Target type** and choose **"/"**.

1. (Optional) Expand **Document tags** to apply resource tags to your runbook. For **Tag key**, enter **Purpose**, and for **Tag value**, enter **LaunchInstanceAndCheckState**.

1. In the **Step 1** section, complete the following steps.

   1. For **Step name**, enter this descriptive step name for the first step of the automation: **LaunchEc2Instance**.

   1. For **Action type**, choose **Run a script** (**aws:executeScript**).

   1. For **Description**, enter a description for the automation step, such as the following.

      ```
      **About This Step**
          
          This step first launches an EC2 instance using the ```aws:executeScript``` action and the provided script.
      ```

   1. Expand **Inputs**.

   1. For **Runtime**, choose the runtime language to use to run the provided script.

   1. For **Handler**, enter **launch\$1instance**. This is the function name declared in the following script.
**Note**  
This is not required for PowerShell.

   1. For **Script**, replace the default contents with the following. Be sure to match the script with the corresponding runtime value.

------
#### [ Python ]

      ```
      def launch_instance(events, context):
            import boto3
            ec2 = boto3.client('ec2')
          
            image_id = events['image_id']
            tag_value = events['tag_value']
            instance_type = events['instance_type']
          
            tag_config = {'ResourceType': 'instance', 'Tags': [{'Key':'Name', 'Value':tag_value}]}
          
            res = ec2.run_instances(ImageId=image_id, InstanceType=instance_type, MaxCount=1, MinCount=1, TagSpecifications=[tag_config])
          
            instance_id = res['Instances'][0]['InstanceId']
          
            print('[INFO] 1 EC2 instance is successfully launched', instance_id)
          
            return { 'InstanceId' : instance_id }
      ```

------
#### [ PowerShell ]

      ```
      Install-Module AWS.Tools.EC2 -Force
          Import-Module AWS.Tools.EC2
          
          $payload = $env:InputPayload | ConvertFrom-Json
          
          $imageid = $payload.image_id
          
          $tagvalue = $payload.tag_value
          
          $instanceType = $payload.instance_type
          
          $type = New-Object Amazon.EC2.InstanceType -ArgumentList $instanceType
          
          $resource = New-Object Amazon.EC2.ResourceType -ArgumentList 'instance'
          
          $tag = @{Key='Name';Value=$tagValue}
          
          $tagSpecs = New-Object Amazon.EC2.Model.TagSpecification
          
          $tagSpecs.ResourceType = $resource
          
          $tagSpecs.Tags.Add($tag)
          
          $res = New-EC2Instance -ImageId $imageId -MinCount 1 -MaxCount 1 -InstanceType $type -TagSpecification $tagSpecs
          
          return @{'InstanceId'=$res.Instances.InstanceId}
      ```

------

   1. Expand **Additional inputs**. 

   1. For **Input name**, choose **InputPayload**. For **Input value**, enter the following YAML data. 

      ```
      image_id: "{{ imageId }}"
          tag_value: "{{ tagValue }}"
          instance_type: "{{ instanceType }}"
      ```

1. Expand **Outputs** and do the following:
   + For **Name**, enter **payload**.
   + For **Selector**, enter **\$1.Payload**.
   + For **Type**, choose `StringMap`.

1. Choose **Add step** to add a second step to the runbook. The second step queries the status of the instance launched in Step 1 and waits until the status returned is `ok`.

1. In the **Step 2** section, do the following.

   1. For **Step name**, enter this descriptive name for the second step of the automation: **WaitForInstanceStatusOk**.

   1. For **Action type**, choose **Run a script** (**aws:executeScript**).

   1. For **Description**, enter a description for the automation step, such as the following.

      ```
      **About This Step**
          
          The script continuously polls the instance status check value for the instance launched in Step 1 until the ```ok``` status is returned.
      ```

   1. For **Runtime**, choose the runtime language to be used for executing the provided script.

   1. For **Handler**, enter **poll\$1instance**. This is the function name declared in the following script.
**Note**  
This is not required for PowerShell.

   1. For **Script**, replace the default contents with the following. Be sure to match the script with the corresponding runtime value.

------
#### [ Python ]

      ```
      def poll_instance(events, context):
            import boto3
            import time
          
            ec2 = boto3.client('ec2')
          
            instance_id = events['InstanceId']
          
            print('[INFO] Waiting for instance status check to report ok', instance_id)
          
            instance_status = "null"
          
            while True:
              res = ec2.describe_instance_status(InstanceIds=[instance_id])
          
              if len(res['InstanceStatuses']) == 0:
                print("Instance status information is not available yet")
                time.sleep(5)
                continue
          
              instance_status = res['InstanceStatuses'][0]['InstanceStatus']['Status']
          
              print('[INFO] Polling to get status of the instance', instance_status)
          
              if instance_status == 'ok':
                break
          
              time.sleep(10)
          
            return {'Status': instance_status, 'InstanceId': instance_id}
      ```

------
#### [ PowerShell ]

      ```
          Install-Module AWS.Tools.EC2 -Force
          
          $inputPayload = $env:InputPayload | ConvertFrom-Json
          
          $instanceId = $inputPayload.payload.InstanceId
          
          $status = Get-EC2InstanceStatus -InstanceId $instanceId
          
          while ($status.Status.Status -ne 'ok'){
             Write-Host 'Polling get status of the instance', $instanceId
          
             Start-Sleep -Seconds 5
          
             $status = Get-EC2InstanceStatus -InstanceId $instanceId
          }
          
          return @{Status = $status.Status.Status; InstanceId = $instanceId}
      ```

------

   1. Expand **Additional inputs**. 

   1. For **Input name**, choose **InputPayload**. For **Input value**, enter the following:

      ```
      {{ LaunchEc2Instance.payload }}
      ```

1. Choose **Create automation** to save the runbook.

# Using scripts in runbooks
<a name="automation-document-script-considerations"></a>

Automation runbooks support running scripts as part of the automation. Automation is a tool in AWS Systems Manager. By using runbooks, you can run scripts directly in AWS without creating a separate compute environment to run your scripts. Because runbooks can run script steps along with other automation step types, such as approvals, you can manually intervene in critical or ambiguous situations. You can send the output from `aws:executeScript` actions in your runbooks to Amazon CloudWatch Logs. For more information, see [Logging Automation action output with CloudWatch Logs](automation-action-logging.md).

## Permissions for using runbooks
<a name="script-permissions"></a>

To use a runbook, Systems Manager must use the permissions of an AWS Identity and Access Management (IAM) role. The method that Automation uses to determine which role's permissions to use depends on a few factors, and whether a step uses the `aws:executeScript` action. 

For runbooks that don't use `aws:executeScript`, Automation uses one of two sources of permissions:
+ The permissions of an IAM service role, or Assume role, that is specified in the runbook or passed in as a parameter.
+ If no IAM service role is specified, the permissions of the user who started the automation. 

When a step in a runbook includes the `aws:executeScript` action, however, an IAM service role (Assume role) is always required if the Python or PowerShell script specified for the action is calling any AWS API operations. Automation checks for this role in the following order:
+ The permissions of an IAM service role, or Assume role, that is specified in the runbook or passed in as a parameter.
+ If no role is found, Automation attempts to run the Python or PowerShell script specified for `aws:executeScript` without any permissions. If the script is calling an AWS API operation (for example the Amazon EC2 `CreateImage` operation), or attempting to act on an AWS resource (such as an EC2 instance), the step containing the script fails, and Systems Manager returns an error message reporting the failure. 

## Adding scripts to runbooks
<a name="adding-scripts"></a>

You can add scripts to your runbooks by including the script inline as part of a step in the runbook. You can also attach scripts to the runbook by uploading the scripts from your local machine or by specifying an Amazon Simple Storage Service (Amazon S3) bucket where the scripts are located. After a step that runs a script is complete, the output of the script is available as a JSON object, which you can then use as input for subsequent steps in your runbook. For more information about the `aws:executeScript` action and how to use attachments for scripts, see [`aws:executeScript` – Run a script](automation-action-executeScript.md).

## Script constraints for runbooks
<a name="script-constraints"></a>

Runbooks enforce a limit of five file attachments. Scripts can either be in the form of a Python script (.py), a PowerShell Core script (.ps1), or attached as contents within a .zip file.

# Using conditional statements in runbooks
<a name="automation-branch-condition"></a>

By default, the steps that you define in the `mainSteps` section of a runbook run in sequential order. After one action is completed, the next action specified in the `mainSteps` section begins. Furthermore, if an action fails to run, the entire automation fails (by default). You can use the `aws:branch` automation action and the runbook options described in this section to create automations that perform *conditional branching*. This means that you can create automations that jump to a different step after evaluating different choices or that dynamically respond to changes when a step is complete. Here is a list of options that you can use to create dynamic automations:
+ **`aws:branch`**: This automation action allows you to create a dynamic automation that evaluates multiple choices in a single step and then jumps to a different step in the runbook based on the results of that evaluation.
+ **`nextStep`**: This option specifies which step in an automation to process next after successfully completing a step. 
+ **`isEnd`**: This option stops an automation at the end of a specific step. The default value for this option is false.
+ **`isCritical`**: This option designates a step as critical for the successful completion of the automation. If a step with this designation fails, then Automation reports the final status of the automation as `Failed`. The default value for this option is `true`.
+ **`onFailure`**: This option indicates whether the automation should stop, continue, or go to a different step on failure. The default value for this option is abort.

The following section describes the `aws:branch` automation action. For more information about the `nextStep`, `isEnd`, `isCritical`, and `onFailure` options, see [Example `aws:branch` runbooks](#branch-runbook-examples).

## Working with the `aws:branch` action
<a name="branch-action-explained"></a>

The `aws:branch` action offers the most dynamic conditional branching options for automations. As noted earlier, this action allows your automation to evaluate multiple conditions in a single step and then jump to a new step based on the results of that evaluation. The `aws:branch` action functions like an `IF-ELIF-ELSE` statement in programming.

Here is a YAML example of an `aws:branch` step.

```
- name: ChooseOSforCommands
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runPowerShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Windows
    - NextStep: runShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Linux
    Default:
      PostProcessing
```

When you specify the `aws:branch` action for a step, you specify `Choices` that the automation must evaluate. The automation can evaluate `Choices` based on the value of a parameter that you specified in the `Parameters` section of the runbook. The automation can also evaluate `Choices` based on output from a previous step.

The automation evaluates each choice by using a Boolean expression. If the evaluation determines that the first choice is `true`, then the automation jumps to the step designated for that choice. If the evaluation determines that the first choice is `false`, then the automation evaluates the next choice. If your step includes three or more `Choices`, then the automation evaluates each choice in sequential order until it evaluates a choice that is `true`. The automation then jumps to the designated step for the `true` choice.

If none of the `Choices` are `true`, the automation checks to see if the step contains a `Default` value. A `Default` value defines a step that the automation should jump to if none of the choices are `true`. If no `Default` value is specified for the step, then the automation processes the next step in the runbook.

Here is an `aws:branch` step in YAML named **chooseOSfromParameter**. The step includes two `Choices`: (`NextStep: runWindowsCommand`) and (`NextStep: runLinuxCommand`). The automation evaluates these `Choices` to determine which command to run for the appropriate operating system. The `Variable` for each choice uses `{{OSName}}`, which is a parameter that the runbook author defined in the `Parameters` section of the runbook.

```
mainSteps:
- name: chooseOSfromParameter
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runWindowsCommand
      Variable: "{{OSName}}"
      StringEquals: Windows
    - NextStep: runLinuxCommand
      Variable: "{{OSName}}"
      StringEquals: Linux
```

Here is an `aws:branch` step in YAML named **chooseOSfromOutput**. The step includes two `Choices`: (`NextStep: runPowerShellCommand`) and (`NextStep: runShellCommand`). The automation evaluates these `Choices` to determine which command to run for the appropriate operating system. The `Variable` for each choice uses `{{GetInstance.platform}}`, which is the output from an earlier step in the runbook. This example also includes an option called `Default`. If the automation evaluates both `Choices`, and neither choice is `true`, then the automation jumps to a step called `PostProcessing`.

```
mainSteps:
- name: chooseOSfromOutput
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runPowerShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Windows
    - NextStep: runShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Linux
    Default:
      PostProcessing
```

### Creating an `aws:branch` step in a runbook
<a name="create-branch-action"></a>

When you create an `aws:branch` step in a runbook, you define the `Choices` the automation should evaluate to determine which step the automation should jump to next. As noted earlier, `Choices` are evaluated by using a Boolean expression. Each choice must define the following options:
+ **NextStep**: The next step in the runbook to process if the designated choice is `true`.
+ **Variable**: Specify either the name of a parameter that is defined in the `Parameters` section of the runbook, a variable defined in the `Variables` section, or specify an output object from a previous step.

  Specify variable values by using the following form.

  `Variable: "{{variable name}}"`

  Specify parameter values by using the following form.

  `Variable: "{{parameter name}}"`

  Specify output object variables by using the following form.

  `Variable: "{{previousStepName.outputName}}"`
**Note**  
Creating the output variable is described in more detail in the next section, [About creating the output variable](#branch-action-output).
+ **Operation**: The criteria used to evaluate the choice, such as `StringEquals: Linux`. The `aws:branch` action supports the following operations:

**String operations**
  + StringEquals
  + EqualsIgnoreCase
  + StartsWith
  + EndsWith
  + Contains

**Numeric operations**
  + NumericEquals
  + NumericGreater
  + NumericLesser
  + NumericGreaterOrEquals
  + NumericLesser
  + NumericLesserOrEquals

**Boolean operation**
  + BooleanEquals
**Important**  
When you create a runbook, the system validates each operation in the runbook. If an operation isn't supported, the system returns an error when you try to create the runbook.
+ **Default**: Specify a fallback step that the automation should jump to if none of the `Choices` are `true`.
**Note**  
If you don't want to specify a `Default` value, then you can specify the `isEnd` option. If none of the `Choices` are `true` and no `Default` value is specified, then the automation stops at the end of the step.

Use the following templates to help you construct the `aws:branch` step in your runbook. Replace each *example resource placeholder* with your own information.

------
#### [ YAML ]

```
mainSteps:
- name: step name
  action: aws:branch
  inputs:
    Choices:
    - NextStep: step to jump to if evaluation for this choice is true
      Variable: "{{parameter name or output from previous step}}"
      Operation type: Operation value
    - NextStep: step to jump to if evaluation for this choice is true
      Variable: "{{parameter name or output from previous step}}"
      Operation type: Operation value
    Default:
      step to jump to if all choices are false
```

------
#### [ JSON ]

```
{
   "mainSteps":[
      {
         "name":"a name for the step",
         "action":"aws:branch",
         "inputs":{
            "Choices":[
               {
                  "NextStep":"step to jump to if evaluation for this choice is true",
                  "Variable":"{{parameter name or output from previous step}}",
                  "Operation type":"Operation value"
               },
               {
                  "NextStep":"step to jump to if evaluation for this choice is true",
                  "Variable":"{{parameter name or output from previous step}}",
                  "Operation type":"Operation value"
               }
            ],
            "Default":"step to jump to if all choices are false"
         }
      }
   ]
}
```

------

#### About creating the output variable
<a name="branch-action-output"></a>

To create an `aws:branch` choice that references the output from a previous step, you need to identify the name of the previous step and the name of the output field. You then combine the names of the step and the field by using the following format.

`Variable: "{{previousStepName.outputName}}"`

For example, the first step in the following example is named `GetInstance`. And then, under `outputs`, there is a field called `platform`. In the second step (`ChooseOSforCommands`), the author wants to reference the output from the platform field as a variable. To create the variable, simply combine the step name (GetInstance) and the output field name (platform) to create `Variable: "{{GetInstance.platform}}"`.

```
mainSteps:
- Name: GetInstance
  action: aws:executeAwsApi
  inputs:
    Service: ssm
    Api: DescribeInstanceInformation
    Filters:
    - Key: InstanceIds
      Values: ["{{ InstanceId }}"]
  outputs:
  - Name: myInstance
    Selector: "$.InstanceInformationList[0].InstanceId"
    Type: String
  - Name: platform
    Selector: "$.InstanceInformationList[0].PlatformType"
    Type: String
- name: ChooseOSforCommands
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runPowerShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Windows
    - NextStep: runShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Linux
    Default:
      Sleep
```

Here is an example that shows how *"Variable": "\$1\$1 describeInstance.Platform \$1\$1"* is created from the previous step and the output.

```
- name: describeInstance
  action: aws:executeAwsApi
  onFailure: Abort
  inputs:
    Service: ec2
    Api: DescribeInstances
    InstanceIds:
    - "{{ InstanceId }}"
  outputs:
  - Name: Platform
    Selector: "$.Reservations[0].Instances[0].Platform"
    Type: String
  nextStep: branchOnInstancePlatform
- name: branchOnInstancePlatform
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runEC2RescueForWindows
      Variable: "{{ describeInstance.Platform }}"
      StringEquals: windows
    Default: runEC2RescueForLinux
```

### Example `aws:branch` runbooks
<a name="branch-runbook-examples"></a>

Here are some example runbooks that use `aws:branch`.

**Example 1: Using `aws:branch` with an output variable to run commands based on the operating system type**

In the first step of this example (`GetInstance`), the runbook author uses the `aws:executeAwsApi` action to call the `ssm` `DescribeInstanceInformation` API operation. The author uses this action to determine the type of operating system being used by an instance. The `aws:executeAwsApi` action outputs the instance ID and the platform type.

In the second step (`ChooseOSforCommands`), the author uses the `aws:branch` action with two `Choices` (`NextStep: runPowerShellCommand`) and (`NextStep: runShellCommand`). The automation evaluates the operating system of the instance by using the output from the previous step (`Variable: "{{GetInstance.platform}}"`). The automation jumps to a step for the designated operating system.

```
---
schemaVersion: '0.3'
assumeRole: "{{AutomationAssumeRole}}"
parameters:
  AutomationAssumeRole:
    default: ""
    type: String
mainSteps:
- name: GetInstance
  action: aws:executeAwsApi
  inputs:
    Service: ssm
    Api: DescribeInstanceInformation
  outputs:
  - Name: myInstance
    Selector: "$.InstanceInformationList[0].InstanceId"
    Type: String
  - Name: platform
    Selector: "$.InstanceInformationList[0].PlatformType"
    Type: String
- name: ChooseOSforCommands
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runPowerShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Windows
    - NextStep: runShellCommand
      Variable: "{{GetInstance.platform}}"
      StringEquals: Linux
    Default:
      Sleep
- name: runShellCommand
  action: aws:runCommand
  inputs:
    DocumentName: AWS-RunShellScript
    InstanceIds:
    - "{{GetInstance.myInstance}}"
    Parameters:
      commands:
      - ls
  isEnd: true
- name: runPowerShellCommand
  action: aws:runCommand
  inputs:
    DocumentName: AWS-RunPowerShellScript
    InstanceIds:
    - "{{GetInstance.myInstance}}"
    Parameters:
      commands:
      - ls
  isEnd: true
- name: Sleep
  action: aws:sleep
  inputs:
    Duration: PT3S
```

**Example 2: Using `aws:branch` with a parameter variable to run commands based on the operating system type**

The runbook author defines several parameter options at the beginning of the runbook in the `parameters` section. One parameter is named `OperatingSystemName`. In the first step (`ChooseOS`), the author uses the `aws:branch` action with two `Choices` (`NextStep: runWindowsCommand`) and (`NextStep: runLinuxCommand`). The variable for these `Choices` references the parameter option specified in the parameters section (`Variable: "{{OperatingSystemName}}"`). When the user runs this runbook, they specify a value at runtime for `OperatingSystemName`. The automation uses the runtime parameter during the `Choices` evaluation. The automation jumps to a step for the designated operating system based on the runtime parameter specified for `OperatingSystemName`.

```
---
schemaVersion: '0.3'
assumeRole: "{{AutomationAssumeRole}}"
parameters:
  AutomationAssumeRole:
    default: ""
    type: String
  OperatingSystemName:
    type: String
  LinuxInstanceId:
    type: String
  WindowsInstanceId:
    type: String
mainSteps:
- name: ChooseOS
  action: aws:branch
  inputs:
    Choices:
    - NextStep: runWindowsCommand
      Variable: "{{OperatingSystemName}}"
      StringEquals: windows
    - NextStep: runLinuxCommand
      Variable: "{{OperatingSystemName}}"
      StringEquals: linux
    Default:
      Sleep
- name: runLinuxCommand
  action: aws:runCommand
  inputs:
    DocumentName: "AWS-RunShellScript"
    InstanceIds:
    - "{{LinuxInstanceId}}"
    Parameters:
      commands:
      - ls
  isEnd: true
- name: runWindowsCommand
  action: aws:runCommand
  inputs:
    DocumentName: "AWS-RunPowerShellScript"
    InstanceIds:
    - "{{WindowsInstanceId}}"
    Parameters:
      commands:
      - date
  isEnd: true
- name: Sleep
  action: aws:sleep
  inputs:
    Duration: PT3S
```

### Creating complex branching automations with operators
<a name="branch-operators"></a>

You can create complex branching automations by using the `And`, `Or`, and `Not` operators in your `aws:branch` steps.

**The 'And' operator**  
Use the `And` operator when you want multiple variables to be `true` for a choice. In the following example, the first choice evaluates if an instance is `running` and uses the `Windows` operating system. If the evaluation of *both* of these variables is true, then the automation jumps to the `runPowerShellCommand` step. If one or more of the variables is `false`, then the automation evaluates the variables for the second choice.

```
mainSteps:
- name: switch2
  action: aws:branch
  inputs:
    Choices:
    - And:
      - Variable: "{{GetInstance.pingStatus}}"
        StringEquals: running
      - Variable: "{{GetInstance.platform}}"
        StringEquals: Windows
      NextStep: runPowerShellCommand

    - And:
      - Variable: "{{GetInstance.pingStatus}}"
        StringEquals: running
      - Variable: "{{GetInstance.platform}}"
        StringEquals: Linux
      NextStep: runShellCommand
    Default:
      sleep3
```

**The 'Or' operator**  
Use the `Or` operator when you want *any* of multiple variables to be true for a choice. In the following example, the first choice evaluates if a parameter string is `Windows` and if the output from an AWS Lambda step is true. If the evaluation determines that *either* of these variables is true, then the automation jumps to the `RunPowerShellCommand` step. If both variables are false, then the automation evaluates the variables for the second choice.

```
- Or:
  - Variable: "{{parameter1}}"
    StringEquals: Windows
  - Variable: "{{BooleanParam1}}"
    BooleanEquals: true
  NextStep: RunPowershellCommand
- Or:
  - Variable: "{{parameter2}}"
    StringEquals: Linux
  - Variable: "{{BooleanParam2}}"
    BooleanEquals: true
  NextStep: RunShellScript
```

**The 'Not' operator**  
Use the `Not` operator when you want to jump to a step defined when a variable is *not* true. In the following example, the first choice evaluates if a parameter string is `Not Linux`. If the evaluation determines that the variable isn't Linux, then the automation jumps to the `sleep2` step. If the evaluation of the first choice determines that it *is* Linux, then the automation evaluates the next choice.

```
mainSteps:
- name: switch
  action: aws:branch
  inputs:
    Choices:
    - NextStep: sleep2
      Not:
        Variable: "{{testParam}}"
        StringEquals: Linux
    - NextStep: sleep1
      Variable: "{{testParam}}"
      StringEquals: Windows
    Default:
      sleep3
```

## Examples of how to use conditional options
<a name="conditional-examples"></a>

This section includes different examples of how to use dynamic options in a runbook. Each example in this section extends the following runbook. This runbook has two actions. The first action is named `InstallMsiPackage`. It uses the `aws:runCommand` action to install an application on a Windows Server instance. The second action is named `TestInstall`. It uses the `aws:invokeLambdaFunction` action to perform a test of the installed application if the application installed successfully. Step one specifies `onFailure: Abort`. This means that if the application didn't install successfully, the automation stops before step two.

**Example 1: Runbook with two linear actions**

```
---
schemaVersion: '0.3'
description: Install MSI package and run validation.
assumeRole: "{{automationAssumeRole}}"
parameters:
  automationAssumeRole:
    type: String
    description: "(Required) Assume role."
  packageName:
    type: String
    description: "(Required) MSI package to be installed."
  instanceIds:
    type: String
    description: "(Required) Comma separated list of instances."
mainSteps:
- name: InstallMsiPackage
  action: aws:runCommand
  maxAttempts: 2
  onFailure: Abort
  inputs:
    InstanceIds:
    - "{{instanceIds}}"
    DocumentName: AWS-RunPowerShellScript
    Parameters:
      commands:
      - msiexec /i {{packageName}}
- name: TestInstall
  action: aws:invokeLambdaFunction
  maxAttempts: 1
  timeoutSeconds: 500
  inputs:
    FunctionName: TestLambdaFunction
...
```

**Creating a dynamic automation that jumps to different steps by using the `onFailure` option**

The following example uses the `onFailure: step:step name`, `nextStep`, and `isEnd` options to create a dynamic automation. With this example, if the `InstallMsiPackage` action fails, then the automation jumps to an action called *PostFailure* (`onFailure: step:PostFailure`) to run an AWS Lambda function to perform some action in the event the install failed. If the install succeeds, then the automation jumps to the TestInstall action (`nextStep: TestInstall`). Both the `TestInstall` and the `PostFailure` steps use the `isEnd` option (`isEnd: true`) so that the automation finishes when either of those steps is completed.

**Note**  
Using the `isEnd` option in the last step of the `mainSteps` section is optional. If the last step doesn't jump to other steps, then the automation stops after running the action in the last step.

**Example 2: A dynamic automation that jumps to different steps**

```
mainSteps
- name: InstallMsiPackage
  action: aws:runCommand
  onFailure: step:PostFailure
  maxAttempts: 2
  inputs:
    InstanceIds:
    - "{{instanceIds}}"
    DocumentName: AWS-RunPowerShellScript
    Parameters:
      commands:
      - msiexec /i {{packageName}}
  nextStep: TestInstall
- name: TestInstall
  action: aws:invokeLambdaFunction
  maxAttempts: 1
  timeoutSeconds: 500
  inputs:
    FunctionName: TestLambdaFunction
  isEnd: true
- name: PostFailure
  action: aws:invokeLambdaFunction
  maxAttempts: 1
  timeoutSeconds: 500
  inputs:
    FunctionName: PostFailureRecoveryLambdaFunction
  isEnd: true
...
```

**Note**  
Before processing a runbook, the system verifies that the runbook doesn't create an infinite loop. If an infinite loop is detected, Automation returns an error and a circle trace showing which steps create the loop.

**Creating a dynamic automation that defines critical steps**

You can specify that a step is critical for the overall success of the automation. If a critical step fails, then Automation reports the status of the automation as `Failed`, even if one or more steps ran successfully. In the following example, the user identifies the *VerifyDependencies* step if the *InstallMsiPackage* step fails (`onFailure: step:VerifyDependencies`). The user specifies that the `InstallMsiPackage` step isn't critical (`isCritical: false`). In this example, if the application failed to install, Automation processes the `VerifyDependencies` step to determine if one or more dependencies is missing, which therefore caused the application install to fail. 

**Example 3: Defining critical steps for the automation **

```
---
name: InstallMsiPackage
action: aws:runCommand
onFailure: step:VerifyDependencies
isCritical: false
maxAttempts: 2
inputs:
  InstanceIds:
  - "{{instanceIds}}"
  DocumentName: AWS-RunPowerShellScript
  Parameters:
    commands:
    - msiexec /i {{packageName}}
nextStep: TestPackage
...
```

# Using action outputs as inputs
<a name="automation-action-outputs-inputs"></a>

Several automation actions return pre-defined outputs. You can pass these outputs as inputs to later steps in your runbook using the format `{{stepName.outputName}}`. You can also define custom outputs for automation actions in your runbooks. This allows you to run scripts, or invoke API operations for other AWS services once so you can reuse the values as inputs in later actions. Parameter types in runbooks are static. This means the parameter type can't be changed after it's defined. To define a step output provide the following fields:
+ Name: (Required) The output name which is used to reference the output value in later steps.
+ Selector: (Required) The JSONPath expression that is used to determine the output value.
+ Type: (Optional) The data type of the value returned by the selector field. Valid type values are `String`, `Integer`, `Boolean`, `StringList`, `StringMap`, `MapList`. The default value is `String`.

If the value of an output doesn't match the data type you've specified, Automation tries to convert the data type. For example, if the value returned is an `Integer`, but the `Type` specified is `String`, the final output value is a `String` value. The following type conversions are supported:
+ `String` values can be converted to `StringList`, `Integer` and `Boolean`.
+ `Integer` values can be converted to `String` and `StringList`.
+ `Boolean` values can be converted to `String` and `StringList`.
+ `StringList`, `IntegerList`, or `BooleanList` values containing one element can be converted to `String`, `Integer`, or `Boolean`.

When using parameters or outputs with automation actions, the data type can't be dynamically changed within an action's input.

Here is an example runbook that demonstrates how to define action outputs, and reference the value as input for a later action. The runbooks does the following:
+ Uses the `aws:executeAwsApi` action to call the Amazon EC2 DescribeImages API operation to get the name of a specific Windows Server 2016 AMI. It outputs the image ID as `ImageId`.
+ Uses the `aws:executeAwsApi` action to call the Amazon EC2 RunInstances API operation to launch one instance that uses the `ImageId` from the previous step. It outputs the instance ID as `InstanceId`.
+ Uses the` aws:waitForAwsResourceProperty` action to poll the Amazon EC2 DescribeInstanceStatus API operation to wait for the instance to reach the `running` state. The action times out in 60 seconds. The step times out if the instance state failed to reach `running` after 60 seconds of polling.
+ Uses the `aws:assertAwsResourceProperty` action to call the Amazon EC2 `DescribeInstanceStatus` API operation to assert that the instance is in the `running` state. The step fails if the instance state isn't `running`.

```
---
description: Sample runbook using AWS API operations
schemaVersion: '0.3'
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
  AutomationAssumeRole:
    type: String
    description: "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf."
    default: ''
  ImageName:
    type: String
    description: "(Optional) Image Name to launch EC2 instance with."
    default: "Windows_Server-2022-English-Full-Base*"
mainSteps:
- name: getImageId
  action: aws:executeAwsApi
  inputs:
    Service: ec2
    Api: DescribeImages
    Filters:  
    - Name: "name"
      Values: 
      - "{{ ImageName }}"
  outputs:
  - Name: ImageId
    Selector: "$.Images[0].ImageId"
    Type: "String"
- name: launchOneInstance
  action: aws:executeAwsApi
  inputs:
    Service: ec2
    Api: RunInstances
    ImageId: "{{ getImageId.ImageId }}"
    MaxCount: 1
    MinCount: 1
  outputs:
  - Name: InstanceId
    Selector: "$.Instances[0].InstanceId"
    Type: "String"
- name: waitUntilInstanceStateRunning
  action: aws:waitForAwsResourceProperty
  timeoutSeconds: 60
  inputs:
    Service: ec2
    Api: DescribeInstanceStatus
    InstanceIds:
    - "{{ launchOneInstance.InstanceId }}"
    PropertySelector: "$.InstanceStatuses[0].InstanceState.Name"
    DesiredValues:
    - running
- name: assertInstanceStateRunning
  action: aws:assertAwsResourceProperty
  inputs:
    Service: ec2
    Api: DescribeInstanceStatus
    InstanceIds:
    - "{{ launchOneInstance.InstanceId }}"
    PropertySelector: "$.InstanceStatuses[0].InstanceState.Name"
    DesiredValues:
    - running
outputs:
- "launchOneInstance.InstanceId"
...
```

Each of the previously described automation actions allows you to call a specific API operation by specifying the service namespace, the API operation name, the input parameters, and the output parameters. Inputs are defined by the API operation that you choose. You can view the API operations (also called methods) by choosing a service in the left navigation on the following [Services Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html) page. Choose a method in the **Client** section for the service that you want to invoke. For example, all API operations (methods) for Amazon Relational Database Service (Amazon RDS) are listed on the following page: [Amazon RDS methods](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html).

You can view the schema for each automation action in the following locations:
+ [`aws:assertAwsResourceProperty` – Assert an AWS resource state or event state](automation-action-assertAwsResourceProperty.md)
+ [`aws:executeAwsApi` – Call and run AWS API operations](automation-action-executeAwsApi.md)
+ [`aws:waitForAwsResourceProperty` – Wait on an AWS resource property](automation-action-waitForAwsResourceProperty.md)

The schemas include descriptions of the required fields for using each action.

**Using the Selector/PropertySelector fields**  
Each Automation action requires that you specify either an output `Selector` (for `aws:executeAwsApi`) or a `PropertySelector` (for `aws:assertAwsResourceProperty` and `aws:waitForAwsResourceProperty`). These fields are used to process the JSON response from an AWS API operation. These fields use the JSONPath syntax.

Here is an example to help illustrate this concept for the `aws:executeAwsAPi` action.

```
---
mainSteps:
- name: getImageId
  action: aws:executeAwsApi
  inputs:
    Service: ec2
    Api: DescribeImages
    Filters:  
      - Name: "name"
        Values: 
          - "{{ ImageName }}"
  outputs:
    - Name: ImageId
      Selector: "$.Images[0].ImageId"
      Type: "String"
...
```

In the `aws:executeAwsApi` step `getImageId`, the automation invokes the `DescribeImages` API operation and receives a response from `ec2`. The automation then applies `Selector - "$.Images[0].ImageId"` to the API response and assigns the selected value to the output `ImageId` variable. Other steps in the same automation can use the value of `ImageId` by specifying `"{{ getImageId.ImageId }}"`.

Here is an example to help illustrate this concept for the `aws:waitForAwsResourceProperty` action.

```
---
- name: waitUntilInstanceStateRunning
  action: aws:waitForAwsResourceProperty
  # timeout is strongly encouraged for action - aws:waitForAwsResourceProperty
  timeoutSeconds: 60
  inputs:
    Service: ec2
    Api: DescribeInstanceStatus
    InstanceIds:
    - "{{ launchOneInstance.InstanceId }}"
    PropertySelector: "$.InstanceStatuses[0].InstanceState.Name"
    DesiredValues:
    - running
...
```

In the `aws:waitForAwsResourceProperty` step `waitUntilInstanceStateRunning`, the automation invokes the `DescribeInstanceStatus` API operation and receives a response from `ec2`. The automation then applies `PropertySelector - "$.InstanceStatuses[0].InstanceState.Name"` to the response and checks if the specified returned value matches a value in the `DesiredValues` list (in this case `running`). The step repeats the process until the response returns an instance state of `running`. 

## Using JSONPath in runbooks
<a name="automation-action-json-path"></a>

A JSONPath expression is a string beginning with "\$1." that is used to select one of more components within a JSON element. The following list includes information about JSONPath operators that are supported by Systems Manager Automation:
+ **Dot-notated child (.)**: Use with a JSON object. This operator selects the value of a specific key.
+ **Deep-scan (..)**: Use with a JSON element. This operator scans the JSON element level by level and selects a list of values with the specific key. The return type of this operator is always a JSON array. In the context of an automation action output type, the operator can be either StringList or MapList.
+ **Array-Index ([ ])**: Use with a JSON array. This operator gets the value of a specific index.
+ **Filter ([?(*expression*)])**: Use with a JSON array. This operator filters JSON array values that match the criteria defined in the filter expression. Filter expressions can only use the following operators: ==, \$1=, >, <, >=, or <=. Combining multiple filter expressions with AND (&&) or OR (\$1\$1) is not supported. The return type of this operator is always a JSON array. 

To better understand JSONPath operators, review the following JSON response from the ec2 `DescribeInstances` API operation. Following this response are several examples that show different results by applying different JSONPath expressions to the response from the `DescribeInstances` API operation.

```
{
    "NextToken": "abcdefg",
    "Reservations": [
        {
            "OwnerId": "123456789012",
            "ReservationId": "r-abcd12345678910",
            "Instances": [
                {
                    "ImageId": "ami-12345678",
                    "BlockDeviceMappings": [
                        {
                            "Ebs": {
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-000000000000"
                            },
                            "DeviceName": "/dev/xvda"
                        }
                    ],
                    "State": {
                        "Code": 16,
                        "Name": "running"
                    }
                }
            ],
            "Groups": []
        },
        {
            "OwnerId": "123456789012",
            "ReservationId": "r-12345678910abcd",
            "Instances": [
                {
                    "ImageId": "ami-12345678",
                    "BlockDeviceMappings": [
                        {
                            "Ebs": {
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-111111111111"
                            },
                            "DeviceName": "/dev/xvda"
                        }
                    ],
                    "State": {
                        "Code": 80,
                        "Name": "stopped"
                    }
                }
            ],
            "Groups": []
        }
    ]
}
```

**JSONPath Example 1: Get a specific String from a JSON response**

```
JSONPath: 
$.Reservations[0].Instances[0].ImageId 

Returns:
"ami-12345678"

Type: String
```

**JSONPath Example 2: Get a specific Boolean from a JSON response**

```
JSONPath:
$.Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.DeleteOnTermination
        
Returns:
true

Type: Boolean
```

**JSONPath Example 3: Get a specific Integer from a JSON response**

```
JSONPath:
$.Reservations[0].Instances[0].State.Code
        
Returns:
16

Type: Integer
```

**JSONPath Example 4: Deep scan a JSON response, then get all of the values for VolumeId as a StringList** 

```
JSONPath:
$.Reservations..BlockDeviceMappings..VolumeId
        
Returns:
[
   "vol-000000000000",
   "vol-111111111111"
]

Type: StringList
```

**JSONPath Example 5: Get a specific BlockDeviceMappings object as a StringMap**

```
JSONPath:
$.Reservations[0].Instances[0].BlockDeviceMappings[0]
        
Returns:
{
   "Ebs" : {
      "DeleteOnTermination" : true,
      "Status" : "attached",
      "VolumeId" : "vol-000000000000"
   },
   "DeviceName" : "/dev/xvda"
}

Type: StringMap
```

**JSONPath Example 6: Deep scan a JSON response, then get all of the State objects as a MapList**

```
JSONPath:
$.Reservations..Instances..State 
    
Returns:
[
   {
      "Code" : 16,
      "Name" : "running"
   },
   {
      "Code" : 80,
      "Name" : "stopped"
   }
]

Type: MapList
```

**JSONPath Example 7: Filter for instances in the `running` state**

```
JSONPath:
$.Reservations..Instances[?(@.State.Name == 'running')]

Returns:
[
  {
    "ImageId": "ami-12345678",
    "BlockDeviceMappings": [
      {
        "Ebs": {
          "DeleteOnTermination": true,
          "Status": "attached",
          "VolumeId": "vol-000000000000"
        },
        "DeviceName": "/dev/xvda"
      }
    ],
    "State": {
      "Code": 16,
      "Name": "running"
    }
  }
]

Type: MapList
```

**JSONPath Example 8: Return the `ImageId` of instances which aren't in the `running` state**

```
JSONPath:
$.Reservations..Instances[?(@.State.Name != 'running')].ImageId

Returns:
[
  "ami-12345678"
]

Type: StringList | String
```

# Creating webhook integrations for Automation
<a name="creating-webhook-integrations"></a>

To send messages using webhooks during an automation, create an integration. Integrations can be invoked during an automation by using the `aws:invokeWebhook` action in your runbook. If you haven't already created a webhook, see [Creating webhooks for integrations](#creating-webhooks). To learn more about the `aws:invokeWebhook` action, see [`aws:invokeWebhook` – Invoke an Automation webhook integration](invoke-webhook.md).

As shown in the following procedures, you can create an integration by using either the Systems Manager Automation console or your preferred command line tool. 

## Creating integrations (console)
<a name="creating-integrations-console"></a>

**To create an integration for Automation (console)**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose the **Integrations** tab.

1. Select **Add integration**, and choose **Webhook**.

1. Enter the required values and any optional values you want to include for the integration.

1. Choose **Add** to create the integration.

## Creating integrations (command line)
<a name="creating-integrations-commandline"></a>

To create an integration using command line tools, you must create the required `SecureString` parameter for an integration. Automation uses a reserved namespace in Parameter Store, a tool in Systems Manager, to store information about your integration. If you create an integration using the AWS Management Console, Automation handles this process for you. Following the namespace, you must specify the type of integration you want to create and then the name of your integration. Currently, Automation supports `webhook` type integrations.

The supported fields for `webhook` type integrations are as follows:
+ Description
+ headers
+ payload
+ URL

**Before you begin**  
If you haven't already, install and configure the AWS Command Line Interface (AWS CLI) or the AWS Tools for PowerShell. For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [Installing the AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up.html).

**To create an integration for Automation (command line)**
+ Run the following commands to create the required `SecureString` parameter for an integration. Replace each *example resource placeholder* with your own information. The `/d9d01087-4a3f-49e0-b0b4-d568d7826553/ssm/integrations/webhook/` namespace is reserved in Parameter Store for integrations. The name of your parameter must use this namespace followed by the name of your integration. For example `/d9d01087-4a3f-49e0-b0b4-d568d7826553/ssm/integrations/webhook/myWebhookIntegration`.

------
#### [ Linux & macOS ]

  ```
  aws ssm put-parameter \
      --name "/d9d01087-4a3f-49e0-b0b4-d568d7826553/ssm/integrations/webhook/myWebhookIntegration" \
      --type "SecureString" \
      --data-type "aws:ssm:integration" \
      --value '{"description": "My first webhook integration for Automation.", "url": "myWebHookURL"}'
  ```

------
#### [ Windows ]

  ```
  aws ssm put-parameter ^
      --name "/d9d01087-4a3f-49e0-b0b4-d568d7826553/ssm/integrations/webhook/myWebhookIntegration" ^
      --type "SecureString" ^
      --data-type "aws:ssm:integration" ^
      --value  "{\"description\":\"My first webhook integration for Automation.\",\"url\":\"myWebHookURL\"}"
  ```

------
#### [ PowerShell ]

  ```
  Write-SSMParameter `
      -Name "/d9d01087-4a3f-49e0-b0b4-d568d7826553/ssm/integrations/webhook/myWebhookIntegration" `
      -Type "SecureString"
      -DataType "aws:ssm:integration"
      -Value '{"description": "My first webhook integration for Automation.", "url": "myWebHookURL"}'
  ```

------

## Creating webhooks for integrations
<a name="creating-webhooks"></a>

When creating webhooks with your provider, note the following:
+ Protocol must be HTTPS.
+ Custom request headers are supported.
+ A default request body can be specified.
+ The default request body can be overridden when an integration is invoked by using the `aws:invokeWebhook` action.

# Handling timeouts in runbooks
<a name="automation-handling-timeouts"></a>

The `timeoutSeconds` property is shared by all automation actions. You can use this property to specify the execution timeout value for an action. Further, you can change how an action timing out affects the automation and overall execution status. You can accomplish this by also defining the `onFailure` and `isCritical` shared properties for an action.

For example, depending on your use case, you might want your automation to continue to a different action and not affect the overall status of the automation if an action times out. In this example, you specify the length of time to wait before the action times out using the `timeoutSeconds` property. Then you specify the action, or step, the automation should go to if there is a timeout. Specify a value using the format `step:step name` for the `onFailure` property rather than the default value of `Abort`. By default, if an action times out, the automation execution status will be `Timed Out`. To prevent a timeout from affecting the automation execution status, specify `false` for the `isCritical` property.

The following example shows how to define the shared properties for an action described in this scenario.

------
#### [ YAML ]

```
- name: verifyImageAvailability
  action: 'aws:waitForAwsResourceProperty'
  timeoutSeconds: 600
  isCritical: false
  onFailure: 'step:getCurrentImageState'
  inputs:
    Service: ec2
    Api: DescribeImages
    ImageIds:
      - '{{ createImage.newImageId }}'
    PropertySelector: '$.Images[0].State'
    DesiredValues:
      - available
  nextStep: copyImage
```

------
#### [ JSON ]

```
{
    "name": "verifyImageAvailability",
    "action": "aws:waitForAwsResourceProperty",
    "timeoutSeconds": 600,
    "isCritical": false,
    "onFailure": "step:getCurrentImageState",
    "inputs": {
        "Service": "ec2",
        "Api": "DescribeImages",
        "ImageIds": [
            "{{ createImage.newImageId }}"
        ],
        "PropertySelector": "$.Images[0].State",
        "DesiredValues": [
            "available"
        ]
    },
    "nextStep": "copyImage"
}
```

------

For more information about properties shared by all automation actions, see [Properties shared by all actions](automation-actions.md#automation-common).

# Systems Manager Automation Runbook Reference
<a name="automation-documents-reference"></a>

To help you get started quickly, AWS Systems Manager provides predefined runbooks. These runbooks are maintained by Amazon Web Services, AWS Support, and AWS Config. The Runbook Reference describes each of the predefined runbooks provided by Systems Manager, Support, and AWS Config. For more information, see [Systems Manager Automation Runbook Reference](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide).

# Tutorials
<a name="automation-tutorials"></a>

The following tutorials help you to use AWS Systems Manager Automation to address common use cases. These tutorials demonstrate how to use your own runbooks, predefined runbooks provided by Automation, and other Systems Manager tools with other AWS services.

**Contents**
+ [Updating AMIs](automation-tutorial-update-ami.md)
  + [Update a Linux AMI](automation-tutorial-update-patch-linux-ami.md)
  + [Update a Linux AMI (AWS CLI)](automation-tutorial-update-ami.md#update-patch-linux-ami-cli)
  + [Update a Windows Server AMI](automation-tutorial-update-patch-windows-ami.md)
  + [Update a golden AMI using Automation, AWS Lambda, and Parameter Store](automation-tutorial-update-patch-golden-ami.md)
    + [Task 1: Create a parameter in Systems Manager Parameter Store](automation-tutorial-update-patch-golden-ami.md#create-parameter-ami)
    + [Task 2: Create an IAM role for AWS Lambda](automation-tutorial-update-patch-golden-ami.md#create-lambda-role)
    + [Task 3: Create an AWS Lambda function](automation-tutorial-update-patch-golden-ami.md#create-lambda-function)
    + [Task 4: Create a runbook and patch the AMI](automation-tutorial-update-patch-golden-ami.md#create-custom-ami-update-runbook)
  + [Updating AMIs using Automation and Jenkins](automation-tutorial-update-patch-ami-jenkins-integration.md)
  + [Updating AMIs for Auto Scaling groups](automation-tutorial-update-patch-windows-ami-autoscaling.md)
    + [Create the **PatchAMIAndUpdateASG** runbook](automation-tutorial-update-patch-windows-ami-autoscaling.md#create-autoscaling-update-runbook)
+ [Using AWS Support self-service runbooks](automation-tutorial-support-runbooks.md)
  + [Run the EC2Rescue tool on unreachable instances](automation-ec2rescue.md)
    + [How it works](automation-ec2rescue.md#automation-ec2rescue-how)
    + [Before you begin](automation-ec2rescue.md#automation-ec2rescue-begin)
      + [Granting `AWSSupport-EC2Rescue` permissions to perform actions on your instances](automation-ec2rescue.md#automation-ec2rescue-access)
        + [Granting permissions by using IAM policies](automation-ec2rescue.md#automation-ec2rescue-access-iam)
        + [Granting permissions by using an CloudFormation template](automation-ec2rescue.md#automation-ec2rescue-access-cfn)
    + [Running the Automation](automation-ec2rescue.md#automation-ec2rescue-executing)
  + [Reset passwords and SSH keys on EC2 instances](automation-ec2reset.md)
    + [How it works](automation-ec2reset.md#automation-ec2reset-how)
    + [Before you begin](automation-ec2reset.md#automation-ec2reset-begin)
      + [Granting AWSSupport-EC2Rescue permissions to perform actions on your instances](automation-ec2reset.md#automation-ec2reset-access)
        + [Granting permissions by using IAM policies](automation-ec2reset.md#automation-ec2reset-access-iam)
        + [Granting permissions by using an CloudFormation template](automation-ec2reset.md#automation-ec2reset-access-cfn)
    + [Running the Automation](automation-ec2reset.md#automation-ec2reset-executing)
+ [Passing data to Automation using input transformers](automation-tutorial-eventbridge-input-transformers.md)

# Updating AMIs
<a name="automation-tutorial-update-ami"></a>

The following tutorials explain how to update Amazon Machine Image (AMIs) to include the latest patches.

**Topics**
+ [Update a Linux AMI](automation-tutorial-update-patch-linux-ami.md)
+ [Update a Linux AMI (AWS CLI)](#update-patch-linux-ami-cli)
+ [Update a Windows Server AMI](automation-tutorial-update-patch-windows-ami.md)
+ [Update a golden AMI using Automation, AWS Lambda, and Parameter Store](automation-tutorial-update-patch-golden-ami.md)
+ [Updating AMIs using Automation and Jenkins](automation-tutorial-update-patch-ami-jenkins-integration.md)
+ [Updating AMIs for Auto Scaling groups](automation-tutorial-update-patch-windows-ami-autoscaling.md)

# Update a Linux AMI
<a name="automation-tutorial-update-patch-linux-ami"></a>

This Systems Manager Automation walkthrough shows you how to use the console or AWS CLI and the `AWS-UpdateLinuxAmi` runbook to update a Linux AMI with the latest patches of packages that you specify. Automation is a tool in AWS Systems Manager. The `AWS-UpdateLinuxAmi` runbook also automates the installation of additional site-specific packages and configurations. You can update a variety of Linux distributions using this walkthrough, including Ubuntu Server, Red Hat Enterprise Linux (RHEL), or Amazon Linux AMIs. For a full list of supported Linux versions, see [Patch Manager prerequisites](patch-manager-prerequisites.md).

The `AWS-UpdateLinuxAmi` runbook allows you to automate image maintenance tasks without having to author the runbook in JSON or YAML. You can use the `AWS-UpdateLinuxAmi` runbook to perform the following types of tasks.
+ Upgrade all distribution packages and Amazon software on an Amazon Linux, Red Hat Enterprise Linux, or Ubuntu Server Amazon Machine Image (AMI). This is the default runbook behavior.
+ Install AWS Systems Manager SSM Agent on an existing image to enable Systems Manager tools, such as running remote commands using AWS Systems Manager Run Command or software inventory collection using Inventory.
+ Install additional software packages.

**Before you begin**  
Before you begin working with runbooks, configure roles and, optionally, EventBridge for Automation. For more information, see [Setting up Automation](automation-setup.md). This walkthrough also requires that you specify the name of an AWS Identity and Access Management (IAM) instance profile. For more information about creating an IAM instance profile, see [Configure instance permissions required for Systems Manager](setup-instance-permissions.md).

The `AWS-UpdateLinuxAmi` runbook accepts the following input parameters.


****  

| Parameter | Type | Description | 
| --- | --- | --- | 
|  SourceAmiId  |  String  |  (Required) The source AMI ID.  | 
|  IamInstanceProfileName  |  String  |  (Required) The name of the IAM instance profile role you created in [Configure instance permissions required for Systems Manager](setup-instance-permissions.md). The instance profile role gives Automation permission to perform actions on your instances, such as running commands or starting and stopping services. The runbook uses only the name of the instance profile role. If you specify the Amazon Resource Name (ARN), the automation fails.  | 
|  AutomationAssumeRole  |  String  |  (Required) The name of the IAM service role you created in [Setting up Automation](automation-setup.md). The service role (also called an assume role) gives Automation permission to assume your IAM role and perform actions on your behalf. For example, the service role allows Automation to create a new AMI when running the `aws:createImage` action in a runbook. For this parameter, the complete ARN must be specified.  | 
|  TargetAmiName  |  String  |  (Optional) The name of the new AMI after it is created. The default name is a system-generated string that includes the source AMI ID, and the creation time and date.  | 
|  InstanceType  |  String  |  (Optional) The type of instance to launch as the workspace host. Instance types vary by region. The default type is t2.micro.  | 
|  PreUpdateScript  |  String  |  (Optional) URL of a script to run before updates are applied. Default (\$1"none\$1") is to not run a script.  | 
|  PostUpdateScript  |  String  |  (Optional) URL of a script to run after package updates are applied. Default (\$1"none\$1") is to not run a script.  | 
|  IncludePackages  |  String  |  (Optional) Only update these named packages. By default (\$1"all\$1"), all available updates are applied.  | 
|  ExcludePackages  |  String  |  (Optional) Names of packages to hold back from updates, under all conditions. By default (\$1"none\$1"), no package is excluded.  | 

**Automation Steps**  
The `AWS-UpdateLinuxAmi` runbook includes the following automation actions, by default.

**Step 1: launchInstance (`aws:runInstances` action) **  
This step launches an instance using Amazon Elastic Compute Cloud (Amazon EC2) userdata and an IAM instance profile role. Userdata installs the appropriate SSM Agent, based on the operating system. Installing SSM Agent enables you to utilize Systems Manager tools such as Run Command, State Manager, and Inventory.

**Step 2: updateOSSoftware (`aws:runCommand` action) **  
This step runs the following commands on the launched instance:  
+ Downloads an update script from Amazon S3.
+ Runs an optional pre-update script.
+ Updates distribution packages and Amazon software.
+ Runs an optional post-update script.
The execution log is stored in the /tmp folder for the user to view later.  
If you want to upgrade a specific set of packages, you can supply the list using the `IncludePackages` parameter. When provided, the system attempts to update only these packages and their dependencies. No other updates are performed. By default, when no *include* packages are specified, the program updates all available packages.  
If you want to exclude upgrading a specific set of packages, you can supply the list to the `ExcludePackages` parameter. If provided, these packages remain at their current version, independent of any other options specified. By default, when no *exclude* packages are specified, no packages are excluded.

**Step 3: stopInstance (`aws:changeInstanceState` action)**  
This step stops the updated instance.

**Step 4: createImage (`aws:createImage` action) **  
This step creates a new AMI with a descriptive name that links it to the source ID and creation time. For example: “AMI Generated by EC2 Automation on \$1\$1global:DATE\$1TIME\$1\$1 from \$1\$1SourceAmiId\$1\$1” where DATE\$1TIME and SourceID represent Automation variables.

**Step 5: terminateInstance (`aws:changeInstanceState` action) **  
This step cleans up the automation by terminating the running instance.

**Output**  
The automation returns the new AMI ID as output.

**Note**  
By default, when Automation runs the `AWS-UpdateLinuxAmi` runbook, the system creates a temporary instance in the default VPC (172.30.0.0/16). If you deleted the default VPC, you will receive the following error:  
`VPC not defined 400`  
To solve this problem, you must make a copy of the `AWS-UpdateLinuxAmi` runbook and specify a subnet ID. For more information, see [VPC not defined 400](automation-troubleshooting.md#automation-trbl-common-vpc).

**To create a patched AMI using Automation (AWS Systems Manager)**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose **Execute automation**.

1. In the **Automation document** list, choose `AWS-UpdateLinuxAmi`.

1. In the **Document details** section, verify that **Document version** is set to **Default version at runtime**.

1. Choose **Next**.

1. In the **Execution mode** section, choose **Simple Execution**.

1. In the **Input parameters** section, enter the information you collected in the **Before you begin** section.

1. Choose **Execute**. The console displays the status of the Automation execution.

After the automation finishes, launch a test instance from the updated AMI to verify changes.

**Note**  
If any step in the automation fails, information about the failure is listed on the **Automation Executions** page. The automation is designed to terminate the temporary instance after successfully completing all tasks. If a step fails, the system might not terminate the instance. So if a step fails, manually terminate the temporary instance.

## Update a Linux AMI (AWS CLI)
<a name="update-patch-linux-ami-cli"></a>

This AWS Systems Manager Automation walkthrough shows you how to use the AWS Command Line Interface (AWS CLI) and the Systems Manager `AWS-UpdateLinuxAmi` runbook to automatically patch a Linux Amazon Machine Image (AMI) with the latest versions of packages that you specify. Automation is a tool in AWS Systems Manager. The `AWS-UpdateLinuxAmi` runbook also automates the installation of additional site-specific packages and configurations. You can update a variety of Linux distributions using this walkthrough, including Ubuntu Server, Red Hat Enterprise Linux (RHEL), or Amazon Linux AMIs. For a full list of supported Linux versions, see [Patch Manager prerequisites](patch-manager-prerequisites.md).

The `AWS-UpdateLinuxAmi` runbook enables you to automate image-maintenance tasks without having to author the runbook in JSON or YAML. You can use the `AWS-UpdateLinuxAmi` runbook to perform the following types of tasks.
+ Upgrade all distribution packages and Amazon software on an Amazon Linux, RHEL, or Ubuntu Server Amazon Machine Image (AMI). This is the default runbook behavior.
+ Install AWS Systems Manager SSM Agent on an existing image to enable Systems Manager capabilities, such as running remote commands using AWS Systems Manager Run Command or software inventory collection using Inventory.
+ Install additional software packages.

**Before you begin**  
Before you begin working with runbooks, configure roles and, optionally, EventBridge for Automation. For more information, see [Setting up Automation](automation-setup.md). This walkthrough also requires that you specify the name of an AWS Identity and Access Management (IAM) instance profile. For more information about creating an IAM instance profile, see [Configure instance permissions required for Systems Manager](setup-instance-permissions.md).

The `AWS-UpdateLinuxAmi` runbook accepts the following input parameters.


****  

| Parameter | Type | Description | 
| --- | --- | --- | 
|  SourceAmiId  |  String  |  (Required) The source AMI ID. You can automatically reference the latest ID of an Amazon EC2 AMI for Linux by using a AWS Systems Manager Parameter Store *public* parameter. For more information, see [Query for the latest Amazon Linux AMI IDs using AWS Systems Manager Parameter Store](https://aws.amazon.com/blogs/compute/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/).  | 
|  IamInstanceProfileName  |  String  |  (Required) The name of the IAM instance profile role you created in [Configure instance permissions required for Systems Manager](setup-instance-permissions.md). The instance profile role gives Automation permission to perform actions on your instances, such as running commands or starting and stopping services. The runbook uses only the name of the instance profile role.  | 
|  AutomationAssumeRole  |  String  |  (Required) The name of the IAM service role you created in [Setting up Automation](automation-setup.md). The service role (also called an assume role) gives Automation permission to assume your IAM role and perform actions on your behalf. For example, the service role allows Automation to create a new AMI when running the `aws:createImage` action in a runbook. For this parameter, the complete ARN must be specified.  | 
|  TargetAmiName  |  String  |  (Optional) The name of the new AMI after it is created. The default name is a system-generated string that includes the source AMI ID, and the creation time and date.  | 
|  InstanceType  |  String  |  (Optional) The type of instance to launch as the workspace host. Instance types vary by Region. The default type is t2.micro.  | 
|  PreUpdateScript  |  String  |  (Optional) URL of a script to run before updates are applied. Default (\$1"none\$1") is to not run a script.  | 
|  PostUpdateScript  |  String  |  (Optional) URL of a script to run after package updates are applied. Default (\$1"none\$1") is to not run a script.  | 
|  IncludePackages  |  String  |  (Optional) Only update these named packages. By default (\$1"all\$1"), all available updates are applied.  | 
|  ExcludePackages  |  String  |  (Optional) Names of packages to hold back from updates, under all conditions. By default (\$1"none\$1"), no package is excluded.  | 

**Automation Steps**  
The `AWS-UpdateLinuxAmi` runbook includes the following steps, by default.

**Step 1: launchInstance (`aws:runInstances` action) **  
This step launches an instance using Amazon Elastic Compute Cloud (Amazon EC2) user data and an IAM instance profile role. User data installs the appropriate SSM Agent, based on the operating system. Installing SSM Agent enables you to utilize Systems Manager tools such as Run Command, State Manager, and Inventory.

**Step 2: updateOSSoftware (`aws:runCommand` action) **  
This step runs the following commands on the launched instance:  
+ Downloads an update script from Amazon Simple Storage Service (Amazon S3).
+ Runs an optional pre-update script.
+ Updates distribution packages and Amazon software.
+ Runs an optional post-update script.
The execution log is stored in the /tmp folder for the user to view later.  
If you want to upgrade a specific set of packages, you can supply the list using the `IncludePackages` parameter. When provided, the system attempts to update only these packages and their dependencies. No other updates are performed. By default, when no *include* packages are specified, the program updates all available packages.  
If you want to exclude upgrading a specific set of packages, you can supply the list to the `ExcludePackages` parameter. If provided, these packages remain at their current version, independent of any other options specified. By default, when no *exclude* packages are specified, no packages are excluded.

**Step 3: stopInstance (`aws:changeInstanceState` action)**  
This step stops the updated instance.

**Step 4: createImage (`aws:createImage` action) **  
This step creates a new AMI with a descriptive name that links it to the source ID and creation time. For example: “AMI Generated by EC2 Automation on \$1\$1global:DATE\$1TIME\$1\$1 from \$1\$1SourceAmiId\$1\$1” where DATE\$1TIME and SourceID represent Automation variables.

**Step 5: terminateInstance (`aws:changeInstanceState` action) **  
This step cleans up the automation by terminating the running instance.

**Output**  
The automation returns the new AMI ID as output.

**Note**  
By default, when Automation runs the `AWS-UpdateLinuxAmi` runbook, the system creates a temporary instance in the default VPC (172.30.0.0/16). If you deleted the default VPC, you will receive the following error:  
`VPC not defined 400`  
To solve this problem, you must make a copy of the `AWS-UpdateLinuxAmi` runbook and specify a subnet ID. For more information, see [VPC not defined 400](automation-troubleshooting.md#automation-trbl-common-vpc).

**To create a patched AMI using Automation**

1. Install and configure the AWS Command Line Interface (AWS CLI), if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).

1. Run the following command to run the `AWS-UpdateLinuxAmi` runbook. Replace each *example resource placeholder* with your own information.

   ```
   aws ssm start-automation-execution \
       --document-name "AWS-UpdateLinuxAmi" \
       --parameters \
       SourceAmiId=AMI ID, \
       IamInstanceProfileName=IAM instance profile, \
       AutomationAssumeRole='arn:aws:iam::{{global:ACCOUNT_ID}}:role/AutomationServiceRole'
   ```

   The command returns an execution ID. Copy this ID to the clipboard. You will use this ID to view the status of the automation.

   ```
   {
       "AutomationExecutionId": "automation execution ID"
   }
   ```

1. To view the automation using the AWS CLI, run the following command:

   ```
   aws ssm describe-automation-executions
   ```

1. To view details about the automation progress, run the following command. Replace *automation execution ID* with your own information.

   ```
   aws ssm get-automation-execution --automation-execution-id automation execution ID
   ```

   The update process can take 30 minutes or more to complete.
**Note**  
You can also monitor the status of the automation in the console. In the list, choose the automation you just ran and then choose the **Steps** tab. This tab shows you the status of the automation actions.

After the automation finishes, launch a test instance from the updated AMI to verify changes.

**Note**  
If any step in the automation fails, information about the failure is listed on the **Automation Executions** page. The automation is designed to terminate the temporary instance after successfully completing all tasks. If a step fails, the system might not terminate the instance. So if a step fails, manually terminate the temporary instance.

# Update a Windows Server AMI
<a name="automation-tutorial-update-patch-windows-ami"></a>

The `AWS-UpdateWindowsAmi` runbook enables you to automate image maintenance tasks on your Amazon Windows Amazon Machine Image (AMI) without having to author the runbook in JSON or YAML. This runbook is supported for Windows Server 2008 R2 or later. You can use the `AWS-UpdateWindowsAmi` runbook to perform the following types of tasks.
+ Install all Windows updates and upgrade Amazon software (default behavior).
+ Install specific Windows updates and upgrade Amazon software.
+ Customize an AMI using your scripts.

**Before you begin**  
Before you begin working with runbooks, [configure roles for Automation](automation-setup-iam.md) to add an `iam:PassRole` policy that references the ARN of the instance profile you want to grant access to. Optionally, configure Amazon EventBridge for Automation, a tool in AWS Systems Manager. For more information, see [Setting up Automation](automation-setup.md). This walkthrough also requires that you specify the name of an AWS Identity and Access Management (IAM) instance profile. For more information about creating an IAM instance profile, see [Configure instance permissions required for Systems Manager](setup-instance-permissions.md).

**Note**  
Updates to AWS Systems Manager SSM Agent are typically rolled out to different regions at different times. When you customize or update an AMI, use only source AMIs published for the region that you are working in. This will ensure that you are working with the latest SSM Agent released for that region and avoid compatibility issues.

The `AWS-UpdateWindowsAmi` runbook accepts the following input parameters.


****  

| Parameter | Type | Description | 
| --- | --- | --- | 
|  SourceAmiId  |  String  |  (Required) The source AMI ID. You can automatically reference the latest Windows Server AMI ID by using a Systems Manager Parameter Store *public* parameter. For more information, see [Query for the latest Windows AMI IDs using AWS Systems Manager Parameter Store](https://aws.amazon.com/blogs/mt/query-for-the-latest-windows-ami-using-systems-manager-parameter-store/).  | 
|  SubnetId  |  String  |  (Optional) The subnet you want to launch the temporary instance into. You must specify a value for this parameter if you've deleted your default VPC.  | 
|  IamInstanceProfileName  |  String  |  (Required) The name of the IAM instance profile role you created in [Configure instance permissions required for Systems Manager](setup-instance-permissions.md). The instance profile role gives Automation permission to perform actions on your instances, such as running commands or starting and stopping services. The runbook uses only the name of the instance profile role.  | 
|  AutomationAssumeRole  |  String  |  (Required) The name of the IAM service role you created in [Setting up Automation](automation-setup.md). The service role (also called an assume role) gives Automation permission to assume your IAM role and perform actions on your behalf. For example, the service role allows Automation to create a new AMI when running the `aws:createImage` action in a runbook. For this parameter, the complete ARN must be specified.  | 
|  TargetAmiName  |  String  |  (Optional) The name of the new AMI after it is created. The default name is a system-generated string that includes the source AMI ID, and the creation time and date.  | 
|  InstanceType  |  String  |  (Optional) The type of instance to launch as the workspace host. Instance types vary by region. The default type is t2.medium.  | 
|  PreUpdateScript  |  String  |  (Optional) A script to run before updating the AMI. Enter a script in the runbook or at runtime as a parameter.  | 
|  PostUpdateScript  |  String  |  (Optional) A script to run after updating the AMI. Enter a script in the runbook or at runtime as a parameter.  | 
|  IncludeKbs  |  String  |  (Optional) Specify one or more Microsoft Knowledge Base (KB) article IDs to include. You can install multiple IDs using comma-separated values. Valid formats: KB9876543 or 9876543.  | 
|  ExcludeKbs  |  String  |  (Optional) Specify one or more Microsoft Knowledge Base (KB) article IDs to exclude. You can exclude multiple IDs using comma-separated values. Valid formats: KB9876543 or 9876543.  | 
|  Categories  |  String  |  (Optional)Specify one or more update categories. You can filter categories using comma-separated values. Options: Critical Update, Security Update, Definition Update, Update Rollup, Service Pack, Tool, Update, or Driver. Valid formats include a single entry, for example: Critical Update. Or, you can specify a comma separated list: Critical Update,Security Update,Definition Update.  | 
|  SeverityLevels  |  String  |  (Optional) Specify one or more MSRC severity levels associated with an update. You can filter severity levels using comma-separated values. Options: Critical, Important, Low, Moderate or Unspecified. Valid formats include a single entry, for example: Critical. Or, you can specify a comma separated list: Critical,Important,Low.  | 

**Automation Steps**  
The `AWS-UpdateWindowsAmi` runbook includes the following steps, by default.

**Step 1: launchInstance (`aws:runInstances` action)**  
This step launches an instance with an IAM instance profile role from the specified `SourceAmiID`.

**Step 2: runPreUpdateScript (`aws:runCommand` action)**  
This step enables you to specify a script as a string that runs before updates are installed.

**Step 3: updateEC2Config (`aws:runCommand` action)**  
This step uses the `AWS-InstallPowerShellModule` runbook to download an AWS public PowerShell module. Systems Manager verifies the integrity of the module by using an SHA-256 hash. Systems Manager then checks the operating system to determine whether to update EC2Config or EC2Launch. EC2Config runs on Windows Server 2008 R2 through Windows Server 2012 R2. EC2Launch runs on Windows Server 2016.

**Step 4: updateSSMAgent (`aws:runCommand` action)**  
This step updates SSM Agent by using the `AWS-UpdateSSMAgent` runbook.

**Step 5: updateAWSPVDriver (`aws:runCommand` action)**  
This step updates AWS PV drivers by using the `AWS-ConfigureAWSPackage` runbook.

**Step 6: updateAwsEnaNetworkDriver (`aws:runCommand` action)**  
This step updates AWS ENA Network drivers by using the `AWS-ConfigureAWSPackage` runbook.

**Step 7: installWindowsUpdates (`aws:runCommand` action) **  
This step installs Windows updates by using the `AWS-InstallWindowsUpdates` runbook. By default, Systems Manager searches for and installs all missing updates. You can change the default behavior by specifying one of the following parameters: `IncludeKbs`, `ExcludeKbs`, `Categories`, or `SeverityLevels`. 

**Step 8: runPostUpdateScript (`aws:runCommand` action)**  
This step enables you to specify a script as a string that runs after the updates have been installed.

**Step 9: runSysprepGeneralize (`aws:runCommand` action) **  
This step uses the `AWS-InstallPowerShellModule` runbook to download an AWS public PowerShell module. Systems Manager verifies the integrity of the module by using an SHA-256 hash. Systems Manager then runs sysprep using AWS-supported methods for either EC2Launch (Windows Server 2016) or EC2Config (Windows Server 2008 R2 through 2012 R2).

**Step 10: stopInstance (`aws:changeInstanceState` action) **  
This step stops the updated instance. 

**Step 11: createImage (`aws:createImage` action) **  
This step creates a new AMI with a descriptive name that links it to the source ID and creation time. For example: “AMI Generated by EC2 Automation on \$1\$1global:DATE\$1TIME\$1\$1 from \$1\$1SourceAmiId\$1\$1” where DATE\$1TIME and SourceID represent Automation variables.

**Step 12: TerminateInstance (`aws:changeInstanceState` action) **  
This step cleans up the automation by terminating the running instance. 

**Output**  
This section enables you to designate the outputs of various steps or values of any parameter as the Automation output. By default, the output is the ID of the updated Windows AMI created by the automation.

**Note**  
By default, when Automation runs the `AWS-UpdateWindowsAmi` runbook and creates a temporary instance, the system uses the default VPC (172.30.0.0/16). If you deleted the default VPC, you will receive the following error:  
VPC not defined 400  
To solve this problem, you must make a copy of the `AWS-UpdateWindowsAmi` runbook and specify a subnet ID. For more information, see [VPC not defined 400](automation-troubleshooting.md#automation-trbl-common-vpc).

**To create a patched Windows AMI by using Automation**

1. Install and configure the AWS Command Line Interface (AWS CLI), if you haven't already.

   For information, see [Installing or updating the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).

1. Run the following command to run the `AWS-UpdateWindowsAmi` runbook. Replace each *example resource placeholder* with your own information. The example command below uses a recent Amazon EC2 AMI to minimize the number of patches that need to be applied. If you run this command more than once, you must specify a unique value for `targetAMIname`. AMI names must be unique.

   ```
   aws ssm start-automation-execution \
       --document-name="AWS-UpdateWindowsAmi" \
       --parameters SourceAmiId='AMI ID',IamInstanceProfileName='IAM instance profile',AutomationAssumeRole='arn:aws:iam::{{global:ACCOUNT_ID}}:role/AutomationServiceRole'
   ```

   The command returns an execution ID. Copy this ID to the clipboard. You will use this ID to view the status of the automation.

   ```
   {
       "AutomationExecutionId": "automation execution ID"
   }
   ```

1. To view the automation using the AWS CLI, run the following command:

   ```
   aws ssm describe-automation-executions
   ```

1. To view details about the automation progress, run the following command.

   ```
   aws ssm get-automation-execution 
       --automation-execution-id automation execution ID
   ```

**Note**  
Depending on the number of patches applied, the Windows patching process run in this sample automation can take 30 minutes or more to complete.

# Update a golden AMI using Automation, AWS Lambda, and Parameter Store
<a name="automation-tutorial-update-patch-golden-ami"></a>

The following example uses the model where an organization maintains and periodically patches their own, proprietary AMIs rather than building from Amazon Elastic Compute Cloud (Amazon EC2) AMIs.

The following procedure shows how to automatically apply operating system (OS) patches to an AMI that is already considered to be the most up-to-date or *latest* AMI. In the example, the default value of the parameter `SourceAmiId` is defined by a AWS Systems Manager Parameter Store parameter called `latestAmi`. The value of `latestAmi` is updated by an AWS Lambda function invoked at the end of the automation. As a result of this Automation process, the time and effort spent patching AMIs is minimized because patching is always applied to the most up-to-date AMI. Parameter Store and Automation are tools of AWS Systems Manager.

**Before you begin**  
Configure Automation roles and, optionally, Amazon EventBridge for Automation. For more information, see [Setting up Automation](automation-setup.md).

**Topics**
+ [Task 1: Create a parameter in Systems Manager Parameter Store](#create-parameter-ami)
+ [Task 2: Create an IAM role for AWS Lambda](#create-lambda-role)
+ [Task 3: Create an AWS Lambda function](#create-lambda-function)
+ [Task 4: Create a runbook and patch the AMI](#create-custom-ami-update-runbook)

## Task 1: Create a parameter in Systems Manager Parameter Store
<a name="create-parameter-ami"></a>

Create a string parameter in Parameter Store that uses the following information:
+ **Name**: `latestAmi`.
+ **Value**: An AMI ID. For example:` ami-188d6e0e`.

For information about how to create a Parameter Store string parameter, see [Creating Parameter Store parameters in Systems Manager](sysman-paramstore-su-create.md).

## Task 2: Create an IAM role for AWS Lambda
<a name="create-lambda-role"></a>

Use the following procedure to create an IAM service role for AWS Lambda. These policies give Lambda permission to update the value of the `latestAmi` parameter using a Lambda function and Systems Manager.

**To create an IAM service role for Lambda**

1. Sign in to the AWS Management Console and open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).

1. In the navigation pane, choose **Policies**, and then choose **Create policy**.

1. Choose the **JSON** tab.

1. Replace the default contents with the following policy. Replace each *example resource placeholder* with your own information.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "logs:CreateLogGroup",
               "Resource": "arn:aws:logs:us-east-1:111122223333:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "logs:CreateLogStream",
                   "logs:PutLogEvents"
               ],
               "Resource": [
                   "arn:aws:logs:us-east-1:111122223333:log-group:/aws/lambda/function name:*"
               ]
           }
       ]
   }
   ```

------

1. Choose **Next: Tags**.

1. (Optional) Add one or more tag-key value pairs to organize, track, or control access for this policy. 

1. Choose **Next: Review**.

1. On the **Review policy** page, for **Name**, enter a name for the inline policy, such as **amiLambda**.

1. Choose **Create policy**.

1. Repeat steps 2 and 3.

1. Paste the following policy. Replace each *example resource placeholder* with your own information.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "ssm:PutParameter",
               "Resource": "arn:aws:ssm:us-east-1:111122223333:parameter/latestAmi"
           },
           {
               "Effect": "Allow",
               "Action": "ssm:DescribeParameters",
               "Resource": "*"
           }
       ]
   }
   ```

------

1. Choose **Next: Tags**.

1. (Optional) Add one or more tag-key value pairs to organize, track, or control access for this policy. 

1. Choose **Next: Review**.

1. On the **Review policy** page, for **Name**, enter a name for the inline policy, such as **amiParameter**.

1. Choose **Create policy**.

1. In the navigation pane, choose **Roles**, and then choose **Create role**.

1. Immediately under **Use case**, choose **Lambda**, and then choose **Next**.

1. On the **Add permissions** page, use the **Search** field to locate the two policies you created earlier.

1. Select the check box next to the policies, and then choose **Next**.

1. For **Role name**, enter a name for your new role, such as **lambda-ssm-role** or another name that you prefer. 
**Note**  
Because various entities might reference the role, you cannot change the name of the role after it has been created.

1. (Optional) Add one or more tag key-value pairs to organize, track, or control access for this role, and then choose **Create role**.

## Task 3: Create an AWS Lambda function
<a name="create-lambda-function"></a>

Use the following procedure to create a Lambda function that automatically updates the value of the `latestAmi` parameter.

**To create a Lambda function**

1. Sign in to the AWS Management Console and open the AWS Lambda console at [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1. Choose **Create function**.

1. On the **Create function** page, choose **Author from scratch**.

1. For **Function name**, enter **Automation-UpdateSsmParam**.

1. For **Runtime**, choose **Python 3.11**.

1. For **Architecture**, select the type of computer processor for Lambda to use to run the function, **x86\$164** or **arm64**, 

1. In the **Permissions** section, expand **Change default execution role**.

1. Choose **Use an existing role**, and then choose the service role for Lambda that you created in Task 2.

1. Choose **Create function**.

1. In the **Code source** area, on the **lambda\$1function** tab, delete the pre-populated code in the field, and then paste the following code sample.

   ```
   from __future__ import print_function
   
   import json
   import boto3
   
   print('Loading function')
   
   
   #Updates an SSM parameter
   #Expects parameterName, parameterValue
   def lambda_handler(event, context):
       print("Received event: " + json.dumps(event, indent=2))
   
       # get SSM client
       client = boto3.client('ssm')
   
       #confirm  parameter exists before updating it
       response = client.describe_parameters(
          Filters=[
             {
              'Key': 'Name',
              'Values': [ event['parameterName'] ]
             },
           ]
       )
   
       if not response['Parameters']:
           print('No such parameter')
           return 'SSM parameter not found.'
   
       #if parameter has a Description field, update it PLUS the Value
       if 'Description' in response['Parameters'][0]:
           description = response['Parameters'][0]['Description']
           
           response = client.put_parameter(
             Name=event['parameterName'],
             Value=event['parameterValue'],
             Description=description,
             Type='String',
             Overwrite=True
           )
       
       #otherwise just update Value
       else:
           response = client.put_parameter(
             Name=event['parameterName'],
             Value=event['parameterValue'],
             Type='String',
             Overwrite=True
           )
           
       responseString = 'Updated parameter %s with value %s.' % (event['parameterName'], event['parameterValue'])
           
       return responseString
   ```

1. Choose **File, Save**.

1. To test the Lambda function, from the **Test** menu, choose **Configure test event**.

1. For **Event name**, enter a name for the test event, such as **MyTestEvent**.

1. Replace the existing text with the following JSON. Replace *AMI ID* with your own information to set your `latestAmi` parameter value.

   ```
   {
      "parameterName":"latestAmi",
      "parameterValue":"AMI ID"
   }
   ```

1. Choose **Save**.

1. Choose **Test** to test the function. On the **Execution result** tab, the status should be reported as **Succeeded**, along with other details about the update.

## Task 4: Create a runbook and patch the AMI
<a name="create-custom-ami-update-runbook"></a>

Use the following procedure to create and run a runbook that patches the AMI you specified for the **latestAmi** parameter. After the automation completes, the value of **latestAmi** is updated with the ID of the newly-patched AMI. Subsequent automations use the AMI created by the previous execution.

**To create and run the runbook**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Documents**.

1. For **Create document**, choose **Automation**.

1. For **Name**, enter **UpdateMyLatestWindowsAmi**.

1. Choose the **Editor** tab, and then choose **Edit**.

1. Choose **OK** when prompted.

1. In the **Document editor** field, replace the default content with the following YAML sample runbook content.

   ```
   ---
   description: Systems Manager Automation Demo - Patch AMI and Update ASG
   schemaVersion: '0.3'
   assumeRole: '{{ AutomationAssumeRole }}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: '(Required) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to execute this document.'
       default: ''
     SourceAMI:
       type: String
       description: The ID of the AMI you want to patch.
       default: '{{ ssm:latestAmi }}'
     SubnetId:
       type: String
       description: The ID of the subnet where the instance from the SourceAMI parameter is launched.
     SecurityGroupIds:
       type: StringList
       description: The IDs of the security groups to associate with the instance that's launched from the SourceAMI parameter.
     NewAMI:
       type: String
       description: The name of of newly patched AMI.
       default: 'patchedAMI-{{global:DATE_TIME}}'
     InstanceProfile:
       type: String
       description: The name of the IAM instance profile you want the source instance to use.
     SnapshotId:
       type: String
       description: (Optional) The snapshot ID to use to retrieve a patch baseline snapshot.
       default: ''
     RebootOption:
       type: String
       description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.'
       allowedValues:
         - NoReboot
         - RebootIfNeeded
       default: RebootIfNeeded
     Operation:
       type: String
       description: (Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.
       allowedValues:
         - Install
         - Scan
       default: Install
   mainSteps:
     - name: startInstances
       action: 'aws:runInstances'
       timeoutSeconds: 1200
       maxAttempts: 1
       onFailure: Abort
       inputs:
         ImageId: '{{ SourceAMI }}'
         InstanceType: m5.large
         MinInstanceCount: 1
         MaxInstanceCount: 1
         IamInstanceProfileName: '{{ InstanceProfile }}'
         SubnetId: '{{ SubnetId }}'
         SecurityGroupIds: '{{ SecurityGroupIds }}'
     - name: verifyInstanceManaged
       action: 'aws:waitForAwsResourceProperty'
       timeoutSeconds: 600
       inputs:
         Service: ssm
         Api: DescribeInstanceInformation
         InstanceInformationFilterList:
           - key: InstanceIds
             valueSet:
               - '{{ startInstances.InstanceIds }}'
         PropertySelector: '$.InstanceInformationList[0].PingStatus'
         DesiredValues:
           - Online
       onFailure: 'step:terminateInstance'
     - name: installPatches
       action: 'aws:runCommand'
       timeoutSeconds: 7200
       onFailure: Abort
       inputs:
         DocumentName: AWS-RunPatchBaseline
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
         InstanceIds:
           - '{{ startInstances.InstanceIds }}'
     - name: stopInstance
       action: 'aws:changeInstanceState'
       maxAttempts: 1
       onFailure: Continue
       inputs:
         InstanceIds:
           - '{{ startInstances.InstanceIds }}'
         DesiredState: stopped
     - name: createImage
       action: 'aws:createImage'
       maxAttempts: 1
       onFailure: Continue
       inputs:
         InstanceId: '{{ startInstances.InstanceIds }}'
         ImageName: '{{ NewAMI }}'
         NoReboot: false
         ImageDescription: Patched AMI created by Automation
     - name: terminateInstance
       action: 'aws:changeInstanceState'
       maxAttempts: 1
       onFailure: Continue
       inputs:
         InstanceIds:
           - '{{ startInstances.InstanceIds }}'
         DesiredState: terminated
     - name: updateSsmParam
       action: aws:invokeLambdaFunction
       timeoutSeconds: 1200
       maxAttempts: 1
       onFailure: Abort
       inputs:
           FunctionName: Automation-UpdateSsmParam
           Payload: '{"parameterName":"latestAmi", "parameterValue":"{{createImage.ImageId}}"}'
   outputs:
   - createImage.ImageId
   ```

1. Choose **Create automation**.

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Choose document** page, choose the **Owned by me** tab.

1. Search for the **UpdateMyLatestWindowsAmi** runbook, and select the button in the **UpdateMyLatestWindowsAmi** card.

1. Choose **Next**.

1. Choose **Simple execution**.

1. Specify values for the input parameters.

1. Choose **Execute**.

1. After the automation completes, choose **Parameter Store** in the navigation pane and confirm that the new value for `latestAmi` matches the value returned by the automation. You can also verify the new AMI ID matches the Automation output in the **AMIs** section of the Amazon EC2 console.

# Updating AMIs using Automation and Jenkins
<a name="automation-tutorial-update-patch-ami-jenkins-integration"></a>

If your organization uses Jenkins software in a CI/CD pipeline, you can add Automation as a post-build step to pre-install application releases into Amazon Machine Images (AMIs). Automation is a tool in AWS Systems Manager. You can also use the Jenkins scheduling feature to call Automation and create your own operating system (OS) patching cadence.

The example below shows how to invoke Automation from a Jenkins server that is running either on-premises or in Amazon Elastic Compute Cloud (Amazon EC2). For authentication, the Jenkins server uses AWS credentials based on an IAM policy that you create in the example and attach to your instance profile.

**Note**  
Be sure to follow Jenkins security best practices when configuring your instance.

**Before you begin**  
Complete the following tasks before you configure Automation with Jenkins:
+ Complete the [Update a golden AMI using Automation, AWS Lambda, and Parameter Store](automation-tutorial-update-patch-golden-ami.md) example. The following example uses the **UpdateMyLatestWindowsAmi** runbook created in that example.
+ Configure IAM roles for Automation. Systems Manager requires an instance profile role and a service role ARN to process automations. For more information, see [Setting up Automation](automation-setup.md).

**To create an IAM policy for the Jenkins server**

1. Sign in to the AWS Management Console and open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).

1. In the navigation pane, choose **Policies**, and then choose **Create policy**.

1. Choose the **JSON** tab.

1. Replace each *example resource placeholder* with your own information.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "ssm:StartAutomationExecution",
               "Resource": [
                   "arn:aws:ssm:us-east-1:111122223333:document/UpdateMyLatestWindowsAmi",
                   "arn:aws:ssm:us-east-1:111122223333:automation-execution/*"
               ]
           }
       ]
   }
   ```

------

1. Choose **Review policy**.

1. On the **Review policy** page, for **Name**, enter a name for the inline policy, such as **JenkinsPolicy**.

1. Choose **Create policy**.

1. In the navigation pane, choose **Roles**.

1. Choose the instance profile that's attached to your Jenkins server.

1. In the **Permissions** tab, select **Add permissions** and choose **Attach policies**.

1. In the **Other permissions policies** section, enter the name of policy you created in the previous steps. For example, **JenkinsPolicy**.

1. Select the check box next to your policy, and choose **Attach policies**.

Use the following procedure to configure the AWS CLI on your Jenkins server.

**To configure the Jenkins server for Automation**

1. Connect to your Jenkins server on port 8080 using your preferred browser to access the management interface.

1. Enter the password found in `/var/lib/jenkins/secrets/initialAdminPassword`. To display your password, run the following command.

   ```
   sudo cat /var/lib/jenkins/secrets/initialAdminPassword
   ```

1. The Jenkins installation script directs you to the **Customize Jenkins** page. Select **Install suggested plugins**.

1. Once the installation is complete, choose **Administrator Credentials**, select **Save Credentials**, and then select **Start Using Jenkins**.

1. In the left navigation pane, choose **Manage Jenkins**, and then choose **Manage Plugins**.

1. Choose the **Available** tab, and then enter **Amazon EC2 plugin**.

1. Select the check box for **Amazon EC2 plugin**, and then select **Install without restart**.

1. When the installation completes, select **Go back to the top page**.

1. Choose **Manage Jenkins**, and then choose **Manage nodes and clouds**.

1. In the **Configure Clouds** section, select **Add a new cloud**, and then choose **Amazon EC2**.

1. Enter your information in the remaining fields. Make sure you select the **Use EC2 instance profile to obtain credentials** option.

Use the following procedure to configure your Jenkins project to invoke Automation.

**To configure your Jenkins server to invoke Automation**

1. Open the Jenkins console in a web browser.

1. Choose the project that you want to configure with Automation, and then choose **Configure**.

1. On the **Build** tab, choose **Add Build Step**.

1. Choose **Execute shell** or **Execute Windows batch command** (depending on your operating system).

1. In the **Command** field, run an AWS CLI command like the following. Replace each *example resource placeholder* with your own information.

   ```
   aws ssm start-automation-execution \
           --document-name runbook name \
           --region AWS Region of your source AMI \
           --parameters runbook parameters
   ```

   The following example command uses the **UpdateMyLatestWindowsAmi** runbook and the Systems Manager Parameter `latestAmi` created in [Update a golden AMI using Automation, AWS Lambda, and Parameter Store](automation-tutorial-update-patch-golden-ami.md).

   ```
   aws ssm start-automation-execution \
           --document-name UpdateMyLatestWindowsAmi \
           --parameters \
               "sourceAMIid='{{ssm:latestAmi}}'"
           --region region
   ```

   In Jenkins, the command looks like the example in the following screenshot.  
![\[A sample command in Jenkins software.\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/sysman-ami-jenkins2.png)

1. In the Jenkins project, choose **Build Now**. Jenkins returns output similar to the following example.  
![\[Sample command output in Jenkins software.\]](http://docs.aws.amazon.com/systems-manager/latest/userguide/images/sysman-ami-jenkins.png)

# Updating AMIs for Auto Scaling groups
<a name="automation-tutorial-update-patch-windows-ami-autoscaling"></a>

The following example updates an Auto Scaling group with a newly patched AMI. This approach ensures that new images are automatically made available to different computing environments that use Auto Scaling groups.

The final step of the automation in this example uses a Python function to create a new launch template that uses the newly patched AMI. Then the Auto Scaling group is updated to use the new launch template. In this type of Auto Scaling scenario, users could terminate existing instances in the Auto Scaling group to force a new instance to launch that uses the new image. Or, users could wait and allow scale-in or scale-out events to naturally launch newer instances.

**Before you begin**  
Complete the following tasks before you begin this example.
+ Configure IAM roles for Automation, a tool in AWS Systems Manager. Systems Manager requires an instance profile role and a service role ARN to process automations. For more information, see [Setting up Automation](automation-setup.md).

## Create the **PatchAMIAndUpdateASG** runbook
<a name="create-autoscaling-update-runbook"></a>

Use the following procedure to create the **PatchAMIAndUpdateASG** runbook that patches the AMI you specify for the **SourceAMI** parameter. The runbook also updates an Auto Scaling group to use the latest, patched AMI.

**To create and run the runbook**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Documents**.

1. In the **Create document** dropdown, choose **Automation**.

1. In the **Name** field, enter **PatchAMIAndUpdateASG**.

1. Choose the **Editor** tab, and choose the **Edit**.

1. Choose **OK** when prompted, and delete the content in the **Document editor** field.

1. In the **Document editor** field, paste the following YAML sample runbook content.

   ```
   ---
   description: Systems Manager Automation Demo - Patch AMI and Update ASG
   schemaVersion: '0.3'
   assumeRole: '{{ AutomationAssumeRole }}'
   parameters:
     AutomationAssumeRole:
       type: String
       description: '(Required) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to execute this document.'
       default: ''
     SourceAMI:
       type: String
       description: '(Required) The ID of the AMI you want to patch.'
     SubnetId:
       type: String
       description: '(Required) The ID of the subnet where the instance from the SourceAMI parameter is launched.'
     SecurityGroupIds:
       type: StringList
       description: '(Required) The IDs of the security groups to associate with the instance launched from the SourceAMI parameter.'
     NewAMI:
       type: String
       description: '(Optional) The name of of newly patched AMI.'
       default: 'patchedAMI-{{global:DATE_TIME}}'
     TargetASG:
       type: String
       description: '(Required) The name of the Auto Scaling group you want to update.'
     InstanceProfile:
       type: String
       description: '(Required) The name of the IAM instance profile you want the source instance to use.'
     SnapshotId:
       type: String
       description: (Optional) The snapshot ID to use to retrieve a patch baseline snapshot.
       default: ''
     RebootOption:
       type: String
       description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.'
       allowedValues:
         - NoReboot
         - RebootIfNeeded
       default: RebootIfNeeded
     Operation:
       type: String
       description: (Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.
       allowedValues:
         - Install
         - Scan
       default: Install
   mainSteps:
     - name: startInstances
       action: 'aws:runInstances'
       timeoutSeconds: 1200
       maxAttempts: 1
       onFailure: Abort
       inputs:
         ImageId: '{{ SourceAMI }}'
         InstanceType: m5.large
         MinInstanceCount: 1
         MaxInstanceCount: 1
         IamInstanceProfileName: '{{ InstanceProfile }}'
         SubnetId: '{{ SubnetId }}'
         SecurityGroupIds: '{{ SecurityGroupIds }}'
     - name: verifyInstanceManaged
       action: 'aws:waitForAwsResourceProperty'
       timeoutSeconds: 600
       inputs:
         Service: ssm
         Api: DescribeInstanceInformation
         InstanceInformationFilterList:
           - key: InstanceIds
             valueSet:
               - '{{ startInstances.InstanceIds }}'
         PropertySelector: '$.InstanceInformationList[0].PingStatus'
         DesiredValues:
           - Online
       onFailure: 'step:terminateInstance'
     - name: installPatches
       action: 'aws:runCommand'
       timeoutSeconds: 7200
       onFailure: Abort
       inputs:
         DocumentName: AWS-RunPatchBaseline
         Parameters:
           SnapshotId: '{{SnapshotId}}'
           RebootOption: '{{RebootOption}}'
           Operation: '{{Operation}}'
         InstanceIds:
           - '{{ startInstances.InstanceIds }}'
     - name: stopInstance
       action: 'aws:changeInstanceState'
       maxAttempts: 1
       onFailure: Continue
       inputs:
         InstanceIds:
           - '{{ startInstances.InstanceIds }}'
         DesiredState: stopped
     - name: createImage
       action: 'aws:createImage'
       maxAttempts: 1
       onFailure: Continue
       inputs:
         InstanceId: '{{ startInstances.InstanceIds }}'
         ImageName: '{{ NewAMI }}'
         NoReboot: false
         ImageDescription: Patched AMI created by Automation
     - name: terminateInstance
       action: 'aws:changeInstanceState'
       maxAttempts: 1
       onFailure: Continue
       inputs:
         InstanceIds:
           - '{{ startInstances.InstanceIds }}'
         DesiredState: terminated
     - name: updateASG
       action: 'aws:executeScript'
       timeoutSeconds: 300
       maxAttempts: 1
       onFailure: Abort
       inputs:
         Runtime: python3.11
         Handler: update_asg
         InputPayload:
           TargetASG: '{{TargetASG}}'
           NewAMI: '{{createImage.ImageId}}'
         Script: |-
           from __future__ import print_function
           import datetime
           import json
           import time
           import boto3
   
           # create auto scaling and ec2 client
           asg = boto3.client('autoscaling')
           ec2 = boto3.client('ec2')
   
           def update_asg(event, context):
               print("Received event: " + json.dumps(event, indent=2))
   
               target_asg = event['TargetASG']
               new_ami = event['NewAMI']
   
               # get object for the ASG we're going to update, filter by name of target ASG
               asg_query = asg.describe_auto_scaling_groups(AutoScalingGroupNames=[target_asg])
               if 'AutoScalingGroups' not in asg_query or not asg_query['AutoScalingGroups']:
                   return 'No ASG found matching the value you specified.'
   
               # gets details of an instance from the ASG that we'll use to model the new launch template after
               source_instance_id = asg_query.get('AutoScalingGroups')[0]['Instances'][0]['InstanceId']
               instance_properties = ec2.describe_instances(
                   InstanceIds=[source_instance_id]
               )
               source_instance = instance_properties['Reservations'][0]['Instances'][0]
   
               # create list of security group IDs
               security_groups = []
               for group in source_instance['SecurityGroups']:
                   security_groups.append(group['GroupId'])
   
               # create a list of dictionary objects for block device mappings
               mappings = []
               for block in source_instance['BlockDeviceMappings']:
                   volume_query = ec2.describe_volumes(
                       VolumeIds=[block['Ebs']['VolumeId']]
                   )
                   volume_details = volume_query['Volumes']
                   device_name = block['DeviceName']
                   volume_size = volume_details[0]['Size']
                   volume_type = volume_details[0]['VolumeType']
                   device = {'DeviceName': device_name, 'Ebs': {'VolumeSize': volume_size, 'VolumeType': volume_type}}
                   mappings.append(device)
   
               # create new launch template using details returned from instance in the ASG and specify the newly patched AMI
               time_stamp = time.time()
               time_stamp_string = datetime.datetime.fromtimestamp(time_stamp).strftime('%m-%d-%Y_%H-%M-%S')
               new_template_name = f'{new_ami}_{time_stamp_string}'
               try:
                   ec2.create_launch_template(
                       LaunchTemplateName=new_template_name,
                       LaunchTemplateData={
                           'BlockDeviceMappings': mappings,
                           'ImageId': new_ami,
                           'InstanceType': source_instance['InstanceType'],
                           'IamInstanceProfile': {
                               'Arn': source_instance['IamInstanceProfile']['Arn']
                           },
                           'KeyName': source_instance['KeyName'],
                           'SecurityGroupIds': security_groups
                       }
                   )
               except Exception as e:
                   return f'Exception caught: {str(e)}'
               else:
                   # update ASG to use new launch template
                   asg.update_auto_scaling_group(
                       AutoScalingGroupName=target_asg,
                       LaunchTemplate={
                           'LaunchTemplateName': new_template_name
                       }
                   )
                   return f'Updated ASG {target_asg} with new launch template {new_template_name} which uses AMI {new_ami}.'
   outputs:
   - createImage.ImageId
   ```

1. Choose **Create automation**.

1. In the navigation pane, choose **Automation**, and then choose **Execute automation**.

1. In the **Choose document** page, choose the **Owned by me** tab.

1. Search for the **PatchAMIAndUpdateASG** runbook, and select the button in the **PatchAMIAndUpdateASG** card.

1. Choose **Next**.

1. Choose **Simple execution**.

1. Specify values for the input parameters. Be sure the `SubnetId` and `SecurityGroupIds` you specify allow access to the public Systems Manager endpoints, or your interface endpoints for Systems Manager.

1. Choose **Execute**.

1. After automation completes, in the Amazon EC2 console, choose **Auto Scaling**, and then choose **Launch Templates**. Verify that you see the new launch template, and that it uses the new AMI.

1. Choose **Auto Scaling**, and then choose **Auto Scaling Groups**. Verify that the Auto Scaling group uses the new launch template.

1. Terminate one or more instances in your Auto Scaling group. Replacement instances will be launched using the new AMI.

# Using AWS Support self-service runbooks
<a name="automation-tutorial-support-runbooks"></a>

This section describes how to use some of the self-service automations created by the AWS Support team. These automations help you manage your AWS resources.

**Support Automation Workflows**  
Support Automation Workflows (SAW) are automation runbooks written and maintained by the AWS Support team. These runbooks help you troubleshoot common issues with your AWS resources, proactively monitor and identify network issues, collect and analyze logs, and more.

SAW runbooks use the **`AWSSupport`** prefix. For example, [https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awssupport-activatewindowswithamazonlicense.html](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awssupport-activatewindowswithamazonlicense.html).

Additionally, customers with Business Support\$1 and higher AWS Support plans also have access to runbooks that use the **`AWSPremiumSupport`** prefix. For example, [https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awspremiumsupport-troubleshootEC2diskusage.html](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awspremiumsupport-troubleshootEC2diskusage.html).

To learn more about AWS Support, see [Getting started with AWS Support](https://docs.aws.amazon.com/awssupport/latest/user/getting-started.html).

**Topics**
+ [Run the EC2Rescue tool on unreachable instances](automation-ec2rescue.md)
+ [Reset passwords and SSH keys on EC2 instances](automation-ec2reset.md)

# Run the EC2Rescue tool on unreachable instances
<a name="automation-ec2rescue"></a>

EC2Rescue can help you diagnose and troubleshoot problems on Amazon Elastic Compute Cloud (Amazon EC2) instances for Linux and Windows Server. You can run the tool manually, as described in [Using EC2Rescue for Linux Server](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Linux-Server-EC2Rescue.html) and [Using EC2Rescue for Windows Server](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/Windows-Server-EC2Rescue.html). Or, you can run the tool automatically by using Systems Manager Automation and the **`AWSSupport-ExecuteEC2Rescue`** runbook. Automation is a tool in AWS Systems Manager. The **`AWSSupport-ExecuteEC2Rescue`** runbook is designed to perform a combination of Systems Manager actions, CloudFormation actions, and Lambda functions that automate the steps normally required to use EC2Rescue. 

You can use the **`AWSSupport-ExecuteEC2Rescue`** runbook to troubleshoot and potentially remediate different types of operating system (OS) issues. Instances with encypted root volumes are not supported. See the following topics for a complete list:

**Windows**: See *Rescue Action* in [Using EC2Rescue for Windows Server with the Command Line](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2rw-cli.html#ec2rw-rescue).

**Linux** and **macOS**: Some EC2Rescue for Linux modules detect and attempt to remediate issues. For more information, see the [https://github.com/awslabs/aws-ec2rescue-linux/tree/master/docs](https://github.com/awslabs/aws-ec2rescue-linux/tree/master/docs) documentation for each module on GitHub.

## How it works
<a name="automation-ec2rescue-how"></a>

Troubleshooting an instance with Automation and the **`AWSSupport-ExecuteEC2Rescue`** runbook works as follows:
+ You specify the ID of the unreachable instance and start the runbook.
+ The system creates a temporary VPC, and then runs a series of Lambda functions to configure the VPC.
+ The system identifies a subnet for your temporary VPC in the same Availability Zone as your original instance.
+ The system launches a temporary, SSM-enabled helper instance.
+ The system stops your original instance, and creates a backup. It then attaches the original root volume to the helper instance.
+ The system uses Run Command to run EC2Rescue on the helper instance. EC2Rescue identifies and attempts to fix issues on the attached, original root volume. When finished, EC2Rescue reattaches the root volume back to the original instance.
+ The system restarts your original instance, and terminates the temporary instance. The system also terminates the temporary VPC and the Lambda functions created at the start of the automation.

## Before you begin
<a name="automation-ec2rescue-begin"></a>

Before you run the following Automation, do the following:
+ Copy the instance ID of the unreachable instance. You will specify this ID in the procedure.
+ Optionally, collect the ID of a subnet in the same availability zone as your unreachable instance. The EC2Rescue instance will be created in this subnet. If you don’t specify a subnet, then Automation creates a new temporary VPC in your AWS account. Verify that your AWS account has at least one VPC available. By default, you can create five VPCs in a Region. If you already created five VPCs in the Region, the automation fails without making changes to your instance. For more information about Amazon VPC quotas, see [VPC and Subnets](https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html#vpc-limits-vpcs-subnets) in the *Amazon VPC User Guide*.
+ Optionally, you can create and specify an AWS Identity and Access Management (IAM) role for Automation. If you don't specify this role, then Automation runs in the context of the user who ran the automation.

### Granting `AWSSupport-EC2Rescue` permissions to perform actions on your instances
<a name="automation-ec2rescue-access"></a>

EC2Rescue needs permission to perform a series of actions on your instances during the automation. These actions invoke the AWS Lambda, IAM, and Amazon EC2 services to safely and securely attempt to remediate issues with your instances. If you have Administrator-level permissions in your AWS account and/or VPC, you might be able to run the automation without configuring permissions, as described in this section. If you don't have Administrator-level permissions, then you or an administrator must configure permissions by using one of the following options.
+ [Granting permissions by using IAM policies](#automation-ec2rescue-access-iam)
+ [Granting permissions by using an CloudFormation template](#automation-ec2rescue-access-cfn)

#### Granting permissions by using IAM policies
<a name="automation-ec2rescue-access-iam"></a>

You can either attach the following IAM policy to your user, group, or role as an inline policy; or, you can create a new IAM managed policy and attach it to your user, group, or role. For more information about adding an inline policy to your user, group, or role see [Working With Inline Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_inline-using.html). For more information about creating a new managed policy, see [Working With Managed Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-using.html).

**Note**  
If you create a new IAM managed policy, you must also attach the **AmazonSSMAutomationRole** managed policy to it so that your instances can communicate with the Systems Manager API.

**IAM Policy for AWSSupport-EC2Rescue**

Replace *account ID* with your own information.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "lambda:InvokeFunction",
                "lambda:DeleteFunction",
                "lambda:GetFunction"
            ],
            "Resource": "arn:aws:lambda:*:111122223333:function:AWSSupport-EC2Rescue-*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::awssupport-ssm.*/*.template",
                "arn:aws:s3:::awssupport-ssm.*/*.zip"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "iam:CreateRole",
                "iam:CreateInstanceProfile",
                "iam:GetRole",
                "iam:GetInstanceProfile",
                "iam:PutRolePolicy",
                "iam:DetachRolePolicy",
                "iam:AttachRolePolicy",
                "iam:PassRole",
                "iam:AddRoleToInstanceProfile",
                "iam:RemoveRoleFromInstanceProfile",
                "iam:DeleteRole",
                "iam:DeleteRolePolicy",
                "iam:DeleteInstanceProfile"
            ],
            "Resource": [
                "arn:aws:iam::111122223333:role/AWSSupport-EC2Rescue-*",
                "arn:aws:iam::111122223333:instance-profile/AWSSupport-EC2Rescue-*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "lambda:CreateFunction",
                "ec2:CreateVpc",
                "ec2:ModifyVpcAttribute",
                "ec2:DeleteVpc",
                "ec2:CreateInternetGateway",
                "ec2:AttachInternetGateway",
                "ec2:DetachInternetGateway",
                "ec2:DeleteInternetGateway",
                "ec2:CreateSubnet",
                "ec2:DeleteSubnet",
                "ec2:CreateRoute",
                "ec2:DeleteRoute",
                "ec2:CreateRouteTable",
                "ec2:AssociateRouteTable",
                "ec2:DisassociateRouteTable",
                "ec2:DeleteRouteTable",
                "ec2:CreateVpcEndpoint",
                "ec2:DeleteVpcEndpoints",
                "ec2:ModifyVpcEndpoint",
                "ec2:Describe*",
                "autoscaling:DescribeAutoScalingInstances"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
```

------

#### Granting permissions by using an CloudFormation template
<a name="automation-ec2rescue-access-cfn"></a>

CloudFormation automates the process of creating IAM roles and policies by using a preconfigured template. Use the following procedure to create the required IAM roles and policies for the EC2Rescue Automation by using CloudFormation.

**To create the required IAM roles and policies for EC2Rescue**

1. Download [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWSSupport-EC2RescueRole.zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWSSupport-EC2RescueRole.zip) and extract the `AWSSupport-EC2RescueRole.json` file to a directory on your local machine.

1. If your AWS account is in a special partition, edit the template to change the ARN values to those for your partition.

   For example, for the China Regions, change all cases of `arn:aws` to `arn:aws-cn`.

1. Sign in to the AWS Management Console and open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create stack**, **With new resources (standard)**.

1. On the **Create stack** page, for **Prerequisite - Prepare template**, choose **Template is ready**.

1. For **Specify template**, choose **Upload a template file**.

1. Choose **Choose file**, and then browse to and select the `AWSSupport-EC2RescueRole.json` file from the directory where you extracted it.

1. Choose **Next**.

1. On the **Specify stack details** page, for **Stack name** field, enter a name to identify this stack, and then choose **Next**.

1. (Optional) In the **Tags** area, apply one or more tag key name/value pairs to the stack.

   Tags are optional metadata that you assign to a resource. Tags enable you to categorize a resource in different ways, such as by purpose, owner, or environment. For example, you might want to tag a stack to identify the type of tasks it runs, the types of targets or other resources involved, and the environment it runs in.

1. Choose **Next**

1. On the **Review** page, review the stack details, and then scroll down and choose the **I acknowledge that CloudFormation might create IAM resources** option.

1. Choose **Create stack**.

   CloudFormation shows the **CREATE\$1IN\$1PROGRESS** status for a few minutes. The status changes to **CREATE\$1COMPLETE** after the stack has been created. You can also choose the refresh icon to check the status of the create process.

1. In the **Stacks** list, choose the option button the stack you just created, and then choose the **Outputs** tab.

1. Note the **Value**. The is the ARN of the AssumeRole. You specify this ARN when you run the Automation in the next procedure, [Running the Automation](#automation-ec2rescue-executing). 

## Running the Automation
<a name="automation-ec2rescue-executing"></a>

**Important**  
The following automation stops the unreachable instance. Stopping the instance can result in lost data on attached instance store volumes (if present). Stopping the instance can also cause the public IP to change, if no Elastic IP is associated.

**To run the `AWSSupport-ExecuteEC2Rescue` Automation**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose **Execute automation**.

1. In the **Automation document** section, choose **Owned by Amazon** from the list.

1. In the runbooks list, choose the button in the card for `AWSSupport-ExecuteEC2Rescue`, and then choose **Next**.

1. In the **Execute automation document** page, choose **Simple execution**.

1. In the **Document details** section, verify that **Document version** is set to the highest default version. For example, **\$1DEFAULT** or **3 (default)**.

1. In the **Input parameters** section, specify the following parameters: 

   1. For **UnreachableInstanceId**, specify the ID of the unreachable instance. 

   1. (Optional) For **EC2RescueInstanceType**, specify an instance type for the EC2Rescue instance. The default instance type is `t2.medium`.

   1. For **AutomationAssumeRole**, if you created roles for this Automation by using the CloudFormation procedure described earlier in this topic, then choose the ARN of the AssumeRole that you created in the CloudFormation console.

   1. (Optional) For **LogDestination**, specify an S3 bucket if you want to collect operating system-level logs while troubleshooting your instance. Logs are automatically uploaded to the specified bucket.

   1. For **SubnetId**, specify a subnet in an existing VPC in the same availability zone as the unreachable instance. By default, Systems Manager creates a new VPC, but you can specify a subnet in an existing VPC if you want.
**Note**  
If you don't see the option to specify a bucket or a subnet ID, verify that you are using the latest **Default** version of the runbook.

1. (Optional) In the **Tags** area, apply one or more tag key name/value pairs to help identify the automation, for example `Key=Purpose,Value=EC2Rescue`.

1. Choose **Execute**.

The runbook creates a backup AMI as part of the automation. All other resources created by the automation are automatically deleted, but this AMI remains in your account. The AMI is named using the following convention:

Backup AMI: AWSSupport-EC2Rescue:*UnreachableInstanceId*

You can locate this AMI in the Amazon EC2 console by searching on the Automation execution ID.

# Reset passwords and SSH keys on EC2 instances
<a name="automation-ec2reset"></a>

You can use the `AWSSupport-ResetAccess` runbook to automatically re-enable local Administrator password generation on Amazon Elastic Compute Cloud (Amazon EC2) instances for Windows Server and to generate a new SSH key on EC2 instances for Linux. The `AWSSupport-ResetAccess` runbook is designed to perform a combination of AWS Systems Manager actions, AWS CloudFormation actions, and AWS Lambda functions that automate the steps normally required to reset the local administrator password.

You can use Automation, a tool in AWS Systems Manager, with the `AWSSupport-ResetAccess` runbook to solve the following problems:

**Windows**

*You lost the EC2 key pair*: To resolve this problem, you can use the **AWSSupport-ResetAccess** runbook to create a password-enabled AMI from your current instance, launch a new instance from the AMI, and select a key pair you own.

*You lost the local Administrator password*: To resolve this problem, you can use the `AWSSupport-ResetAccess` runbook to generate a new password that you can decrypt with the current EC2 key pair.

**Linux**

*You lost your EC2 key pair, or you configured SSH access to the instance with a key you lost*: To resolve this problem, you can use the `AWSSupport-ResetAccess` runbook to create a new SSH key for your current instance, which enables you to connect to the instance again.

**Note**  
If your EC2 instance for Windows Server is configured for Systems Manager, you can also reset your local Administrator password by using EC2Rescue and AWS Systems Manager Run Command. For more information, see [Using EC2Rescue for Windows Server with Systems Manager Run Command](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2rw-ssm.html) in the *Amazon EC2 User Guide*.

**Related information**  
[Connect to your Linux instance from Windows using PuTTY](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html) in the *Amazon EC2 User Guide*

## How it works
<a name="automation-ec2reset-how"></a>

Troubleshooting an instance with Automation and the `AWSSupport-ResetAccess` runbook works as follows:
+ You specify the ID of the instance and run the runbook.
+ The system creates a temporary VPC, and then runs a series of Lambda functions to configure the VPC.
+ The system identifies a subnet for your temporary VPC in the same Availability Zone as your original instance.
+ The system launches a temporary, SSM-enabled helper instance.
+ The system stops your original instance, and creates a backup. It then attaches the original root volume to the helper instance.
+ The system uses Run Command to run EC2Rescue on the helper instance. On Windows, EC2Rescue enables password generation for the local Administrator by using EC2Config or EC2Launch on the attached, original root volume. On Linux, EC2Rescue generates and injects a new SSH key and saves the private key, encrypted, in Parameter Store. When finished, EC2Rescue reattaches the root volume back to the original instance.
+ The system creates a new Amazon Machine Image (AMI) of your instance, now that password generation is enabled. You can use this AMI to create a new EC2 instance, and associate a new key pair if needed.
+ The system restarts your original instance, and terminates the temporary instance. The system also terminates the temporary VPC and the Lambda functions created at the start of the automation.
+ **Windows**: Your instance generates a new password you can decode from the Amazon EC2 console using the current key pair assigned to the instance.

  **Linux**: You can SSH to the instance by using the SSH key stored in Systems Manager Parameter Store as **/ec2rl/openssh/*instance ID*/key**.

## Before you begin
<a name="automation-ec2reset-begin"></a>

Before you run the following Automation, do the following:
+ Copy the instance ID of the instance on which you want to reset the Administrator password. You will specify this ID in the procedure.
+ Optionally, collect the ID of a subnet in the same availability zone as your unreachable instance. The EC2Rescue instance will be created in this subnet. If you don’t specify a subnet, then Automation creates a new temporary VPC in your AWS account. Verify that your AWS account has at least one VPC available. By default, you can create five VPCs in a Region. If you already created five VPCs in the Region, the automation fails without making changes to your instance. For more information about Amazon VPC quotas, see [VPC and Subnets](https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html#vpc-limits-vpcs-subnets) in the *Amazon VPC User Guide*.
+ Optionally, you can create and specify an AWS Identity and Access Management (IAM) role for Automation. If you don't specify this role, then Automation runs in the context of the user who ran the automation.

### Granting AWSSupport-EC2Rescue permissions to perform actions on your instances
<a name="automation-ec2reset-access"></a>

EC2Rescue needs permission to perform a series of actions on your instances during the automation. These actions invoke the AWS Lambda, IAM, and Amazon EC2 services to safely and securely attempt to remediate issues with your instances. If you have Administrator-level permissions in your AWS account and/or VPC, you might be able to run the automation without configuring permissions, as described in this section. If you don't have Administrator-level permissions, then you or an administrator must configure permissions by using one of the following options.
+ [Granting permissions by using IAM policies](#automation-ec2reset-access-iam)
+ [Granting permissions by using an CloudFormation template](#automation-ec2reset-access-cfn)

#### Granting permissions by using IAM policies
<a name="automation-ec2reset-access-iam"></a>

You can either attach the following IAM policy to your user, group, or role as an inline policy; or, you can create a new IAM managed policy and attach it to your user, group, or role. For more information about adding an inline policy to your user, group, or role see [Working With Inline Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_inline-using.html). For more information about creating a new managed policy, see [Working With Managed Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-using.html).

**Note**  
If you create a new IAM managed policy, you must also attach the **AmazonSSMAutomationRole** managed policy to it so that your instances can communicate with the Systems Manager API.

**IAM Policy for `AWSSupport-ResetAccess`**

Replace *account ID* with your own information.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "lambda:InvokeFunction",
                "lambda:DeleteFunction",
                "lambda:GetFunction"
            ],
            "Resource": "arn:aws:lambda:*:111122223333:function:AWSSupport-EC2Rescue-*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::awssupport-ssm.*/*.template",
                "arn:aws:s3:::awssupport-ssm.*/*.zip"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "iam:CreateRole",
                "iam:CreateInstanceProfile",
                "iam:GetRole",
                "iam:GetInstanceProfile",
                "iam:PutRolePolicy",
                "iam:DetachRolePolicy",
                "iam:AttachRolePolicy",
                "iam:PassRole",
                "iam:AddRoleToInstanceProfile",
                "iam:RemoveRoleFromInstanceProfile",
                "iam:DeleteRole",
                "iam:DeleteRolePolicy",
                "iam:DeleteInstanceProfile"
            ],
            "Resource": [
                "arn:aws:iam::111122223333:role/AWSSupport-EC2Rescue-*",
                "arn:aws:iam::111122223333:instance-profile/AWSSupport-EC2Rescue-*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "lambda:CreateFunction",
                "ec2:CreateVpc",
                "ec2:ModifyVpcAttribute",
                "ec2:DeleteVpc",
                "ec2:CreateInternetGateway",
                "ec2:AttachInternetGateway",
                "ec2:DetachInternetGateway",
                "ec2:DeleteInternetGateway",
                "ec2:CreateSubnet",
                "ec2:DeleteSubnet",
                "ec2:CreateRoute",
                "ec2:DeleteRoute",
                "ec2:CreateRouteTable",
                "ec2:AssociateRouteTable",
                "ec2:DisassociateRouteTable",
                "ec2:DeleteRouteTable",
                "ec2:CreateVpcEndpoint",
                "ec2:DeleteVpcEndpoints",
                "ec2:ModifyVpcEndpoint",
                "ec2:Describe*"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
```

------

#### Granting permissions by using an CloudFormation template
<a name="automation-ec2reset-access-cfn"></a>

CloudFormation automates the process of creating IAM roles and policies by using a preconfigured template. Use the following procedure to create the required IAM roles and policies for the EC2Rescue Automation by using CloudFormation.

**To create the required IAM roles and policies for EC2Rescue**

1. Download [https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWSSupport-EC2RescueRole.zip](https://docs.aws.amazon.com/systems-manager/latest/userguide/samples/AWSSupport-EC2RescueRole.zip) and extract the `AWSSupport-EC2RescueRole.json` file to a directory on your local machine.

1. If your AWS account is in a special partition, edit the template to change the ARN values to those for your partition.

   For example, for the China Regions, change all cases of `arn:aws` to `arn:aws-cn`.

1. Sign in to the AWS Management Console and open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create stack**, **With new resources (standard)**.

1. On the **Create stack** page, for **Prerequisite - Prepare template**, choose **Template is ready**.

1. For **Specify template**, choose **Upload a template file**.

1. Choose **Choose file**, and then browse to and select the `AWSSupport-EC2RescueRole.json` file from the directory where you extracted it.

1. Choose **Next**.

1. On the **Specify stack details** page, for **Stack name** field, enter a name to identify this stack, and then choose **Next**.

1. (Optional) In the **Tags** area, apply one or more tag key name/value pairs to the stack.

   Tags are optional metadata that you assign to a resource. Tags enable you to categorize a resource in different ways, such as by purpose, owner, or environment. For example, you might want to tag a stack to identify the type of tasks it runs, the types of targets or other resources involved, and the environment it runs in.

1. Choose **Next**

1. On the **Review** page, review the stack details, and then scroll down and choose the **I acknowledge that CloudFormation might create IAM resources** option.

1. CloudFormation shows the **CREATE\$1IN\$1PROGRESS** status for a few minutes. The status changes to **CREATE\$1COMPLETE** after the stack has been created. You can also choose the refresh icon to check the status of the create process.

1. In the stack list, choose the option next to the stack you just created, and then choose the **Outputs** tab.

1. Copy the **Value**. The is the ARN of the AssumeRole. You will specify this ARN when you run the Automation. 

## Running the Automation
<a name="automation-ec2reset-executing"></a>

The following procedure describes how to run the `AWSSupport-ResetAccess` runbook by using the AWS Systems Manager console.

**Important**  
The following automation stops the instance. Stopping the instance can result in lost data on attached instance store volumes (if present). Stopping the instance can also cause the public IP to change, if no Elastic IP is associated. To avoid these configuration changes, use Run Command to reset access. For more information, see [Using EC2Rescue for Windows Server with Systems Manager Run Command](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2rw-ssm.html) in the *Amazon EC2 User Guide*.

**To run the AWSSupport-ResetAccess Automation**

1. Open the AWS Systems Manager console at [https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/).

1. In the navigation pane, choose **Automation**.

1. Choose **Execute automation**.

1. In the **Automation document** section, choose **Owned by Amazon** from the list.

1. In the runbooks list, choose the button in the card for **AWSSupport-ResetAccess**, and then choose **Next**.

1. In the **Execute automation document** page, choose **Simple execution**.

1. In the **Document details** section, verify that **Document version** is set to the highest default version. For example, **\$1DEFAULT** or **3 (default)**.

1. In the **Input parameters** section, specify the following parameters: 

   1. For **InstanceID**, specify the ID of the unreachable instance. 

   1. For **SubnetId**, specify a subnet in an existing VPC in the same availability zone as the instance you specified. By default, Systems Manager creates a new VPC, but you can specify a subnet in an existing VPC if you want.
**Note**  
If you don't see the option to specify a subnet ID, verify that you are using the latest **Default** version of the runbook.

   1. For **EC2RescueInstanceType**, specify an instance type for the EC2Rescue instance. The default instance type is `t2.medium`.

   1. For **AssumeRole**, if you created roles for this Automation by using the CloudFormation procedure described earlier in this topic, then specify the AssumeRole ARN that you noted in the CloudFormation console.

1. (Optional) In the **Tags** area, apply one or more tag key name/value pairs to help identify the automation, for example `Key=Purpose,Value=ResetAccess`.

1. Choose **Execute**.

1. To monitor the automation progress, choose the running automation, and then choose the **Steps** tab. When the automation is finished, choose the **Descriptions** tab, and then choose **View output** to view the results. To view the output of individual steps, choose the **Steps** tab, and then choose **View Outputs** next to a step.

The runbook creates a backup AMI and a password-enabled AMI as part of the automation. All other resources created by the automation are automatically deleted, but these AMIs remain in your account. The AMIs are named using the following conventions:
+ Backup AMI: `AWSSupport-EC2Rescue:InstanceID`
+ Password-enabled AMI: AWSSupport-EC2Rescue: Password-enabled AMI from *Instance ID*

You can locate these AMIs by searching on the Automation execution ID.

For Linux, the new SSH private key for your instance is saved, encrypted, in Parameter Store. The parameter name is **/ec2rl/openssh/*instance ID*/key**.

# Passing data to Automation using input transformers
<a name="automation-tutorial-eventbridge-input-transformers"></a>

This AWS Systems Manager Automation tutorial shows how to use the input transformer feature of Amazon EventBridge to extract the `instance-id` of an Amazon Elastic Compute Cloud (Amazon EC2) instance from an instance state change event. Automation is a tool in AWS Systems Manager. We use the input transformer to pass that data to the `AWS-CreateImage` runbook target as the `InstanceId` input parameter. The rule is triggered when any instance changes to the `stopped` state.

For more information about working with input transformers, see [Tutorial: Use Input Transformer to Customize What is Passed to the Event Target](https://docs.aws.amazon.com/eventbridge/latest/userguide/eventbridge-input-transformer-tutorial.html) in the *Amazon EventBridge User Guide*.

**Before you begin**  
Verify that you added the required permissions and trust policy for EventBridge to your Systems Manager Automation service role. For more information, see [Overview of Managing Access Permissions to Your EventBridge Resources](https://docs.aws.amazon.com/eventbridge/latest/userguide/iam-access-control-identity-based-eventbridge.html) in the *Amazon EventBridge User Guide*.

**To use input transformers with Automation**

1. Open the Amazon EventBridge console at [https://console.aws.amazon.com/events/](https://console.aws.amazon.com/events/).

1. In the navigation pane, choose **Rules**.

1. Choose **Create rule**.

1. Enter a name and description for the rule.

   A rule can't have the same name as another rule in the same Region and on the same event bus.

1. For **Event bus**, choose the event bus that you want to associate with this rule. If you want this rule to respond to matching events that come from your own AWS account, select **default**. When an AWS service in your account emits an event, it always goes to your account’s default event bus.

1. For **Rule type**, choose **Rule with an event pattern**.

1. Choose **Next**.

1. For **Event source**, choose **AWS events or EventBridge partner events**.

1. In the **Event pattern** section, choose **Use pattern form**.

1. For **Event source**, choose **AWS services**.

1. For **AWS service**, choose **EC2**.

1. For **Event type**, choose **EC2 Instance State-change Notification**.

1. For **Event Type Specification 1**, select **Specific state(s)**, and then choose **stopped**.

1. For **Event Type Specification 2**, select **Any instance**, or select **Specific instance Id(s)** and enter the IDs of the instances to monitor.

1. Choose **Next**.

1. For **Target types**, choose **AWS service**.

1. For **Select a target**, choose **Systems Manager Automation**.

1. For **Document**, choose **AWS-CreateImage**.

1. In the **Configure automation parameter(s)** section, choose **Input Transformer**.

1. For **Input path**, enter **\$1"instance":"\$1.detail.instance-id"\$1**.

1. For **Template**, enter **\$1"InstanceId":[<instance>]\$1**.

1. For **Execution role**, choose **Use existing role** and choose your Automation service role.

1. Choose **Next**.

1. (Optional) Enter one or more tags for the rule. For more information, see [Tagging Your Amazon EventBridge Resources](https://docs.aws.amazon.com/eventbridge/latest/userguide/eventbridge-tagging.html) in the *Amazon EventBridge User Guide*.

1. Choose **Next**.

1. Review the details of the rule and choose **Create rule**.

# Learn about statuses returned by Systems Manager Automation
<a name="automation-statuses"></a>

AWS Systems Manager Automation reports detailed status information about the various statuses an automation action or step goes through when you run an automation and for the overall automation. Automation is a tool in AWS Systems Manager. You can monitor automation statuses using the following methods:
+ Monitor the **Execution status** in the Systems Manager Automation console.
+ Use your preferred command line tools. For the AWS Command Line Interface (AWS CLI), you can use [describe-automation-step-executions](https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-automation-step-executions.html) or [get-automation-execution](https://docs.aws.amazon.com/cli/latest/reference/ssm/get-automation-execution.html). For the AWS Tools for Windows PowerShell, you can use [Get-SSMAutomationStepExecution](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-SSMAutomationStepExecution.html) or [Get-SSMAutomationExecution](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-SSMAutomationExecution.html).
+ Configure Amazon EventBridge to respond to action or automation status changes.

For more information about handling timeouts in an automation, see [Handling timeouts in runbooks](automation-handling-timeouts.md).

## About automation statuses
<a name="automation-statuses-about"></a>

Automation reports status details for individual automation actions in addition to the overall automation.

The overall automation status can be different than the status reported by an individual action or step as noted in the following tables.


**Detailed status for actions**  

| Status | Details | 
| --- | --- | 
| Pending | The step hasn't started running. If your automation uses conditional actions, steps remain in this state after an automation has completed if the condition wasn't met to run the step. Steps also remain in this state if the automation is canceled before the step runs. | 
| InProgress | The step is running. | 
| Waiting | The step is waiting for input. | 
| Success | The step completed successfully. This is a terminal state. | 
| TimedOut | A step or approval wasn't completed before the specified timeout period. This is a terminal state. | 
| Cancelling | The step is in the process of stopping after being canceled by a requester. | 
| Cancelled | The step was stopped by a requester before it completed. This is a terminal state. | 
| Failed |  The step didn't complete successfully. This is a terminal state.  | 
| Exited |  Only returned by the `aws:loop` action. The loop didn't fully complete. A step inside the loop moved to an outside step using the `nextStep`, `onCancel`, or `onFailure` properties.  | 


**Detailed status for an automation**  

| Status | Details | 
| --- | --- | 
| Pending | The automation hasn't started running. | 
| InProgress | The automation is running. | 
| Waiting | The automation is waiting for input. | 
| Success | The automation completed successfully. This is a terminal state. | 
| TimedOut | A step or approval wasn't completed before the specified timeout period. This is a terminal state. | 
| Cancelling | The automation is in the process of stopping after being canceled by a requester. | 
| Cancelled | The automation was stopped by a requester before it completed. This is a terminal state. | 
| Failed |  The automation didn't complete successfully. This is a terminal state.  | 

# Troubleshooting Systems Manager Automation
<a name="automation-troubleshooting"></a>

Use the following information to help you troubleshoot problems with AWS Systems Manager Automation, a tool in AWS Systems Manager. This topic includes specific tasks to resolve issues based on Automation error messages.

**Topics**
+ [Common Automation errors](#automation-trbl-common)
+ [Automation execution failed to start](#automation-trbl-access)
+ [Execution started, but status is failed](#automation-trbl-exstrt)
+ [Execution started, but timed out](#automation-trbl-to)

## Common Automation errors
<a name="automation-trbl-common"></a>

This section includes information about common Automation errors.

### VPC not defined 400
<a name="automation-trbl-common-vpc"></a>

By default, when Automation runs either the `AWS-UpdateLinuxAmi` runbook or the `AWS-UpdateWindowsAmi` runbook, the system creates a temporary instance in the default VPC (172.30.0.0/16). If you deleted the default VPC, you will receive the following error:

`VPC not defined 400`

To solve this problem, you must specify a value for the `SubnetId` input parameter.

## Automation execution failed to start
<a name="automation-trbl-access"></a>

An automation can fail with an access denied error or an invalid assume role error if you haven't properly configured AWS Identity and Access Management (IAM) roles, and policies for Automation.

### Access denied
<a name="automation-trbl-access-denied"></a>

The following examples describe situations when an automation failed to start with an access denied error.

**Access Denied to Systems Manager API**  
**Error message**: `User: user arn isn't authorized to perform: ssm:StartAutomationExecution on resource: document arn (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)`
+ Possible cause 1: The user attempting to start the automation doesn't have permission to invoke the `StartAutomationExecution` API. To resolve this issue, attach the required IAM policy to the user that was used to start the automation. 
+ Possible cause 2: The user attempting to start the automation has permission to invoke the `StartAutomationExecution` API but doesn't have permission to invoke the API by using the specific runbook. To resolve this issue, attach the required IAM policy to the user that was used to start the automation. 

**Access denied due to missing PassRole permissions**  
**Error message**: `User: user arn isn't authorized to perform: iam:PassRole on resource: automation assume role arn (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)`

The user attempting to start the automation doesn't have PassRole permission for the assume role. To resolve this issue, attach the iam:PassRole policy to the role of the user attempting to start the automation. For more information, see [Task 2: Attach the iam:PassRole policy to your Automation role](automation-setup-iam.md#attach-passrole-policy).

### Invalid assume role
<a name="automation-trbl-ar"></a>

When you run an Automation, an assume role is either provided in the runbook or passed as a parameter value for the runbook. Different types of errors can occur if the assume role isn't specified or configured properly.

**Malformed Assume Role**  
**Error message**: `The format of the supplied assume role ARN isn't valid.` The assume role is improperly formatted. To resolve this issue, verify that a valid assume role is specified in your runbook or as a runtime parameter when starting the automation.

**Assume role can't be assumed**  
**Error message**: `The defined assume role is unable to be assumed. (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: InvalidAutomationExecutionParametersException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)`
+ Possible cause 1: The assume role doesn't exist. To resolve this issue, create the role. For more information, see [Setting up Automation](automation-setup.md). Specific details for creating this role are described in the following topic, [Task 1: Create a service role for Automation](automation-setup-iam.md#create-service-role).
+ Possible cause 2: The assume role doesn't have a trust relationship with the Systems Manager service. To resolve this issue, create the trust relationship. For more information, see [I Can't Assume A Role](https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_roles.html#troubleshoot_roles_cant-assume-role) in the *IAM User Guide*. 

## Execution started, but status is failed
<a name="automation-trbl-exstrt"></a>

### Action-specific failures
<a name="automation-trbl-actspec"></a>

Runbooks contain steps and steps run in order. Each step invokes one or more AWS service APIs. The APIs determine the inputs, behavior, and outputs of the step. There are multiple places where an error can cause a step to fail. Failure messages indicate when and where an error occurred.

To see a failure message in the Amazon Elastic Compute Cloud (Amazon EC2) console, choose the **View Outputs** link of the failed step. To see a failure message from the AWS CLI, call `get-automation-execution` and look for the `FailureMessage` attribute in a failed `StepExecution`.

In the following examples, a step associated with the `aws:runInstance` action failed. Each example explores a different type of error.

**Missing Image**  
**Error message**: `Automation Step Execution fails when it's launching the instance(s). Get Exception from RunInstances API of ec2 Service. Exception Message from RunInstances API: [The image id '[ami id]' doesn't exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidAMIID.NotFound; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.`

The `aws:runInstances` action received input for an `ImageId` that doesn't exist. To resolve this problem, update the runbook or parameter values with the correct AMI ID.

**Assume role policy lacks sufficient permissions**  
**Error message**: `Automation Step Execution fails when it's launching the instance(s). Get Exception from RunInstances API of ec2 Service. Exception Message from RunInstances API: [You aren't authorized to perform this operation. Encoded authorization failure message: xxxxxxx (Service: AmazonEC2; Status Code: 403; Error Code: UnauthorizedOperation; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.`

The assume role doesn't have sufficient permission to invoke the `RunInstances` API on EC2 instances. To resolve this problem, attach an IAM policy to the assume role that has permission to invoke the `RunInstances` API. For more information, see the [Create the service roles for Automation using the console](automation-setup-iam.md).

**Unexpected State**  
**Error message**: `Step fails when it's verifying launched instance(s) are ready to be used. Instance i-xxxxxxxxx entered unexpected state: shutting-down. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.`
+ Possible cause 1: There is a problem with the instance or the Amazon EC2 service. To resolve this problem, login to the instance or review the instance system log to understand why the instance started shutting down.
+ Possible cause 2: The user data script specified for the `aws:runInstances` action has a problem or incorrect syntax. Verify the syntax of the user data script. Also, verify that the user data scripts doesn't shut down the instance, or invoke other scripts that shut down the instance.

**Action-Specific Failures Reference**  
When a step fails, the failure message might indicate which service was being invoked when the failure occurred. The following table lists the services invoked by each action. The table also provides links to information about each service.


****  

| Action | AWS services invoked by this action | For information about this service | Troubleshooting content | 
| --- | --- | --- | --- | 
|  `aws:runInstances`  |  Amazon EC2  |  [ Amazon EC2 User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)  |  [Troubleshooting EC2 Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-troubleshoot.html)  | 
|  `aws:changeInstanceState`  |  Amazon EC2  |  [Amazon EC2 User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)  |  [Troubleshooting EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-troubleshoot.html)  | 
|  `aws:runCommand`  |  Systems Manager  |   [AWS Systems Manager Run Command](run-command.md)  |   [Troubleshooting Systems Manager Run Command](troubleshooting-remote-commands.md)  | 
|  `aws:createImage`  |  Amazon EC2  |  [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)  |  | 
|  `aws:createStack`  |  CloudFormation  |  [AWS CloudFormation User Guide](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)  |  [Troubleshooting CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html)  | 
|  `aws:deleteStack`  |  CloudFormation  |  [AWS CloudFormation User Guide](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)  |  [Troubleshooting CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html)  | 
|  `aws:deleteImage`  |  Amazon EC2  |  [Amazon Machines Images](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)  |  | 
|  `aws:copyImage`  |  Amazon EC2  |  [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)  |  | 
|  `aws:createTag`  |  Amazon EC2, Systems Manager  |  [EC2 Resource and Tags](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_Resources.html)  |  | 
|  `aws:invokeLambdaFunction`  |  AWS Lambda  |  [AWS Lambda Developer Guide](https://docs.aws.amazon.com/lambda/latest/dg/)  |  [Troubleshooting Lambda](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions.html)  | 

### Automation service internal error
<a name="automation-trbl-err"></a>

**Error message**: `Internal Server Error. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.`

A problem with the Automation service is preventing the specified runbook from running correctly. To resolve this issue, contact AWS Support. Provide the execution ID and customer ID, if available.

## Execution started, but timed out
<a name="automation-trbl-to"></a>

**Error message**: `Step timed out while step is verifying launched instance(s) are ready to be used. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.`

A step in the `aws:runInstances` action timed out. This can happen if the step action takes longer to run than the value specified for `timeoutSeconds` in the step. To resolve this issue, specify a longer value for the `timeoutSeconds` parameter in the `aws:runInstances` action. If that doesn't solve the problem, investigate why the step takes longer to run than expected