Admins who work with Ansible for configuration management should check out the dry run, also referred to as check mode to deploy changes safely.
This built-in feature tests playbooks against the intended host -- but doesn't make any actual modifications. It is similar to the -whatif parameter in PowerShell. When you run an Ansible playbook in check mode, it reviews the syntax and proceeds to run through -- and observe only -- each task. This simulated playbook experience enables you to see the tasks in action, successful or not, before pushing them to production systems on a real run.
How to use check mode for a dry run
To run an Ansible playbook in check mode, simply add --check when executing the ansible-playbook command. Watch the video to see check mode in action.
This tutorial uses a VM running Ubuntu in Microsoft Azure to update the app cache on the Ubuntu server, as well as to install Apache's HTTP Server service and enable it.
Open your terminal to create a dry run. Then SSH into the Ansible control server and write in the playbook. The Ansible playbook is a YAML file. Be sure to specify that file in the dry run. This tutorial uses an Ansible Vault encrypted string, which means you must also write in a command to unencrypt it. Use the command --check to signify to Ansible that this playbook executes as a dry run and should not enact any changes in the environment. Add the -v verbose flag so that Ansible displays background information. Now input the Vault pass and run the playbook.
Ansible returns a confirmation of success when it completes the playbook's dry run. Note the verbose output, under "start and enable the Apache2 service" section. Because this is a dry run, the server isn't found on the host, but Ansible assumes it will be there on a full run of the playbook.
Clear the screen and run the command a second time in check mode. Ansible returns an identical output -- and will every time, as no changes are made to the system by the dry run.
Finally, remove the --check flag to follow through on the playbook's commands and make the change to the system. Note that the output has changed this time, and the playbook works.
Watch out for playbooks containing custom scripts within your tasks during an Ansible dry run. If you're using the Ansible 'shell' or 'command,' these common modules do not support check mode. Ansible will automatically skip them when performing a dry run. You can change this behavior by adding check mode: no in the tasks. Beware: With this setup, Ansible will make modifications to the target even when running in check mode.
Here's an example of using check mode: no in your tasks:
- name: this will make changes to the system even if you are running in check mode command: /must/run/this.sh check_mode: no - name: this will always run under check mode and not change the system lineinfile: line: "text in my file" dest: /path/to/myfile state: present check_mode: yes
Adding on to the already powerful check mode, use the --diff command simultaneously. With --diff, you can see additional output of what the playbook would change and not just a changed vs. OK set of results. With --diff, Ansible displays detailed change information output comparing the current state with the new state.
Example of using --diff and --check simultaneously:
ansible-playbook myplaybook.yml --check --diff
Dry runs are a fantastic tool to accelerate change testing, and can help provide confidence in playbook creation. However, take time when reviewing playbooks to confirm they're fully compatible with check mode before you run tasks in this mode, or you might make some unwanted changes.
Transcript - Try out an Ansible dry run in under 5 minutes
Hello, and welcome to this video.
I'm using Ansible check mode to perform a dry run of your Ansible playbooks. Just a quick general overview of our working environment: I do have a virtual machine running Ubuntu in Microsoft Azure. And then just a quick overview of the playbook that we're going to be running check mode against: This is going to update the App Cache on this Ubuntu server. And then it's also going to install the Apache HTTP server and service. Lastly, it's going to make sure that the service is set to 'enabled.' And the last file before we get into our dry run -- I just want to show you the credential file that I'm using; these other variables for my Ansible user.
Now we're ready to open up our terminal and run our dry run.
So let's open up our Ansible control server connection. Here I am SSHed into my Ansible server; I'm also in my project directory. And then I'm going to type in and run our playbook. That is going to be the Ansible playbook command: the YAML file; I'm going to specify that. And then here's the important part: Since I'm using an Ansible Vault encrypted string, I do need to ask for the vault password to unencrypt that. And then the most important bit here is the --check that is going to be and signify our dry run mode. I'm also going to use a 'verbose' flag so we can see some of that background information on how that check mode actually runs.
Let's run it.
Okay, and here, because I am using the Vault pass, I have to pop that in real quick, and then the playbook begins. Things to keep in mind: We're going to see here it is going to gather fat. So that is not something that gets ignored when you run a dry run, as well as this 'ping' command that I've instructed it to run -- that is still also going to run, even though we are in check mode. Be aware that some modules will still run while you're in this dry run mode. It's just not going to make any changes to the system.
With our dry run now completed, we can view the output. Right here it is saying in the recap that everything came back okay. So the syntax -- the tasks that we've configured and coded -- have all been successful. One of the key verbose outputs I want you to pay attention to here is under the "start and enable the Apache2 service" section. It does state that the Apache2 service was not found on the host, but it would assume it is on the full run.
So it knows that it's running in a check mode and it's not going to make that change, because it is in that check or dry run state. And just to showcase how powerful and repeatable this is by running dry runs while you're creating your code, we're going to run this again.
So here I've cleared our screen, we're going to run the command again. Also in check mode, put in my Vault password. And the nice part here is we're going to get the exact same output every time because we are not making changes to the system, we are just validating that the playbook that we're running would do what we expect. And here at the conclusion of our second dry run -- we can see that the output is identical to what we saw before. So there were no changes made to our destination system. This is exactly what we want out of our dry mode, because we're checking "did our playbook get coded correctly?"
And just in conclusion here, as we've run our dry mode successfully, the code is going to execute as we expect, let's remove that 'check' flag and no longer do a dry run. We're going to actually follow through with our playbook as if it was going to make changes to our destination system. Takes a couple of minutes here, but we will see that the output does change now that we've run this.
Here at the end of our non-dry run completing, we can see that there were changes made to the system. Namely: We did install the Apache2 service and that everything did still come back OK otherwise. And here I've cleared my console. We're going to run one more time just to show what happens when we run the playbook after it's already made the changes, but we're going to run the playbook again. I want to make sure that nothing's changed on the endpoint system. So we should see that everything comes back, OK, with the zero changes this time because nothing has been modified from the state that we expect. And that's exactly what we see here. So it's similar to a dry run, because we're going to check in that final configuration against what our playbook should have.
I hope this video has shown you the value of running a dry mode of your Ansible playbooks before you push that code to production.