Hugo Future Imperfect Slim

Dina Muscanell

Fierce. DevOps. Engineer

How to run Chef Test Kitchen in Azure DevOps builds using Microsoft hosted (free) agents.

Learn how to use free Microsoft hosted agents in Azure DevOps to run Chef Test Kitchen. Examples of azure-pipeline files using only PowerShell as well as the Chef Integration from the marketplace using variables and variable groups. **Updated 7/12/2019**

5 minute read


Reminder: There is a limit of one parallel (concurrent) build on private azure devops projects. If your project is public, you can run 10 parallel builds for free.


This posts assumes you understand the basics steps required for setting up a test kitchen using the azurerm driver, if you need to review them, go here

The Microsoft hosted free build agents, do not come with Chef on them. In order for us to run test kitchen, we’ve got to orchestrate the same steps required to get test kitchen running locally but in the azure-pipelines.yml file:

  • Install the Chef DK
  • Add the Chef DK to the system environment variable for the path (since this will be executed in one powershell session)
  • Create the .azure folder with a credentials file
  • Install the gem for azurerm test kitchen
  • Run test kitchen
  • Before we start writing code, I’d recommend staging your variables in Azure DevOps. I created a variable group for all my test kitchen variables called test-kitchen


Before we start writing code, I’d recommend staging your variables in Azure DevOps. I created a variable group for all my test kitchen variables called test-kitchen

variables-groups



All pipelines can access this variable group in the screen grab above but you can also restrict access. You should also encrypt your sensitive variables (i.e. ClientSecret), you can do that by clicking the lock icon to the right after you enter them.

Now that we’ve prestaged our variables, there are two ways you can setup CI.



let’s look at what our azure-pipelines.yml looks like…

Powershell Steps

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
  branches:
    include:
      - '*'

pool:
  vmImage: 'VS2017-Win2016'

variables:
  - group: test-kitchen
  - name: cookbookPath
    value: "$(Build.Repository.LocalPath)\\< cookbook source location >"
  - name: agentUserPath
    value: "C:/Users/VssAdministrator"

steps:
  - powershell: |
      . { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -channel current -project chefdk
    displayName: 'Install Chef DK'

  - powershell: |
      Write-Host "##vso[task.setvariable variable=PATH;]${env:PATH};C:\opscode\chefdk\bin";
    displayName: 'Add Chef to Path'

  - powershell: |
      New-Item -ItemType Directory -Path '$(agentUserPath)/.azure'
    displayName: 'Create .azure directory'

  - powershell: |
      New-Item -ItemType File -Path '$(agentUserPath)/.azure/credentials' -Force
    displayName: 'Create credentials file'

  - powershell: |
      Set-Content -Path '$(agentUserPath)/.azure/credentials' -Value `
      "[$env:azure_subscription]
      client_id = $(ClientId)
      client_secret = $(ClientSecret)
      tenant_id = $(TenantId)"
    env:
      ClientSecret: $(Client_Secret) # required for referencing secure variable
    displayName: 'Set content for credentials file'

  - powershell: |
      Set-Location $(cookbookPath)
      kitchen test --destroy==always
    displayName: 'Run Test Kitchen'


All the powershell commands above are run inline but you could also put them into a script and call that specific script in your azure-pipelines.yml file.

Chef Integration for Azure Pipelines

In order to run these steps you must have the Chef Integration extension from the marketplace. It is free to download. Just hit the shopping bag icon in the upper right and search for Chef Integration. Once installed, you can call the tasks. A heads up that in the documentation (here) for installing the chef-dk it notes that a hosted windows agent is not compatible but I haven’t had any issues.

trigger:
  branches:
    include:
      - '*'

pool:
  vmImage: 'windows-2019'

variables:
  - group: test-kitchen
  - name: cookbookPath
    value: "$(Build.Repository.LocalPath)\\< cookbook source location >"
  - name: agentUserPath
    value: "C:/Users/VssAdministrator"

steps:
  - task: vsts-chef-task-install-chefdk@1
    inputs:
      chefDKChannel: 'stable'
    displayName: 'Install Chefdk'

  - powershell: |
      Set-Location "$(agentUserPath)"
      $null = New-Item -Type Directory -Path '.azure'
      Set-Content .azure\credentials "[$env:azure_subscription]
      client_id = $env:ClientID
      client_secret = $env:ClientSecret
      tenant_id = $env:TenantId"
    env:
      ClientSecret: $(Client_Secret)
    displayName: 'Configure credentials for kitchen-azurem'

  - task: vsts-chef-task-test-kitchen@1
    inputs:
      tkAzureEndpoint: 'chef-test-kitchen'
      tkCommand: 'test --destroy==always'
      tkKitchenFile: 'kitchen.yml'
      tkKitchenFolder: '$(cookbookPath)'
    displayName: 'Run Test Kitchen'

If you do decide to use a variable group, take note of the syntax. We must follow the styling to reference group variables and also set variables in this file. There is also a very specific way for referencing encrypted secrets, explained by Microsoft here In order to add the chef executable to the path we must do it by running a logging command (referenced from stack overflow here).

My build with minimal chef logic takes about 17 minutes to run all steps (no matter which method is selected):

all-build-steps


During my “Run Test Kitchen” there is a TON of output, but here are some screen grabs of a chef-client running finishing and tests passing:

pipeline-running-chef


Inspec Tests:

inspec-tests



For my pipeline builds when I was trying to get everything configured correctly, my test kitchen resources needed to be manually deleted from Azure, so make sure they aren’t sitting out there costing you $$$.

If you are curious about my .kitchen.yml file, I am keeping it as simple as possible:

---
driver:
  name: azurerm
  subscription_id: "<%= ENV['azure_subscription'] %>" # make sure the environment variable is set
  location: 'EastUS2'
  machine_size: 'Standard_D2s_v3'
  username: "azure"

transport:
  name: winrm
  elevated: true

verifier:
  name: inspec

provisioner:
  name: chef_zero
  deprecations_as_errors: true
  retry_on_exit_code:
    - 20
    - 35
    - 259 # required exit code for powershell 5 to install without a chef client failure
  max_retries: 15
  wait_for_retry: 180
  client_rb:
    exit_status: :enabled

platforms:
  - name: windows2012R2-sql2016
    driver:
      image_urn: "MicrosoftSQLServer:SQL2016-WS2012R2:SQLDEV:latest"

suites:
  - name: default
    run_list:
      - recipe[powershell::powershell5]
    attributes:
      powershell:
        installation_reboot_mode: 'delayed_reboot'

Recent posts

See more

Categories

About

About