> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cortex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Update EC2 instance

export const RecipeBadges = ({badges = []}) => {
  const map = {
    "recipe": {
      label: "Recipe",
      color: "#A86400"
    },
    "ai-excellence": {
      label: "AI excellence",
      color: "#653EE8"
    },
    "production-readiness": {
      label: "Production readiness",
      color: "#226686"
    },
    "incident-mgmt": {
      label: "Incident management",
      color: "#86198F"
    },
    "migrations": {
      label: "Migrations",
      color: "#0E7C66"
    },
    "compliance": {
      label: "Compliance",
      color: "#475569"
    },
    "dora": {
      label: "DORA metrics",
      color: "#1D4ED8"
    },
    "security": {
      label: "Security",
      color: "#B42318"
    },
    "operational-readiness": {
      label: "Operational readiness",
      color: "#B54708"
    },
    "dev-onboarding": {
      label: "Developer onboarding",
      color: "#C11574"
    }
  };
  const items = badges.map(key => map[key]).filter(Boolean);
  if (items.length === 0) return null;
  return <div className="not-prose flex flex-wrap gap-2 mb-6">
      {items.map(b => <span key={b.label} className="rounded-lg px-2 py-1 text-xs font-medium" style={{
    backgroundColor: b.color,
    color: b.textColor || "#FFFFFF"
  }}>
          {b.label}
        </span>)}
    </div>;
};

<RecipeBadges badges={["recipe", "production-readiness"]} />

This Workflow allows you to streamline modifications to an existing EC2 instance.

## How to use a Workflow in Cortex to update an EC2 instance with Terraform

### Prerequisite

Before getting started, you should have already followed the guide to [Provision an EC2 instance with Terraform](/guides/production-readiness/terraform/provision).

### Step 1: Start creating the Workflow

Follow the steps in the documentation to [create a Workflow](/streamline/workflows/create) and [configure its basic settings](/streamline/workflows/create#creating-a-workflow).

In the Workflow's basic settings, set its scope to apply to the entity type `AWS::EC2::Instance` and the group `terraform`. The prerequisite Workflow [Provision an EC2 instance with Terraform](/guides/production-readiness/terraform/provision) automatically adds the group to the entities it creates.

### Step 2: Add blocks to the Workflow

The instructions on this page describe how to create this Workflow in the Cortex UI, but it is also possible to copy the Workflow YAML and add it to your workspace via the [Cortex CLI](https://pypi.org/project/cortexapps-cli/). This allows you to quickly set up the example configuration then iterate on it for your own use case. Expand the tile below to learn more.

<Accordion title="Workflow YAML instructions">
  To upload the Workflow example YAML into your workspace:

  1. Save the Workflow example YAML file below:

  ```yaml theme={null}
  name: "[Terraform Cloud] - Update EC2 instance"
  tag: update-ec2-instance
  description: null
  isDraft: true
  filter:
    entityFilter:
      typeFilter:
        types:
        - AWS::EC2::Instance
      entityGroupFilter: null
    ownershipScope: ALL
    type: ENTITY
  runResponseTemplate: null
  failedRunResponseTemplate: null
  actions:
  - name: Get Descriptor
    slug: get-descriptor
    schema:
      expression: .context.entity.descriptor
      type: JQ
    outgoingActions:
    - get-terraform-file
    isRootAction: true
  - name: Getting Terraform File
    slug: get-terraform-file
    schema:
      inputs:
        ref: main
        path: "{{actions.get-descriptor.outputs.result.info.x-cortex-git.github.basepath}}/main.tf"
        repo: "{{actions.get-descriptor.outputs.result.info.x-cortex-git.github.repository}}"
      integrationAlias: cortex
      actionIdentifier: github.getFile
      type: ADVANCED_HTTP_REQUEST
    outgoingActions:
    - decoding-file-content
    isRootAction: false
  - name: Decoding File Content
    slug: decoding-file-content
    schema:
      expression: .actions."get-terraform-file".outputs.response.content | gsub("\n";"")
        | @base64d
      type: JQ
    outgoingActions:
    - getting-current-properties
    isRootAction: false
  - name: Getting Current Properties
    slug: getting-current-properties
    schema:
      script: |
        var fileContent = actions['decoding-file-content'].outputs.result

        var fileObject = hcl.parseToObject(fileContent)

        return fileObject
      type: JAVASCRIPT
    outgoingActions:
    - get-current-region
    isRootAction: false
  - name: Get Current Region
    slug: get-current-region
    schema:
      expression: ".actions.\"getting-current-properties\".outputs.result[0].provider.aws[0].region"
      type: JQ
    outgoingActions:
    - get-current-instance-type
    isRootAction: false
  - name: Get Current Instance Type
    slug: get-current-instance-type
    schema:
      expression: ".actions.\"getting-current-properties\".outputs.result[0].resource.aws_instance.ubuntu[0].instance_type"
      type: JQ
    outgoingActions:
    - get-current-instance-name
    isRootAction: false
  - name: Get Current Instance Name
    slug: get-current-instance-name
    schema:
      expression: ".actions.\"getting-current-properties\".outputs.result[0].resource.aws_instance.ubuntu[0].tags.Name"
      type: JQ
    outgoingActions:
    - setting-github-fields
    isRootAction: false
  - name: Setting GitHub Fields
    slug: setting-github-fields
    schema:
      expression: |-
        {
        "pr_name" : "PR for " + .actions."get-current-instance-name".outputs.result ,
        "branch_name" : "branch-for-" + .actions."get-current-instance-name".outputs.result ,
        "repo_name" : "cremerica/sample-iac-repo",
        "commit_msg": "Commit automated by Cortex"
        }
      type: JQ
    outgoingActions:
    - user-input
    isRootAction: false
  - name: User input
    slug: user-input
    schema:
      inputs:
      - name: Current Instance Type
        description: null
        key: current-instance-type
        required: false
        defaultValue: null
        placeholder: null
        validationRegex: null
        type: INPUT_FIELD
      - name: Instance-Type
        description: null
        key: instance-type
        required: false
        options:
        - t2.micro
        - t2.medium
        - t2.large
        defaultValue: null
        placeholder: ""
        allowAdditionalOptions: false
        type: SELECT_FIELD
      - name: Current Region
        description: null
        key: current-region
        required: false
        defaultValue: null
        placeholder: null
        validationRegex: null
        type: INPUT_FIELD
      - name: New Region
        description: null
        key: new-region
        required: false
        options:
        - us-west-2
        - us-west-1
        - us-east-1
        - us-east-2
        defaultValue: null
        placeholder: null
        allowAdditionalOptions: false
        type: SELECT_FIELD
      inputOverrides:
      - inputKey: current-instance-type
        outputVariable: actions.get-current-instance-type.outputs.result
        editable: false
        type: VALUE
      - inputKey: current-region
        outputVariable: actions.get-current-region.outputs.result
        editable: false
        type: VALUE
      type: USER_INPUT
    outgoingActions:
    - get-new-instance-type
    isRootAction: false
  - name: Get New instance Type
    slug: get-new-instance-type
    schema:
      expression: if .actions."user-input".outputs."instance-type" == null then .actions."user-input".outputs."current-instance-type"
        else .actions."user-input".outputs."instance-type" end
      type: JQ
    outgoingActions:
    - get-new-region
    isRootAction: false
  - name: Get New Region
    slug: get-new-region
    schema:
      expression: if .actions."user-input".outputs."new-region" == null then .actions."get-current-region".outputs.result
        else  .actions."user-input".outputs."new-region" end
      type: JQ
    outgoingActions:
    - scaffolder
    isRootAction: false
  - name: 'Modify '
    slug: scaffolder
    schema:
      scaffolderTemplateId: st2babdd4cc74929f2
      createNewRepository: false
      createService: false
      inputOverrides:
      - inputKey: instance_type
        outputVariable: actions.get-new-instance-type.outputs.result
        editable: true
        type: VALUE
      - inputKey: resource_name
        outputVariable: actions.get-current-instance-name.outputs.result
        editable: true
        type: VALUE
      - inputKey: project_name
        outputVariable: actions.get-current-instance-name.outputs.result
        editable: true
        type: VALUE
      - inputKey: publisherRepoFullName
        outputVariable: actions.setting-github-fields.outputs.result.repo_name
        editable: false
        type: VALUE
      - inputKey: publisherBranch
        outputVariable: actions.setting-github-fields.outputs.result.branch_name
        editable: true
        type: VALUE
      - inputKey: publisherPullRequestTitle
        outputVariable: actions.setting-github-fields.outputs.result.pr_name
        editable: false
        type: VALUE
      - inputKey: publisherPullRequestBody
        outputVariable: actions.setting-github-fields.outputs.result.pr_name
        editable: true
        type: VALUE
      - inputKey: publisherCommitMessage
        outputVariable: actions.setting-github-fields.outputs.result.commit_msg
        editable: false
        type: VALUE
      - inputKey: region
        outputVariable: actions.get-new-region.outputs.result
        editable: true
        type: VALUE
      type: SCAFFOLDER
    outgoingActions: []
    isRootAction: false
  runRestrictionPolicies: []
  iconTag: null
  variables: []
  ```

  2. Use the [Cortex CLI](https://pypi.org/project/cortexapps-cli/) to run this command, using the path to your Workflow YAML file:<br />
     `cortex workflows create -f <path-to-your-workflow.yaml>`
</Accordion>

Expand the tiles below to learn about each block in this Workflow and how to configure them in the Cortex UI:

<AccordionGroup>
  <Accordion title="Data transformation">
    Get the entity descriptor with a data transformation block.

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Get Descriptor` and the slug `get-descriptor`.
    3. Add a jq expression to get the entity descriptor:

    ```jq theme={null}
    .context.entity.descriptor
    ```

    4. At the bottom of the side panel, click **Save**.
  </Accordion>

  <Accordion title="GitHub get file">
    This block gets the Terraform file you want to update.

    1. Click **+** in the center of the page. In the block library modal, choose **GitHub > Get file**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Getting Terraform file` and the slug `get-terraform-file`.
    3. For the Required parameters, configure the following:
       * Repository: `{{actions.get-descriptor.outputs.result.info.x-cortex-git.github.repository}}`
       * Path: `{{actions.get-descriptor.outputs.result.info.x-cortex-git.github.basepath}}/main.tf`
       * Ref: `main`
    4. Save the block.
  </Accordion>

  <Accordion title="Data transformation">
    Take the output from the previous block and decode its file contents.

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Decoding file content` and the slug `decoding-file-content`.
    3. Add a jq expression:

    ```jq theme={null}
    .actions."get-terraform-file".outputs.response.content | gsub("\n";"") | @base64d
    ```

    4. At the bottom of the side panel, click **Save**.
  </Accordion>

  <Accordion title="JavaScript">
    Run a script to get the current properties from the file you got in previous steps of the Workflow.

    1. Click **+** in the center of the page. In the block library modal, choose **GitHub > Get file**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Getting current properties` and the slug `getting-current-properties`.
    3. Add a JavaScript expression:

    ```javascript theme={null}
    /*#CORTEX_IGNORE*/import {_, YAML, hcl, context, actions, variables, fetch} from './utils.js'; async () => {
    var fileContent = actions['decoding-file-content'].outputs.result

    var fileObject = hcl.parseToObject(fileContent)

    return fileObject

    /*#CORTEX_IGNORE*/}
    ```

    4. Save the block.
  </Accordion>

  <Accordion title="Data transformations">
    Add four Data transformation blocks to reformat the output from previous blocks:

    **Get current region**

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Get current region` and the slug `get-current-region`.
    3. Add a jq expression:

    ```jq theme={null}
    .actions."getting-current-properties".outputs.result[0].provider.aws[0].region
    ```

    4. At the bottom of the side panel, click **Save**.

    **Get current instance type**

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Get current instance type` and the slug `get-current-instance-type`.
    3. Add a jq expression:

    ```jq theme={null}
    .actions."getting-current-properties".outputs.result[0].resource.aws_instance.ubuntu[0].instance_type
    ```

    4. At the bottom of the side panel, click **Save**.

    **Get current instance name**

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Get current instance name` and the slug `get-current-instance-name`.
    3. Add a jq expression:

    ```jq theme={null}
    .actions."getting-current-properties".outputs.result[0].resource.aws_instance.ubuntu[0].tags.Name
    ```

    4. At the bottom of the side panel, click **Save**.

    **Set GitHub fields**

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Setting GitHub fields` and the slug `setting-github-fields`.
    3. Add a jq expression:

    ```jq theme={null}
    {
    "pr_name" : "PR for " + .actions."get-current-instance-name".outputs.result ,
    "branch_name" : "branch-for-" + .actions."get-current-instance-name".outputs.result ,
    "repo_name" : "cremerica/sample-iac-repo",
    "commit_msg": "Commit automated by Cortex"
    }
    ```

    4. At the bottom of the side panel, click **Save**.
  </Accordion>

  <Accordion title="User input">
    In this example, we add a User Input block to gather resource details from the output of previous blocks and prompt the user to select the instance type and new region.

    1. Click **+** in the center of the page. In the block library modal, choose **User input**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `User input` and the slug `user-input`.
    3. Click **+Add user input**. Add the following:
       * **Name**: Current instance type
       * **Key**: current-instance-type
       * **Type**: Text
       * **Path to override value**: `actions.get-current-instance-type.outputs.result`
       * Click **Add input**.
    4. Click **+Add user input**. Add the following:
       * **Name**: Instance type
       * **Key**: instance-type
       * **Type**: Select
       * **Data source**: Manual
       * **Placeholder**: In this example, the resource size options are t2.micro, t2.medium, and t2.large.
       * Click **Add input**.
    5. Click **+Add user input**. Add the following:
       * **Name**: Current region
       * **Key**: get-current-region
       * **Type**: Text
       * **Path to override value**: `actions.get-current-region.outputs.result`
       * Click **Add input**.
    6. Click **+Add user input**. Add the following:
       * **Name**: New region
       * **Key**: new-region
       * **Type**: Select
       * **Placeholder**: In this example, the options are us-west-2, us-west-1, us-east-1, and us-east-2.
       * Click **Add input**.
    7. Save the block.
  </Accordion>

  <Accordion title="Data transformations">
    Use two data transformations to format the new instance type and region that were entered during the previous step:

    **Get new instance type**

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Get new instance type` and the slug `get-new-instance-type`.
    3. Add a jq expression:

    ```jq theme={null}
    if .actions."user-input".outputs."instance-type" == null then .actions."user-input".outputs."current-instance-type" else .actions."user-input".outputs."instance-type" end
    ```

    4. At the bottom of the side panel, click **Save**.

    **Get new region**

    1. Click **+** in the center of the page. In the block library modal, choose **Data transformation**.
    2. In the block configuration side panel, enter a name and unique slug for this block.
       1. In this example, we use the name `Get new region` and the slug `get-new-region`.
    3. Add a jq expression:

    ```jq theme={null}
    if .actions."user-input".outputs."new-region" == null then .actions."get-current-region".outputs.result else  .actions."user-input".outputs."new-region" end
    ```

    4. At the bottom of the side panel, click **Save**.
  </Accordion>

  <Accordion title="Scaffolder">
    Run a Scaffolder to make modifications. In this block, you will configure override variables to pre-fill parts of the Scaffolder template based on the output of previous steps.

    1. Click **+** in the center of the page. In the block library modal, select the **Scaffolder** block.
    2. In the side panel, enter a name and unique slug for the block.
       1. In this example, we use the name `Modify` and the slug `scaffolder`.
    3. Under **Scaffolder template**, select your template. In this example, we use the `New EC2 Instance` template.
    4. Select the option to **Open a pull request**.
    5. Add override variables. The **Variable** dropdown pulls in all the variables that are able to be overridden in the Git provider and in the Scaffolder template. In this example, we apply the following overrides:
       * **instance\_type**: `actions.get-new-instance-type.outputs.result`
         * This overrides it with the output of the "Get new instance type" block earlier in the Workflow.
       * **resource\_name**: `actions.get-current-instance-name.outputs.result`
         * This overrides it with the output of the "Get current instance name" block earlier in the Workflow.
       * **project\_name**: `actions.get-current-instance-name.outputs.result`
         * This overrides it with the output of the "Get current instance name" block earlier in the Workflow.
       * **publisherRepoFullName**: `actions.setting-github-fields.outputs.result.repo_name`
         * This overrides it with the output of the "Setting GitHub fields" block earlier in the Workflow.
       * **publisherBranch**: `actions.setting-github-fields.outputs.result.branch_name`
         * This overrides it with the branch\_name output of the "Setting GitHub fields" block earlier in the Workflow.
       * **publisherPullRequestTitle**: `actions.setting-github-fields.outputs.result.pr_name`
         * This overrides it with the pr\_name output of the "Setting GitHub fields" block earlier in the Workflow.
       * **publisherPullRequestBody**: `actions.setting-github-fields.outputs.result.pr_name`
         * This overrides it with the pr\_name output of the "Setting GitHub fields" block earlier in the Workflow.
       * **publisherCommitMessage**: `actions.setting-github-fields.outputs.result.commit_msg`
         * This overrides it with the commit\_msg output of the "Setting GitHub fields" block earlier in the Workflow.
       * **region**: `actions.get-new-region.outputs.result`
         * This overrides it with the output of the resource region chosen during the "Get new region" block earlier in the Workflow.
    6. Set a timeout of 5 minutes.
    7. At the bottom of the side panel, click **Save**.
  </Accordion>
</AccordionGroup>

### Step 3: Run the Workflow

When you run the Workflow, the following events happen:

* The Workflow obtains the entity descriptor and gets the Terraform file.
* The Data transformation steps decode the file contents, reshape the data, then use that reformatted data to set fields in GitHub.
* The User input step collects the current instance type, new instance type, and current region.
* The data is transformed, and the reformatted data is used to apply modifications to the EC2 instance.


## Related topics

- [Managing Terraform infra in Cortex](/ingesting-data-into-cortex/entities-overview/entities/terraform.md)
- [Manage Terraform infrastructure](/guides/production-readiness/terraform.md)
- [Provision EC2 instance with Terraform](/guides/production-readiness/terraform/provision.md)
