vagrantup 0.1.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 (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/Gemfile +17 -0
  4. data/README.md +45 -0
  5. data/Rakefile +41 -0
  6. data/VERSION +1 -0
  7. data/bin/.gitignore +0 -0
  8. data/bin/vagrant +15 -0
  9. data/bin/vagrant-box +35 -0
  10. data/bin/vagrant-down +28 -0
  11. data/bin/vagrant-halt +29 -0
  12. data/bin/vagrant-init +28 -0
  13. data/bin/vagrant-package +30 -0
  14. data/bin/vagrant-reload +30 -0
  15. data/bin/vagrant-resume +28 -0
  16. data/bin/vagrant-ssh +28 -0
  17. data/bin/vagrant-suspend +28 -0
  18. data/bin/vagrant-up +30 -0
  19. data/config/default.rb +29 -0
  20. data/lib/vagrant.rb +14 -0
  21. data/lib/vagrant/actions/base.rb +93 -0
  22. data/lib/vagrant/actions/box/add.rb +22 -0
  23. data/lib/vagrant/actions/box/destroy.rb +14 -0
  24. data/lib/vagrant/actions/box/download.rb +63 -0
  25. data/lib/vagrant/actions/box/unpackage.rb +49 -0
  26. data/lib/vagrant/actions/runner.rb +128 -0
  27. data/lib/vagrant/actions/vm/destroy.rb +14 -0
  28. data/lib/vagrant/actions/vm/down.rb +12 -0
  29. data/lib/vagrant/actions/vm/export.rb +41 -0
  30. data/lib/vagrant/actions/vm/forward_ports.rb +32 -0
  31. data/lib/vagrant/actions/vm/halt.rb +14 -0
  32. data/lib/vagrant/actions/vm/import.rb +17 -0
  33. data/lib/vagrant/actions/vm/move_hard_drive.rb +53 -0
  34. data/lib/vagrant/actions/vm/package.rb +61 -0
  35. data/lib/vagrant/actions/vm/provision.rb +71 -0
  36. data/lib/vagrant/actions/vm/reload.rb +17 -0
  37. data/lib/vagrant/actions/vm/resume.rb +16 -0
  38. data/lib/vagrant/actions/vm/shared_folders.rb +69 -0
  39. data/lib/vagrant/actions/vm/start.rb +50 -0
  40. data/lib/vagrant/actions/vm/suspend.rb +16 -0
  41. data/lib/vagrant/actions/vm/up.rb +35 -0
  42. data/lib/vagrant/box.rb +129 -0
  43. data/lib/vagrant/busy.rb +73 -0
  44. data/lib/vagrant/commands.rb +174 -0
  45. data/lib/vagrant/config.rb +156 -0
  46. data/lib/vagrant/downloaders/base.rb +13 -0
  47. data/lib/vagrant/downloaders/file.rb +21 -0
  48. data/lib/vagrant/downloaders/http.rb +47 -0
  49. data/lib/vagrant/env.rb +140 -0
  50. data/lib/vagrant/ssh.rb +43 -0
  51. data/lib/vagrant/util.rb +45 -0
  52. data/lib/vagrant/vm.rb +57 -0
  53. data/script/vagrant-ssh-expect.sh +22 -0
  54. data/templates/Vagrantfile +8 -0
  55. data/test/test_helper.rb +91 -0
  56. data/test/vagrant/actions/base_test.rb +32 -0
  57. data/test/vagrant/actions/box/add_test.rb +37 -0
  58. data/test/vagrant/actions/box/destroy_test.rb +18 -0
  59. data/test/vagrant/actions/box/download_test.rb +118 -0
  60. data/test/vagrant/actions/box/unpackage_test.rb +101 -0
  61. data/test/vagrant/actions/runner_test.rb +236 -0
  62. data/test/vagrant/actions/vm/destroy_test.rb +24 -0
  63. data/test/vagrant/actions/vm/down_test.rb +32 -0
  64. data/test/vagrant/actions/vm/export_test.rb +88 -0
  65. data/test/vagrant/actions/vm/forward_ports_test.rb +50 -0
  66. data/test/vagrant/actions/vm/halt_test.rb +27 -0
  67. data/test/vagrant/actions/vm/import_test.rb +36 -0
  68. data/test/vagrant/actions/vm/move_hard_drive_test.rb +108 -0
  69. data/test/vagrant/actions/vm/package_test.rb +155 -0
  70. data/test/vagrant/actions/vm/provision_test.rb +103 -0
  71. data/test/vagrant/actions/vm/reload_test.rb +44 -0
  72. data/test/vagrant/actions/vm/resume_test.rb +27 -0
  73. data/test/vagrant/actions/vm/shared_folders_test.rb +117 -0
  74. data/test/vagrant/actions/vm/start_test.rb +55 -0
  75. data/test/vagrant/actions/vm/suspend_test.rb +27 -0
  76. data/test/vagrant/actions/vm/up_test.rb +76 -0
  77. data/test/vagrant/box_test.rb +92 -0
  78. data/test/vagrant/busy_test.rb +81 -0
  79. data/test/vagrant/commands_test.rb +252 -0
  80. data/test/vagrant/config_test.rb +123 -0
  81. data/test/vagrant/downloaders/base_test.rb +20 -0
  82. data/test/vagrant/downloaders/file_test.rb +32 -0
  83. data/test/vagrant/downloaders/http_test.rb +40 -0
  84. data/test/vagrant/env_test.rb +293 -0
  85. data/test/vagrant/ssh_test.rb +95 -0
  86. data/test/vagrant/util_test.rb +64 -0
  87. data/test/vagrant/vm_test.rb +96 -0
  88. metadata +263 -0
@@ -0,0 +1,13 @@
1
+ module Vagrant
2
+ module Downloaders
3
+ # Represents a base class for a downloader. A downloader handles
4
+ # downloading a box file to a temporary file.
5
+ class Base
6
+ include Vagrant::Util
7
+
8
+ # Downloads the source file to the destination file. It is up to
9
+ # implementors of this class to handle the logic.
10
+ def download!(source_url, destination_file); end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module Vagrant
2
+ module Downloaders
3
+ # "Downloads" a file to a temporary file. Basically, this downloader
4
+ # simply does a file copy.
5
+ class File < Base
6
+ BUFFERSIZE = 1048576 # 1 MB
7
+
8
+ def download!(source_url, destination_file)
9
+ # For now we read the contents of one into a buffer
10
+ # and copy it into the other. In the future, we should do
11
+ # a system-level file copy (FileUtils.cp).
12
+ open(source_url) do |f|
13
+ loop do
14
+ break if f.eof?
15
+ destination_file.write(f.read(BUFFERSIZE))
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,47 @@
1
+ module Vagrant
2
+ module Downloaders
3
+ # Downloads a file from an HTTP URL to a temporary file. This
4
+ # downloader reports its progress to stdout while downloading.
5
+ class HTTP < Base
6
+ # ANSI escape code to clear lines from cursor to end of line
7
+ CL_RESET = "\r\e[0K"
8
+
9
+ def download!(source_url, destination_file)
10
+ Net::HTTP.get_response(URI.parse(source_url)) do |response|
11
+ total = response.content_length
12
+ progress = 0
13
+ segment_count = 0
14
+
15
+ response.read_body do |segment|
16
+ # Report the progress out
17
+ progress += segment.length
18
+ segment_count += 1
19
+
20
+ # Progress reporting is limited to every 25 segments just so
21
+ # we're not constantly updating
22
+ if segment_count % 25 == 0
23
+ report_progress(progress, total)
24
+ segment_count = 0
25
+ end
26
+
27
+ # Store the segment
28
+ destination_file.write(segment)
29
+ end
30
+ end
31
+
32
+ complete_progress
33
+ end
34
+
35
+ def report_progress(progress, total)
36
+ percent = (progress.to_f / total.to_f) * 100
37
+ print "#{CL_RESET}Download Progress: #{percent.to_i}% (#{progress} / #{total})"
38
+ $stdout.flush
39
+ end
40
+
41
+ def complete_progress
42
+ # Just clear the line back out
43
+ print "#{CL_RESET}"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,140 @@
1
+ module Vagrant
2
+ class Env
3
+ ROOTFILE_NAME = "Vagrantfile"
4
+ HOME_SUBDIRS = ["tmp", "boxes"]
5
+
6
+ # Initialize class variables used
7
+ @@persisted_vm = nil
8
+ @@root_path = nil
9
+ @@box = nil
10
+
11
+ extend Vagrant::Util
12
+
13
+ class << self
14
+ def box; @@box; end
15
+ def persisted_vm; @@persisted_vm; end
16
+ def root_path; @@root_path; end
17
+ def dotfile_path;File.join(root_path, Vagrant.config.vagrant.dotfile_name); end
18
+ def home_path; File.expand_path(Vagrant.config.vagrant.home); end
19
+ def tmp_path; File.join(home_path, "tmp"); end
20
+ def boxes_path; File.join(home_path, "boxes"); end
21
+
22
+ def load!(opts={})
23
+ load_root_path!(Pathname.new(Dir.pwd), opts)
24
+ load_config!
25
+ load_home_directory!
26
+ load_box!
27
+ load_vm!
28
+ end
29
+
30
+ def load_config!
31
+ # Prepare load paths for config files
32
+ load_paths = [File.join(PROJECT_ROOT, "config", "default.rb")]
33
+ load_paths << File.join(box.directory, ROOTFILE_NAME) if box
34
+ load_paths << File.join(root_path, ROOTFILE_NAME) if root_path
35
+
36
+ # Then clear out the old data
37
+ Config.reset!
38
+
39
+ load_paths.each do |path|
40
+ logger.info "Loading config from #{path}..."
41
+ load path if File.exist?(path)
42
+ end
43
+
44
+ # Execute the configurations
45
+ Config.execute!
46
+ end
47
+
48
+ def load_home_directory!
49
+ home_dir = File.expand_path(Vagrant.config.vagrant.home)
50
+
51
+ dirs = HOME_SUBDIRS.collect { |path| File.join(home_dir, path) }
52
+ dirs.unshift(home_dir)
53
+
54
+ dirs.each do |dir|
55
+ next if File.directory?(dir)
56
+
57
+ logger.info "Creating home directory since it doesn't exist: #{dir}"
58
+ FileUtils.mkdir_p(dir)
59
+ end
60
+ end
61
+
62
+ def load_box!
63
+ @@box = Box.find(Vagrant.config.vm.box) if Vagrant.config.vm.box
64
+
65
+ if @@box
66
+ logger.info("Reloading configuration to account for loaded box...")
67
+ load_config!
68
+ end
69
+ end
70
+
71
+ def load_vm!
72
+ return unless root_path
73
+
74
+ File.open(dotfile_path) do |f|
75
+ @@persisted_vm = Vagrant::VM.find(f.read)
76
+ end
77
+ rescue Errno::ENOENT
78
+ @@persisted_vm = nil
79
+ end
80
+
81
+ def persist_vm(vm)
82
+ File.open(dotfile_path, 'w+') do |f|
83
+ f.write(vm.uuid)
84
+ end
85
+ end
86
+
87
+ def load_root_path!(path=Pathname.new(Dir.pwd), opts={})
88
+ if path.to_s == '/'
89
+ return false if opts[:suppress_errors]
90
+ error_and_exit(<<-msg)
91
+ A `#{ROOTFILE_NAME}` was not found! This file is required for vagrant to run
92
+ since it describes the expected environment that vagrant is supposed
93
+ to manage. Please create a #{ROOTFILE_NAME} and place it in your project
94
+ root.
95
+ msg
96
+ return
97
+ end
98
+
99
+ file = "#{path}/#{ROOTFILE_NAME}"
100
+ if File.exist?(file)
101
+ @@root_path = path.to_s
102
+ return true
103
+ end
104
+
105
+ load_root_path!(path.parent, opts)
106
+ end
107
+
108
+ def require_box
109
+ if !box
110
+ if !Vagrant.config.vm.box
111
+ error_and_exit(<<-msg)
112
+ No base box was specified! A base box is required as a staring point
113
+ for every vagrant virtual machine. Please specify one in your Vagrantfile
114
+ using `config.vm.box`
115
+ msg
116
+ else
117
+ error_and_exit(<<-msg)
118
+ Specified box `#{Vagrant.config.vm.box}` does not exist!
119
+
120
+ The box must be added through the `vagrant box add` command. Please view
121
+ the documentation associated with the command for more information.
122
+ msg
123
+ end
124
+ end
125
+ end
126
+
127
+ def require_persisted_vm
128
+ if !persisted_vm
129
+ error_and_exit(<<-error)
130
+ The task you're trying to run requires that the vagrant environment
131
+ already be created, but unfortunately this vagrant still appears to
132
+ have no box! You can setup the environment by setting up your
133
+ #{ROOTFILE_NAME} and running `vagrant up`
134
+ error
135
+ return
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,43 @@
1
+ module Vagrant
2
+ class SSH
3
+ SCRIPT = File.join(File.dirname(__FILE__), '..', '..', 'script', 'vagrant-ssh-expect.sh')
4
+
5
+ class << self
6
+ def connect(opts={})
7
+ options = {}
8
+ [:host, :password, :username].each do |param|
9
+ options[param] = opts[param] || Vagrant.config.ssh.send(param)
10
+ end
11
+
12
+ Kernel.exec "#{SCRIPT} #{options[:username]} #{options[:password]} #{options[:host]} #{port(opts)}".strip
13
+ end
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|
17
+ yield ssh
18
+ end
19
+ end
20
+
21
+ def upload!(from, to)
22
+ execute do |ssh|
23
+ scp = Net::SCP.new(ssh)
24
+ scp.upload!(from, to)
25
+ end
26
+ end
27
+
28
+ def up?
29
+ Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => port, :password => Vagrant.config.ssh.password, :timeout => 5) do |ssh|
30
+ return true
31
+ end
32
+
33
+ false
34
+ rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
35
+ false
36
+ end
37
+
38
+ def port(opts={})
39
+ opts[:port] || Vagrant.config.vm.forwarded_ports[Vagrant.config.ssh.forwarded_port_key][:hostport]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ module Vagrant
2
+ module Util
3
+ def self.included(base)
4
+ base.extend Vagrant::Util
5
+ end
6
+
7
+ def error_and_exit(error)
8
+ abort <<-error
9
+ =====================================================================
10
+ Vagrant experienced an error!
11
+
12
+ #{error.chomp}
13
+ =====================================================================
14
+ error
15
+ end
16
+
17
+ def logger
18
+ Logger.singleton_logger
19
+ end
20
+ end
21
+
22
+ class Logger < ::Logger
23
+ @@singleton_logger = nil
24
+
25
+ class << self
26
+ def singleton_logger
27
+ # TODO: Buffer messages until config is loaded, then output them?
28
+ if Vagrant.config.loaded?
29
+ @@singleton_logger ||= Vagrant::Logger.new(Vagrant.config.vagrant.log_output)
30
+ else
31
+ Vagrant::Logger.new(nil)
32
+ end
33
+ end
34
+
35
+ def reset_logger!
36
+ @@singleton_logger = nil
37
+ end
38
+ end
39
+
40
+ def format_message(level, time, progname, msg)
41
+ "[#{level} #{time.strftime('%m-%d-%Y %X')}] Vagrant: #{msg}\n"
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,57 @@
1
+ module Vagrant
2
+ class VM < Actions::Runner
3
+ include Vagrant::Util
4
+
5
+ attr_accessor :vm
6
+ attr_accessor :from
7
+
8
+ class << self
9
+ # Finds a virtual machine by a given UUID and either returns
10
+ # a Vagrant::VM object or returns nil.
11
+ def find(uuid)
12
+ vm = VirtualBox::VM.find(uuid)
13
+ return nil if vm.nil?
14
+ new(vm)
15
+ end
16
+ end
17
+
18
+ def initialize(vm=nil)
19
+ @vm = vm
20
+ end
21
+
22
+ def package(out_path, include_files=[])
23
+ add_action(Actions::VM::Export)
24
+ add_action(Actions::VM::Package, out_path, include_files)
25
+ execute!
26
+ end
27
+
28
+ def start
29
+ return if @vm.running?
30
+
31
+ actions = [Actions::VM::ForwardPorts, Actions::VM::SharedFolders, Actions::VM::Start]
32
+ actions.each do |action|
33
+ add_action(action)
34
+ end
35
+
36
+ execute!
37
+ end
38
+
39
+ def destroy
40
+ execute!(Actions::VM::Down)
41
+ end
42
+
43
+ def suspend
44
+ execute!(Actions::VM::Suspend)
45
+ end
46
+
47
+ def resume
48
+ execute!(Actions::VM::Resume)
49
+ end
50
+
51
+ def saved?
52
+ @vm.saved?
53
+ end
54
+
55
+ def powered_off?; @vm.powered_off? end
56
+ end
57
+ end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/expect
2
+
3
+ set uname [lrange $argv 0 0]
4
+ set password [lrange $argv 1 1]
5
+ set host [lrange $argv 2 2]
6
+ set port [lrange $argv 3 3]
7
+
8
+ if { $port != "" } {
9
+ set port_option "-p $port"
10
+ } else {
11
+ set port_option ""
12
+ }
13
+
14
+ spawn ssh $port_option -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $uname@$host
15
+
16
+ expect "*password: " {
17
+ send "$password\r"
18
+ } timeout {
19
+ send_user "Error connecting"
20
+ }
21
+
22
+ interact
@@ -0,0 +1,8 @@
1
+ Vagrant::Config.run do |config|
2
+ # All Vagrant configuration is done here. For a detailed explanation
3
+ # and listing of configuration options, please check the documentation
4
+ # online.
5
+
6
+ # Every Vagrant virtual environment requires a box to build off of.
7
+ config.vm.box = "base"
8
+ end
@@ -0,0 +1,91 @@
1
+ begin
2
+ require File.expand_path('../.bundle/environment', __FILE__)
3
+ rescue LoadError
4
+ # Fallback on doing the resolve at runtime.
5
+ require "rubygems"
6
+ require "bundler"
7
+ Bundler.setup
8
+ end
9
+
10
+ # ruby-debug, not necessary, but useful if we have it
11
+ begin
12
+ require 'ruby-debug'
13
+ rescue LoadError; end
14
+
15
+
16
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'vagrant')
17
+ require 'contest'
18
+ require 'mocha'
19
+
20
+ class Test::Unit::TestCase
21
+ # Clears the previous config and sets up the new config
22
+ def mock_config
23
+ Vagrant::Config.instance_variable_set(:@config_runners, nil)
24
+ Vagrant::Config.instance_variable_set(:@config, nil)
25
+
26
+ Vagrant::Config.run do |config|
27
+ config.vagrant.dotfile_name = ".hobo"
28
+
29
+ config.ssh.username = "foo"
30
+ config.ssh.password = "bar"
31
+ config.ssh.host = "baz"
32
+ config.ssh.forwarded_port_key = "ssh"
33
+ config.ssh.max_tries = 10
34
+
35
+ config.vm.box = "foo"
36
+ config.vm.box_ovf = "box.ovf"
37
+ config.vm.base_mac = "42"
38
+ config.vm.project_directory = "/hobo"
39
+ config.vm.disk_image_format = 'VMDK'
40
+ config.vm.forward_port("ssh", 22, 2222)
41
+
42
+ config.package.name = 'vagrant'
43
+ config.package.extension = '.box'
44
+
45
+ config.chef.cookbooks_path = "cookbooks"
46
+ config.chef.provisioning_path = "/tmp/hobo-chef"
47
+ config.chef.json = {
48
+ :recipes => ["hobo_main"]
49
+ }
50
+
51
+ config.vagrant.home = '~/.home'
52
+ end
53
+
54
+ if block_given?
55
+ Vagrant::Config.run do |config|
56
+ yield config
57
+ end
58
+ end
59
+
60
+ if block_given?
61
+ Vagrant::Config.run do |config|
62
+ yield config
63
+ end
64
+ end
65
+
66
+ Vagrant::Config.execute!
67
+ end
68
+
69
+ # Sets up the mocks and instantiates an action for testing
70
+ def mock_action(action_klass, *args)
71
+ vm = mock("vboxvm")
72
+ mock_vm = mock("vm")
73
+ action = action_klass.new(mock_vm, *args)
74
+
75
+ mock_vm.stubs(:vm).returns(vm)
76
+ mock_vm.stubs(:vm=)
77
+ mock_vm.stubs(:invoke_callback)
78
+ mock_vm.stubs(:invoke_around_callback).yields
79
+ mock_vm.stubs(:actions).returns([action])
80
+
81
+ [mock_vm, vm, action]
82
+ end
83
+
84
+ # Sets up the mocks and stubs for a downloader
85
+ def mock_downloader(downloader_klass)
86
+ tempfile = mock("tempfile")
87
+ tempfile.stubs(:write)
88
+
89
+ [downloader_klass.new, tempfile]
90
+ end
91
+ end