vagrant 0.1.4 → 0.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/Gemfile +1 -1
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/bin/vagrant-box +1 -2
  5. data/bin/vagrant-down +1 -2
  6. data/bin/vagrant-halt +1 -2
  7. data/bin/vagrant-init +1 -2
  8. data/bin/vagrant-package +1 -2
  9. data/bin/vagrant-reload +1 -2
  10. data/bin/vagrant-resume +1 -2
  11. data/bin/vagrant-ssh +1 -2
  12. data/bin/vagrant-status +29 -0
  13. data/bin/vagrant-suspend +1 -2
  14. data/bin/vagrant-up +1 -2
  15. data/config/default.rb +5 -9
  16. data/keys/README.md +10 -0
  17. data/keys/vagrant +27 -0
  18. data/keys/vagrant.pub +1 -0
  19. data/lib/vagrant/actions/base.rb +14 -0
  20. data/lib/vagrant/actions/collection.rb +36 -0
  21. data/lib/vagrant/actions/runner.rb +4 -10
  22. data/lib/vagrant/actions/vm/boot.rb +4 -5
  23. data/lib/vagrant/actions/vm/customize.rb +17 -0
  24. data/lib/vagrant/actions/vm/destroy.rb +11 -2
  25. data/lib/vagrant/actions/vm/forward_ports.rb +24 -0
  26. data/lib/vagrant/actions/vm/import.rb +1 -0
  27. data/lib/vagrant/actions/vm/provision.rb +30 -52
  28. data/lib/vagrant/actions/vm/reload.rb +2 -2
  29. data/lib/vagrant/actions/vm/shared_folders.rb +37 -25
  30. data/lib/vagrant/actions/vm/up.rb +8 -4
  31. data/lib/vagrant/active_list.rb +66 -0
  32. data/lib/vagrant/commands.rb +44 -0
  33. data/lib/vagrant/config.rb +64 -47
  34. data/lib/vagrant/downloaders/file.rb +2 -12
  35. data/lib/vagrant/env.rb +48 -12
  36. data/lib/vagrant/provisioners/base.rb +22 -0
  37. data/lib/vagrant/provisioners/chef.rb +102 -0
  38. data/lib/vagrant/provisioners/chef_server.rb +96 -0
  39. data/lib/vagrant/provisioners/chef_solo.rb +67 -0
  40. data/lib/vagrant/ssh.rb +25 -6
  41. data/lib/vagrant/stacked_proc_runner.rb +33 -0
  42. data/lib/vagrant/vm.rb +8 -0
  43. data/lib/vagrant.rb +10 -5
  44. data/test/test_helper.rb +22 -6
  45. data/test/vagrant/actions/collection_test.rb +110 -0
  46. data/test/vagrant/actions/runner_test.rb +11 -7
  47. data/test/vagrant/actions/vm/boot_test.rb +7 -7
  48. data/test/vagrant/actions/vm/customize_test.rb +16 -0
  49. data/test/vagrant/actions/vm/destroy_test.rb +19 -6
  50. data/test/vagrant/actions/vm/forward_ports_test.rb +52 -0
  51. data/test/vagrant/actions/vm/import_test.rb +10 -3
  52. data/test/vagrant/actions/vm/provision_test.rb +75 -70
  53. data/test/vagrant/actions/vm/reload_test.rb +3 -2
  54. data/test/vagrant/actions/vm/shared_folders_test.rb +62 -9
  55. data/test/vagrant/actions/vm/up_test.rb +4 -4
  56. data/test/vagrant/active_list_test.rb +169 -0
  57. data/test/vagrant/config_test.rb +145 -29
  58. data/test/vagrant/downloaders/file_test.rb +4 -19
  59. data/test/vagrant/env_test.rb +96 -23
  60. data/test/vagrant/provisioners/base_test.rb +27 -0
  61. data/test/vagrant/provisioners/chef_server_test.rb +175 -0
  62. data/test/vagrant/provisioners/chef_solo_test.rb +142 -0
  63. data/test/vagrant/provisioners/chef_test.rb +116 -0
  64. data/test/vagrant/ssh_test.rb +29 -8
  65. data/test/vagrant/stacked_proc_runner_test.rb +43 -0
  66. data/test/vagrant/vm_test.rb +23 -0
  67. data/vagrant.gemspec +35 -8
  68. metadata +42 -11
  69. data/script/vagrant-ssh-expect.sh +0 -22
