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
data/lib/sprinkle/deployment.rb
CHANGED
@@ -52,7 +52,9 @@ module Sprinkle
|
|
52
52
|
# the actor. For more information on what configuration options are
|
53
53
|
# available, view the corresponding Sprinkle::Actors page.
|
54
54
|
def delivery(type, &block) #:doc:
|
55
|
-
|
55
|
+
type=type.to_s.titleize
|
56
|
+
type="SSH" if type=="Ssh"
|
57
|
+
@style = ("Sprinkle::Actors::" + type).constantize.new &block
|
56
58
|
end
|
57
59
|
|
58
60
|
def method_missing(sym, *args, &block) #:nodoc:
|
@@ -62,11 +64,29 @@ module Sprinkle
|
|
62
64
|
def respond_to?(sym) #:nodoc:
|
63
65
|
!!@defaults[sym]
|
64
66
|
end
|
67
|
+
|
68
|
+
def active_policies
|
69
|
+
if role=Sprinkle::OPTIONS[:only_role]
|
70
|
+
role=role.to_sym
|
71
|
+
POLICIES.select {|x| [x.roles].flatten.include?(role) }
|
72
|
+
else
|
73
|
+
POLICIES
|
74
|
+
end
|
75
|
+
end
|
65
76
|
|
66
77
|
def process #:nodoc:
|
67
|
-
|
78
|
+
active_policies.each do |policy|
|
68
79
|
policy.process(self)
|
69
80
|
end
|
81
|
+
rescue Sprinkle::Errors::RemoteCommandFailure => e
|
82
|
+
e.print_summary
|
83
|
+
exit
|
84
|
+
rescue Sprinkle::Errors::TransferFailure => e
|
85
|
+
e.print_summary
|
86
|
+
exit
|
87
|
+
ensure
|
88
|
+
# do any cleanup our actor may need to close network sockets, etc
|
89
|
+
@style.teardown if @style.respond_to?(:teardown)
|
70
90
|
end
|
71
91
|
end
|
72
92
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Errors
|
3
|
+
|
4
|
+
class PrettyFailure < StandardError #:nodoc:
|
5
|
+
|
6
|
+
attr_accessor :details
|
7
|
+
|
8
|
+
def initialize(installer, details={}, previous_error=nil)
|
9
|
+
@installer = installer
|
10
|
+
@details = details
|
11
|
+
@previous_error = previous_error
|
12
|
+
end
|
13
|
+
|
14
|
+
def log(s, o)
|
15
|
+
puts s
|
16
|
+
puts "-" * (s.length+2)
|
17
|
+
puts o
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
21
|
+
def boxed(s)
|
22
|
+
puts red("-"*54)
|
23
|
+
puts red("| #{s.center(50)} |")
|
24
|
+
puts red("-"*54)
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def color(code, s)
|
31
|
+
"\033[%sm%s\033[0m"%[code,s]
|
32
|
+
end
|
33
|
+
|
34
|
+
def red(s)
|
35
|
+
color(31, s)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Errors
|
3
|
+
|
4
|
+
class RemoteCommandFailure < PrettyFailure #:nodoc:
|
5
|
+
|
6
|
+
def print_summary
|
7
|
+
summary
|
8
|
+
log "Command", @details[:command]
|
9
|
+
# capistrano returns this
|
10
|
+
log "Hosts", @details[:hosts] if @details[:hosts]
|
11
|
+
# ssh actor returns error and stdout outputs
|
12
|
+
log "STDERR", @details[:error] unless @details[:error].blank?
|
13
|
+
log "STDOUT", @details[:stdout] unless @details[:stdout].blank?
|
14
|
+
log "Actor error message", @details[:message] if @details[:message]
|
15
|
+
end
|
16
|
+
|
17
|
+
def summary
|
18
|
+
boxed("Package '#{@installer.package.name}' returned error code #{@details[:code]}.")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Errors
|
3
|
+
|
4
|
+
class TransferFailure < PrettyFailure #:nodoc:
|
5
|
+
|
6
|
+
def self.no_permission(installer,e)
|
7
|
+
tf=TransferFailure.new(installer, {}, e)
|
8
|
+
tf.details[:error]=e.message
|
9
|
+
tf
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_summary
|
13
|
+
summary
|
14
|
+
# log "Command", @details[:command]
|
15
|
+
log "ERROR", @details[:error]
|
16
|
+
if details[:error] =~ /Permission denied/
|
17
|
+
log "HINTS", "You may want to try passing the :sudo option to transfer."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def summary
|
22
|
+
boxed("Package '#{@installer.package.name}' could not transfer #{@installer.source}")
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
# = Apt Package Installer
|
4
|
-
#
|
5
3
|
# The Apt package installer uses the +apt-get+ command to install
|
6
4
|
# packages. The apt installer has only one option which can be
|
7
5
|
# modified which is the +dependencies_only+ option. When this is
|
@@ -13,38 +11,41 @@ module Sprinkle
|
|
13
11
|
# First, a simple installation of the magic_beans package:
|
14
12
|
#
|
15
13
|
# package :magic_beans do
|
16
|
-
# description "Beans beans they're good for your heart..."
|
17
14
|
# apt 'magic_beans_package'
|
15
|
+
# verify { has_apt 'magic_beans_package' }
|
18
16
|
# end
|
19
17
|
#
|
20
18
|
# Second, only build the magic_beans dependencies:
|
21
19
|
#
|
22
20
|
# package :magic_beans_depends do
|
23
|
-
# apt 'magic_beans_package'
|
21
|
+
# apt 'magic_beans_package' do
|
22
|
+
# dependencies_only true
|
23
|
+
# end
|
24
24
|
# end
|
25
25
|
#
|
26
26
|
# As you can see, setting options is as simple as creating a
|
27
27
|
# block and calling the option as a method with the value as
|
28
28
|
# its parameter.
|
29
|
-
class Apt <
|
30
|
-
attr_accessor :packages #:nodoc:
|
31
|
-
|
29
|
+
class Apt < PackageInstaller
|
32
30
|
def initialize(parent, *packages, &block) #:nodoc:
|
33
|
-
packages
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
super parent, *packages, &block
|
32
|
+
@options.reverse_merge!(:dependencies_only => false)
|
33
|
+
end
|
34
|
+
|
35
|
+
auto_api
|
36
|
+
|
37
|
+
verify_api do
|
38
|
+
def has_apt(package)
|
39
|
+
@commands << "dpkg --status #{package} | grep \"ok installed\""
|
40
|
+
end
|
41
41
|
end
|
42
42
|
|
43
43
|
protected
|
44
44
|
|
45
45
|
def install_commands #:nodoc:
|
46
46
|
command = @options[:dependencies_only] ? 'build-dep' : 'install'
|
47
|
-
"env DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive
|
47
|
+
noninteractive = "env DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive"
|
48
|
+
"#{noninteractive} #{sudo_cmd}apt-get --force-yes -qyu #{command} #{@packages.join(' ')}"
|
48
49
|
end
|
49
50
|
|
50
51
|
end
|
@@ -1,16 +1,27 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
#
|
3
|
+
# The Binary installer will download a binary archive and then extract
|
4
|
+
# it in the directory specified by the prefix option.
|
4
5
|
#
|
5
|
-
#
|
6
|
-
# prefix "/home/user/local"
|
7
|
-
# archives "/home/user/sources"
|
8
|
-
# end
|
6
|
+
# == Example Usage
|
9
7
|
#
|
8
|
+
# binary "http://some.url.com/archive.tar.gz" do
|
9
|
+
# prefix "/home/user/local"
|
10
|
+
# archives "/home/user/sources"
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# This example will download archive.tar.gz to /home/user/sources and then
|
14
|
+
# extract it into /home/user/local.
|
10
15
|
class Binary < Installer
|
16
|
+
|
17
|
+
api do
|
18
|
+
def binary(source, options = {}, &block)
|
19
|
+
install Sprinkle::Installers::Binary.new(self, source, options, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
11
23
|
def initialize(parent, binary_archive, options = {}, &block) #:nodoc:
|
12
24
|
@binary_archive = binary_archive
|
13
|
-
@options = options
|
14
25
|
super parent, options, &block
|
15
26
|
end
|
16
27
|
|
@@ -24,10 +35,14 @@ module Sprinkle
|
|
24
35
|
|
25
36
|
def install_commands #:nodoc:
|
26
37
|
commands = [ "bash -c 'wget -cq --directory-prefix=#{@options[:archives].first} #{@binary_archive}'" ]
|
27
|
-
commands << "bash -c
|
38
|
+
commands << "bash -c \"cd #{@options[:prefix].first} && #{extract_command} '#{@options[:archives].first}/#{archive_name}'\""
|
39
|
+
end
|
40
|
+
|
41
|
+
def archive_name #:nodoc:
|
42
|
+
@archive_name ||= @binary_archive.split("/").last.gsub('%20', ' ')
|
28
43
|
end
|
29
44
|
|
30
|
-
def extract_command
|
45
|
+
def extract_command #:nodoc:
|
31
46
|
case archive_name
|
32
47
|
when /(tar.gz)|(tgz)$/
|
33
48
|
'tar xzf'
|
@@ -9,24 +9,31 @@ module Sprinkle
|
|
9
9
|
#
|
10
10
|
# package :magic_beans do
|
11
11
|
# description "Beans beans they're good for your heart..."
|
12
|
-
# brew '
|
12
|
+
# brew 'ntp'
|
13
|
+
#
|
14
|
+
# verify { has_brew 'ntp' }
|
15
|
+
#
|
13
16
|
# end
|
14
17
|
#
|
15
|
-
class Brew <
|
16
|
-
attr_accessor :formulas #:nodoc:
|
18
|
+
class Brew < PackageInstaller
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
api do
|
21
|
+
def brew(*names, &block)
|
22
|
+
@recommends << :homebrew
|
23
|
+
install_package(*names, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
verify_api do
|
28
|
+
def has_brew(package)
|
29
|
+
@commands << "brew list | grep #{package}"
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
protected
|
27
34
|
|
28
35
|
def install_commands #:nodoc:
|
29
|
-
"brew install #{@
|
36
|
+
"brew install #{@packages.join(' ')}"
|
30
37
|
end
|
31
38
|
|
32
39
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# The Port installer installs OpenBSD and FreeBSD ports.
|
3
|
+
# The BSD Port installer installs OpenBSD and FreeBSD ports.
|
6
4
|
# Before usage, the ports sytem must be installed and
|
7
|
-
#
|
5
|
+
# ready on the target operating system.
|
8
6
|
#
|
9
7
|
# == Example Usage
|
10
8
|
#
|
@@ -16,9 +14,15 @@ module Sprinkle
|
|
16
14
|
#
|
17
15
|
class BsdPort < Installer
|
18
16
|
attr_accessor :port #:nodoc:
|
17
|
+
|
18
|
+
api do
|
19
|
+
def bsd_port(port, options ={}, &block)
|
20
|
+
install Sprinkle::Installers::BsdPort.new(self, port, options, &block)
|
21
|
+
end
|
22
|
+
end
|
19
23
|
|
20
|
-
def initialize(parent, port, &block) #:nodoc:
|
21
|
-
super parent, &block
|
24
|
+
def initialize(parent, port, options={}, &block) #:nodoc:
|
25
|
+
super parent, options, &block
|
22
26
|
@port = port
|
23
27
|
end
|
24
28
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
# = Deb Package Installer
|
4
|
-
#
|
5
3
|
# The Deb installer installs deb packages sourced from a remote URL
|
6
4
|
#
|
7
5
|
# == Example Usage
|
@@ -12,14 +10,9 @@ module Sprinkle
|
|
12
10
|
# deb 'http://debs.example.com/magic_beans.deb'
|
13
11
|
# end
|
14
12
|
#
|
15
|
-
class Deb <
|
16
|
-
|
17
|
-
|
18
|
-
def initialize(parent, packages, &block) #:nodoc:
|
19
|
-
super parent, &block
|
20
|
-
packages = [packages] unless packages.is_a? Array
|
21
|
-
@packages = packages
|
22
|
-
end
|
13
|
+
class Deb < PackageInstaller
|
14
|
+
|
15
|
+
auto_api
|
23
16
|
|
24
17
|
protected
|
25
18
|
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# The Pkg package installer installs FreeBSD packages.
|
3
|
+
# The FreeBSDPkg installer installs FreeBSD packages.
|
6
4
|
#
|
7
5
|
# == Example Usage
|
8
6
|
#
|
@@ -17,14 +15,10 @@ module Sprinkle
|
|
17
15
|
# package :magic_beans do
|
18
16
|
# freebsd_pkg %w(magic_beans magic_sauce)
|
19
17
|
# end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
super parent, &block
|
25
|
-
packages = [packages] unless packages.is_a? Array
|
26
|
-
@packages = packages
|
27
|
-
end
|
18
|
+
#
|
19
|
+
class FreebsdPkg < PackageInstaller
|
20
|
+
|
21
|
+
auto_api
|
28
22
|
|
29
23
|
protected
|
30
24
|
|
@@ -19,9 +19,15 @@ module Sprinkle
|
|
19
19
|
#
|
20
20
|
class FreebsdPortinstall < Installer
|
21
21
|
attr_accessor :port #:nodoc:
|
22
|
+
|
23
|
+
api do
|
24
|
+
def freebsd_portinstall(port, options={}, &block)
|
25
|
+
install Sprinkle::Installers::FreebsdPortinstall.new(self, port, options, &block)
|
26
|
+
end
|
27
|
+
end
|
22
28
|
|
23
|
-
def initialize(parent, port, &block) #:nodoc:
|
24
|
-
super parent, &block
|
29
|
+
def initialize(parent, port, options={}, &block) #:nodoc:
|
30
|
+
super parent, options, &block
|
25
31
|
@port = port
|
26
32
|
end
|
27
33
|
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# The gem package installer installs ruby gems.
|
3
|
+
# The gem package installer installs Ruby gems.
|
6
4
|
#
|
7
5
|
# The installer has a single optional configuration: source.
|
8
6
|
# By changing source you can specify a given ruby gems
|
@@ -29,6 +27,14 @@ module Sprinkle
|
|
29
27
|
# block and calling the option as a method with the value as
|
30
28
|
# its parameter.
|
31
29
|
class Gem < Installer
|
30
|
+
|
31
|
+
api do
|
32
|
+
def gem(name, options = {}, &block)
|
33
|
+
@recommends << :rubygems
|
34
|
+
install Sprinkle::Installers::Gem.new(self, name, options, &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
32
38
|
attr_accessor :gem #:nodoc:
|
33
39
|
|
34
40
|
def initialize(parent, gem, options = {}, &block) #:nodoc:
|
@@ -1,13 +1,37 @@
|
|
1
1
|
module Sprinkle
|
2
2
|
module Installers
|
3
3
|
class Group < Installer
|
4
|
-
|
5
|
-
|
4
|
+
# The user installer helps add groups. You may pass flags as an option.
|
5
|
+
#
|
6
|
+
# == Example Usage
|
7
|
+
#
|
8
|
+
# package :users do
|
9
|
+
# add_group 'webguys', :flags => "--shell /usr/bin/zsh"
|
10
|
+
#
|
11
|
+
# verify do
|
12
|
+
# has_group 'webguys'
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
|
16
|
+
api do
|
17
|
+
def add_group(group, options={}, &block)
|
18
|
+
install Sprinkle::Installers::Group.new(self, group, options, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
verify_api do
|
23
|
+
def has_group(group)
|
24
|
+
@commands << "id -g #{group}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(package, groupname, options, &block) #:nodoc:
|
29
|
+
super package, options, &block
|
6
30
|
@groupname = groupname
|
7
|
-
@options = options
|
8
31
|
end
|
32
|
+
|
9
33
|
protected
|
10
|
-
def install_commands
|
34
|
+
def install_commands #:nodoc:
|
11
35
|
"addgroup #{@options[:flags]} #{@groupname}"
|
12
36
|
end
|
13
37
|
end
|