Since at least July 2013 (the initial commit in my current Salt configuration repository at home) I have been using SaltStack to orchestrate and configure my systems, including VMs, at home. In the last few years Ansible has grown in popularity and I have recently been looking closely at it due to its integration with Azure and Microsoft include Ansible in their Azure documentation and Cloud Shell Platform.

Microsoft’s example uses a dedicated Virtual Machine to run Ansible, however this is not desirable for a number of reasons including an unnecessary additional machine to manage and the costs associated with having another virtual machine. It is, with a little bit of effort, possible to run Ansible directly through the Azure DevOps service as Russ McKendrick described. What follows is my version, with Ansible’s dynamic inventory module, based upon the work he started.

The pipeline

After a bit of tweaking, I came up with this working pipeline configuration file:

# Do not automatically run this pipeline
trigger:
- none

steps:
  - task: UsePythonVersion@0
    displayName: 'Install Python'
    inputs:
      versionSpec: '3.6'
  - task: AzureCLI@2
    displayName: 'Azure CLI'
    inputs:
      # Pass SUBSCRIPTION_NAME as an argument to the playbook run - everything else it will figure out
      azureSubscription: '$(SUBSCRIPTION_NAME)'
      addSpnToEnvironment: true
      scriptType: 'bash'
      scriptLocation: 'inlineScript'
      inlineScript: |
        echo "##vso[task.setvariable variable=ARM_SUBSCRIPTION_ID]$(az account show --query="id" -o tsv)"
        echo "##vso[task.setvariable variable=ARM_CLIENT_ID]${servicePrincipalId}"
        echo "##vso[task.setvariable variable=ARM_CLIENT_SECRET]${servicePrincipalKey}"
        echo "##vso[task.setvariable variable=ARM_TENANT_ID]${tenantId}"
  - script: pip install ansible
    displayName: 'Install Ansible'
  - script: pip install -r https://raw.githubusercontent.com/ansible-collections/azure/dev/requirements-azure.txt
    displayName: 'Install modules needed for Azure'
  - script: ansible-galaxy collection install azure.azcollection
    displayName: 'Install Ansible Azure Collection'
  - script: wget https://raw.githubusercontent.com/ansible-collections/community.general/main/scripts/inventory/azure_rm.py
    displayName: 'Fetch Azure dynamic inventory script'
  - script: chmod +x azure_rm.py
    displayName: 'Make inventory script executable'
  - script: ansible-playbook -i azure_rm.py Ansible/site.yml
    displayName: 'Run Ansible Playbook'
    env:
      AZURE_CLIENT_ID: $(ARM_CLIENT_ID)
      AZURE_SECRET: $(ARM_CLIENT_SECRET)
      AZURE_TENANT: $(ARM_TENANT_ID)
      AZURE_SUBSCRIPTION_ID: $(ARM_SUBSCRIPTION_ID)

The Ansible playbook

I kept this really simple, and just used the example from Microsoft’s page which shows the running state for all of the VMs in Azure. The file was saved as ‘site.yml’ in the ‘Ansible’ subdirectory of the repository:

- name: Test the inventory script
  hosts: azure
  connection: local
  gather_facts: no
  tasks:
    - debug: msg=" has powerstate "

Future work

I want to explore if I can do what we currently do with Azure DevOps with GitHub actions instead as well as migrate existing laborious, monolithic and/or manual processes to more automated, encapsulated and streamlined tools.