core: BoxCheckOutdated is *much* simpler, unified logic, tests
This commit is contained in:
parent
1a5ad9f3d5
commit
61a1082d65
|
@ -20,11 +20,6 @@ module Vagrant
|
|||
if !machine.config.vm.box_check_update
|
||||
return @app.call(env)
|
||||
end
|
||||
|
||||
if !env.has_key?(:box_outdated_refresh)
|
||||
env[:box_outdated_refresh] = true
|
||||
env[:box_outdated_ignore_errors] = true
|
||||
end
|
||||
end
|
||||
|
||||
if !machine.box
|
||||
|
@ -33,22 +28,28 @@ module Vagrant
|
|||
# message anyways.
|
||||
raise Errors::BoxOutdatedNoBox, name: machine.config.vm.box
|
||||
end
|
||||
box = machine.box
|
||||
constraints = machine.config.vm.box_version
|
||||
|
||||
if env[:box_outdated_refresh]
|
||||
env[:ui].output(I18n.t(
|
||||
"vagrant.box_outdated_checking_with_refresh",
|
||||
name: machine.box.name))
|
||||
begin
|
||||
check_outdated_refresh(env)
|
||||
rescue Errors::VagrantError => e
|
||||
raise if !env[:box_outdated_ignore_errors]
|
||||
env[:ui].detail(I18n.t(
|
||||
"vagrant.box_outdated_metadata_error",
|
||||
message: e.message))
|
||||
end
|
||||
else
|
||||
@logger.info("Checking if box is outdated locally")
|
||||
check_outdated_local(env)
|
||||
env[:ui].output(I18n.t(
|
||||
"vagrant.box_outdated_checking_with_refresh",
|
||||
name: box.name))
|
||||
update = nil
|
||||
begin
|
||||
update = box.has_update?(constraints)
|
||||
rescue Errors::VagrantError => e
|
||||
raise if !env[:box_outdated_ignore_errors]
|
||||
env[:ui].detail(I18n.t(
|
||||
"vagrant.box_outdated_metadata_error_single",
|
||||
message: e.message))
|
||||
end
|
||||
env[:box_outdated] = update != nil
|
||||
if update
|
||||
env[:ui].warn(I18n.t(
|
||||
"vagrant.box_outdated_single",
|
||||
name: update[0].name,
|
||||
current: box.version,
|
||||
latest: update[1].version))
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
|
@ -71,38 +72,6 @@ module Vagrant
|
|||
|
||||
env[:box_outdated] = false
|
||||
end
|
||||
|
||||
def check_outdated_refresh(env)
|
||||
machine = env[:machine]
|
||||
|
||||
if !machine.box.metadata_url
|
||||
# This box doesn't have a metadata URL, so we can't
|
||||
# possibly check the version information.
|
||||
raise Errors::BoxOutdatedNoMetadata, name: machine.box.name
|
||||
end
|
||||
|
||||
md = machine.box.load_metadata
|
||||
newer = md.version(
|
||||
"> #{machine.box.version}", provider: machine.box.provider)
|
||||
if !newer
|
||||
if env[:box_outdated_success_ui]
|
||||
env[:ui].success(I18n.t(
|
||||
"vagrant.box_up_to_date_single",
|
||||
name: machine.box.name,
|
||||
version: machine.box.version))
|
||||
end
|
||||
|
||||
env[:box_outdated] = false
|
||||
return
|
||||
end
|
||||
|
||||
env[:ui].warn(I18n.t(
|
||||
"vagrant.box_outdated_single",
|
||||
name: machine.box.name,
|
||||
current: machine.box.version,
|
||||
latest: newer.version))
|
||||
env[:box_outdated] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
require "log4r"
|
||||
|
||||
module Vagrant
|
||||
module Action
|
||||
module Builtin
|
||||
# This middleware updates a specific box if there are updates available.
|
||||
class BoxUpdate
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new(
|
||||
"vagrant::action::builtin::box_update")
|
||||
end
|
||||
|
||||
def call(env)
|
||||
machine = env[:machine]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -104,6 +104,32 @@ module Vagrant
|
|||
BoxMetadata.new(File.open(tf.path, "r"))
|
||||
end
|
||||
|
||||
# Checks if the box has an update and returns the metadata, version,
|
||||
# and provider. If the box doesn't have an update that satisfies the
|
||||
# constraints, it will return nil.
|
||||
#
|
||||
# This will potentially make a network call if it has to load the
|
||||
# metadata from the network.
|
||||
#
|
||||
# @param [String] version Version constraints the update must
|
||||
# satisfy. If nil, the version constrain defaults to being a
|
||||
# larger version than this box.
|
||||
# @return [Array]
|
||||
def has_update?(version=nil)
|
||||
if !@metadata_url
|
||||
raise Errors::BoxUpdateNoMetadata, name: @name
|
||||
end
|
||||
|
||||
version += ", " if version
|
||||
version ||= ""
|
||||
version += "> #{@version}"
|
||||
md = self.load_metadata
|
||||
newer = md.version(version, provider: @provider)
|
||||
return nil if !newer
|
||||
|
||||
[md, newer, newer.provider(@provider)]
|
||||
end
|
||||
|
||||
# This repackages this box and outputs it to the given path.
|
||||
#
|
||||
# @param [Pathname] path The full path (filename included) of where
|
||||
|
|
|
@ -176,10 +176,6 @@ module Vagrant
|
|||
error_key(:box_outdated_no_box)
|
||||
end
|
||||
|
||||
class BoxOutdatedNoMetadata < VagrantError
|
||||
error_key(:box_outdated_no_metadata)
|
||||
end
|
||||
|
||||
class BoxProviderDoesntMatch < VagrantError
|
||||
error_key(:box_provider_doesnt_match)
|
||||
end
|
||||
|
@ -204,6 +200,10 @@ module Vagrant
|
|||
error_key(:untar_failure, "vagrant.actions.box.unpackage")
|
||||
end
|
||||
|
||||
class BoxUpdateNoMetadata < VagrantError
|
||||
error_key(:box_update_no_metadata)
|
||||
end
|
||||
|
||||
class BoxVerificationFailed < VagrantError
|
||||
error_key(:failed, "vagrant.actions.box.verify")
|
||||
end
|
||||
|
|
|
@ -8,7 +8,13 @@ module VagrantPlugins
|
|||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant box outdated"
|
||||
o.banner = "Usage: vagrant box outdated [options]"
|
||||
o.separator ""
|
||||
o.separator "Checks if there is a new version available for the box"
|
||||
o.separator "that are you are using. If you pass in the --global flag,"
|
||||
o.separator "all boxes will be checked for updates."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("--global", "Check all boxes installed.") do |g|
|
||||
|
@ -17,6 +23,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
# If we're checking the boxes globally, then do that.
|
||||
if options[:global]
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandBox
|
||||
module Command
|
||||
class Update < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant box update [options]"
|
||||
o.separator ""
|
||||
o.separator "Updates the box that is in use in the current Vagrant environment,"
|
||||
o.separator "if there any updates available. This does not destroy/recreate the"
|
||||
o.separator "machine, so you'll have to do that to see changes."
|
||||
o.separator ""
|
||||
o.separator "To update a specific box (not tied to a Vagrant environment), use the"
|
||||
o.separator "--box flag."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("--box VALUE", String, "Update a specific box") do |b|
|
||||
options[:box] = b
|
||||
end
|
||||
end
|
||||
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
with_target_vms(argv) do |machine|
|
||||
@env.action_runner.run(Vagrant::Action.action_box_update, {
|
||||
box_outdated_force: true,
|
||||
box_outdated_refresh: true,
|
||||
box_outdated_success_ui: true,
|
||||
machine: machine,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -37,7 +37,7 @@ en:
|
|||
installed, but your Vagrant machine is running against
|
||||
version '%{old}'. To update to version '%{new}',
|
||||
destroy and recreate your machine.
|
||||
box_outdated_metadata_error: |-
|
||||
box_outdated_metadata_error_single: |-
|
||||
Error loading box metadata while attempting to check for
|
||||
updates: %{message}
|
||||
box_outdated_single: |-
|
||||
|
@ -373,11 +373,6 @@ en:
|
|||
that this issue can be fixed.
|
||||
|
||||
%{error}
|
||||
box_outdated_no_metadata: |-
|
||||
The box '%{name}' is not a versioned box. The box was added
|
||||
directly instead of from a box catalog. Vagrant can only
|
||||
check the versions of boxes that were added from a catalog
|
||||
such as from the public Vagrant Server.
|
||||
box_outdated_no_box: |-
|
||||
The box '%{name}' isn't downloaded or added yet, so we can't
|
||||
check if it is outdated. Run a `vagrant up` or add the box
|
||||
|
@ -409,6 +404,11 @@ en:
|
|||
the provider specified. Please double-check and try again.
|
||||
|
||||
The providers for this are: %{providers}
|
||||
box_update_no_metadata: |-
|
||||
The box '%{name}' is not a versioned box. The box was added
|
||||
directly instead of from a box catalog. Vagrant can only
|
||||
check the versions of boxes that were added from a catalog
|
||||
such as from the public Vagrant Server.
|
||||
bundler_disabled: |-
|
||||
Vagrant's built-in bundler management mechanism is disabled because
|
||||
Vagrant is running in an external bundler environment. In these
|
||||
|
|
|
@ -23,8 +23,11 @@ describe Vagrant::Action::Builtin::BoxCheckOutdated do
|
|||
|
||||
let(:box) do
|
||||
box_dir = iso_env.box3("foo", "1.0", :virtualbox)
|
||||
Vagrant::Box.new("foo", :virtualbox, "1.0", box_dir)
|
||||
Vagrant::Box.new("foo", :virtualbox, "1.0", box_dir).tap do |b|
|
||||
b.stub(has_update?: nil)
|
||||
end
|
||||
end
|
||||
|
||||
let(:machine) do
|
||||
m = iso_vagrant_env.machine(iso_vagrant_env.machine_names[0], :dummy)
|
||||
m.config.vm.box_check_update = true
|
||||
|
@ -69,185 +72,63 @@ describe Vagrant::Action::Builtin::BoxCheckOutdated do
|
|||
end
|
||||
end
|
||||
|
||||
context "without refreshing" do
|
||||
before do
|
||||
env[:box_outdated_refresh] = false
|
||||
context "with a box" do
|
||||
it "sets env if no update" do
|
||||
box.should_receive(:has_update?).and_return(nil)
|
||||
|
||||
machine.stub(box: box)
|
||||
end
|
||||
|
||||
it "isn't outdated if there are no newer boxes" do
|
||||
iso_env.box3("foo", "0.5", :virtualbox)
|
||||
|
||||
app.should_receive(:call).with(env)
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_false
|
||||
end
|
||||
|
||||
it "is outdated if there are newer boxes" do
|
||||
iso_env.box3("foo", "1.5", :virtualbox)
|
||||
it "sets env if there is an update" do
|
||||
md = Vagrant::BoxMetadata.new(StringIO.new(<<-RAW))
|
||||
{
|
||||
"name": "foo",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0"
|
||||
},
|
||||
{
|
||||
"version": "1.1",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
|
||||
app.should_receive(:call).with(env)
|
||||
box.should_receive(:has_update?).with(machine.config.vm.box_version).
|
||||
and_return([md, md.version("1.1"), md.version("1.1").provider("virtualbox")])
|
||||
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_true
|
||||
end
|
||||
end
|
||||
|
||||
context "with refreshing" do
|
||||
before do
|
||||
env[:box_outdated_refresh] = true
|
||||
it "raises error if has_update? errors" do
|
||||
box.should_receive(:has_update?).and_raise(Vagrant::Errors::VagrantError)
|
||||
|
||||
app.should_receive(:call).never
|
||||
|
||||
expect { subject.call(env) }.to raise_error(Vagrant::Errors::VagrantError)
|
||||
end
|
||||
|
||||
context "no metadata URL" do
|
||||
let(:box) do
|
||||
box_dir = iso_env.box3("foo", "1.0", :virtualbox)
|
||||
Vagrant::Box.new("foo", :virtualbox, "1.0", box_dir)
|
||||
end
|
||||
it "doesn't raise an error if ignore errors is on" do
|
||||
env[:box_outdated_ignore_errors] = true
|
||||
|
||||
before do
|
||||
machine.stub(box: box)
|
||||
end
|
||||
box.should_receive(:has_update?).and_raise(Vagrant::Errors::VagrantError)
|
||||
app.should_receive(:call).with(env).once
|
||||
|
||||
it "raises an exception" do
|
||||
app.should_receive(:call).never
|
||||
|
||||
expect { subject.call(env) }.
|
||||
to raise_error(Vagrant::Errors::BoxOutdatedNoMetadata)
|
||||
end
|
||||
end
|
||||
|
||||
context "with metadata URL" do
|
||||
let(:metadata_url) do
|
||||
Tempfile.new("vagrant").tap do |f|
|
||||
f.close
|
||||
end
|
||||
end
|
||||
|
||||
let(:box_dir) { iso_env.box3("foo", "1.0", :virtualbox) }
|
||||
|
||||
context "isn't outdated" do
|
||||
before do
|
||||
File.open(metadata_url.path, "w") do |f|
|
||||
f.write(<<-RAW)
|
||||
{
|
||||
"name": "foo/bar",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "#{iso_env.box2_file(:virtualbox)}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
end
|
||||
|
||||
box = Vagrant::Box.new(
|
||||
"foo", :virtualbox, "1.0", box_dir,
|
||||
metadata_url: metadata_url.path)
|
||||
machine.stub(box: box)
|
||||
end
|
||||
|
||||
it "marks it isn't outdated" do
|
||||
app.should_receive(:call).with(env)
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_false
|
||||
end
|
||||
|
||||
it "talks to the UI" do
|
||||
env[:box_outdated_success_ui] = true
|
||||
|
||||
app.should_receive(:call).with(env)
|
||||
env[:ui].should_receive(:success)
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_false
|
||||
end
|
||||
|
||||
it "doesn't talk to UI if it is told" do
|
||||
app.should_receive(:call).with(env)
|
||||
env[:ui].should_receive(:success).never
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_false
|
||||
end
|
||||
end
|
||||
|
||||
it "is outdated if it is" do
|
||||
File.open(metadata_url.path, "w") do |f|
|
||||
f.write(<<-RAW)
|
||||
{
|
||||
"name": "foo/bar",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0"
|
||||
},
|
||||
{
|
||||
"version": "1.5",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "#{iso_env.box2_file(:virtualbox)}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
end
|
||||
|
||||
box = Vagrant::Box.new(
|
||||
"foo", :virtualbox, "1.0", box_dir, metadata_url: metadata_url.path)
|
||||
machine.stub(box: box)
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_true
|
||||
end
|
||||
|
||||
it "isn't outdated if the newer box is for another provider" do
|
||||
File.open(metadata_url.path, "w") do |f|
|
||||
f.write(<<-RAW)
|
||||
{
|
||||
"name": "foo/bar",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0"
|
||||
},
|
||||
{
|
||||
"version": "1.5",
|
||||
"providers": [
|
||||
{
|
||||
"name": "vmware",
|
||||
"url": "#{iso_env.box2_file(:vmware)}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
end
|
||||
|
||||
box = Vagrant::Box.new(
|
||||
"foo", :virtualbox, "1.0", box_dir, metadata_url: metadata_url.path)
|
||||
machine.stub(box: box)
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_false
|
||||
end
|
||||
expect { subject.call(env) }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
require File.expand_path("../../base", __FILE__)
|
||||
|
||||
require "pathname"
|
||||
require "stringio"
|
||||
require "tempfile"
|
||||
|
||||
require "vagrant/box_metadata"
|
||||
|
||||
describe Vagrant::Box do
|
||||
include_context "unit"
|
||||
|
||||
|
@ -76,6 +79,116 @@ describe Vagrant::Box do
|
|||
end
|
||||
end
|
||||
|
||||
context "#has_update?" do
|
||||
subject do
|
||||
described_class.new(
|
||||
name, provider, version, directory,
|
||||
metadata_url: "foo")
|
||||
end
|
||||
|
||||
it "raises an exception if no metadata_url is set" do
|
||||
subject = described_class.new(
|
||||
name, provider, version, directory)
|
||||
|
||||
expect { subject.has_update?("> 0") }.
|
||||
to raise_error(Vagrant::Errors::BoxUpdateNoMetadata)
|
||||
end
|
||||
|
||||
it "returns nil if there is no update" do
|
||||
metadata = Vagrant::BoxMetadata.new(StringIO.new(<<-RAW))
|
||||
{
|
||||
"name": "foo",
|
||||
"versions": [
|
||||
{ "version": "1.0" }
|
||||
]
|
||||
}
|
||||
RAW
|
||||
|
||||
subject.stub(load_metadata: metadata)
|
||||
|
||||
expect(subject.has_update?).to be_nil
|
||||
end
|
||||
|
||||
it "returns the updated box info if there is an update available" do
|
||||
metadata = Vagrant::BoxMetadata.new(StringIO.new(<<-RAW))
|
||||
{
|
||||
"name": "foo",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0"
|
||||
},
|
||||
{
|
||||
"version": "1.1",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
|
||||
subject.stub(load_metadata: metadata)
|
||||
|
||||
result = subject.has_update?
|
||||
expect(result).to_not be_nil
|
||||
|
||||
expect(result[0]).to be_kind_of(Vagrant::BoxMetadata)
|
||||
expect(result[1]).to be_kind_of(Vagrant::BoxMetadata::Version)
|
||||
expect(result[2]).to be_kind_of(Vagrant::BoxMetadata::Provider)
|
||||
|
||||
expect(result[0].name).to eq("foo")
|
||||
expect(result[1].version).to eq("1.1")
|
||||
expect(result[2].url).to eq("bar")
|
||||
end
|
||||
|
||||
it "returns the updated box info within constraints" do
|
||||
metadata = Vagrant::BoxMetadata.new(StringIO.new(<<-RAW))
|
||||
{
|
||||
"name": "foo",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0"
|
||||
},
|
||||
{
|
||||
"version": "1.1",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "bar"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.4",
|
||||
"providers": [
|
||||
{
|
||||
"name": "virtualbox",
|
||||
"url": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
RAW
|
||||
|
||||
subject.stub(load_metadata: metadata)
|
||||
|
||||
result = subject.has_update?(">= 1.1, < 1.4")
|
||||
expect(result).to_not be_nil
|
||||
|
||||
expect(result[0]).to be_kind_of(Vagrant::BoxMetadata)
|
||||
expect(result[1]).to be_kind_of(Vagrant::BoxMetadata::Version)
|
||||
expect(result[2]).to be_kind_of(Vagrant::BoxMetadata::Provider)
|
||||
|
||||
expect(result[0].name).to eq("foo")
|
||||
expect(result[1].version).to eq("1.1")
|
||||
expect(result[2].url).to eq("bar")
|
||||
end
|
||||
end
|
||||
|
||||
context "#load_metadata" do
|
||||
let(:metadata_url) do
|
||||
Tempfile.new("vagrant").tap do |f|
|
||||
|
|
Loading…
Reference in New Issue