core: BoxCheckOutdated can check if a box is outdated
This commit is contained in:
parent
f2509f5c65
commit
e537e02d9d
|
@ -9,6 +9,7 @@ module Vagrant
|
|||
# and are thus available to all plugins as a "standard library" of sorts.
|
||||
module Builtin
|
||||
autoload :BoxAdd, "vagrant/action/builtin/box_add"
|
||||
autoload :BoxCheckOutdated, "vagrant/action/builtin/box_check_outdated"
|
||||
autoload :BoxRemove, "vagrant/action/builtin/box_remove"
|
||||
autoload :Call, "vagrant/action/builtin/call"
|
||||
autoload :Confirm, "vagrant/action/builtin/confirm"
|
||||
|
@ -45,6 +46,14 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
# This actions checks if a box is outdated in a given Vagrant
|
||||
# environment for a single machine.
|
||||
def self.action_box_outdated
|
||||
Builder.new.tap do |b|
|
||||
b.use Builtin::BoxCheckOutdated
|
||||
end
|
||||
end
|
||||
|
||||
# This is the action that will remove a box given a name (and optionally
|
||||
# a provider). This middleware sequence is built-in to Vagrant. Plugins
|
||||
# can hook into this like any other middleware sequence.
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
require "digest/sha1"
|
||||
require "log4r"
|
||||
require "pathname"
|
||||
require "uri"
|
||||
|
||||
require "vagrant/box_metadata"
|
||||
require "vagrant/util/downloader"
|
||||
require "vagrant/util/file_checksum"
|
||||
require "vagrant/util/platform"
|
||||
|
||||
module Vagrant
|
||||
module Action
|
||||
module Builtin
|
||||
# This middleware checks if there are outdated boxes. By default,
|
||||
# it only checks locally, but if `box_outdated_refresh` is set, it
|
||||
# will refresh the metadata associated with a box.
|
||||
class BoxCheckOutdated
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new(
|
||||
"vagrant::action::builtin::box_check_outdated")
|
||||
end
|
||||
|
||||
def call(env)
|
||||
machine = env[:machine]
|
||||
|
||||
if !machine.box
|
||||
# The box doesn't exist. I suppose technically that means
|
||||
# that it is "outdated" but we show a specialized error
|
||||
# message anyways.
|
||||
raise Errors::BoxOutdatedNoBox, name: machine.config.vm.box
|
||||
end
|
||||
|
||||
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
|
||||
env[:ui].success(I18n.t(
|
||||
"vagrant.box_up_to_date_single",
|
||||
name: machine.box.name,
|
||||
version: machine.box.version))
|
||||
|
||||
env[:box_outdated] = false
|
||||
return @app.call(env)
|
||||
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
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -172,6 +172,14 @@ module Vagrant
|
|||
error_key(:box_metadata_malformed)
|
||||
end
|
||||
|
||||
class BoxOutdatedNoBox < VagrantError
|
||||
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
|
||||
|
|
|
@ -5,10 +5,34 @@ module VagrantPlugins
|
|||
module Command
|
||||
class Outdated < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
OptionParser.new do |o|
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant box outdated"
|
||||
o.separator ""
|
||||
|
||||
o.on("--global", "Check all boxes installed.") do |g|
|
||||
options[:global] = g
|
||||
end
|
||||
end
|
||||
|
||||
argv = parse_options(opts)
|
||||
|
||||
# If we're checking the boxes globally, then do that.
|
||||
if options[:global]
|
||||
outdated_global
|
||||
return 0
|
||||
end
|
||||
|
||||
with_target_vms(argv) do |machine|
|
||||
@env.action_runner.run(Vagrant::Action.action_box_outdated, {
|
||||
box_outdated_refresh: true,
|
||||
machine: machine,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def outdated_global
|
||||
boxes = {}
|
||||
@env.boxes.all.reverse.each do |name, version, provider|
|
||||
next if boxes[name]
|
||||
|
@ -49,9 +73,6 @@ module VagrantPlugins
|
|||
latest: latest.to_s,))
|
||||
end
|
||||
end
|
||||
|
||||
# Success, exit status 0
|
||||
0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,12 +30,18 @@ en:
|
|||
Loading metadata for box '%{name}'
|
||||
box_outdated: |-
|
||||
* '%{name}' is outdated! Current: %{current}. Latest: %{latest}
|
||||
box_outdated_single: |-
|
||||
A newer version of the box '%{name}' is available! You currently
|
||||
have version '%{current}'. The latest is version '%{latest}'. Run
|
||||
`vagrant box update` to update.
|
||||
box_outdated_metadata_error: |-
|
||||
* '%{name}': Error loading metadata: %{message}
|
||||
box_outdated_no_metadata: |-
|
||||
* '%{name}' wasn't added from a catalog, no version information
|
||||
box_up_to_date: |-
|
||||
* '%{name}' (v%{version}) is up to date
|
||||
box_up_to_date_single: |-
|
||||
Your box '%{name}' (v%{version}) is running the latest version.
|
||||
cfengine_bootstrapping: |-
|
||||
Bootstrapping CFEngine with policy server: %{policy_server}...
|
||||
cfengine_bootstrapping_policy_hub: |-
|
||||
|
@ -357,6 +363,15 @@ 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
|
||||
with `vagrant box add` to download an appropriate version.
|
||||
box_provider_doesnt_match: |-
|
||||
The box you attempted to add doesn't match the provider you specified.
|
||||
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
describe Vagrant::Action::Builtin::BoxCheckOutdated do
|
||||
include_context "unit"
|
||||
|
||||
let(:app) { lambda { |env| } }
|
||||
let(:env) { {
|
||||
machine: machine,
|
||||
} }
|
||||
|
||||
subject { described_class.new(app, env) }
|
||||
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
isolated_environment.tap do |env|
|
||||
env.vagrantfile("")
|
||||
end
|
||||
end
|
||||
|
||||
let(:iso_vagrant_env) { iso_env.create_vagrant_env }
|
||||
|
||||
let(:box) do
|
||||
box_dir = iso_env.box3("foo", "1.0", :virtualbox)
|
||||
Vagrant::Box.new("foo", :virtualbox, "1.0", box_dir)
|
||||
end
|
||||
let(:machine) { iso_vagrant_env.machine(iso_vagrant_env.machine_names[0], :dummy) }
|
||||
|
||||
context "no box" do
|
||||
it "raises an exception if the machine doesn't have a box yet" do
|
||||
machine.stub(box: nil)
|
||||
|
||||
app.should_receive(:call).never
|
||||
|
||||
expect { subject.call(env) }.
|
||||
to raise_error(Vagrant::Errors::BoxOutdatedNoBox)
|
||||
end
|
||||
end
|
||||
|
||||
context "box with 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
|
||||
|
||||
before do
|
||||
machine.stub(box: box)
|
||||
end
|
||||
|
||||
it "raises an exception" do
|
||||
app.should_receive(:call).never
|
||||
|
||||
expect { subject.call(env) }.
|
||||
to raise_error(Vagrant::Errors::BoxOutdatedNoMetadata)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a 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) }
|
||||
|
||||
it "isn't outdated if it isn't" 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)
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(env[:box_outdated]).to be_false
|
||||
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
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue