sprinkle 0.7.5 → 0.7.6

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sprinkle (0.7.4)
4
+ sprinkle (0.7.6)
5
5
  activesupport (>= 2.0.2)
6
6
  capistrano (>= 2.5.5)
7
7
  erubis (>= 2.7.0)
@@ -56,8 +56,11 @@ end
56
56
  deployment do
57
57
 
58
58
  # mechanism for deployment
59
- delivery :capistrano do
60
- recipes 'deploy'
59
+ # delivery :capistrano do
60
+ # recipes 'deploy'
61
+ # end
62
+ delivery :dummy do
63
+ role :app, "test"
61
64
  end
62
65
 
63
66
  # source based package installer defaults
@@ -17,6 +17,8 @@ def require_all(*args) # :nodoc:
17
17
  Dir[File.dirname(__FILE__) + "/sprinkle/#{f}"].each { |e| require e } }
18
18
  end
19
19
 
20
+ $LOAD_PATH << File.dirname(__FILE__)
21
+
20
22
  require 'sprinkle/version'
21
23
 
22
24
  require_all "extensions/*.rb"
@@ -100,11 +100,10 @@ module Sprinkle
100
100
  define_task(name, roles) do
101
101
  via = fetch(:run_method, :run)
102
102
  commands.each do |command|
103
- if command == :TRANSFER
104
- opts.reverse_merge!(:recursive => true)
105
- upload inst.sourcepath, inst.destination, :via => :scp,
106
- :recursive => opts[:recursive]
107
- elsif command == :RECONNECT
103
+ if command.is_a? Commands::Transfer
104
+ upload command.source, command.destination, :via => :scp,
105
+ :recursive => command.recursive?
106
+ elsif command.is_a? Commands::Reconnect
108
107
  teardown_connections_to(sessions.keys)
109
108
  else
110
109
  # this reset the log
@@ -4,6 +4,8 @@ require 'pp'
4
4
  module Sprinkle
5
5
  module Actors
6
6
  class Dummy < Actor #:nodoc:
7
+
8
+ attr_accessor :per_host
7
9
 
8
10
  def initialize(&block) #:nodoc:
9
11
  # @config.set(:_sprinkle_actor, self)
@@ -23,6 +25,7 @@ module Sprinkle
23
25
  end
24
26
 
25
27
  def install(installer, roles, opts={})
28
+ @installer = installer
26
29
  if self.per_host=opts.delete(:per_host)
27
30
  servers_per_role(roles).each do |server|
28
31
  installer.reconfigure_for(server)
@@ -45,10 +48,16 @@ module Sprinkle
45
48
  def servers_per_role(role)
46
49
  @roles[role]
47
50
  end
51
+
52
+ def print_command(cmd)
53
+ puts cmd.inspect
54
+ end
48
55
 
49
56
  def process(name, commands, roles, opts = {}) #:nodoc:
50
57
  # puts "PROCESS: #{name} on #{roles}"
51
- pp commands
58
+ commands.each do |cmd|
59
+ print_command(cmd)
60
+ end
52
61
  # return false if suppress_and_return_failures
53
62
  true
54
63
  end
@@ -53,11 +53,11 @@ module Sprinkle
53
53
  def process(name, commands, roles, opts = {}) #:nodoc:
54
54
  @log_recorder = Sprinkle::Utility::LogRecorder.new
55
55
  commands.each do |command|
56
- if command == :RECONNECT
56
+ if command.is_a?(Commands::Reconnect)
57
57
  res = 0
58
- elsif command == :TRANSFER
59
- res = transfer(@installer.sourcepath, @installer.destination, roles,
60
- :recursive => @installer.options[:recursive])
58
+ elsif command.is_a?(Commands::Transfer)
59
+ res = transfer(command.source, command.destination, roles,
60
+ :recursive => command.recursive?)
61
61
  else
62
62
  res = run_command command
63
63
  end
@@ -162,11 +162,11 @@ module Sprinkle
162
162
  def execute_on_host(commands,host) #:nodoc:
163
163
  prepare_commands(commands).each do |cmd|
164
164
  case cmd
165
- when :RECONNECT
165
+ when cmd.is_a?(Commands::Reconnect) then
166
166
  reconnect host
167
- when :TRANSFER
168
- transfer_to_host(@installer.sourcepath, @installer.destination, host,
169
- :recursive => @installer.options[:recursive])
167
+ when cmd.is_a?(Commands::Transfer) then
168
+ transfer_to_host(cmd.source, cmd.destination, host,
169
+ :recursive => cmd.recursive?)
170
170
  else
171
171
  run_command cmd, host
172
172
  end
@@ -0,0 +1,23 @@
1
+ module Sprinkle
2
+ module Commands
3
+ class Command
4
+
5
+ def initialize(str, opts = {})
6
+ @sudo = opts[:sudo]
7
+ @str = str
8
+ # this is a dummy class for now, not intended to be used directly
9
+ raise
10
+ end
11
+
12
+ def sudo?
13
+ @sudo
14
+ end
15
+
16
+ def string
17
+ # TODO: sudo
18
+ @str
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module Sprinkle
2
+ module Commands
3
+ class Reconnect < Command
4
+
5
+ def initialize()
6
+ end
7
+
8
+ def inspect
9
+ ":RECONNECT"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module Sprinkle
2
+ module Commands
3
+ class Transfer < Command
4
+
5
+ attr_reader :source, :destination, :opts
6
+
7
+ def initialize(source, destination, opts={})
8
+ @source = source
9
+ @destination = destination
10
+ @opts = opts
11
+ end
12
+
13
+ def recursive?
14
+ !!@opts[:recursive]
15
+ end
16
+
17
+ def inspect
18
+ ":TRANSFER, src: #{source}, dest: #{destination}, opts: #{@opts.inspect}"
19
+ end
20
+
21
+ def eql?(a,b)
22
+ a.source == b.source &&
23
+ a.destionation == b.destination &&
24
+ a.opts == b.opts
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -32,8 +32,23 @@ module Sprinkle
32
32
  # @nginx_port = 8080
