capsaicin 0.1.9 → 0.1.10

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.
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ begin
15
15
  s.email = "joe@ankhcraft.com"
16
16
  s.rubyforge_project = "capsaicin"
17
17
 
18
- s.add_dependency 'capistrano', ['>= 2.0']
18
+ s.add_dependency 'capistrano', ['>= 2.5']
19
19
  s.add_dependency 'archive-tar-minitar', ['>= 0.5']
20
20
  end
21
21
  rescue LoadError
@@ -26,7 +26,6 @@ require 'rake/testtask'
26
26
  Rake::TestTask.new(:test) do |test|
27
27
  test.libs << 'test'
28
28
  test.pattern = 'test/**/*_test.rb'
29
- test.verbose = true
30
29
  end
31
30
 
32
31
  begin
@@ -34,7 +33,6 @@ begin
34
33
  Rcov::RcovTask.new do |test|
35
34
  test.libs << 'test'
36
35
  test.pattern = 'test/**/*_test.rb'
37
- test.verbose = true
38
36
  end
39
37
  rescue LoadError
40
38
  task :rcov do
@@ -2,4 +2,4 @@
2
2
  :major: 0
3
3
  :minor: 1
4
4
  :build:
5
- :patch: 9
5
+ :patch: 10
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{capsaicin}
8
- s.version = "0.1.9"
8
+ s.version = "0.1.10"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Joe Khoobyar"]
12
- s.date = %q{2010-06-15}
12
+ s.date = %q{2010-06-16}
13
13
  s.description = %q{Spicy capistrano extensions for various needs}
14
14
  s.email = %q{joe@ankhcraft.com}
15
15
  s.extra_rdoc_files = [
@@ -39,6 +39,7 @@ Gem::Specification.new do |s|
39
39
  "lib/capsaicin/sys.rb",
40
40
  "lib/capsaicin/ui.rb",
41
41
  "test/capsaicin/files/local_test.rb",
42
+ "test/capsaicin/invocation_test.rb",
42
43
  "test/helper.rb"
43
44
  ]
