teuton 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/bin/teuton +4 -0
  3. data/lib/teuton/application.rb +53 -0
  4. data/lib/teuton/case_manager/case/builtin/main.rb +24 -0
  5. data/lib/teuton/case_manager/case/builtin/package.rb +20 -0
  6. data/lib/teuton/case_manager/case/builtin/service.rb +32 -0
  7. data/lib/teuton/case_manager/case/builtin/user.rb +20 -0
  8. data/lib/teuton/case_manager/case/case.rb +114 -0
  9. data/lib/teuton/case_manager/case/close.rb +29 -0
  10. data/lib/teuton/case_manager/case/config.rb +76 -0
  11. data/lib/teuton/case_manager/case/dsl/check.rb +24 -0
  12. data/lib/teuton/case_manager/case/dsl/deprecated.rb +14 -0
  13. data/lib/teuton/case_manager/case/dsl/expect.rb +78 -0
  14. data/lib/teuton/case_manager/case/dsl/getset.rb +22 -0
  15. data/lib/teuton/case_manager/case/dsl/goto.rb +35 -0
  16. data/lib/teuton/case_manager/case/dsl/log.rb +14 -0
  17. data/lib/teuton/case_manager/case/dsl/main.rb +11 -0
  18. data/lib/teuton/case_manager/case/dsl/missing.rb +12 -0
  19. data/lib/teuton/case_manager/case/dsl/send.rb +69 -0
  20. data/lib/teuton/case_manager/case/dsl/target.rb +16 -0
  21. data/lib/teuton/case_manager/case/dsl/unique.rb +11 -0
  22. data/lib/teuton/case_manager/case/main.rb +7 -0
  23. data/lib/teuton/case_manager/case/play.rb +59 -0
  24. data/lib/teuton/case_manager/case/result/ext_array.rb +43 -0
  25. data/lib/teuton/case_manager/case/result/ext_compare.rb +147 -0
  26. data/lib/teuton/case_manager/case/result/ext_filter.rb +68 -0
  27. data/lib/teuton/case_manager/case/result/result.rb +73 -0
  28. data/lib/teuton/case_manager/case/runner.rb +134 -0
  29. data/lib/teuton/case_manager/case_manager.rb +76 -0
  30. data/lib/teuton/case_manager/check_cases.rb +73 -0
  31. data/lib/teuton/case_manager/dsl.rb +31 -0
  32. data/lib/teuton/case_manager/export_manager.rb +20 -0
  33. data/lib/teuton/case_manager/hall_of_fame.rb +28 -0
  34. data/lib/teuton/case_manager/main.rb +6 -0
  35. data/lib/teuton/case_manager/report.rb +52 -0
  36. data/lib/teuton/case_manager/show.rb +19 -0
  37. data/lib/teuton/case_manager/utils.rb +57 -0
  38. data/lib/teuton/command/create.rb +20 -0
  39. data/lib/teuton/command/download.rb +26 -0
  40. data/lib/teuton/command/main.rb +9 -0
  41. data/lib/teuton/command/play.rb +34 -0
  42. data/lib/teuton/command/readme.rb +23 -0
  43. data/lib/teuton/command/test.rb +35 -0
  44. data/lib/teuton/command/update.rb +27 -0
  45. data/lib/teuton/command/version.rb +13 -0
  46. data/lib/teuton/files/start.rb +13 -0
  47. data/lib/teuton/project/configfile_reader.rb +49 -0
  48. data/lib/teuton/project/laboratory/builtin.rb +23 -0
  49. data/lib/teuton/project/laboratory/dsl.rb +117 -0
  50. data/lib/teuton/project/laboratory/laboratory.rb +55 -0
  51. data/lib/teuton/project/laboratory/show.rb +161 -0
  52. data/lib/teuton/project/name_file_finder.rb +129 -0
  53. data/lib/teuton/project/project.rb +62 -0
  54. data/lib/teuton/project/project_creator.rb +79 -0
  55. data/lib/teuton/project/readme/dsl.rb +109 -0
  56. data/lib/teuton/project/readme/lang.rb +30 -0
  57. data/lib/teuton/project/readme/readme.rb +156 -0
  58. data/lib/teuton/rake_function/check.rb +39 -0
  59. data/lib/teuton/rake_function/install.rb +36 -0
  60. data/lib/teuton/report/close.rb +34 -0
  61. data/lib/teuton/report/formatter/array_formatter.rb +84 -0
  62. data/lib/teuton/report/formatter/base_formatter.rb +33 -0
  63. data/lib/teuton/report/formatter/csv_formatter.rb +31 -0
  64. data/lib/teuton/report/formatter/formatter_factory.rb +73 -0
  65. data/lib/teuton/report/formatter/html_formatter.rb +81 -0
  66. data/lib/teuton/report/formatter/json_formatter.rb +17 -0
  67. data/lib/teuton/report/formatter/list_formatter.rb +71 -0
  68. data/lib/teuton/report/formatter/moodle_csv_formatter.rb +28 -0
  69. data/lib/teuton/report/formatter/resume_array_formatter.rb +49 -0
  70. data/lib/teuton/report/formatter/resume_json_formatter.rb +16 -0
  71. data/lib/teuton/report/formatter/resume_list_formatter.rb +62 -0
  72. data/lib/teuton/report/formatter/resume_txt_formatter.rb +102 -0
  73. data/lib/teuton/report/formatter/resume_yaml_formatter.rb +16 -0
  74. data/lib/teuton/report/formatter/txt_formatter.rb +102 -0
  75. data/lib/teuton/report/formatter/xml_formatter.rb +42 -0
  76. data/lib/teuton/report/formatter/yaml_formatter.rb +18 -0
  77. data/lib/teuton/report/report.rb +55 -0
  78. data/lib/teuton/report/show.rb +111 -0
  79. data/lib/teuton/utils/verbose.rb +15 -0
  80. data/lib/teuton.rb +17 -0
  81. metadata +263 -0
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Case#DSL#unique
4
+ module DSL
5
+ def unique(key, value)
6
+ return if value.nil?
7
+
8
+ k = (key.to_s + '=' + value.to_s).to_sym
9
+ @uniques << k
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'dsl/main'
4
+ require_relative 'config'
5
+ require_relative 'close'
6
+ require_relative 'play'
7
+ require_relative 'runner'
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Case class:
4
+ # * play
5
+ # * play_in_parallel
6
+ # * play_in_sequence
7
+ # * fill_report
8
+ # * close_opened_sessions
9
+ class Case
10
+ def play
11
+ if skip?
12
+ verbose "Skipping case <#{@config.get(:tt_members)}>\n"
13
+ return false
14
+ end
15
+ # TODO: Delete old reports???
16
+ start_time = Time.now
17
+ play_in_sequence if get(:tt_sequence) == true # Play in sequence
18
+ play_in_parallel if get(:tt_sequence) != true # Play in parallel
19
+ fill_report(start_time, Time.now)
20
+ close_opened_sessions
21
+ end
22
+ alias start play
23
+
24
+ def close_opened_sessions
25
+ @sessions.each_value do |s|
26
+ s.close if s.class == Net::SSH::Connection::Session
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def play_in_parallel
33
+ @groups.each do |t|
34
+ @action[:groupname] = t[:name]
35
+ instance_eval(&t[:block])
36
+ end
37
+ end
38
+
39
+ def play_in_sequence
40
+ verboseln "Starting case <#{@config.get(:tt_members)}>"
41
+ @groups.each do |t|
42
+ verbose "* Processing <#{t[:name]}> "
43
+ @action[:groupname] = t[:name]
44
+ instance_eval(&t[:block])
45
+ verbose "\n"
46
+ end
47
+ verboseln "\n"
48
+ end
49
+
50
+ def fill_report(start_time, finish_time)
51
+ @report.head.merge! @config.global
52
+ @report.head.merge! @config.local
53
+ @report.head.merge! @config.running
54
+ @report.tail[:case_id] = @id
55
+ @report.tail[:start_time_] = start_time
56
+ @report.tail[:finish_time] = finish_time
57
+ @report.tail[:duration] = finish_time - start_time
58
+ end
59
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is an extension of Result class
4
+ class Result
5
+ def count
6
+ @alterations << 'count'
7
+ if @content.class == Array
8
+ @content = [@content.count]
9
+ self
10
+ elsif @content.nil?
11
+ @content = ['0']
12
+ else
13
+ @content = [@content.to_i.to_s]
14
+ end
15
+ self
16
+ end
17
+
18
+ def include?(value)
19
+ @expected = "Include <#{value}> value"
20
+ @content[0].include?(value)
21
+ end
22
+
23
+ def not_include?(value)
24
+ @expected = "Not include <#{value}> value"
25
+ !@content[0].include?(value)
26
+ end
27
+
28
+ def contain?(value)
29
+ @expected = "Contain <#{value}> value"
30
+ @content.contain? value
31
+ end
32
+
33
+ def empty
34
+ @expected = 'Empty!'
35
+ @content.empty
36
+ end
37
+
38
+ alias count! count
39
+ alias length count
40
+ alias len count
41
+ alias size count
42
+ alias empty? empty
43
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is an extension of Result class
4
+ class Result
5
+ def eq(input)
6
+ @expected = input
7
+
8
+ case input.class.to_s
9
+ when 'Fixnum'
10
+ value = @content[0].to_i
11
+ puts '[WARN] Fixnum class is deprecated!'
12
+ puts ' Upgrade your Ruby version.'
13
+ when 'Float'
14
+ value = @content[0].to_f
15
+ when 'Integer'
16
+ value = @content[0].to_i
17
+ when 'String'
18
+ value = @content[0].to_s
19
+ else
20
+ value = @content[0]
21
+ end
22
+ value == input
23
+ end
24
+ alias eq? eq
25
+ alias equal eq
26
+ alias equal? eq
27
+ alias is_equal? eq
28
+
29
+ def neq(external)
30
+ @expected = "Not equal to #{external}"
31
+
32
+ case external.class.to_s
33
+ when 'Fixnum'
34
+ internal = @content[0].to_i
35
+ puts '[WARN] Fixnum class is deprecated!'
36
+ puts ' Upgrade your Ruby version.'
37
+ when 'Float'
38
+ internal = @content[0].to_f
39
+ when 'Integer'
40
+ internal = @content[0].to_i
41
+ else
42
+ internal = @content[0]
43
+ end
44
+ internal != external
45
+ end
46
+ alias neq? neq
47
+ alias not_equal neq
48
+ alias not_equal? neq
49
+
50
+ def ge(input)
51
+ @expected = "Greater or equal to #{input}"
52
+ return false if @content.nil? || @content[0].nil?
53
+
54
+ value = @content[0]
55
+ case input.class.to_s
56
+ when 'Fixnum'
57
+ value = @content[0].to_i
58
+ puts '[WARN] Fixnum class is deprecated!'
59
+ puts ' Upgrade your Ruby version.'
60
+ when 'Float'
61
+ value = @content[0].to_f
62
+ when 'Integer'
63
+ value = @content[0].to_i
64
+ end
65
+ value >= input
66
+ end
67
+ alias greater_or_equal ge
68
+ alias greater_or_equal? ge
69
+
70
+ def gt(input)
71
+ @expected = "Greater than #{input}"
72
+ return false if @content.nil? || @content[0].nil?
73
+
74
+ value = @content[0]
75
+ case input.class.to_s
76
+ when 'Fixnum'
77
+ value = @content[0].to_i
78
+ puts '[WARN] Fixnum class is deprecated!'
79
+ puts ' Upgrade your Ruby version.'
80
+ when 'Float'
81
+ value = @content[0].to_f
82
+ when 'Integer'
83
+ value = @content[0].to_i
84
+ end
85
+ value > input
86
+ end
87
+ alias greater gt
88
+ alias greater_than gt
89
+
90
+ def le(input)
91
+ @expected = "Lesser or equal to #{input}"
92
+
93
+ return false if @content.nil? || @content[0].nil?
94
+
95
+ value = @content[0]
96
+ case input.class.to_s
97
+ when 'Fixnum'
98
+ value = @content[0].to_i
99
+ puts '[WARN] Fixnum class is deprecated!'
100
+ puts ' Upgrade your Ruby version.'
101
+ when 'Float'
102
+ value = @content[0].to_f
103
+ when 'Integer'
104
+ value = @content[0].to_i
105
+ end
106
+ value <= input
107
+ end
108
+ alias lesser_or_equal le
109
+ alias lesser_or_equal? le
110
+
111
+ def lt(input)
112
+ @expected = "Lesser than #{input}"
113
+ return false if @content.nil? || @content[0].nil?
114
+
115
+ value = @content[0]
116
+ case input.class.to_s
117
+ when 'Fixnum'
118
+ value = @content[0].to_i
119
+ puts '[WARN] Fixnum class is deprecated!'
120
+ puts ' Upgrade your Ruby version.'
121
+ when 'Float'
122
+ value = @content[0].to_f
123
+ when 'Integer'
124
+ value = @content[0].to_i
125
+ end
126
+ value < input
127
+ end
128
+ alias lesser lt
129
+ alias smaller lt
130
+ alias lesser_than lt
131
+
132
+ # Return 'true' if the parameter value is near to the target value.
133
+ # To get this we consider a 10% desviation or less, as an acceptable result.
134
+ def near_to?(input)
135
+ @expected = "Is near to #{input}"
136
+ return false if @content.nil?
137
+
138
+ target = @content[0].to_f
139
+ desv = (target * 10.0) / 100.0
140
+ return true if (target - input.to_f).abs.to_f <= desv
141
+
142
+ false
143
+ end
144
+ alias near_to near_to?
145
+ alias near? near_to?
146
+ alias near near_to?
147
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is an extension of Result class
4
+ class Result
5
+ # TODO: Error line 102 undefined include? method for 0 Fixnum...
6
+ def find(filter)
7
+ @alterations << "find(#{filter})"
8
+ case filter.class.to_s
9
+ when 'Array'
10
+ find_when_array(filter)
11
+ when 'String' || 'Integer'
12
+ @content.select! { |i| i.include?(filter.to_s) }
13
+ when 'Regexp'
14
+ @content.select! { |i| filter.match(i) }
15
+ end
16
+ self
17
+ end
18
+ alias grep find
19
+ alias grep! find
20
+ alias find! find
21
+
22
+ def not_find(p_filter)
23
+ @alterations << "not_find(#{p_filter})"
24
+ return self if @content.size.zero?
25
+
26
+ @content.reject! { |i| i.include?(p_filter) }
27
+ self
28
+ end
29
+ alias grep_v not_find
30
+
31
+ def since(filter)
32
+ @alterations << "since(#{filter})"
33
+ return self if @content.size.zero?
34
+
35
+ if filter.class == String
36
+ flag = false
37
+ @content.select! do |i|
38
+ flag = true if i.include?(filter.to_s)
39
+ flag
40
+ end
41
+ end
42
+ self
43
+ end
44
+
45
+ def until(filter)
46
+ @alterations << "until(#{filter})"
47
+ return self if @content.size.zero?
48
+
49
+ if filter.class == String
50
+ flag = true
51
+ @content.select! do |i|
52
+ flag = false if i.include?(filter.to_s)
53
+ flag
54
+ end
55
+ end
56
+ self
57
+ end
58
+
59
+ private
60
+
61
+ def find_when_array(filter)
62
+ @content.select! do |line|
63
+ flag = false
64
+ filter.each { |i| flag ||= line.include?(i) }
65
+ flag
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext_array'
4
+ require_relative 'ext_compare'
5
+ require_relative 'ext_filter'
6
+
7
+ # This object contains data returned by remote/local execution
8
+ # * initialize
9
+ # * alterations
10
+ # * content
11
+ # * debug
12
+ # * ok?
13
+ # * reset
14
+ # * restore
15
+ # * value
16
+ class Result
17
+ attr_reader :content
18
+ attr_accessor :exitstatus
19
+
20
+ def initialize
21
+ reset
22
+ end
23
+
24
+ def alterations
25
+ @alterations.join(' & ')
26
+ end
27
+
28
+ def content=(content)
29
+ @content_backup = content.clone
30
+ @content = content.clone
31
+ end
32
+
33
+ def reset
34
+ @content_backup = []
35
+ @content = []
36
+ @exitstatus = nil
37
+ @value = nil
38
+ @expected = nil
39
+ @alterations = []
40
+ end
41
+
42
+ def debug
43
+ print "\n" + '*' * 20
44
+ print " [DEBUG] count=#{@content.count} "
45
+ puts '*' * 20
46
+ @content.each_with_index do |item, index|
47
+ puts format('%2d: %s', index, item)
48
+ end
49
+ puts '*' * 57
50
+ end
51
+
52
+ def expected
53
+ @expected.to_s
54
+ end
55
+
56
+ def ok?
57
+ return false if @exitstatus.nil?
58
+
59
+ @exitstatus.zero?
60
+ end
61
+
62
+ def restore
63
+ temp = @content_backup.clone
64
+ reset
65
+ @content_backup = temp
66
+ @content = temp.clone
67
+ end
68
+ alias restore! restore
69
+
70
+ def value
71
+ @content[0]
72
+ end
73
+ end
@@ -0,0 +1,134 @@
1
+
2
+ require 'net/ssh'
3
+ require 'net/sftp'
4
+ require 'net/telnet'
5
+
6
+ # Class Case
7
+ # * run_local_cmd
8
+ # * run_remote_cmd
9
+ # * run_remote_cmd_ssh
10
+ # * run_remote_cmd_telnet
11
+ class Case
12
+
13
+ private
14
+
15
+ def run_local_cmd()
16
+ @action[:conn_type] = :local
17
+ i = my_execute( @action[:command], @action[:encoding] )
18
+ @result.exitstatus = i[:exitstatus]
19
+ @result.content = i[:content]
20
+ end
21
+
22
+ def run_remote_cmd(input_hostname)
23
+ hostname = input_hostname.to_s
24
+ i = (hostname + '_protocol').to_sym
25
+ protocol = @config.get(i) if @config.get(i)
26
+ protocol = :ssh if protocol.nil? || protocol == 'NODATA'
27
+ protocol = protocol.to_sym
28
+ case protocol
29
+ when :ssh
30
+ run_remote_cmd_ssh(input_hostname)
31
+ when :telnet
32
+ run_remote_cmd_telnet(input_hostname)
33
+ else
34
+ log("Protocol #{protocol} unknown! Use ssh or telnet.", :error)
35
+ end
36
+ end
37
+
38
+ def run_remote_cmd_ssh(input_hostname)
39
+ @action[:conn_type] = :ssh
40
+ hostname = input_hostname.to_s
41
+ ip = @config.get((hostname + '_ip').to_sym)
42
+ username = @config.get((hostname + '_username').to_sym).to_s
43
+ password = @config.get((hostname + '_password').to_sym).to_s
44
+ text = ''
45
+ begin
46
+ if @sessions[hostname].nil?
47
+ @sessions[hostname] = Net::SSH.start(ip,
48
+ username,
49
+ password: password,
50
+ keepalive: true,
51
+ timeout: 30,
52
+ non_interactive: true)
53
+ end
54
+ if @sessions[hostname].class == Net::SSH::Connection::Session
55
+ text = @sessions[hostname].exec!(@action[:command].to_s)
56
+ end
57
+ rescue Errno::EHOSTUNREACH
58
+ @sessions[hostname] = :nosession
59
+ @conn_status[hostname] = :host_unreachable
60
+ verbose Application.instance.letter[:error]
61
+ log("Host #{ip} unreachable!", :error)
62
+ rescue Net::SSH::AuthenticationFailed
63
+ @sessions[hostname] = :nosession
64
+ @conn_status[hostname] = :error_authentication_failed
65
+ verbose Application.instance.letter[:error]
66
+ log('SSH::AuthenticationFailed!', :error)
67
+ rescue Net::SSH::HostKeyMismatch
68
+ @sessions[hostname] = :nosession
69
+ @conn_status[hostname] = :host_key_mismatch
70
+ verbose Application.instance.letter[:error]
71
+ log('SSH::HostKeyMismatch!', :error)
72
+ log("* The destination server's fingerprint is not matching " \
73
+ 'what is in your local known_hosts file.', :error)
74
+ log('* Remove the existing entry in your local known_hosts file', :error)
75
+ log("* Try this => ssh-keygen -f '/home/USERNAME/.ssh/known_hosts' " \
76
+ "-R #{ip}", :error)
77
+ rescue StandardError => e
78
+ @sessions[hostname] = :nosession
79
+ @conn_status[hostname] = :error
80
+ verbose Application.instance.letter[:error]
81
+ log("[#{e.class}] SSH on <#{username}@#{ip}>" \
82
+ " exec: #{@action[:command]}", :error)
83
+ end
84
+ output = encode_and_split(@action[:encoding], text)
85
+ @result.content = output
86
+ @result.content.compact!
87
+ end
88
+
89
+ def run_remote_cmd_telnet(input_hostname)
90
+ @action[:conn_type] = :telnet
91
+ app = Application.instance
92
+ hostname = input_hostname.to_s
93
+ ip = @config.get((hostname + '_ip').to_sym)
94
+ username = @config.get((hostname + '_username').to_sym).to_s
95
+ password = @config.get((hostname + '_password').to_sym).to_s
96
+ text = ''
97
+ begin
98
+ if @sessions[hostname].nil? || @sessions[hostname] == :ok
99
+ h = Net::Telnet.new( 'Host' => ip,
100
+ 'Timeout' => 30,
101
+ 'Prompt' => /login|teuton|[$%#>]/ )
102
+ # 'Prompt' => Regexp.new(username[1, 40]))
103
+ # 'Prompt' => /[$%#>] \z/n)
104
+ h.login(username, password)
105
+ text = ''
106
+ h.cmd(@action[:command]) { |i| text << i }
107
+ h.close
108
+ @sessions[hostname] = :ok
109
+ end
110
+ rescue Net::OpenTimeout
111
+ @sessions[hostname] = :nosession
112
+ @conn_status[hostname] = :open_timeout
113
+ verbose Application.instance.letter[:error]
114
+ log(" ExceptionType=<Net::OpenTimeout> doing <telnet #{ip}>", :error)
115
+ log(' └── Revise host IP!', :warn)
116
+ rescue Net::ReadTimeout
117
+ @sessions[hostname] = :nosession
118
+ @conn_status[hostname] = :read_timeout
119
+ verbose Application.instance.letter[:error]
120
+ log(" ExceptionType=<Net::ReadTimeout> doing <telnet #{ip}>", :error)
121
+ rescue StandardError => e
122
+ @sessions[hostname] = :nosession
123
+ @conn_status[hostname] = :error
124
+ verbose Application.instance.letter[:error]
125
+ log(" ExceptionType=<#{e.class}> doing telnet on <#{username}@#{ip}>" \
126
+ " exec: #{@action[:command]}", :error)
127
+ log(" └── username=<#{username}>, password=<#{password}>," \
128
+ " ip=<#{ip}>, HOSTID=<#{hostname}>", :warn)
129
+ end
130
+ output = encode_and_split(@action[:encoding], text)
131
+ @result.content = output
132
+ @result.content.compact!
133
+ end
134
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require_relative '../application'
5
+ require_relative '../report/report'
6
+ require_relative '../project/configfile_reader'
7
+ require_relative 'case/case'
8
+ require_relative 'export_manager'
9
+ require_relative 'main'
10
+ require_relative 'utils'
11
+
12
+ # This class does all the job
13
+ # Organize the hole job, sending orders to others classes
14
+ # * initialize
15
+ # * play
16
+ # Split into several files:
17
+ # * case_manager/check_cases
18
+ # * case_manager/export
19
+ # * case_manager/hall_of_fame
20
+ # * case_manager/report
21
+ # * case_manager/show
22
+ class CaseManager
23
+ include Singleton
24
+ include Utils
25
+
26
+ def initialize
27
+ @cases = []
28
+ @report = Report.new(0)
29
+ @report.filename = 'resume'
30
+ end
31
+
32
+ def play(&block)
33
+ check_cases!
34
+ instance_eval(&block)
35
+ # Run export if user pass option command "--export=json"
36
+ i = Application.instance.options['export']
37
+ export(format: i.to_sym) unless i.nil?
38
+ # Accept "configfile" param REVISE There exists?
39
+ i = Application.instance.options['configfile']
40
+ export(format: i.to_sym) unless i.nil?
41
+ end
42
+
43
+ def export(args = {})
44
+ if args.class != Hash
45
+ puts "[ERROR] CaseManager#export: Argument = <#{args}>, " \
46
+ "class = #{args.class}"
47
+ puts ' Usage: export :format => :colored_text'
48
+ raise '[ERROR] CaseManager#export: Argument error!'
49
+ end
50
+ ExportManager.run(@report, @cases, args)
51
+ preserve_files if args[:preserve] == true
52
+ end
53
+
54
+ def preserve_files
55
+ app = Application.instance
56
+ t = Time.now
57
+ subdir = "#{t.year}#{format('%02d',t.month)}#{format('%02d',t.day)}-" \
58
+ "#{format('%02d',t.hour)}#{format('%02d',t.min)}" \
59
+ "#{format('%02d',t.sec)}"
60
+ logdir = File.join(app.output_basedir, app.global[:tt_testname], subdir)
61
+ srcdir = File.join(app.output_basedir, app.global[:tt_testname])
62
+ puts "[INFO] Preserving files => #{logdir}"
63
+ FileUtils.mkdir(logdir)
64
+ Dir.glob('var/learn-08-preserve/**.*').each do |file|
65
+ FileUtils.cp(file, logdir)
66
+ end
67
+ end
68
+
69
+ def send(args = {})
70
+ threads = []
71
+ puts ''
72
+ puts "[INFO] Sending files...#{args.to_s}"
73
+ @cases.each { |c| threads << Thread.new { c.send(args) } }
74
+ threads.each(&:join)
75
+ end
76
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # CaseManager#check_cases!
4
+ class CaseManager
5
+ private
6
+
7
+ def check_cases!
8
+ app = Application.instance
9
+
10
+ # Load configurations from config file
11
+ configdata = ConfigFileReader.read(app.config_path)
12
+ app.ialias = configdata[:alias]
13
+ app.global = configdata[:global]
14
+ app.global[:tt_testname] = app.global[:tt_testname] || app.test_name
15
+ app.global[:tt_sequence] = false if app.global[:tt_sequence].nil?
16
+
17
+ # Create out dir
18
+ outdir = app.global[:tt_outdir] ||
19
+ File.join('var', app.global[:tt_testname])
20
+ ensure_dir outdir
21
+ @report.output_dir = outdir
22
+
23
+ # Fill report head
24
+ open_main_report(app.config_path)
25
+
26
+ # create cases and run
27
+ configdata[:cases].each { |config| @cases << Case.new(config) }
28
+ start_time = run_all_cases # run cases
29
+
30
+ uniques = collect_uniques_for_all_cases
31
+ close_reports_for_all_cases(uniques)
32
+ close_main_report(start_time)
33
+ end
34
+
35
+ def run_all_cases
36
+ start_time = Time.now
37
+ if Application.instance.global[:tt_sequence]
38
+ verboseln "[INFO] Running in sequence (#{start_time})"
39
+ # Run every case in sequence
40
+ @cases.each(&:play)
41
+ else
42
+ verboseln "[INFO] Running in parallel (#{start_time})"
43
+ threads = []
44
+ # Run all cases in parallel
45
+ @cases.each { |c| threads << Thread.new { c.play } }
46
+ threads.each(&:join)
47
+ end
48
+ start_time
49
+ end
50
+
51
+ def collect_uniques_for_all_cases
52
+ uniques = {} # Collect "unique" values from all cases
53
+ @cases.each do |c|
54
+ c.uniques.each do |key|
55
+ if uniques[key].nil?
56
+ uniques[key] = [c.id]
57
+ else
58
+ uniques[key] << c.id
59
+ end
60
+ end
61
+ end
62
+ uniques
63
+ end
64
+
65
+ def close_reports_for_all_cases(uniques)
66
+ threads = []
67
+ @cases.each { |c| threads << Thread.new { c.close uniques } }
68
+ threads.each(&:join)
69
+
70
+ # Build Hall of Fame
71
+ build_hall_of_fame
72
+ end
73
+ end