looock7897
looock7897

Reputation: 27

Ansible write on file from jinja file

I want to lanch a application :

command=/usr/bin/toto --config /var/toto/conf1.json /var/toto/conf2.json /var/toto/conf3.json

the config file are on /var/toto directory

task.yml

- name: Ansible find file
  find:
    paths: "/var/toto"
  register: found_files

- name: print files
  debug:
    msg: "{{ found_files['files'] | map(attribute='path') | map('regex_replace','^.*/(.*)$','\\1') | list }}"
  register: file_name
 
- name: Create the Jinja2 based template
  template:
    src: "etc/control/config.conf.j2"
    dest: "/etc/control/config.conf"
  with_dict: "{{ file_name }}"

config.conf.j2

command=/usr/bin/toto --config {% for item in file_name %} /var/toto/{{ item }} {% endfor %}

but, I have get this on my file

/etc/control/config.conf

command=/usr/bin/toto --config  /var/opt/msg  /var/opt/failed  /var/opt/changed

varfile_name :

"msg": [                                                                                                                                                                        "conf1.json",                                                                                                                                                       "conf2.json",                                                                                                                                                          "conf3.json"                                                                                                                                                                                                                                                                                                               
]

Upvotes: 0

Views: 541

Answers (1)

larsks
larsks

Reputation: 311248

You're iterating over the dictionary in file_name, which is a task result. If you were to print that out, you would find that it contains something like:

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => {
    "file_name": {
        "changed": false,
        "failed": false,
        "msg": [
            "file1",
            "file2",
            "file3"
        ]
    }
}

So when you iterate over it using for item in file_name, you're iterating over the top level keys (changed, failed, msg).

But this is all the wrong way to do it. You never use the debug module to create variables; that's what set_fact is for. You want something like:

- name: build list of files
  set_fact:
    file_name: "{{ found_files['files'] | map(attribute='path') | map('regex_replace','^.*/(.*)$','\\1') | list }}"

- name: Create the Jinja2 based template
  template:
    src: "config.conf.j2"
    dest: "config.conf"

After the set_fact task, the variable file_name will contain a list of file names.


It looks like you're using that regular expression to get the basename of the files found in your find task. There's a basename filter that can do that with less complexity:

- name: print files
  set_fact:
    file_name: "{{ found_files['files'] | map(attribute='path') | map('basename') | list }}"

- name: Create the Jinja2 based template
  template:
    src: "config.conf.j2"
    dest: "config.conf"

Here's the playbook I'm using to test this locally:

- hosts: localhost
  gather_facts: true
  tasks:
    - name: find files
      find:
        paths: /tmp/example
      register: found_files

    - name: print files
      set_fact:
        file_name: "{{ found_files['files'] | map(attribute='path') | map('basename') | list }}"

    - name: Create the Jinja2 based template
      template:
        src: "config.conf.j2"
        dest: "config.conf"

Before running this, I run:

mkdir /tmp/example
touch /tmp/exampe/file{1,2,3}

This produces a config.conf file that looks like:

command=/usr/bin/toto --config  /var/toto/file3  /var/toto/file2  /var/toto/file1 

Upvotes: 1

Related Questions