vagrant 0.8.10 → 0.9.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 (324) hide show
  1. data/CHANGELOG.md +77 -1
  2. data/Gemfile +0 -14
  3. data/LICENSE +1 -1
  4. data/bin/vagrant +47 -20
  5. data/config/default.rb +6 -14
  6. data/lib/vagrant.rb +132 -5
  7. data/lib/vagrant/action.rb +45 -123
  8. data/lib/vagrant/action/box/destroy.rb +7 -3
  9. data/lib/vagrant/action/box/download.rb +8 -8
  10. data/lib/vagrant/action/box/package.rb +2 -2
  11. data/lib/vagrant/action/box/unpackage.rb +13 -7
  12. data/lib/vagrant/action/box/verify.rb +5 -5
  13. data/lib/vagrant/action/builder.rb +23 -19
  14. data/lib/vagrant/action/builtin.rb +117 -79
  15. data/lib/vagrant/action/env/set.rb +7 -4
  16. data/lib/vagrant/action/environment.rb +3 -41
  17. data/lib/vagrant/action/general/package.rb +14 -29
  18. data/lib/vagrant/action/general/validate.rb +2 -2
  19. data/lib/vagrant/action/runner.rb +53 -0
  20. data/lib/vagrant/action/vm/boot.rb +9 -9
  21. data/lib/vagrant/action/vm/check_accessible.rb +2 -2
  22. data/lib/vagrant/action/vm/check_box.rb +10 -12
  23. data/lib/vagrant/action/vm/check_guest_additions.rb +8 -8
  24. data/lib/vagrant/action/vm/check_port_collisions.rb +85 -0
  25. data/lib/vagrant/action/vm/clean_machine_folder.rb +4 -4
  26. data/lib/vagrant/action/vm/clear_forwarded_ports.rb +3 -11
  27. data/lib/vagrant/action/vm/clear_network_interfaces.rb +31 -0
  28. data/lib/vagrant/action/vm/clear_shared_folders.rb +2 -11
  29. data/lib/vagrant/action/vm/customize.rb +19 -9
  30. data/lib/vagrant/action/vm/destroy.rb +4 -4
  31. data/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb +2 -12
  32. data/lib/vagrant/action/vm/discard_state.rb +4 -4
  33. data/lib/vagrant/action/vm/export.rb +13 -8
  34. data/lib/vagrant/action/vm/forward_ports.rb +55 -102
  35. data/lib/vagrant/action/vm/halt.rb +9 -6
  36. data/lib/vagrant/action/vm/host_name.rb +4 -4
  37. data/lib/vagrant/action/vm/import.rb +19 -10
  38. data/lib/vagrant/action/vm/match_mac_address.rb +4 -9
  39. data/lib/vagrant/action/vm/network.rb +300 -94
  40. data/lib/vagrant/action/vm/nfs.rb +41 -26
  41. data/lib/vagrant/action/vm/package.rb +1 -1
  42. data/lib/vagrant/action/vm/package_vagrantfile.rb +5 -2
  43. data/lib/vagrant/action/vm/provision.rb +42 -13
  44. data/lib/vagrant/action/vm/provisioner_cleanup.rb +2 -2
  45. data/lib/vagrant/action/vm/{clear_nfs_exports.rb → prune_nfs_exports.rb} +7 -7
  46. data/lib/vagrant/action/vm/resume.rb +4 -4
  47. data/lib/vagrant/action/vm/setup_package_files.rb +54 -0
  48. data/lib/vagrant/action/vm/share_folders.rb +63 -39
  49. data/lib/vagrant/action/vm/suspend.rb +4 -4
  50. data/lib/vagrant/action/warden.rb +13 -6
  51. data/lib/vagrant/box.rb +9 -55
  52. data/lib/vagrant/box_collection.rb +22 -17
  53. data/lib/vagrant/cli.rb +62 -47
  54. data/lib/vagrant/command.rb +18 -20
  55. data/lib/vagrant/command/base.rb +135 -90
  56. data/lib/vagrant/command/box.rb +46 -21
  57. data/lib/vagrant/command/box_add.rb +33 -0
  58. data/lib/vagrant/command/box_list.rb +25 -0
  59. data/lib/vagrant/command/box_remove.rb +23 -0
  60. data/lib/vagrant/command/box_repackage.rb +23 -0
  61. data/lib/vagrant/command/destroy.rb +16 -5
  62. data/lib/vagrant/command/halt.rb +25 -7
  63. data/lib/vagrant/command/init.rb +30 -7
  64. data/lib/vagrant/command/package.rb +49 -18
  65. data/lib/vagrant/command/provision.rb +22 -9
  66. data/lib/vagrant/command/reload.rb +18 -5
  67. data/lib/vagrant/command/resume.rb +18 -5
  68. data/lib/vagrant/command/ssh.rb +69 -31
  69. data/lib/vagrant/command/ssh_config.rb +37 -22
  70. data/lib/vagrant/command/status.rb +22 -20
  71. data/lib/vagrant/command/suspend.rb +18 -5
  72. data/lib/vagrant/command/up.rb +41 -8
  73. data/lib/vagrant/communication.rb +7 -0
  74. data/lib/vagrant/communication/base.rb +56 -0
  75. data/lib/vagrant/communication/ssh.rb +200 -0
  76. data/lib/vagrant/config.rb +29 -103
  77. data/lib/vagrant/config/base.rb +18 -26
  78. data/lib/vagrant/config/container.rb +37 -0
  79. data/lib/vagrant/config/error_recorder.rb +1 -1
  80. data/lib/vagrant/config/loader.rb +125 -0
  81. data/lib/vagrant/config/nfs.rb +1 -3
  82. data/lib/vagrant/config/package.rb +1 -3
  83. data/lib/vagrant/config/ssh.rb +31 -16
  84. data/lib/vagrant/config/top.rb +36 -25
  85. data/lib/vagrant/config/vagrant.rb +2 -5
  86. data/lib/vagrant/config/vm.rb +115 -56
  87. data/lib/vagrant/config/vm/provisioner.rb +16 -20
  88. data/lib/vagrant/config/vm/sub_vm.rb +1 -1
  89. data/lib/vagrant/data_store.rb +23 -15
  90. data/lib/vagrant/downloaders/base.rb +7 -5
  91. data/lib/vagrant/downloaders/file.rb +4 -4
  92. data/lib/vagrant/downloaders/http.rb +4 -5
  93. data/lib/vagrant/driver.rb +7 -0
  94. data/lib/vagrant/driver/virtualbox.rb +121 -0
  95. data/lib/vagrant/driver/virtualbox_4_0.rb +411 -0
  96. data/lib/vagrant/driver/virtualbox_4_1.rb +411 -0
  97. data/lib/vagrant/driver/virtualbox_base.rb +284 -0
  98. data/lib/vagrant/environment.rb +221 -240
  99. data/lib/vagrant/errors.rb +74 -25
  100. data/lib/vagrant/guest.rb +16 -0
  101. data/lib/vagrant/guest/arch.rb +48 -0
  102. data/lib/vagrant/{systems → guest}/base.rb +30 -18
  103. data/lib/vagrant/guest/debian.rb +61 -0
  104. data/lib/vagrant/{systems → guest}/freebsd.rb +11 -18
  105. data/lib/vagrant/guest/gentoo.rb +32 -0
  106. data/lib/vagrant/guest/linux.rb +78 -0
  107. data/lib/vagrant/{systems → guest}/linux/config.rb +2 -4
  108. data/lib/vagrant/guest/linux/error.rb +9 -0
  109. data/lib/vagrant/guest/redhat.rb +66 -0
  110. data/lib/vagrant/guest/solaris.rb +114 -0
  111. data/lib/vagrant/{systems → guest}/suse.rb +2 -2
  112. data/lib/vagrant/guest/ubuntu.rb +23 -0
  113. data/lib/vagrant/hosts.rb +23 -6
  114. data/lib/vagrant/hosts/arch.rb +7 -3
  115. data/lib/vagrant/hosts/base.rb +36 -46
  116. data/lib/vagrant/hosts/bsd.rb +53 -16
  117. data/lib/vagrant/hosts/fedora.rb +14 -0
  118. data/lib/vagrant/hosts/freebsd.rb +6 -36
  119. data/lib/vagrant/hosts/linux.rb +45 -20
  120. data/lib/vagrant/hosts/windows.rb +16 -0
  121. data/lib/vagrant/provisioners.rb +10 -7
  122. data/lib/vagrant/provisioners/base.rb +11 -34
  123. data/lib/vagrant/provisioners/chef.rb +30 -26
  124. data/lib/vagrant/provisioners/chef_client.rb +37 -23
  125. data/lib/vagrant/provisioners/chef_solo.rb +61 -16
  126. data/lib/vagrant/provisioners/puppet.rb +70 -38
  127. data/lib/vagrant/provisioners/puppet_server.rb +12 -13
  128. data/lib/vagrant/provisioners/shell.rb +24 -24
  129. data/lib/vagrant/registry.rb +49 -0
  130. data/lib/vagrant/ssh.rb +82 -153
  131. data/lib/vagrant/ui.rb +118 -50
  132. data/lib/vagrant/util/busy.rb +1 -1
  133. data/lib/vagrant/util/file_mode.rb +12 -0
  134. data/lib/vagrant/util/network_ip.rb +28 -0
  135. data/lib/vagrant/util/platform.rb +1 -0
  136. data/lib/vagrant/util/subprocess.rb +227 -0
  137. data/lib/vagrant/version.rb +1 -1
  138. data/lib/vagrant/vm.rb +111 -97
  139. data/tasks/acceptance.rake +3 -3
  140. data/tasks/test.rake +7 -2
  141. data/templates/commands/init/Vagrantfile.erb +11 -4
  142. data/templates/{ssh_config.erb → commands/ssh_config/config.erb} +0 -0
  143. data/templates/guests/arch/network_dhcp.erb +7 -0
  144. data/templates/guests/arch/network_static.erb +7 -0
  145. data/templates/guests/debian/network_dhcp.erb +6 -0
  146. data/templates/guests/debian/network_static.erb +7 -0
  147. data/templates/guests/gentoo/network_dhcp.erb +4 -0
  148. data/templates/guests/gentoo/network_static.erb +4 -0
  149. data/templates/guests/redhat/network_dhcp.erb +6 -0
  150. data/templates/guests/redhat/network_static.erb +7 -0
  151. data/templates/locales/en.yml +241 -122
  152. data/templates/{chef_server_client.erb → provisioners/chef_client/client.erb} +0 -0
  153. data/templates/{chef_solo_solo.erb → provisioners/chef_solo/solo.erb} +0 -0
  154. data/test/acceptance/base.rb +10 -10
  155. data/test/acceptance/box_test.rb +28 -6
  156. data/test/acceptance/destroy_test.rb +1 -1
  157. data/test/acceptance/halt_test.rb +4 -4
  158. data/test/acceptance/init_test.rb +3 -3
  159. data/test/acceptance/networking/host_only_test.rb +37 -0
  160. data/test/acceptance/networking/port_forward_test.rb +125 -0
  161. data/test/acceptance/package_test.rb +46 -0
  162. data/test/acceptance/provisioning/basic_test.rb +61 -0
  163. data/test/acceptance/provisioning/chef_solo_test.rb +37 -0
  164. data/test/acceptance/provisioning/shell_test.rb +53 -0
  165. data/test/acceptance/resume_test.rb +1 -1
  166. data/test/acceptance/skeletons/chef_solo_basic/README.md +3 -0
  167. data/test/acceptance/skeletons/chef_solo_basic/cookbooks/basic/recipes/default.rb +5 -0
  168. data/test/acceptance/skeletons/chef_solo_json/README.md +3 -0
  169. data/test/acceptance/skeletons/chef_solo_json/cookbooks/basic/recipes/default.rb +6 -0
  170. data/test/acceptance/skeletons/provisioner_multi/README.md +3 -0
  171. data/test/acceptance/skeletons/provisioner_multi/cookbooks/basic/recipes/default.rb +5 -0
  172. data/test/acceptance/ssh_test.rb +7 -2
  173. data/test/acceptance/support/config.rb +1 -1
  174. data/test/acceptance/support/isolated_environment.rb +41 -150
  175. data/test/acceptance/support/matchers/match_output.rb +1 -1
  176. data/test/acceptance/support/matchers/succeed.rb +14 -0
  177. data/test/acceptance/support/network_tests.rb +29 -0
  178. data/test/acceptance/support/output.rb +9 -1
  179. data/test/acceptance/support/shared/base_context.rb +16 -9
  180. data/test/acceptance/support/shared/command_examples.rb +4 -4
  181. data/test/acceptance/suspend_test.rb +1 -1
  182. data/test/acceptance/up_basic_test.rb +26 -7
  183. data/test/acceptance/up_with_box_url.rb +1 -1
  184. data/test/acceptance/vagrant_test.rb +1 -1
  185. data/test/acceptance/version_test.rb +0 -5
  186. data/test/support/isolated_environment.rb +46 -0
  187. data/test/{acceptance/support → support}/tempdir.rb +0 -0
  188. data/test/unit/base.rb +21 -0
  189. data/test/unit/support/isolated_environment.rb +39 -0
  190. data/test/unit/support/shared/base_context.rb +30 -0
  191. data/test/unit/vagrant/action/builder_test.rb +126 -177
  192. data/test/unit/vagrant/action/environment_test.rb +10 -21
  193. data/test/unit/vagrant/action/runner_test.rb +65 -0
  194. data/test/unit/vagrant/action/warden_test.rb +64 -97
  195. data/test/unit/vagrant/box_collection_test.rb +44 -33
  196. data/test/unit/vagrant/box_test.rb +25 -65
  197. data/test/unit/vagrant/command/base_test.rb +141 -14
  198. data/test/unit/vagrant/config/base_test.rb +16 -43
  199. data/test/unit/vagrant/config/loader_test.rb +79 -0
  200. data/test/unit/vagrant/config/top_test.rb +69 -0
  201. data/test/unit/vagrant/config/vm_test.rb +62 -47
  202. data/test/unit/vagrant/config_test.rb +16 -151
  203. data/test/unit/vagrant/data_store_test.rb +43 -61
  204. data/test/unit/vagrant/downloaders/base_test.rb +12 -22
  205. data/test/unit/vagrant/downloaders/file_test.rb +58 -31
  206. data/test/unit/vagrant/downloaders/http_test.rb +12 -86
  207. data/test/unit/vagrant/environment_test.rb +107 -536
  208. data/test/unit/vagrant/hosts_test.rb +36 -0
  209. data/test/unit/vagrant/registry_test.rb +56 -0
  210. data/test/unit/vagrant/util/file_checksum_test.rb +23 -0
  211. data/test/unit/vagrant/util/hash_with_indifferent_access_test.rb +23 -24
  212. data/test/unit/vagrant/util/network_ip_test.rb +17 -0
  213. data/test/unit/vagrant/util/retryable_test.rb +90 -34
  214. data/test/unit/vagrant_test.rb +27 -0
  215. data/test/{unit → unit_legacy}/locales/en.yml +0 -0
  216. data/test/{unit → unit_legacy}/test_helper.rb +0 -0
  217. data/test/{unit → unit_legacy}/vagrant/action/box/destroy_test.rb +0 -0
  218. data/test/{unit → unit_legacy}/vagrant/action/box/download_test.rb +0 -0
  219. data/test/{unit → unit_legacy}/vagrant/action/box/package_test.rb +0 -0
  220. data/test/{unit → unit_legacy}/vagrant/action/box/unpackage_test.rb +0 -0
  221. data/test/{unit → unit_legacy}/vagrant/action/box/verify_test.rb +0 -0
  222. data/test/{unit → unit_legacy}/vagrant/action/env/set_test.rb +0 -0
  223. data/test/{unit → unit_legacy}/vagrant/action/general/package_test.rb +0 -0
  224. data/test/{unit → unit_legacy}/vagrant/action/general/validate_test.rb +0 -0
  225. data/test/{unit → unit_legacy}/vagrant/action/vm/boot_test.rb +0 -0
  226. data/test/{unit → unit_legacy}/vagrant/action/vm/check_accessible_test.rb +0 -0
  227. data/test/{unit → unit_legacy}/vagrant/action/vm/check_box_test.rb +0 -0
  228. data/test/{unit → unit_legacy}/vagrant/action/vm/check_guest_additions_test.rb +0 -0
  229. data/test/{unit → unit_legacy}/vagrant/action/vm/clean_machine_folder_test.rb +0 -0
  230. data/test/{unit → unit_legacy}/vagrant/action/vm/clear_forwarded_ports_test.rb +0 -0
  231. data/test/{unit → unit_legacy}/vagrant/action/vm/clear_nfs_exports_test.rb +0 -0
  232. data/test/{unit → unit_legacy}/vagrant/action/vm/clear_shared_folders_test.rb +0 -0
  233. data/test/{unit → unit_legacy}/vagrant/action/vm/customize_test.rb +0 -0
  234. data/test/{unit → unit_legacy}/vagrant/action/vm/destroy_test.rb +0 -0
  235. data/test/{unit → unit_legacy}/vagrant/action/vm/destroy_unused_network_interfaces_test.rb +0 -0
  236. data/test/{unit → unit_legacy}/vagrant/action/vm/discard_state_test.rb +0 -0
  237. data/test/{unit → unit_legacy}/vagrant/action/vm/export_test.rb +0 -0
  238. data/test/{unit → unit_legacy}/vagrant/action/vm/forward_ports_helpers_test.rb +0 -0
  239. data/test/{unit → unit_legacy}/vagrant/action/vm/forward_ports_test.rb +0 -0
  240. data/test/{unit → unit_legacy}/vagrant/action/vm/halt_test.rb +0 -0
  241. data/test/{unit → unit_legacy}/vagrant/action/vm/host_name_test.rb +0 -0
  242. data/test/{unit → unit_legacy}/vagrant/action/vm/import_test.rb +0 -0
  243. data/test/{unit → unit_legacy}/vagrant/action/vm/match_mac_address_test.rb +0 -0
  244. data/test/{unit → unit_legacy}/vagrant/action/vm/modify_test.rb +0 -0
  245. data/test/{unit → unit_legacy}/vagrant/action/vm/network_test.rb +0 -0
  246. data/test/{unit → unit_legacy}/vagrant/action/vm/nfs_helpers_test.rb +0 -0
  247. data/test/{unit → unit_legacy}/vagrant/action/vm/nfs_test.rb +0 -0
  248. data/test/{unit → unit_legacy}/vagrant/action/vm/package_test.rb +0 -0
  249. data/test/{unit → unit_legacy}/vagrant/action/vm/package_vagrantfile_test.rb +0 -0
  250. data/test/{unit → unit_legacy}/vagrant/action/vm/provision_test.rb +0 -0
  251. data/test/{unit → unit_legacy}/vagrant/action/vm/provisioner_cleanup_test.rb +0 -0
  252. data/test/{unit → unit_legacy}/vagrant/action/vm/resume_test.rb +0 -0
  253. data/test/{unit → unit_legacy}/vagrant/action/vm/share_folders_test.rb +0 -0
  254. data/test/{unit → unit_legacy}/vagrant/action/vm/suspend_test.rb +0 -0
  255. data/test/{unit → unit_legacy}/vagrant/action_test.rb +0 -0
  256. data/test/unit_legacy/vagrant/box_collection_test.rb +45 -0
  257. data/test/unit_legacy/vagrant/box_test.rb +74 -0
  258. data/test/{unit → unit_legacy}/vagrant/cli_test.rb +0 -0
  259. data/test/unit_legacy/vagrant/command/base_test.rb +23 -0
  260. data/test/{unit → unit_legacy}/vagrant/command/group_base_test.rb +0 -0
  261. data/test/{unit → unit_legacy}/vagrant/command/helpers_test.rb +0 -0
  262. data/test/{unit → unit_legacy}/vagrant/command/init_test.rb +0 -0
  263. data/test/{unit → unit_legacy}/vagrant/command/package_test.rb +0 -0
  264. data/test/unit_legacy/vagrant/config/base_test.rb +52 -0
  265. data/test/{unit → unit_legacy}/vagrant/config/error_recorder_test.rb +0 -0
  266. data/test/{unit → unit_legacy}/vagrant/config/ssh_test.rb +0 -0
  267. data/test/{unit → unit_legacy}/vagrant/config/vagrant_test.rb +0 -0
  268. data/test/{unit → unit_legacy}/vagrant/config/vm/provisioner_test.rb +0 -0
  269. data/test/unit_legacy/vagrant/config/vm_test.rb +47 -0
  270. data/test/unit_legacy/vagrant/config_test.rb +148 -0
  271. data/test/unit_legacy/vagrant/downloaders/http_test.rb +93 -0
  272. data/test/unit_legacy/vagrant/environment_test.rb +539 -0
  273. data/test/{unit → unit_legacy}/vagrant/errors_test.rb +0 -0
  274. data/test/{unit → unit_legacy}/vagrant/hosts/base_test.rb +0 -0
  275. data/test/{unit → unit_legacy}/vagrant/hosts/bsd_test.rb +0 -0
  276. data/test/{unit → unit_legacy}/vagrant/hosts/linux_test.rb +0 -0
  277. data/test/{unit → unit_legacy}/vagrant/plugin_test.rb +0 -0
  278. data/test/{unit → unit_legacy}/vagrant/provisioners/base_test.rb +0 -0
  279. data/test/{unit → unit_legacy}/vagrant/provisioners/chef_client_test.rb +0 -0
  280. data/test/{unit → unit_legacy}/vagrant/provisioners/chef_solo_test.rb +0 -0
  281. data/test/{unit → unit_legacy}/vagrant/provisioners/chef_test.rb +0 -0
  282. data/test/{unit → unit_legacy}/vagrant/provisioners/puppet_server_test.rb +0 -0
  283. data/test/{unit → unit_legacy}/vagrant/provisioners/puppet_test.rb +0 -0
  284. data/test/{unit → unit_legacy}/vagrant/provisioners/shell_test.rb +0 -0
  285. data/test/{unit → unit_legacy}/vagrant/ssh/session_test.rb +0 -0
  286. data/test/{unit → unit_legacy}/vagrant/ssh_test.rb +0 -0
  287. data/test/{unit → unit_legacy}/vagrant/systems/base_test.rb +0 -0
  288. data/test/{unit → unit_legacy}/vagrant/systems/linux_test.rb +0 -0
  289. data/test/{unit → unit_legacy}/vagrant/util/busy_test.rb +0 -0
  290. data/test/{unit → unit_legacy}/vagrant/util/counter_test.rb +0 -0
  291. data/test/{unit → unit_legacy}/vagrant/util/platform_test.rb +0 -0
  292. data/test/{unit → unit_legacy}/vagrant/util/stacked_proc_runner_test.rb +0 -0
  293. data/test/{unit → unit_legacy}/vagrant/util/template_renderer_test.rb +0 -0
  294. data/test/{unit → unit_legacy}/vagrant/vm_test.rb +0 -0
  295. data/vagrant.gemspec +7 -9
  296. metadata +214 -216
  297. data/keys/vagrant.ppk +0 -26
  298. data/lib/vagrant/action/box.rb +0 -11
  299. data/lib/vagrant/action/env.rb +0 -7
  300. data/lib/vagrant/action/general.rb +0 -8
  301. data/lib/vagrant/action/vm.rb +0 -34
  302. data/lib/vagrant/action/vm/forward_ports_helpers.rb +0 -28
  303. data/lib/vagrant/action/vm/modify.rb +0 -37
  304. data/lib/vagrant/action/vm/nfs_helpers.rb +0 -11
  305. data/lib/vagrant/command/group_base.rb +0 -107
  306. data/lib/vagrant/command/helpers.rb +0 -33
  307. data/lib/vagrant/command/named_base.rb +0 -14
  308. data/lib/vagrant/command/upgrade_to_060.rb +0 -45
  309. data/lib/vagrant/command/version.rb +0 -13
  310. data/lib/vagrant/ssh/session.rb +0 -136
  311. data/lib/vagrant/systems.rb +0 -13
  312. data/lib/vagrant/systems/arch.rb +0 -34
  313. data/lib/vagrant/systems/debian.rb +0 -36
  314. data/lib/vagrant/systems/gentoo.rb +0 -27
  315. data/lib/vagrant/systems/linux.rb +0 -82
  316. data/lib/vagrant/systems/linux/error.rb +0 -9
  317. data/lib/vagrant/systems/redhat.rb +0 -48
  318. data/lib/vagrant/systems/solaris.rb +0 -113
  319. data/lib/vagrant/systems/ubuntu.rb +0 -17
  320. data/templates/network_entry_arch.erb +0 -9
  321. data/templates/network_entry_debian.erb +0 -8
  322. data/templates/network_entry_gentoo.erb +0 -5
  323. data/templates/network_entry_redhat.erb +0 -9
  324. data/test/unit/vagrant/ui_test.rb +0 -29