33
33
  # file '/etc/nginx.conf',
34
34
  # :contents => render("nginx.conf")
35
- # # ./templates/nginx.conf.erb or
36
- # # ./templates/nginx.conf should contain the erb template
35
+ # # where [cwd] is the current working dir you're running sprinkle from
36
+ # # [cwd]/templates/nginx.conf.erb or
37
+ # # [cwd]/templates/nginx.conf should contain the erb template
38
+ # end
39
+ #
40
+ # You can also tell the package where to look for templates, so that if you have
41
+ # a complex package hierarchy such as:
42
+ #
43
+ # .../packages/p/postfix.rb
44
+ # .../packages/p/postfix/templates/main.cf.erb
45
+ #
46
+ # package :postfix do
47
+ # template_search_path File.dirname(__FILE__)
48
+ # file '/etc/postfix/main.cf', :contents => render("main.cf")
49
+ # # searches for:
50
+ # # ../packages/p/main.cf[.erb]
51
+ # # ../packages/p/templates/main.cf[.erb]
37
52
  # end
38
53
  class FileInstaller < Installer
39
54
  attr_reader :sourcepath, :destination, :contents #:nodoc:
@@ -60,7 +75,7 @@ module Sprinkle
60
75
  end
61
76
 
62
77
  def install_commands #:nodoc:
63
- :TRANSFER
78
+ Commands::Transfer.new(sourcepath, destination)
64
79
  end
65
80
 
66
81
  # calls chown own to set the file ownership
@@ -87,12 +102,16 @@ module Sprinkle
87
102
  end
88
103
 
89
104
  def setup_source
90
- @file=Tempfile.new(@package.name.to_s)
91
- @file.print(@contents)
105
+ @file = Tempfile.new(@package.name.to_s)
106
+ @file.print @contents
92
107
  @file.close
93
108
  @sourcepath = @file.path
94
109
  end
95
110
 
111
+ def post_process
112
+ @file.unlink
113
+ end
114
+
96
115
  end
97
116
  end
98
117
  end
@@ -130,6 +130,10 @@ module Sprinkle
130
130
  return false
131
131
  end
132
132
 
133
+ # Called right after processing, can be used for local cleanup such
134
+ # as removing any temporary files created on the local system, etc
135
+ def post_process; end
136
+
133
137
  # Called right before an installer is exected, can be used for logging
134
138
  # and announcing what is about to happen
135
139
  def announce; end
@@ -144,6 +148,7 @@ module Sprinkle
144
148
  logger.debug " --> Running #{self.class.name} for roles: #{roles}"
145
149
  @delivery.install(self, roles, :per_host => per_host?)
146
150
  end
151
+ post_process
147
152
  end
148
153
 
149
154
  # More complicated installers that have different stages, and require pre/post commands
@@ -0,0 +1,82 @@
1
+ module Sprinkle
2
+ module Installers
3
+ # = Pecl extension installed
4
+ #
5
+ # Installs the specified pecl extension
6
+ #
7
+ # == Example Usage
8
+ #
9
+ # package :php_stuff do
10
+ # pecl 'mongo'
11
+ # verify { has_pecl 'mongo' }
12
+ # end
13
+ #
14
+ # You can optionally pass a version number to both `pecl` and `has_pecl`:
15
+ #
16
+ # package :php_stuff do
17
+ # pecl 'mongo', :version => "1.4.3"
18
+ # verify { has_pecl 'mongo', :version => "1.4.3" }
19
+ # end
20
+ #
21
+ # Some extensions need an ini file. You can have that generated, by passing the `:ini_file` option:
22
+ #
23
+ # package :php_stuff do
24
+ # pecl 'mongo', :ini_file => true
25
+ # end
26
+ #
27
+ # If you need more fine grained control of the location or contents of the ini file, use:
28
+ #
29
+ # package :php_stuff do
30
+ # pecl 'mongo', :ini_file => { :path => "/etc/php5/apache2/php.ini",
31
+ # :content => "extension=mongo.so",
32
+ # :sudo => true }
33
+ # end
34
+ #
35
+ class Pecl < Installer
36
+ attr_accessor :package_name, :package_version
37
+
38
+ api do
39
+ def pecl(package_name, options = {}, &block)
40
+ install Pecl.new(self, package_name, options, &block)
41
+ end
42
+ end
43
+
44
+ verify_api do
45
+ def has_pecl(package_name, options = {})
46
+ @commands = "TERM= pecl list | grep '^#{package_name}\\\\s*" + (options[:version] ? options[:version].to_s : "") + "'"
47
+ end
48
+ end
49
+
50
+ def initialize(parent, package_name, options = {}, &block) #:nodoc:
51
+ super parent, &block
52
+ @package_name = package_name
53
+ @package_version = options[:version]
54
+ @ini_file = options[:ini_file]
55
+ setup_ini if @ini_file
56
+ end
57
+
58
+ def setup_ini
59
+ @ini_file = to_ini_file_hash(@ini_file)
60
+ text = @ini_file[:content] || "extension=#{@package_name}.so"
61
+ path = @ini_file[:path] || "/etc/php5/conf.d/#{@package_name}.ini"
62
+ use_sudo = @ini_file[:sudo]===false ? false : true
63
+ post(:install) do
64
+ file(path, :content => text, :sudo => use_sudo)
65
+ end
66
+ end
67
+
68
+ def to_ini_file_hash(s)
69
+ return {:content => s} if s.is_a? String
70
+ return {} if s===true
71
+ s
72
+ end
73
+
74
+ protected
75
+ def install_commands #:nodoc:
76
+ cmd = "TERM= pecl install --alldeps #{@package_name}"
77
+ cmd << "-#{@package_version}" if @package_version
78
+ cmd
79
+ end
80
+ end
81
+ end
82
+ end
@@ -21,7 +21,7 @@ module Sprinkle
21
21
  # :RECONNECT is a symbol that the actors understand to mean to drop
