crafterm-sprinkle 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CREDITS +2 -1
  2. data/Manifest.txt +11 -2
  3. data/{README.rdoc → README.txt} +25 -5
  4. data/bin/sprinkle +7 -0
  5. data/config/hoe.rb +2 -2
  6. data/examples/rails/rails.rb +4 -2
  7. data/lib/sprinkle.rb +8 -2
  8. data/lib/sprinkle/actors/actors.rb +17 -0
  9. data/lib/sprinkle/actors/capistrano.rb +41 -4
  10. data/lib/sprinkle/actors/vlad.rb +39 -4
  11. data/lib/sprinkle/configurable.rb +31 -0
  12. data/lib/sprinkle/deployment.rb +46 -6
  13. data/lib/sprinkle/extensions/arbitrary_options.rb +1 -1
  14. data/lib/sprinkle/extensions/array.rb +1 -3
  15. data/lib/sprinkle/extensions/blank_slate.rb +1 -1
  16. data/lib/sprinkle/extensions/dsl_accessor.rb +1 -1
  17. data/lib/sprinkle/extensions/string.rb +1 -1
  18. data/lib/sprinkle/extensions/symbol.rb +1 -1
  19. data/lib/sprinkle/installers/apt.rb +33 -6
  20. data/lib/sprinkle/installers/gem.rb +34 -6
  21. data/lib/sprinkle/installers/installer.rb +64 -29
  22. data/lib/sprinkle/installers/rake.rb +15 -2
  23. data/lib/sprinkle/installers/rpm.rb +20 -3
  24. data/lib/sprinkle/installers/source.rb +74 -16
  25. data/lib/sprinkle/package.rb +127 -2
  26. data/lib/sprinkle/policy.rb +42 -2
  27. data/lib/sprinkle/script.rb +11 -1
  28. data/lib/sprinkle/verifiers/directory.rb +16 -0
  29. data/lib/sprinkle/verifiers/executable.rb +36 -0
  30. data/lib/sprinkle/verifiers/file.rb +20 -0
  31. data/lib/sprinkle/verifiers/process.rb +21 -0
  32. data/lib/sprinkle/verifiers/ruby.rb +25 -0
  33. data/lib/sprinkle/verifiers/symlink.rb +30 -0
  34. data/lib/sprinkle/verify.rb +114 -0
  35. data/lib/sprinkle/version.rb +1 -1
  36. data/spec/sprinkle/actors/capistrano_spec.rb +21 -1
  37. data/spec/sprinkle/configurable_spec.rb +46 -0
  38. data/spec/sprinkle/installers/apt_spec.rb +1 -5
  39. data/spec/sprinkle/installers/gem_spec.rb +1 -1
  40. data/spec/sprinkle/installers/installer_spec.rb +55 -29
  41. data/spec/sprinkle/package_spec.rb +137 -0
  42. data/spec/sprinkle/verify_spec.rb +160 -0
  43. data/sprinkle.gemspec +6 -6
  44. metadata +17 -4
  45. data/examples/merb/deploy.rb +0 -5