@@ -0,0 +1,67 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # This class implements provisioning via chef-solo.
4
+ class ChefSolo < Chef
5
+ def prepare
6
+ share_cookbook_folders
7
+ end
8
+
9
+ def provision!
10
+ chown_provisioning_folder
11
+ setup_json
12
+ setup_solo_config
13
+ run_chef_solo
14
+ end
15
+
16
+ def share_cookbook_folders
17
+ host_cookbook_paths.each_with_index do |cookbook, i|
18
+ Vagrant.config.vm.share_folder("vagrant-chef-solo-#{i}", cookbook_path(i), cookbook)
19
+ end
20
+ end
21
+
22
+ def setup_solo_config
23
+ solo_file = <<-solo
24
+ file_cache_path "#{Vagrant.config.chef.provisioning_path}"
25
+ cookbook_path #{cookbooks_path}
26
+ solo
27
+
28
+ logger.info "Uploading chef-solo configuration script..."
29
+ SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef.provisioning_path, "solo.rb"))
30
+ end
31
+
32
+ def run_chef_solo
33
+ logger.info "Running chef-solo..."
34
+ SSH.execute do |ssh|
35
+ ssh.exec!("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
36
+ # TODO: Very verbose. It would be easier to save the data and only show it during
37
+ # an error, or when verbosity level is set high
38
+ logger.info("#{stream}: #{data}")
39
+ end
40
+ end
41
+ end
42
+
43
+ def host_cookbook_paths
44
+ cookbooks = Vagrant.config.chef.cookbooks_path
45
+ cookbooks = [cookbooks] unless cookbooks.is_a?(Array)
46
+ cookbooks.collect! { |cookbook| File.expand_path(cookbook, Env.root_path) }
47
+ return cookbooks
48
+ end
49
+
50
+ def cookbook_path(i)
51
+ File.join(Vagrant.config.chef.provisioning_path, "cookbooks-#{i}")
52
+ end
53
+
54
+ def cookbooks_path
55
+ result = []
56
+ host_cookbook_paths.each_with_index do |host_path, i|
57
+ result << cookbook_path(i)
58
+ end
59
+
60
+ # We're lucky that ruby's string and array syntax for strings is the
61
+ # same as JSON, so we can just convert to JSON here and use that
62
+ result = result.to_s if result.length == 1
63
+ result.to_json
64
+ end
65
+ end
66
+ end
67
+ end
data/lib/vagrant/ssh.rb CHANGED
@@ -1,19 +1,22 @@
1
1
  module Vagrant
2
2
  class SSH
3
- SCRIPT = File.join(File.dirname(__FILE__), '..', '..', 'script', 'vagrant-ssh-expect.sh')
3
+ include Vagrant::Util
4
4
 
5
5
  class << self
6
6
  def connect(opts={})
7
7
  options = {}
8
- [:host, :password, :username].each do |param|
8
+ [:host, :username, :private_key_path].each do |param|
9
9
  options[param] = opts[param] || Vagrant.config.ssh.send(param)
10
10
  end
11
11
 
12
- Kernel.exec "#{SCRIPT} #{options[:username]} #{options[:password]} #{options[:host]} #{port(opts)}".strip
12
+ Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
13
13
  end
14
14
 
15
- def execute
16
- Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config[:ssh][:username], :port => port, :password => Vagrant.config[:ssh][:password]) do |ssh|
15
+ def execute(opts={})
16
+ Net::SSH.start(Vagrant.config.ssh.host,
17
+ Vagrant.config[:ssh][:username],
18
+ opts.merge( :port => port,
19
+ :keys => [Vagrant.config.ssh.private_key_path])) do |ssh|
17
20
  yield ssh
18
21
  end
19
22
  end
@@ -29,7 +32,7 @@ module Vagrant
29
32
  check_thread = Thread.new do
