vagrant 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. data/.gitignore +1 -0
  2. data/.yardopts +1 -0
  3. data/CHANGELOG.md +56 -0
  4. data/Gemfile +14 -3
  5. data/Gemfile.lock +38 -11
  6. data/README.md +1 -1
  7. data/bin/vagrant +20 -5
  8. data/config/default.rb +6 -8
  9. data/lib/vagrant.rb +40 -13
  10. data/lib/vagrant/action.rb +56 -16
  11. data/lib/vagrant/action/box/destroy.rb +3 -1
  12. data/lib/vagrant/action/box/download.rb +8 -13
  13. data/lib/vagrant/action/box/unpackage.rb +8 -11
  14. data/lib/vagrant/action/box/verify.rb +3 -3
  15. data/lib/vagrant/action/builder.rb +3 -30
  16. data/lib/vagrant/action/builtin.rb +6 -1
  17. data/lib/vagrant/action/environment.rb +14 -62
  18. data/lib/vagrant/action/general/package.rb +29 -22
  19. data/lib/vagrant/action/vm/boot.rb +5 -12
  20. data/lib/vagrant/action/vm/check_box.rb +4 -4
  21. data/lib/vagrant/action/vm/check_guest_additions.rb +4 -6
  22. data/lib/vagrant/action/vm/clear_forwarded_ports.rb +2 -2
  23. data/lib/vagrant/action/vm/clear_nfs_exports.rb +1 -1
  24. data/lib/vagrant/action/vm/clear_shared_folders.rb +1 -1
  25. data/lib/vagrant/action/vm/customize.rb +1 -1
  26. data/lib/vagrant/action/vm/destroy.rb +1 -2
  27. data/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb +1 -1
  28. data/lib/vagrant/action/vm/disable_networks.rb +11 -9
  29. data/lib/vagrant/action/vm/discard_state.rb +2 -2
  30. data/lib/vagrant/action/vm/export.rb +10 -11
  31. data/lib/vagrant/action/vm/forward_ports.rb +21 -9
  32. data/lib/vagrant/action/vm/halt.rb +3 -8
  33. data/lib/vagrant/action/vm/import.rb +16 -14
  34. data/lib/vagrant/action/vm/match_mac_address.rb +1 -1
  35. data/lib/vagrant/action/vm/network.rb +9 -16
  36. data/lib/vagrant/action/vm/nfs.rb +14 -18
  37. data/lib/vagrant/action/vm/provision.rb +5 -5
  38. data/lib/vagrant/action/vm/resume.rb +1 -1
  39. data/lib/vagrant/action/vm/share_folders.rb +6 -44
  40. data/lib/vagrant/action/vm/suspend.rb +1 -1
  41. data/lib/vagrant/action/warden.rb +74 -0
  42. data/lib/vagrant/box.rb +18 -82
  43. data/lib/vagrant/box_collection.rb +47 -0
  44. data/lib/vagrant/cli.rb +55 -0
  45. data/lib/vagrant/command/base.rb +106 -0
  46. data/lib/vagrant/command/box.rb +33 -0
  47. data/lib/vagrant/command/destroy.rb +17 -0
  48. data/lib/vagrant/command/group_base.rb +99 -0
  49. data/lib/vagrant/command/halt.rb +18 -0
  50. data/lib/vagrant/command/helpers.rb +33 -0
  51. data/lib/vagrant/command/init.rb +14 -0
  52. data/lib/vagrant/command/named_base.rb +14 -0
  53. data/lib/vagrant/command/package.rb +41 -0
  54. data/lib/vagrant/command/provision.rb +17 -0
  55. data/lib/vagrant/command/reload.rb +17 -0
  56. data/lib/vagrant/command/resume.rb +17 -0
  57. data/lib/vagrant/command/ssh.rb +41 -0
  58. data/lib/vagrant/command/ssh_config.rb +21 -0
  59. data/lib/vagrant/command/status.rb +23 -0
  60. data/lib/vagrant/command/suspend.rb +17 -0
  61. data/lib/vagrant/command/up.rb +20 -0
  62. data/lib/vagrant/command/upgrade_to_060.rb +45 -0
  63. data/lib/vagrant/command/version.rb +13 -0
  64. data/lib/vagrant/config.rb +107 -189
  65. data/lib/vagrant/config/base.rb +67 -0
  66. data/lib/vagrant/config/error_recorder.rb +19 -0
  67. data/lib/vagrant/config/nfs.rb +10 -0
  68. data/lib/vagrant/config/package.rb +9 -0
  69. data/lib/vagrant/config/ssh.rb +28 -0
  70. data/lib/vagrant/config/vagrant.rb +21 -0
  71. data/lib/vagrant/config/vm.rb +111 -0
  72. data/lib/vagrant/data_store.rb +68 -0
  73. data/lib/vagrant/downloaders/file.rb +3 -3
  74. data/lib/vagrant/downloaders/http.rb +5 -5
  75. data/lib/vagrant/environment.rb +246 -243
  76. data/lib/vagrant/errors.rb +306 -0
  77. data/lib/vagrant/hosts/base.rb +1 -1
  78. data/lib/vagrant/hosts/bsd.rb +3 -9
  79. data/lib/vagrant/hosts/linux.rb +3 -9
  80. data/lib/vagrant/plugin.rb +50 -0
  81. data/lib/vagrant/provisioners/base.rb +0 -6
  82. data/lib/vagrant/provisioners/chef.rb +63 -58
  83. data/lib/vagrant/provisioners/chef_server.rb +9 -11
  84. data/lib/vagrant/provisioners/chef_solo.rb +2 -2
  85. data/lib/vagrant/ssh.rb +34 -37
  86. data/lib/vagrant/systems/base.rb +0 -13
  87. data/lib/vagrant/systems/linux.rb +10 -33
  88. data/lib/vagrant/systems/solaris.rb +59 -0
  89. data/lib/vagrant/test_helpers.rb +109 -0
  90. data/lib/vagrant/ui.rb +65 -0
  91. data/lib/vagrant/util.rb +9 -19
  92. data/lib/vagrant/util/glob_loader.rb +19 -17
  93. data/lib/vagrant/util/hash_with_indifferent_access.rb +63 -0
  94. data/lib/vagrant/util/plain_logger.rb +2 -0
  95. data/lib/vagrant/util/platform.rb +2 -0
  96. data/lib/vagrant/util/resource_logger.rb +5 -70
  97. data/lib/vagrant/util/retryable.rb +25 -0
  98. data/lib/vagrant/util/template_renderer.rb +1 -1
  99. data/lib/vagrant/version.rb +1 -1
  100. data/lib/vagrant/vm.rb +27 -13
  101. data/templates/commands/init/Vagrantfile.erb +13 -0
  102. data/templates/config/validation_failed.erb +7 -0
  103. data/templates/locales/en.yml +402 -0
  104. data/templates/package_Vagrantfile.erb +1 -1
  105. data/test/locales/en.yml +8 -0
  106. data/test/test_helper.rb +19 -103
  107. data/test/vagrant/action/box/destroy_test.rb +7 -19
  108. data/test/vagrant/action/box/download_test.rb +9 -25
  109. data/test/vagrant/action/box/package_test.rb +2 -2
  110. data/test/vagrant/action/box/unpackage_test.rb +8 -34
  111. data/test/vagrant/action/box/verify_test.rb +10 -19
  112. data/test/vagrant/action/builder_test.rb +0 -15
  113. data/test/vagrant/action/env/set_test.rb +1 -1
  114. data/test/vagrant/action/environment_test.rb +8 -26
  115. data/test/vagrant/action/general/package_test.rb +53 -53
  116. data/test/vagrant/action/vm/boot_test.rb +5 -22
  117. data/test/vagrant/action/vm/check_box_test.rb +35 -25
  118. data/test/vagrant/action/vm/clean_machine_folder_test.rb +1 -1
  119. data/test/vagrant/action/vm/clear_forwarded_ports_test.rb +1 -1
  120. data/test/vagrant/action/vm/clear_nfs_exports_test.rb +1 -1
  121. data/test/vagrant/action/vm/clear_shared_folders_test.rb +1 -1
  122. data/test/vagrant/action/vm/customize_test.rb +2 -1
  123. data/test/vagrant/action/vm/destroy_test.rb +1 -2
  124. data/test/vagrant/action/vm/destroy_unused_network_interfaces_test.rb +1 -1
  125. data/test/vagrant/action/vm/disable_networks_test.rb +10 -1
  126. data/test/vagrant/action/vm/discard_state_test.rb +10 -1
  127. data/test/vagrant/action/vm/export_test.rb +9 -37
  128. data/test/vagrant/action/vm/forward_ports_helpers_test.rb +2 -2
  129. data/test/vagrant/action/vm/forward_ports_test.rb +19 -16
  130. data/test/vagrant/action/vm/halt_test.rb +11 -1
  131. data/test/vagrant/action/vm/import_test.rb +37 -21
  132. data/test/vagrant/action/vm/match_mac_address_test.rb +1 -1
  133. data/test/vagrant/action/vm/network_test.rb +8 -7
  134. data/test/vagrant/action/vm/nfs_helpers_test.rb +6 -3
  135. data/test/vagrant/action/vm/nfs_test.rb +20 -45
  136. data/test/vagrant/action/vm/package_test.rb +1 -1
  137. data/test/vagrant/action/vm/package_vagrantfile_test.rb +1 -1
  138. data/test/vagrant/action/vm/provision_test.rb +10 -17
  139. data/test/vagrant/action/vm/resume_test.rb +1 -1
  140. data/test/vagrant/action/vm/share_folders_test.rb +25 -106
  141. data/test/vagrant/action/vm/suspend_test.rb +1 -1
  142. data/test/vagrant/action/warden_test.rb +105 -0
  143. data/test/vagrant/action_test.rb +5 -27
  144. data/test/vagrant/box_collection_test.rb +44 -0
  145. data/test/vagrant/box_test.rb +5 -105
  146. data/test/vagrant/cli_test.rb +35 -0
  147. data/test/vagrant/command/base_test.rb +23 -0
  148. data/test/vagrant/command/group_base_test.rb +15 -0
  149. data/test/vagrant/command/helpers_test.rb +88 -0
  150. data/test/vagrant/config/base_test.rb +52 -0
  151. data/test/vagrant/config/error_recorder_test.rb +18 -0
  152. data/test/vagrant/config/ssh_test.rb +12 -0
  153. data/test/vagrant/config/vagrant_test.rb +11 -0
  154. data/test/vagrant/config/vm_test.rb +70 -0
  155. data/test/vagrant/config_test.rb +113 -206
  156. data/test/vagrant/data_store_test.rb +68 -0
  157. data/test/vagrant/downloaders/base_test.rb +1 -1
  158. data/test/vagrant/downloaders/file_test.rb +4 -3
  159. data/test/vagrant/downloaders/http_test.rb +14 -4
  160. data/test/vagrant/environment_test.rb +290 -590
  161. data/test/vagrant/errors_test.rb +42 -0
  162. data/test/vagrant/hosts/base_test.rb +1 -1
  163. data/test/vagrant/hosts/bsd_test.rb +3 -6
  164. data/test/vagrant/hosts/linux_test.rb +3 -5
  165. data/test/vagrant/plugin_test.rb +9 -0
  166. data/test/vagrant/provisioners/base_test.rb +1 -1
  167. data/test/vagrant/provisioners/chef_server_test.rb +31 -35
  168. data/test/vagrant/provisioners/chef_solo_test.rb +1 -1
  169. data/test/vagrant/provisioners/chef_test.rb +7 -7
  170. data/test/vagrant/ssh_session_test.rb +3 -10
  171. data/test/vagrant/ssh_test.rb +25 -33
  172. data/test/vagrant/systems/linux_test.rb +6 -71
  173. data/test/vagrant/ui_test.rb +29 -0
  174. data/test/vagrant/util/hash_with_indifferent_access_test.rb +39 -0
  175. data/test/vagrant/util/resource_logger_test.rb +14 -81
  176. data/test/vagrant/util/retryable_test.rb +38 -0
  177. data/test/vagrant/util/template_renderer_test.rb +4 -4
  178. data/test/vagrant/vm_test.rb +47 -26
  179. data/vagrant.gemspec +14 -12
  180. metadata +142 -108
  181. data/bin/.gitignore +0 -0
  182. data/lib/vagrant/action/action_exception.rb +0 -16
  183. data/lib/vagrant/action/env/error_halt.rb +0 -16
  184. data/lib/vagrant/action/exception_catcher.rb +0 -14
  185. data/lib/vagrant/action/vm/persist.rb +0 -22
  186. data/lib/vagrant/active_list.rb +0 -83
  187. data/lib/vagrant/command.rb +0 -27
  188. data/lib/vagrant/commands/base.rb +0 -181
  189. data/lib/vagrant/commands/box.rb +0 -16
  190. data/lib/vagrant/commands/box/add.rb +0 -30
  191. data/lib/vagrant/commands/box/list.rb +0 -30
  192. data/lib/vagrant/commands/box/remove.rb +0 -30
  193. data/lib/vagrant/commands/box/repackage.rb +0 -35
  194. data/lib/vagrant/commands/destroy.rb +0 -37
  195. data/lib/vagrant/commands/halt.rb +0 -43
  196. data/lib/vagrant/commands/init.rb +0 -36
  197. data/lib/vagrant/commands/package.rb +0 -81
  198. data/lib/vagrant/commands/provision.rb +0 -31
  199. data/lib/vagrant/commands/reload.rb +0 -36
  200. data/lib/vagrant/commands/resume.rb +0 -35
  201. data/lib/vagrant/commands/ssh.rb +0 -78
  202. data/lib/vagrant/commands/ssh_config.rb +0 -45
  203. data/lib/vagrant/commands/status.rb +0 -125
  204. data/lib/vagrant/commands/suspend.rb +0 -36
  205. data/lib/vagrant/commands/up.rb +0 -44
  206. data/lib/vagrant/exceptions/uncallable_action.rb +0 -17
  207. data/lib/vagrant/util/translator.rb +0 -35
  208. data/templates/strings.yml +0 -341
  209. data/templates/unison/crontab_entry.erb +0 -1
  210. data/templates/unison/script.erb +0 -71
  211. data/test/vagrant/action/env/error_halt_test.rb +0 -21
  212. data/test/vagrant/action/exception_catcher_test.rb +0 -30
  213. data/test/vagrant/action/vm/persist_test.rb +0 -50
  214. data/test/vagrant/active_list_test.rb +0 -173
  215. data/test/vagrant/command_test.rb +0 -53
  216. data/test/vagrant/commands/base_test.rb +0 -139
  217. data/test/vagrant/commands/box/add_test.rb +0 -34
  218. data/test/vagrant/commands/box/list_test.rb +0 -32
  219. data/test/vagrant/commands/box/remove_test.rb +0 -41
  220. data/test/vagrant/commands/box/repackage_test.rb +0 -52
  221. data/test/vagrant/commands/destroy_test.rb +0 -44
  222. data/test/vagrant/commands/halt_test.rb +0 -50
  223. data/test/vagrant/commands/init_test.rb +0 -71
  224. data/test/vagrant/commands/package_test.rb +0 -97
  225. data/test/vagrant/commands/provision_test.rb +0 -60
  226. data/test/vagrant/commands/reload_test.rb +0 -47
  227. data/test/vagrant/commands/resume_test.rb +0 -44
  228. data/test/vagrant/commands/ssh_config_test.rb +0 -77
  229. data/test/vagrant/commands/ssh_test.rb +0 -129
  230. data/test/vagrant/commands/status_test.rb +0 -40
  231. data/test/vagrant/commands/suspend_test.rb +0 -44
  232. data/test/vagrant/commands/up_test.rb +0 -49
  233. data/test/vagrant/util/translator_test.rb +0 -61
  234. data/test/vagrant/util_test.rb +0 -27
