Ansible Variables: a Rookie Mistake

I have spent a few hours trying to find why my role applies patches to the wrong Oracle Home. The mistake I made could be excused for Java Developer, but not for a guy who spends days with Ansible.

The root cause is the different variable visibility model. Red Hat Ansible does not appreciate role or play boundaries and dynamically evaluates facts and variable values for each target. Let me illustrate  this with an example:

  • I have a playbook with two plays.
  • Each play select a different sub-set of patches, using product code
  • The role applies selected patches to the current oracle home.
  • Both plays target the same host.
  • Role derivates target Oracle Home using other variables defined in the call.

There is some Ansible code to illustrate the behavior

- name: Apply OHS Patches
  hosts: oim-cluster
  vars: 
    java_home: "/u01/app/product/jdk"
    mw_base: "/u01/app/product"
    mw_version: "12"
  tasks:
    - name: Apply Product patches:
      include_role: 
         name: oracle-patch
      vars: 
        product: "ohs" 
        oracle_home: "{{ mw_base }}/{{ product }}{{ mw_version }}"
        patch_id: "all" 
        
- name: Apply OIM Patches
  hosts: oim-cluster
  vars: 
    java_home: "/u01/app/product/jdk"
    mw_base: "/u01/app/product"
    mw_version: "12"
  tasks:
    - name: Apply Product patches:
      include_role: 
         name: oracle-patch
      vars: 
        product: "idm" 
        oracle_home: "{{ mw_base }}/{{ product }}{{ mw_version }}"
        patch_id: "all"
        
Two plays call the same role to upgrade oracle product

And now the mistake. The role oracle-patch had  an "internal" variable definition.

- name: Werdo Local variable declaration
  set_fact: 
     oh: "{{ oracle _home }}"
  when: oh is not defined    
Cod that lead to the error

The problem with the code above that it defines a fact. And it will be preserved over role calls, or different plays in the same playbook, as soon as they run on the same targets. On top of it, this task updates the fact only if the fact is new. So I eliminated a new fact definition and replaced it with the direct variable usage to fix the error.

It's time to go ahead and refresh my knowledge about variables and facts in Red Hat Ansible. If you have the same plans, I'd recommend starting with documentation and learn about variable usage and especially about variable precedencies.