core: support plugin sources, and mask Bundler errors
This commit is contained in:
parent
84ecca5c15
commit
f612ec7549
|
@ -1,4 +1,5 @@
|
|||
require "pathname"
|
||||
require "set"
|
||||
require "tempfile"
|
||||
|
||||
require "bundler"
|
||||
|
@ -94,9 +95,15 @@ module Vagrant
|
|||
f.tap do |gemfile|
|
||||
gemfile.puts(%Q[source "https://rubygems.org"])
|
||||
gemfile.puts(%Q[source "http://gems.hashicorp.com"])
|
||||
gemfile.puts(%Q[gem "vagrant", "= #{Vagrant::VERSION}"])
|
||||
gemfile.puts("group :plugins do")
|
||||
sources = plugins.values.map { |p| p["sources"] }.flatten.compact.uniq
|
||||
sources.each do |source|
|
||||
next if source == ""
|
||||
gemfile.puts(%Q[source "#{source}"])
|
||||
end
|
||||
|
||||
gemfile.puts(%Q[gem "vagrant", "= #{Vagrant::VERSION}"])
|
||||
|
||||
gemfile.puts("group :plugins do")
|
||||
plugins.each do |name, plugin|
|
||||
version = plugin["gem_version"]
|
||||
version = nil if version == ""
|
||||
|
@ -108,9 +115,11 @@ module Vagrant
|
|||
|
||||
gemfile.puts(%Q[gem "#{name}", #{version.inspect}, #{opts.inspect}])
|
||||
end
|
||||
|
||||
gemfile.puts("end")
|
||||
|
||||
gemfile.close
|
||||
|
||||
puts File.read(gemfile.path)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -168,6 +168,10 @@ module Vagrant
|
|||
error_key(:failed, "vagrant.actions.box.verify")
|
||||
end
|
||||
|
||||
class BundlerError < VagrantError
|
||||
error_key(:bundler_error)
|
||||
end
|
||||
|
||||
class CFEngineBootstrapFailed < VagrantError
|
||||
error_key(:cfengine_bootstrap_failed)
|
||||
end
|
||||
|
|
|
@ -33,6 +33,7 @@ module Vagrant
|
|||
plugins[name] = {
|
||||
"require" => opts[:require],
|
||||
"gem_version" => opts[:version],
|
||||
"sources" => opts[:sources],
|
||||
}
|
||||
|
||||
result = nil
|
||||
|
@ -44,11 +45,17 @@ module Vagrant
|
|||
|
||||
# Add the plugin to the state file
|
||||
@global_file.add_plugin(
|
||||
result.name, version: opts[:version], require: opts[:require])
|
||||
result.name,
|
||||
version: opts[:version],
|
||||
require: opts[:require],
|
||||
sources: opts[:sources],
|
||||
)
|
||||
|
||||
result
|
||||
rescue ::Bundler::GemNotFound
|
||||
raise Errors::PluginGemNotFound, name: name
|
||||
rescue ::Bundler::BundlerError => e
|
||||
raise Errors::BundlerError, message: e.to_s
|
||||
end
|
||||
|
||||
# Uninstalls the plugin with the given name.
|
||||
|
@ -59,11 +66,15 @@ module Vagrant
|
|||
|
||||
# Clean the environment, removing any old plugins
|
||||
Vagrant::Bundler.instance.clean(installed_plugins)
|
||||
rescue ::Bundler::BundlerError => e
|
||||
raise Errors::BundlerError, message: e.to_s
|
||||
end
|
||||
|
||||
# Updates all or a specific set of plugins.
|
||||
def update_plugins(specific)
|
||||
Vagrant::Bundler.instance.update(installed_plugins, specific)
|
||||
rescue ::Bundler::BundlerError => e
|
||||
raise Errors::BundlerError, message: e.to_s
|
||||
end
|
||||
|
||||
# This returns the list of plugins that should be enabled.
|
||||
|
|
|
@ -33,6 +33,7 @@ module Vagrant
|
|||
"vagrant_version" => Vagrant::VERSION,
|
||||
"gem_version" => opts[:version] || "",
|
||||
"require" => opts[:require] || "",
|
||||
"sources" => opts[:sources] || [],
|
||||
}
|
||||
|
||||
save!
|
||||
|
|
|
@ -24,6 +24,7 @@ module VagrantPlugins
|
|||
def call(env)
|
||||
entrypoint = env[:plugin_entry_point]
|
||||
plugin_name = env[:plugin_name]
|
||||
sources = env[:plugin_sources]
|
||||
version = env[:plugin_version]
|
||||
|
||||
# Determine the plugin name we'll look for in the installed set
|
||||
|
@ -52,7 +53,10 @@ module VagrantPlugins
|
|||
|
||||
manager = Vagrant::Plugin::Manager.instance
|
||||
plugin_spec = manager.install_plugin(
|
||||
plugin_name, version: version, require: entrypoint)
|
||||
plugin_name,
|
||||
version: version,
|
||||
require: entrypoint,
|
||||
sources: sources,)
|
||||
|
||||
# Record it so we can uninstall if something goes wrong
|
||||
@installed_plugin_name = plugin_spec.name
|
||||
|
|
|
@ -254,6 +254,13 @@ en:
|
|||
The box '%{name}' is still stored on disk in the Vagrant 1.0.x
|
||||
format. This box must be upgraded in order to work properly with
|
||||
this version of Vagrant.
|
||||
bundler_error: |-
|
||||
Bundler, the underlying system Vagrant uses to install plugins,
|
||||
reported an error. The error is shown below. These errors are usually
|
||||
caused by misconfigured plugin installations or transient network
|
||||
issues. The error from Bundler is:
|
||||
|
||||
%{message}
|
||||
cfengine_bootstrap_failed: |-
|
||||
Failed to bootstrap CFEngine. Please see the output above to
|
||||
see what went wrong and address the issue.
|
||||
|
|
|
@ -18,7 +18,7 @@ describe VagrantPlugins::CommandPlugin::Action::InstallGem do
|
|||
it "should install the plugin" do
|
||||
spec = Gem::Specification.new
|
||||
manager.should_receive(:install_plugin).with(
|
||||
"foo", version: nil, require: nil).once.and_return(spec)
|
||||
"foo", version: nil, require: nil, sources: nil).once.and_return(spec)
|
||||
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
|
@ -29,7 +29,7 @@ describe VagrantPlugins::CommandPlugin::Action::InstallGem do
|
|||
it "should specify the version if given" do
|
||||
spec = Gem::Specification.new
|
||||
manager.should_receive(:install_plugin).with(
|
||||
"foo", version: "bar", require: nil).once.and_return(spec)
|
||||
"foo", version: "bar", require: nil, sources: nil).once.and_return(spec)
|
||||
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
|
@ -41,7 +41,7 @@ describe VagrantPlugins::CommandPlugin::Action::InstallGem do
|
|||
it "should specify the entrypoint if given" do
|
||||
spec = Gem::Specification.new
|
||||
manager.should_receive(:install_plugin).with(
|
||||
"foo", version: "bar", require: "baz").once.and_return(spec)
|
||||
"foo", version: "bar", require: "baz", sources: nil).once.and_return(spec)
|
||||
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
|
@ -50,6 +50,18 @@ describe VagrantPlugins::CommandPlugin::Action::InstallGem do
|
|||
env[:plugin_version] = "bar"
|
||||
subject.call(env)
|
||||
end
|
||||
|
||||
it "should specify the sources if given" do
|
||||
spec = Gem::Specification.new
|
||||
manager.should_receive(:install_plugin).with(
|
||||
"foo", version: nil, require: nil, sources: ["foo"]).once.and_return(spec)
|
||||
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
env[:plugin_name] = "foo"
|
||||
env[:plugin_sources] = ["foo"]
|
||||
subject.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#recover" do
|
||||
|
|
|
@ -16,12 +16,83 @@ describe Vagrant::Plugin::Manager do
|
|||
Pathname.new(p)
|
||||
end
|
||||
|
||||
let(:bundler) { double("bundler") }
|
||||
|
||||
after do
|
||||
path.unlink if path.file?
|
||||
end
|
||||
|
||||
before do
|
||||
Vagrant::Bundler.stub(instance: bundler)
|
||||
end
|
||||
|
||||
subject { described_class.new(path) }
|
||||
|
||||
describe "#install_plugin" do
|
||||
it "installs the plugin and adds it to the state file" do
|
||||
specs = Array.new(5) { Gem::Specification.new }
|
||||
specs[3].name = "foo"
|
||||
bundler.should_receive(:install).once.with do |plugins|
|
||||
expect(plugins).to have_key("foo")
|
||||
end.and_return(specs)
|
||||
|
||||
result = subject.install_plugin("foo")
|
||||
|
||||
# It should return the spec of the installed plugin
|
||||
expect(result).to eql(specs[3])
|
||||
|
||||
# It should've added the plugin to the state
|
||||
expect(subject.installed_plugins).to have_key("foo")
|
||||
end
|
||||
|
||||
it "masks GemNotFound with our error" do
|
||||
bundler.should_receive(:install).and_raise(Bundler::GemNotFound)
|
||||
|
||||
expect { subject.install_plugin("foo") }.
|
||||
to raise_error(Vagrant::Errors::PluginGemNotFound)
|
||||
end
|
||||
|
||||
it "masks bundler errors with our own error" do
|
||||
bundler.should_receive(:install).and_raise(Bundler::InstallError)
|
||||
|
||||
expect { subject.install_plugin("foo") }.
|
||||
to raise_error(Vagrant::Errors::BundlerError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#uninstall_plugin" do
|
||||
it "removes the plugin from the state" do
|
||||
sf = Vagrant::Plugin::StateFile.new(path)
|
||||
sf.add_plugin("foo")
|
||||
|
||||
# Sanity
|
||||
expect(subject.installed_plugins).to have_key("foo")
|
||||
|
||||
# Test
|
||||
bundler.should_receive(:clean).once.with({})
|
||||
|
||||
# Remove it
|
||||
subject.uninstall_plugin("foo")
|
||||
expect(subject.installed_plugins).to_not have_key("foo")
|
||||
end
|
||||
|
||||
it "masks bundler errors with our own error" do
|
||||
bundler.should_receive(:clean).and_raise(Bundler::InstallError)
|
||||
|
||||
expect { subject.uninstall_plugin("foo") }.
|
||||
to raise_error(Vagrant::Errors::BundlerError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update_plugins" do
|
||||
it "masks bundler errors with our own error" do
|
||||
bundler.should_receive(:update).and_raise(Bundler::InstallError)
|
||||
|
||||
expect { subject.update_plugins([]) }.
|
||||
to raise_error(Vagrant::Errors::BundlerError)
|
||||
end
|
||||
end
|
||||
|
||||
context "without state" do
|
||||
describe "#installed_plugins" do
|
||||
it "is empty initially" do
|
||||
|
@ -30,7 +101,6 @@ describe Vagrant::Plugin::Manager do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
context "with state" do
|
||||
before do
|
||||
sf = Vagrant::Plugin::StateFile.new(path)
|
||||
|
|
|
@ -34,6 +34,7 @@ describe Vagrant::Plugin::StateFile do
|
|||
"vagrant_version" => Vagrant::VERSION,
|
||||
"gem_version" => "",
|
||||
"require" => "",
|
||||
"sources" => [],
|
||||
})
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue