Vikram Ranabhatt
Vikram Ranabhatt

Reputation: 7620

The error was: 'dict object' has no attribute 'ansible_facts

I am iterating over yml file and filtering and keeping those microservice metadata in the list which is in the command line argument passed

ansible-playbook -i inventory/inventory sp-deployer.yml --ask-vault-pass --extra-vars '{"microservices_list":[iwan,csrservice]}'

Finally I need these three value from the yml file based on the criteria mentioned above. I have created ansible sp-deployer.yml for this purpose. I have used set_facts for creating dynamic list. First list works fine but the moment I create second one it fails.

name: "ms_service"
port: "830"
streams: "noti,jk-noti"

vars.yml

    version: 1
    name: user
    jobs:
      ns1:
        ip: "1.1.1.1"
        ns_version: "4.2"
        f_packs:
          - f-pack-1:
            name: "pack1"
            microservices:
            - microservice-1:
              name: "ms_service"
              port: "830"
              streams: "noti,jk-noti"
            - microservice-2:
              name: "ms_service1"
              port: "830"
              streams: "noti1,jk-noti1"
          - f-pack-2:
            name: "pack4"
            microservices:
            - microservice-1:
              name: "ms_service3"
              port: "830"
              streams: "noti,jk-noti3"
            - microservice-2:
              name: "ms_service4"
              port: "830"
              streams: "noti,jk-noti4"
            - microservice-3:
              name: "ms_service5"
              port: "830"
              streams: "noti,jk-noti5"

Script:sp-deployer.yml

    ---
- hosts: localhost
  vars_files:
    - ./vars.yml
  sudo: yes
  tasks:

  - name: Reading vars.yml file and preparing list of microservice with its metadata
    set_fact: foo_item="{{ item.1 }}"
    register: result    
    with_subelements:
     - "{{ jobs.ns1.f_packs }}"   ###item.0
     - microservices       ###item.1

  - name: make first list
    set_fact: foo="{{ result.results | map(attribute='ansible_facts.foo_item') | list }}"

  - name: print register
    debug: msg="{{ item }}" verbosity=3
    with_items:    
      - "{{ foo }}"

  - name: Filtering micro service list with match found from command line input
    when: item[0].name == item[1]
    set_fact: foo_item1="{{ item.0 }}"
    register: result_final    
    with_nested:
      - "{{ foo }}"
      - "{{ microservices_list }}"
  - name: make a list
    set_fact: foo1="{{ result_final.results | map(attribute='ansible_facts.foo_item1') | list }}"

ERROR

TASK [make a list] *************************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'dict object' has no attribute 'ansible_facts'\n\nThe error appears to have been in '/home/user/ansible/sp-deployer1.yml': line 40, 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: make a list\n    ^ here\n"}
    to retry, use: --limit @/home/user/ansible/sp-deployer1.retry

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=1   

Upvotes: 0

Views: 16789

Answers (1)

Konstantin Suvorov
Konstantin Suvorov

Reputation: 68239

Friendly advice: always check registered variables with debug if you bump on such errors.

The reason for your error is that set_fact don't yield ansible_facts dict if the loop iteration is skipped.
And I see you have when statement in your loop.

To overcome this error, you should select only those loop iterations, that have ansible_facts dict defined:

- name: make a list
  set_fact: foo1="{{ result_final.results | selectattr('ansible_facts','defined') | map(attribute='ansible_facts.foo_item1') | list }}"

Upvotes: 6

Related Questions