Add the Communicator plugin API.
This allows communication protocols to be defined for the machine. This is how things like SSH will be implemented.
This commit is contained in:
parent
f1c1dfad2f
commit
a1cef830e3
|
@ -85,14 +85,16 @@ module Vagrant
|
|||
|
||||
# These are the various plugin versions and their components in
|
||||
# a lazy loaded Hash-like structure.
|
||||
c = PLUGIN_COMPONENTS = Registry.new
|
||||
c.register(:"1") { Plugin::V1::Plugin }
|
||||
c.register([:"1", :command]) { Plugin::V1::Command }
|
||||
c.register([:"1", :config]) { Plugin::V1::Config }
|
||||
c.register([:"1", :guest]) { Plugin::V1::Guest }
|
||||
c.register([:"1", :host]) { Plugin::V1::Host }
|
||||
c.register([:"1", :provider]) { Plugin::V1::Provider }
|
||||
c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
|
||||
PLUGIN_COMPONENTS = Registry.new.tap do |c|
|
||||
c.register(:"1") { Plugin::V1::Plugin }
|
||||
c.register([:"1", :command]) { Plugin::V1::Command }
|
||||
c.register([:"1", :communicator]) { Plugin::V1::Communicator }
|
||||
c.register([:"1", :config]) { Plugin::V1::Config }
|
||||
c.register([:"1", :guest]) { Plugin::V1::Guest }
|
||||
c.register([:"1", :host]) { Plugin::V1::Host }
|
||||
c.register([:"1", :provider]) { Plugin::V1::Provider }
|
||||
c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
|
||||
end
|
||||
|
||||
# The source root is the path to the root directory of
|
||||
# the Vagrant gem.
|
||||
|
|
|
@ -92,6 +92,25 @@ module Vagrant
|
|||
@env.action_runner.run(callable, env)
|
||||
end
|
||||
|
||||
# Returns a communication object for executing commands on the remote
|
||||
# machine. Note that the _exact_ semantics of this are up to the
|
||||
# communication provider itself. Despite this, the semantics are expected
|
||||
# to be consistent across operating systems. For example, all linux-based
|
||||
# systems should have similar communication (usually a shell). All
|
||||
# Windows systems should have similar communication as well. Therefore,
|
||||
# prior to communicating with the machine, users of this method are
|
||||
# expected to check the guest OS to determine their behavior.
|
||||
#
|
||||
# This method will _always_ return some valid communication object.
|
||||
# The `ready?` API can be used on the object to check if communication
|
||||
# is actually ready.
|
||||
#
|
||||
# @return [Object]
|
||||
def communicate
|
||||
# For now, we always return SSH. In the future, we'll abstract
|
||||
# this and allow plugins to define new methods of communication.
|
||||
end
|
||||
|
||||
# This sets the unique ID associated with this machine. This will
|
||||
# persist this ID so that in the future Vagrant will be able to find
|
||||
# this machine again. The unique ID must be absolutely unique to the
|
||||
|
|
|
@ -6,6 +6,7 @@ module Vagrant
|
|||
module Plugin
|
||||
module V1
|
||||
autoload :Command, "vagrant/plugin/v1/command"
|
||||
autoload :Communicator, "vagrant/plugin/v1/communicator"
|
||||
autoload :Config, "vagrant/plugin/v1/config"
|
||||
autoload :Guest, "vagrant/plugin/v1/guest"
|
||||
autoload :Host, "vagrant/plugin/v1/host"
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
module Vagrant
|
||||
module Plugin
|
||||
module V1
|
||||
# Base class for a communicator in Vagrant. A communicator is
|
||||
# responsible for communicating with a machine in some way. There
|
||||
# are various stages of Vagrant that require things such as uploading
|
||||
# files to the machine, executing shell commands, etc. Implementors
|
||||
# of this class are expected to provide this functionality in some
|
||||
# way.
|
||||
#
|
||||
# Note that a communicator must provide **all** of the methods
|
||||
# in this base class. There is currently no way for one communicator
|
||||
# to provide say a more efficient way of uploading a file, but not
|
||||
# provide shell execution. This sort of thing will come in a future
|
||||
# version.
|
||||
class Communicator
|
||||
# This returns true/false depending on if the given machine
|
||||
# can be communicated with using this communicator. If this returns
|
||||
# `true`, then this class will be used as the primary communication
|
||||
# method for the machine.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def self.match?(machine)
|
||||
false
|
||||
end
|
||||
|
||||
# Initializes the communicator with the machine that we will be
|
||||
# communicating with. This base method does nothing (it doesn't
|
||||
# even store the machine in an instance variable for you), so you're
|
||||
# expected to override this and do something with the machine if
|
||||
# you care about it.
|
||||
#
|
||||
# @param [Machine] machine The machine this instance is expected to
|
||||
# communicate with.
|
||||
def initialize(machine)
|
||||
end
|
||||
|
||||
# Checks if the target machine is ready for communication. If this
|
||||
# returns true, then all the other methods for communicating with
|
||||
# the machine are expected to be functional.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def ready?
|
||||
false
|
||||
end
|
||||
|
||||
# Download a file from the remote machine to the local machine.
|
||||
#
|
||||
# @param [String] from Path of the file on the remote machine.
|
||||
# @param [String] to Path of where to save the file locally.
|
||||
def download(from, to)
|
||||
end
|
||||
|
||||
# Upload a file to the remote machine.
|
||||
#
|
||||
# @param [String] from Path of the file locally to upload.
|
||||
# @param [String] to Path of where to save the file on the remote
|
||||
# machine.
|
||||
def upload(from, to)
|
||||
end
|
||||
|
||||
# Execute a command on the remote machine. The exact semantics
|
||||
# of this method are up to the implementor, but in general the
|
||||
# users of this class will expect this to be a shell.
|
||||
#
|
||||
# This method gives you no way to write data back to the remote
|
||||
# machine, so only execute commands that don't expect input.
|
||||
#
|
||||
# @param [String] command Command to execute.
|
||||
# @yield [type, data] Realtime output of the command being executed.
|
||||
# @yieldparam [String] type Type of the output. This can be
|
||||
# `:stdout`, `:stderr`, etc. The exact types are up to the
|
||||
# implementor.
|
||||
# @yieldparam [String] data Data for the given output.
|
||||
# @return [Integer] Exit code of the command.
|
||||
def execute(command, opts=nil)
|
||||
end
|
||||
|
||||
# Executes a command on the remote machine with administrative
|
||||
# privileges. See {#execute} for documentation, as the API is the
|
||||
# same.
|
||||
#
|
||||
# @see #execute
|
||||
def sudo(command, opts=nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
describe Vagrant::Plugin::V1::Communicator do
|
||||
let(:machine) { Object.new }
|
||||
|
||||
it "should not match by default" do
|
||||
described_class.match?(machine).should_not be
|
||||
end
|
||||
end
|
|
@ -13,6 +13,7 @@ describe Vagrant do
|
|||
|
||||
it "returns the proper components for version 1" do
|
||||
described_class.plugin("1", :command).should == Vagrant::Plugin::V1::Command
|
||||
described_class.plugin("1", :communicator).should == Vagrant::Plugin::V1::Communicator
|
||||
described_class.plugin("1", :config).should == Vagrant::Plugin::V1::Config
|
||||
described_class.plugin("1", :guest).should == Vagrant::Plugin::V1::Guest
|
||||
described_class.plugin("1", :host).should == Vagrant::Plugin::V1::Host
|
||||
|
|
Loading…
Reference in New Issue