Add provider capaiblity :has_communicator

This commit is contained in:
sophia 2020-05-18 14:10:42 -04:00
parent 672859e296
commit 66a3b58c08
9 changed files with 120 additions and 103 deletions

View File

@ -24,6 +24,7 @@ module Vagrant
autoload :HandleBox, "vagrant/action/builtin/handle_box"
autoload :HandleBoxUrl, "vagrant/action/builtin/handle_box_url"
autoload :HandleForwardedPortCollisions, "vagrant/action/builtin/handle_forwarded_port_collisions"
autoload :HasProvisioner, "vagrant/action/builtin/has_provisioner"
autoload :IsEnvSet, "vagrant/action/builtin/is_env_set"
autoload :IsState, "vagrant/action/builtin/is_state"
autoload :Lock, "vagrant/action/builtin/lock"

View File

@ -0,0 +1,36 @@
module Vagrant
module Action
module Builtin
# This middleware is used with Call to test if this machine
# has available provisioners
class HasProvisioner
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::action::builtin::has_provisioner")
end
def call(env)
machine = env[:machine]
if machine.provider.capability?(:has_communicator)
has_communicator = machine.provider.capability(:has_communicator)
else
has_communicator = true
end
env[:skip] = []
if !has_communicator
machine.config.vm.provisioners.each do |p|
if p.communicator_required
env[:skip].push(p)
@logger.info("Skipping running provisioner #{p.name || 'no name'}, type: #{p.type}")
p.run = :never
end
end
end
@app.call(env)
end
end
end
end
end

View File

@ -75,7 +75,7 @@ module VagrantPlugins
@type = type
@before = options[:before]
@after = options[:after]
@communicator_required = options[:communicator_required] || true
@communicator_required = options.fetch(:communicator_required, true)
# Attempt to find the provisioner...
if !Vagrant.plugin("2").manager.provisioners[type]

View File

@ -67,9 +67,6 @@ module VagrantPlugins
end
b3.use Call, HasProvisioner do |env3, b4|
if env3[:skip].length > 0
b4.use Message, I18n.t("docker_provider.messages.not_provisioning", provisioiners: check_skipped_provisioners(env3[:skip]))
end
b4.use Provision
end
end
@ -214,9 +211,6 @@ module VagrantPlugins
b.use Call, IsState, :running do |env, b2|
if env[:machine_action] != :run_command
b2.use Call, HasProvisioner do |env2, b3|
if env2[:skip].length > 0
b3.use Message, I18n.t("docker_provider.messages.not_provisioning", provisioiners: check_skipped_provisioners(env2[:skip]))
end
b3.use Provision
end
end
@ -298,7 +292,6 @@ module VagrantPlugins
autoload :DestroyNetwork, action_root.join("destroy_network")
autoload :ForwardedPorts, action_root.join("forwarded_ports")
autoload :HasSSH, action_root.join("has_ssh")
autoload :HasProvisioner, action_root.join("has_provisioner")
autoload :HostMachine, action_root.join("host_machine")
autoload :HostMachineBuildDir, action_root.join("host_machine_build_dir")
autoload :HostMachinePortChecker, action_root.join("host_machine_port_checker")
@ -319,13 +312,6 @@ module VagrantPlugins
autoload :Start, action_root.join("start")
autoload :Stop, action_root.join("stop")
autoload :WaitForRunning, action_root.join("wait_for_running")
private
def self.check_skipped_provisioners(provisioners)
skipped_provisioners = provisioners.map { |p| "#{p.name || 'no name'}, type: #{p.type}" }
skipped_provisioners.join("\n- ")
end
end
end
end

View File

@ -1,26 +0,0 @@
module VagrantPlugins
module DockerProvider
module Action
# This middleware is used with Call to test if this machine
# has available provisioners
class HasProvisioner
def initialize(app, env)
@app = app
end
def call(env)
env[:skip] = []
if !env[:machine].provider_config.has_ssh
env[:machine].config.vm.provisioners.each do |p|
if p.communicator_required
env[:skip].push(p)
p.run = :never
end
end
end
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,11 @@
module VagrantPlugins
module DockerProvider
module Cap
module HasCommunicator
def self.has_communicator(machine)
return machine.provider_config.has_ssh
end
end
end
end
end

View File