@@ -12,8 +12,8 @@ module Vagrant
12
12
  def call(env)
13
13
  @app.call(env)
14
14
 
15
- if !env.error? && provisioning_enabled?
16
- @env.logger.info "Beginning provisioning process..."
15
+ if provisioning_enabled?
16
+ @env.ui.info I18n.t("vagrant.actions.vm.provision.beginning")
17
17
  @provisioner.provision!
18
18
  end
19
19
  end
@@ -27,7 +27,7 @@ module Vagrant
27
27
 
28
28
  if provisioner.is_a?(Class)
29
29
  @provisioner = provisioner.new(@env)
30
- return @env.error!(:provisioner_invalid_class) unless @provisioner.is_a?(Provisioners::Base)
30
+ raise Errors::ProvisionInvalidClass.new if !@provisioner.is_a?(Provisioners::Base)
31
31
  elsif provisioner.is_a?(Symbol)
32
32
  # We have a few hard coded provisioners for built-ins
33
33
  mapping = {
@@ -36,11 +36,11 @@ module Vagrant
36
36
  }
37
37
 
38
38
  provisioner_klass = mapping[provisioner]
39
- return @env.error!(:provisioner_unknown_type, :provisioner => provisioner.to_s) if provisioner_klass.nil?
39
+ raise Errors::ProvisionUnknownType.new(:provisioner => provisioner.to_s) if provisioner_klass.nil?
40
40
  @provisioner = provisioner_klass.new(@env)
41
41
  end
42
42
 
43
- @env.logger.info "Provisioning enabled with #{@provisioner.class}"
43
+ @env.ui.info I18n.t("vagrant.actions.vm.provision.enabled", :provisioner => @provisioner.class.to_s)
44
44
  @provisioner.prepare
45
45
  @provisioner
46
46
  end
@@ -8,7 +8,7 @@ module Vagrant
8
8
 
9
9
  def call(env)
10
10
  if env["vm"].vm.saved?
11
- env.logger.info "Resuming suspended VM..."
11
+ env.ui.info I18n.t("vagrant.actions.vm.resume.resuming")
12
12
  env["actions"].run(Boot)
13
13
  end
14
14
 
@@ -2,8 +2,6 @@ module Vagrant
2
2
  class Action
3
3
  module VM
4
4
  class ShareFolders
5
- include ExceptionCatcher
6
-
7
5
  def initialize(app, env)
8
6
  @app = app
9
7
  @env = env
@@ -16,14 +14,7 @@ module Vagrant
16
14
 
17
15
  @app.call(env)
18
16
 
19
- if !env.error?
20
- catch_action_exception(env) do
21
- # Only mount and setup shared folders in the absense of an
22
- # error
23
- mount_shared_folders
24
- setup_unison
25
- end
26
- end
17
+ mount_shared_folders
27
18
  end