@@ -1,5 +1,5 @@
1
1
  module Vagrant
2
- class Action
2
+ module Action
3
3
  module VM
4
4
  class Suspend
5
5
  def initialize(app, env)
@@ -7,9 +7,9 @@ module Vagrant
7
7
  end
8
8
 
9
9
  def call(env)
10
- if env["vm"].vm.running?
11
- env.ui.info I18n.t("vagrant.actions.vm.suspend.suspending")
12
- env["vm"].vm.save_state
10
+ if env[:vm].state == :running
11
+ env[:ui].info I18n.t("vagrant.actions.vm.suspend.suspending")
12
+ env[:vm].driver.suspend
13
13
  end
14
14
 
15
15
  @app.call(env)
@@ -1,5 +1,7 @@
1
+ require "log4r"
2
+
1
3
  module Vagrant
2
- class Action
4
+ module Action
3
5
  # The action warden is a middleware which injects itself between
4
6
  # every other middleware, watching for exceptions which are raised
5
7
  # and performing proper cleanup on every action by calling the `recover`
@@ -16,6 +18,7 @@ module Vagrant
16
18
  def initialize(actions, env)
17
19
  @stack = []
18
20
  @actions = actions.map { |m| finalize_action(m, env) }
21
+ @logger = Log4r::Logger.new("vagrant::action::warden")
19
22
  end
