Add test coverage for architecture support

This commit is contained in:
Chris Roberts 2023-07-28 10:40:32 -07:00
parent 51adb12547
commit 6e13612111
19 changed files with 1753 additions and 205 deletions

View File

@ -67,4 +67,16 @@ describe VagrantPlugins::CommandBox::Command::Add do
to raise_error(Vagrant::Errors::CLIInvalidUsage) to raise_error(Vagrant::Errors::CLIInvalidUsage)
end end
end end
context "with architecture flag" do
let(:argv) { ["foo", "--architecture", "test-arch"] }
it "executes the runner with box architecture set" do
expect(action_runner).to receive(:run) do |_, opts|
expect(opts[:box_architecture]).to eq("test-arch")
end
subject.execute
end
end
end end

View File

@ -81,4 +81,40 @@ describe VagrantPlugins::CommandBox::Command::Remove do
to raise_error(Vagrant::Errors::CLIInvalidUsage) to raise_error(Vagrant::Errors::CLIInvalidUsage)
end end
end end
context "with architecture flag" do
let(:argv) { ["foo", "--architecture", "test-arch"] }
it "should execute runner with box architecture set" do
expect(action_runner).to receive(:run) do |_, opts|
expect(opts[:box_architecture]).to eq("test-arch")
end
subject.execute
end
end
context "with all providers flag" do
let(:argv) { ["foo", "--all-providers"] }
it "should execute runner with all providers enabled" do
expect(action_runner).to receive(:run) do |_, opts|
expect(opts[:box_remove_all_providers]).to be(true)
end
subject.execute
end
end
context "with all architectures flag" do
let(:argv) { ["foo", "--all-architectures"] }
it "should execute runner with all architectures enabled" do
expect(action_runner).to receive(:run) do |_, opts|
expect(opts[:box_remove_all_architectures]).to be(true)
end
subject.execute
end
end
end end

View File

@ -37,18 +37,16 @@ describe VagrantPlugins::CommandBox::Command::Update do
describe "execute" do describe "execute" do
context "updating specific box" do context "updating specific box" do
let(:argv) { ["--box", "foo"] } let(:argv) { ["--box", "foo"] }
let(:scratch) { Dir.mktmpdir("vagrant-test-command-box-update-execute") } let(:scratch) { Dir.mktmpdir("vagrant-test-command-box-update-execute") }
let(:metadata_url) { Pathname.new(scratch).join("metadata.json") } let(:metadata_url) { Pathname.new(scratch).join("metadata.json") }
let(:box_args) { ["foo", "1.0", :virtualbox] }
let(:box_opts) { {metadata_url: metadata_url.to_s} }
before do before do
metadata_url.open("w") do |f| metadata_url.open("w") do |f|
f.write("") f.write("")
end end
test_iso_env.box3( test_iso_env.box3(*box_args, **box_opts)
"foo", "1.0", :virtualbox, metadata_url: metadata_url.to_s)
end end
after do after do
@ -72,43 +70,43 @@ describe VagrantPlugins::CommandBox::Command::Update do
it "does the correct update if there is an update" do it "does the correct update if there is an update" do
metadata_url.open("w") do |f| metadata_url.open("w") do |f|
f.write(<<-RAW) f.write(
{ {
"name": "foo", name: "foo",
"versions": [ versions: [
{
"version": "1.0"
},
{
"version": "1.8",
"providers": [
{ {
"name": "virtualbox", version: "1.0"
"url": "bar" },
}
]
},
{
"version": "1.10",
"providers": [
{ {
"name": "virtualbox", version: "1.8",
"url": "bar" providers: [
} {
] name: "virtualbox",
}, url: "bar"
{ }
"version": "1.11", ]
"providers": [ },
{ {
"name": "virtualbox", version: "1.10",
"url": "bar" providers: [
{
name: "virtualbox",
url: "bar"
}
]
},
{
version: "1.11",
providers: [
{
name: "virtualbox",
url: "bar"
}
]
} }
] ]
} }.to_json
] )
}
RAW
end end
action_called = false action_called = false
@ -147,25 +145,25 @@ describe VagrantPlugins::CommandBox::Command::Update do
it "updates the proper box" do it "updates the proper box" do
metadata_url.open("w") do |f| metadata_url.open("w") do |f|
f.write(<<-RAW) f.write(
{ {
"name": "foo", name: "foo",
"versions": [ versions: [
{ {
"version": "1.0" version: "1.0"
}, },
{ {
"version": "1.1", version: "1.1",
"providers": [ providers: [
{ {
"name": "vmware", name: "vmware",
"url": "bar" url: "bar"
} }
] ]
} }
] ]
} }.to_json
RAW )
end end
test_iso_env.box3("foo", "1.0", :vmware) test_iso_env.box3("foo", "1.0", :vmware)
@ -200,25 +198,25 @@ describe VagrantPlugins::CommandBox::Command::Update do
it "passes down download options" do it "passes down download options" do
metadata_url.open("w") do |f| metadata_url.open("w") do |f|
f.write(<<-RAW) f.write(
{ {
"name": "foo", name: "foo",
"versions": [ versions: [
{
"version": "1.0"
},
{
"version": "1.1",
"providers": [
{ {
"name": "virtualbox", version: "1.0"
"url": "bar" },
{
version: "1.1",
providers: [
{
name: "virtualbox",
url: "bar"
}
]
} }
] ]
} }.to_json
] )
}
RAW
end end
action_called = false action_called = false
@ -249,6 +247,174 @@ describe VagrantPlugins::CommandBox::Command::Update do
to raise_error(Vagrant::Errors::BoxNotFound) to raise_error(Vagrant::Errors::BoxNotFound)
end end
end end
context "with architecture" do
let(:box_opts) { {metadata_url: metadata_url.to_s, architecture: "test-arch"} }
it "doesn't update if they're up to date" do
called = false
allow(action_runner).to receive(:run) do |callable, opts|
if opts[:box_provider]
called = true
end
opts
end
subject.execute
expect(called).to be(false)
end
it "does the correct update if there is an update" do
metadata_url.open("w") do |f|
f.write(
{
name: "foo",
versions: [
{
version: "1.0"
},
{
version: "1.8",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: "test-arch",
default_architecture: true
}
]
},
{
version: "1.10",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: "test-arch",
default_architecture: true
}
]
},
{
version: "1.11",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: "test-arch",
default_architecture: true
}
]
}
]
}.to_json
)
end
action_called = false
allow(action_runner).to receive(:run) do |action, opts|
if opts[:box_provider]
action_called = true
expect(opts[:box_force]).to eq(nil)
expect(opts[:box_url]).to eq(metadata_url.to_s)
expect(opts[:box_provider]).to eq("virtualbox")
expect(opts[:box_version]).to eq("1.11")
expect(opts[:box_architecture]).to eq("test-arch")
expect(opts[:box_download_ca_path]).to be_nil
expect(opts[:box_download_ca_cert]).to be_nil
expect(opts[:box_download_client_cert]).to be_nil
expect(opts[:box_download_insecure]).to be_nil
end
opts
end
subject.execute
expect(action_called).to be(true)
end
it "raises an error if there are multiple providers" do
test_iso_env.box3("foo", "1.0", :vmware)
expect(action_runner).to receive(:run).never
expect { subject.execute }.
to raise_error(Vagrant::Errors::BoxUpdateMultiProvider)
end
it "raises an error if there are multiple architectures" do
test_iso_env.box3("foo", "1.0", :virtualbox, architecture: "other-arch")
expect(action_runner).to receive(:run).never
expect { subject.execute }.
to raise_error(Vagrant::Errors::BoxUpdateMultiArchitecture)
end
context "with multiple architectures and specifying the architecture" do
let(:argv) { ["--box", "foo", "--architecture", "other-arch"] }
it "updates the proper box" do
metadata_url.open("w") do |f|
f.write(
{
name: "foo",
versions: [
{
version: "1.0"
},
{
version: "1.1",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: "test-arch",
},
{
name: "virtualbox",
url: "bar",
architecture: "other-arch",
}
]
}
]
}.to_json
)
end
test_iso_env.box3("foo", "1.0", :virtualbox, architecture: "other-arch")
action_called = false
allow(action_runner).to receive(:run) do |action, opts|
if opts[:box_provider]
action_called = true
expect(opts[:box_url]).to eq(metadata_url.to_s)
expect(opts[:box_provider]).to eq("virtualbox")
expect(opts[:box_version]).to eq("1.1")
expect(opts[:box_architecture]).to eq("other-arch")
end
opts
end
subject.execute
expect(action_called).to be(true)
end
it "raises an error if that provider doesn't exist" do
expect(action_runner).to receive(:run).never
expect { subject.execute }.
to raise_error(Vagrant::Errors::BoxNotFoundWithProviderArchitecture)
end
end
end
end end
context "updating environment machines" do context "updating environment machines" do
@ -286,25 +452,27 @@ describe VagrantPlugins::CommandBox::Command::Update do
context "boxes have an update" do context "boxes have an update" do
let(:md) { let(:md) {
md = Vagrant::BoxMetadata.new(StringIO.new(<<-RAW)) Vagrant::BoxMetadata.new(
{ StringIO.new(
"name": "foo",
"versions": [
{ {
"version": "1.0" name: "foo",
}, versions: [
{ {
"version": "1.1", version: "1.0"
"providers": [ },
{ {
"name": "virtualbox", version: "1.1",
"url": "bar" providers: [
} {
name: "virtualbox",
url: "bar"
}
]
}
] ]
} }.to_json
] )
} )
RAW
} }
before { allow(machine).to receive(:box).and_return(box) } before { allow(machine).to receive(:box).and_return(box) }

