capsaicin 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Joe Khoobyar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = capsaicin
2
+
3
+ Joe Khoobyar's spicy capistrano extensions.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Joe Khoobyar. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'rake/rdoctask'
5
+ require 'rake/testtask'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |s|
10
+ s.name = "capsaicin"
11
+ s.homepage = "http://github.com/joekhoobyar/capsaicin"
12
+ s.summary = "Joe Khoobyar's spicy capistrano extensions"
13
+ s.description = %Q{Spicy capistrano extensions for various needs}
14
+
15
+ s.authors = ["Joe Khoobyar"]
16
+ s.email = "joe@ankhcraft.com"
17
+
18
+ s.add_dependency 'capistrano', ['>= 2.0']
19
+ s.add_dependency 'archive-tar-minitar', ['>= 0.5']
20
+ end
21
+ rescue LoadError
22
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
23
+ end
24
+
25
+ # --------- RDoc Documentation ---------
26
+ desc "Generate RDoc documentation"
27
+ Rake::RDocTask.new(:rdoc) do |rdoc|
28
+ rdoc.options << '--line-numbers' << '--inline-source' <<
29
+ '--main' << 'README' <<
30
+ '--title' << "Capsaicin" <<
31
+ '--charset' << 'utf-8'
32
+ rdoc.rdoc_dir = "doc"
33
+ rdoc.rdoc_files.include 'README*'
34
+ rdoc.rdoc_files.include('lib/**/*.rb')
35
+ end
36
+
37
+ Rake::TestTask.new do |t|
38
+ t.libs << "test"
39
+ t.libs << "lib"
40
+ end
41
+
42
+ task :default => :build
43
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 2
3
+ :major: 0
4
+ :minor: 1
data/lib/capsaicin.rb ADDED
@@ -0,0 +1,10 @@
1
+ unless Capistrano::Configuration.respond_to?(:instance)
2
+ abort "capsaicin requires capistrano 2.0 or later"
3
+ end
4
+ require 'capistrano'
5
+
6
+ require File.join(File.dirname(__FILE__), %w(capsaicin sys))
7
+ require File.join(File.dirname(__FILE__), %w(capsaicin invocation))
8
+ require File.join(File.dirname(__FILE__), %w(capsaicin files))
9
+ require File.join(File.dirname(__FILE__), %w(capsaicin service))
10
+ require File.join(File.dirname(__FILE__), %w(capsaicin ui))
@@ -0,0 +1,7 @@
1
+ module Capsaicin
2
+ module Bundle
3
+
4
+ end
5
+
6
+ Capistrano.plugin :bundle
7
+ end
@@ -0,0 +1,47 @@
1
+ module Capsaicin
2
+ module Files
3
+
4
+ COMMANDS = [ %w(mkdir mkdir_p rmdir cp cp_r rm rm_f rm_r rm_rf
5
+ chmod chmod_R chown chown_R touch),
6
+ %w(ln ln_s ln_sf mv install) ]
7
+
8
+ FILE_TESTS = [
9
+ %w(blockdev? -b),
10
+ %w(chardev? -c),
11
+ %w(directory? -d),
12
+ %w(exists? -e),
13
+ %w(file? -f),
14
+ %w(grpowned? -G),
15
+ %w(owned? -O),
16
+ %w(pipe? -p),
17
+ %w(readable? -r),
18
+ %w(setgid? -g),
19
+ %w(setuid? -u),
20
+ %w(size? -s),
21
+ %w(socket? -S),
22
+ %w(sticky? -k),
23
+ %w(symlink? -h),
24
+ %w(writable? -w),
25
+ %w(executable? -x)
26
+ ]
27
+
28
+ LOCAL_RUN_METHODS = [:system, :local_run]
29
+
30
+ require File.join(File.dirname(__FILE__), %w(files local.rb))
31
+ require File.join(File.dirname(__FILE__), %w(files remote.rb))
32
+
33
+ class_eval(Local.public_instance_methods(false).map do |m|
34
+ "def #{m}(*args, &block)\n send(_via.to_s + '_files').#{m}(*args, &block)\nend"
35
+ end.join("\n"), __FILE__, __LINE__)
36
+
37
+ def _via
38
+ if LOCAL_RUN_METHODS.include? @config.fetch(:run_method, nil)
39
+ :local
40
+ else
41
+ :remote
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ Capistrano.plugin :files, Capsaicin::Files
@@ -0,0 +1,49 @@
1
+ require 'fileutils'
2
+
3
+ module Capsaicin
4
+ module Files
5
+ module Local
6
+
7
+ include FileUtils::Verbose
8
+
9
+ public *COMMANDS.flatten
10
+ public :pwd
11
+
12
+ FILE_TESTS.each do |m,t|
13
+ class_eval <<-EODEF, __FILE__, __LINE__
14
+ def #{m}(a, options={})
15
+ logger.trace "test #{t} \#{a.gsub ' ', '\\ '}" if logger
16
+ File.#{m} a
17
+ end
18
+ EODEF
19
+ end
20
+
21
+ def tail_f(file, n=10)
22
+ unless defined? File::Tail::Logfile then gem 'file-tail'; require 'file/tail' end
23
+ File::Tail::Logfile.tail(file, :backward=>n) do |line| puts line end
24
+ rescue Interrupt
25
+ logger.trace "interrupted (Ctrl-C)" if logger
26
+ end
27
+
28
+ def upload(from, to)
29
+ cp from, to
30
+ end
31
+
32
+ def download(from, to)
33
+ cp from, to
34
+ end
35
+
36
+ def cd(dir, options={})
37
+ if block_given?
38
+ dir, dir2 = pwd, dir
39
+ cd dir2
40
+ yield
41
+ end
42
+ cd dir
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+
49
+ Capistrano.plugin :local_files, Capsaicin::Files::Local
@@ -0,0 +1,117 @@
1
+ require 'fileutils'
2
+
3
+ module Capsaicin
4
+ module Files
5
+ module Remote
6
+
7
+ COMMANDS.each_with_index do |l,n|
8
+ l.each do |m|
9
+ k, f = m.split('_')
10
+ f = ' -' + f if f
11
+ class_eval <<-EODEF, __FILE__, __LINE__
12
+ def #{m}(*args)
13
+ options = args.pop if Hash === args.last
14
+ _r '#{k}#{f}', args#{', ' + (n+1).to_s if n > 0}
15
+ end
16
+ EODEF
17
+ end
18
+ end
19
+
20
+ FILE_TESTS.each do |m,t|
21
+ class_eval <<-EODEF
22
+ def #{m}(a, options={})
23
+ _t "test #{t}", a
24
+ end
25
+ EODEF
26
+ end
27
+
28
+ def tail_f(file, n=10)
29
+ cmd = "tail -n #{n} -f #{_q file}"
30
+ case v = _via
31
+ when :system, :local_run
32
+ send v, cmd
33
+ else
34
+ stream cmd, :via => v
35
+ end
36
+ rescue Interrupt
37
+ logger.trace "interrupted (Ctrl-C)" if logger
38
+ end
39
+
40
+ def upload(*args)
41
+ case _via
42
+ when :system, :local_run
43
+ cp(*args)
44
+ else
45
+ @config.upload(*args)
46
+ end
47
+ end
48
+
49
+ def download(*args)
50
+ case _via
51
+ when :system, :local_run
52
+ cp(*args)
53
+ else
54
+ @config.download(*args)
55
+ end
56
+ end
57
+
58
+ def cd(dir, options={})
59
+ if block_given?
60
+ dir, dir2 = pwd, dir
61
+ _r 'cd', dir2
62
+ yield
63
+ end
64
+ _r 'cd', dir
65
+ end
66
+
67
+ def pwd
68
+ capture 'pwd', :via => _via
69
+ end
70
+
71
+ private
72
+
73
+ def _t(cmd, args=nil, min=nil)
74
+ cmd = _a cmd, args, min
75
+ if _via == :system then
76
+ local_run(cmd)
77
+ else
78
+ capture("#{cmd}; echo $?", :via => _via).strip == '0'
79
+ end
80
+ end
81
+
82
+ def _r(cmd, args=nil, min=nil)
83
+ cmd = _a cmd, args, min
84
+ if _via != :system then
85
+ invoke_command cmd, :via => _via
86
+ else
87
+ local_run cmd
88
+ end
89
+ end
90
+
91
+ def _a(cmd, args=nil, min=nil)
92
+ case args
93
+ when NilClass
94
+ raise ArgumentError unless min.nil? or min.zero?
95
+ when Array
96
+ args = args.flatten
97
+ raise ArgumentError if (min || 1) > args.length
98
+ cmd = "#{cmd} #{_q(*args)}" if args.any?
99
+ else
100
+ raise ArgumentError if min and min < 1
101
+ cmd = "#{cmd} #{_q args}"
102
+ end
103
+ end
104
+
105
+ def _q(*list)
106
+ list.map { |l| "'#{l.gsub("'", "\\'")}'" }.join ' '
107
+ end
108
+
109
+ def _via
110
+ @config.fetch(:run_method, nil)
111
+ end
112
+
113
+ end
114
+ end
115
+ end
116
+
117
+ Capistrano.plugin :remote_files, Capsaicin::Files::Remote
@@ -0,0 +1,48 @@
1
+ module Capsaicin
2
+
3
+ module Invocation
4
+
5
+ # Capistrano's system() override is only available from the base deployment strategy.
6
+ # Also, we could do with a few more windows checks.
7
+ def local_run(*args, &block)
8
+ args.pop if Hash===args.last
9
+ cmd = args.join(' ')
10
+ if RUBY_PLATFORM =~ /win32|mingw|mswin/
11
+ cmd.gsub!('/','\\') # Replace / with \\
12
+ cmd.gsub!(/^cd /,'cd /D ') # Replace cd with cd /D
13
+ cmd.gsub!(/&& cd /,'&& cd /D ') # Replace cd with cd /D
14
+ logger.trace "executing locally: #{cmd}"
15
+ Kernel.system cmd
16
+ else
17
+ logger.trace "executing locally: #{cmd}"
18
+ Kernel.system cmd
19
+ end
20
+ end
21
+
22
+ # Always uses :runner to sudo as someone.
23
+ # Equivalent to: sudo "command", :as => fetch(:runner,nil)
24
+ def sudo_as(*args, &block)
25
+ options = Hash===args.last ? args.pop.dup : {}
26
+ options[:as] = fetch(:runner, nil)
27
+ sudo *args.push(options), &block
28
+ end
29
+
30
+ # Extremely helpful if you only have permission to: sudo su SOMEUSER -c "command"
31
+ def sudo_su(*args, &block)
32
+ options = Hash===args.last ? args.pop.dup : {}
33
+ args[0] = "su #{fetch(:runner, nil)} -c '#{args[0]}'"
34
+ sudo *args.push(options), &block
35
+ end
36
+
37
+ # Extremely helpful if you only have permission to: sudo su - SOMEUSER
38
+ def sudo_su_to(*args, &block)
39
+ options = Hash===args.last ? args.pop.dup : {}
40
+ options[:shell] = false
41
+ cmd = args[0].gsub(/[$\\`"]/) { |m| "\\#{m}" }
42
+ args[0] = "echo \"#{cmd}\" | #{sudo} su - #{fetch(:runner, nil)}"
43
+ run *args.push(options), &block
44
+ end
45
+ end
46
+
47
+ Capistrano::Configuration.send :include, Invocation
48
+ end
@@ -0,0 +1,21 @@
1
+ module Capsaicin
2
+
3
+ module Service
4
+
5
+ SVC_ACTION_CAPTIONS = Hash.new do |h,k|
6
+ h[k] = "#{k.to_s.capitalize} Service"
7
+ end.update :status => 'Check Status',
8
+ :check => 'Check Config',
9
+ :summary => 'Status Summary'
10
+
11
+ %w(lsb crm windows command).each do |k|
12
+ require File.join(File.dirname(__FILE__), 'service', k+'.rb')
13
+ end
14
+
15
+ include LSB, CRM, Windows, Command
16
+
17
+ end
18
+
19
+ end
20
+
21
+ Capistrano.plugin :service, Capsaicin::Service
@@ -0,0 +1,44 @@
1
+ module Capsaicin
2
+ module Service
3
+ module Command
4
+
5
+ # Check for the existance of a generic Windows NT service.
6
+ def command?(start, stop)
7
+ files.executable? start and files.executable? stop
8
+ end
9
+
10
+ # Defines a recipe to control a generic Windows NT service.
11
+ #
12
+ def command(id,start,stop,*args)
13
+ options = Hash===args.last ? args.pop : {}
14
+
15
+ svc_name = id.to_s
16
+ svc_desc = next_description(:reset) || (svc_name.capitalize unless options.delete(:hide))
17
+ extras = args.pop if Array === args.last
18
+ via = options.delete(:via)
19
+
20
+ namespace id do
21
+
22
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:start]}" if svc_desc
23
+ task :start, options do
24
+ send(via || fetch(:run_method, :local_run), start)
25
+ end
26
+
27
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:stop]}" if svc_desc
28
+ task :stop, options do
29
+ send(via || fetch(:run_method, :local_run), stop)
30
+ end
31
+
32
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:restart]}" if svc_desc
33
+ task :restart, options do
34
+ stop
35
+ start
36
+ end
37
+
38
+ instance_eval { yield } if block_given?
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,84 @@
1
+ module Capsaicin
2
+ module Service
3
+ module CRM
4
+
5
+ DEFAULT_ACTIONS = [ [ :status, '-W' ],
6
+ [ :summary, "-x | awk '/^raw xml:/ { exit }; { print }'" ],
7
+ [ :start, "--meta -d 'target_role'" ],
8
+ [ :stop, "--meta -p 'target_role' -v 'stopped'" ] ]
9
+
10
+ OCF_DEFAULT_ACTIONS = [ [ :validate, '-c -C' ],
11
+ [ :monitor, '-c -m' ] ]
12
+
13
+ # Defines a recipe to control a cluster-managed service, using heartbeat or pacemaker.
14
+ #
15
+ def crm(id,*args)
16
+ options = Hash===args.last ? args.pop : {}
17
+
18
+ svc_name = id.to_s
19
+ svc_desc = next_description(:reset) || (svc_name.capitalize unless options.delete(:hide))
20
+ svc_actions = DEFAULT_ACTIONS
21
+ svc_actions += args.pop if Array === args.last
22
+
23
+ namespace id do
24
+
25
+ case args.first
26
+ when String; id = args.shift.intern
27
+ when Symbol; id = args.shift
28
+ end
29
+ svc_cmd = "/usr/sbin/crm_resource -r #{id.to_s.split(':').last}"
30
+
31
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:status]}" if svc_desc
32
+ task :default, options do
33
+ sudo "#{svc_cmd} -W"
34
+ end
35
+
36
+ svc_actions.each do |svc_action,svc_args|
37
+ svc_action = svc_action.intern unless Symbol===svc_action
38
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[svc_action]}" if svc_desc
39
+ task svc_action, options do
40
+ sudo "#{svc_cmd} #{svc_args}"
41
+ end
42
+ end
43
+
44
+ instance_eval { yield } if block_given?
45
+ end
46
+ end
47
+
48
+ # Defines a recipe providing additional controls for a cluster-managed service,
49
+ # using the ocf_resource tool which interoperates with heartbeat or pacemaker.
50
+ #
51
+ # For more information about ocf_resource and other add-ons for heartbeat/pacemaker,
52
+ # see http://github.com/joekhoobyar/ha-tools
53
+ #
54
+ def crm_ocf(id,*args)
55
+ options = Hash===args.last ? args.pop : {}
56
+
57
+ svc_name = id.to_s
58
+ svc_desc = next_description(:reset) || (svc_name.capitalize unless options.delete(:hide))
59
+ svc_actions = DEFAULT_ACTIONS
60
+ svc_actions += args.pop if Array === args.last
61
+
62
+ namespace id do
63
+
64
+ case args.first
65
+ when String; id = args.shift.intern
66
+ when Symbol; id = args.shift
67
+ end
68
+ svc_cmd = "ocf_resource -g #{id.to_s.split(':').last}"
69
+
70
+ svc_actions.each do |svc_action,svc_args|
71
+ svc_action = svc_action.intern if String === svc_action
72
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[svc_action]}" if svc_desc
73
+ task svc_action, options do
74
+ sudo "#{svc_cmd} #{svc_args}"
75
+ end
76
+ end
77
+
78
+ instance_eval { yield } if block_given?
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,48 @@
1
+ module Capsaicin
2
+ module Service
3
+ module LSB
4
+
5
+ DEFAULT_ACTIONS = %w(status start stop restart)
6
+
7
+ # Check for the existance of a generic LSB initscript.
8
+ def lsb?(id, basedir="/etc/init.d")
9
+ files.exists? "#{basedir}/#{id.to_s.split(':').last}"
10
+ end
11
+
12
+ # Defines a recipe to control a generic LSB service.
13
+ #
14
+ def lsb(id,*args)
15
+ options = Hash===args.last ? args.pop : {}
16
+
17
+ basedir = options.delete(:basedir)
18
+ svc_name = id.to_s
19
+ svc_desc = next_description(:reset) || (svc_name.capitalize unless options.delete(:hide))
20
+ svc_actions = DEFAULT_ACTIONS
21
+ svc_actions += args.pop if Array === args.last
22
+
23
+ namespace id do
24
+ case args.first
25
+ when String; id = args.shift.intern
26
+ when Symbol; id = args.shift
27
+ end
28
+ svc_cmd = "#{basedir || '/etc/init.d'}/#{id.to_s.split(':').last}"
29
+
30
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:status]}" if svc_desc
31
+ task :default, options do
32
+ send(basedir ? run_method : :sudo, "#{svc_cmd} status")
33
+ end
34
+
35
+ svc_actions.each do |svc_action|
36
+ svc_action = svc_action.intern if String === svc_action
37
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[svc_action]}" if svc_desc
38
+ task svc_action, options do
39
+ send(basedir ? run_method : :sudo, "#{svc_cmd} #{svc_action}")
40
+ end
41
+ end
42
+
43
+ instance_eval { yield } if block_given?
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,62 @@
1
+ module Capsaicin
2
+ module Service
3
+ module Windows
4
+
5
+ DEFAULT_ACTIONS = [:start, :stop]
6
+
7
+ # Check for the existance of a generic Windows NT service.
8
+ def windows?(id, verbose=false)
9
+ logger.trace "executing locally: sc query \"#{id}\"" if logger and verbose
10
+ $1.to_i if `sc query "#{id}"` =~ /STATE +: +([0-9])+ +([^ ]+)/
11
+ ensure
12
+ logger.trace " service status => #{$2} (#{$1})" if logger and verbose
13
+ end
14
+
15
+ # Defines a recipe to control a generic Windows NT service.
16
+ #
17
+ def windows(id,*args)
18
+ options = Hash===args.last ? args.pop : {}
19
+
20
+ svc_name = id.to_s
21
+ svc_desc = next_description(:reset) || (svc_name.capitalize unless options.delete(:hide))
22
+ svc_actions = DEFAULT_ACTIONS
23
+ svc_actions += args.pop if Array === args.last
24
+
25
+ namespace id do
26
+ case args.first
27
+ when String; id = args.shift.intern
28
+ when Symbol; id = args.shift
29
+ end
30
+
31
+ [:default, :status].each do |k|
32
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:status]}" if svc_desc
33
+ task k, options do
34
+ service.windows? id, true or
35
+ abort "Failed to get service status for #{svc_name}"
36
+ end
37
+ end
38
+
39
+ DEFAULT_ACTIONS.each do |svc_action|
40
+ svc_action = svc_action.intern if String === svc_action
41
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[svc_action]}" if svc_desc
42
+ task svc_action, options do
43
+ local_run "net #{svc_action} \"#{id}\""
44
+ end
45
+ end
46
+
47
+ desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:restart]}" if svc_desc
48
+ task :restart, options do
49
+ case service.windows?(id)
50
+ when 4, 2; stop
51
+ when NilClass; abort "Failed to get service status for #{svc_name}"
52
+ end
53
+ start
54
+ end
55
+
56
+ instance_eval { yield } if block_given?
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,11 @@
1
+ module Capsaicin
2
+ module LocalSys
3
+
4
+ def windows?
5
+ @windows ||= !! (RUBY_PLATFORM =~ /cygwin|mingw|win32|mswin|windows/)
6
+ end
7
+
8
+ end
9
+
10
+ Capistrano.plugin :local_sys, LocalSys
11
+ end
@@ -0,0 +1,20 @@
1
+ module Capsaicin
2
+ module UI
3
+ module AskPass
4
+ def password_prompt(prompt='Password: ')
5
+ if cap_askpass = ENV['CAP_ASKPASS']
6
+ `#{cap_askpass} "#{prompt}"`.strip
7
+ else
8
+ password_prompt_console
9
+ end
10
+ end
11
+ end
12
+
13
+ (class << Capistrano::CLI; self; end).class_eval do
14
+ alias :password_prompt_console :password_prompt
15
+ include AskPass
16
+ alias :password_prompt_askpass :password_prompt
17
+ end
18
+ end
19
+ end
20
+
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capsaicin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Joe Khoobyar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-07 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "2.0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: archive-tar-minitar
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0.5"
34
+ version:
35
+ description: Spicy capistrano extensions for various needs
36
+ email: joe@ankhcraft.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - LICENSE
46
+ - README.rdoc
47
+ - Rakefile
48
+ - VERSION.yml
49
+ - lib/capsaicin.rb
50
+ - lib/capsaicin/bundle.rb
51
+ - lib/capsaicin/files.rb
52
+ - lib/capsaicin/files/local.rb
53
+ - lib/capsaicin/files/remote.rb
54
+ - lib/capsaicin/invocation.rb
55
+ - lib/capsaicin/service.rb
56
+ - lib/capsaicin/service/command.rb
57
+ - lib/capsaicin/service/crm.rb
58
+ - lib/capsaicin/service/lsb.rb
59
+ - lib/capsaicin/service/windows.rb
60
+ - lib/capsaicin/sys.rb
61
+ - lib/capsaicin/ui.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/joekhoobyar/capsaicin
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.2
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Joe Khoobyar's spicy capistrano extensions
90
+ test_files: []
91
+