vagrantup 0.4.3.dev → 0.5.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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/config/default.rb +6 -6
  4. data/lib/vagrant.rb +6 -3
  5. data/lib/vagrant/action.rb +77 -0
  6. data/lib/vagrant/action/action_exception.rb +16 -0
  7. data/lib/vagrant/action/box/destroy.rb +19 -0
  8. data/lib/vagrant/action/box/download.rb +78 -0
  9. data/lib/vagrant/action/box/unpackage.rb +58 -0
  10. data/lib/vagrant/action/box/verify.rb +23 -0
  11. data/lib/vagrant/action/builder.rb +151 -0
  12. data/lib/vagrant/action/builtin.rb +114 -0
  13. data/lib/vagrant/action/env/error_halt.rb +16 -0
  14. data/lib/vagrant/action/env/set.rb +18 -0
  15. data/lib/vagrant/action/environment.rb +98 -0
  16. data/lib/vagrant/action/exception_catcher.rb +14 -0
  17. data/lib/vagrant/action/vm/boot.rb +54 -0
  18. data/lib/vagrant/action/vm/check_box.rb +27 -0
  19. data/lib/vagrant/action/vm/check_guest_additions.rb +32 -0
  20. data/lib/vagrant/action/vm/clean_machine_folder.rb +43 -0
  21. data/lib/vagrant/action/vm/clear_forwarded_ports.rb +39 -0
  22. data/lib/vagrant/action/vm/clear_nfs_exports.rb +20 -0
  23. data/lib/vagrant/action/vm/clear_shared_folders.rb +32 -0
  24. data/lib/vagrant/action/vm/customize.rb +21 -0
  25. data/lib/vagrant/action/vm/destroy.rb +20 -0
  26. data/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb +35 -0
  27. data/lib/vagrant/action/vm/disable_networks.rb +26 -0
  28. data/lib/vagrant/action/vm/export.rb +53 -0
  29. data/lib/vagrant/action/vm/forward_ports.rb +121 -0
  30. data/lib/vagrant/action/vm/forward_ports_helpers.rb +28 -0
  31. data/lib/vagrant/action/vm/halt.rb +34 -0
  32. data/lib/vagrant/action/vm/import.rb +33 -0
  33. data/lib/vagrant/action/vm/match_mac_address.rb +19 -0
  34. data/lib/vagrant/{actions → action}/vm/network.rb +47 -55
  35. data/lib/vagrant/action/vm/nfs.rb +161 -0
  36. data/lib/vagrant/action/vm/nfs_helpers.rb +11 -0
  37. data/lib/vagrant/action/vm/package.rb +99 -0
  38. data/lib/vagrant/action/vm/persist.rb +22 -0
  39. data/lib/vagrant/action/vm/provision.rb +50 -0
  40. data/lib/vagrant/action/vm/resume.rb +20 -0
  41. data/lib/vagrant/{actions/vm/shared_folders.rb → action/vm/share_folders.rb} +48 -45
  42. data/lib/vagrant/action/vm/suspend.rb +20 -0
  43. data/lib/vagrant/box.rb +3 -7
  44. data/lib/vagrant/commands/base.rb +1 -3
  45. data/lib/vagrant/commands/package.rb +4 -9
  46. data/lib/vagrant/commands/up.rb +0 -2
  47. data/lib/vagrant/config.rb +15 -1
  48. data/lib/vagrant/downloaders/file.rb +1 -1
  49. data/lib/vagrant/downloaders/http.rb +2 -1
  50. data/lib/vagrant/environment.rb +18 -14
  51. data/lib/vagrant/hosts/base.rb +77 -0
  52. data/lib/vagrant/hosts/bsd.rb +53 -0
  53. data/lib/vagrant/hosts/linux.rb +52 -0
  54. data/lib/vagrant/provisioners/base.rb +17 -9
  55. data/lib/vagrant/provisioners/chef.rb +1 -1
  56. data/lib/vagrant/provisioners/chef_server.rb +4 -8
  57. data/lib/vagrant/provisioners/chef_solo.rb +1 -2
  58. data/lib/vagrant/ssh.rb +12 -4
  59. data/lib/vagrant/systems/base.rb +4 -0
  60. data/lib/vagrant/systems/linux.rb +12 -1
  61. data/lib/vagrant/util.rb +16 -0
  62. data/lib/vagrant/util/busy.rb +59 -0
  63. data/lib/vagrant/util/plain_logger.rb +11 -0
  64. data/lib/vagrant/util/platform.rb +18 -0
  65. data/lib/vagrant/util/resource_logger.rb +128 -0
  66. data/lib/vagrant/version.rb +6 -0
  67. data/lib/vagrant/vm.rb +10 -12
  68. data/templates/chef_solo_solo.erb +2 -1
  69. data/templates/nfs/exports.erb +3 -0
  70. data/templates/nfs/exports_linux.erb +3 -0
  71. data/templates/strings.yml +23 -3
  72. metadata +121 -196
  73. data/.gitignore +0 -11
  74. data/Gemfile +0 -18
  75. data/Rakefile +0 -41
  76. data/VERSION +0 -1
  77. data/bin/.gitignore +0 -0
  78. data/lib/vagrant/actions/base.rb +0 -130
  79. data/lib/vagrant/actions/box/add.rb +0 -23
  80. data/lib/vagrant/actions/box/destroy.rb +0 -14
  81. data/lib/vagrant/actions/box/download.rb +0 -67
  82. data/lib/vagrant/actions/box/unpackage.rb +0 -42
  83. data/lib/vagrant/actions/box/verify.rb +0 -32
  84. data/lib/vagrant/actions/collection.rb +0 -36
  85. data/lib/vagrant/actions/runner.rb +0 -131
  86. data/lib/vagrant/actions/vm/boot.rb +0 -43
  87. data/lib/vagrant/actions/vm/customize.rb +0 -19
  88. data/lib/vagrant/actions/vm/destroy.rb +0 -24
  89. data/lib/vagrant/actions/vm/down.rb +0 -22
  90. data/lib/vagrant/actions/vm/export.rb +0 -45
  91. data/lib/vagrant/actions/vm/forward_ports.rb +0 -134
  92. data/lib/vagrant/actions/vm/halt.rb +0 -24
  93. data/lib/vagrant/actions/vm/import.rb +0 -23
  94. data/lib/vagrant/actions/vm/move_hard_drive.rb +0 -51
  95. data/lib/vagrant/actions/vm/package.rb +0 -94
  96. data/lib/vagrant/actions/vm/provision.rb +0 -49
  97. data/lib/vagrant/actions/vm/reload.rb +0 -17
  98. data/lib/vagrant/actions/vm/resume.rb +0 -16
  99. data/lib/vagrant/actions/vm/start.rb +0 -26
  100. data/lib/vagrant/actions/vm/suspend.rb +0 -16
  101. data/lib/vagrant/actions/vm/up.rb +0 -53
  102. data/lib/vagrant/busy.rb +0 -79
  103. data/lib/vagrant/resource_logger.rb +0 -126
  104. data/lib/vagrant/util/error_helper.rb +0 -13
  105. data/lib/vagrant/util/output_helper.rb +0 -9
  106. data/test/test_helper.rb +0 -149
  107. data/test/vagrant/actions/base_test.rb +0 -32
  108. data/test/vagrant/actions/box/add_test.rb +0 -36
  109. data/test/vagrant/actions/box/destroy_test.rb +0 -17
  110. data/test/vagrant/actions/box/download_test.rb +0 -137
  111. data/test/vagrant/actions/box/unpackage_test.rb +0 -99
  112. data/test/vagrant/actions/box/verify_test.rb +0 -44
  113. data/test/vagrant/actions/collection_test.rb +0 -113
  114. data/test/vagrant/actions/runner_test.rb +0 -268
  115. data/test/vagrant/actions/vm/boot_test.rb +0 -49
  116. data/test/vagrant/actions/vm/customize_test.rb +0 -21
  117. data/test/vagrant/actions/vm/destroy_test.rb +0 -37
  118. data/test/vagrant/actions/vm/down_test.rb +0 -39
  119. data/test/vagrant/actions/vm/export_test.rb +0 -88
  120. data/test/vagrant/actions/vm/forward_ports_test.rb +0 -253
  121. data/test/vagrant/actions/vm/halt_test.rb +0 -65
  122. data/test/vagrant/actions/vm/import_test.rb +0 -45
  123. data/test/vagrant/actions/vm/move_hard_drive_test.rb +0 -106
  124. data/test/vagrant/actions/vm/network_test.rb +0 -291
  125. data/test/vagrant/actions/vm/package_test.rb +0 -254
  126. data/test/vagrant/actions/vm/provision_test.rb +0 -99
  127. data/test/vagrant/actions/vm/reload_test.rb +0 -46
  128. data/test/vagrant/actions/vm/resume_test.rb +0 -26
  129. data/test/vagrant/actions/vm/shared_folders_test.rb +0 -211
  130. data/test/vagrant/actions/vm/start_test.rb +0 -73
  131. data/test/vagrant/actions/vm/suspend_test.rb +0 -26
  132. data/test/vagrant/actions/vm/up_test.rb +0 -96
  133. data/test/vagrant/active_list_test.rb +0 -173
  134. data/test/vagrant/box_test.rb +0 -154
  135. data/test/vagrant/busy_test.rb +0 -78
  136. data/test/vagrant/command_test.rb +0 -53
  137. data/test/vagrant/commands/base_test.rb +0 -139
  138. data/test/vagrant/commands/box/add_test.rb +0 -34
  139. data/test/vagrant/commands/box/list_test.rb +0 -32
  140. data/test/vagrant/commands/box/remove_test.rb +0 -41
  141. data/test/vagrant/commands/destroy_test.rb +0 -44
  142. data/test/vagrant/commands/halt_test.rb +0 -50
  143. data/test/vagrant/commands/init_test.rb +0 -55
  144. data/test/vagrant/commands/package_test.rb +0 -104
  145. data/test/vagrant/commands/provision_test.rb +0 -60
  146. data/test/vagrant/commands/reload_test.rb +0 -44
  147. data/test/vagrant/commands/resume_test.rb +0 -44
  148. data/test/vagrant/commands/ssh_config_test.rb +0 -77
  149. data/test/vagrant/commands/ssh_test.rb +0 -129
  150. data/test/vagrant/commands/status_test.rb +0 -40
  151. data/test/vagrant/commands/suspend_test.rb +0 -44
  152. data/test/vagrant/commands/up_test.rb +0 -47
  153. data/test/vagrant/config_test.rb +0 -287
  154. data/test/vagrant/downloaders/base_test.rb +0 -28
  155. data/test/vagrant/downloaders/file_test.rb +0 -33
  156. data/test/vagrant/downloaders/http_test.rb +0 -62
  157. data/test/vagrant/environment_test.rb +0 -770
  158. data/test/vagrant/provisioners/base_test.rb +0 -33
  159. data/test/vagrant/provisioners/chef_server_test.rb +0 -176
  160. data/test/vagrant/provisioners/chef_solo_test.rb +0 -183
  161. data/test/vagrant/provisioners/chef_test.rb +0 -175
  162. data/test/vagrant/resource_logger_test.rb +0 -145
  163. data/test/vagrant/ssh_session_test.rb +0 -46
  164. data/test/vagrant/ssh_test.rb +0 -296
  165. data/test/vagrant/systems/linux_test.rb +0 -179
  166. data/test/vagrant/util/error_helper_test.rb +0 -5
  167. data/test/vagrant/util/output_helper_test.rb +0 -5
  168. data/test/vagrant/util/plain_logger_test.rb +0 -17
  169. data/test/vagrant/util/platform_test.rb +0 -18
  170. data/test/vagrant/util/stacked_proc_runner_test.rb +0 -43
  171. data/test/vagrant/util/template_renderer_test.rb +0 -144
  172. data/test/vagrant/util/translator_test.rb +0 -61
  173. data/test/vagrant/util_test.rb +0 -27
  174. data/test/vagrant/vm_test.rb +0 -235
  175. data/vagrant.gemspec +0 -291
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4d485f02b4c6701bc3480af690f847ca1b6a774f
4
- data.tar.gz: 3d77d7c1035b7488ce588a2831b539fae889bca6
3
+ metadata.gz: b5919826f09f53bdfac384281bed18f97fc4967d
4
+ data.tar.gz: d5832323003e80dd65689d28c8247e362d399946
5
5
  SHA512:
