screwcap 0.7.4 → 0.8

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/.gemtest ADDED
File without changes
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ Hoe.plugin :newgem
11
11
  # Generate all the Rake tasks
12
12
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
13
  $hoe = Hoe.spec 'screwcap' do
14
- self.version = '0.7.4'
14
+ self.version = '0.8'
15
15
  self.developer 'Grant Ammons', 'grant@pipelinedeals.com'
16
16
  self.rubyforge_name = self.name # TODO this is default value
17
17
  self.extra_deps = [['net-ssh','>= 2.0.23'],['net-ssh-gateway','>=1.0.1'], ['net-scp','>=1.0.4']]
data/lib/screwcap.rb CHANGED
@@ -16,7 +16,7 @@ require 'screwcap/sequence'
16
16
  require 'screwcap/task_manager'
17
17
 
18
18
  module Screwcap
19
- VERSION='0.7.4'
19
+ VERSION='0.8'
20
20
 
21
21
  class TaskNotFound < RuntimeError; end
22
22
  class NoServersDefined < Exception; end
@@ -6,18 +6,15 @@ class Runner
6
6
  @@silent = options[:silent]
7
7
  @@verbose = options[:verbose]
8
8
  task = options[:task]
9
+ results = []
9
10
 
10
11
  if (task.__servers.nil? or task.__servers == [] or task.__servers.compact == []) and task.__built_commands.any? {|c| c[:type] == :remote or c[:type] == :scp }
11
12
  raise Screwcap::ConfigurationError, "The task #{task.name} includes remote commands, however no servers were defined for this task."
12
13
  end
13
14
 
14
15
  if options[:servers] and task.__servers
15
- begin
16
- servers = options[:servers].select {|s| task.__servers.include? s.__name }
17
- connections = servers.map {|server| server.connect! }.flatten
18
- rescue Net::SSH::AuthenticationFailed => e
19
- raise Net::SSH::AuthenticationFailed, "Authentication failed for server named #{server.name}. Please check your authentication credentials."
20
- end
16
+ servers = options[:servers].select {|s| task.__servers.include? s.__name }
17
+ connections = servers.map {|server| server.connect! }.flatten
21
18
  end
22
19
 
23
20
  _log "\nExecuting task #{task.name}\n", :color => :blue
@@ -25,20 +22,33 @@ class Runner
25
22
  task.__built_commands.each do |command|
26
23
  ret = case command[:type]
27
24
  when :remote
28
- threads = []
29
- if command[:parallel] == false
30
- connections.each { |connection| run_remote_command(command, connection, options) }
25
+ if command[:parallel] == false or command[:block]
26
+ connections.each do |connection|
27
+ results << run_remote_command(command, connection[:connection], options)
28
+ if command[:block]
29
+ opts = task.__options.clone.merge(:stderr => command[:stderr], :stdout => command[:stdout], :exit_code => command[:exit_code])
30
+ opts[:servers] = task.__servers
31
+ opts[:name] = "Run results"
32
+
33
+ inner_task = Task.new(opts, &command[:block])
34
+ inner_task.__build_commands(options[:tasks])
35
+ results << self.execute!(options.merge(:task => inner_task))
36
+ end
37
+ end
31
38
  else
39
+ threads = []
32
40
  connections.each do |connection|
33
41
  threads << Thread.new(connection) do |conn|
34
- run_remote_command(command, conn, options)
42
+ results << run_remote_command(command, conn[:connection], options)
35
43
  end
36
44
  end
37
45
  threads.each {|t| t.join }
38
46
  end
39
47
  when :local
40
- ret = `#{command[:command]}`
41
- command[:stdout] = ret
48
+ result = {}
49
+ result[:stdout] = `#{command[:command]}`
50
+ result[:exit_code] = $?.to_i
51
+ results << result
42
52
  if $?.to_i == 0
43
53
  if options[:verbose]
44
54
  _log " O: #{ret}\n", :color => :green
@@ -48,7 +58,6 @@ class Runner
48
58
  else
49
59
  _errorlog(" E: (local): #{command[:command]} return exit code: #{$?}\n", :color => :red) if $? != 0
50
60
  end
