crafterm-sprinkle 0.2.2 → 0.2.3

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