Pergunta

I am triying to provision with chef. I need ruby and rubygems for root user and another user 'deploy'

ruby and rubygems are installed and work for root user (in test case "vagrant").

I create one user for use after with capistrano in order to deploy my app

user 'deploy' do
  password '$1$zOC.txvE$ex544C.YpxV.HqNh/2AKQ0'
  home "/home/deploy"
  supports :manage_home => true
  shell "/bin/bash"
end

Then I try to change gem sources for this 'deploy' user

execute 'change sources to our gem server' do
  command "gem sources -r http://rubygems.org/ && gem sources -a http://my.gem.server/"
  creates "~/.gemrc"
  user 'deploy'
  cwd "/home/deploy"
end

but get this error

[2014-02-14T14:38:27+00:00] ERROR: execute[change sources to our gem server] (beesor-cookbook::user line 13) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'       
---- Begin output of gem sources -r http://rubygems.org/ && gem sources -a http://my.gem.server/ ----       
STDOUT: source http://rubygems.org/ not present in cache       
STDERR: ERROR:  While executing gem ... (Errno::EACCES)       
    Permission denied - /home/vagrant/.gemrc       
---- End output of gem sources -r http://rubygems.org/ && gem sources -a http://my.gem.server/ ----       
Ran gem sources -r http://rubygems.org/ && gem sources -a http://my.gem.server/ returned 1 
Foi útil?

Solução

This is the problem with using an execute resource. You are running the execute resource as a non-privileged user. However, you want the associated file to still be owned by the non-privledged user, right? The code that Stephen suggested will work, but the .gemrc will be owned by the root user. Depending on how Rubygems reads it's gemrcs, it may not like that the file is owned by a different user. So you'll either need to manually chown and chmod the file inside the execute command, or just use a template.

If you run the command locally on your machine, you'll see the generated gemrc looks like:

---
:sources:
- http://my.gem.server

I would recommend using a pure template resource instead:

template '/home/deploy/.gemrc' do
  source 'gemrc.erb'
  user 'deploy'
  group 'deploy'
  mode '0644'
  variables(source: 'http://my.gem.server')
end

And then the associated erb:

---
:sources:
- <%= @source %>

This could also be expanded to support multiple source endpoints. Additionally, because you're using an idempotent resource:

  • You get a nice diff output in the Chef Client run

    You'll see a git-style diff in the output, which is very useful for debugging

  • You can notify other resources of a change

    If you need to install a gem after the template sources have change (for example), you can safely use notifications for this. Those notifications will only trigger when the template has changed:

template '/home/deploy/.gemrc' do
  # ...
  notifies :install, 'gem_package[foo]', :immediately
end

gem_package 'foo' do
  action :nothing
end
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top