30
33
  begin
31
34
  Thread.current[:result] = false
32
- Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => port, :password => Vagrant.config.ssh.password, :timeout => Vagrant.config.ssh.timeout) do |ssh|
35
+ execute(:timeout => Vagrant.config.ssh.timeout) do |ssh|
33
36
  Thread.current[:result] = true
34
37
  end
35
38
  rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
@@ -39,6 +42,22 @@ module Vagrant
39
42
 
40
43
  check_thread.join(Vagrant.config.ssh.timeout)
41
44
  return check_thread[:result]
45
+ rescue Net::SSH::AuthenticationFailed
46
+ error_and_exit(<<-msg)
47
+ SSH authentication failed! While this could be due to a variety of reasons,
48
+ the two most common are: private key path is incorrect or you're using a box
49
+ which was built for Vagrant 0.1.x.
50
+
51
+ Vagrant 0.2.x dropped support for password-based authentication. If you're
52
+ tring to `vagrant up` a box which does not support Vagrant's private/public
53
+ keypair, then this error will be raised. To resolve this, read the guide
54
+ on converting base boxes from password-based to keypairs here:
55
+
56
+ http://vagrantup.com/docs/converting_password_to_key_ssh.html
57
+
58
+ If the box was built for 0.2.x and contains a custom public key, perhaps
59
+ the path to the private key is incorrect. Check your `config.ssh.private_key_path`.
60
+ msg
42
61
  end
43
62
 
44
63
  def port(opts={})
@@ -0,0 +1,33 @@
1
+ module Vagrant
2
+ # Represents the "stacked proc runner" behavior which is used a
3
+ # couple places within Vagrant. This allows procs to "stack" on
4
+ # each other, then all execute in a single action. An example of
5
+ # its uses can be seen in the {Config} class.
6
+ module StackedProcRunner
7
+ # Returns the proc stack. This should always be called as the
8
+ # accessor of the stack. The instance variable itself should _never_
9
+ # be used.
10
+ #
11
+ # @return [Array<Proc>]
12
+ def proc_stack
13
+ @_proc_stack ||= []
14
+ end
15
+
16
+ # Adds (pushes) a proc to the stack. The actual proc added here is
17
+ # not executed, but merely stored.
18
+ #
19
+ # @param [Proc] block
20
+ def push_proc(&block)
21
+ proc_stack << block
22
+ end
23
+
24
+ # Executes all the procs on the stack, passing in the given arguments.
25
+ # The stack is not cleared afterwords. It is up to the user of this
26
+ # mixin to clear the stack by calling `proc_stack.clear`.
27
+ def run_procs!(*args)
28
+ proc_stack.each do |proc|
29
+ proc.call(*args)
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/vagrant/vm.rb CHANGED
@@ -19,6 +19,14 @@ module Vagrant
19
19
  @vm = vm
20
20
  end
21
21
 
22
+ def uuid
23
+ vm ? vm.uuid : nil
24
+ end
25
+
26
+ def reload!
27
+ @vm = VirtualBox::VM.find(@vm.uuid)
28
+ end
29
+
22
30
  def package(out_path, include_files=[])
23
31
  add_action(Actions::VM::Export)
24
32
  add_action(Actions::VM::Package, out_path, include_files)
data/lib/vagrant.rb CHANGED
@@ -1,14 +1,19 @@
1
1
  libdir = File.dirname(__FILE__)
2
- $:.unshift(libdir)
3
2
  PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
4
3
 
5
4
  # The libs which must be loaded prior to the rest
6
5
  %w{tempfile open-uri json pathname logger uri net/http virtualbox net/ssh archive/tar/minitar
7
- net/scp fileutils vagrant/util vagrant/actions/base vagrant/downloaders/base vagrant/actions/runner}.each do |f|
8
- require f
6
+ net/scp fileutils}.each do |lib|
7
+ require lib
8
+ end
9
+
10
+ # The vagrant specific files which must be loaded prior to the rest
11
+ %w{vagrant/util vagrant/stacked_proc_runner vagrant/actions/base vagrant/downloaders/base vagrant/actions/collection
12
+ vagrant/actions/runner vagrant/config vagrant/provisioners/base vagrant/provisioners/chef}.each do |f|
13
+ require File.expand_path(f, libdir)
9
14
  end
