Provision EC2 instance with Terraform

This Workflow allows you to gather information about the resources, scaffold a new repository, create a new Terraform workspace, create an entity in your Cortex workspace, then send a message to Slack to confirm that the EC2 instance has been created.

How to use a Cortex Workflow to provision an EC2 instance with Terraform

Considerations

Step 1: Register the Scaffolder template in Cortex

Follow the instructions to register the Scaffolder template in Cortex. Use the following template:

chevron-rightCookiecutter templatehashtag

Save the JSON template below to register in Cortex:

{
    "project_name" :"new-vm",
    "resource_name": "my-ec2-instance",
    "region": [ "us-east-1","us-east-2", "us-west-1","us-west-2"],
    "instance_type": [ "t2.micro", "t2.medium","t2.large"],
    "version": "0.2"
}

Step 2: Start creating the Workflow

Follow the steps in the documentation to create a Workflow and configure its basic settings.

Step 3: 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 CLIarrow-up-right. 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.

chevron-rightWorkflow YAML instructionshashtag

To upload the Workflow example YAML into your workspace:

  1. Save the Workflow example YAML file below:

  1. Use the Cortex CLIarrow-up-right to run this command, using the path to your Workflow YAML file: cortex workflows create -f <path-to-your-workflow.yaml>

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

chevron-rightUser inputhashtag

In this example, we add a User Input block to gather resource details from the user. For the resource size and region, the user can select from the options configured here.

  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 Resource details and the slug resource-details.

  3. Click +Add user input. Add the following:

    • Name: Resource Name

    • Key: resource-name

    • Type: Text

    • Placeholder: my-ec2-instance

    • Click Add input.

  4. Click +Add user input. Add the following:

    • Name: Resource Size

    • Key: resource-size

    • 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: Resource Region

    • Key: resource-region

    • Type: Select

    • Data source: Manual

    • Placeholder: In this example, the region options are us-east-1, us-east-2, us-west-1, and us-west-2.

    • Click Add input.

  6. At the bottom of the side panel, click Save.

chevron-rightData transformationshashtag

In this Workflow, we use two Data transformation blocks to reshape the data before scaffolding:

Create a data transformation to lowercase the resource 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 Slugify Resource Name and the slug slugify-resource-name.

  3. Add a jq expression to take the output of the previous action, then downcase its characters:

  1. At the bottom of the side panel, click Save.

Create a second data transformation to get GitHub details:

  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.

    • In this example, we use the name Getting GitHub details and the slug getting-github-details.

  3. Add a jq expression to take the output of the previous action, and use that to create a PR name and branch name:

  1. At the bottom of the side panel, click Save.

chevron-rightScaffolderhashtag

This block creates a new repository in your connected Git integration, using templating to apply the outputs of previous blocks to the Scaffolder configuration.

  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 Scaffold Git Repo and the slug scaffold-git-repo.

  3. Under Scaffolder template, select your template. In this example, we use the New EC2 Instance template.

  4. Select the option to Create a new repo.

  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:

    • resource_name: actions.slugify-resource-name.outputs.result

      • This overrides it with the output of the "Slugify resource name" block earlier in the Workflow.

    • region: actions.resource-details.outputs.resource-region

      • This overrides it with the output of the resource region chosen during the "Resource details" block earlier in the Workflow.

    • instance_type: actions.resource-details.outputs.resource-size

      • This overrides it with the output of the resource size chosen during the "Resource details" block earlier in the Workflow.

    • publisherRepoName: actions.slugify-resource-name.outputs.result

      • This overrides it with the output of the "Slugify resource name" earlier in the Workflow.

    • publisherPullRequestTitle: actions.getting-github-details.outputs.result.pr_name

      • This overrides it with the pr_name output from the "Getting GitHub details" block earlier in the Workflow.

    • publisherBranch: actions.getting-github-details.outputs.result.branch_name

      • This overrides it with the branch_name output from the "Getting GitHub details" block earlier in the Workflow.

    • publisherRepoFullName: actions.getting-github-details.outputs.result.repo_name

      • This overrides it with the repo_name output from the "Getting GitHub details" block earlier in the Workflow.

    • publisherCommitMessage: actions.getting-github-details.outputs.result.commit_msg

      • This overrides it with the commit_msg output from the "Getting GitHub details" block earlier in the Workflow.

    • project_name: actions.slugify-resource-name.outputs.result

      • This overrides it with the output from the "Slugify resource name" block earlier in the Workflow.

    • publisherPullRequestBody: actions.getting-github-details.outputs.result.pr_name

      • This overrides it with the pr_name output from the "Getting GitHub details" block earlier in the Workflow.

  6. At the bottom of the side panel, click Save.

chevron-rightGitHub merge branchhashtag

This block sets the head branch name and merges it.

  1. Click + in the center of the page. In the block library modal, select the GitHub > Merge a branch block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example, we use the name Merge a branch and the slug merge-a-branch.

  3. Configure the block:

    • Repository: Enter your repository name

    • Base branch: Enter the name of the branch into which changes will be merged, e.g. main.

    • Head branch: Enter the name of the head branch containing the changes to merge.

      • In our example, we use the following template to pull the "branch name" output from the earlier Data transformation step whose slug is getting-github-details: {{actions.getting-github-details.outputs.result.branch_name}}

    • Commit message: Optionally enter a commit message.

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