28
19
 
29
20
  # This method returns an actual list of VirtualBox shared
@@ -36,31 +27,13 @@ module Vagrant
36
27
 
37
28
  # This to prevent overwriting the actual shared folders data
38
29
  value = value.dup
39
-
40
- if value[:sync]
41
- # Syncing this folder. Change the guestpath to reflect
42
- # what we're actually mounting.
43
- value[:original] = value.dup
44
- value[:guestpath] = "#{value[:guestpath]}#{@env.env.config.unison.folder_suffix}"
45
- end
46
-
47
30
  acc[key] = value
48
31
  acc
49
32
  end
50
33
  end
51
34
 
52
- # This method returns the list of shared folders which are to
53
- # be synced via unison.
54
- def unison_folders
55
- shared_folders.inject({}) do |acc, data|
56
- key, value = data
57
- acc[key] = value if !!value[:sync]
58
- acc
59
- end
60
- end
61
-
62
35
  def create_metadata
63
- @env.logger.info "Creating shared folders metadata..."
36
+ @env.ui.info I18n.t("vagrant.actions.vm.share_folders.creating")
64
37
 
65
38
  shared_folders.each do |name, data|
66
39
  folder = VirtualBox::SharedFolder.new
@@ -73,28 +46,17 @@ module Vagrant
73
46
  end
