teuton 2.1.8 → 2.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -8
- data/bin/check_teuton +43 -0
- data/docs/changelog/contributions.md +32 -0
- data/docs/changelog/v2.1.md +22 -0
- data/docs/changelog/v2.2.md +29 -0
- data/docs/commands/README.md +105 -7
- data/docs/commands/example_check.md +54 -0
- data/docs/commands/example_run.md +112 -0
- data/docs/dsl/README.md +11 -9
- data/docs/dsl/definition/expect.md +25 -21
- data/docs/dsl/definition/group.md +5 -1
- data/docs/dsl/definition/result.md +45 -34
- data/docs/dsl/definition/run_local.md +34 -0
- data/docs/dsl/definition/run_remote.md +119 -0
- data/docs/dsl/definition/target.md +6 -0
- data/docs/dsl/execution/export.md +27 -19
- data/docs/dsl/execution/play.md +4 -0
- data/docs/dsl/execution/send.md +21 -2
- data/docs/dsl/execution/show.md +13 -8
- data/docs/dsl/setting/get.md +24 -8
- data/docs/dsl/setting/set.md +8 -3
- data/docs/install/README.md +19 -26
- data/docs/install/modes_of_use.md +27 -26
- data/docs/install/scripts.md +53 -36
- data/docs/install/vagrant_docker.md +56 -0
- data/docs/learn/README.md +13 -6
- data/docs/learn/example-01-target.md +78 -61
- data/docs/learn/example-02-config.md +152 -0
- data/docs/learn/example-03-remote-hosts.md +31 -25
- data/docs/learn/example-04-use.md +23 -17
- data/docs/learn/example-05-debug.md +24 -17
- data/docs/learn/example-06-log.md +70 -0
- data/lib/teuton/application.rb +7 -4
- data/lib/teuton/case_manager/case/case.rb +4 -1
- data/lib/teuton/case_manager/case/dsl/expect.rb +3 -1
- data/lib/teuton/case_manager/case/dsl/goto.rb +12 -7
- data/lib/teuton/case_manager/case/dsl/macro.rb +38 -0
- data/lib/teuton/case_manager/case/dsl/main.rb +1 -2
- data/lib/teuton/case_manager/case/dsl/target.rb +1 -1
- data/lib/teuton/case_manager/case/runner.rb +7 -7
- data/lib/teuton/case_manager/case_manager.rb +1 -20
- data/lib/teuton/case_manager/check_cases.rb +12 -2
- data/lib/teuton/case_manager/dsl.rb +4 -6
- data/lib/teuton/case_manager/export_manager.rb +29 -3
- data/lib/teuton/case_manager/report.rb +29 -8
- data/lib/teuton/case_manager/show.rb +8 -4
- data/lib/teuton/cli.rb +1 -0
- data/lib/teuton/cli/play.rb +1 -0
- data/lib/teuton/cli/version.rb +1 -4
- data/lib/teuton/files/config.yaml +0 -1
- data/lib/teuton/files/start.rb +1 -1
- data/lib/teuton/files/template/case.html +135 -0
- data/lib/teuton/files/template/resume.html +115 -0
- data/lib/teuton/project/laboratory/builtin.rb +2 -1
- data/lib/teuton/project/laboratory/dsl.rb +13 -15
- data/lib/teuton/project/laboratory/laboratory.rb +5 -1
- data/lib/teuton/project/laboratory/show.rb +21 -13
- data/lib/teuton/project/name_file_finder.rb +6 -1
- data/lib/teuton/project/project.rb +7 -3
- data/lib/teuton/project/readme/dsl.rb +3 -1
- data/lib/teuton/project/readme/readme.rb +37 -26
- data/lib/teuton/project/skeleton.rb +20 -4
- data/lib/teuton/report/close.rb +15 -11
- data/lib/teuton/report/formatter/formatter_factory.rb +10 -6
- data/lib/teuton/report/formatter/html_formatter.rb +16 -79
- data/lib/teuton/report/formatter/resume_html_formatter.rb +39 -0
- data/lib/teuton/report/formatter/resume_yaml_formatter.rb +7 -1
- data/lib/teuton/report/report.rb +5 -4
- data/lib/teuton/report/show.rb +55 -26
- metadata +26 -39
- data/docs/changelog/todo.md +0 -46
- data/docs/commands/create_skeleton.md +0 -31
- data/docs/commands/help.md +0 -13
- data/docs/commands/revise_test.md +0 -46
- data/docs/commands/run_test_unit.md +0 -78
- data/docs/commands/show_version.md +0 -9
- data/docs/developers/01-telnet.md +0 -121
- data/docs/developers/02-ssh.md +0 -93
- data/docs/developers/03-encoding.md +0 -153
- data/docs/developers/comparative.md +0 -17
- data/docs/dsl/_Sidebar.md +0 -30
- data/docs/dsl/definition/goto.md +0 -112
- data/docs/dsl/definition/run.md +0 -23
- data/docs/install/tested_os.md +0 -25
- data/docs/install/vagrant.md +0 -9
- data/docs/learn/example-02-configfile.md +0 -174
- data/docs/learn/quick-demo.md +0 -170
- data/lib/teuton/case_manager/case/dsl/check.rb +0 -24
- data/lib/teuton/case_manager/case/dsl/missing.rb +0 -12
- data/lib/teuton/files/gitignore +0 -2
@@ -1,6 +1,10 @@
|
|
1
|
-
|
2
1
|
[<< back](README.md)
|
3
2
|
|
3
|
+
1. [Tree directory](#tree-directory)
|
4
|
+
2. [Execution section](#execution-section)
|
5
|
+
3. [Users file](#users-file)
|
6
|
+
4. [Network file](#network-file)
|
7
|
+
|
4
8
|
# Example: learn-04-use
|
5
9
|
|
6
10
|
Learn how to:
|
@@ -14,8 +18,8 @@ Learn how to:
|
|
14
18
|
This example has more files:
|
15
19
|
|
16
20
|
```bash
|
17
|
-
$ tree
|
18
|
-
|
21
|
+
$ tree example/learn-04-use
|
22
|
+
example/learn-04-require
|
19
23
|
├── config.yaml
|
20
24
|
├── network.rb
|
21
25
|
├── README.md
|
@@ -23,11 +27,11 @@ learn/learn-04-require
|
|
23
27
|
└── users.rb
|
24
28
|
```
|
25
29
|
|
26
|
-
* `README.md` and `config.yaml` are the same as previous
|
30
|
+
* `README.md` and `config.yaml` are the same as previous example.
|
27
31
|
|
28
|
-
## Execution
|
32
|
+
## Execution section
|
29
33
|
|
30
|
-
Previous `start.rb` file is splited in: start.rb, users.rb and network.rb.
|
34
|
+
Previous `start.rb` file is now splited in: start.rb, users.rb and network.rb.
|
31
35
|
|
32
36
|
Let's see current `start.rb` file:
|
33
37
|
|
@@ -43,35 +47,37 @@ end
|
|
43
47
|
|
44
48
|
* `use`, indicates external rb file that will be included/imported into main rb file. It's a good idea to organize project files, when the number of groups/targets is high.
|
45
49
|
|
46
|
-
##
|
50
|
+
## Users file
|
47
51
|
|
48
52
|
> Require Windows OS on remote machine.
|
49
53
|
|
50
54
|
Let's see `users.rb` file
|
55
|
+
|
51
56
|
```ruby
|
52
|
-
group "User configuration" do
|
53
|
-
|
54
|
-
|
57
|
+
group "Use file: User configuration" do
|
58
|
+
|
59
|
+
target "Create user #{gett(:username)}"
|
60
|
+
run "net user", on: :host1
|
55
61
|
expect get(:username)
|
56
|
-
end
|
57
62
|
|
63
|
+
end
|
58
64
|
```
|
59
65
|
|
60
|
-
##
|
66
|
+
## Network file
|
61
67
|
|
62
68
|
> Require Windows OS on remote machine.
|
63
69
|
|
64
70
|
Let's see `network.rb` file:
|
65
71
|
|
66
72
|
```ruby
|
67
|
-
group "Network configuracion" do
|
73
|
+
group "Use file: Network configuracion" do
|
68
74
|
|
69
|
-
target "
|
70
|
-
|
75
|
+
target "Update computer name with #{gett(:host1_hostname)}"
|
76
|
+
run "hostname", on: :host1
|
71
77
|
expect_one get(:host1_hostname)
|
72
78
|
|
73
|
-
target "DNS Server
|
74
|
-
|
79
|
+
target "Ensure DNS Server is working"
|
80
|
+
run "nslookup www.google.es", on: :host1
|
75
81
|
expect "Nombre:"
|
76
82
|
|
77
83
|
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
|
2
2
|
[<< back](README.md)
|
3
3
|
|
4
|
+
1. [Tree directory](#tree-directory)
|
5
|
+
2. [Execution section](#execution-section)
|
6
|
+
3. [Check test](#check-test)
|
7
|
+
4. [Debug](#debug)
|
8
|
+
|
4
9
|
# Example: learn-05-debug
|
5
10
|
|
6
11
|
Learn how to:
|
@@ -13,7 +18,7 @@ Learn how to:
|
|
13
18
|
|
14
19
|
```bash
|
15
20
|
$ tree learn/learn-05-debug
|
16
|
-
|
21
|
+
example/learn-05-debug
|
17
22
|
├── config.yaml
|
18
23
|
├── external.rb
|
19
24
|
├── internal.rb
|
@@ -21,7 +26,7 @@ learn/learn-05-debug
|
|
21
26
|
└── start.rb
|
22
27
|
```
|
23
28
|
|
24
|
-
## Execution
|
29
|
+
## Execution section
|
25
30
|
|
26
31
|
The `start.rb` is main execution rb file, and uses `external` and `internal` rb files.
|
27
32
|
|
@@ -37,24 +42,26 @@ play do
|
|
37
42
|
end
|
38
43
|
```
|
39
44
|
|
40
|
-
##
|
45
|
+
## Check test
|
41
46
|
|
42
47
|
Tests grows and becames huge, with a lot of targets (That isn't a problem). Then, we organize them spliting into several files and invoke `use` keywork from our main rb file to load other files (That's good idea) .
|
43
48
|
|
44
|
-
When this happend, sometimes we need to verify or check rb file consistency and syntax, and we will do it with `teuton check PATH/TO/PROJECT/FOLDER`.
|
49
|
+
When this happend, sometimes we need to verify or check rb file consistency and syntax, and we will do it with `teuton check PATH/TO/PROJECT/FOLDER`.
|
50
|
+
|
51
|
+
Let's see example `teuton check examples/learn-01-target`:
|
45
52
|
|
46
53
|
```bash
|
47
|
-
|
48
|
-
[INFO]
|
49
|
-
[INFO]
|
54
|
+
[INFO] ScriptPath => examples/learn-01-target/start.rb
|
55
|
+
[INFO] ConfigPath => examples/learn-01-target/config.yaml
|
56
|
+
[INFO] Pwd => /mnt/home/leap/proy/repos/teuton.d/teuton
|
50
57
|
[INFO] TestName => learn-01-target
|
51
58
|
|
52
|
-
|
53
|
-
| GROUP:
|
54
|
-
|
55
|
-
(001) target Create user
|
59
|
+
+----------------------------+
|
60
|
+
| GROUP: Learn about targets |
|
61
|
+
+----------------------------+
|
62
|
+
(001) target Create user david
|
56
63
|
weight 1.0
|
57
|
-
|
64
|
+
run 'id david' on localhost
|
58
65
|
expect david (String)
|
59
66
|
|
60
67
|
+--------------+-------+
|
@@ -83,23 +90,23 @@ teuton check examples/learn-01-target
|
|
83
90
|
|
84
91
|
In this case, Teuton detects that there isn't exist config file, and propose us content for `config.yaml`.
|
85
92
|
|
86
|
-
##
|
93
|
+
## Debug
|
87
94
|
|
88
|
-
Every time we invoke `
|
95
|
+
Every time we invoke `run` or `goto` keywork, an OS command is executed. The output is showed on screen and saved into **result** internal object.
|
89
96
|
|
90
|
-
We could debug it invoking `result.debug` into our
|
97
|
+
We could debug it invoking `result.debug` into our tests. Let's see an example from `external.rb` file:
|
91
98
|
|
92
99
|
```ruby
|
93
100
|
group "Windows: external configuration" do
|
94
101
|
|
95
102
|
target "Localhost: Verify connectivity with #{gett(:windows1_ip)}"
|
96
|
-
run
|
103
|
+
run "ping #{get(:windows1_ip)} -c 1"
|
97
104
|
result.debug
|
98
105
|
expect_one "0% packet loss"
|
99
106
|
result.debug
|
100
107
|
|
101
108
|
target "Localhost: netbios-ssn service working on #{gett(:windows1_ip)}"
|
102
|
-
run
|
109
|
+
run "nmap -Pn #{get(:windows1_ip)}"
|
103
110
|
expect "139/tcp", "open"
|
104
111
|
|
105
112
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
[<< back](README.md)
|
2
|
+
|
3
|
+
1. [Definition section](#definition-section)
|
4
|
+
2. [Run test](#execution-section)
|
5
|
+
3. [Result](#result)
|
6
|
+
|
7
|
+
# Example: learn-06-log
|
8
|
+
|
9
|
+
Let's learn how to create log messages.
|
10
|
+
|
11
|
+
> This example is on GitHub repository at `examples/learn-06-log/`.
|
12
|
+
|
13
|
+
## Definition section
|
14
|
+
|
15
|
+
Test definition section (Group):
|
16
|
+
```ruby
|
17
|
+
group "Learning about log messages" do
|
18
|
+
log 'Using log messages...'
|
19
|
+
|
20
|
+
target "Create user david"
|
21
|
+
run "id david"
|
22
|
+
expect "david"
|
23
|
+
|
24
|
+
log 'Problem detected!', :error
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
> In this example, localhost's OS must be GNU/Linux (any other compatible OS) because the command used is `id david`.
|
29
|
+
|
30
|
+
## Result
|
31
|
+
|
32
|
+
**Let's see example**: Content of `var/learn-06-log/case-01.txt` file.
|
33
|
+
|
34
|
+
```bash
|
35
|
+
CONFIGURATION
|
36
|
+
+-------------+--------------+
|
37
|
+
| tt_members | anonymous |
|
38
|
+
| tt_sequence | false |
|
39
|
+
| tt_skip | false |
|
40
|
+
| tt_testname | learn-06-log |
|
41
|
+
+-------------+--------------+
|
42
|
+
|
43
|
+
LOGS
|
44
|
+
[19:23:20] : Using log messages...
|
45
|
+
[19:23:20] ERROR: Problem detected!
|
46
|
+
|
47
|
+
GROUPS
|
48
|
+
- Learning about log messages
|
49
|
+
01 (1.0/1.0)
|
50
|
+
Description : Create user david
|
51
|
+
Command : id david
|
52
|
+
Duration : 0.003 (local)
|
53
|
+
Alterations : find(david) & count
|
54
|
+
Expected : Greater than 0 (String)
|
55
|
+
Result : 1 (Integer)
|
56
|
+
|
57
|
+
RESULTS
|
58
|
+
+--------------+---------------------------+
|
59
|
+
| case_id | 01 |
|
60
|
+
| start_time | 2020-04-22 19:23:20 +0100 |
|
61
|
+
| finish_time | 2020-04-22 19:23:20 +0100 |
|
62
|
+
| duration | 0.003096755 |
|
63
|
+
| unique_fault | 0 |
|
64
|
+
| max_weight | 1.0 |
|
65
|
+
| good_weight | 1.0 |
|
66
|
+
| fail_weight | 0.0 |
|
67
|
+
| fail_counter | 0 |
|
68
|
+
| grade | 100 |
|
69
|
+
+--------------+---------------------------+
|
70
|
+
```
|
data/lib/teuton/application.rb
CHANGED
@@ -6,7 +6,7 @@ require 'singleton'
|
|
6
6
|
class Application
|
7
7
|
include Singleton
|
8
8
|
|
9
|
-
VERSION = '2.1.
|
9
|
+
VERSION = '2.1.9' # Application version
|
10
10
|
NAME = 'teuton' # Application name
|
11
11
|
|
12
12
|
attr_reader :letter
|
@@ -14,8 +14,11 @@ class Application
|
|
14
14
|
attr_reader :default
|
15
15
|
attr_accessor :options
|
16
16
|
attr_accessor :verbose
|
17
|
-
attr_accessor :global
|
18
|
-
attr_accessor :
|
17
|
+
attr_accessor :global # Global configuration params
|
18
|
+
attr_accessor :ialias # Internal alias
|
19
|
+
attr_accessor :macros # Array of macros
|
20
|
+
attr_accessor :groups # Array of groups
|
21
|
+
attr_accessor :uses # Array of uses
|
19
22
|
attr_accessor :hall_of_fame
|
20
23
|
attr_accessor :project_path, :script_path, :config_path, :test_name
|
21
24
|
|
@@ -38,7 +41,7 @@ class Application
|
|
38
41
|
|
39
42
|
@global = {}
|
40
43
|
@ialias = {}
|
41
|
-
@
|
44
|
+
@macros = {}
|
42
45
|
@groups = []
|
43
46
|
@uses = [] # TODO
|
44
47
|
@hall_of_fame = []
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'rainbow'
|
4
|
+
|
3
5
|
# DSL module:
|
4
6
|
# * expect_none
|
5
7
|
# * expect_one
|
@@ -62,7 +64,7 @@ module DSL
|
|
62
64
|
app = Application.instance
|
63
65
|
c = app.letter[:bad]
|
64
66
|
c = app.letter[:good] if cond
|
65
|
-
verbose c
|
67
|
+
verbose Rainbow(c).yellow.bright
|
66
68
|
end
|
67
69
|
|
68
70
|
# Set weight value for the action
|
@@ -6,10 +6,22 @@ require_relative '../runner'
|
|
6
6
|
# * goto
|
7
7
|
# * run
|
8
8
|
module DSL
|
9
|
+
##
|
10
|
+
# DLS run: It's the same as goto :localhost
|
11
|
+
# @param command (String)
|
12
|
+
# @param args (Hash)
|
13
|
+
def run(command, args = {})
|
14
|
+
args[:exec] = command.to_s
|
15
|
+
host = :localhost
|
16
|
+
host = args[:on] if args[:on]
|
17
|
+
goto(host, args)
|
18
|
+
end
|
19
|
+
|
9
20
|
# Run command from the host identify as pHostname
|
10
21
|
# goto :host1, :execute => "command"
|
11
22
|
def goto(host = :localhost, args = {})
|
12
23
|
@result.reset
|
24
|
+
args[:on] = host unless args[:on]
|
13
25
|
@action[:command] = args[:execute] if args[:execute]
|
14
26
|
@action[:command] = args[:exec] if args[:exec]
|
15
27
|
tempfile(args[:tempfile]) if args[:tempfile]
|
@@ -20,11 +32,4 @@ module DSL
|
|
20
32
|
@action[:duration] = (Time.now - start_time).round(3)
|
21
33
|
end
|
22
34
|
alias on goto
|
23
|
-
|
24
|
-
##
|
25
|
-
# DLS run: It's the same as goto :localhost
|
26
|
-
def run(command, args = {})
|
27
|
-
args[:exec] = command.to_s
|
28
|
-
goto(:localhost, args)
|
29
|
-
end
|
30
35
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../../../application'
|
3
|
+
|
4
|
+
# DSL module methods: assert, missing_method
|
5
|
+
module DSL
|
6
|
+
##
|
7
|
+
# Invoke macro
|
8
|
+
# @param name (String) Macro name
|
9
|
+
# @param input (Hash) Macro params
|
10
|
+
def macro(name, input = {})
|
11
|
+
macros = Application.instance.macros
|
12
|
+
unless macros[name]
|
13
|
+
log("Macro #{name} not found!", :error)
|
14
|
+
return
|
15
|
+
end
|
16
|
+
input.each_pair { |k, v| set(k, v) }
|
17
|
+
errors = []
|
18
|
+
macros[name][:args].each do |i|
|
19
|
+
errors << i if get(i) == 'NODATA'
|
20
|
+
end
|
21
|
+
if errors.count > 0
|
22
|
+
log("Macro #{name} => required params #{errors.join(',')}",:error)
|
23
|
+
else
|
24
|
+
instance_eval(¯os[name][:block])
|
25
|
+
end
|
26
|
+
input.each_pair { |k, v| unset(k) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# If a method call is missing, then:
|
30
|
+
# * delegate to concept parent.
|
31
|
+
# * Invoke macro (assert)
|
32
|
+
def method_missing(method, args = {})
|
33
|
+
a = method.to_s
|
34
|
+
return instance_eval("get(:#{a[0, a.size - 1]})") if a[a.size - 1] == '?'
|
35
|
+
return macro a[6, a.size], args if a[0,6]=='macro_'
|
36
|
+
macro a, args
|
37
|
+
end
|
38
|
+
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'check'
|
4
3
|
require_relative 'expect'
|
5
4
|
require_relative 'getset'
|
6
5
|
require_relative 'goto'
|
7
6
|
require_relative 'log'
|
8
|
-
require_relative '
|
7
|
+
require_relative 'macro'
|
9
8
|
require_relative 'send'
|
10
9
|
require_relative 'target'
|
11
10
|
require_relative 'unique'
|
@@ -84,17 +84,17 @@ class Case
|
|
84
84
|
rescue Errno::EHOSTUNREACH
|
85
85
|
@sessions[hostname] = :nosession
|
86
86
|
@conn_status[hostname] = :host_unreachable
|
87
|
-
verbose Application.instance.letter[:error]
|
87
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
88
88
|
log("Host #{ip} unreachable!", :error)
|
89
89
|
rescue Net::SSH::AuthenticationFailed
|
90
90
|
@sessions[hostname] = :nosession
|
91
91
|
@conn_status[hostname] = :error_authentication_failed
|
92
|
-
verbose Application.instance.letter[:error]
|
92
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
93
93
|
log('SSH::AuthenticationFailed!', :error)
|
94
94
|
rescue Net::SSH::HostKeyMismatch
|
95
95
|
@sessions[hostname] = :nosession
|
96
96
|
@conn_status[hostname] = :host_key_mismatch
|
97
|
-
verbose Application.instance.letter[:error]
|
97
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
98
98
|
log('SSH::HostKeyMismatch!', :error)
|
99
99
|
log("* The destination server's fingerprint is not matching " \
|
100
100
|
'what is in your local known_hosts file.', :error)
|
@@ -104,7 +104,7 @@ class Case
|
|
104
104
|
rescue StandardError => e
|
105
105
|
@sessions[hostname] = :nosession
|
106
106
|
@conn_status[hostname] = :error
|
107
|
-
verbose Application.instance.letter[:error]
|
107
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
108
108
|
log("[#{e.class}] SSH on <#{username}@#{ip}>" \
|
109
109
|
" exec: #{@action[:command]}", :error)
|
110
110
|
end
|
@@ -137,18 +137,18 @@ class Case
|
|
137
137
|
rescue Net::OpenTimeout
|
138
138
|
@sessions[hostname] = :nosession
|
139
139
|
@conn_status[hostname] = :open_timeout
|
140
|
-
verbose Application.instance.letter[:error]
|
140
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
141
141
|
log(" ExceptionType=<Net::OpenTimeout> doing <telnet #{ip}>", :error)
|
142
142
|
log(' └── Revise host IP!', :warn)
|
143
143
|
rescue Net::ReadTimeout
|
144
144
|
@sessions[hostname] = :nosession
|
145
145
|
@conn_status[hostname] = :read_timeout
|
146
|
-
verbose Application.instance.letter[:error]
|
146
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
147
147
|
log(" ExceptionType=<Net::ReadTimeout> doing <telnet #{ip}>", :error)
|
148
148
|
rescue StandardError => e
|
149
149
|
@sessions[hostname] = :nosession
|
150
150
|
@conn_status[hostname] = :error
|
151
|
-
verbose Application.instance.letter[:error]
|
151
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
152
152
|
log(" ExceptionType=<#{e.class}> doing telnet on <#{username}@#{ip}>" \
|
153
153
|
" exec: #{@action[:command]}", :error)
|
154
154
|
log(" └── username=<#{username}>, password=<#{password}>," \
|