From 35e9fa53d404dd0808309c8e82d882fcfe27bb83 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Mar 2010 09:15:20 -0700 Subject: [PATCH] Vagrant::Commands moved to instance methods on the environment rather than class methods --- bin/vagrant-box | 2 +- bin/vagrant-down | 2 +- bin/vagrant-halt | 2 +- bin/vagrant-package | 2 +- bin/vagrant-reload | 2 +- bin/vagrant-resume | 2 +- bin/vagrant-ssh | 2 +- bin/vagrant-status | 2 +- bin/vagrant-suspend | 2 +- bin/vagrant-up | 2 +- lib/vagrant/commands.rb | 375 ++++++++++---------- lib/vagrant/environment.rb | 9 + test/vagrant/commands_test.rb | 574 +++++++++++++++---------------- test/vagrant/environment_test.rb | 14 + 14 files changed, 500 insertions(+), 492 deletions(-) diff --git a/bin/vagrant-box b/bin/vagrant-box index 8833c1fe3..262478032 100755 --- a/bin/vagrant-box +++ b/bin/vagrant-box @@ -26,7 +26,7 @@ EOS run do |command| begin - Vagrant::Commands.box(command.argv) + Vagrant::Commands.execute(:box, command.argv) rescue ArgumentError educate end diff --git a/bin/vagrant-down b/bin/vagrant-down index 20ccbc389..58f865c8a 100755 --- a/bin/vagrant-down +++ b/bin/vagrant-down @@ -22,6 +22,6 @@ Destroys the vagrant environment. EOS run do |command| - Vagrant::Commands.down + Vagrant::Commands.execute(:down) end end diff --git a/bin/vagrant-halt b/bin/vagrant-halt index 04d64e7f0..36cf5d85a 100755 --- a/bin/vagrant-halt +++ b/bin/vagrant-halt @@ -23,6 +23,6 @@ of pulling the power on your computer. EOS run do |command| - Vagrant::Commands.halt + Vagrant::Commands.execute(:halt) end end diff --git a/bin/vagrant-package b/bin/vagrant-package index de77f1b92..d1e11e9d6 100755 --- a/bin/vagrant-package +++ b/bin/vagrant-package @@ -24,6 +24,6 @@ EOS opt :include, "files to include in the package", :type => :strings run do |command| - Vagrant::Commands.package(command.argv[0], command.opts[:include]) + Vagrant::Commands.execute(:package, command.argv[0], command.opts[:include]) end end diff --git a/bin/vagrant-reload b/bin/vagrant-reload index 34280062a..b7750bcb8 100755 --- a/bin/vagrant-reload +++ b/bin/vagrant-reload @@ -24,6 +24,6 @@ the VM, and reruns the chef recipes. EOS run do |command| - Vagrant::Commands.reload + Vagrant::Commands.execute(:reload) end end diff --git a/bin/vagrant-resume b/bin/vagrant-resume index cb8979043..0244bd5c4 100755 --- a/bin/vagrant-resume +++ b/bin/vagrant-resume @@ -22,6 +22,6 @@ Resumes the vagrant environment. EOS run do |command| - Vagrant::Commands.resume + Vagrant::Commands.execute(:resume) end end diff --git a/bin/vagrant-ssh b/bin/vagrant-ssh index 5f5fed1ae..e1f580e7e 100755 --- a/bin/vagrant-ssh +++ b/bin/vagrant-ssh @@ -22,6 +22,6 @@ Opens an SSH connection into the created VM. EOS run do |command| - Vagrant::Commands.ssh + Vagrant::Commands.execute(:ssh) end end diff --git a/bin/vagrant-status b/bin/vagrant-status index 2e4f0d461..123161bc1 100755 --- a/bin/vagrant-status +++ b/bin/vagrant-status @@ -24,6 +24,6 @@ etc. EOS run do |command| - Vagrant::Commands.status + Vagrant::Commands.execute(:status) end end diff --git a/bin/vagrant-suspend b/bin/vagrant-suspend index 534012d4c..ed5eddd15 100755 --- a/bin/vagrant-suspend +++ b/bin/vagrant-suspend @@ -22,6 +22,6 @@ Suspends the vagrant environment. EOS run do |command| - Vagrant::Commands.suspend + Vagrant::Commands.execute(:suspend) end end diff --git a/bin/vagrant-up b/bin/vagrant-up index 908b621d5..ef7b81874 100755 --- a/bin/vagrant-up +++ b/bin/vagrant-up @@ -24,6 +24,6 @@ already running. EOS run do |command| - Vagrant::Commands.up + Vagrant::Commands.execute(:up) end end diff --git a/lib/vagrant/commands.rb b/lib/vagrant/commands.rb index e77bdfd2e..0c5ddf401 100644 --- a/lib/vagrant/commands.rb +++ b/lib/vagrant/commands.rb @@ -4,7 +4,191 @@ module Vagrant # documentation and also takes the commands out of some of # the other classes. class Commands - extend Vagrant::Util + include Vagrant::Util + + # The environment which these commands will act on + attr_reader :env + + # Initialize a new {Commands} instance for the given environment. + # This merely prepares the {env} variable. + def initialize(env) + @env = env + end + + # Bring up a vagrant instance. This handles everything from importing + # the base VM, setting up shared folders, forwarded ports, etc to + # provisioning the instance with chef. {up} also starts the instance, + # running it in the background. + def up + if env.vm + logger.info "VM already created. Starting VM if its not already running..." + env.vm.start + else + env.require_box + env.create_vm.execute!(Actions::VM::Up) + end + end + + # Tear down a vagrant instance. This not only shuts down the instance + # (if its running), but also deletes it from the system, including the + # hard disks associated with it. + # + # This command requires that an instance already be brought up with + # `vagrant up`. + def down + env.require_persisted_vm + env.vm.destroy + end + + # Reload the environment. This is almost equivalent to the {up} command + # except that it doesn't import the VM and do the initialize bootstrapping + # of the instance. Instead, it forces a shutdown (if its running) of the + # VM, updates the metadata (shared folders, forwarded ports), restarts + # the VM, and then reruns the provisioning if enabled. + def reload + env.require_persisted_vm + env.vm.execute!(Actions::VM::Reload) + end + + # SSH into the vagrant instance. This will setup an SSH connection into + # the vagrant instance, replacing the running ruby process with the SSH + # connection. + # + # This command requires that an instance already be brought up with + # `vagrant up`. + def ssh + env.require_persisted_vm + env.ssh.connect + end + + # Halts a running vagrant instance. This forcibly halts the instance; + # it is the equivalent of pulling the power on a machine. The instance + # can be restarted again with {up}. + # + # This command requires than an instance already be brought up with + # `vagrant up`. + def halt + env.require_persisted_vm + env.vm.execute!(Actions::VM::Halt) + end + + # Suspend a running vagrant instance. This suspends the instance, saving + # the state of the VM and "pausing" it. The instance can be resumed + # again with {resume}. + # + # This command requires that an instance already be brought up with + # `vagrant up`. + def suspend + env.require_persisted_vm + env.vm.suspend + end + + # Resume a running vagrant instance. This resumes an already suspended + # instance (from {suspend}). + # + # This command requires that an instance already be brought up with + # `vagrant up`. + def resume + env.require_persisted_vm + env.vm.resume + end + + # Export and package the current vm + # + # This command requires that an instance be powered off + def package(out_path=nil, include_files=[]) + env.require_persisted_vm + error_and_exit(:vm_power_off_to_package) unless env.vm.powered_off? + + env.vm.package(out_path, include_files) + end + + # Manages the `vagrant box` command, allowing the user to add + # and remove boxes. This single command, given an array, determines + # which action to take and calls the respective action method + # (see {box_add} and {box_remove}) + def box(argv) + sub_commands = ["list", "add", "remove"] + + if !sub_commands.include?(argv[0]) + error_and_exit(:command_box_invalid) + end + + send("box_#{argv[0]}", env, *argv[1..-1]) + end + + # Lists all added boxes + def box_list(env) + boxes = Box.all(env).sort + + wrap_output do + if !boxes.empty? + puts "Installed Vagrant Boxes:\n\n" + boxes.each do |box| + Kernel.puts box + end + else + Kernel.puts "No Vagrant Boxes Added!" + end + end + end + + # Adds a box to the local filesystem, given a URI. + def box_add(env, name, path) + Box.add(env, name, path) + end + + # Removes a box. + def box_remove(env, name) + box = Box.find(env, name) + if box.nil? + error_and_exit(:box_remove_doesnt_exist) + return # for tests + end + + box.destroy + end + + # Outputs the status of the current environment. This command outputs + # useful information such as whether or not the environment is created + # and if its running, suspended, etc. + def status + wrap_output do + if !env.vm + puts <<-msg +The environment has not yet been created. Run `vagrant up` to create the +environment. +msg + else + additional_msg = "" + if env.vm.vm.running? + additional_msg = <<-msg +To stop this VM, you can run `vagrant halt` to shut it down forcefully, +or you can run `vagrant suspend` to simply suspend the virtual machine. +In either case, to restart it again, simply run a `vagrant up`. +msg + elsif env.vm.vm.saved? + additional_msg = <<-msg +To resume this VM, simply run `vagrant up`. +msg + elsif env.vm.vm.powered_off? + additional_msg = <<-msg +To restart this VM, simply run `vagrant up`. +msg + end + + if !additional_msg.empty? + additional_msg.chomp! + additional_msg = "\n\n#{additional_msg}" + end + + puts <<-msg +The environment has been created. The status of the current environment's +virtual machine is: "#{env.vm.vm.state}."#{additional_msg} +msg + end + end + end class << self # Initializes a directory for use with vagrant. This command copies an @@ -24,192 +208,11 @@ module Vagrant end end - # Outputs the status of the current environment. This command outputs - # useful information such as whether or not the environment is created - # and if its running, suspended, etc. - def status + # Runs a command in the current environment by loading the environment + # of the current working directory prior to executing. + def execute(command, *args) env = Environment.load! - - wrap_output do - if !env.vm - puts <<-msg -The environment has not yet been created. Run `vagrant up` to create the -environment. -msg - else - additional_msg = "" - if env.vm.vm.running? - additional_msg = <<-msg -To stop this VM, you can run `vagrant halt` to shut it down forcefully, -or you can run `vagrant suspend` to simply suspend the virtual machine. -In either case, to restart it again, simply run a `vagrant up`. -msg - elsif env.vm.vm.saved? - additional_msg = <<-msg -To resume this VM, simply run `vagrant up`. -msg - elsif env.vm.vm.powered_off? - additional_msg = <<-msg -To restart this VM, simply run `vagrant up`. -msg - end - - if !additional_msg.empty? - additional_msg.chomp! - additional_msg = "\n\n#{additional_msg}" - end - - puts <<-msg -The environment has been created. The status of the current environment's -virtual machine is: "#{env.vm.vm.state}."#{additional_msg} -msg - end - end - end - - # Bring up a vagrant instance. This handles everything from importing - # the base VM, setting up shared folders, forwarded ports, etc to - # provisioning the instance with chef. {up} also starts the instance, - # running it in the background. - def up - env = Environment.load! - - if env.vm - logger.info "VM already created. Starting VM if its not already running..." - env.vm.start - else - env.require_box - env.create_vm.execute!(Actions::VM::Up) - end - end - - # Tear down a vagrant instance. This not only shuts down the instance - # (if its running), but also deletes it from the system, including the - # hard disks associated with it. - # - # This command requires that an instance already be brought up with - # `vagrant up`. - def down - env = Environment.load! - env.require_persisted_vm - env.vm.destroy - end - - # Reload the environment. This is almost equivalent to the {up} command - # except that it doesn't import the VM and do the initialize bootstrapping - # of the instance. Instead, it forces a shutdown (if its running) of the - # VM, updates the metadata (shared folders, forwarded ports), restarts - # the VM, and then reruns the provisioning if enabled. - def reload - env = Environment.load! - env.require_persisted_vm - env.vm.execute!(Actions::VM::Reload) - end - - # SSH into the vagrant instance. This will setup an SSH connection into - # the vagrant instance, replacing the running ruby process with the SSH - # connection. - # - # This command requires that an instance already be brought up with - # `vagrant up`. - def ssh - env = Environment.load! - env.require_persisted_vm - env.ssh.connect - end - - # Halts a running vagrant instance. This forcibly halts the instance; - # it is the equivalent of pulling the power on a machine. The instance - # can be restarted again with {up}. - # - # This command requires than an instance already be brought up with - # `vagrant up`. - def halt - env = Environment.load! - env.require_persisted_vm - env.vm.execute!(Actions::VM::Halt) - end - - # Suspend a running vagrant instance. This suspends the instance, saving - # the state of the VM and "pausing" it. The instance can be resumed - # again with {resume}. - # - # This command requires that an instance already be brought up with - # `vagrant up`. - def suspend - env = Environment.load! - env.require_persisted_vm - env.vm.suspend - end - - # Resume a running vagrant instance. This resumes an already suspended - # instance (from {suspend}). - # - # This command requires that an instance already be brought up with - # `vagrant up`. - def resume - env = Environment.load! - env.require_persisted_vm - env.vm.resume - end - - # Export and package the current vm - # - # This command requires that an instance be powered off - def package(out_path=nil, include_files=[]) - env = Environment.load! - env.require_persisted_vm - error_and_exit(:vm_power_off_to_package) unless env.vm.powered_off? - - env.vm.package(out_path, include_files) - end - - # Manages the `vagrant box` command, allowing the user to add - # and remove boxes. This single command, given an array, determines - # which action to take and calls the respective action method - # (see {box_add} and {box_remove}) - def box(argv) - env = Environment.load! - - sub_commands = ["list", "add", "remove"] - - if !sub_commands.include?(argv[0]) - error_and_exit(:command_box_invalid) - end - - send("box_#{argv[0]}", env, *argv[1..-1]) - end - - # Lists all added boxes - def box_list(env) - boxes = Box.all(env).sort - - wrap_output do - if !boxes.empty? - puts "Installed Vagrant Boxes:\n\n" - boxes.each do |box| - puts box - end - else - puts "No Vagrant Boxes Added!" - end - end - end - - # Adds a box to the local filesystem, given a URI. - def box_add(env, name, path) - Box.add(env, name, path) - end - - # Removes a box. - def box_remove(env, name) - box = Box.find(env, name) - if box.nil? - error_and_exit(:box_remove_doesnt_exist) - return # for tests - end - - box.destroy + env.commands.send(command, *args) end end end diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 7eebdc2b7..ecc0bb924 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -15,6 +15,7 @@ module Vagrant attr_reader :vm attr_reader :ssh attr_reader :active_list + attr_reader :commands #--------------------------------------------------------------- # Class Methods @@ -98,6 +99,7 @@ module Vagrant load_vm! load_ssh! load_active_list! + load_commands! self end @@ -191,6 +193,13 @@ module Vagrant @active_list = ActiveList.new(self) end + # Loads the instance of {Commands} for this environment. This allows + # users of the instance to run commands such as "up" "down" etc. in + # the context of this environment. + def load_commands! + @commands = Commands.new(self) + end + #--------------------------------------------------------------- # Methods to manage VM #--------------------------------------------------------------- diff --git a/test/vagrant/commands_test.rb b/test/vagrant/commands_test.rb index 40415951d..431effbd5 100644 --- a/test/vagrant/commands_test.rb +++ b/test/vagrant/commands_test.rb @@ -11,315 +11,297 @@ class CommandsTest < Test::Unit::TestCase Vagrant::Environment.stubs(:load!).returns(@env) end - context "init" do + context "instance methods" do setup do - @file = mock("file") - @file.stubs(:write) - File.stubs(:open).yields(@file) - @rootfile_path = File.join(Dir.pwd, Vagrant::Environment::ROOTFILE_NAME) - - Vagrant::Util::TemplateRenderer.stubs(:render) + @commands = Vagrant::Commands.new(@env) end - should "error and exit if a rootfile already exists" do - File.expects(:exist?).with(@rootfile_path).returns(true) - Vagrant::Commands.expects(:error_and_exit).with(:rootfile_already_exists).once - Vagrant::Commands.init - end - - should "write to the rootfile path using the template renderer" do - result = "foo" - Vagrant::Util::TemplateRenderer.expects(:render).returns(result).once - @file.expects(:write).with(result).once - File.expects(:open).with(@rootfile_path, 'w+').yields(@file) - - Vagrant::Commands.init - end - - should "use the given base box if given" do - box = "zooo" - Vagrant::Util::TemplateRenderer.expects(:render).with(Vagrant::Environment::ROOTFILE_NAME, :default_box => box) - Vagrant::Commands.init(box) - end - - should "use the default `base` if no box is given" do - Vagrant::Util::TemplateRenderer.expects(:render).with(Vagrant::Environment::ROOTFILE_NAME, :default_box => "base") - Vagrant::Commands.init - end - end - - context "up" do - setup do - @new_vm = mock("vm") - @new_vm.stubs(:execute!) - - @env.stubs(:vm).returns(nil) - @env.stubs(:require_box) - @env.stubs(:create_vm).returns(@new_vm) - end - - should "require load the environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.up - end - - should "require a box" do - @env.expects(:require_box).once - Vagrant::Commands.up - end - - should "call the up action on VM if it doesn't exist" do - @new_vm.expects(:execute!).with(Vagrant::Actions::VM::Up).once - Vagrant::Commands.up - end - - should "call start on the persisted vm if it exists" do - @env.stubs(:vm).returns(@persisted_vm) - @persisted_vm.expects(:start).once - @env.expects(:create_vm).never - Vagrant::Commands.up - end - end - - context "down" do - setup do - @persisted_vm.stubs(:destroy) - end - - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.down - end - - should "require a persisted VM" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.down - end - - should "destroy the persisted VM and the VM image" do - @persisted_vm.expects(:destroy).once - Vagrant::Commands.down - end - end - - context "reload" do - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.reload - end - - should "require a persisted VM" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.reload - end - - should "call the `reload` action on the VM" do - @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Reload).once - Vagrant::Commands.reload - end - end - - context "ssh" do - setup do - @env.ssh.stubs(:connect) - end - - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.ssh - end - - should "require a persisted VM" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.ssh - end - - should "connect to SSH" do - @env.ssh.expects(:connect).once - Vagrant::Commands.ssh - end - end - - context "halt" do - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.halt - end - - should "require a persisted VM" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.halt - end - - should "call the `halt` action on the VM" do - @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt).once - Vagrant::Commands.halt - end - end - - context "suspend" do - setup do - @persisted_vm.stubs(:suspend) - @persisted_vm.stubs(:saved?).returns(false) - end - - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.suspend - end - - should "require a persisted VM" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.suspend - end - - should "suspend the VM" do - @persisted_vm.expects(:suspend).once - Vagrant::Commands.suspend - end - end - - context "resume" do - setup do - @persisted_vm.stubs(:resume) - @persisted_vm.stubs(:saved?).returns(true) - end - - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.resume - end - - should "require a persisted VM" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.resume - end - - should "save the state of the VM" do - @persisted_vm.expects(:resume).once - Vagrant::Commands.resume - end - end - - context "package" do - setup do - @persisted_vm.stubs(:package) - @persisted_vm.stubs(:powered_off?).returns(true) - end - - should "load the current environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.package - end - - should "require a persisted vm" do - @env.expects(:require_persisted_vm).once - Vagrant::Commands.package - end - - should "error and exit if the VM is not powered off" do - @persisted_vm.stubs(:powered_off?).returns(false) - Vagrant::Commands.expects(:error_and_exit).with(:vm_power_off_to_package).once - @persisted_vm.expects(:package).never - Vagrant::Commands.package - end - - should "call package on the persisted VM" do - @persisted_vm.expects(:package).once - Vagrant::Commands.package - end - - should "pass the out path and include_files to the package method" do - out_path = mock("out_path") - include_files = mock("include_files") - @persisted_vm.expects(:package).with(out_path, include_files).once - Vagrant::Commands.package(out_path, include_files) - end - - should "default to an empty array when not include_files are specified" do - out_path = mock("out_path") - @persisted_vm.expects(:package).with(out_path, []).once - Vagrant::Commands.package(out_path) - end - end - - context "box" do - setup do - Vagrant::Commands.stubs(:box_foo) - Vagrant::Commands.stubs(:box_add) - Vagrant::Commands.stubs(:box_remove) - end - - should "load the environment" do - Vagrant::Environment.expects(:load!).once.returns(@env) - Vagrant::Commands.box(["add"]) - end - - should "error and exit if the first argument is not a valid subcommand" do - Vagrant::Commands.expects(:error_and_exit).with(:command_box_invalid).once - Vagrant::Commands.box(["foo"]) - end - - should "not error and exit if the first argument is a valid subcommand" do - commands = ["add", "remove"] - - commands.each do |command| - Vagrant::Commands.expects(:error_and_exit).never - Vagrant::Commands.expects("box_#{command}".to_sym).once - Vagrant::Commands.box([command]) + context "initialization" do + should "set up the environment variable" do + env = mock("env") + command = Vagrant::Commands.new(env) + assert_equal env, command.env end end - should "forward any additional arguments" do - Vagrant::Commands.expects(:box_add).with(@env, 1,2,3).once - Vagrant::Commands.box(["add",1,2,3]) + context "up" do + setup do + @new_vm = mock("vm") + @new_vm.stubs(:execute!) + + @env.stubs(:vm).returns(nil) + @env.stubs(:require_box) + @env.stubs(:create_vm).returns(@new_vm) + end + + should "require a box" do + @env.expects(:require_box).once + @commands.up + end + + should "call the up action on VM if it doesn't exist" do + @new_vm.expects(:execute!).with(Vagrant::Actions::VM::Up).once + @commands.up + end + + should "call start on the persisted vm if it exists" do + @env.stubs(:vm).returns(@persisted_vm) + @persisted_vm.expects(:start).once + @env.expects(:create_vm).never + @commands.up + end + end + + context "down" do + setup do + @persisted_vm.stubs(:destroy) + end + + should "require a persisted VM" do + @env.expects(:require_persisted_vm).once + @commands.down + end + + should "destroy the persisted VM and the VM image" do + @persisted_vm.expects(:destroy).once + @commands.down + end + end + + context "reload" do + should "require a persisted VM" do + @env.expects(:require_persisted_vm).once + @commands.reload + end + + should "call the `reload` action on the VM" do + @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Reload).once + @commands.reload + end + end + + context "ssh" do + setup do + @env.ssh.stubs(:connect) + end + + should "require a persisted VM" do + @env.expects(:require_persisted_vm).once + @commands.ssh + end + + should "connect to SSH" do + @env.ssh.expects(:connect).once + @commands.ssh + end + end + + context "halt" do + should "require a persisted VM" do + @env.expects(:require_persisted_vm).once + @commands.halt + end + + should "call the `halt` action on the VM" do + @persisted_vm.expects(:execute!).with(Vagrant::Actions::VM::Halt).once + @commands.halt + end + end + + context "suspend" do + setup do + @persisted_vm.stubs(:suspend) + @persisted_vm.stubs(:saved?).returns(false) + end + + should "require a persisted VM" do + @env.expects(:require_persisted_vm).once + @commands.suspend + end + + should "suspend the VM" do + @persisted_vm.expects(:suspend).once + @commands.suspend + end + end + + context "resume" do + setup do + @persisted_vm.stubs(:resume) + @persisted_vm.stubs(:saved?).returns(true) + end + + should "require a persisted VM" do + @env.expects(:require_persisted_vm).once + @commands.resume + end + + should "save the state of the VM" do + @persisted_vm.expects(:resume).once + @commands.resume + end + end + + context "package" do + setup do + @persisted_vm.stubs(:package) + @persisted_vm.stubs(:powered_off?).returns(true) + end + + should "require a persisted vm" do + @env.expects(:require_persisted_vm).once + @commands.package + end + + should "error and exit if the VM is not powered off" do + @persisted_vm.stubs(:powered_off?).returns(false) + @commands.expects(:error_and_exit).with(:vm_power_off_to_package).once + @persisted_vm.expects(:package).never + @commands.package + end + + should "call package on the persisted VM" do + @persisted_vm.expects(:package).once + @commands.package + end + + should "pass the out path and include_files to the package method" do + out_path = mock("out_path") + include_files = mock("include_files") + @persisted_vm.expects(:package).with(out_path, include_files).once + @commands.package(out_path, include_files) + end + + should "default to an empty array when not include_files are specified" do + out_path = mock("out_path") + @persisted_vm.expects(:package).with(out_path, []).once + @commands.package(out_path) + end + end + + context "box" do + setup do + @commands.stubs(:box_foo) + @commands.stubs(:box_add) + @commands.stubs(:box_remove) + end + + should "error and exit if the first argument is not a valid subcommand" do + @commands.expects(:error_and_exit).with(:command_box_invalid).once + @commands.box(["foo"]) + end + + should "not error and exit if the first argument is a valid subcommand" do + commands = ["add", "remove", "list"] + + commands.each do |command| + @commands.expects(:error_and_exit).never + @commands.expects("box_#{command}".to_sym).once + @commands.box([command]) + end + end + + should "forward any additional arguments" do + @commands.expects(:box_add).with(@env, 1,2,3).once + @commands.box(["add",1,2,3]) + end + end + + context "box list" do + setup do + @boxes = ["foo", "bar"] + + Vagrant::Box.stubs(:all).returns(@boxes) + @commands.stubs(:wrap_output) + end + + should "call all on box and sort the results" do + @all = mock("all") + @all.expects(:sort).returns(@boxes) + Vagrant::Box.expects(:all).with(@env).returns(@all) + @commands.box_list(@env) + end + end + + context "box add" do + setup do + @name = "foo" + @path = "bar" + end + + should "execute the add action with the name and path" do + Vagrant::Box.expects(:add).with(@env, @name, @path).once + @commands.box_add(@env, @name, @path) + end + end + + context "box remove" do + setup do + @name = "foo" + end + + should "error and exit if the box doesn't exist" do + Vagrant::Box.expects(:find).returns(nil) + @commands.expects(:error_and_exit).with(:box_remove_doesnt_exist).once + @commands.box_remove(@env, @name) + end + + should "call destroy on the box if it exists" do + @box = mock("box") + Vagrant::Box.expects(:find).with(@env, @name).returns(@box) + @box.expects(:destroy).once + @commands.box_remove(@env, @name) + end end end - context "box list" do - setup do - @boxes = ["foo", "bar"] + context "class methods" do + context "init" do + setup do + @file = mock("file") + @file.stubs(:write) + File.stubs(:open).yields(@file) + @rootfile_path = File.join(Dir.pwd, Vagrant::Environment::ROOTFILE_NAME) - Vagrant::Box.stubs(:all).returns(@boxes) - Vagrant::Commands.stubs(:puts) + Vagrant::Util::TemplateRenderer.stubs(:render) + end + + should "error and exit if a rootfile already exists" do + File.expects(:exist?).with(@rootfile_path).returns(true) + Vagrant::Commands.expects(:error_and_exit).with(:rootfile_already_exists).once + Vagrant::Commands.init + end + + should "write to the rootfile path using the template renderer" do + result = "foo" + Vagrant::Util::TemplateRenderer.expects(:render).returns(result).once + @file.expects(:write).with(result).once + File.expects(:open).with(@rootfile_path, 'w+').yields(@file) + + Vagrant::Commands.init + end + + should "use the given base box if given" do + box = "zooo" + Vagrant::Util::TemplateRenderer.expects(:render).with(Vagrant::Environment::ROOTFILE_NAME, :default_box => box) + Vagrant::Commands.init(box) + end + + should "use the default `base` if no box is given" do + Vagrant::Util::TemplateRenderer.expects(:render).with(Vagrant::Environment::ROOTFILE_NAME, :default_box => "base") + Vagrant::Commands.init + end end - should "call all on box and sort the results" do - @all = mock("all") - @all.expects(:sort).returns(@boxes) - Vagrant::Box.expects(:all).with(@env).returns(@all) - Vagrant::Commands.box_list(@env) - end - end + context "executing commands in the current environment" do + should "load the environment then send the command to the commands instance" do + method = :foo + args = [1,2,3] - context "box add" do - setup do - @name = "foo" - @path = "bar" - end - - should "execute the add action with the name and path" do - Vagrant::Box.expects(:add).with(@env, @name, @path).once - Vagrant::Commands.box_add(@env, @name, @path) - end - end - - context "box remove" do - setup do - @name = "foo" - end - - should "error and exit if the box doesn't exist" do - Vagrant::Box.expects(:find).returns(nil) - Vagrant::Commands.expects(:error_and_exit).with(:box_remove_doesnt_exist).once - Vagrant::Commands.box_remove(@env, @name) - end - - should "call destroy on the box if it exists" do - @box = mock("box") - Vagrant::Box.expects(:find).with(@env, @name).returns(@box) - @box.expects(:destroy).once - Vagrant::Commands.box_remove(@env, @name) + Vagrant::Environment.expects(:load!).returns(@env) + @env.commands.expects(:send).with(method, *args).once + Vagrant::Commands.execute(method, *args) + end end end end diff --git a/test/vagrant/environment_test.rb b/test/vagrant/environment_test.rb index c0dbd5a12..16f0afb97 100644 --- a/test/vagrant/environment_test.rb +++ b/test/vagrant/environment_test.rb @@ -146,6 +146,7 @@ class EnvironmentTest < Test::Unit::TestCase @env.expects(:load_vm!).once.in_sequence(call_seq) @env.expects(:load_ssh!).once.in_sequence(call_seq) @env.expects(:load_active_list!).once.in_sequence(call_seq) + @env.expects(:load_commands!).once.in_sequence(call_seq) assert_equal @env, @env.load! end end @@ -424,6 +425,19 @@ class EnvironmentTest < Test::Unit::TestCase assert_equal active_list, @env.active_list end end + + context "loading the commands" do + setup do + @env = mock_environment + end + + should "initialize the Commands object with the given environment" do + commands = mock("commands") + Vagrant::Commands.expects(:new).with(@env).returns(commands) + @env.load_commands! + assert_equal commands, @env.commands + end + end end context "requiring properties" do