sprinkle 0.4.2 → 0.5.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +5 -0
  3. data/Gemfile.lock +54 -0
  4. data/README.markdown +178 -166
  5. data/Rakefile +4 -28
  6. data/bin/sprinkle +14 -1
  7. data/lib/sprinkle.rb +5 -1
  8. data/lib/sprinkle/actors/actors.rb +20 -5
  9. data/lib/sprinkle/actors/capistrano.rb +62 -36
  10. data/lib/sprinkle/actors/dummy.rb +127 -0
  11. data/lib/sprinkle/actors/local.rb +59 -17
  12. data/lib/sprinkle/actors/ssh.rb +189 -107
  13. data/lib/sprinkle/actors/vlad.rb +51 -32
  14. data/lib/sprinkle/configurable.rb +2 -1
  15. data/lib/sprinkle/deployment.rb +22 -2
  16. data/lib/sprinkle/errors/pretty_failure.rb +41 -0
  17. data/lib/sprinkle/errors/remote_command_failure.rb +24 -0
  18. data/lib/sprinkle/errors/transfer_failure.rb +28 -0
  19. data/lib/sprinkle/installers/apt.rb +17 -16
  20. data/lib/sprinkle/installers/binary.rb +23 -8
  21. data/lib/sprinkle/installers/brew.rb +17 -10
  22. data/lib/sprinkle/installers/bsd_port.rb +10 -6
  23. data/lib/sprinkle/installers/deb.rb +3 -10
  24. data/lib/sprinkle/installers/freebsd_pkg.rb +5 -11
  25. data/lib/sprinkle/installers/freebsd_portinstall.rb +8 -2
  26. data/lib/sprinkle/installers/gem.rb +9 -3
  27. data/lib/sprinkle/installers/group.rb +28 -4
  28. data/lib/sprinkle/installers/installer.rb +58 -7
  29. data/lib/sprinkle/installers/mac_port.rb +13 -6
  30. data/lib/sprinkle/installers/npm.rb +42 -0
  31. data/lib/sprinkle/installers/openbsd_pkg.rb +4 -11
  32. data/lib/sprinkle/installers/opensolaris_pkg.rb +7 -13
  33. data/lib/sprinkle/installers/package_installer.rb +33 -0
  34. data/lib/sprinkle/installers/pacman.rb +5 -13
  35. data/lib/sprinkle/installers/pear.rb +40 -0
  36. data/lib/sprinkle/installers/push_text.rb +18 -5
  37. data/lib/sprinkle/installers/rake.rb +7 -2
  38. data/lib/sprinkle/installers/reconnect.rb +29 -0
  39. data/lib/sprinkle/installers/replace_text.rb +11 -2
  40. data/lib/sprinkle/installers/rpm.rb +8 -6
  41. data/lib/sprinkle/installers/runner.rb +41 -16
  42. data/lib/sprinkle/installers/smart.rb +6 -17
  43. data/lib/sprinkle/installers/source.rb +22 -10
  44. data/lib/sprinkle/installers/thor.rb +7 -0
  45. data/lib/sprinkle/installers/transfer.rb +62 -41
  46. data/lib/sprinkle/installers/user.rb +34 -4
  47. data/lib/sprinkle/installers/yum.rb +10 -10
  48. data/lib/sprinkle/installers/zypper.rb +4 -15
  49. data/lib/sprinkle/package.rb +81 -98
  50. data/lib/sprinkle/policy.rb +11 -4
  51. data/lib/sprinkle/utility/log_recorder.rb +33 -0
  52. data/lib/sprinkle/verifiers/directory.rb +1 -1
  53. data/lib/sprinkle/verifiers/executable.rb +1 -1
  54. data/lib/sprinkle/verifiers/file.rb +11 -2
  55. data/lib/sprinkle/verifiers/package.rb +2 -14
  56. data/lib/sprinkle/verifiers/permission.rb +40 -0
  57. data/lib/sprinkle/verifiers/symlink.rb +2 -2
  58. data/lib/sprinkle/verifiers/test.rb +21 -0
  59. data/lib/sprinkle/verify.rb +3 -3
  60. data/lib/sprinkle/version.rb +3 -0
  61. data/spec/fixtures/my_file.txt +1 -0
  62. data/spec/sprinkle/actors/capistrano_spec.rb +16 -3
  63. data/spec/sprinkle/actors/local_spec.rb +24 -6
  64. data/spec/sprinkle/actors/ssh_spec.rb +38 -0
  65. data/spec/sprinkle/installers/apt_spec.rb +23 -2
  66. data/spec/sprinkle/installers/binary_spec.rb +22 -14
  67. data/spec/sprinkle/installers/brew_spec.rb +4 -4
  68. data/spec/sprinkle/installers/installer_spec.rb +36 -7
  69. data/spec/sprinkle/installers/npm_spec.rb +16 -0
  70. data/spec/sprinkle/installers/pear_spec.rb +16 -0
  71. data/spec/sprinkle/installers/push_text_spec.rb +23 -1
  72. data/spec/sprinkle/installers/rpm_spec.rb +5 -0
  73. data/spec/sprinkle/installers/runner_spec.rb +27 -11
  74. data/spec/sprinkle/installers/smart_spec.rb +60 -0
  75. data/spec/sprinkle/installers/source_spec.rb +4 -4
  76. data/spec/sprinkle/installers/transfer_spec.rb +31 -16
  77. data/spec/sprinkle/package_spec.rb +10 -2
  78. data/spec/sprinkle/policy_spec.rb +6 -0
  79. data/spec/sprinkle/verify_spec.rb +18 -4
  80. data/sprinkle.gemspec +22 -158
  81. metadata +178 -96
  82. data/TODO +0 -56
  83. data/VERSION +0 -1
  84. data/lib/sprinkle/verifiers/apt.rb +0 -21
  85. data/lib/sprinkle/verifiers/brew.rb +0 -21
  86. data/lib/sprinkle/verifiers/rpm.rb +0 -21
  87. data/lib/sprinkle/verifiers/users_groups.rb +0 -33
