skip to Main Content

having an ansible playbook that will run on all hosts including Debian based & RedHat based servers
this will install mariadb on RHEL based servers only doing some configuration changes, start the service once the service started handlers are used to change the root password but the problem is handlers seems to be applied on all the hosts instead of RHEL based servers only, when statement is not working with handlers, check the following code:


---

  - name: "Install & Configure MariaDB server on RHEL8"
    hosts: all
    vars:
      required_distribution: "RedHat"
      required_version: "8"

      my_packages:
        - mariadb-server
        - python3-PyMySQL
    tasks:
      - name: "check & install MariaDB on RHEL 8 only"
        yum:
          name: "{{ item }}"
          state: present
        loop: "{{ my_packages }}"
        when: "ansible_distribution == required_distribution and ansible_distribution_major_version == required_version"

      - name: "start & enable MariaDb service"
        service:
          name: mariadb
          state: started
          enabled: true
        when: "ansible_distribution == required_distribution and ansible_distribution_major_version == required_version"
        notify:
          - root_password

    handlers:
      - name: root_password
        mysql_user:
          name: root
          password: password
        when: "ansible_distribution == required_distribution and ansible_distribution_major_version == required_version"

getting this warning:

RUNNING HANDLER [root_password] ****************************************************************************************************************************************************
task path: /home/student/labs/lab6/lab6.yaml:29
[WARNING]: Module did not set no_log for update_********
changed: [server-b] => {"changed": true, "msg": "Password updated (new style)", "user": "root"}
changed: [server-a] => {"changed": true, "msg": "Password updated (new style)", "user": "root"}
changed: [server-d] => {"changed": true, "msg": "Password updated (new style)", "user": "root"}
changed: [server-c] => {"changed": true, "msg": "Password updated (new style)", "user": "root"}
META: ran handlers
META: ran handlers

what I am considering here is the handler is also applying on ubuntu-a server & giving me "[WARNING]: Module did not set no_log for update_**"

if this warning is not coming from ubuntu-a server then how to remove this and what’s the issue in my playbook, is this only applied on RHEL based servers on handlers as well?

I am also looking for some effective way of writing the playbook so that each time I don’t have to write when block to filter out my managed hosts it must be checked once (may be at play level) and will apply on all tasks

2

Answers


  1. Given the inventory

    shell> cat hosts
    host_A
    host_B
    
    [test_ubuntu]
    host_A ansible_host=10.1.0.184
    
    [test_ubuntu:vars]
    ansible_connection=ssh
    ansible_user=admin
    ansible_become=yes
    ansible_become_user=root
    ansible_become_method=sudo
    ansible_python_interpreter=/usr/bin/python3.9
    
    [test_centos]
    host_B ansible_host=10.1.0.74
    
    [test_centos:vars]
    ansible_connection=ssh
    ansible_user=admin
    ansible_become=yes
    ansible_become_user=root
    ansible_become_method=sudo
    ansible_python_interpreter=/bin/python3.6
    


    Q: "Effective way of writing the playbook to filter out my managed hosts."

    A: Use inventory plugin constructed. See

    shell> ansible-doc -t inventory ansible.builtin.constructed
    
    1. Cache the facts. Configure cache, e.g.
    shell> cat ansible.cfg
    [defaults]
    gathering = smart
    fact_caching = jsonfile
    fact_caching_connection = /tmp/ansible_cache
    fact_caching_prefix = ansible_facts_
    fact_caching_timeout = 86400
    ...
    

    and run the playbook

    shell> cat pb2.yml
    - hosts: all
      tasks:
        - debug:
            msg: Completed.
    

    This will create the cache

    shell> tree /tmp/ansible_cache/
    /tmp/ansible_cache/
    ├── ansible_facts_host_A
    └── ansible_facts_host_B
    
    1. Create the inventory
    shell> tree inventory/
    inventory/
    ├── 01-hosts
    └── 02-constructed.yml
    
    0 directories, 2 files
    
    shell> cat inventory/01-hosts 
    host_A
    host_B
    
    [test_ubuntu]
    host_A ansible_host=10.1.0.184
    
    [test_ubuntu:vars]
    ansible_connection=ssh
    ansible_user=admin
    ansible_become=yes
    ansible_become_user=root
    ansible_become_method=sudo
    ansible_python_interpreter=/usr/bin/python3.9
    
    [test_centos]
    host_B ansible_host=10.1.0.74
    
    [test_centos:vars]
    ansible_connection=ssh
    ansible_user=admin
    ansible_become=yes
    ansible_become_user=root
    ansible_become_method=sudo
    ansible_python_interpreter=/bin/python3.6
    
    shell> cat inventory/02-constructed.yml 
    plugin: ansible.builtin.constructed
    strict: true
    groups:
      centos_8: ansible_distribution == 'CentOS' and ansible_distribution_major_version == '8'
      ubuntu_20: ansible_distribution == 'Ubuntu' and ansible_distribution_major_version == '20'
    

    Test the inventory

    shell> ansible-inventory -i inventory --graph
    @all:
      |--@centos_8:
      |  |--host_B
      |--@test_centos:
      |  |--host_B
      |--@test_ubuntu:
      |  |--host_A
      |--@ubuntu_20:
      |  |--host_A
      |--@ungrouped:
    

    You can see that the plugin constructed created groups centos_8 and ubuntu_20.

    1. Use the groups in a play. For example,
    shell> cat pb3.yml
    - hosts: centos_8
    
      tasks:
    
        - setup:
            gather_subset: distribution
        - debug:
            msg: |
              ansible_distribution: {{ ansible_distribution }}
              ansible_distribution_major_version: {{ ansible_distribution_major_version }}
    
        - debug:
            msg: Trigger handler
          changed_when: true
          notify: root_password
    
      handlers:
    
        - name: root_password
          debug:
            msg: Change root password
    

    gives

    shell> ansible-playbook -i inventory pb3.yml 
    
    PLAY [centos_8] ******************************************************************************
    
    TASK [setup] *********************************************************************************
    ok: [host_B]
    
    TASK [debug] *********************************************************************************
    ok: [host_B] => 
      msg: |-
        ansible_distribution: CentOS
        ansible_distribution_major_version: 8
    
    TASK [debug] *********************************************************************************
    changed: [host_B] => 
      msg: Trigger handler
    
    RUNNING HANDLER [root_password] **************************************************************
    ok: [host_B] => 
      msg: Change root password
    
    PLAY RECAP ***********************************************************************************
    host_B: ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    


    Q: "The handler is also applying on Ubuntu."

    A: In your code, there is no reason for this. For example, given the data

      required_distribution: "CentOS"
      required_version: "8"
    

    the tasks

        - setup:
            gather_subset: distribution
        - debug:
            msg: |
              ansible_distribution: {{ ansible_distribution }}
              ansible_distribution_major_version: {{ ansible_distribution_major_version }}
    

    give

    ok: [host_A] => 
      msg: |-
        ansible_distribution: Ubuntu
        ansible_distribution_major_version: 20
    ok: [host_B] => 
      msg: |-
        ansible_distribution: CentOS
        ansible_distribution_major_version: 8
    

    Your condition works as expected

        - debug:
            msg: |
              ansible_distribution is {{ required_distribution }} and
              ansible_distribution_major_version is {{ required_version }}
          when: "ansible_distribution == required_distribution and ansible_distribution_major_version == required_version"
    

    gives

    skipping: [host_A]
    ok: [host_B] => 
      msg: |-
        ansible_distribution is CentOS and
        ansible_distribution_major_version is 8
    

    You don’t have to quote the condition

          when: ansible_distribution == required_distribution and ansible_distribution_major_version == required_version
    

    You can format it

          when: ansible_distribution == required_distribution and
                ansible_distribution_major_version == required_version
    

    , or even better

          when:
            - ansible_distribution == required_distribution
            - ansible_distribution_major_version == required_version
    

    All options give the same result.

    Test the handler. There is no reason to put the condition into the handler when the condition is in the task that will trigger it

      handlers:
    
        - name: root_password
          debug:
            msg: Change root password
    

    The task below will trigger the handler for required_distribution and required_version only

        - debug:
            msg: Trigger handler
          changed_when: true
          notify: root_password
          when:
            - ansible_distribution == required_distribution
            - ansible_distribution_major_version == required_version
    

    gives

    TASK [debug] *********************************************************************************
    skipping: [host_A]
    changed: [host_B] => 
      msg: Trigger handler
    
    RUNNING HANDLER [root_password] **************************************************************
    ok: [host_B] => 
      msg: Change root password
    
    PLAY RECAP ***********************************************************************************
    


    • Example of a complete playbook for testing
    - hosts: all
      gather_facts: false
    
      vars:
    
        required_distribution: "CentOS"
        required_version: "8"
    
      tasks:
    
        - setup:
            gather_subset: distribution
        - debug:
            msg: |
              ansible_distribution: {{ ansible_distribution }}
              ansible_distribution_major_version: {{ ansible_distribution_major_version }}
    
        - debug:
            msg: |
              ansible_distribution is {{ required_distribution }} and
              ansible_distribution_major_version is {{ required_version }}
          when: "ansible_distribution == required_distribution and ansible_distribution_major_version == required_version"
    
        - debug:
            msg: |
              ansible_distribution is {{ required_distribution }} and
              ansible_distribution_major_version is {{ required_version }}
          when: ansible_distribution == required_distribution and ansible_distribution_major_version == required_version
    
        - debug:
            msg: |
              ansible_distribution is {{ required_distribution }} and
              ansible_distribution_major_version is {{ required_version }}
          when: ansible_distribution == required_distribution and
                ansible_distribution_major_version == required_version
    
        - debug:
            msg: |
              ansible_distribution is {{ required_distribution }} and
              ansible_distribution_major_version is {{ required_version }}
          when:
            - ansible_distribution == required_distribution
            - ansible_distribution_major_version == required_version
    
        - debug:
            msg: Trigger handler
          changed_when: true
          notify: root_password
          when:
            - ansible_distribution == required_distribution
            - ansible_distribution_major_version == required_version
    
      handlers:
    
        - name: root_password
          debug:
            msg: Change root password
    
    • The tree of this project
    shell> tree .
    .
    ├── ansible.cfg
    ├── hosts
    ├── inventory
    │   ├── 01-hosts
    │   └── 02-constructed.yml
    ├── pb2.yml
    ├── pb3.yml
    └── pb.yml
    
    1 directory, 7 files
    

    Login or Signup to reply.
  2. I don’t think that message indicates the handler is running on Ubuntu, but it’s hard to say without seeing your inventory and other more info.

    Anyways, if you want to only apply when "when" once (good impulse, you have two options:

    1. Put all of your tasks in a "block" and apply the when to the block. You shouldn’t even need then when on the handler if all of the tasks are skipped using the same when.

    2. If what you really want is to bail on the play altogether on non RedHat 8 hosts, you could use end_host like this, as the first task in your play.

    # Example showing how to end the play for specific targets
    - name: End the play for hosts are not the desired versions
      ansible.builtin.meta: end_host
      when: ansible_distribution != required_distribution or ansible_distribution_major_version != required_version
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search