6
- metadata.gz: 1b7cafe48f0ca5431eda69e78afc18b8da67824b817b0f95bc4a3a3fa8eee128313cfd94d343536ba62f619184042eece42ba5f987114c07952a35bbdba0f302
7
- data.tar.gz: 81fb6df77278bf24dbaa0165b4aefe14633df1fa020bea1678e33b441324ccb1ab9b728a30f51e77f3ed97815bece5e0f9d1d9e6e430ebccc7443c57025ea534
6
+ metadata.gz: 4aca6e7ce3d461cba9e9aae477d09516441ae9562141a49c6d77aa77796987374cc509a2d088be6ce8e1ed8829c4b77c7b14a287a2d51ac5f33bcd1659d10d70
7
+ data.tar.gz: 5036c5c3487329e82f3cb4d8c67b362e07221eb33512b7231d8bcb63424cbfed150a331e9f704dfe9ea3125d5999c4ae1c565d6fface8103ced08c061fe2e6b0
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Vagrant
2
2
 
3
3
  * Website: [http://vagrantup.com](http://vagrantup.com)
4
+ * Source: [http://github.com/mitchellh/vagrant](http://github.com/mitchellh/vagrant)
4
5
  * IRC: `#vagrant` on Freenode
5
6
  * Mailng list: [Google Groups](http://groups.google.com/group/vagrant-up)
6
7
 
@@ -3,6 +3,7 @@ Vagrant::Config.run do |config|
3
3
  config.vagrant.log_output = STDOUT
4
4
  config.vagrant.dotfile_name = ".vagrant"
5
5
  config.vagrant.home = "~/.vagrant"
6
+ config.vagrant.host = :detect
6
7
 
7
8
  config.ssh.username = "vagrant"
8
9
  config.ssh.host = "localhost"
@@ -11,9 +12,11 @@ Vagrant::Config.run do |config|
11
12
  config.ssh.max_tries = 10
12
13
  config.ssh.timeout = 30
13
14
  config.ssh.private_key_path = File.join(PROJECT_ROOT, 'keys', 'vagrant')
15
+ config.ssh.forward_agent = false
14
16
 
15
17
  config.vm.auto_port_range = (2200..2250)
16
18
  config.vm.box_ovf = "box.ovf"
19
+ config.vm.box_url = nil
17
20
  config.vm.base_mac = "0800279C2E42"
18
21
  config.vm.forward_port("ssh", 22, 2222, :auto => true)
19
22
  config.vm.disk_image_format = 'VMDK'
@@ -33,11 +36,8 @@ Vagrant::Config.run do |config|
33
36
  config.unison.crontab_entry_file = "/tmp/vagrant-unison-crontab"
34
37
  config.unison.log_file = "/tmp/v-unison-log-%s"
35
38
 
36
- # TODO fix these
37
- # config.vm.sync_opts = "-terse -group -owner -batch -silent"
38
- # config.vm.sync_script = "/tmp/sync"
39
- # config.vm.sync_crontab_entry_file = "/tmp/crontab-entry"
39
+ config.nfs.map_uid = :auto
40
+ config.nfs.map_gid = :auto
40
41
 
41
- config.package.name = 'vagrant'
42
- config.package.extension = '.box'
42
+ config.package.name = 'package.box'
43
43
  end
@@ -11,6 +11,9 @@ end
11
11
  require File.expand_path("util/glob_loader", libdir)
12
12
 
13
13
  # Load them up
14
- Vagrant::GlobLoader.glob_require(libdir, %w{util/stacked_proc_runner
15
- actions/base downloaders/base actions/collection actions/runner config
16
- provisioners/base provisioners/chef systems/base commands/base commands/box})
14
+ Vagrant::GlobLoader.glob_require(libdir, %w{util util/stacked_proc_runner
15
+ downloaders/base config provisioners/base provisioners/chef systems/base
16
+ commands/base commands/box action/exception_catcher hosts/base})
17
+
18
+ # Initialize the built-in actions
19
+ Vagrant::Action.builtin!
@@ -0,0 +1,77 @@
1
+ module Vagrant
2
+ # Manages action running and registration. Every Vagrant environment
3
+ # has an instance of {Action} to allow for running in the context of
4
+ # the environment.
5
+ class Action
6
+ include Util
7
+
8
+ class << self
9
+ # Returns the list of registered actions.
10
+ def actions
11
+ @actions ||= {}
12
+ end
13
+
14
+ # Registers an action and associates it with a symbol. This
15
+ # symbol can then be referenced in other action builds and
16
+ # callbacks can be registered on that symbol.
17
+ #
18
+ # @param [Symbol] key
19
+ def register(key, callable)
20
+ actions[key] = callable
21
+ end
22
+
23
+ # Retrieves a registered action by key.
24
+ def [](key)
25
+ actions[key]
26
+ end
27
+ end
28
+
29
+ # The environment to run the actions in.
30
+ attr_reader :env
31
+
32
+ # Initializes the action with the given environment which the actions
33
+ # will be run in.
34
+ #
35
+ # @param [Environment] env
36
+ def initialize(env)
37
+ @env = env
38
+ end
39
+
40
+ # Runs the given callable object in the context of the environment.
41
+ # If a symbol is given as the `callable` parameter, then it is looked
42
+ # up in the registered actions list which are registered with {register}.
43
+ #
44
+ # @param [Object] callable An object which responds to `call`.
45
+ def run(callable, options=nil)
46
+ callable = Builder.new.use(callable) if callable.kind_of?(Class)
47
+ callable = self.class.actions[callable] if callable.kind_of?(Symbol)
48
+
49
+ action_environment = Action::Environment.new(env)
50
+ action_environment.merge!(options || {})
51
+
52
+ # Run the action chain in a busy block, marking the environment as
53
+ # interrupted if a SIGINT occurs, and exiting cleanly once the
54
+ # chain has been run.
55
+ int_callback = lambda do
56
+ if action_environment.interrupted?
57
+ env.logger.info "Exiting immediately!"
58
+ abort
59
+ end
60
+
61
+ env.logger.info "Waiting for cleanup before exiting..."
62
+ action_environment.error!(:interrupt)
63
+ end
64
+
65
+ Busy.busy(int_callback) { callable.call(action_environment) }
66
+ exit if action_environment.interrupted?
67
+
68
+ if action_environment.error?
69
+ # Erroneous environment resulted. Properly display error
70
+ # message.
71
+ key, options = action_environment.error
72
+ error_and_exit(key, options)
73
+ return false
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,16 @@
1
+ module Vagrant
2
+ class Action
3
+ class ActionException < Exception
4
+ attr_reader :key
5
+ attr_reader :data
6
+
7
+ def initialize(key, data = {})
8
+ @key = key
9
+ @data = data
10
+
11
+ message = Vagrant::Util::Translator.t(key, data)
12
+ super(message)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module Vagrant
2
+ class Action
3
+ module Box
4
+ class Destroy
5
+ def initialize(app, env)
6
+ @app = app
7
+ @env = env
8
+ end
9
+
10
+ def call(env)
11
+ env.logger.info "Deleting box directory..."
12
+ FileUtils.rm_rf(env["box"].directory)
13
+
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,78 @@
1
+ module Vagrant
2
+ class Action
3
+ module Box
4
+ class Download
5
+ BASENAME = "box"
6
+
7
+ include Util
8
+
9
+ attr_reader :temp_path
10
+
11
+ def initialize(app, env)
12
+ @app = app
13
+ @env = env
14
+ @env["download.classes"] ||= []
15
+ @env["download.classes"] += [Downloaders::HTTP, Downloaders::File]
16
+ end
17
+
18
+ def call(env)
19
+ @env = env
20
+
21
+ download if instantiate_downloader
22
+ return if env.error?
23
+
24
+ @app.call(@env)
25
+
26
+ cleanup
27
+ end
28
+
29
+ def instantiate_downloader
30
+ @env["download.classes"].each do |klass|
31
+ if klass.match?(@env["box"].uri)
32
+ @env.logger.info "Downloading with #{klass}..."
33
+ @downloader = klass.new(@env)
34
+ end
35
+ end
36
+
37
+ if !@downloader
38
+ @env.error!(:box_download_unknown_type)
39
+ return false
40
+ end
41
+
42
+ @downloader.prepare(@env["box"].uri)
43
+ true
44
+ end
45
+
46
+ def download
47
+ with_tempfile do |tempfile|
48
+ download_to(tempfile)
49
+ @temp_path = @env["download.temp_path"] = tempfile.path
50
+ end
51
+ end
52
+
53
+ def cleanup
54
+ if temp_path && File.exist?(temp_path)
55
+ @env.logger.info "Cleaning up downloaded box..."
56
+ File.unlink(temp_path)
57
+ end
58
+ end
59
+
60
+ def with_tempfile
61
+ @env.logger.info "Creating tempfile for storing box file..."
62
+ File.open(box_temp_path, Platform.tar_file_options) do |tempfile|
63
+ yield tempfile
64
+ end
65
+ end
66
+
67
+ def box_temp_path
68
+ File.join(@env.env.tmp_path, BASENAME + Time.now.to_i.to_s)
69
+ end
70
+
71
+ def download_to(f)
72
+ @env.logger.info "Copying box to temporary location..."
73
+ @downloader.download!(@env["box"].uri, f)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,58 @@
1
+ module Vagrant
2
+ class Action
3
+ module Box
4
+ # Unpackages a downloaded box to a given directory with a given
5
+ # name.
6
+ #
7
+ # # Required Variables
8
+ #
9
+ # * `download.temp_path` - A location for the downloaded box. This is
10
+ # set by the {Download} action.
11
+ # * `box` - A {Vagrant::Box} object.
12
+ #
13
+ class Unpackage
14
+ attr_reader :box_directory
15
+
16
+ def initialize(app, env)
17
+ @app = app
18
+ @env = env
19
+ end
20
+
21
+ def call(env)
22
+ @env = env
23
+
24
+ return if !setup_box_directory
25
+ decompress
26
+
27
+ @app.call(@env)
28
+
29
+ cleanup if @env.error?
30
+ end
31
+
32
+ def cleanup
33
+ if File.directory?(box_directory)
34
+ FileUtils.rm_rf(box_directory)
35
+ end
36
+ end
37
+
38
+ def setup_box_directory
39
+ if File.directory?(@env["box"].directory)
40
+ @env.error!(:box_already_exists, :box_name => @env["box"].name)
41
+ return false
42
+ end
43
+
44
+ FileUtils.mkdir_p(@env["box"].directory)
45
+ @box_directory = @env["box"].directory
46
+ true
47
+ end
48
+
49
+ def decompress
50
+ Dir.chdir(@env["box"].directory) do
51
+ @env.logger.info "Extracting box to #{@env["box"].directory}..."
52
+ Archive::Tar::Minitar.unpack(@env["download.temp_path"], @env["box"].directory)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,23 @@
1
+ module Vagrant
2
+ class Action
3
+ module Box
4
+ class Verify
5
+ def initialize(app, env)
6
+ @app = app
7
+ @env = env
8
+ end
9
+
10
+ def call(env)
11
+ begin
12
+ env.logger.info "Verifying box..."
13
+ VirtualBox::Appliance.new(env["box"].ovf_file)
14
+ rescue Exception
15
+ return env.error!(:box_verification_failed)
16
+ end
17
+
18
+ @app.call(env)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,151 @@
1
+ module Vagrant
2
+ class Action
3
+ # Action builder which provides a nice DSL for building up
4
+ # a middleware sequence for Vagrant actions. This code is based
5
+ # heavily off of `Rack::Builder` and `ActionDispatch::MiddlewareStack`
6
+ # in Rack and Rails, respectively.
7
+ #
8
+ # Usage
9
+ #
10
+ # Building an action sequence is very easy:
11
+ #
12
+ # app = Vagrant::Action::Builder.new do
13
+ # use MiddlewareA
14
+ # use MiddlewareB
15
+ # end
16
+ #
17
+ # Vagrant::Action.run(app)
18
+ #
19
+ class Builder
20
+ # Initializes the builder. An optional block can be passed which
21
+ # will be evaluated in the context of the instance.
22
+ def initialize(&block)
23
+ instance_eval(&block) if block_given?
24
+ end
25
+
26
+ # Returns the current stack of middlewares. You probably won't
27
+ # need to use this directly, and its recommended that you don't.
28
+ #
29
+ # @return [Array]
30
+ def stack
31
+ @stack ||= []
32
+ end
33
+
34
+ # Returns a mergeable version of the builder. If `use` is called with
35
+ # the return value of this method, then the stack will merge, instead
36
+ # of being treated as a separate single middleware.
37
+ def flatten
38
+ lambda do |env|
39
+ self.call(env)
40
+ end
41
+ end
42
+
43
+ # Adds a middleware class to the middleware stack. Any additional
44
+ # args and a block, if given, are saved and passed to the initializer
45
+ # of the middleware.
46
+ #
47
+ # @param [Class] middleware The middleware class
48
+ def use(middleware, *args, &block)
49
+ if middleware.kind_of?(Builder)
50
+ # Prepend with a environment setter if args are given
51
+ self.use(Env::Set, *args, &block) if !args.empty? && args.first.is_a?(Hash)
52
+
53
+ # Merge in the other builder's stack into our own
54
+ self.stack.concat(middleware.stack)
55
+ else
56
+ self.stack << [middleware, args, block]
57
+ end
58
+
59
+ self
60
+ end
61
+
62
+ # Inserts a middleware at the given index or directly before the
63
+ # given middleware object.
64
+ def insert(index, middleware, *args, &block)
65
+ index = self.index(index) unless index.is_a?(Integer)
66
+ stack.insert(index, [middleware, args, block])
67
+ end
68
+
69
+ alias_method :insert_before, :insert
70
+
71
+ # Inserts a middleware after the given index or middleware object.
72
+ def insert_after(index, middleware, *args, &block)
73
+ index = self.index(index) unless index.is_a?(Integer)
74
+ raise "no such middleware to insert after: #{index.inspect}" unless index
75
+ insert(index + 1, middleware, *args, &block)
76
+ end
77
+
78
+ # Swaps out the given middlware object or index with the new
79
+ # middleware.
80
+ def swap(index, middleware, *args, &block)
81
+ if index.is_a?(Integer)
82
+ delete(index)
83
+ insert(index, middleware, *args, &block)
84
+ else
85
+ insert_before(index, middleware, *args, &block)
86
+ delete(index)
87
+ end
88
+ end
89
+
90
+ # Deletes the given middleware object or index
91
+ def delete(index)
92
+ index = self.index(index) unless index.is_a?(Integer)
93
+ stack.delete_at(index)
94
+ end
95
+
96
+ # Returns the numeric index for the given middleware object.
97
+ #
98
+ # @param [Object] object The item to find the index for
99
+ # @return [Integer]
100
+ def index(object)
101
+ stack.each_with_index do |item, i|
102
+ return i if item[0] == object
103
+ end
104
+
105
+ nil
106
+ end
107
+
108
+ # Converts the builder stack to a runnable action sequence.
109
+ #
110
+ # @param [Vagrant::Action::Environment] env The action environment
111
+ # @return [Object] A callable object
112
+ def to_app(env)
113
+ # Prepend the error halt task so errneous environments are halted
114
+ # before the chain even begins.
115
+ items = stack.dup.unshift([Env::ErrorHalt, [], nil])
116
+
117
+ # Convert each middleware into a lambda which takes the next
118
+ # middleware.
119
+ items = items.collect do |item|
120
+ klass, args, block = item
121
+
122
+ lambda do |app|
123
+ if klass.is_a?(Class)
124
+ # A middleware klass which is to be instantiated with the
125
+ # app, env, and any arguments given
126
+ klass.new(app, env, *args, &block)
127
+ elsif klass.respond_to?(:call)
128
+ # Make it a lambda which calls the item then forwards
129
+ # up the chain
130
+ lambda do |e|
131
+ klass.call(e)
132
+ app.call(e)
133
+ end
134
+ else
135
+ raise "Invalid middleware: #{item.inspect}"
136
+ end
137
+ end
138
+ end
139
+
140
+ # Append the final step and convert into flattened call chain.
141
+ items << lambda { |env| }
142
+ items[0...-1].reverse.inject(items.last) { |a,e| e.call(a) }
143
+ end
144
+
145
+ # Runs the builder stack with the given environment.
146
+ def call(env)
147
+ to_app(env).call(env)
148
+ end
149
+ end
150
+ end
151
+ end