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.
- data/LICENCE +21 -0
- data/README.md +50 -0
- data/Version +1 -0
- data/bin/loin +5 -0
- data/config/default.rb +26 -0
- data/lib/tenderloin/actions/base.rb +93 -0
- data/lib/tenderloin/actions/box/add.rb +22 -0
- data/lib/tenderloin/actions/box/destroy.rb +14 -0
- data/lib/tenderloin/actions/box/download.rb +63 -0
- data/lib/tenderloin/actions/box/unpackage.rb +46 -0
- data/lib/tenderloin/actions/runner.rb +138 -0
- data/lib/tenderloin/actions/vm/boot.rb +52 -0
- data/lib/tenderloin/actions/vm/destroy.rb +18 -0
- data/lib/tenderloin/actions/vm/halt.rb +14 -0
- data/lib/tenderloin/actions/vm/import.rb +32 -0
- data/lib/tenderloin/actions/vm/move_hard_drive.rb +53 -0
- data/lib/tenderloin/actions/vm/provision.rb +71 -0
- data/lib/tenderloin/actions/vm/reload.rb +17 -0
- data/lib/tenderloin/actions/vm/shared_folders.rb +47 -0
- data/lib/tenderloin/actions/vm/start.rb +17 -0
- data/lib/tenderloin/actions/vm/up.rb +55 -0
- data/lib/tenderloin/box.rb +143 -0
- data/lib/tenderloin/busy.rb +73 -0
- data/lib/tenderloin/cli.rb +59 -0
- data/lib/tenderloin/commands.rb +154 -0
- data/lib/tenderloin/config.rb +144 -0
- data/lib/tenderloin/downloaders/base.rb +13 -0
- data/lib/tenderloin/downloaders/file.rb +21 -0
- data/lib/tenderloin/downloaders/http.rb +47 -0
- data/lib/tenderloin/env.rb +156 -0
- data/lib/tenderloin/fusion_vm.rb +85 -0
- data/lib/tenderloin/ssh.rb +49 -0
- data/lib/tenderloin/util.rb +51 -0
- data/lib/tenderloin/vm.rb +63 -0
- data/lib/tenderloin/vmx_file.rb +28 -0
- data/lib/tenderloin.rb +14 -0
- data/script/tenderloin-ssh-expect.sh +23 -0
- data/templates/Tenderfile +8 -0
- data/test/tenderloin/actions/base_test.rb +32 -0
- data/test/tenderloin/actions/box/add_test.rb +37 -0
- data/test/tenderloin/actions/box/destroy_test.rb +18 -0
- data/test/tenderloin/actions/box/download_test.rb +118 -0
- data/test/tenderloin/actions/box/unpackage_test.rb +100 -0
- data/test/tenderloin/actions/runner_test.rb +262 -0
- data/test/tenderloin/actions/vm/boot_test.rb +55 -0
- data/test/tenderloin/actions/vm/destroy_test.rb +24 -0
- data/test/tenderloin/actions/vm/down_test.rb +32 -0
- data/test/tenderloin/actions/vm/export_test.rb +88 -0
- data/test/tenderloin/actions/vm/forward_ports_test.rb +50 -0
- data/test/tenderloin/actions/vm/halt_test.rb +27 -0
- data/test/tenderloin/actions/vm/import_test.rb +36 -0
- data/test/tenderloin/actions/vm/move_hard_drive_test.rb +108 -0
- data/test/tenderloin/actions/vm/package_test.rb +181 -0
- data/test/tenderloin/actions/vm/provision_test.rb +103 -0
- data/test/tenderloin/actions/vm/reload_test.rb +44 -0
- data/test/tenderloin/actions/vm/resume_test.rb +27 -0
- data/test/tenderloin/actions/vm/shared_folders_test.rb +117 -0
- data/test/tenderloin/actions/vm/start_test.rb +28 -0
- data/test/tenderloin/actions/vm/suspend_test.rb +27 -0
- data/test/tenderloin/actions/vm/up_test.rb +98 -0
- data/test/tenderloin/box_test.rb +139 -0
- data/test/tenderloin/busy_test.rb +83 -0
- data/test/tenderloin/commands_test.rb +269 -0
- data/test/tenderloin/config_test.rb +123 -0
- data/test/tenderloin/downloaders/base_test.rb +20 -0
- data/test/tenderloin/downloaders/file_test.rb +32 -0
- data/test/tenderloin/downloaders/http_test.rb +40 -0
- data/test/tenderloin/env_test.rb +345 -0
- data/test/tenderloin/ssh_test.rb +103 -0
- data/test/tenderloin/util_test.rb +64 -0
- data/test/tenderloin/vm_test.rb +89 -0
- data/test/test_helper.rb +92 -0
- 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
         |