74
47
 
75
48
  def mount_shared_folders
76
- @env.logger.info "Mounting shared folders..."
49
+ @env.ui.info I18n.t("vagrant.actions.vm.share_folders.mounting")
77
50
 
78
51
  @env["vm"].ssh.execute do |ssh|
79
52
  shared_folders.each do |name, data|
80
- @env.logger.info "-- #{name}: #{data[:guestpath]}"
53
+ @env.ui.info(I18n.t("vagrant.actions.vm.share_folders.mounting_entry",
54
+ :name => name,
55
+ :guest_path => data[:guestpath]))
81
56
  @env["vm"].system.mount_shared_folder(ssh, name, data[:guestpath])
82
57
  end
83
58
  end
84
59
  end
85
-
86
- def setup_unison
87
- return if unison_folders.empty?
88
-
89
- @env["vm"].ssh.execute do |ssh|
90
- @env["vm"].system.prepare_unison(ssh)
91
-
92
- @env.logger.info "Creating unison crontab entries..."
93
- unison_folders.each do |name, data|
94
- @env["vm"].system.create_unison(ssh, data)
95
- end
96
- end
97
- end
98
60
  end
99
61
  end
100
62
  end
@@ -8,7 +8,7 @@ module Vagrant
8
8
 
9
9
  def call(env)