10
15
 
11
16
  # Glob require the rest
12
- Dir[File.join(PROJECT_ROOT, "lib", "vagrant", "**", "*.rb")].each do |f|
13
- require f
17
+ Dir[File.join(libdir, "vagrant", "**", "*.rb")].each do |f|
18
+ require File.expand_path(f)
14
19
  end
data/test/test_helper.rb CHANGED
@@ -20,11 +20,10 @@ require 'mocha'
20
20
  class Test::Unit::TestCase
21
21
  # Clears the previous config and sets up the new config
22
22
  def mock_config
23
- Vagrant::Config.instance_variable_set(:@config_runners, nil)
24
- Vagrant::Config.instance_variable_set(:@config, nil)
23
+ Vagrant::Config.reset!
25
24
 
26
25
  Vagrant::Config.run do |config|
27
- config.vagrant.dotfile_name = ".hobo"
26
+ config.vagrant.dotfile_name = ".vagrant"
28
27
 
29
28
  config.ssh.username = "foo"
30
29
  config.ssh.password = "bar"
@@ -32,21 +31,28 @@ class Test::Unit::TestCase
32
31
  config.ssh.forwarded_port_key = "ssh"
33
32
  config.ssh.max_tries = 10
34
33
  config.ssh.timeout = 10
34
+ config.ssh.private_key_path = '~/foo'
35
35
 
36
36
  config.vm.box = "foo"
37
37
  config.vm.box_ovf = "box.ovf"
38
38
  config.vm.base_mac = "42"
39
- config.vm.project_directory = "/hobo"
39
+ config.vm.project_directory = "/vagrant"
40
40
  config.vm.disk_image_format = 'VMDK'
41
41
  config.vm.forward_port("ssh", 22, 2222)
42
+ config.vm.shared_folder_uid = nil
43
+ config.vm.shared_folder_gid = nil
42
44
 
43
45
  config.package.name = 'vagrant'
44
46
  config.package.extension = '.box'
45
47
 
48
+ # Chef
49
+ config.chef.chef_server_url = "http://localhost:4000"
50
+ config.chef.validation_key_path = "validation.pem"
51
+ config.chef.client_key_path = "/zoo/foo/bar.pem"
46
52
  config.chef.cookbooks_path = "cookbooks"
47
- config.chef.provisioning_path = "/tmp/hobo-chef"
53
+ config.chef.provisioning_path = "/tmp/vagrant-chef"
48
54
  config.chef.json = {
49
- :recipes => ["hobo_main"]
55
+ :recipes => ["vagrant_main"]
50
56
  }
51
57
 
52
58
  config.vagrant.home = '~/.home'
@@ -72,6 +78,7 @@ class Test::Unit::TestCase
72
78
  vm = mock("vboxvm")
73
79
  mock_vm = mock("vm")
74
80
  action = action_klass.new(mock_vm, *args)
81
+ stub_default_action_dependecies(action)
75
82
 
76
83
  mock_vm.stubs(:vm).returns(vm)
77
84
  mock_vm.stubs(:vm=)
@@ -82,6 +89,11 @@ class Test::Unit::TestCase
82
89
  [mock_vm, vm, action]
83
90
  end
84
91
 
92
+ def stub_default_action_dependecies(mock, klass=MockAction)
93
+ mock.stubs(:precedes).returns([])
94
+ mock.stubs(:follows).returns([])
95
+ end
96
+
85
97
  # Sets up the mocks and stubs for a downloader
86
98
  def mock_downloader(downloader_klass)
87
99
  tempfile = mock("tempfile")
@@ -90,3 +102,7 @@ class Test::Unit::TestCase
90
102
  [downloader_klass.new, tempfile]
91
103
  end
92
104
  end
105
+
106
+ class MockAction; end
107
+ class MockActionOther; end
108
+
@@ -0,0 +1,110 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class CollectionTest < Test::Unit::TestCase
4
+ context "checking uniqueness" do
5
+ setup do
6
+ @actions = Vagrant::Actions::Collection.new([1])
7
+ end
8
+
9
+ should "return true if there are duplicate classes in the collection" do
10
+ @actions << 1
11
+ assert @actions.duplicates?
12
+ end
13
+
14
+ should "return false it all the classes are unique" do
15
+ @actions << 1.0 << "foo"
16
+ assert !@actions.duplicates?
17
+ end
18
+
19
+ should "raise an exception when there are duplicates" do
20
+ @actions << 1
21
+ assert_raise Vagrant::Actions::DuplicateActionException do
22
+ @actions.duplicates!
23
+ end
24
+ end
25
+
26
+ should "not raise an exception when there are no duplicates" do
27
+ @actions << 1.0 << "foo"
28
+ assert_nothing_raised do
29
+ @actions.duplicates!
30
+ end
31
+ end
32
+ end
33
+
34
+ context "verifying dependencies" do
35
+ setup do
36
+ @mock_action = mock('action')
37
+ @mock_action.stubs(:class).returns(MockAction)
38
+
39
+ @mock_action2 = mock('action2')
40
+ @mock_action2.stubs(:class).returns(MockActionOther)
41
+ # see test_helper
42
+ stub_default_action_dependecies(@mock_action)
43
+ stub_default_action_dependecies(@mock_action2)
44
+ end
45
+
46
+ context "that come before an action" do
47
+ setup do
48
+ @mock_action.stubs(:follows).returns([MockActionOther])
49
+ end
50
+ should "raise an exception if they are not met" do
51
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
52
+ collection.new([@mock_action]).dependencies!
53
+ end
54
+ end
55
+
56
+ should "not raise an exception if they are met" do
57
+ assert_nothing_raised do
58
+ collection.new([@mock_action2, @mock_action]).dependencies!
59
+ end
60
+ end
61
+ end
62
+
63
+ context "that follow an an action" do
64
+ setup do
65
+ @mock_action.stubs(:precedes).returns([MockActionOther])
66
+ end
67
+
68
+ should "raise an exception if they are not met" do
69
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
70
+ collection.new([@mock_action]).dependencies!
71
+ end
72
+ end
73
+
74
+ should "not raise an exception if they are met" do
75
+ assert_nothing_raised do
76
+ collection.new([@mock_action, @mock_action2]).dependencies!
77
+ end
78
+ end
79
+ end
80
+
81
+ context "that are before and after an action" do
82
+ setup do
83
+ @mock_action.stubs(:precedes).returns([MockActionOther])
84
+ @mock_action.stubs(:follows).returns([MockActionOther])
85
+ end
86
+
87
+ should "raise an exception if they are met" do
88
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
89
+ collection.new([@mock_action2, @mock_action]).dependencies!
90
+ end
91
+ end
92
+
93
+ should "not raise and exception if they are met" do
94
+ assert_nothing_raised do
95
+ collection.new([@mock_action2, @mock_action, @mock_action2]).dependencies!
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ context "klasses" do
102
+ should "return a list of the collection element's classes" do
103
+ @action = mock('action')
104
+ assert_equal collection.new([@action]).klasses, [@action.class]
105
+ assert_equal collection.new([@action, 1.0, "foo"]).klasses, [@action.class, Float, String]
106
+ end
107
+ end
108
+
109
+ def collection; Vagrant::Actions::Collection end
110
+ end
@@ -6,6 +6,7 @@ class ActionRunnerTest < Test::Unit::TestCase
6
6
  action.stubs(:prepare)
7
7
  action.stubs(:execute!)
8
8
  action.stubs(:cleanup)
9
+ stub_default_action_dependecies(action)
9
10
  action
10
11
  end
11
12
 
@@ -135,6 +136,7 @@ class ActionRunnerTest < Test::Unit::TestCase
135
136
  should "clear the actions and run a single action if given to execute!" do
136
137
  action = mock("action")
137
138
  run_action = mock("action_run")
139
+ stub_default_action_dependecies(run_action)
138
140
  run_class = mock("run_class")
139
141
  run_class.expects(:new).once.returns(run_action)
