teuton 3.2.0 → 3.3.0
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.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/bin/teuton +2 -3
- data/docs/commands/README.md +8 -7
- data/docs/commands/check.md +17 -15
- data/docs/commands/help.md +17 -7
- data/docs/commands/readme.md +1 -1
- data/docs/devel/todo.md +74 -4
- data/docs/dsl/send.md +3 -3
- data/docs/dsl/show.md +2 -2
- data/docs/dsl/target.md +0 -14
- data/docs/install/t-node.md +10 -21
- data/docs/learn/02-target.md +49 -47
- data/docs/learn/03-remote_hosts.md +14 -15
- data/docs/learn/04-config.md +67 -68
- data/docs/learn/06-cmd_check.md +26 -24
- data/docs/learn/07-target_weight.md +3 -3
- data/docs/learn/08-unique_values.md +31 -29
- data/docs/learn/10-debug.md +36 -0
- data/docs/learn/13-feedback.md +10 -9
- data/docs/learn/15-readme.md +2 -2
- data/docs/learn/16-include.md +7 -7
- data/docs/learn/18-log.md +44 -43
- data/docs/learn/23-test-code.md +13 -10
- data/docs/learn/24-test-sql.md +5 -5
- data/docs/learn/26-expect_sequence.md +1 -1
- data/docs/learn/27-run_script.md +8 -5
- data/lib/teuton/case/action/action.rb +39 -0
- data/lib/teuton/case/action/manager.rb +63 -0
- data/lib/teuton/case/case.rb +17 -21
- data/lib/teuton/case/close.rb +3 -3
- data/lib/teuton/case/dsl/all.rb +1 -0
- data/lib/teuton/case/dsl/event.rb +24 -0
- data/lib/teuton/case/dsl/expect.rb +13 -12
- data/lib/teuton/case/dsl/expect_sequence.rb +1 -2
- data/lib/teuton/case/dsl/log.rb +3 -7
- data/lib/teuton/case/dsl/macro.rb +3 -2
- data/lib/teuton/case/dsl/run.rb +11 -17
- data/lib/teuton/case/dsl/send.rb +1 -17
- data/lib/teuton/case/dsl/target.rb +8 -4
- data/lib/teuton/case/dsl/upload.rb +1 -4
- data/lib/teuton/case/dsl/weight.rb +3 -3
- data/lib/teuton/case/execute/execute_base.rb +1 -1
- data/lib/teuton/case/execute/execute_local.rb +2 -2
- data/lib/teuton/case/execute/execute_manager.rb +6 -6
- data/lib/teuton/case/execute/execute_ssh.rb +6 -6
- data/lib/teuton/case/execute/execute_telnet.rb +4 -4
- data/lib/teuton/case/play.rb +8 -9
- data/lib/teuton/case/result/ext_compare.rb +10 -10
- data/lib/teuton/case_manager/case_manager.rb +4 -4
- data/lib/teuton/case_manager/dsl.rb +11 -10
- data/lib/teuton/case_manager/export_manager.rb +6 -12
- data/lib/teuton/case_manager/ext/check_cases.rb +1 -1
- data/lib/teuton/case_manager/ext/report.rb +0 -4
- data/lib/teuton/case_manager/show_resume_report.rb +29 -30
- data/lib/teuton/check/checker.rb +17 -8
- data/lib/teuton/check/dsl/all.rb +18 -10
- data/lib/teuton/check/dsl/expect.rb +29 -45
- data/lib/teuton/check/dsl/getset.rb +2 -2
- data/lib/teuton/check/dsl/run.rb +2 -2
- data/lib/teuton/check/show.rb +28 -34
- data/lib/teuton/cli/app.rb +123 -0
- data/lib/teuton/cli/run.rb +38 -0
- data/lib/teuton/errors.rb +94 -0
- data/lib/teuton/readme/action.rb +29 -0
- data/lib/teuton/readme/dsl/all.rb +17 -6
- data/lib/teuton/readme/dsl/expect.rb +3 -3
- data/lib/teuton/readme/dsl/run.rb +5 -11
- data/lib/teuton/readme/main.rb +13 -6
- data/lib/teuton/readme/readme.rb +12 -15
- data/lib/teuton/report/formatter/default/array.rb +15 -29
- data/lib/teuton/report/formatter/default/txt.rb +43 -32
- data/lib/teuton/report/formatter/formatter.rb +4 -13
- data/lib/teuton/report/formatter/resume/txt.rb +29 -28
- data/lib/teuton/report/formatter/resume/xml.rb +4 -4
- data/lib/teuton/report/report.rb +3 -1
- data/lib/teuton/utils/config_file_reader.rb +3 -11
- data/lib/teuton/utils/logger.rb +15 -10
- data/lib/teuton/utils/name_file_finder.rb +3 -11
- data/lib/teuton/utils/project.rb +4 -3
- data/lib/teuton/version.rb +1 -1
- data/lib/teuton.rb +6 -11
- metadata +8 -5
- data/docs/tutorial/es/nginx/README.md +0 -546
- data/lib/teuton/cli.rb +0 -120
- data/lib/teuton/deprecated/utils.rb +0 -14
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class Case
|
|
2
|
+
class Action
|
|
3
|
+
attr_reader :id
|
|
4
|
+
attr_accessor :groupname, :description, :weight,
|
|
5
|
+
:command, :encoding, :host, :exec,
|
|
6
|
+
:conn_type, :duration,
|
|
7
|
+
:result, :output,
|
|
8
|
+
:alterations, :expected, :check
|
|
9
|
+
attr_writer :score
|
|
10
|
+
|
|
11
|
+
def initialize(id = 1)
|
|
12
|
+
@id = id
|
|
13
|
+
@groupname = nil
|
|
14
|
+
@description = "No description!"
|
|
15
|
+
@weight = 1.0
|
|
16
|
+
@check = false
|
|
17
|
+
@score = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def score
|
|
21
|
+
return @score unless @score.nil?
|
|
22
|
+
return 0.0 if @check == false
|
|
23
|
+
|
|
24
|
+
@weight
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_h
|
|
28
|
+
{
|
|
29
|
+
id: id,
|
|
30
|
+
groupname: groupname, description: description, weight: weight,
|
|
31
|
+
command: command, encoding: encoding, host: host, exec: exec,
|
|
32
|
+
conn_type: conn_type, duration: duration,
|
|
33
|
+
result: result, output: output,
|
|
34
|
+
alterations: alterations, expected: expected, check: check,
|
|
35
|
+
score: score
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require_relative "action"
|
|
2
|
+
|
|
3
|
+
class Case
|
|
4
|
+
class ActionManager
|
|
5
|
+
OBJECTS = %i[last_target every_target all_targets].freeze
|
|
6
|
+
CONDITIONS = %i[failed is_ok].freeze
|
|
7
|
+
ACTIONS = %i[scores_to_zero stop log].freeze
|
|
8
|
+
|
|
9
|
+
attr_reader :actions, :events, :current_action
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@current_action = nil
|
|
13
|
+
@actions = []
|
|
14
|
+
@events = {runonce: [], repeat: []}
|
|
15
|
+
@stopped = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def add_event(...)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def check_event(...)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def last_action
|
|
25
|
+
@actions.last
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def next_action
|
|
29
|
+
if @current_action.nil?
|
|
30
|
+
@current_action = Action.new(1)
|
|
31
|
+
return @current_action
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
@actions << @current_action
|
|
35
|
+
@current_action = Action.new(last_action.id + 1)
|
|
36
|
+
@current_action.groupname = last_action.groupname
|
|
37
|
+
@current_action.description = last_action.description
|
|
38
|
+
@current_action
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def stopped?
|
|
42
|
+
@stopped
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def scores_to_zero
|
|
46
|
+
@action.each { |action| action.score = 0 }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def stop
|
|
50
|
+
@stop_test = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_h
|
|
54
|
+
@actions.map { _1.to_h }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def trigger_events!
|
|
58
|
+
@events[:repeat].each do |event|
|
|
59
|
+
# TODO: Do something
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/teuton/case/case.rb
CHANGED
|
@@ -4,6 +4,8 @@ require_relative "../utils/project"
|
|
|
4
4
|
require_relative "../utils/verbose"
|
|
5
5
|
require_relative "../report/report"
|
|
6
6
|
require_relative "dsl/all"
|
|
7
|
+
# require_relative "action/action"
|
|
8
|
+
require_relative "action/manager"
|
|
7
9
|
require_relative "config"
|
|
8
10
|
require_relative "close"
|
|
9
11
|
# require_relative "builtin/main"
|
|
@@ -15,26 +17,24 @@ class Case
|
|
|
15
17
|
include DSL
|
|
16
18
|
include Verbose
|
|
17
19
|
|
|
18
|
-
#
|
|
20
|
+
# INFO: Used by ExecuteManager
|
|
19
21
|
attr_accessor :action, :result, :sessions, :conn_status
|
|
20
|
-
|
|
21
|
-
attr_reader :id, :config, :uniques, :skip
|
|
22
|
+
attr_reader :id, :config, :uniques, :skip, :action_manager
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
@current_case_id = Project.value[:base_case_id]
|
|
25
|
+
|
|
26
|
+
def self.next_id
|
|
27
|
+
@current_case_id = @current_case_id.next
|
|
28
|
+
end
|
|
24
29
|
|
|
25
30
|
def initialize(config)
|
|
26
31
|
@config = Case::Config.new(
|
|
27
32
|
local: config,
|
|
28
33
|
global: Project.value[:global]
|
|
29
34
|
)
|
|
35
|
+
@id = Case.next_id
|
|
30
36
|
@groups = Project.value[:groups]
|
|
31
|
-
|
|
32
|
-
@id = @@id
|
|
33
|
-
@@id = @@id.next
|
|
34
|
-
|
|
35
|
-
# Define Case Report
|
|
36
37
|
@report = Report.new(@id)
|
|
37
|
-
@report.output_dir = Project.value[:output_dir]
|
|
38
38
|
|
|
39
39
|
# Default configuration
|
|
40
40
|
@skip = false
|
|
@@ -43,23 +43,16 @@ class Case
|
|
|
43
43
|
@skip = true
|
|
44
44
|
@skip = false if Project.value[:options]["case"].include? @id.to_i
|
|
45
45
|
end
|
|
46
|
-
@verbose = Project.value[:verbose]
|
|
47
|
-
|
|
48
46
|
@tempdir = File.join(Project.value[:output_dir], "tmp", @id.to_s)
|
|
47
|
+
@verbose = Project.value[:verbose]
|
|
49
48
|
|
|
50
49
|
@unique_values = {}
|
|
51
50
|
@result = Result.new
|
|
52
|
-
@
|
|
53
|
-
@action =
|
|
54
|
-
id: 0,
|
|
55
|
-
weight: 1.0,
|
|
56
|
-
description: "No description!",
|
|
57
|
-
groupname: nil
|
|
58
|
-
}
|
|
51
|
+
@action_manager = ActionManager.new
|
|
52
|
+
@action = @action_manager.next_action
|
|
59
53
|
@uniques = []
|
|
60
54
|
@sessions = {} # Store opened sessions for this case
|
|
61
55
|
@conn_status = {}
|
|
62
|
-
tempfile :default
|
|
63
56
|
end
|
|
64
57
|
|
|
65
58
|
def export(format)
|
|
@@ -69,7 +62,6 @@ class Case
|
|
|
69
62
|
end
|
|
70
63
|
|
|
71
64
|
def filename
|
|
72
|
-
# called from: close_main_report
|
|
73
65
|
@report.filename
|
|
74
66
|
end
|
|
75
67
|
|
|
@@ -79,6 +71,10 @@ class Case
|
|
|
79
71
|
@report.tail[:grade]
|
|
80
72
|
end
|
|
81
73
|
|
|
74
|
+
def last_action
|
|
75
|
+
@action_manager.actions.last
|
|
76
|
+
end
|
|
77
|
+
|
|
82
78
|
def members
|
|
83
79
|
return "-" if skip
|
|
84
80
|
|
data/lib/teuton/case/close.rb
CHANGED
|
@@ -5,11 +5,11 @@ class Case
|
|
|
5
5
|
# Invoked from check_cases!
|
|
6
6
|
|
|
7
7
|
fails = 0
|
|
8
|
-
|
|
9
|
-
next unless
|
|
8
|
+
uniques.each_pair do |key, values|
|
|
9
|
+
next unless values&.include?(id) && (values&.count&.> 1)
|
|
10
10
|
|
|
11
11
|
fails += 1
|
|
12
|
-
log_unique_message(key,
|
|
12
|
+
log_unique_message(key, values)
|
|
13
13
|
end
|
|
14
14
|
@report.tail[:unique_fault] = fails
|
|
15
15
|
@report.close
|
data/lib/teuton/case/dsl/all.rb
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module DSL
|
|
2
|
+
def event(**args, &block)
|
|
3
|
+
object = args[:on]
|
|
4
|
+
unless Case::ActionManager::OBJECTS.include? object
|
|
5
|
+
Logger.warn "Incorrect argument in event on: #{object} ..."
|
|
6
|
+
Logger.info "Valid OBJECTS: #{Case::ActionManager::OBJECTS.join(",")}"
|
|
7
|
+
return
|
|
8
|
+
end
|
|
9
|
+
condition = args[:when]
|
|
10
|
+
unless Case::ActionManager::CONDITIONS.include? condition
|
|
11
|
+
Logger.warn "Incorrect argument in event on: :#{object} when: #{condition}"
|
|
12
|
+
Logger.info "Valid CONDITIONS: #{Case::ActionManager::CONDITIONS.join(",")}"
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if object == :every_target
|
|
17
|
+
@action_manager.events << {args: args, block: block}
|
|
18
|
+
else
|
|
19
|
+
# last_target, all_targets
|
|
20
|
+
log "Event triggered on: #{object}, when: #{condition} Target #{@action.id}"
|
|
21
|
+
# TODO: do something more
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -15,27 +15,28 @@ module DSL
|
|
|
15
15
|
elsif input.instance_of?(String) || input.instance_of?(Regexp) || input.instance_of?(Array)
|
|
16
16
|
expect_any input
|
|
17
17
|
else
|
|
18
|
-
|
|
18
|
+
Logger.warn "Case expect TypeError: <expect #{input} (#{input.class})>"
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def expect2(cond, args = {})
|
|
23
|
-
@
|
|
24
|
-
@action[:id] = @action_counter
|
|
25
|
-
if @result.exitcode < 0
|
|
23
|
+
if @result.exitcode.negative?
|
|
26
24
|
# When exitcode is less than zero, it is because there has been
|
|
27
25
|
# an error in the remote connection (SSH or Telnet)
|
|
28
|
-
@action
|
|
29
|
-
@action
|
|
26
|
+
@action.check = false
|
|
27
|
+
@action.result = @action.output
|
|
30
28
|
else
|
|
31
|
-
@action
|
|
32
|
-
@action
|
|
29
|
+
@action.check = cond
|
|
30
|
+
@action.result = (args[:value] || @result.value)
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
@action
|
|
36
|
-
@action
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
@action.alterations = @result.alterations
|
|
34
|
+
@action.expected = (args[:expected] || @result.expected)
|
|
35
|
+
|
|
36
|
+
@action_manager.trigger_events!
|
|
37
|
+
@report.lines << @action.to_h
|
|
38
|
+
@action = @action_manager.next_action
|
|
39
|
+
# TODO: weight(1.0)
|
|
39
40
|
|
|
40
41
|
c = Settings.letter[:fail]
|
|
41
42
|
c = Settings.letter[:good] if cond
|
|
@@ -164,8 +164,7 @@ class ExpectSequence
|
|
|
164
164
|
elsif value.is_a? Regexp
|
|
165
165
|
return true << index if value.match(line)
|
|
166
166
|
else
|
|
167
|
-
|
|
168
|
-
exit 1
|
|
167
|
+
raise Teuton::UnexpectedSequenceTypeError, value.class
|
|
169
168
|
end
|
|
170
169
|
false
|
|
171
170
|
end
|
data/lib/teuton/case/dsl/log.rb
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
require "rainbow"
|
|
2
2
|
|
|
3
3
|
module DSL
|
|
4
|
-
|
|
5
|
-
# Record log message
|
|
6
|
-
# @param text (String)
|
|
7
|
-
# @param type (Symbol) Values :info, :warn or :error
|
|
4
|
+
# type => :info, :warn or :error
|
|
8
5
|
def log(text = "", type = :info)
|
|
9
6
|
s = " INFO"
|
|
10
|
-
s = Rainbow("WARN
|
|
7
|
+
s = Rainbow(" WARN").color(:yellow) if type == :warn
|
|
11
8
|
s = Rainbow("ERROR").bg(:red) if type == :error
|
|
12
9
|
t = Time.now
|
|
13
10
|
f = format("%<hour>02d:%<min>02d:%<sec>02d", {hour: t.hour, min: t.min, sec: t.sec})
|
|
14
|
-
msg = "[#{f}] #{s}
|
|
11
|
+
msg = "[#{f}] #{s}| #{text}"
|
|
15
12
|
msg = "[#{f}] #{text}" if s == ""
|
|
16
13
|
@report.lines << msg
|
|
17
14
|
end
|
|
18
|
-
# alias_method :msg, :log
|
|
19
15
|
end
|
|
@@ -11,9 +11,9 @@ module DSL
|
|
|
11
11
|
def macro(name, input = {})
|
|
12
12
|
macros = Project.value[:macros]
|
|
13
13
|
unless macros[name]
|
|
14
|
-
msg = "DSL '#{name}'
|
|
14
|
+
msg = "Unknown DSL keyword '#{name}'"
|
|
15
15
|
log(msg, :error)
|
|
16
|
-
Logger.
|
|
16
|
+
Logger.warn(msg)
|
|
17
17
|
return
|
|
18
18
|
end
|
|
19
19
|
input.each_pair { |k, v| set(k, v) }
|
|
@@ -39,6 +39,7 @@ module DSL
|
|
|
39
39
|
elsif a[0, 6] == "macro_"
|
|
40
40
|
return macro a[6, a.size], args
|
|
41
41
|
end
|
|
42
|
+
|
|
42
43
|
macro a, args
|
|
43
44
|
end
|
|
44
45
|
|
data/lib/teuton/case/dsl/run.rb
CHANGED
|
@@ -4,32 +4,26 @@ require_relative "../execute/execute_manager"
|
|
|
4
4
|
|
|
5
5
|
module DSL
|
|
6
6
|
##
|
|
7
|
-
# DSL run
|
|
8
|
-
# run: It's the same as goto :localhost
|
|
7
|
+
# DSL run
|
|
9
8
|
# @param command (String)
|
|
10
9
|
# @param args (Hash)
|
|
11
10
|
def run(command, args = {})
|
|
12
|
-
|
|
13
|
-
host = args[:on] || :localhost
|
|
14
|
-
|
|
15
|
-
end
|
|
11
|
+
@action.command = command.to_s
|
|
12
|
+
@action.host = args[:on] || :localhost
|
|
13
|
+
@action.encoding = args[:encoding] || "UTF-8"
|
|
16
14
|
|
|
17
|
-
# Run command from the host identify as "host"
|
|
18
|
-
# goto :host1, execute: "command"
|
|
19
|
-
def goto(host = :localhost, args = {})
|
|
20
15
|
@result.reset
|
|
21
|
-
args[:on] = host unless args[:on]
|
|
22
|
-
@action[:command] = args[:execute].to_s if args[:execute]
|
|
23
|
-
@action[:command] = args[:exec].to_s if args[:exec]
|
|
24
|
-
tempfile(args[:tempfile]) if args[:tempfile]
|
|
25
|
-
@action[:encoding] = args[:encoding] || "UTF-8"
|
|
26
16
|
|
|
27
|
-
ExecuteManager.new(self).call(host)
|
|
28
|
-
@action
|
|
17
|
+
ExecuteManager.new(self).call(@action.host)
|
|
18
|
+
@action.output = if @result.content.size < 2
|
|
29
19
|
@result.value.clone
|
|
30
20
|
else
|
|
31
21
|
"(#{@result.content.size} lines)"
|
|
32
22
|
end
|
|
33
23
|
end
|
|
34
|
-
|
|
24
|
+
|
|
25
|
+
def goto(...)
|
|
26
|
+
Logger.warn "Keyword DSL deprecated! <goto>"
|
|
27
|
+
run(...)
|
|
28
|
+
end
|
|
35
29
|
end
|
data/lib/teuton/case/dsl/send.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module DSL
|
|
4
|
-
# * send,
|
|
4
|
+
# * send, tempdir, remote_tempdir
|
|
5
5
|
def send(logfile, args = {})
|
|
6
6
|
return if skip?
|
|
7
7
|
|
|
@@ -46,26 +46,10 @@ module DSL
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def tempfile(input = nil)
|
|
50
|
-
return @action[:tempfile] if input.nil?
|
|
51
|
-
|
|
52
|
-
name = input
|
|
53
|
-
name = "teuton.tmp" if input == :default
|
|
54
|
-
|
|
55
|
-
@action[:tempfile] = File.join(@tempdir, name)
|
|
56
|
-
@action[:remote_tempfile] = File.join(remote_tempdir, name)
|
|
57
|
-
|
|
58
|
-
@action[:tempfile]
|
|
59
|
-
end
|
|
60
|
-
|
|
61
49
|
def tempdir
|
|
62
50
|
@tempdir
|
|
63
51
|
end
|
|
64
52
|
|
|
65
|
-
def remote_tempfile
|
|
66
|
-
@action[:remote_tempfile]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
53
|
def remote_tempdir
|
|
70
54
|
File.join("/", "tmp") # TODO: Remove this?
|
|
71
55
|
end
|
|
@@ -3,14 +3,18 @@
|
|
|
3
3
|
# DSL#target
|
|
4
4
|
module DSL
|
|
5
5
|
def readme(_text)
|
|
6
|
-
# Usefull
|
|
6
|
+
# Usefull when running.
|
|
7
|
+
# It's works only with "teuton reamde" command action.
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def target(desc, args = {})
|
|
10
|
-
@action
|
|
11
|
-
@action[:asset] = args[:asset].to_s if args[:asset]
|
|
11
|
+
@action.description = desc.to_s
|
|
12
12
|
w = args[:weight] || 1.0
|
|
13
13
|
weight(w)
|
|
14
14
|
end
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
def goal(...)
|
|
17
|
+
Logger.warn("Keyword deprecated: Replace 'goal' by 'target'.")
|
|
18
|
+
target(...)
|
|
19
|
+
end
|
|
16
20
|
end
|
|
@@ -15,10 +15,7 @@ module DSL
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def upload_one(localpath, args = {})
|
|
18
|
-
if args[:to].nil?
|
|
19
|
-
Logger.err("ERROR upload requires to: XXX")
|
|
20
|
-
exit 1
|
|
21
|
-
end
|
|
18
|
+
raise ArgumentError, "upload requires 'to: XXX'" if args[:to].nil?
|
|
22
19
|
|
|
23
20
|
host = get_host(args[:to])
|
|
24
21
|
if host.protocol == "ssh"
|
|
@@ -2,11 +2,11 @@ module DSL
|
|
|
2
2
|
def weight(value = nil)
|
|
3
3
|
# Set weight value for the action
|
|
4
4
|
if value.nil?
|
|
5
|
-
@action
|
|
5
|
+
@action.weight
|
|
6
6
|
elsif value == :default
|
|
7
|
-
@action
|
|
7
|
+
@action.weight = 1.0
|
|
8
8
|
else
|
|
9
|
-
@action
|
|
9
|
+
@action.weight = value.to_f
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -8,8 +8,8 @@ class ExecuteLocal < ExecuteBase
|
|
|
8
8
|
include Verbose
|
|
9
9
|
|
|
10
10
|
def call
|
|
11
|
-
action
|
|
12
|
-
response = my_execute(action
|
|
11
|
+
action.conn_type = :local
|
|
12
|
+
response = my_execute(action.command, action.encoding)
|
|
13
13
|
result.exitcode = response[:exitcode]
|
|
14
14
|
result.content = response[:content]
|
|
15
15
|
end
|
|
@@ -5,7 +5,7 @@ require_relative "execute_telnet"
|
|
|
5
5
|
class ExecuteManager
|
|
6
6
|
def initialize(parent)
|
|
7
7
|
@parent = parent
|
|
8
|
-
# READ: @config, cmd = action
|
|
8
|
+
# READ: @config, cmd = action.command
|
|
9
9
|
# WRITE: @action, @result, @session
|
|
10
10
|
# my_execute, encode_and_split methods?
|
|
11
11
|
end
|
|
@@ -13,7 +13,7 @@ class ExecuteManager
|
|
|
13
13
|
def call(host)
|
|
14
14
|
start_time = Time.now
|
|
15
15
|
run_on(host)
|
|
16
|
-
action
|
|
16
|
+
action.duration = (Time.now - start_time).round(3)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
private
|
|
@@ -34,16 +34,16 @@ class ExecuteManager
|
|
|
34
34
|
protocol = config.get(:"#{host}_protocol")
|
|
35
35
|
ip = config.get(:"#{host}_ip")
|
|
36
36
|
|
|
37
|
-
if protocol.to_s.
|
|
37
|
+
if protocol.to_s.casecmp("local").zero? || host.to_s == "localhost"
|
|
38
38
|
# Protocol force => local
|
|
39
39
|
ExecuteLocal.new(@parent).call
|
|
40
|
-
elsif protocol.to_s.
|
|
40
|
+
elsif protocol.to_s.casecmp("ssh").zero?
|
|
41
41
|
# Protocol force => ssh
|
|
42
42
|
ExecuteSSH.new(@parent).call(host)
|
|
43
|
-
elsif protocol.to_s.
|
|
43
|
+
elsif protocol.to_s.casecmp("telnet").zero?
|
|
44
44
|
# Protocol force => telnet
|
|
45
45
|
ExecuteTelnet.new(@parent).call(host)
|
|
46
|
-
elsif ip.to_s.
|
|
46
|
+
elsif ip.to_s.casecmp("localhost").zero? || ip.to_s.include?("127.0.0.")
|
|
47
47
|
# run_cmd_localhost
|
|
48
48
|
ExecuteLocal.new(@parent).call
|
|
49
49
|
elsif ip == "NODATA"
|
|
@@ -6,7 +6,7 @@ require_relative "execute_base"
|
|
|
6
6
|
|
|
7
7
|
class ExecuteSSH < ExecuteBase
|
|
8
8
|
def call(input_hostname)
|
|
9
|
-
action
|
|
9
|
+
action.conn_type = :ssh
|
|
10
10
|
hostname = input_hostname.to_s
|
|
11
11
|
ip = config.get(:"#{hostname}_ip").to_s
|
|
12
12
|
username = config.get(:"#{hostname}_username").to_s
|
|
@@ -20,14 +20,14 @@ class ExecuteSSH < ExecuteBase
|
|
|
20
20
|
ip2 = ip
|
|
21
21
|
username2 = username
|
|
22
22
|
password2 = password
|
|
23
|
-
command2 = action
|
|
23
|
+
command2 = action.command
|
|
24
24
|
hostname = config.get(:"#{hostname}_route")
|
|
25
25
|
ip = config.get(:"#{hostname}_ip").to_s
|
|
26
26
|
username = config.get(:"#{hostname}_username").to_s
|
|
27
27
|
password = config.get(:"#{hostname}_password").to_s
|
|
28
28
|
ostype = config.get(:"#{hostname}_ostype").to_s
|
|
29
29
|
|
|
30
|
-
action
|
|
30
|
+
action.command = if ostype.downcase.start_with? "win"
|
|
31
31
|
"echo y | plink #{username2}@#{ip2} -ssh -pw #{password2} \"#{command2}\""
|
|
32
32
|
else
|
|
33
33
|
"sshpass -p #{password2} #{username2}@#{ip2} #{command2}"
|
|
@@ -49,7 +49,7 @@ class ExecuteSSH < ExecuteBase
|
|
|
49
49
|
)
|
|
50
50
|
end
|
|
51
51
|
if sessions[hostname].instance_of? Net::SSH::Connection::Session
|
|
52
|
-
text = sessions[hostname].exec!(action
|
|
52
|
+
text = sessions[hostname].exec!(action.command)
|
|
53
53
|
exitcode = text.exitstatus
|
|
54
54
|
else
|
|
55
55
|
text = "TEUTON_ERROR_SSH_NO_CONNECTION"
|
|
@@ -84,9 +84,9 @@ class ExecuteSSH < ExecuteBase
|
|
|
84
84
|
text = "TEUTON_ERROR_SSH"
|
|
85
85
|
exitcode = -1
|
|
86
86
|
log("[#{e.class}] SSH on <#{username}@#{ip}>" \
|
|
87
|
-
" exec: #{action
|
|
87
|
+
" exec: #{action.command}", :error)
|
|
88
88
|
end
|
|
89
89
|
result.exitcode = exitcode
|
|
90
|
-
result.content = encode_and_split(action
|
|
90
|
+
result.content = encode_and_split(action.encoding, text)
|
|
91
91
|
end
|
|
92
92
|
end
|
|
@@ -4,7 +4,7 @@ require_relative "execute_base"
|
|
|
4
4
|
|
|
5
5
|
class ExecuteTelnet < ExecuteBase
|
|
6
6
|
def call(input_hostname)
|
|
7
|
-
action
|
|
7
|
+
action.conn_type = :telnet
|
|
8
8
|
hostname = input_hostname.to_s
|
|
9
9
|
ip = config.get((hostname + "_ip").to_sym)
|
|
10
10
|
port = config.get((hostname + "_port").to_sym)
|
|
@@ -31,7 +31,7 @@ class ExecuteTelnet < ExecuteBase
|
|
|
31
31
|
password = config.get((hostname + "_password").to_sym).to_s
|
|
32
32
|
h.login(username, password)
|
|
33
33
|
end
|
|
34
|
-
h.cmd(action
|
|
34
|
+
h.cmd(action.command) { |i| text << i }
|
|
35
35
|
h.close
|
|
36
36
|
sessions[hostname] = :ok
|
|
37
37
|
exitcode = 0
|
|
@@ -51,11 +51,11 @@ class ExecuteTelnet < ExecuteBase
|
|
|
51
51
|
sessions[hostname] = :nosession
|
|
52
52
|
conn_status[hostname] = :error
|
|
53
53
|
log(" ExceptionType=<#{e.class}> doing telnet on <#{username}@#{ip}>" \
|
|
54
|
-
" exec: #{action
|
|
54
|
+
" exec: #{action.command}", :error)
|
|
55
55
|
log(" └── username=<#{username}>, password=<#{password}>," \
|
|
56
56
|
" ip=<#{ip}>, HOSTID=<#{hostname}>", :warn)
|
|
57
57
|
end
|
|
58
58
|
result.exitcode = exitcode
|
|
59
|
-
result.content = encode_and_split(action
|
|
59
|
+
result.content = encode_and_split(action.encoding, text)
|
|
60
60
|
end
|
|
61
61
|
end
|
data/lib/teuton/case/play.rb
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
class Case
|
|
4
4
|
# READ: sessions, config, groups, action, report
|
|
5
|
-
# TODO: groups from Project or from Case???
|
|
6
5
|
def play
|
|
7
6
|
if skip?
|
|
8
7
|
verbose Rainbow("S").green
|
|
@@ -13,7 +12,7 @@ class Case
|
|
|
13
12
|
fill_report(start_time, Time.now)
|
|
14
13
|
close_opened_sessions
|
|
15
14
|
end
|
|
16
|
-
alias_method :start, :play
|
|
15
|
+
# alias_method :start, :play
|
|
17
16
|
|
|
18
17
|
private
|
|
19
18
|
|
|
@@ -25,18 +24,18 @@ class Case
|
|
|
25
24
|
|
|
26
25
|
def play_groups_in_sequence
|
|
27
26
|
verboseln "\n==> Running case [#{@config.get(:tt_members)}]" if get(:tt_sequence) == true
|
|
28
|
-
@groups.each do |
|
|
29
|
-
@action
|
|
30
|
-
instance_eval(&
|
|
27
|
+
@groups.each do |group|
|
|
28
|
+
@action.groupname = group[:name]
|
|
29
|
+
instance_eval(&group[:block])
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
def play_groups_in_parallel
|
|
35
34
|
verboseln "Running case [#{@config.get(:tt_members)}]"
|
|
36
|
-
@groups.each do |
|
|
37
|
-
verbose "* Processing [#{
|
|
38
|
-
@action
|
|
39
|
-
instance_eval(&
|
|
35
|
+
@groups.each do |group|
|
|
36
|
+
verbose "* Processing [#{group[:name]}] "
|
|
37
|
+
@action.groupname = group[:name]
|
|
38
|
+
instance_eval(&group[:block])
|
|
40
39
|
verbose "\n"
|
|
41
40
|
end
|
|
42
41
|
verboseln "\n"
|