Terraform Cloud provides the facility to store your terraform data. You can store your tfstate files on workspaces and keep the whole set of module packages with all tf files on the registry. The registry is both Public and Private. And here, we will deal with the private registry for creating terraform module and push terraform package.
Prerequisites
- Terraform Cloud Id
- Azure DevOps Id
- GitHub Id
- Understanding of API
Basic Setup for Terraform Cloud Module
We set up each environment one by one before creating the pipeline.
1. Create a Token on Terraform Cloud to access the API.
2. Now we need to check the access to create module.
3. Connect GitHub to Azure DevOps.
4. Connecting repository to Azure Pipeline.
All these four setups were done in last blog named: Create Module in Private Terraform Registry with Azure Pipeline
Now we will add a Group Variable named “TerraformRegistryVariables” with values for TERRAFORM_REGISTRY_TOKEN and TF_ORGANISATION and then add your pipeline in permissions.


We need to create version.json to add version before pushing packages in following way:

Azure Pipeline for Terraform package
We will use following pipeline:
pool:
vmImage: 'ubuntu-latest'
parameters:
- name: JSON_MODULE_LOCATION
displayName: "LocationOfJsonForModule"
type: string
default: "module.json"
- name: JSON_VERSION_LOCATION
displayName: "LocationOfJsonForVersion"
type: string
default: "module/version.json"
- name: TERRAFORM_PACKAGE_LOCATION
displayName: "LocationOfPackage"
type: string
default: "module"
- name: MODULE_NAME
displayName: "NameOfModuleInRegistry"
default: "aks"
type: string
- name: PROVIDER
displayName: "TerraformCloudProvider"
type: string
default: "azurerm"
variables:
- group: TerraformRegistryVariables
jobs:
- job: "TerraformPackaging"
steps:
- checkout: self
displayName: Clean Checkout
clean: true
- script: |
curl --header "Authorization: Bearer $(TERRAFORM_REGISTRY_TOKEN)" --header "Content-Type: application/vnd.api+json" --request POST --data @${{ parameters.JSON_MODULE_LOCATION }} https://app.terraform.io/api/v2/organizations/$(TF_ORGANIZATION)/registry-modules | jq -r
displayName: "Terraform Registry Module Creation"
name: "ModuleCreation"
- script: |
tar cvfz ${{ parameters.MODULE_NAME }}.tar.gz ${{ parameters.TERRAFORM_PACKAGE_LOCATION }}/*
ls
displayName: "Terraform Module Package Build"
name: "PackageBuild"
- script: |
export version_url="https://app.terraform.io/api/v2/organizations/$(TF_ORGANIZATION)/registry-modules/private/$(TF_ORGANIZATION)/${{ parameters.MODULE_NAME }}/${{ parameters.PROVIDER }}/versions"
export push_url=$(curl --location {$version_url} --header 'Content-Type: application/vnd.api+json' --header 'Authorization: Bearer $(TERRAFORM_REGISTRY_TOKEN)' --data @${{ parameters.JSON_VERSION_LOCATION }} | jq -r '.data.links.upload')
curl --location $push_url --request PUT --header 'Content-Type: application/octet-stream' --data-binary @${{ parameters.MODULE_NAME}}.tar.gz
displayName: "Package Push"
name: "PackagePush"
The Terraform Module Package pipeline requires the following parameters and variables:
Name | Displayname | type | Default |
---|---|---|---|
JSON_MODULE_LOCATION | location of module.json file | string | “module.json” |
TERRAFORM_MODULE_VERSION | location of version.json file | string | “version.json” |
TERRAFORM_MODULE_LOCATION | Terraform Module Package Location | String | “module” |
TERRAFORM_MODULE_NAME | Name of module | string | “aks” |
TERRAFORM_REGISTRY_TOKEN | Terraform registry access token | string | This value from variable group |
TF_ORGANIZATION | Name of Organisation | string | “TerraformRegistryVariables” |
PROVIDER | Name of Provider | string | “azurerm” |
There are 3 sections in the pipeline:
- ModuleCreation: Already defined its working in the blog: Create Module in Private Terraform Registry with Azure Pipeline, if there is already a module with same configuration no new module is created.
- PackageBuild:
- This step has the script where it creates a tar file for the terraform module package.
- PackagePush:
- This step has two POST requests:
- Firstly, the POST method creates generates an URL to push package to terraform cloud module.
- Secondly, the POST method pushes the packages to the module created in first step.
- This step has two POST requests:
And now, we run the pipeline with all values required.



And now, when we visit the module, we will see the package pushed.

All the source material is available at the repository