"gem" module reports gem as present when it is not and therefore will not install

I am running Ansible using “brew install --HEAD ansible”, which currently prints it’s version as “ansible 1.4”.

Here is my task:

  • name: install ruby gem bundler
    gem: name=bundler state=present version=1.3.5 user_install=no
    sudo: true

When I run, it states that there is no change - bundler appears to the gem module to be installed??, though it is not.

I went further and tried the following:

ansible utilities -v --sudo -i development -m gem -a ‘name=bundler state=present version=1.3.5 user_install=no’

192.168.10.24 | success >> {

“changed”: false,

“name”: “bundler”,

“state”: “present”,

“version”: “1.3.5”

}

Seemingly the same behavior. If I run without --sudo:

ansible utilities -v -i development -m gem -a ‘name=bundler state=present version=1.3.5 user_install=no’

192.168.10.24 | FAILED >> {

“cmd”: [

“/usr/bin/gem”,

“install”,

“–version”,

“1.3.5”,

“–include-dependencies”,

“–no-user-install”,

“–no-rdoc”,

“–no-ri”,

“bundler”

],

“failed”: true,

“msg”: “ERROR: While executing gem … (Gem::FilePermissionError)\n You don’t have write permissions into the /var/lib/gems/1.9.1 directory.”,

“rc”: 1,

“stderr”: “ERROR: While executing gem … (Gem::FilePermissionError)\n You don’t have write permissions into the /var/lib/gems/1.9.1 directory.\n”,

“stdout”: “INFO: gem install -y is now default and will be removed\nINFO: use --ignore-dependencies to install only the gems you list\n”

}

I made the effort of running the “gem” module manually on the target host by setting ANSIBLE_KEEP_REMOTE_FILES=true and then running “sudo /usr/bin/python /home/vagrant/.ansible/tmp/ansible-1384877605.76-187131457818350/gem”. That worked great by installing bundler.

I have also made an attempt to discover what the “gem” python script is doing in the filesystem during a playbook run and during a manual run, as described, by using auditd. You can see the output over here: https://gist.github.com/aiwilliams/a86bf5d3deee57f2c72d. Seems to me they’re both working with the same directories, but otherwise I didn’t get much indication why it behaves differently when executed by ansible-playbook.

It’s got to be an environment thing, I would have though, but it seems that the bash environment is the same and I’ve verified that the gem environment is the same.

Any clues what might be going on?

Thanks, Adam

Perhaps there is some way the install process for bundler is done very differently than other gems?

Wow, somehow I totally missed this reply. Thank you for responding. Sorry for the terrible formatting of my post. I’ll consider your suggestion and update this thread once I have an answer. Again, very strange that it works fine when I leave the module on the server, login there, and execute it (the python script).

Also keep in mind that ansible runs “/bin/sh -c python ” for modules on the client nodes, and will only have environment variables that have been specified by “environment:” on the task.

Hi,

I can see this behaviour with following gems

github: haste
rubygems: ops_build

opsci:~ $ sudo gem list

*** LOCAL GEMS ***

TASK: [common-server | Install Haste client binary] ***************************
<opsci.rsd.com> ESTABLISH CONNECTION FOR USER: rsd
<opsci.rsd.com> REMOTE_MODULE gem name=haste state=latest
<opsci.rsd.com> EXEC ssh -C -tt -q -o ControlPersist=15m -F /Users/haad/.ansible/ssh_config -o ControlPath=“/Users/haad/.ansible/cp/ansible-ssh-%h-%p-%r” -o StrictHostKeyChecking=no -o Port=22 -o IdentityFile=“/Users/haad/.ssh/id_rsa” -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=rsd -o ConnectTimeout=19 opsci.rsd.com /bin/sh -c ‘mkdir -p $HOME/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757 && echo $HOME/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757’
<opsci.rsd.com> PUT /var/folders/yq/_h9bmb6x1qxb7p4_w5xhkgx80000gn/T/tmp1sQb3z TO /home/rsd/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757/gem
<opsci.rsd.com> EXEC ssh -C -tt -q -o ControlPersist=15m -F /Users/haad/.ansible/ssh_config -o ControlPath=“/Users/haad/.ansible/cp/ansible-ssh-%h-%p-%r” -o StrictHostKeyChecking=no -o Port=22 -o IdentityFile=“/Users/haad/.ssh/id_rsa” -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=rsd -o ConnectTimeout=19 opsci.rsd.com /bin/sh -c ‘sudo -k && sudo -H -S -p “[sudo via ansible, key=bqhjegrwqcfakjiubogaofvswknlictj] password: " -u root /bin/sh -c '”’“‘echo SUDO-SUCCESS-bqhjegrwqcfakjiubogaofvswknlictj; LANG=C LC_CTYPE=C /usr/bin/python /home/rsd/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757/gem; rm -rf /home/rsd/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757/ >/dev/null 2>&1’”‘"’’
ok: [opsci-server] => {“changed”: false, “name”: “haste”, “state”: “latest”, “version”: “0.2.1”}

Hi Adam

comments inline.

( TL;DR:

* good work on the troubleshooting!
* I think you're right, this is likely an environment/path thing.
* Ansible 1.4 is ancient, that probably isn't helping.
* there's an executable parameter you can use to hardcode the gem
command to run.
)

Hi,

I can see this behaviour with following gems