@@ -0,0 +1,40 @@
1
+ module Sprinkle
2
+ module Verifiers
3
+ # = Permission and ownership Verifier
4
+ #
5
+ # Contains a verifier to check the permissions and ownership of a file or directory.
6
+ #
7
+ # == Example Usage
8
+ #
9
+ # verify { has_permission '/etc/apache2/apache2.conf', 0644 }
10
+ #
11
+ # verify { belongs_to_user '/etc/apache2/apache2.conf', 'noop' }
12
+ #
13
+ # verify { belongs_to_user '/etc/apache2/apache2.conf', 1000 }
14
+ #
15
+ module Permission
16
+ Sprinkle::Verify.register(Sprinkle::Verifiers::Permission)
17
+
18
+ def has_permission(path, permission)
19
+ @commands << "find #{path} -maxdepth 0 -perm #{permission} | egrep '.*'"
20
+ end
21
+
22
+ def belongs_to_user(path, user)
23
+ if user.is_a?(Integer)
24
+ @commands << "find #{path} -maxdepth 0 -uid #{user} | egrep '.*'"
25
+ else
26
+ @commands << "find #{path} -maxdepth 0 -user #{user} | egrep '.*'"
27
+ end
28
+ end
29
+
30
+ def belongs_to_group(path, group)
31
+ if group.is_a?(Integer)
32
+ @commands << "find #{path} -maxdepth 0 -gid #{group} | egrep '.*'"
33
+ else
34
+ @commands << "find #{path} -maxdepth 0 -group #{group} | egrep '.*'"
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -20,9 +20,9 @@ module Sprinkle
20
20
  # given, it checks that <tt>symlink</tt> points to <tt>file</tt>
21
21
  def has_symlink(symlink, file = nil)
22
22
  if file.nil?
23
- @commands << "test -L #{symlink}"
23
+ test "-L #{symlink}"
24
24
  else
25
- @commands << "test '#{file}' = `readlink #{symlink}`"
25
+ test "'#{file}' = `readlink #{symlink}`"
26
26
  end
27
27
  end
28
28
  end
@@ -0,0 +1,21 @@
1
+ module Sprinkle
2
+ module Verifiers
3
+ # = Test Verifier
4
+ #
5
+ # Checks that a specific test runs successfully (using the unix test command)
6
+ #
7
+ # == Example Usage
8
+ #
9
+ # verify { test '-f /some_file' }
10
+ #
11
+ module Test
12
+ Sprinkle::Verify.register(Sprinkle::Verifiers::Test)
13
+
14
+ # Checks to make sure a test runs successfully on the remote server
15
+ def test(args)
16
+ @commands << "test #{args}"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -84,16 +84,16 @@ module Sprinkle
84
84
  def process(roles, pre = false) #:nodoc:
85
85
  assert_delivery
86
86
 
87
- description = @description.empty? ? @package.name : @description
87
+ description = @description.empty? ? " (#{@package.name})" : @description
88
88
 
89
89
  if logger.debug?
90
90
  logger.debug "#{@package.name}#{description} verification sequence: #{@commands.join('; ')} for roles: #{roles}\n"
91
91
  end
92
92
 
93
93
  unless Sprinkle::OPTIONS[:testing]
94
- logger.info "#{" " * @options[:padding]}--> Verifying #{description}..."
94
+ logger.debug "#{" " * @options[:padding]}--> Verifying #{description}..."
95
95
 
96
- unless @delivery.process(@package.name, @commands, roles, true)
96
+ unless @delivery.verify(self, roles)
97
97
  # Verification failed, halt sprinkling gracefully.
98
98
  raise Sprinkle::VerificationFailed.new(@package, description)
99
99
  end
@@ -0,0 +1,3 @@
1
+ module Sprinkle
2
+ Version = "0.5"
3
+ end
@@ -0,0 +1 @@
1
+ ...
@@ -146,6 +146,9 @@ describe Sprinkle::Actors::Capistrano do
146
146
  @cap = create_cap do; recipes 'deploy'; end
147
147
  @cap.stub!(:run).and_return
148
148
 
149
+ @package = Package.new(@name) {}
150
+ @installer = Sprinkle::Installers::Transfer.new(@package, "file.txt","/tmp/file.txt")
151
+
149
152
  @testing_errors = false
150
153
  end
151
154
 
@@ -176,7 +179,7 @@ describe Sprinkle::Actors::Capistrano do
176
179
  end
177
180
 
178
181
  after do
179
- @cap.transfer @name, @source, @dest, @roles unless @testing_errors
182
+ @cap.process @package.name, @installer.install_sequence, @roles
180
183
  end
181
184
  end
182
185
 
@@ -221,6 +224,10 @@ describe Sprinkle::Actors::Capistrano do
221
224
 
222
225
  @cap = create_cap do; recipes 'deploy'; end
223
226
  @cap.config.stub!(:upload).and_return
227
+
228
+ @package = Package.new(@name) {}
229
+ @installer = Sprinkle::Installers::Transfer.new(@package, @source, @dest, :recursive => true)
230
+ @cap.instance_variable_set("@installer", @installer)
224
231
  end
225
232
 
226
233
  it 'should call upload with the source and destination via :scp' do
@@ -233,7 +240,8 @@ describe Sprinkle::Actors::Capistrano do
233
240
  end
234
241
 
235
242
  after do
236
- @cap.transfer @name, @source, @dest, @roles
243
+ @installer.instance_variable_set("@delivery", @cap)
244
+ @installer.process(@roles)
237
245
  end
238
246
  end
239
247
 
@@ -246,6 +254,10 @@ describe Sprinkle::Actors::Capistrano do
246
254
 
247
255
  @cap = create_cap do; recipes 'deploy'; end
248
256
  @cap.config.stub!(:upload).and_return
257
+
258
+ @package = Package.new(@name) {}
259
+ @installer = Sprinkle::Installers::Transfer.new(@package, @source,@dest, :recursive => false)
260
+ @cap.instance_variable_set("@installer", @installer)
249
261
  end
250
262
 
251
263
  it 'should call upload with the source and destination via :scp' do
@@ -258,7 +270,8 @@ describe Sprinkle::Actors::Capistrano do
258
270
  end
259
271
 
260
272
  after do
261
- @cap.transfer @name, @source, @dest, @roles, false
273
+ @installer.instance_variable_set("@delivery", @cap)
274
+ @installer.process(@roles)
262
275
  end