View File

@ -40,7 +40,7 @@ describe VagrantPlugins::CloudCommand::BoxCommand::Command::Show do
end end
it "should display the box results" do it "should display the box results" do
expect(subject).to receive(:format_box_results).with(box, env) expect(subject).to receive(:format_box_results).with(box, env, {})
subject.show_box(org_name, box_name, access_token, options) subject.show_box(org_name, box_name, access_token, options)
end end
@ -62,7 +62,7 @@ describe VagrantPlugins::CloudCommand::BoxCommand::Command::Show do
end end
it "should print the version details" do it "should print the version details" do
expect(subject).to receive(:format_box_results).with(box_version, env) expect(subject).to receive(:format_box_results).with(box_version, env, {})
subject.show_box(org_name, box_name, access_token, options) subject.show_box(org_name, box_name, access_token, options)
end end
@ -144,6 +144,34 @@ describe VagrantPlugins::CloudCommand::BoxCommand::Command::Show do
subject.execute subject.execute
end end
end end
context "with architectures flag set" do
let(:arch_option) { "test-arch" }
before { argv.push("--architectures").push(arch_option) }
it "shouild show box with architectures option set" do
expect(subject).to receive(:show_box) do |*_, opts|
expect(opts[:architectures]).to eq([arch_option])
end
subject.execute
end
end
context "with providers flag set" do
let(:provider_option) { "test-provider" }
before { argv.push("--providers").push(provider_option) }
it "shilud show box with providers option set" do
expect(subject).to receive(:show_box) do |*_, opts|
expect(opts[:providers]).to eq([provider_option])
end
subject.execute
end
end
end end
end end
end end

View File

@ -43,7 +43,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Create do
subject { described_class.new(argv, env) } subject { described_class.new(argv, env) }
it "should add a new provider to the box version" do it "should add a new provider to the box version" do
expect(version).to receive(:add_provider).with(provider_name) expect(version).to receive(:add_provider).with(provider_name, nil)
subject.create_provider(org_name, box_name, box_version, provider_name, provider_url, access_token, options) subject.create_provider(org_name, box_name, box_version, provider_name, provider_url, access_token, options)
end end
@ -166,6 +166,59 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Create do
subject.execute subject.execute
end end
end end
it "should include detected host architecture by default" do
host_arch = double("host-arch")
expect(Vagrant::Util::Platform).to receive(:architecture).and_return(host_arch)
expect(subject).to receive(:create_provider) do |*_, opts|
expect(opts[:architecture]).to eq(host_arch)
end
subject.execute
end
context "with architecture flag" do
let(:arch_option) { "test-arch" }
before { argv.push("--architecture").push(arch_option) }
it "should include the architecture option" do
expect(subject).to receive(:create_provider) do |*args, opts|
expect(opts[:architecture]).to eq(arch_option)
end
subject.execute
end
end
context "with default architecture flag" do
before { argv.push(default_arch_flag) }
context "when flag is enabled" do
let(:default_arch_flag) { "--default-architecture" }
it "should include default architecture with true value" do
expect(subject).to receive(:create_provider) do |*args, opts|
expect(opts[:default_architecture]).to be(true)
end
subject.execute
end
end
context "when flag is disabled" do
let(:default_arch_flag) { "--no-default-architecture" }
it "should include default architecture with false value" do
expect(subject).to receive(:create_provider) do |*args, opts|
expect(opts[:default_architecture]).to be(false)
end
subject.execute
end
end
end
end end
end end
end end

View File

@ -16,7 +16,8 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
let(:organization) { double("organization") } let(:organization) { double("organization") }
let(:box) { double("box", versions: [version]) } let(:box) { double("box", versions: [version]) }
let(:version) { double("version", version: box_version, providers: [provider]) } let(:version) { double("version", version: box_version, providers: [provider]) }
let(:provider) { double("provider", name: box_version_provider) } let(:provider) { double("provider", name: box_version_provider, architecture: architecture) }
let(:architecture) { double("test-architecture") }
describe "#delete_provider" do describe "#delete_provider" do
let(:options) { {} } let(:options) { {} }
@ -30,8 +31,14 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
with(custom_server: anything, access_token: access_token). with(custom_server: anything, access_token: access_token).
and_return(account) and_return(account)
allow(subject).to receive(:with_provider). allow(subject).to receive(:with_provider).
with(account: account, org: org_name, box: box_name, version: box_version, provider: box_version_provider). with(
and_yield(provider) account: account,
org: org_name,
box: box_name,
version: box_version,
provider: box_version_provider,
architecture: architecture
).and_yield(provider)
allow(provider).to receive(:delete) allow(provider).to receive(:delete)
end end
@ -39,11 +46,11 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
it "should delete the provider" do it "should delete the provider" do
expect(provider).to receive(:delete) expect(provider).to receive(:delete)
subject.delete_provider(org_name, box_name, box_version, box_version_provider, access_token, options) subject.delete_provider(org_name, box_name, box_version, box_version_provider, architecture, account, options)
end end
it "should return zero on success" do it "should return zero on success" do
r = subject.delete_provider(org_name, box_name, box_version, box_version_provider, access_token, options) r = subject.delete_provider(org_name, box_name, box_version, box_version_provider, architecture, account, options)
expect(r).to eq(0) expect(r).to eq(0)
end end
@ -53,7 +60,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
end end
it "should return non-zero" do it "should return non-zero" do
r = subject.delete_provider(org_name, box_name, box_version, box_version_provider, access_token, options) r = subject.delete_provider(org_name, box_name, box_version, box_version_provider, architecture, account, options)
expect(r).to be_a(Integer) expect(r).to be_a(Integer)
expect(r).not_to eq(0) expect(r).not_to eq(0)
end end
@ -75,11 +82,16 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
let(:client) { double("client", token: access_token) } let(:client) { double("client", token: access_token) }
before do before do
allow(VagrantCloud::Account).to receive(:new).and_return(account)
allow(account).to receive(:organization).with(name: org_name).
and_return(organization)
allow(iso_env).to receive(:action_runner).and_return(action_runner) allow(iso_env).to receive(:action_runner).and_return(action_runner)
allow(subject).to receive(:client_login). allow(subject).to receive(:client_login).
and_return(client) and_return(client)
allow(iso_env.ui).to receive(:ask). allow(iso_env.ui).to receive(:ask).
and_return("y") and_return("y")
allow(subject).to receive(:select_provider_architecture).
and_return(architecture)
allow(subject).to receive(:delete_provider) allow(subject).to receive(:delete_provider)
end end
@ -115,7 +127,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
it "should delete the provider" do it "should delete the provider" do
expect(subject).to receive(:delete_provider). expect(subject).to receive(:delete_provider).
with(org_name, box_name, version_arg, provider_arg, access_token, anything) with(org_name, box_name, version_arg, provider_arg, architecture, account, anything)
subject.execute subject.execute
end end
@ -124,6 +136,43 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
subject.execute subject.execute
end end
context "with architecture argument" do
let(:architecture_argument) { "test-arch" }
before { argv << architecture_argument }
it "should delete the provider" do
expect(subject).to receive(:delete_provider).
with(org_name, box_name, version_arg, provider_arg, architecture_argument, account, anything)
subject.execute
end
it "should not attempt to select the architecture" do
expect(subject).not_to receive(:select_provider_architecture)
subject.execute
end
end
context "with multiple provider architectures" do
let(:box_version) { double("box-version", providers: providers) }
let(:providers) {
[
double("dummy-provider", architecture: "amd64"),
double("dummy-provider", architecture: "arm64")
]
}
before do
expect(subject).to receive(:select_provider_architecture).and_call_original
expect(subject).to receive(:with_version).and_yield(box_version)
end
it "should prompt for architecture selection" do
expect(iso_env.ui).to receive(:ask).and_return("amd64")
subject.execute
end
end
context "with force flag" do context "with force flag" do
before { argv << "--force" } before { argv << "--force" }

View File

@ -12,6 +12,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do
let(:box_name) { "my-box" } let(:box_name) { "my-box" }
let(:box_version) { "1.0.0" } let(:box_version) { "1.0.0" }
let(:box_version_provider) { "my-provider" } let(:box_version_provider) { "my-provider" }
let(:box_architecture) { "box-architecture" }
let(:account) { double("account") } let(:account) { double("account") }
let(:organization) { double("organization") } let(:organization) { double("organization") }
let(:box) { double("box", versions: [version]) } let(:box) { double("box", versions: [version]) }
@ -31,7 +32,14 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do
with(custom_server: anything, access_token: access_token). with(custom_server: anything, access_token: access_token).
and_return(account) and_return(account)
allow(subject).to receive(:with_provider). allow(subject).to receive(:with_provider).
with(account: account, org: org_name, box: box_name, version: box_version, provider: box_version_provider). with(
account: account,
org: org_name,
box: box_name,
version: box_version,
provider: box_version_provider,
architecture: box_architecture
).
and_yield(provider) and_yield(provider)
allow(provider).to receive(:save) allow(provider).to receive(:save)
allow(subject).to receive(:format_box_results) allow(subject).to receive(:format_box_results)
@ -41,24 +49,60 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do
it "should update the provider" do it "should update the provider" do
expect(provider).to receive(:save) expect(provider).to receive(:save)
subject.update_provider(org_name, box_name, box_version, box_version_provider, provider_url, access_token, options) subject.update_provider(
org_name,
box_name,
box_version,
box_version_provider,
box_architecture,
provider_url,
access_token,
options
)
end end
it "should return 0 on success" do it "should return 0 on success" do
result = subject.update_provider(org_name, box_name, box_version, box_version_provider, provider_url, access_token, options) result = subject.update_provider(
org_name,
box_name,
box_version,
box_version_provider,
box_architecture,
provider_url,
access_token,
options
)
expect(result).to eq(0) expect(result).to eq(0)
end end
it "should return non-zero result on error" do it "should return non-zero result on error" do
expect(provider).to receive(:save).and_raise(VagrantCloud::Error) expect(provider).to receive(:save).and_raise(VagrantCloud::Error)
result = subject.update_provider(org_name, box_name, box_version, box_version_provider, provider_url, access_token, options) result = subject.update_provider(
org_name,
box_name,
box_version,
box_version_provider,
box_architecture,
provider_url,
access_token,
options
)
expect(result).not_to eq(0) expect(result).not_to eq(0)
expect(result).to be_a(Integer) expect(result).to be_a(Integer)
end end
it "should not update the URL when unset" do it "should not update the URL when unset" do
expect(provider).not_to receive(:url=) expect(provider).not_to receive(:url=)
subject.update_provider(org_name, box_name, box_version, box_version_provider, provider_url, access_token, options) subject.update_provider(
org_name,
box_name,
box_version,
box_version_provider,
box_architecture,
provider_url,
access_token,
options
)
end end
context "when URL is set" do context "when URL is set" do
@ -66,19 +110,78 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do
it "should update the URL" do it "should update the URL" do
expect(provider).to receive(:url=).with(provider_url) expect(provider).to receive(:url=).with(provider_url)
subject.update_provider(org_name, box_name, box_version, box_version_provider, provider_url, access_token, options) subject.update_provider(
org_name,
box_name,
box_version,
box_version_provider,
box_architecture,
provider_url,
access_token,
options
)
end end
end end
context "with options set" do context "with options set" do
let(:checksum) { double("checksum") } let(:checksum) { double("checksum") }
let(:checksum_type) { double("checksum_type") } let(:checksum_type) { double("checksum_type") }
let(:options) { {checksum: checksum, checksum_type: checksum_type} } let(:options) { {} }
it "should set checksum options before saving" do after do
expect(provider).to receive(:checksum=).with(checksum) subject.update_provider(
expect(provider).to receive(:checksum_type=).with(checksum_type) org_name,
subject.update_provider(org_name, box_name, box_version, box_version_provider, provider_url, access_token, options) box_name,
box_version,
box_version_provider,
box_architecture,
provider_url,
access_token,
options
)
end
it "should not modify option controlled values when unset" do
expect(provider).not_to receive(:checksum=)
expect(provider).not_to receive(:checksum_type=)
expect(provider).not_to receive(:architecture=)
expect(provider).not_to receive(:default_architecture=)
end
context "with checksum options set" do
let(:options) { {checksum: checksum, checksum_type: checksum_type} }
it "should set checksum options before saving" do
expect(provider).to receive(:checksum=).with(checksum)
expect(provider).to receive(:checksum_type=).with(checksum_type)
end
end
context "with architecture option set" do
let(:architecture) { double("architecture") }
let(:options) { {architecture: architecture} }
it "should set architecture before saving" do
expect(provider).to receive(:architecture=).with(architecture)
end
end
context "with default architecture option set" do
context "with true value" do
let(:options) { {default_architecture: true} }
it "should set default architecture to true" do
expect(provider).to receive(:default_architecture=).with(true)
end
end
context "with false value" do
let(:options) { {default_architecture: false} }
it "should set default architecture to false" do
expect(provider).to receive(:default_architecture=).with(false)
end
end
end end
end end
end end
@ -134,38 +237,127 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do
before { argv << version_arg } before { argv << version_arg }
it "should create the provider" do it "shows help" do
expect(subject).to receive(:update_provider).with(org_name, box_name, version_arg, provider_arg, any_args) expect { subject.execute }.
subject.execute to raise_error(Vagrant::Errors::CLIInvalidUsage)
end end
it "should not provide URL value" do context "with architecture argument" do
expect(subject).to receive(:update_provider).with(org_name, box_name, version_arg, provider_arg, nil, any_args) let(:architecture_arg) { "box-architecture" }
subject.execute
end
context "with URL argument" do before { argv << architecture_arg }
let(:url_arg) { "provider-url" }
before { argv << url_arg } it "should create the provider" do
expect(subject).
it "should provide the URL value" do to receive(:update_provider).
expect(subject).to receive(:update_provider).with(org_name, box_name, version_arg, provider_arg, url_arg, any_args) with(
org_name,
box_name,
version_arg,
provider_arg,
architecture_arg,
any_args
)
subject.execute subject.execute
end end
end
context "with checksum and checksum type flags" do it "should not provide URL value" do
let(:checksum_arg) { "checksum" } expect(subject).
let(:checksum_type_arg) { "checksum_type" } to receive(:update_provider).
with(
before { argv.push("--checksum").push(checksum_arg).push("--checksum-type").push(checksum_type_arg) } org_name,
box_name,
it "should include the checksum options" do version_arg,
expect(subject).to receive(:update_provider). provider_arg,
with(org_name, box_name, version_arg, provider_arg, any_args, hash_including(checksum: checksum_arg, checksum_type: checksum_type_arg)) architecture_arg,
nil,
any_args
)
subject.execute subject.execute
end end
context "with URL argument" do
let(:url_arg) { "provider-url" }
before { argv << url_arg }
it "should provide the URL value" do
expect(subject).
to receive(:update_provider).
with(
org_name,
box_name,
version_arg,
provider_arg,
architecture_arg,
url_arg,
any_args
)
subject.execute
end
end
context "with checksum and checksum type flags" do
let(:checksum_arg) { "checksum" }
let(:checksum_type_arg) { "checksum_type" }
before { argv.push("--checksum").push(checksum_arg).push("--checksum-type").push(checksum_type_arg) }
it "should include the checksum options" do
expect(subject).
to receive(:update_provider).
with(
org_name,
box_name,
version_arg,
provider_arg,
architecture_arg,
any_args,
hash_including(
checksum: checksum_arg,
checksum_type: checksum_type_arg
)
)
subject.execute
end
end
context "with architecture flag" do
let(:architecture_flag) { "test-arch" }
before { argv.push("--architecture").push(architecture_flag) }
it "should include the architecture flag" do
expect(subject).to receive(:update_provider) do |*_, opts|
expect(opts[:architecture]).to eq(architecture_flag)
end
subject.execute
end
end
context "with default architecture flag" do
context "enabled" do
before { argv.push("--default-architecture") }
it "should include default architecture set to true" do
expect(subject).to receive(:update_provider) do |*_, opts|
expect(opts[:default_architecture]).to be(true)
end
subject.execute
end
end
context "disabled" do
before { argv.push("--no-default-architecture") }
it "should include default architecture set to false" do
expect(subject).to receive(:update_provider) do |*_, opts|
expect(opts[:default_architecture]).to be(false)
end
subject.execute
end
end
end
end end
end end
end end

View File

@ -20,16 +20,20 @@ describe VagrantPlugins::CloudCommand::Command::Publish do
let(:ui) { Vagrant::UI::Silent.new } let(:ui) { Vagrant::UI::Silent.new }
let(:upload_url) { double("upload_url") } let(:upload_url) { double("upload_url") }
let(:access_token) { double("access_token") } let(:access_token) { double("access_token") }
let(:default_architecture) { double("default-architecture") }
subject { described_class.new(argv, iso_env) } subject { described_class.new(argv, iso_env) }
before do before do
allow(Vagrant::Util::Platform).to receive(:architecture).
and_return(default_architecture)
allow(iso_env).to receive(:ui).and_return(ui) allow(iso_env).to receive(:ui).and_return(ui)
allow(File).to receive(:stat).with(box). allow(File).to receive(:stat).with(box).
and_return(double("box_stat", size: box_size)) and_return(double("box_stat", size: box_size))
allow(VagrantCloud::Account).to receive(:new). allow(VagrantCloud::Account).to receive(:new).
with(custom_server: anything, access_token: anything). with(custom_server: anything, access_token: anything).
and_return(account) and_return(account)
allow(provider).to receive(:architecture=).with(default_architecture)
end end
describe "#upload_box_file" do describe "#upload_box_file" do
@ -148,21 +152,69 @@ describe VagrantPlugins::CloudCommand::Command::Publish do
let(:options) { {} } let(:options) { {} }
it "should not modify the provider" do it "should not modify the provider" do
expect(provider).not_to receive(:url=)
expect(provider).not_to receive(:checksum=)
expect(provider).not_to receive(:checksum_type=)
expect(provider).not_to receive(:architecture=)
expect(provider).not_to receive(:default_architecture=)
subject.set_provider_info(provider, options) subject.set_provider_info(provider, options)
end end
end end
context "with options set" do context "with options" do
let(:options) { {url: url, checksum: checksum, checksum_type: checksum_type} } let(:options) { {} }
let(:url) { double("url") } let(:url) { double("url") }
let(:checksum) { double("checksum") } let(:checksum) { double("checksum") }
let(:checksum_type) { double("checksum_type") } let(:checksum_type) { double("checksum_type") }
let(:architecture) { double("architecture") }
it "should set info on provider" do after { subject.set_provider_info(provider, options) }
expect(provider).to receive(:url=).with(url)
expect(provider).to receive(:checksum=).with(checksum) context "with url set" do
expect(provider).to receive(:checksum_type=).with(checksum_type) before { options[:url] = url }
subject.set_provider_info(provider, options)
it "should set url on provider" do
expect(provider).to receive(:url=).with(url)
end
end
context "with checksum set" do
before do
options[:checksum] = checksum
options[:checksum_type] = checksum_type
end
it "should set checksum on provider" do
expect(provider).to receive(:checksum=).with(checksum)
expect(provider).to receive(:checksum_type=).with(checksum_type)
end
end
context "with architecture set" do
before { options[:architecture] = architecture }
it "should set architecture on provider" do
expect(provider).to receive(:architecture=).with(architecture)
end
end
context "with default architecture set" do
context "with true value" do
before { options[:default_architecture] = true }
it "should set default architecture to true" do
expect(provider).to receive(:default_architecture=).with(true)
end
end
context "with false value" do
before { options[:default_architecture] = false }
it "should set default architecture to false" do
expect(provider).to receive(:default_architecture=).with(false)
end
end
end end
end end
end end

View File

