sprinkle 0.5.0 → 0.5.1
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/.travis.yml +6 -0
- data/CREDITS +6 -3
- data/README.md +1 -0
- data/bin/sprinkle +1 -2
- data/lib/sprinkle.rb +4 -1
- data/lib/sprinkle/actors/actor.rb +44 -0
- data/lib/sprinkle/actors/capistrano.rb +8 -1
- data/lib/sprinkle/actors/dummy.rb +8 -82
- data/lib/sprinkle/actors/local.rb +5 -1
- data/lib/sprinkle/actors/ssh.rb +8 -2
- data/lib/sprinkle/actors/vlad.rb +6 -1
- data/lib/sprinkle/installers/installer.rb +6 -2
- data/lib/sprinkle/installers/push_text.rb +10 -2
- data/lib/sprinkle/installers/replace_text.rb +2 -2
- data/lib/sprinkle/policy.rb +14 -1
- data/lib/sprinkle/version.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/sprinkle/installers/installer_spec.rb +1 -1
- data/spec/sprinkle/installers/push_text_spec.rb +16 -1
- data/spec/sprinkle/installers/replace_text_spec.rb +12 -2
- data/spec/sprinkle/package_spec.rb +1 -1
- data/spec/sprinkle/policy_spec.rb +15 -0
- data/spec/sprinkle/sprinkle_spec.rb +5 -2
- data/spec/sprinkle/verify_spec.rb +1 -1
- data/sprinkle.gemspec +3 -1
- metadata +3 -2
- data/lib/sprinkle/actors/actors.rb +0 -32
data/.travis.yml
ADDED
data/CREDITS
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
= CREDITS
|
2
2
|
|
3
|
-
Many thanks to the following people who have submitted ideas, patches, helped with
|
4
|
-
and/or generally provided support to Sprinkle, I really appreciate your help:
|
3
|
+
Many thanks to the following people who have submitted ideas, patches, helped with
|
4
|
+
testing and/or generally provided support to Sprinkle, I really appreciate your help:
|
5
5
|
|
6
|
+
Koen Punt (http://github.com/koenpunt)
|
7
|
+
Manuel Meurer (http://github.com/manuelmeurer)
|
6
8
|
Kristin Baumann (http://crafterm.net/kristin/blog/)
|
7
9
|
Ben Schwarz (http://germanforblack.com/)
|
8
10
|
Jim Freeze (http://www.artima.com/rubycs/articles/ruby_as_dslP.html)
|
@@ -31,4 +33,5 @@ Geoff Garside (http://geoffgarside.co.uk/)
|
|
31
33
|
Oliver Kiessler (http://inceedo.com)
|
32
34
|
Nick Plante (http://blog.zerosum.org)
|
33
35
|
|
34
|
-
The transfer installer contains a piece of exception reporting code copied from
|
36
|
+
The transfer installer contains a piece of exception reporting code copied from
|
37
|
+
the Chef library (http://wiki.opscode.com/display/chef/Home)
|
data/README.md
CHANGED
@@ -6,6 +6,7 @@ its been created.
|
|
6
6
|
|
7
7
|
[](https://travis-ci.org/sprinkle-tool/sprinkle)
|
8
8
|
|
9
|
+
* `#sprinkle` channel on the Freenode IRC Network
|
9
10
|
* <http://redartisan.com/2008/5/27/sprinkle-intro>
|
10
11
|
* <http://github.com/sprinkle-tool/sprinkle>
|
11
12
|
* <http://github.com/benschwarz/passenger-stack>
|
data/bin/sprinkle
CHANGED
@@ -90,8 +90,7 @@ def verbosity(options)
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def log_level(options)
|
93
|
-
|
94
|
-
Object.logger.level = options[:verbose] ? severity::DEBUG : severity::INFO
|
93
|
+
Object.logger.level = OPTIONS[:verbose] ? Logger::Severity::DEBUG : Logger::Severity::INFO
|
95
94
|
end
|
96
95
|
|
97
96
|
require File.dirname(__FILE__) + '/../lib/sprinkle'
|
data/lib/sprinkle.rb
CHANGED
@@ -37,6 +37,9 @@ class Object
|
|
37
37
|
include Sprinkle::Package, Sprinkle::Policy, Sprinkle::Deployment
|
38
38
|
|
39
39
|
def logger # :nodoc:
|
40
|
-
|
40
|
+
# ActiveSupport::BufferedLogger was deprecated and replaced by ActiveSupport::Logger in Rails 4.
|
41
|
+
# Use ActiveSupport::Logger if available.
|
42
|
+
active_support_logger = defined?(ActiveSupport::Logger) ? ActiveSupport::Logger : ActiveSupport::BufferedLogger
|
43
|
+
@@__log__ ||= active_support_logger.new($stdout, active_support_logger::Severity::INFO)
|
41
44
|
end
|
42
45
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Sprinkle
|
2
|
+
module Actors
|
3
|
+
# An actor is a method of command delivery to a remote machine. Actors are the
|
4
|
+
# layer setting between Sprinkle and the systems you and wanting to apply
|
5
|
+
# policies to. All actors should inherit from Sprinkle::Actors::Actor.
|
6
|
+
#
|
7
|
+
# Sprinkle ships with actors for Capistrano, Vlad, localhost and pure SSH.
|
8
|
+
# 99% of the time these should be sufficient but you can always write your
|
9
|
+
# own actor otherwise.
|
10
|
+
#
|
11
|
+
# == Writing an actor
|
12
|
+
#
|
13
|
+
# Actors must provide only 3 methods:
|
14
|
+
#
|
15
|
+
# * install (installer, roles, options)
|
16
|
+
# * verify (verifier, roles, options)
|
17
|
+
# * servers_for_role? (roles)
|
18
|
+
#
|
19
|
+
# Hopefully these methods are kind of fairly obvious. They should return true
|
20
|
+
# to indicate success and false to indicate failure.
|
21
|
+
# The actual commands you need to execute can be retrived from
|
22
|
+
# +installer.install_sequence+ and +verifier.commands+.
|
23
|
+
class Actor
|
24
|
+
|
25
|
+
# an actor must define this method so that each policy can ask the actor
|
26
|
+
# if there are any servers with that policy's roles so the policy knows
|
27
|
+
# whether it should execute or not
|
28
|
+
#
|
29
|
+
# input: a single role or array of roles
|
30
|
+
def servers_for_role?(r)
|
31
|
+
raise "please define servers_for_role?"
|
32
|
+
end
|
33
|
+
|
34
|
+
def install(*args)
|
35
|
+
raise "you must define install"
|
36
|
+
end
|
37
|
+
|
38
|
+
def verify(*args)
|
39
|
+
raise "you must define verify"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -17,7 +17,7 @@ module Sprinkle
|
|
17
17
|
# Recipes is given a list of files which capistrano will include and load.
|
18
18
|
# These recipes are mainly to set variables such as :user, :password, and to
|
19
19
|
# set the app domain which will be sprinkled.
|
20
|
-
class Capistrano
|
20
|
+
class Capistrano < Actor
|
21
21
|
attr_accessor :config, :loaded_recipes #:nodoc:
|
22
22
|
|
23
23
|
def initialize(&block) #:nodoc:
|
@@ -37,6 +37,13 @@ module Sprinkle
|
|
37
37
|
@config.load 'deploy' # normally in the config directory for rails
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
# Determines if there are any servers for the given roles
|
42
|
+
def servers_for_role?(roles)
|
43
|
+
roles=Array(roles)
|
44
|
+
roles.any? { |r| @config.roles.keys.include? (r) }
|
45
|
+
end
|
46
|
+
|
40
47
|
|
41
48
|
# Defines a recipe file which will be included by capistrano. Use these
|
42
49
|
# recipe files to set capistrano specific configurations. Default recipe
|
@@ -3,24 +3,7 @@ require 'pp'
|
|
3
3
|
|
4
4
|
module Sprinkle
|
5
5
|
module Actors
|
6
|
-
|
7
|
-
#
|
8
|
-
# Capistrano is one of the delivery method options available out of the
|
9
|
-
# box with Sprinkle. If you have the capistrano gem install, you may use
|
10
|
-
# this delivery. The only configuration option available, and which is
|
11
|
-
# mandatory to include is +recipes+. An example:
|
12
|
-
#
|
13
|
-
# deployment do
|
14
|
-
# delivery :capistrano do
|
15
|
-
# recipes 'deploy'
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# Recipes is given a list of files which capistrano will include and load.
|
20
|
-
# These recipes are mainly to set variables such as :user, :password, and to
|
21
|
-
# set the app domain which will be sprinkled.
|
22
|
-
class Dummy #:nodoc:
|
23
|
-
attr_accessor :config, :loaded_recipes #:nodoc:
|
6
|
+
class Dummy < Actor #:nodoc:
|
24
7
|
|
25
8
|
def initialize(&block) #:nodoc:
|
26
9
|
# @config.set(:_sprinkle_actor, self)
|
@@ -28,26 +11,17 @@ module Sprinkle
|
|
28
11
|
self.instance_eval &block
|
29
12
|
end
|
30
13
|
|
31
|
-
# Defines a recipe file which will be included by capistrano. Use these
|
32
|
-
# recipe files to set capistrano specific configurations. Default recipe
|
33
|
-
# included is "deploy." But if any other recipe is specified, it will
|
34
|
-
# include that instead. Multiple recipes may be specified through multiple
|
35
|
-
# recipes calls, an example:
|
36
|
-
#
|
37
|
-
# deployment do
|
38
|
-
# delivery :capistrano do
|
39
|
-
# recipes 'deploy'
|
40
|
-
# recipes 'magic_beans'
|
41
|
-
# end
|
42
|
-
# end
|
43
|
-
# def recipes(script)
|
44
|
-
# end
|
45
|
-
|
46
14
|
def role(role, server, opts={})
|
47
15
|
@roles[role]||=[]
|
48
16
|
@roles[role] << [ server, opts ]
|
49
17
|
end
|
50
18
|
|
19
|
+
# Determines if there are any servers for the given roles
|
20
|
+
def servers_for_role?(roles)
|
21
|
+
roles=Array(roles)
|
22
|
+
roles.any? { |r| @roles.keys.include? (r) }
|
23
|
+
end
|
24
|
+
|
51
25
|
def install(installer, roles, opts={})
|
52
26
|
if per_host=opts.delete(:per_host)
|
53
27
|
servers_per_role(roles).each do |server|
|
@@ -74,54 +48,6 @@ module Sprinkle
|
|
74
48
|
# return false if suppress_and_return_failures
|
75
49
|
true
|
76
50
|
end
|
77
|
-
|
78
|
-
def transfer(name, source, destination, roles, recursive = true, suppress_and_return_failures = false)
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
# REVISIT: can we set the description somehow?
|
85
|
-
def define_task(name, roles, &block)
|
86
|
-
@config.task task_sym(name), :roles => roles, &block
|
87
|
-
end
|
88
|
-
|
89
|
-
def run(task)
|
90
|
-
@config.send task_sym(task)
|
91
|
-
end
|
92
|
-
|
93
|
-
def task_sym(name)
|
94
|
-
"install_#{name.to_task_name}".to_sym
|
95
|
-
end
|
96
51
|
end
|
97
52
|
end
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
=begin
|
102
|
-
|
103
|
-
# channel: the SSH channel object used for this response
|
104
|
-
# stream: either :err or :out, for stderr or stdout responses
|
105
|
-
# output: the text that the server is sending, might be in chunks
|
106
|
-
run "apt-get update" do |channel, stream, output|
|
107
|
-
if output =~ /Are you sure?/
|
108
|
-
answer = Capistrano::CLI.ui.ask("Are you sure: ")
|
109
|
-
channel.send_data(answer + "\n")
|
110
|
-
else
|
111
|
-
# allow the default callback to be processed
|
112
|
-
Capistrano::Configuration.default_io_proc.call[channel, stream, output]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
You can tell subversion to use a different username+password by
|
119
|
-
setting a couple variables:
|
120
|
-
set :svn_username, "my svn username"
|
121
|
-
set :svn_password, "my svn password"
|
122
|
-
If you don't want to set the password explicitly in your recipe like
|
123
|
-
that, you can make capistrano prompt you for it like this:
|
124
|
-
set(:svn_password) { Capistrano::CLI.password_prompt("Subversion
|
125
|
-
password: ") }
|
126
|
-
- Jamis
|
127
|
-
=end
|
53
|
+
end
|
@@ -16,10 +16,14 @@ module Sprinkle
|
|
16
16
|
#
|
17
17
|
# Note: The local actor completely ignores roles and behaves as if your
|
18
18
|
# local system was a member of all roles defined.
|
19
|
-
class Local
|
19
|
+
class Local < Actor
|
20
20
|
|
21
21
|
class LocalCommandError < StandardError; end
|
22
22
|
|
23
|
+
def servers_for_role?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
23
27
|
def install(installer, roles, opts = {}) #:nodoc:
|
24
28
|
# all local installer cares about is the commands
|
25
29
|
@installer = installer
|
data/lib/sprinkle/actors/ssh.rb
CHANGED
@@ -25,7 +25,7 @@ module Sprinkle
|
|
25
25
|
# gateway "work.sshgateway.com"
|
26
26
|
# end
|
27
27
|
# end
|
28
|
-
class SSH
|
28
|
+
class SSH < Actor
|
29
29
|
attr_accessor :options #:nodoc:
|
30
30
|
|
31
31
|
class SSHCommandFailure < StandardError #:nodoc:
|
@@ -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 = {}.with_indifferent_access
|
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?
|
@@ -55,6 +55,12 @@ module Sprinkle
|
|
55
55
|
def roles(roles)
|
56
56
|
@roles = roles
|
57
57
|
end
|
58
|
+
|
59
|
+
# Determines if there are any servers for the given roles
|
60
|
+
def servers_for_role?(roles)
|
61
|
+
roles=Array(roles)
|
62
|
+
roles.any? { |r| @roles.keys.include? (r) }
|
63
|
+
end
|
58
64
|
|
59
65
|
# Define a role and add servers to it
|
60
66
|
#
|
data/lib/sprinkle/actors/vlad.rb
CHANGED
@@ -16,12 +16,17 @@ module Sprinkle
|
|
16
16
|
# script is given a list of files which vlad will include and load.
|
17
17
|
# These recipes are mainly to set variables such as :user, :password, and to
|
18
18
|
# set the app domain which will be sprinkled.
|
19
|
-
class Vlad
|
19
|
+
class Vlad < Actor
|
20
20
|
attr_accessor :loaded_recipes #:nodoc:
|
21
21
|
|
22
22
|
def initialize(&block) #:nodoc:
|
23
23
|
self.instance_eval &block if block
|
24
24
|
end
|
25
|
+
|
26
|
+
def servers_for_role?
|
27
|
+
raise "The vlad actor needs a maintainer. "+
|
28
|
+
"Please file an issue on github.com/sprinkle-tool/sprinkle if you can help."
|
29
|
+
end
|
25
30
|
|
26
31
|
# Defines a script file which will be included by vlad. Use these
|
27
32
|
# script files to set vlad specific configurations. Multiple scripts
|
@@ -82,11 +82,15 @@ module Sprinkle
|
|
82
82
|
def sudo_cmd
|
83
83
|
"sudo " if sudo?
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
def sudo?
|
87
87
|
options[:sudo] or package.sudo?
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
|
+
def escape_shell_arg(str)
|
91
|
+
str.gsub("'", "'\\\\''").gsub("/", "\\\\/").gsub("\n", '\n').gsub('&', '\\\&')
|
92
|
+
end
|
93
|
+
|
90
94
|
def pre(stage, *commands)
|
91
95
|
@pre[stage] ||= []
|
92
96
|
@pre[stage] += commands
|
@@ -47,12 +47,20 @@ module Sprinkle
|
|
47
47
|
@path = path
|
48
48
|
end
|
49
49
|
|
50
|
+
def announce
|
51
|
+
log "--> Append '#{@text}' to file #{@path}"
|
52
|
+
end
|
53
|
+
|
50
54
|
protected
|
51
55
|
|
52
56
|
def install_commands #:nodoc:
|
53
|
-
|
57
|
+
escaped_text = escape_shell_arg(@text)
|
58
|
+
escaped_regex = Regexp.escape(@text)
|
59
|
+
command = ""
|
60
|
+
command << "#{sudo_cmd}grep -qPzo '^#{escaped_regex}$' #{@path} || " if option?(:idempotent)
|
61
|
+
command << "/bin/echo -e '#{escaped_text}' |#{sudo_cmd}tee -a #{@path}"
|
62
|
+
command
|
54
63
|
end
|
55
|
-
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -13,7 +13,7 @@ module Sprinkle
|
|
13
13
|
# end
|
14
14
|
#
|
15
15
|
# If you user has access to 'sudo' and theres a file that requires
|
16
|
-
#
|
16
|
+
# privileges, you can pass :sudo => true
|
17
17
|
#
|
18
18
|
# package :magic_beans do
|
19
19
|
# replace_text 'Port 22', 'Port 2500', '/etc/ssh/sshd_config', :sudo => true
|
@@ -46,7 +46,7 @@ module Sprinkle
|
|
46
46
|
protected
|
47
47
|
|
48
48
|
def install_commands #:nodoc:
|
49
|
-
"#{
|
49
|
+
"#{sudo_cmd}sed -i 's/#{escape_shell_arg(@regex)}/#{escape_shell_arg(@text)}/g' #{@path}"
|
50
50
|
end
|
51
51
|
|
52
52
|
end
|
data/lib/sprinkle/policy.rb
CHANGED
@@ -49,7 +49,18 @@ module Sprinkle
|
|
49
49
|
POLICIES << p
|
50
50
|
p
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
|
+
class NoMatchingServersError < StandardError #:nodoc:
|
54
|
+
def initialize(name, roles)
|
55
|
+
@name = name
|
56
|
+
@roles = roles
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
"Policy #{@name} is to be installed on #{@roles.inspect} but no server has such a role."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
53
64
|
class Policy #:nodoc:
|
54
65
|
attr_reader :name, :roles
|
55
66
|
|
@@ -73,6 +84,8 @@ module Sprinkle
|
|
73
84
|
def to_s; name; end
|
74
85
|
|
75
86
|
def process(deployment)
|
87
|
+
raise NoMatchingServersError.new(@name, @roles) unless deployment.style.servers_for_role?(@roles)
|
88
|
+
|
76
89
|
all = []
|
77
90
|
|
78
91
|
logger.info "[#{name}]"
|
data/lib/sprinkle/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,10 @@ require 'sprinkle'
|
|
3
3
|
|
4
4
|
class Object
|
5
5
|
def logger
|
6
|
+
# ActiveSupport::BufferedLogger was deprecated and replaced by ActiveSupport::Logger in Rails 4.
|
7
|
+
# Use ActiveSupport::Logger if available.
|
8
|
+
active_support_logger = defined?(ActiveSupport::Logger) ? ActiveSupport::Logger : ActiveSupport::BufferedLogger
|
6
9
|
@@__log_file__ ||= StringIO.new
|
7
|
-
@@__log__ =
|
10
|
+
@@__log__ = active_support_logger.new @@__log_file__, active_support_logger::Severity::INFO
|
8
11
|
end
|
9
12
|
end
|
@@ -69,7 +69,7 @@ describe Sprinkle::Installers::Installer do
|
|
69
69
|
|
70
70
|
before do
|
71
71
|
Sprinkle::OPTIONS[:testing] = true
|
72
|
-
@logger = mock(
|
72
|
+
@logger = mock(:debug => true, :debug? => true)
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'should not invoke the delivery mechanism with the install sequence' do
|
@@ -39,7 +39,22 @@ describe Sprinkle::Installers::PushText do
|
|
39
39
|
@install_commands = @installer.send :install_commands
|
40
40
|
end
|
41
41
|
it "should grep for existing of the string" do
|
42
|
-
@install_commands.should == %q
|
42
|
+
@install_commands.should == %q<grep -qPzo '^another\-hair\-brained\-idea$' /dev/mind/late-night || /bin/echo -e 'another-hair-brained-idea' |tee -a /dev/mind/late-night>
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'with multiline idempotent' do
|
47
|
+
before do
|
48
|
+
mline = <<-MULTI
|
49
|
+
^search( [adnor]{2,3} rescue)?$
|
50
|
+
^fries( [adnor]{2,3} barbecue)?
|
51
|
+
^songs( [adnor]{2,3} autocue)?
|
52
|
+
MULTI
|
53
|
+
@installer = create_text mline.strip, '/dev/mind/late-night', :idempotent => true
|
54
|
+
@install_commands = @installer.send :install_commands
|
55
|
+
end
|
56
|
+
it "should grep for existence of the string" do
|
57
|
+
@install_commands.should == %q<grep -qPzo '^\^search\(\ \[adnor\]\{2,3\}\ rescue\)\?\$\n\^fries\(\ \[adnor\]\{2,3\}\ barbecue\)\?\n\^songs\(\ \[adnor\]\{2,3\}\ autocue\)\?$' /dev/mind/late-night || /bin/echo -e '^search( [adnor]{2,3} rescue)?$\n^fries( [adnor]{2,3} barbecue)?\n^songs( [adnor]{2,3} autocue)?' |tee -a /dev/mind/late-night>
|
43
58
|
end
|
44
59
|
end
|
45
60
|
|
@@ -3,8 +3,7 @@ require File.expand_path("../../spec_helper", File.dirname(__FILE__))
|
|
3
3
|
describe Sprinkle::Installers::ReplaceText do
|
4
4
|
|
5
5
|
before do
|
6
|
-
@package = mock(Sprinkle::Package, :name => 'package')
|
7
|
-
@options = {:sudo => true}
|
6
|
+
@package = mock(Sprinkle::Package, :name => 'package', :sudo? => false)
|
8
7
|
end
|
9
8
|
|
10
9
|
def create_replacement_text(regex, text, path, options={}, &block)
|
@@ -20,6 +19,13 @@ describe Sprinkle::Installers::ReplaceText do
|
|
20
19
|
@installer.path.should == '/etc/example/foo.conf'
|
21
20
|
end
|
22
21
|
|
22
|
+
it 'should not escape original search string and replacement' do
|
23
|
+
@installer = create_replacement_text "some option with 'quotes' & ampersand", "other 'quotes' & ampersand", '/etc/example/foo.conf'
|
24
|
+
@installer.regex.should == %q[some option with 'quotes' & ampersand]
|
25
|
+
@installer.text.should == %q[other 'quotes' & ampersand]
|
26
|
+
@installer.path.should == '/etc/example/foo.conf'
|
27
|
+
end
|
28
|
+
|
23
29
|
end
|
24
30
|
|
25
31
|
describe 'during installation' do
|
@@ -40,6 +46,10 @@ describe Sprinkle::Installers::ReplaceText do
|
|
40
46
|
@installer.send(:install_sequence).should == [ 'op1', "sed -i 's/bad option/super option/g' /etc/brand/new.conf", 'op2' ]
|
41
47
|
end
|
42
48
|
|
49
|
+
it 'should correctly escape search string and replacement' do
|
50
|
+
installer = create_replacement_text "some option with 'quotes' & ampersand", "other 'quotes' & ampersand", '/etc/example/foo.conf'
|
51
|
+
installer.send(:install_commands).should == "sed -i 's/some option with '\\''quotes'\\'' \\& ampersand/other '\\''quotes'\\'' \\& ampersand/g' /etc/example/foo.conf"
|
52
|
+
end
|
43
53
|
end
|
44
54
|
|
45
55
|
end
|
@@ -352,7 +352,7 @@ CODE
|
|
352
352
|
@pkg.installers = [ @installer ]
|
353
353
|
@installer.stub!(:defaults)
|
354
354
|
@installer.stub!(:process)
|
355
|
-
@logger = mock(
|
355
|
+
@logger = mock(:debug => true, :debug? => true)
|
356
356
|
@logger.stub!(:info)
|
357
357
|
end
|
358
358
|
|
@@ -6,6 +6,17 @@ describe Sprinkle::Policy do
|
|
6
6
|
before do
|
7
7
|
@name = 'a policy'
|
8
8
|
end
|
9
|
+
|
10
|
+
describe 'with a role with no matching servers' do
|
11
|
+
before do
|
12
|
+
@policy = policy @name, :roles => :app do; end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise an error" do
|
16
|
+
@deployment = mock(:style => Sprinkle::Actors::Dummy.new {})
|
17
|
+
lambda { @policy.process(@deployment) }.should raise_error(Sprinkle::Policy::NoMatchingServersError)
|
18
|
+
end
|
19
|
+
end
|
9
20
|
|
10
21
|
describe 'when created' do
|
11
22
|
|
@@ -46,6 +57,8 @@ describe Sprinkle::Policy do
|
|
46
57
|
|
47
58
|
before do
|
48
59
|
@deployment = mock(Sprinkle::Deployment)
|
60
|
+
actor = mock(:servers_for_role? => true)
|
61
|
+
@deployment.stub!(:style).and_return(actor)
|
49
62
|
Sprinkle::Package::PACKAGES.clear # reset full package list before each spec is run
|
50
63
|
|
51
64
|
@a = package :a do; requires :b; requires :c; end
|
@@ -125,6 +138,8 @@ describe Sprinkle::Policy, 'with missing packages' do
|
|
125
138
|
|
126
139
|
before do
|
127
140
|
@deployment = mock(Sprinkle::Deployment)
|
141
|
+
actor = mock(:servers_for_role? => true)
|
142
|
+
@deployment.stub!(:style).and_return(actor)
|
128
143
|
Sprinkle::Package::PACKAGES.clear # reset full package list before each spec is run
|
129
144
|
|
130
145
|
@policy = policy :test, :roles => :app do; requires :z; end
|
@@ -15,11 +15,14 @@ describe Sprinkle do
|
|
15
15
|
it 'should automatically create a logger object on Kernel' do
|
16
16
|
Object.should respond_to(:logger)
|
17
17
|
logger.should_not be_nil
|
18
|
-
|
18
|
+
# ActiveSupport::BufferedLogger was deprecated and replaced by ActiveSupport::Logger in Rails 4.
|
19
|
+
# Use ActiveSupport::Logger if available
|
20
|
+
active_support_logger = defined?(ActiveSupport::Logger) ? ActiveSupport::Logger : ActiveSupport::BufferedLogger
|
21
|
+
logger.class.should == active_support_logger
|
19
22
|
end
|
20
23
|
|
21
24
|
it 'should create a logger of level INFO' do
|
22
|
-
logger.level.should ==
|
25
|
+
logger.level.should == Logger::Severity::INFO
|
23
26
|
end
|
24
27
|
|
25
28
|
end
|
@@ -180,7 +180,7 @@ describe Sprinkle::Verify do
|
|
180
180
|
describe 'when testing' do
|
181
181
|
before do
|
182
182
|
Sprinkle::OPTIONS[:testing] = true
|
183
|
-
@logger = mock(
|
183
|
+
@logger = mock(:debug => true, :debug? => true)
|
184
184
|
end
|
185
185
|
|
186
186
|
it 'should not call process on the delivery' do
|
data/sprinkle.gemspec
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require "./lib/sprinkle/version"
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
4
|
s.name = "sprinkle"
|
3
|
-
s.version =
|
5
|
+
s.version = Sprinkle::Version
|
4
6
|
|
5
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
8
|
s.authors = ["Marcus Crafter", "Josh Goebel"]
|
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.5.
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -133,6 +133,7 @@ extra_rdoc_files:
|
|
133
133
|
- README.md
|
134
134
|
files:
|
135
135
|
- .gitignore
|
136
|
+
- .travis.yml
|
136
137
|
- CREDITS
|
137
138
|
- Gemfile
|
138
139
|
- Gemfile.lock
|
@@ -161,7 +162,7 @@ files:
|
|
161
162
|
- examples/rails/rails.rb
|
162
163
|
- examples/sprinkle/sprinkle.rb
|
163
164
|
- lib/sprinkle.rb
|
164
|
-
- lib/sprinkle/actors/
|
165
|
+
- lib/sprinkle/actors/actor.rb
|
165
166
|
- lib/sprinkle/actors/capistrano.rb
|
166
167
|
- lib/sprinkle/actors/dummy.rb
|
167
168
|
- lib/sprinkle/actors/local.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# The only point of this file is to give RDoc a definition for
|
3
|
-
# Sprinkle::Actors. This file in production is never actually included
|
4
|
-
# since ActiveSupport only on-demand loads classes which are needed
|
5
|
-
# and this module is never explicitly needed.
|
6
|
-
#++
|
7
|
-
|
8
|
-
module Sprinkle
|
9
|
-
# An actor is a method of command delivery to a remote machine. Actors are the
|
10
|
-
# layer setting between Sprinkle and the systems you and wanting to apply
|
11
|
-
# policies to.
|
12
|
-
#
|
13
|
-
# Sprinkle ships with actors for Capistrano, Vlad, localhost and pure SSH.
|
14
|
-
# 99% of the time these should be sufficient but you can always write your
|
15
|
-
# own actor otherwise.
|
16
|
-
#
|
17
|
-
# == Writing an actor
|
18
|
-
#
|
19
|
-
# Actors must provide only 3 methods:
|
20
|
-
#
|
21
|
-
# * install (installer, roles, options)
|
22
|
-
# * verify (verifier, roles, options)
|
23
|
-
# * transfer (source, destination, roles, options)
|
24
|
-
#
|
25
|
-
# Hopefully these methods are kind of fairly obvious. They should return true
|
26
|
-
# to indicate success and false to indicate failure.
|
27
|
-
# The actual commands you need to execute can be retrived from
|
28
|
-
# +installer.install_sequence+ and +verifier.commands+.
|
29
|
-
|
30
|
-
module Actors
|
31
|
-
end
|
32
|
-
end
|