sprinkle 0.2.6 → 0.3.0

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