@ -45,6 +45,7 @@ describe VagrantPlugins::CloudCommand::Command::Search do
end end
context "with valid options" do context "with valid options" do
let(:architecture) { double("architecture") }
let(:provider) { double("provider") } let(:provider) { double("provider") }
let(:sort) { double("sort") } let(:sort) { double("sort") }
let(:order) { double("order") } let(:order) { double("order") }
@ -52,6 +53,7 @@ describe VagrantPlugins::CloudCommand::Command::Search do
let(:page) { double("page") } let(:page) { double("page") }
let(:options) { { let(:options) { {
architecture: architecture,
provider: provider, provider: provider,
sort: sort, sort: sort,
order: order, order: order,

View File

@ -116,6 +116,34 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
end end
end end
describe "#box_architecture" do
it "is not required" do
subject.box_architecture = nil
subject.finalize!
assert_valid
end
it "is :auto by default" do
subject.finalize!
assert_valid
expect(subject.box_architecture).to eq(:auto)
end
it "can be set to custom value" do
subject.box_architecture = "test-arch"
subject.finalize!
assert_valid
expect(subject.box_architecture).to eq("test-arch")
end
it "is converted to string" do
subject.box_architecture = :test_arch
subject.finalize!
assert_valid
expect(subject.box_architecture).to eq("test_arch")
end
end
context "#box_check_update" do context "#box_check_update" do
it "defaults to true" do it "defaults to true" do
with_temp_env("VAGRANT_BOX_UPDATE_CHECK_DISABLE" => "") do with_temp_env("VAGRANT_BOX_UPDATE_CHECK_DISABLE" => "") do

View File

@ -100,8 +100,11 @@ module Unit
# @param [String] provider # @param [String] provider
# @return [Pathname] # @return [Pathname]
def box3(name, version, provider, **opts) def box3(name, version, provider, **opts)
args = [name, version, provider.to_s]
args << opts[:architecture].to_s if opts[:architecture]
# Create the directory for the box # Create the directory for the box
box_dir = boxes_dir.join(name, version, provider.to_s) box_dir = boxes_dir.join(*args)
box_dir.mkpath box_dir.mkpath
# Create the metadata.json for it # Create the metadata.json for it

View File

@ -210,7 +210,7 @@ describe Vagrant::Action::Builtin::BoxAdd, :skip_windows, :bsdtar do
env[:box_provider] = "virtualbox" env[:box_provider] = "virtualbox"
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", ["virtualbox"], "0").and_return(box) "foo", ["virtualbox"], "0", nil).and_return(box)
expect(box_collection).to receive(:add).never expect(box_collection).to receive(:add).never
expect(app).to receive(:call).never expect(app).to receive(:call).never
@ -903,6 +903,304 @@ describe Vagrant::Action::Builtin::BoxAdd, :skip_windows, :bsdtar do
subject.call(env) subject.call(env)
end end
context "with box architecture configured" do
before do
allow(Vagrant::Util::Platform).to receive(:architecture).and_return("test-arch")
end
context "set to :auto" do
before do
env[:box_architecture] = :auto
end
it "adds the latest version of a box with only one provider and matching architecture" do
box_path = iso_env.box2_file(:virtualbox)
tf = Tempfile.new(["vagrant-box-latest-version", ".json"]).tap do |f|
f.write(
{
name: "foo/bar",
versions: [
{
version: "0.5",
},
{
version: "0.7",
providers: [
{
name: "virtualbox",
url: "/dev/null/invalid.path",
architecture: "amd64",
default_architecture: true,
},
{
name: "virtualbox",
url: "#{box_path}",
architecture: "test-arch",
default_architecture: false,
}
]
}
]
}.to_json
)
f.close
end
env[:box_url] = tf.path
expect(box_collection).to receive(:add).with(any_args) { |path, name, version, opts|
expect(checksum(path)).to eq(checksum(box_path))
expect(name).to eq("foo/bar")
expect(version).to eq("0.7")
expect(opts[:metadata_url]).to eq("file://#{tf.path}")
expect(opts[:architecture]).to eq(:auto)
true
}.and_return(box)
expect(app).to receive(:call).with(env)
subject.call(env)
end
it "adds the latest version of a box with only one provider and no unknown architecture set as default" do
box_path = iso_env.box2_file(:virtualbox)
tf = Tempfile.new(["vagrant-box-latest-version", ".json"]).tap do |f|
f.write(
{
name: "foo/bar",
versions: [
{
version: "0.5",
},
{
version: "0.7",
providers: [
{
name: "virtualbox",
url: "#{box_path}",
architecture: "unknown",
default_architecture: true,
},
{
name: "virtualbox",
url: "/dev/null/invalid.path",
architecture: "amd64",
default_architecture: false,
}
]
}
]
}.to_json
)
f.close
end
env[:box_url] = tf.path
expect(box_collection).to receive(:add).with(any_args) { |path, name, version, opts|
expect(checksum(path)).to eq(checksum(box_path))
expect(name).to eq("foo/bar")
expect(version).to eq("0.7")
expect(opts[:metadata_url]).to eq("file://#{tf.path}")
expect(opts[:architecture]).to eq(:auto)
true
}.and_return(box)
expect(app).to receive(:call).with(env)
subject.call(env)
end
it "errors adding latest version of a box with only one provider and no matching architecture" do
allow(Vagrant::Util::Platform).to receive(:architecture).and_return("test-arch")
box_path = iso_env.box2_file(:virtualbox)
tf = Tempfile.new(["vagrant-box-latest-version", ".json"]).tap do |f|
f.write(
{
name: "foo/bar",
versions: [
{
version: "0.5",
},
{
version: "0.7",
providers: [
{
name: "virtualbox",
url: "#{box_path}",
architecture: "amd64",
default_architecture: true,
},
{
name: "virtualbox",
url: "/dev/null/invalid.path",
architecture: "arm64",
default_architecture: false,
}
]
}
]
}.to_json
)
f.close
end
env[:box_url] = tf.path
expect {
subject.call(env)
}.to raise_error(Vagrant::Errors::BoxAddNoMatchingVersion)
end
end
context "set to nil" do
before do
env[:box_architecture] = nil
end
it "adds the latest version of a box with only one provider and default architecture" do
box_path = iso_env.box2_file(:virtualbox)
tf = Tempfile.new(["vagrant-box-latest-version", ".json"]).tap do |f|
f.write(
{
name: "foo/bar",
versions: [
{
version: "0.5",
},
{
version: "0.7",
providers: [
{
name: "virtualbox",
url: "#{box_path}",
architecture: "amd64",
default_architecture: true,
},
{
name: "virtualbox",
url: "/dev/null/invalid.path",
architecture: "test-arch",
default_architecture: false,
}
]
}
]
}.to_json
)
f.close
end
env[:box_url] = tf.path
expect(box_collection).to receive(:add).with(any_args) { |path, name, version, opts|
expect(checksum(path)).to eq(checksum(box_path))
expect(name).to eq("foo/bar")
expect(version).to eq("0.7")
expect(opts[:metadata_url]).to eq("file://#{tf.path}")
expect(opts[:architecture]).to be_nil
true
}.and_return(box)
expect(app).to receive(:call).with(env)
subject.call(env)
end
end
context "set to explicit value" do
before do
env[:box_architecture] = "arm64"
end
it "adds the latest version of a box with only one provider and matching architecture" do
box_path = iso_env.box2_file(:virtualbox)
tf = Tempfile.new(["vagrant-box-latest-version", ".json"]).tap do |f|
f.write(
{
name: "foo/bar",
versions: [
{
version: "0.5",
},
{
version: "0.7",
providers: [
{
name: "virtualbox",
url: "#{box_path}",
architecture: "arm64",
default_architecture: false,
},
{
name: "virtualbox",
url: "/dev/null/invalid.path",
architecture: "test-arch",
default_architecture: true,
}
]
}
]
}.to_json
)
f.close
end
env[:box_url] = tf.path
expect(box_collection).to receive(:add).with(any_args) { |path, name, version, opts|
expect(checksum(path)).to eq(checksum(box_path))
expect(name).to eq("foo/bar")
expect(version).to eq("0.7")
expect(opts[:metadata_url]).to eq("file://#{tf.path}")
expect(opts[:architecture]).to eq("arm64")
true
}.and_return(box)
expect(app).to receive(:call).with(env)
subject.call(env)
end
it "errors adding the latest version of a box with only one provider and no matching architecture" do
box_path = iso_env.box2_file(:virtualbox)
tf = Tempfile.new(["vagrant-box-latest-version", ".json"]).tap do |f|
f.write(
{
name: "foo/bar",
versions: [
{
version: "0.5",
},
{
version: "0.7",
providers: [
{
name: "virtualbox",
url: "#{box_path}",
architecture: "amd64",
default_architecture: true,
},
{
name: "virtualbox",
url: "/dev/null/invalid.path",
architecture: "386",
default_architecture: false,
}
]
}
]
}.to_json
)
f.close
end
env[:box_url] = tf.path
expect {
subject.call(env)
}.to raise_error(Vagrant::Errors::BoxAddNoMatchingVersion)
end
end
end
it "adds the latest version of a box with the specified provider" do it "adds the latest version of a box with the specified provider" do
box_path = iso_env.box2_file(:vmware) box_path = iso_env.box2_file(:vmware)
tf = Tempfile.new(["vagrant-box-specific-provider", ".json"]).tap do |f| tf = Tempfile.new(["vagrant-box-specific-provider", ".json"]).tap do |f|
@ -1304,7 +1602,7 @@ describe Vagrant::Action::Builtin::BoxAdd, :skip_windows, :bsdtar do
env[:box_url] = tf.path env[:box_url] = tf.path
expect(box_collection).to receive(:find). expect(box_collection).to receive(:find).
with("foo/bar", "virtualbox", "0.7").and_return(box) with("foo/bar", "virtualbox", "0.7", nil).and_return(box)
expect(box_collection).to receive(:add).never expect(box_collection).to receive(:add).never
expect(app).to receive(:call).never expect(app).to receive(:call).never

View File

@ -17,7 +17,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
subject { described_class.new(app, env) } subject { described_class.new(app, env) }
let(:box_collection) { double("box_collection") } let(:box_collection) { double("box_collection") }
let(:home_path) { "foo" } let(:home_path) { double("home-path") }
let(:machine_index) { [] } let(:machine_index) { [] }
let(:iso_env) { isolated_environment } let(:iso_env) { isolated_environment }
@ -27,12 +27,12 @@ describe Vagrant::Action::Builtin::BoxRemove do
end end
it "deletes the box if it is the only option" do it "deletes the box if it is the only option" do
allow(box_collection).to receive(:all).and_return([["foo", "1.0", :virtualbox]]) allow(box_collection).to receive(:all).and_return([["foo", "1.0", :virtualbox, nil]])
env[:box_name] = "foo" env[:box_name] = "foo"
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box_collection).to receive(:clean).with(box.name) expect(box_collection).to receive(:clean).with(box.name)
.and_return(true) .and_return(true)
expect(box).to receive(:destroy!).once expect(box).to receive(:destroy!).once
@ -54,7 +54,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
env[:box_provider] = "virtualbox" env[:box_provider] = "virtualbox"
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box_collection).to receive(:clean).with(box.name) expect(box_collection).to receive(:clean).with(box.name)
.and_return(false) .and_return(false)
expect(box).to receive(:destroy!).once expect(box).to receive(:destroy!).once
@ -76,7 +76,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
env[:box_version] = "1.0" env[:box_version] = "1.0"
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box_collection).to receive(:clean).with(box.name) expect(box_collection).to receive(:clean).with(box.name)
.and_return(false) .and_return(false)
expect(box).to receive(:destroy!).once expect(box).to receive(:destroy!).once
@ -87,6 +87,131 @@ describe Vagrant::Action::Builtin::BoxRemove do
expect(env[:box_removed]).to equal(box) expect(env[:box_removed]).to equal(box)
end end
context "with architecture" do
let(:architecture) { "test-arch" }
let(:box) do
box_dir = iso_env.box3("foo", "1.0", :virtualbox, architecture: architecture)
Vagrant::Box.new("foo", :virtualbox, "1.0", box_dir, architecture: architecture)
end
it "deletes the box if it is the only option" do
allow(box_collection).to receive(:all).and_return([["foo", "1.0", :virtualbox, architecture]])
env[:box_name] = "foo"
expect(box_collection).to receive(:find).
with("foo", :virtualbox, "1.0", architecture).
and_return(box)
expect(box_collection).to receive(:clean).
with(box.name).
and_return(true)
expect(box).to receive(:destroy!).once
expect(app).to receive(:call).with(env).once
subject.call(env)
expect(env[:box_removed]).to equal(box)
end
it "deletes the box with the specified provider if given" do
allow(box_collection).to receive(:all)
.and_return([
["foo", "1.0", :virtualbox, architecture],
["foo", "1.0", :vmware, architecture],
])
env[:box_name] = "foo"
env[:box_provider] = "virtualbox"
expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0", architecture).and_return(box)
expect(box_collection).to receive(:clean).with(box.name)
.and_return(false)
expect(box).to receive(:destroy!).once
expect(app).to receive(:call).with(env).once
subject.call(env)
expect(env[:box_removed]).to equal(box)
end
it "deletes the box with the specified version if given" do
allow(box_collection).to receive(:all)
.and_return([
["foo", "1.0", :virtualbox, architecture],
["foo", "1.1", :virtualbox, architecture],
])
env[:box_name] = "foo"
env[:box_version] = "1.0"
expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0", architecture).and_return(box)
expect(box_collection).to receive(:clean).with(box.name)
.and_return(false)
expect(box).to receive(:destroy!).once
expect(app).to receive(:call).with(env).once
subject.call(env)
expect(env[:box_removed]).to equal(box)
end
it "deletes the box with the specificed version and architecture" do
allow(box_collection).to receive(:all)
.and_return([
["foo", "1.0", :virtualbox, architecture],
["foo", "1.0", :virtualbox, "other-arch"],
])
env[:box_name] = "foo"
env[:box_version] = "1.0"
env[:box_architecture] = architecture
expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0", architecture).and_return(box)
expect(box_collection).to receive(:clean).with(box.name)
.and_return(false)
expect(box).to receive(:destroy!).once
expect(app).to receive(:call).with(env).once
subject.call(env)
expect(env[:box_removed]).to equal(box)
end
it "errors when box with specified version does not included specified architecture" do
allow(box_collection).to receive(:all)
.and_return([
["foo", "1.0", :virtualbox, architecture],
["foo", "1.0", :virtualbox, "other-arch"],
])
env[:box_name] = "foo"
env[:box_version] = "1.0"
env[:box_architecture] = "unknown-arch"
expect {
subject.call(env)
}.to raise_error(Vagrant::Errors::BoxRemoveArchitectureNotFound)
end
it "errors when box with specified version has multiple architectures" do
allow(box_collection).to receive(:all)
.and_return([
["foo", "1.0", :virtualbox, architecture],
["foo", "1.0", :virtualbox, "other-arch"],
])
env[:box_name] = "foo"
env[:box_version] = "1.0"
expect {
subject.call(env)
}.to raise_error(Vagrant::Errors::BoxRemoveMultiArchitecture)
end
end
context "checking if a box is in use" do context "checking if a box is in use" do
def new_entry(name, provider, version, valid=true) def new_entry(name, provider, version, valid=true)
Vagrant::MachineIndex::Entry.new.tap do |entry| Vagrant::MachineIndex::Entry.new.tap do |entry|
@ -117,7 +242,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
it "does delete if the box is not in use" do it "does delete if the box is not in use" do
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box).to receive(:destroy!).once expect(box).to receive(:destroy!).once
expect(box_collection).to receive(:clean).with(box.name) expect(box_collection).to receive(:clean).with(box.name)
.and_return(true) .and_return(true)
@ -133,7 +258,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
with(anything, env).and_return(result) with(anything, env).and_return(result)
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box_collection).to receive(:clean).with(box.name) expect(box_collection).to receive(:clean).with(box.name)
.and_return(true) .and_return(true)
expect(box).to receive(:destroy!).once expect(box).to receive(:destroy!).once
@ -149,7 +274,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
with(anything, env).and_return(result) with(anything, env).and_return(result)
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box).to receive(:destroy!).never expect(box).to receive(:destroy!).never
subject.call(env) subject.call(env)
@ -164,7 +289,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
with(anything, env).and_return(result) with(anything, env).and_return(result)
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box).to receive(:destroy!).never expect(box).to receive(:destroy!).never
subject.call(env) subject.call(env)
@ -178,7 +303,7 @@ describe Vagrant::Action::Builtin::BoxRemove do
with(anything, env).and_return(result) with(anything, env).and_return(result)
expect(box_collection).to receive(:find).with( expect(box_collection).to receive(:find).with(
"foo", :virtualbox, "1.0").and_return(box) "foo", :virtualbox, "1.0", nil).and_return(box)
expect(box_collection).to receive(:clean).with(box.name) expect(box_collection).to receive(:clean).with(box.name)
.and_return(true) .and_return(true)
expect(box).to receive(:destroy!) expect(box).to receive(:destroy!)

