sprinkle 0.2.6 → 0.3.0

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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ pkg
2
+ .DS_Store
3
+ .idea
4
+ .*.swp
5
+ sprinkle.gemspec
data/CREDITS CHANGED
@@ -25,5 +25,9 @@ Justin Pease (http://jit.nuance9.com)
25
25
  Tobias Lütke (http://blog.leetsoft.com)
26
26
  Josh Reynolds (http://github.com/jreynolds)
27
27
  Jan Ulbrich (http://www.ulbrich.net)
28
+ Chris Gaffney (http://github.com/gaffneyc)
29
+ Maxmpz (http://github.com/maxmpz)
30
+ Geoff Garside (http://geoffgarside.co.uk/)
31
+ Oliver Kiessler (http://inceedo.com)
28
32
 
29
33
  The transfer installer contains a piece of exception reporting code copied from the Chef library (http://wiki.opscode.com/display/chef/Home)
data/Rakefile CHANGED
@@ -1,4 +1,50 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
3
-
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "sprinkle"
8
+ gem.summary = "Ruby DSL based software provisioning tool"
9
+ gem.description = "Ruby DSL based software provisioning tool"
10
+ gem.email = "crafterm@redartisan.com"
11
+ gem.rubyforge_project = 'sprinkle'
12
+ gem.homepage = "http://github.com/crafterm/sprinkle"
13
+ gem.authors = ["Marcus Crafter"]
14
+ gem.add_development_dependency "rspec", ">= 1.2.9"
15
+ gem.add_dependency('activesupport', '>= 2.0.2')
16
+ gem.add_dependency('highline', '>= 1.4.0')
17
+ gem.add_dependency('capistrano', '>= 2.5.5')
18
+
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :spec => :check_dependencies
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "sprinkle #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/TODO ADDED
@@ -0,0 +1,56 @@
1
+ Version 0.1 plan
2
+ ================
3
+
4
+ INSTALLER
5
+ * Fix up apt so that we can handle it if it asks questions, or fail? Check with Ben
6
+ * Support alternate gem package sources - DONE
7
+ * MD5/SHA1 checking on the installation files?
8
+
9
+ MISC
10
+ * Growl support
11
+ * Do a merb example
12
+ * Fix up printing of output so that its nice and a bit more like ports - DONE
13
+ * print ports style output for stages (installing, configuring, etc...)
14
+ * Add an option to print the hierarchy tree of packages to be installed only - DONE
15
+ * BlankSlate - active support has one
16
+ * CREDITS file - DONE
17
+ * Get #!/usr/bin/env sprinkle working - DONE
18
+
19
+ OPERATING SYSTEM
20
+ * OS abstraction
21
+ * build essential on Ubuntu only for example
22
+
23
+ TESTING
24
+ * Test on a base system Ubuntu system - DONE
25
+ * Multiple runs, check system that's partially installed - DONE
26
+ * Resuming downloads with wget ok - DONE
27
+
28
+ ERRORS
29
+ * Need to think about handling errors nicely
30
+ * Recovering from an error, and or successive runs of sprinkle
31
+ * store installed state on the remote server so we can skip installed packages?
32
+ * what about self healing things later? need to think about it
33
+
34
+ DOCUMENTATION
35
+ * Document the code somewhat, at least review that its all ok
36
+ * Wiki
37
+ * Home page somewhere? point to github
38
+ * Blog post
39
+ * Screencast - use that cool screenflow tool?
40
+
41
+ Post Version 0.1 plan
42
+ =====================
43
+
44
+ CONFIGURATION
45
+ * Think about it - talk to Lincoln and Ben
46
+ * Use cap 2.3 send/download file helpers, might be useful somehow for transporting config files
47
+
48
+ ACTOR
49
+ * Investigate a pure net:ssh/gateway delivery mechanism, ie. without cap?
50
+ * Generate a cap task file as output? not sure if people would be interested in this?
51
+ * use ruby2ruby to generate the file, nice :)
52
+
53
+ MISC
54
+ * Slicehost API support for creating a slice on the way
55
+ * active resource
56
+ * SSH keys, have to deploy them somehow?
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
data/bin/sprinkle CHANGED
@@ -16,6 +16,10 @@ require 'optparse'
16
16
  OPTIONS = {}
17
17
  MANDATORY_OPTIONS = %w( path )
18
18
 
19
+ ARGV.each do |arg|
20
+ ENV[$1] = $2 if arg =~ /^(\w+)=(.*)$/
21
+ end
22
+
19
23
  parser = OptionParser.new do |opts|
20
24
  opts.banner = <<BANNER
21
25
  Sprinkle
@@ -1,2 +1,2 @@
1
1
  set :user, 'root'
2
- role :app, 'yourhost.com', :primary => true
2
+ role :app, 'sprinkle.redartisan.com', :primary => true
@@ -22,7 +22,11 @@ module Sprinkle
22
22
  def user(user)
23
23
  @options[:user] = user
24
24
  end
25
-
25
+
26
+ def password(password)
27
+ @options[:password] = password
28
+ end
29
+
26
30
  def process(name, commands, roles, suppress_and_return_failures = false)
27
31
  return process_with_gateway(name, commands, roles) if gateway_defined?
28
32
  process_direct(name, commands, roles)
@@ -71,7 +75,7 @@ module Sprinkle
71
75
  execute_on_connection(commands, ssh)
72
76
  end
73
77
  else # direct SSH connection
74
- Net::SSH.start(host, @options[:user]) do |ssh|
78
+ Net::SSH.start(host, @options[:user], :password => @options[:password]) do |ssh|
75
79
  execute_on_connection(commands, ssh)
76
80
  end
77
81
  end
@@ -0,0 +1,46 @@
1
+ module Sprinkle
2
+ module Installers
3
+ # = Binary Installer
4
+ #
5
+ # binary "http://some.url.com/archive.tar.gz" do
6
+ # prefix "/home/user/local"
7
+ # archives "/home/user/sources"
8
+ # end
9
+ #
10
+ class Binary < Installer
11
+ def initialize(parent, binary_archive, options = {}, &block) #:nodoc:
12
+ @binary_archive = binary_archive
13
+ @options = options
14
+ super parent, options, &block
15
+ end
16
+
17
+ def prepare_commands #:nodoc:
18
+ raise 'No installation area defined' unless @options[:prefix]
19
+ raise 'No archive download area defined' unless @options[:archives]
20
+
21
+ [ "mkdir -p #{@options[:prefix]}",
22
+ "mkdir -p #{@options[:archives]}" ]
23
+ end
24
+
25
+ def install_commands #:nodoc:
26
+ commands = [ "bash -c 'wget -cq --directory-prefix=#{@options[:archives]} #{@binary_archive}'" ]
27
+ commands << "bash -c 'cd #{@options[:prefix]} && #{extract_command} #{@options[:archives]}/#{@binary_archive.split("/").last}'"
28
+ end
29
+
30
+ def extract_command(archive_name = @binary_archive.split("/").last)
31
+ case archive_name
32
+ when /(tar.gz)|(tgz)$/
33
+ 'tar xzf'
34
+ when /(tar.bz2)|(tb2)$/
35
+ 'tar xjf'
36
+ when /tar$/
37
+ 'tar xf'
38
+ when /zip$/
39
+ 'unzip'
40
+ else
41
+ raise "Unknown binary archive format: #{archive_name}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,36 @@
1
+ module Sprinkle
2
+ module Installers
3
+ # = FreeBSD Portinstall Installer
4
+ #
5
+ # The Portinstall installer installs FreeBSD ports.
6
+ # It uses the ports-mgmt/portupgrade port to install.
7
+ # Before usage, the ports system must be installed and
8
+ # read on the target operating system.
9
+ # It is recommended to use `portsnap fetch extract` to
10
+ # install the ports system.
11
+ #
12
+ # == Example Usage
13
+ #
14
+ # Installing the magic_beans port.
15
+ #
16
+ # package :magic_beans do
17
+ # freebsd_portinstall 'magic/magic_beans'
18
+ # end
19
+ #
20
+ class FreebsdPortinstall < Installer
21
+ attr_accessor :port #:nodoc:
22
+
23
+ def initialize(parent, port, &block) #:nodoc:
24
+ super parent, &block
25
+ @port = port
26
+ end
27
+
28
+ protected
29
+
30
+ def install_commands #:nodoc:
31
+ "portinstall --batch #{@port}"
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -111,7 +111,8 @@ module Sprinkle
111
111
 
112
112
  extras = {
113
113
  :enable => '--enable', :disable => '--disable',
114
- :with => '--with', :without => '--without'
114
+ :with => '--with', :without => '--without',
115
+ :option => '-',
115
116
  }
116
117
 
117
118
  extras.inject(command) { |m, (k, v)| m << create_options(k, v) if options[k]; m }
@@ -178,7 +179,7 @@ module Sprinkle
178
179
  end
179
180
 
180
181
  def base_dir #:nodoc:
181
- if archive_name.split('/').last =~ /(.*)\.(tar\.gz|tgz|tar\.bz2|tar|tb2)/
182
+ if archive_name.split('/').last =~ /(.*)\.(tar\.gz|tgz|tar\.bz2|tar|tb2|zip)/
182
183
  return $1
183
184
  end
184
185
  raise "Unknown base path for source archive: #{@source}, please update code knowledge"
@@ -107,7 +107,7 @@ module Sprinkle
107
107
 
108
108
  class Package #:nodoc:
109
109
  include ArbitraryOptions
110
- attr_accessor :name, :provides, :installer, :dependencies, :recommends, :verifications
110
+ attr_accessor :name, :provides, :installers, :dependencies, :recommends, :verifications
111
111
 
112
112
  def initialize(name, metadata = {}, &block)
113
113
  raise 'No package name supplied' unless name
@@ -118,69 +118,74 @@ module Sprinkle
118
118
  @recommends = []
119
119
  @optional = []
120
120
  @verifications = []
121
+ @installers = []
121
122
  self.instance_eval &block
122
123
  end
123
124
 
124
125
  def freebsd_pkg(*names, &block)
125
- @installer = Sprinkle::Installers::FreebsdPkg.new(self, *names, &block)
126
+ @installers << Sprinkle::Installers::FreebsdPkg.new(self, *names, &block)
126
127
  end
127
128
 
128
129
  def openbsd_pkg(*names, &block)
129
- @installer = Sprinkle::Installers::OpenbsdPkg.new(self, *names, &block)
130
+ @installers << Sprinkle::Installers::OpenbsdPkg.new(self, *names, &block)
130
131
  end
131
132
 
132
133
  def opensolaris_pkg(*names, &block)
133
- @installer = Sprinkle::Installers::OpensolarisPkg.new(self, *names, &block)
134
+ @installers << Sprinkle::Installers::OpensolarisPkg.new(self, *names, &block)
134
135
  end
135
136
 
136
137
  def bsd_port(port, &block)
137
- @installer = Sprinkle::Installers::BsdPort.new(self, port, &block)
138
+ @installers << Sprinkle::Installers::BsdPort.new(self, port, &block)
138
139
  end
139
140
 
140
141
  def mac_port(port, &block)
141
- @installer = Sprinkle::Installers::MacPort.new(self, port, &block)
142
+ @installers << Sprinkle::Installers::MacPort.new(self, port, &block)
142
143
  end
143
144
 
144
145
  def apt(*names, &block)
145
- @installer = Sprinkle::Installers::Apt.new(self, *names, &block)
146
+ @installers << Sprinkle::Installers::Apt.new(self, *names, &block)
146
147
  end
147
148
 
148
149
  def deb(*names, &block)
149
- @installer = Sprinkle::Installers::Deb.new(self, *names, &block)
150
+ @installers << Sprinkle::Installers::Deb.new(self, *names, &block)
150
151
  end
151
152
 
152
153
  def rpm(*names, &block)
153
- @installer = Sprinkle::Installers::Rpm.new(self, *names, &block)
154
+ @installers << Sprinkle::Installers::Rpm.new(self, *names, &block)
154
155
  end
155
156
 
156
157
  def yum(*names, &block)
157
- @installer = Sprinkle::Installers::Yum.new(self, *names, &block)
158
+ @installers << Sprinkle::Installers::Yum.new(self, *names, &block)
158
159
  end
159
160
 
160
161
  def gem(name, options = {}, &block)
161
162
  @recommends << :rubygems
162
- @installer = Sprinkle::Installers::Gem.new(self, name, options, &block)
163
+ @installers << Sprinkle::Installers::Gem.new(self, name, options, &block)
163
164
  end
164
165
 
165
166
  def source(source, options = {}, &block)
166
167
  @recommends << :build_essential # Ubuntu/Debian
167
- @installer = Sprinkle::Installers::Source.new(self, source, options, &block)
168
+ @installers << Sprinkle::Installers::Source.new(self, source, options, &block)
169
+ end
170
+
171
+ def binary(source, options = {}, &block)
172
+ @installers << Sprinkle::Installers::Binary.new(self, source, options, &block)
168
173
  end
169
174
 
170
175
  def rake(name, options = {}, &block)
171
- @installer = Sprinkle::Installers::Rake.new(self, name, options, &block)
176
+ @installers << Sprinkle::Installers::Rake.new(self, name, options, &block)
172
177
  end
173
178
 
174
179
  def noop(&block)
175
- @installer = Sprinkle::Installers::Noop.new(self, name, options, &block)
180
+ @installers << Sprinkle::Installers::Noop.new(self, name, options, &block)
176
181
  end
177
182
 
178
183
  def push_text(text, path, options = {}, &block)
179
- @installer = Sprinkle::Installers::PushText.new(self, text, path, options, &block)
184
+ @installers << Sprinkle::Installers::PushText.new(self, text, path, options, &block)
180
185
  end
181
186
 
182
- def transfer(source, destination, options = {}, &block)
183
- @installer = Sprinkle::Installers::Transfer.new(self, source, destination, options, &block)
187
+ def transfer(source, destination, options = {}, &block)
188
+ @installers << Sprinkle::Installers::Transfer.new(self, source, destination, options, &block)
184
189
  end
185
190
 
186
191
  def verify(description = '', &block)
@@ -203,8 +208,10 @@ module Sprinkle
203
208
  end
204
209
  end
205
210
 
206
- @installer.defaults(deployment)
207
- @installer.process(roles)
211
+ @installers.each do |installer|
212
+ installer.defaults(deployment)
213
+ installer.process(roles)
214
+ end
208
215
 
209
216
  process_verifications(deployment, roles)
210
217
  end
@@ -291,7 +298,7 @@ module Sprinkle
291
298
  end
292
299
 
293
300
  def meta_package?
294
- @installer == nil
301
+ @installers.blank?
295
302
  end
296
303
  end
297
304
  end
@@ -0,0 +1,21 @@
1
+ module Sprinkle
2
+ module Verifiers
3
+ # = RPM Verifier
4
+ #
5
+ # Contains a verifier to check the existance of an RPM package.
6
+ #
7
+ # == Example Usage
8
+ #
9
+ # verify { has_rpm 'ntp' }
10
+ #
11
+ module Rpm
12
+ Sprinkle::Verify.register(Sprinkle::Verifiers::Rpm)
13
+
14
+ # Checks to make sure <tt>package</tt> exists in the rpm installed database on the remote server.
15
+ def has_rpm(package)
16
+ @commands << "rpm -qa | grep #{package}"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
data/script/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/sprinkle.rb'}"
7
+ puts "Loading sprinkle gem"
8
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Sprinkle::Installers::FreebsdPortinstall do
4
+
5
+ before do
6
+ @package = mock(Sprinkle::Package, :name => 'package')
7
+ end
8
+
9
+ def create_port(ports, &block)
10
+ Sprinkle::Installers::FreebsdPortinstall.new(@package, ports, &block)
11
+ end
12
+
13
+ describe 'when created' do
14
+
15
+ it 'should accept a single package to install' do
16
+ @installer = create_port 'lang/ruby'
17
+ @installer.port.should == 'lang/ruby'
18
+ end
19
+
20
+ end
21
+
22
+ describe 'during installation' do
23
+
24
+ before do
25
+ @installer = create_port 'lang/ruby' do
26
+ pre :install, 'op1'
27
+ post :install, 'op2'
28
+ end
29
+ @install_commands = @installer.send :install_commands
30
+ end
31
+
32
+ it 'should invoke the port installer for all specified packages' do
33
+ @install_commands.should =~ /portinstall --batch lang\/ruby/
34
+ end
35
+
36
+ it 'should automatically insert pre/post commands for the specified package' do
37
+ @installer.send(:install_sequence).should == [ 'op1', 'portinstall --batch lang/ruby', 'op2' ]
38
+ end
39
+
40
+ end
41
+
42
+ end