22
22
  # and reestablish any SSH conncetions they have open
23
23
  def install_commands #:nodoc:
24
- :RECONNECT
24
+ Commands::Reconnect.new()
25
25
  end
26
26
 
27
27
  end
@@ -103,7 +103,7 @@ module Sprinkle
103
103
 
104
104
  multi_attributes :enable, :disable, :with, :without, :option,
105
105
  :custom_install
106
- attributes :configure_command, :build_command, :install_command, :custom_archive
106
+ attributes :configure_command, :build_command, :install_command, :custom_archive, :custom_dir
107
107
 
108
108
  def install_sequence #:nodoc:
109
109
  prepare + download + extract + configure + build + install
@@ -1,3 +1,5 @@
1
+ require 'tempfile'
2
+
1
3
  module Sprinkle
2
4
  module Installers
3
5
  # = File transfer installer
@@ -25,17 +27,34 @@ module Sprinkle
25
27
  # via this method. If you wish to disable recursive transfers, you can pass
26
28
  # :recursive => false, although it will not be obeyed when using the Vlad actor.
27
29
  #
30
+ # As an alternative to :recursive, you can use the :tarball option. When this is
31
+ # supplied, the source file(s) are first packed in a tar.gz archive, then
32
+ # transferred to a temp dir and finally unpacked at the destination. This is usually
33
+ # much faster when transferring many small files (Such as a typical rails application)
34
+ # You can optionally supply :exclude, which is an array of glob-patterns to not
35
+ # include in the tarball
36
+ #
37
+ # package :webapp do
38
+ # transfer 'app/', '/var/www/' do
39
+ # tarball :exclude => %w(.git log/*)
40
+ # end
41
+ # end
42
+ #
28
43
  # Should you need to run commands before or after the file transfer (making
29
44
  # directories or changing permissions), you can use the pre/post :install directives
30
45
  # and they will be run.
31
- #
46
+ #
32
47
  # == Rendering templates
33
48
  #
34
49
  # Rendering templates with transfer has been depreciated. Please see the file
35
50
  # installer if you want to use templates.
36
51
  class Transfer < Installer
37
52
  attr_accessor :source, :destination, :sourcepath #:nodoc:
38
-
53
+
54
+ # Include deprecated code
55
+ # Mainly, this makes it easier to see where to cut, when next major version comes along
56
+ DEPRECATED = true #:nodoc:
57
+
39
58
  api do
40
59
  def transfer(source, destination, options = {}, &block)
41
60
  options.reverse_merge!(:binding => binding())
@@ -43,92 +62,136 @@ module Sprinkle
43
62
  end
44
63
  end
45
64
 
46
- def initialize(parent, source, destination, options={}, &block) #:nodoc:
47
- @source = source
48
- @destination = destination
49
- @orig_destination = destination
50
- super parent, options, &block
51
- @binding = options[:binding]
52
- if sudo? # perform the transfer in two steps if we're using sudo
53
- final = @destination
54
- @destination = "/tmp/sprinkle_#{File.basename(@destination)}"
55
- # make sure we push the move ahead of any other post install tasks
56
- # a user may have requested
57
- post(:install).unshift ["#{sudo_cmd}mv #{@destination} #{final}"]
58
- end
65
+ def initialize(parent, source, destination, options = {}, &block) #:nodoc:
66
+ options.reverse_merge! :recursive => true
67
+
68
+ @source = source # Original source
69
+ @sourcepath = source # What the actor will transfer (may be the same as @source)
70
+ @final_destination = destination # Final destination
71
+ @destination = destination # Where the actor will place the file (May be same as @final_destination)
72
+
59
73
  owner(options[:owner]) if options[:owner]
60
74
  mode(options[:mode]) if options[:mode]
75
+ tarball(options[:tarball]) if options[:tarball]
76
+
77
+ super parent, options, &block
78
+
79
+ if DEPRECATED
80
+ @binding = options[:binding]
81
+ options[:render] = true if source_is_template?
82
+ options[:recursive] = false if options[:render]
83
+ setup_rendering if options[:render]
84
+ end
85
+ setup_tarball if tarball?
86
+ setup_sudo if sudo?
87
+ end
61
88
 
62
- options[:render]=true if source_is_template?
63
- options[:recursive]=false if options[:render]
89
+ def tarball(options = {})
90
+ @tarball = true
91
+ @exclude = options===true ? [] : options[:exclude]
64
92
  end
65
-
93
+
66
94
  def owner(owner)
67
95
  @owner = owner
68
- post :install, "#{sudo_cmd}chown #{owner} #{@orig_destination}"
96
+ post(:install, "#{sudo_cmd}chown -R #{@owner} #{@final_destination}")
69
97
  end
70
-
98
+
71
99
  def mode(mode)
72
100
  @mode = mode
73
- post :install, "#{sudo_cmd}chmod #{mode} #{@orig_destination}"
101
+ post(:install, "#{sudo_cmd}chmod -R #{@mode} #{@final_destination}")
74
102
  end
75
103
 
76
- def install_commands
77
- :TRANSFER
104
+ def tarball?
105
+ @tarball
78
106
  end
79
107
 
80
- def render_template(template, context, prefix)
81
- require 'tempfile'
82
-
83
- output = @package.template(template, context)
84
-
85
- final_tempfile = Tempfile.new(prefix.to_s)
86
- final_tempfile.print(output)
87
- final_tempfile.close
88
- final_tempfile
89
- end
90
-
91
- def render_template_file(path, context, prefix)
92
- template = source_is_template? ? path : File.read(path)
93
- tempfile = render_template(template, context, @package.name)
94
- tempfile
95
- end
96
-
97
- def source_is_template?
98
- @source.split("\n").size>1
108
+ def install_commands
109
+ Commands::Transfer.new(sourcepath, destination,
110
+ :recursive => options[:recursive])
99
111
  end
