Skip to content

Create Terraform Module #91

Create Terraform Module

Create Terraform Module #91

Workflow file for this run

# This workflow runs manually.
#
# `Create Terraform Module` job run Terraform Cloud API call to retrieve the workspace id.
# It then uses API calls to find the variable ID and value. After several validations, it
# updates the variable in Terraform Cloud using an API call.
#
# Finally, it uses `checkout` to download the content of the repository. It runs
# `hashicorp/tfc-workflows-github/actions/upload-configuration` to creates a configuration version
# and uploads the directory containing files for a specified Terraform Cloud Workspace. Then, it
# performs an API driven run in Terraform Cloud, using a configuration version and the workspace's
# current variables.
#
# Documentation
# - https://github.com/actions/checkout
# - https://github.com/hashicorp/tfc-workflows-github/tree/main/actions/upload-configuration
# - https://github.com/hashicorp/tfc-workflows-github/tree/main/actions/create-run
#
# Prerequisites:
# - A Terraform Cloud workspace
# - A Terraform Cloud API token with required permissions
#
# Terraform Cloud user API token stored as a GitHub secret (e.g. TF_API_TOKEN) in the repository.
# Documentation:
# - https://www.terraform.io/docs/cloud/users-teams-organizations/api-tokens.html
# - https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets
name: "Create Terraform Module"
on: # yamllint disable-line rule:truthy
workflow_dispatch:
inputs:
module_name:
description: The name of the module to create. Module name must use a three-part name format like `terraform-<PROVIDER>-<NAME>` and contain only alphanumeric and hypens.
required: true
type: string
jobs:
job:
name: Create Terraform Module
runs-on: ubuntu-latest
env:
TF_API_TOKEN: ${{ secrets.TFC_API_TOKEN }}
TF_CLOUD_ORGANIZATION: ConseilsTI
TF_VARIABLE: module_names
steps:
- name: Get workspace ID
id: get_workspace_id
env:
EVENT_CONTEXT: ${{ toJSON(github.event) }}
run: |
echo "INFO | Building required variables."
workspace_name=$(echo "${EVENT_CONTEXT}" | jq -r ".repository.name")
workspace_name="${workspace_name,,}"
echo "workspace_name=${workspace_name}" >> "${GITHUB_OUTPUT}"
echo "INFO | Workspace name: ${workspace_name}"
tfc_api_url="https://app.terraform.io/api/v2"
auth_header="Authorization: Bearer ${TF_API_TOKEN}"
content_header="Content-Type: application/vnd.api+json"
echo "INFO | Running API call to get workspace ID."
workspace_id=$(curl -sS -H "${auth_header}" -H "${content_header}" -L "${tfc_api_url}/organizations/${{ env.TF_CLOUD_ORGANIZATION }}/workspaces/${workspace_name}" | jq -r '.data."id"')
if [[ "${workspace_id}" != "null" ]]; then
echo "INFO | Workspace ID: ${workspace_id}"
echo "workspace_id=${workspace_id}" >> "${GITHUB_OUTPUT}"
else
echo "ERROR | Unable to get workspace ID."
exit 1
fi
- name: Get variable
id: get_variable
run: |
echo "INFO | Building required variables."
tfc_api_url="https://app.terraform.io/api/v2"
auth_header="Authorization: Bearer ${TF_API_TOKEN}"
content_header="Content-Type: application/vnd.api+json"
echo "INFO | Running API call to get variable id."
variable_id=$(curl -sS -H "${auth_header}" -H "${content_header}" -L "${tfc_api_url}/workspaces/${{ steps.get_workspace_id.outputs.workspace_id }}/vars" | jq '.data[] | select(.attributes.key == "${{ env.TF_VARIABLE }}" ) | .id')
if [[ "${variable_id}" != "null" ]]; then
echo "INFO | Variable ID: ${variable_id}"
echo "variable_id=${variable_id}" >> "${GITHUB_OUTPUT}"
else
echo "ERROR | Unable to get variable id."
exit 1
fi
echo "INFO | Running API call to get variable value."
variable_value=$(curl -sS -H "${auth_header}" -H "${content_header}" -L "${tfc_api_url}/workspaces/${{ steps.get_workspace_id.outputs.workspace_id }}/vars" | jq '.data[] | select(.attributes.key == "${{ env.TF_VARIABLE }}" ) | .attributes.value')
if [[ "${variable_value}" != "null" ]]; then
echo "INFO | Variable value: ${variable_value}"
echo "variable_value=${variable_value}" >> "${GITHUB_OUTPUT}"
else
echo "ERROR | Unable to get variable value."
exit 1
fi
- name: Update variable
run: |
echo "INFO | Building required variables."
tfc_api_url="https://app.terraform.io/api/v2"
auth_header="Authorization: Bearer ${TF_API_TOKEN}"
content_header="Content-Type: application/vnd.api+json"
variable_value=$(echo -e "${{ steps.get_variable.outputs.variable_value }}")
if [[ "${{ github.event.inputs.module_name }}" =~ ^terraform-[a-zA-Z]+-[a-zA-Z0-9-]+$ ]]; then
echo "INFO | Module's name use a three-part name format like \"terraform-<PROVIDER>-<NAME>\" and contain only alphanumeric and hypens."
else
echo "ERROR | Module's name must use a three-part name format like \"terraform-<PROVIDER>-<NAME>\" and contain only alphanumeric and hypens."
exit 1
fi
if [[ "${variable_value}" =~ ^\[.*\]$ ]]; then
echo "INFO | Variable is an array."
else
echo "ERROR | Variable is not an array."
exit 1
fi
if [[ "${variable_value}" =~ "${{ github.event.inputs.module_name }}" ]]; then
echo "ERROR | Module's name is already in use."
exit 1
fi
echo "INFO | Adding new module's name into the array."
variable_value="${variable_value::-1}, \"${{ github.event.inputs.module_name }}\"]"
printf 'INFO | Converting \\" into \\\\".'
variable_value=${variable_value//\"/\\\"}
echo "INFO | Building JSON payload."
json_string='{"data":{"id":"'"${{ steps.get_variable.outputs.variable_id }}"'","attributes":{"value":"'"${variable_value}"'"},"type":"vars"}}'
json_payload=$(echo "${json_string}" | jq)
echo "INFO | Running API call to update variable."
{
run=$(curl -sS --request PATCH --url "${tfc_api_url}/vars/${{ steps.get_variable.outputs.variable_id }}" \
--header "${auth_header}" --header "${content_header}" --data "${json_payload}")
if ! [[ "${run}" =~ "{\"data\":" ]]; then
echo "ERROR | Unable to update variable."
echo "${run}"
exit 1
else
echo "INFO | Variable updated."
fi
} ||
{
echo "ERROR | Unable to update variable."
exit 1
}
- uses: actions/checkout@v4
- uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.2.0
id: upload
with:
workspace: ${{ steps.get_workspace_id.outputs.workspace_name }}
directory: ./
- uses: hashicorp/tfc-workflows-github/actions/create-run@v1.2.0
id: create-run
with:
workspace: ${{ steps.get_workspace_id.outputs.workspace_name }}
configuration_version: ${{ steps.upload.outputs.configuration_version_id }}