Error running playbook that only affects one of the hosts

315 views Asked by At

I've recently started using more and more Ansible, and especially AWX, for simple repetitive tasks. Below is a playbook for downloading, installing and configuring logging via a Bash script. The script is for two hosts: Ubuntu 20.04 and CentOS 7.6, and for the latter, making some changes to SELinux is required.

The question is, why am I getting an error for the Ubuntu only and not the CentOS also?

Here is the playbook:

# Download an run Nagios Log Server configuration script
---
- name: nagios-log configure
  hosts: all
  remote_user: root
  tasks:
  
  - name: Distribution
    debug: msg="{{ ansible_distribution }}"

  - name: Download setup-linux.sh
    get_url: 
      url: http://10.10.10.10/nagioslogserver/scripts/setup-linux.sh
      validate_certs: no
      dest: /tmp/setup-linux.sh
      
  - name: Change script permission
    file: dest=/tmp/setup-linux.sh mode=a+x
      
  - name: Run setup-linux.sh
    shell: /tmp/setup-linux.sh -s 10.10.10.10 -p 5544
    register: ps
    failed_when: "ps.rc not in [ 0, 1 ]"
    
  - name: Install policycoreutils if needed
    yum: 
      name: 
        - policycoreutils
        - policycoreutils-python
      state: latest
    when: ansible_distribution == 'CentOS'
        
  - name: Check if policy file exists
    stat:
      path: /etc/selinux/targeted/active/ports.local
    register: result
    when: ansible_distribution == 'CentOS'

  - name: Check whether line exists
    find:
      paths: /etc/selinux/targeted/active/ports.local 
      contains: '5544'
    register: found
    when: result.stat.exists == True
    
  - name: Add SELinux policy exception if missing
    command: semanage port -a -t syslogd_port_t -p udp 5544
    when: found.matched > 0
    
  - name: Restart rsyslog
    systemd:
      name: rsyslog
      state: restarted
      enabled: yes

And here is the error output when running the playbook on AWX:

TASK [Check whether line exists] ***********************************************
fatal: [Ubuntu.domain.corp]: FAILED! => {"msg": "The conditional check 'result.stat.exists == True' failed. The error was: error while evaluating conditional (result.stat.exists == True): 'dict object' has no attribute 'stat'\n\nThe error appears to be in '/tmp/awx_154_1811rny6/project/nagios-log.yml': line 39, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - name: Check whether line exists\n    ^ here\n"}
ok: [Centos.domain.corp]

For reasons I can't comprehend, the CentOS server is fine, but the Ubuntu is getting a strange error that I don't understand. I've tried other methods to achieve the same logic as the when command.

1

There are 1 answers

1
toydarian On BEST ANSWER

You get this error, because you register the variable result in

  - name: Check if policy file exists
    stat:
      path: /etc/selinux/targeted/active/ports.local
    register: result
    when: ansible_distribution == 'CentOS'

But because of when: ansible_distribution == 'CentOS' this does not run on Ubuntu and therefor the variable result does not exist when running the playbook on Ubuntu.

To fix this (and run the task using result on CentOS only as well) you can change it to this:

  - name: Check whether line exists
    find:
      paths: /etc/selinux/targeted/active/ports.local 
      contains: '5544'
    register: found
    when:
    - ansible_distribution == 'CentOS'
    - result.stat.exists == True

  - name: Add SELinux policy exception if missing
    command: semanage port -a -t syslogd_port_t -p udp 5544
    when:
    - ansible_distribution == 'CentOS'
    - found.matched > 0

Or you can put all CentOS specific tasks in a block like this:

  - name: CentOS specific tasks
    block:
    - name: Install policycoreutils if needed
      yum: 
        name: 
          - policycoreutils
          - policycoreutils-python
        state: latest
    - name: Check if policy file exists
      stat:
        path: /etc/selinux/targeted/active/ports.local
      register: result
    - name: Check whether line exists
      find:
        paths: /etc/selinux/targeted/active/ports.local 
        contains: '5544'
      register: found
      when: result.stat.exists == True      
    - name: Add SELinux policy exception if missing
      command: semanage port -a -t syslogd_port_t -p udp 5544
      when: found.matched > 0
    when: ansible_distribution == 'CentOS'

Or you can put them in their own file and include that file. There are actually a lot of ways to do this.