Samselvaprabu
Samselvaprabu

Reputation: 18187

How to include files one by one using dictionary key in ansible?

I am trying to invoke test cases one by one from ansible. Each test case is written in a yml file.

---
- hosts: localhost
  tasks:

  - set_fact:
      k8s_tests: 
        san-1.yml: "Scale replica to 1"
        san-2.yml: "Scale replica to 2"

  - name: display local tests
    debug: var=k8s_tests

  - include: "{{ k8s_test_item }}"
    vars:
      local_test: "{{ k8s_test_item }}"
    with_items: "{{ k8s_tests }}"
    loop_control:
      loop_var: k8s_test_item

When i execute it , the order of the file is wrong. The include should be running in the order of san-1.yml first then san-2.yml but it was opposite.

TASK [include] *********************************************************************************
included: /root/oc310/jenkinsrun/containers/K8S/san-2.yml for localhost
included: /root/oc310/jenkinsrun/containers/K8S/san-1.yml for localhost

So i added dictsort to sort the dictionary.

- include: "{{ k8s_test_item }}"
    vars:
      local_test: "{{ k8s_test_item }}"
    with_items: "{{ k8s_tests | dictsort }}"
    loop_control:
      loop_var: k8s_test_item 

but it tries to include both key and value and fails.

TASK [include] *********************************************************************************
included: /root/oc310/jenkinsrun/containers/K8S/san-1.yml for localhost
fatal: [localhost]: FAILED! => {"reason": "Could not find or access '/root/oc310/jenkinsrun/containers/K8S/Scale replica to 1' on the Ansible Controller."}
included: /root/oc310/jenkinsrun/containers/K8S/san-2.yml for localhost
fatal: [localhost]: FAILED! => {"reason": "Could not find or access '/root/oc310/jenkinsrun/containers/K8S/Scale replica to 2' on the Ansible Controller."}

The values 'Scale replica to 1' and 'Scale replica to 2' are not files and they should not be included. I tried to sort by key but still it tries to include based on value as well and fails.

- include: "{{ k8s_test_item }}"
    vars:
      local_test: "{{ k8s_test_item }}"
    with_items: "{{ k8s_tests | dictsort(false,'key') }}"
    loop_control:
      loop_var: k8s_test_item

below is the same output

TASK [include] *********************************************************************************
included: /root/oc310/jenkinsrun/containers/K8S/san-1.yml for localhost
fatal: [localhost]: FAILED! => {"reason": "Could not find or access '/root/oc310/jenkinsrun/containers/K8S/Scale replica to 1' on the Ansible Controller."}
included: /root/oc310/jenkinsrun/containers/K8S/san-2.yml for localhost
fatal: [localhost]: FAILED! => {"reason": "Could not find or access '/root/oc310/jenkinsrun/containers/K8S/Scale replica to 2' on the Ansible Controller."}

I need to include the file in order one by one. How to achieve this?

Upvotes: 0

Views: 131

Answers (1)

Zeitounator
Zeitounator

Reputation: 44730

Here is a solution to make sure your file names are always sorted correctly. You need to:

  • Transform your dictionary to a list with the dict2items filter
  • Extract only the key attribute for each element in the list with the map filter
  • sort the resulting list

Below is an implementation with a debug to show each described steps.

Notes:

  • I had to reverse the order in var declaration to get the same initial result as yours and have a successful demo
  • loop is the new keyword for defining loops and is equivalent here to with_list. See loop documentation
---
- name: Looping demo
  hosts: localhost
  gather_facts: false

  vars:
    k8s_tests:
      san-2.yml: "Scale replica to 2"
      san-1.yml: "Scale replica to 1"

  tasks:
    - name: Show initial var
      debug:
        var: k8s_tests

    - name: Show transforming dict to list
      debug:
        msg: "{{ k8s_tests | dict2items }}"

    - name: Show attribute extraction
      debug:
        msg: "{{ k8s_tests | dict2items | map(attribute='key') | list }}"

    - name: Show final sorted result
      debug:
        msg: "{{ k8s_tests | dict2items | map(attribute='key') | sort }}"

    - name: Actually looping over the data
      debug:
        var: item
      loop: "{{ k8s_tests | dict2items | map(attribute='key') | sort }}"

Upvotes: 1

Related Questions