I have ansible installed on the Windows Subsystem for Linux. This version is 2.9.6.
I also have an ansible tower that is version 3.7.2 which has Ansible version 2.9.27.
I basically use the ansible installation on my WSL to play with and debug playbooks to get them working. Once they are working, I upload them to my Git Repository and pull them into the Ansible Tower for execution.
I am still fairly new to Ansible so perhaps this is a very simple issue. I have a playbook that runs just fine on my ansible (2.9.6) WLS environment.
When I run the same playbook in my Ansible Tower, it doesn't run any tasks.
The playbook is fairly simple. I want to use it to change the password on a local Windows account. The playbook is in a file named change_user_password.yml. The contents are shown below:
- name: Change user password
hosts: all
tasks:
- name: Include OS-specific variables.
include_vars: "{{ ansible_os_family }}.yml"
- name: Print OS Family
debug:
msg: "Ansible OS family is {{ ansible_os_family }}"
- name: Print uname
debug:
msg: "Uname variable is {{ uname }}"
- name: Print newpass
debug:
msg: "Newpass variable is {{ newpass }}"
- name: Change pwd (Redhat).
ping:
when: ansible_os_family == 'RedHat'
- name: Change pwd (Debian).
ping:
when: ansible_os_family == 'Debian'
- name: Change pwd (Windows).
win_user:
name: "{{ uname }}"
password: "{{ newpass }}"
when: ansible_os_family == 'Windows'
When run on the command line with ansible-playbook in my WSL environment I pass in the --extra-vars for uname and newpass variables as shown below:
ansible-playbook -i ../hosts.ini --limit cssvr-prod change_user_password.yml --extra-vars="uname=myadmin newpass=test1234TEST"
Output typically looks like this:
PLAY [Change user password] ***************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************
ok: [cssvr-prod]
TASK [Include OS-specific variables.] *****************************************************************************************************************************************************************
ok: [cssvr-prod]
TASK [Print OS Family] ********************************************************************************************************************************************************************************
ok: [cssvr-prod] => {
"msg": "Ansible OS family is Windows"
}
TASK [Print uname] ************************************************************************************************************************************************************************************
ok: [cssvr-prod] => {
"msg": "Uname variable is myadmin"
}
TASK [Print newpass] **********************************************************************************************************************************************************************************
ok: [cssvr-prod] => {
"msg": "Newpass variable is test1234TEST"
}
TASK [Change pwd (Redhat).] ***************************************************************************************************************************************************************************
skipping: [cssvr-prod]
TASK [Change pwd (Debian).] ***************************************************************************************************************************************************************************
skipping: [cssvr-prod]
TASK [Change pwd (Windows).] **************************************************************************************************************************************************************************
changed: [cssvr-prod]
PLAY RECAP ********************************************************************************************************************************************************************************************
cssvr-prod : ok=6 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
When I run this playbook from Ansible Tower, I add uname and newpass as extra variables in the Extra Variables box on the Template for this play. I add the cssvr-prod host in the Limit box. When I run it, no tasks are run. NOTE: The warning below is expected, the inventory and groups are imported from Azure. Some of our Azure resource groups have hyphens in their name which apparently is illegal in the ansible hosts file as a group name.
Using /etc/ansible/ansible.cfg as config file
SSH password:
[WARNING]: Invalid characters were found in group names but not replaced, use
-vvvv to see details
PLAY [all] *********************************************************************
PLAY RECAP *********************************************************************
I'm pulling what little hair I have left out trying to figure out why the code behaves this way on Tower.
Related
The Script, running on a Linux host, should call some Windows hosts holding Oracle Databases. Each Oracle Database is in DNS with its name "db-[ORACLE_SID]".
Lets say you have a database with ORACLE SID TEST02, it can be resolved as db-TEST02.
The complete script is doing some more stuff, but this example is sufficient to explain the problem.
The db-[SID] hostnames must be added as dynamic hosts to be able to parallelize the processing.
The problem is that oracle_databases is not passed to the new playbook. It works if I change the hosts from windows to localhost, but I need to analyze something first and get some data from the windows hosts, so this is not an option.
Here is the script:
---
# ansible-playbook parallel.yml -e "databases=TEST01,TEST02,TEST03"
- hosts: windows
gather_facts: false
vars:
ansible_connection: winrm
ansible_port: 5985
ansible_winrm_transport: kerberos
ansible_winrm_kerberos_delegation: true
tasks:
- set_fact:
database: "{{ databases.split(',') }}"
- name: Add databases as hosts, to parallelize the shutdown process
add_host:
name: "db-{{ item }}"
groups: oracle_databases
loop: "{{ database | list}}"
##### just to check, what is in oracle_databases
- name: show the content of oracle_databases
debug:
msg: "{{ item }}"
with_inventory_hostnames:
- oracle_databases
- hosts: oracle_databases
gather_facts: true
tasks:
- debug:
msg:
- "Hosts, on which the playbook is running: {{ ansible_play_hosts }}"
verbosity: 1
My inventory file is just small, but there will be more windows hosts in future:
[adminsw1#obelix oracle_change_home]$ cat inventory
[local]
localhost
[windows]
windows68
And the output
[adminsw1#obelix oracle_change_home]$ ansible-playbook para.yml -l windows68 -e "databases=TEST01,TEST02"
/usr/lib/python2.7/site-packages/ansible/parsing/vault/__init__.py:44: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
from cryptography.exceptions import InvalidSignature
/usr/lib/python2.7/site-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.23) or chardet (2.2.1) doesn't match a supported version!
RequestsDependencyWarning)
PLAY [windows] *****************************************************************************************************************************
TASK [set_fact] ****************************************************************************************************************************
ok: [windows68]
TASK [Add databases as hosts, to parallelize the shutdown process] *************************************************************************
changed: [windows68] => (item=TEST01)
changed: [windows68] => (item=TEST02)
TASK [show the content of oracle_databases] ************************************************************************************************
ok: [windows68] => (item=db-TEST01) => {
"msg": "db-TEST01"
}
ok: [windows68] => (item=db-TEST02) => {
"msg": "db-TEST02"
}
PLAY [oracle_databases] ********************************************************************************************************************
skipping: no hosts matched
PLAY RECAP *********************************************************************************************************************************
windows68 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
It might be possible that Ansible is not parsing the updated inventory file file, or the hosts name is being malformed in as it updates the inventory.
In this scenario, you can use the -vv or -vvvv parameter in your Ansible command to get extra logging.
This will give you a complete picture into what Ansible is actually doing as it tries to parse hosts.
I found out, what the problem was. The playbook is restricted to a host "windows68" and therefore canĀ“t be run at the hosts added by the dynamic inventory.
It will work that way:
[adminsw1#obelix oracle_change_home]$ ansible-playbook para.yml -l windows68,oracle_databases -e "databases=TEST01,TEST02"
I am using the below Ansible code to get the file system details (NAME,MOUNTPOINT,FSTYPE,SIZE) from node servers to control server. I am not getting any issues while running the playbook. But the CSV file is not copied to control machine.
Can anyone please help me on this?
tasks:
- name: Fsdetails
shell: |
lsblk -o NAME,MOUNTPOINT,FSTYPE,SIZE > $(hostname).csv
register: fsdetails_files_to_copy
- name: Fetch the fsdetails
fetch:
src: "{{ item }}"
dest: /data3/deployments/remediation
flat: yes
with_items: "{{ fsdetails_files_to_copy.stdout_lines }}"
Output:
PLAY [all] ************************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [10.xxx.xxx.xx]
TASK [Fsdetails] ******************************************************************************************
changed: [10.xxx.xxx.xx]
TASK [Fetch the fsdetails] ********************************************************************************
PLAY RECAP ************************************************************************************************
10.xxx.xxx.xx : ok=2 changed=1 unreachable=0 failed=0
Your shell command is not returning anything, since it is writing the output to the CSV file. Because of this, your fetch task has nothing to loop on (stdout_lines is an empty list).
What you could do is make your shell task echo the CSV name $(hostname):
- name: Fsdetails
shell: |
lsblk -o NAME,MOUNTPOINT,FSTYPE,SIZE > $(hostname).csv && echo $(hostname).csv
register: fsdetails_files_to_copy
This way, your fetch task will pick the correct filename to download.
Network guy pretending to "code"...(insert laughter/shame here).
I am trying to create a playbook full of STIG requirements. I would like to be able to run this playbook against network devices, then easily copy the results into our the .ckl files.
In case it's not completely and utterly apparent, I have been using Ansible for less than a week.
*First I am having ansible register the output of a command.
*Then I would like ansible to validate certain words or phrases are in the output of the register.
*Then of course have a debug message state "Not a Finding {insert register here}", or "Open {insert register here}"
I cannot seem to get the "when {this pharse} (is (or not) in) register.stdout" to work.
Using Ansible 2.9
- hosts: ios
connection: network_cli
gather_facts: no
tasks:
- name: Gather Username Configuration Lines
ios_command:
commands: show run | i username localadmin
register: output
- debug:
msg: "{{ output.stdout }}"
- name: Username has correct privilege level
block:
- debug:
msg: "{{ output.stdout }}"
when: "'privilege 15' in output.stdout"
Output:
$ ansible-playbook ciscouserprivcheck.yml -u localadmin -k
SSH password:
PLAY [ios] *************************************************************************************************************************************
TASK [Gather Username Configuration Lines] *****************************************************************************************************
ok: [Cisco1]
TASK [debug] ***********************************************************************************************************************************
ok: [Cisco1] =>
msg:
- username localadmin privilege 15 secret 5 $1$o1t2$VoZhNwm3bMfsTJ6e8RIdl1
TASK [debug] ***********************************************************************************************************************************
skipping: [Cisco1]
PLAY RECAP *************************************************************************************************************************************
Cisco1 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
I have a "master" ansible playbook in which I call multiple playbooks using "import_playbook". At this point all the variables which are needed in the "child" playbooks are retrieved from the inventory file and this is working.
#master_playbook.yml
- import_playbook: playbook1.yaml
- import_playbook: playbook2.yaml
What I'd like to do is instead of listing the passwords required in the "child" playbooks in the inventory file, I'd like the "master" playbook to prompt the user for the required passwords and then pass those passwords to the "child" playbooks. The "child" playbooks would still retrieve the remaining variables (non-passwords) needed from the inventory file.
I can get the usage of vars_prompt to work and be able to input the passwords, however the part I'm stuck on is being able to then pass those variables from the "master" playbook to the "child" playbooks as part of the "import_playbook" operation.
Looking to accomplish something equivalent to the below, but this does not work.
#master_playbook.yml
-vars_prompt:
- name: "password1"
prompt: "Enter password1"
- name: "password2"
prompt: "Enter password2"
- import_playbook: playbook1.yaml
vars:
password1: "{{ password1 }}"
password2: "{{ password2 }}"
- import_playbook: playbook2.yaml
vars:
password1: "{{ password1 }}"
password2: "{{ password2 }}"
I managed to work around this by using set_fact, like so:
# site.yml
---
- name: Prompt for password
hosts: all
vars_prompt:
- name: prompted_password
prompt: Enter password
tasks:
- name: Set password as host fact
set_fact:
password: "{{prompted_password}}"
- name: Import playbook 1
import_playbook: playbook1.yml
- name: Import playbook 1
import_playbook: playbook2.yml
You should now be able to use password within the imported playbooks. That said, I'm not sure this is the proper ansible way of doing things.
I created the following playbook
---
- hosts: localhost
roles:
- parent
tasks:
- name: Importing child01 playbook
import_playbook: child01.yml
...
I then ran the following command:
ansible-playbook -e "pass1=blah" ./import.yml
Both the parent role and child01 playbook just have a debug statement showing the value of pass1. The output I got is as follows:
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [parent : Parent task 1] **************************************************
ok: [localhost] => {
"pass1": "blah"
}
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [child01 : Child 1 first task] ********************************************
ok: [localhost] => {
"pass1": "blah"
}
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
So, cannot include using vars_prompt or vars, but can pass in on the command line. Maybe this can work for you?
I defined a envs.sh script inside the /etc/profile.d/ folder.
When executing a ansible-playbook, I'm trying to get the value of this env var but it instead throws me an error:
Ansible test:
debug: msg="{{ ansible_env.NGN_VAL }} is an environment variable"
Error:
fatal: [xxx.yyy.zzz.kkk] => One or more undefined variables: 'dict object' has no attribute 'NGN_VAL'
FATAL: all hosts have already failed -- aborting
Why it doesn't execute the scripts inside that folder? When I connect through ssh, I echo it and it displays its value. How do I set remote environment variables and obtain them during ansible execution?
Thanks
Test with this if you want catch the environment variable.
[jenkins#scsblnx-828575 jenkins]$ cat mypass
export MYPASSWD=3455637
[jenkins#scsblnx-828575 jenkins]$ cat test.yml
- hosts: all
user: jenkins
tasks:
- name: Test variables.
shell: source /apps/opt/jenkins/mypass && echo $MYPASSWD
register: myenvpass
- debug: var=myenvpass.stdout
[jenkins#scsblnx-828575 jenkins]$ ansible-playbook -i hosts test.yml
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [127.0.0.1]
TASK [Test variables.] *********************************************************
changed: [127.0.0.1]
TASK [debug] *******************************************************************
ok: [127.0.0.1] => {
"myenvpass.stdout": "3455637"
}
PLAY RECAP *********************************************************************
127.0.0.1 : ok=3 changed=1 unreachable=0 failed=0
In my point of view you can accomplish using a mix of ansible vault and system environment variables.
Create and encrypt a file with ansible vault (this is where you put the content of your remote env variable):
$ ansible-vault create vars_environment.yml
Put your password to encrypt this file and write content of your variable, for example:
ngn_val: supersecret
I use to load my permanent environment variables in /etc/profile.d directory but they are more paths:
/etc/profile.d
/etc/profile
/etc/environment
~/.profile
It is a good way to write a template in your playbook, although your can use the copy module:
---
# environment.yml
- name: Get enviroment variable server
hosts: debian.siccamdb.sm
vars:
dest_profile_environment: /etc/profile.d/environment.sh
vars_files:
- vars_environment.yml
tasks:
- name: "Template {{ dest_profile_enviroment }}"
template:
src: environment.sh.j2
dest: "{{ dest_profile_environment }}"
mode: '0644'
- name: Load env variable
shell: ". {{ dest_profile_environment }} && echo $NGN_VAL"
register: env_variable
- name: Debug env variable
debug:
var: env_variable.stdout_lines[0]
The important thing here is in the shell task because you have to source your environment variable and the use it by the register keyword which can be used to capture the output of a command in a variable.
This is the template's content in this example the file environment.sh.j2:
export NGN_VAL={{ ngn_val }}
Type your password o the vars_environment.yml file after run the playbook:
ansible-playbook --vault-id #prompt environment.yml
The output is the following:
PLAY [Get enviroment variable server] *************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************************************
ok: [debian.siccamdb.sm]
TASK [Template {{ dest_profile_enviroment }}] *****************************************************************************************************************************************************************************************
changed: [debian.siccamdb.sm]
TASK [Load env variable] **************************************************************************************************************************************************************************************************************
changed: [debian.siccamdb.sm]
TASK [Debug env variable] *************************************************************************************************************************************************************************************************************
ok: [debian.siccamdb.sm] => {
"env_variable.stdout_lines[0]": "supersecret"
}
PLAY RECAP ****************************************************************************************************************************************************************************************************************************
debian.siccamdb.sm : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Another way to accomplish is using custom facts in your remote server. This is a good practice if you want to leave the content of your variable in the remote server and using in playbooks without the needs of ansible vault.