sprinkle 0.4.2 → 0.5.0.rc1
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 +8 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +54 -0
- data/README.markdown +178 -166
- data/Rakefile +4 -28
- data/bin/sprinkle +14 -1
- data/lib/sprinkle.rb +5 -1
- data/lib/sprinkle/actors/actors.rb +20 -5
- data/lib/sprinkle/actors/capistrano.rb +62 -36
- data/lib/sprinkle/actors/dummy.rb +127 -0
- data/lib/sprinkle/actors/local.rb +59 -17
- data/lib/sprinkle/actors/ssh.rb +189 -107
- data/lib/sprinkle/actors/vlad.rb +51 -32
- data/lib/sprinkle/configurable.rb +2 -1
- data/lib/sprinkle/deployment.rb +22 -2
- data/lib/sprinkle/errors/pretty_failure.rb +41 -0
- data/lib/sprinkle/errors/remote_command_failure.rb +24 -0
- data/lib/sprinkle/errors/transfer_failure.rb +28 -0
- data/lib/sprinkle/installers/apt.rb +17 -16
- data/lib/sprinkle/installers/binary.rb +23 -8
- data/lib/sprinkle/installers/brew.rb +17 -10
- data/lib/sprinkle/installers/bsd_port.rb +10 -6
- data/lib/sprinkle/installers/deb.rb +3 -10
- data/lib/sprinkle/installers/freebsd_pkg.rb +5 -11
- data/lib/sprinkle/installers/freebsd_portinstall.rb +8 -2
- data/lib/sprinkle/installers/gem.rb +9 -3
- data/lib/sprinkle/installers/group.rb +28 -4
- data/lib/sprinkle/installers/installer.rb +58 -7
- data/lib/sprinkle/installers/mac_port.rb +13 -6
- data/lib/sprinkle/installers/npm.rb +42 -0
- data/lib/sprinkle/installers/openbsd_pkg.rb +4 -11
- data/lib/sprinkle/installers/opensolaris_pkg.rb +7 -13
- data/lib/sprinkle/installers/package_installer.rb +33 -0
- data/lib/sprinkle/installers/pacman.rb +5 -13
- data/lib/sprinkle/installers/pear.rb +40 -0
- data/lib/sprinkle/installers/push_text.rb +18 -5
- data/lib/sprinkle/installers/rake.rb +7 -2
- data/lib/sprinkle/installers/reconnect.rb +29 -0
- data/lib/sprinkle/installers/replace_text.rb +11 -2
- data/lib/sprinkle/installers/rpm.rb +8 -6
- data/lib/sprinkle/installers/runner.rb +41 -16
- data/lib/sprinkle/installers/smart.rb +6 -17
- data/lib/sprinkle/installers/source.rb +22 -10
- data/lib/sprinkle/installers/thor.rb +7 -0
- data/lib/sprinkle/installers/transfer.rb +62 -41
- data/lib/sprinkle/installers/user.rb +34 -4
- data/lib/sprinkle/installers/yum.rb +10 -10
- data/lib/sprinkle/installers/zypper.rb +4 -15
- data/lib/sprinkle/package.rb +81 -98
- data/lib/sprinkle/policy.rb +11 -4
- data/lib/sprinkle/utility/log_recorder.rb +33 -0
- data/lib/sprinkle/verifiers/directory.rb +1 -1
- data/lib/sprinkle/verifiers/executable.rb +1 -1
- data/lib/sprinkle/verifiers/file.rb +11 -2
- data/lib/sprinkle/verifiers/package.rb +2 -14
- data/lib/sprinkle/verifiers/permission.rb +40 -0
- data/lib/sprinkle/verifiers/symlink.rb +2 -2
- data/lib/sprinkle/verifiers/test.rb +21 -0
- data/lib/sprinkle/verify.rb +3 -3
- data/lib/sprinkle/version.rb +3 -0
- data/spec/fixtures/my_file.txt +1 -0
- data/spec/sprinkle/actors/capistrano_spec.rb +16 -3
- data/spec/sprinkle/actors/local_spec.rb +24 -6
- data/spec/sprinkle/actors/ssh_spec.rb +38 -0
- data/spec/sprinkle/installers/apt_spec.rb +23 -2
- data/spec/sprinkle/installers/binary_spec.rb +22 -14
- data/spec/sprinkle/installers/brew_spec.rb +4 -4
- data/spec/sprinkle/installers/installer_spec.rb +36 -7
- data/spec/sprinkle/installers/npm_spec.rb +16 -0
- data/spec/sprinkle/installers/pear_spec.rb +16 -0
- data/spec/sprinkle/installers/push_text_spec.rb +23 -1
- data/spec/sprinkle/installers/rpm_spec.rb +5 -0
- data/spec/sprinkle/installers/runner_spec.rb +27 -11
- data/spec/sprinkle/installers/smart_spec.rb +60 -0
- data/spec/sprinkle/installers/source_spec.rb +4 -4
- data/spec/sprinkle/installers/transfer_spec.rb +31 -16
- data/spec/sprinkle/package_spec.rb +10 -2
- data/spec/sprinkle/policy_spec.rb +6 -0
- data/spec/sprinkle/verify_spec.rb +18 -4
- data/sprinkle.gemspec +22 -158
- metadata +178 -96
- data/TODO +0 -56
- data/VERSION +0 -1
- data/lib/sprinkle/verifiers/apt.rb +0 -21
- data/lib/sprinkle/verifiers/brew.rb +0 -21
- data/lib/sprinkle/verifiers/rpm.rb +0 -21
- data/lib/sprinkle/verifiers/users_groups.rb +0 -33
@@ -25,6 +25,12 @@ module Sprinkle
|
|
25
25
|
#
|
26
26
|
class ReplaceText < Installer
|
27
27
|
attr_accessor :regex, :text, :path #:nodoc:
|
28
|
+
|
29
|
+
api do
|
30
|
+
def replace_text(regex, text, path, options={}, &block)
|
31
|
+
install Sprinkle::Installers::ReplaceText.new(self, regex, text, path, options, &block)
|
32
|
+
end
|
33
|
+
end
|
28
34
|
|
29
35
|
def initialize(parent, regex, text, path, options={}, &block) #:nodoc:
|
30
36
|
super parent, options, &block
|
@@ -32,11 +38,14 @@ module Sprinkle
|
|
32
38
|
@text = text
|
33
39
|
@path = path
|
34
40
|
end
|
41
|
+
|
42
|
+
def announce
|
43
|
+
log "--> Replace '#{@regex}' with '#{@text}' in file #{@path}"
|
44
|
+
end
|
35
45
|
|
36
46
|
protected
|
37
|
-
|
47
|
+
|
38
48
|
def install_commands #:nodoc:
|
39
|
-
logger.info "--> Replace '#{@regex}' with '#{@text}' in file #{@path}"
|
40
49
|
"#{'sudo ' if option?(:sudo)}sed -i 's/#{@regex.gsub("'", "'\\\\''").gsub("/", "\\\\/").gsub("\n", '\n')}/#{@text.gsub("'", "'\\\\''").gsub("/", "\\\\/").gsub("\n", '\n')}/g' #{@path}"
|
41
50
|
end
|
42
51
|
|
@@ -10,6 +10,7 @@ module Sprinkle
|
|
10
10
|
#
|
11
11
|
# package :magic_beans do
|
12
12
|
# rpm 'magic_beans'
|
13
|
+
# verify { has_rpm 'magic_beans' }
|
13
14
|
# end
|
14
15
|
#
|
15
16
|
# You may also specify multiple rpms as an array:
|
@@ -17,13 +18,14 @@ module Sprinkle
|
|
17
18
|
# package :magic_beans do
|
18
19
|
# rpm %w(magic_beans magic_sauce)
|
19
20
|
# end
|
20
|
-
class Rpm <
|
21
|
-
attr_accessor :packages #:nodoc:
|
21
|
+
class Rpm < PackageInstaller
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
auto_api
|
24
|
+
|
25
|
+
verify_api do
|
26
|
+
def has_rpm(package)
|
27
|
+
@commands << "rpm -qa | grep #{package}"
|
28
|
+
end
|
27
29
|
end
|
28
30
|
|
29
31
|
protected
|
@@ -1,18 +1,43 @@
|
|
1
1
|
module Sprinkle
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
2
|
+
module Installers
|
3
|
+
# The runner installer is great for running a simple command.
|
4
|
+
#
|
5
|
+
# == Example Usage
|
6
|
+
#
|
7
|
+
# package :magic_beans do
|
8
|
+
# runner "make world"
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# You can also pass multiple commands as arguments or an array.
|
12
|
+
#
|
13
|
+
# package :magic_beans do
|
14
|
+
# runner "make world", "destroy world"
|
15
|
+
# runner [ "make world", "destroy world" ]
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
class Runner < Installer
|
19
|
+
|
20
|
+
api do
|
21
|
+
def runner(*cmds, &block)
|
22
|
+
options = cmds.extract_options!
|
23
|
+
install Sprinkle::Installers::Runner.new(self, cmds, options, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_accessor :cmds #:nodoc:
|
28
|
+
def initialize(parent, cmds, options = {}, &block) #:nodoc:
|
29
|
+
super parent, options, &block
|
30
|
+
@cmds = [*cmds].flatten
|
31
|
+
raise "you need to specify a command" if cmds.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def install_commands #:nodoc:
|
37
|
+
sudo_cmd ?
|
38
|
+
@cmds.map { |cmd| "#{sudo_cmd}#{cmd}"} :
|
39
|
+
@cmds
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
18
43
|
end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
class Smart <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@packages = packages
|
3
|
+
class Smart < PackageInstaller
|
4
|
+
|
5
|
+
api do
|
6
|
+
def smart(*names, &block)
|
7
|
+
install Sprinkle::Installers::Smart.new(self, *names, &block)
|
8
|
+
end
|
10
9
|
end
|
11
10
|
|
12
11
|
protected
|
@@ -16,14 +15,4 @@ module Sprinkle
|
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|
19
|
-
end
|
20
|
-
|
21
|
-
module Sprinkle
|
22
|
-
module Package
|
23
|
-
class Package
|
24
|
-
def smart(*names, &block)
|
25
|
-
@installer = Sprinkle::Installers::Smart.new(self, *names, &block)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
18
|
end
|
@@ -62,24 +62,40 @@ module Sprinkle
|
|
62
62
|
# end
|
63
63
|
# end
|
64
64
|
#
|
65
|
+
# Fifth, specifying a custom directory where the archive actually is extracted to:
|
66
|
+
#
|
67
|
+
# package :ruby_build do
|
68
|
+
# source 'https://github.com/sstephenson/ruby-build/archive/v20130227.tar.gz' do
|
69
|
+
# custom_dir 'ruby-build-20130227'
|
70
|
+
# custom_install './install.sh'
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
65
74
|
# As you can see, setting options is as simple as creating a
|
66
75
|
# block and calling the option as a method with the value as
|
67
76
|
# its parameter.
|
68
77
|
|
69
78
|
class Source < Installer
|
70
79
|
attr_accessor :source #:nodoc:
|
80
|
+
|
81
|
+
api do
|
82
|
+
def source(source, options = {}, &block)
|
83
|
+
@recommends << :build_essential # Ubuntu/Debian
|
84
|
+
install Sprinkle::Installers::Source.new(self, source, options, &block)
|
85
|
+
end
|
86
|
+
end
|
71
87
|
|
72
88
|
def initialize(parent, source, options = {}, &block) #:nodoc:
|
73
|
-
@source = source
|
74
89
|
super parent, options, &block
|
90
|
+
@source = source
|
91
|
+
end
|
92
|
+
|
93
|
+
def install_sequence #:nodoc:
|
94
|
+
prepare + download + extract + configure + build + install
|
75
95
|
end
|
76
96
|
|
77
97
|
protected
|
78
98
|
|
79
|
-
def install_sequence #:nodoc:
|
80
|
-
prepare + download + extract + configure + build + install
|
81
|
-
end
|
82
|
-
|
83
99
|
%w( prepare download extract configure build install ).each do |stage|
|
84
100
|
define_method stage do
|
85
101
|
pre_commands(stage.to_sym) + self.send("#{stage}_commands") + post_commands(stage.to_sym)
|
@@ -97,11 +113,7 @@ module Sprinkle
|
|
97
113
|
end
|
98
114
|
|
99
115
|
def download_commands #:nodoc:
|
100
|
-
|
101
|
-
[ "cp #{@source} #{@options[:archives].first}/#{archive_name}" ]
|
102
|
-
else
|
103
|
-
[ "wget -cq -O '#{@options[:archives].first}/#{archive_name}' #{@source}" ]
|
104
|
-
end
|
116
|
+
[ "wget -cq -O '#{@options[:archives].first}/#{archive_name}' #{@source}" ]
|
105
117
|
end
|
106
118
|
|
107
119
|
def extract_commands #:nodoc:
|
@@ -20,6 +20,13 @@ module Sprinkle
|
|
20
20
|
# end
|
21
21
|
|
22
22
|
class Thor < Installer
|
23
|
+
|
24
|
+
api do
|
25
|
+
def thor(name, options = {}, &block)
|
26
|
+
install Sprinkle::Installers::Thor.new(self, name, options, &block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
23
30
|
def initialize(parent, commands, options = {}, &block) #:nodoc:
|
24
31
|
super parent, options, &block
|
25
32
|
@commands = commands
|
@@ -84,16 +84,46 @@ module Sprinkle
|
|
84
84
|
# directories or changing permissions), you can use the pre/post :install directives
|
85
85
|
# and they will be run.
|
86
86
|
class Transfer < Installer
|
87
|
-
attr_accessor :source, :destination #:nodoc:
|
87
|
+
attr_accessor :source, :destination, :sourcepath #:nodoc:
|
88
|
+
|
89
|
+
api do
|
90
|
+
def transfer(source, destination, options = {}, &block)
|
91
|
+
options.merge!(:binding => binding())
|
92
|
+
install Sprinkle::Installers::Transfer.new(self, source, destination, options, &block)
|
93
|
+
end
|
94
|
+
end
|
88
95
|
|
89
96
|
def initialize(parent, source, destination, options={}, &block) #:nodoc:
|
90
|
-
super parent, options, &block
|
91
97
|
@source = source
|
92
98
|
@destination = destination
|
99
|
+
@orig_destination = destination
|
100
|
+
super parent, options, &block
|
101
|
+
@binding = options[:binding]
|
102
|
+
# perform the transfer in two steps if we're using sudo
|
103
|
+
if sudo?
|
104
|
+
final = @destination
|
105
|
+
@destination = "/tmp/sprinkle_#{File.basename(@destination)}"
|
106
|
+
post :install, "#{sudo_cmd}mv #{@destination} #{final}"
|
107
|
+
end
|
108
|
+
owner(options[:owner]) if options[:owner]
|
109
|
+
mode(options[:mode]) if options[:mode]
|
110
|
+
|
111
|
+
options[:render]=true if source_is_template?
|
112
|
+
options[:recursive]=false if options[:render]
|
113
|
+
end
|
114
|
+
|
115
|
+
def owner(owner)
|
116
|
+
@owner = owner
|
117
|
+
post :install, "#{sudo_cmd}chown #{owner} #{@orig_destination}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def mode(mode)
|
121
|
+
@mode = mode
|
122
|
+
post :install, "#{sudo_cmd}chmod #{mode} #{@orig_destination}"
|
93
123
|
end
|
94
124
|
|
95
125
|
def install_commands
|
96
|
-
|
126
|
+
:TRANSFER
|
97
127
|
end
|
98
128
|
|
99
129
|
def self.render_template(template, context, prefix)
|
@@ -118,60 +148,51 @@ module Sprinkle
|
|
118
148
|
end
|
119
149
|
|
120
150
|
def render_template_file(path, context, prefix)
|
121
|
-
template = File.read(path)
|
151
|
+
template = source_is_template? ? path : File.read(path)
|
122
152
|
tempfile = render_template(template, context, @package.name)
|
123
153
|
tempfile
|
124
154
|
end
|
155
|
+
|
156
|
+
def source_is_template?
|
157
|
+
@source.split("\n").size>1
|
158
|
+
end
|
125
159
|
|
126
160
|
def process(roles) #:nodoc:
|
127
161
|
assert_delivery
|
128
162
|
|
129
|
-
|
130
|
-
logger.debug "transfer: #{@source} -> #{@destination} for roles: #{roles}\n"
|
131
|
-
end
|
163
|
+
logger.debug "transfer: #{@source} -> #{@destination} for roles: #{roles}\n"
|
132
164
|
|
133
|
-
|
134
|
-
pre = pre_commands(:install)
|
135
|
-
unless pre.empty?
|
136
|
-
sequence = pre; sequence = sequence.join('; ') if sequence.is_a? Array
|
137
|
-
logger.info "#{@package.name} pre-transfer commands: #{sequence} for roles: #{roles}\n"
|
138
|
-
@delivery.process @package.name, [pre].flatten, roles
|
139
|
-
end
|
165
|
+
return if Sprinkle::OPTIONS[:testing]
|
140
166
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
else
|
150
|
-
context[k] = v
|
151
|
-
end
|
167
|
+
if options[:render]
|
168
|
+
if options[:locals]
|
169
|
+
context = {}
|
170
|
+
options[:locals].each_pair do |k,v|
|
171
|
+
if v.respond_to?(:call)
|
172
|
+
context[k] = v.call
|
173
|
+
else
|
174
|
+
context[k] = v
|
152
175
|
end
|
153
|
-
else
|
154
|
-
context = binding()
|
155
176
|
end
|
156
|
-
|
157
|
-
tempfile = render_template_file(@source, context, @package.name)
|
158
|
-
sourcepath = tempfile.path
|
159
|
-
logger.info "Rendering template #{@source} to temporary file #{sourcepath}"
|
160
|
-
recursive = false
|
161
177
|
else
|
162
|
-
|
178
|
+
# context = binding()
|
179
|
+
context = @binding
|
163
180
|
end
|
164
181
|
|
165
|
-
|
166
|
-
@
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
logger.info "#{@package.name} post-transfer commands: #{sequence} for roles: #{roles}\n"
|
172
|
-
@delivery.process @package.name, [post].flatten, roles
|
182
|
+
tempfile = render_template_file(@source, context, @package.name)
|
183
|
+
@sourcepath = tempfile.path
|
184
|
+
if source_is_template?
|
185
|
+
logger.debug "Rendering inline template to temporary file #{sourcepath}"
|
186
|
+
else
|
187
|
+
logger.debug "Rendering template #{@source} to temporary file #{sourcepath}"
|
173
188
|
end
|
189
|
+
recursive = false
|
190
|
+
else
|
191
|
+
@sourcepath = @source
|
174
192
|
end
|
193
|
+
|
194
|
+
logger.debug " --> Transferring #{sourcepath} to #{@orig_destination} for roles: #{roles}"
|
195
|
+
@delivery.install(self, roles, :recursive => @options[:recursive])
|
175
196
|
end
|
176
197
|
end
|
177
198
|
end
|
@@ -1,13 +1,43 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
+
# The user installer helps add users. You may pass flags as an option.
|
4
|
+
#
|
5
|
+
# == Example Usage
|
6
|
+
#
|
7
|
+
# package :users do
|
8
|
+
# add_user 'admin', :flags => "--disabled-password"
|
9
|
+
#
|
10
|
+
# verify do
|
11
|
+
# has_user 'admin', :in_group = "root"
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
|
3
15
|
class User < Installer
|
4
|
-
|
5
|
-
|
16
|
+
|
17
|
+
api do
|
18
|
+
def add_user(username, options={}, &block)
|
19
|
+
install Sprinkle::Installers::User.new(self, username, options, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
verify_api do
|
24
|
+
def has_user(user, opts = {})
|
25
|
+
if opts[:in_group]
|
26
|
+
@commands << "id -nG #{user} | xargs -n1 echo | grep #{opts[:in_group]}"
|
27
|
+
else
|
28
|
+
@commands << "id #{user}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(package, username, options = {}, &block) #:nodoc:
|
34
|
+
super package, options, &block
|
6
35
|
@username = username
|
7
|
-
@options = options
|
8
36
|
end
|
37
|
+
|
9
38
|
protected
|
10
|
-
|
39
|
+
|
40
|
+
def install_commands #:nodoc:
|
11
41
|
"adduser #{@options[:flags]} #{@username}"
|
12
42
|
end
|
13
43
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
# = Yum Package Installer
|
4
|
-
#
|
5
3
|
# The Yum package installer installs RPM packages.
|
6
4
|
#
|
7
5
|
# == Example Usage
|
@@ -10,20 +8,22 @@ module Sprinkle
|
|
10
8
|
#
|
11
9
|
# package :magic_beans do
|
12
10
|
# yum 'magic_beans'
|
11
|
+
# verify { has_yum 'magic_beans' }
|
13
12
|
# end
|
14
13
|
#
|
15
|
-
# You may also specify multiple rpms as an array:
|
14
|
+
# You may also specify multiple rpms as arguments or an array:
|
16
15
|
#
|
17
16
|
# package :magic_beans do
|
18
|
-
# yum
|
17
|
+
# yum "magic_beans", "magic_sauce"
|
19
18
|
# end
|
20
|
-
class Yum <
|
21
|
-
|
19
|
+
class Yum < PackageInstaller
|
20
|
+
|
21
|
+
auto_api
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
verify_api do
|
24
|
+
def has_yum(package)
|
25
|
+
@commands << "yum list installed #{package} | grep ^#{package}"
|
26
|
+
end
|
27
27
|
end
|
28
28
|
|
29
29
|
protected
|