sprinkle 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +20 -0
- data/lib/sprinkle/actors/capistrano.rb +9 -9
- data/lib/sprinkle/actors/dummy.rb +1 -1
- data/lib/sprinkle/actors/ssh.rb +1 -1
- data/lib/sprinkle/extensions/attributes.rb +56 -0
- data/lib/sprinkle/installers/apt.rb +4 -2
- data/lib/sprinkle/installers/binary.rb +4 -4
- data/lib/sprinkle/installers/gem.rb +2 -8
- data/lib/sprinkle/installers/installer.rb +27 -9
- data/lib/sprinkle/installers/replace_text.rb +5 -1
- data/lib/sprinkle/installers/runner.rb +4 -0
- data/lib/sprinkle/installers/source.rb +26 -11
- data/lib/sprinkle/installers/transfer.rb +0 -2
- data/lib/sprinkle/installers/user.rb +6 -3
- data/lib/sprinkle/package.rb +23 -6
- data/lib/sprinkle/verify.rb +3 -3
- data/lib/sprinkle/version.rb +1 -1
- data/spec/sprinkle/actors/capistrano_spec.rb +11 -10
- data/spec/sprinkle/installers/apt_spec.rb +2 -2
- data/spec/sprinkle/installers/gem_spec.rb +1 -1
- data/spec/sprinkle/installers/installer_spec.rb +25 -15
- data/spec/sprinkle/installers/push_text_spec.rb +15 -0
- data/spec/sprinkle/installers/rpm_spec.rb +0 -4
- data/spec/sprinkle/installers/source_spec.rb +20 -10
- data/spec/sprinkle/installers/user_spec.rb +30 -0
- data/spec/sprinkle/verify_spec.rb +0 -11
- metadata +5 -7
- data/lib/sprinkle/configurable.rb +0 -32
- data/lib/sprinkle/extensions/arbitrary_options.rb +0 -10
- data/lib/sprinkle/extensions/dsl_accessor.rb +0 -15
- data/spec/sprinkle/configurable_spec.rb +0 -47
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
* push_text was escaping & and / when it should not be
|
2
|
+
|
3
|
+
*Stefano Diem Benatti*
|
4
|
+
|
1
5
|
* Sprinkle `sudo_cmd` and Capistrino should work together instead of getting in each others way
|
2
6
|
|
3
7
|
When using the capistrano actor `sudo_cmd` will now use the capistrano
|
@@ -13,3 +17,19 @@
|
|
13
17
|
* verify of local actor was never returning false so installers would never be executed
|
14
18
|
|
15
19
|
*Edgars Beigarts*
|
20
|
+
|
21
|
+
* Capistrano actor now defaults to loading "Capfile" not "deploy" when no block is given.
|
22
|
+
If for some reason you just have a 'deploy' file in your root folder you
|
23
|
+
should `capify .` your setup and move your deploy.rb file into the config
|
24
|
+
folder. Or you can provide a block with `recipe 'deploy'` to force the
|
25
|
+
old behavior.
|
26
|
+
|
27
|
+
*Josh Goebel*
|
28
|
+
|
29
|
+
* Capistrano actor now uses the configured setting of `run_method`, instead of always sudo.
|
30
|
+
The default Capistrano setup prefers sudo, so nothing should change for
|
31
|
+
most users. If you want to NOT use sudo to run commands you can set
|
32
|
+
`use_sudo` or `run_method` accordingly in your capistrano recipes:
|
33
|
+
`set :use_sudo, false` or `set :run_method, :run`
|
34
|
+
|
35
|
+
*Michael Nigh*
|
@@ -30,16 +30,16 @@ module Sprinkle
|
|
30
30
|
def @config.recipes(script)
|
31
31
|
_sprinkle_actor.recipes(script)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
if block
|
35
35
|
@config.instance_eval &block
|
36
36
|
else
|
37
|
-
@config.load
|
37
|
+
@config.load "Capfile" if File.exist?("Capfile")
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
def sudo?
|
42
|
-
@config.fetch(:run_method, :
|
42
|
+
@config.fetch(:run_method, :run) == :sudo
|
43
43
|
end
|
44
44
|
|
45
45
|
def sudo_command
|
@@ -49,7 +49,7 @@ module Sprinkle
|
|
49
49
|
# Determines if there are any servers for the given roles
|
50
50
|
def servers_for_role?(roles)
|
51
51
|
roles=Array(roles)
|
52
|
-
roles.any? { |r| @config.roles.keys.include?
|
52
|
+
roles.any? { |r| @config.roles.keys.include?(r) }
|
53
53
|
end
|
54
54
|
|
55
55
|
|
@@ -97,7 +97,7 @@ module Sprinkle
|
|
97
97
|
@log_recorder = log_recorder = Sprinkle::Utility::LogRecorder.new
|
98
98
|
commands = commands.map {|x| rewrite_command(x)}
|
99
99
|
define_task(name, roles) do
|
100
|
-
via = fetch(:run_method, :
|
100
|
+
via = fetch(:run_method, :run)
|
101
101
|
commands.each do |command|
|
102
102
|
if command == :TRANSFER
|
103
103
|
opts.reverse_merge!(:recursive => true)
|
@@ -108,9 +108,9 @@ module Sprinkle
|
|
108
108
|
else
|
109
109
|
# this reset the log
|
110
110
|
log_recorder.reset command
|
111
|
-
invoke_command(command, {:via => via}) do |
|
112
|
-
|
113
|
-
log_recorder.log(
|
111
|
+
invoke_command(command, {:via => via}) do |ch, stream, out|
|
112
|
+
::Capistrano::Configuration.default_io_proc.call(ch, stream, out) if Sprinkle::OPTIONS[:verbose]
|
113
|
+
log_recorder.log(stream, out)
|
114
114
|
end
|
115
115
|
end
|
116
116
|
end
|
@@ -123,7 +123,7 @@ module Sprinkle
|
|
123
123
|
# rip out any double sudos from the beginning of the command
|
124
124
|
def rewrite_command(cmd)
|
125
125
|
return cmd if cmd.is_a?(Symbol)
|
126
|
-
via = @config.fetch(:run_method, :
|
126
|
+
via = @config.fetch(:run_method, :run)
|
127
127
|
if via == :sudo and cmd =~ /^#{sudo_command}/
|
128
128
|
cmd.gsub(/^#{sudo_command}\s?/,"")
|
129
129
|
else
|
@@ -19,7 +19,7 @@ module Sprinkle
|
|
19
19
|
# Determines if there are any servers for the given roles
|
20
20
|
def servers_for_role?(roles)
|
21
21
|
roles=Array(roles)
|
22
|
-
roles.any? { |r| @roles.keys.include?
|
22
|
+
roles.any? { |r| @roles.keys.include?(r) }
|
23
23
|
end
|
24
24
|
|
25
25
|
def install(installer, roles, opts={})
|
data/lib/sprinkle/actors/ssh.rb
CHANGED
@@ -43,7 +43,7 @@ module Sprinkle
|
|
43
43
|
|
44
44
|
def initialize(options = {}, &block) #:nodoc:
|
45
45
|
@options = options.update(:user => 'root')
|
46
|
-
@roles = {}
|
46
|
+
@roles = {}
|
47
47
|
@connection_cache = SSHConnectionCache.new
|
48
48
|
self.instance_eval &block if block
|
49
49
|
raise "You must define at least a single role." if @roles.empty?
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Attributes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
attr_accessor :delivery
|
7
|
+
end
|
8
|
+
|
9
|
+
def defaults(deployment)
|
10
|
+
defaults = deployment.defaults[self.class.name.split(/::/).last.downcase.to_sym]
|
11
|
+
self.set_defaults(&defaults) if defaults
|
12
|
+
@delivery = deployment.style
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_defaults(&block)
|
16
|
+
before = @options
|
17
|
+
@options = {}
|
18
|
+
self.instance_eval(&block) if block
|
19
|
+
@options = before.reverse_merge(@options)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def read_from_package(m)
|
25
|
+
@package.send(m) if @package.respond_to?(m)
|
26
|
+
end
|
27
|
+
|
28
|
+
def option?(sym)
|
29
|
+
!!@options[sym]
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
|
34
|
+
def attributes(*list)
|
35
|
+
list.each do |a|
|
36
|
+
define_method a do |*val|
|
37
|
+
val=nil if val.empty?
|
38
|
+
val ? @options[a] = val.first : @options[a] || read_from_package(a)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def multi_attributes(*list)
|
44
|
+
list.each do |a|
|
45
|
+
define_method a do |*val|
|
46
|
+
val = val.try(:first)
|
47
|
+
return @options[a] unless val
|
48
|
+
@options[a]||=[]
|
49
|
+
val.is_a?(Array) ? @options[a] += val : @options[a] << val
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -31,6 +31,8 @@ module Sprinkle
|
|
31
31
|
super parent, *packages, &block
|
32
32
|
@options.reverse_merge!(:dependencies_only => false)
|
33
33
|
end
|
34
|
+
|
35
|
+
attributes :dependencies_only
|
34
36
|
|
35
37
|
auto_api
|
36
38
|
|
@@ -44,8 +46,8 @@ module Sprinkle
|
|
44
46
|
|
45
47
|
def install_commands #:nodoc:
|
46
48
|
command = @options[:dependencies_only] ? 'build-dep' : 'install'
|
47
|
-
noninteractive = "env DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive"
|
48
|
-
"#{noninteractive}
|
49
|
+
noninteractive = "#{sudo_cmd}env DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive"
|
50
|
+
"#{noninteractive} apt-get --force-yes -qyu #{command} #{@packages.join(' ')}"
|
49
51
|
end
|
50
52
|
|
51
53
|
end
|
@@ -29,13 +29,13 @@ module Sprinkle
|
|
29
29
|
raise 'No installation area defined' unless @options[:prefix]
|
30
30
|
raise 'No archive download area defined' unless @options[:archives]
|
31
31
|
|
32
|
-
[ "mkdir -p #{@options[:prefix]
|
33
|
-
"mkdir -p #{@options[:archives]
|
32
|
+
[ "mkdir -p #{@options[:prefix]}",
|
33
|
+
"mkdir -p #{@options[:archives]}" ]
|
34
34
|
end
|
35
35
|
|
36
36
|
def install_commands #:nodoc:
|
37
|
-
commands = [ "bash -c 'wget -cq --directory-prefix=#{@options[:archives]
|
38
|
-
commands << "bash -c \"cd #{@options[:prefix]
|
37
|
+
commands = [ "bash -c 'wget -cq --directory-prefix=#{@options[:archives]} #{@binary_archive}'" ]
|
38
|
+
commands << "bash -c \"cd #{@options[:prefix]} && #{extract_command} '#{@options[:archives]}/#{archive_name}'\""
|
39
39
|
end
|
40
40
|
|
41
41
|
def archive_name #:nodoc:
|
@@ -41,14 +41,8 @@ module Sprinkle
|
|
41
41
|
super parent, options, &block
|
42
42
|
@gem = gem
|
43
43
|
end
|
44
|
-
|
45
|
-
|
46
|
-
# package defines an installer called source so here we specify a method directly
|
47
|
-
# rather than rely on the automatic options processing since packages' method missing
|
48
|
-
# won't be run
|
49
|
-
return @options[:source] unless location
|
50
|
-
@options[:source] = location
|
51
|
-
end
|
44
|
+
|
45
|
+
attributes :source, :repository, :http_proxy, :build_flags, :version
|
52
46
|
|
53
47
|
protected
|
54
48
|
|
@@ -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::
|
54
|
+
include Sprinkle::Attributes
|
55
|
+
|
55
56
|
attr_accessor :delivery, :package, :options, :pre, :post #:nodoc:
|
56
57
|
|
57
58
|
def initialize(package, options = {}, &block) #:nodoc:
|
@@ -60,6 +61,8 @@ module Sprinkle
|
|
60
61
|
@pre = {}; @post = {}
|
61
62
|
self.instance_eval(&block) if block
|
62
63
|
end
|
64
|
+
|
65
|
+
attributes :prefix, :archives, :builds
|
63
66
|
|
64
67
|
class << self
|
65
68
|
def subclasses
|
@@ -67,7 +70,7 @@ module Sprinkle
|
|
67
70
|
end
|
68
71
|
|
69
72
|
def api(&block)
|
70
|
-
Sprinkle::Package::Package.
|
73
|
+
Sprinkle::Package::Package.add_api &block
|
71
74
|
end
|
72
75
|
|
73
76
|
def verify_api(&block)
|
@@ -88,19 +91,36 @@ module Sprinkle
|
|
88
91
|
end
|
89
92
|
|
90
93
|
def escape_shell_arg(str)
|
91
|
-
str.gsub("'", "'\\\\''").gsub("
|
94
|
+
str.gsub("'", "'\\\\''").gsub("\n", '\n')
|
92
95
|
end
|
93
96
|
|
94
|
-
def pre(stage, *commands)
|
97
|
+
def pre(stage, *commands, &block)
|
95
98
|
@pre[stage] ||= []
|
96
99
|
@pre[stage] += commands
|
97
|
-
@pre[stage] +=
|
100
|
+
@pre[stage] += commands_from_block(block)
|
98
101
|
end
|
99
102
|
|
100
|
-
def post(stage, *commands)
|
103
|
+
def post(stage, *commands, &block)
|
101
104
|
@post[stage] ||= []
|
102
105
|
@post[stage] += commands
|
103
|
-
@post[stage] +=
|
106
|
+
@post[stage] += commands_from_block(block)
|
107
|
+
end
|
108
|
+
|
109
|
+
def commands_from_block(block)
|
110
|
+
return [] unless block
|
111
|
+
out = nil
|
112
|
+
diff = @package.with_private_install_queue do
|
113
|
+
out = block.call
|
114
|
+
end
|
115
|
+
diff.empty? ? out : diff.map {|x| x.install_sequence }
|
116
|
+
end
|
117
|
+
|
118
|
+
def method_missing(method, *args, &block)
|
119
|
+
if package.class.installer_methods.include?(method)
|
120
|
+
@package.send(method, *args, &block)
|
121
|
+
else
|
122
|
+
super(method, *args, &block)
|
123
|
+
end
|
104
124
|
end
|
105
125
|
|
106
126
|
def per_host?
|
@@ -113,8 +133,6 @@ module Sprinkle
|
|
113
133
|
def announce; end
|
114
134
|
|
115
135
|
def process(roles) #:nodoc:
|
116
|
-
assert_delivery
|
117
|
-
|
118
136
|
if logger.debug?
|
119
137
|
sequence = install_sequence; sequence = sequence.join('; ') if sequence.is_a? Array
|
120
138
|
logger.debug "#{@package.name} install sequence: #{sequence} for roles: #{roles}\n"
|
@@ -45,8 +45,12 @@ module Sprinkle
|
|
45
45
|
|
46
46
|
protected
|
47
47
|
|
48
|
+
def escape_sed_arg(s)
|
49
|
+
escape_shell_arg(s).gsub("/", "\\\\/").gsub('&', '\\\&')
|
50
|
+
end
|
51
|
+
|
48
52
|
def install_commands #:nodoc:
|
49
|
-
"#{sudo_cmd}sed -i 's/#{
|
53
|
+
"#{sudo_cmd}sed -i 's/#{escape_sed_arg(@regex)}/#{escape_sed_arg(@text)}/g' #{@path}"
|
50
54
|
end
|
51
55
|
|
52
56
|
end
|
@@ -90,6 +90,9 @@ module Sprinkle
|
|
90
90
|
@source = source
|
91
91
|
end
|
92
92
|
|
93
|
+
multi_attributes :enable, :disable, :with, :without, :option,
|
94
|
+
:custom_install
|
95
|
+
|
93
96
|
def install_sequence #:nodoc:
|
94
97
|
prepare + download + extract + configure + build + install
|
95
98
|
end
|
@@ -107,23 +110,23 @@ module Sprinkle
|
|
107
110
|
raise 'No build area defined' unless @options[:builds]
|
108
111
|
raise 'No source download area defined' unless @options[:archives]
|
109
112
|
|
110
|
-
[ "mkdir -p #{@options[:prefix]
|
111
|
-
"mkdir -p #{@options[:builds]
|
112
|
-
"mkdir -p #{@options[:archives]
|
113
|
+
[ "mkdir -p #{@options[:prefix]}",
|
114
|
+
"mkdir -p #{@options[:builds]}",
|
115
|
+
"mkdir -p #{@options[:archives]}" ]
|
113
116
|
end
|
114
117
|
|
115
118
|
def download_commands #:nodoc:
|
116
|
-
[ "wget -cq -O '#{@options[:archives]
|
119
|
+
[ "wget -cq -O '#{@options[:archives]}/#{archive_name}' #{@source}" ]
|
117
120
|
end
|
118
121
|
|
119
122
|
def extract_commands #:nodoc:
|
120
|
-
[ "bash -c 'cd #{@options[:builds]
|
123
|
+
[ "bash -c 'cd #{@options[:builds]} && #{extract_command} #{@options[:archives]}/#{archive_name}'" ]
|
121
124
|
end
|
122
125
|
|
123
126
|
def configure_commands #:nodoc:
|
124
127
|
return [] if custom_install?
|
125
128
|
|
126
|
-
command = "bash -c 'cd #{build_dir} && ./configure --prefix=#{@options[:prefix]
|
129
|
+
command = "bash -c 'cd #{build_dir} && ./configure --prefix=#{@options[:prefix]} "
|
127
130
|
|
128
131
|
extras = {
|
129
132
|
:enable => '--enable', :disable => '--disable',
|
@@ -152,21 +155,33 @@ module Sprinkle
|
|
152
155
|
|
153
156
|
# REVISIT: must be better processing of custom install commands somehow? use splat operator?
|
154
157
|
def custom_install_commands #:nodoc:
|
155
|
-
dress @options[:custom_install], :install
|
158
|
+
dress @options[:custom_install], nil, :install
|
156
159
|
end
|
157
160
|
|
158
161
|
protected
|
162
|
+
|
163
|
+
def pre_commands(stage) #:nodoc:
|
164
|
+
dress @pre[stage] || [], :pre, stage
|
165
|
+
end
|
166
|
+
|
167
|
+
def post_commands(stage) #:nodoc:
|
168
|
+
dress @post[stage] || [], :post, stage
|
169
|
+
end
|
170
|
+
|
159
171
|
|
160
172
|
# dress is overriden from the base Sprinkle::Installers::Installer class so that the command changes
|
161
173
|
# directory to the build directory first. Also, the result of the command is logged.
|
162
|
-
def dress(commands, stage)
|
163
|
-
|
174
|
+
def dress(commands, pre_or_post, stage)
|
175
|
+
chdir = "cd #{build_dir} && "
|
176
|
+
chdir = "" if [:prepare, :download].include?(stage)
|
177
|
+
chdir = "" if stage == :extract and pre_or_post == :pre
|
178
|
+
commands.collect { |command| "bash -c '#{chdir}#{command} >> #{@package.name}-#{stage}.log 2>&1'" }
|
164
179
|
end
|
165
180
|
|
166
181
|
private
|
167
182
|
|
168
183
|
def create_options(key, prefix) #:nodoc:
|
169
|
-
@options[key].
|
184
|
+
@options[key].inject('') { |m, option| m << "#{prefix}-#{option} "; m }
|
170
185
|
end
|
171
186
|
|
172
187
|
def extract_command #:nodoc:
|
@@ -195,7 +210,7 @@ module Sprinkle
|
|
195
210
|
end
|
196
211
|
|
197
212
|
def build_dir #:nodoc:
|
198
|
-
"#{@options[:builds]
|
213
|
+
"#{@options[:builds]}/#{options[:custom_dir] || base_dir}"
|
199
214
|
end
|
200
215
|
|
201
216
|
def base_dir #:nodoc:
|
@@ -29,16 +29,19 @@ module Sprinkle
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def initialize(package, username, options = {}, &block) #:nodoc:
|
34
34
|
super package, options, &block
|
35
35
|
@username = username
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
protected
|
39
39
|
|
40
40
|
def install_commands #:nodoc:
|
41
|
-
|
41
|
+
noninteractive = "--gecos ,,,"
|
42
|
+
flags = @options[:flags] || ""
|
43
|
+
flags << noninteractive unless flags =~ /--gecos/
|
44
|
+
"adduser #{flags} #{@username}"
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
data/lib/sprinkle/package.rb
CHANGED
@@ -106,9 +106,17 @@ module Sprinkle
|
|
106
106
|
end
|
107
107
|
|
108
108
|
class Package #:nodoc:
|
109
|
-
# include ArbitraryOptions
|
110
109
|
attr_accessor :name, :provides, :installers, :verifications
|
111
110
|
attr_accessor :args, :opts
|
111
|
+
cattr_reader :installer_methods
|
112
|
+
@@installer_methods = []
|
113
|
+
|
114
|
+
def self.add_api(&block)
|
115
|
+
before = self.instance_methods
|
116
|
+
self.class_eval &block
|
117
|
+
added = self.instance_methods - before
|
118
|
+
@@installer_methods += added.map(&:to_sym)
|
119
|
+
end
|
112
120
|
|
113
121
|
def initialize(name, metadata = {}, &block)
|
114
122
|
raise 'No package name supplied' unless name
|
@@ -166,10 +174,6 @@ module Sprinkle
|
|
166
174
|
raise ContextError, "Cannot call get inside a package, must be inside an Installer block"
|
167
175
|
end
|
168
176
|
|
169
|
-
def noop(&block)
|
170
|
-
install Sprinkle::Installers::Runner.new(self, "echo noop", &block)
|
171
|
-
end
|
172
|
-
|
173
177
|
# meta installer
|
174
178
|
# TODO - fix to be atomic
|
175
179
|
def push_file(file, options ={}, &block)
|
@@ -249,6 +253,19 @@ module Sprinkle
|
|
249
253
|
end
|
250
254
|
|
251
255
|
def to_s; @name; end
|
256
|
+
|
257
|
+
# allow an installer to request a private install queue from the package
|
258
|
+
# for example to allow pre and post hooks to have their own installers that
|
259
|
+
# do not mess with the packages installer list
|
260
|
+
#
|
261
|
+
# returns: the private queue
|
262
|
+
def with_private_install_queue()
|
263
|
+
b = @installers
|
264
|
+
@installers = private_queue =[]
|
265
|
+
yield
|
266
|
+
@installers = b
|
267
|
+
private_queue
|
268
|
+
end
|
252
269
|
|
253
270
|
protected
|
254
271
|
|
@@ -256,7 +273,7 @@ module Sprinkle
|
|
256
273
|
@installers << i
|
257
274
|
i
|
258
275
|
end
|
259
|
-
|
276
|
+
|
260
277
|
private
|
261
278
|
|
262
279
|
def add_dependencies(packages, kind)
|
data/lib/sprinkle/verify.rb
CHANGED
@@ -59,7 +59,7 @@ module Sprinkle
|
|
59
59
|
# verify { has_magic_beans('ranch') }
|
60
60
|
# end
|
61
61
|
class Verify
|
62
|
-
include Sprinkle::
|
62
|
+
include Sprinkle::Attributes
|
63
63
|
attr_accessor :package, :description, :commands #:nodoc:
|
64
64
|
|
65
65
|
class <<self
|
@@ -69,6 +69,8 @@ module Sprinkle
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
attributes :padding
|
73
|
+
|
72
74
|
def initialize(package, description = '', &block) #:nodoc:
|
73
75
|
raise 'Verify requires a block.' unless block
|
74
76
|
|
@@ -82,8 +84,6 @@ module Sprinkle
|
|
82
84
|
end
|
83
85
|
|
84
86
|
def process(roles, pre = false) #:nodoc:
|
85
|
-
assert_delivery
|
86
|
-
|
87
87
|
description = @description.empty? ? " (#{@package.name})" : @description
|
88
88
|
|
89
89
|
if logger.debug?
|
data/lib/sprinkle/version.rb
CHANGED
@@ -55,7 +55,7 @@ describe Sprinkle::Actors::Capistrano do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'should evaluate the block against the actor instance' do
|
58
|
-
@actor.loaded_recipes.should
|
58
|
+
@actor.loaded_recipes.should == ['cool gear']
|
59
59
|
end
|
60
60
|
|
61
61
|
end
|
@@ -63,7 +63,8 @@ describe Sprinkle::Actors::Capistrano do
|
|
63
63
|
describe 'without a block' do
|
64
64
|
|
65
65
|
it 'should automatically load the default capistrano configuration' do
|
66
|
-
|
66
|
+
File.stub!(:exist?).with("Capfile").and_return true
|
67
|
+
@cap.should_receive(:load).with('Capfile').and_return
|
67
68
|
end
|
68
69
|
|
69
70
|
after do
|
@@ -77,15 +78,13 @@ describe Sprinkle::Actors::Capistrano do
|
|
77
78
|
describe 'recipes' do
|
78
79
|
|
79
80
|
it 'should add the recipe location to an internal store' do
|
80
|
-
@cap = create_cap
|
81
|
-
recipes 'deploy'
|
82
|
-
end
|
81
|
+
@cap = create_cap { recipes "deploy" }
|
83
82
|
@cap.loaded_recipes.should == [ @recipes ]
|
84
83
|
end
|
85
84
|
|
86
85
|
it 'should load the given recipe' do
|
87
86
|
@cap.should_receive(:load).with(@recipes).and_return
|
88
|
-
create_cap
|
87
|
+
@cap = create_cap { recipes "deploy" }
|
89
88
|
end
|
90
89
|
|
91
90
|
end
|
@@ -131,6 +130,7 @@ describe Sprinkle::Actors::Capistrano do
|
|
131
130
|
# pretend the package or installer has also added sudo
|
132
131
|
@commands =["sudo op1"]
|
133
132
|
@cap.stub(:sudo_command).and_return("sudo")
|
133
|
+
@cap.config.stub!(:fetch).and_return(:sudo)
|
134
134
|
@cap.unstub!(:run)
|
135
135
|
@cap.config.should_receive(:invoke_command).with('op1', :via => :sudo).ordered.and_return
|
136
136
|
end
|
@@ -205,12 +205,13 @@ describe Sprinkle::Actors::Capistrano do
|
|
205
205
|
@cap.config.stub!(:invoke_command).and_return
|
206
206
|
end
|
207
207
|
|
208
|
-
it 'should
|
209
|
-
@cap.config.should_receive(:invoke_command).with('op1', :via => :
|
210
|
-
@cap.config.should_receive(:invoke_command).with('op2', :via => :
|
208
|
+
it 'should run the supplied commands by default' do
|
209
|
+
@cap.config.should_receive(:invoke_command).with('op1', :via => :run).ordered.and_return
|
210
|
+
@cap.config.should_receive(:invoke_command).with('op2', :via => :run).ordered.and_return
|
211
211
|
end
|
212
212
|
|
213
|
-
it 'should
|
213
|
+
it 'should use sudo to invoke commands when so configured' do
|
214
|
+
@cap.config.set :run_method, :sudo
|
214
215
|
@cap.config.should_receive(:invoke_command).with('op1', :via => :sudo).ordered.and_return
|
215
216
|
@cap.config.should_receive(:invoke_command).with('op2', :via => :sudo).ordered.and_return
|
216
217
|
end
|
@@ -50,14 +50,14 @@ describe Sprinkle::Installers::Apt do
|
|
50
50
|
@package = create_pkg "name", :use_sudo => true
|
51
51
|
@installer = create_apt 'ruby'
|
52
52
|
@install_commands = @installer.send :install_commands
|
53
|
-
@install_commands.should =~ /sudo
|
53
|
+
@install_commands.should =~ /sudo env/
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'should use sudo if installer specifies' do
|
57
57
|
@package = create_pkg "name", :use_sudo => false
|
58
58
|
@installer = create_apt 'ruby', :sudo => true
|
59
59
|
@install_commands = @installer.send :install_commands
|
60
|
-
@install_commands.should =~ /sudo
|
60
|
+
@install_commands.should =~ /sudo env/
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'should invoke the apt installer for all specified packages' do
|
@@ -9,7 +9,7 @@ describe Sprinkle::Installers::Gem do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def create_gem(gem, version = nil, options = {}, &block)
|
12
|
-
@package = mock(Sprinkle::Package, :name => gem, :version => version
|
12
|
+
@package = mock(Sprinkle::Package, :name => gem, :version => version)
|
13
13
|
Sprinkle::Installers::Gem.new(@package, gem, options, &block)
|
14
14
|
end
|
15
15
|
|
@@ -42,19 +42,18 @@ describe Sprinkle::Installers::Installer do
|
|
42
42
|
|
43
43
|
it 'should accept an optional block to customize installers defaults' do
|
44
44
|
@installer = create_installer do; prefix '/usr/local'; end
|
45
|
-
@installer.prefix.
|
45
|
+
@installer.prefix.should == '/usr/local'
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'should override any deployment level defaults' do
|
49
49
|
@installer = create_installer do; prefix '/usr/local'; end
|
50
50
|
@installer.defaults(@deployment)
|
51
|
-
@installer.prefix.
|
51
|
+
@installer.prefix.should == '/usr/local'
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
describe 'during configuration' do
|
57
|
-
# We just check to make sure it has the Sprinkle::Configurable method
|
58
57
|
it 'should be configurable' do
|
59
58
|
@installer.should respond_to(:defaults)
|
60
59
|
end
|
@@ -126,41 +125,52 @@ describe Sprinkle::Installers::Installer do
|
|
126
125
|
|
127
126
|
describe "with a pre command" do
|
128
127
|
|
129
|
-
def create_installer_with_pre_command(cmd=
|
128
|
+
def create_installer_with_pre_command(cmd = nil, &block)
|
130
129
|
installer = Sprinkle::Installers::Installer.new @package do
|
131
|
-
pre :install, cmd
|
130
|
+
pre :install, cmd if cmd
|
132
131
|
|
133
132
|
def install_commands
|
134
133
|
["installer"]
|
135
134
|
end
|
136
135
|
end
|
137
|
-
|
136
|
+
installer.instance_eval &block if block
|
138
137
|
installer.stub!(:puts).and_return
|
139
138
|
installer.delivery = @delivery
|
140
139
|
installer
|
141
140
|
end
|
142
141
|
before do
|
143
142
|
@installer = create_installer_with_pre_command('run')
|
143
|
+
@package.stub!(:installers).and_return []
|
144
144
|
end
|
145
145
|
describe "string commands" do
|
146
146
|
it "should insert the pre command for the specific package in the installation process" do
|
147
147
|
@installer.send(:install_sequence).should == [ 'run', 'installer' ]
|
148
148
|
end
|
149
|
-
end
|
149
|
+
end
|
150
|
+
describe "block with their embeded installers" do
|
151
|
+
before(:each) do
|
152
|
+
@package = Package.new("package") do; end
|
153
|
+
@installer = create_installer_with_pre_command do
|
154
|
+
pre :install do
|
155
|
+
runner "b" do
|
156
|
+
pre(:install) { runner "a" }
|
157
|
+
post(:install) { runner "c" }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
it "should properly execute pre and post blocks" do
|
163
|
+
@installer.send(:install_sequence).should == [ "a", "b", "c", 'installer' ]
|
164
|
+
end
|
165
|
+
end
|
150
166
|
describe "blocks as commands" do
|
151
167
|
before(:each) do
|
152
|
-
@
|
168
|
+
@package = Package.new("package") do; end
|
169
|
+
@installer = create_installer_with_pre_command do
|
153
170
|
pre :install do
|
154
171
|
%w(a b c)
|
155
172
|
end
|
156
|
-
|
157
|
-
def install_commands
|
158
|
-
["installer"]
|
159
|
-
end
|
160
173
|
end
|
161
|
-
|
162
|
-
@installer.stub!(:puts).and_return
|
163
|
-
@installer.delivery = @delivery
|
164
174
|
end
|
165
175
|
it "should be able to store a block if it's the pre command" do
|
166
176
|
@installer.send(:install_sequence).should == [ "a", "b", "c", 'installer' ]
|
@@ -89,6 +89,21 @@ MULTI
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
describe 'sending a string with special characters' do
|
93
|
+
|
94
|
+
it "should not escape an ampersand" do
|
95
|
+
@installer = create_text "bob & lucy", "/dev/mind/the-day-after"
|
96
|
+
@install_commands = @installer.send :install_commands
|
97
|
+
@install_commands.should == %q[/bin/echo -e 'bob & lucy' |tee -a /dev/mind/the-day-after]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not escape a slash" do
|
101
|
+
@installer = create_text "bob/lucy", "/dev/mind/the-day-after"
|
102
|
+
@install_commands = @installer.send :install_commands
|
103
|
+
@install_commands.should == %q[/bin/echo -e 'bob/lucy' |tee -a /dev/mind/the-day-after]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
92
107
|
describe 'sending a string with single quotes' do
|
93
108
|
before do
|
94
109
|
@installer = create_text "I'm a string with a single quote", "/dev/mind/the-day-after"
|
@@ -76,35 +76,35 @@ describe Sprinkle::Installers::Source do
|
|
76
76
|
describe 'customized configuration' do
|
77
77
|
|
78
78
|
it 'should support specification of "enable" options' do
|
79
|
-
@installer.enable.
|
79
|
+
@installer.enable.should == %w( headers ssl deflate so )
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'should support specification of "disable" options' do
|
83
|
-
@installer.disable.
|
83
|
+
@installer.disable.should == %w( cache proxy rewrite )
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'should support specification of "with" options' do
|
87
|
-
@installer.with.
|
87
|
+
@installer.with.should == %w( debug extras )
|
88
88
|
end
|
89
89
|
|
90
90
|
it 'should support specification of "without" options' do
|
91
|
-
@installer.without.
|
91
|
+
@installer.without.should == %w( fancyisms pandas )
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'should support specification of "option" options' do
|
95
|
-
@installer.option.
|
95
|
+
@installer.option.should == %w( foo bar baz )
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'should support customized build area' do
|
99
|
-
@installer.prefix.
|
99
|
+
@installer.prefix.should == '/usr/local'
|
100
100
|
end
|
101
101
|
|
102
102
|
it 'should support customized source area' do
|
103
|
-
@installer.archives.
|
103
|
+
@installer.archives.should == '/usr/local/archives'
|
104
104
|
end
|
105
105
|
|
106
106
|
it 'should support customized install area' do
|
107
|
-
@installer.builds.
|
107
|
+
@installer.builds.should == '/usr/local/builds'
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -285,9 +285,16 @@ describe Sprinkle::Installers::Source do
|
|
285
285
|
it 'should run all pre-prepare commands' do
|
286
286
|
@commands.each { |k, v| @installer.should_receive(:pre_commands).with(k).and_return(v) }
|
287
287
|
end
|
288
|
+
|
289
|
+
it "should be logged" do
|
290
|
+
pending
|
291
|
+
end
|
288
292
|
|
289
293
|
it 'should be run relative to the source build area' do
|
290
|
-
|
294
|
+
[:prepare, :download, :extract].each { |stage, command|
|
295
|
+
@installer.send(:pre_commands, stage).first.should_not =~ %r{cd /usr/builds/ruby-1.8.6-p111} }
|
296
|
+
[:configure, :build, :install].each { |stage, command|
|
297
|
+
@installer.send(:pre_commands, stage).first.should =~ %r{cd /usr/builds/ruby-1.8.6-p111} }
|
291
298
|
end
|
292
299
|
|
293
300
|
after do
|
@@ -318,7 +325,10 @@ describe Sprinkle::Installers::Source do
|
|
318
325
|
end
|
319
326
|
|
320
327
|
it 'should be run relative to the source build area' do
|
321
|
-
|
328
|
+
[:prepare, :download].each { |stage, command|
|
329
|
+
@installer.send(:post_commands, stage).first.should_not =~ %r{cd /usr/builds/ruby-1.8.6-p111} }
|
330
|
+
[:extract, :configure, :build, :install].each { |stage, command|
|
331
|
+
@installer.send(:post_commands, stage).first.should =~ %r{cd /usr/builds/ruby-1.8.6-p111} }
|
322
332
|
end
|
323
333
|
|
324
334
|
after do
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path("../../spec_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Sprinkle::Installers::User do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@package = mock(Sprinkle::Package, :name => 'spec')
|
7
|
+
@user = "bob"
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_user(name, options = {}, &block)
|
11
|
+
Sprinkle::Installers::User.new "spec", name, options, &block
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'during installation' do
|
15
|
+
|
16
|
+
it "should invoke add user" do
|
17
|
+
@installer = create_user 'bob'
|
18
|
+
@install_commands = @installer.send :install_commands
|
19
|
+
@install_commands.should == "adduser --gecos ,,, bob"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should use actual gecos options if passed" do
|
23
|
+
@installer = create_user 'bob', :flags => "--gecos bob,,,"
|
24
|
+
@install_commands = @installer.send :install_commands
|
25
|
+
@install_commands.should == "adduser --gecos bob,,, bob"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -140,17 +140,6 @@ describe Sprinkle::Verify do
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
-
describe 'with configurations' do
|
144
|
-
# Make sure it includes Sprinkle::Configurable
|
145
|
-
it 'should respond to configurable methods' do
|
146
|
-
@verification.should respond_to(:defaults)
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'should default padding option to 4' do
|
150
|
-
@verification.padding.should eql(4)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
143
|
describe 'with process' do
|
155
144
|
it 'should raise an error when no delivery mechanism is set' do
|
156
145
|
@verification.instance_variable_set(:@delivery, nil)
|
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.
|
4
|
+
version: 0.6.0
|
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-05-
|
13
|
+
date: 2013-05-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -169,15 +169,13 @@ files:
|
|
169
169
|
- lib/sprinkle/actors/local.rb
|
170
170
|
- lib/sprinkle/actors/ssh.rb
|
171
171
|
- lib/sprinkle/actors/vlad.rb
|
172
|
-
- lib/sprinkle/configurable.rb
|
173
172
|
- lib/sprinkle/deployment.rb
|
174
173
|
- lib/sprinkle/errors/pretty_failure.rb
|
175
174
|
- lib/sprinkle/errors/remote_command_failure.rb
|
176
175
|
- lib/sprinkle/errors/transfer_failure.rb
|
177
|
-
- lib/sprinkle/extensions/arbitrary_options.rb
|
178
176
|
- lib/sprinkle/extensions/array.rb
|
177
|
+
- lib/sprinkle/extensions/attributes.rb
|
179
178
|
- lib/sprinkle/extensions/blank_slate.rb
|
180
|
-
- lib/sprinkle/extensions/dsl_accessor.rb
|
181
179
|
- lib/sprinkle/extensions/string.rb
|
182
180
|
- lib/sprinkle/extensions/symbol.rb
|
183
181
|
- lib/sprinkle/installers/apt.rb
|
@@ -235,7 +233,6 @@ files:
|
|
235
233
|
- spec/sprinkle/actors/capistrano_spec.rb
|
236
234
|
- spec/sprinkle/actors/local_spec.rb
|
237
235
|
- spec/sprinkle/actors/ssh_spec.rb
|
238
|
-
- spec/sprinkle/configurable_spec.rb
|
239
236
|
- spec/sprinkle/deployment_spec.rb
|
240
237
|
- spec/sprinkle/extensions/array_spec.rb
|
241
238
|
- spec/sprinkle/extensions/string_spec.rb
|
@@ -261,6 +258,7 @@ files:
|
|
261
258
|
- spec/sprinkle/installers/source_spec.rb
|
262
259
|
- spec/sprinkle/installers/thor_spec.rb
|
263
260
|
- spec/sprinkle/installers/transfer_spec.rb
|
261
|
+
- spec/sprinkle/installers/user_spec.rb
|
264
262
|
- spec/sprinkle/installers/yum_spec.rb
|
265
263
|
- spec/sprinkle/installers/zypper_spec.rb
|
266
264
|
- spec/sprinkle/package_spec.rb
|
@@ -300,7 +298,6 @@ test_files:
|
|
300
298
|
- spec/sprinkle/actors/capistrano_spec.rb
|
301
299
|
- spec/sprinkle/actors/local_spec.rb
|
302
300
|
- spec/sprinkle/actors/ssh_spec.rb
|
303
|
-
- spec/sprinkle/configurable_spec.rb
|
304
301
|
- spec/sprinkle/deployment_spec.rb
|
305
302
|
- spec/sprinkle/extensions/array_spec.rb
|
306
303
|
- spec/sprinkle/extensions/string_spec.rb
|
@@ -326,6 +323,7 @@ test_files:
|
|
326
323
|
- spec/sprinkle/installers/source_spec.rb
|
327
324
|
- spec/sprinkle/installers/thor_spec.rb
|
328
325
|
- spec/sprinkle/installers/transfer_spec.rb
|
326
|
+
- spec/sprinkle/installers/user_spec.rb
|
329
327
|
- spec/sprinkle/installers/yum_spec.rb
|
330
328
|
- spec/sprinkle/installers/zypper_spec.rb
|
331
329
|
- spec/sprinkle/package_spec.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module Sprinkle
|
2
|
-
#--
|
3
|
-
# TODO: Possible documentation?
|
4
|
-
#++
|
5
|
-
module Configurable #:nodoc:
|
6
|
-
attr_accessor :delivery
|
7
|
-
|
8
|
-
def defaults(deployment)
|
9
|
-
defaults = deployment.defaults[self.class.name.split(/::/).last.downcase.to_sym]
|
10
|
-
self.instance_eval(&defaults) if defaults
|
11
|
-
@delivery = deployment.style
|
12
|
-
end
|
13
|
-
|
14
|
-
def assert_delivery
|
15
|
-
raise 'Unknown command delivery target' unless @delivery
|
16
|
-
end
|
17
|
-
|
18
|
-
def method_missing(sym, *args, &block)
|
19
|
-
unless args.empty? # mutate if not set
|
20
|
-
@options ||= {}
|
21
|
-
@options[sym] = args unless @options[sym]
|
22
|
-
end
|
23
|
-
|
24
|
-
@options[sym] || @package.send(sym, *args, &block) # try the parents options if unknown
|
25
|
-
end
|
26
|
-
|
27
|
-
# both nil and false should return false
|
28
|
-
def option?(sym)
|
29
|
-
!!@options[sym]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
module ArbitraryOptions #:nodoc:
|
2
|
-
def self.included(base)
|
3
|
-
base.alias_method_chain :method_missing, :arbitrary_options
|
4
|
-
end
|
5
|
-
|
6
|
-
def method_missing_with_arbitrary_options(sym, *args, &block)
|
7
|
-
self.class.dsl_accessor sym
|
8
|
-
send(sym, *args, &block)
|
9
|
-
end
|
10
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
-
|
3
|
-
describe Sprinkle::Configurable do
|
4
|
-
module MyPrefix
|
5
|
-
class Configurable
|
6
|
-
include Sprinkle::Configurable
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
before do
|
11
|
-
@configurable = MyPrefix::Configurable.new
|
12
|
-
@default = Proc.new { }
|
13
|
-
@defaults = { :configurable => @default }
|
14
|
-
@deployment = Object.new
|
15
|
-
@deployment.stub!(:defaults).and_return(@defaults)
|
16
|
-
@deployment.stub!(:style)
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should be configurable via external defaults' do
|
20
|
-
@configurable.should respond_to(:defaults)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should select the defaults for the particular concrete installer class' do
|
24
|
-
@deployment.should_receive(:defaults).and_return(@defaults)
|
25
|
-
@defaults.should_receive(:[]).with(:configurable).and_return(@default)
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should configure the installer delivery mechansim' do
|
29
|
-
@configurable.should_receive(:instance_eval)
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'should maintain an options hash set arbitrarily via method missing' do
|
33
|
-
@configurable.instance_eval do
|
34
|
-
hsv 'gts'
|
35
|
-
end
|
36
|
-
@configurable.hsv.first.should == 'gts'
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should allow the delivery instance variable to be accessed' do
|
40
|
-
@configurable.delivery = "string"
|
41
|
-
@configurable.instance_variable_get(:@delivery).should eql("string")
|
42
|
-
end
|
43
|
-
|
44
|
-
after do
|
45
|
-
@configurable.defaults(@deployment)
|
46
|
-
end
|
47
|
-
end
|