How can I create multiple paths with usernames defined in vars file?
---
- hosts: hostname
gather_facts: false
vars_files:
- /home/ansible/usernames
tasks:
- name: Checking if home directory exists
with_items: "{{ username }}"
vars:
paths: &paths
- "/home/{{ username }}/"
- "/home/{{ username }}/data"
loop: "{{ paths }}"
become: yes
become_user: "{{ username }}"
stat:
path: "{{ paths }}"
register: play1
- name: Check paths from play1
debug:
var: play1
- name: Creating directories
loop: "{{ play1.results }}"
register: play2
become: yes
become_user: "{{ item.item }}"
file:
path: /home/{{ item.item }}/.ssh
state: directory
mode: '0700'
owner: "{{ item.item }}"
group: "system-group"
when: not item.stat.exists and not item.stat.pw_name == '"{{ item }}"'
- name: Display Creating directories
debug:
var: play2
Extract from input file.
username:
- user1
- user2
This is the error I'm getting:
ERROR: failed: [server] (item=/home/[u'user1', u'user2']/) => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "ansible_loop_var": "item", "changed": false, "item": "/home/[u'user1', u'user2']/", "module_stderr": "Shared connection to server closed.\r\n", "module_stdout": "sudo: unknown user: [uuser1,\r\nsudo: unable to initialize policy plugin\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
Related
My inventory file is having below host groups:
[uat1]
123.11.23.22 ansible_user="xxx"
[OS_uat2]
123.45.6.7 ansible_user="yyy"
[uat1_childs:children]
uat1
OS_uat2
I am having the vars file which is having param for below hosts. I am running a playbook to run a shell command. I am passing some parameters with the playbook. I am passing deployment_environment as uat1_childs. This is giving me error. Playbook is:
- name: play to ping test
gather_facts: false
hosts: "{{ deployment_environment }}"
ignore_unreachable: yes
vars_files:
- r_params.yml
vars:
package: "{{ package }}"
tasks:
- set_fact:
env_param: "{{ deployment_environment }}"
- name: ping test
ping:
data: pong
- name: Deploy Services on "{{ deployment_environment }}"
shell: cd "{{ env_select[env_param].script_path }}"; sh "{{ env_select[env_param].script_path }}/deploy.sh" "param1" "param2" "{{ env_select[env_param].repo }}" "{{ artifact_version }}" "{{ env_select[env_param].ENV }}" "{{ arti_username }}" "{{ arti_pass }}" "{{ deployer }}" "{{ package }}" "{{ env_select[env_param].deployment_path }}"
when: (package == "abc")
with_items: "{{ groups[{{ 'deployment_environment' }}] }}"
This is giving me error as:
fatal: [123.11.23.22]: FAILED! =>
{
"msg": "'dict object' has no attribute 'deployment_environment'"
}
fatal: [123.45.6.7]: FAILED! =>
{
"msg": "'dict object' has no attribute 'deployment_environment'"
}
I tried removing apostrophe in with items, still it is giving me error. Cant identify how to run the task in all children host group.
I have this playbook below to set user/group on the user's home directory.
jimbo and bobo here have different UID and GIDs on the different boxes.
Running this script will set the UID/GID ownership of the directories incorrectly.
For example, it will set /home/jimbo on operatorbox1 (1) to be owned by the UID of jimbo from operatorbox2 (2) - which is of course not the correct UID on operatorbox1 (1).
It does this seemingly randomly. If I run this playbook multiple times the ownership of the directories will flip back and forth.
Guessing I have something fundamental missing here. Why is this happening? Thanks!
ansible-playbook v2.9.23
./vars/operators.yml
---
operators:
jimbo: sshekeywhatever
bobo: sshkeywhatever
playbook.yml
---
- name: Setup operators
hosts:
- bastionbox
- operatorbox
become: true
vars_files:
- "./vars/operators.yml"
tasks:
- name: Set home directory permissions
file:
path: "/home/{{ item.key }}"
state: directory
owner: "{{ item.key }}"
group: "{{ item.key }}"
recurse: true
with_dict:
- "{{ operators }}"
I can't reproduce the problem. Below is a playbook for testing
- hosts: bastionbox,operatorbox
gather_facts: false
become: true
vars:
operators: [jimbo, bobo]
tasks:
- name: Create users
user:
name: "{{ item }}"
shell: /usr/sbin/nologin
uid: "{{ range(2500, 2600)|random }}"
loop: "{{ operators }}"
when: create_users|d(false)|bool
- name: List users uid
block:
- getent:
database: passwd
- debug:
msg: "{{ inventory_hostname }} {{ item }} uid: {{ getent_passwd[item].1 }}"
loop: "{{ operators }}"
when: list_users|d(false)|bool
- name: Set home directory owner and group
file:
state: directory
path: "/home/{{ item }}"
owner: "{{ item }}"
group: "{{ item }}"
recurse: true
loop: "{{ operators }}"
when: set_homes|d(false)|bool
- name: List homes
block:
- find:
paths: /home
file_type: directory
patterns: "{{ operators }}"
register: out
- debug:
msg: "{{ inventory_hostname }} {{ item.path }} uid: {{ item.uid }}"
loop: "{{ out.files }}"
loop_control:
label: "{{ inventory_hostname }}"
when: list_homes|d(false)|bool
- name: Delete users
user:
name: "{{ item }}"
state: absent
remove: true
loop: "{{ operators }}"
when: delete_users|d(false)|bool
Create users
shell> ansible-playbook -e create_users=true pb.yml
List users
shell> ansible-playbook -e list_users=true pb.yml
msg: 'bastionbox jimbo uid: 2572'
msg: 'operatorbox jimbo uid: 2537'
msg: 'bastionbox bobo uid: 2505'
msg: 'operatorbox bobo uid: 2557'
List homes
shell> ansible-playbook -e list_homes=true pb.yml
msg: 'bastionbox /home/bobo uid: 2505'
msg: 'operatorbox /home/jimbo uid: 2537'
msg: 'bastionbox /home/jimbo uid: 2572'
msg: 'operatorbox /home/bobo uid: 2557'
Set homes (task is idempotent)
shell> ansible-playbook -e set_homes=true pb.yml
TASK [Set home directory owner and group] *************************
ok: [operatorbox] => (item=jimbo)
ok: [bastionbox] => (item=jimbo)
ok: [operatorbox] => (item=bobo)
ok: [bastionbox] => (item=bobo)
I am trying to shutdown databases in a loop, the catch is some databases run as a different user and others just run as oracle. I login as oracle user and run the playbook and if the database is run as oracle user it goes through fine. If it is running as a different user I would like to become that user (oracle user has permissions to do that).
Here is my main playbook:
[oracle#ansctrlsrv.localdomain epd3]$ cat test.yml
---
- hosts: testdrive
tasks:
- set_fact:
db_list: "{{ lookup('file', 'vars/' ~ inventory_hostname ~ '.dblist')|from_yaml }}"
- name: Shutdown running databases
include_tasks: shutdowndb.yml
loop: "{{ db_list }}"
DB list is as follows:
[oracle#ansctrlsrv.localdomain epd3]$ cat vars/dbsrv.localdomain.dblist
- ebs1
- ebs2
- ndb1
[oracle#ansctrlsrv.localdomain epd3]$ cat shutdowndb.yml
---
- debug: msg='Shutting down {{ item }}'
- name: Execute shutdown
shell: id "{{ item }}"
register: shutdown_output
become: "{{ item is search('ebs') | ternary('yes','no') }}"
become_user: "{{ item }}"
- debug: msg="{{ shutdown_output.stdout }}"
[oracle#ansctrlsrv.localdomain epd3]$ cat inventory
[testdrive]
dbsrv.localdomain
[oracle#ansctrlsrv.localdomain epd3]$ ansible-playbook -i inventory test.yml
TASK [Execute shutdown] ***
fatal: [dbsrv1.localdomain]: FAILED! => {"changed": false, "module_stderr": "Shared connection to dbsrv1.localdomain closed.\r\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1} ...ignoring
I tried this question on another thread but got closed, so trying another hand after realizing a few issues myself such as being unable to run blocks of code with a loop, etc.
Appreciate any help.
Set become user conditionally
Fix the line
shell: id "{{ item }}"
correct syntax (use shell only when necessary)
command: "id {{ item }}"
The playbook below
- hosts: testdrive
tasks:
- set_fact:
db_list: "{{ lookup('file', 'vars/' ~ inventory_hostname ~ '.dblist')|from_yaml }}"
- name: Shutdown running databases
include_tasks: shutdowndb.yml
loop: "{{ db_list }}"
with the included tasks
$ cat shutdowndb.yml
- debug:
msg:
- "shell: {{ 'shutdown.sh ' ~ item }}"
- "become: {{ item is search('ebs')|ternary('yes', 'no') }}"
- "become_user: {{ item }}"
give
"msg": [
"shell: shutdown.sh ebs1",
"become: yes",
"become_user: ebs1"
]
"msg": [
"shell: shutdown.sh ebs2",
"become: yes",
"become_user: ebs2"
]
"msg": [
"shell: shutdown.sh ndb1",
"become: no",
"become_user: ndb1"
]
Q: "Why the command whoami is still giving oracle rather than ebs1?"
A: Short answer: Because become is not set to True.
Debugging
1) Is it possible to become all of the users in db_list? Yes.
- hosts: test_01
become: no
remote_user: admin
vars:
db_list: ['ebs1', 'ebs2', 'ndb1']
tasks:
- command: whoami
become_user: "{{ item }}"
become: true
register: result
loop: "{{ db_list }}"
- debug:
msg: "{{ result.results|json_query('[].stdout') }}"
give
"msg": [
"ebs1",
"ebs2",
"ndb1"
]
2) Does search and ternary work properly? Yes.
- debug:
msg: "{{ item is search('ebs')|ternary(true, false) }}"
loop: "{{ db_list }}"
gives
"msg": true
"msg": true
"msg": false
3) Does become and become_user work properly?. Yes.
- command: whoami
become_user: "{{ item }}"
become: "{{ item is search('ebs')|ternary(true, false) }}"
register: result
loop: "{{ db_list }}"
- debug:
msg: "{{ result.results|json_query('[].stdout') }}"
give
"msg": [
"ebs1",
"ebs2",
"admin"
]
Self explanatory. I want to link based on $(which {{ item }}).
Already saw the register function, but as I need to do a nested loop I'm not sure how to use it.
name: Link bins to user path
command: 'ln -s \$(which {{ item.1 }}) /home/{{ item.0 }}/bin/{{ item.1 }}'
with_nested:
- "{{ jail_users }}"
- "{{ jail_user_commands }}
Output:
failed: [rousertest] (item=[u'bob', u'date']) => {"changed": true,
"cmd": ["ln", "-s", "$(which", "date)", "/home/bob/bin/date"], "delta":
"0:00:00.011825", "end": "2019-07-11 08:17:32.921705", "item": ["bob", "date"], "msg": "non-zero return code", "rc": 1, "start": "2019-07-11
08:17:32.909880", "stderr": "ln: target ‘/home/bob/bin/date’ is not a
directory", "stderr_lines": ["ln: target ‘/home/bob/bin/date’ is not a
directory"], "stdout": "", "stdout_lines": []
Of course I was expecting something like this:
sudo ansible server -i inventory -m shell -a 'echo $(which date)'
rousertest | SUCCESS | rc=0 >>
/usr/bin/date
Below is the play. Avoid using command module for link. Use file module with state=link.
- name: Link binary
hosts: all
gather_facts: true
vars:
files:
- date
- ls
users:
- user1
- user2
tasks:
- name: Find paths
command: which {{ item }}
with_items:
- "{{ files }}"
register: result
- name: Link bins to user path
file:
src: "{{ item.1.stdout }}"
dest: "/home/{{ item.0 }}/bin/{{ item.1.item }}"
owner: "{{ item.0 }}"
group: "{{ item.0 }}"
state: link
with_nested:
- "{{ users }}"
- "{{ result.results }}"
i have playbook, which have include. Also have var_prompt "name_VM" and i need transfer variable in include playbook "new-vm.yml", but i have error:
TASK [hostname]
**************************************************************** fatal: [192.168.250.102]: FAILED! => {"failed": true, "msg": "the
field 'args' has an invalid value, which appears to include a variable
that is undefined. The error was: {{ name_VM }}: 'name_VM' is
undefined\n\nThe error appears to have been in
'/etc/ansible/playbooks/tasks/new-vm.yml': line 7, column 7, but
may\nbe elsewhere in the file depending on the exact syntax
problem.\n\nThe offending line appears to be:\n\n pre_tasks:\n -
hostname:\n ^ here\n"}
How to transfer variables in pre_tasks include playbook?
Main playbook:
- hosts: localhost
gather_facts: false
connection: local
become: true
vars_files:
- ../roles/vm-create/vars/am-default.yml
vars_prompt:
- name: "name_VM"
prompt: "VM name:"
private: no
default: "vm001"
- name: "size_hard"
prompt: "Size hard disk (Gb)"
private: no
default: "16"
- name: "size_memory"
prompt: "Size memory (Mb)"
private: no
default: "2048"
- name: "count_CPU"
prompt: "Count CPU:"
private: no
default: "2"
roles:
- vm-create
tasks:
- include: tasks/check-ip.yml
- include: tasks/new-vm.yml
new-vm playbook:
- hosts: temp
vars:
ldap_server: ldap://ldap.example.com
agent_server: zabbix.aexample.com
pre_tasks:
- hostname:
name: "{{ name_vm }}"
roles:
- { role: zabbix-agent, tags: [ 'zabbix' ] }
- { role: ldap-client, tags: [ 'ldap' ] }
- { role: motd, tags: [ 'motd' ] }
tasks:
- telegram:
token: 'bot12345:XXXXXX'
chat_id: XXXXX
msg: "New VM {{ ansible_hostname }} ({{ ansible_all_ipv4_addresses }}) is created and has been configured."
tags:
- telegram
check_ip.yml in which i add host:
- vsphere_guest:
vcenter_hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_user }}"
password: "{{ vcenter_pass }}"
guest: "{{ name_VM }}"
vmware_guest_facts: yes
validate_certs: no
register: vsphere_facts
until: vsphere_facts.ansible_facts.hw_eth0.ipaddresses[0] | match("192.168.250.")
retries: 6
delay: 10
- name: Ensure virtual machine is in the dynamic inventory
add_host:
name: "{{ vsphere_facts.ansible_facts.hw_eth0.ipaddresses[0] }}"
ansible_user: root
ansible_ssh_pass: pass
groups: temp
In your case name_VM is play-bound and will not be visible from second play.
You need to assign a fact to temp host (I guess you use add_host somewhere inside vm-create role; so just add name_vm: "{{ name_VM }}" host fact there).
Then in second play you can access {{ name_vm }} host fact.
Update: example, based on question edit.
- name: Ensure virtual machine is in the dynamic inventory
add_host:
name: "{{ vsphere_facts.ansible_facts.hw_eth0.ipaddresses[0] }}"
name_vm: "{{ name_VM }}"
ansible_user: root
ansible_ssh_pass: pass
groups: temp