Terraform Contribution Guide

Important

While this page describes and summarizes important aspects of contributing to AVM, it only references some of the shared and language specific requirements.

Therefore, this contribution guide MUST be used in conjunction with the Terraform specifications. ALL AVM modules (Resource and Pattern modules) MUST meet the respective requirements described in these specifications!

Summary

This section lists AVM’s Terraform-specific contribution guidance.

Subsections of Terraform Modules

Terraform Composition

Important

While this page describes and summarizes important aspects of the composition of AVM modules, it may not reference All of the shared and language specific requirements.

Therefore, this guide MUST be used in conjunction with the Terraform specifications. ALL AVM modules (Resource and Pattern modules) MUST meet the respective requirements described in these specifications!

Important

Before jumping on implementing your contribution, please review the AVM Module specifications, in particular the Terraform specification pages, to make sure your contribution complies with the AVM module’s design and principles.

Repositories

Each Terraform AVM module will have its own GitHub Repository in the Azure GitHub Organization as per SNFR19.

This repo will be created by the Module Owners and the AVM Core team collaboratively, including the configuration of permissions as per SNFR9

Directory and File Structure

Below is the directory and file structure expected for each AVM Terraform repository/module.
See template repo here.

  • tests/ - (for unit tests and additional tests if required - e.g. tflint etc.)
    • unit/ - (optional, may use further sub-directories if required)
  • modules/ - (for sub-modules only if used)
  • examples/ - (all examples must deploy without successfully without requiring input - these are customer facing)
    • <at least one folder> - (at least one example that uses the variable defaults minimum/required parameters/variables only)
    • <other folders for examples as required>
  • /... - (Module files that live in the root of module directory)
    • _header.md - (required for documentation generation)
    • _footer.md - (required for documentation generation)
    • main.tf
    • locals.tf
    • variables.tf
    • outputs.tf
    • terraform.tf
    • README.md (autogenerated)
    • main.resource1.tf (If a larger module you may chose to use dot notation for each resource)
    • locals.resource1.tf

Directory and File Structure

/ root
├───.github/
│   ├───actions/
│   │   ├───avmfix/
│   │   │   └───action.yml
│   │   ├───docs-check/
│   │   │   └───action.yml
│   │   ├───e2e-getexamples/
│   │   │   └───action.yml
│   │   ├───e2e-testexamples/
│   │   │   └───action.yml
│   │   ├───linting/
│   │   │   └───action.yml
│   │   └───version-check/
│   │       └───action.yml
│   ├───policies/
│   │   ├───avmrequiredfiles.yml
│   │   └───branchprotection.yml
│   ├───workflows/
│   │   ├───e2e.yml
│   │   ├───linting.yml
│   │   └───version-check.yml
│   ├───CODEOWNERS
│   └───dependabot.yml
├───.vscode/
│   ├───extensions.json
│   └───settings.json
├───examples/
│   ├───<example_folder>/
│   │   ├───README.md
│   │   ├───_footer.md
│   │   ├───_header.md
│   │   ├───main.tf
│   │   └───variables.tf
│   ├───.terraform-docs.yml
│   └───README.md
├───modules/
│   └───README.md
├───tests/
│   └───README.md
├───.gitignore
├───.terraform-docs.yml
├───CODE_OF_CONDUCT.md
├───LICENSE
├───Makefile
├───README.md
├───SECURITY.md
├───SUPPORT.md
├───_footer.md
├───_header.md
├───avm
├───avm.bat
├───locals.tf
├───main.privateendpoint.tf
├───main.telemetry.tf
├───main.tf
├───outputs.tf
├───terraform.tf
└───variables.tf

Code Styling

This section points to conventions to be followed when developing a module.

Casing

Use snake_casing as per TFNFR3.

Input Parameters and Variables

Make sure to review all specifications of Category: Inputs/Outputs within the Terraform specification pages.

Tip

See examples in specifications SNFR14 and TFFR14.

Resources

Resources are primarily leveraged by resource modules to declare the primary resource of the main resource type deployed by the AVM module.

Make sure to review all specifications covering resource properties and usage.

Tip

See examples in specifications SFR1 and RMFR1.

Outputs

Make sure to review all specifications of Category: Inputs/Outputs within the Terraform specification pages.

Tip

See examples in specification RMFR7 and TFFR2.

Interfaces

Note

This section is only relevant for contributions to resource modules.

To meet RMFR4 and RMFR5 AVM resource modules must leverage consistent interfaces for all the optional features/extension resources supported by the AVM module primary resource.

Please refer to the Terraform Interfaces page.

Telemetry

To meet SFR3 & SFR4.
We use a telemetry provider modtm.
This is a lightweight telemetry provider that sends telemetry data to Azure Application Insights via a HTTP POST front end service.

The telemetry provider is included in the module by default and is enabled by default.
You do not need to change the configuration included in the template repo.

You must make sure to have the modtm provider in your required_providers.
The linter will check this for you.
However, inside your terraform.tf file please make sure you have this entry:

terraform {
  required_providers {
    # .. other required providers as needed
    modtm = {
      source = "Azure/modtm"
      version = "~> 0.3"
    }
  }
}

Eventual Consistency

When creating modules, it is important to understand that the Azure Resource Manager (ARM) API is sometimes eventually consistent.
This means that when you create a resource, it may not be available immediately.
A good example of this is data plane role assignments.
When you create such a role assignment, it may take some time for the role assignment to be available.
We can use an optional time_sleep resource to wait for the role assignment to be available before creating resources that depend on it.