44
45
  s.homepage = %q{http://github.com/joekhoobyar/capsaicin}
@@ -49,6 +50,7 @@ Gem::Specification.new do |s|
49
50
  s.summary = %q{Joe Khoobyar's spicy capistrano extensions}
50
51
  s.test_files = [
51
52
  "test/capsaicin/files/local_test.rb",
53
+ "test/capsaicin/invocation_test.rb",
52
54
  "test/helper.rb"
53
55
  ]
54
56
 
@@ -57,14 +59,14 @@ Gem::Specification.new do |s|
57
59
  s.specification_version = 3
58
60
 
59
61
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
60
- s.add_runtime_dependency(%q<capistrano>, [">= 2.0"])
62
+ s.add_runtime_dependency(%q<capistrano>, [">= 2.5"])
61
63
  s.add_runtime_dependency(%q<archive-tar-minitar>, [">= 0.5"])
62
64
  else
63
- s.add_dependency(%q<capistrano>, [">= 2.0"])
65
+ s.add_dependency(%q<capistrano>, [">= 2.5"])
64
66
  s.add_dependency(%q<archive-tar-minitar>, [">= 0.5"])
65
67
  end
66
68
  else
67
- s.add_dependency(%q<capistrano>, [">= 2.0"])
69
+ s.add_dependency(%q<capistrano>, [">= 2.5"])
68
70
  s.add_dependency(%q<archive-tar-minitar>, [">= 0.5"])
69
71
  end
70
72
  end
@@ -28,9 +28,6 @@ module Capistrano # :nodoc:
28
28
  FileUtils.rm_rf destination rescue nil
29
29
  end
30
30
 
31
- def check! # :nodoc:
32
- end
33
-
34
31
  private
35
32
 
36
33
  def local_copy_dir # :nodoc:
@@ -17,6 +17,14 @@ module Capsaicin
17
17
  end
18
18
  end
19
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
+
20
28
  def chmod(mode, list, options={})
21
29
  _r 'chmod', Array(list).unshift(mode.to_s(8))
22
30
  end
@@ -36,14 +44,6 @@ module Capsaicin
36
44
  _r 'install', src.push(dest)
37
45
  end
38
46
 
39
- FILE_TESTS.each do |m,t|
40
- class_eval <<-EODEF
41
- def #{m}(a, options={})
42
- _t "test #{t}", a
43
- end
44
- EODEF
45
- end
46
-
47
47
  def tail_f(file, n=10)
48
48
  cmd = "tail -n #{n} -f #{_q file}"
49
49
  case v = _via
@@ -56,6 +56,15 @@ module Capsaicin
56
56
  logger.trace "interrupted (Ctrl-C)" if logger
57
57
  end
58
58
 
59
+ def put(data, path, options={})
60
+ case _via
61
+ when :system, :local_run
62
+ FileUtils::Verbose.copy_stream StringIO.new(from), to
63
+ else
64
+ upload StringIO.new(data), path, options
65
+ end
66
+ end
67
+
59
68
  def upload(from, to, options={}, &block)
60
69
  case _via
61
70
  when :system, :local_run
@@ -70,11 +79,20 @@ module Capsaicin
70
79
  to2, to = to, "/tmp/#{tof}-#{Time.now.utc.to_i}"
71
80
  end
72
81
  end
82
+ options = options.dup
83
+ mode = options.delete(:mode)
73
84
  @config.upload(from, to, options, &block)
74
85
  if to2
75
- run "chmod 0644 #{to}"
76
- cp to, to2
77
- run "rm -f #{to}"
86
+ begin
87
+ run "chmod 0644 #{to}", :via=>:run
88
+ cp to, to2
89
+ if mode
90
+ mode = mode.is_a?(Numeric) ? '0'+mode.to_s(8) : mode.to_s
91
+ run "chmod #{mode} #{to2}"
92
+ end
93
+ ensure
94
+ run "rm -f #{to}", :via=>:run
95
+ end
78
96
  end
79
97
  end
80
98
  end
@@ -88,28 +106,6 @@ module Capsaicin
88
106
  end
89
107
  end
90
108
 
91
- def put(data, path, options={})
92
- case _via
93
- when :system, :local_run
94
- FileUtils::Verbose.copy_stream StringIO.new(from), to
95
- else
96
- if _via.to_s[0,4] == 'sudo'
97
- if path[-1]==?/ || path[-1]==?\\ || directory?(path)
98
- abort "Target path is a directory!"
99
- else
100
- pathf = File.basename path
101
- path2, path = path, "/tmp/#{pathf}-#{Time.now.utc.to_i}"
102
- end
103
- end
104
- @config.put(data, path, options)
105
- if path2
106
- run "chmod 0644 #{path}"
107
- cp path, path2
108
- run "rm -f #{path}"
109
- end
110
- end
111
- end
112
-
113
109
  def cd(dir, options={})
114
110
  if block_given?
115
111
  dir, dir2 = pwd, dir
@@ -1,28 +1,62 @@
1
1
  module Capsaicin
2
2
 
3
3
  module Invocation
4
-
4
+
5
+ def self.included(base)
6
+ [:run, :sudo].each do |k|
7
+ base.send :alias_method, :"#{k}_without_override", k
8
+ base.send :alias_method, k, :"#{k}_with_override"
9
+ end
10
+ end
11
+
12
+ # Allows overriding the default behavior of +run+ by setting
13
+ # :override_run_method and (optionally) :override_runner
14
+ def run_with_override(cmd, options={}, &block)
15
+ via = options[:via] || fetch(:override_run_method, :run)
16
+ if cmd.include?(sudo) or :run == via
17
+ run_without_override cmd, options, &block
18
+ else
19
+ options = options.dup
20
+ as = fetch(:override_runner, nil) and options[:as] ||= as
21
+ send via, cmd, options, &block
22
+ end
23
+ end
24
+
25
+ # Allows overriding the default behavior of +sudo+ by setting
26
+ # :override_sudo_method and (optionally) :override_sudo_runner
27
+ def sudo_with_override(*args, &block)
28
+ options = Hash===args.last ? args.pop.dup : {}
29
+ as = fetch(:override_sudo_runner, nil) and options[:as] ||= as
30
+ args << options unless options.empty?
31
+ if :sudo == (via = fetch(:override_sudo_method, :sudo))
32
+ options[:via] = :run
33
+ sudo_without_override *args, &block
34
+ else
35
+ send via, *args, &block
36
+ end
37
+ end
38
+
5
39
  # Automatically uses the :run_method variable to run things.
6
40
  # Equivalent to +invoke_command *args, :via=>fetch(:run_method, :run)+
7
41
  def vrun(*args, &block)
8
- options = Hash===args.last ? args.pop.dup : {}
9
- options[:via] = fetch(:run_method, :run)
42
+ options = Hash===args.last ? args.pop.dup : {}
43
+ options[:via] ||= fetch(:run_method, :run)
10
44
  invoke_command *args.push(options), &block
11
45
  end
12
46
 
13
47
  # Automatically uses the :run_method variable to run things.
14
48
  # Equivalent to +capture *args, :via=>fetch(:run_method, :run)+
15
49
  def vcapture(*args, &block)
16
- options = Hash===args.last ? args.pop.dup : {}
17
- options[:via] = fetch(:run_method, :run)
50
+ options = Hash===args.last ? args.pop.dup : {}
51
+ options[:via] ||= fetch(:run_method, :run)
18
52
  capture *args.push(options), &block
19
53
  end
20
54
 
21
55
  # Automatically uses the :run_method variable to run things.
22
56
  # Equivalent to +stream *args, :via=>fetch(:run_method, :run)+
23
57
  def vstream(*args, &block)
24
- options = Hash===args.last ? args.pop.dup : {}
25
- options[:via] = fetch(:run_method, :run)
58
+ options = Hash===args.last ? args.pop.dup : {}
59
+ options[:via] ||= fetch(:run_method, :run)
26
60
  stream *args.push(options), &block
27
61
  end
28
62
 
@@ -46,25 +80,29 @@ module Capsaicin
46
80
  # Always uses :runner to sudo as someone.
47
81
  # Equivalent to: sudo "command", :as => fetch(:runner,nil)
48
82
  def sudo_as(*args, &block)
49
- options = Hash===args.last ? args.pop.dup : {}
50
- options[:as] = fetch(:runner, nil)
51
- sudo *args.push(options), &block
83
+ options = Hash===args.last ? args.pop.dup : {}
84
+ options[:as] ||= fetch(:runner, nil)
85
+ sudo_without_override *args.push(options), &block
52
86
  end
53
87
 
54
- # Extremely helpful if you only have permission to: sudo su SOMEUSER -c "command"
88
+ # Extremely helpful if you only have permission to: sudo su SOMEUSER -c 'command'
55
89
  def sudo_su(*args, &block)
56
- options = Hash===args.last ? args.pop.dup : {}
57
- args[0] = "su #{fetch(:runner, nil)} -c '#{args[0]}'"
58
- sudo *args.push(options), &block
90
+ options = Hash===args.last ? args.pop.dup : {}
91
+ options[:as] ||= fetch(:runner, nil)
92
+ return sudo_as(options, &block) if args.empty? # compatibility with capistrano's +sudo+
93
+ args[0] = "su #{options.delete(:as)} -c '#{args[0].gsub("'","'\"'\"'")}'"
94
+ sudo_without_override *args.push(options), &block
59
95
  end
