Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
818 views
in Technique[技术] by (71.8m points)

yaml - Ansible to get the dict like values from a file to the playbook or loop

I am looking for a way to get the value from a text, yaml or json file while going through loop.

My code is working as i'm Iterating over a list of hashes with loop but the problem is when i'll have multiple entries to be Iterate over that's why i want to place all these values into a file and then call them in the task/playbook rather than writing bunch of line into the play.

Please suggest or help to get it through..

Below is the working code:

---
- hosts: localhost
  gather_facts: no

  vars:
    config: "{{ playbook_dir }}/{{ config_file }}"
    contents: "{{lookup('file', config)}}"
    server_profile_template: 'Test_apc_SY 480 Gen10 2 NVMe Application Template 20190601 V1.0'
    server_hardware: "SY 480 Gen9 1"
    template_name: []
    server_list: []

  tasks:
    - name: Create server profile
      oneview_server_profile:
        config: "{{ config }}"
        data:
          serverProfileTemplateName: "{{ server_profile_template }}"
          serverHardwareName: "{{ item.Bay }}"
          name: "{{ item.Profilename }}"
        params:
          force: True
      loop:
        - { Bay: "ENT0005, bay 11", Profilename: "test_profile01" }
        - { Bay: "ENT0005, bay 12", Profilename: "test_profile02" }

      delegate_to: localhost
      register: result

    - debug: msg= "{{ result }}"
    - debug: msg= "{{ result.msg }}"

...

What is intended:

$ cat bayfile.yml
---

-  'Bay: "ENT0005, bay 11", Profilename: "test_profile01"'
-  'Bay: "ENT0005, bay 12", Profilename: "test_profile02"'

...

What i tried:

loop: "{{ lookup('file', '{{ bayfile.yml }}') }}"

But above not working.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You're headed in the right direction, but there are a couple of issues:

Bad YAML syntax in your datafile.

In your example, you show:

-  'Bay: "ENT0005, bay 11", Profilename: "test_profile01"'
-  'Bay: "ENT0005, bay 12", Profilename: "test_profile02"'

That's a list of strings (because you have each list item enclosed in single quotes). If you want to reproduce the data you've shown in your playbook, you want a list of dictionaries. You probably want this instead:

- Bay: "ENT0005, bay 11"
  Profilename: "test_profile01"

- Bay: "ENT0005, bay 12"
  Profilename: "test_profile02"

The following is identical, just using a slightly different syntax:

- {Bay: "ENT0005, bay 11", Profilename: "test_profile01"}
- {Bay: "ENT0005, bay 12", Profilename: "test_profile02"}

Nested jinja2 template markers

You never nest {{...}} markers; you only need the outermost set...everything inside is already in a Jinja template context. Rather than:

loop: "{{ lookup('file', '{{ bayfile.yml }}') }}"

You would write:

loop: "{{ lookup('file', 'bayfile.yml') }}"

Convert data to YAML

Lastly, when you use a file lookup like that, the result is simply a string (the contents of the file). You want to de-serialize that into Ansible data structures, so you'll need the from_yaml filter:

loop: "{{ lookup('file', 'bayfile.yml')  | from_yaml }}"

Putting that all together, we get something like this:

- hosts: localhost
  gather_facts: false

  tasks:
    - name: Create server profile
      debug:
        msg:
          - "{{ item.Bay }}"
          - "{{ item.Profilename }}"
      loop: "{{ lookup('file', 'bayfile.yml') | from_yaml }}"

Using include_vars

Note that instead of using the file lookup and the from_yaml filter, you could use an include_vars task in your playbook. You would first need to reformat your datafile so that it's a dictionary instead of a list, like this:

oneview_servers:
  - Bay: "ENT0005, bay 11"
    Profilename: "test_profile01"

  - Bay: "ENT0005, bay 12"
    Profilename: "test_profile02"

And then you could write your playbook like this:

- hosts: localhost
  gather_facts: false

  tasks:
    - name: Read data
      include_vars:
        file: bayfile.yml
        name: data

    - name: Create server profile
      debug:
        msg:
          - "{{ item.Bay }}"
          - "{{ item.Profilename }}"
      loop: "{{ data.oneview_servers }}"

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...