140
142
  @runner.actions << action
@@ -148,7 +150,6 @@ class ActionRunnerTest < Test::Unit::TestCase
148
150
  end
149
151
 
150
152
  should "clear actions after running execute!" do
151
- @runner.actions << mock_fake_action
152
153
  @runner.actions << mock_fake_action
153
154
  assert !@runner.actions.empty? # sanity
154
155
  @runner.execute!
@@ -158,9 +159,10 @@ class ActionRunnerTest < Test::Unit::TestCase
158
159
  should "run #prepare on all actions, then #execute!" do
159
160
  action_seq = sequence("action_seq")
160
161
  actions = []
161
- 5.times do |i|
162
+ [MockAction, MockActionOther].each_with_index do |klass, i|
162
163
  action = mock("action#{i}")
163
-
164
+ action.expects(:class).returns(klass)
165
+ stub_default_action_dependecies(action, klass)
164
166
  @runner.actions << action
165
167
  actions << action
166
168
  end
@@ -176,10 +178,12 @@ class ActionRunnerTest < Test::Unit::TestCase
176
178
 
177
179
  context "exceptions" do
178
180
  setup do
179
- @actions = [mock_fake_action, mock_fake_action]
180
- @actions.each do |a|
181
- a.stubs(:rescue)
182
- @runner.actions << a
181
+ @actions = [MockAction, MockActionOther].map do |klass|
182
+ action = mock_fake_action
183
+ action.expects(:class).returns(klass)
184
+ action.stubs(:rescue)
185
+ @runner.actions << action
186
+ action
183
187
  end
184
188
 
185
189
  @exception = Exception.new
@@ -7,6 +7,13 @@ class BootActionTest < Test::Unit::TestCase
7
7
  mock_config
8
8
  end
9
9
 
10
+ context "preparing" do
11
+ should "add the root shared folder" do
12
+ Vagrant.config.vm.expects(:share_folder).with("vagrant-root", Vagrant.config.vm.project_directory, Vagrant::Env.root_path).once
13
+ @action.prepare
14
+ end
15
+ end
16
+
10
17
  context "execution" do
11
18
  should "invoke the 'boot' around callback" do
12
19
  boot_seq = sequence("boot_seq")
@@ -45,11 +52,4 @@ class BootActionTest < Test::Unit::TestCase
45
52
  assert !@action.wait_for_boot(0)
46
53
  end
47
54
  end
48
-
49
- context "callbacks" do
50
- should "setup the root directory shared folder" do
51
- expected = ["vagrant-root", Vagrant::Env.root_path, Vagrant.config.vm.project_directory]
52
- assert_equal expected, @action.collect_shared_folders
53
- end
54
- end
55
55
  end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class CustomizeActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Customize)
6
+ mock_config
7
+ end
8
+
9
+ context "executing" do
10
+ should "run the VM customization procs then save the VM" do
11
+ Vagrant.config.vm.expects(:run_procs!).with(@vm)
12
+ @vm.expects(:save).with(true).once
13
+ @action.execute!
14
+ end
15
+ end
16
+ end
@@ -2,23 +2,36 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
2
 
3
3
  class DestroyActionTest < Test::Unit::TestCase
4
4
  setup do
5
- @mock_vm, @vm, @action = mock_action(Vagrant::Actions::VM::Destroy)
5
+ @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Destroy)
6
6
  mock_config
7
7
  end
8
8
 
9
9
  context "executing" do
10
- setup do
11
- @vm.stubs(:destroy)
10
+ should "invoke an around callback around the destroy" do
11
+ @runner.expects(:invoke_around_callback).with(:destroy).once
12
+ @action.execute!
12
13
  end
13
14
 
14
- should "invoke an around callback around the destroy" do
15
- @mock_vm.expects(:invoke_around_callback).with(:destroy).once
15
+ should "destroy VM and clear persist" do
16
+ @runner.stubs(:invoke_around_callback).yields
17
+ clear_seq = sequence("clear")
18
+ @action.expects(:destroy_vm).in_sequence(clear_seq)
19
+ @action.expects(:depersist).in_sequence(clear_seq)
16
20
  @action.execute!