100
112
 
101
- def process(roles) #:nodoc:
102
- logger.debug "transfer: #{@source} -> #{@destination} for roles: #{roles}\n"
113
+ if DEPRECATED
114
+ def render_template(template, context, prefix)
115
+ output = @package.template(template, context)
116
+ final_tempfile = Tempfile.new(prefix.to_s)
117
+ final_tempfile.print(output)
118
+ final_tempfile.close
119
+ final_tempfile
120
+ end
103
121
 
104
- return if Sprinkle::OPTIONS[:testing]
122
+ def render_template_file(path, context, prefix)
123
+ template = source_is_template? ? path : File.read(path)
124
+ tempfile = render_template(template, context, @package.name)
125
+ tempfile
126
+ end
105
127
 
106
- if options[:render]
128
+ def source_is_template?
129
+ @source.split("\n").size > 1
130
+ end
131
+
132
+ def setup_rendering
107
133
  ActiveSupport::Deprecation.warn("transfer :render is depreciated, please use the `file` installer now.")
108
134
  ActiveSupport::Deprecation.warn("transfer :render will be removed from Sprinkle v0.8")
109
- if options[:locals]
110
- context = {}
111
- options[:locals].each_pair do |k,v|
112
- if v.respond_to?(:call)
113
- context[k] = v.call
114
- else
115
- context[k] = v
135
+ if @options[:render]
136
+ raise "Incompatible combination of options :render and :tarball" if tarball?
137
+ if @options[:locals]
138
+ context = {}
139
+ @options[:locals].each_pair do |k,v|
140
+ if v.respond_to?(:call)
141
+ context[k] = v.call
142
+ else
143
+ context[k] = v
144
+ end
116
145
  end
146
+ else
147
+ context = @binding
117
148
  end
118
- else
119
- context = @binding
149
+
150
+ @tempfile = render_template_file(@source, context, @package.name).path
151
+ @sourcepath = @tempfile
152
+ @options[:recursive] = false
120
153
  end
154
+ end
155
+ end
156
+
157
+ def setup_tarball
158
+ # tar files locally and scp to a temp location
159
+ # then untar after transfer
160
+ tar_options = @exclude.map {|glob| "--exclude \"#{glob}\" " }.join('')
161
+ @tempfile = make_tmpname
162
+ local_command = "cd '#{@source}' ; #{local_tar_bin} -zcf '#{@tempfile}' #{tar_options}."
163
+ logger.debug " --> Compressing #{@source} locally"
164
+ raise "Unable to tar #{@source}" unless system(local_command)
165
+ @sourcepath = @tempfile
166
+ @destination = "/tmp/#{File.basename(@tempfile)}"
167
+ post(:install).unshift [
168
+ "#{sudo_cmd}tar -zxf '#{@destination}' -C '#{@final_destination}'",
169
+ "#{sudo_cmd}rm '#{@destination}'"
170
+ ]
171
+ end
172
+
173
+ def setup_sudo
174
+ @destination = "/tmp/sprinkle_#{File.basename(@destination)}"
175
+ # make sure we push the move ahead of any other post install tasks
176
+ # a user may have requested
177
+ post(:install).unshift "#{sudo_cmd}mv #{@destination} #{@final_destination}"
178
+ end
121
179
 
122
- tempfile = render_template_file(@source, context, @package.name)
123
- @sourcepath = tempfile.path
124
- @options[:recursive] = false
125
- else
126
- @sourcepath = @source
180
+ protected
181
+ def local_tar_bin
182
+ @local_tar_bin ||= (`uname` =~ /Darwin/ ? "COPYFILE_DISABLE=true /usr/bin/gnutar" : "tar")
183
+ end
184
+
185
+ def post_process
186
+ return unless @tempfile
187
+ logger.debug " --> Deleting local temp file"
188
+ File.delete @tempfile
189
+ end
190
+
191
+ def make_tmpname
192
+ Dir::Tmpname.make_tmpname(['/tmp/sprinkle-', '.tar.gz'], nil)
127
193
  end
128
194
 
129
- logger.debug " --> Transferring #{sourcepath} to #{@orig_destination} for roles: #{roles}"
130
- @delivery.install(self, roles, :recursive => @options[:recursive])
131
- end
132
195
  end
133
196
  end
134
197
  end
@@ -317,7 +317,7 @@ module Sprinkle
317
317
  tree = []
318
318
  packages.each do |dep, config|
319
319
  package = PACKAGES.find_all(dep, config)
320
- raise "Package definition not found for key: #{dep}" if package.empty? and opts[:required]
320
+ raise MissingPackageError.new(dep) if package.empty? and opts[:required]
321
321
  next if package.empty? # skip missing recommended packages as they're allowed to not exist
322
322
  package = Chooser.select_package(dep, package) #if package.size>1
323
323
  package = package.instance(config)
@@ -1,7 +1,9 @@
1
+ require 'pp'
1
2
  require 'erubis'
2
3
  require 'digest/md5'
3
4
 
4
5
  module Sprinkle::Package
6
+ # For help on rendering, see the Sprinkle::Installers::FileInstaller.
5
7
  module Rendering
6
8
  extend ActiveSupport::Concern
7
9
 
@@ -9,19 +11,21 @@ module Sprinkle::Package
9
11
  self.send :include, Helpers
10
12
  end
11
13
 
14
+ # render src as ERB
12
15
  def template(src, context=binding)
13
16
  eruby = Erubis::Eruby.new(src)
14
17
  eruby.result(context)
15
18
  rescue Object => e
16
19
  raise Sprinkle::Errors::TemplateError.new(e, src, context)
17
20
  end
18
-
21
+
22
+ # read in filename and render it as ERB
19
23
  def render(filename, context=binding)
20
24
  contents=File.read(expand_filename(filename))
21
25
  template(contents, context)
22
26
  end
