crafterm-sprinkle 0.2.2 → 0.2.3

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/CREDITS CHANGED
@@ -19,3 +19,8 @@ Jorgen Orehøj Erichsen (http://blog.erichsen.net)
19
19
  Joshua Sierles (http://diluvia.net)
20
20
  Julian Russell (http://github.com/plusplus)
21
21
  Dave (Gassto) (http://github.com/gassto)
22
+ Bodaniel Jeanes (http://bjeanes.github.com)
23
+ Jacob Harris (http://open.nytimes.com)
24
+ Justin Pease (http://jit.nuance9.com)
25
+ Tobias Lütke (http://blog.leetsoft.com)
26
+ Josh Reynolds (http://github.com/jreynolds)
data/Manifest.txt CHANGED
@@ -54,7 +54,13 @@ lib/sprinkle/installers/push_text.rb
54
54
  lib/sprinkle/installers/rake.rb
55
55
  lib/sprinkle/installers/rpm.rb
56
56
  lib/sprinkle/installers/source.rb
57
+ lib/sprinkle/installers/transfer.rb
57
58
  lib/sprinkle/installers/yum.rb
59
+ lib/sprinkle/installers/freebsd_pkg.rb
60
+ lib/sprinkle/installers/openbsd_pkg.rb
61
+ lib/sprinkle/installers/opensolaris_pkg.rb
62
+ lib/sprinkle/installers/bsd_port.rb
63
+ lib/sprinkle/installers/mac_port.rb
58
64
  lib/sprinkle/package.rb
59
65
  lib/sprinkle/policy.rb
60
66
  lib/sprinkle/script.rb
@@ -89,6 +95,10 @@ spec/sprinkle/installers/rake_spec.rb
89
95
  spec/sprinkle/installers/rpm_spec.rb
90
96
  spec/sprinkle/installers/source_spec.rb
91
97
  spec/sprinkle/installers/yum_spec.rb
98
+ spec/sprinkle/installers/openbsd_pkg_spec.rb
99
+ spec/sprinkle/installers/freebsd_pkg_spec.rb
100
+ spec/sprinkle/installers/bsd_port_spec.rb
101
+ spec/sprinkle/installers/mac_port_spec.rb
92
102
  spec/sprinkle/package_spec.rb
93
103
  spec/sprinkle/policy_spec.rb
94
104
  spec/sprinkle/script_spec.rb
data/bin/sprinkle CHANGED
@@ -73,7 +73,7 @@ def log_level(options)
73
73
  Object.logger.level = ActiveSupport::BufferedLogger::Severity::DEBUG if options[:verbose]
74
74
  end
75
75
 
76
- require 'sprinkle'
76
+ require File.dirname(__FILE__) + '/../lib/sprinkle'
77
77
 
78
78
  powder = OPTIONS[:path]
79
79
  raise "Sprinkle script is not readable: #{powder}" unless File.readable?(powder)
@@ -25,8 +25,15 @@ module Sprinkle
25
25
  @config = ::Capistrano::Configuration.new
26
26
  @config.logger.level = Sprinkle::OPTIONS[:verbose] ? ::Capistrano::Logger::INFO : ::Capistrano::Logger::IMPORTANT
27
27
  @config.set(:password) { ::Capistrano::CLI.password_prompt }
28
+
29
+ @config.set(:_sprinkle_actor, self)
30
+
31
+ def @config.recipes(script)
32
+ _sprinkle_actor.recipes(script)
33
+ end
34
+
28
35
  if block
29
- self.instance_eval &block
36
+ @config.instance_eval &block
30
37
  else
31
38
  @config.load 'deploy' # normally in the config directory for rails
32
39
  end
@@ -69,6 +76,22 @@ module Sprinkle
69
76
  end
70
77
  end
71
78
 
79
+ def transfer(name, source, destination, roles, recursive = true, suppress_and_return_failures = false)
80
+ define_task(name, roles) do
81
+ upload source, destination, :via => :scp, :recursive => recursive
82
+ end
83
+
84
+ begin
85
+ run(name)
86
+ return true
87
+ rescue ::Capistrano::CommandError => e
88
+ return false if suppress_and_return_failures
89
+
90
+ # Reraise error if we're not suppressing it
91
+ raise
92
+ end
93
+ end
94
+
72
95
  private
73
96
 
74
97
  # REVISIT: can we set the description somehow?
@@ -25,6 +25,13 @@ module Sprinkle
25
25
  return true
26
26
  end
27
27
 
28
+ def transfer(name, source, destination, roles, recursive = true, suppress_and_return_failures = false)
29
+ if recursive
30
+ flags = "-R "
31
+ end
32
+
33
+ system "cp #{flags}#{source} #{destination}"
34
+ end
28
35
  end
29
36
  end
30
37
  end
@@ -1,4 +1,5 @@
1
1
  require 'net/ssh/gateway'
2
+ require 'net/scp'
2
3
 
3
4
  module Sprinkle
4
5
  module Actors
@@ -26,7 +27,12 @@ module Sprinkle
26
27
  return process_with_gateway(name, commands, roles) if gateway_defined?
27
28
  process_direct(name, commands, roles)
28
29
  end
29
-
30
+
31
+ def transfer(name, source, destination, roles, recursive = true, suppress_and_return_failures = false)
32
+ return transfer_with_gateway(name, source, destination, roles, recursive) if gateway_defined?
33
+ transfer_direct(name, source, destination, roles, recursive)
34
+ end
35
+
30
36
  protected
31
37
 
32
38
  def process_with_gateway(name, commands, roles)
@@ -39,10 +45,25 @@ module Sprinkle
39
45
  Array(roles).each { |role| execute_on_role(commands, role) }
40
46
  end
41
47
 
48
+ def transfer_with_gateway(name, source, destination, roles, recursive)
49
+ on_gateway do |gateway|
50
+ Array(roles).each { |role| transfer_to_role(source, destination, role, recursive, gateway) }
51
+ end
52
+ end
53
+
54
+ def transfer_direct(name, source, destination, roles, recursive)
55
+ Array(roles).each { |role| transfer_to_role(source, destination, role, recursive) }
56
+ end
57
+
42
58
  def execute_on_role(commands, role, gateway = nil)
43
59
  hosts = @options[:roles][role]
44
60
  Array(hosts).each { |host| execute_on_host(commands, host, gateway) }
45
61
  end
62
+
63
+ def transfer_to_role(source, destination, role, gateway = nil)
64
+ hosts = @options[:roles][role]
65
+ Array(hosts).each { |host| transfer_to_host(source, destination, host, gateway) }
66
+ end
46
67
 
47
68
  def execute_on_host(commands, host, gateway = nil)
48
69
  if gateway # SSH connection via gateway
@@ -64,6 +85,23 @@ module Sprinkle
64
85
  end
65
86
  end
66
87
 
88
+ def transfer_to_host(source, destination, host, recursive, gateway = nil)
89
+ if gateway # SSH connection via gateway
90
+ gateway.ssh(host, @options[:user]) do |ssh|
91
+ transfer_on_connection(source, destination, recursive, ssh)
92
+ end
93
+ else # direct SSH connection
94
+ Net::SSH.start(host, @options[:user]) do |ssh|
95
+ transfer_on_connection(source, destination, recursive, ssh)
96
+ end
97
+ end
98
+ end
99
+
100
+ def transfer_on_connection(source, destination, recursive, connection)
101
+ scp = Net::SCP.new(connection)
102
+ scp.upload! source, destination, :recursive => recursive
103
+ end
104
+
67
105
  private
68
106
 
69
107
  def gateway_defined?
@@ -50,6 +50,19 @@ module Sprinkle
50
50
  rescue ::Vlad::CommandFailedError => e
51
51
  return false if suppress_and_return_failures
52
52
 
53
+ # Reraise error if we're not suppressing it
54
+ raise
55
+ end
56
+ end
57
+
58
+ # Sorry, all transfers are recursive
59
+ def transfer(name, source, destination, roles, recursive = true, suppress_and_return_failures = false) #:nodoc:
60
+ begin
61
+ rsync source, destination
62
+ return true
63
+ rescue ::Vlad::CommandFailedError => e
64
+ return false if suppress_and_return_failures
65
+
53
66
  # Reraise error if we're not suppressing it
54
67
  raise
55
68
  end
@@ -52,7 +52,7 @@ 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
- @style = Actors.const_get(type.to_s.titleize).new &block
55
+ @style = ("Sprinkle::Actors::" + type.to_s.titleize).constantize.new &block
56
56
  end
57
57
 
58
58
  def method_missing(sym, *args, &block) #:nodoc:
@@ -54,6 +54,7 @@ module Sprinkle
54
54
  cmd << " --source #{source}" if source
55
55
  cmd << " --install-dir #{repository}" if option?(:repository)
56
56
  cmd << " --no-rdoc --no-ri" unless option?(:build_docs)
57
+ cmd << " --http-proxy #{http_proxy}" if option?(:http_proxy)
57
58
  cmd << " -- #{build_flags}" if option?(:build_flags)
58
59
  cmd
59
60
  end
@@ -37,7 +37,7 @@ module Sprinkle
37
37
  protected
38
38
 
39
39
  def install_commands #:nodoc:
40
- "echo '#{@text}' |#{'sudo' if option?(:sudo)} tee -a #{@path}"
40
+ "echo -e '#{@text.gsub("\n", '\n')}' |#{'sudo' if option?(:sudo)} tee -a #{@path}"
41
41
  end
42
42
 
43
43
  end
@@ -46,16 +46,26 @@ module Sprinkle
46
46
  # package :magic_beans do
47
47
  # source 'http://magicbeansland.com/latest-1.1.1.tar.gz' do
48
48
  # prefix '/usr/local'
49
- #
49
+ #
50
50
  # pre :prepare { 'echo "Here we go folks."' }
51
51
  # post :extract { 'echo "I believe..."' }
52
52
  # pre :build { 'echo "Cross your fingers!"' }
53
53
  # end
54
54
  # end
55
55
  #
56
+ # Fourth, specifying a custom archive name because the downloaded file name
57
+ # differs from the source URL:
58
+ #
59
+ # package :gitosis do
60
+ # source 'http://github.com/crafterm/sprinkle/tarball/master' do
61
+ # custom_archive 'crafterm-sprinkle-518e33c835986c03ec7ae8ea88c657443b006f28.tar.gz'
62
+ # end
63
+ # end
64
+ #
56
65
  # As you can see, setting options is as simple as creating a
57
66
  # block and calling the option as a method with the value as
58
67
  # its parameter.
68
+
59
69
  class Source < Installer
60
70
  attr_accessor :source #:nodoc:
61
71
 
@@ -143,7 +153,7 @@ module Sprinkle
143
153
  end
144
154
 
145
155
  def extract_command #:nodoc:
146
- case @source
156
+ case archive_name
147
157
  when /(tar.gz)|(tgz)$/
148
158
  'tar xzf'
149
159
  when /(tar.bz2)|(tb2)$/
@@ -158,7 +168,7 @@ module Sprinkle
158
168
  end
159
169
 
160
170
  def archive_name #:nodoc:
161
- name = @source.split('/').last
171
+ name = @options[:custom_archive] || @source.split('/').last
162
172
  raise "Unable to determine archive name for source: #{source}, please update code knowledge" unless name
163
173
  name
164
174
  end
@@ -168,12 +178,12 @@ module Sprinkle
168
178
  end
169
179
 
170
180
  def base_dir #:nodoc:
171
- if @source.split('/').last =~ /(.*)\.(tar\.gz|tgz|tar\.bz2|tb2)/
181
+ if archive_name.split('/').last =~ /(.*)\.(tar\.gz|tgz|tar\.bz2|tar|tb2)/
172
182
  return $1
173
183
  end
174
184
  raise "Unknown base path for source archive: #{@source}, please update code knowledge"
175
185
  end
176
-
186
+
177
187
  end
178
188
  end
179
189
  end
@@ -168,16 +168,24 @@ module Sprinkle
168
168
 
169
169
  def rake(name, options = {}, &block)
170
170
  @installer = Sprinkle::Installers::Rake.new(self, name, options, &block)
171
+ end
172
+
173
+ def noop(&block)
174
+ @installer = Sprinkle::Installers::Noop.new(self, name, options, &block)
171
175
  end
172
176
 
173
177
  def push_text(text, path, options = {}, &block)
174
178
  @installer = Sprinkle::Installers::PushText.new(self, text, path, options, &block)
175
179
  end
176
-
177
- def verify(description = '', &block)
178
- @verifications << Sprinkle::Verify.new(self, description, &block)
180
+
181
+ def transfer(source, destination, options = {}, &block)
182
+ @installer = Sprinkle::Installers::Transfer.new(self, source, destination, options, &block)
179
183
  end
180
184
 
185
+ def verify(description = '', &block)
186
+ @verifications << Sprinkle::Verify.new(self, description, &block)
187
+ end
188
+
181
189
  def process(deployment, roles)
182
190
  return if meta_package?
183
191
 
@@ -2,7 +2,7 @@ module Sprinkle #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- TINY = 2
5
+ TINY = 3
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -135,6 +135,51 @@ describe Sprinkle::Actors::Capistrano do
135
135
 
136
136
  end
137
137
 
138
+ describe 'transferring files' do
139
+
140
+ before do
141
+ @source = 'source'
142
+ @dest = 'dest'
143
+ @roles = %w( app )
144
+ @name = 'name'
145
+
146
+ @cap = create_cap do; recipes 'deploy'; end
147
+ @cap.stub!(:run).and_return
148
+
149
+ @testing_errors = false
150
+ end
151
+
152
+ it 'should dynamically create a capistrano task containing calling upload' do
153
+ @cap.config.should_receive(:task).and_return
154
+ end
155
+
156
+ it 'should invoke capistrano task after creation' do
157
+ @cap.should_receive(:run).with(@name).and_return
158
+ end
159
+
160
+ it 'should raise capistrano errors when suppressing parameter is not set' do
161
+ @testing_errors = true
162
+
163
+ @cap.should_receive(:run).and_raise(::Capistrano::CommandError)
164
+ lambda { @cap.process @name, @commands, @roles }.should raise_error(::Capistrano::CommandError)
165
+ end
166
+
167
+ it 'should not raise errors and instead return false when suppressing parameter is set' do
168
+ @testing_errors = true
169
+
170
+ @cap.should_receive(:run).and_raise(::Capistrano::CommandError)
171
+
172
+ value = nil
173
+ lambda { value = @cap.process(@name, @commands, @roles, true) }.should_not raise_error(::Capistrano::CommandError)
174
+
175
+ value.should_not be
176
+ end
177
+
178
+ after do
179
+ @cap.transfer @name, @source, @dest, @roles unless @testing_errors
180
+ end
181
+ end
182
+
138
183
  describe 'generated task' do
139
184
 
140
185
  before do
@@ -167,4 +212,54 @@ describe Sprinkle::Actors::Capistrano do
167
212
 
168
213
  end
169
214
 
215
+ describe 'generated transfer' do
216
+ before do
217
+ @source = 'source'
218
+ @dest = 'dest'
219
+ @roles = %w( app )
220
+ @name = 'name'
221
+
222
+ @cap = create_cap do; recipes 'deploy'; end
223
+ @cap.config.stub!(:upload).and_return
224
+ end
225
+
226
+ it 'should call upload with the source and destination via :scp' do
227
+ @cap.config.should_receive(:upload).with(@source, @dest, :via => :scp, :recursive => true).and_return
228
+ end
229
+
230
+ it 'should be applicable for the supplied roles' do
231
+ @cap.stub!(:run).and_return
232
+ @cap.config.should_receive(:task).with(:install_name, :roles => @roles).and_return
233
+ end
234
+
235
+ after do
236
+ @cap.transfer @name, @source, @dest, @roles
237
+ end
238
+ end
239
+
240
+ describe 'generated transfer when recursive is false' do
241
+ before do
242
+ @source = 'source'
243
+ @dest = 'dest'
244
+ @roles = %w( app )
245
+ @name = 'name'
246
+
247
+ @cap = create_cap do; recipes 'deploy'; end
248
+ @cap.config.stub!(:upload).and_return
249
+ end
250
+
251
+ it 'should call upload with the source and destination via :scp' do
252
+ @cap.config.should_receive(:upload).with(@source, @dest, :via => :scp, :recursive => false).and_return
253
+ end
254
+
255
+ it 'should be applicable for the supplied roles' do
256
+ @cap.stub!(:run).and_return
257
+ @cap.config.should_receive(:task).with(:install_name, :roles => @roles).and_return
258
+ end
259
+
260
+ after do
261
+ @cap.transfer @name, @source, @dest, @roles, false
262
+ end
263
+ end
264
+
170
265
  end
@@ -5,7 +5,7 @@ describe Sprinkle::Installers::Gem do
5
5
  before do
6
6
  @gem = 'rails'
7
7
  @version = '2.0.2'
8
- @options = { :source => 'http://gems.github.com/', :repository => '/tmp/gems', :build_flags => '--build_flag=foo' }
8
+ @options = { :source => 'http://gems.github.com/', :repository => '/tmp/gems', :build_flags => '--build_flag=foo', :http_proxy => 'http://proxy:8080' }
9
9
  end
10
10
 
11
11
  def create_gem(gem, version = nil, options = {}, &block)
@@ -39,6 +39,10 @@ describe Sprinkle::Installers::Gem do
39
39
  @installer.build_flags.should == @options[:build_flags]
40
40
  end
41
41
 
42
+ it 'should optionally store the http proxy' do
43
+ @installer.http_proxy.should == @options[:http_proxy]
44
+ end
45
+
42
46
  end
43
47
 
44
48
  describe 'during installation' do
@@ -86,6 +90,18 @@ describe Sprinkle::Installers::Gem do
86
90
 
87
91
  end
88
92
 
93
+ describe 'with http proxy' do
94
+
95
+ before do
96
+ @installer = create_gem @gem, nil, :http_proxy => 'http://proxy:8080'
97
+ end
98
+
99
+ it 'should install with defined build flags' do
100
+ @installer.send(:install_commands).should == "gem install #{@gem} --no-rdoc --no-ri --http-proxy http://proxy:8080"
101
+ end
102
+
103
+ end
104
+
89
105
  end
90
106
 
91
107
  end
@@ -36,7 +36,7 @@ describe Sprinkle::Installers::PushText do
36
36
  end
37
37
 
38
38
  it 'should automatically insert pre/post commands for the specified package' do
39
- @installer.send(:install_sequence).should == [ 'op1', "echo 'another-hair-brained-idea' | tee -a /dev/mind/late-night", 'op2' ]
39
+ @installer.send(:install_sequence).should == [ 'op1', "echo -e 'another-hair-brained-idea' | tee -a /dev/mind/late-night", 'op2' ]
40
40
  end
41
41
 
42
42
  end
@@ -48,7 +48,7 @@ describe Sprinkle::Installers::PushText do
48
48
  end
49
49
 
50
50
  it "should invoke the push installer with sudo" do
51
- @install_commands.should =~ /echo 'I\'m a special user' | sudo tee -a \/dev\/mind\/the-day-after/
51
+ @install_commands.should =~ /echo -e 'I\'m a special user' | sudo tee -a \/dev\/mind\/the-day-after/
52
52
  end
53
53
  end
54
54
 
@@ -161,6 +161,20 @@ describe Sprinkle::Installers::Source do
161
161
  )
162
162
  end
163
163
 
164
+ describe 'with a custom archive definition' do
165
+ before do
166
+ @installer.options[:custom_archive] = 'super-foo.tar'
167
+ end
168
+
169
+ it 'should install the source from the custom archive' do
170
+ @installer.send(:extract_commands).first.should =~ /super-foo/
171
+ @installer.send(:configure_commands).first.should =~ /super-foo/
172
+ @installer.send(:build_commands).first.should =~ /super-foo/
173
+ @installer.send(:install_commands).first.should =~ /super-foo/
174
+ end
175
+
176
+ end
177
+
164
178
  describe 'during a customized install' do
165
179
 
166
180
  before do
@@ -174,7 +188,7 @@ describe Sprinkle::Installers::Source do
174
188
  it 'should store the custom install commands' do
175
189
  @installer.options[:custom_install].should == 'ruby setup.rb'
176
190
  end
177
-
191
+
178
192
  it 'should identify as having a custom install command' do
179
193
  @installer.should be_custom_install
180
194
  end
@@ -190,25 +204,25 @@ describe Sprinkle::Installers::Source do
190
204
  it 'should install the source using a custom installation command' do
191
205
  @installer.send(:custom_install_commands).first.should =~ /ruby setup.rb/
192
206
  end
193
-
207
+
194
208
  it 'should be run relative to the source build area' do
195
209
  @installer.send(:custom_install_commands).first.should =~ %r{cd /usr/builds/ruby-1.8.6-p111}
196
210
  end
197
-
211
+
198
212
  describe 'with a customized directory' do
199
-
213
+
200
214
  before do
201
215
  @installer.options[:custom_dir] = 'test'
202
216
  end
203
-
217
+
204
218
  it 'should install the source from the custom dir path' do
205
219
  @installer.send(:custom_install_commands).first.should =~ /test/
206
220
  end
207
-
221
+
208
222
  it 'should store the custom build dir path' do
209
223
  @installer.options[:custom_dir].should == 'test'
210
224
  end
211
-
225
+
212
226
  end
213
227
 
214
228
  end
data/sprinkle.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{sprinkle}
3
- s.version = "0.2.2"
3
+ s.version = "0.2.3"
4
4
 
5
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
6
  s.authors = ["Marcus Crafter", "Mitchell Hashimoto"]
@@ -21,6 +21,9 @@ task :check_version do
21
21
  end
22
22
  end
23
23
 
24
+ task :clobber_rcov do
25
+ end
26
+
24
27
  desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
28
  task :install_gem_no_doc => [:clean, :package] do
26
29
  sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crafterm-sprinkle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcus Crafter