60
96
 
61
97
  # Extremely helpful if you only have permission to: sudo su - SOMEUSER
62
98
  def sudo_su_to(*args, &block)
63
- options = Hash===args.last ? args.pop.dup : {}
99
+ options = Hash===args.last ? args.pop.dup : {}
100
+ options[:as] ||= fetch(:runner, nil)
101
+ return sudo_as(options, &block) if args.empty? # compatibility with capistrano's +sudo+
64
102
  options[:shell] = false
65
- cmd = args[0].gsub(/[$\\`"]/) { |m| "\\#{m}" }
66
- args[0] = "echo \"#{cmd}\" | #{sudo} su - #{fetch(:runner, nil)}"
67
- run *args.push(options), &block
103
+ cmd = args[0].gsub(/[$\\`"]/) { |m| "\\#{m}" }
104
+ args[0] = "echo \"#{cmd}\" | #{sudo_without_override} su - #{options.delete(:as)}"
105
+ run_without_override *args.push(options), &block
68
106
  end
69
107
  end
70
108
  end
@@ -2,12 +2,12 @@ module Capsaicin
2
2
  module Service
3
3
  module Command
4
4
 
5
- # Check for the existance of a generic Windows NT service.
5
+ # Check for the existance of a command-based service.
6
6
  def command?(start, stop)
7
7
  files.executable? start and files.executable? stop
8
8
  end
9
9
 
10
- # Defines a recipe to control a generic Windows NT service.
10
+ # Defines a recipe to control a command-based service.
11
11
  #
12
12
  def command(id,start,stop,*args)
13
13
  options = Hash===args.last ? args.pop : {}
@@ -21,12 +21,12 @@ module Capsaicin
21
21
 
22
22
  desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:start]}" if svc_desc