# In variables.tf...
variable "wait_for_rbac_before_foo_operations" {
  type: object({
    create  = optional(string, "30s")
    destroy = optional(string, "0s")
  })
  default     = {}
  description = <<DESCRIPTION
This variable controls the amount of time to wait before performing foo operations.
It only applies when `var.role_assignments` and `var.foo` are both set.
This is useful when you are creating role assignments on the bar resource and immediately creating foo resources in it.
The default is 30 seconds for create and 0 seconds for destroy.
DESCRIPTION
}

# In main.tf...
resource "time_sleep" "wait_for_rbac_before_foo_operations" {
  count = length(var.role_assignments) > 0 && length(var.foo) > 0 ? 1 : 0
  depends_on = [
    azurerm_role_assignment.this
  ]
  create_duration  = var.wait_for_rbac_before_foo_operations.create
  destroy_duration = var.wait_for_rbac_before_foo_operations.destroy

  # This ensures that the sleep is re-created when the role assignments change.
  triggers = {
    role_assignments = jsonencode(var.role_assignments)
  }
}

resource "azurerm_foo" "this" {
  for_each = var.foo
  depends_on = [
    time_sleep.wait_for_rbac_before_foo_operations
  ]
  # ...
}

Terraform Contribution Flow

High-level contribution flow


---
config:
  nodeSpacing: 20
  rankSpacing: 20
  diagramPadding: 50
  padding: 5
  flowchart:
    wrappingWidth: 300
    padding: 5
  layout: elk
  elk:
    mergeEdges: true
    nodePlacementStrategy: LINEAR_SEGMENTS
---

flowchart TD
  A(1 - Fork the module source repository)
    click A "/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/#1-fork-the-module-source-repository"
  B(2 - Setup your Azure test environment)
    click B "/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/#2-prepare-your-azure-test-environment"
  C(3 - Implement your contribution)
    click C "/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/#3-implement-your-contribution"
  D{4 - Pre-commit<br>checks successful?}
    click D "/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/#4-run-pre-commit-checks"
  E(5 - Create a pull request to the upstream repository)
    click E "/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/#5-create-a-pull-request-to-the-upstream-repository"
  A --> B
  B --> C
  C --> D
  D -->|yes|E
  D -->|no|C

GitFlow for contributors

The GitFlow process outlined here depicts and suggests a way of working with Git and GitHub. It serves to synchronize the forked repository with the original upstream repository. It is not a strict requirement to follow this process, but it is highly recommended to do so.

---

config:
  logLevel: debug
  gitGraph:
    rotateCommitLabel: false
---

gitGraph LR:
  commit id:"fork"
  branch fork/main
  checkout fork/main
  commit id:"checkout feature" type: HIGHLIGHT
  branch feature
  checkout feature
  commit id:"checkout fix"
  branch fix
  checkout main
  merge feature id: "Pull Request 'Feature'" type: HIGHLIGHT
  checkout fix
  commit id:"Patch 1"
  commit id:"Patch 2"
  checkout main
  merge fix id: "Pull Request 'Fix'" type: HIGHLIGHT
Tip

When implementing the GitFlow process as described, it is advisable to configure the local clone of your forked repository with an additional remote for the upstream repository. This will allow you to easily synchronize your locally forked repository with the upstream repository. Remember, there is a difference between the forked repository on GitHub and the clone of the forked repository on your local machine.

UpstreamToForkAndSourceRepository UpstreamToForkAndSourceRepository

Note

Each time in the following sections we refer to ‘your xyz’, it is an indicator that you have to change something in your own environment.

Prepare your developer environment

1. Fork the module source repository

Important

Each Terraform AVM module will have its own GitHub repository in the Azure GitHub Organization as per SNFR19.

This repository will be created by the Module owners and the AVM Core team collaboratively, including the configuration of permissions as per SNFR9

Module contributors are expected to fork the corresponding repository and work on a branch from within their fork, before then creating a Pull Request (PR) back into the source repository’s main branch.

To do so, simply navigate to your desired repository, select the 'Fork' button to the top right of the UI, select where the fork should be created (i.e., the owning organization) and finally click ‘Create fork’.

Note

If the module repository you want to contribute to is not yet available, please get in touch with the respective module owner which can be tracked in the Terraform Resource Modules index see PrimaryModuleOwnerGHHandle column.

Optional: The usage of local source branches

For consistent contributors but also Azure-org members in general it is possible to get invited as collaborator of the module repository which enables you to work on branches instead of forks. To get invited get in touch with the module owner since it’s the module owner’s decision who gets invited as collaborator.

2. Prepare your Azure test environment

AVM performs end-to-end (e2e) test deployments of all modules in Azure for validation. We recommend you to perform a local e2e test deployment of your module before you create a PR to the upstream repository. Especially because the e2e test deployment will be triggered automatically once you create a PR to the upstream repository.

  1. Have/create an Azure Active Directory Service Principal with at least Contributor & User Access Administrator permissions on the Management-Group/Subscription you want to test the modules in. You might find the following links useful:

    # Linux/MacOs
    export ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) # or set <subscription_id>
    export ARM_TENANT_ID=$(az account show --query tenantId --output tsv) # or set <tenant_id>
    export ARM_CLIENT_ID=<client_id>
    export ARM_CLIENT_SECRET=<service_principal_password>
    
    # Windows/Powershell
    $env:ARM_SUBSCRIPTION_ID = $(az account show --query id --output tsv) # or set <subscription_id>
    $env:ARM_TENANT_ID = $(az account show --query tenantId --output tsv) # or set <tenant_id>
    $env:ARM_CLIENT_ID = "<client_id>"
    $env:ARM_CLIENT_SECRET = "<service_principal_password>"
  2. Change to the root of your module repository and run ./avm docscheck (Linux/MacOs) / avm.bat docscheck (Windows) to verify the container image is working as expected or needs to be pulled first. You will need this later.

    PullLatestAzterraformContainerImage PullLatestAzterraformContainerImage