20
23
 
21
24
  def call(env)
@@ -24,17 +27,17 @@ module Vagrant
24
27
  begin
25
28
  # Call the next middleware in the sequence, appending to the stack
26
29
  # of "recoverable" middlewares in case something goes wrong!
27
- raise Errors::VagrantInterrupt if env.interrupted?
30
+ raise Errors::VagrantInterrupt if env[:interrupted]
28
31
  action = @actions.shift
29
- env["logger"].info("warden") { "Calling action: #{action}" }
32
+ @logger.info("Calling action: #{action}")
30
33
  @stack.unshift(action).first.call(env)
31
- raise Errors::VagrantInterrupt if env.interrupted?
34
+ raise Errors::VagrantInterrupt if env[:interrupted]
32
35
  rescue SystemExit
33
36
  # This means that an "exit" or "abort" was called. In these cases,
34
37
  # we just exit immediately.
35
38
  raise
36
39
  rescue Exception => e
37
- env["logger"].info("warden") { "Error occurred: #{e}" }
40
+ @logger.error("Error occurred: #{e}")
38
41
  env["vagrant.error"] = e
39
42
 
40
43
  # Something went horribly wrong. Start the rescue chain then
@@ -50,7 +53,7 @@ module Vagrant
50
53
  def begin_rescue(env)