51
- ret
52
61
  when :scp
53
62
  threads = []
54
63
  servers.each do |server|
@@ -59,29 +68,30 @@ class Runner
59
68
  command[:block].call
60
69
  end
61
70
  end
62
- _log "\nComplete\n", :color => :blue
63
- task.__built_commands # for tests
71
+ _log "Complete\n", :color => :blue
72
+ results
64
73
  end
65
74
 
66
75
  private
67
76
 
68
77
  def self.run_remote_command(command, ssh, options)
69
78
  stdout, stderr, exit_code, exit_signal = ssh_exec! ssh, command[:command]
70
- command[:stdout] = stdout
71
- command[:stderr] = stderr
72
- command[:exit_code] = exit_code
79
+ ret = {:command => command[:command]}
80
+ ret[:stdout] = command[:stdout] = stdout
81
+ ret[:stderr] = command[:stderr] = stderr
82
+ ret[:exit_code] = command[:exit_code] = exit_code
73
83
  if exit_code == 0
74
84
  if @@verbose
75
85
  _log(" I: #{command[:command]}\n", :color => :green)
76
86
  _log(" O: #{command[:stdout]}\n", :color => :green)
77
87
  else
78
88
  _log(".", :color => :green)
79
- $stdout.flush
80
89
  end
81
90
  else
82
- _errorlog(" E: (#{options[:address]}): #{command[:command]} return exit code: #{exit_code}\n", :color => :red) if exit_code != 0
91
+ _log(" I: #{command[:command]}\n", :color => :green)
92
+ _errorlog(" E: (exit code: #{exit_code}) #{command[:stderr]} \n", :color => :red)
83
93
  end
84
- exit_code
94
+ ret
85
95
  end
86
96
 
87
97
  # courtesy of flitzwald on stackoverflow
@@ -36,10 +36,18 @@ class Server < Screwcap::Base
36
36
 
37
37
  def connect!
38
38
  self.__addresses.each do |address|
39
- if self.__gateway
40
- self.__connections << __gateway.__get_gateway_connection.ssh(address, self.__user, options_for_net_ssh)
41
- else
42
- self.__connections << Net::SSH.start(address, self.__user, options_for_net_ssh)
39
+
40
+ # do not re-connect. return if we have already been connected
41
+ next if self.__connections.any? {|conn| conn[:address] == address }
42
+
43
+ begin
44
+ if self.__gateway
45
+ self.__connections << {:address => address, :connection => __gateway.__get_gateway_connection.ssh(address, self.__user, options_for_net_ssh) }
46
+ else
47
+ self.__connections << {:address => address, :connection => Net::SSH.start(address, self.__user, options_for_net_ssh) }
48
+ end
49
+ rescue Net::SSH::AuthenticationFailed => e
50
+ raise Net::SSH::AuthenticationFailed, "Authentication failed for server named #{self.name}. Please check your authentication credentials."
43
51
  end
44
52
  end
45
53
  self.__connections
data/lib/screwcap/task.rb CHANGED
@@ -47,11 +47,11 @@ class Task < Screwcap::Base
47
47
  # run "ls -l", :onfailure => :rollback
48
48
  # end
49
49
 
50
- def run arg, options = {}
50
+ def run arg, options = {}, &block
51
51
  if arg.class == Symbol
52
- self.__commands << options.merge({:command => self.send(arg), :type => :remote, :from => self.__name})
52
+ self.__commands << options.merge({:command => self.send(arg), :type => :remote, :from => self.__name, :block => block})
53
53
  else
54
- self.__commands << options.merge({:command => arg, :type => :remote, :from => self.__name})
54
+ self.__commands << options.merge({:command => arg, :type => :remote, :from => self.__name, :block => block})
55
55
  end
56
56
  end
57
57
 
@@ -221,6 +221,19 @@ class Task < Screwcap::Base
221
221
  self.__servers = [self.__servers] if self.__servers.class != Array
222
222
  end
223
223
 
224
+ # convenience function to look at the exit status of a parent task
225
+ def exit_code
226
+ self.__options[:exit_code]
227
+ end
228
+
229
+ def stdout
230
+ self.__options[:stdout]
231
+ end
232
+
233
+ def stderr
234
+ self.__options[:stderr]
235
+ end
236
+
224
237
  private
