I’ve been working with DSC for about 2 years now and am surprised by how little I have found on this topic. I come from an application development background so I have high expectations of my local development process. Specifically:
- Easily list dependencies in 1 place. Use that list for both local development and in production deployments.
- Rapid iterations of change code => build code => test change => repeat. Rapid meaning 1 - 10 seconds.
- Azure Automation pull server
- Local Windows 10 dev machine
- Target DSC node - an Azure VM. OS varies but is usually Windows Server 2012 R2
This is how I used to do it:
- Deploy the VM. Do not register it to Azure Automation.
- Log into the VM.
- Install git, VS Code, clone repo.
- Source code has all PowerShell modules in it. This means 3rd party OS (gross, I know) and custom modules we wrote.
- Source code has DSC configs.
- Custom build script copies all modules to a directory in the PSModulesPath.
- Custom build script complies the config (dot sourced).
- Custom build script applies the config to localhost with Start-DscConfiguration.
- Rapidly repeat steps 6 - 8 to work through any compilation or runtime errors.
- When task is complete, check in changes to modules & config.
- Delete the VM.
- Push modules to Azure Automation. All modules needed are in the project so we know we are deploying the same versions we just tested.
- Push configs to Azure Automation. Compile them.
- Deploy the VM to Azure. This time, let it register to Azure Automation.
- Very rapid feedback when developing both configs and custom modules.
- Setting up a dev machine on the target DSC node is cumbersome. Imagine if the DSC failed on step 13. I now have to set the whole thing up again to troubleshoot.
- Obvious problem - 3rd party modules are included in the project. This is fixed in the next process described below.
This is the direction I’m heading for an improved process:
- Deploy a VM to Azure. Let it register with Azure Automation pull server. (Assume a minimal or empty DSC config exists just to let the initial registration succeed).
- On my local workstation, Install-Module all modules my config depends on.
- Compile the config (dot source). Iterate to work through compilation errors.
- Upload the mof(s) to Azure Automation.
- Remote into the Azure VM and trigger an on-demand pull with Update-DscConfiguration.
- Review errors in Event logs.
- Repeat from 2 - 6 until task is complete.
- Deploy all 3rd party and custom modules to Azure Automation using an ARM template or similar.
- Let Azure Automation comple the DSC.
- Verify the config was applied successfully.
- Check in changes.
- No need to setup dev tools on the target DSC node. Can just use my local workstation.
- Removed source controlled 3rd party modules from my project. I can now just install the package and version I want, when I want it.
- There is no single manifest for modules. Notice step 2 uses Install-Module and step 8 uses something else. We must roll our own manifest to prevent simple mistakes.
- Feedback loop is slower. The time it takes to see the results of a change in this process is significantly slower than what was used in process A.
How do you do it?