ansibleansible-template

AnsibleUnsafeText object' has no attribute 'hostname'


I am receiving the below error if I use set_fact and {% if %} {% else %} statements in my playbook.

FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'hostname'. 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'hostname'\n\nThe error appears to be in '/runner/project/playbooks/Stack_Status.yml': line 148, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n    - name: Write report data\n      ^ here\n"}

The piece of code having issue is here:

- name: Set final stack version fact
      set_fact:
        stack_version: >
          {% if composer_stack is defined and composer_stack != 'Stack not deployed' %}
            {{ composer_stack }}
          {% elif fleet_agent_stack is defined and fleet_agent_stack != 'Stack not deployed' %}
            {{ fleet_agent_stack }}
          {% else %}
            V3 Stack not deployed
          {% endif %}

- name: Gather server report
      set_fact:
        server_report: >
          {
            "hostname": "{{ inventory_hostname }}",
            "stack_version": "{{ stack_version | default('N/A') }}"
          }

- name: Write report data
      shell: |
        echo "\"{{ server_report.hostname }}\",\"{{ server_report.stack_version }}\"" >> "{{ report_file }}"

I am expecting to either display the version of Composer if it is running, or print the version of Fleet-Manager and both are not running display, Stack is not deployed.


Solution

  • The error message says it already

    AnsibleUnsafeText object' has no attribute 'hostname'
    

    the string object is not a dictionary since with the given set_fact: server_report task only a string with YAML content was created.

    The minimal example playbook

    ---
    - hosts: example
      become: false
      gather_facts: false
    
      tasks:
    
      - set_fact:
          stack_version: >
            {% if composer_stack is defined and composer_stack != 'Stack not deployed' %}
            {{ composer_stack }}
            {% elif fleet_agent_stack is defined and fleet_agent_stack != 'Stack not deployed' %}
            {{ fleet_agent_stack }}
            {% else %}
            V3 Stack not deployed
            {% endif %}
    
      - set_fact:
          server_report: >
            {
               "hostname": "{{ inventory_hostname }}",
               "stack_version": "{{ stack_version | default('N/A') }}"
            }
    
      - name: Content of variable is
        debug:
          var: server_report | type_debug
    
      - name: Whereby it should be
        debug:
          var: server_report | from_yaml | type_debug
    
      - name: Now it is working
        debug:
          msg: "{{ ( server_report | from_yaml ).hostname | trim }}"
    
      - name: Even for
        debug:
          msg: "{{ ( server_report | from_yaml ).stack_version | trim }}"
    

    will result into an output of

    PLAY [example] *******************************
    
    TASK [set_fact] ******************************
    ok: [host.example.com]
    
    TASK [set_fact] ******************************
    ok: [host.example.com]
    
    TASK [Content of variable is] ****************
    ok: [host.example.com] =>
      server_report | type_debug: str
    
    TASK [Whereby it should be] ******************
    ok: [host.example.com] =>
      server_report | from_yaml | type_debug: dict
    
    TASK [Now it is working] *********************
      msg: host.example.com
    
    TASK [Even for] ******************************
    ok: [host.example.com] =>
      msg: V3 Stack not deployed
    

    Documentation Links