View File

@ -36,11 +36,11 @@ describe Vagrant::BoxCollection, :skip_windows, :bsdtar do
# Verify some output # Verify some output
results = subject.all results = subject.all
expect(results.length).to eq(5) expect(results.length).to eq(5)
expect(results.include?(["foo", "1.0", :virtualbox])).to be expect(results).to include(["foo", "1.0", :virtualbox, nil])
expect(results.include?(["foo", "1.0", :vmware])).to be expect(results).to include(["foo", "1.0", :vmware, nil])
expect(results.include?(["bar", "0", :ec2])).to be expect(results).to include(["bar", "0", :ec2, nil])
expect(results.include?(["foo/bar", "1.0", :virtualbox])).to be expect(results).to include(["foo/bar", "1.0", :virtualbox, nil])
expect(results.include?(["foo:colon", "1.0", :virtualbox])).to be expect(results).to include(["foo:colon", "1.0", :virtualbox, nil])
end end
it "should return the boxes and their providers even if box has wrong version" do it "should return the boxes and their providers even if box has wrong version" do
@ -57,11 +57,11 @@ describe Vagrant::BoxCollection, :skip_windows, :bsdtar do
# Verify some output # Verify some output
results = subject.all results = subject.all
expect(results.length).to eq(4) expect(results.length).to eq(4)
expect(results.include?(["foo", "1.0", :virtualbox])).not_to be expect(results).not_to include(["foo", "1.0", :virtualbox, nil])
expect(results.include?(["foo", "1.0", :vmware])).to be expect(results).to include(["foo", "1.0", :vmware, nil])
expect(results.include?(["bar", "0", :ec2])).to be expect(results).to include(["bar", "0", :ec2, nil])
expect(results.include?(["foo/bar", "1.0", :virtualbox])).to be expect(results).to include(["foo/bar", "1.0", :virtualbox, nil])
expect(results.include?(["foo:colon", "1.0", :virtualbox])).to be expect(results).to include(["foo:colon", "1.0", :virtualbox, nil])
end end
it 'does not raise an exception when a file appears in the boxes dir' do it 'does not raise an exception when a file appears in the boxes dir' do
@ -175,7 +175,7 @@ describe Vagrant::BoxCollection, :skip_windows, :bsdtar do
# Make sure the results still exist # Make sure the results still exist
results = subject.all results = subject.all
expect(results.length).to eq(1) expect(results.length).to eq(1)
expect(results.include?(["foo", "1.0", :vmware])).to be expect(results).to include(["foo", "1.0", :vmware, nil])
end end
it "doesn't remove the directory if a version exists" do it "doesn't remove the directory if a version exists" do
@ -195,7 +195,7 @@ describe Vagrant::BoxCollection, :skip_windows, :bsdtar do
# Make sure the results still exist # Make sure the results still exist
results = subject.all results = subject.all
expect(results.length).to eq(1) expect(results.length).to eq(1)
expect(results.include?(["foo", "1.0", :virtualbox])).to be expect(results).to include(["foo", "1.0", :virtualbox, nil])
end end
end end

