Conflicting gem dependencies (knife plugin)

272 Views Asked by At

I am working on a knife plugin and am running into a dependency conflict between my gem and another that's installed:

$ gem list fog
fog (1.24.0, 1.20.0, 1.11.1)

I have knife-ec2 installed, which depends on fog 1.20.0. The gem I'm working on has a dependency on fog 1.23.0. It is not dependent on knife-ec2 at all.

When I run my knife plugin, I get an error:

$ knife myplugin
`raise_if_conflicts': Unable to activate knife-ec2-0.8.0, because fog-1.24.0 conflicts with fog (~> 1.20.0) (Gem::LoadError)

If I uninstall knife-ec2, my knife plugin runs without issue.

I don't understand why the ec2 gem is loading while I run my own plugin. Does knife load all of plugins? Is there a way to resolve 2 knife plugins that have different versions of the same dependency?

1

There are 1 best solutions below

0
On

It seems like knife does indeed load all of it's plugins when it's being run. This poses a bit of a problem if 2 different plugins depend on different versions of a gem.

I can't see a clear way to resolve this for system-installed knife plugin gems, but have a workaround. It's not the most elegant solution, but it works for me, and might for you. It's a Bundler-based workaround:

  1. Create a directory to work in.
  2. Create a Gemfile with non-conflicting dependencies. An example of my gem file is shown below.
  3. Install dependencies locally using bundler: bundle install --path vendor/bundle (I am using the same path that bundler would install to if using the bundle install --deployment option, and generates a Gemfile.lock (given that you have consistent pathing on your local gems).
  4. Execute knife via bundler: bundle exec knife myplugin -h - success

I have a number of plugin sets that I need to have working together, so have a few directories with Gemfiles in them that I can use in different environments: from bundler from each of the directories, each configured with different plugin sets.

Sample Gemfile:

source 'https://rubygems.org'
gem "fog", "~> 1.24"
gem "knife-myplugin", :path => "/path/to/myplugin"