Terraform: Calling Remote Modules

2 minute read

Description

One of the first things you will want to do once you start learning terraform is to break out code into chunks called modules. Using this in combination with a remote repo will allow you pin certain terraform configurations to git tags.

So strategically speaking, what you want to do is create two different types of repos for your Terraform code: One for applications and one for modules. The applications will then call the modules in chunks. Anyone familiar with a scripting language will be familiar with these terms:

  • Controller script that calls functions
  • Stacks that call sub routines.

Well Terraform calls Stacks or Controller scripts “module compositions” and the functions or small repeatable ‘do-one-thing-and-one-thing-only’ type code modules. The following is how you would go about doing this with Azure Devops Pipelines.

Note: You can see the code for this post on my Github repo.

To Resolve

  1. So in your main.tf (or whatever file) for your application deployment, you will just make various calls to your remote modules like on line 49 here.

    • Note the remote calls using the source argument. Also note that these should always point to a specific tag. The tag can be generated through a release which I cover in another post.
    • Also note the passing of data between the module calls like in module.learning-vnet.name which works just like the data block or any other Terraform block. See line 57.
  2. The next thing to be aware of when you call another module is your Azure Devops Pipeline. I’m not an expert on Azure Devops permissions so please bear with me if I’m wrong, but this is what I have done to get one repo in our Devops Organization to call a remote repo in our Devops Organization. See here for the docs. In the build.yaml add this to the top:

    1
    2
    3
    4
    5
    6
    
    resources:
       repositories:
       - repository: MyRepo-subnet
          type: git
          name: MyProject/MyRepo-subnet
          ref: main
    
    • And then under steps:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    steps:
       - checkout: self        
       - checkout: MyRepo-subnet
       - task: PowerShell@2
          displayName: Tokenize TF-Module Sources
          env:
             SYSTEM_ACCESSTOKEN: $(System.AccessToken)
          inputs:
             targetType: 'inline'
             script: |
             git config --global http.extraHeader 'Authorization: Bearer $(System.AccessToken)'
    
    • Doing these steps should allow one repo to pull the contents of another repo based on a git tagged version which will never change (a point in time) unless the called repo deletes the git tag and pins that same tag name to another commit which is bad practice if following semantic versioning. I cover this more in my other post.