teuton 2.5.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/CHANGELOG.md +2 -0
- data/docs/changelog/todo.md +4 -6
- data/docs/changelog/v2.6.md +4 -0
- data/docs/changelog/v2.7.md +11 -0
- data/docs/diagram.md +55 -0
- data/docs/learn/02-target.md +37 -12
- data/docs/learn/03-remote_hosts.md +1 -1
- data/docs/learn/04-config.md +1 -1
- data/docs/learn/06-cmd_check.md +4 -6
- data/docs/learn/07-target_weight.md +1 -3
- data/docs/learn/21-exit_codes.md +9 -16
- data/docs/learn/README.md +1 -1
- data/lib/teuton/case/case.rb +95 -0
- data/lib/teuton/{case_manager/case → case}/close.rb +2 -0
- data/lib/teuton/{case_manager/case → case}/config.rb +3 -3
- data/lib/teuton/{case_manager/case → case/deprecated}/runner.rb +14 -10
- data/lib/teuton/case/deprecated/utils.rb +40 -0
- data/lib/teuton/{case_manager/case/dsl/main.rb → case/dsl/all.rb} +0 -2
- data/lib/teuton/{case_manager/case → case}/dsl/expect.rb +25 -9
- data/lib/teuton/{case_manager/case → case}/dsl/goto.rb +10 -9
- data/lib/teuton/{case_manager/case → case}/dsl/log.rb +1 -2
- data/lib/teuton/{case_manager/case → case}/dsl/macro.rb +2 -2
- data/lib/teuton/{case_manager/case → case}/dsl/send.rb +3 -8
- data/lib/teuton/case/execute/execute_base.rb +55 -0
- data/lib/teuton/case/execute/execute_local.rb +29 -0
- data/lib/teuton/case/execute/execute_manager.rb +56 -0
- data/lib/teuton/case/execute/execute_ssh.rb +90 -0
- data/lib/teuton/case/execute/execute_telnet.rb +56 -0
- data/lib/teuton/{case_manager/case → case}/play.rb +11 -14
- data/lib/teuton/case_manager/case_manager.rb +20 -39
- data/lib/teuton/case_manager/check_cases.rb +14 -12
- data/lib/teuton/case_manager/dsl.rb +7 -9
- data/lib/teuton/case_manager/export_manager.rb +19 -6
- data/lib/teuton/case_manager/hall_of_fame.rb +9 -10
- data/lib/teuton/case_manager/report.rb +11 -9
- data/lib/teuton/case_manager/send_manager.rb +17 -0
- data/lib/teuton/{report/show.rb → case_manager/show_report.rb} +4 -6
- data/lib/teuton/case_manager/utils.rb +2 -43
- data/lib/teuton/check/dsl.rb +1 -2
- data/lib/teuton/check/laboratory.rb +7 -7
- data/lib/teuton/check/show.rb +5 -8
- data/lib/teuton/cli.rb +10 -0
- data/lib/teuton/readme/dsl.rb +5 -7
- data/lib/teuton/readme/lang.rb +3 -2
- data/lib/teuton/readme/readme.rb +15 -18
- data/lib/teuton/report/formatter/default/array.rb +6 -5
- data/lib/teuton/report/formatter/default/txt.rb +1 -0
- data/lib/teuton/report/formatter/resume/array.rb +3 -3
- data/lib/teuton/report/formatter/resume/html.rb +2 -2
- data/lib/teuton/report/report.rb +6 -5
- data/lib/teuton/skeleton.rb +8 -10
- data/lib/teuton/{application.rb → utils/application.rb} +13 -5
- data/lib/teuton/utils/name_file_finder.rb +40 -45
- data/lib/teuton/utils/project.rb +73 -0
- data/lib/teuton/{case_manager/case → utils}/result/ext_array.rb +5 -5
- data/lib/teuton/{case_manager/case → utils}/result/result.rb +10 -8
- data/lib/teuton/utils/settings.rb +12 -0
- data/lib/teuton/utils/verbose.rb +2 -2
- data/lib/teuton/version.rb +1 -1
- data/lib/teuton.rb +28 -27
- metadata +43 -30
- data/lib/teuton/case_manager/case/case.rb +0 -117
- data/lib/teuton/case_manager/case/main.rb +0 -7
- data/lib/teuton/case_manager/main.rb +0 -3
- /data/lib/teuton/{case_manager/case → case}/builtin/main.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/builtin/package.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/builtin/service.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/builtin/teuton_file.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/builtin/teuton_host.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/builtin/user.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/dsl/getset.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/dsl/target.rb +0 -0
- /data/lib/teuton/{case_manager/case → case}/dsl/unique.rb +0 -0
- /data/lib/teuton/{case_manager/case → utils}/result/ext_compare.rb +0 -0
- /data/lib/teuton/{case_manager/case → utils}/result/ext_filter.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fa647498d568e303c8c02ea44277a595f3796a404a523daf6c1b0408110de97
|
4
|
+
data.tar.gz: b733858b7e97b373aca8477a359649b5e6614cdd60caffbdd052e450aa12dffa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60b94cd2ef2632e1fdbe81515909be71bce35d011f739ecc97806c1cfaa8115a7b743ee4369b54dffe366f1d7b06486fe451827c2fb4ce7fd37448fbf56b549b
|
7
|
+
data.tar.gz: 312bd19998b3ef68cc61780dda49cf1711033736a2593206501d5f428cd64780974a2adfc4198dd1097b178f6202637dcc10e11131c90495de553fc33547520f
|
data/docs/CHANGELOG.md
CHANGED
data/docs/changelog/todo.md
CHANGED
@@ -2,17 +2,15 @@
|
|
2
2
|
## TO-DO
|
3
3
|
|
4
4
|
New features:
|
5
|
-
-
|
6
|
-
-
|
7
|
-
-
|
5
|
+
- Teuton readme --lang=es and export files with other langs
|
6
|
+
- Snode Dockerfile with SSH server
|
7
|
+
- Auto Parse new input format, and detect parse errors
|
8
8
|
|
9
9
|
Revise:
|
10
10
|
* verify get(:key) and get('key') works fine!
|
11
|
-
* Formatter: xml
|
11
|
+
* Formatter: xml
|
12
12
|
|
13
13
|
Internal changes:
|
14
|
-
* Application to Settings
|
15
14
|
* Laboratory to Checker
|
16
15
|
* Unify messages ERROR, INFO, WARN. etc
|
17
|
-
* Create SendManager as ExportManager?
|
18
16
|
* Add tt_label as alias of tt_members
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
## [2.7.0]
|
3
|
+
|
4
|
+
New features:
|
5
|
+
- [ADD] "teuton config PROJECTPATH" will suggest suitable configuration for the project.
|
6
|
+
- [ADD] Every one line command output is registered into reports.
|
7
|
+
- [ADD] "expect_exit 1", check last command exit code is equal to 1.
|
8
|
+
|
9
|
+
Internal changes:
|
10
|
+
* Application class splited into Settings and Project classes
|
11
|
+
* Create SendManager similar to ExportManager
|
data/docs/diagram.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
[<<back](../README.md)
|
2
|
+
|
3
|
+
# Diagram
|
4
|
+
|
5
|
+
```mermaid
|
6
|
+
flowchart TB
|
7
|
+
|
8
|
+
subgraph user
|
9
|
+
CLI --> Teuton
|
10
|
+
end
|
11
|
+
|
12
|
+
subgraph "create\nnew\nproject"
|
13
|
+
Teuton -- create --> Skeleton("Sekeleton\nFiles")
|
14
|
+
end
|
15
|
+
|
16
|
+
subgraph "Check\nproject files"
|
17
|
+
Teuton -- check --> Laboratory("Laboratory\nDSL\nShow\nBuiltin!")
|
18
|
+
end
|
19
|
+
|
20
|
+
subgraph "Create readme\nfrom project"
|
21
|
+
Teuton -- readme --> Readme("Readme\nDSL\nLang!")
|
22
|
+
end
|
23
|
+
|
24
|
+
subgraph manager
|
25
|
+
Teuton -- run --> manager/DSL
|
26
|
+
manager/DSL -- play --> CaseManager("CaseManager\ncheck_cases\nExportManager\nSendManager\nShowReport")
|
27
|
+
ReportManager --> HallOfFame
|
28
|
+
end
|
29
|
+
|
30
|
+
subgraph "case folder"
|
31
|
+
CaseManager --> Case("Case\nConfig\nClose\nPlay\nRunner\ncase/DSL\ncase/builtin!")
|
32
|
+
end
|
33
|
+
|
34
|
+
subgraph utils
|
35
|
+
Verbose
|
36
|
+
|
37
|
+
Readme --> ConfigFileReader
|
38
|
+
Laboratory --> ConfigFileReader
|
39
|
+
CaseManager --> ConfigFileReader
|
40
|
+
|
41
|
+
Laboratory --> Result
|
42
|
+
Readme --> Result("Result\next_array\next_compare\next_filter")
|
43
|
+
Case --> Result
|
44
|
+
|
45
|
+
Laboratory --> Application
|
46
|
+
Readme --> Application
|
47
|
+
manager/DSL -- use/macros/groups --> Application("Application\nNameFileFinder")
|
48
|
+
Case --> Application
|
49
|
+
end
|
50
|
+
|
51
|
+
subgraph report
|
52
|
+
CaseManager --> Report("Report\nFormatter\nfiles/template")
|
53
|
+
Case --> Report
|
54
|
+
end
|
55
|
+
```
|
data/docs/learn/02-target.md
CHANGED
@@ -15,13 +15,31 @@ group "Learn about targets" do
|
|
15
15
|
|
16
16
|
target "Create user david"
|
17
17
|
run "id david"
|
18
|
-
expect "david"
|
18
|
+
expect ["uid=", "(david)", "gid="]
|
19
|
+
|
20
|
+
target "Delete user vader"
|
21
|
+
run "id vader"
|
22
|
+
expect ["id:", "vader", "no exist"]
|
19
23
|
|
20
24
|
end
|
21
25
|
```
|
22
26
|
|
23
27
|
> In this example, our localhost's OS is GNU/Linux (or any other compatible OS) because the command executed is `id david`.
|
24
28
|
|
29
|
+
When the user exists, we expect this words: `uid=, (david), gid=`.
|
30
|
+
|
31
|
+
```
|
32
|
+
❯ id david
|
33
|
+
uid=1000(david) gid=1000(david) grupos=1000(david)
|
34
|
+
```
|
35
|
+
|
36
|
+
But when user does not exist, we expect different words: `id:, vader, no exist`.
|
37
|
+
|
38
|
+
```
|
39
|
+
❯ id vader
|
40
|
+
id: «vader»: no existe ese usuario
|
41
|
+
```
|
42
|
+
|
25
43
|
## Execution section
|
26
44
|
|
27
45
|
When we run this teuton test, the execution section (`play`) is processed. This seccion now contains this:
|
@@ -41,7 +59,7 @@ end
|
|
41
59
|
Execute this command to run the test:
|
42
60
|
|
43
61
|
```console
|
44
|
-
> teuton run examples/
|
62
|
+
> teuton run examples/02-target
|
45
63
|
|
46
64
|
CASE RESULTS
|
47
65
|
+------+-----------+-------+-------+
|
@@ -54,7 +72,7 @@ Report files are created into `var/02-target/` folder:
|
|
54
72
|
|
55
73
|
```console
|
56
74
|
var
|
57
|
-
└──
|
75
|
+
└── 02-target
|
58
76
|
├── case-01.txt
|
59
77
|
├── moodle.csv
|
60
78
|
└── resume.txt
|
@@ -63,35 +81,42 @@ var
|
|
63
81
|
Let's see one report:
|
64
82
|
|
65
83
|
```
|
66
|
-
|
67
|
-
|
84
|
+
❯ cat var/02-target/case-01.txt
|
68
85
|
CONFIGURATION
|
69
86
|
+-------------+-----------+
|
70
87
|
| tt_members | anonymous |
|
71
88
|
| tt_sequence | false |
|
72
89
|
| tt_skip | false |
|
73
|
-
| tt_testname |
|
90
|
+
| tt_testname | 02-target |
|
74
91
|
+-------------+-----------+
|
75
92
|
|
93
|
+
|
76
94
|
GROUPS
|
77
95
|
- Learn about targets
|
78
96
|
01 (1.0/1.0)
|
79
97
|
Description : Create user david
|
80
98
|
Command : id david
|
81
99
|
Duration : 0.002 (local)
|
82
|
-
Alterations : find(david) & count
|
100
|
+
Alterations : find(uid=) & find((david)) & find(gid=) & count
|
101
|
+
Expected : Greater than 0 (String)
|
102
|
+
Result : 1 (Integer)
|
103
|
+
02 (1.0/1.0)
|
104
|
+
Description : Delete user vader
|
105
|
+
Command : id vader
|
106
|
+
Duration : 0.002 (local)
|
107
|
+
Alterations : find(id:) & find(vader) & find(no exist) & count
|
83
108
|
Expected : Greater than 0 (String)
|
84
109
|
Result : 1 (Integer)
|
85
110
|
|
86
111
|
RESULTS
|
87
112
|
+--------------+---------------------------+
|
88
113
|
| case_id | 01 |
|
89
|
-
| start_time |
|
90
|
-
| finish_time |
|
91
|
-
| duration | 0.
|
114
|
+
| start_time | 2023-04-10 09:09:30 +0100 |
|
115
|
+
| finish_time | 2023-04-10 09:09:30 +0100 |
|
116
|
+
| duration | 0.003863242 |
|
92
117
|
| unique_fault | 0 |
|
93
|
-
| max_weight |
|
94
|
-
| good_weight |
|
118
|
+
| max_weight | 2.0 |
|
119
|
+
| good_weight | 2.0 |
|
95
120
|
| fail_weight | 0.0 |
|
96
121
|
| fail_counter | 0 |
|
97
122
|
| grade | 100 |
|
data/docs/learn/04-config.md
CHANGED
data/docs/learn/06-cmd_check.md
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
|
4
4
|
# check test
|
5
5
|
|
6
|
-
Check Teuton
|
6
|
+
Check Teuton check syntax and show statistics.
|
7
7
|
|
8
8
|
```
|
9
|
-
❯ teuton check examples/05-use
|
9
|
+
❯ teuton check examples/05-use
|
10
10
|
|
11
11
|
+--------------------------+
|
12
12
|
| GROUP: Using file: users |
|
@@ -14,7 +14,7 @@ Check Teuton test syntax and show statistics.
|
|
14
14
|
(001) target Create user get(username)
|
15
15
|
weight 1.0
|
16
16
|
run 'id get(username)' on host1
|
17
|
-
expect get(username) (
|
17
|
+
expect ["uid=", "(get(username))", "gid="] (Array)
|
18
18
|
|
19
19
|
+----------------------------+
|
20
20
|
| GROUP: Using file: network |
|
@@ -32,6 +32,7 @@ Check Teuton test syntax and show statistics.
|
|
32
32
|
+-------------+-------+
|
33
33
|
| DSL Stats | Count |
|
34
34
|
+-------------+-------+
|
35
|
+
| Uses | 2 |
|
35
36
|
| Groups | 2 |
|
36
37
|
| Targets | 3 |
|
37
38
|
| Runs | 3 |
|
@@ -44,7 +45,4 @@ Check Teuton test syntax and show statistics.
|
|
44
45
|
| * hostname | 2 |
|
45
46
|
| Sets | 0 |
|
46
47
|
+-------------+-------+
|
47
|
-
+----------------------+
|
48
|
-
| Revising CONFIG file |
|
49
|
-
+----------------------+
|
50
48
|
```
|
@@ -19,15 +19,13 @@ end
|
|
19
19
|
```
|
20
20
|
|
21
21
|
```
|
22
|
-
❯ teuton check examples/07-target_weight
|
23
|
-
|
24
22
|
+--------------------------+
|
25
23
|
| GROUP: Using file: users |
|
26
24
|
+--------------------------+
|
27
25
|
(001) target Create user get(username)
|
28
26
|
weight 1.0
|
29
27
|
run 'id get(username)' on host1
|
30
|
-
expect get(username) (
|
28
|
+
expect ["uid=", "(get(username))", "gid="] (Array)
|
31
29
|
|
32
30
|
+----------------------------+
|
33
31
|
| GROUP: Using file: network |
|
data/docs/learn/21-exit_codes.md
CHANGED
@@ -1,24 +1,17 @@
|
|
1
1
|
[<< back](README.md)
|
2
2
|
|
3
|
-
# Example:
|
3
|
+
# Example: exit_codes
|
4
4
|
|
5
|
-
|
5
|
+
`result` stores information from the last command executed by a "run" action. [Offers many functions](../dsl/definition/result.md)) that transforms output data, and also exitcode is captured.
|
6
6
|
|
7
|
-
|
7
|
+
## Example
|
8
8
|
|
9
|
-
## Description
|
10
|
-
|
11
|
-
Take a look at this section:
|
12
9
|
```ruby
|
13
10
|
target "Exist user root"
|
14
|
-
run "id root
|
15
|
-
|
16
|
-
```
|
17
|
-
|
18
|
-
It is posible to invoke the execution of several commands in sequence "cmd1;cmd2". Keep in mind that the last one must show the exit code. In the case of GNU/Linux is "echo $?", but it is different on others OOSS.
|
11
|
+
run "id root"
|
12
|
+
expect_exit 0
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
> * [result](../dsl/execution/result.md) keyword.
|
14
|
+
target "No user vader"
|
15
|
+
run "id vader"
|
16
|
+
expect_exit 1
|
17
|
+
```
|
data/docs/learn/README.md
CHANGED
@@ -17,7 +17,7 @@ Learn how write your own Teuton tests:
|
|
17
17
|
1. [Export other FORMATS](11-export.md)
|
18
18
|
1. [PRESERVE old reports](12-preserve.md)
|
19
19
|
1. [Hide FEEDBACK from reports](13-feedback.md)
|
20
|
-
1. [MOODLE
|
20
|
+
1. [MOODLE](14-moodle_id.md)
|
21
21
|
1. [Build README from test](15-readme.md)
|
22
22
|
1. [INCLUDE more configuration files](16-include.md)
|
23
23
|
1. [ALIAS](17-alias.md)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../utils/project"
|
4
|
+
require_relative "../utils/verbose"
|
5
|
+
require_relative "../utils/result/result"
|
6
|
+
require_relative "../report/report"
|
7
|
+
require_relative "dsl/all"
|
8
|
+
require_relative "config"
|
9
|
+
require_relative "close"
|
10
|
+
require_relative "play"
|
11
|
+
require_relative "builtin/main"
|
12
|
+
|
13
|
+
class Case
|
14
|
+
# Case: export, filename, grade, members,skip
|
15
|
+
include DSL
|
16
|
+
include Verbose
|
17
|
+
|
18
|
+
attr_accessor :action # Updated by ExecuteManager
|
19
|
+
attr_accessor :result # Updated by ExecuteManager
|
20
|
+
attr_accessor :sessions # Updated by ExecuteManager
|
21
|
+
attr_accessor :conn_status # Updated by ExecuteManager
|
22
|
+
|
23
|
+
attr_reader :id
|
24
|
+
attr_reader :config # Readed by ExecuteManager
|
25
|
+
attr_reader :uniques
|
26
|
+
attr_reader :skip
|
27
|
+
@@id = "01" # First case ID value
|
28
|
+
|
29
|
+
def initialize(config)
|
30
|
+
@config = Case::Config.new(
|
31
|
+
local: config,
|
32
|
+
global: Project.value[:global]
|
33
|
+
)
|
34
|
+
@groups = Project.value[:groups]
|
35
|
+
|
36
|
+
@id = @@id
|
37
|
+
@@id = @@id.next
|
38
|
+
|
39
|
+
# Define Case Report
|
40
|
+
@report = Report.new(@id)
|
41
|
+
@report.output_dir = File.join("var", @config.global[:tt_testname])
|
42
|
+
|
43
|
+
# Default configuration
|
44
|
+
@skip = false
|
45
|
+
@skip = get(:tt_skip) unless get(:tt_skip) == "NODATA"
|
46
|
+
unless Project.value[:options]["case"].nil?
|
47
|
+
@skip = true
|
48
|
+
@skip = false if Project.value[:options]["case"].include? @id.to_i
|
49
|
+
end
|
50
|
+
@debug = Project.debug?
|
51
|
+
@verbose = Project.value[:verbose]
|
52
|
+
|
53
|
+
@tmpdir = File.join("var", @config.get(:tt_testname), "tmp", @id.to_s)
|
54
|
+
# ensure_dir @tmpdir # REVISE: When we will need this? Samba?
|
55
|
+
|
56
|
+
@unique_values = {}
|
57
|
+
@result = Result.new
|
58
|
+
@action_counter = 0
|
59
|
+
@action = {
|
60
|
+
id: 0,
|
61
|
+
weight: 1.0,
|
62
|
+
description: "No description!",
|
63
|
+
groupname: nil
|
64
|
+
}
|
65
|
+
@uniques = []
|
66
|
+
@sessions = {} # Store opened sessions for this case
|
67
|
+
@conn_status = {}
|
68
|
+
tempfile :default
|
69
|
+
end
|
70
|
+
|
71
|
+
def export(format)
|
72
|
+
return if skip?
|
73
|
+
|
74
|
+
@report.export format
|
75
|
+
end
|
76
|
+
|
77
|
+
def filename
|
78
|
+
# called from: close_main_report
|
79
|
+
@report.filename
|
80
|
+
end
|
81
|
+
|
82
|
+
def grade
|
83
|
+
return 0.0 if skip
|
84
|
+
|
85
|
+
@report.tail[:grade]
|
86
|
+
end
|
87
|
+
|
88
|
+
def members
|
89
|
+
return "-" if skip
|
90
|
+
|
91
|
+
@report.head[:tt_members] || "noname"
|
92
|
+
end
|
93
|
+
|
94
|
+
alias_method :skip?, :skip
|
95
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "../utils/project"
|
4
4
|
|
5
5
|
# Class Case::Config
|
6
6
|
# * get
|
@@ -13,8 +13,8 @@ class Case
|
|
13
13
|
attr_reader :ialias, :global, :local, :running
|
14
14
|
|
15
15
|
def initialize(args)
|
16
|
-
@ialias = args[:alias] ||
|
17
|
-
@global = args[:global] ||
|
16
|
+
@ialias = args[:alias] || Project.value[:ialias].clone
|
17
|
+
@global = args[:global] || Project.value[:global].clone
|
18
18
|
@local = args[:local] || {}
|
19
19
|
@running = {}
|
20
20
|
|
@@ -6,6 +6,8 @@ require_relative "dsl/log"
|
|
6
6
|
class Case
|
7
7
|
private
|
8
8
|
|
9
|
+
# READ: @config
|
10
|
+
# WRITE: @action, @result, @session
|
9
11
|
def run_cmd_on(host)
|
10
12
|
protocol = @config.get("#{host}_protocol".to_sym)
|
11
13
|
ip = @config.get("#{host}_ip".to_sym)
|
@@ -30,15 +32,13 @@ class Case
|
|
30
32
|
|
31
33
|
def run_cmd_localhost
|
32
34
|
@action[:conn_type] = :local
|
33
|
-
|
34
|
-
@result.
|
35
|
-
@result.content =
|
35
|
+
resp = my_execute(@action[:command], @action[:encoding])
|
36
|
+
@result.exitcode = resp[:exitcode]
|
37
|
+
@result.content = resp[:content]
|
36
38
|
end
|
37
39
|
|
38
|
-
##
|
39
|
-
# Run remote command
|
40
|
-
# @param input_hostname (Symbol or String)
|
41
40
|
def run_cmd_remote(input_hostname)
|
41
|
+
# @param input_hostname (Symbol or String)
|
42
42
|
hostname = input_hostname.to_s
|
43
43
|
i = (hostname + "_protocol").to_sym
|
44
44
|
protocol = @config.get(i) if @config.get(i)
|
@@ -86,6 +86,7 @@ class Case
|
|
86
86
|
end
|
87
87
|
|
88
88
|
text = ""
|
89
|
+
exitcode = 0
|
89
90
|
begin
|
90
91
|
if @sessions[hostname].nil?
|
91
92
|
@sessions[hostname] = Net::SSH.start(
|
@@ -100,23 +101,24 @@ class Case
|
|
100
101
|
end
|
101
102
|
text = if @sessions[hostname].instance_of? Net::SSH::Connection::Session
|
102
103
|
@sessions[hostname].exec!(@action[:command])
|
103
|
-
# ssh.exec!("ls -l /home/jamis") do |channel, stream, data|
|
104
|
-
# stdout << data if stream == :stdout
|
105
|
-
# end
|
106
104
|
else
|
107
105
|
"SSH: NO CONNECTION!"
|
108
106
|
end
|
107
|
+
exitcode = text.exitstatus
|
109
108
|
rescue Errno::EHOSTUNREACH
|
110
109
|
@sessions[hostname] = :nosession
|
111
110
|
@conn_status[hostname] = :host_unreachable
|
111
|
+
exitcode = -1
|
112
112
|
log("Host #{ip} unreachable!", :error)
|
113
113
|
rescue Net::SSH::AuthenticationFailed
|
114
114
|
@sessions[hostname] = :nosession
|
115
115
|
@conn_status[hostname] = :error_authentication_failed
|
116
|
+
exitcode = -1
|
116
117
|
log("SSH::AuthenticationFailed!", :error)
|
117
118
|
rescue Net::SSH::HostKeyMismatch
|
118
119
|
@sessions[hostname] = :nosession
|
119
120
|
@conn_status[hostname] = :host_key_mismatch
|
121
|
+
exitcode = -1
|
120
122
|
log("SSH::HostKeyMismatch!", :error)
|
121
123
|
log("* The destination server's fingerprint is not matching " \
|
122
124
|
"what is in your local known_hosts file.", :error)
|
@@ -126,11 +128,12 @@ class Case
|
|
126
128
|
rescue => e
|
127
129
|
@sessions[hostname] = :nosession
|
128
130
|
@conn_status[hostname] = :error
|
131
|
+
exitcode = -1
|
129
132
|
log("[#{e.class}] SSH on <#{username}@#{ip}>" \
|
130
133
|
" exec: #{@action[:command]}", :error)
|
131
134
|
end
|
132
135
|
output = encode_and_split(@action[:encoding], text)
|
133
|
-
|
136
|
+
@result.exitcode = exitcode
|
134
137
|
@result.content = output
|
135
138
|
@result.content.compact!
|
136
139
|
end
|
@@ -180,6 +183,7 @@ class Case
|
|
180
183
|
" ip=<#{ip}>, HOSTID=<#{hostname}>", :warn)
|
181
184
|
end
|
182
185
|
output = encode_and_split(@action[:encoding], text)
|
186
|
+
@result.exitcode = -1
|
183
187
|
@result.content = output
|
184
188
|
@result.content.compact!
|
185
189
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "rainbow"
|
3
|
+
require_relative "../utils/project"
|
4
|
+
|
5
|
+
module Utils
|
6
|
+
def encode_and_split(encoding, text)
|
7
|
+
# Convert text to UTF-8 deleting unknown chars
|
8
|
+
text ||= "" # Ensure text is not nil
|
9
|
+
flag = [:default, "UTF-8"].include? encoding
|
10
|
+
return text.encode("UTF-8", invalid: :replace).split("\n") if flag
|
11
|
+
|
12
|
+
# Convert text from input ENCODING to UTF-8
|
13
|
+
ec = Encoding::Converter.new(encoding.to_s, "UTF-8")
|
14
|
+
begin
|
15
|
+
text = ec.convert(text)
|
16
|
+
rescue => e
|
17
|
+
warn "[ERROR] #{e}"
|
18
|
+
warn " Suggest declare text encoding, for example:"
|
19
|
+
warn " run 'command', on: :host, :encoding => 'ISO-8859-1'"
|
20
|
+
end
|
21
|
+
|
22
|
+
text.split("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
def my_execute(cmd, encoding = "UTF-8")
|
26
|
+
# TODO: mover a la clase ExecuteManager
|
27
|
+
return {exitstatus: 0, content: ""} if Project.debug?
|
28
|
+
|
29
|
+
begin
|
30
|
+
text, status = Open3.capture2e(cmd)
|
31
|
+
exitstatus = status.exitstatus
|
32
|
+
rescue => e
|
33
|
+
verbose Rainbow("!").green
|
34
|
+
text = e.to_s
|
35
|
+
exitstatus = 1
|
36
|
+
end
|
37
|
+
content = encode_and_split(encoding, text)
|
38
|
+
{exitstatus: exitstatus, content: content}
|
39
|
+
end
|
40
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DSL
|
4
|
+
# expect, expect2, expect_any, expect_first, expect_last
|
5
|
+
# expect_nothing, expect_none, expect_one
|
6
|
+
|
4
7
|
# expect <condition>, :weight => <value>
|
5
8
|
def expect(input, args = {})
|
6
9
|
if input.instance_of?(TrueClass) || input.instance_of?(FalseClass)
|
@@ -16,18 +19,16 @@ module DSL
|
|
16
19
|
@action_counter += 1
|
17
20
|
@action[:id] = @action_counter
|
18
21
|
@action[:check] = cond
|
19
|
-
@action[:result] = @result.value
|
20
22
|
|
21
|
-
@action[:
|
22
|
-
@action[:expected] = @result.expected
|
23
|
-
@action[:expected] = args[:expected] if args[:expected]
|
23
|
+
@action[:result] = (args[:value] || @result.value)
|
24
24
|
|
25
|
+
@action[:alterations] = @result.alterations
|
26
|
+
@action[:expected] = (args[:expected] || @result.expected)
|
25
27
|
@report.lines << @action.clone
|
26
28
|
weight(1.0)
|
27
29
|
|
28
|
-
|
29
|
-
c =
|
30
|
-
c = app.letter[:good] if cond
|
30
|
+
c = Settings.letter[:bad]
|
31
|
+
c = Settings.letter[:good] if cond
|
31
32
|
verbose Rainbow(c).green
|
32
33
|
end
|
33
34
|
|
@@ -40,6 +41,22 @@ module DSL
|
|
40
41
|
expect2 result.count.gt(0), args
|
41
42
|
end
|
42
43
|
|
44
|
+
def expect_exit(value)
|
45
|
+
@result.alterations = "Read exit code"
|
46
|
+
real_value = result.exitcode
|
47
|
+
cond = if value.is_a? Range
|
48
|
+
expect_value = "With range #{value}"
|
49
|
+
value.to_a.include? real_value
|
50
|
+
elsif value.is_a? Array
|
51
|
+
expect_value = "Inside list #{value}"
|
52
|
+
value.include? real_value
|
53
|
+
else
|
54
|
+
expect_value = value
|
55
|
+
(real_value == value.to_i)
|
56
|
+
end
|
57
|
+
expect2 cond, value: real_value, expected: expect_value
|
58
|
+
end
|
59
|
+
|
43
60
|
def expect_first(input, args = {})
|
44
61
|
@result.first
|
45
62
|
output = input
|
@@ -54,7 +71,6 @@ module DSL
|
|
54
71
|
expect2 input, expected: output
|
55
72
|
end
|
56
73
|
|
57
|
-
# def expect_none(input, args = {})
|
58
74
|
def expect_nothing(args = {})
|
59
75
|
expect2 result.count.eq(0), args
|
60
76
|
end
|
@@ -79,8 +95,8 @@ module DSL
|
|
79
95
|
expect2 result.count.eq(1), args
|
80
96
|
end
|
81
97
|
|
82
|
-
# Set weight value for the action
|
83
98
|
def weight(value = nil)
|
99
|
+
# Set weight value for the action
|
84
100
|
if value.nil?
|
85
101
|
@action[:weight]
|
86
102
|
elsif value == :default
|