What is the correct way of going about doing this: I have a task with the shell module that exports a var from the Bash shell.
Can I access said var from another task (maybe setting environment?) without having to register command output and parse shellvar_register.stdout?
Does Ansible scope an ansible_env for localhost and remote host?
---
- name: test var play
hosts: localhost
tasks:
- name: export shell var
become: no
local_action: shell export shellvar=foo
args:
executable: /bin/bash
#register: shellvar_register
- name: print debug msg
local_action:
module: debug
msg: "{{ ansible_env.shellvar }}"
% ansible-playbook playbooks/test/test_shellvar.yml
PLAY [test var play] ***
TASK [Gathering Facts] ***
ok: [localhost]
TASK [export shell var] ***
changed: [localhost -> localhost]
TASK [print debug msg] ***
fatal: [localhost]: FAILED! => {"msg": "The task includes an option
with an undefined variable. The error was: 'dict object' has no
attribute
'shellvar'\n\nThe error appears to be in '/home/robert/tmp/common.git
/playbooks/test/test_shellvar.yml': line 12, column 5, but may\nbe
elsewhere in the file depending on the exact syntax problem.\n\nThe
offending line appears to be:\n\n\n - name: print debug msg\n ^
here\n"}
to retry, use: --limit #/home/robert/tmp/common.git/playbooks
/test/test_shellvar.retry
PLAY RECAP ***
localhost: ok=2 changed=1 unreachable=0 failed=1 skipped=0
c.f. https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#registering-variables
Your shell exits when the task is over. Just capture the value as an ansible value for later uses.
- name: set a var
command: 'echo foo'
register: not_a_shell_var
- name: show it
debug:
msg: "{{ not_a_shell_var.stdout }}"
you could use set_fact like in Ansible: Store command's stdout in new variable? and set a new ansible variable, which you can use in other plays too.
- hosts: loc
tasks:
- name: set a ansible variable for later use
set_fact:
new_ansible_var: "foo"
- name: run a command with this var
shell: "shellvar={{ new_ansible_var }} {{ playbook_dir }}/bash_script_using_shellvar.sh"
The first task sets the ansible_variable. The second task takes this variable for shellvar, so the bashscript can use shellvar.
Related
I'm very new with ansible so I need help to complete my first ansible playbook
I need to get the results from file created below logs directory.
I also need to input container name which is migrated to find results file named with container and starts with 1 and 3 (2 results of files need)
can't find which part got wrong.
Please help me out
Thank you in advance.
---
- name : find the results for migration ended
hosts: newmigservers
tasks:
- pause:
prompt: "what is the container name?"
echo: yes
register: result
- set_fact:
container: "{{ result.user_input }}"
- debug:
var: container
- name: find where the container is
shell: "grep -lr '{{ container }}'"
args:
chdir: "logs/"
register: grep_output
- name: cat 1,3 file for the results
command: cat {{ grep_output }}
register: results
PLAY [find the results for migration ended] *************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [1.1.1.1]
ok: [2.2.2.2]
ok: [3.3.3.3]
TASK [pause] ********************************************************************************************************************************************************************************************************************************
[pause]
what is the container name?:
ok: [1.1.1.1]
TASK [set_fact] *****************************************************************************************************************************************************************************************************************************
ok: [1.1.1.1]
fatal: [2.2.2.2]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'result' is undefined\n\nThe error appears to have been in '/home/amber/results.yml': line 9, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n register: result\n - set_fact:\n ^ here\n"}
fatal: [3.3.3.3]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'result' is undefined\n\nThe error appears to have been in '/home/amber/results.yml': line 9, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n register: result\n - set_fact:\n ^ here\n"}
TASK [debug] ********************************************************************************************************************************************************************************************************************************
ok: [1.1.1.1] => {
"container": "amber_test_file_size.txt"
}
TASK [find where the container is] **********************************************************************************************************************************************************************************************************
skipping: [2.2.2.2]
TASK [cat 1,3 file for the results] *********************************************************************************************************************************************************************************************************
skipping: [3.3.3.3.]
to retry, use: --limit #/home/amber/results.retry
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
1.1.1.1 : ok=4 changed=0 unreachable=0 failed=0
2.2.2.2 : ok=1 changed=0 unreachable=0 failed=1
3.3.3.3 : ok=1 changed=0 unreachable=0 failed=1
Pause runs only once for the play batch, causing only the first server in the batch (1.1.1.1 in my case) to pick the variable.
You can workaround this by adding serial to your playbook as below:
---
- name : find the results for migration ended
hosts: newmigservers
serial: 1
tasks:
- pause:
prompt: "what is the container name?"
echo: yes
register: result
- set_fact:
container: "{{ result.user_input }}"
- debug:
var: container
I'm facing a mysterious ansible behaviour.
I've set groups, hosts and groups vars in my inventory file, but the ansible-playbook command is raising Undefined Variable for all my group vars, while printing them with the ansible debug module show the variable well.
Here is my inventory.ini file:
[windows]
ad_server ansible_host=mrspw00550.mydomain.com
[windows:vars]
ansible_connection=winrm
ansible_winrm_transport=ntlm
ansible_port=5985
ansible_become_method=runas
dns_zone=mydomain.com
ptr_zone=10.in-addr.arpa
dns_server=10.0.100.100
[linux]
web_server ansible_host=10.0.101.129
[linux:vars]
ansible_connection=ssh
ansible_become=yes
ansible_become_method=sudo
dns_zone=mydomain.com
ptr_zone=10.in-addr.arpa
dns_server=10.0.100.100
linux_home_dir=/home/ldaphome
the playbook file (set-hostname-and-dns.yml):
- name: Debug vars
debug: var=hostvars[inventory_hostname]['dns_zone']
delegate_to: ad_server
- name: Set hostname and make DNS registrations
block:
- name: Set hostname
hostname:
name: "web.{{ dns_zone }}"
delegate_to: web_server
- name: Create a DNS registration of type A
win_dns_record:
name: "web"
type: "A"
value: "{{ inventory_hostname }}"
zone: "{{ dns_zone }}"
computer_name: "{{ dns_server }}"
delegate_to: "{{ ad_server }}"
- name: Create a DNS registration of type PTR
win_dns_record:
name: "{{ inventory_hostname }}"
type: "PTR"
value: "web"
zone: "{{ ptr_zone }}"
computer_name: "{{ dns_server }}"
delegate_to: "{{ ad_server }}"
Running the ansible-playbook command gives :
$ ansible-playbook playbook.yml -i inventory-files/inventory.ini
PLAY [localhost] *********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [localhost]
TASK [create-linux-vm : Debug vars] **************************************************************************************************************************************************************************
ok: [localhost -> mrspw00550.mydomain.com] => {
"hostvars[inventory_hostname]['dns_zone']": "VARIABLE IS NOT DEFINED!"
}
TASK [create-linux-vm : Set web_server hostname] **************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dns_zone' is undefined\n\nThe error appears to be in 'set-hostname-and-dns.yml': line 14, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n block:\n - name: Set {{ vm_name }} hostname\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"}
PLAY RECAP ***************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Running debug module:
$ ansible -m debug -i inventory-files/inventory.ini -a "var=hostvars[inventory_hostname]['dns_zone']" all
ad_server | SUCCESS => {
"hostvars[inventory_hostname]['dns_zone']": "mydomain.com"
}
web_server | SUCCESS => {
"hostvars[inventory_hostname]['dns_zone']": "mydomain.com"
}
$
So as you can see, ansible-playbook command is unable to retrieve my host vars, while ansible debug module does.
The result is the same even if I define those variables in inventory-files/group_vars/linux.yml or inventory-files/group_vars/windows.yml, the variable is still as undefined by ansible. The problem is the same if try to access any other variable than special variables from inventory running ansible-playbook
What could be wrong there?
I tried with delegate_facts set to true, it didn't work.
Then defined a local group in the inventory containing localhost and defined my local group vars there like this :
[local]
localhost
[local:vars]
ansible_connection=local
dns_zone=mydomain.com
ptr_zone=10.in-addr.arpa
dns_server=10.0.100.100
linux_home_dir=/home/ldaphome
and remove those var from remote hosts facts, as I don't really those variables there. All my tasks are executed on the localhost and delegated to the remote hosts depending to the action.
I'd also like to precise that specifically ask for var/fact like #Zeitounator mentioned above ({{ hostvars['ad_server'].ptr_zone }}) in his comment works too.
*****************************[UPDATE]***************************************
I want to edit a script with Ansible. ✔ SOLVED
I found the replace module but in my attempt to run the playbook I get an error. ✔ SOLVED
I want for each value that passes to the variable "result" to do something different. ✘ UNSOLVED
- name: Automation of a job in DataStage
hosts: dshost
vars_prompt:
- name: project
prompt: 'Enter the project'
private: no
- name: j0b
prompt: 'Enter the job'
private: no
tasks:
- name: Copying file script to modify then
copy:
src: /home/ansible/Downloads/script.sh
dest: /home/dsadm/script.sh
- name: Replaces the variables that we've passed
replace:
path: /home/dsadm/script.sh
regexp: '{{ item.regexp1 }}'
replace: '{{ item.replace }}'
backup: yes
with_items:
- { regexp1: 'project', replace: '{{ project }}' }
- { regexp1: 'j0b', replace: '{{ j0b }}' }
- name: Running the script
command: sh /home/dsadm/script.sh
register: result
- name: Check if the script is executed correctly
debug:
msg: "The file script was executed without errors"
when: result.stdout == "\r\nStatus code = 0 \r\n"
The script :
#!/bin/bash
cd /opt/IBM/InformationServer/Server/DSEngine/
. ./dsenv
$DSHOME/bin/dsjob -run project j0b
rtn=$?
**************(UPDATE)********* The output is :
sudo ansible-playbook testJob.yml
[sudo] password for ansible:
Enter the project: dstage1
Enter the job: limits
PLAY [Automation of a job in DataStage] ****************************************************
TASK [Gathering Facts] *********************************************************************
ok: [172.16.2.112]
TASK [Copying file script to modify then] **************************************************
changed: [172.16.2.112]
TASK [Replaces the variables that we've passed] ********************************************
changed: [172.16.2.112] => (item={u'regexp1': u'project', u'replace': u'dstage1'})
changed: [172.16.2.112] => (item={u'regexp1': u'j0b', u'replace': u'limits'})
TASK [Running the script] ******************************************************************
changed: [172.16.2.112]
TASK [Check if the script is executed correctly] *******************************************
skipping: [172.16.2.112]
PLAY RECAP *********************************************************************************
172.16.2.112 : ok=4 changed=3 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
UPDATE 04/07/2019
How can I achive that my playbook to does what I want depending on the variable result?
Correct syntax is
- name: Step one
hosts: xxx.xx.x.xxx
vars_prompt:
...
This is the reason for the error
"ERROR! the field 'hosts' is required but was not set"
I'm trying to find the UUID of a VM based on it's hostname. I'm not sure what is missing in my syntax here, but I've tried several different methods. Here is the sample playbook I'm working with currently:
---
- name: Test taking snapshot by UUID
hosts: tst000.company.com
vars_files:
- vars/credentials.yml
tasks:
- name: Gather all registered virtual machines
vmware_vm_facts:
hostname: 'vcenter.company.com'
username: '{{ vcenter.username }}'
password: '{{ vcenter.password }}'
validate_certs: False
delegate_to: localhost
register: vmfacts
- debug:
var: vmfacts.virtual_machines.{{ ansible_facts['hostname'] }}.uuid
- set_fact:
vm_uuid: "{{ lookup('vars', 'vmfacts.virtual_machines.' + ansible_facts['hostname'] + '.uuid') }}"
Results are as follows:
Identity added: /opt/tmp/awx_2507_ithHYD/credential_3
(/opt/tmp/awx_2507_ithHYD/credential_3) Vault password:
PLAY [Test taking snapshot by UUID]
********************************************
TASK [Gathering Facts]
********************************************************* ok: [tst000.company.com]
TASK [Gather all registered virtual machines]
********************************** ok: [tst000.company.com -> localhost]
TASK [debug]
******************************************************************* ok: [tst000.company.com] => {
"vmfacts.virtual_machines.tst000.uuid": "421d2491-8896-e52f-e4f5-5118687ce0e9" }
TASK [set_fact]
**************************************************************** fatal: [tst000.company.com]: FAILED! => {"msg": "The task
includes an option with an undefined variable. The error was: No
variable found with this name:
vmfacts.virtual_machines.tst000.uuid\\n\\nThe error appears to
have been in '/var/lib/awx/projects/quick-stuff/test_snapshot.yml':
line 21, column 7, but may\\nbe elsewhere in the file depending on the
exact syntax problem.\\n\\nThe offending line appears to be:\\n\\n\\n
- set_fact:\\n ^ here\\n"}
PLAY RECAP
********************************************************************* tst000.company.com : ok=3 changed=0 unreachable=0
failed=1
In the debug and set_fact modules, you can see that the ansible_facts['hostname]' properly places the hostname as needed, however, it returns the proper value in the debug module, but is claiming there is no variable found by that name in the set_fact module. I'm not sure what is wrong with my syntax here.
There's no need to use the lookup in that way, since vars and its hostvars friend are effectively dicts:
- set_fact:
vm_uuid: "{{ vmfacts.virtual_machines[ansible_facts['hostname']].uuid }}"
Using Ansible, to host server(172.19.113.104) I want to copy files ( ansibletest & MariaDB-client-5.1.67-122.el5.x86_64.rpm ) from remote server(172.19.113.87), but it should not copy if file exist already.
I tried like below but throwing error:
- hosts: webservers
vars:
ip: 172.19.113.87
tasks:
- name: this is to pull
local_action: shell 'ls /opt/ansibletest'
register: result
- name: ts2
synchronize: src={{ item }} dest=/opt/ mode=pull
with_items:
- "/opt/ansibletest"
- "/opt/MariaDB-client-5.1.67-122.el5.x86_64.rpm"
when: result.shell.exists == true
[root#rbtstaging ansible]# ansible-playbook fetch.yml
PLAY [webservers] ************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************
ok: [172.19.113.87]
TASK [this is to pull] *******************************************************************************************************************************************
changed: [172.19.113.87]
TASK [ts2] *******************************************************************************************************************************************************
fatal: [172.19.113.87]: FAILED! => {"msg": "The conditional check 'result.stat.exists == True' failed. The error was: error while evaluating conditional (result.stat.exists == True): 'dict object' has no attribute 'stat'\n\nThe error appears to have been in '/RND/sudhir/ansible/fetch.yml': line 9, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: ts2\n ^ here\n"}
to retry, use: --limit #/RND/sudhir/ansible/fetch.retry
PLAY RECAP *******************************************************************************************************************************************************
172.19.113.87 : ok=2 changed=1 unreachable=0 failed=1
Note: Files exist with permission
You can prepend the fetch (fetch file from remote server - copy will send the file to the remove server) by a local "stat" operation, and check for existence of the local file.
local_action:
module: stat
path: /path/to/local/file
register: local_file
become: no
fetch:
src: /path/to/remote/file
dest: /path/to/local/file
flat: yes
when: local_file.stat.exists == False