It is highly advisable to maintain modules in a separate repository and link them to your primary Terraform directory. In this scenario, we will simulate this practice by housing the modules in a distinct repository and accessing them through either the SSH or HTTPS protocol.
Accessing Terraform modules from a different repository offers several advantages in the context of infrastructure automation:
Modularity and Reusability
Keeping modules in a separate repository promotes modularity, allowing you to reuse them across multiple projects, Modules encapsulate specific functionalities, making it easier to reuse and share them. This modular approach reduces redundancy and promotes consistent infrastructure patterns.
Centralized Maintenance
Having modules in a dedicated repository centralizes maintenance efforts. Changes, updates, and improvements to modules can be managed in one location. This simplifies version control, ensuring consistency and reliability across various projects.
Security and Access Control
Enhanced security measures can be applied to the module repository, repository housing modules can have its security measures, access controls, and authentication mechanisms, ensuring that only authorized personnel can make changes to critical infrastructure components.
Modules Repo
Terraform Primary Repo
root.tf code
# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.2"
}
}
required_version = ">= 1.1.0"
}
provider "azurerm" {
features {}
subscription_id = "491e1121-c626-46e3-98ba-98f9f0434964"
tenant_id = "2047b1bd-994d-4366-9d87-647dac583343"
client_id = "a78d2362-7c1d-475b-b06c-683634019705"
client_secret = "aSR8Q~UzW_2fWfpMn********0XbUB"
}
data "azurerm_resource_group" "example" {
name = var.rgname
}
module "subnet" {
source = "git::https://[email protected]/rkrvritN45PSP/RVRIT/_git/modules//module-project-practice//modules/azure-subnet"
//source = "./modules/azure-subnet"
subnetname = var.subnetname
rgname = var.rgname
nertworkname = var.nertworkname
address = var.address
}
module "privatednszone" {
source = "git::https://[email protected]/rkrvritN45PSP/RVRIT/_git/modules//module-project-practice//modules/azure-privatednszone"
// source = "./modules/azure-privatednszone"
dnsname = var.dnsname
rgname = var.rgname
}
module "postgresdb" {
source = "git::https://[email protected]/rkrvritN45PSP/RVRIT/_git/modules//module-project-practice//modules/azure-postgres-db"
// source = "./modules/azure-postgres-db"
dbname = var.dbname
rgname = var.rgname
location = var.location
delegated_subnet_id = module.subnet.subnet-id
private_dns_zone_id = module.privatednszone.privatesdns-id
administrator_login = var.administrator_login
administrator_password = var.administrator_password
zone = var.zone
storage_mb = var.storage_mb
sku_name = var.sku_name
}
Manual Execution
Clone the code to the VM and change directory to Terraform-Repo folder
git clone https://[email protected]/rkrvritN45PSP/RVRIT/_git/Terraform-Repo
cd Terraform-Repo
terraform init
terraform plan -var-file=/home/azureuser/Terraform-Repo/dev.tfvars
terraform apply -var-file=/home/azureuser/Terraform-Repo/dev.tfvars
Terraform init output
azureuser@ado-201-vm:~/Terraform-Repo$ terraform init
Initializing the backend...
Initializing modules...
Downloading git::https://[email protected]/rkrvritN45PSP/RVRIT/_git/modules for postgresdb...
- postgresdb in .terraform/modules/postgresdb/module-project-practice/modules/azure-postgres-db
Downloading git::https://[email protected]/rkrvritN45PSP/RVRIT/_git/modules for privatednszone...
- privatednszone in .terraform/modules/privatednszone/module-project-practice/modules/azure-privatednszone
Downloading git::https://[email protected]/rkrvritN45PSP/RVRIT/_git/modules for subnet...
- subnet in .terraform/modules/subnet/module-project-practice/modules/azure-subnet
Initializing provider plugins...
- Finding hashicorp/azurerm versions matching "~> 3.0.2"...
- Installing hashicorp/azurerm v3.0.2...
- Installed hashicorp/azurerm v3.0.2 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform plan output
Terraform apply output
Still you can use the pipelines to achieve this using automated approach
trigger: none
pr:
branches:
include:
- main
paths:
include:
- '*/*'
pool:
# vmImage: 'ubuntu-latest'
name: 'ado-201-pool'
variables:
- group: sharedservicesaccount
jobs:
- job: terraform_plan
displayName: Terraform Plan
steps:
- checkout: self
- task: TerraformInstaller@0
displayName: Install Terraform latest
- task: AzureCLI@2
displayName: 'Download secret-dev.auto.tfvars file from storage account'
inputs:
azureSubscription: 'Azure subscription 1(491e1-46e3-98ba-98f9f0434964)'
scriptLocation: 'inlineScript'
scriptType: 'bash'
inlineScript: |
az login --service-principal --username "$(clientIdnpd)" --password "$(clientSecretnpd)" --tenant "$(tenantIdnpd)"
az storage blob download --account-name terraformstorpipe --account-key $(es-account-key) --container-name tfvars --name dev.tfvars --file $(Agent.TempDirectory)/dev.auto.tfvars
- task: CopyFiles@2
inputs:
SourceFolder: '$(Agent.TempDirectory)'
Contents: 'auto.tfvars'
TargetFolder: '$(System.DefaultWorkingDirectory)/module-project-practice'
- task: TerraformTaskV2@2
displayName: 'Terraform : Init'
inputs:
workingDirectory: '$(System.DefaultWorkingDirectory)/module-project-practice'
backendServiceArm: 'terra-storageaccount'
backendAzureRmResourceGroupName: '102-RG'
backendAzureRmStorageAccountName: 'terraformstorpipe'
backendAzureRmContainerName: 'tfvars'
backendAzureRmKey: 'dev.tfstate'
- task: TerraformTaskV2@2
displayName: 'Terraform : Plan'
inputs:
workingDirectory: '$(System.DefaultWorkingDirectory)/module-project-practice'
command: plan
environmentServiceNameAzureRM: '102-RG-SC'
commandOptions: '-out=$(System.DefaultWorkingDirectory)/module-project-practice/terraform.tfplan'
- task: PublishBuildArtifacts@1
displayName: 'Terraform : Publish Plan'
inputs:
pathToPublish: '$(System.DefaultWorkingDirectory)'
artifactName: tfplan
- job: terraform_plan_review
displayName: Terraform Plan Review
dependsOn: ['terraform_plan']
pool: server
steps:
- task: ManualValidation@0
timeoutInMinutes: 10 # task times out in 1 day (1440)
inputs:
notifyUsers: |
[email protected]
instructions: 'Please validate the terraform plan and resume'
onTimeout: 'reject'
- job: Deploy
displayName: Terraform Deploy
cancelTimeoutInMinutes: 240
dependsOn: ['terraform_plan_review']
steps:
- task: TerraformInstaller@0
displayName: Install Terraform latest
- download: current
artifact: tfplan
- task: CmdLine@2
displayName: 'Terraform : Init Upgrade'
inputs:
workingDirectory: '$(Pipeline.Workspace)/tfplan/module-project-practice'
script: |
chmod -R a+x .terraform
- task: TerraformTaskV2@2
displayName: 'Terraform : Validate and Apply'
inputs:
command: apply
environmentServiceNameAzureRM: '102-RG-SC'
workingDirectory: '$(Pipeline.Workspace)/tfplan/module-project-practice'
commandOptions: 'terraform.tfplan'
To conclude, accessing Terraform modules from a different repository brings efficiency, consistency, and security to the process of infrastructure automation and also it promotes scalable and maintainable approach to manage infrastructure as a code