3. Implement your contribution

To implement your contribution, we kindly ask you to first review the Terraform specifications and composition guidelines in particular to make sure your contribution complies with the repository’s design and principles.

Tip

To get a head start on developing your module, consider using the tooling recommended per spec TFNFR37. For example you can use the newres tool to help with creating variables.tf and main.tf if you’re developing a module using Azurerm provider.

4. Run Pre-commit Checks

Important

Make sure you have Docker installed and running on your machine.

Note

To simplify and help with the execution of commands like pre-commit, pr-check, docscheck, fmt, test-example, etc. there is now a simplified avm script available distributed to all repositories via terraform-azurerm-avm-template which combines all scripts from the avm_scripts folder in the tfmod-scaffold repository using avmmakefile.

The avm script also makes sure to pull the latest mcr.microsoft.com/azterraform:latest container image before executing any command.

4.1. Run pre-commit and pr-check

The following commands will run all pre-commit checks and the pr-check.

# Running all pre-commit checks
# `pre-commit` runs depsensure fmt fumpt autofix docs
# `pr-check` runs fmtcheck tfvalidatecheck lint unit-test

## Linux/MacOs
./avm pre-commit
./avm pr-check

## Windows
avm.bat pre-commit
avm.bat pr-check

4.2 Run e2e tests

Currently you have two options to run e2e tests:

Note

With the help of the avm script and the commands ./avm test-example (Linux/MacOs) / avm.bat test-example (Windows) you will be able to run it in a more simplified way. Currently the test-example command is not completely ready yet and will be released soon. Therefore please use the below docker command for now.

  1. Run e2e tests with the help of the azterraform docker container image.

    # Linux/MacOs
    
    docker run --rm -v $(pwd):/src -w /src -v $HOME/.azure:/root/.azure -e TF_IN_AUTOMATION -e AVM_MOD_PATH=/src -e AVM_EXAMPLE=<example_folder> -e ARM_SUBSCRIPTION_ID -e ARM_TENANT_ID -e ARM_CLIENT_ID -e ARM_CLIENT_SECRET mcr.microsoft.com/azterraform:latest make test-example
    
    # Powershell
    
    docker run --rm -v ${pwd}:/src -w /src -v $HOME/.azure:/root/.azure -e TF_IN_AUTOMATION -e AVM_MOD_PATH=/src -e AVM_EXAMPLE=<example_folder> -e ARM_SUBSCRIPTION_ID -e ARM_TENANT_ID -e ARM_CLIENT_ID -e ARM_CLIENT_SECRET mcr.microsoft.com/azterraform:latest make test-example

    Make sure to replace <client_id> and <service_principal_password> with the values of your service principal as well as <example_folder> (e.g. default) with the name of the example folder you want to run e2e tests for.

  2. Run e2e tests with the help of terraform init/plan/apply.

    Simply run terraform init and terraform apply in the example folder you want to run e2e tests for. Make sure to set the environment variables ARM_SUBSCRIPTION_ID, ARM_TENANT_ID, ARM_CLIENT_ID and ARM_CLIENT_SECRET before you run terraform init and terraform apply or make sure you have a valid Azure CLI session and are logged in with az login.

5. Create a pull request to the upstream repository

Once you are satisfied with your contribution and validated it, submit a pull request to the upstream repository and work with the module owner to get the module reviewed by the AVM Core team, by following the initial module review process for Terraform Modules, described here. This is a prerequisite for publishing the module. Once the review process is complete and your PR is approved, merge it into the upstream repository and the Module owner will publish the module to the HashiCorp Terraform Registry.

5.1 Create the Pull Request [Contributor]

These steps are performed by the contributor:

  1. Navigate to the upstream repository and click on the Pull requests tab.
  2. Click on the New pull request button.
  3. Ensure the base repository is set to the upstream AVM repo.
  4. Ensure the base branch is set to main.
  5. Ensure your head repository and compare branch are set to your fork and the branch you are working on.
  6. Click on the Create pull request button.

5.2 Review the Pull Request [Owner]

  1. IMPORTANT: The module owner must first check for any malicious code or changes to workflow files. If they are found, the owner should close the PR and report the contributor.
  2. Review the changes made by the contributor and determine whether end to end tests need to be run.
  3. If end to end tests do not need to be run (e.g. doc changes, small changes, etc) then so long as the static analysis passes, the PR can be merged to main.
  4. If end to end tests do need to be run, then follow the steps in 5.3.

5.3 Release Branch and Run End to End Tests [Owner]

  1. IMPORTANT: The module owner must first check for any malicious code or changes to workflow files. If they are found, the owner should close the PR and report the contributor.
  2. Create a release branch from main. Suggested naminmg convention is release/<description-of-change>.
  3. Open the PR created by the contributor and click Edit at the top right of the PR.
  4. Change the base branch to the release branch you just created.
  5. Wait for the PR checks to run, validate the code looks good and then merge the PR into the release branch.
  6. Create a new PR from the release branch to the main branch of the AVM module.
  7. The end to end tests should trigger and you can approve the run.
  8. Once the end to end tests have passed, merge the PR into the main branch.
  9. If the end to end tests fail, investigate the failure. You have two options:
    1. Work with the contributor to resolve the issue and ask them to submit a new PR from their fork branch to the release branch.
      1. Re-run the tests and merge to main. Repeat the loop as required.
    2. If the issue is a simple fix, resolve it directly in the release branch, re-run the tests and merge to main.

