I believe I have found a couple bugs in the way that running the system-level install as root via sudo
works with this role.
The bugs I observed were:
-
When playbook was run as non-root user with any of: sudo: True
, sudo: true
, sudo: yes
, or --sudo
command line option, RVM installer script would fail due to file permissions issues:
TASK: [altermn.rvm | updating RVM] ********************************************
<mauth00.tst.lan.returnpath.net> REMOTE_MODULE command source /etc/profile.d/rvm.sh && rvm get stable executable=/bin/bash #USE_SHELL
failed: [mauth00.tst.lan.returnpath.net] => {"changed": true, "cmd": "source /etc/profile.d/rvm.sh && rvm get stable", "delta": "0:00:01.871639", "end": "2015-08-24 15:53:56.982704", "rc": 23, "start": "2015-08-24 15:53:55.111065", "warnings": []}
stderr: curl: (23) Failed writing body (0 != 860)
curl: (23) Failed writing body (0 != 15926)
Could not update RVM, get some help at #rvm IRC channel at freenode servers.
stdout: Downloading https://get.rvm.io
Downloading https://github.com/rvm/rvm/archive/1.26.11.tar.gz
Could not download 'https://github.com/rvm/rvm/archive/1.26.11.tar.gz'.
curl returned status '23'.
Downloading https://bitbucket.org/mpapis/rvm/get/1.26.11.tar.gz
Could not download 'https://bitbucket.org/mpapis/rvm/get/1.26.11.tar.gz'.
curl returned status '23'.
FATAL: all hosts have already failed -- aborting
-
When playbook was run against a node with RVM already installed, and with: auto_update_rvm: true
and --user=root
(to avoid first bug), install would fail due to gpg key not being installed into root
's gpg
keychain
[[email protected] ~]# source /etc/profile.d/rvm.sh && rvm get stable
Downloading https://get.rvm.io
Downloading https://github.com/rvm/rvm/archive/1.26.11.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc
gpg: Signature made Mon 30 Mar 2015 03:52:13 PM MDT using RSA key ID BF04FF17
gpg: Can't check signature: No public key
Warning, RVM 1.26.0 introduces signed releases and automated check of signatures when GPG software found.
Assuming you trust Michal Papis import the mpapis public key (downloading the signatures).
GPG signature verification failed for '/usr/local/rvm/archives/rvm-1.26.11.tgz' - 'https://github.com/rvm/rvm/releases/download/1.26.11/1.26.11.tar.gz.asc'!
try downloading the signatures:
gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
or if it fails:
command curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -
the key can be compared with:
https://rvm.io/mpapis.asc
https://keybase.io/mpapis
Could not update RVM, get some help at #rvm IRC channel at freenode servers.
It appears that even when run with any of these options: - { role: altermn.rvm, sudo: yes }
, sudo: True
, sudo: true
, sudo: yes
, or --sudo
command line option, the user that actually runs the tasks which have sudo: "{{ sudo }}"
are not actually being run as root unless the user running the playbook is already root (--user=root
).
Debugging
I added some debug tasks to the role to verify this, and tested against Ansible v1.8.4
and v1.9.2
and saw the same behavior:
---
- name: Configure Ruby
hosts: ruby_hosts
sudo: true
roles:
- { role: altermn.rvm, sudo: True, tags: rvm }
roles/altermn.rvm/tasks/receive_key.yml
:
- name: whoami
shell: whoami
sudo: "{{ sudo }}"
register: ansible_user_is_running_as
always_run: true
ignore_errors: true
tags:
- debug
- name: Who is Ansible running as?
debug:
var: ansible_user_is_running_as
always_run: true
ignore_errors: true
tags:
- debug
- name: sudoDOdooo!
debug:
msg: "{{ sudo }}"
always_run: true
ignore_errors: true
tags:
- debug
As you can see, the user returned by the whoami
command which is supposedly run as sudo with sudo: True
actually returns ansible
:
[[email protected]]$ ./bin/docker-run 'ansible-playbook -i inventory/racktables.py playbooks/ruby_host/rvm.yml -e rp_environment=test --user=ansible --diff -vv --check --tags=rvm,debug '
PLAY [Configure Ruby] ********************************************************
GATHERING FACTS ***************************************************************
<rubynode00.example.com> REMOTE_MODULE setup CHECKMODE=True
ok: [rubynode00.example.com]
TASK: [altermn.rvm | ensure necessary yum packages are installed] *************
<rubynode00.example.com> REMOTE_MODULE yum name=curl,gnupg2 state=present CHECKMODE=True
ok: [rubynode00.example.com] => (item=curl,gnupg2) => {"changed": false, "item": "curl,gnupg2", "msg": "", "rc": 0, "results": ["curl-7.19.7-36.el6_4.x86_64 providing curl is already installed", "gnupg2-2.0.14-4.el6.x86_64 providing gnupg2 is already installed"]}
TASK: [altermn.rvm | ensure necessary apt packages are installed] *************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | checking that RVM is installed] **************************
<rubynode00.example.com> REMOTE_MODULE stat path=/etc/profile.d/rvm.sh CHECKMODE=True
ok: [rubynode00.example.com] => {"changed": false, "stat": {"atime": 1440421983.2096033, "checksum": "f219eb582a5520c5c79fd5b1cb727d7307c2349b", "ctime": 1414434821.7944453, "dev": 64769, "exists": true, "gid": 0, "gr_name": "root", "inode": 9133, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "md5": "afde9903e1fc2f5c989d54a97d4611ce", "mode": "0755", "mtime": 1414434821.7924473, "nlink": 1, "path": "/etc/profile.d/rvm.sh", "pw_name": "root", "rgrp": true, "roth": true, "rusr": true, "size": 1720, "uid": 0, "wgrp": false, "woth": false, "wusr": true, "xgrp": true, "xoth": true, "xusr": true}}
TASK: [altermn.rvm | Check for mpapis gpg key] ********************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | whoami] **************************************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | Who is Ansible running as?] ******************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | sudoDOdooo!] *********************************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | receiving key] *******************************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | downloading RVM installer] *******************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | set executable RVM installer] ****************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | installing RVM] ******************************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | removing RVM installer] **********************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | setting RVM autolibs on] *********************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | Check for mpapis gpg key] ********************************
<rubynode00.example.com> REMOTE_MODULE command gpg --list-keys mpapis #USE_SHELL
changed: [rubynode00.example.com] => {"changed": true, "cmd": "gpg --list-keys mpapis", "delta": "0:00:00.005546", "end": "2015-08-24 15:47:21.012892", "rc": 0, "start": "2015-08-24 15:47:21.007346", "stderr": "", "stdout": "pub 4096R/D39DC0E3 2014-10-28\nuid Michal Papis (RVM signing) <[email protected]>\nsub 4096R/BF04FF17 2014-10-28 [expires: 2016-01-05]", "warnings": []}
TASK: [altermn.rvm | whoami] **************************************************
<rubynode00.example.com> REMOTE_MODULE command whoami #USE_SHELL
changed: [rubynode00.example.com] => {"changed": true, "cmd": "whoami", "delta": "0:00:00.002383", "end": "2015-08-24 15:47:21.464745", "rc": 0, "start": "2015-08-24 15:47:21.462362", "stderr": "", "stdout": "ansible", "warnings": []}
TASK: [altermn.rvm | Who is Ansible running as?] ******************************
ok: [rubynode00.example.com] => {
"var": {
"ansible_user_is_running_as": {
"changed": true,
"cmd": "whoami",
"delta": "0:00:00.002383",
"end": "2015-08-24 15:47:21.464745",
"invocation": {
"module_args": "whoami",
"module_name": "shell"
},
"rc": 0,
"start": "2015-08-24 15:47:21.462362",
"stderr": "",
"stdout": "ansible",
"stdout_lines": [
"ansible"
],
"warnings": []
}
}
}
TASK: [altermn.rvm | sudoDOdooo!] *********************************************
ok: [rubynode00.example.com] => {
"msg": "True"
}
TASK: [altermn.rvm | receiving key] *******************************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | updating RVM] ********************************************
skipping: [rubynode00.example.com]
ok: [rubynode00.example.com] => {"msg": "check mode not supported for shell", "skipped": true}
TASK: [altermn.rvm | setting default Ruby version] ****************************
skipping: [rubynode00.example.com]
ok: [rubynode00.example.com] => {"msg": "check mode not supported for shell", "skipped": true}
TASK: [altermn.rvm | installing Ruby] *****************************************
skipping: [rubynode00.example.com]
TASK: [altermn.rvm | setting default Ruby version] ****************************
skipping: [rubynode00.example.com]
PLAY RECAP ********************************************************************
rubynode00.example.com : ok=7 changed=2 unreachable=0 failed=0
I have found that by calling the role with ansible_sudo: True
, and removing all the sudo: "{{ sudo }}"
task lines fixes the problem.
It appears that this is due to a problem in Ansible where it does not evaluate the contents of sudo: "{{ foo }}"
, but simply passes it along to utils.boolean
.
The fix or workaround mentioned here to preserve the conditional ability to run with sudo is to duplicate tasks, and have one with sudo: true
, one with sudo: false
, then use when:
conditions to run the appropriate one.