263
276
  end
264
277
 
@@ -4,26 +4,44 @@ describe Sprinkle::Actors::Local do
4
4
 
5
5
  before do
6
6
  @local = Sprinkle::Actors::Local.new
7
+
8
+ @package = Package.new("super") {}
7
9
  end
8
10
 
9
- describe 'when processing commands' do
11
+ describe 'when installing' do
10
12
 
11
13
  before do
14
+ @installer = Sprinkle::Installers::Runner.new(@package, "echo hi")
12
15
  @commands = %w( op1 op2 )
13
16
  @roles = %w( app )
14
17
  @name = 'name'
15
-
16
- @local.stub!(:system).and_return
18
+
19
+ @local.stub!(:run_command).and_return(0)
17
20
  end
18
21
 
19
22
  it 'should run the commands on the local system' do
20
- @local.should_receive(:system).twice.and_return
23
+ @local.should_receive(:run_command).once.and_return(0)
24
+ @local.install @installer, @roles
21
25
  end
26
+
27
+ end
28
+
29
+ describe 'when verifying' do
22
30
 
23
- after do
24
- @local.process @name, @commands, @roles
31
+ before do
32
+ @verifier = Sprinkle::Verify::new(@package) {}
33
+ @verifier.commands += ["test","test"]
34
+ @roles = %w( app )
35
+ @name = 'name'
36
+
37
+ @local.stub!(:run_command).and_return(0)
25
38
  end
26
39
 
40
+ it 'should run the commands on the local system' do
41
+ @local.should_receive(:run_command).twice.and_return
42
+ @local.verify @verifier, @roles
43
+ end
44
+
27
45
  end
28
46
 
29
47
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sprinkle::Actors::SSH do
4
+ describe 'process' do
5
+ before do
6
+ subject.stub(:gateway_defined?).and_return(false)
7
+ end
8
+
9
+ subject do
10
+ Sprinkle::Actors::SSH.new do
11
+ role :app, "booger.com"
12
+ end
13
+ end
14
+
15
+ let(:commands) { %w[one two three] }
16
+ let(:roles) { %w[app] }
17
+
18
+ describe 'when use_sudo is true' do
19
+ before do
20
+ subject.use_sudo(true)
21
+ end
22
+
23
+ it 'prepends "sudo" to each command' do
24
+ subject.send(:prepare_commands,commands).should == ['sudo one', 'sudo two', 'sudo three']
25
+ end
26
+ end
27
+
28
+ describe 'when use_sudo is false' do
29
+ before do
30
+ subject.use_sudo(false)
31
+ end
32
+
33
+ it 'does not prepend "sudo" to each command' do
34
+ subject.send(:prepare_commands,commands).should == commands
35
+ end
36
+ end
37
+ end
38
+ end
@@ -3,11 +3,17 @@ require File.expand_path("../../spec_helper", File.dirname(__FILE__))
3
3
  describe Sprinkle::Installers::Apt do
4
4
 
5
5
  before do
6
- @package = mock(Sprinkle::Package, :name => 'package')
6
+ @package = create_pkg "name", :use_sudo => false
7
+ end
8
+
9
+ def create_pkg(name="name", opts={})
10
+ @package = Sprinkle::Package::Package.new(name) {}
11
+ @package.use_sudo opts[:use_sudo]
12
+ @package
7
13
  end
8
14
 
9
15
  def create_apt(*debs, &block)
10
- Sprinkle::Installers::Apt.new(@package, *debs, &block)
16
+ installer=@package.apt *debs, &block
11
17
  end
12
18
 
13
19
  describe 'when created' do
@@ -28,6 +34,7 @@ describe Sprinkle::Installers::Apt do
28
34
  end
29
35
 
30
36
  end
37
+
31
38
 
32
39
  describe 'during installation' do
33
40
 
@@ -38,6 +45,20 @@ describe Sprinkle::Installers::Apt do
38
45
  end
39
46
  @install_commands = @installer.send :install_commands
40
47
  end