51
54
  @stack.each do |act|
52
55
  if act.respond_to?(:recover)
53
- env["logger"].info("warden") { "Calling recover: #{act}" }
56
+ @logger.info("Calling recover: #{act}")
54
57
  act.recover(env)
55
58
  end
56
59
  end
@@ -65,6 +68,10 @@ module Vagrant
65
68
  def finalize_action(action, env)
66
69
  klass, args, block = action
67
70
 
71
+ # Default the arguments to an empty array. Otherwise in Ruby 1.8
72
+ # a `nil` args will actually pass `nil` into the class.
73
+ args ||= []
74
+
68
75
  if klass.is_a?(Class)
69
76
  # A action klass which is to be instantiated with the
70
77
  # app, env, and any arguments given
@@ -7,29 +7,10 @@ module Vagrant
7
7
  # is kicked out to middlewares.
8
8
  class Box
9
9
  # The name of the box.
10
- attr_accessor :name
10
+ attr_reader :name
11
11
 
12
- # The URI for a new box. This is not available for existing boxes.
13
- attr_accessor :uri
14
-
15
- # The environment which this box belongs to. Although this could
16
- # actually be many environments, this points to the environment
17
- # of a specific instance.
18
- attr_reader :env
19
-
20
- class << self
21
- # Adds a new box with given name from the given URI. This method
22
- # begins the process of adding a box from a given URI by setting up
23
- # the {Box} instance and calling {#add}.
24
- #
25
- # @param [String] name The name of the box
26
- # @param [String] uri URI to the box file
27
- def add(env, name, uri)
28
- box = new(env, name)
29
- box.uri = uri
30
- box.add
31
- end
32
- end
12
+ # The directory where this box is stored
13
+ attr_reader :directory
33
14
 