@ -67,6 +67,11 @@ module VagrantPlugins
Cap::ProxyMachine
end
provider_capability("docker", "has_communicator") do
require_relative "cap/has_communicator"
Cap::HasCommunicator
end
protected
def self.init!

View File

@ -1,62 +0,0 @@
require_relative "../../../../base"
require_relative "../../../../../../plugins/providers/docker/action/has_provisioner"
describe VagrantPlugins::DockerProvider::Action::HasProvisioner do
include_context "unit"
let(:sandbox) { isolated_environment }
let(:iso_env) do
# We have to create a Vagrantfile so there is a root path
sandbox.vagrantfile("")
sandbox.create_vagrant_env
end
let(:provisioner_one) { double("provisioner_one") }
let(:provisioner_two) { double("provisioner_two") }
let(:provisioners) { [provisioner_one, provisioner_two] }
let(:machine) do
iso_env.machine(iso_env.machine_names[0], :docker).tap do |m|
allow(m).to receive_message_chain(:config, :vm, :provisioners).and_return(provisioners)
end
end
let(:env) {{ machine: machine, ui: machine.ui, root_path: Pathname.new(".") }}
let(:app) { lambda { |*args| }}
subject { described_class.new(app, env) }
after do
sandbox.close
end
describe "#call" do
before do
allow(provisioner_one).to receive(:communicator_required).and_return(true)
allow(provisioner_two).to receive(:communicator_required).and_return(false)
end
it "does not skip any provisioners if provider has ssh" do
env[:machine].provider_config.has_ssh = true
expect(provisioner_one).to_not receive(:communicator_required)
expect(provisioner_two).to_not receive(:communicator_required)
subject.call(env)
expect(env[:skip]).to eq([])
end
it "skips provisioners that require a communicator if provider does not have ssh" do
env[:machine].provider_config.has_ssh = false
expect(provisioner_one).to receive(:communicator_required)
expect(provisioner_two).to receive(:communicator_required)
expect(provisioner_one).to receive(:run=).with(:never)
subject.call(env)
expect(env[:skip]).to eq([provisioner_one])
end
end
end

View File

@ -0,0 +1,66 @@
require File.expand_path("../../../../base", __FILE__)
describe Vagrant::Action::Builtin::HasProvisioner do
include_context "unit"
let(:provisioner_one) { double("provisioner_one") }
let(:provisioner_two) { double("provisioner_two") }
let(:provisioners) { [provisioner_one, provisioner_two] }
let(:machine) { double("machine") }
let(:ui) {double("ui") }
let(:env) {{ machine: machine, ui: ui, root_path: Pathname.new(".") }}
let(:app) { lambda { |*args| }}
subject { described_class.new(app, env) }
describe "#call" do
before do
allow(provisioner_one).to receive(:communicator_required).and_return(true)
allow(provisioner_one).to receive(:name)
allow(provisioner_one).to receive(:type)
allow(provisioner_two).to receive(:communicator_required).and_return(false)
allow(provisioner_two).to receive(:name)
allow(provisioner_two).to receive(:type)
allow(machine).to receive_message_chain(:config, :vm, :provisioners).and_return(provisioners)
end
context "provider has capability :has_communicator" do
before do
allow(machine).to receive_message_chain(:provider, :capability?).with(:has_communicator).and_return(true)
end
it "does not skip any provisioners if provider has ssh" do
allow(machine).to receive_message_chain(:provider, :capability).with(:has_communicator).and_return(true)
expect(provisioner_one).to_not receive(:communicator_required)
expect(provisioner_two).to_not receive(:communicator_required)
subject.call(env)
expect(env[:skip]).to eq([])
end
it "skips provisioners that require a communicator if provider does not have ssh" do
allow(machine).to receive_message_chain(:provider, :capability).with(:has_communicator).and_return(false)
expect(provisioner_one).to receive(:communicator_required)
expect(provisioner_two).to receive(:communicator_required)
expect(provisioner_one).to receive(:run=).with(:never)
subject.call(env)
expect(env[:skip]).to eq([provisioner_one])
end
end
context "provider does not have capability :has_communicator" do
before do
allow(machine).to receive_message_chain(:provider, :capability?).with(:has_communicator).and_return(false)
end
it "does not skip any provisioners" do
expect(provisioner_one).to_not receive(:communicator_required)
expect(provisioner_two).to_not receive(:communicator_required)
subject.call(env)
expect(env[:skip]).to eq([])
end
end
end
end