sprinkle 0.4.2 → 0.5.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|