34
15
  # Creates a new box instance. Given an optional `name` parameter,
35
16
  # newly created instance will have that name, otherwise it defaults
@@ -37,47 +18,20 @@ module Vagrant
37
18
  #
38
19
  # **Note:** This method does not actually _create_ the box, but merely
39
20
  # returns a new, abstract representation of it. To add a box, see {#add}.
40
- def initialize(env=nil, name=nil)
41
- @name = name
42
- @env = env
43
- end
44
-
45
- # Returns path to the OVF file of the box. The OVF file is an open
46
- # virtual machine file which contains specifications of the exported
47
- # virtual machine this box contains.
48
- #
49
- # This will only be valid once the box is imported.
50
- #
51
- # @return [String]
52
- def ovf_file
53
- directory.join(env.config.vm.box_ovf)
54
- end
55
-
56
- # Begins the process of adding a box to the vagrant installation. This
57
- # method requires that `name` and `uri` be set. The logic of this method
58
- # is kicked out to the `box_add` registered middleware.
59
- def add
60
- raise Errors::BoxAlreadyExists, :name => name if File.directory?(directory)
61
- env.actions.run(:box_add, { "box" => self, "validate" => false })
21
+ def initialize(name, directory, action_runner)
22
+ @name = name
23
+ @directory = directory
24
+ @action_runner = action_runner
62
25
  end