github: haste
rubygems: ops_build

opsci:~ $ sudo gem list

*** LOCAL GEMS ***

First question: are you sure this is the same gem binary Ansible is driving?
sudo can sometimes do odd things with env. variables etc, so i'd 'sudo
-i' and then
check 'which gem' and check the environment.

TASK: [common-server | Install Haste client binary]
***************************
<opsci.rsd.com> ESTABLISH CONNECTION FOR USER: rsd
<opsci.rsd.com> REMOTE_MODULE gem name=haste state=latest
<opsci.rsd.com> EXEC ssh -C -tt -q -o ControlPersist=15m -F
/Users/haad/.ansible/ssh_config -o
ControlPath="/Users/haad/.ansible/cp/ansible-ssh-%h-%p-%r" -o
StrictHostKeyChecking=no -o Port=22 -o
IdentityFile="/Users/haad/.ssh/id_rsa" -o KbdInteractiveAuthentication=no -o
PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o
PasswordAuthentication=no -o User=rsd -o ConnectTimeout=19 opsci.rsd.com
/bin/sh -c 'mkdir -p
$HOME/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757 && chmod a+rx
$HOME/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757 && echo
$HOME/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757'
<opsci.rsd.com> PUT
/var/folders/yq/_h9bmb6x1qxb7p4_w5xhkgx80000gn/T/tmp1sQb3z TO
/home/rsd/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757/gem
<opsci.rsd.com> EXEC ssh -C -tt -q -o ControlPersist=15m -F
/Users/haad/.ansible/ssh_config -o
ControlPath="/Users/haad/.ansible/cp/ansible-ssh-%h-%p-%r" -o
StrictHostKeyChecking=no -o Port=22 -o
IdentityFile="/Users/haad/.ssh/id_rsa" -o KbdInteractiveAuthentication=no -o
PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o
PasswordAuthentication=no -o User=rsd -o ConnectTimeout=19 opsci.rsd.com
/bin/sh -c 'sudo -k && sudo -H -S -p "[sudo via ansible,
key=bqhjegrwqcfakjiubogaofvswknlictj] password: " -u root /bin/sh -c
'"'"'echo SUDO-SUCCESS-bqhjegrwqcfakjiubogaofvswknlictj; LANG=C LC_CTYPE=C
/usr/bin/python
/home/rsd/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757/gem; rm -rf
/home/rsd/.ansible/tmp/ansible-tmp-1423500136.86-230822911136757/ >/dev/null
2>&1'"'"''
ok: [opsci-server] => {"changed": false, "name": "haste", "state": "latest",
"version": "0.2.1"}

I am running Ansible using "brew install --HEAD ansible", which currently
prints it's version as "ansible 1.4".

Here is my task:

- name: install ruby gem bundler
  gem: name=bundler state=present version=1.3.5 user_install=no
  sudo: true

That looks ok - you can also set executable=... if you want to ensure you know
which 'gem' binary to use.

When I run, it states that there is no change - bundler appears to the gem
module to be installed??, though it is not.

I went further and tried the following:

ansible utilities -v --sudo -i development -m gem -a 'name=bundler
state=present version=1.3.5 user_install=no'

192.168.10.24 | success >> {

    "changed": false,

    "name": "bundler",

    "state": "present",

    "version": "1.3.5"

}

Seemingly the same behavior. If I run without --sudo:

ansible utilities -v -i development -m gem -a 'name=bundler state=present
version=1.3.5 user_install=no'

192.168.10.24 | FAILED >> {

That makes sense as you no longer have permissions to write to system folders.

One last thing - you are going to be a lot better off not using 1.4,
it's pretty old.
A straight github checkout works great for me on OS X, so it might be worth
avoiding homebrew.

Just for the record problem was in user_install default value. Which by default installs gems to root home and not to global cache.
After removing gems adn running play with following module attr it works like a charm.

gem: name={{item}} state=latest include_dependencies=yes user_install=no

Oh sorry, thought you'd already pasted a run with "user_install=no"
explicitly set
(the one that moaned about not having the correct permission). I
should have pointed
that out more clearly, glad it's sorted now anyway.

I had exactly the same problem when running on VirtualBox VM (Ubuntu 14.4, Ansible 1.9)

`
vagrant@localhost:~$ sudo gem list

*** LOCAL GEMS ***

vagrant@localhost:~$ gem list

*** LOCAL GEMS ***

vagrant@localhost:~$ ansible localhost -m gem -a “name=sass state=latest include_dependencies=yes user_install=no” --sudo
localhost | success >> {
“changed”: false,
“name”: “sass”,
“state”: “latest”,
“version”: “3.4.14”
}

vagrant@localhost:~$ sudo gem list

*** LOCAL GEMS ***

vagrant@localhost:~$ gem list

*** LOCAL GEMS ***

`

While it works when I ran on my real machine

`
khiem@khiem-SVS13123CVW ~/ansible/avanan $ ansible localhost -m gem -a “name=sass state=present user_install=no” --sudo -K
SUDO password:
localhost | success >> {
“changed”: true,
“name”: “sass”,
“state”: “present”
}

khiem@khiem-SVS13123CVW ~/ansible/avanan $ gem list

*** LOCAL GEMS ***

sass (3.4.14)
`

I endup temporarily switch to use shelll command: gem install sass, losing idempotence :frowning: