vagrant 0.5.4 → 0.6.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 (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