225
238
 
226
239
  def method_missing(m, *args) # :nodoc
@@ -182,7 +182,7 @@ class TaskManager < Screwcap::Base
182
182
  ret = []
183
183
  tasks_to_run.each do |task|
184
184
  ret << task.__build_commands(self.__tasks)
185
- Runner.execute!(:task => task, :servers => self.__servers, :silent => self.__options[:silent], :verbose => self.__options[:verbose])
185
+ Runner.execute!(:task => task, :tasks => self.__tasks, :servers => self.__servers, :silent => self.__options[:silent], :verbose => self.__options[:verbose])
186
186
  end
187
187
 
188
188
  $stdout << "\033[0m"
data/screwcap.gemspec CHANGED
@@ -6,7 +6,7 @@ require 'bundler/version'
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "screwcap"
9
- s.version = "0.7.4"
9
+ s.version = "0.8"
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.author = "Grant Ammons"
12
12
  s.email = ["grant@pipelinedealsco.com"]
data/spec/runner_spec.rb CHANGED
@@ -64,4 +64,38 @@ describe "The Runner" do
64
64
  :silent => true
65
65
  @@testvar.should == :bango
66
66
  end
67
+
68
+ it "should yield a run block" do
69
+ Runner.stubs(:ssh_exec!).returns(["ok\n","",0,nil]).then.returns(["","no\n",1,nil])
70
+ revert_task = Task.new :name => :revert do
71
+ run "revert" do |results|
72
+ if results.exit_code != 0
73
+ run "failed"
74
+ else
75
+ run "succeeded"
76
+ end
77
+ end
78
+ end
79
+ task = Task.new :name => :runblock, :server => :server do
80
+ run "do_something" do |results|
81
+ revert
82
+ end
83
+ end
84
+ task.__build_commands
85
+ task.validate([@server])
86
+ commands = Runner.execute! :name => :runblock, :task => task, :tasks => [task, revert_task], :servers => [@server], :silent => true
87
+ command_names(commands).should == %w(do_something revert failed)
88
+ end
89
+ end
90
+
91
+ def command_names(commands)
92
+ ret = []
93
+ commands.each do |command|
94
+ if command.class == Hash
95
+ ret << command[:command]
96
+ elsif command.class == Array
97
+ ret << command_names(command)
98
+ end
99
+ end
100
+ ret.flatten
67
101
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: screwcap
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 7
9
- - 4
10
- version: 0.7.4
8
+ - 8
9
+ version: "0.8"
11
10
  platform: ruby
12
11
  authors:
13
12
  - Grant Ammons
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-03-30 00:00:00 -04:00
17
+ date: 2011-04-16 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -67,37 +66,21 @@ dependencies:
67
66
  type: :runtime
68
67
  version_requirements: *id003
69
68
  - !ruby/object:Gem::Dependency
70
- name: rubyforge
69
+ name: hoe
71
70
  prerelease: false
72
71
  requirement: &id004 !ruby/object:Gem::Requirement
73
72
  none: false
74
73
  requirements:
75
74
  - - ">="
76
75
  - !ruby/object:Gem::Version
77
- hash: 7
76
+ hash: 35
78
77
  segments:
79
78
  - 2
80
- - 0
79
+ - 9
81
80
  - 4
82
- version: 2.0.4
81
+ version: 2.9.4
83
82
  type: :development
84
83
  version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: hoe
87
- prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 19
94
- segments:
95
- - 2
96
- - 7
97
- - 0
98
- version: 2.7.0
99
- type: :development
100
- version_requirements: *id005
101
84
  description: Screwcap is a library that wraps Net::SSH and makes it easy to perform actions on remote servers.
102
85
  email:
103
86
  - grant@pipelinedeals.com
@@ -150,6 +133,7 @@ files:
150
133
  - test/config/upload.rb
151
134
  - test/config/use.rb
152
135
  - test/config/use2.rb
136
+ - .gemtest
153
137
  has_rdoc: true
154
138
  homepage: http://gammons.github.com/screwcap
155
139
  licenses: []