Common mistakes to avoid and recommendations to follow

  • If you contribute to a new module then search and update TODOs (which are coming with the terraform-azurerm-avm-template) within the code and remove the TODO comments once complete
  • terraform.lock.hcl shouldn’t be in the repository as per the .gitignore file
  • Update the support.md file
  • \_header.md needs to be updated
  • support.md needs to be updated
  • Exclude terraform.tfvars file from the repository

Subsections of Contribution Flow

Terraform Owner Contribution Flow

This section describes the contribution flow for module owners who are responsible for creating and maintaining Terraform Module repositories.

Important

This contribution flow is for Module owners only.

As a Terraform Module Owner you need to be aware of the AVM contribution process overview & Terraform specifications (including Interfaces) as as these need to be considered during pull request reviews for the modules you own.

Info

Make sure module authors/contributors tested their module in their environment before raising a PR. The PR uses e2e checks with 1ES agents in the 1ES subscriptions. At the moment their is no read access to the 1ES subscription. Also if more than two subscriptions are required for testing, that’s currently not supported.

1. Owner Activities and Responsibilities

Familiarise yourself with the responsibilities as Module Owner outlined in Team Definitions & RACI and in the TF Issue Triage.

  1. Watch Pull Request (PR) and issue (questions/feedback) activity for your module(s) in your repository and ensure that PRs are reviewed and merged in a timely manner as outlined in SNFR11.
Info

Make sure module authors/contributors tested their module in their environment before raising a PR. Also because once a PR is raised a e2e GitHib workflow pipeline is required to be run successfully before the PR can be merged. This is to ensure that the module is working as expected and is compliant with the AVM specifications.

2. GitHub repository creation and configuration

Once your module has been approved and you are ready to start development, you need to request that a new repository be created for your module.

You do that by adding a comment to the issue with the #RFRC tag. The  Status: Ready For Repository Creation 📝  label will then be applied. This will trigger the creation of the repository and the configuration of the repository with the required settings.

Info

If you need your repository to be created urgently, please message the AVM Core team in the AVM Teams channel.

Once your module is ready for development, the  Status: Repository Created 📄  label will be added to the issue and you’ll be notified it is ready.

3. Module Development Activities

You can now start developing your module, following standard guidance for Terraform module development.

Some useful things to know:

Pull Request

You can raise a pull request anytime, don’t wait until the end of the development cycle. Raise the PR after you first push your branch.

You can then use the PR to run end to end tests, check linting, etc.

Once readdy for review, you can request a review per step 4.

Grept

Grept is a linting tool for repositories, ensures predefined standards, maintains codebase consistency, and quality.
It’s using the grept configuration files from the Azure-Verified-Modules-Grept repository.

You can see here which files are synced from the terraform-azurerm-avm-template repository.

Set environment variables and run Grept:

export GITHUB_REPOSITORY_OWNER=Azure
export GITHUB_REPOSITORY=Azure/terraform-azurerm-avm-res-<RP>-<modulename>"

./avm grept-apply
$env:GITHUB_REPOSITORY_OWNER="Azure"
$env:GITHUB_REPOSITORY="Azure/terraform-azurerm-avm-res-<RP>-<modulename>"

./avm grept-apply

Custom Variables and Secrets for end to end tests

The respoitory has an environment called test, it has have approvals and secrets applied to it ready to run end to end tests.

  • In the unusual cicumstance that you need to use your own tenant and subscription for end to end tests, you can override the secrets by setting ARM_TENANT_ID_OVERRIDE, ARM_SUBSCRIPTION_ID_OVERRIDE, and ARM_CLIENT_ID_OVERRIDE secrets.
  • If you need to supply additional secrets or variables for your end to end tests, you can add them to the test environment. They must be prefixed with TF_VAR_, otherwise they will be ignored.

4. Review the module

Once the development of the module has been completed, get the module reviewed from the AVM Core team by following the AVM Review of Terraform Modules process here which is a pre-requisite for the next step.

5. Publish the module

Once a module has been reviewed and the PR is merged to main. Follow the below steps to publish the module to the HashiCorp Registry.

Ensure your module is ready for publishing:

  1. Create a release with a new tag (e.g. 0.1.0) via Github UI.

    • Go to the releases tab and click on Draft a new release.
    • Ensure that the Target is set to the main branch.
    • Select Choose a tag and type in a new tag, such as 0.1.0 Make sure to create the tag from the main branch.
    • Generate the release notes using the Generate release notes button.

    DeploymentProtectionRules DeploymentProtectionRules

  2. Elevate your respository access using the Open Source Management Portal.

  3. Sign in to the HashiCorp Registry using GitHub.

  4. Publish a module by selecting the Publish button in the top right corner, then Module

  5. Select the repository and accept the terms.

Info

Once a module gets updated and becomes a new version/release it will be automatically published with the latest published release version to the HashiCorp Registry.

Important

When an AVM Module is published to the HashiCorp Registry, it MUST follow the below requirements:

  • Resource Module: terraform-<provider>-avm-res-<rp>-<ARM resource type> as per RMNFR1
  • Pattern Module: terraform-<provider>-avm-ptn-<patternmodulename> as per PMNFR1

Terraform Core Team Repository Creation Process

This section describes the process for AVM core team members who are responsible for creating Terraform Module repositories.

Important

This contribution flow is for AVM Core Team members only.

1. Find Issues Ready for Repository Creation

  1. When a module owner is ready to start development, they will add the  Status: Ready For Repository Creation 📝  label to the proposal via a comment issue.
  2. To find issues that are ready for repository creation, click this link
  3. Open one of the issues to find the details you need.
    1. Module name: This will be in the format avm-<type>-<name>. e.g. avm-res-network-virtualnetwork
    2. Module owner GitHub handle: This will be in the content of the issue
    3. Module description: If this does not exist, then create one. The description will automtically be prefixed with Terraform Azure Verified <module-type> Module for ..., where <module-type> is either Resource, Pattern, or Utility

2. Create the repository

  1. Open a PowerShell terminal

  2. Clone the https://github.com/Azure/terraform-azure-modules repository and navigate to the repository_creation_helper folder

    git clone "https://github.com/Azure/terraform-azure-modules"
    cd ./terraform-azure-modules/repository_creation_helper
  3. Install the GitHub CLI if you don’t already have it installed: https://cli.github.com

  4. Login to GitHub CLI

    gh auth login -h "github.com" -w -p "https" -s "delete_repo" -s "workflow" -s "read:user" -s "user:email"

    Follow the prompts to login to your GitHub account.

  5. Run the following command, replacing the values with the details you collected in step 1

    $moduleProvider = "azurerm" # Only change this if you know why you need to change it :)
    $moduleName = "<module name>" # Replace with the module name (do not include the "terraform-azurerm" prefix)
    $moduleDescription = "<module description>" # Replace with a short description of the module
    $moduleOwner = "<github user handle>" # Replace with the GitHub handle of the module owner
    
    ./New-Repository.ps1 `
        -moduleProvider $moduleProvider `
        -moduleName $moduleName `
        -moduleDescription $moduleDescription `
        -moduleOwner $moduleOwner

    For example:

    $moduleProvider = "azurerm" # Only change this if you know why you need to change it :)
    $moduleName = "avm-res-network-virtualnetwork" # Replace with the module name (do not include the "terraform-azurerm" prefix)
    $moduleDescription = "Virtual Networks" # Replace with a short description of the module
    $moduleOwner = "jaredfholgate" # Replace with the GitHub handle of the module owner
    
    ./New-Repository.ps1 `
        -moduleProvider $moduleProvider `
        -moduleName $moduleName `
        -moduleDescription $moduleDescription `
        -moduleOwner $moduleOwner
  6. The script will stop and prompt you to fill out the Microsoft Open Source details,

  7. Open the Open Source Portal using the link in the script output.

  8. Click Complete Setup, then use the following table to provide the settings:

    QuestionAnswer
    Classify the repositoryProduction
    Assign a Service tree or Opt-outAzure Verified Modules / AVM
    Direct ownersAdd the module owner and yourself as direct owners. Add the avm-team-module-owners as security group.
    Is this going to ship as a public open source licensed projectYes, creating an open source licensed project
    What type of open source will this beSample code
    What license will you be releasing withMIT
    Did your team write all the code and create all of the assets you are releasing?Yes, all created by my team
    Does this project send any data or telemetry back to Microsoft?Yes, telemetry
    Does this project implement cryptographyNo
    Project nameAzure Verified Module (Terraform) for ‘module name
    Project version1
    Project descriptionAzure Verified Module (Terraform) for ‘module name’. Part of AVM project - https://aka.ms/avm
    Business goalsCreate IaC module that will accelerate deployment on Azure using Microsoft best practice.
    Will this be used in a Microsoft product or service?This is open source project and can be leveraged in Microsoft service and product.
    Adopt security best practice?Yes, use just-in-time elevation
    Maintainer permissionsLeave empty
    Write permissionsLeave empty
    Repository templateUncheck
    Add .gitignoreUncheck
  9. Click Finish setup + start business review to complete the setup

  10. Wait for it to process and then click View repository

  11. If you don’t see the Elevate your access button, then refresh the browser window

  12. Click Elevate your access and follow the prompts to elevate your access

  13. Now head back over to the terminal and type yes and hit enter to complete the repository configuration

  14. Open the new repository in GitHub.com and verify it all looks good.

    1. On the home page
      1. The name is correct
      2. The description is correct
      3. The Terraform registry url looks good
      4. The repository has the template files in it
    2. In Setting
      1. The repository is public
      2. The Collaborators and teams are correct

3. Request the GitHub App Install

  1. Create a new issue at https://github.com/microsoft/github-operations/issues/new?template=GitHub-App-Installation-Request.md

  2. Update the issue with the following details:

    1. Title: [GitHub App] Installation Request - Azure Verified Modules

    2. Body - replace <repository url> with the URL of the repository you created in step 2:

      > __Note:__ If the app is listed on the [Auto-Approved list](https://docs.opensource.microsoft.com/github/apps/approvals/), you do not need to complete this form.
      
      You complete these steps:
      
      - [x] Confirm the app is not in the [Auto-Approved list](https://docs.opensource.microsoft.com/github/apps/approvals/)
      - [x] Fill out and verify the information in this form
      - [x] Update the title to reflect the org/repo and/or app name
      - [x] Submit the native request within the GitHub user interface
      
      Operations will help complete these steps:
      
      - [ ] Approve the app if already requested on GitHub natively
      - [ ] Close this issue
      
      Finally, you'll complete any configuration with the app or your repo that is required once approved.
      
      # My request
      
      - GitHub App name: Azure Verified Modules
      
      - GitHub organization in which the app would be installed: Azure
      
      - Is this an app created by you and/or your team?
      
        - [x] Yes, this is an app created by me and/or my team
        - [ ] No, this is a Microsoft 1st-party app created by another team
        - [ ] No, this is a 3rd-party marketplace app
      
      - If this __is an app created by you and/or your team__, please provide some ownership information in case future questions come up:
      
        - Service Tree ID: our service tree ID is: Unchanged
        - A few specific individuals at Microsoft if we have questions (corporate email list):Unchanged
        - An optional team discussion list: Unchanged
      
      - Is this an app you/your team created to address [reduced PAT lifetimes](https://aka.ms/opensource/tsg/pat)?
        - [x] Yes
        - [ ] No
      
      - Are you looking for this app to be installed on individual repos or all repos in an organization?
      
        - [x] Individual repos: <repository url>
        - [ ] All repos in an organization
      
      - Does this app have any side-effects if it is installed into all repos in an organization? Side effects can include creating labels, issues, pull requests, automatic checks on PRs, etc.
      
        - [ ] Yes, it has side effects and you should be careful if installing to all repos in an org
        - [x] No side effects
      
      - Please provide a description of the app's functionality and what are you trying to accomplish by utilizing this app:
      
        Unchanged
      
      - For any major permissions (org admin, repo admin, etc.), can you explain what they are and why they are needed?
      
        Unchanged
      
      - Any other notes or information can you provide about the app?
  3. Submit the issue

4. Notify the Module Owner and Update the Issue Status

  1. Add a comment to the issue you found in step 1 to let the module owner know that the repository has been created and is be ready for them to start development.

    @<module owner> The module repository has now been created. You can find it at <repository url>.
    
    The final step of repository configuration is still in progress, but you will be able to start developing your code immediately.
    
    The final step is to create the environment and credentials require to run the end to end tests. If the environment called `test` is not available in 48 hours, please let me know.
    
    Thanks
  2. Add the  Status: Repository Created 📄  label to the issue

  3. Remove the  Status: Ready For Repository Creation 📝  label from the issue

Terraform Contribution Prerequisites

To contribute to this project, you need to have a GitHub account which is linked to your Microsoft corporate identity account and be a member of the Azure organization.

Tooling

Required Tooling

Tip

We recommend to use Linux or MacOS for your development environment. You can use Windows Subsystem for Linux (WSL) if you are using Windows.

To contribute to this project the following tooling is required:

The following tooling/extensions are recommended to assist you developing for the project:

Visual Studio Code Extensions

  • Go extension for Visual Studio Code
  • For visibility of Bracket Pairs:
    • Inside Visual Studio Code, add editor.bracketPairColorization.enabled: true to your settings.json, to enable bracket pair colorization.

Review of Terraform Modules

The AVM module review is a critical step before an AVM Terraform module gets published to the Terraform Registry and made publicly available for customers, partners and wider community to consume and contribute to. It serves as a quality assurance step to ensure that the AVM Terraform module complies with the Terraform specifications of AVM. The below process outlines the steps that both the module owner and module reviewer need to follow.

  1. The module owner completes the development of the module in their branch or fork.

  2. The module owner submits a pull request (PR) titled AVM-Review-PR and ensures that all checks are passing on that PR as that is a pre-requisite to request a review.

  3. The module owner assigns the avm-core-team-technical-terraform GitHub team as reviewer on the PR.

  4. The module owner leaves the following comment as it is on the module proposal in the AVM - Module Triage project by searching for their module proposal by name there.

    ➕ AVM Terraform Module Review Request
    I have completed my initial development of the module and I would like to request a review of my module before publishing it to the Terraform Registry. The latest code is in a PR titled [AVM-Review-PR](REPLACE WITH URL TO YOUR PR) on the module repo and all checks on that PR are passing.
  5. The AVM team moves the module proposal from “In Development” to “In Review” in the AVM - Module Triage project.

  6. The AVM team will assign a module reviewer who will open a blank issue on the module titled “AVM-Review” and populate it with the below mark down. This template already marks the specs as compliant which are covered by the checks that run on the PR. There are some specs which don’t need to be checked at the time of publishing the module therefore they are marked as NA.

    ➕ AVM Terraform Module Review Issue

    Dear module owner,

    As per the module ownership requirements and responsibilities at the time of [assignment](REPLACE WITH THE LINK TO THE AVM MODULE PROPOSAL), the AVM Team is opening this issue, requesting you to validate your module against the below AVM specifications and confirm its compliance.

    Please don’t close this issue and merge your AVM-Review-PR until advised to do so. This review is a prerequisite for publishing your module’s v0.1.0 in the Terraform Registry. The AVM team is happy to assist with any questions you might have.

    Requested Actions

    1. Complete the below task list by ticking off the tasks.
    2. Complete the below table by updating the Compliant column with Yes, No or NA as possible values.

    Please use the comments columns to provide additional details especially if the Compliant column is updated to No or NA.

    ### Tasks
    - [ ] Address comments on AVM-Review-PR if any
    - [ ] Ensure that all checks on AVM-Review-PR are passing
    - [ ] Make sure you have run [grept](https://azure.github.io/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/owner-contribution-flow/#5-grept) and [pre-commit and pr-check](https://azure.github.io/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/#41-run-pre-commit-and-pr-check).
    - [ ] Tick this to acknowledge specs with comment "Module Owner to action this spec post-publish as appropriate" in the table below.
    - [ ] Please update the _header.md file as it contains instructions which - once actioned - need to be replaced with Module Name and Description.
    IDSpecCompliantComments
    1ID: SFR1 - Category: Composition - Preview ServicesNA if no preview services are used
    2ID: SFR2 - Category: Composition - WAF AlignedEnsure only high priority reliability & security recommendations are implemented if any
    3ID: SFR3 - Category: Telemetry - Deployment/Usage Telemetry
    4ID: SFR4 - Category: Telemetry - Telemetry Enablement FlexibilityYesYes if AVM Template Repo has been used
    5ID: SFR5 - Category: Composition - Availability Zones
    6ID: SFR6 - Category: Composition - Data Redundancy
    7ID: SNFR25 - Category: Composition - Resource Naming
    8ID: SNFR1 - Category: Testing - Prescribed TestsYesYes if all e2e test, version-check & linting checks passed
    9ID: SNFR2 - Category: Testing - E2E TestingYesYes if e2e tests passed
    10ID: SNFR3 - Category: Testing - AVM Compliance TestsYesYes if all e2e test, version-check & linting checks passed
    11ID: SNFR4 - Category: Testing - Unit TestsNA if no tests created in tests folder
    12ID: SNFR5 - Category: Testing - Upgrade TestsNAModule Owner to action this spec post-publish as appropriate
    13ID: SNFR6 - Category: Testing - Static Analysis/Linting TestsYesYes if all linting checks passed
    14ID: SNFR7 - Category: Testing - Idempotency TestsYesYes if e2e tests passed
    15ID: SNFR24 - Category: Testing - Testing Child, Extension & Interface ResourcesYesYes if e2e tests passed
    16ID: SNFR8 - Category: Contribution/Support - Module Owner(s) GitHub
    17ID: SNFR20 - Category: Contribution/Support - GitHub Teams Only
    18ID: SNFR9 - Category: Contribution/Support - AVM & PG Teams GitHub Repo Permissions
    19ID: SNFR10 - Category: Contribution/Support - MIT LicensingYesYes if AVM Template Repo has been used
    20ID: SNFR11 - Category: Contribution/Support - Issues Response TimesNAModule Owner to action this spec post-publish as appropriate
    21ID: SNFR12 - Category: Contribution/Support - Versions SupportedNAModule Owner to action this spec post-publish as appropriate
    22ID: SNFR23 - Category: Contribution/Support - GitHub Repo Labels
    23ID: SNFR14 - Category: Inputs - Data Types
    24ID: SNFR22 - Category: Inputs - Parameters/Variables for Resource IDs
    25ID: SNFR15 - Category: Documentation - Automatic Documentation GenerationYesYes if linting / docs check passed
    26ID: SNFR16 - Category: Documentation - Examples/E2EYesYes if e2e tests passed
    27ID: SNFR17 - Category: Release - Semantic VersioningYesYes if version-check check passed
    28ID: SNFR18 - Category: Release - Breaking ChangesNAModule Owner to action this spec post-publish as appropriate
    29ID: SNFR19 - Category: Publishing - Registries TargetedNAModule Owner to action this spec post-publish as appropriate
    30ID: SNFR21 - Category: Publishing - Cross Language CollaborationNAModule Owner to action this spec post-publish as appropriate
    31ID: RMFR1 - Category: Composition - Single Resource Only
    32ID: RMFR2 - Category: Composition - No Resource Wrapper Modules
    33ID: RMFR3 - Category: Composition - Resource Groups
    34ID: RMFR4 - Category: Composition - AVM Consistent Feature & Extension Resources Value AddYesYes if linting / terraform check passed
    35ID: RMFR5 - Category: Composition - AVM Consistent Feature & Extension Resources Value Add Interfaces/SchemasYesYes if linting / terraform check passed
    36ID: RMFR8 - Category: Composition - Dependency on child and other resources
    37ID: RMFR6 - Category: Inputs - Parameter/Variable Naming
    38ID: RMFR7 - Category: Outputs - Minimum Required OutputsYesYes if linting / terraform check passed
    39ID: RMNFR1 - Category: Naming - Module Naming
    40ID: RMNFR2 - Category: Inputs - Parameter/Variable Naming
    41ID: RMNFR3 - Category: Composition - RP CollaborationNAModule Owner to action this spec post-publish as appropriate
    42ID: PMFR1 - Category: Composition - Resource Group CreationNA if this is not a pattern module
    43ID: PMNFR1 - Category: Naming - Module NamingNA if this is not a pattern module
    44ID: PMNFR2 - Category: Composition - Use Resource Modules to Build a Pattern ModuleNA if this is not a pattern module
    45ID: PMNFR3 - Category: Composition - Use other Pattern Modules to Build a Pattern ModuleNA if this is not a pattern module
    46ID: PMNFR4 - Category: Hygiene - Missing Resource Module(s)NA if this is not a pattern module
    47ID: PMNFR5 - Category: Inputs - Parameter/Variable NamingNA if this is not a pattern module
    48ID: TFFR1 - Category: Composition - Cross-Referencing Modules
    49ID: TFFR2 - Category: Outputs - Additional Terraform OutputsYesYes if linting / terraform check passed
    50ID: TFNFR1 - Category: Documentation - Descriptions
    51ID: TFNFR2 - Category: Documentation - Module Documentation GenerationYesYes if linting / docs check passed
    52ID: TFNFR3 - Category: Contribution/Support - GitHub Repo Branch ProtectionYesYes if AVM Template Repo has been used
    53ID: TFNFR4 - Category: Composition - Code Styling - lower snake_casingYesYes if linting / terraform check passed
    54ID: TFNFR5 - Category: Testing - Test ToolingYesYes if linting / terraform check passed
    55ID: TFNFR6 - Category: Code Style - Resource & Data Order
    56ID: TFNFR7 - Category: Code Style - count & for_each Use
    57ID: TFNFR8 - Category: Code Style - Resource & Data Block OrdersYesYes if linting / avmfix check passed
    58ID: TFNFR9 - Category: Code Style - Module Block Order
    59ID: TFNFR10 - Category: Code Style - No Double Quotes in ignore_changes
    60ID: TFNFR11 - Category: Code Style - Null Comparison Toggle
    61ID: TFNFR12 - Category: Code Style - Dynamic for Optional Nested Objects
    62ID: TFNFR13 - Category: Code Style - Default Values with coalesce/try
    63ID: TFNFR14 - Category: Inputs - Not allowed variables
    64ID: TFNFR15 - Category: Code Style - Variable Definition OrderYesYes if linting / avmfix check passed
    65ID: TFNFR16 - Category: Code Style - Variable Naming RulesYesYes if linting / terraform check passed
    66ID: TFNFR17 - Category: Code Style - Variables with DescriptionsYesYes if linting / terraform check passed
    67ID: TFNFR18 - Category: Code Style - Variables with TypesYesYes if linting / terraform check passed
    68ID: TFNFR19 - Category: Code Style - Sensitive Data Variables
    69ID: TFNFR20 - Category: Code Style - Non-Nullable Defaults for collection values
    70ID: TFNFR21 - Category: Code Style - Discourage Nullability by DefaultYesYes if linting / avmfix check passed
    71ID: TFNFR22 - Category: Code Style - Avoid sensitive = falseYesYes if linting / avmfix check passed
    72ID: TFNFR23 - Category: Code Style - Sensitive Default Value ConditionsYesYes if linting / terraform check passed
    73ID: TFNFR24 - Category: Code Style - Handling Deprecated VariablesNAModule Owner to action this spec post-publish as appropriate
    74ID: TFNFR25 - Category: Code Style - Verified Modules RequirementsYesYes if linting / terraform check passed
    75ID: TFNFR26 - Category: Code Style - Providers in required_providersYesYes if linting / terraform check passed
    76ID: TFNFR27 - Category: Code Style - Provider Declarations in ModulesYesYes if linting / terraform check passed
    77ID: TFNFR29 - Category: Code Style - Sensitive Data OutputsYesYes if linting / avmfix check passed
    78ID: TFNFR30 - Category: Code Style - Handling Deprecated OutputsNAModule Owner to action this spec post-publish as appropriate
    79ID: TFNFR31 - Category: Code Style - locals.tf for Locals Only
    80ID: TFNFR32 - Category: Code Style - Alphabetical Local ArrangementYesYes if linting / avmfix check passed
    81ID: TFNFR33 - Category: Code Style - Precise Local Types
    82ID: TFNFR34 - Category: Code Style - Using Feature TogglesNAModule Owner to action this spec post-publish as appropriate
    83ID: TFNFR35 - Category: Code Style - Reviewing Potential Breaking ChangesNAModule Owner to action this spec post-publish as appropriate
    84ID: TFNFR36 - Category: Code Style - Setting prevent_deletion_if_contains_resources
    85ID: TFNFR37 - Category: Code Style - Tool Usage by Module Owner
  7. The module reviewer can update the Compliance column for specs in line 42 to 47 to NA, in case the module being reviewed isn’t a pattern module.

  8. The module reviewer reviews the code in the PR and leaves comments to request any necessary updates.

  9. The module reviewer assigns the AVM-Review issue to the module owner and links the AVM-Review Issue to the AVM-Review-PR so that once the module reviewer approves the PR and the module owner merges the AVM-Review-PR, the AMV-Review issue is automatically closed. The module reviews responds to the module owner’s comment on the Module Proposal in AVM Repo with the following

    ➕ AVM Terraform Module Review Initiation Message
    Thank you for requesting a review of your module. The AVM module review process has been initiated, please perform the **Requested Actions** on the AVM-Review issue on the module repo.
  10. The module owner updates the check list and the table in the AVM-Review issue and notifies the module reviewer in a comment.

  11. The module reviewer performs the final review and ensures that all checks in the checklist are complete and the specifications table has been updated with no requirements having compliance as ‘No’.

  12. The module reviewer approves the AVM-Review-PR, and leaves the following comment on the AVM-Review issue with the following comment.

    ➕ AVM Terraform Module Review Completion Message
    Thank you for contributing this module and completing the review process per AVM specs. The AVM-Review-PR has been approved and once you merge it that will close this AVM-Review issue. You may proceed with [publishing](/Azure-Verified-Modules/contributing/terraform/terraform-contribution-flow/owner-contribution-flow/#7-publish-the-module) this module to the HashiCorp Terraform Registry with an initial pre-release version of v0.1.0. Please keep future versions also pre-release i.e. < 1.0.0 until AVM becomes generally available (GA) of which the AVM team will notify you.
    
    **Requested Action**: Once published please update your [module proposal](REPLACE WITH THE LINK TO THE MODULE PROPOSAL) with the following comment.
    
    "The initial review of this module is complete, and the module has been published to the registry. Requesting AVM team to close this module proposal and mark the module available in the module index.
    Terraform Registry Link: <REPLACE WITH THE LINK OF THE MODULE IN TERRAFORM REGISTRY>
    GitHub Repo Link: <REPLACE WITH THE LINK OF THE MODULE IN GITHUB>"
  13. Once the module owner perform the requested action in the previous step, the module reviewer updates the module proposal by performing the following steps:

  • Assign label Status: Module Available :green_circle: to the module proposal.
  • Update the module index excel file and CSV file by creating a PR to update the module index and links the module proposal as an issue that gets closed once the PR is merged which will move the module proposal from “In Review” to “Done” in the AVM - Module Triage project.