sprinkle 0.7.2 → 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://travis-ci.org/sprinkle-tool/sprinkle.png?branch=master)](https://travis-ci.org/sprinkle-tool/sprinkle)
|
7
|
+
[![Build Status](https://travis-ci.org/sprinkle-tool/sprinkle.png?branch=master)](https://travis-ci.org/sprinkle-tool/sprinkle) [![Code Climate](https://codeclimate.com/github/sprinkle-tool/sprinkle.png)](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
|