How to prevent the second "gem install XXX" from reinstalling? - ruby

gem install XXX seems to run the installation process even if the package is already installed. i.e. if I do
$ gem install chef
...
$ gem list | grep chef
chef (0.9.8)
$ gem install chef
...
the second gem install chef seems to install chef again!
How can I get this to result in a noop and the message "chef is already installed", or similar, the way most package management tools work?
I can achieve what I want via
$ gem list | grep chef > /dev/null || gem install chef
but there must be a better way that I'm missing.

According to the /lib/rubygems/commands/install_command.rb file of the RubyGems sources, there is no other, "legal", way to do that, so your own is the best.

Related

RVM Ruby Install Breaks Chef-Client On Bootstrapped Node

I have a Red Hat Enterprise Linux Server release 6.7 node that I have bootstrapped with CHEF. I've successfully executed multiple cookbooks/recipes on this node. Now I need to setup this node to run Ruby On Rails applications.
I have a cookbook with recipes that successfully ::
installs RVM
installs Ruby v2.2
The Problem
After RVM installs Ruby, the CHEF-Client on the bootstrapped node no longer works. Regardless of what Cookbook/Recipe(s) I try to run, I get the following output ::
PS C:\Users\JW031544\workspace\CHEF\chef-repo> knife ssh dh2vrtooldev01 "chef-client -o recipe[MY_COOKBOOK::default]" --manual-list --ssh-user MY_USER --ssh-password "MY_PASS"
dh2vrtooldev01 Ignoring executable-hooks-1.3.2 because its extensions are not built. Try: gem pristine executable-hooks --version 1.3.2
dh2vrtooldev01 Ignoring gem-wrappers-1.2.7 because its extensions are not built. Try: gem pristine gem-wrappers --version 1.2.7
dh2vrtooldev01 Ignoring nokogiri-1.6.8.1 because its extensions are not built. Try: gem pristine nokogiri --version 1.6.8.1
dh2vrtooldev01 /opt/chef/embedded/lib/ruby/site_ruby/2.3.0/rubygems/dependency.rb:308:in `to_specs': Could not find 'addressable' (= 2.4.0) among 45 total gem(s) (Gem::MissingSpecError)
dh2vrtooldev01 Checked in 'GEM_PATH=/usr/local/rvm/gems/ruby-2.2.4:/usr/local/rvm/gems/ruby-2.2.4#global', execute `gem env` for more information
dh2vrtooldev01 from /opt/chef/embedded/lib/ruby/site_ruby/2.3.0/rubygems/dependency.rb:320:in `to_spec'
dh2vrtooldev01 from /opt/chef/embedded/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_gem.rb:65:in `gem'
dh2vrtooldev01 from /usr/bin/chef-client:4:in `<main>'
If I go onto the node and tell RVM to remove that version of Ruby, then the CHEF-Client will begin working again just fine.
The Question
Does anyone have any idea why CHEF-Client suddenly forgets how to run once RVM installs a version of Ruby?
Source Code
(default.rb)
include_recipe 'abl_rails::rvm_install'
include_recipe 'abl_rails::ruby_install'
(rvm_install.rb)
# Install RVM (if it doesn't already exist)
execute 'install_rvm' do
cwd '/root/'
command 'curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -; curl -L get.rvm.io | bash -s stable'
not_if {::File.exists?('/etc/profile.d/rvm.sh')}
end
(ruby_install.rb)
# Install Ruby
bash 'install_ruby' do
cwd '/root/'
code <<-EOH
source /etc/profile.d/rvm.sh;
rvm install #{node['ruby_version']};
EOH
not_if "source /etc/profile.d/rvm.sh; ruby --version | grep #{node['ruby_version']}", :cwd => '/root'
notifies :run, "bash[set_default_rvm_ruby]", :immediately
end
# Set the default Ruby version in RVM
bash "set_default_rvm_ruby" do
cwd '/root'
code <<-EOH
source /etc/profile.d/rvm.sh;
rvm use #{node['ruby_version']} --default;
EOH
action :run
end
rvm overrides the cd internal function with a custom function, and that is causing the error. Try removing rvm and use a different ruby manager such as rbenv.
Check this blog post for other differences between rvm and rbenv : http://jonathan-jackson.net/rvm-and-rbenv
I'll be honest, I had the same issue before (but not with chef), read a bit more about rvm and decided that it was not the right tool for me. I'm sure there must be a way to make rvm play nicely, but I decided it was not worth the effort.
This may be fixed in chef-client 12.17.x so that chef-client correctly breaks out of the RVM environment:
Related Chef bugs:
https://github.com/chef/appbundler/pull/24
https://github.com/chef/chef/issues/5589
If it is still broken after 12.17.x (when ::Gem.clear_paths exists in the /opt/chef/bin/chef-client appbundler binstub) then a new issue should get cut against appbundler.
(As an RVM user, though, I would not recommend using it for running production services, but I find it very nice to use in a dev workstation kind of environment -- but YMMV).

Controlling Vagrant plugin dependencies via Ansible

I have an Ansible playbook that installs Vagrant, and then instructs Vagrant to install a specific plugin. Vagrant has trouble installing a gem it needs, and says:
An error occurred while installing nokogiri (1.6.6.2), and Bundler cannot continue.
Make sure that `sudo gem install nokogiri -v '1.6.6.2'` succeeds before bundling.
stdout: Installing the 'vagrant-aws --version '0.5.0'' plugin. This can take a few minutes...
While I have trouble installing Nokogiri using the command:
$ sudo gem install nokogiri -v '1.6.6.2'
as vagrant does it, I have found that I can install Nokogiri manually, using this command:
$ sudo gem install nokogiri -v 1.6.6.2 -- --use-system-libraries --with-xml2-include=/usr/include/libxml2
Even after I installed the gem manually, vagrant still fails if I manually tell it to install the plugin.
Is there a way to get better control of these dependencies so that vagrant won't fail and my playbook will complete?
It turns out I was missing some key dependencies: build-essential, libxslt1-dev, libxml2-dev, and zlib1g-dev. I found this comment here: https://github.com/mitchellh/vagrant-aws/issues/163#issuecomment-27603855 very helpful.
I believe it's an issue with using sudo to install the ruby gem.
I solved this issue by installing Ruby Version Manager, which installs and manages gems in your home directory.
After installing RVM I could install nokogiri without sudo, but vagrant-aws still failed to install until I re-installed vagrant. If you are building a fresh environment with Ansible then you can probably just install RVM before you install vagrant the first time (or any other ruby stuff). There are other ways to fix your gem permissions as well.
Here are the steps I took:
Install Ruby Version Manager (https://rvm.io/rvm/install)
curl -sSL https://get.rvm.io | bash -s stable --ruby
Install nokogiri without sudo
gem install nokogiri
Re-install vagrant (http://www.vagrantup.com/downloads)

Kitchen/berkshelf wants old gem?

I want to test some changes to a cookbook, so I did what I used to do, but the result was far from normal:
$ ../gem-sucks/bin/kitchen converge
-----> Starting Kitchen (v1.2.1)
!!!!!! The `berkshelf' gem is missing and must be installed or cannot be properly activated. Run `gem install berkshelf` or add the following to your Gemfile if you are using Bundler: `gem 'berkshelf'`.
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::UserError
>>>>>> Message: Could not load or activate Berkshelf (can't activate json-1.8.0, already activated json-1.8.1)
>>>>>> ----------------------
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose --all` for configuration
$ gem list | grep berkshelf
berkshelf (3.2.1, 3.1.4, 2.0.10, 2.0.9)
berkshelf-api-client (1.2.0)
$ gem list | grep json
json (1.8.1, 1.8.0)
multi_json (1.10.1, 1.7.9)
The machine is running debian Jessie, and lots of packages (I have no idea whether anything ruby related is among) has been updated since I touched this cookbook last.
How do I make kitchen work again?
Make sure that the chefdk is in the front of your path.
PATH=/opt/chefdk/bin:/Users/sowen/.rvm/gems/ruby-2.2.0/bin:/Users/sowen/.rvm/gems/ruby-2.2.0#global/bin:/Users/sowen/.rvm/rubies/ruby-2.2.0/bin:/opt/chefdk/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/sowen/go/bin:/Users/sowen/.rvm/bin:/Users/sowen/.rvm/bin:/Users/sowen/go/bin
I ran into this same problem until I adjusted and re-sourced my bash_profile
If you're using ChefDk, then you might be able to fix the problem by deleting the gems installed at GEM_HOME (in my case /home/username/.chefdk).
If that doesn't work, try using bundle as in bundle exec kitchen converge, this should allow you to use the installed gems in your list.
I had a similar issue but json wasn't installed in GEM_HOME and I ended up having to run the following command to resolve my issue.
gem uninstall -i /opt/chefdk/embedded/lib/ruby/gems/2.1.0 json
Look this issue https://github.com/test-kitchen/kitchen-vagrant/pull/126
you need re install berkshelf by gem, then apply patch kitchen-vagrant
Install upstream kitchen-vagrant
git clone https://github.com/test-kitchen/kitchen-vagrant.git
cd kitchen-vagrant
gem build kitchen-vagrant.gemspec
gem install kitchen-vagrant-0.15.0.gem
Re install old Berkshelf
gem install berkshelf

Installing a dev version of Vagrant but bundler doesn't seem to be installing the vagrant gem from source

I am trying to get a hackable installation of vagrant working on my machine. It uses bundler, and in its Gemspec it refers to the remote "." to add itself as a gem. The bundle install command seems to be working, but the "vagrant" gem doesn't seem to appear in gem list:
alexandma#ALEXANDMA-1-MBP ~/Projects/vagrant_ (master)
bundle install | grep "vagrant "
Using vagrant 1.6.4.dev from source at .
alexandma#ALEXANDMA-1-MBP ~/Projects/vagrant_ (master)
gem list | grep -c vagrant
0
Installing a gem from a file path or Git repository with Bundler will not install an actual gem file that can be seen by the gem command. Only Bundler is aware of the gem, so you'll need to run Bundler-aware commands to use it. In this case, running bundle list will show the entire list of dependencies including the line you see from the output of bundle install (Using vagrant 1.6.4.dev from source at .). To invoke the bundled version of Vagrant, you'll need to run bundle exec vagrant.

Removing all installed Gems and starting over

I recently started learning Ruby and Ruby on Rails, and have watched a plethora of getting started materials. I have been finding lately that I keep getting errors where gems won't install or they will be installed but they can't be used for some reason, and I have decided that I want to remove everything down to once again just having Ruby installed and start over with the installation. One training video had me install most of my gems with RVM, so I don't know if that changes anything.
So in short my question is "How to I get rid of RVM, Rubygems, and all installed Gems so that I can start over with just Ruby?"
Edit: I am on Mac OS 10.6
gem uninstall -aIx
Uninstalls all gems without prompt.
Options
-a, --[no-]all Uninstall all matching versions
-I, --[no-]ignore-dependencies Ignore dependency requirements while
uninstalling
-x, --[no-]executables Uninstall applicable executables without
confirmation
From the RVM support site:
RVM installs everything into ~/.rvm.
To remove RVM from your system run 'rm
-rf ~/.rvm'. You may have one additional config file in ~/.rvmrc and
of course the RVM hook in your
bash/zsh startup files.
So, just go to the command line and type rm -rf ~/.rvm
All the installed gems are in the ~/.rvm folders, so doing the above will remove the gems and installed rubies in one go.
Gems you added pre-RVM with the default ruby install can be removed by typing this at the command prompt:
for x in `gem list --no-versions`; do gem uninstall $x -a -x -I; done
For Windows and Unix copy/paste in command prompt (Ruby 1.9.x).
ruby -e "`gem list`.split(/$/).each { |line| puts `gem uninstall -Iax #{line.split(' ')[0]}` unless line.strip.empty? }"
using RVM, you could just type...
rvm gemset empty GEMSET
where GEMSET is the gemset which you would like to empty. then...
install bundle
yum install bundler and finally
bundle install
rvm implode (see cli docs) seems to work - and it even tells you where to look at for leftovers
This is work for me on Ubuntu 16.04. For me, when I was executing
command rails -v it throw errors because of NameError. I have
installed 3 version of rails (4.2.0, 4.2.6, 5.0.0.1). I was trying
to uninstall unnecessary gem using command gem uninstall rails -v
version number but I won't able to, but I find a way to solve
this problem. In order to uninstall all gems, you have to loop
through all entries in gem list with bash scripting. This method is
very inconvenient. Thanks to Rubygems 2.1.0, you now could do it
with one command.
STEP - 1
Firstly, please make sure you upgrade your Rubygems to 2.1.0 or
newer. For this run this command (Incase you are working on an older
version. You can check your gem version using this command any one
of them gem -v or gem --version)
gem update --system
gem --version
STEP - 2
Run this command in you terminal
gem uninstall --all
Step - 3
Install gem bundles (it is not necessary I think just for
precautions)
gem install bundle
Step - 4
Install the rails on your system using this command
gem install rails -v specific version you want to install you can check the rails version on the official site rails all versions
example :- I have installed rails 4.2.6
version, you install as per requirement.
gem install rails -v 4.2.6
Step - 5
Finally check the version of installed rails framework application
by Using basic command rails -v. It will echoed the current
version of rails frameworks. Enjoy :)
References
http://ruby-journal.com/how-to-uninstall-all-ruby-gems/
http://guides.rubyonrails.org/v4.1/getting_started.html
Step 1:
I first kept running into an error that said:
You don't have write permissions for the /usr/bin directory
To get permission, I became a root user with (this is potentially dangerous for reasons beyond my current understanding):
sudo -s
Credit
Step 2:
Then, I kept running into an error that said:
[gem] cannot be uninstalled because it is a default gem
This allowed me to uninstall everything:
for i in `gem list --no-versions`; do gem uninstall -aIx $i; done
Credit
FWIW, there are some weird cases where gems are installed but not really installed:
This should do the trick reasonably reliably.
gem uninstall -Iax `gem list | grep default | awk '{print $1}'`

Resources