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