48
+
49
+ it 'should use sudo if package specifies' do
50
+ @package = create_pkg "name", :use_sudo => true
51
+ @installer = create_apt 'ruby'
52
+ @install_commands = @installer.send :install_commands
53
+ @install_commands.should =~ /sudo apt-get/
54
+ end
55
+
56
+ it 'should use sudo if installer specifies' do
57
+ @package = create_pkg "name", :use_sudo => false
58
+ @installer = create_apt 'ruby', :sudo => true
59
+ @install_commands = @installer.send :install_commands
60
+ @install_commands.should =~ /sudo apt-get/
61
+ end
41
62
 
42
63
  it 'should invoke the apt installer for all specified packages' do
43
64
  @install_commands.should =~ /apt-get --force-yes -qyu install ruby/
@@ -3,25 +3,23 @@ require File.expand_path("../../spec_helper", File.dirname(__FILE__))
3
3
  describe Sprinkle::Installers::Binary do
4
4
  include Sprinkle::Deployment
5
5
 
6
- def create_context
7
- binary = 'http://www.example.com/archive.tar.gz'
8
-
6
+ def create_context(source = 'http://www.example.com/archive.tar.gz')
9
7
  deployment = deployment do
10
8
  delivery :capistrano
11
- binary "http://www.example.com/archive.tar.gz" do
9
+ binary source do
12
10
  prefix '/prefix/directory'
13
11
  archives '/archives/directory'
14
12
  end
15
13
  end
16
14
 
17
- installer = create_binary binary do
15
+ installer = create_binary source do
18
16
  prefix '/prefix/directory'
19
17
  archives '/archives/directory'
20
18
  end
21
19
 
22
20
  installer.defaults(@deployment)
23
-
24
- [binary, deployment, installer]
21
+
22
+ [source, deployment, installer]
25
23
  end
26
24
 
27
25
  def create_binary(binary, version = nil, &block)
@@ -33,7 +31,7 @@ describe Sprinkle::Installers::Binary do
33
31
  before do
34
32
  @binary, @deployment, @installer = create_context
35
33
  end
36
-
34
+
37
35
  it "should return mkdir command to create the prefix directory" do
38
36
  @installer.send(:prepare_commands)[0].should == 'mkdir -p /prefix/directory'
39
37
  end
@@ -41,24 +39,34 @@ describe Sprinkle::Installers::Binary do
41
39
  @installer.send(:prepare_commands)[1].should == 'mkdir -p /archives/directory'
42
40
  end
43
41
  end
44
-
45
-
42
+
43
+
46
44
  describe "binary#install_commands" do
47
45
  before do
48
46
  @binary, @deployment, @installer = create_context
49
47
  end
50
-
48
+
51
49
  it "should return a commands to place the binary in the correct archive directory" do
52
50
  @installer.send(:install_commands)[0].should =~ /--directory-prefix=\/archives\/directory/
53
51
  end
54
-
52
+
55
53
  it "should return a command to extract to the correct prefix folder" do
56
54
  @installer.send(:install_commands)[1].should =~ /cd \/prefix\/directory/
57
55
  end
58
56
 
59
57
  it "should return a command to extract the right file in the right directory" do
60
- @installer.send(:install_commands)[1].should =~ / \/archives\/directory\/archive.tar.gz/
58
+ @installer.send(:install_commands)[1].should =~ / '\/archives\/directory\/archive.tar.gz'/
61
59
  end
62
60
  end
63
-
61
+
62
+ describe "when source contains spaces (%20's) in path" do
63
+ before do
64
+ _, _, @installer = create_context('http://c758482.r82.cf2.rackcdn.com/Sublime%20Text%202.0.1%20x64.tar.bz2')
65
+ end
66
+
67
+ it "should correctly interpret the archive filename as it gets extracted downloaded to file system" do
68
+ @installer.send(:install_commands)[1].should =~ / '\/archives\/directory\/Sublime Text 2.0.1 x64.tar.bz2'/
69
+ end
70
+ end
71
+
64
72
  end
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../../spec_helper'
3
3
  describe Sprinkle::Installers::Brew do
4
4
 
5
5
  before do
6
- @formula = mock(Sprinkle::Package, :name => 'formula')
6
+ @formula = mock(Sprinkle::Package, :name => 'formula', :sudo? => false)
7
7
  end
