vagrant,chef,rbenv(chef-rbenv)でgemをインストール時のエラー対処


## githubのプルリク

どうしたもんかと解決策を探していたところ、プルリクにありましたのでまとめたものです。

* https://github.com/fnichol/chef-rbenv/issues/98
* https://github.com/fnichol/chef-rbenv/issues/107

## Vagrantfile,Berksfileの内容

* centos6.5 - 64bitを使用しています。

```Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  # 個人で好きなように
  config.vm.box = "vm_centos_6.5"
  config.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.5-x86_64-v20140504.box"

  # Omnibus
  config.omnibus.chef_version = :latest

  # Chef
  config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = ["../cookbooks", "../site-cookbooks"]
    chef.run_list = [
      "ruby_build",
      "rbenv::system"
    ]

    chef.json = {
      "rbenv" => {
        "global" => "2.2.1",
        "rubies" => [ "2.2.1" ],
        "gems" => {
          "2.2.1" => [
            { "name" => "bundler" }
          ]
        }
      }
    }
  end

end

```

```Berksfile
source "https://api.berkshelf.com"

cookbook 'ruby_build'
cookbook 'rbenv', :git => 'https://github.com/muskox/chef-rbenv'
```

こんな感じの設定で`vagrant up`するとエラーが発生します。
chefのバージョンアップにより発生しているようです。

## エラーと解決策2つ(A,B)

### NoMethodError undefined method `rbenv_rehash'


```error.log
==> default: [2015-04-07T21:18:15+00:00] INFO: Building rbenv_ruby[2.2.1] (system), this could take a while...
==> default: [2015-04-07T21:22:38+00:00] INFO: script[rbenv install 2.2.1 (system)] ran successfully
==> default: [2015-04-07T21:22:38+00:00] INFO: script[rbenv global 2.2.1 (system)] ran successfully
==> default: 
==> default: ================================================================================
==> default: Error executing action `install` on resource 'rbenv_gem[2.2.1::bundler] (system)'
==> default: ================================================================================
==> default: 
==> default: 
==> default: NoMethodError
==> default: -------------
==> default: undefined method `rbenv_rehash' for #<Chef::Provider::Package::RbenvRubygems:0x000000089f8280>
==> default: 
==> default: 
==> default: Cookbook Trace:
==> default: ---------------
==> default: 
==> default: /tmp/vagrant-chef/2901d75c86b5ccba09402efe1b2d9b8a/cookbooks/rbenv/libraries/chef_provider_package_rbenvrubygems.rb:89:in `rehash'
==> default: /tmp/vagrant-chef/2901d75c86b5ccba09402efe1b2d9b8a/cookbooks/rbenv/libraries/chef_provider_package_rbenvrubygems.rb:69:in `install_package'
==> default: 
==> default: Resource Declaration:
==> default: ---------------------
==> default: # In /tmp/vagrant-chef/2901d75c86b5ccba09402efe1b2d9b8a/cookbooks/rbenv/recipes/system.rb
==> default: 
==> default:  46:     rbenv_gem gem['name'] do
==> default:  47:       rbenv_version rubie
==> default:  48: 
==> default:  49:       %w{version action options source}.each do |attr|
==> default:  50:         send(attr, gem[attr]) if gem[attr]
==> default:  51:       end
==> default:  52:     end
==> default:  53:   end
==> default: 
==> default: Compiled Resource:
==> default: ------------------
==> default: # Declared in /tmp/vagrant-chef/2901d75c86b5ccba09402efe1b2d9b8a/cookbooks/rbenv/recipes/system.rb:46:in `block (2 levels) in from_file'
==> default: 
==> default: rbenv_gem("bundler") do
==> default:   provider Chef::Provider::Package::RbenvRubygems
==> default:   action :install
==> default:   retries 0
==> default:   retry_delay 2
==> default:   default_guard_interpreter :default
==> default:   declared_type :rbenv_gem
==> default:   cookbook_name :rbenv
==> default:   recipe_name "system"
==> default:   rbenv_version "2.2.1"
==> default:   package_name "bundler"
==> default:   gem_binary "export RBENV_ROOT=\"/usr/local/rbenv\" && export PATH=\"$RBENV_ROOT/bin:$RBENV_ROOT/shims:$PATH\" && export RBENV_VERSION=\"2.2.1\" && $RBENV_ROOT/shims/gem"
==> default:   version "1.9.2"
==> default: end
==> default: 
==> default: 
==> default: [2015-04-07T21:22:43+00:00] INFO: Running queued delayed notifications before re-raising exception
==> default: [2015-04-07T21:22:43+00:00] ERROR: Running exception handlers
==> default: [2015-04-07T21:22:43+00:00] ERROR: Exception handlers complete
==> default: [2015-04-07T21:22:43+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
==> default: [2015-04-07T21:22:43+00:00] ERROR: rbenv_gem[2.2.1::bundler] (system) (rbenv::system line 46) had an error: NoMethodError: undefined method `rbenv_rehash' for #<Chef::Provider::Package::RbenvRubygems:0x000000089f8280>
==> default: [2015-04-07T21:22:43+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
```


### A.cookbookのrbenvを修正する

```cookbooks/rbenv/libraries/chef_provider_package_rbenvrubygems.rb
### 追記
require 'etc'
###

class Chef
  module Rbenv
  ...
  end

  class Provider
    class Package
      class RbenvRubygems < Chef::Provider::Package::Rubygems
      
        ...
        
        def install_package(name, version)
          # super
          ### 元の呼び出しをコメント化して、追記
          run_as_user(rbenv_user) { super }
          ###
          rehash
          true
        end

        def remove_package(name, version)
          # super
          ### 元の呼び出しをコメント化して、追記
          run_as_user(rbenv_user) { super }
          ###
          rehash
          true
        end
        
        ...

        # def rehash
        #   rbenv_rehash new_resource do
        #     root_path rbenv_root
        #     user rbenv_user if rbenv_user
        #     action :nothing
        #   end.run_action(:run)
        # end
        
        ### 元のメソッドをコメント化して、追記
        def rehash
          e = ::Chef::Resource::RbenvRehash.new(new_resource.name, @run_context)
          e.root_path rbenv_root
          e.user rbenv_user if rbenv_user
          e.action :nothing
          e.run_action(:run)
        end
        ###
        
      end
    end
  end
end

```

```cookbooks/rbenv/libraries/chef_rbenv_script_helpers.rb
class Chef
  module Rbenv
    module ScriptHelpers
    
      ...

      ### 追記
      def run_as_user(username, &block)
        if username
          user = Etc.getpwnam(username)
          Process.fork do
            Process.uid = user.uid
            block.call
          end
          Process.wait
        else
          block.call
        end
      end
      ###
      
    end
  end
end

```

### B.chefのバージョンを下げる

```
# config.omnibus.chef_version = :latest
config.omnibus.chef_version = "11.18.6"
```