core: commands can use the IDs from anywhere to control
This commit is contained in:
parent
9a16af10ad
commit
a0e9f46251
|
@ -108,9 +108,11 @@ module Vagrant
|
||||||
|
|
||||||
@lock.synchronize do
|
@lock.synchronize do
|
||||||
with_index_lock do
|
with_index_lock do
|
||||||
return nil if !@machines[uuid]
|
data = find_by_prefix(uuid)
|
||||||
|
return nil if !data
|
||||||
|
uuid = data["id"]
|
||||||
|
|
||||||
entry = Entry.new(uuid, @machines[uuid].merge("id" => uuid))
|
entry = Entry.new(uuid, data)
|
||||||
|
|
||||||
# Lock this machine
|
# Lock this machine
|
||||||
lock_file = lock_machine(uuid)
|
lock_file = lock_machine(uuid)
|
||||||
|
@ -127,6 +129,14 @@ module Vagrant
|
||||||
entry
|
entry
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Tests if the index has the given UUID.
|
||||||
|
#
|
||||||
|
# @param [String] uuid
|
||||||
|
# @return [Boolean]
|
||||||
|
def include?(uuid)
|
||||||
|
!!find_by_prefix(uuid)
|
||||||
|
end
|
||||||
|
|
||||||
# Releases an entry, unlocking it.
|
# Releases an entry, unlocking it.
|
||||||
#
|
#
|
||||||
# This is an idempotent operation. It is safe to call this even if you're
|
# This is an idempotent operation. It is safe to call this even if you're
|
||||||
|
@ -192,6 +202,17 @@ module Vagrant
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
# Finds a machine where the UUID is prefixed by the given string.
|
||||||
|
#
|
||||||
|
# @return [Hash]
|
||||||
|
def find_by_prefix(prefix)
|
||||||
|
@machines.each do |uuid, data|
|
||||||
|
return data.merge("id" => uuid) if uuid.start_with?(prefix)
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
# Locks a machine exclusively to us, returning the file handle
|
# Locks a machine exclusively to us, returning the file handle
|
||||||
# that holds the lock.
|
# that holds the lock.
|
||||||
#
|
#
|
||||||
|
|
|
@ -82,9 +82,6 @@ module Vagrant
|
||||||
@logger.debug(" -- names: #{names.inspect}")
|
@logger.debug(" -- names: #{names.inspect}")
|
||||||
@logger.debug(" -- options: #{options.inspect}")
|
@logger.debug(" -- options: #{options.inspect}")
|
||||||
|
|
||||||
# Using VMs requires a Vagrant environment to be properly setup
|
|
||||||
raise Errors::NoEnvironmentError if !@env.root_path
|
|
||||||
|
|
||||||
# Setup the options hash
|
# Setup the options hash
|
||||||
options ||= {}
|
options ||= {}
|
||||||
|
|
||||||
|
@ -92,6 +89,21 @@ module Vagrant
|
||||||
names ||= []
|
names ||= []
|
||||||
names = [names] if !names.is_a?(Array)
|
names = [names] if !names.is_a?(Array)
|
||||||
|
|
||||||
|
# Determine if we require a local Vagrant environment. There are
|
||||||
|
# two cases that we require a local environment:
|
||||||
|
#
|
||||||
|
# * We're asking for ANY/EVERY VM (no names given).
|
||||||
|
#
|
||||||
|
# * We're asking for specific VMs, at least once of which
|
||||||
|
# is NOT in the local machine index.
|
||||||
|
#
|
||||||
|
requires_local_env = false
|
||||||
|
requires_local_env = true if names.empty?
|
||||||
|
requires_local_env ||= names.any? { |n|
|
||||||
|
!@env.machine_index.include?(n)
|
||||||
|
}
|
||||||
|
raise Errors::NoEnvironmentError if requires_local_env && !@env.root_path
|
||||||
|
|
||||||
# Cache the active machines outside the loop
|
# Cache the active machines outside the loop
|
||||||
active_machines = @env.active_machines
|
active_machines = @env.active_machines
|
||||||
|
|
||||||
|
@ -112,6 +124,20 @@ module Vagrant
|
||||||
provider_to_use = options[:provider]
|
provider_to_use = options[:provider]
|
||||||
provider_to_use = provider_to_use.to_sym if provider_to_use
|
provider_to_use = provider_to_use.to_sym if provider_to_use
|
||||||
|
|
||||||
|
# If we have this machine in our index, load that.
|
||||||
|
entry = @env.machine_index.get(name.to_s)
|
||||||
|
if entry
|
||||||
|
@env.machine_index.release(entry)
|
||||||
|
|
||||||
|
# Create an environment for this location and yield the
|
||||||
|
# machine in that environment.
|
||||||
|
env = Vagrant::Environment.new(
|
||||||
|
cwd: entry.vagrantfile_path,
|
||||||
|
home_path: @env.home_path,
|
||||||
|
)
|
||||||
|
next env.machine(entry.name.to_sym, entry.provider.to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
active_machines.each do |active_name, active_provider|
|
active_machines.each do |active_name, active_provider|
|
||||||
if name == active_name
|
if name == active_name
|
||||||
# We found an active machine with the same name
|
# We found an active machine with the same name
|
||||||
|
|
|
@ -800,9 +800,11 @@ en:
|
||||||
|
|
||||||
%{types}
|
%{types}
|
||||||
no_env: |-
|
no_env: |-
|
||||||
A Vagrant environment is required to run this command. Run `vagrant init`
|
A Vagrant environment or target machine is required to run this
|
||||||
to set one up in this directory, or change to a directory with a
|
command. Run `vagrant init` to create a new Vagrant environment. Or,
|
||||||
Vagrantfile and try again.
|
get an ID of a target machine from `vagrant global-status` to run
|
||||||
|
this command on. A final option is to change to a directory with a
|
||||||
|
Vagrantfile and to try again.
|
||||||
plugin_gem_not_found: |-
|
plugin_gem_not_found: |-
|
||||||
The plugin '%{name}' could not be installed because it could not
|
The plugin '%{name}' could not be installed because it could not
|
||||||
be found. Please double check the name and try again.
|
be found. Please double check the name and try again.
|
||||||
|
|
|
@ -12,6 +12,13 @@ describe Vagrant::MachineIndex do
|
||||||
let(:data_dir) { temporary_dir }
|
let(:data_dir) { temporary_dir }
|
||||||
let(:entry_klass) { Vagrant::MachineIndex::Entry }
|
let(:entry_klass) { Vagrant::MachineIndex::Entry }
|
||||||
|
|
||||||
|
let(:new_entry) do
|
||||||
|
entry_klass.new.tap do |e|
|
||||||
|
e.name = "foo"
|
||||||
|
e.vagrantfile_path = "/bar"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
subject { described_class.new(data_dir) }
|
subject { described_class.new(data_dir) }
|
||||||
|
|
||||||
it "raises an exception if the data file is corrupt" do
|
it "raises an exception if the data file is corrupt" do
|
||||||
|
@ -96,6 +103,17 @@ describe Vagrant::MachineIndex do
|
||||||
expect(result.updated_at).to eq("foo")
|
expect(result.updated_at).to eq("foo")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns a valid entry by unique prefix" do
|
||||||
|
result = subject.get("b")
|
||||||
|
|
||||||
|
expect(result).to_not be_nil
|
||||||
|
expect(result.id).to eq("bar")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should include? by prefix" do
|
||||||
|
expect(subject.include?("b")).to be_true
|
||||||
|
end
|
||||||
|
|
||||||
it "locks the entry so subsequent gets fail" do
|
it "locks the entry so subsequent gets fail" do
|
||||||
result = subject.get("bar")
|
result = subject.get("bar")
|
||||||
expect(result).to_not be_nil
|
expect(result).to_not be_nil
|
||||||
|
@ -114,14 +132,22 @@ describe Vagrant::MachineIndex do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#set and #get and #delete" do
|
describe "#include" do
|
||||||
let(:new_entry) do
|
it "should not include non-existent things" do
|
||||||
entry_klass.new.tap do |e|
|
expect(subject.include?("foo")).to be_false
|
||||||
e.name = "foo"
|
end
|
||||||
e.vagrantfile_path = "/bar"
|
|
||||||
|
it "should include created entries" do
|
||||||
|
result = subject.set(new_entry)
|
||||||
|
expect(result.id).to_not be_empty
|
||||||
|
subject.release(result)
|
||||||
|
|
||||||
|
subject = described_class.new(data_dir)
|
||||||
|
expect(subject.include?(result.id)).to be_true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#set and #get and #delete" do
|
||||||
it "adds a new entry" do
|
it "adds a new entry" do
|
||||||
result = subject.set(new_entry)
|
result = subject.set(new_entry)
|
||||||
expect(result.id).to_not be_empty
|
expect(result.id).to_not be_empty
|
||||||
|
|
|
@ -2,6 +2,8 @@ require File.expand_path("../../../../base", __FILE__)
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
|
|
||||||
describe Vagrant::Plugin::V2::Command do
|
describe Vagrant::Plugin::V2::Command do
|
||||||
|
include_context "unit"
|
||||||
|
|
||||||
describe "parsing options" do
|
describe "parsing options" do
|
||||||
let(:klass) do
|
let(:klass) do
|
||||||
Class.new(described_class) do
|
Class.new(described_class) do
|
||||||
|
@ -53,18 +55,17 @@ describe Vagrant::Plugin::V2::Command do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:default_provider) { :virtualbox }
|
|
||||||
|
|
||||||
let(:environment) do
|
let(:environment) do
|
||||||
env = double("environment")
|
# We have to create a Vagrantfile so there is a root path
|
||||||
env.stub(:active_machines => [])
|
test_iso_env.vagrantfile("")
|
||||||
env.stub(:default_provider => default_provider)
|
test_iso_env.create_vagrant_env
|
||||||
env.stub(:root_path => "foo")
|
|
||||||
env
|
|
||||||
end
|
end
|
||||||
|
let(:test_iso_env) { isolated_environment }
|
||||||
|
|
||||||
let(:instance) { klass.new([], environment) }
|
let(:instance) { klass.new([], environment) }
|
||||||
|
|
||||||
|
subject { instance }
|
||||||
|
|
||||||
it "should raise an exception if a root_path is not available" do
|
it "should raise an exception if a root_path is not available" do
|
||||||
environment.stub(:root_path => nil)
|
environment.stub(:root_path => nil)
|
||||||
|
|
||||||
|
@ -82,8 +83,8 @@ describe Vagrant::Plugin::V2::Command do
|
||||||
bar_vm.stub(ui: Vagrant::UI::Silent.new)
|
bar_vm.stub(ui: Vagrant::UI::Silent.new)
|
||||||
|
|
||||||
environment.stub(:machine_names => [:foo, :bar])
|
environment.stub(:machine_names => [:foo, :bar])
|
||||||
allow(environment).to receive(:machine).with(:foo, default_provider).and_return(foo_vm)
|
allow(environment).to receive(:machine).with(:foo, environment.default_provider).and_return(foo_vm)
|
||||||
allow(environment).to receive(:machine).with(:bar, default_provider).and_return(bar_vm)
|
allow(environment).to receive(:machine).with(:bar, environment.default_provider).and_return(bar_vm)
|
||||||
|
|
||||||
vms = []
|
vms = []
|
||||||
instance.with_target_vms do |vm|
|
instance.with_target_vms do |vm|
|
||||||
|
@ -106,7 +107,7 @@ describe Vagrant::Plugin::V2::Command do
|
||||||
foo_vm.stub(:name => "foo", :provider => :foobarbaz)
|
foo_vm.stub(:name => "foo", :provider => :foobarbaz)
|
||||||
foo_vm.stub(ui: Vagrant::UI::Silent.new)
|
foo_vm.stub(ui: Vagrant::UI::Silent.new)
|
||||||
|
|
||||||
allow(environment).to receive(:machine).with(:foo, default_provider).and_return(foo_vm)
|
allow(environment).to receive(:machine).with(:foo, environment.default_provider).and_return(foo_vm)
|
||||||
|
|
||||||
vms = []
|
vms = []
|
||||||
instance.with_target_vms("foo") { |vm| vms << vm }
|
instance.with_target_vms("foo") { |vm| vms << vm }
|
||||||
|
@ -167,8 +168,8 @@ describe Vagrant::Plugin::V2::Command do
|
||||||
name = :foo
|
name = :foo
|
||||||
machine = double("machine")
|
machine = double("machine")
|
||||||
|
|
||||||
allow(environment).to receive(:machine).with(name, default_provider).and_return(machine)
|
allow(environment).to receive(:machine).with(name, environment.default_provider).and_return(machine)
|
||||||
machine.stub(:name => name, :provider => default_provider)
|
machine.stub(:name => name, :provider => environment.default_provider)
|
||||||
machine.stub(ui: Vagrant::UI::Silent.new)
|
machine.stub(ui: Vagrant::UI::Silent.new)
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
@ -198,16 +199,37 @@ describe Vagrant::Plugin::V2::Command do
|
||||||
machine = double("machine")
|
machine = double("machine")
|
||||||
|
|
||||||
environment.stub(:active_machines => [])
|
environment.stub(:active_machines => [])
|
||||||
allow(environment).to receive(:machine).with(name, default_provider).and_return(machine)
|
allow(environment).to receive(:machine).with(name, environment.default_provider).and_return(machine)
|
||||||
environment.stub(:machine_names => [])
|
environment.stub(:machine_names => [])
|
||||||
environment.stub(:primary_machine_name => name)
|
environment.stub(:primary_machine_name => name)
|
||||||
machine.stub(:name => name, :provider => default_provider)
|
machine.stub(:name => name, :provider => environment.default_provider)
|
||||||
machine.stub(ui: Vagrant::UI::Silent.new)
|
machine.stub(ui: Vagrant::UI::Silent.new)
|
||||||
|
|
||||||
vms = []
|
vms = []
|
||||||
instance.with_target_vms(nil, :single_target => true) { |vm| vms << machine }
|
instance.with_target_vms(nil, :single_target => true) { |vm| vms << machine }
|
||||||
expect(vms).to eq([machine])
|
expect(vms).to eq([machine])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should yield machines from another environment" do
|
||||||
|
iso_env = isolated_environment
|
||||||
|
iso_env.vagrantfile("")
|
||||||
|
other_env = iso_env.create_vagrant_env(
|
||||||
|
home_path: environment.home_path)
|
||||||
|
other_machine = other_env.machine(
|
||||||
|
other_env.machine_names[0], other_env.default_provider)
|
||||||
|
|
||||||
|
# Set an ID on it so that it is "created" in the index
|
||||||
|
other_machine.id = "foo"
|
||||||
|
|
||||||
|
# Make sure we don't have a root path, to test
|
||||||
|
environment.stub(root_path: nil)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
subject.with_target_vms(other_machine.index_uuid) { |m| results << m }
|
||||||
|
|
||||||
|
expect(results.length).to eq(1)
|
||||||
|
expect(results[0].id).to eq(other_machine.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "splitting the main and subcommand args" do
|
describe "splitting the main and subcommand args" do
|
||||||
|
|
Loading…
Reference in New Issue