Skip to content

Playbooks

In this lab you will run a playbook, check the syntax, and fix the syntax error.

Create Playbook

Copy the following playbook into your ansible playbook directory. This is normally found under your_home_directory/ansible/playbooks.

---
hosts: localhost
tasks:
    - name: "check if file1.txt exists"
      stat:
          path: /home/directoryA/file1.txt
      register: file_exists
    - name: "check if directoryB exists"
      stat:
          path: /home/directoryB
      register: path_exists
    - meta: end_play
      when: file_exists.stat.exists is False and path_exists.stat.exists == False
    - name: "create group userC"
      group:
          name: userC
          state: present
    - name: "create user userC"
      user:
          name: userC
          comment: userC
          group: userC
    - name: "copy file1.txt from directory A to directory B, re-own to userC, give r-xr--r-- permissions"
      copy:
          src: /home/directoryA/file1.txt
          dest: /home/directoryB
          owner: userC
          group: userC
          mode: 0544
...

Run Your Playbook

$ ansible-playbook example.yaml

Expected Output:

ERROR! Syntax Error while loading YAML.
  mapping values are not allowed in this context

The error appears to be in '/Users/user1/example/example.yaml': line 25, column 12, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

    - name: copy file1.txt from directory A to directory B, re-own to userC, give r-xr--r-- permissions
       copy:
           ^ here

Unfortunately, the response indicates that the system found a syntax error. Continue onto the next section to find out how to catch these errors before running a playbook.

Run Syntax Check and Dry Run

Without running a syntax check, open the example.yaml file and try to determine which lines have errors. There are only two issues, but they are not quick to find. Extrapolate the time taken for a five-hundred plus line ansible playbook, and syntax checking becomes much more palatable.

Syntax Checks

In the case for the code above, the syntax checker would have caught the indentation mistake. It validates that the yaml file follows the recommended standards and is formatted in a parsable manner. At the end of the command, append --syntax-check.

$ ansible-playbook example.yaml --syntax-check

Expected Output:

ERROR! Syntax Error while loading YAML.
  did not find expected '-' indicator

The error appears to be in '/Users/user1/example/example.yaml': line 25, column 6, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

    - name: copy file1.txt from directory A to directory B, re-own to userC, give r-xr--r-- permissions
     copy:
     ^ here

The syntax checker indicates a problem with the copy module. It now becomes obvious that an erroneous space interfered with the template. Open the file, and realign ‘copy’ with ‘name’.

After fixing the indentation error, run the syntax check again. It now shows no errors, but one issue remains which the syntax check is not registering. This is where a ‘dry run’ comes into play.

Dry Run

The next step is to go through a dry run to check and see if the playbook will execute successfully.

$ansible-playbook example.yaml --check

Expected Output:

ERROR! The conditional check 'file_exists.stat.exists is False and path_exists.stat.exists == False' failed. The error was: template error while templating string: no test named 'False'. String: {% if file_exists.stat.exists is False and path_exists.stat.exists == False %} True {% else %} False {% endif %}

The error appears to be in '/Users/user1/example/example.yaml': line 13, column 7, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

      register: path_exists
    - meta: end_play
      ^ here

The dry run indicates that the ‘when’ clause cannot interpret the ‘is’ comparison operator for a boolean object. Any number of small errors can cause the script to fail part way through. Open the yaml file and correct the mistake.

Bringing it Together

Before:

when: file_exists.stat.exists is False and path_exists.stat.exists == False
After:
when: file_exists.stat.exists == False and path_exists.stat.exists == False

A final execution of the script should return the following:

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [check if file1.txt exists] ***********************************************
ok: [localhost]

TASK [check if directoryB exists] **********************************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

You have successfully created and executed your first playbook. The next logical step is to add another play into the playbook. Add another inventory item such as system2, and perform a slightly altered variation of the above play. The options are endless.

Resources