17
21
  end
22
+ end
18
23
 
24
+ context "destroying the VM" do
19
25
  should "destroy VM and attached images" do
20
26
  @vm.expects(:destroy).with(:destroy_image => true).once
21
- @action.execute!
27
+ @action.destroy_vm
28
+ end
29
+ end
30
+
31
+ context "depersisting" do
32
+ should "call depersist_vm on Env" do
33
+ Vagrant::Env.expects(:depersist_vm).with(@runner).once
34
+ @action.depersist
22
35
  end
23
36
  end
24
37
  end
@@ -6,6 +6,58 @@ class ForwardPortsActionTest < Test::Unit::TestCase
6
6
  mock_config
7
7
  end
8
8
 
9
+ context "checking for colliding ports" do
10
+ setup do
11
+ @forwarded_port = mock("forwarded_port")
12
+ @forwarded_port.stubs(:hostport)
13
+ @forwarded_ports = [@forwarded_port]
14
+
15
+ @vm = mock("vm")
16
+ @vm.stubs(:forwarded_ports).returns(@forwarded_ports)
17
+ @vm.stubs(:running?).returns(true)
18
+ @vm.stubs(:uuid).returns("foo")
19
+ @mock_vm.stubs(:uuid).returns("bar")
20
+ vms = [@vm]
21
+ VirtualBox::VM.stubs(:all).returns(vms)
22
+
23
+ mock_config do |config|
24
+ config.vm.forwarded_ports.clear
25
+ config.vm.forward_port("ssh", 22, 2222)
26
+ end
27
+ end
28
+
29
+ should "ignore vms which aren't running" do
30
+ @vm.expects(:running?).returns(false)
31
+ @vm.expects(:forwarded_ports).never
32
+ @action.prepare
33
+ end
34
+
35
+ should "ignore vms which are equivalent to ours" do
36
+ @mock_vm.expects(:uuid).returns(@vm.uuid)
37
+ @vm.expects(:forwarded_ports).never
38
+ @action.prepare
39
+ end
40
+
41
+ should "not raise any errors if no forwarded ports collide" do
42
+ @forwarded_port.expects(:hostport).returns(80)
43
+ assert_nothing_raised { @action.prepare }
44
+ end
45
+
46
+ should "raise an ActionException if a port collides" do
47
+ @forwarded_port.expects(:hostport).returns(2222)
48
+ assert_raises(Vagrant::Actions::ActionException) {
49
+ @action.prepare
50
+ }
51
+ end
52
+
53
+ should "convert ports to strings prior to checking" do
54
+ @forwarded_port.expects(:hostport).returns("2222")
55
+ assert_raises(Vagrant::Actions::ActionException) {
56
+ @action.prepare
57
+ }
58
+ end
59
+ end
60
+
9
61
  context "execution" do
10
62
  should "clear all previous ports and forward new ports" do
11
63
  exec_seq = sequence("exec_seq")
@@ -23,14 +23,21 @@ class ImportActionTest < Test::Unit::TestCase
23
23
  end
24
24
 
25
25
  should "call import on VirtualBox::VM with the proper base" do
26
- VirtualBox::VM.expects(:import).once.with(@ovf_file)
27
- @import.execute!
26
+ VirtualBox::VM.expects(:import).once.with(@ovf_file).returns("foo")
27
+ assert_nothing_raised { @import.execute! }
28
+ end
29
+
30
+ should "raise an exception if import is nil" do
31
+ @mock_vm.expects(:vm).returns(nil)
32
+ assert_raises(Vagrant::Actions::ActionException) {
33
+ @import.execute!
34
+ }
28
35
  end
29
36
 
30
37
  should "set the resulting VM as the VM of the Vagrant VM object" do
31
38
  new_vm = mock("new_vm")
32
39
  @mock_vm.expects(:vm=).with(new_vm).once
33
- VirtualBox::VM.expects(:import).returns(new_vm)
40
+ VirtualBox::VM.expects(:import).returns(new_vm).returns("foo")
34
41
  @import.execute!
35
42
  end
36
43
  end