8
8
 
9
9
  def create_brew(*formulas, &block)
@@ -14,17 +14,17 @@ describe Sprinkle::Installers::Brew do
14
14
 
15
15
  it 'should accept a single package to install' do
16
16
  @installer = create_brew 'ruby'
17
- @installer.formulas.should == [ 'ruby' ]
17
+ @installer.packages.should == [ 'ruby' ]
18
18
  end
19
19
 
20
20
  it 'should accept an array of packages to install' do
21
21
  @installer = create_brew %w( gcc gdb g++ )
22
- @installer.formulas.should == ['gcc', 'gdb', 'g++']
22
+ @installer.packages.should == ['gcc', 'gdb', 'g++']
23
23
  end
24
24
 
25
25
  it 'should remove options from packages list' do
26
26
  @installer = create_brew 'ruby'
27
- @installer.formulas.should == [ 'ruby' ]
27
+ @installer.packages.should == [ 'ruby' ]
28
28
  end
29
29
 
30
30
  end
@@ -7,7 +7,7 @@ describe Sprinkle::Installers::Installer do
7
7
  @package = mock(Sprinkle::Package, :name => 'package')
8
8
  @empty = Proc.new { }
9
9
  @sequence = ['op1', 'op2']
10
- @delivery = mock(Sprinkle::Deployment, :process => true)
10
+ @delivery = mock(Sprinkle::Deployment, :process => true, :install => true)
11
11
  @installer = create_installer
12
12
  @installer.delivery = @delivery
13
13
  @roles = []
@@ -61,9 +61,9 @@ describe Sprinkle::Installers::Installer do
61
61
 
62
62
  describe 'during installation' do
63
63
 
64
- it 'should request the install sequence from the concrete class' do
65
- @installer.should_receive(:install_sequence).and_return(@sequence)
66
- end
64
+ # it 'should request the install sequence from the concrete class' do
65
+ # @installer.should_receive(:install_sequence).and_return(@sequence)
66
+ # end
67
67
 
68
68
  describe 'when testing' do
69
69
 
@@ -81,10 +81,39 @@ describe Sprinkle::Installers::Installer do
81
81
  end
82
82
 
83
83
  end
84
+
85
+ describe "with sudo from package level" do
86
+ before do
87
+ @installer.package = mock(Sprinkle::Package, :name => 'package', :sudo? => true)
88
+ end
89
+
90
+ it "should know it uses sudo" do
91
+ @installer.sudo?.should == true
92
+ end
93
+
94
+ it "should offer up the sudo command" do
95
+ @installer.sudo_cmd.should =~ /sudo /
96
+ end
97
+ end
98
+
99
+ describe "with sudo" do
100
+ before do
101
+ @installer = Sprinkle::Installers::Installer.new @package, :sudo => true
102
+ @installer.delivery = @delivery
103
+ end
104
+
105
+ it "should know it uses sudo" do
106
+ @installer.sudo?.should == true
107
+ end
108
+
109
+ it "should offer up the sudo command" do
110
+ @installer.sudo_cmd.should =~ /sudo /
111
+ end
112
+ end
84
113
 
85
114
  describe 'when in production' do
86
115
  it 'should invoke the delivery mechanism to process the install sequence' do
87
- @delivery.should_receive(:process).with(@package.name, @sequence, @roles)
116
+ @delivery.should_receive(:install).with(@installer, @roles, :per_host => false)
88
117
  end
89
118
  end
90
119
 
@@ -130,12 +159,12 @@ describe Sprinkle::Installers::Installer do
130
159
  @installer.send(:install_sequence).should == [ "a", "b", "c", 'installer' ]
131
160
  end
132
161
  end
133
- describe "blocks as commands" do
162
+ describe "arrays as commands" do
134
163
  before(:each) do
135
164
  @array = ["a", "b"]
136
165
  @installer = create_installer_with_pre_command(@array)
137
166
  end
138
- it "should be able to store a block if it's the pre command" do
167
+ it "should be able to store an array if it's the pre command" do
139
168
  @installer.send(:install_sequence).should == [ @array, 'installer' ].flatten
140
169
  end
141
170
  end