23
23
  task :start, options do
24
- send(via || fetch(:run_method, :local_run), start)
24
+ send(via || fetch(:run_method, :run), start)
25
25
  end
26
26
 
27
27
  desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[:stop]}" if svc_desc
28
28
  task :stop, options do
29
- send(via || fetch(:run_method, :local_run), stop)
29
+ send(via || fetch(:run_method, :run), stop)
30
30
  end
31
31
 
32
32
  unless extras.key? :restart
@@ -40,7 +40,7 @@ module Capsaicin
40
40
  extras.each do |k,cmd|
41
41
  desc "#{svc_desc}: #{SVC_ACTION_CAPTIONS[k]}" if svc_desc
42
42
  task k, options do
43
- send(via || fetch(:run_method, :local_run), cmd)
43
+ send(via || fetch(:run_method, :run), cmd)
44
44
  end
45
45
  end
46
46
 
@@ -0,0 +1,112 @@
1
+ require 'helper'
2
+ require 'tmpdir'
3
+ require 'capsaicin/invocation'
4
+
5
+ class Capsaicin::InvocationTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @ext = CapistranoMock.new
9
+ class << @ext
10
+ include Capsaicin::Invocation
11
+ end
12
+ end
13
+
14
+ def teardown
15
+ end
16
+
17
+ def test_vrun
18
+ check_run_methods :vrun, :invoke_command
19
+ end
20
+
21
+ def test_vcapture
22
+ check_run_methods :vcapture, :capture
23
+ end
24
+
25
+ def test_vstream
26
+ check_run_methods :vstream, :stream
27
+ end
28
+
29
+ def test_sudo_as
30
+ check_as_methods :sudo_as, :sudo
31
+ end
32
+
33
+ def test_sudo_su
34
+ check_as_methods(:sudo_su, :sudo) {|c,as| ["su #{as} -c '#{c}'", {}] }
35
+ end
36
+
37
+ def test_sudo_su_escapes_single_quotes
38
+ check_as_methods(:sudo_su, :sudo,"echo 'abc'") do |c,as|
39
+ ["su #{as} -c 'echo '\"'\"'abc'\"'\"''", {}]
40
+ end
41
+ end
42
+
43
+ def test_sudo_su_to
44
+ check_as_methods(:sudo_su_to, :run) do |c,as|
45
+ ["echo \"uptime\" | sudo su - #{as}", {:shell=>false}]
46
+ end
47
+ end
48
+
49
+ def test_run_without_override
50
+ @ext.run 'uptime'
51
+ assert_equal [%w(uptime) << {}], @ext.invocations[:run].last
52
+ end
53
+
54
+ def test_run_with_override
55
+ @ext.set :override_run_method, :sudo
56
+ @ext.set :override_runnner, :admin
57
+ @ext.run 'uptime'
58
+ assert_equal [%w(uptime)], @ext.invocations[:sudo].last
59
+ end
60
+
61
+ def test_sudo_without_override
62
+ @ext.sudo 'uptime'
63
+ assert_equal [%w(uptime)], @ext.invocations[:sudo].last
64
+ end
65
+
66
+ def test_sudo_with_override
67
+ @ext.set :override_sudo_method, :sudo_as
68
+ @ext.set :override_sudo_runner, :admin
69
+ @ext.sudo 'uptime'
70
+ assert_equal [%w(uptime) << {:as=>:admin}], @ext.invocations[:sudo].last
71
+ @ext.set :override_sudo_method, :sudo_su_to
72
+ @ext.sudo 'uptime'
73
+ assert_equal [["echo \"uptime\" | sudo su - admin", {:shell=>false}]], @ext.invocations[:run].last
74
+ end
75
+
76
+ private
77
+
78
+ def check_run_methods(method,key)
79
+ [:run, :sudo].each do |via|
80
+ @ext.send method, 'uptime'
81
+ assert_equal [%w(uptime) << {:via=>via}], @ext.invocations[key].last
82
+ @ext.set :run_method, :sudo
83
+ end
84
+ [:sudo, :run].each do |via|
85
+ @ext.send method, 'uptime', &block=Proc.new{}
86
+ assert_equal [%w(uptime) << {:via=>via}, block], @ext.invocations[key].last
87
+ @ext.unset :run_method
88
+ end
89
+ @ext.send method, 'uptime', :via=>:sudo
90
+ assert_equal [%w(uptime) << {:via=>:sudo}], @ext.invocations[key].last
91
+ end
92
+
93
+ def check_as_methods(method,key,cmd='uptime',&p)
94
+ p ||= lambda{|c,as| [c, {:as=>as}] }
95
+ [nil, :admin].each do |as|
96
+ @ext.send method,cmd
97
+ assert_equal [p[cmd,as]], @ext.invocations[key].last
98
+ @ext.set :runner, :admin
99
+ end
100
+ @ext.send method, cmd, :as=>:busybody
101
+ assert_equal [p[cmd,:busybody]], @ext.invocations[key].last
102
+ [:admin, nil].each do |as|
103
+ @ext.send method, cmd, &block=Proc.new{}
104
+ assert_equal [p[cmd,as], block], @ext.invocations[key].last
105
+ @ext.unset :runner
106
+ end
107
+ @ext.send method, cmd, :as=>:busybody
108
+ assert_equal [p[cmd,:busybody]], @ext.invocations[key].last
109
+ @ext.send method, :as=>:busybody
110
+ assert_equal [[{:as=>:busybody}]], @ext.invocations[:sudo].last
111
+ end
112
+ end
@@ -2,9 +2,14 @@ require 'stringio'
2
2
  require 'test/unit'