10
10
  if env["vm"].vm.running?
11
- env.logger.info "Saving VM state and suspending execution..."
11
+ env.ui.info I18n.t("vagrant.actions.vm.suspend.suspending")
12
12
  env["vm"].vm.save_state
13
13
  end
14
14
 
@@ -0,0 +1,74 @@
1
+ module Vagrant
2
+ class Action
3
+ # The action warden is a middleware which injects itself between
4
+ # every other middleware, watching for exceptions which are raised
5
+ # and performing proper cleanup on every action by calling the `recover`
6
+ # method. The warden therefore allows middlewares to not worry about
7
+ # exceptional events, and by providing a simple callback, can clean up
8
+ # in any erroneous case.
9
+ #
10
+ # Except for those who are curious about the internal workings of Vagrant,
11
+ # Warden will "just work" behind the scenes.
12
+ class Warden
13
+ attr_accessor :actions, :stack
14
+
15
+ def initialize(actions, env)
16
+ @stack = []
17
+ @actions = actions.map { |m| finalize_action(m, env) }
18
+ end
19
+
20
+ def call(env)
21
+ return if @actions.empty?
22
+
23
+ begin
24
+ # Call the next middleware in the sequence, appending to the stack
25
+ # of "recoverable" middlewares in case something goes wrong!
26
+ raise Errors::VagrantInterrupt.new if env.interrupted?
27
+ @stack.unshift(@actions.shift).first.call(env)
28
+ raise Errors::VagrantInterrupt.new if env.interrupted?
29
+ rescue Exception => e
30
+ env["vagrant.error"] = e
31
+
32
+ # Something went horribly wrong. Start the rescue chain then
33
+ # reraise the exception to properly kick us out of limbo here.
34
+ begin_rescue(env)
35
+ raise
36
+ end
37
+ end
38
+
39
+ # Begins the recovery sequence for all middlewares which have run.
40
+ # It does this by calling `recover` (if it exists) on each middleware
41
+ # which has already run, in reverse order.
42
+ def begin_rescue(env)
43
+ @stack.each do |act|
44
+ act.recover(env) if act.respond_to?(:recover)
45
+ end
46
+
47
+ # Clear stack so that warden down the middleware chain doesn't
48
+ # rescue again.
49
+ @stack.clear
50
+ end
51
+
52
+ # A somewhat confusing function which simply initializes each
53
+ # middleware properly to call the next middleware in the sequence.
54
+ def finalize_action(action, env)
55
+ klass, args, block = action
56
+
57
+ if klass.is_a?(Class)
58
+ # A action klass which is to be instantiated with the
59
+ # app, env, and any arguments given
60
+ klass.new(self, env, *args, &block)
61
+ elsif klass.respond_to?(:call)
62
+ # Make it a lambda which calls the item then forwards
63
+ # up the chain
64
+ lambda do |e|
65
+ klass.call(e)
66
+ self.call(e)
67
+ end
68
+ else
69
+ raise "Invalid action: #{action.inspect}"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
data/lib/vagrant/box.rb CHANGED
@@ -4,42 +4,7 @@ module Vagrant
4
4
  # virtual machine, at the least. They are created with `vagrant package`
5
5
  # and may contain additional files if specified by the creator. This
6
6
  # class serves to help manage these boxes, although most of the logic
