From eee6fefd67478665d3a3cdb6c31c6460a5e0216a Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Mon, 21 Apr 2025 16:32:39 -0700 Subject: [PATCH] Add a `:none` communicator Adds a communicator which does not provide communication to the guest machine. All methods for the communicator are simply stubbed with a successful result. This allows a guest to be configured with the `:none` communicator and Vagrant to properly `up` it. This currently lacks any user notification or guards within configuration to verify guest configuration does not rely on the communicator. It is wrapped as experimental to allow early access to the basic functionality without making it generally available. --- plugins/communicators/none/communicator.rb | 46 +++++++++++++++++++ plugins/communicators/none/plugin.rb | 26 +++++++++++ .../communicators/none/communicator_test.rb | 38 +++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 plugins/communicators/none/communicator.rb create mode 100644 plugins/communicators/none/plugin.rb create mode 100644 test/unit/plugins/communicators/none/communicator_test.rb diff --git a/plugins/communicators/none/communicator.rb b/plugins/communicators/none/communicator.rb new file mode 100644 index 000000000..cdd4e6fb1 --- /dev/null +++ b/plugins/communicators/none/communicator.rb @@ -0,0 +1,46 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +require "log4r" +require "vagrant" + +module VagrantPlugins + module CommunicatorNone + # This class provides no communication with the VM. + # It allows Vagrant to manage a machine lifecycle + # while not actually connecting to it. The communicator + # stubs out all methods to be successful allowing + # Vagrant to proceed "as normal" without actually + # doing anything. + class Communicator < Vagrant.plugin("2", :communicator) + def self.match?(_) + # Any machine can be not communicated with + true + end + + def initialize(_) + @logger = Log4r::Logger.new(self.class.name.downcase) + end + + def ready? + @logger.debug("#ready? stub called on none") + true + end + + def execute(*_) + @logger.debug("#execute stub called on none") + 0 + end + + def sudo(*_) + @logger.debug("#sudo stub called on none") + 0 + end + + def test(*_) + @logger.debug("#test stub called on none") + true + end + end + end +end diff --git a/plugins/communicators/none/plugin.rb b/plugins/communicators/none/plugin.rb new file mode 100644 index 000000000..bfcd98497 --- /dev/null +++ b/plugins/communicators/none/plugin.rb @@ -0,0 +1,26 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +require "vagrant" + +module VagrantPlugins + Vagrant::Util::Experimental.guard_with(:none_communicator) do + module CommunicatorNone + class Plugin < Vagrant.plugin("2") + name "none communicator" + description <<-DESC + This plugin provides no communication to remote machines. + It allows Vagrant to manage remote machines without the + ability to connect to them for configuration/provisioning. + Any calls to methods provided by this communicator will + always be successful. + DESC + + communicator("none") do + require File.expand_path("../communicator", __FILE__) + Communicator + end + end + end + end +end diff --git a/test/unit/plugins/communicators/none/communicator_test.rb b/test/unit/plugins/communicators/none/communicator_test.rb new file mode 100644 index 000000000..983f91f87 --- /dev/null +++ b/test/unit/plugins/communicators/none/communicator_test.rb @@ -0,0 +1,38 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +require File.expand_path("../../../../base", __FILE__) + +require Vagrant.source_root.join("plugins/communicators/none/communicator") + +describe VagrantPlugins::CommunicatorNone::Communicator do + include_context "unit" + + let(:machine) { double(:machine) } + + subject { described_class.new(machine) } + + context "#ready?" do + it "should be true" do + expect(subject.ready?).to be + end + end + + context "#execute" do + it "should be successful regardless of command" do + expect(subject.execute("/bin/false")).to eq(0) + end + end + + context "#sudo" do + it "should be successful regardless of command" do + expect(subject.execute("/bin/false")).to eq(0) + end + end + + context "test" do + it "should be true" do + expect(subject.test("/bin/false")).to be + end + end +end