3
3
  require 'rubygems'
4
4
  require 'capistrano/logger'
5
+ require 'capistrano/configuration/variables'
5
6
 
6
7
  class CapistranoMock
7
8
 
9
+ include Capistrano::Configuration::Variables
10
+
11
+ attr_reader :invocations
12
+
8
13
  def logbuf
9
14
  @logbuf ||= StringIO.new
10
15
  end
@@ -17,4 +22,21 @@ class CapistranoMock
17
22
  @logger
18
23
  end
19
24
 
25
+ %w(invoke_command capture stream run).each do |k|
26
+ class_eval %Q{
27
+ def #{k}(*args, &block)
28
+ args = [args]
29
+ args << block if block
30
+ ((@invocations ||= {})[:#{k}] ||= []) << args
31
+ end
32
+ }
33
+ end
34
+
35
+ def sudo(*args, &block)
36
+ return 'sudo' if args.empty?
37
+ args = [args]
38
+ args << block if block
39
+ ((@invocations ||= {})[:sudo] ||= []) << args
40
+ end
41
+
20
42
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 9
9
- version: 0.1.9
8
+ - 10
9
+ version: 0.1.10
10
10
  platform: ruby
11
11
  authors:
12
12
  - Joe Khoobyar
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-15 00:00:00 -04:00
17
+ date: 2010-06-16 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -26,8 +26,8 @@ dependencies:
26
26
  - !ruby/object:Gem::Version
27
27
  segments:
28
28
  - 2
29
- - 0
30
- version: "2.0"
29
+ - 5
30
+ version: "2.5"
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
33
  - !ruby/object:Gem::Dependency
@@ -75,6 +75,7 @@ files:
75
75
  - lib/capsaicin/sys.rb
76
76
  - lib/capsaicin/ui.rb
77
77
  - test/capsaicin/files/local_test.rb
78
+ - test/capsaicin/invocation_test.rb
78
79
  - test/helper.rb
79
80
  has_rdoc: true
80
81
  homepage: http://github.com/joekhoobyar/capsaicin
@@ -108,4 +109,5 @@ specification_version: 3
108
109
  summary: Joe Khoobyar's spicy capistrano extensions
109
110
  test_files:
110
111
  - test/capsaicin/files/local_test.rb
112
+ - test/capsaicin/invocation_test.rb
111
113
  - test/helper.rb