63
26
 
64
27
  # Begins the process of destroying this box. This cannot be undone!
65
28
  def destroy
66
- env.actions.run(:box_remove, { "box" => self, "validate" => false })
29
+ @action_runner.run(:box_remove, { :box_name => @name, :box_directory => @directory })
67
30
  end
68
31
 
69
32
  # Begins sequence to repackage this box.
70
33
  def repackage(options=nil)
71
- env.actions.run(:box_repackage, { "box" => self, "validate" => false }.merge(options || {}))
72
- end
73
-
74
- # Returns the directory to the location of this boxes content in the local
75
- # filesystem. Note that if the box isn't imported yet, then the path may not
76
- # yet exist, but still represents where the box will be imported to.
77
- #
78
- # @return [String]
79
- def directory
80
- env.boxes_path.join(name)
34
+ @action_runner.run(:box_repackage, { :box_name => @name, :box_directory => @directory })
81
35
  end
82
36
 
83
37
  # Implemented for comparison with other boxes. Comparison is implemented
@@ -2,26 +2,20 @@ require 'forwardable'
2
2
 
3
3
  module Vagrant
4
4
  # Represents a collection of boxes, providing helpful methods for
5
- # finding boxes. An instance of this is returned by {Environment#boxes}.
6
- #
7
- # # Finding a Box
8
- #
9
- # To find a box, use the {#find} method with the name of the box. The name
10
- # is an exact match search.
11
- #
12
- # env.boxes.find("base") # => #<Vagrant::Box>
13
- #
5
+ # finding boxes.
14
6
  class BoxCollection
15
7
  include Enumerable
16
8
  extend Forwardable
17
9
  def_delegators :@boxes, :length, :each
18
10
 
19
- # The environment this box collection belongs to
20
- attr_reader :env
11
+ # The directory that the boxes are being searched for.
12
+ attr_reader :directory
21
13
 
22
- def initialize(env)
23
- @env = env
24
- @boxes = []
14
+ # Initializes the class to search for boxes in the given directory.
15
+ def initialize(directory, action_runner)
16
+ @directory = directory
17
+ @boxes = []
18
+ @action_runner = action_runner
25
19
 
26
20
  reload!
27
21
  end
@@ -36,15 +30,26 @@ module Vagrant
36
30
  nil
37
31
  end
38
32
 
33
+ # Adds a box to this collection with the given name and located
34
+ # at the given URL.
35
+ def add(name, url)
36
+ raise Errors::BoxAlreadyExists, :name => name if find(name)
37
+
38
+ @action_runner.run(:box_add,
39
+ :box_name => name,
40
+ :box_url => url,
41
+ :box_directory => @directory.join(name))
42
+ end
43
+
39
44
  # Loads the list of all boxes from the source. This modifies the
40
45
  # current array.
41
46
  def reload!
42
47
  @boxes.clear
43
48
 
44
- Dir.open(env.boxes_path) do |dir|
49
+ Dir.open(@directory) do |dir|
45
50
  dir.each do |d|
46
- next if d == "." || d == ".." || !File.directory?(env.boxes_path.join(d))
47
- @boxes << Box.new(env, d)
51
+ next if d == "." || d == ".." || !@directory.join(d).directory?
52
+ @boxes << Box.new(d, @directory.join(d), @action_runner)
48
53
  end
49
54
  end
50
55
  end
@@ -1,55 +1,70 @@
1
- require 'thor'
1
+ require 'log4r'
2
+ require 'optparse'
2
3
 
3
4
  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 }
5
+ # Manages the command line interface to Vagrant.
6
+ class CLI < Command::Base
7
+ def initialize(argv, env)
8
+ super
9
+
10
+ @logger = Log4r::Logger.new("vagrant::cli")
11
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
12
+
13
+ @logger.info("CLI: #{@main_args.inspect} #{@sub_command.inspect} #{@sub_args.inspect}")
14
+ end
15
+
16
+ def execute
17
+ if @main_args.include?("-v") || @main_args.include?("--version")
18
+ # Version short-circuits the whole thing. Just print
19
+ # the version and exit.
20
+ @env.ui.info(I18n.t("vagrant.commands.version.output",
21
+ :version => Vagrant::VERSION),
22
+ :prefix => false)
23
+
24
+ return
25
+ elsif @main_args.include?("-h") || @main_args.include?("--help")
26
+ # Help is next in short-circuiting everything. Print
27
+ # the help and exit.
28
+ return help
46
29
  end
47
30
 
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
31
+ # If we reached this far then we must have a subcommand. If not,
32
+ # then we also just print the help and exit.
33
+ command_class = Vagrant.commands.get(@sub_command.to_sym) if @sub_command
34
+ return help if !command_class || !@sub_command
35
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
36
+
37
+ # Initialize and execute the command class.
38
+ command_class.new(@sub_args, @env).execute
39
+ end
40
+
41
+ # This prints out the help for the CLI.
42
+ def help
43
+ # We use the optionparser for this. Its just easier. We don't use
44
+ # an optionparser above because I don't think the performance hits
45
+ # of creating a whole object are worth checking only a couple flags.
46
+ opts = OptionParser.new do |opts|
47
+ opts.banner = "Usage: vagrant [-v] [-h] command [<args>]"
48
+ opts.separator ""
49
+ opts.on("-v", "--version", "Print the version and exit.")
50
+ opts.on("-h", "--help", "Print this help.")
51
+ opts.separator ""
52
+ opts.separator "Available subcommands:"
53
+
54
+ # Add the available subcommands as separators in order to print them
55
+ # out as well.
56
+ keys = []
57
+ Vagrant.commands.each { |key, value| keys << key.to_s }
58
+
59
+ keys.sort.each do |key|
60
+ opts.separator " #{key}"
61
+ end
62
+
63
+ opts.separator ""
64
+ opts.separator "For help on any individual command run `vagrant COMMAND -h`"
52
65
  end
