vagrant 0.2.0 → 0.3.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.
- data/Gemfile +4 -4
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/bin/vagrant +5 -13
- data/config/default.rb +1 -0
- data/keys/README.md +8 -1
- data/keys/vagrant.ppk +26 -0
- data/lib/vagrant.rb +3 -3
- data/lib/vagrant/actions/base.rb +15 -4
- data/lib/vagrant/actions/box/add.rb +1 -1
- data/lib/vagrant/actions/box/download.rb +72 -66
- data/lib/vagrant/actions/box/unpackage.rb +1 -4
- data/lib/vagrant/actions/runner.rb +1 -1
- data/lib/vagrant/actions/vm/boot.rb +5 -7
- data/lib/vagrant/actions/vm/customize.rb +2 -2
- data/lib/vagrant/actions/vm/destroy.rb +2 -2
- data/lib/vagrant/actions/vm/down.rb +7 -0
- data/lib/vagrant/actions/vm/export.rb +10 -4
- data/lib/vagrant/actions/vm/forward_ports.rb +5 -15
- data/lib/vagrant/actions/vm/halt.rb +5 -3
- data/lib/vagrant/actions/vm/import.rb +10 -3
- data/lib/vagrant/actions/vm/move_hard_drive.rb +1 -3
- data/lib/vagrant/actions/vm/package.rb +33 -10
- data/lib/vagrant/actions/vm/provision.rb +4 -4
- data/lib/vagrant/actions/vm/reload.rb +1 -1
- data/lib/vagrant/actions/vm/resume.rb +1 -1
- data/lib/vagrant/actions/vm/shared_folders.rb +7 -7
- data/lib/vagrant/actions/vm/start.rb +3 -2
- data/lib/vagrant/actions/vm/suspend.rb +2 -2
- data/lib/vagrant/actions/vm/up.rb +7 -17
- data/lib/vagrant/active_list.rb +52 -45
- data/lib/vagrant/box.rb +18 -11
- data/lib/vagrant/busy.rb +7 -0
- data/lib/vagrant/command.rb +27 -0
- data/lib/vagrant/commands/base.rb +163 -0
- data/lib/vagrant/commands/box.rb +16 -0
- data/lib/vagrant/commands/box/add.rb +24 -0
- data/lib/vagrant/commands/box/list.rb +30 -0
- data/lib/vagrant/commands/box/remove.rb +31 -0
- data/lib/vagrant/commands/destroy.rb +23 -0
- data/lib/vagrant/commands/down.rb +16 -0
- data/lib/vagrant/commands/halt.rb +23 -0
- data/lib/vagrant/commands/init.rb +32 -0
- data/lib/vagrant/commands/package.rb +46 -0
- data/lib/vagrant/commands/reload.rb +22 -0
- data/lib/vagrant/commands/resume.rb +22 -0
- data/lib/vagrant/commands/ssh.rb +22 -0
- data/lib/vagrant/commands/ssh_config.rb +30 -0
- data/lib/vagrant/commands/status.rb +58 -0
- data/lib/vagrant/commands/suspend.rb +23 -0
- data/lib/vagrant/commands/up.rb +26 -0
- data/lib/vagrant/config.rb +21 -11
- data/lib/vagrant/downloaders/file.rb +5 -5
- data/lib/vagrant/downloaders/http.rb +10 -15
- data/lib/vagrant/environment.rb +259 -0
- data/lib/vagrant/provisioners/base.rb +7 -0
- data/lib/vagrant/provisioners/chef.rb +24 -9
- data/lib/vagrant/provisioners/chef_server.rb +23 -48
- data/lib/vagrant/provisioners/chef_solo.rb +48 -22
- data/lib/vagrant/ssh.rb +95 -46
- data/lib/vagrant/util.rb +2 -2
- data/lib/vagrant/util/errors.rb +36 -0
- data/lib/vagrant/util/platform.rb +12 -0
- data/lib/vagrant/util/progress_meter.rb +33 -0
- data/lib/vagrant/util/stacked_proc_runner.rb +35 -0
- data/lib/vagrant/util/template_renderer.rb +83 -0
- data/lib/vagrant/vm.rb +1 -0
- data/templates/{Vagrantfile → Vagrantfile.erb} +2 -2
- data/templates/chef_server_client.erb +16 -0
- data/templates/chef_solo_solo.erb +4 -0
- data/templates/errors.yml +157 -0
- data/templates/package_Vagrantfile.erb +11 -0
- data/templates/ssh_config.erb +7 -0
- data/test/test_helper.rb +12 -15
- data/test/vagrant/actions/box/add_test.rb +1 -2
- data/test/vagrant/actions/box/destroy_test.rb +0 -1
- data/test/vagrant/actions/box/download_test.rb +40 -15
- data/test/vagrant/actions/box/unpackage_test.rb +2 -3
- data/test/vagrant/actions/collection_test.rb +8 -5
- data/test/vagrant/actions/runner_test.rb +8 -6
- data/test/vagrant/actions/vm/boot_test.rb +12 -11
- data/test/vagrant/actions/vm/customize_test.rb +2 -3
- data/test/vagrant/actions/vm/destroy_test.rb +2 -3
- data/test/vagrant/actions/vm/down_test.rb +16 -3
- data/test/vagrant/actions/vm/export_test.rb +4 -5
- data/test/vagrant/actions/vm/forward_ports_test.rb +6 -5
- data/test/vagrant/actions/vm/halt_test.rb +8 -2
- data/test/vagrant/actions/vm/import_test.rb +5 -5
- data/test/vagrant/actions/vm/move_hard_drive_test.rb +4 -6
- data/test/vagrant/actions/vm/package_test.rb +60 -22
- data/test/vagrant/actions/vm/provision_test.rb +7 -16
- data/test/vagrant/actions/vm/reload_test.rb +3 -2
- data/test/vagrant/actions/vm/resume_test.rb +0 -1
- data/test/vagrant/actions/vm/shared_folders_test.rb +17 -12
- data/test/vagrant/actions/vm/start_test.rb +10 -3
- data/test/vagrant/actions/vm/suspend_test.rb +1 -2
- data/test/vagrant/actions/vm/up_test.rb +19 -11
- data/test/vagrant/active_list_test.rb +148 -129
- data/test/vagrant/box_test.rb +26 -14
- data/test/vagrant/busy_test.rb +15 -6
- data/test/vagrant/command_test.rb +53 -0
- data/test/vagrant/commands/base_test.rb +118 -0
- data/test/vagrant/commands/box/add_test.rb +34 -0
- data/test/vagrant/commands/box/list_test.rb +32 -0
- data/test/vagrant/commands/box/remove_test.rb +41 -0
- data/test/vagrant/commands/destroy_test.rb +32 -0
- data/test/vagrant/commands/down_test.rb +17 -0
- data/test/vagrant/commands/halt_test.rb +28 -0
- data/test/vagrant/commands/init_test.rb +55 -0
- data/test/vagrant/commands/package_test.rb +84 -0
- data/test/vagrant/commands/reload_test.rb +28 -0
- data/test/vagrant/commands/resume_test.rb +33 -0
- data/test/vagrant/commands/ssh_config_test.rb +54 -0
- data/test/vagrant/commands/ssh_test.rb +32 -0
- data/test/vagrant/commands/status_test.rb +20 -0
- data/test/vagrant/commands/suspend_test.rb +33 -0
- data/test/vagrant/commands/up_test.rb +41 -0
- data/test/vagrant/config_test.rb +42 -17
- data/test/vagrant/downloaders/file_test.rb +7 -0
- data/test/vagrant/downloaders/http_test.rb +12 -0
- data/test/vagrant/environment_test.rb +595 -0
- data/test/vagrant/provisioners/base_test.rb +7 -1
- data/test/vagrant/provisioners/chef_server_test.rb +41 -51
- data/test/vagrant/provisioners/chef_solo_test.rb +93 -62
- data/test/vagrant/provisioners/chef_test.rb +61 -15
- data/test/vagrant/ssh_test.rb +166 -38
- data/test/vagrant/util/errors_test.rb +57 -0
- data/test/vagrant/util/progress_meter_test.rb +33 -0
- data/test/vagrant/{stacked_proc_runner_test.rb → util/stacked_proc_runner_test.rb} +3 -3
- data/test/vagrant/util/template_renderer_test.rb +138 -0
- data/test/vagrant/vm_test.rb +3 -2
- data/vagrant.gemspec +88 -33
- metadata +94 -51
- data/bin/vagrant-box +0 -34
- data/bin/vagrant-down +0 -27
- data/bin/vagrant-halt +0 -28
- data/bin/vagrant-init +0 -27
- data/bin/vagrant-package +0 -29
- data/bin/vagrant-reload +0 -29
- data/bin/vagrant-resume +0 -27
- data/bin/vagrant-ssh +0 -27
- data/bin/vagrant-status +0 -29
- data/bin/vagrant-suspend +0 -27
- data/bin/vagrant-up +0 -29
- data/lib/vagrant/commands.rb +0 -234
- data/lib/vagrant/env.rb +0 -189
- data/lib/vagrant/stacked_proc_runner.rb +0 -33
- data/test/vagrant/commands_test.rb +0 -269
- data/test/vagrant/env_test.rb +0 -418
@@ -4,6 +4,7 @@ module Vagrant
|
|
4
4
|
class ChefSolo < Chef
|
5
5
|
def prepare
|
6
6
|
share_cookbook_folders
|
7
|
+
share_role_folders
|
7
8
|
end
|
8
9
|
|
9
10
|
def provision!
|
@@ -15,24 +16,28 @@ module Vagrant
|
|
15
16
|
|
16
17
|
def share_cookbook_folders
|
17
18
|
host_cookbook_paths.each_with_index do |cookbook, i|
|
18
|
-
|
19
|
+
env.config.vm.share_folder("v-csc-#{i}", cookbook_path(i), cookbook)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def share_role_folders
|
24
|
+
host_role_paths.each_with_index do |role, i|
|
25
|
+
env.config.vm.share_folder("v-csr-#{i}", role_path(i), role)
|
26
|
+
end
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
def setup_solo_config
|
30
|
+
setup_config("chef_solo_solo", "solo.rb", {
|
31
|
+
:provisioning_path => env.config.chef.provisioning_path,
|
32
|
+
:cookbooks_path => cookbooks_path,
|
33
|
+
:roles_path => roles_path
|
34
|
+
})
|
30
35
|
end
|
31
36
|
|
32
37
|
def run_chef_solo
|
33
38
|
logger.info "Running chef-solo..."
|
34
|
-
|
35
|
-
ssh.exec!("cd #{
|
39
|
+
env.ssh.execute do |ssh|
|
40
|
+
ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
|
36
41
|
# TODO: Very verbose. It would be easier to save the data and only show it during
|
37
42
|
# an error, or when verbosity level is set high
|
38
43
|
logger.info("#{stream}: #{data}")
|
@@ -40,28 +45,49 @@ solo
|
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
|
-
def
|
44
|
-
|
45
|
-
cookbooks = [cookbooks] unless cookbooks.is_a?(Array)
|
46
|
-
cookbooks.collect! { |cookbook| File.expand_path(cookbook, Env.root_path) }
|
47
|
-
return cookbooks
|
48
|
+
def host_folder_paths(paths)
|
49
|
+
[paths].flatten.collect { |path| File.expand_path(path, env.root_path) }
|
48
50
|
end
|
49
51
|
|
50
|
-
def
|
51
|
-
File.join(
|
52
|
+
def folder_path(folder, i)
|
53
|
+
File.join(env.config.chef.provisioning_path, "#{folder}-#{i}")
|
52
54
|
end
|
53
55
|
|
54
|
-
def
|
56
|
+
def folders_path(folders, folder)
|
55
57
|
result = []
|
56
|
-
|
57
|
-
result <<
|
58
|
+
folders.each_with_index do |host_path, i|
|
59
|
+
result << folder_path(folder, i)
|
58
60
|
end
|
59
61
|
|
60
62
|
# We're lucky that ruby's string and array syntax for strings is the
|
61
63
|
# same as JSON, so we can just convert to JSON here and use that
|
62
|
-
result = result.to_s if result.length == 1
|
64
|
+
result = result[0].to_s if result.length == 1
|
63
65
|
result.to_json
|
64
66
|
end
|
67
|
+
|
68
|
+
def host_cookbook_paths
|
69
|
+
host_folder_paths(env.config.chef.cookbooks_path)
|
70
|
+
end
|
71
|
+
|
72
|
+
def host_role_paths
|
73
|
+
host_folder_paths(env.config.chef.roles_path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def cookbook_path(i)
|
77
|
+
folder_path("cookbooks", i)
|
78
|
+
end
|
79
|
+
|
80
|
+
def role_path(i)
|
81
|
+
folder_path("roles", i)
|
82
|
+
end
|
83
|
+
|
84
|
+
def cookbooks_path
|
85
|
+
folders_path(host_cookbook_paths, "cookbooks")
|
86
|
+
end
|
87
|
+
|
88
|
+
def roles_path
|
89
|
+
folders_path(host_role_paths, "roles")
|
90
|
+
end
|
65
91
|
end
|
66
92
|
end
|
67
|
-
end
|
93
|
+
end
|
data/lib/vagrant/ssh.rb
CHANGED
@@ -1,68 +1,117 @@
|
|
1
1
|
module Vagrant
|
2
|
+
# Manages SSH access to a specific environment. Allows an environment to
|
3
|
+
# replace the process with SSH itself, run a specific set of commands,
|
4
|
+
# upload files, or even check if a host is up.
|
2
5
|
class SSH
|
3
6
|
include Vagrant::Util
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# Reference back up to the environment which this SSH object belongs
|
9
|
+
# to
|
10
|
+
attr_accessor :env
|
11
|
+
|
12
|
+
def initialize(environment)
|
13
|
+
@env = environment
|
14
|
+
end
|
11
15
|
|
12
|
-
|
16
|
+
# Connects to the environment's virtual machine, replacing the ruby
|
17
|
+
# process with an SSH process. This method optionally takes a hash
|
18
|
+
# of options which override the configuration values.
|
19
|
+
def connect(opts={})
|
20
|
+
if Mario::Platform.windows?
|
21
|
+
error_and_exit(:ssh_unavailable_windows,
|
22
|
+
:key_path => env.config.ssh.private_key_path,
|
23
|
+
:ssh_port => port(opts))
|
13
24
|
end
|
14
25
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
opts.merge( :port => port,
|
19
|
-
:keys => [Vagrant.config.ssh.private_key_path])) do |ssh|
|
20
|
-
yield ssh
|
21
|
-
end
|
26
|
+
options = {}
|
27
|
+
[:host, :username, :private_key_path].each do |param|
|
28
|
+
options[param] = opts[param] || env.config.ssh.send(param)
|
22
29
|
end
|
23
30
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
31
|
+
check_key_permissions(options[:private_key_path])
|
32
|
+
|
33
|
+
# Some hackery going on here. On Mac OS X Leopard (10.5), exec fails
|
34
|
+
# (GH-51). As a workaround, we fork and wait. On all other platforms,
|
35
|
+
# we simply exec.
|
36
|
+
pid = nil
|
37
|
+
pid = fork if Util::Platform.leopard?
|
38
|
+
Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip if pid.nil?
|
39
|
+
Process.wait(pid) if pid
|
40
|
+
end
|
41
|
+
|
42
|
+
# Opens an SSH connection to this environment's virtual machine and yields
|
43
|
+
# a Net::SSH object which can be used to execute remote commands.
|
44
|
+
def execute(opts={})
|
45
|
+
Net::SSH.start(env.config.ssh.host,
|
46
|
+
env.config[:ssh][:username],
|
47
|
+
opts.merge( :port => port,
|
48
|
+
:keys => [env.config.ssh.private_key_path])) do |ssh|
|
49
|
+
yield ssh
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Uploads a file from `from` to `to`. `from` is expected to be a filename
|
54
|
+
# or StringIO, and `to` is expected to be a path. This method simply forwards
|
55
|
+
# the arguments to `Net::SCP#upload!` so view that for more information.
|
56
|
+
def upload!(from, to)
|
57
|
+
execute do |ssh|
|
58
|
+
scp = Net::SCP.new(ssh)
|
59
|
+
scp.upload!(from, to)
|
29
60
|
end
|
61
|
+
end
|
30
62
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
63
|
+
# Checks if this environment's machine is up (i.e. responding to SSH).
|
64
|
+
#
|
65
|
+
# @return [Boolean]
|
66
|
+
def up?
|
67
|
+
check_thread = Thread.new do
|
68
|
+
begin
|
69
|
+
Thread.current[:result] = false
|
70
|
+
execute(:timeout => env.config.ssh.timeout) do |ssh|
|
71
|
+
Thread.current[:result] = true
|
40
72
|
end
|
73
|
+
rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
|
74
|
+
# False, its defaulted above
|
41
75
|
end
|
76
|
+
end
|
42
77
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
the two most common are: private key path is incorrect or you're using a box
|
49
|
-
which was built for Vagrant 0.1.x.
|
78
|
+
check_thread.join(env.config.ssh.timeout)
|
79
|
+
return check_thread[:result]
|
80
|
+
rescue Net::SSH::AuthenticationFailed
|
81
|
+
error_and_exit(:vm_ssh_auth_failed)
|
82
|
+
end
|
50
83
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
84
|
+
# Checks the file permissions for the private key, resetting them
|
85
|
+
# if needed, or on failure erroring.
|
86
|
+
def check_key_permissions(key_path)
|
87
|
+
# TODO: This only works on unix based systems for now. Windows
|
88
|
+
# systems will need to be investigated further.
|
89
|
+
stat = File.stat(key_path)
|
55
90
|
|
56
|
-
|
91
|
+
if stat.owned? && file_perms(key_path) != "600"
|
92
|
+
logger.info "Permissions on private key incorrect, fixing..."
|
93
|
+
File.chmod(0600, key_path)
|
57
94
|
|
58
|
-
|
59
|
-
the path to the private key is incorrect. Check your `config.ssh.private_key_path`.
|
60
|
-
msg
|
95
|
+
error_and_exit(:ssh_bad_permissions, :key_path => key_path) if file_perms(key_path) != "600"
|
61
96
|
end
|
97
|
+
rescue Errno::EPERM
|
98
|
+
# This shouldn't happen since we verify we own the file, but just
|
99
|
+
# in case.
|
100
|
+
error_and_exit(:ssh_bad_permissions, :key_path => key_path)
|
101
|
+
end
|
62
102
|
|
63
|
-
|
64
|
-
|
65
|
-
|
103
|
+
# Returns the file permissions of a given file. This is fairly unix specific
|
104
|
+
# and probably doesn't belong in this class. Will be refactored out later.
|
105
|
+
def file_perms(path)
|
106
|
+
perms = sprintf("%o", File.stat(path).mode)
|
107
|
+
perms.reverse[0..2].reverse
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the port which is either given in the options hash or taken from
|
111
|
+
# the config by finding it in the forwarded ports hash based on the
|
112
|
+
# `config.ssh.forwarded_port_key`
|
113
|
+
def port(opts={})
|
114
|
+
opts[:port] || env.config.vm.forwarded_ports[env.config.ssh.forwarded_port_key][:hostport]
|
66
115
|
end
|
67
116
|
end
|
68
117
|
end
|
data/lib/vagrant/util.rb
CHANGED
@@ -10,12 +10,12 @@ module Vagrant
|
|
10
10
|
puts "====================================================================="
|
11
11
|
end
|
12
12
|
|
13
|
-
def error_and_exit(
|
13
|
+
def error_and_exit(key, data = {})
|
14
14
|
abort <<-error
|
15
15
|
=====================================================================
|
16
16
|
Vagrant experienced an error!
|
17
17
|
|
18
|
-
#{
|
18
|
+
#{Errors.error_string(key, data).chomp}
|
19
19
|
=====================================================================
|
20
20
|
error
|
21
21
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Vagrant
|
4
|
+
module Util
|
5
|
+
# This class is responsible for outputting errors. It retrieves the errors,
|
6
|
+
# based on their key, from the error file, and then outputs it.
|
7
|
+
class Errors
|
8
|
+
@@errors = nil
|
9
|
+
|
10
|
+
class <<self
|
11
|
+
# Resets the internal errors hash to nil, forcing a reload on the next
|
12
|
+
# access of {errors}.
|
13
|
+
def reset!
|
14
|
+
@@errors = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the hash of errors from the error YML files. This only loads once,
|
18
|
+
# then returns a cached value until {reset!} is called.
|
19
|
+
#
|
20
|
+
# @return [Hash]
|
21
|
+
def errors
|
22
|
+
@@errors ||= YAML.load_file(File.join(PROJECT_ROOT, "templates", "errors.yml"))
|
23
|
+
end
|
24
|
+
|
25
|
+
# Renders the error with the given key and data parameters and returns
|
26
|
+
# the rendered result.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
def error_string(key, data = {})
|
30
|
+
template = errors[key] || "Unknown error key: #{key}"
|
31
|
+
TemplateRenderer.render_string(template, data)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Util
|
3
|
+
# A mixin which allows any class to be able to show a "progress meter"
|
4
|
+
# to standard out. The progress meter shows the progress of an operation
|
5
|
+
# with console-animated text in stdout.
|
6
|
+
module ProgressMeter
|
7
|
+
# Updates the progress meter with the given progress amount and total.
|
8
|
+
# This method will do the math to figure out a percentage and show it
|
9
|
+
# within stdout.
|
10
|
+
#
|
11
|
+
# @param [Float] progress Progress
|
12
|
+
# @param [Float] total Total
|
13
|
+
def update_progress(progress, total, show_parts=true)
|
14
|
+
percent = (progress.to_f / total.to_f) * 100
|
15
|
+
print "#{cl_reset}Progress: #{percent.to_i}%"
|
16
|
+
print " (#{progress} / #{total})" if show_parts
|
17
|
+
$stdout.flush
|
18
|
+
end
|
19
|
+
|
20
|
+
# Completes the progress meter by resetting it off of the screen.
|
21
|
+
def complete_progress
|
22
|
+
# Just clear the line back out
|
23
|
+
print "#{cl_reset}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def cl_reset
|
27
|
+
reset = "\r"
|
28
|
+
reset += "\e[0K" unless Mario::Platform.windows?
|
29
|
+
reset
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Util
|
3
|
+
# Represents the "stacked proc runner" behavior which is used a
|
4
|
+
# couple places within Vagrant. This allows procs to "stack" on
|
5
|
+
# each other, then all execute in a single action. An example of
|
6
|
+
# its uses can be seen in the {Config} class.
|
7
|
+
module StackedProcRunner
|
8
|
+
# Returns the proc stack. This should always be called as the
|
9
|
+
# accessor of the stack. The instance variable itself should _never_
|
10
|
+
# be used.
|
11
|
+
#
|
12
|
+
# @return [Array<Proc>]
|
13
|
+
def proc_stack
|
14
|
+
@_proc_stack ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
# Adds (pushes) a proc to the stack. The actual proc added here is
|
18
|
+
# not executed, but merely stored.
|
19
|
+
#
|
20
|
+
# @param [Proc] block
|
21
|
+
def push_proc(&block)
|
22
|
+
proc_stack << block
|
23
|
+
end
|
24
|
+
|
25
|
+
# Executes all the procs on the stack, passing in the given arguments.
|
26
|
+
# The stack is not cleared afterwords. It is up to the user of this
|
27
|
+
# mixin to clear the stack by calling `proc_stack.clear`.
|
28
|
+
def run_procs!(*args)
|
29
|
+
proc_stack.each do |proc|
|
30
|
+
proc.call(*args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Vagrant
|
5
|
+
module Util
|
6
|
+
# This class is used to render the ERB templates in the
|
7
|
+
# `GEM_ROOT/templates` directory.
|
8
|
+
class TemplateRenderer < OpenStruct
|
9
|
+
class <<self
|
10
|
+
# Render a given template and return the result. This method optionally
|
11
|
+
# takes a block which will be passed the renderer prior to rendering, which
|
12
|
+
# allows the caller to set any view variables within the renderer itself.
|
13
|
+
#
|
14
|
+
# @return [String] Rendered template
|
15
|
+
def render(*args)
|
16
|
+
render_with(:render, *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Render a given string and return the result. This method optionally
|
20
|
+
# takes a block which will be passed the renderer prior to rendering, which
|
21
|
+
# allows the caller to set any view variables within the renderer itself.
|
22
|
+
#
|
23
|
+
# @param [String] template The template data string.
|
24
|
+
# @return [String] Rendered template
|
25
|
+
def render_string(*args)
|
26
|
+
render_with(:render_string, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Method used internally to DRY out the other renderers. This method
|
30
|
+
# creates and sets up the renderer before calling a specified method on it.
|
31
|
+
def render_with(method, template, data={})
|
32
|
+
renderer = new(template, data)
|
33
|
+
yield renderer if block_given?
|
34
|
+
renderer.send(method.to_sym)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(template, data = {})
|
39
|
+
super()
|
40
|
+
|
41
|
+
data[:template] = template
|
42
|
+
data.each do |key, value|
|
43
|
+
send("#{key}=", value)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Renders the template using the class intance as the binding. Because the
|
48
|
+
# renderer inherits from `OpenStruct`, additional view variables can be
|
49
|
+
# added like normal accessors.
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
def render
|
53
|
+
# TODO: Seems like a pretty dirty way to do this. Perhaps refactor this
|
54
|
+
old_template = template
|
55
|
+
result = nil
|
56
|
+
File.open(full_template_path, 'r') do |f|
|
57
|
+
self.template = f.read
|
58
|
+
result = render_string
|
59
|
+
end
|
60
|
+
|
61
|
+
result
|
62
|
+
ensure
|
63
|
+
self.template = old_template
|
64
|
+
end
|
65
|
+
|
66
|
+
# Renders a template, handling the template as a string, but otherwise
|
67
|
+
# acting the same way as {#render}.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
def render_string
|
71
|
+
ERB.new(template).result(binding)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the full path to the template, taking into accoun the gem directory
|
75
|
+
# and adding the `.erb` extension to the end.
|
76
|
+
#
|
77
|
+
# @return [String]
|
78
|
+
def full_template_path
|
79
|
+
File.join(PROJECT_ROOT, 'templates', "#{template}.erb")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|