View File

@ -9,34 +9,32 @@ describe Vagrant::BoxMetadata do
include_context "unit" include_context "unit"
let(:raw) do let(:raw) do
<<-RAW {
{ name: "foo",
"name": "foo", description: "bar",
"description": "bar", versions: [
"versions": [ {
{ version: "1.0.0",
"version": "1.0.0", providers: [
"providers": [ { name: "virtualbox" },
{ "name": "virtualbox" }, { name: "vmware" }
{ "name": "vmware" } ],
] },
}, {
{ version: "1.1.5",
"version": "1.1.5", providers: [
"providers": [ { name: "virtualbox" }
{ "name": "virtualbox" } ]
] },
}, {
{ version: "1.1.0",
"version": "1.1.0", providers: [
"providers": [ { name: "virtualbox" },
{ "name": "virtualbox" }, { name: "vmware" }
{ "name": "vmware" } ]
] }
} ]
] }.to_json
}
RAW
end end
subject { described_class.new(raw) } subject { described_class.new(raw) }
@ -53,9 +51,7 @@ describe Vagrant::BoxMetadata do
context "with poorly formatted JSON" do context "with poorly formatted JSON" do
let(:raw) { let(:raw) {
<<-RAW {name: "foo"}.to_json + ","
{ "name": "foo", }
RAW
} }
it "raises an exception" do it "raises an exception" do
@ -66,15 +62,14 @@ describe Vagrant::BoxMetadata do
context "with poorly formatted version" do context "with poorly formatted version" do
let(:raw) { let(:raw) {
<<-RAW {
{ "name": "foo", name: "foo",
"versions": [ versions: [
{ {
"version": "I AM NOT VALID" version: "I AM NOT VALID"
} }
] ]
} }.to_json
RAW
} }
it "raises an exception" do it "raises an exception" do
@ -124,6 +119,213 @@ describe Vagrant::BoxMetadata do
["1.0.0", "1.1.0"]) ["1.0.0", "1.1.0"])
end end
end end
context "with architecture" do
let(:raw) do
{
name: "foo",
description: "bar",
versions: [
{
version: "1.0.0",
providers: [
{
name: "virtualbox",
default_architecture: true,
architecture: "amd64"
},
{
name: "virtualbox",
default_architecture: false,
architecture: "arm64"
},
{
name: "vmware",
default_architecture: true,
architecture: "arm64"
},
{
name: "vmware",
default_architecture: false,
architecture: "amd64"
}
],
},
{
version: "1.1.5",
providers: [
{
name: "virtualbox",
architecture: "amd64",
default_architecture: true,
}
]
},
{
version: "1.1.6",
providers: [
{
name: "virtualbox",
architecture: "arm64",
default_architecture: true,
},
]
},
{
version: "1.1.0",
providers: [
{
name: "virtualbox",
architecture: "amd64",
default_architecture: true,
},
{
name: "vmware",
architecture: "amd64",
default_architecture: true,
}
]
},
{
version: "2.0.0",
providers: [
{
name: "vmware",
architecture: "arm64",
default_architecture: true,
}
]
}
]
}.to_json
end
subject { described_class.new(raw) }
before { allow(Vagrant::Util::Platform).to receive(:architecture).and_return("amd64") }
describe "#version" do
it "matches an exact version" do
result = subject.version("1.0.0")
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.0.0")
end
it "matches a constraint with latest matching version" do
result = subject.version(">= 1.0")
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.1.5")
end
it "matches complex constraints" do
result = subject.version(">= 0.9, ~> 1.0.0")
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.0.0")
end
context "with provider filter" do
it "matches the constraint that has the given provider" do
result = subject.version(">= 0", provider: :vmware)
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.1.0")
end
it "matches the exact version that has the given provider" do
result = subject.version("1.0.0", provider: :virtualbox)
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.0.0")
end
it "does not match exact version that has given provider but not host architecture" do
result = subject.version("1.1.6", provider: :virtualbox)
expect(result).to be_nil
end
context "with architecture filter" do
it "matches the exact version that has provider with host architecture when using :auto" do
result = subject.version("1.0.0", provider: :virtualbox, architecture: :auto)
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.0.0")
end
it "matches the exact version that has provider with defined host architecture" do
result = subject.version("1.0.0", provider: :virtualbox, architecture: "arm64")
expect(result).to_not be_nil
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.0.0")
end
it "does not match the exact version that has provider with defined host architecture" do
result = subject.version("1.0.0", provider: :virtualbox, architecture: "ppc64")
expect(result).to be_nil
end
end
end
context "with architecture filter" do
it "matches a constraint that has the detected host architecture" do
result = subject.version("> 0", architecture: :auto)
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.1.5")
end
it "matches a constraint that has the provided architecture" do
result = subject.version("> 0", architecture: "arm64")
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("2.0.0")
end
it "matches exact version that has the provided architecture" do
result = subject.version("1.0.0", architecture: "arm64")
expect(result).to be_kind_of(Vagrant::BoxMetadata::Version)
expect(result.version).to eq("1.0.0")
end
it "does not match exact version that does not have provided architecture" do
result = subject.version("2.0.0", architecture: "amd64")
expect(result).to be_nil
end
end
end
describe "#versions" do
it "returns the versions it contained" do
expect(subject.versions).
to eq(["1.0.0", "1.1.0", "1.1.5", "1.1.6", "2.0.0"])
end
context "with provider filter" do
it "filters versions" do
expect(subject.versions(provider: :vmware)).
to eq(["1.0.0", "1.1.0", "2.0.0"])
end
end
context "with architecture filter" do
it "filters versions" do
expect(subject.versions(architecture: "arm64")).
to eq(["1.0.0", "1.1.6", "2.0.0"])
end
it "returns none when no matching architecture available" do
expect(subject.versions(architecture: "other")).
to be_empty
end
it "filters based on host architecture when :auto used" do
expect(subject.versions(architecture: :auto)).
to eq(subject.versions(architecture: "amd64"))
end
end
end
end
end end
describe Vagrant::BoxMetadata::Version do describe Vagrant::BoxMetadata::Version do
@ -203,4 +405,28 @@ describe Vagrant::BoxMetadata::Provider do
expect(subject.checksum_type).to be_nil expect(subject.checksum_type).to be_nil
end end
end end
describe "architecture" do
it "is set properly" do
raw["architecture"] = "test-arch"
expect(subject.architecture).to eq("test-arch")
end
it "is nil if not set" do
expect(subject.architecture).to be_nil
end
end
describe "#architecture_support?" do
it "is false if architecture is not supported" do
expect(subject.architecture_support?).to be(false)
end
it "is true if architecture is supported" do
raw["default_architecture"] = false
expect(subject.architecture_support?).to be(true)
end
end
end end