66
+
67
+ @env.ui.info(opts.help, :prefix => false)
53
68
  end
54
69
  end
55
70
  end
@@ -1,25 +1,23 @@
1
1
  module Vagrant
2
2
  module Command
3
3
  autoload :Base, 'vagrant/command/base'
4
- autoload :GroupBase, 'vagrant/command/group_base'
5
- autoload :Helpers, 'vagrant/command/helpers'
6
- autoload :NamedBase, 'vagrant/command/named_base'
4
+
5
+ autoload :Box, 'vagrant/command/box'
6
+ autoload :BoxAdd, 'vagrant/command/box_add'
7
+ autoload :BoxRemove, 'vagrant/command/box_remove'
8
+ autoload :BoxRepackage, 'vagrant/command/box_repackage'
9
+ autoload :BoxList, 'vagrant/command/box_list'
10
+ autoload :Destroy, 'vagrant/command/destroy'
11
+ autoload :Halt, 'vagrant/command/halt'
12
+ autoload :Init, 'vagrant/command/init'
13
+ autoload :Package, 'vagrant/command/package'
14
+ autoload :Provision, 'vagrant/command/provision'
15
+ autoload :Reload, 'vagrant/command/reload'
16
+ autoload :Resume, 'vagrant/command/resume'
17
+ autoload :SSH, 'vagrant/command/ssh'
18
+ autoload :SSHConfig, 'vagrant/command/ssh_config'
19
+ autoload :Status, 'vagrant/command/status'
20
+ autoload :Suspend, 'vagrant/command/suspend'
21
+ autoload :Up, 'vagrant/command/up'
7
22
  end
8
23
  end
9
-
10
- # The built-in commands must always be loaded
11
- require 'vagrant/command/box'
12
- require 'vagrant/command/destroy'
13
- require 'vagrant/command/halt'
14
- require 'vagrant/command/init'
15
- require 'vagrant/command/package'
16
- require 'vagrant/command/provision'
17
- require 'vagrant/command/reload'
18
- require 'vagrant/command/resume'
19
- require 'vagrant/command/ssh'
20
- require 'vagrant/command/ssh_config'
21
- require 'vagrant/command/status'
22
- require 'vagrant/command/suspend'
23
- require 'vagrant/command/up'
24
- require 'vagrant/command/upgrade_to_060'
25
- require 'vagrant/command/version'
@@ -1,105 +1,150 @@
1
- require 'thor/group'
2
- require 'thor/actions'
1
+ require 'log4r'
3
2
 
4
3
  module Vagrant
5
4
  module Command
6
- # A {Base} is the superclass for all commands which are single
7
- # commands, e.g. `vagrant init`, `vagrant up`. Not commands like
8
- # `vagrant box add`. For commands which have more subcommands, use
9
- # a {GroupBase}.
5
+ # Base class for any CLI commands.
10
6
  #
11
- # A {Base} is a subclass of `Thor::Group`, so view the documentation
12
- # there on how to add arguments, descriptions etc. The important note
13
- # about this is that when invoked, _all public methods_ will be called
14
- # in the order they are defined. If you don't want a method called when
15
- # the command is invoked, it must be made `protected` or `private`.
16
- #
17
- # The best way to get examples of how to create your own command is to
18
- # view the various Vagrant commands, which are relatively simple, and
19
- # can be found in the Vagrant source tree at `lib/vagrant/command/`.
20
- #
21
- # # Defining a New Command
22
- #
23
- # To define a new single command, create a new class which inherits
24
- # from this class, then call {register} to register the command. That's
25
- # it! When the command is invoked, _all public methods_ will be called.
26
- # Below is an example `SayHello` class:
27
- #
28
- # class SayHello < Vagrant::Command::Base
29
- # register "hello", "Says hello"
30
- #
31
- # def hello
32
- # env.ui.info "Hello"
33
- # end
34
- # end
35
- #
36
- # In this case, the above class is invokable via `vagrant hello`. To give
37
- # this a try, just copy and paste the above into a Vagrantfile somewhere.
38
- # The command will be available for that project!
39
- #
40
- # Also note that the above example uses `env.ui` to output. It is recommended
41
- # you use this instead of raw "puts" since it is configurable and provides
42
- # additional functionality, such as colors and asking for user input. See
43
- # the {UI} class for more information.
44
- #
45
- # ## Defining Command-line Options
46
- #
47
- # Most command line actions won't be as simple as `vagrant hello`, and will
48
- # probably require parameters or switches. Luckily, Thor makes adding these
49
- # easy:
50
- #
51
- # class SayHello < Vagrant::Command::Base
52
- # register "hello", "Says hello"
53
- # argument :name, :type => :string
54
- #
55
- # def hello
56
- # env.ui.info "Hello, #{name}"
57
- # end
58
- # end
59
- #
60
- # Then, the above can be invoked with `vagrant hello Mitchell` which would
61
- # output "Hello, Mitchell." If instead you're looking for switches, such as
62
- # "--name Mitchell", then take a look at `class_option`, an example of which
63
- # can be found in the {PackageCommand}.
64
- class Base < Thor::Group
65
- include Thor::Actions
66
- include Helpers
67
-
68
- attr_reader :env
69
-
70
- # Register the command with the main Vagrant CLI under the
71
- # given name. The name will be used for accessing it from the CLI,
72
- # so if you name it "lamp", then the command to invoke this
73
- # will be `vagrant lamp`.
74
- #
75
- # The description is used when the help is listed, and is meant to be
76
- # a brief (one sentence) description of what the command does.
7
+ # This class provides documentation on the interface as well as helper
8
+ # functions that a command has.
9
+ class Base
10
+ def initialize(argv, env)
11
+ @argv = argv
12
+ @env = env
13
+ @logger = Log4r::Logger.new("vagrant::command::#{self.class.to_s.downcase}")
14
+ end
15
+
16
+ # This is what is called on the class to actually execute it. Any
17
+ # subclasses should implement this method and do any option parsing
18
+ # and validation here.
19
+ def execute; end
20
+
21
+ protected
22
+
23
+ # Parses the options given an OptionParser instance.
77
24
  #