23
-
24
- # Helper methods can be called from inside your package and
27
+
28
+ # Helper methods can be called from inside your package and
25
29
  # verification code
26
30
  module Helpers
27
31
  # return the md5 of a string (as a hex string)
@@ -30,14 +34,49 @@ module Sprinkle::Package
30
34
  end
31
35
  end
32
36
 
33
- private
34
-
37
+ # sets the path a package should use to search for templates
38
+ def template_search_path(path)
39
+ @template_search_path = path
40
+ end
41
+
42
+ private
43
+
44
+ def search_paths(n) #:nodoc:
45
+ # if we are given an absolute path, return just that path
46
+ return [File.dirname(n)] if n.starts_with? "/"
47
+
48
+ pwd = Dir.pwd
49
+ package_dir = @template_search_path
50
+
51
+ p = []
52
+ # if ./ is used assume the path is relative to the package
53
+ if package_dir
54
+ p << File.expand_path(File.join(package_dir,"templates"))
55
+ p << File.expand_path(package_dir)
56
+ else
57
+ # otherwise search template folders relate to cwd
58
+ p << File.expand_path(File.join(pwd,"templates"))
59
+ p << File.expand_path(pwd)
60
+ end
61
+
62
+ p.uniq
63
+ end
64
+
35
65
  def expand_filename(n) #:nodoc:
36
- return n.to_s if n.to_s.starts_with? "/"
37
- ["./templates/#{n}","./templates/#{n}.erb"].each do |f|
66
+ name = File.basename(n)
67
+ paths = search_paths(n).map do |p|
68
+ [File.join(p,name), File.join(p,"#{name}.erb")]
69
+ end.flatten
70
+
71
+ paths.each do |f|
38
72
  return f if File.exist?(f)
39
73
  end
40
- raise "template file not found"
74
+
75
+ puts "RESOLVED SEARCH PATHS"
76
+ pp paths
77
+
78
+ raise "template not found: #{n}"
79
+
41
80
  end
42
81
 
43
82
  end
@@ -12,6 +12,16 @@ module Sprinkle
12
12
  end
13
13
  end
14
14
 
15
+ class MissingPackageError < StandardError #:nodoc:
16
+ def initialize(name)
17
+ @name = name
18
+ end
19
+
20
+ def to_s
21
+ "Package definition not found for key: #{@name}"
22
+ end
23
+ end
24
+
15
25
  # = Policies
16
26
  #
17
27
  # Policies define a set of packages which are required for a certain
@@ -93,7 +103,7 @@ module Sprinkle
93
103
 
94
104
  opts = args.clone.extract_options!
95
105
  package = Sprinkle::Package::PACKAGES.find_all(p, opts)
96
- raise "Package definition not found for key: #{p}" unless package
106
+ raise MissingPackageError.new(p) unless package.any?
97
107
  package = Sprinkle::Package::Chooser.select_package(p, package) if package.is_a? Array # handle virtual package selection
98
108
  # get an instance of the package and pass our config options
99
109
  package = package.instance(*args)
@@ -1,3 +1,3 @@
1
1
  module Sprinkle
2
- Version = "0.7.5"
2
+ Version = "0.7.6"
3
3
  end
@@ -7,6 +7,33 @@ describe Sprinkle::Package::Rendering, 'rendering' do
7
7
  @package = package :something do
8
8
  end
9
9
  end
10
+
11
+ describe "path expansion" do
12
+
13
+ it "should know / is root" do
14
+ dirs = @package.send :search_paths, "/test/file"
15
+ dirs.should eq ["/test"]
16
+ end
17
+
18
+ it "./ is local to where we tell it to be" do
19
+ Dir.stub(:pwd).and_return("/path/is/")
20
+ @package.template_search_path "/my/super/package/"
21
+ dirs = @package.send :search_paths, "./test/file"
22
+ dirs.should include("/my/super/package")
23
+ dirs.should include("/my/super/package/templates")
24
+ dirs.should_not include("/path/is")
25
+ dirs.should_not include("/path/is/templates")
26
+ end
27
+
28
+ it "should search pwd when amgiguous" do
29
+ Dir.stub(:pwd).and_return("/path/is/")
30
+ dirs = @package.send :search_paths, "test/file"
31
+ dirs.should include("/path/is")
32
+ dirs.should include("/path/is/templates")
33
+ dirs.size.should eq 2
34
+ end
35
+
36
+ end
10
37
 
11
38
  it "should be able to calculate md5s" do
12
39
  @package.md5("test").should == "098f6bcd4621d373cade4e832627b4f6"
@@ -7,7 +7,6 @@ describe Sprinkle::Installers::FileInstaller do
7
7
  @package = double(Sprinkle::Package, :name => 'package', :sudo? => false)
8
8
  @empty = Proc.new { }
9
9
  @delivery = double(Sprinkle::Deployment, :install => true)
10
- @source = 'source'
11
10
  @destination = 'destination'
12
11
  @contents = "hi"
13
12
  @installer = create_file_installer(@destination, :contents => @contents)
@@ -17,6 +16,12 @@ describe Sprinkle::Installers::FileInstaller do
17
16
  source do; prefix '/usr/bin'; end
18
17
  end
19
18
  end
19
+
20
+ def simplify(seq)
21
+ seq.map do |cmd|
22
+ cmd.is_a?(Sprinkle::Commands::Transfer) ? :TRANSFER : cmd
23
+ end
24
+ end
20
25
 
21
26
  def create_file_installer(dest, options={}, &block)
22
27
  i = Sprinkle::Installers::FileInstaller.new(@package, dest, options, &block)
@@ -25,14 +30,41 @@ describe Sprinkle::Installers::FileInstaller do
25
30
  end
26
31
 
27
32
  describe 'when created' do