View File

@ -19,6 +19,7 @@ describe Vagrant::Box, :skip_windows do
let(:name) { "foo" } let(:name) { "foo" }
let(:provider) { :virtualbox } let(:provider) { :virtualbox }
let(:version) { "1.0" } let(:version) { "1.0" }
let(:architecture) { "test-architecture" }
let(:directory) { environment.box3("foo", "1.0", :virtualbox) } let(:directory) { environment.box3("foo", "1.0", :virtualbox) }
subject { described_class.new(name, provider, version, directory) } subject { described_class.new(name, provider, version, directory) }
@ -209,6 +210,154 @@ describe Vagrant::Box, :skip_windows do
expect(result[1].version).to eq("1.1") expect(result[1].version).to eq("1.1")
expect(result[2].url).to eq("bar") expect(result[2].url).to eq("bar")
end end
context "with architecture" do
subject do
described_class.new(
name, provider, version, directory,
architecture: architecture,
metadata_url: "foo"
)
end
it "raises an exception if no metadata_url is set" do
subject = described_class.new(
name, provider, version, directory,
architecture: architecture,
)
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(
{
name: "foo",
versions: [ { version: "1.0" } ]
}.to_json
)
allow(subject).to receive(:load_metadata).and_return(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(
{
name: "foo",
versions: [
{version: "1.0"},
{
version: "1.1",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: architecture,
}
]
}
]
}.to_json
)
allow(subject).to receive(:load_metadata).and_return(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 nil if update does not support architecture" do
metadata = Vagrant::BoxMetadata.new(
{
name: "foo",
versions: [
{version: "1.0"},
{
version: "1.1",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: "other-architecture",
}
]
}
]
}.to_json
)
allow(subject).to receive(:load_metadata).and_return(metadata)
result = subject.has_update?
expect(result).to be_nil
end
it "returns the updated box info within constraints" do
metadata = Vagrant::BoxMetadata.new(
{
name: "foo",
versions: [
{
version: "1.0",
},
{
version: "1.1",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: architecture
},
]
},
{
version: "1.2",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: "other-architecture",
},
]
},
{
version: "1.4",
providers: [
{
name: "virtualbox",
url: "bar",
architecture: architecture
}
]
}
]
}.to_json
)
allow(subject).to receive(:load_metadata).and_return(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
end end
context "#automatic_update_check_allowed?" do context "#automatic_update_check_allowed?" do
@ -236,12 +385,13 @@ describe Vagrant::Box, :skip_windows do
context "#in_use?" do context "#in_use?" do
let(:index) { [] } let(:index) { [] }
def new_entry(name, provider, version) def new_entry(name, provider, version, architecture=nil)
Vagrant::MachineIndex::Entry.new.tap do |entry| Vagrant::MachineIndex::Entry.new.tap do |entry|
entry.extra_data["box"] = { entry.extra_data["box"] = {
"name" => name, "name" => name,
"provider" => provider, "provider" => provider,
"version" => version, "version" => version,
"architecture" => architecture,
} }
end end
end end
@ -261,6 +411,27 @@ describe Vagrant::Box, :skip_windows do
expect(subject.in_use?(index)).to eq([matching]) expect(subject.in_use?(index)).to eq([matching])
end end
context "with architecture information" do
subject { described_class.new(name, provider, version, directory, architecture: architecture) }
it "returns nil if the index has no matching entries" do
index << new_entry("foo", "bar", "1.0", "amd64")
index << new_entry("foo", "baz", "1.2", "arm64")
index << new_entry(name, provider.to_s, version, "random-arch")
expect(subject).to_not be_in_use(index)
end
it "returns matching entries if they exist" do
matching = new_entry(name, provider.to_s, version, architecture)
index << new_entry("foo", "bar", "1.0", "amd64")
index << matching
index << new_entry("foo", "baz", "1.2")
expect(subject.in_use?(index)).to eq([matching])
end
end
end end
context "#load_metadata" do context "#load_metadata" do

View File

@ -26,6 +26,7 @@ describe Vagrant::Machine do
double("box").tap do |b| double("box").tap do |b|
allow(b).to receive(:name).and_return("foo") allow(b).to receive(:name).and_return("foo")
allow(b).to receive(:provider).and_return(:dummy) allow(b).to receive(:provider).and_return(:dummy)
allow(b).to receive(:architecture)
allow(b).to receive(:version).and_return("1.0") allow(b).to receive(:version).and_return("1.0")
end end
end end
@ -580,6 +581,7 @@ describe Vagrant::Machine do
box = double("box") box = double("box")
allow(box).to receive(:name).and_return("foo") allow(box).to receive(:name).and_return("foo")
allow(box).to receive(:provider).and_return(:bar) allow(box).to receive(:provider).and_return(:bar)
allow(box).to receive(:architecture)
allow(box).to receive(:version).and_return("1.2.3") allow(box).to receive(:version).and_return("1.2.3")
subject.box = box subject.box = box
@ -599,6 +601,7 @@ describe Vagrant::Machine do
expect(entry.extra_data["box"]).to eq({ expect(entry.extra_data["box"]).to eq({
"name" => box.name, "name" => box.name,
"provider" => box.provider.to_s, "provider" => box.provider.to_s,
"architecture" => nil,
"version" => box.version, "version" => box.version,
}) })
env.machine_index.release(entry) env.machine_index.release(entry)

View File

@ -11,6 +11,70 @@ describe Vagrant::Util::Platform do
after { described_class.reset! } after { described_class.reset! }
subject { described_class } subject { described_class }
describe "#architecture" do
let(:cpu_string) { "unknown" }
before do
allow(RbConfig::CONFIG).
to receive(:[]).with("target_cpu").
and_return(cpu_string)
end
context "when cpu is x86_64" do
let(:cpu_string) { "x86_64" }
it "should be mapped to amd64" do
expect(described_class.architecture).to eq("amd64")
end
end
context "when cpu is i386" do
let(:cpu_string) { "i386" }
it "should be mapped to 386" do
expect(described_class.architecture).to eq("386")
end
end
context "when cpu is arm64" do
let(:cpu_string) { "arm64" }
it "should be arm64" do
expect(described_class.architecture).to eq("arm64")
end
end
context "when cpu is aarch64" do
let(:cpu_string) { "aarch64" }
it "should be mapped to arm64" do
expect(described_class.architecture).to eq("arm64")
end
end
context "when cpu is unmapped value" do
let(:cpu_string) { "custom-cpu" }
it "should be returned as-is" do
expect(described_class.architecture).to eq(cpu_string)
end
end
context "when environment variable override is set" do
let(:host_override) { "custom-host-override" }
before do
allow(ENV).to receive(:[]).
with("VAGRANT_HOST_ARCHITECTURE").
and_return(host_override)
end
it "should return the custom override" do
expect(subject.architecture).to eq(host_override)
end
end
end
describe "#cygwin_path" do describe "#cygwin_path" do
let(:path) { "C:\\msys2\\home\\vagrant" } let(:path) { "C:\\msys2\\home\\vagrant" }
let(:updated_path) { "/home/vagrant" } let(:updated_path) { "/home/vagrant" }

View File

@ -266,6 +266,44 @@ describe Vagrant::Vagrantfile do
expect(box.version).to eq("1.3") expect(box.version).to eq("1.3")
end end
it "configures with the custom box architecture" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
config.vm.box_architecture = "custom-arch"
end
results = subject.machine_config(:default, :foo, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.vm.box_architecture).to eq("custom-arch")
end
it "configures with the default box architecture" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
end
results = subject.machine_config(:default, :foo, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.vm.box_architecture).to eq(:auto)
end
it "configures box architecture to nil" do
register_provider("foo")
configure do |config|
config.vm.box = "base"
config.vm.box_architecture = nil
end
results = subject.machine_config(:default, :foo, boxes)
config = results[:config]
expect(config.vm.box).to eq("base")
expect(config.vm.box_architecture).to be_nil
end
it "configures with box config of other supported formats" do it "configures with box config of other supported formats" do
register_provider("foo", nil, box_format: "bar") register_provider("foo", nil, box_format: "bar")