I tried this one
---
- name: py
hosts: master
tasks:
- name:
command: /home/vagrant/test.py
register: csvfile
changed_when: false
- debug:
var: csvfile
- name: Create csvfile directories
file:
path: "/tmp/{{ item.host }}_{{ item.app }}"
state: directory
with_dict: "{{ csvfile }}"
Test.py results are:
{'key': 'stdout_lines', 'value': ["{'host': '123', 'app': 'abc'}", "{'host': '2345', 'app': 'def'}", "{'host': '8484', 'app': 'ghju'}", "{'host': '89393', 'app': 'yruru'}"]}
and i'm getting error at "/{{ item.host }}_{{ item.app }}"
Can someone help me?
The registered variable csvfile must have the attribute stdout_lines
csvfile:
stdout_lines:
- {'host': '123', 'app': 'abc'}
- {'host': '2345', 'app': 'def'}
- {'host': '8484', 'app': 'ghju'}
- {'host': '89393', 'app': 'yruru'}
The simple loop should do the job
- name: Create csvfile directories
file:
path: "/tmp/{{ item.host }}_{{ item.app }}"
state: directory
loop: "{{ csvfile.stdout_lines }}"
The key/value decomposition was added very probably by with_dict. Please confirm, update and fix the question. Post the output of the task
- debug:
var: csvfile
There are a bunch of things wrong, so while this is an "answer" because it is too big to fit into a comment here on S.O., it is not the fix to your problem because there is so much wrong with your code.
As your debug output demonstrates, the register: captures the output of the whole task, and not just the output from your program. Thus, at the very least you would need with_dict: "{{ csvfile.stdout }}" but that, too, will not work because the output is not an interoperability format that ansible can use. Just because it is written in python and your script is written in python does not mean they can communicate
You will need to have the test.py call json.dump or json.dumps on the results, and not just print() or repr or whatever it is calling now, so that the output can be parsed by ansible back into an actual data structure in your playbook
Then, what happens next depends on whether you continue to write out each dictionary from test.py on a per-line basis, or you choose to package them all into a list of dictionaries and dump that as JSON
Start by fixing the output from test.py to be parseable by ansible, and we'll go from there
Sumanth, you can try the same approach but using with_items:
- name: Create csvfile directories
file:
path: "/tmp/{{ item.host }}_{{ item.app }}"
state: directory
with_items: "{{ csvfile.stdout_lines }}"
Related
I have a two main variable with subvariables. The main variable VELABx and VELABy match the ansible_hostnames. Following an example of the variables mentioned:
VELABx
location: "text1.1"
initialism: "text1.2"
VELABy
location: "text2.1"
initialism: "text2.2"
Now I'd like to run a task which replaces a regexp with the location variable based on the current ansible_hostname. So, I tried this code, but it leads into an error.
- name: Replace location for VELABx
replace:
dest: "/path/to/file"
regexp: 'location'
replace: "{{ {{ansible_hostname}}.location }}"
remote_user: rssuser
become: no
when: ansible_hostname == "VELABx"
What am I doing wrong? How can I solve this? Can anyone bring up a solution?
Things are always easier when you manage to create a proper structure of data. For example, given the dictionaries in a file
shell> cat velab.yml
VELABx:
location: "text1.1"
initialism: "text1.2"
VELABy:
location: "text2.1"
initialism: "text2.2"
you can include the data from the file into a dictionary, e.g.
- hosts: VELABx,VELABy,VELABz
tasks:
- include_vars:
file: velab.yml
name: velab
run_once: true
- debug:
var: velab
run_once: true
gives
velab:
VELABx:
initialism: text1.2
location: text1.1
VELABy:
initialism: text2.2
location: text2.1
The data you provided in the question are not YAML dictionaries. The colon is missing behind the keys. Either fix it, if you can or parse the file. Anyway, create the dictionary whatever is the source.
Then, given the files
shell> ssh admin#10.1.0.61 cat /tmp/velab.txt
location
shell> ssh admin#10.1.0.62 cat /tmp/velab.txt
location
shell> ssh admin#10.1.0.63 cat /tmp/velab.txt
location
the task to replace the location is simple
- name: Replace location for VELAB*
replace:
dest: /tmp/velab.txt
regexp: location
replace: "{{ velab[inventory_hostname]['location'] }}"
when: velab[inventory_hostname] is defined
gives
shell> ansible-playbook playbook.yml -CD
PLAY [VELABx,VELABy,VELABz] ******************************************
...
TASK [Replace location for VELAB*] ***********************************
skipping: [VELABz]
--- before: /tmp/velab.txt
+++ after: /tmp/velab.txt
## -1 +1 ##
-location
+text1.1
changed: [VELABx]
--- before: /tmp/velab.txt
+++ after: /tmp/velab.txt
## -1 +1 ##
-location
+text2.1
changed: [VELABy]
The next option is to remove the condition and use the default value, instead of skipping the host, when the host is missing in the dictionary
- name: Replace location for VELAB*
replace:
dest: /tmp/velab.txt
regexp: location
replace: "{{ velab[inventory_hostname]['location']|
default(default_location) }}"
vars:
default_location: "text99.1"
you must use loopkup, {{}} inside other {{}} is incorrect
---
- hosts: localhost
gather_facts: false
vars:
ansible_hostname: VELABx
VELABx:
location: "text1.1"
initialism: "text1.2"
VELABy:
location: "text2.1"
initialism: "text2.2"
tasks:
- name: DEBUG
debug:
msg: "{{ lookup('vars', ansible_hostname ).location }}"
- name: Replace location for VELABx
replace:
dest: "/path/to/file"
regexp: 'location'
replace: "{{ lookup('vars', ansible_hostname ).location }}"
when: ansible_hostname == "VELABx"
I have included the below variable file in my playbook:
more vars/was_vars.yaml
::::::::::::::
10.9.12.112: "/was/IBM/WebSphere"
10.8.10.28: "/was/IBM/profiles"
10.7.120.129: "/app/tmp"
Here is my playbook:
- name: Configure nodes
hosts: dest_nodes
user: "{{ USER }}"
tasks:
- name: Construct File Path on "{{ inventory_hostname }}".
command: "touch {{ BASEPATH }}/{{ ( item | splitext)[1] }}/del.tmp"
when: "{{ Layer == 'APP' }}"
file: path="{{ "{{ inventory_hostname }}" }}/{{ App_List }}/{{ Rel_Path }}/del.tmp state=directory mode=u=rwx,g=rw,o=r"
when: "{{ Layer == 'WAS' }}"
"{{ inventory_hostname }}" gets substituted with "10.9.12.112" which should then get further substituted to "/was/IBM/WebSphere" as stated in the included vars("was_vars.yaml") file.
I'm getting the below Syntax error with my current code:
ERROR! conflicting action statements: command, file
The error appears to be in '/app/Ansible/deploy.yml': line 133, column 4, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
tasks:
- name: Construct File Path on "{{ inventory_hostname }}".
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
I'm on the latest version on ansible.
Can you please suggest?
1) The dash is missing in front of the file module.
2) Nested expansion is not possible (wrong: "{{ "{{ inventory_hostname }}" }}").
3) when: condition is expanded by default.
4) The whole string shall be quoted when the expansion of a variable is included.
5) The index of the expansion {{ ( item | splitext)[1] }} wont work.
6) It's not clear where do the variable item and the filter splitext come from.
The correct syntax might be
tasks:
- name: "Construct File Path on {{ inventory_hostname }}."
command: "touch {{ BASEPATH }}/{{ item|splitext|first }}/del.tmp"
when: Layer == 'APP'
- file:
path: "{{ inventory_hostname }}/{{ App_List }}/{{ Rel_Path }}/del.tmp"
state: directory
mode: "u=rwx,g=rw,o=r"
when: Layer == 'WAS'
(not tested)
Thank you for the inputs but what we are actually looking for is how to get the expansion to work...
I.e the inventory_hostname would be substituted with host ip say 10.9.12.112 ... But how do we code to get "/was/IBM/WebSphere" substituted matching the IP from the included variable file?
Can you try as :
"{{vars[inventory_hostname]}}"
or if you want one more level use as :
"{{vars[vars[inventory_hostname]]}}"
I am new to ansible and am trying to use variables from a vars.yml file in a playbook.yml file.
vars.yml
---
- firstvar:
id: 1
name: One
- secondvar:
id: 2
name: two
playbook.yml
---
- hosts: localhost
tasks:
- name: Import vars
include_vars:
file: ./vars.yml
name: vardata
- name: Use FirstVar
iso_vlan:
vlan_id: "{{ vardata.firstvar.id }}"
name: "{{ vardata.firstvar.name }}"
state: present
- name: Use Secondvar
iso_vlan:
vlan_id: "{{ vardata.secondvar.id }}"
name: "{{ vardata.secondvar.name }}"
state: present
So you can see here I am treating the imported variable data, which is stored in vardata, as object and trying to call each of them in other tasks. I am pretty sure these imported vars at the first task are only available in that very task. How can I use that in other tasks? It would output as variables undefined for each tasks. Any input is appreciated.
Your vars.yml file isn't formatted correctly.
Try this:
---
firstvar:
id: 1
name: One
secondvar:
id: 2
name: two
I used this to test it:
---
- hosts: localhost
tasks:
- name: Import vars
include_vars:
file: ./vars.yml
name: vardata
- name: debug
debug:
msg: "{{ vardata.firstvar.name }}"
- name: more debug
debug:
msg: "{{ vardata.secondvar.id }}"
On top of the error you made when declaring the variables (syntax is very important), you can also define include_vars: ./vars.yml such that you can just call {{ firstvar.name }}, {{ firstvar.id }} immediately. Much more leaner/shorter.
im trying to create 2 archives out of 2 folders by using archive module.
Unfortunately it´s not working without any error.
My tasks looks like this:
tasks:
- name: create a tarball of logfiles
archive:
path: "{{ item.path }}"
dest: /tmp/{{ ansible_hostname }}_{{ item.name }}_{{ ansible_date_time.date }}.tar.gz
register: ausgabe
with_items:
- { name: 'xxxxxx', path: '/opt/jira/xxx/xxxxxx' }
- { name: 'xxxxxxx', path: '/opt/jira/xxxx/xxxxxxx' }
Output:
TASK [create a tarball of logfiles] ************************************************************************************************************************************************
ok: [xxxxxxx] => (item={u'path': u'/opt/jira/xxx/xxxx', u'name': u'xxxxx'})
ok: [xxxxxxx] => (item={u'path': u'/opt/jira/xxx/xxxx', u'name': u'xxxxxx'})
The tar.gz files are not created.
Can somebody help me on this?
Thx
Harry
Whenever you are using variables or 'templating' your playbook make sure that you use " (inverted-commas) properly.
I have modified your archive module's statements and I got the required result.
archive:
dest: "/tmp/{{ ansible_hostname }}_{{ item.name }}_{{ ansible_date_time.date }}.tar.gz"
path: "{{ item.path }}"
Output:
myHost_xxxxxx_2018-06-12.tar.gz
myHost_xxxxxxx_2018-06-12.tar.gz
My requirement is that I want to dynamically include a variable file in my Ansible script. I can do that by putting following in my ansible task-
- name: Include vars file
include_vars: vars/dev.yml
- name: Some other task
cp: copy something
Above works if I keep the dev.yml in my vars directory. Now I actually do not want to put the dev.yml in the directory, I want to pull it from S3 and then use the variable in it. Something like below-
- name: Get dev file
s3:
bucket: bucket_name
object: object_name
dest: "dest_directory" ## Here I want the destination to be vars/dev.yml
mode: get
aws_access_key: "{{ s3.aws_access_key }}"
aws_access_key: "{{ s3.aws_secret_key }}"
- name: Include vars file
include_vars: vars/dev.yml
- name: Some other task that uses vars in dev.yml
template: render some template using vars in dev.yml and copy to server
The above will actually not work. How do I do this?
Thanks Konstantin Suvorov for help. I just needed to add delegate_to in my task.
- name: Get dev file
s3:
bucket: bucket_name
object: object_name
dest: vars/dev.yml
mode: get
aws_access_key: "{{ s3.aws_access_key }}"
aws_access_key: "{{ s3.aws_secret_key }}"
delegate_to: localhost
- name: Include vars file
include_vars: vars/dev.yml