Chef-client - is it possible to re-read gem repo address?

Hello

I want to get rid of default rubygems.org repository in my environment and add my own. At the top of a run list my node has a recipe

  execute 'del_rubygems_repo' do
    command '/opt/chef/embedded/bin/gem sources --remove https://rubygems.org'
    action :nothing
  end.run_action(:run)
  
  execute 'add_repo' do
    command '/opt/chef/embedded/bin/gem sources --add http://myrepo'
    action :nothing
  end.run_action(:run)

The second recipe is

chef_gem 'some-gem' do
  compile_time true if respond_to?(:compile_time)
end

Unfortunately at first chef-client’s run even after I change the repository address chef-client still wants to install ‘some-gem’ from rubygems.org which is impossible in my environment because nodes don’t have access to the Internet. The second run works just fine. I don’t want to use a proxy server. Is it possible to make it re-read .gemrc with the propper gem repo address at the first run? Current situation is very painful with an initial bootstraping. Any idea how to solve this?

We’ve gone through the same exercise ourselves trying out Gem Mirror/Gem in a box and Vendoring.

Your code should work in most circumstances although you’ve hard coded paths to your known installation of Ruby, the one in the Chef folder; if you run ChefDK the path will be different and if you use Linux you might have another version of Ruby installed.

Instead of hard coding the path you could use something like Gem class and use Gem.bindir in the recipe…

Instead of using an execute resource you could use shell_out which means you wouldn’t have to run the resource at compile time (I found Chef-Sugar at_compile_time nicer too) or again try the Gem class, there are default_sources, sources and sources= methods.

Can you debug this with Chef-Shell and a breakpoint or Pry or Chef::Log to see what sources Gem thinks are available.

What have you tried so far? I’m wondering if you have to clear sources to update the Gem caches?

Good luck.

Thanks for the very helpful reply.

I ended up with sth like this

  ruby_block 'set_gem_repos' do
    block do
      gem_binary = RbConfig::CONFIG['bindir'] + "/gem"

      Gem.sources.each do |r|
        node['my-cookbook']['repo'].each do |a|
          unless r.include? "#{a}"
            %x{ "#{gem_binary}" sources --remove "#{r}" }
            break
          end
        end      
      end

      Gem.sources = node['my-cookbook']['repo']

      Gem.sources.each do |r|
        %x{ "#{gem_binary}" sources --add "#{r}" }
      end

    end
    action :nothing
  end.run_action(:run)

Works like a charm.

Good stuff!