Reputation: 37
I have a vars data type file:
foo:
foo_root_path: faaa
foo_dest_path: baa
bar:
bar_root_path: xyz
bar_dest_path: wxy
baz:
baz_root_path: abc
baz_dest_path: def
I have a playbook which prompts user to see the type of data I am getting, if it is a foo
, a bar
or a baz
.
I am creating a role to check if vars prompt == foo
then access values in foo
and use them to execute a copy command.
I am new to Ansible and trying to understand
What I have now is this, where for every when condition I am repeating my commands but I want to use loops and conditionals:
role:
when: "'foo' == {{ data_type }}"
- name: move foo data from source to destination
copy:
src: '{{ foo_root_path }}/{{ name }}'
dest: '{{foo_destination_path}}'
owner: foo
group: foo
mode: '0644'
when: "'bar' == {{ type }}"
- name: move bar
copy:
src: '{{ bar_root_path }}/{{ name }}'
dest: '{{bar_destination_path}}'
owner: bar
group: bar
mode: '0644'
when: "'baz' == {{ type }}"
- name: move baz
copy:
src: '{{ baz_root_path }}/{{ name }}'
dest: '{{baz_destination_path}}'
owner: baz
group: baz
mode: '0000'
What I want to achieve is to use conditionals to find out what the vars prompt is and then access the vars section to do the copy command once substituting the params from vars file instead of three commands.
Upvotes: 1
Views: 1346
Reputation: 39314
You can use the vars
lookup in order to achieve such a task.
Note that all variables, accessible to that host are accessible via that lookup, might there be from play variables, task variable, inventory variable or imported via var_files
, the syntax stays the same.
This ables you to look for a variable based on a variable, for example:
lookup('vars', type)
Would give you the dictionary
foo_root_path: faaa
foo_dest_path: baa
When type
is foo
.
And since your type is also part of your dictionary keys, you will also need to use the tilde symbol ~
, which is the concatenation operator in Jinja:
"{{ type ~ '_root_path' }}"
Would give you the string
foo_root_path
When type
is foo
.
So given the playbook:
- hosts: all
gather_facts: no
vars:
foo:
foo_root_path: faaa
foo_dest_path: baa
bar:
bar_root_path: xyz
bar_dest_path: wxy
baz:
baz_root_path: abc
baz_dest_path: def
vars_prompt:
- name: type
prompt: "What variable type do you want to use?"
private: no
pre_tasks:
- assert:
that: lookup('vars', type, default='') | length
tasks:
- debug:
msg:
root_path: "{{ lookup('vars', type)[type ~ '_root_path'] }}"
dest_path: "{{ lookup('vars', type)[type ~ '_dest_path'] }}"
Here are some runs of it:
What variable type do you want to use?: foo
PLAY [all] *******************************************************************************************************
TASK [assert] ****************************************************************************************************
ok: [localhost] => {
"changed": false,
"msg": "All assertions passed"
}
TASK [debug] *****************************************************************************************************
ok: [localhost] => {
"msg": {
"dest_path": "baa",
"root_path": "faaa"
}
}
PLAY RECAP *******************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
What variable type do you want to use?: bar
PLAY [all] *******************************************************************************************************
TASK [assert] ****************************************************************************************************
ok: [localhost] => {
"changed": false,
"msg": "All assertions passed"
}
TASK [debug] *****************************************************************************************************
ok: [localhost] => {
"msg": {
"dest_path": "wxy",
"root_path": "xyz"
}
}
PLAY RECAP *******************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
assert
module defined as pre_tasks
.default=''
if the variable is undefined, otherwise, the vars
lookup will error, as prompted in the documentation.length
, via the Jinja filter, would evaluate to false
, if the string happens to be empty, making length
return 0
, otherwise, if it is a dictionary, the length
would be a value > 0
and so, evaluate to true
.
What variable type do you want to use?: evil
PLAY [all] *******************************************************************************************************
TASK [assert] ****************************************************************************************************
fatal: [localhost]: FAILED! => {
"assertion": "lookup('vars', type, default='') | length",
"changed": false,
"evaluated_to": false,
"msg": "Assertion failed"
}
PLAY RECAP *******************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
So adapting all this to your case gives this playbook:
- hosts: all
gather_facts: no
vars:
name: file.ext
foo:
foo_root_path: faaa
foo_dest_path: baa
bar:
bar_root_path: xyz
bar_dest_path: wxy
baz:
baz_root_path: abc
baz_dest_path: def
vars_prompt:
- name: type
prompt: "What variable type do you want to use?"
private: no
pre_tasks:
- assert:
that: lookup('vars', type, default='') | length
tasks:
- name: "Move {{ type }} data from source to destination"
copy:
src: "{{ lookup('vars', type)[type ~ '_root_path'] }}/{{ name }}"
dest: "{{ lookup('vars', type)[type ~ '_dest_path'] }}"
owner: "{{ type }}"
group: "{{ type }}"
mode: "0644"
Upvotes: 2