Using GitHub Actions to deploy Aviatrix

black metal emergency exit staircase
Photo by ready made on Pexels.com

Automating Terraform with CI/CD enforces configuration best practices, promotes collaboration and automates the Terraform workflow.

GitHub Actions Prime

Actions

An action is a custom application for the GitHub Actions platform that performs a repeated task. GitHub Actions is composed by:

  • events: an event is a specific activity in a repository that triggers a workflow run.
  • workflows: a workflow is a configurable automated process that will run one or more jobs.

Workflow

Workflows are defined by a YAML in a repository and will run when triggered by an event or manually. A workflow contains one or more jobs which can run in sequential order or in parallel.

Jobs

A job is a set of steps in a workflow that execute on the same runner. Each step is either a shell script that will be executed, or an action that will be run. Each job runs inside its own runner (a vm or a container), and has steps that run a script or run an action.

Runners

A runner is a server that runs workflows. Each runner can run a single job at a time. GitHub provides Ubuntu Linux, Microsoft Windows, and macOS runners to run workflows.

Creating workflows for Aviatrix

The architecture we will implement is based on the following diagram:

The steps are detailed below.

  • Create a github repository
  • Clone to your machine:
  • create a terraform cloud workspace
  • The execution mode is set to local (GitHub runners will take care of that):
  • configure the previously created github repository as the VCS:
  • create a directory called .github and a sub-directory called workflows:
ricardotrentin@RicardontinsMBP terraform % ls -l .github/workflows
total 8
-rw-r--r-- 1 ricardotrentin staff 1874 Nov 10 13:37 avx-deploy-github-actions.yaml

The yaml file is where the workflow is configured:

  • GitHub Action checkout checks out the repository in the runner VM (ubuntu latest)
  • GitHub Action setup-terraform sets up and configures the Terraform CLI
name: 'AVX Deploy'
on:
  push:
    branches: [ main ]
jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
        with:
          cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
      - name: Terraform Format
        id: fmt
        run: terraform fmt -check
        continue-on-error: true
      - name: Terraform Init
        id: init
        run: terraform init
      - name: Terraform Plan
        id: plan
        if: github.event_name == 'pull_request'
        run: terraform plan -no-color
        continue-on-error: true
      - name: Update Pull Request
        uses: actions/github-script@v6
        if: github.event_name == 'pull_request'
        env:
          PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const output = `#### Terraform Format and Style πŸ–Œ\`${{ steps.fmt.outcome }}\`
            #### Terraform Initialization βš™οΈ\`${{ steps.init.outcome }}\`
            #### Terraform Validation πŸ€–\`${{ steps.validate.outcome }}\`
            <details><summary>Validation Output</summary>

            \`\`\`\n
            ${{ steps.validate.outputs.stdout }}
            \`\`\`

            </details>

           #### Terraform Plan πŸ“–\`${{ steps.plan.outcome }}\`

           <details><summary>Show Plan</summary>

           \`\`\`\n
           ${process.env.PLAN}
           \`\`\`

          </details>

         *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.tf_actions_working_dir }}\`, Workflow: \`${{ github.workflow }}\`*`;

         github.rest.issues.createComment({
           issue_number: context.issue.number,
           owner: context.repo.owner,
           repo: context.repo.repo,
           body: output
        })
      - name: Terraform Plan Status
        if: steps.plan.outcome == 'failure'
        run: exit 1

      - name: Approval
        uses: trstringer/manual-approval@v1
        with:
          secret: ${{ github.TOKEN }}
          approvers: rtrentin73
          minimum-approvals: 1
          exclude-workflow-initiator-as-approver: false      

      - name: Terraform Apply
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: terraform apply -auto-approve

Once the terraform files are ready (not in the scope of this blog):

ricardotrentin@RicardontinsMBP terraform % ls
README.md       peering.tf      provider.tf     spoke.tf        transit.tf      variables.tf    vnet.tf

Save them and then run the following git commands:

git add .
git commit
git push 

The git push will trigger the workflow that will create a runner, install terraform, download modules, plan, and apply the tf files:

The last step before “applying” is a manual approval:

Once the workflow action is approved, the apply runs:

References

https://docs.github.com/en/actions

https://docs.github.com/en/actions/deployment

https://developer.hashicorp.com/terraform/tutorials/automation/github-actions

https://github.com/marketplace/actions/hashicorp-setup-terraform

Leave a Reply