78
- # Some additional options may be passed in as the last parameter:
25
+ # This is a convenience method that properly handles duping the
26
+ # originally argv array so that it is not destroyed.
79
27
  #
80
- # * `:alias` - If given as an array or string, these will be aliases
81
- # for the same command. For example, `vagrant version` is also
82
- # `vagrant --version` and `vagrant -v`
28
+ # This method will also automatically detect "-h" and "--help"
29
+ # and print help. And if any invalid options are detected, the help
30
+ # will be printed, as well.
83
31
  #
84
- # @param [String] usage
85
- # @param [String] description
86
- # @param [Hash] opts
87
- def self.register(usage, description, opts=nil)
88
- desc description
89
- CLI.register(self, extract_name_from_usage(usage), usage, desc, opts)
32
+ # If this method returns `nil`, then you should assume that help
33
+ # was printed and parsing failed.
34
+ def parse_options(opts=nil)
35
+ # Creating a shallow copy of the arguments so the OptionParser
36
+ # doesn't destroy the originals.
37
+ argv = @argv.dup
38
+
39
+ # Default opts to a blank optionparser if none is given
40
+ opts ||= OptionParser.new
41
+
42
+ # Add the help option, which must be on every command.
43
+ opts.on_tail("-h", "--help", "Print this help") do
44
+ puts opts.help
45
+ return nil
46
+ end
47
+
48
+ opts.parse!(argv)
49
+ return argv
50
+ rescue OptionParser::InvalidOption
51
+ raise Errors::CLIInvalidOptions, :help => opts.help.chomp
90
52
  end
91
53
 
92
- def initialize(*args)
93
- super
94
- initialize_environment(*args)
54
+ # Yields a VM for each target VM for the command.
55
+ #
56
+ # This is a convenience method for easily implementing methods that
57
+ # take a target VM (in the case of multi-VM) or every VM if no
58
+ # specific VM name is specified.
59
+ #
60
+ # @param [String] name The name of the VM. Nil if every VM.
61
+ # @param [Boolean] single_target If true, then an exception will be
62
+ # raised if more than one target is found.
63
+ def with_target_vms(name=nil, single_target=false)
64
+ # Using VMs requires a Vagrant environment to be properly setup
65
+ raise Errors::NoEnvironmentError if !@env.root_path
66
+
67
+ # First determine the proper array of VMs.
68
+ vms = []
69
+ if name
70
+ raise Errors::MultiVMEnvironmentRequired if !@env.multivm?
71
+
72
+ if name =~ /^\/(.+?)\/$/
73
+ # This is a regular expression name, so we convert to a regular
74
+ # expression and allow that sort of matching.
75
+ regex = Regexp.new($1.to_s)
76
+
77
+ @env.vms.each do |name, vm|
78
+ vms << vm if name =~ regex
79
+ end
80
+
81
+ raise Errors::VMNoMatchError if vms.empty?
82
+ else
83
+ # String name, just look for a specific VM
84
+ vms << @env.vms[name.to_sym]
85
+ raise Errors::VMNotFoundError, :name => name if !vms[0]
86
+ end
87
+ else
88
+ vms = @env.vms_ordered
89
+ end
90
+
91
+ # Make sure we're only working with one VM if single target
92
+ raise Errors::MultiVMTargetRequired if single_target && vms.length != 1
93
+
94
+ # Go through each VM and yield it!
95
+ vms.each do |old_vm|
96
+ # We get a new VM from the environment here to avoid potentially
97
+ # stale VMs (if there was a config reload on the environment
98
+ # or something).
99
+ vm = @env.vms[old_vm.name]
100
+ yield vm
101
+ end
95
102
  end
96
103
 
97
- protected
104
+ # This method will split the argv given into three parts: the
105
+ # flags to this command, the subcommand, and the flags to the
106
+ # subcommand. For example:
107
+ #
108
+ # -v status -h -v
109
+ #
110
+ # The above would yield 3 parts:
111
+ #
112
+ # ["-v"]
113
+ # "status"
114
+ # ["-h", "-v"]
115
+ #
116
+ # These parts are useful because the first is a list of arguments
117
+ # given to the current command, the second is a subcommand, and the
118
+ # third are the commands given to the subcommand.
119
+ #
120
+ # @return [Array] The three parts.
121
+ def split_main_and_subcommand(argv)
122
+ # Initialize return variables
123
+ main_args = nil
124
+ sub_command = nil
125
+ sub_args = []
126
+
127
+ # We split the arguments into two: One set containing any
128
+ # flags before a word, and then the rest. The rest are what
129
+ # get actually sent on to the subcommand.
130
+ argv.each_index do |i|
131
+ if !argv[i].start_with?("-")
132
+ # We found the beginning of the sub command. Split the
133
+ # args up.
134
+ main_args = argv[0, i]
135
+ sub_command = argv[i]
136
+ sub_args = argv[i + 1, argv.length - i + 1]
137
+
138
+ # Break so we don't find the next non flag and shift our
139
+ # main args.
140
+ break
141
+ end
142
+ end
143
+
144
+ # Handle the case that argv was empty or didn't contain any subcommand
145
+ main_args = argv.dup if main_args.nil?
98
146
 
99
- # Extracts the name of the command from a usage string. Example:
100
- # `init [box_name] [box_url]` becomes just `init`.
101
- def self.extract_name_from_usage(usage)
102
- /^([-_a-zA-Z0-9]+)(\s+(.+?))?$/.match(usage).to_a[1]
147
+ return [main_args, sub_command, sub_args]
103
148
  end
104
149
  end
105
150
  end