vaguerent/test/unit/vagrant/vagrantfile_test.rb
Chris Roberts 648be1369f Fallback to Vagrantfile configuration when local metadata lookup fails
The project local metadata file may contain invalid information to properly
lookup the configured box. This may occur if the file has been moved,
modified, or the backing box has been removed. In those cases, fall back
to the configuration defined in the Vagrantfile to load the box.
2018-11-02 13:59:53 -07:00

493 lines
13 KiB
Ruby

require File.expand_path("../../base", __FILE__)
require "pathname"
require "tmpdir"
require "vagrant/vagrantfile"
describe Vagrant::Vagrantfile do
include_context "unit"
let(:keys) { [] }
let(:loader) {
Vagrant::Config::Loader.new(
Vagrant::Config::VERSIONS, Vagrant::Config::VERSIONS_ORDER)
}
subject { described_class.new(loader, keys) }
before do
keys << :test
end
def configure(&block)
loader.set(:test, [["2", block]])
end
# A helper to register a provider for use in tests.
def register_provider(name, config_class=nil, options=nil)
provider_cls = Class.new(VagrantTests::DummyProvider) do
if options && options[:unusable]
def self.usable?(raise_error=false)
raise Vagrant::Errors::VagrantError if raise_error
false
end
end
end
register_plugin("2") do |p|
p.provider(name, options) { provider_cls }
if config_class
p.config(name, :provider) { config_class }
end
end
provider_cls
end
describe "#config" do
it "exposes the global configuration" do
configure do |config|
config.vm.box = "what"
end
expect(subject.config.vm.box).to eq("what")
end
end
describe "#machine" do
let(:boxes) { Vagrant::BoxCollection.new(iso_env.boxes_dir) }
let(:data_path) { Pathname.new(Dir.mktmpdir("vagrant-machine-data-path")) }
let(:env) { iso_env.create_vagrant_env }
let(:iso_env) { isolated_environment }
let(:vagrantfile) { described_class.new(loader, keys) }
subject { vagrantfile.machine(:default, :foo, boxes, data_path, env) }
before do
@foo_config_cls = Class.new(Vagrant.plugin("2", "config")) do
attr_accessor :value
end
@provider_cls = register_provider("foo", @foo_config_cls)
configure do |config|
config.vm.box = "foo"
config.vm.provider "foo" do |p|
p.value = "rawr"
end
end
iso_env.box3("foo", "1.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
end
VF
end
after do
FileUtils.rm_rf(data_path.to_s)
end
describe '#data_dir' do
subject { super().data_dir }
it { should eq(data_path) }
end
describe '#env' do
subject { super().env }
it { should equal(env) }
end
describe '#name' do
subject { super().name }
it { should eq(:default) }
end
describe '#provider' do
subject { super().provider }
it { should be_kind_of(@provider_cls) }
end
describe '#provider_name' do
subject { super().provider_name }
it { should eq(:foo) }
end
describe '#vagrantfile' do
subject { super().vagrantfile }
it { should equal(vagrantfile) }
end
it "has the proper box" do
expect(subject.box.name).to eq("foo")
end
it "has the valid configuration" do
expect(subject.config.vm.box).to eq("foo")
end
it "loads the provider-specific configuration" do
expect(subject.provider_config).to be_kind_of(@foo_config_cls)
expect(subject.provider_config.value).to eq("rawr")
end
end
describe "#machine_config" do
let(:iso_env) { isolated_environment }
let(:boxes) { Vagrant::BoxCollection.new(iso_env.boxes_dir) }
it "should return a basic configured machine" do
provider_cls = register_provider("foo")
configure do |config|
config.vm.box = "foo"
end
results = subject.machine_config(:default, :foo, boxes)
box = results[:box]
config = results[:config]
expect(config.vm.box).to eq("foo")
expect(box).to be_nil
expect(results[:provider_cls]).to equal(provider_cls)
end
it "configures without a provider or boxes" do
register_provider("foo")
configure do |config|
config.vm.box = "foo"
end
results = subject.machine_config(:default, nil, nil)
box = results[:box]
config = results[:config]
expect(config.vm.box).to eq("foo")
expect(box).to be_nil
expect(results[:provider_cls]).to be_nil
end
it "configures with sub-machine config" do
register_provider("foo")
configure do |config|
config.ssh.port = "1"
config.vm.box = "base"
config.vm.define "foo" do |f|
f.ssh.port = 100
end
end
results = subject.machine_config(:foo, :foo, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(100)
end
it "configures with box configuration if it exists" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
end
iso_env.box3("base", "1.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
end
VF
results = subject.machine_config(:default, :foo, boxes)
box = results[:box]
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(123)
expect(box).to_not be_nil
expect(box.name).to eq("base")
end
it "does not configure box configuration if set to ignore" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
config.vm.ignore_box_vagrantfile = true
end
iso_env.box3("base", "1.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
config.vm.hostname = "hello"
end
VF
results = subject.machine_config(:default, :foo, boxes)
box = results[:box]
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(nil)
expect(config.vm.hostname).to eq(nil)
expect(box).to_not be_nil
expect(box.name).to eq("base")
end
it "configures with the proper box version" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
config.vm.box_version = "~> 1.2"
end
iso_env.box3("base", "1.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
end
VF
iso_env.box3("base", "1.3", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 245
end
VF
results = subject.machine_config(:default, :foo, boxes)
box = results[:box]
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(245)
expect(box).to_not be_nil
expect(box.name).to eq("base")
expect(box.version).to eq("1.3")
end
it "configures with box config of other supported formats" do
register_provider("foo", nil, box_format: "bar")
configure do |config|
config.vm.box = "base"
end
iso_env.box3("base", "1.0", :bar, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
end
VF
results = subject.machine_config(:default, :foo, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(123)
end
it "loads provider overrides if set" do
register_provider("foo")
register_provider("bar")
configure do |config|
config.ssh.port = 1
config.vm.box = "base"
config.vm.provider "foo" do |_, c|
c.ssh.port = 100
end
end
# Test with the override
results = subject.machine_config(:default, :foo, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(100)
# Test without the override
results = subject.machine_config(:default, :bar, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.ssh.port).to eq(1)
end
it "loads the proper box if in a provider override" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
config.vm.box_version = "1.0"
config.vm.provider "foo" do |_, c|
c.vm.box = "foobox"
c.vm.box_version = "2.0"
end
end
iso_env.box3("base", "1.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 123
end
VF
iso_env.box3("foobox", "2.0", :foo, vagrantfile: <<-VF)
Vagrant.configure("2") do |config|
config.ssh.port = 234
end
VF
results = subject.machine_config(:default, :foo, boxes)
config = results[:config]
box = results[:box]
expect(config.vm.box).to eq("foobox")
expect(config.ssh.port).to eq(234)
expect(config.vm.box_version).to eq("2.0")
expect(box).to_not be_nil
expect(box.name).to eq("foobox")
expect(box.version).to eq("2.0")
end
it "raises an error if the machine is not found" do
expect { subject.machine_config(:foo, :foo, boxes) }.
to raise_error(Vagrant::Errors::MachineNotFound)
end
it "raises an error if the provider is not found" do
expect { subject.machine_config(:default, :foo, boxes) }.
to raise_error(Vagrant::Errors::ProviderNotFound)
end
it "raises an error if the provider is not found but gives suggestion" do
register_provider("foo")
expect { subject.machine_config(:default, :Foo, boxes) }.
to raise_error(Vagrant::Errors::ProviderNotFoundSuggestion)
end
it "raises an error if the provider is not usable" do
register_provider("foo", nil, unusable: true)
expect { subject.machine_config(:default, :foo, boxes) }.
to raise_error(Vagrant::Errors::ProviderNotUsable)
end
context "local box metadata file" do
let(:data_path) { double(:data_path) }
let(:meta_file) { double(:meta_file) }
let(:box_version) { "2.0" }
before do
register_provider("foo")
iso_env.box3("base", "1.0", :foo)
allow(data_path).to receive(:join).with("box_meta").
and_return(meta_file)
allow(meta_file).to receive(:file?).and_return(false)
configure do |config|
config.vm.box = "base"
config.vm.box_version = box_version
end
end
it "checks for local box metadata file" do
expect(meta_file).to receive(:file?).and_return(false)
subject.machine_config(:default, :foo, boxes, data_path)
end
context "file exists" do
let(:meta_file_content) { '{"name":"base","version":"1.0"}' }
before do
allow(meta_file).to receive(:file?).and_return(true)
allow(meta_file).to receive(:read).and_return(meta_file_content)
end
it "reads the local box metadata file" do
expect(meta_file).to receive(:read).and_return(meta_file_content)
subject.machine_config(:default, :foo, boxes, data_path)
end
it "properly loads the box defined in metadata" do
result = subject.machine_config(:default, :foo, boxes, data_path)
expect(result[:box]).not_to be_nil
end
context "with invalid box version" do
let(:box_version) { "1.0" }
let(:meta_file_content) { '{"name":"base","version":"2.0"}' }
it "loads box base on Vagrantfile information" do
result = subject.machine_config(:default, :foo, boxes, data_path)
expect(result[:box]).not_to be_nil
end
end
end
end
end
describe "#machine_names" do
it "returns the default name when single-VM" do
configure { |config| }
expect(subject.machine_names).to eq([:default])
end
it "returns all of the names in a multi-VM" do
configure do |config|
config.vm.define "foo"
config.vm.define "bar"
end
expect(subject.machine_names).to eq(
[:foo, :bar])
end
end
describe "#machine_names_and_options" do
it "returns the default name" do
configure { |config| }
expect(subject.machine_names_and_options).to eq({
default: { config_version: "2" },
})
end
it "returns all the machines" do
configure do |config|
config.vm.define "foo"
config.vm.define "bar", autostart: false
config.vm.define "baz", autostart: true
end
expect(subject.machine_names_and_options).to eq({
foo: { config_version: "2" },
bar: { config_version: "2", autostart: false },
baz: { config_version: "2", autostart: true },
})
end
end
describe "#primary_machine_name" do
it "returns the default name when single-VM" do
configure { |config| }
expect(subject.primary_machine_name).to eq(:default)
end
it "returns the designated machine in multi-VM" do
configure do |config|
config.vm.define "foo"
config.vm.define "bar", primary: true
config.vm.define "baz"
end
expect(subject.primary_machine_name).to eq(:bar)
end
it "returns nil if no designation in multi-VM" do
configure do |config|
config.vm.define "foo"
config.vm.define "baz"
end
expect(subject.primary_machine_name).to be_nil
end
end
end