data/CREDITS CHANGED
@@ -13,4 +13,5 @@ Matt Allen (http://blog.allen.com.au)
13
13
  Eric Hodel (http://blog.segment7.net)
14
14
  Pete Yandell (http://notahat.com)
15
15
  Adam Meehan (http://duckpunching.com)
16
- Mitchell Hashimoto (http://mitchellhashimoto.com)
16
+ Mitchell Hashimoto (http://mitchellhashimoto.com)
17
+ Ari Lerner (http://www.citrusbyte.com)
data/Manifest.txt CHANGED
@@ -2,12 +2,11 @@ CREDITS
2
2
  History.txt
3
3
  MIT-LICENSE
4
4
  Manifest.txt
5
- README.rdoc
5
+ README.txt
6
6
  Rakefile
7
7
  bin/sprinkle
8
8
  config/hoe.rb
9
9
  config/requirements.rb
10
- examples/merb/deploy.rb
11
10
  examples/rails/README
12
11
  examples/rails/deploy.rb
13
12
  examples/rails/packages/database.rb
@@ -18,8 +17,10 @@ examples/rails/packages/server.rb
18
17
  examples/rails/rails.rb
19
18
  examples/sprinkle/sprinkle.rb
20
19
  lib/sprinkle.rb
20
+ lib/sprinkle/actors/actors.rb
21
21
  lib/sprinkle/actors/capistrano.rb
22
22
  lib/sprinkle/actors/vlad.rb
23
+ lib/sprinkle/configurable.rb
23
24
  lib/sprinkle/deployment.rb
24
25
  lib/sprinkle/extensions/arbitrary_options.rb
25
26
  lib/sprinkle/extensions/array.rb
@@ -36,6 +37,13 @@ lib/sprinkle/installers/source.rb
36
37
  lib/sprinkle/package.rb
37
38
  lib/sprinkle/policy.rb
38
39
  lib/sprinkle/script.rb
40
+ lib/sprinkle/verifiers/directory.rb
41
+ lib/sprinkle/verifiers/executable.rb
42
+ lib/sprinkle/verifiers/file.rb
43
+ lib/sprinkle/verifiers/process.rb
44
+ lib/sprinkle/verifiers/ruby.rb
45
+ lib/sprinkle/verifiers/symlink.rb
46
+ lib/sprinkle/verify.rb
39
47
  lib/sprinkle/version.rb
40
48
  script/destroy
41
49
  script/generate
@@ -54,6 +62,7 @@ spec/sprinkle/package_spec.rb
54
62
  spec/sprinkle/policy_spec.rb
55
63
  spec/sprinkle/script_spec.rb
56
64
  spec/sprinkle/sprinkle_spec.rb
65
+ spec/sprinkle/verify_spec.rb
57
66
  sprinkle.gemspec
58
67
  tasks/deployment.rake
59
68
  tasks/environment.rake
@@ -20,10 +20,16 @@ An example package description follows:
20
20
  version '1.8.6'
21
21
  source "ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-#{version}-p111.tar.gz"
22
22
  requires :ruby_dependencies
23
+
24
+ verify do
25
+ has_file '/usr/bin/ruby'
26
+ end
23
27
  end
24
28
 
25
29
  This defines a package called 'ruby', that uses the source based installer to build Ruby 1.8.6 from source,
26
- installing the package 'ruby_dependencies' beforehand.
30
+ installing the package 'ruby_dependencies' beforehand. Additionally, the package verifies it was installed
31
+ correctly by verifying the file '/usr/bin/ruby' exists after installation. If this verification fails, the
32
+ sprinkle script will gracefully stop.
27
33
 
28
34
  Reasonable defaults are set by sprinkle, such as the install prefix, download area, etc, but can be customized
29
35
  globally or per package (see below for an example).
@@ -60,13 +66,14 @@ remote hosts. Currently Sprinkle supports the use of Capistrano or Vlad to issue
60
66
  but could also be extended to use any other command transport mechanism or be used to simply issue installation
61
67
  commands on the local system.
62
68
 
63
- An full example Sprinkle deployment script for deploying Rails (via gems), MySQL (via APT), and Apache (via source):
69
+ An full example Sprinkle deployment script for deploying Rails (via gems), MySQL (via APT), Apache (via source)
70
+ and Git (via source with dependencies from APT):
64
71
 
65
72
  # Sprinkle Rails deployment script
66
73
  #
67
- # This is an example Sprinkle script, configured to install Rails from gems, Apache and Ruby from source,
68
- # and mysql from apt on an Ubuntu system. Installation is configured to run via Capistrano (and
69
- # an accompanying deploy.rb recipe script). Source based packages are downloaded and built into
74
+ # This is an example Sprinkle script, configured to install Rails from gems, Apache, Ruby and Git from source,
75
+ # and mysql and Git dependencies from apt on an Ubuntu system. Installation is configured to run via
76
+ # Capistrano (and an accompanying deploy.rb recipe script). Source based packages are downloaded and built into
70
77
  # /usr/local on the remote system.
71
78
  #
72
79
  # A sprinkle script is separated into 3 different sections. Packages, policies and deployment.
@@ -148,6 +155,18 @@ An full example Sprinkle deployment script for deploying Rails (via gems), MySQL
148
155
  version '1.0.5'
149
156
  requires :mongrel
150
157
  end
158
+
159
+ package :git, :provides => :scm do
160
+ description 'Git Distributed Version Control'
161
+ version '1.5.6.3'
162
+ source "http://kernel.org/pub/software/scm/git/git-#{version}.tar.gz"
163
+ requires :git_dependencies
164
+ end
165
+
166
+ package :git_dependencies do
167
+ description 'Git Build Dependencies'
168
+ apt 'git', :dependencies_only => true
169
+ end
151
170
 
152
171
  # Policies
153
172
 
@@ -161,6 +180,7 @@ An full example Sprinkle deployment script for deploying Rails (via gems), MySQL
161
180
  requires :appserver
162
181
  requires :database
163
182
  requires :webserver
183
+ requires :scm
164
184
  end
165
185
 
166
186
  # Deployment
data/bin/sprinkle CHANGED
@@ -46,6 +46,8 @@ BANNER
46
46
  "Verbose output") { |OPTIONS[:verbose]| }
47
47
  opts.on("-c", "--cloud",
48
48
  "Show powder cloud, ie. package hierarchy and installation order") { |OPTIONS[:cloud]| }
49
+ opts.on("-f", "--force",
50
+ "Force installation of all packages even if it is detected that it has been previously installed") { |OPTIONS[:force]| }
49
51
  opts.on("-h", "--help",
50
52
  "Show this help message.") { puts opts; exit }
51
53
  opts.parse!(ARGV)
@@ -55,6 +57,10 @@ BANNER
55
57
  end
56
58
  end
57
59
 
60
+ def force_mode(options)
61
+ Sprinkle::OPTIONS[:force] = OPTIONS[:force] || false
62
+ end
63
+
58
64
  def operation_mode(options)
59
65
  Sprinkle::OPTIONS[:testing] = OPTIONS[:testing] || false
60
66
  end
@@ -72,6 +78,7 @@ require 'sprinkle'
72
78
  powder = OPTIONS[:path]
73
79
  raise "Sprinkle script is not readable: #{powder}" unless File.readable?(powder)
74
80
 
81
+ force_mode(OPTIONS)
75
82
  operation_mode(OPTIONS)
76
83
  powder_cloud(OPTIONS)
77
84
  log_level(OPTIONS)
data/config/hoe.rb CHANGED
@@ -35,7 +35,7 @@ VERS = Sprinkle::VERSION::STRING + (REV ? ".#{REV}" : "")
35
35
  RDOC_OPTS = ['--quiet', '--title', 'sprinkle documentation',
36
36
  "--opname", "index.html",
37
37
  "--line-numbers",
38
- "--main", "README",
38
+ "--main", "README.txt",
39
39
  "--inline-source"]
40
40
 
41
41
  class Hoe
@@ -59,7 +59,7 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
59
59
  # == Optional
60
60
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
61
  p.extra_deps = [ ['activesupport', '>= 2.0.2'], ['highline', '>= 1.4.0'], ['capistrano', '>= 2.2.0'] ] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
62
-
62
+
63
63
  #p.spec_extras = {} # A hash of extra values to set in the gemspec.
64
64
 
65
65
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  # Annotated Example Sprinkle Rails deployment script
4
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.
5
+ # This is an example Sprinkle script configured to install Rails from gems, Apache, Ruby,
6
+ # Sphinx and Git from source, and mysql and Git dependencies from apt on an Ubuntu system.
7
7
  #
8
8
  # Installation is configured to run via capistrano (and an accompanying deploy.rb recipe script).
9
9
  # Source based packages are downloaded and built into /usr/local on the remote system.
@@ -22,6 +22,7 @@ require 'packages/rails'
22
22
  require 'packages/database'
23
23
  require 'packages/server'
24
24
  require 'packages/search'
25
+ require 'packages/scm'
25
26
 
26
27
 
27
28
  # Policies
@@ -39,6 +40,7 @@ policy :rails, :roles => :app do
39
40
  requires :database
40
41
  requires :webserver
41
42
  requires :search
43
+ requires :scm
42
44
  end
43
45
 
44
46
 
data/lib/sprinkle.rb CHANGED
@@ -10,17 +10,23 @@ Dependencies.load_paths << File.dirname(__FILE__)
10
10
 
11
11
  # Load up extensions to existing classes
12
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 }
13
15
 
14
16
  # Configuration options
15
17
  module Sprinkle
16
- OPTIONS = { :testing => false, :verbose => false }
18
+ OPTIONS = { :testing => false, :verbose => false, :force => false }
17
19
  end
18
20
 
21
+ # Object is extended to give the package, policy, and deployment methods. To
22
+ # read about each method, see the corresponding module which is included.
23
+ #--
19
24
  # Define a logging target and understand packages, policies and deployment DSL
25
+ #++
20
26
  class Object
21
27
  include Sprinkle::Package, Sprinkle::Policy, Sprinkle::Deployment
22
28
 
23
- def logger
29
+ def logger # :nodoc:
24
30
  @@__log__ ||= ActiveSupport::BufferedLogger.new($stdout, ActiveSupport::BufferedLogger::Severity::INFO)
25
31
  end
26
32
  end
@@ -0,0 +1,17 @@
1
+ #--
2
+ # The only point of this file is to give RDoc a definition for
3
+ # Sprinkle::Actors. This file in production is never actually included
4
+ # since ActiveSupport only on-demand loads classes which are needed
5
+ # and this module is never explicitly needed.
6
+ #++
7
+
8
+ module Sprinkle
9
+ # An actor is a method of command delivery to a remote machine. It is the
10
+ # layer between sprinkle and the SSH connection to run commands. This gives
11
+ # you the flexibility to define custom actors, for whatever purpose you need.
12
+ #
13
+ # 99% of the time, however, the two built-in actors Sprinkle::Actors::Capistrano
14
+ # and Sprinkle::Actors::Vlad will be enough.
15
+ module Actors
16
+ end
17
+ end
@@ -2,10 +2,26 @@ require 'capistrano/cli'
2
2
 
3
3
  module Sprinkle
4
4
  module Actors
5
+ # = Capistrano Delivery Method
6
+ #
7
+ # Capistrano is one of the delivery method options available out of the
8
+ # box with Sprinkle. If you have the capistrano gem install, you may use
9
+ # this delivery. The only configuration option available, and which is
10
+ # mandatory to include is +recipes+. An example:
11
+ #
12
+ # deployment do
13
+ # delivery :capistrano do
14
+ # recipes 'deploy'
15
+ # end
16
+ # end
17
+ #
18
+ # Recipes is given a list of files which capistrano will include and load.
19
+ # These recipes are mainly to set variables such as :user, :password, and to
20
+ # set the app domain which will be sprinkled.
5
21
  class Capistrano
6
- attr_accessor :config, :loaded_recipes
22
+ attr_accessor :config, :loaded_recipes #:nodoc:
7
23
 
8
- def initialize(&block)
24
+ def initialize(&block) #:nodoc:
9
25
  @config = ::Capistrano::Configuration.new
10
26
  @config.logger.level = Sprinkle::OPTIONS[:verbose] ? ::Capistrano::Logger::INFO : ::Capistrano::Logger::IMPORTANT
11
27
  @config.set(:password) { ::Capistrano::CLI.password_prompt }
@@ -16,20 +32,41 @@ module Sprinkle
16
32
  end
17
33
  end
18
34
 
35
+ # Defines a recipe file which will be included by capistrano. Use these
36
+ # recipe files to set capistrano specific configurations. Default recipe
37
+ # included is "deploy." But if any other recipe is specified, it will
38
+ # include that instead. Multiple recipes may be specified through multiple
39
+ # recipes calls, an example:
40
+ #
41
+ # deployment do
42
+ # delivery :capistrano do
43
+ # recipes 'deploy'
44
+ # recipes 'magic_beans'
45
+ # end
46
+ # end
19
47
  def recipes(script)
20
48
  @loaded_recipes ||= []
21
49
  @config.load script
22
50
  @loaded_recipes << script
23
51
  end
24
52
 
25
- def process(name, commands, roles)
53
+ def process(name, commands, roles, suppress_and_return_failures = false) #:nodoc:
26
54
  define_task(name, roles) do
27
55
  via = fetch(:run_method, :sudo)
28
56
  commands.each do |command|
29
57
  invoke_command command, :via => via
30
58
  end
31
59
  end
32
- run(name)
60
+
61
+ begin
62
+ run(name)
63
+ return true
64
+ rescue ::Capistrano::CommandError => e
65
+ return false if suppress_and_return_failures
66
+
67
+ # Reraise error if we're not suppressing it
68
+ raise
69
+ end
33
70
  end
34
71
 
35
72
  private
@@ -1,23 +1,58 @@
1
1
  module Sprinkle
2
2
  module Actors
3
+ # = Vlad Delivery Method
4
+ #
5
+ # Vlad is one of the delivery method options available out of the
6
+ # box with Sprinkle. If you have the vlad the deployer gem install, you
7
+ # may use this delivery. The only configuration option available, and
8
+ # which is mandatory to include is +script+. An example:
9
+ #
10
+ # deployment do
11
+ # delivery :vlad do
12
+ # script 'deploy'
13
+ # end
14
+ # end
15
+ #
16
+ # script is given a list of files which capistrano will include and load.
17
+ # These recipes are mainly to set variables such as :user, :password, and to
18
+ # set the app domain which will be sprinkled.
3
19
  class Vlad
4
20
  require 'vlad'
5
- attr_accessor :loaded_recipes
21
+ attr_accessor :loaded_recipes #:nodoc:
6
22
 
7
- def initialize(&block)
23
+ def initialize(&block) #:nodoc:
8
24
  self.instance_eval &block if block
9
25
  end
10
26
 
27
+ # Defines a script file which will be included by vlad. Use these
28
+ # script files to set vlad specific configurations. Multiple scripts
29
+ # may be specified through multiple script calls, an example:
30
+ #
31
+ # deployment do
32
+ # delivery :vlad do
33
+ # script 'deploy'
34
+ # script 'magic_beans'
35
+ # end
36
+ # end
11
37
  def script(name)
12
38
  @loaded_recipes ||= []
13
39
  self.load name
14
40
  @loaded_recipes << script
15
41
  end
16
42
 
17
- def process(name, commands, roles)
43
+ def process(name, commands, roles, suppress_and_return_failures = false) #:nodoc:
18
44
  commands = commands.join ' && ' if commands.is_a? Array
19
45
  t = remote_task(task_sym(name), :roles => roles) { run commands }
20
- t.invoke
46
+
47
+ begin
48
+ t.invoke
49
+ return true
50
+ rescue ::Vlad::CommandFailedError => e
51
+ return false if suppress_and_return_failures
52
+
53
+ # Reraise error if we're not suppressing it
54
+ raise
55
+ end
21
56
  end
22
57
 
23
58
  private
@@ -0,0 +1,31 @@
1
+ module Sprinkle
2
+ #--
3
+ # TODO: Possible documentation?
4
+ #++
5
+ module Configurable #:nodoc:
6
+ attr_accessor :delivery
7
+
8
+ def defaults(deployment)
9
+ defaults = deployment.defaults[self.class.name.split(/::/).last.downcase.to_sym]
10
+ self.instance_eval(&defaults) if defaults
11
+ @delivery = deployment.style
12
+ end
13
+
14
+ def assert_delivery
15
+ raise 'Unknown command delivery target' unless @delivery
16
+ end
17
+
18
+ def method_missing(sym, *args, &block)
19
+ unless args.empty? # mutate if not set
20
+ @options ||= {}
21
+ @options[sym] = *args unless @options[sym]
22
+ end
23
+
24
+ @options[sym] || @package.send(sym, *args, &block) # try the parents options if unknown
25
+ end
26
+
27
+ def option?(sym)
28
+ !@options[sym].nil?
29
+ end
30
+ end
31
+ end
@@ -1,29 +1,69 @@
1
1
  module Sprinkle
2
+ # Deployment blocks specify deployment specific information about a
3
+ # sprinkle script. An example:
4
+ #
5
+ # deployment do
6
+ # # mechanism for deployment
7
+ # delivery :capistrano do
8
+ # recipes 'deploy'
9
+ # end
10
+ #
11
+ # # source based package installer defaults
12
+ # source do
13
+ # prefix '/usr/local'
14
+ # archives '/usr/local/sources'
15
+ # builds '/usr/local/build'
16
+ # end
17
+ # end
18
+ #
19
+ # What the above example does is tell sprinkle that we will be using
20
+ # *capistrano* (Sprinkle::Actors::Capistrano) for deployment and
21
+ # everything within the block is capistrano specific configuration.
22
+ # For more information on what options are available, check the corresponding
23
+ # Sprinkle::Actors doc page.
24
+ #
25
+ # In addition to what delivery mechanism we're using, we specify some
26
+ # configuration options for the "source" command. The only things
27
+ # configurable, at this time, in the deployment block other than
28
+ # the delivery method are installers. If installers are configurable,
29
+ # they will say so on their corresponding documentation page. See
30
+ # Sprinkle::Installers
31
+ #
32
+ # <b>Only one deployment block is on any given sprinkle script</b>
2
33
  module Deployment
34
+ # The method outlined above which specifies deployment specific information
35
+ # for a sprinkle script. For more information, read the header of this module.
3
36
  def deployment(&block)
4
37
  @deployment = Deployment.new(&block)
5
38
  end
6
39
 
7
40
  class Deployment
8
- attr_accessor :style, :defaults
41
+ attr_accessor :style, :defaults #:nodoc:
9
42
 
10
- def initialize(&block)
43
+ def initialize(&block) #:nodoc:
11
44
  @defaults = {}
12
45
  self.instance_eval(&block)
13
46
  raise 'No delivery mechanism defined' unless @style
14
47
  end
15
48
 
16
- def delivery(type, &block)
49
+ # Specifies which Sprinkle::Actors to use for delivery. Although all
50
+ # actors jobs are the same: to run remote commands on a server, you
51
+ # may have a personal preference. The block you pass is used to configure
52
+ # the actor. For more information on what configuration options are
53
+ # available, view the corresponding Sprinkle::Actors page.
54
+ def delivery(type, &block) #:doc:
17
55
  @style = Actors.const_get(type.to_s.titleize).new &block
18
56
  end
19
57
 
20
- def method_missing(sym, *args, &block)
58
+ def method_missing(sym, *args, &block) #:nodoc:
21
59
  @defaults[sym] = block
22
60
  end
23
61
 
24
- def respond_to?(sym); !!@defaults[sym]; end
62
+ def respond_to?(sym) #:nodoc:
63
+ !!@defaults[sym]
64
+ end
25
65
 
26
- def process
66
+ def process #:nodoc:
27
67
  POLICIES.each do |policy|
28
68
  policy.process(self)
29
69
  end