Build up some operations that can be run.

These are heavily inspired by Fabric! Thanks!
This commit is contained in:
Mitchell Hashimoto 2012-05-05 19:28:50 -07:00
parent 00aba5ac03
commit 1d7e02cd63
3 changed files with 136 additions and 45 deletions

View File

@ -1,7 +1,8 @@
require "log4r"
module Vagrant
class EasyCommand
module EasyCommand
autoload :Base, "vagrant/easy_command/base"
autoload :Operations, "vagrant/easy_command/operations"
# This creates a new easy command. This typically is not called
# directly. Instead, the plugin interface's `easy_command` is
# used to create one of these.
@ -11,47 +12,5 @@ module Vagrant
command.configure(name, &block)
command
end
# Base class for all easy commands. This contains the basic code
# that knows how to run the easy commands.
class Base < Vagrant::Command::Base
@@command = nil
@@runner = nil
# This is called by the {EasyCommand.create} method when creating
# an easy command to set the invocation command.
def self.configure(name, &block)
@@command = name
@@runner = block
end
def initialize(*args, &block)
super
@logger = Log4r::Logger.new("vagrant::easy_command::#{@@command}")
end
def execute
# Build up a basic little option parser
opts = OptionParser.new do |opts|
opts.banner = "Usage: vagrant #{@@command}"
end
# Parse the options
argv = parse_options(opts)
return if !argv
# Run the action for each VM.
@logger.info("Running easy command: #{@@command}")
with_target_vms(argv) do |vm|
@logger.debug("Running easy command for VM: #{vm.name}")
@@runner.call(nil)
end
# Exit status 0 every time for now
0
end
end
end
end

View File

@ -0,0 +1,46 @@
require "log4r"
module Vagrant
module EasyCommand
# Base class for all easy commands. This contains the basic code
# that knows how to run the easy commands.
class Base < Vagrant::Command::Base
@@command = nil
@@runner = nil
# This is called by the {EasyCommand.create} method when creating
# an easy command to set the invocation command.
def self.configure(name, &block)
@@command = name
@@runner = block
end
def initialize(*args, &block)
super
@logger = Log4r::Logger.new("vagrant::easy_command::#{@@command}")
end
def execute
# Build up a basic little option parser
opts = OptionParser.new do |opts|
opts.banner = "Usage: vagrant #{@@command}"
end
# Parse the options
argv = parse_options(opts)
return if !argv
# Run the action for each VM.
@logger.info("Running easy command: #{@@command}")
with_target_vms(argv) do |vm|
@logger.debug("Running easy command for VM: #{vm.name}")
@@runner.call(Operations.new(vm))
end
# Exit status 0 every time for now
0
end
end
end
end

View File

@ -0,0 +1,86 @@
require "ostruct"
require "log4r"
require "vagrant/util/subprocess"
module Vagrant
module EasyCommand
# This class contains all the "operations" that easy commands are able
# to run. An instance of this is class is what is sent into the callback
# for all easy commands.
class Operations
def initialize(vm)
@logger = Log4r::Logger.new("vagrant::easy_command::operations")
@vm = vm
end
# Runs a command on the local machine. This will return an object where
# you can access the `exit_code`, `stdout`, and `stderr` easiy:
#
# output = local("echo foo")
# puts "Output was #{output.stdout}"
#
# (Likewise, `exit_code` and `stderr` are attributes on the return value)
#
# It is recommended you use this `local` method rather than trying to
# manually use Ruby's underlying subprocess tools because this will use
# the Vagrant `Subprocess` class which has been refined over the years
# to work equally well on Windows, Mac OS X, Linux as well as on many
# runtimes such as CRuby and JRuby.
#
# @param [String] command Command to run
def local(command)
@logger.info("local: #{command}")
Vagrant::Util::Subprocess.execute(command)
end
# Run a shell command within the VM. The command will run within a
# shell environment, and the output and exit code will be returned
# as an object with attributes: `exit_code, `stdout`, and `stderr`.
# Example:
#
# output = run("echo foo")
# puts "Output was #{output.stdout}"
#
# @param [String] command Command to run
def run(command)
@logger.info("run: #{command}")
remote_command(:execute, command)
end
# Same as {run} except runs the command with superuser privileges
# via `sudo`.
#
# @param [String] command Command
def sudo(command)
@logger.info("sudo: #{command}")
remote_command(:sudo, command)
end
protected
# Runs a command on the remote host.
def remote_command(type, command)
# If the VM is not running, then we can't run SSH commands...
raise Errors::VMNotRunningError if @vm.state != :running
# Initialize the result object, execute, and store the data
result = OpenStruct.new
result.stderr = ""
result.stdout = ""
result.exit_code = @vm.channel.send(type, command,
:error_check => false) do |type, data|
if type == :stdout
result.stdout += data
elsif type == :stderr
result.stderr += data
end
end
# Return the result
result
end
end
end
end