sprinkle 0.7.2 → 0.7.3
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/.gitignore +5 -1
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/sprinkle/actors/ssh.rb +44 -65
- data/lib/sprinkle/actors/ssh/connection_cache.rb +26 -0
- data/lib/sprinkle/extensions/sudo.rb +13 -0
- data/lib/sprinkle/installers/file.rb +17 -16
- data/lib/sprinkle/installers/installer.rb +2 -9
- data/lib/sprinkle/installers/runner.rb +25 -8
- data/lib/sprinkle/installers/source.rb +2 -1
- data/lib/sprinkle/installers/thor.rb +0 -1
- data/lib/sprinkle/installers/user.rb +0 -1
- data/lib/sprinkle/policy.rb +4 -3
- data/lib/sprinkle/utility/log_recorder.rb +2 -2
- data/lib/sprinkle/verifiers/file.rb +2 -2
- data/lib/sprinkle/verifiers/permission.rb +4 -10
- data/lib/sprinkle/verify.rb +2 -1
- data/lib/sprinkle/version.rb +1 -1
- data/spec/sprinkle/installers/file_spec.rb +51 -10
- data/spec/sprinkle/installers/runner_spec.rb +57 -40
- data/spec/sprinkle/installers/source_spec.rb +3 -3
- data/spec/sprinkle/verify_spec.rb +31 -2
- metadata +4 -7
- data/bad.rb +0 -16
- data/config/deploy.rb +0 -25
- data/inner.rb +0 -45
- data/test.rb +0 -102
- data/work/inner.rb +0 -24
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Sprinkle is a software provisioning tool you can use to build remote servers wit
|
|
4
4
|
system has been installed. For example, to install a Rails or Merb stack on a brand new slice directly after
|
5
5
|
its been created.
|
6
6
|
|
7
|
-
[](https://travis-ci.org/sprinkle-tool/sprinkle)
|
7
|
+
[](https://travis-ci.org/sprinkle-tool/sprinkle) [](https://codeclimate.com/github/sprinkle-tool/sprinkle/)
|
8
8
|
|
9
9
|
* `#sprinkle` channel on the Freenode IRC Network
|
10
10
|
* <http://redartisan.com/2008/5/27/sprinkle-intro>
|
data/lib/sprinkle/actors/ssh.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'net/ssh/gateway'
|
2
2
|
require 'net/scp'
|
3
|
+
require File.dirname(__FILE__) + "/ssh/connection_cache"
|
3
4
|
|
4
5
|
module Sprinkle
|
5
6
|
module Actors
|
@@ -43,20 +44,10 @@ module Sprinkle
|
|
43
44
|
class SSHCommandFailure < StandardError #:nodoc:
|
44
45
|
attr_accessor :details
|
45
46
|
end
|
46
|
-
|
47
|
-
class SSHConnectionCache #:nodoc:
|
48
|
-
def initialize; @cache={}; end
|
49
|
-
def start(host, user, opts={})
|
50
|
-
key="#{host}#{user}#{opts.to_s}"
|
51
|
-
@cache[key] ||= Net::SSH.start(host,user,opts)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
|
47
|
+
|
56
48
|
def initialize(options = {}, &block) #:nodoc:
|
57
49
|
@options = options.update(:user => 'root')
|
58
50
|
@roles = {}
|
59
|
-
@connection_cache = SSHConnectionCache.new
|
60
51
|
self.instance_eval &block if block
|
61
52
|
raise "You must define at least a single role." if @roles.empty?
|
62
53
|
end
|
@@ -115,24 +106,17 @@ module Sprinkle
|
|
115
106
|
def sudo_command #:nodoc:
|
116
107
|
"sudo"
|
117
108
|
end
|
118
|
-
|
119
|
-
def setup_gateway #:nodoc:
|
120
|
-
@gateway ||= Net::SSH::Gateway.new(@options[:gateway], @options[:user]) if @options[:gateway]
|
121
|
-
end
|
122
109
|
|
123
110
|
def teardown #:nodoc:
|
124
|
-
|
111
|
+
connections.shutdown!
|
125
112
|
end
|
126
113
|
|
127
|
-
def verify(verifier, roles
|
128
|
-
@verifier = verifier
|
114
|
+
def verify(verifier, roles) #:nodoc:
|
129
115
|
# issue all the verification steps in a single SSH command
|
130
116
|
commands=[verifier.commands.join(" && ")]
|
131
117
|
process(verifier.package.name, commands, roles)
|
132
118
|
rescue SSHCommandFailure => e
|
133
119
|
false
|
134
|
-
ensure
|
135
|
-
@verifier = nil
|
136
120
|
end
|
137
121
|
|
138
122
|
def install(installer, roles, opts = {}) #:nodoc:
|
@@ -144,24 +128,20 @@ module Sprinkle
|
|
144
128
|
@installer = nil
|
145
129
|
end
|
146
130
|
|
147
|
-
|
131
|
+
private
|
148
132
|
|
149
133
|
def raise_error(e) #:nodoc:
|
150
134
|
raise Sprinkle::Errors::RemoteCommandFailure.new(@installer, e.details, e)
|
151
135
|
end
|
152
136
|
|
153
|
-
def process(name, commands, roles
|
154
|
-
|
155
|
-
r=execute_on_role(commands, roles)
|
156
|
-
logger.debug green "process returning #{r}"
|
157
|
-
return r
|
137
|
+
def process(name, commands, roles) #:nodoc:
|
138
|
+
execute_on_role(commands, roles)
|
158
139
|
end
|
159
140
|
|
160
141
|
def execute_on_role(commands, role) #:nodoc:
|
161
142
|
hosts = @roles[role]
|
162
143
|
Array(hosts).each do |host|
|
163
144
|
success = execute_on_host(commands, host)
|
164
|
-
return false unless success
|
165
145
|
end
|
166
146
|
end
|
167
147
|
|
@@ -174,33 +154,28 @@ module Sprinkle
|
|
174
154
|
end
|
175
155
|
|
176
156
|
def execute_on_host(commands,host) #:nodoc:
|
177
|
-
session = ssh_session(host)
|
178
|
-
@log_recorder = Sprinkle::Utility::LogRecorder.new
|
179
157
|
prepare_commands(commands).each do |cmd|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
end
|
189
|
-
@log_recorder.reset cmd
|
190
|
-
res = ssh(session, cmd)
|
191
|
-
if res != 0
|
192
|
-
fail=SSHCommandFailure.new
|
193
|
-
fail.details = @log_recorder.hash.merge(:hosts => host)
|
194
|
-
raise fail
|
158
|
+
case cmd
|
159
|
+
when :RECONNECT
|
160
|
+
reconnect host
|
161
|
+
when :TRANSFER
|
162
|
+
transfer_to_host(@installer.sourcepath, @installer.destination, host,
|
163
|
+
:recursive => @installer.options[:recursive])
|
164
|
+
else
|
165
|
+
run_command cmd, host
|
195
166
|
end
|
196
167
|
end
|
197
|
-
true
|
198
168
|
end
|
199
169
|
|
200
|
-
def
|
201
|
-
|
170
|
+
def run_command(cmd,host) #:nodoc:
|
171
|
+
@log_recorder= Sprinkle::Utility::LogRecorder.new(cmd)
|
172
|
+
session = ssh_session(host)
|
202
173
|
logger.debug "[#{session.host}] ssh: #{cmd}"
|
203
|
-
channel_runner(session, cmd)
|
174
|
+
if channel_runner(session, cmd) != 0
|
175
|
+
fail=SSHCommandFailure.new
|
176
|
+
fail.details = @log_recorder.hash.merge(:hosts => host)
|
177
|
+
raise fail
|
178
|
+
end
|
204
179
|
end
|
205
180
|
|
206
181
|
def channel_runner(session, command) #:nodoc:
|
@@ -244,7 +219,7 @@ module Sprinkle
|
|
244
219
|
|
245
220
|
def transfer_to_host(source, destination, host, opts={}) #:nodoc:
|
246
221
|
logger.debug "upload: #{destination}"
|
247
|
-
session =
|
222
|
+
session = ssh_session(host)
|
248
223
|
scp = Net::SCP.new(session)
|
249
224
|
scp.upload! source, destination, :recursive => opts[:recursive], :chunk_size => 32.kilobytes
|
250
225
|
rescue RuntimeError => e
|
@@ -256,28 +231,32 @@ module Sprinkle
|
|
256
231
|
end
|
257
232
|
|
258
233
|
def ssh_session(host) #:nodoc:
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
end
|
234
|
+
connections.start(host, @options[:user], @options.slice(:password, :keys))
|
235
|
+
end
|
236
|
+
|
237
|
+
def reconnect(host) #:nodoc:
|
238
|
+
connections.reconnect host
|
239
|
+
end
|
240
|
+
|
241
|
+
def connections #:nodoc:
|
242
|
+
@connection_cache ||= SSHConnectionCache.new @options.slice(:gateway, :user)
|
243
|
+
end
|
265
244
|
|
266
245
|
private
|
267
|
-
def color(code,
|
268
|
-
"\033[%sm%s\033[0m"%[code,
|
246
|
+
def color(code, text)
|
247
|
+
"\033[%sm%s\033[0m"%[code,text]
|
269
248
|
end
|
270
|
-
def red(
|
271
|
-
color(31,
|
249
|
+
def red(text)
|
250
|
+
color(31, text)
|
272
251
|
end
|
273
|
-
def yellow(
|
274
|
-
color(33,
|
252
|
+
def yellow(text)
|
253
|
+
color(33, text)
|
275
254
|
end
|
276
|
-
def green(
|
277
|
-
color(32,
|
255
|
+
def green(text)
|
256
|
+
color(32, text)
|
278
257
|
end
|
279
|
-
def blue(
|
280
|
-
color(34,
|
258
|
+
def blue(text)
|
259
|
+
color(34, text)
|
281
260
|
end
|
282
261
|
end
|
283
262
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Actors
|
3
|
+
class SSHConnectionCache #:nodoc:
|
4
|
+
def initialize(options={})
|
5
|
+
@cache = {}
|
6
|
+
@gateway = Net::SSH::Gateway.new(options[:gateway], options[:user]) if options[:gateway]
|
7
|
+
end
|
8
|
+
def start(host, user, opts={})
|
9
|
+
key="#{host}/#{user}#{opts.to_s}"
|
10
|
+
if @gateway
|
11
|
+
@cache[key] ||= @gateway.ssh(host, user, opts)
|
12
|
+
else
|
13
|
+
@cache[key] ||= Net::SSH.start(host, user, opts)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def reconnect(host)
|
17
|
+
@cache.delete_if do |k,v|
|
18
|
+
(v.close; true) if k =~ /^#{host}\//
|
19
|
+
end
|
20
|
+
end
|
21
|
+
def shutdown!
|
22
|
+
@gateway.shutdown! if @gateway
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -21,61 +21,62 @@ module Sprinkle
|
|
21
21
|
#
|
22
22
|
# Should you need to run commands before or after the file transfer (making
|
23
23
|
# directories or changing permissions), you can use the pre/post :install directives.
|
24
|
-
#
|
24
|
+
#
|
25
25
|
# == Rendering templates
|
26
26
|
#
|
27
|
-
# Use the template render helper to render an ERB template to a remote file (you
|
27
|
+
# Use the template render helper to render an ERB template to a remote file (you
|
28
28
|
# can use variables in your templates by setting them as instance variables inside
|
29
29
|
# your package. Templates have access to package methods such as opts, args, etc.
|
30
30
|
#
|
31
31
|
# package :nginx_conf do
|
32
32
|
# @nginx_port = 8080
|
33
|
-
# file '/etc/nginx.conf',
|
33
|
+
# file '/etc/nginx.conf',
|
34
34
|
# :contents => render("nginx.conf")
|
35
|
-
# # ./templates/nginx.conf.erb or
|
35
|
+
# # ./templates/nginx.conf.erb or
|
36
36
|
# # ./templates/nginx.conf should contain the erb template
|
37
37
|
# end
|
38
38
|
class FileInstaller < Installer
|
39
39
|
attr_reader :sourcepath, :destination, :contents #:nodoc:
|
40
|
-
|
40
|
+
|
41
41
|
api do
|
42
42
|
def file(destination, options = {}, &block) #:nodoc:
|
43
43
|
# options.merge!(:binding => binding())
|
44
44
|
install FileInstaller.new(self, destination, options, &block)
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def initialize(parent, destination, options={}, &block) #:nodoc:
|
49
49
|
@destination = destination
|
50
50
|
@contents = options[:content] || options[:contents]
|
51
51
|
raise "need :contents key for file" unless @contents
|
52
52
|
super parent, options, &block
|
53
|
-
|
54
|
-
post_move_if_sudo
|
55
|
-
setup_source
|
53
|
+
|
56
54
|
# setup file attributes
|
57
55
|
owner options[:owner] if options[:owner]
|
58
56
|
mode options[:mode] if options[:mode]
|
57
|
+
|
58
|
+
post_move_if_sudo
|
59
|
+
setup_source
|
59
60
|
end
|
60
|
-
|
61
|
+
|
61
62
|
def install_commands #:nodoc:
|
62
63
|
:TRANSFER
|
63
64
|
end
|
64
|
-
|
65
|
+
|
65
66
|
# calls chown own to set the file ownership
|
66
67
|
def owner(owner)
|
67
68
|
@owner = owner
|
68
69
|
post :install, "#{sudo_cmd}chown #{owner} #{@destination}"
|
69
70
|
end
|
70
|
-
|
71
|
+
|
71
72
|
# calls chmod to set the files permissions
|
72
73
|
def mode(mode)
|
73
74
|
@mode = mode
|
74
75
|
post :install, "#{sudo_cmd}chmod #{mode} #{@destination}"
|
75
76
|
end
|
76
|
-
|
77
|
+
|
77
78
|
private
|
78
|
-
|
79
|
+
|
79
80
|
def post_move_if_sudo
|
80
81
|
return unless sudo? # perform the file copy in two steps if we're using sudo
|
81
82
|
final = @destination
|
@@ -84,14 +85,14 @@ module Sprinkle
|
|
84
85
|
# a user may have requested
|
85
86
|
post(:install).unshift ["#{sudo_cmd}mv #{@destination} #{final}"]
|
86
87
|
end
|
87
|
-
|
88
|
+
|
88
89
|
def setup_source
|
89
90
|
file=Tempfile.new(@package.name.to_s)
|
90
91
|
file.print(@contents)
|
91
92
|
file.close
|
92
93
|
@sourcepath = file.path
|
93
94
|
end
|
94
|
-
|
95
|
+
|
95
96
|
end
|
96
97
|
end
|
97
98
|
end
|
@@ -51,7 +51,8 @@ module Sprinkle
|
|
51
51
|
# or post :install. If this is the case, it will be documented on
|
52
52
|
# the installation method's corresponding documentation page.
|
53
53
|
class Installer
|
54
|
-
include Sprinkle::Attributes
|
54
|
+
include Sprinkle::Attributes
|
55
|
+
include Sprinkle::Sudo
|
55
56
|
|
56
57
|
delegate :version, :to => :package
|
57
58
|
|
@@ -84,14 +85,6 @@ module Sprinkle
|
|
84
85
|
end
|
85
86
|
end
|
86
87
|
|
87
|
-
def sudo_cmd
|
88
|
-
return "#{@delivery.try(:sudo_command) || "sudo"} " if sudo?
|
89
|
-
end
|
90
|
-
|
91
|
-
def sudo?
|
92
|
-
options[:sudo] or package.sudo? or @delivery.try(:sudo?)
|
93
|
-
end
|
94
|
-
|
95
88
|
def escape_shell_arg(str)
|
96
89
|
str.gsub("'", "'\\\\''").gsub("\n", '\n')
|
97
90
|
end
|
@@ -15,33 +15,50 @@ module Sprinkle
|
|
15
15
|
# runner [ "make world", "destroy world" ]
|
16
16
|
# end
|
17
17
|
#
|
18
|
+
# Environment variables can be supplied throught the :env option.
|
19
|
+
#
|
20
|
+
# package :magic_beans do
|
21
|
+
# runner "make world", :env => {
|
22
|
+
# :PATH => '/this/is/my/path:$PATH'
|
23
|
+
# }
|
24
|
+
# end
|
25
|
+
#
|
18
26
|
class Runner < Installer
|
19
|
-
|
27
|
+
|
20
28
|
api do
|
21
29
|
def runner(*cmds, &block)
|
22
30
|
options = cmds.extract_options!
|
23
31
|
install Runner.new(self, cmds, options, &block)
|
24
32
|
end
|
25
|
-
|
33
|
+
|
26
34
|
# runs 'echo noop' on the remote host
|
27
35
|
def noop
|
28
36
|
install Runner.new(self, "echo noop")
|
29
37
|
end
|
30
38
|
end
|
31
|
-
|
39
|
+
|
32
40
|
attr_accessor :cmds #:nodoc:
|
33
41
|
def initialize(parent, cmds, options = {}, &block) #:nodoc:
|
34
42
|
super parent, options, &block
|
43
|
+
@env = options.delete(:env)
|
35
44
|
@cmds = [*cmds].flatten
|
36
45
|
raise "you need to specify a command" if cmds.nil?
|
37
46
|
end
|
38
|
-
|
47
|
+
|
39
48
|
protected
|
40
|
-
|
49
|
+
|
50
|
+
def env_str #:nodoc:
|
51
|
+
@env_str ||= @env.inject("env ") do |s, (k,v)|
|
52
|
+
s << "#{k.to_s.upcase}=#{v} "
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
41
56
|
def install_commands #:nodoc:
|
42
|
-
|
43
|
-
|
44
|
-
|
57
|
+
cmds = @env ? @cmds.map { |cmd| "#{env_str}#{cmd}"} : @cmds
|
58
|
+
|
59
|
+
sudo? ?
|
60
|
+
cmds.map { |cmd| "#{sudo_cmd}#{cmd}"} :
|
61
|
+
cmds
|
45
62
|
end
|
46
63
|
end
|
47
64
|
end
|
@@ -102,7 +102,8 @@ module Sprinkle
|
|
102
102
|
end
|
103
103
|
|
104
104
|
multi_attributes :enable, :disable, :with, :without, :option,
|
105
|
-
:custom_install
|
105
|
+
:custom_install
|
106
|
+
attributes :configure_command, :build_command, :install_command
|
106
107
|
|
107
108
|
def install_sequence #:nodoc:
|
108
109
|
prepare + download + extract + configure + build + install
|
data/lib/sprinkle/policy.rb
CHANGED
@@ -68,8 +68,8 @@ module Sprinkle
|
|
68
68
|
end
|
69
69
|
|
70
70
|
# tell a policy which packages are required
|
71
|
-
def requires(package,
|
72
|
-
@packages << [package,
|
71
|
+
def requires(package, *args)
|
72
|
+
@packages << [package, args]
|
73
73
|
end
|
74
74
|
|
75
75
|
def packages #:nodoc:
|
@@ -91,7 +91,8 @@ module Sprinkle
|
|
91
91
|
@packages.each do |p, args|
|
92
92
|
cloud_info " * requires package #{p}"
|
93
93
|
|
94
|
-
|
94
|
+
opts = args.clone.extract_options!
|
95
|
+
package = Sprinkle::Package::PACKAGES.find_all(p, opts)
|
95
96
|
raise "Package definition not found for key: #{p}" unless package
|
96
97
|
package = Sprinkle::Package::Chooser.select_package(p, package) if package.is_a? Array # handle virtual package selection
|
97
98
|
# get an instance of the package and pass our config options
|
@@ -38,7 +38,7 @@ module Sprinkle
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def md5_of_file(path, md5)
|
41
|
-
test "\"
|
41
|
+
test "\"`#{sudo_cmd}md5sum #{path} | cut -f1 -d' '`\" = \"#{md5}\""
|
42
42
|
end
|
43
43
|
|
44
44
|
def file_contains(path, text)
|
@@ -55,7 +55,7 @@ module Sprinkle
|
|
55
55
|
raise "Couldn't find local file #{localfile}" unless ::File.exists?(localfile)
|
56
56
|
require 'digest/md5'
|
57
57
|
local = Digest::MD5.hexdigest(::File.read(localfile))
|
58
|
-
|
58
|
+
md5_of_file remotefile, local
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -20,19 +20,13 @@ module Sprinkle
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def belongs_to_user(path, user)
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
@commands << "find #{path} -maxdepth 0 -user #{user} | egrep '.*'"
|
27
|
-
end
|
23
|
+
arg = user.is_a?(Integer) ? "-uid" : "-user"
|
24
|
+
@commands << "find #{path} -maxdepth 0 #{arg} #{user} | egrep '.*'"
|
28
25
|
end
|
29
26
|
|
30
27
|
def belongs_to_group(path, group)
|
31
|
-
|
32
|
-
|
33
|
-
else
|
34
|
-
@commands << "find #{path} -maxdepth 0 -group #{group} | egrep '.*'"
|
35
|
-
end
|
28
|
+
arg = group.is_a?(Integer) ? "-gid" : "-group"
|
29
|
+
@commands << "find #{path} -maxdepth 0 #{arg} #{group} | egrep '.*'"
|
36
30
|
end
|
37
31
|
|
38
32
|
end
|
data/lib/sprinkle/verify.rb
CHANGED
@@ -61,7 +61,8 @@ module Sprinkle
|
|
61
61
|
class Verify
|
62
62
|
include Sprinkle::Attributes
|
63
63
|
include Sprinkle::Package::Rendering::Helpers
|
64
|
-
|
64
|
+
include Sprinkle::Sudo
|
65
|
+
attr_accessor :package, :description, :commands, :options #:nodoc:
|
65
66
|
|
66
67
|
delegate :opts, :to => :package
|
67
68
|
delegate :args, :to => :package
|
data/lib/sprinkle/version.rb
CHANGED
@@ -7,8 +7,8 @@ describe Sprinkle::Installers::FileInstaller do
|
|
7
7
|
@package = mock(Sprinkle::Package, :name => 'package', :sudo? => false)
|
8
8
|
@empty = Proc.new { }
|
9
9
|
@delivery = mock(Sprinkle::Deployment, :install => true)
|
10
|
-
|
11
|
-
|
10
|
+
@source = 'source'
|
11
|
+
@destination = 'destination'
|
12
12
|
@contents = "hi"
|
13
13
|
@installer = create_file_installer(@destination, :contents => @contents)
|
14
14
|
@roles = []
|
@@ -21,7 +21,7 @@ describe Sprinkle::Installers::FileInstaller do
|
|
21
21
|
def create_file_installer(dest, options={}, &block)
|
22
22
|
i = Sprinkle::Installers::FileInstaller.new(@package, dest, options, &block)
|
23
23
|
i.delivery = @delivery
|
24
|
-
|
24
|
+
i
|
25
25
|
end
|
26
26
|
|
27
27
|
describe 'when created' do
|
@@ -34,24 +34,65 @@ describe Sprinkle::Installers::FileInstaller do
|
|
34
34
|
describe 'during installation' do
|
35
35
|
|
36
36
|
context "setting mode and owner" do
|
37
|
-
before do
|
37
|
+
before do
|
38
38
|
@installer = create_file_installer @destination, :content => @contents do
|
39
39
|
mode "744"
|
40
40
|
owner "root"
|
41
41
|
end
|
42
42
|
@installer_commands = @installer.install_sequence
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
it "should include command to set owner" do
|
46
46
|
@installer_commands.should include("chmod 744 #{@destination}")
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
it "should include command to set mode" do
|
50
50
|
@installer_commands.should include("chown root #{@destination}")
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context "setting mode and owner with sudo" do
|
56
|
+
before do
|
57
|
+
@installer = create_file_installer @destination, :content => @contents do
|
58
|
+
@options[:sudo]= true
|
59
|
+
mode "744"
|
60
|
+
owner "root"
|
61
|
+
end
|
62
|
+
@installer_commands = @installer.install_sequence
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should run commands in correct order" do
|
66
|
+
@installer_commands.should == [
|
67
|
+
:TRANSFER,
|
68
|
+
"sudo mv /tmp/sprinkle_#{@destination} #{@destination}",
|
69
|
+
"sudo chmod 744 #{@destination}",
|
70
|
+
"sudo chown root #{@destination}"
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "setting mode and owner with sudo as options" do
|
76
|
+
before do
|
77
|
+
@installer = create_file_installer @destination, :content => @contents,
|
78
|
+
:mode => "744", :owner => "root" do
|
79
|
+
@options[:sudo]= true
|
80
|
+
end
|
81
|
+
@installer_commands = @installer.install_sequence
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should run commands in correct order" do
|
85
|
+
@installer_commands.should == [
|
86
|
+
:TRANSFER,
|
87
|
+
"sudo mv /tmp/sprinkle_#{@destination} #{@destination}",
|
88
|
+
"sudo chown root #{@destination}",
|
89
|
+
"sudo chmod 744 #{@destination}"
|
90
|
+
]
|
91
|
+
end
|
92
|
+
|
53
93
|
end
|
54
94
|
|
95
|
+
|
55
96
|
context 'single pre/post commands' do
|
56
97
|
before do
|
57
98
|
@installer = create_file_installer @destination, :content => @contents do
|
@@ -67,7 +108,7 @@ describe Sprinkle::Installers::FileInstaller do
|
|
67
108
|
end
|
68
109
|
|
69
110
|
end
|
70
|
-
|
111
|
+
|
71
112
|
context 'pre/post with sudo' do
|
72
113
|
before do
|
73
114
|
@installer = create_file_installer @destination, :content => @contents do
|
@@ -80,7 +121,7 @@ describe Sprinkle::Installers::FileInstaller do
|
|
80
121
|
end
|
81
122
|
|
82
123
|
it "should call the pre and post install commands around the file transfer" do
|
83
|
-
@installer_commands.should == ["op1",:TRANSFER,
|
124
|
+
@installer_commands.should == ["op1",:TRANSFER,
|
84
125
|
"sudo mv /tmp/sprinkle_destination destination", "op2"]
|
85
126
|
end
|
86
127
|
end
|
@@ -101,7 +142,7 @@ describe Sprinkle::Installers::FileInstaller do
|
|
101
142
|
|
102
143
|
end
|
103
144
|
|
104
|
-
|
145
|
+
after do
|
105
146
|
@installer.process @roles
|
106
147
|
end
|
107
148
|
end
|
@@ -2,46 +2,63 @@ require File.expand_path("../../spec_helper", File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
describe Sprinkle::Installers::Runner do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe 'during installation' do
|
28
|
-
|
29
|
-
it 'should use sudo if specified locally' do
|
30
|
-
@installer = create_runner 'teste', :sudo => true
|
31
|
-
@install_commands = @installer.send :install_commands
|
32
|
-
@install_commands.should == ['sudo teste']
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should accept multiple commands" do
|
36
|
-
@installer = create_runner 'teste', 'test2'
|
37
|
-
@install_commands = @installer.send :install_commands
|
38
|
-
@install_commands.should == ['teste','test2']
|
5
|
+
before do
|
6
|
+
@package = mock(Sprinkle::Package, :name => 'package', :sudo? => false)
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_runner(*cmds)
|
10
|
+
options=cmds.extract_options!
|
11
|
+
Sprinkle::Installers::Runner.new(@package, cmds, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'when created' do
|
15
|
+
it 'should accept a single cmd to run' do
|
16
|
+
@installer = create_runner 'teste'
|
17
|
+
@installer.cmds.should == ['teste']
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should accept an array of commands to run' do
|
21
|
+
@installer = create_runner ['teste', 'world']
|
22
|
+
@installer.cmds.should == ['teste', 'world']
|
23
|
+
@installer.install_sequence.should == ['teste', 'world']
|
39
24
|
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'during installation' do
|
28
|
+
|
29
|
+
it 'should use sudo if specified locally' do
|
30
|
+
@installer = create_runner 'teste', :sudo => true
|
31
|
+
@install_commands = @installer.send :install_commands
|
32
|
+
@install_commands.should == ['sudo teste']
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should accept env options and convert to uppercase" do
|
36
|
+
@installer = create_runner 'command1', :env => {
|
37
|
+
:z => 'foo',
|
38
|
+
:PATH => '/some/path',
|
39
|
+
:user => 'deploy',
|
40
|
+
:a => 'bar'
|
41
|
+
}
|
42
|
+
@install_commands = @installer.send :install_commands
|
43
|
+
command_parts = @install_commands.first.split(/ /)
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
command_parts.shift.should == 'env'
|
46
|
+
command_parts.pop.should == 'command1'
|
47
|
+
|
48
|
+
command_parts.should =~ ['PATH=/some/path', 'USER=deploy', 'Z=foo', 'A=bar']
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should accept multiple commands" do
|
53
|
+
@installer = create_runner 'teste', 'test2'
|
54
|
+
@install_commands = @installer.send :install_commands
|
55
|
+
@install_commands.should == ['teste','test2']
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should run the given command for all specified packages' do
|
59
|
+
@installer = create_runner 'teste'
|
60
|
+
@install_commands = @installer.send :install_commands
|
61
|
+
@install_commands.should == ['teste']
|
62
|
+
end
|
63
|
+
end
|
47
64
|
end
|
@@ -237,9 +237,9 @@ describe Sprinkle::Installers::Source do
|
|
237
237
|
end
|
238
238
|
|
239
239
|
it 'should store the custom commands' do
|
240
|
-
@installer.options[:configure_command].
|
241
|
-
@installer.options[:build_command].
|
242
|
-
@installer.options[:install_command].
|
240
|
+
@installer.options[:configure_command].should == './custom-configure'
|
241
|
+
@installer.options[:build_command].should == 'custom-make'
|
242
|
+
@installer.options[:install_command].should == 'custom-make install'
|
243
243
|
end
|
244
244
|
|
245
245
|
it 'should use the custom commands' do
|
@@ -54,12 +54,34 @@ describe Sprinkle::Verify do
|
|
54
54
|
|
55
55
|
# Check for a certain RPM package
|
56
56
|
has_rpm 'ntp'
|
57
|
+
|
58
|
+
belongs_to_user "/etc/", "me"
|
59
|
+
belongs_to_user "/etc/", 2
|
60
|
+
belongs_to_group "/etc/", "root"
|
61
|
+
belongs_to_group "/etc/", 0
|
57
62
|
end
|
58
63
|
end
|
59
64
|
@verification = @package.verifications[0]
|
60
|
-
@delivery = mock(Sprinkle::Deployment, :process => true)
|
65
|
+
@delivery = mock(Sprinkle::Deployment, :process => true, :sudo_command => "sudo")
|
61
66
|
@verification.delivery = @delivery
|
62
67
|
end
|
68
|
+
|
69
|
+
describe "with sudo" do
|
70
|
+
before do
|
71
|
+
@package = package @name do
|
72
|
+
use_sudo true
|
73
|
+
gem 'nonexistent'
|
74
|
+
verify 'moo' do
|
75
|
+
md5_of_file "/etc/secret", "123abc"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
@verification = @package.verifications[0]
|
79
|
+
@verification.delivery = @delivery
|
80
|
+
end
|
81
|
+
it "should run sudo when necessary" do
|
82
|
+
@verification.commands.should include(%{test "`sudo md5sum /etc/secret | cut -f1 -d' '`" = "123abc"})
|
83
|
+
end
|
84
|
+
end
|
63
85
|
|
64
86
|
describe 'when created' do
|
65
87
|
it 'should raise error without a block' do
|
@@ -68,6 +90,13 @@ describe Sprinkle::Verify do
|
|
68
90
|
end
|
69
91
|
|
70
92
|
describe 'with checks' do
|
93
|
+
it "should test that a file belongs to a given user or group" do
|
94
|
+
@verification.commands.should include("find /etc/ -maxdepth 0 -user me | egrep '.*'")
|
95
|
+
@verification.commands.should include("find /etc/ -maxdepth 0 -uid 2 | egrep '.*'")
|
96
|
+
@verification.commands.should include("find /etc/ -maxdepth 0 -group root | egrep '.*'")
|
97
|
+
@verification.commands.should include("find /etc/ -maxdepth 0 -gid 0 | egrep '.*'")
|
98
|
+
end
|
99
|
+
|
71
100
|
it 'should do a "test -f" on the has_file check' do
|
72
101
|
@verification.commands.should include('test -f my_file.txt')
|
73
102
|
end
|
@@ -77,7 +106,7 @@ describe Sprinkle::Verify do
|
|
77
106
|
end
|
78
107
|
|
79
108
|
it 'should do a md5sum to see if a file matches local file' do
|
80
|
-
@verification.commands.should include(%{
|
109
|
+
@verification.commands.should include(%{test "`md5sum my_file.txt | cut -f1 -d' '`" = "ed20d984b757ad5291963389fc209864"})
|
81
110
|
end
|
82
111
|
|
83
112
|
it 'should do a "test -d" on the has_directory check' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sprinkle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-06-
|
13
|
+
date: 2013-06-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -158,9 +158,7 @@ files:
|
|
158
158
|
- MIT-LICENSE
|
159
159
|
- README.md
|
160
160
|
- Rakefile
|
161
|
-
- bad.rb
|
162
161
|
- bin/sprinkle
|
163
|
-
- config/deploy.rb
|
164
162
|
- examples/packages/build_essential.rb
|
165
163
|
- examples/packages/databases/mysql.rb
|
166
164
|
- examples/packages/databases/mysql_source.rb
|
@@ -183,13 +181,13 @@ files:
|
|
183
181
|
- examples/rails/rails.rb
|
184
182
|
- examples/rails/templates/mysql.cnf.erb
|
185
183
|
- examples/sprinkle/sprinkle.rb
|
186
|
-
- inner.rb
|
187
184
|
- lib/sprinkle.rb
|
188
185
|
- lib/sprinkle/actors/actor.rb
|
189
186
|
- lib/sprinkle/actors/capistrano.rb
|
190
187
|
- lib/sprinkle/actors/dummy.rb
|
191
188
|
- lib/sprinkle/actors/local.rb
|
192
189
|
- lib/sprinkle/actors/ssh.rb
|
190
|
+
- lib/sprinkle/actors/ssh/connection_cache.rb
|
193
191
|
- lib/sprinkle/actors/vlad.rb
|
194
192
|
- lib/sprinkle/core.rb
|
195
193
|
- lib/sprinkle/deployment.rb
|
@@ -201,6 +199,7 @@ files:
|
|
201
199
|
- lib/sprinkle/extensions/attributes.rb
|
202
200
|
- lib/sprinkle/extensions/blank_slate.rb
|
203
201
|
- lib/sprinkle/extensions/string.rb
|
202
|
+
- lib/sprinkle/extensions/sudo.rb
|
204
203
|
- lib/sprinkle/extensions/symbol.rb
|
205
204
|
- lib/sprinkle/installers/apt.rb
|
206
205
|
- lib/sprinkle/installers/binary.rb
|
@@ -299,8 +298,6 @@ files:
|
|
299
298
|
- spec/templates/test.erb
|
300
299
|
- sprinkle.gemspec
|
301
300
|
- templates/test.erb
|
302
|
-
- test.rb
|
303
|
-
- work/inner.rb
|
304
301
|
homepage: https://github.com/sprinkle-tool/sprinkle
|
305
302
|
licenses:
|
306
303
|
- MIT
|
data/bad.rb
DELETED
data/config/deploy.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
set :application, "set your application name here"
|
2
|
-
set :repository, "set your repository location here"
|
3
|
-
|
4
|
-
# set :scm, :git # You can set :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
|
5
|
-
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
|
6
|
-
|
7
|
-
role :web, "pastie.org" # Your HTTP server, Apache/etc
|
8
|
-
role :app, "pastie.org" # This may be the same as your `Web` server
|
9
|
-
role :db, "pastie.org", :primary => true # This is where Rails migrations will run
|
10
|
-
role :db, "pastie.org"
|
11
|
-
|
12
|
-
# if you want to clean up old releases on each deploy uncomment this:
|
13
|
-
# after "deploy:restart", "deploy:cleanup"
|
14
|
-
|
15
|
-
# if you're still using the script/reaper helper you will need
|
16
|
-
# these http://github.com/rails/irs_process_scripts
|
17
|
-
|
18
|
-
# If you are using Passenger mod_rails uncomment this:
|
19
|
-
namespace :deploy do
|
20
|
-
task :start do ; end
|
21
|
-
# task :stop do ; end
|
22
|
-
# task :restart, :roles => :app, :except => { :no_release => true } do
|
23
|
-
# run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
|
24
|
-
# end
|
25
|
-
end
|
data/inner.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
policy :twice, :roles => :app do
|
2
|
-
requires :hostname
|
3
|
-
# requires :db
|
4
|
-
# requires :web, :name => "bob"
|
5
|
-
# requires :web, :name => "suzy"
|
6
|
-
# requires :web, :name => "nick"
|
7
|
-
end
|
8
|
-
|
9
|
-
package :hostname do
|
10
|
-
apt "test" do
|
11
|
-
pre :install do
|
12
|
-
runner "BEFORE"
|
13
|
-
runner "BEFORE 2"
|
14
|
-
end
|
15
|
-
post :install do
|
16
|
-
runner "AFTER" do
|
17
|
-
pre(:install) { runner "before after" }
|
18
|
-
post(:install) { runner "after after" }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
deployment do
|
25
|
-
|
26
|
-
# delivery :dummy do
|
27
|
-
# role :app, 'beta1.pastie.org'
|
28
|
-
# role :app, 'beta2.pastie.org'
|
29
|
-
# end
|
30
|
-
|
31
|
-
# use vlad for deployment
|
32
|
-
# delivery :ssh do
|
33
|
-
# role :app, 'beta1.pastie.org'
|
34
|
-
# user "appz"
|
35
|
-
# end
|
36
|
-
|
37
|
-
# delivery :capistrano
|
38
|
-
delivery :capistrano do
|
39
|
-
role :app, 'beta1.pastie.org'
|
40
|
-
# role :app, 'beta2.pastie.org'
|
41
|
-
set :user, "appz"
|
42
|
-
set :use_sudo, true
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
data/test.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# package :echo do
|
2
|
-
# runner "echo hello world"
|
3
|
-
# end
|
4
|
-
#
|
5
|
-
# package :version do
|
6
|
-
# runner "cat /etc/lsb-release"
|
7
|
-
# end
|
8
|
-
#
|
9
|
-
# policy :once, :roles => :app do
|
10
|
-
# requires :echo
|
11
|
-
# requires :version
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
package :db do
|
15
|
-
# go do
|
16
|
-
# puts "<eval db>"
|
17
|
-
# runner "installing the db"
|
18
|
-
# end
|
19
|
-
verify do
|
20
|
-
has_file "/etc/db"
|
21
|
-
end
|
22
|
-
# runner "finalized"
|
23
|
-
end
|
24
|
-
|
25
|
-
package :hostname do
|
26
|
-
# go do
|
27
|
-
# # puts "<eval hostname : #{hostname}>"
|
28
|
-
# runner "echo #{hostname} > /etc/hostname", :sudo => true
|
29
|
-
# end
|
30
|
-
# push_text "now", "/etc/stupid_file"
|
31
|
-
# details "using name: front.pastie.org"
|
32
|
-
|
33
|
-
# runner "echo 'hostname'"
|
34
|
-
# runner "cat /etc/hostname"
|
35
|
-
|
36
|
-
version "5"
|
37
|
-
|
38
|
-
@what = "secret"
|
39
|
-
@something = "else"
|
40
|
-
file "/Users/jgoebel/notnow#{version}", :contents => c=render(:first)
|
41
|
-
# transfer "<%= @what %>\n<%= @what + something %>", "/Users/jgoebel/notnow2", :render => true,
|
42
|
-
# :binding => binding
|
43
|
-
|
44
|
-
verify do
|
45
|
-
has_file "/Users/jgoebel/notnow#{version}"
|
46
|
-
# md5_of_file "/Users/jgoebel/notnow", md5(c)
|
47
|
-
end
|
48
|
-
# verify do
|
49
|
-
# has_executable "/bin/ccc"
|
50
|
-
# end
|
51
|
-
end
|
52
|
-
|
53
|
-
package :web do
|
54
|
-
requires :db
|
55
|
-
|
56
|
-
# go do
|
57
|
-
# # puts "<eval web>"
|
58
|
-
# runner "installing web #{opts[:name]}"
|
59
|
-
# end
|
60
|
-
# runner "finalized"
|
61
|
-
|
62
|
-
verify do
|
63
|
-
# has_file "/etc/web/#{opts[:name]}"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
policy :twice, :roles => :app do
|
68
|
-
requires :hostname
|
69
|
-
# requires :db
|
70
|
-
# requires :web, :name => "bob"
|
71
|
-
# requires :web, :name => "suzy"
|
72
|
-
# requires :web, :name => "nick"
|
73
|
-
end
|
74
|
-
|
75
|
-
deployment do
|
76
|
-
|
77
|
-
# delivery :dummy do
|
78
|
-
# role :app, 'beta1.pastie.org'
|
79
|
-
# role :app, 'beta2.pastie.org'
|
80
|
-
# end
|
81
|
-
|
82
|
-
delivery :local
|
83
|
-
|
84
|
-
# delivery :vlad do
|
85
|
-
# script "vlad"
|
86
|
-
# end
|
87
|
-
|
88
|
-
# use ssh for deployment
|
89
|
-
# delivery :ssh do
|
90
|
-
# role :app, 'front.pastie.org'
|
91
|
-
# user "appz"
|
92
|
-
# end
|
93
|
-
|
94
|
-
# delivery :capistrano
|
95
|
-
# delivery :capistrano do
|
96
|
-
# role :app, 'beta1.pastie.org'
|
97
|
-
# role :app, 'beta2.pastie.org'
|
98
|
-
# set :user, "appz"
|
99
|
-
# set :use_sudo, true
|
100
|
-
# end
|
101
|
-
|
102
|
-
end
|
data/work/inner.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
policy :sprinkle, :roles => :app do
|
2
|
-
requires :sprinkle
|
3
|
-
end
|
4
|
-
|
5
|
-
package :sprinkle do
|
6
|
-
i=runner "test" do
|
7
|
-
# pre(:install) { install Installers::Runner.new(self,"before") }
|
8
|
-
# pre(:install) { runner "pre" }
|
9
|
-
# post(:install) { runner "after" }
|
10
|
-
post(:install) { noop }
|
11
|
-
end
|
12
|
-
# puts runner("blah")
|
13
|
-
# puts i.inspect
|
14
|
-
runner "next"
|
15
|
-
end
|
16
|
-
|
17
|
-
deployment do
|
18
|
-
|
19
|
-
# use vlad for deployment
|
20
|
-
delivery :dummy do
|
21
|
-
# role :app, 'yourhost.com'
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|