简体   繁体   中英

Ansible Setting fact with dynamic key/value

I am trying to set ansible facts from the stdout of a command task I call from another role.

Role A:

- name: example command
  command: client get -s {{ service }}
  register: vars_string

- name: set vars
  set_fact: vars={{ vars_string.stdout.split('\n')}}
  when:
    - vars_string.stdout | length > 0

- name: set vars as facts
  set_fact: "{{ item }}"
  with_items: "{{ vars }}"

vars output:

"vars": [
        "tst=ansible", 
        "example=values"
]

Role B:

- debug:
    var: tst

Results from Role B:

Expectation: { "tst": "ansible" }

Reality: { "tst": "VARIABLE IS NOT DEFINED!" } { "tst": "VARIABLE IS NOT DEFINED!" }

I have tried to spit vars into a dict and use set_fact: "{{ item.key }}": "{{ item.value }}" as well. This returned the same results.

I want to be able to call by the variable name returned from the command in future roles. Any ideas?

Two points about your code snippet that may interest you:

  • There is already a split-by-newline version of the output from your command, it's vars_string.stdout_lines
  • I can't tell if you just chose that variable by accident, or you were trying to actually assign to the vars built-in variable, but either way, don't do that

As best I can tell, there is no supported syntax for assigning arbitrary top-level host facts from within just a task.

You have two choices: write out those variables to a file, then use include_vars: to read them in -- which will assign them as host facts, or concede to the way set_fact: wants things and be content with those dynamic variables living underneath a known key in hostfacts

We'll show the latter first, because it's shorter:

- set_fact:
    my_facts: >-
      {{ "{" + (vars_string.stdout_lines
      | map('regex_replace', '^([^=]+)=(.+)', '"\1": "\2"')
      | join(",")) + "}"
      }}
  when:
  - vars_string.stdout | length > 0

Of course, be aware that trickery won't work if your keys or values have non-JSON friendly characters in them, but if that simple version doesn't work, ask a follow-up question, because there are a lot more tricks in that same vein

The include_vars: way is:

- tempfile:
    state: file
    suffix: .json
  register: vars_filename

- copy:
    dest: '{{ vars_filename.path }}'
    content: >-
       {{ "{" + (vars_string.stdout_lines
       | map('regex_replace', '^([^=]+)=(.+)', '"\1": "\2"')
       | join(",")) + "}"
       }}

- include_vars:
    file: '{{ vars_filename.path }}'

- file:
    path: '{{ vars_filename.path }}'
    state: absent

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM