tenderloin 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. data/LICENCE +21 -0
  2. data/README.md +50 -0
  3. data/Version +1 -0
  4. data/bin/loin +5 -0
  5. data/config/default.rb +26 -0
  6. data/lib/tenderloin/actions/base.rb +93 -0
  7. data/lib/tenderloin/actions/box/add.rb +22 -0
  8. data/lib/tenderloin/actions/box/destroy.rb +14 -0
  9. data/lib/tenderloin/actions/box/download.rb +63 -0
  10. data/lib/tenderloin/actions/box/unpackage.rb +46 -0
  11. data/lib/tenderloin/actions/runner.rb +138 -0
  12. data/lib/tenderloin/actions/vm/boot.rb +52 -0
  13. data/lib/tenderloin/actions/vm/destroy.rb +18 -0
  14. data/lib/tenderloin/actions/vm/halt.rb +14 -0
  15. data/lib/tenderloin/actions/vm/import.rb +32 -0
  16. data/lib/tenderloin/actions/vm/move_hard_drive.rb +53 -0
  17. data/lib/tenderloin/actions/vm/provision.rb +71 -0
  18. data/lib/tenderloin/actions/vm/reload.rb +17 -0
  19. data/lib/tenderloin/actions/vm/shared_folders.rb +47 -0
  20. data/lib/tenderloin/actions/vm/start.rb +17 -0
  21. data/lib/tenderloin/actions/vm/up.rb +55 -0
  22. data/lib/tenderloin/box.rb +143 -0
  23. data/lib/tenderloin/busy.rb +73 -0
  24. data/lib/tenderloin/cli.rb +59 -0
  25. data/lib/tenderloin/commands.rb +154 -0
  26. data/lib/tenderloin/config.rb +144 -0
  27. data/lib/tenderloin/downloaders/base.rb +13 -0
  28. data/lib/tenderloin/downloaders/file.rb +21 -0
  29. data/lib/tenderloin/downloaders/http.rb +47 -0
  30. data/lib/tenderloin/env.rb +156 -0
  31. data/lib/tenderloin/fusion_vm.rb +85 -0
  32. data/lib/tenderloin/ssh.rb +49 -0
  33. data/lib/tenderloin/util.rb +51 -0
  34. data/lib/tenderloin/vm.rb +63 -0
  35. data/lib/tenderloin/vmx_file.rb +28 -0
  36. data/lib/tenderloin.rb +14 -0
  37. data/script/tenderloin-ssh-expect.sh +23 -0
  38. data/templates/Tenderfile +8 -0
  39. data/test/tenderloin/actions/base_test.rb +32 -0
  40. data/test/tenderloin/actions/box/add_test.rb +37 -0
  41. data/test/tenderloin/actions/box/destroy_test.rb +18 -0
  42. data/test/tenderloin/actions/box/download_test.rb +118 -0
  43. data/test/tenderloin/actions/box/unpackage_test.rb +100 -0
  44. data/test/tenderloin/actions/runner_test.rb +262 -0
  45. data/test/tenderloin/actions/vm/boot_test.rb +55 -0
  46. data/test/tenderloin/actions/vm/destroy_test.rb +24 -0
  47. data/test/tenderloin/actions/vm/down_test.rb +32 -0
  48. data/test/tenderloin/actions/vm/export_test.rb +88 -0
  49. data/test/tenderloin/actions/vm/forward_ports_test.rb +50 -0
  50. data/test/tenderloin/actions/vm/halt_test.rb +27 -0
  51. data/test/tenderloin/actions/vm/import_test.rb +36 -0
  52. data/test/tenderloin/actions/vm/move_hard_drive_test.rb +108 -0
  53. data/test/tenderloin/actions/vm/package_test.rb +181 -0
  54. data/test/tenderloin/actions/vm/provision_test.rb +103 -0
  55. data/test/tenderloin/actions/vm/reload_test.rb +44 -0
  56. data/test/tenderloin/actions/vm/resume_test.rb +27 -0
  57. data/test/tenderloin/actions/vm/shared_folders_test.rb +117 -0
  58. data/test/tenderloin/actions/vm/start_test.rb +28 -0
  59. data/test/tenderloin/actions/vm/suspend_test.rb +27 -0
  60. data/test/tenderloin/actions/vm/up_test.rb +98 -0
  61. data/test/tenderloin/box_test.rb +139 -0
  62. data/test/tenderloin/busy_test.rb +83 -0
  63. data/test/tenderloin/commands_test.rb +269 -0
  64. data/test/tenderloin/config_test.rb +123 -0
  65. data/test/tenderloin/downloaders/base_test.rb +20 -0
  66. data/test/tenderloin/downloaders/file_test.rb +32 -0
  67. data/test/tenderloin/downloaders/http_test.rb +40 -0
  68. data/test/tenderloin/env_test.rb +345 -0
  69. data/test/tenderloin/ssh_test.rb +103 -0
  70. data/test/tenderloin/util_test.rb +64 -0
  71. data/test/tenderloin/vm_test.rb +89 -0
  72. data/test/test_helper.rb +92 -0
  73. metadata +241 -0
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class ExportActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Export)
6
+ mock_config
7
+ end
8
+
9
+ context "executing" do
10
+ should "setup the temp dir then export" do
11
+ exec_seq = sequence('execute')
12
+ @action.expects(:setup_temp_dir).once.in_sequence(exec_seq)
13
+ @action.expects(:export).once.in_sequence(exec_seq)
14
+ @action.execute!
15
+ end
16
+ end
17
+
18
+ context "setting up the temporary directory" do
19
+ setup do
20
+ @time_now = Time.now.to_i.to_s
21
+ Time.stubs(:now).returns(@time_now)
22
+
23
+ @tmp_path = "foo"
24
+ Tenderloin::Env.stubs(:tmp_path).returns(@tmp_path)
25
+
26
+ @temp_dir = File.join(Tenderloin::Env.tmp_path, @time_now)
27
+ FileUtils.stubs(:mkpath)
28
+ end
29
+
30
+ should "create the temporary directory using the current time" do
31
+ FileUtils.expects(:mkpath).with(@temp_dir).once
32
+ @action.setup_temp_dir
33
+ end
34
+
35
+ should "set the temporary directory to the temp_dir variable" do
36
+ @action.setup_temp_dir
37
+ assert_equal @temp_dir, @action.temp_dir
38
+ end
39
+ end
40
+
41
+ context "path to OVF file" do
42
+ setup do
43
+ @temp_dir = "foo"
44
+ @action.stubs(:temp_dir).returns(@temp_dir)
45
+ end
46
+
47
+ should "be the temporary directory joined with the OVF filename" do
48
+ assert_equal File.join(@temp_dir, Tenderloin.config.vm.box_ovf), @action.ovf_path
49
+ end
50
+ end
51
+
52
+ context "exporting" do
53
+ setup do
54
+ @ovf_path = mock("ovf_path")
55
+ @action.stubs(:ovf_path).returns(@ovf_path)
56
+ end
57
+
58
+ should "call export on the runner with the ovf path" do
59
+ @vm.expects(:export).with(@ovf_path, {}, true).once
60
+ @action.export
61
+ end
62
+ end
63
+
64
+ context "cleanup" do
65
+ setup do
66
+ @temp_dir = "foo"
67
+ @action.stubs(:temp_dir).returns(@temp_dir)
68
+ end
69
+
70
+ should "remove the temporary directory" do
71
+ FileUtils.expects(:rm_r).with(@temp_dir).once
72
+ @action.cleanup
73
+ end
74
+
75
+ should "not remove a directory if temp_dir is nil" do
76
+ FileUtils.expects(:rm_r).never
77
+ @action.stubs(:temp_dir).returns(nil)
78
+ @action.cleanup
79
+ end
80
+ end
81
+
82
+ context "rescue" do
83
+ should "call cleanup method" do
84
+ @action.expects(:cleanup).once
85
+ @action.rescue(nil)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class ForwardPortsActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @mock_vm, @vm, @action = mock_action(Tenderloin::Actions::VM::ForwardPorts)
6
+ mock_config
7
+ end
8
+
9
+ context "execution" do
10
+ should "clear all previous ports and forward new ports" do
11
+ exec_seq = sequence("exec_seq")
12
+ @action.expects(:clear).once.in_sequence(exec_seq)
13
+ @action.expects(:forward_ports).once.in_sequence(exec_seq)
14
+ @action.execute!
15
+ end
16
+ end
17
+
18
+ context "forwarding ports" do
19
+ should "create a port forwarding for the VM" do
20
+ forwarded_ports = mock("forwarded_ports")
21
+
22
+ Tenderloin.config.vm.forwarded_ports.each do |name, opts|
23
+ forwarded_ports.expects(:<<).with do |port|
24
+ assert_equal name, port.name
25
+ assert_equal opts[:hostport], port.hostport
26
+ assert_equal opts[:guestport], port.guestport
27
+ true
28
+ end
29
+ end
30
+
31
+ @vm.expects(:forwarded_ports).returns(forwarded_ports)
32
+ @vm.expects(:save).with(true).once
33
+ @action.forward_ports
34
+ end
35
+ end
36
+
37
+ context "clearing forwarded ports" do
38
+ should "call destroy on all forwarded ports" do
39
+ forwarded_ports = []
40
+ 5.times do |i|
41
+ port = mock("port#{i}")
42
+ port.expects(:destroy).with(true).once
43
+ forwarded_ports << port
44
+ end
45
+
46
+ @vm.expects(:forwarded_ports).returns(forwarded_ports)
47
+ @action.clear
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class HaltActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Halt)
6
+ mock_config
7
+ end
8
+
9
+ context "executing" do
10
+ setup do
11
+ @vm.stubs(:running?).returns(true)
12
+ end
13
+
14
+ should "force the VM to stop" do
15
+ @vm.expects(:stop).with(true).once
16
+ @action.execute!
17
+ end
18
+
19
+ should "raise an ActionException if VM is not running" do
20
+ @vm.stubs(:running?).returns(false)
21
+ @vm.expects(:stop).never
22
+ assert_raises(Tenderloin::Actions::ActionException) {
23
+ @action.execute!
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class ImportActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @mock_vm, @vm, @import = mock_action(Tenderloin::Actions::VM::Import)
6
+
7
+ @ovf_file = "foo"
8
+ @box = mock("box")
9
+ @box.stubs(:ovf_file).returns(@ovf_file)
10
+ Tenderloin::Env.stubs(:box).returns(@box)
11
+
12
+ VirtualBox::VM.stubs(:import)
13
+ end
14
+
15
+ should "run in a busy block" do
16
+ Tenderloin::Busy.expects(:busy).once
17
+ @import.execute!
18
+ end
19
+
20
+ should "invoke an around callback around the import" do
21
+ @mock_vm.expects(:invoke_around_callback).with(:import).once
22
+ @import.execute!
23
+ end
24
+
25
+ should "call import on VirtualBox::VM with the proper base" do
26
+ VirtualBox::VM.expects(:import).once.with(@ovf_file)
27
+ @import.execute!
28
+ end
29
+
30
+ should "set the resulting VM as the VM of the Tenderloin VM object" do
31
+ new_vm = mock("new_vm")
32
+ @mock_vm.expects(:vm=).with(new_vm).once
33
+ VirtualBox::VM.expects(:import).returns(new_vm)
34
+ @import.execute!
35
+ end
36
+ end
@@ -0,0 +1,108 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class MoveHardDriveActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @mock_vm, @vm, @action = mock_action(Tenderloin::Actions::VM::MoveHardDrive)
6
+ @hd_location = "/foo"
7
+ mock_config do |config|
8
+ File.expects(:directory?).with(@hd_location).returns(true)
9
+ config.vm.hd_location = @hd_location
10
+ end
11
+ end
12
+
13
+
14
+ should "be able to identifiy a hard drive within the storage controllers" do
15
+ hd = mock('hd')
16
+ hd_image = mock('hd_image')
17
+ hd_image.expects(:is_a?).returns(true)
18
+ hd.expects(:image).returns(hd_image)
19
+
20
+ dvd = mock('dvd')
21
+ controller = mock('controller')
22
+ controller.expects(:devices).returns([hd, dvd])
23
+
24
+ @vm.expects(:storage_controllers).once.returns([controller])
25
+ assert_equal @action.find_hard_drive, hd
26
+ end
27
+
28
+ context "execution" do
29
+ should "error and exit if the vm is not powered off" do
30
+ @mock_vm.expects(:powered_off?).returns(false)
31
+ @action.expects(:error_and_exit).once
32
+ @action.execute!
33
+ end
34
+
35
+ should "move the hard drive if vm is powered off" do
36
+ @mock_vm.expects(:powered_off?).returns(true)
37
+ @action.expects(:error_and_exit).never
38
+ @action.expects(:destroy_drive_after).once
39
+ @action.execute!
40
+ end
41
+ end
42
+
43
+ context "new image path" do
44
+ setup do
45
+ @hd = mock("hd")
46
+ @image = mock("image")
47
+ @filename = "foo"
48
+ @hd.stubs(:image).returns(@image)
49
+ @image.stubs(:filename).returns(@filename)
50
+ @action.stubs(:hard_drive).returns(@hd)
51
+ end
52
+
53
+ should "be the configured hd location and the existing hard drive filename" do
54
+ joined = File.join(Tenderloin.config.vm.hd_location, @filename)
55
+ assert_equal joined, @action.new_image_path
56
+ end
57
+ end
58
+
59
+ context "cloning and attaching new image" do
60
+ setup do
61
+ @hd = mock("hd")
62
+ @image = mock("image")
63
+ @hd.stubs(:image).returns(@image)
64
+ @action.stubs(:hard_drive).returns(@hd)
65
+ @new_image_path = "foo"
66
+ @action.stubs(:new_image_path).returns(@new_image_path)
67
+ end
68
+
69
+ should "clone to the new path" do
70
+ new_image = mock("new_image")
71
+ @image.expects(:clone).with(@new_image_path, Tenderloin.config.vm.disk_image_format, true).returns(new_image).once
72
+ @hd.expects(:image=).with(new_image).once
73
+ @vm.expects(:save).once
74
+ @action.clone_and_attach
75
+ end
76
+ end
77
+
78
+ context "destroying the old image" do
79
+ setup do
80
+ @hd = mock("hd")
81
+ @action.stubs(:hard_drive).returns(@hd)
82
+ end
83
+
84
+ should "yield the block, and destroy the old image after" do
85
+ image = mock("image")
86
+ image.stubs(:filename).returns("foo")
87
+ destroy_seq = sequence("destroy_seq")
88
+ @hd.expects(:image).returns(image).in_sequence(destroy_seq)
89
+ @hd.expects(:foo).once.in_sequence(destroy_seq)
90
+ image.expects(:destroy).with(true).once.in_sequence(destroy_seq)
91
+
92
+ @action.destroy_drive_after { @hd.foo }
93
+ end
94
+
95
+ # Ensures that the image is not destroyed in an "ensure" block
96
+ should "not destroy the image if an exception is raised" do
97
+ image = mock("image")
98
+ image.expects(:destroy).never
99
+ @hd.expects(:image).returns(image)
100
+
101
+ assert_raises(Exception) do
102
+ @action.destroy_drive_after do
103
+ raise Exception.new("FOO")
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,181 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class PackageActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Package, "bing", [])
6
+
7
+ mock_config
8
+ end
9
+
10
+ context "initialization" do
11
+ def get_action(*args)
12
+ runner, vm, action = mock_action(Tenderloin::Actions::VM::Package, *args)
13
+ return action
14
+ end
15
+
16
+ should "make out_path 'package' by default if nil is given" do
17
+ action = get_action(nil, [])
18
+ assert_equal "package", action.out_path
19
+ end
20
+
21
+ should "make include files an empty array by default" do
22
+ action = get_action("foo", nil)
23
+ assert action.include_files.is_a?(Array)
24
+ assert action.include_files.empty?
25
+ end
26
+ end
27
+
28
+ context "executing" do
29
+ setup do
30
+ @action.stubs(:compress)
31
+ end
32
+
33
+ should "compress" do
34
+ package_seq = sequence("package_seq")
35
+ @action.expects(:compress).in_sequence(package_seq)
36
+ @action.execute!
37
+ end
38
+ end
39
+
40
+ context "tar path" do
41
+ should "be the temporary directory with the name and extension attached" do
42
+ pwd = "foo"
43
+ FileUtils.stubs(:pwd).returns(pwd)
44
+ assert_equal File.join(pwd, "#{@action.out_path}#{Tenderloin.config.package.extension}"), @action.tar_path
45
+ end
46
+ end
47
+
48
+ context "temp path" do
49
+ setup do
50
+ @export = mock("export")
51
+ @action.expects(:export_action).returns(@export)
52
+ end
53
+
54
+ should "use the export action's temp dir" do
55
+ path = mock("path")
56
+ @export.expects(:temp_dir).returns(path)
57
+ @action.temp_path
58
+ end
59
+ end
60
+
61
+ context "compression" do
62
+ setup do
63
+ @tar_path = "foo"
64
+ @action.stubs(:tar_path).returns(@tar_path)
65
+
66
+ @temp_path = "foo"
67
+ @action.stubs(:temp_path).returns(@temp_path)
68
+
69
+ @include_files = []
70
+ @action.stubs(:include_files).returns(@include_files)
71
+
72
+ @pwd = "bar"
73
+ FileUtils.stubs(:pwd).returns(@pwd)
74
+ FileUtils.stubs(:cd)
75
+
76
+ @file = mock("file")
77
+ File.stubs(:open).yields(@file)
78
+
79
+ @output = mock("output")
80
+ @tar = Archive::Tar::Minitar
81
+ Archive::Tar::Minitar::Output.stubs(:open).yields(@output)
82
+ @tar.stubs(:pack_file)
83
+ end
84
+
85
+ should "open the tar file with the tar path properly" do
86
+ File.expects(:open).with(@tar_path, File::CREAT | File::WRONLY, 0644).once
87
+ @action.compress
88
+ end
89
+
90
+ should "open tar file" do
91
+ Archive::Tar::Minitar::Output.expects(:open).with(@file).once
92
+ @action.compress
93
+ end
94
+
95
+ #----------------------------------------------------------------
96
+ # Methods below this comment test the block yielded by Minitar open
97
+ #----------------------------------------------------------------
98
+ should "cd to the directory and append the directory" do
99
+ @files = []
100
+ compress_seq = sequence("compress_seq")
101
+
102
+ FileUtils.expects(:pwd).once.returns(@pwd).in_sequence(compress_seq)
103
+ FileUtils.expects(:cd).with(@temp_path).in_sequence(compress_seq)
104
+ Dir.expects(:glob).returns(@files).in_sequence(compress_seq)
105
+
106
+ 5.times do |i|
107
+ file = mock("file#{i}")
108
+ @tar.expects(:pack_file).with(file, @output).once.in_sequence(compress_seq)
109
+ @files << file
110
+ end
111
+
112
+ FileUtils.expects(:cd).with(@pwd).in_sequence(compress_seq)
113
+ @action.compress
114
+ end
115
+
116
+ should "pop back to the current directory even if an exception is raised" do
117
+ cd_seq = sequence("cd_seq")
118
+ FileUtils.expects(:cd).with(@temp_path).raises(Exception).in_sequence(cd_seq)
119
+ FileUtils.expects(:cd).with(@pwd).in_sequence(cd_seq)
120
+
121
+ assert_raises(Exception) {
122
+ @action.compress
123
+ }
124
+ end
125
+
126
+ should "add included files when passed" do
127
+ compress_seq = sequence("compress")
128
+ @files = []
129
+ 5.times do |i|
130
+ file = mock("file#{i}")
131
+ @tar.expects(:pack_file).with(file, @output).once.in_sequence(compress_seq)
132
+ @files << file
133
+ end
134
+
135
+ @action.expects(:include_files).returns(@files)
136
+ @action.compress
137
+ end
138
+
139
+ should "not add files when none are specified" do
140
+ @tar.expects(:pack_file).never
141
+ Dir.expects(:glob).once.returns([])
142
+ @action.compress
143
+ end
144
+ end
145
+
146
+ context "preparing the action" do
147
+ context "checking include files" do
148
+ setup do
149
+ @include_files = ['fooiest', 'booiest']
150
+ @runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Package, "bing", @include_files)
151
+ @runner.stubs(:find_action).returns("foo")
152
+ end
153
+
154
+ should "check that all the include files exist" do
155
+ @include_files.each do |file|
156
+ File.expects(:exists?).with(file).returns(true)
157
+ end
158
+ @action.prepare
159
+ end
160
+
161
+ should "raise an exception when an include file does not exist" do
162
+ File.expects(:exists?).once.returns(false)
163
+ assert_raises(Tenderloin::Actions::ActionException) { @action.prepare }
164
+ end
165
+ end
166
+
167
+ context "loading export reference" do
168
+ should "find and store a reference to the export action" do
169
+ @export = mock("export")
170
+ @runner.expects(:find_action).with(Tenderloin::Actions::VM::Export).once.returns(@export)
171
+ @action.prepare
172
+ assert @export.equal?(@action.export_action)
173
+ end
174
+
175
+ should "raise an exception if the export action couldn't be found" do
176
+ @runner.expects(:find_action).with(Tenderloin::Actions::VM::Export).once.returns(nil)
177
+ assert_raises(Tenderloin::Actions::ActionException) { @action.prepare }
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,103 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class ProvisionActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @mock_vm, @vm, @action = mock_action(Tenderloin::Actions::VM::Provision)
6
+
7
+ Tenderloin::SSH.stubs(:execute)
8
+ Tenderloin::SSH.stubs(:upload!)
9
+
10
+ mock_config
11
+ end
12
+
13
+ context "shared folders" do
14
+ should "setup shared folder on VM for the cookbooks" do
15
+ File.expects(:expand_path).with(Tenderloin.config.chef.cookbooks_path, Tenderloin::Env.root_path).returns("foo")
16
+ @action.expects(:cookbooks_path).returns("bar")
17
+ assert_equal ["tenderloin-provisioning", "foo", "bar"], @action.collect_shared_folders
18
+ end
19
+ end
20
+
21
+ context "cookbooks path" do
22
+ should "return the proper cookbook path" do
23
+ cookbooks_path = File.join(Tenderloin.config.chef.provisioning_path, "cookbooks")
24
+ assert_equal cookbooks_path, @action.cookbooks_path
25
+ end
26
+ end
27
+
28
+ context "permissions on provisioning folder" do
29
+ should "chown the folder to the ssh user" do
30
+ ssh = mock("ssh")
31
+ ssh.expects(:exec!).with("sudo chown #{Tenderloin.config.ssh.username} #{Tenderloin.config.chef.provisioning_path}")
32
+ Tenderloin::SSH.expects(:execute).yields(ssh)
33
+ @action.chown_provisioning_folder
34
+ end
35
+ end
36
+
37
+ context "generating and uploading json" do
38
+ def assert_json
39
+ Tenderloin::SSH.expects(:upload!).with do |json, path|
40
+ data = JSON.parse(json.read)
41
+ yield data
42
+ true
43
+ end
44
+
45
+ @action.setup_json
46
+ end
47
+
48
+ should "merge in the extra json specified in the config" do
49
+ Tenderloin.config.chef.json = { :foo => "BAR" }
50
+ assert_json do |data|
51
+ assert_equal "BAR", data["foo"]
52
+ end
53
+ end
54
+
55
+ should "add the directory as a special case to the JSON" do
56
+ assert_json do |data|
57
+ assert_equal Tenderloin.config.vm.project_directory, data["tenderloin"]["directory"]
58
+ end
59
+ end
60
+
61
+ should "add the config to the JSON" do
62
+ assert_json do |data|
63
+ assert_equal Tenderloin.config.vm.project_directory, data["tenderloin"]["config"]["vm"]["project_directory"]
64
+ end
65
+ end
66
+
67
+ should "upload a StringIO to dna.json" do
68
+ StringIO.expects(:new).with(anything).returns("bar")
69
+ File.expects(:join).with(Tenderloin.config.chef.provisioning_path, "dna.json").once.returns("baz")
70
+ Tenderloin::SSH.expects(:upload!).with("bar", "baz").once
71
+ @action.setup_json
72
+ end
73
+ end
74
+
75
+ context "generating and uploading chef solo configuration file" do
76
+ should "upload properly generate the configuration file using configuration data" do
77
+ expected_config = <<-config
78
+ file_cache_path "#{Tenderloin.config.chef.provisioning_path}"
79
+ cookbook_path "#{@action.cookbooks_path}"
80
+ config
81
+
82
+ StringIO.expects(:new).with(expected_config).once
83
+ @action.setup_solo_config
84
+ end
85
+
86
+ should "upload this file as solo.rb to the provisioning folder" do
87
+ @action.expects(:cookbooks_path).returns("cookbooks")
88
+ StringIO.expects(:new).returns("foo")
89
+ File.expects(:join).with(Tenderloin.config.chef.provisioning_path, "solo.rb").once.returns("bar")
90
+ Tenderloin::SSH.expects(:upload!).with("foo", "bar").once
91
+ @action.setup_solo_config
92
+ end
93
+ end
94
+
95
+ context "running chef solo" do
96
+ should "cd into the provisioning directory and run chef solo" do
97
+ ssh = mock("ssh")
98
+ ssh.expects(:exec!).with("cd #{Tenderloin.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json").once
99
+ Tenderloin::SSH.expects(:execute).yields(ssh)
100
+ @action.run_chef_solo
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class ReloadActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Reload)
6
+ mock_config
7
+ end
8
+
9
+ context "sub-actions" do
10
+ setup do
11
+ @default_order = [Tenderloin::Actions::VM::ForwardPorts, Tenderloin::Actions::VM::SharedFolders, Tenderloin::Actions::VM::Boot]
12
+ @vm.stubs(:running?).returns(false)
13
+ end
14
+
15
+ def setup_action_expectations
16
+ default_seq = sequence("default_seq")
17
+ @default_order.each do |action|
18
+ @runner.expects(:add_action).with(action).once.in_sequence(default_seq)
19
+ end
20
+ end
21
+
22
+ should "do the proper actions by default" do
23
+ setup_action_expectations
24
+ @action.prepare
25
+ end
26
+
27
+ should "halt if the VM is running" do
28
+ @vm.expects(:running?).returns(true)
29
+ @default_order.unshift(Tenderloin::Actions::VM::Halt)
30
+ setup_action_expectations
31
+ @action.prepare
32
+ end
33
+
34
+ should "add in the provisioning step if enabled" do
35
+ mock_config do |config|
36
+ config.chef.enabled = true
37
+ end
38
+
39
+ @default_order.push(Tenderloin::Actions::VM::Provision)
40
+ setup_action_expectations
41
+ @action.prepare
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class ResumeActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Resume)
6
+ mock_config
7
+ end
8
+
9
+ context "executing" do
10
+ setup do
11
+ @vm.stubs(:saved?).returns(true)
12
+ end
13
+
14
+ should "save the state of the VM" do
15
+ @runner.expects(:start).once
16
+ @action.execute!
17
+ end
18
+
19
+ should "raise an ActionException if the VM is not saved" do
20
+ @vm.expects(:saved?).returns(false)
21
+ @vm.expects(:start).never
22
+ assert_raises(Tenderloin::Actions::ActionException) {
23
+ @action.execute!
24
+ }
25
+ end
26
+ end
27
+ end