public
Rubygem
Description: Sprinkle is a software provisioning tool you can use to build remote servers with. eg. to install a Rails or Merb stack on a brand new slice directly after its been created
Homepage: http://github.com/crafterm/sprinkle
Clone URL: git://github.com/crafterm/sprinkle.git
Click here to lend your support to: sprinkle and make a donation at www.pledgie.com !
sprinkle / lib / sprinkle / verify.rb
100644 114 lines (102 sloc) 3.727 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
module Sprinkle
  # = Verification Methods
  #
  # As documented in Sprinkle::Package, you may define a block on a package
  # which verifies that a package was installed correctly. If this verification
  # block fails, Sprinkle will stop the script gracefully, raising the error.
  #
  # In addition to checking post install if it was successfully, verification
  # blocks are also ran before an install to see if a package is <em>already</em>
  # installed. If this is the case, the package is skipped and Sprinkle continues
  # with the next package. This behavior can be overriden by setting the -f flag on
  # the sprinkle script or setting Sprinkle::OPTIONS[:force] to true if you're
  # using sprinkle programmatically.
  #
  # == An Example
  #
  # The following verifies that rails was installed correctly be checking to see
  # if the 'rails' command is available on the command line:
  #
  # package :rails do
  # gem 'rails'
  #
  # verify do
  # has_executable 'rails'
  # end
  # end
  #
  # == Available Verifiers
  #
  # There are a variety of available methods for use in the verification block.
  # The standard methods are defined in the Sprinkle::Verifiers module, so see
  # their corresponding documentation.
  #
  # == Custom Verifiers
  #
  # If you feel that the built-in verifiers do not offer a certain aspect of
  # verification which you need, you may create your own verifier! Simply wrap
  # any method in a module which you want to use:
  #
  # module MagicBeansVerifier
  # def has_magic_beans(sauce)
  # @commands << '[ -z "`echo $' + sauce + '`"]'
  # end
  # end
  #
  # The method can append as many commands as it wishes to the @commands array.
  # These commands will be run on the remote server and <b>MUST</b> give an
  # exit status of 0 if successful or other if unsuccessful.
  #
  # To register your verifier, call the register method on Sprinkle::Verify:
  #
  # Sprinle::Verify.register(MagicBeansVerifier)
  #
  # And now you may use it like any other verifier:
  #
  # package :magic_beans do
  # gem 'magic_beans'
  #
  # verify { has_magic_beans('ranch') }
  # end
  class Verify
    include Sprinkle::Configurable
    attr_accessor :package, :description, :commands #:nodoc:
    
    class <<self
      # Register a verification module
      def register(new_module)
        class_eval { include new_module }
      end
    end
    
    def initialize(package, description = '', &block) #:nodoc:
      raise 'Verify requires a block.' unless block
      
      @package = package
      @description = description
      @commands = []
      @options ||= {}
      @options[:padding] = 4
      
      self.instance_eval(&block)
    end
    
    def process(roles, pre = false) #:nodoc:
      assert_delivery
      
      description = @description.empty? ? @package.name : @description
      
      if logger.debug?
        logger.debug "#{@package.name}#{description} verification sequence: #{@commands.join('; ')} for roles: #{roles}\n"
      end
      
      unless Sprinkle::OPTIONS[:testing]
        logger.info "#{" " * @options[:padding]}--> Verifying #{description}..."
        
        unless @delivery.process(@package.name, @commands, roles, true)
          # Verification failed, halt sprinkling gracefully.
          raise Sprinkle::VerificationFailed.new(@package, description)
        end
      end
    end
  end
  
  class VerificationFailed < Exception #:nodoc:
    attr_accessor :package, :description
    
    def initialize(package, description)
      super("Verifying #{package.name}#{description} failed.")
      
      @package = package
      @description = description
    end
  end
end