sprinkle 0.4.2 → 0.5.0.rc1

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