33
+ before do
34
+ @source = "/tmp/file"
35
+ Tempfile.any_instance.stub(:path).and_return(@source)
36
+ @installer = create_file_installer(@destination, :contents => @contents)
37
+ @transfer = @installer.install_sequence.detect {|x| x.is_a? Sprinkle::Commands::Transfer }
38
+ end
39
+
28
40
  it 'should accept a source and destination to install' do
29
41
  @installer.contents.should eq @contents
30
42
  @installer.destination.should eq @destination
31
43
  end
44
+
45
+ it 'should create a transfer command' do
46
+ @transfer.source.should eq @source
47
+ @transfer.destination.should eq @destination
48
+ end
49
+
50
+ it 'should not be using recursive' do
51
+ @transfer.recursive?.should eq false
52
+ end
32
53
  end
33
54
 
34
55
  describe 'during installation' do
35
56
 
57
+ context "post process hooks" do
58
+
59
+ it "should remove its temporary file" do
60
+ @tmp = double(:print => true, :close => true, :path => "/file")
61
+ Tempfile.stub(:new).and_return(@tmp)
62
+ @installer = create_file_installer(@destination, :contents => @contents)
63
+ @tmp.should_receive(:unlink)
64
+ end
65
+
66
+ end
67
+
36
68
  context "setting mode and owner" do
37
69
  before do
38
70
  @installer = create_file_installer @destination, :content => @contents do
@@ -59,7 +91,7 @@ describe Sprinkle::Installers::FileInstaller do
59
91
  mode "744"
60
92
  owner "root"
61
93
  end
62
- @installer_commands = @installer.install_sequence
94
+ @installer_commands = simplify @installer.install_sequence
63
95
  end
64
96
 
65
97
  it "should run commands in correct order" do
@@ -78,7 +110,7 @@ describe Sprinkle::Installers::FileInstaller do
78
110
  :mode => "744", :owner => "root" do
79
111
  @options[:sudo]= true
80
112
  end
81
- @installer_commands = @installer.install_sequence
113
+ @installer_commands = simplify @installer.install_sequence
82
114
  end
83
115
 
84
116
  it "should run commands in correct order" do
@@ -99,7 +131,7 @@ describe Sprinkle::Installers::FileInstaller do
99
131
  pre :install, 'op1'
100
132
  post :install, 'op2'
101
133
  end
102
- @installer_commands = @installer.install_sequence
134
+ @installer_commands = simplify @installer.install_sequence
103
135
  @delivery = @installer.delivery
104
136
  end
105
137
 
@@ -116,7 +148,7 @@ describe Sprinkle::Installers::FileInstaller do
116
148
  pre :install, 'op1'
117
149
  post :install, 'op2'
118
150
  end
119
- @installer_commands = @installer.install_sequence
151
+ @installer_commands = simplify @installer.install_sequence
120
152
  @delivery = @installer.delivery
121
153
  end
122
154
 
@@ -132,7 +164,7 @@ describe Sprinkle::Installers::FileInstaller do
132
164
  pre :install, 'op1', 'op1-1'
133
165
  post :install, 'op2', 'op2-1'
134
166
  end
135
- @installer_commands = @installer.install_sequence
167
+ @installer_commands = simplify @installer.install_sequence
136
168
  @delivery = @installer.delivery
137
169
  end
138
170
 
@@ -0,0 +1,78 @@
1
+ require File.expand_path("../../spec_helper", File.dirname(__FILE__))
2
+
3
+ describe Sprinkle::Installers::Pecl do
4
+ before do
5
+ # @package = double(Sprinkle::Package, :name => 'spec', :class => double(Sprinkle::Package, :installer_methods => []))
6
+ @package = Package.new("test") {}
7
+ end
8
+
9
+ describe 'providing just package name' do
10
+ before do
11
+ @installer = Sprinkle::Installers::Pecl.new(@package, 'spec')
12
+ end
13
+
14
+ describe 'during installation' do
15
+ it 'should invoke the pecl installer' do
16
+ @install_commands = @installer.send :install_commands
17
+ @install_commands.should == "TERM= pecl install --alldeps spec"
18
+ end
19
+ end
20
+ end
21
+
22
+ describe 'providing explicit version' do
23
+ before do
24
+ @installer = Sprinkle::Installers::Pecl.new(@package, 'spec', :version => '1.1.1')
25
+ end
26
+
27
+ describe 'during installation' do
28
+ it 'should invoke the pecl installer' do
29
+ @install_commands = @installer.send :install_commands
30
+ @install_commands.should == "TERM= pecl install --alldeps spec-1.1.1"
31
+ end
32
+ end
33
+ end
34
+
35
+ describe 'providing ini_file option' do
36
+ describe 'during installation' do
37
+ it 'should transfer file with default arguments in post install' do
38
+ @installer = Sprinkle::Installers::Pecl.new(@package, 'spec', :ini_file => true) do
39
+ self.stub(:file) do |path,options|
40
+ path.should == "/etc/php5/conf.d/spec.ini"
41
+ options[:content].should == "extension=spec.so"
42
+ options[:sudo].should == true
43
+ "post install file transfer"
44
+ end
45
+ end
46
+ @install_sequence = @installer.install_sequence
47
+ @install_sequence.should include("TERM= pecl install --alldeps spec")
48
+ @install_sequence.should include("post install file transfer")
49
+ end
50
+
51
+ it 'should use custom path and content if provided' do
52
+ @installer = Sprinkle::Installers::Pecl.new(@package, 'spec', :ini_file => {:path => "/custom/path", :content => "hello"}) do
53
+ self.stub(:file) do |path,options|
54
+ path.should == "/custom/path"
55
+ options[:content].should == "hello"
56
+ end
57
+ end
58
+ end
59
+
60
+ it 'should use custom content if string passed' do
61
+ @installer = Sprinkle::Installers::Pecl.new(@package, 'spec', :ini_file => "hello") do
62
+ self.stub(:file) do |path,options|
63
+ options[:content].should == "hello"
64
+ end
65
+ end
66
+ end
67
+
68
+ it 'should NOT use sudo if explicitly denied' do
69
+ @installer = Sprinkle::Installers::Pecl.new(@package, 'spec', :ini_file => {:sudo => false}) do
70
+ self.stub(:file) do |path,options|
71
+ options[:sudo].should == false
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ end
@@ -201,6 +201,18 @@ describe Sprinkle::Installers::Source do
201
201
  @installer.send(:install_commands).first.should =~ /super-foo/
