rouster 0.5 → 0.7
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.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.reek +63 -0
- data/.travis.yml +11 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +102 -0
- data/README.md +233 -7
- data/Rakefile +52 -34
- data/Vagrantfile +26 -8
- data/examples/aws.rb +85 -0
- data/examples/openstack.rb +61 -0
- data/examples/passthrough.rb +71 -0
- data/lib/rouster.rb +380 -262
- data/lib/rouster/deltas.rb +470 -138
- data/lib/rouster/puppet.rb +155 -26
- data/lib/rouster/testing.rb +205 -46
- data/lib/rouster/tests.rb +40 -11
- data/lib/rouster/vagrant.rb +311 -0
- data/path_helper.rb +3 -4
- data/plugins/aws.rb +347 -0
- data/plugins/openstack.rb +136 -0
- data/test/basic.rb +4 -1
- data/test/functional/deltas/test_get_crontab.rb +64 -2
- data/test/functional/deltas/test_get_groups.rb +74 -2
- data/test/functional/deltas/test_get_os.rb +68 -0
- data/test/functional/deltas/test_get_packages.rb +73 -6
- data/test/functional/deltas/test_get_ports.rb +26 -1
- data/test/functional/deltas/test_get_services.rb +43 -5
- data/test/functional/deltas/test_get_users.rb +35 -2
- data/test/functional/puppet/test_facter.rb +41 -1
- data/test/functional/test_caching.rb +2 -2
- data/test/functional/test_inspect.rb +1 -1
- data/test/functional/test_is_file.rb +17 -1
- data/test/functional/test_is_in_file.rb +40 -0
- data/test/functional/test_new.rb +233 -22
- data/test/functional/test_passthroughs.rb +94 -0
- data/test/functional/test_put.rb +2 -2
- data/test/functional/test_validate_file.rb +104 -3
- data/test/puppet/test_apply.rb +8 -6
- data/test/unit/puppet/resources/puppet_run_with_failed_exec +59 -0
- data/test/unit/puppet/resources/puppet_run_with_successful_exec +61 -0
- data/test/unit/puppet/test_get_puppet_star.rb +27 -4
- data/test/unit/puppet/test_puppet_parsing.rb +44 -0
- data/test/unit/test_new.rb +88 -0
- data/test/unit/test_parse_ls_string.rb +67 -0
- data/test/unit/testing/resources/osx-launchd +285 -0
- data/test/unit/testing/resources/rhel-systemd +46 -0
- data/test/unit/testing/resources/rhel-systemv +41 -0
- data/test/unit/testing/resources/rhel-upstart +20 -0
- data/test/unit/testing/test_get_services.rb +178 -0
- data/test/unit/testing/test_validate_cron.rb +78 -0
- data/test/unit/testing/test_validate_package.rb +36 -10
- data/test/unit/testing/test_validate_port.rb +5 -0
- metadata +42 -21
- data/test/puppet/test_roles.rb +0 -186
data/lib/rouster/tests.rb
CHANGED
|
@@ -44,7 +44,7 @@ class Rouster
|
|
|
44
44
|
if raw.match(/No such file or directory/)
|
|
45
45
|
res = nil
|
|
46
46
|
elsif raw.match(/Permission denied/)
|
|
47
|
-
@
|
|
47
|
+
@logger.info(sprintf('dir(%s) output[%s], try with sudo', dir, raw)) unless self.uses_sudo?
|
|
48
48
|
res = nil
|
|
49
49
|
else
|
|
50
50
|
res = parse_ls_string(raw)
|
|
@@ -120,7 +120,7 @@ class Rouster
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
if raw.match(/No such file or directory/)
|
|
123
|
-
@
|
|
123
|
+
@logger.info(sprintf('is_file?(%s) output[%s], try with sudo', file, raw)) unless self.uses_sudo?
|
|
124
124
|
res = nil
|
|
125
125
|
elsif raw.match(/Permission denied/)
|
|
126
126
|
res = nil
|
|
@@ -257,18 +257,19 @@ class Rouster
|
|
|
257
257
|
# parameters
|
|
258
258
|
# * <file> - path of filename to examine
|
|
259
259
|
# * <regex> - regular expression/string to be passed to grep
|
|
260
|
+
# * <flags> - flags to include in grep command
|
|
260
261
|
# * [scp] - downloads file to host machine before grepping (functionality not implemented, was planned when a new SSH connection was required for each run() command, not sure it is necessary any longer)
|
|
261
|
-
def is_in_file?(file, regex, scp=false)
|
|
262
|
+
def is_in_file?(file, regex, flags='', scp=false)
|
|
262
263
|
|
|
263
264
|
res = nil
|
|
264
265
|
|
|
265
266
|
if scp
|
|
266
267
|
# download the file to a temporary directory
|
|
267
|
-
@
|
|
268
|
+
@logger.warn('is_in_file? scp option not implemented yet')
|
|
268
269
|
end
|
|
269
270
|
|
|
270
271
|
begin
|
|
271
|
-
command = sprintf("grep -c '%s' %s", regex, file)
|
|
272
|
+
command = sprintf("grep -c%s '%s' %s", flags, regex, file)
|
|
272
273
|
res = self.run(command)
|
|
273
274
|
rescue Rouster::RemoteExecutionError
|
|
274
275
|
return false
|
|
@@ -373,14 +374,14 @@ class Rouster
|
|
|
373
374
|
# * RedHat
|
|
374
375
|
# * Ubuntu
|
|
375
376
|
def is_process_running?(name)
|
|
376
|
-
# TODO support
|
|
377
|
-
# TODO do better validation than just grepping for a matching filename
|
|
377
|
+
# TODO support Solaris
|
|
378
|
+
# TODO do better validation than just grepping for a matching filename, start with removing 'grep' from output
|
|
378
379
|
begin
|
|
379
380
|
|
|
380
381
|
os = self.os_type()
|
|
381
382
|
|
|
382
383
|
case os
|
|
383
|
-
when :
|
|
384
|
+
when :rhel, :osx, :ubuntu, :debian
|
|
384
385
|
res = self.run(sprintf('ps ax | grep -c %s', name))
|
|
385
386
|
else
|
|
386
387
|
raise InternalError.new(sprintf('currently unable to determine running process list on OS[%s]', os))
|
|
@@ -467,6 +468,25 @@ class Rouster
|
|
|
467
468
|
end
|
|
468
469
|
end
|
|
469
470
|
|
|
471
|
+
##
|
|
472
|
+
# is_symlink?
|
|
473
|
+
#
|
|
474
|
+
# uses file() to return boolean indicating whether parameter passed is a symlink
|
|
475
|
+
#
|
|
476
|
+
# parameters
|
|
477
|
+
# * <file> - path of filename to validate
|
|
478
|
+
def is_symlink?(file)
|
|
479
|
+
res = nil
|
|
480
|
+
|
|
481
|
+
begin
|
|
482
|
+
res = self.file(file)
|
|
483
|
+
rescue => e
|
|
484
|
+
return false
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
res.class.eql?(Hash) ? res[:symlink?] : false
|
|
488
|
+
end
|
|
489
|
+
|
|
470
490
|
##
|
|
471
491
|
# is_user?
|
|
472
492
|
#
|
|
@@ -564,8 +584,8 @@ class Rouster
|
|
|
564
584
|
value += 4
|
|
565
585
|
when 'w'
|
|
566
586
|
value += 2
|
|
567
|
-
when 'x', 't'
|
|
568
|
-
# is 't' really right here? copying Salesforce::Vagrant
|
|
587
|
+
when 'x', 't', 's'
|
|
588
|
+
# is 't' / 's' really right here? copying Salesforce::Vagrant
|
|
569
589
|
value += 1
|
|
570
590
|
when '-'
|
|
571
591
|
# noop
|
|
@@ -579,17 +599,26 @@ class Rouster
|
|
|
579
599
|
end
|
|
580
600
|
|
|
581
601
|
res[:mode] = mode
|
|
582
|
-
res[:name] = tokens[-1] # TODO better here: this does not support files/dirs with spaces
|
|
583
602
|
res[:owner] = tokens[2]
|
|
584
603
|
res[:group] = tokens[3]
|
|
585
604
|
res[:size] = tokens[4]
|
|
586
605
|
|
|
587
606
|
res[:directory?] = tokens[0][0].chr.eql?('d')
|
|
588
607
|
res[:file?] = ! res[:directory?]
|
|
608
|
+
res[:symlink?] = tokens[0][0].chr.eql?('l')
|
|
589
609
|
res[:executable?] = [ tokens[0][3].chr.eql?('x'), tokens[0][6].chr.eql?('x'), tokens[0][9].chr.eql?('x') || tokens[0][9].chr.eql?('t') ]
|
|
590
610
|
res[:writeable?] = [ tokens[0][2].chr.eql?('w'), tokens[0][5].chr.eql?('w'), tokens[0][8].chr.eql?('w') ]
|
|
591
611
|
res[:readable?] = [ tokens[0][1].chr.eql?('r'), tokens[0][4].chr.eql?('r'), tokens[0][7].chr.eql?('r') ]
|
|
592
612
|
|
|
613
|
+
# TODO better here: this does not support files/dirs with spaces
|
|
614
|
+
if res[:symlink?]
|
|
615
|
+
# not sure if we should only be adding this value if we're a symlink, or adding it to all results and just using nil if not a link
|
|
616
|
+
res[:target] = tokens[-1]
|
|
617
|
+
res[:name] = tokens[-3]
|
|
618
|
+
else
|
|
619
|
+
res[:name] = tokens[-1]
|
|
620
|
+
end
|
|
621
|
+
|
|
593
622
|
res
|
|
594
623
|
end
|
|
595
624
|
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
require sprintf('%s/../../%s', File.dirname(File.expand_path(__FILE__)), 'path_helper')
|
|
2
|
+
|
|
3
|
+
## Vagrant specific (and related) methods
|
|
4
|
+
|
|
5
|
+
class Rouster
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# vagrant
|
|
9
|
+
#
|
|
10
|
+
# abstraction layer to call vagrant faces
|
|
11
|
+
#
|
|
12
|
+
# parameters
|
|
13
|
+
# * <face> - vagrant face to call (include arguments)
|
|
14
|
+
def vagrant(face, sleep_time=10)
|
|
15
|
+
if self.is_passthrough?
|
|
16
|
+
@logger.warn(sprintf('calling [vagrant %s] on a passthrough host is a noop', face))
|
|
17
|
+
return nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
unless @vagrant_concurrency.eql?(true)
|
|
21
|
+
# TODO don't (ab|re)use variables
|
|
22
|
+
0.upto(@retries) do |try|
|
|
23
|
+
break if self.is_vagrant_running?().eql?(false)
|
|
24
|
+
|
|
25
|
+
sleep sleep_time # TODO log a message?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
0.upto(@retries) do |try| # TODO should really be doing this with 'retry', but i think this code is actually cleaner
|
|
30
|
+
begin
|
|
31
|
+
return self._run(sprintf('cd %s; vagrant %s', File.dirname(@vagrantfile), face))
|
|
32
|
+
rescue
|
|
33
|
+
@logger.error(sprintf('failed vagrant command[%s], attempt[%s/%s]', face, try, retries)) if self.retries > 0
|
|
34
|
+
sleep sleep_time
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
raise InternalError.new(sprintf('failed to execute [%s], exitcode[%s], output[%s]', face, self.exitcode, self.get_output()))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# up
|
|
45
|
+
# runs `vagrant up <name>` from the Vagrantfile path
|
|
46
|
+
# if :sshtunnel is passed to the object during instantiation, the tunnel is created here as well
|
|
47
|
+
def up
|
|
48
|
+
@logger.info('up()')
|
|
49
|
+
|
|
50
|
+
# don't like putting this here, may be refactored
|
|
51
|
+
if self.is_passthrough?
|
|
52
|
+
if (self.passthrough[:type].equal?(:aws) or self.passthrough[:type].equal?(:raiden))
|
|
53
|
+
self.aws_up()
|
|
54
|
+
elsif (self.passthrough[:type].equal?(:openstack))
|
|
55
|
+
self.ostack_up()
|
|
56
|
+
else
|
|
57
|
+
self.vagrant(sprintf('up %s', @name))
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
self.vagrant(sprintf('up %s', @name))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@ssh_info = nil # in case the ssh-info has changed, a la destroy/rebuild
|
|
64
|
+
self.connect_ssh_tunnel() if @sshtunnel
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
##
|
|
68
|
+
# halt
|
|
69
|
+
# runs `vagrant halt <name>` from the Vagrantfile path
|
|
70
|
+
def halt
|
|
71
|
+
@logger.info('halt()')
|
|
72
|
+
self.vagrant(sprintf('halt %s', @name))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# package -- though vagrant docs still refer to 'repackage'
|
|
77
|
+
# runs `vagrant package <name> <provider>`
|
|
78
|
+
def package(provider='virtualbox') # TODO get the provider as a first class citizen on the rouster object
|
|
79
|
+
@logger.info(sprintf('package(%s)', provider))
|
|
80
|
+
self.vagrant(sprintf('package %s %s', @name, provider))
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# destroy
|
|
85
|
+
# runs `vagrant destroy <name>` from the Vagrantfile path
|
|
86
|
+
def destroy
|
|
87
|
+
@logger.info('destroy()')
|
|
88
|
+
|
|
89
|
+
# don't like putting this here, may be refactored
|
|
90
|
+
if self.is_passthrough?
|
|
91
|
+
if (self.passthrough[:type].equal?(:aws) or self.passthrough[:type].equal?(:raiden))
|
|
92
|
+
self.aws_destroy()
|
|
93
|
+
elsif self.is_passthrough? and self.passthrough[:type].equal?(:openstack)
|
|
94
|
+
self.ostack_destroy()
|
|
95
|
+
else
|
|
96
|
+
raise InternalError.new(sprintf('failed to execute destroy(), unsupported passthrough type %s', self.passthrough[:type]))
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
self.vagrant(sprintf('destroy -f %s', @name))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
disconnect_ssh_tunnel
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
##
|
|
106
|
+
# status
|
|
107
|
+
#
|
|
108
|
+
# runs `vagrant status <name>` from the Vagrantfile path
|
|
109
|
+
# parses the status and provider out of output, but only status is returned
|
|
110
|
+
def status
|
|
111
|
+
status = nil
|
|
112
|
+
|
|
113
|
+
if @cache_timeout
|
|
114
|
+
if @cache.has_key?(:status)
|
|
115
|
+
if (Time.now.to_i - @cache[:status][:time]) < @cache_timeout
|
|
116
|
+
@logger.debug(sprintf('using cached status[%s] from [%s]', @cache[:status][:status], @cache[:status][:time]))
|
|
117
|
+
return @cache[:status][:status]
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# don't like putting this here, may be refactored
|
|
123
|
+
@logger.info('status()')
|
|
124
|
+
if self.is_passthrough?
|
|
125
|
+
if (self.passthrough[:type].equal?(:aws) or self.passthrough[:type].equal?(:raiden))
|
|
126
|
+
status = self.aws_status()
|
|
127
|
+
elsif self.passthrough[:type].equal?(:openstack)
|
|
128
|
+
status = self.ostack_status()
|
|
129
|
+
else
|
|
130
|
+
raise InternalError.new(sprintf('failed to execute status(), unsupported passthrough type %s', self.passthrough[:type]))
|
|
131
|
+
end
|
|
132
|
+
else
|
|
133
|
+
self.vagrant(sprintf('status %s', @name))
|
|
134
|
+
|
|
135
|
+
# else case here (both for nil/non-matching output) is handled by non-0 exit code
|
|
136
|
+
output = self.get_output()
|
|
137
|
+
if output.nil?
|
|
138
|
+
if self.is_passthrough?() and self.passthrough[:type].eql?(:local)
|
|
139
|
+
status = 'running'
|
|
140
|
+
else
|
|
141
|
+
status = 'not-created'
|
|
142
|
+
end
|
|
143
|
+
elsif output.match(/^#{@name}\s*(.*\s?\w+)\s\((.+)\)$/)
|
|
144
|
+
# vagrant 1.2+, $1 = status, $2 = provider
|
|
145
|
+
status = $1
|
|
146
|
+
elsif output.match(/^#{@name}\s+(.+)$/)
|
|
147
|
+
# vagrant 1.2-, $1 = status
|
|
148
|
+
status = $1
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
if @cache_timeout
|
|
153
|
+
@cache[:status] = Hash.new unless @cache[:status].class.eql?(Hash)
|
|
154
|
+
@cache[:status][:time] = Time.now.to_i
|
|
155
|
+
@cache[:status][:status] = status
|
|
156
|
+
@logger.debug(sprintf('caching status[%s] at [%s]', @cache[:status][:status], @cache[:status][:time]))
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
return status
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
##
|
|
163
|
+
# reload
|
|
164
|
+
#
|
|
165
|
+
# runs `vagrant reload <name> [--no-provision]` from the Vagrantfile path
|
|
166
|
+
# +no_provision+ Boolean whether or not to stop reprovisioning
|
|
167
|
+
def reload(no_provision = true)
|
|
168
|
+
|
|
169
|
+
if self.is_passthrough?
|
|
170
|
+
@logger.warn('calling [vagrant reload] on a passthrough host is a noop')
|
|
171
|
+
return nil
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
@logger.info('reload()')
|
|
175
|
+
self.vagrant(sprintf('reload %s %s', @name, no_provision ? '--no-provision' : ''))
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
##
|
|
179
|
+
# suspend
|
|
180
|
+
#
|
|
181
|
+
# runs `vagrant suspend <name>` from the Vagrantfile path
|
|
182
|
+
def suspend
|
|
183
|
+
@logger.info('suspend()')
|
|
184
|
+
self.vagrant(sprintf('suspend %s', @name))
|
|
185
|
+
disconnect_ssh_tunnel() unless self.is_passthrough?()
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
##
|
|
189
|
+
# is_vagrant_running?()
|
|
190
|
+
#
|
|
191
|
+
# returns true|false if a vagrant process is running on the host machine
|
|
192
|
+
#
|
|
193
|
+
# meant to be used to prevent race-y conditions when interacting with VirtualBox (potentially others, haven't tested)
|
|
194
|
+
def is_vagrant_running?
|
|
195
|
+
res = false
|
|
196
|
+
|
|
197
|
+
begin
|
|
198
|
+
# TODO would like to get the 2 -v greps into a single call..
|
|
199
|
+
raw = self._run("ps -ef | grep -v 'grep' | grep -v 'ssh' | grep '#{self.vagrantbinary}'")
|
|
200
|
+
res = true
|
|
201
|
+
rescue
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
@logger.debug(sprintf('is_vagrant_running?[%s]', res))
|
|
205
|
+
res
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
##
|
|
209
|
+
# sandbox_available?
|
|
210
|
+
#
|
|
211
|
+
# returns true or false after attempting to find out if the sandbox
|
|
212
|
+
# subcommand is available
|
|
213
|
+
def sandbox_available?
|
|
214
|
+
if self.is_passthrough?
|
|
215
|
+
@logger.warn('sandbox* methods on a passthrough host is a noop')
|
|
216
|
+
return nil
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
if @cache.has_key?(:sandbox_available?)
|
|
220
|
+
@logger.debug(sprintf('using cached sandbox_available?[%s]', @cache[:sandbox_available?]))
|
|
221
|
+
return @cache[:sandbox_available?]
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
@logger.info('sandbox_available()')
|
|
225
|
+
begin
|
|
226
|
+
# at some point, vagrant changed its behavior on exit code here, so rescuing
|
|
227
|
+
self._run(sprintf('cd %s; vagrant', File.dirname(@vagrantfile))) # calling 'vagrant' without parameters to determine available faces
|
|
228
|
+
rescue
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
sandbox_available = false
|
|
232
|
+
if self.get_output().match(/^\s+sandbox$/)
|
|
233
|
+
sandbox_available = true
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
@cache[:sandbox_available?] = sandbox_available
|
|
237
|
+
@logger.debug(sprintf('caching sandbox_available?[%s]', @cache[:sandbox_available?]))
|
|
238
|
+
@logger.error('sandbox support is not available, please install the "sahara" gem first, https://github.com/jedi4ever/sahara') unless sandbox_available
|
|
239
|
+
|
|
240
|
+
return sandbox_available
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
##
|
|
244
|
+
# sandbox_on
|
|
245
|
+
# runs `vagrant sandbox on` from the Vagrantfile path
|
|
246
|
+
def sandbox_on
|
|
247
|
+
if self.is_passthrough?
|
|
248
|
+
@logger.warn('sandbox* methods on a passthrough host is a noop')
|
|
249
|
+
return nil
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
if self.sandbox_available?
|
|
253
|
+
return self.vagrant(sprintf('sandbox on %s', @name))
|
|
254
|
+
else
|
|
255
|
+
raise ExternalError.new('sandbox plugin not installed')
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
##
|
|
260
|
+
# sandbox_off
|
|
261
|
+
# runs `vagrant sandbox off` from the Vagrantfile path
|
|
262
|
+
def sandbox_off
|
|
263
|
+
if self.is_passthrough?
|
|
264
|
+
@logger.warn('sandbox* methods on a passthrough host is a noop')
|
|
265
|
+
return nil
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
if self.sandbox_available?
|
|
269
|
+
return self.vagrant(sprintf('sandbox off %s', @name))
|
|
270
|
+
else
|
|
271
|
+
raise ExternalError.new('sandbox plugin not installed')
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
##
|
|
276
|
+
# sandbox_rollback
|
|
277
|
+
# runs `vagrant sandbox rollback` from the Vagrantfile path
|
|
278
|
+
def sandbox_rollback
|
|
279
|
+
if self.is_passthrough?
|
|
280
|
+
@logger.warn('sandbox* methods on a passthrough host is a noop')
|
|
281
|
+
return nil
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
if self.sandbox_available?
|
|
285
|
+
self.disconnect_ssh_tunnel
|
|
286
|
+
self.vagrant(sprintf('sandbox rollback %s', @name))
|
|
287
|
+
self.connect_ssh_tunnel
|
|
288
|
+
else
|
|
289
|
+
raise ExternalError.new('sandbox plugin not installed')
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
##
|
|
294
|
+
# sandbox_commit
|
|
295
|
+
# runs `vagrant sandbox commit` from the Vagrantfile path
|
|
296
|
+
def sandbox_commit
|
|
297
|
+
if self.is_passthrough?
|
|
298
|
+
@logger.warn('sandbox* methods on a passthrough host is a noop')
|
|
299
|
+
return nil
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
if self.sandbox_available?
|
|
303
|
+
self.disconnect_ssh_tunnel
|
|
304
|
+
self.vagrant(sprintf('sandbox commit %s', @name))
|
|
305
|
+
self.connect_ssh_tunnel
|
|
306
|
+
else
|
|
307
|
+
raise ExternalError.new('sandbox plugin not installed')
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
end
|
data/path_helper.rb
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# this gets us Rouster, still need to figure out how to find vagrant
|
|
4
4
|
$LOAD_PATH << File.join([File.dirname(__FILE__), 'lib'])
|
|
5
|
+
$LOAD_PATH << File.join([File.dirname(__FILE__), 'plugins'])
|
|
6
|
+
$LOAD_PATH << File.expand_path(sprintf('%s/..', File.dirname(__FILE__)))
|
|
7
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
|
5
8
|
|
|
6
9
|
require 'rubygems'
|
|
7
10
|
|
|
8
11
|
# debugging help
|
|
9
|
-
begin
|
|
10
|
-
require 'debugger'
|
|
11
|
-
rescue LoadError
|
|
12
|
-
end
|
|
13
12
|
|
|
14
13
|
class Object
|
|
15
14
|
def my_methods
|