user9624894
user9624894

Reputation: 23

Variable won't be filtered correctly

what am I doing wrong? I use below task to get all defined log_dirs of a host. Those information are stored in a fact, which is a dict and this works like a charm.

- name: get all_log_dirs
  set_fact:
    all_log_dirs="{{ (all_log_dirs|default({})) | combine( { item.key:vars[item.key] } ) }}"
  with_dict: "{{ vars }}"
  when: item.key is search('^((?!splunk).)*_log_dir')

Here the appropriate output:

 "ansible_facts": {
     "all_log_dirs": {
        "springboot_server_log_dir": "{{ server_deployment_dir }}/logs"}

But the problem is, if I now want to use the new dict for e. g.:

- name: create symlink for splunk if not present
  file:
    src: "{{ item.value }}"
    dest: "{{ splunk_log_dir }}/{{ item.key | regex_replace('_server_log_dir|_log_dir') | regex_replace('eap','jboss-eap') }}"
    state: link
  with_dict: "{{ all_log_dirs }}"

I only get:

failed: [...] (item={'value': u'{{ server_deployment_dir }}/logs', 'key': u'springboot_server_log_dir'}) => {
"changed": false,
"invocation": {
    "module_args": {
        "dest": "/somedir/springboot",
        "path": "/somedir/springboot",
        "src": "{{ server_deployment_dir }}/logs",
        "state": "link",
    }
},
"msg": "src file does not exist, use \"force=yes\" if you really want to create the link: /somedir/{{ server_deployment_dir }}/logs",
"path": "/somedir/springboot",
"src": "{{ server_deployment_dir }}/logs",
"state": "absent"

}

Why isn't {{ server_deployment_dir }} filtered correctly by Ansible? Even I change src to dest and the way around, it won't work, because the variable isn't being filtered.

The value of {{ server_deployment_dir }} is of course host specific and is sth like /opt/applicationXY/appDeployDir

Upvotes: 2

Views: 83

Answers (1)

Konstantin Suvorov
Konstantin Suvorov

Reputation: 68269

Don't use vars object. Period.

It is internal variable storage intended for under-the-hood usage.

When Ansible template engine detects vars access, it stops further templating chain!

Example:

---
- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    myvar1: hello
    myvar2: world
    myvar3: "{{ myvar2 }}"
  tasks:
    - debug:
        msg: "{{ myvar1 }} {{ myvar3 }}"
    - debug:
        msg: "{{ vars['myvar1'] }} {{ vars['myvar3'] }}"

Result:

TASK [debug] ***************************
ok: [localhost] => {
    "msg": "hello world"
}

TASK [debug] ***************************
ok: [localhost] => {
    "msg": "hello {{ myvar2 }}"
}

Update: if you utterly need to access variable trough vars object, there's vars lookup available in Ansible 2.5; and it templates values as usual:

E.g.

- debug:
    msg: "{{ lookup('vars','myvar1') }} {{ lookup('vars','myvar3') }}"

results to hello world in the context of my previous example.

Upvotes: 2

Related Questions