202
202
  end
203
203
 
204
+ end
205
+ describe 'with a custom dir definition' do
206
+ before do
207
+ @installer.options[:custom_dir] = 'super-foo'
208
+ end
209
+
210
+ it 'should install the source from the custom archive' do
211
+ @installer.send(:configure_commands).first.should =~ /super-foo/
212
+ @installer.send(:build_commands).first.should =~ /super-foo/
213
+ @installer.send(:install_commands).first.should =~ /super-foo/
214
+ end
215
+
204
216
  end
205
217
 
206
218
  describe 'with default configure, build, and install commands' do
@@ -7,7 +7,7 @@ describe Sprinkle::Installers::Transfer do
7
7
  before do
8
8
  @package = double(Sprinkle::Package, :name => 'package', :sudo? => false)
9
9
  @empty = Proc.new { }
10
- @delivery = double(Sprinkle::Deployment, :install => true)
10
+ @delivery = double(Sprinkle::Deployment, :install => true, :sudo_command => "sudo", :sudo? => false)
11
11
  @source = 'source'
12
12
  @destination = 'destination'
13
13
  @installer = create_transfer(@source, @destination)
@@ -18,6 +18,12 @@ describe Sprinkle::Installers::Transfer do
18
18
  end
19
19
  end
20
20
 
21
+ def simplify(seq)
22
+ seq.map do |cmd|
23
+ cmd.is_a?(Sprinkle::Commands::Transfer) ? :TRANSFER : cmd
24
+ end
25
+ end
26
+
21
27
  def create_transfer(source, dest, options={}, &block)
22
28
  i = Sprinkle::Installers::Transfer.new(@package, source, dest, options, &block)
23
29
  i.delivery = @delivery
@@ -29,27 +35,39 @@ describe Sprinkle::Installers::Transfer do
29
35
  @installer.source.should eq @source
30
36
  @installer.destination.should eq @destination
31
37
  end
38
+
39
+ it 'should create a transfer command with destination and source' do
40
+ transfer = @installer.install_sequence.detect {|x| x.is_a? Sprinkle::Commands::Transfer }
41
+ transfer.source.should eq @source
42
+ transfer.destination.should eq @destination
43
+ end
44
+
45
+ it 'should default to recursive true' do
46
+ transfer = @installer.install_sequence.detect {|x| x.is_a? Sprinkle::Commands::Transfer }
47
+ transfer.recursive?.should eq true
48
+ end
32
49
  end
33
50
 
34
51
  describe 'during installation' do
35
52
 
36
53
  context "setting mode and owner" do
37
- before do
54
+ before do
38
55
  @installer = create_transfer @source, @destination do
39
56
  mode "744"
40
57
  owner "root"
41
58
  end
59
+ @installer.process @roles
42
60
  @installer_commands = @installer.install_sequence
43
61
  end
44
-
62
+
45
63
  it "should include command to set owner" do
46
- @installer_commands.should include("chmod 744 #{@destination}")
64
+ @installer_commands.should include("chmod -R 744 #{@destination}")
47
65
  end
48
-
66
+
49
67
  it "should include command to set mode" do
50
- @installer_commands.should include("chown root #{@destination}")
68
+ @installer_commands.should include("chown -R root #{@destination}")
51
69
  end
52
-
70
+
53
71
  end
54
72
 
55
73
  context 'single pre/post commands' do
@@ -58,12 +76,12 @@ describe Sprinkle::Installers::Transfer do
58
76
  pre :install, 'op1'
59
77
  post :install, 'op2'
60
78
  end
61
- @installer_commands = @installer.install_sequence
79
+ @installer_commands = simplify @installer.install_sequence
62
80
  @delivery = @installer.delivery
63
81
  end
64
82
 
65
83
  it "should call the pre and post install commands around the file transfer" do
66
- @installer_commands.should eq ["op1",:TRANSFER, "op2"]
84
+ @installer_commands.should eq ["op1", :TRANSFER, "op2"]
67
85
  end
68
86
 
69
87
  # it "should call transfer with recursive defaulted to nil" do
@@ -72,21 +90,21 @@ describe Sprinkle::Installers::Transfer do
72
90
  # end
73
91
 
74
92
  end
75
-
93
+
76
94
  context 'pre/post with sudo' do
77
95
  before do
78
- @installer = create_transfer @source, @destination do
79
- @options[:sudo]= true
96
+ @delivery = double(Sprinkle::Deployment, :install => true, :sudo_command => "sudo")
97
+ @installer = create_transfer @source, @destination, :sudo => true do
80
98
  pre :install, 'op1'
81
99
  post :install, 'op2'
82
100
  end
83
- @installer_commands = @installer.install_sequence
101
+ @installer.process @roles
102
+ @installer_commands = simplify @installer.install_sequence
84
103
  @delivery = @installer.delivery
85
104
  end
86
105
 
87
106
  it "should call the pre and post install commands around the file transfer" do
88
- @installer_commands.should eq ["op1",:TRANSFER,
89
- "sudo mv /tmp/sprinkle_destination destination", "op2"]
107
+ @installer_commands.should eq ["op1", :TRANSFER, "sudo mv /tmp/sprinkle_destination destination", "op2"]
90
108
  end
91
109
  end
92
110
 
@@ -96,7 +114,7 @@ describe Sprinkle::Installers::Transfer do
96
114
  pre :install, 'op1', 'op1-1'
97
115
  post :install, 'op2', 'op2-1'
98
116
  end
99
- @installer_commands = @installer.install_sequence
117
+ @installer_commands = simplify @installer.install_sequence
100
118
  @delivery = @installer.delivery
