Sheldon
Sheldon

Reputation: 179

ansible: specifying directory path using variable

My Task: Generate jinja2 templates

Challenge: i wanted to make my playbook/roles independent, and usable in any server irrespective of their HOME directory name, So i have stored the $HOME path into a variable and use that directory location variable to access jinja2 source files.. $HOME stored variable works fine in all tasks, but i am getting error while i use it inside template module"

my role structure..

roles/
└── my_role
    ├── defaults
    │   ├── main
    │   │   └── input.yml
    │   └── main.yml
    ├── files
    │   ├── conf
    │   │   └── test.yml
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   ├── data-input.yml
    │   ├── main.yml
    ├── templates
    │   ├── DIR1
    │   │   ├── PATH1
    │   │   │   ├── file1
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        ├── main
        │   └── input.yml
        └── main.yml

and my task for generating jinja2 templates..

---
  - include_vars: vars/main/input.yml

  - name: Generate templates
    template:
        src: {{ home }}/roles/my_role/templates/DIR1/PATH1/file1
        dest: {{ home }}/roles/my_role/templates/DIR1/PATH1/file2

{{ home }} stands for /home/ansible that i have stored it to name home using $HOME linux variable.

Getting Error:

ERROR! Syntax Error while loading YAML.
  did not find expected key

The error appears to be in '/home/ansible/roles/my_role/tasks/data_input.yml': line 6, column 24, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

    template:
        src: {{ home }}/roles/my_role/templates/DIR1/PATH1/file1
                       ^ here

i have even tried templates/DIR1/PATH1/file1 directory only. but no luck. It works fine when i specify full directory path /home/ansible/roles/my_role/templates/DIR1/PATH1/file1 in both src and dest..

please help.

thanks in advance..

Upvotes: 2

Views: 11688

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68104

Use env plugin to "read the value of environment variables". For example

- set_fact:
    my_home: "{{ lookup('env','HOME') }}"
- template:
    src: "{{ my_home }}/roles/my_role/templates/DIR1/PATH1/file1"


Notes

1) It's possible to use role_path special variable

"The path to the dir of the currently running role"

For example

src: '{{ role_path }}/templates/DIR1/PATH1/file1'

2) But, this shouldn't be necessary because of The magic of ‘local’ paths

"Relative paths get attempted first with a ‘files|templates|vars’ appended (if not already present), depending on the action being taken, ‘files’ is the default. (i.e include_vars will use vars/). The paths will be searched from most specific to most general (i.e role before play).|

Hence, the path below show work by default

src: 'DIR1/PATH1/file1'

For example the role

$ tree roles/test14/
roles/test14/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
│   └── DIR1
│       └── PATH1
│           └── file1
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

$ cat roles/test14/tasks/main.yml 
- template:
    src: 'DIR1/PATH1/file1'
    dest: '/scratch/tmp/test14'

$ cat roles/test14/templates/DIR1/PATH1/file1 
{{ inventory_hostname }}

with the playbook

$ cat test14.yml
- hosts: localhost
  roles:
    - test14

works as expected

PLAY RECAP localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

$ cat /scratch/tmp/test14 
localhost

Upvotes: 3

Zeitounator
Zeitounator

Reputation: 44675

Rule: In an ansible yaml files (included, in roles, your playbook....), values containing jinja2 template expressions and starting with "{{" MUST be enclosed in quotes.

Good practice: Enclose any string containing jinja2 template expression in quotes.

=>

        src: "{{ home }}/roles/my_role/templates/DIR1/PATH1/file1"
        dest: "{{ home }}/roles/my_role/templates/DIR1/PATH1/file2"

Upvotes: 4

Related Questions