chevron-rightHTTP requestshashtag

There are three HTTP requests that perform the following actions: Create a workspace in Terraform, add the AWS access key environment variable, and add the AWS secret key environment variable.

Create a workspace in Terraform

  1. Click + in the center of the page. In the block library modal, select the HTTP request block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example, we use the name Create workspace and the slug create-workspace.

  3. Configure the block:

    1. HTTP method: POST

    2. URL: In our example, we set this to: https://app.terraform.io/api/v2/organizations/{{context.secrets.tf_organization}}/workspaces/

    3. Headers: Set the following headers:

      • Content-Type: application/vnd.api+json

      • Authorization: Bearer {{ context.secrets.tf_token }}

    4. Payload: In our example, we enter the following:

  1. Save the block.

Add the AWS access key environment variable

  1. Click + in the center of the page. In the block library modal, select the HTTP request block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Add AWS Access Key environment variable and the slug add-aws-access-key-environment-variable.

  3. Configure the block:

    1. HTTP method: POST

    2. URL: In our example, we set this to: https://app.terraform.io/api/v2/workspaces/{{ actions.create-workspace.outputs.body.data.id }}/vars

    3. Headers: Set the following headers:

      • Content-Type: application/vnd.api+json

      • Authorization: Bearer {{ context.secrets.tf_token }}

    4. Payload: In our example, we enter the following:

  1. Save the block.

Add the AWS secret key environment variable

  1. Click + in the center of the page. In the block library modal, select the HTTP request block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Add AWS Secret Key environment variable and the slug add-aws-secret-key-environment-variable.

  3. Configure the block:

    1. HTTP method: POST

    2. URL: In our example, we set this to: https://app.terraform.io/api/v2/workspaces/{{ actions.create-workspace.outputs.body.data.id }}/vars

    3. Headers: Set the following headers:

      • Content-Type: application/vnd.api+json

      • Authorization: Bearer {{ context.secrets.tf_token }}

    4. Payload: In our example, we enter the following:

  1. Save the block.

chevron-rightAsync HTTP requesthashtag

Note: If you are using PR automation such as Atlantisarrow-up-right, then you do not need to include this HTTP call to Plan and Apply.

  1. Click + in the center of the page. In the block library modal, select the Async HTTP request block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Plan and Apply and the slug plan-and-apply.

  3. Configure the block:

    1. HTTP method: POST

    2. URL: In our example, we set this to: https://app.terraform.io/api/v2/runs

    3. Headers: Set the following headers:

      • Content-Type: application/vnd.api+json

      • Authorization: Bearer {{ context.secrets.tf_token }}

    4. Timeout: 5 minutes

    5. Payload: In our example, we enter the following:

  1. Save the block.

chevron-rightData transformationshashtag

This four data transformations take output from previous blocks then parse the ARN, get the EC2 ID, get the AWS region, and get the AWS account.

Parse the ARN

  1. Click + in the center of the page. In the block library modal, select the Data transformation block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Parse arn and the slug parse-arn.

  3. Enter a jq expression:

  1. Save the block.

Get EC2 ID

  1. Click + in the center of the page. In the block library modal, select the Data transformation block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Get EC2 ID and the slug get-ec2-id.

  3. Enter a jq expression:

  1. Save the block.

Get region

  1. Click + in the center of the page. In the block library modal, select the Data transformation block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Get region and the slug get-region.

  3. Enter a jq expression:

  1. Save the block.

Get AWS account

  1. Click + in the center of the page. In the block library modal, select the Data transformation block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Get AWS account and the slug get-aws-account.

  3. Enter a jq expression:

  1. Save the block.

chevron-rightCreate or patch entityhashtag

In this step, we use the output of previous blocks to create a new entity in Cortex.

  1. Click + in the center of the page. In the block library modal, select the Create or patch entity block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Add entity to catalog and the slug add-entity-to-catalog.

  3. Under descriptor, enter the following:

chevron-rightSend Slack messagehashtag

In this step, we use the output of previous steps to send a templated message via Slack informing the user that their EC2 instance has been created..

  1. Click + in the center of the page. In the block library modal, select the Slack block.

  2. In the side panel, enter a name and unique slug for the block.

    • In this example we use the name Send message and the slug send-message.

  3. Select a Slack channel name.

  4. Enter text for the message that will be sent via Slack. In our example, we use the following:

  1. Save the block.

Step 4: Run the Workflow

When you run the Workflow, the following events happen:

  • The Workflow pauses to collect responses from the user during the User Input step.

  • The Data transformation steps reshape the responses, then that reformatted data is used to create a repository during the Scaffolder step.

  • A new Terraform workspace is created, and the AWS access key and secret key variables are included. The async HTTP request block triggers the planning and applying process in Terraform.

  • The data is transformed, and the reformatted data is used to create an entity in Cortex.

  • A message is sent in Slack to confirm that the EC2 instance has been provisioned. It includes a link to the EC2 instance and a link to the newly-created entity in Cortex:

    A Slack message confirms the EC2 instance is created.
  • The entity in Cortex is connected to the repository and to the Terraform workspace.

Last updated

Was this helpful?