Init command. Tests for the base command.
This commit is contained in:
parent
2691b0493c
commit
48b7596357
|
@ -3,6 +3,15 @@ require 'virtualbox'
|
||||||
require "vagrant/util/glob_loader"
|
require "vagrant/util/glob_loader"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
|
# TODO: Move more classes over to the autoload model. We'll
|
||||||
|
# start small, but slowly move everything over.
|
||||||
|
|
||||||
|
autoload :CLI, 'vagrant/cli'
|
||||||
|
|
||||||
|
module Command
|
||||||
|
autoload :Base, 'vagrant/command/base'
|
||||||
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
attr_writer :ui
|
attr_writer :ui
|
||||||
|
|
||||||
|
@ -31,7 +40,7 @@ end
|
||||||
# Load them up. One day we'll convert this to autoloads. Today
|
# Load them up. One day we'll convert this to autoloads. Today
|
||||||
# is not that day. Low hanging fruit for anyone wishing to do it.
|
# is not that day. Low hanging fruit for anyone wishing to do it.
|
||||||
libdir = File.expand_path("lib/vagrant", Vagrant.source_root)
|
libdir = File.expand_path("lib/vagrant", Vagrant.source_root)
|
||||||
Vagrant::GlobLoader.glob_require(libdir, %w{util util/stacked_proc_runner cli
|
Vagrant::GlobLoader.glob_require(libdir, %w{util util/stacked_proc_runner
|
||||||
downloaders/base config provisioners/base provisioners/chef systems/base
|
downloaders/base config provisioners/base provisioners/chef systems/base
|
||||||
action/exception_catcher hosts/base})
|
action/exception_catcher hosts/base})
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
require 'thor'
|
require 'thor'
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
|
# Entrypoint for the Vagrant CLI. This class should never be
|
||||||
|
# initialized directly (like a typical Thor class). Instead,
|
||||||
|
# use {Environment#cli} to invoke the CLI.
|
||||||
class CLI < Thor
|
class CLI < Thor
|
||||||
attr_reader :env
|
# Registers the given class with the CLI so it can be accessed.
|
||||||
|
# The class must be a subclass of either {Command} or {GroupCommand}.
|
||||||
def initialize(args=[], options={}, config={})
|
def self.register(klass, name, usage, description)
|
||||||
super
|
if klass <= Thor # TODO: make Command::GroupBase
|
||||||
|
# A subclass of Thor is a subcommand, since it contains
|
||||||
# Set the UI to a shell based UI using the shell object which
|
# many smaller commands within it.
|
||||||
# Thor sets up.
|
desc usage, description
|
||||||
Vagrant.ui = UI::Shell.new(shell) if !Vagrant.ui.is_a?(UI::Shell)
|
subcommand name, klass
|
||||||
|
elsif klass <= Command::Base
|
||||||
# The last argument must _always_ be a Vagrant Environment class.
|
# A subclass of Thor::Group is a single command, since it
|
||||||
raise CLIMissingEnvironment.new("This command requires that a Vagrant environment be properly passed in as the last parameter.") if !config[:env]
|
# is invoked as a whole.
|
||||||
@env = config[:env]
|
desc usage, description
|
||||||
|
define_method(name) { |*args| invoke klass, args }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
require 'thor/group'
|
||||||
|
require 'thor/actions'
|
||||||
|
|
||||||
|
module Vagrant
|
||||||
|
module Command
|
||||||
|
# A CLI command is the subclass for all commands which are single
|
||||||
|
# commands, e.g. `vagrant init`, `vagrant up`. Not commands like
|
||||||
|
# `vagrant box add`. For commands which have more subcommands, use
|
||||||
|
# a {GroupBase}.
|
||||||
|
#
|
||||||
|
# A {Base} is a subclass of `Thor::Group`, so view the documentation
|
||||||
|
# there on how to add arguments, descriptions etc. The important note
|
||||||
|
# about this is that when invoked, _all public methods_ will be called
|
||||||
|
# in the order they are defined. If you don't want a method called when
|
||||||
|
# the command is invoked, it must be made `protected` or `private`.
|
||||||
|
#
|
||||||
|
# The best way to get examples of how to create your own command is to
|
||||||
|
# view the various Vagrant commands, which are relatively simple.
|
||||||
|
class Base < Thor::Group
|
||||||
|
include Thor::Actions
|
||||||
|
|
||||||
|
# Register the command with the main Vagrant CLI under the
|
||||||
|
# given name. The name will be used for accessing it from the CLI,
|
||||||
|
# so if you name it "lamp", then the command to invoke this
|
||||||
|
# will be `vagrant lamp`.
|
||||||
|
#
|
||||||
|
# The description added to the class via the `desc` method will be
|
||||||
|
# used as a description for the command.
|
||||||
|
def self.register(usage)
|
||||||
|
# Extracts the name out of the usage string. So `init [foo] [bar]`
|
||||||
|
# becomes "init"
|
||||||
|
_, name = /^([a-zA-Z0-9]+)(\s+(.+?))?$/.match(usage).to_a
|
||||||
|
CLI.register(self, name, usage, desc)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(args=[], options={}, config={})
|
||||||
|
super
|
||||||
|
|
||||||
|
# Set the UI to a shell based UI using the shell object which
|
||||||
|
# Thor sets up.
|
||||||
|
Vagrant.ui = UI::Shell.new(shell) if !Vagrant.ui.is_a?(UI::Shell)
|
||||||
|
|
||||||
|
# The last argument must _always_ be a Vagrant Environment class.
|
||||||
|
raise CLIMissingEnvironment.new("This command requires that a Vagrant environment be properly passed in as the last parameter.") if !config[:env]
|
||||||
|
@env = config[:env]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
module Vagrant
|
||||||
|
module Command
|
||||||
|
class InitCommand < Base
|
||||||
|
desc "Initializes the current folder for Vagrant usage"
|
||||||
|
argument :box_name, :type => :string, :optional => true, :default => "base"
|
||||||
|
argument :box_url, :type => :string, :optional => true
|
||||||
|
source_root File.expand_path("templates/commands/init", Vagrant.source_root)
|
||||||
|
register "init [box_name] [box_url]"
|
||||||
|
|
||||||
|
def execute
|
||||||
|
template "Vagrantfile.erb", "Vagrantfile"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
Vagrant::Config.run do |config|
|
||||||
|
# All Vagrant configuration is done here. For a detailed explanation
|
||||||
|
# and listing of configuration options, please view the documentation
|
||||||
|
# online.
|
||||||
|
|
||||||
|
# Every Vagrant virtual environment requires a box to build off of.
|
||||||
|
config.vm.box = "<%= box_name %>"
|
||||||
|
<% if !box_url.nil? %>
|
||||||
|
|
||||||
|
# The url from where the 'config.vm.box' box will be fetched if it
|
||||||
|
# doesn't already exist on the user's system
|
||||||
|
config.vm.box_url = "<%= box_url %>"<% end %>
|
||||||
|
end
|
|
@ -3,40 +3,14 @@ require "test_helper"
|
||||||
class CLITest < Test::Unit::TestCase
|
class CLITest < Test::Unit::TestCase
|
||||||
setup do
|
setup do
|
||||||
@klass = Vagrant::CLI
|
@klass = Vagrant::CLI
|
||||||
@env = mock_environment
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context "setting up a UI" do
|
context "registering" do
|
||||||
setup do
|
should "register a base command as a single invokable" do
|
||||||
Vagrant.ui = nil
|
base = Class.new(Vagrant::Command::Base)
|
||||||
end
|
name = "__test_registering_single_subcommand"
|
||||||
|
@klass.register(base, name, name, "A description")
|
||||||
should "setup a shell UI" do
|
assert @klass.tasks[name]
|
||||||
silence_stream(STDOUT) { @klass.start([], :env => @env) }
|
|
||||||
assert Vagrant.ui.is_a?(Vagrant::UI::Shell)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "setup a shell UI only once" do
|
|
||||||
silence_stream(STDOUT) { @klass.start([], :env => @env) }
|
|
||||||
ui = Vagrant.ui
|
|
||||||
silence_stream(STDOUT) { @klass.start([], :env => @env) }
|
|
||||||
assert Vagrant.ui.equal?(ui)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "requiring an environment" do
|
|
||||||
should "raise an exception if the environment is not sent in" do
|
|
||||||
assert_raises(Vagrant::CLIMissingEnvironment) {
|
|
||||||
@klass.start([])
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
should "not raise an exception if the environment is properly sent in" do
|
|
||||||
silence_stream(STDOUT) do
|
|
||||||
assert_nothing_raised {
|
|
||||||
@klass.start([], :env => @env)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class CommandBaseTest < Test::Unit::TestCase
|
||||||
|
setup do
|
||||||
|
@klass = Vagrant::Command::Base
|
||||||
|
@env = mock_environment
|
||||||
|
end
|
||||||
|
|
||||||
|
context "setting up a UI" do
|
||||||
|
setup do
|
||||||
|
Vagrant.ui = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
should "setup a shell UI" do
|
||||||
|
silence_stream(STDOUT) { @klass.start([], :env => @env) }
|
||||||
|
assert Vagrant.ui.is_a?(Vagrant::UI::Shell)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "setup a shell UI only once" do
|
||||||
|
silence_stream(STDOUT) { @klass.start([], :env => @env) }
|
||||||
|
ui = Vagrant.ui
|
||||||
|
silence_stream(STDOUT) { @klass.start([], :env => @env) }
|
||||||
|
assert Vagrant.ui.equal?(ui)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "requiring an environment" do
|
||||||
|
should "raise an exception if the environment is not sent in" do
|
||||||
|
assert_raises(Vagrant::CLIMissingEnvironment) {
|
||||||
|
@klass.start([])
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
should "not raise an exception if the environment is properly sent in" do
|
||||||
|
silence_stream(STDOUT) do
|
||||||
|
assert_nothing_raised {
|
||||||
|
@klass.start([], :env => @env)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue