I have an ansible playbook that has created a file (/tmp/values.txt) in each server with the following content
1.1.1.1
2.2.2.2
3.3.3.3
4.4.4.4
5.5.5.5
And I have a conf file named etcd.conf in the /tmp/etcd.conf with the following content
and I need to substitute the value of each line from /tmp/values.txt, so /tmp/etcd.conf will look like this:
SELF_IP=1.1.1.1
NODE_1_IP=2.2.2.2
NODE_2_IP=3.3.3.3
NODE_3_IP=4.4.4.4
NODE_4_IP=5.5.5.5
Is there a way I can do this? I used the following lookup method but it only works in the controll server
- name: Create etcd.conf
template:
src: etcd.conf.j2
dest: /tmp/etcd.conf
vars:
my_values: "{{ lookup('file', '/tmp/values.txt').split('\n') }}"
my_vars: [SELF_IP, NODE_1_IP, NODE_2_IP, NODE_3_IP, NODE_4_IP]
my_dict: "{{ dict(my_vars|zip(my_values)) }}"
You can use the slurp: task to grab the content for each machine, or use command: cat /tmp/values.txt and then examine the stdout_lines of its register:-ed variable to achieve that same .split("\n") behavior (I believe you'll still need to use that .split call after | b64decode if you use the slurp approach)
What will likely require some massaging is that you'll need to identify the group (which may very well include all) of inventory hostnames for which that command will produce content, and then grab the hostvar out of them to get all values
Conceptually, similar to [ hostvars[hv].tmp_values.stdout_lines for hv in groups[the_group] ] | join("\n"), but it'll be tedious to write out, so I'd only want to do that if you aren't able to get it to work on your own
Related
How can I put the discovered values into loop variables so that they are on one line using Ansible task? I have now task like this
- name: Updating test.conf
lineinfile:
path: "/root/test.conf"
regexp: "test="
line: "test={{ hostvars[item]['ansible_env'].SSH_CONNECTION.split(' ')[2] }}"
state: present
with_nested:
- "{{groups['app']}}"
It needs that when invoking the job, it takes the IP addresses from the servers that are in the app group and puts them on a single line. Currently, it performs such a substitution twice with which they are replaced and finally there is only one address in the test parameter.
I need format after task like this:
test=1.1.1.1, 2.2.2.2
While jinja2 is heavily inspired from python, its does not allow you to do all the same operations. To join a list your would have to do something like:
- debug:
msg: "{{ myvar | join(',') }}"
vars:
myvar:
- foo
- bar
When in doubt, always use a simple playwook with a debug task to validate your jinja code.
so I'm using this simple playbook as an example:
- name: Show interfaces
junos_command:
commands:
- show interfaces
display: text
register: json_response
And I need to save json_response to a file:
- name: Saving logs to output
copy:
content: "{{ json_response.stdout }}"
dest: "./output.txt"
I know that json_response.stdout_lines has the real organized json, but when I save it, it comes ALL unindented, and if I use "json_response.stdout" it comes "indented" but he doesn't recognize '\n' as a breakline character, so I execute another task to replace \n to breakline. My problem here is, anyway I can save json_response variable in a correctly way? When I execute the playbook the debug var prints perfectly indented on my shell, but doesn't work for my output file.
Thanks.
You can try one of the formatting filters, e.g. like this:
- name: Saving logs to output
copy:
content: "{{ json_response.stdout | to_nice_json(indent=4) }}"
dest: "./output.txt"
More details and examples can be found in the Ansible Documentation.
I am relatively new to ansible.
I have a parameters.yml with something like this:
parameters:
stuff: bullshit
otherstuff: otherbullshit
domain_locale: domain.locale.test
domain_differentlocale1: domain.differentlocale1.test
domain_differentlocale2: domain.differentlocale2.test
domain_differentlocale3: domain.differentlocale3.test
uninteresting_stuff: uninteresting_bullshit
This file is in another directory, but I could also symlink it to be in defaults/main.yml. Doesn't matter.
What I would like to accomplish is grep somehow within an ansible task these domain.*.test values and use it as vars in another task with ansible. This other task would be to write it directly after 127.0.0.1 localhost in the same line in the /etc/hosts.
I am not even sure which of the modules to use in ansible. include_vars has no additional grep as I see it. set_fact does not read from a different file(can I combine it with a shell command? how?). lineinfile does not have a source and dest, so it is also limited to one file.
I also thought this post would help me: Ansible read multiple variables with same name from vars_file
but it does not need the grep part, I need.
Here you go:
---
- hosts: localhost
gather_facts: no
vars:
parameters:
stuff: bullshit
otherstuff: otherbullshit
domain_locale: domain.locale.test
domain_differentlocale1: domain.differentlocale1.test
domain_differentlocale2: domain.differentlocale2.test
domain_differentlocale3: domain.differentlocale3.test
uninteresting_stuff: uninteresting_bullshit
tasks:
- lineinfile:
dest: /tmp/test.txt
regexp: ^127.0.0.1
line: "127.0.0.1 localhost {{ parameters.values() | select('match','domain.*test') | list | join(' ') }}"
I have a playbook that registers three variables. I want to produce a CSV report of those three variables on all hosts in my inventory.
This SO answer suggests to use:
- local_action: copy content={{ foo_result }} dest=/path/to/destination/file
But that does not append to the csv file.
Also, I have to manually compose by comma separators in this case.
Any ideas on how to log (append) variables to a local file?
If you are wanting to append a line to a file rather than replace it's contents then this is probably best suited to the lineinfile module and utilising the module's ability to insert a line at the end of the file.
The equivalent task to the copy one that you used would be something like:
- name: log foo_result to file
lineinfile:
line: "{{ foo_result }}"
insertafter: EOF
dest: /path/to/destination/file
delegate_to: 127.0.0.1
Note that I've used the long hand for delegating tasks locally rather than local_action. I personally feel that the syntax reads a lot clearer but you could easily use the following instead if you prefer the more compact syntax of local_action:
- local_action: lineinfile line={{ foo_result }} insertafter=EOF dest=/path/to/destination/file
I am looking for something that would be similar to with_items: but that would get the list of items from a file instead of having to include it in the playbook file.
How can I do this in ansible?
I managed to find an easy alternative:
- debug: msg="{{item}}"
with_lines: cat files/branches.txt
Latest Ansible recommends loop instead of with_something. It can be used in combination with lookup and splitlines(), as Ikar Pohorský pointed out:
- debug: msg="{{item}}"
loop: "{{ lookup('file', 'files/branches.txt').splitlines() }}"
files/branches.txt should be relative to the playbook
Lets say you have a file like
item 1
item 2
item 3
And you want to install these items. Simply get the file contents to a variable using register. And use this variable for with_items. Make sure your file has one item per line.
---
- hosts: your-host
remote_user: your-remote_user
tasks:
- name: get the file contents
command: cat /path/to/your/file
register: my_items
- name: install these items
pip: name:{{item}}
with_items: my_items.stdout_lines
I am surprised that nobody mentioned the ansible Lookups, I think that is exactly what you want.
It reads contents that you want to use in your playbook but do not want to include inside the playbook from files, pipe, csv, redis etc from your local control machine(not from remote machine, that is important, since in most cases, these contents are alongside your playbook on your local machine), and it works with ansible loops.
---
- hosts: localhost
gather_facts: no
tasks:
- name: Loop over lines in a file
debug:
var: item
with_lines: cat "./files/lines"
with_lines here is actually loop with lines lookup, to see how the lines lookup works, see the code here, it just runs any commands you give it(so you can give it any thing like echo, cat etc), then split the output into lines and return them.
There are many powerful lookups, to get the comprehensive list, check out the lookup plugins folder.