101
119
  end
102
120
 
@@ -114,19 +132,19 @@ describe Sprinkle::Installers::Transfer do
114
132
  describe "if the :render flag is true" do
115
133
  before do
116
134
  allow(::ActiveSupport::Deprecation).to receive(:warn)
117
- @installer = create_transfer @source, @destination, :render => true
118
- @delivery = @installer.delivery
119
- @delivery.stub(:render_template_file)
120
135
  @tempfile = Tempfile.new("foo")
136
+ Sprinkle::Installers::Transfer.any_instance.
137
+ should_receive(:render_template_file).
138
+ with(@source, anything, @package.name).
139
+ and_return(@tempfile)
140
+ @installer = create_transfer @source, @destination, :render => true
121
141
  end
122
142
 
123
143
  it "should render the source file as a template to a tempfile" do
124
- @installer.should_receive(:render_template_file).with(@source, anything, @package.name).and_return(@tempfile)
125
144
  @delivery.stub(:transfer)
126
145
  end
127
146
 
128
147
  it "should call transfer with recursive set to false" do
129
- @installer.should_receive(:render_template_file).with(@source, anything, @package.name).and_return(@tempfile)
130
148
  @installer.options[:recursive].should eq false
131
149
  end
132
150
 
@@ -140,13 +158,45 @@ describe Sprinkle::Installers::Transfer do
140
158
  @installer = create_transfer @source, @destination, :recursive => false
141
159
  end
142
160
 
143
- it "should call transfer with recursive set to false" do
144
- @installer.delivery
145
- @installer.options[:recursive].should eq false
161
+ it "should created transfer command with recursive set to false" do
162
+ transfer = @installer.install_sequence.detect {|x| x.is_a? Sprinkle::Commands::Transfer }
163
+ transfer.recursive?.should eq false
146
164
  end
165
+ end
147
166
 
148
- after do
167
+ describe "if the :tarball option is set" do
168
+ it "should tar locally, then transfer and extract, finally deleting local tempfile" do
169
+ @installer = create_transfer @source, @destination, :tarball => true do
170
+ self.stub(:local_tar_bin) { "tar" }
171
+ self.stub(:make_tmpname) { "/tmp/foo.tar.gz" }
172
+ self.should_receive(:system) do |command|
173
+ command.should == "cd 'source' ; tar -zcf '/tmp/foo.tar.gz' ."
174
+ true
175
+ end
176
+ File.should_receive(:delete) do |path|
177
+ path.should == "/tmp/foo.tar.gz"
178
+ end
179
+ end
149
180
  @installer.process @roles
181
+ install_sequence = @installer.install_sequence
182
+ install_sequence.should include("tar -zxf '/tmp/foo.tar.gz' -C 'destination'")
183
+ install_sequence.should include("rm '/tmp/foo.tar.gz'")
184
+ end
185
+
186
+ describe "and the :exclude option is provided" do
187
+ it "should pass --exclude option to local tar command" do
188
+ @installer = create_transfer @source, @destination, :tarball => {:exclude => %w(.git log/*)} do
189
+ self.stub(:local_tar_bin) { "tar" }
190
+ self.stub(:make_tmpname) { "/tmp/foo.tar.gz" }
191
+ self.should_receive(:system) do |command|
192
+ command.should == "cd 'source' ; tar -zcf '/tmp/foo.tar.gz' --exclude \".git\" --exclude \"log/*\" ."
193
+ true
194
+ end
195
+ end
196
+ end
150
197
  end
198
+
151
199
  end
200
+
201
+
152
202
  end
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.7.5
4
+ version: 0.7.6
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-08-29 00:00:00.000000000 Z
13
+ date: 2013-09-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -189,6 +189,9 @@ files:
189
189
  - lib/sprinkle/actors/ssh.rb
190
190
  - lib/sprinkle/actors/ssh/connection_cache.rb
191
191
  - lib/sprinkle/actors/vlad.rb
192
+ - lib/sprinkle/commands/command.rb
193
+ - lib/sprinkle/commands/reconnect.rb
194
+ - lib/sprinkle/commands/transfer.rb
192
195
  - lib/sprinkle/core.rb
193
196
  - lib/sprinkle/deployment.rb
194
197
  - lib/sprinkle/errors/pretty_failure.rb
@@ -220,6 +223,7 @@ files:
220
223
  - lib/sprinkle/installers/package_installer.rb
221
224
  - lib/sprinkle/installers/pacman.rb
222
225
  - lib/sprinkle/installers/pear.rb
226
+ - lib/sprinkle/installers/pecl.rb
223
227
  - lib/sprinkle/installers/push_text.rb
224
228
  - lib/sprinkle/installers/rake.rb
225
229
  - lib/sprinkle/installers/reconnect.rb
@@ -276,6 +280,7 @@ files:
276
280
  - spec/sprinkle/installers/openbsd_pkg_spec.rb
277
281
  - spec/sprinkle/installers/opensolaris_pkg_spec.rb
278
282
  - spec/sprinkle/installers/pear_spec.rb
283
+ - spec/sprinkle/installers/pecl_spec.rb
279
284
  - spec/sprinkle/installers/push_text_spec.rb
280
285
  - spec/sprinkle/installers/rake_spec.rb
281
286
  - spec/sprinkle/installers/replace_text_spec.rb
@@ -348,6 +353,7 @@ test_files:
348
353
  - spec/sprinkle/installers/openbsd_pkg_spec.rb
349
354
  - spec/sprinkle/installers/opensolaris_pkg_spec.rb
350
355
  - spec/sprinkle/installers/pear_spec.rb
356
+ - spec/sprinkle/installers/pecl_spec.rb
351
357
  - spec/sprinkle/installers/push_text_spec.rb
352
358
  - spec/sprinkle/installers/rake_spec.rb
353
359
  - spec/sprinkle/installers/replace_text_spec.rb