7
- # is kicked out to actions.
8
- #
9
- # What can the {Box} class do?
10
- #
11
- # * Find boxes
12
- # * Add existing boxes (from some URI)
13
- # * Delete existing boxes
14
- #
15
- # # Finding Boxes
16
- #
17
- # Using the {Box.find} method, you can search for existing boxes. This
18
- # method will return `nil` if none is found or an instance of {Box}
19
- # otherwise.
20
- #
21
- # box = Vagrant::Box.find("base")
22
- # if box.nil?
23
- # puts "Box not found!"
24
- # else
25
- # puts "Box exists at #{box.directory}"
26
- # end
27
- #
28
- # # Adding a Box
29
- #
30
- # Boxes can be added from any URI. Some schemas aren't supported; if this
31
- # is the case, the error will output to the logger.
32
- #
33
- # Vagrant::Box.add("foo", "http://myfiles.com/foo.box")
34
- #
35
- # # Destroying a box
36
- #
37
- # Boxes can be deleted as well. This method is _final_ and there is no way
38
- # to undo this action once it is completed.
39
- #
40
- # box = Vagrant::Box.find("foo")
41
- # box.destroy
42
- #
7
+ # is kicked out to middlewares.
43
8
  class Box
44
9
  # The name of the box.
45
10
  attr_accessor :name
@@ -50,36 +15,9 @@ module Vagrant
50
15
  # The environment which this box belongs to. Although this could
51
16
  # actually be many environments, this points to the environment
52
17
  # of a specific instance.
53
- attr_accessor :env
18
+ attr_reader :env
54
19
 
55
20
  class << self
56
- # Returns an array of all created boxes, as strings.
57
- #
58
- # @return [Array<String>]
59
- def all(env)
60
- results = []
61
-
62
- Dir.open(env.boxes_path) do |dir|
63
- dir.each do |d|
64
- next if d == "." || d == ".." || !File.directory?(File.join(env.boxes_path, d))
65
- results << d.to_s
66
- end
67
- end
68
-
69
- results
70
- end
71
-
72
- # Finds a box with the given name. This method searches for a box
73
- # with the given name, returning `nil` if none is found or returning
74
- # a {Box} instance otherwise.
75
- #
76
- # @param [String] name The name of the box
77
- # @return [Box] Instance of {Box} representing the box found
78
- def find(env, name)
79
- return nil unless File.directory?(directory(env, name))
80
- new(env, name)
81
- end
82
-
83
21
  # Adds a new box with given name from the given URI. This method
84
22
  # begins the process of adding a box from a given URI by setting up
85
23
  # the {Box} instance and calling {#add}.
@@ -87,22 +25,10 @@ module Vagrant
87
25
  # @param [String] name The name of the box
88
26
  # @param [String] uri URI to the box file
89
27
  def add(env, name, uri)
90
- box = new
91
- box.name = name
28
+ box = new(env, name)
92
29
  box.uri = uri
93
- box.env = env
94
30
  box.add
95
31
  end
96
-
97
- # Returns the directory to a box of the given name. The name given
98
- # as a parameter is not checked for existence; this method simply
99
- # returns the directory which would be used if the box did exist.
100
- #
101
- # @param [String] name Name of the box whose directory you're interested in.
102
- # @return [String] Full path to the box directory.
103
- def directory(env, name)
104
- File.join(env.boxes_path, name)
105
- end
106
32
  end
107
33
 
108
34
  # Creates a new box instance. Given an optional `name` parameter,
@@ -120,19 +46,21 @@ module Vagrant
120
46
  # virtual machine file which contains specifications of the exported
121
47
  # virtual machine this box contains.
122
48
  #
49
+ # This will only be valid once the box is imported.
50
+ #
123
51
  # @return [String]
124
52
  def ovf_file
125
- File.join(directory, env.config.vm.box_ovf)
53
+ directory.join(env.config.vm.box_ovf)
126
54
  end
127
55
 
128
56
  # Begins the process of adding a box to the vagrant installation. This
129
57
  # method requires that `name` and `uri` be set. The logic of this method
130
- # is kicked out to the {Actions::Box::Add add box} action.
58
+ # is kicked out to the `box_add` registered middleware.
131
59
  def add
132
60
  env.actions.run(:box_add, { "box" => self })
133
61
  end
134
62
 
135
- # Begins the process of destroying this box.
63
+ # Begins the process of destroying this box. This cannot be undone!
136
64
  def destroy
137
65
  env.actions.run(:box_remove, { "box" => self })
138
66
  end
@@ -143,11 +71,19 @@ module Vagrant
143
71
  end
144
72
 
145
73
  # Returns the directory to the location of this boxes content in the local
146
- # filesystem.
74
+ # filesystem. Note that if the box isn't imported yet, then the path may not
75
+ # yet exist, but still represents where the box will be imported to.
147
76
  #
148
77
  # @return [String]
149
78
  def directory
150
- self.class.directory(env, self.name)
79
+ env.boxes_path.join(name)
80
+ end
81
+
82
+ # Implemented for comparison with other boxes. Comparison is implemented
83
+ # by simply comparing name.
84
+ def <=>(other)
85
+ return super if !other.is_a?(self.class)
86
+ name <=> other.name
151
87
  end
152
88
  end
153
89
  end
@@ -0,0 +1,47 @@
1
+ module Vagrant
2
+ # Represents a collection of boxes, providing helpful methods for
3
+ # finding boxes. An instance of this is returned by {Environment#boxes}.
4
+ #
5
+ # # Finding a Box
6
+ #
7
+ # To find a box, use the {#find} method with the name of the box. The name
8
+ # is an exact match search.
9
+ #
10
+ # env.boxes.find("base") # => #<Vagrant::Box>
11
+ #
12
+ class BoxCollection < Array
13
+ # The environment this box collection belongs to
14
+ attr_reader :env
15
+
16
+ def initialize(env)
17
+ super()
18
+
19
+ @env = env
20
+ reload!
21
+ end
22
+
23
+ # Find a box in the collection by the given name. The name must
24
+ # be a string, for now.
25
+ def find(name)
26
+ each do |box|
27
+ return box if box.name == name
28
+ end
29
+
30
+ nil
31
+ end
32
+
33
+ # Loads the list of all boxes from the source. This modifies the
34
+ # current array.
35
+ def reload!
36
+ clear
37
+
38
+ Dir.open(env.boxes_path) do |dir|
39
+ dir.each do |d|
40
+ next if d == "." || d == ".." || !File.directory?(env.boxes_path.join(d))
41
+ self << Box.new(env, d)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,55 @@
1
+ require 'thor'
2
+
3
+ module Vagrant
4
+ # Entrypoint for the Vagrant CLI. This class should never be
5
+ # initialized directly (like a typical Thor class). Instead,
6
+ # use {Environment#cli} to invoke the CLI.
7
+ #
8
+ # # Defining Custom CLI Commands
9
+ #
10
+ # If you're looking to define custom CLI commands, then look at
11
+ # one of the two following classes:
12
+ #
13
+ # * {Command::Base} - Implementing a single command such as `vagrant up`, e.g.
14
+ # one without subcommands. Also take a look at {Command::NamedBase}.
15
+ # * {Command::GroupBase} - Implementing a command with subcommands, such as
16
+ # `vagrant box`, which has the `list`, `add`, etc. subcommands.
17
+ #
18
+ # The above linked classes contain the main documentation for each
19
+ # type of command.
20
+ class CLI < Thor
21
+ # Registers the given class with the CLI so it can be accessed.
22
+ # The class must be a subclass of either {Command::Base} or {Command::GroupBase}.
23
+ # Don't call this method directly, instead call the {Command::Base.register}
24
+ # or {Command::GroupBase.register} methods.
25
+ #
26
+ # @param [Class] klass Command class
27
+ # @param [String] name Command name, accessed at `vagrant NAME`
28
+ # @param [String] usage Command usage, such as "vagrant NAME [--option]"
29
+ # @param [String] description Description of the command shown during the
30
+ # command listing.
31
+ # @param [Hash] opts Other options (not gone into detail here, look at
32
+ # the source instead).
33
+ def self.register(klass, name, usage, description, opts=nil)
34
+ opts ||= {}
35
+
36
+ if klass <= Command::GroupBase
37
+ # A subclass of GroupBase is a subcommand, since it contains
38
+ # many smaller commands within it.
39
+ desc usage, description, opts
40
+ subcommand name, klass
41
+ elsif klass <= Command::Base
42
+ # A subclass of Base is a single command, since it
43
+ # is invoked as a whole (as Thor::Group)
44
+ desc usage, description, opts
45
+ define_method(name) { |*args| invoke klass, args }
46
+ end
47
+
48
+ if opts[:alias]
49
+ # Alises are defined for this command, so properly alias the
50
+ # newly defined method/subcommand:
51
+ map opts[:alias] => name
52
+ end
53
+ end
54
+ end
55
+ end