teuton 3.2.0 → 3.2.1
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 +1 -1
- data/bin/teuton +2 -3
- data/docs/commands/readme.md +1 -1
- data/docs/devel/todo.md +74 -1
- data/docs/dsl/send.md +3 -3
- data/docs/dsl/show.md +2 -2
- data/docs/tutorial/es/nginx/README.md +4 -4
- data/lib/teuton/case/action.rb +31 -0
- data/lib/teuton/case/case.rb +8 -12
- data/lib/teuton/case/close.rb +1 -1
- data/lib/teuton/case/dsl/expect.rb +9 -10
- data/lib/teuton/case/dsl/expect_sequence.rb +1 -2
- data/lib/teuton/case/dsl/macro.rb +3 -2
- data/lib/teuton/case/dsl/run.rb +4 -5
- data/lib/teuton/case/dsl/send.rb +1 -17
- data/lib/teuton/case/dsl/target.rb +6 -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 +7 -8
- data/lib/teuton/case_manager/case_manager.rb +4 -4
- data/lib/teuton/case_manager/dsl.rb +6 -9
- data/lib/teuton/case_manager/export_manager.rb +6 -12
- data/lib/teuton/case_manager/ext/check_cases.rb +1 -1
- 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 +7 -5
- 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/txt.rb +2 -2
- data/lib/teuton/report/formatter/formatter.rb +4 -13
- data/lib/teuton/report/formatter/resume/txt.rb +2 -2
- 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/version.rb +1 -1
- data/lib/teuton.rb +6 -11
- metadata +6 -2
- data/lib/teuton/cli.rb +0 -120
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3516a5e7aa9c634173b9e5eb7861ff1714ee4e583da4bcad3c01ac8400831313
|
|
4
|
+
data.tar.gz: c551387224c5c47a545c4455a673d7401495b0a2ef000770010c8d0d3926079d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 320eb8621ce4b42c2f5316a2b8edb7a8a6ea01abf9fc2e42588df583bd3baa10a22b51b9389d829544a1fae82a84934f6e1c82d98624a6bd263a8cafb5db2678
|
|
7
|
+
data.tar.gz: 80cc780a54d6b2771904475f5cd89b6954b46c9cf9e04a173cc6dc0e996db13eb3bed7dd2c92b252ae8d58faedb16d1f361d4e151fb26f8baab4f812349086c1
|
data/README.md
CHANGED
data/bin/teuton
CHANGED
data/docs/commands/readme.md
CHANGED
data/docs/devel/todo.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Aplicar las recomendaciones del informe de seguridad de Andrés.
|
|
10
10
|
* verify get(:key) and get('key') works fine!
|
|
11
11
|
* Formatter: xml
|
|
12
|
+
* Revisar la utilidad de action.assets al generar README.
|
|
12
13
|
|
|
13
14
|
# 2. Documentacion
|
|
14
15
|
|
|
@@ -45,7 +46,7 @@ Ampliar las estadísticas de salida en el report `resume`:
|
|
|
45
46
|
|
|
46
47
|
Nueva feature "eventos".
|
|
47
48
|
|
|
48
|
-
* La idea está
|
|
49
|
+
* La idea está desarrollada en el enlace siguiente.
|
|
49
50
|
* [Propuesta](https://github.com/dvarrui/teuton-book/blob/main/docs/03.eventos/index.md)
|
|
50
51
|
|
|
51
52
|
Idea antigua: `ensure`
|
|
@@ -177,6 +178,78 @@ Expandir el modo de ejecución y medir rendimiento:
|
|
|
177
178
|
- Fibras
|
|
178
179
|
- Actores
|
|
179
180
|
|
|
181
|
+
## 4.6 Excepciones vs exit
|
|
182
|
+
|
|
183
|
+
La buena práctica es la separación de responsabilidades:
|
|
184
|
+
|
|
185
|
+
* La librería nunca debe hacer exit ni abort. Su trabajo es exclusivamente levantar excepciones personalizadas cuando algo sale mal.
|
|
186
|
+
* El ejecutable (CLI) es el único que debe capturar esas excepciones, mostrarlas de forma amigable por la terminal y decidir cuándo terminar el proceso con exit 1.
|
|
187
|
+
|
|
188
|
+
* **Paso 1: Definir excepciones personalizadas**:
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
# lib/teuton/errors.rb
|
|
192
|
+
module Teuton
|
|
193
|
+
class Error < StandardError; end
|
|
194
|
+
class ConfigurationError < Error; end
|
|
195
|
+
class ExecutionError < Error; end
|
|
196
|
+
end
|
|
197
|
+
```
|
|
198
|
+
* **Paso 2: Reemplazar los exit 1 en la librería por `raise`**
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
# lib/teuton/runner.rb
|
|
202
|
+
def run
|
|
203
|
+
if invalid_config?
|
|
204
|
+
raise Teuton::ConfigurationError, "Configuración inválida"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
* Paso 3: Capturar las excepciones en CLI
|
|
210
|
+
* Integración con Thor
|
|
211
|
+
|
|
212
|
+
1. Hacer que Thor devuelva un código de salida 1 en errores de Thor
|
|
213
|
+
|
|
214
|
+
```ruby
|
|
215
|
+
# lib/teuton/cli.rb
|
|
216
|
+
require "thor"
|
|
217
|
+
|
|
218
|
+
module Teuton
|
|
219
|
+
class CLI < Thor
|
|
220
|
+
# Esto asegura que si Thor falla internamente (ej: comandos/opciones inválidas),
|
|
221
|
+
# el programa salga con código 1 en lugar de 0.
|
|
222
|
+
def self.exit_on_failure?
|
|
223
|
+
true
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
desc "run", "Ejecuta un script de Teuton"
|
|
227
|
+
def run
|
|
228
|
+
# Aquí llamas a la lógica de tu gema
|
|
229
|
+
# Si hay un error, tu lógica lanzará una excepción (ej: Teuton::Error)
|
|
230
|
+
Teuton::Runner.new.execute
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
2. Lanzar excepciones personalizadas en la lógica de tu librería.
|
|
237
|
+
|
|
238
|
+
```ruby
|
|
239
|
+
# lib/teuton/runner.rb
|
|
240
|
+
module Teuton
|
|
241
|
+
class Runner
|
|
242
|
+
def execute
|
|
243
|
+
if algun_error_detectado?
|
|
244
|
+
raise Teuton::Error, "Ocurrió un error al ejecutar los tests"
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
3. Capturar excepciones en el ejecutable bin/teuton
|
|
252
|
+
|
|
180
253
|
# 5. Proyectos
|
|
181
254
|
|
|
182
255
|
Ideas que emepzaron como un nuevo feature pero por sus dimensiones, funcionalidades y características van ha derivar a su propio proyecto independiente:
|
data/docs/dsl/send.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
8
|
```ruby
|
|
9
|
-
|
|
9
|
+
play do
|
|
10
10
|
export
|
|
11
11
|
send copy_to: :host1
|
|
12
12
|
end
|
|
@@ -31,7 +31,7 @@ If you export several files using differents output formats, you will use severa
|
|
|
31
31
|
In this example we export html and txt files, but only send txt to remote hosts:
|
|
32
32
|
|
|
33
33
|
```ruby
|
|
34
|
-
|
|
34
|
+
play do
|
|
35
35
|
export format: :json
|
|
36
36
|
export format: :txt
|
|
37
37
|
|
|
@@ -42,7 +42,7 @@ end
|
|
|
42
42
|
If you want to send every exported output file, then do like this:
|
|
43
43
|
|
|
44
44
|
```ruby
|
|
45
|
-
|
|
45
|
+
play do
|
|
46
46
|
export format: :html
|
|
47
47
|
send copy_to: :host1
|
|
48
48
|
|
data/docs/dsl/show.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
When all tests are finished, the `show` command displays information on the screen about the final results.
|
|
6
6
|
|
|
7
7
|
```ruby
|
|
8
|
-
|
|
8
|
+
play do
|
|
9
9
|
show
|
|
10
10
|
end
|
|
11
11
|
```
|
|
@@ -18,7 +18,7 @@ end
|
|
|
18
18
|
| `show verbose: NUMBER` | NUMBER is the value of the verbose level |
|
|
19
19
|
|
|
20
20
|
```ruby
|
|
21
|
-
|
|
21
|
+
play do
|
|
22
22
|
show verbose: 1
|
|
23
23
|
end
|
|
24
24
|
```
|
|
@@ -43,7 +43,7 @@ Usando la siguiente plantilla de ejemplo de la herramienta Teuton:
|
|
|
43
43
|
expect_fail
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
play do
|
|
47
47
|
show
|
|
48
48
|
export
|
|
49
49
|
end
|
|
@@ -80,7 +80,7 @@ group "Nginx Web Service Checks" do
|
|
|
80
80
|
expect ["Hola Mundo!"]
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
play do
|
|
84
84
|
show
|
|
85
85
|
export
|
|
86
86
|
end
|
|
@@ -109,7 +109,7 @@ group "Comprobar el servicio web Nginx" do
|
|
|
109
109
|
expect "Hola Mundo!"
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
play do
|
|
113
113
|
show
|
|
114
114
|
export
|
|
115
115
|
end
|
|
@@ -129,7 +129,7 @@ end
|
|
|
129
129
|
# File: start.rb (Script principal)
|
|
130
130
|
use "nginx"
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
play do
|
|
133
133
|
show
|
|
134
134
|
export
|
|
135
135
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class Case
|
|
2
|
+
class Action
|
|
3
|
+
attr_reader :id
|
|
4
|
+
attr_accessor :groupname, :description, :weight, :asset,
|
|
5
|
+
:command, :encoding, :host, :exec, :conn_type, :duration,
|
|
6
|
+
:result, :output, :alterations, :expected, :check
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@id = 0
|
|
10
|
+
@groupname = nil
|
|
11
|
+
@description = "No description!"
|
|
12
|
+
@weight = 1.0
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def next
|
|
16
|
+
@id += 1
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_h
|
|
21
|
+
{
|
|
22
|
+
id: id,
|
|
23
|
+
groupname: groupname, description: description, weight: weight, asset: asset,
|
|
24
|
+
command: command, encoding: encoding, host: host, exec: exec,
|
|
25
|
+
conn_type: conn_type, duration: duration,
|
|
26
|
+
result: result, output: output,
|
|
27
|
+
alterations: alterations, expected: expected, check: check
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/teuton/case/case.rb
CHANGED
|
@@ -4,6 +4,7 @@ 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"
|
|
7
8
|
require_relative "config"
|
|
8
9
|
require_relative "close"
|
|
9
10
|
# require_relative "builtin/main"
|
|
@@ -20,7 +21,11 @@ class Case
|
|
|
20
21
|
# Readed by ExecuteManager
|
|
21
22
|
attr_reader :id, :config, :uniques, :skip
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
@current_case_id = "00" # First case ID value
|
|
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(
|
|
@@ -28,9 +33,7 @@ class Case
|
|
|
28
33
|
global: Project.value[:global]
|
|
29
34
|
)
|
|
30
35
|
@groups = Project.value[:groups]
|
|
31
|
-
|
|
32
|
-
@id = @@id
|
|
33
|
-
@@id = @@id.next
|
|
36
|
+
@id = Case.next_id
|
|
34
37
|
|
|
35
38
|
# Define Case Report
|
|
36
39
|
@report = Report.new(@id)
|
|
@@ -49,17 +52,10 @@ class Case
|
|
|
49
52
|
|
|
50
53
|
@unique_values = {}
|
|
51
54
|
@result = Result.new
|
|
52
|
-
@
|
|
53
|
-
@action = {
|
|
54
|
-
id: 0,
|
|
55
|
-
weight: 1.0,
|
|
56
|
-
description: "No description!",
|
|
57
|
-
groupname: nil
|
|
58
|
-
}
|
|
55
|
+
@action = Action.new
|
|
59
56
|
@uniques = []
|
|
60
57
|
@sessions = {} # Store opened sessions for this case
|
|
61
58
|
@conn_status = {}
|
|
62
|
-
tempfile :default
|
|
63
59
|
end
|
|
64
60
|
|
|
65
61
|
def export(format)
|
data/lib/teuton/case/close.rb
CHANGED
|
@@ -20,21 +20,20 @@ module DSL
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def expect2(cond, args = {})
|
|
23
|
-
@
|
|
24
|
-
|
|
25
|
-
if @result.exitcode < 0
|
|
23
|
+
@action.next
|
|
24
|
+
if @result.exitcode.negative?
|
|
26
25
|
# When exitcode is less than zero, it is because there has been
|
|
27
26
|
# an error in the remote connection (SSH or Telnet)
|
|
28
|
-
@action
|
|
29
|
-
@action
|
|
27
|
+
@action.check = false
|
|
28
|
+
@action.result = @action.output
|
|
30
29
|
else
|
|
31
|
-
@action
|
|
32
|
-
@action
|
|
30
|
+
@action.check = cond
|
|
31
|
+
@action.result = (args[:value] || @result.value)
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
@action
|
|
36
|
-
@action
|
|
37
|
-
@report.lines << @action.
|
|
34
|
+
@action.alterations = @result.alterations
|
|
35
|
+
@action.expected = (args[:expected] || @result.expected)
|
|
36
|
+
@report.lines << @action.to_h
|
|
38
37
|
weight(1.0)
|
|
39
38
|
|
|
40
39
|
c = Settings.letter[:fail]
|
|
@@ -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
|
|
@@ -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("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
|
@@ -19,13 +19,12 @@ module DSL
|
|
|
19
19
|
def goto(host = :localhost, args = {})
|
|
20
20
|
@result.reset
|
|
21
21
|
args[:on] = host unless args[:on]
|
|
22
|
-
@action
|
|
23
|
-
@action
|
|
24
|
-
|
|
25
|
-
@action[:encoding] = args[:encoding] || "UTF-8"
|
|
22
|
+
@action.command = args[:execute].to_s if args[:execute]
|
|
23
|
+
@action.command = args[:exec].to_s if args[:exec]
|
|
24
|
+
@action.encoding = args[:encoding] || "UTF-8"
|
|
26
25
|
|
|
27
26
|
ExecuteManager.new(self).call(host)
|
|
28
|
-
@action
|
|
27
|
+
@action.output = if @result.content.size < 2
|
|
29
28
|
@result.value.clone
|
|
30
29
|
else
|
|
31
30
|
"(#{@result.content.size} lines)"
|
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,16 @@
|
|
|
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
|
|
11
|
+
@action.description = desc.to_s
|
|
12
|
+
@action.asset = args[:asset].to_s if args[:asset]
|
|
12
13
|
w = args[:weight] || 1.0
|
|
13
14
|
weight(w)
|
|
14
15
|
end
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
alias_method :goal, :target # DEPRECATE
|
|
16
18
|
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
|
|
@@ -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"
|
|
@@ -29,11 +29,11 @@ class CaseManager
|
|
|
29
29
|
check_cases!
|
|
30
30
|
instance_eval(&block)
|
|
31
31
|
# Run export if user pass option command "--export=FORMAT"
|
|
32
|
-
|
|
33
|
-
export(format:
|
|
32
|
+
option = Project.value[:options]["export"]
|
|
33
|
+
export(format: option.to_sym) unless option.nil?
|
|
34
34
|
# Accept "configfile" param REVISE There exists?
|
|
35
|
-
|
|
36
|
-
export(format:
|
|
35
|
+
option = Project.value[:options]["configfile"]
|
|
36
|
+
export(format: option.to_sym) unless option.nil?
|
|
37
37
|
# TODO: Export Stats
|
|
38
38
|
# StatsManager.new.call(@cases)
|
|
39
39
|
end
|