auser-sprinkle 0.1.5

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 (69) hide show
  1. data/CREDITS +16 -0
  2. data/History.txt +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/Manifest.txt +67 -0
  5. data/README.rdoc +224 -0
  6. data/Rakefile +4 -0
  7. data/bin/sprinkle +86 -0
  8. data/config/hoe.rb +70 -0
  9. data/config/requirements.rb +17 -0
  10. data/examples/merb/deploy.rb +5 -0
  11. data/examples/rails/README +15 -0
  12. data/examples/rails/deploy.rb +2 -0
  13. data/examples/rails/packages/database.rb +9 -0
  14. data/examples/rails/packages/essential.rb +6 -0
  15. data/examples/rails/packages/rails.rb +28 -0
  16. data/examples/rails/packages/search.rb +11 -0
  17. data/examples/rails/packages/server.rb +28 -0
  18. data/examples/rails/rails.rb +71 -0
  19. data/examples/sprinkle/sprinkle.rb +38 -0
  20. data/lib/sprinkle.rb +28 -0
  21. data/lib/sprinkle/actors/capistrano.rb +89 -0
  22. data/lib/sprinkle/actors/vlad.rb +39 -0
  23. data/lib/sprinkle/configurable.rb +24 -0
  24. data/lib/sprinkle/deployment.rb +33 -0
  25. data/lib/sprinkle/extensions/arbitrary_options.rb +10 -0
  26. data/lib/sprinkle/extensions/array.rb +7 -0
  27. data/lib/sprinkle/extensions/blank_slate.rb +5 -0
  28. data/lib/sprinkle/extensions/dsl_accessor.rb +15 -0
  29. data/lib/sprinkle/extensions/string.rb +10 -0
  30. data/lib/sprinkle/extensions/symbol.rb +7 -0
  31. data/lib/sprinkle/installers/apt.rb +25 -0
  32. data/lib/sprinkle/installers/gem.rb +33 -0
  33. data/lib/sprinkle/installers/installer.rb +74 -0
  34. data/lib/sprinkle/installers/rake.rb +17 -0
  35. data/lib/sprinkle/installers/rpm.rb +20 -0
  36. data/lib/sprinkle/installers/source.rb +121 -0
  37. data/lib/sprinkle/package.rb +127 -0
  38. data/lib/sprinkle/policy.rb +85 -0
  39. data/lib/sprinkle/script.rb +13 -0
  40. data/lib/sprinkle/verifiers/directory.rb +11 -0
  41. data/lib/sprinkle/verifiers/executable.rb +17 -0
  42. data/lib/sprinkle/verifiers/file.rb +11 -0
  43. data/lib/sprinkle/verifiers/symlink.rb +15 -0
  44. data/lib/sprinkle/verify.rb +55 -0
  45. data/lib/sprinkle/version.rb +9 -0
  46. data/script/destroy +14 -0
  47. data/script/generate +14 -0
  48. data/spec/spec.opts +1 -0
  49. data/spec/spec_helper.rb +17 -0
  50. data/spec/sprinkle/actors/capistrano_spec.rb +170 -0
  51. data/spec/sprinkle/configurable_spec.rb +46 -0
  52. data/spec/sprinkle/deployment_spec.rb +80 -0
  53. data/spec/sprinkle/extensions/array_spec.rb +19 -0
  54. data/spec/sprinkle/extensions/string_spec.rb +21 -0
  55. data/spec/sprinkle/installers/apt_spec.rb +74 -0
  56. data/spec/sprinkle/installers/gem_spec.rb +75 -0
  57. data/spec/sprinkle/installers/installer_spec.rb +151 -0
  58. data/spec/sprinkle/installers/rpm_spec.rb +50 -0
  59. data/spec/sprinkle/installers/source_spec.rb +331 -0
  60. data/spec/sprinkle/package_spec.rb +422 -0
  61. data/spec/sprinkle/policy_spec.rb +126 -0
  62. data/spec/sprinkle/script_spec.rb +51 -0
  63. data/spec/sprinkle/sprinkle_spec.rb +25 -0
  64. data/spec/sprinkle/verify_spec.rb +137 -0
  65. data/sprinkle.gemspec +43 -0
  66. data/tasks/deployment.rake +34 -0
  67. data/tasks/environment.rake +7 -0
  68. data/tasks/rspec.rake +21 -0
  69. metadata +158 -0
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'sprinkle'
@@ -0,0 +1,5 @@
1
+ set :application, "application"
2
+
3
+ role :app, "yourhost.com"
4
+ role :web, "yourhost.com"
5
+ role :db, "yourhost.com", :primary => true
@@ -0,0 +1,15 @@
1
+ = Example Rails Spinkle Deployment Script
2
+
3
+ The following example shows how you can provision Rails and associated packages onto a remote server (or set of servers).
4
+
5
+ == Usage:
6
+
7
+ $> sprinkle -s rails.rb
8
+
9
+ or in test mode:
10
+
11
+ $> sprinkle -t -s rails.rb
12
+
13
+ == Information
14
+
15
+ For more information, please see: http://github.com/crafterm/sprinkle/tree/master/README.txt
@@ -0,0 +1,2 @@
1
+ set :user, 'root'
2
+ role :app, 'yourhost.com', :primary => true
@@ -0,0 +1,9 @@
1
+ package :mysql, :provides => :database do
2
+ description 'MySQL Database'
3
+ apt %w( mysql-server mysql-client )
4
+ end
5
+
6
+ package :mysql_driver do
7
+ description 'Ruby MySQL database driver'
8
+ gem 'mysql'
9
+ end
@@ -0,0 +1,6 @@
1
+ ## Special package, anything that defines a 'source' package means build-essential should be installed for Ubuntu
2
+
3
+ package :build_essential do
4
+ description 'Build tools'
5
+ apt 'build-essential'
6
+ end
@@ -0,0 +1,28 @@
1
+ ## Defines available packages
2
+
3
+ package :ruby do
4
+ description 'Ruby Virtual Machine'
5
+ version '1.8.6'
6
+ source "ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-#{version}-p111.tar.gz" # implicit :style => :gnu
7
+ requires :ruby_dependencies
8
+ end
9
+
10
+ package :ruby_dependencies do
11
+ description 'Ruby Virtual Machine Build Dependencies'
12
+ apt %w( bison zlib1g-dev libssl-dev libreadline5-dev libncurses5-dev file )
13
+ end
14
+
15
+ package :rubygems do
16
+ description 'Ruby Gems Package Management System'
17
+ version '1.2.0'
18
+ source "http://rubyforge.org/frs/download.php/38646/rubygems-#{version}.tgz" do
19
+ custom_install 'ruby setup.rb'
20
+ end
21
+ requires :ruby
22
+ end
23
+
24
+ package :rails do
25
+ description 'Ruby on Rails'
26
+ gem 'rails'
27
+ version '2.1.0'
28
+ end
@@ -0,0 +1,11 @@
1
+ package :sphinx, :provides => :search do
2
+ description 'MySQL full text search engine'
3
+ version '0.9.8-rc2'
4
+ source "http://www.sphinxsearch.com/downloads/sphinx-#{version}.tar.gz"
5
+ requires :mysql_dev
6
+ end
7
+
8
+ package :mysql_dev do
9
+ description 'MySQL Database development package'
10
+ apt %w( libmysqlclient15-dev )
11
+ end
@@ -0,0 +1,28 @@
1
+ package :mongrel do
2
+ description 'Mongrel Application Server'
3
+ gem 'mongrel'
4
+ version '1.1.4'
5
+ end
6
+
7
+ package :mongrel_cluster, :provides => :appserver do
8
+ description 'Cluster Management for Mongrel'
9
+ gem 'mongrel_cluster'
10
+ version '1.0.5'
11
+ requires :mongrel
12
+ end
13
+
14
+ package :apache, :provides => :webserver do
15
+ description 'Apache 2 HTTP Server'
16
+ version '2.2.9'
17
+ source "http://www.apache.org/dist/httpd/httpd-#{version}.tar.bz2" do
18
+ enable %w( mods-shared=all proxy proxy-balancer proxy-http rewrite cache headers ssl deflate so )
19
+ prefix "/opt/local/apache2-#{version}"
20
+ post :install, 'install -m 755 support/apachectl /etc/init.d/apache2', 'update-rc.d -f apache2 defaults'
21
+ end
22
+ requires :apache_dependencies
23
+ end
24
+
25
+ package :apache_dependencies do
26
+ description 'Apache 2 HTTP Server Build Dependencies'
27
+ apt %w( openssl libtool mawk zlib1g-dev libssl-dev )
28
+ end
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env sprinkle -s
2
+
3
+ # Annotated Example Sprinkle Rails deployment script
4
+ #
5
+ # This is an example Sprinkle script configured to install Rails from gems, Apache, Ruby and
6
+ # Sphinx from source, and mysql from apt on an Ubuntu system.
7
+ #
8
+ # Installation is configured to run via capistrano (and an accompanying deploy.rb recipe script).
9
+ # Source based packages are downloaded and built into /usr/local on the remote system.
10
+ #
11
+ # A sprinkle script is separated into 3 different sections. Packages, policies and deployment:
12
+
13
+
14
+ # Packages (separate files for brevity)
15
+ #
16
+ # Defines the world of packages as we know it. Each package has a name and
17
+ # set of metadata including its installer type (eg. apt, source, gem, etc). Packages can have
18
+ # relationships to each other via dependencies.
19
+
20
+ require 'packages/essential'
21
+ require 'packages/rails'
22
+ require 'packages/database'
23
+ require 'packages/server'
24
+ require 'packages/search'
25
+
26
+
27
+ # Policies
28
+ #
29
+ # Names a group of packages (optionally with versions) that apply to a particular set of roles:
30
+ #
31
+ # Associates the rails policy to the application servers. Contains rails, and surrounding
32
+ # packages. Note, appserver, database, webserver and search are all virtual packages defined above.
33
+ # If there's only one implementation of a virtual package, it's selected automatically, otherwise
34
+ # the user is requested to select which one to use.
35
+
36
+ policy :rails, :roles => :app do
37
+ requires :rails, :version => '2.1.0'
38
+ requires :appserver
39
+ requires :database
40
+ requires :webserver
41
+ requires :search
42
+ end
43
+
44
+
45
+ # Deployment
46
+ #
47
+ # Defines script wide settings such as a delivery mechanism for executing commands on the target
48
+ # system (eg. capistrano), and installer defaults (eg. build locations, etc):
49
+ #
50
+ # Configures spinkle to use capistrano for delivery of commands to the remote machines (via
51
+ # the named 'deploy' recipe). Also configures 'source' installer defaults to put package gear
52
+ # in /usr/local
53
+
54
+ deployment do
55
+
56
+ # mechanism for deployment
57
+ delivery :capistrano do
58
+ recipes 'deploy'
59
+ end
60
+
61
+ # source based package installer defaults
62
+ source do
63
+ prefix '/usr/local'
64
+ archives '/usr/local/sources'
65
+ builds '/usr/local/build'
66
+ end
67
+
68
+ end
69
+
70
+ # End of script, given the above information, Spinkle will apply the defined policy on all roles using the
71
+ # deployment settings specified.
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env sprinkle -c -s
2
+
3
+ # Example of the simplest Sprinkle script to install a single gem on a remote host. This
4
+ # particular script assumes that rubygems (and ruby, etc) are already installed on the remote
5
+ # host. To see a larger example of installing an entire ruby, rubygems, gem stack from source,
6
+ # please see the rails example.
7
+
8
+ # Packages, only sprinkle is defined in this world
9
+
10
+ package :sprinkle do
11
+ description 'Sprinkle Provisioning Tool'
12
+ gem 'crafterm-sprinkle' do
13
+ source 'http://gems.github.com' # use alternate gem server
14
+ #repository '/opt/local/gems' # specify an alternate local gem repository
15
+ end
16
+ end
17
+
18
+
19
+ # Policies, sprinkle policy requires only the sprinkle gem
20
+
21
+ policy :sprinkle, :roles => :app do
22
+ requires :sprinkle
23
+ end
24
+
25
+
26
+ # Deployment settings
27
+
28
+ deployment do
29
+
30
+ # use vlad for deployment
31
+ delivery :vlad do
32
+ role :app, 'yourhost.com'
33
+ end
34
+
35
+ end
36
+
37
+ # End of script, given the above information, Spinkle will apply the defined policy on all roles using the
38
+ # deployment settings specified.
data/lib/sprinkle.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+
4
+ # Use active supports auto load mechanism
5
+ Dependencies.load_paths << File.dirname(__FILE__)
6
+
7
+ # Configure active support to log auto-loading of dependencies
8
+ #Dependencies::RAILS_DEFAULT_LOGGER = Logger.new($stdout)
9
+ #Dependencies.log_activity = true
10
+
11
+ # Load up extensions to existing classes
12
+ Dir[File.dirname(__FILE__) + '/sprinkle/extensions/*.rb'].each { |e| require e }
13
+ # Load up the verifiers so they can register themselves
14
+ Dir[File.dirname(__FILE__) + '/sprinkle/verifiers/*.rb'].each { |e| require e }
15
+
16
+ # Configuration options
17
+ module Sprinkle
18
+ OPTIONS = { :testing => false, :verbose => false, :force => false }
19
+ end
20
+
21
+ # Define a logging target and understand packages, policies and deployment DSL
22
+ class Object
23
+ include Sprinkle::Package, Sprinkle::Policy, Sprinkle::Deployment
24
+
25
+ def logger
26
+ @@__log__ ||= ActiveSupport::BufferedLogger.new($stdout, ActiveSupport::BufferedLogger::Severity::INFO)
27
+ end
28
+ end
@@ -0,0 +1,89 @@
1
+ require 'capistrano/cli'
2
+
3
+ module Sprinkle
4
+ module Actors
5
+ class Capistrano
6
+ attr_accessor :config, :loaded_recipes
7
+
8
+ def initialize(&block)
9
+ @config = ::Capistrano::Configuration.new
10
+ @config.logger.level = Sprinkle::OPTIONS[:verbose] ? ::Capistrano::Logger::INFO : ::Capistrano::Logger::IMPORTANT
11
+ @config.set(:password) { ::Capistrano::CLI.password_prompt }
12
+ if block
13
+ self.instance_eval &block
14
+ else
15
+ @config.load 'deploy' # normally in the config directory for rails
16
+ end
17
+ end
18
+
19
+ def recipes(script)
20
+ @loaded_recipes ||= []
21
+ @config.load script
22
+ @loaded_recipes << script
23
+ end
24
+
25
+ def process(name, commands, roles, suppress_and_return_failures = false)
26
+ define_task(name, roles) do
27
+ via = fetch(:run_method, :sudo)
28
+ commands.each do |command|
29
+ invoke_command command, :via => via
30
+ end
31
+ end
32
+
33
+ begin
34
+ run(name)
35
+ return true
36
+ rescue ::Capistrano::CommandError => e
37
+ return false if suppress_and_return_failures
38
+
39
+ # Reraise error if we're not suppressing it
40
+ raise
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ # REVISIT: can we set the description somehow?
47
+ def define_task(name, roles, &block)
48
+ @config.task task_sym(name), :roles => roles, &block
49
+ end
50
+
51
+ def run(task)
52
+ @config.send task_sym(task)
53
+ end
54
+
55
+ def task_sym(name)
56
+ "install_#{name.to_task_name}".to_sym
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ =begin
64
+
65
+ # channel: the SSH channel object used for this response
66
+ # stream: either :err or :out, for stderr or stdout responses
67
+ # output: the text that the server is sending, might be in chunks
68
+ run "apt-get update" do |channel, stream, output|
69
+ if output =~ /Are you sure?/
70
+ answer = Capistrano::CLI.ui.ask("Are you sure: ")
71
+ channel.send_data(answer + "\n")
72
+ else
73
+ # allow the default callback to be processed
74
+ Capistrano::Configuration.default_io_proc.call[channel, stream, output]
75
+ end
76
+ end
77
+
78
+
79
+
80
+ You can tell subversion to use a different username+password by
81
+ setting a couple variables:
82
+ set :svn_username, "my svn username"
83
+ set :svn_password, "my svn password"
84
+ If you don't want to set the password explicitly in your recipe like
85
+ that, you can make capistrano prompt you for it like this:
86
+ set(:svn_password) { Capistrano::CLI.password_prompt("Subversion
87
+ password: ") }
88
+ - Jamis
89
+ =end
@@ -0,0 +1,39 @@
1
+ module Sprinkle
2
+ module Actors
3
+ class Vlad
4
+ require 'vlad'
5
+ attr_accessor :loaded_recipes
6
+
7
+ def initialize(&block)
8
+ self.instance_eval &block if block
9
+ end
10
+
11
+ def script(name)
12
+ @loaded_recipes ||= []
13
+ self.load name
14
+ @loaded_recipes << script
15
+ end
16
+
17
+ def process(name, commands, roles, suppress_and_return_failures = false)
18
+ commands = commands.join ' && ' if commands.is_a? Array
19
+ t = remote_task(task_sym(name), :roles => roles) { run commands }
20
+
21
+ begin
22
+ t.invoke
23
+ return true
24
+ rescue ::Vlad::CommandFailedError => e
25
+ return false if suppress_and_return_failures
26
+
27
+ # Reraise error if we're not suppressing it
28
+ raise
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def task_sym(name)
35
+ "install_#{name.to_task_name}".to_sym
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ module Sprinkle
2
+ module Configurable
3
+ attr_accessor :delivery
4
+
5
+ def defaults(deployment)
6
+ defaults = deployment.defaults[self.class.name.split(/::/).last.downcase.to_sym]
7
+ self.instance_eval(&defaults) if defaults
8
+ @delivery = deployment.style
9
+ end
10
+
11
+ def assert_delivery
12
+ raise 'Unknown command delivery target' unless @delivery
13
+ end
14
+
15
+ def method_missing(sym, *args, &block)
16
+ unless args.empty? # mutate if not set
17
+ @options ||= {}
18
+ @options[sym] = *args unless @options[sym]
19
+ end
20
+
21
+ @options[sym] || @package.send(sym, *args, &block) # try the parents options if unknown
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ module Sprinkle
2
+ module Deployment
3
+ def deployment(&block)
4
+ @deployment = Deployment.new(&block)
5
+ end
6
+
7
+ class Deployment
8
+ attr_accessor :style, :defaults
9
+
10
+ def initialize(&block)
11
+ @defaults = {}
12
+ self.instance_eval(&block)
13
+ raise 'No delivery mechanism defined' unless @style
14
+ end
15
+
16
+ def delivery(type, &block)
17
+ @style = Actors.const_get(type.to_s.titleize).new &block
18
+ end
19
+
20
+ def method_missing(sym, *args, &block)
21
+ @defaults[sym] = block
22
+ end
23
+
24
+ def respond_to?(sym); !!@defaults[sym]; end
25
+
26
+ def process
27
+ POLICIES.each do |policy|
28
+ policy.process(self)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end