teuton 2.5.0 → 2.7.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/docs/CHANGELOG.md +2 -0
  3. data/docs/changelog/todo.md +4 -6
  4. data/docs/changelog/v2.6.md +4 -0
  5. data/docs/changelog/v2.7.md +11 -0
  6. data/docs/diagram.md +55 -0
  7. data/docs/learn/02-target.md +37 -12
  8. data/docs/learn/03-remote_hosts.md +1 -1
  9. data/docs/learn/04-config.md +1 -1
  10. data/docs/learn/06-cmd_check.md +4 -6
  11. data/docs/learn/07-target_weight.md +1 -3
  12. data/docs/learn/21-exit_codes.md +9 -16
  13. data/docs/learn/README.md +1 -1
  14. data/lib/teuton/case/case.rb +95 -0
  15. data/lib/teuton/{case_manager/case → case}/close.rb +2 -0
  16. data/lib/teuton/{case_manager/case → case}/config.rb +3 -3
  17. data/lib/teuton/{case_manager/case → case/deprecated}/runner.rb +14 -10
  18. data/lib/teuton/case/deprecated/utils.rb +40 -0
  19. data/lib/teuton/{case_manager/case/dsl/main.rb → case/dsl/all.rb} +0 -2
  20. data/lib/teuton/{case_manager/case → case}/dsl/expect.rb +25 -9
  21. data/lib/teuton/{case_manager/case → case}/dsl/goto.rb +10 -9
  22. data/lib/teuton/{case_manager/case → case}/dsl/log.rb +1 -2
  23. data/lib/teuton/{case_manager/case → case}/dsl/macro.rb +2 -2
  24. data/lib/teuton/{case_manager/case → case}/dsl/send.rb +3 -8
  25. data/lib/teuton/case/execute/execute_base.rb +55 -0
  26. data/lib/teuton/case/execute/execute_local.rb +29 -0
  27. data/lib/teuton/case/execute/execute_manager.rb +56 -0
  28. data/lib/teuton/case/execute/execute_ssh.rb +90 -0
  29. data/lib/teuton/case/execute/execute_telnet.rb +56 -0
  30. data/lib/teuton/{case_manager/case → case}/play.rb +11 -14
  31. data/lib/teuton/case_manager/case_manager.rb +20 -39
  32. data/lib/teuton/case_manager/check_cases.rb +14 -12
  33. data/lib/teuton/case_manager/dsl.rb +7 -9
  34. data/lib/teuton/case_manager/export_manager.rb +19 -6
  35. data/lib/teuton/case_manager/hall_of_fame.rb +9 -10
  36. data/lib/teuton/case_manager/report.rb +11 -9
  37. data/lib/teuton/case_manager/send_manager.rb +17 -0
  38. data/lib/teuton/{report/show.rb → case_manager/show_report.rb} +4 -6
  39. data/lib/teuton/case_manager/utils.rb +2 -43
  40. data/lib/teuton/check/dsl.rb +1 -2
  41. data/lib/teuton/check/laboratory.rb +7 -7
  42. data/lib/teuton/check/show.rb +5 -8
  43. data/lib/teuton/cli.rb +10 -0
  44. data/lib/teuton/readme/dsl.rb +5 -7
  45. data/lib/teuton/readme/lang.rb +3 -2
  46. data/lib/teuton/readme/readme.rb +15 -18
  47. data/lib/teuton/report/formatter/default/array.rb +6 -5
  48. data/lib/teuton/report/formatter/default/txt.rb +1 -0
  49. data/lib/teuton/report/formatter/resume/array.rb +3 -3
  50. data/lib/teuton/report/formatter/resume/html.rb +2 -2
  51. data/lib/teuton/report/report.rb +6 -5
  52. data/lib/teuton/skeleton.rb +8 -10
  53. data/lib/teuton/{application.rb → utils/application.rb} +13 -5
  54. data/lib/teuton/utils/name_file_finder.rb +40 -45
  55. data/lib/teuton/utils/project.rb +73 -0
  56. data/lib/teuton/{case_manager/case → utils}/result/ext_array.rb +5 -5
  57. data/lib/teuton/{case_manager/case → utils}/result/result.rb +10 -8
  58. data/lib/teuton/utils/settings.rb +12 -0
  59. data/lib/teuton/utils/verbose.rb +2 -2
  60. data/lib/teuton/version.rb +1 -1
  61. data/lib/teuton.rb +28 -27
  62. metadata +43 -30
  63. data/lib/teuton/case_manager/case/case.rb +0 -117
  64. data/lib/teuton/case_manager/case/main.rb +0 -7
  65. data/lib/teuton/case_manager/main.rb +0 -3
  66. /data/lib/teuton/{case_manager/case → case}/builtin/main.rb +0 -0
  67. /data/lib/teuton/{case_manager/case → case}/builtin/package.rb +0 -0
  68. /data/lib/teuton/{case_manager/case → case}/builtin/service.rb +0 -0
  69. /data/lib/teuton/{case_manager/case → case}/builtin/teuton_file.rb +0 -0
  70. /data/lib/teuton/{case_manager/case → case}/builtin/teuton_host.rb +0 -0
  71. /data/lib/teuton/{case_manager/case → case}/builtin/user.rb +0 -0
  72. /data/lib/teuton/{case_manager/case → case}/dsl/getset.rb +0 -0
  73. /data/lib/teuton/{case_manager/case → case}/dsl/target.rb +0 -0
  74. /data/lib/teuton/{case_manager/case → case}/dsl/unique.rb +0 -0
  75. /data/lib/teuton/{case_manager/case → utils}/result/ext_compare.rb +0 -0
  76. /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: 8f53359ed5f8eae1b3a798630c5d56ae46076073bface7d3788de57b245a80cb
4
- data.tar.gz: 366afd9ccee6db9bdf5756fe5954050231681763489bab11b1841e9279998c08
3
+ metadata.gz: 7fa647498d568e303c8c02ea44277a595f3796a404a523daf6c1b0408110de97
4
+ data.tar.gz: b733858b7e97b373aca8477a359649b5e6614cdd60caffbdd052e450aa12dffa
5
5
  SHA512:
6
- metadata.gz: a40866560ec0d622b48322c0689dfe36cb9820cf565ce4258a8b71d38a1a3cc88e57f68e208c0d2a6c1a0787b7a2698af0446757bb2167fdf04d2bcd8002178f
7
- data.tar.gz: 288e6105576a15ac25eb20d298bb552b77347b65a3a2df6632d0ef26063061c77c32ef02af88a6f7244790df9573b6e79d7e9fee8b0606006a41b0cd171a51c5
6
+ metadata.gz: 60b94cd2ef2632e1fdbe81515909be71bce35d011f739ecc97806c1cfaa8115a7b743ee4369b54dffe366f1d7b06486fe451827c2fb4ce7fd37448fbf56b549b
7
+ data.tar.gz: 312bd19998b3ef68cc61780dda49cf1711033736a2593206501d5f428cd64780974a2adfc4198dd1097b178f6202637dcc10e11131c90495de553fc33547520f
data/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ * [version 2.5](changelog/v2.5.md)
6
+ * [version 2.4](changelog/v2.4.md)
5
7
  * [version 2.3](changelog/v2.3.md)
6
8
  * [version 2.2](changelog/v2.2.md)
7
9
  * [version 2.1](changelog/v2.1.md)
@@ -2,17 +2,15 @@
2
2
  ## TO-DO
3
3
 
4
4
  New features:
5
- - Parse new input format, and detect parse errors
6
- - Teuton readme --lang=es
7
- - Export files with other langs
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,4 @@
1
+
2
+ ## [2.6.0]
3
+
4
+ - [ADD] When running local or SSH commands, stdout and stderr are captured and readed by "expect" sentence.
@@ -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
+ ```
@@ -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/01-target
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
- └── 01-target
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
- > more var/02-target/case-01.txt
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 | 01-target |
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 | 2022-12-24 13:31:28 +0000 |
90
- | finish_time | 2022-12-24 13:31:28 +0000 |
91
- | duration | 0.001880141 |
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 | 1.0 |
94
- | good_weight | 1.0 |
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 |
@@ -43,7 +43,7 @@ Define 1 target (item to be checked):
43
43
  group "Remote hosts" do
44
44
  target "Create user david"
45
45
  run "id david", on: :host1
46
- expect "david"
46
+ expect [ "uid=", "(david)", "gid=" ]
47
47
  end
48
48
  ```
49
49
 
@@ -24,7 +24,7 @@ group "Reading params from config file" do
24
24
 
25
25
  target "Create user #{get(:username)}"
26
26
  run "id #{get(:username)}"
27
- expect get(:username)
27
+ expect [ "uid=", "("+get(:username)+")", "gid=" ]
28
28
 
29
29
  end
30
30
  ```
@@ -3,10 +3,10 @@
3
3
 
4
4
  # check test
5
5
 
6
- Check Teuton test syntax and show statistics.
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) (String)
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) (String)
28
+ expect ["uid=", "(get(username))", "gid="] (Array)
31
29
 
32
30
  +----------------------------+
33
31
  | GROUP: Using file: network |
@@ -1,24 +1,17 @@
1
1
  [<< back](README.md)
2
2
 
3
- # Example: 16-exit_codes
3
+ # Example: exit_codes
4
4
 
5
- _I am sorry! We have not solved the problem of getting the exit code of the commands so that it works for any platform. But we can help you do this work._
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
- `result` stores information from the last command executed by a "run" action. [Offers many functions](../dsl/definition/result.md)) that transforms output data, but also we have been added tow more: first and last.
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;echo $?"
15
- expect_last "0"
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
- All terminal output generated by `run` action is captured (Use `result.debug` to show result content into screen), and as we need only the last line, we use `expect_last "0"`.
21
-
22
- > More information about:
23
- > * [expect](../dsl/definition/expect.md) keyword.
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 ID](14-moodle_id.md)
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
@@ -2,6 +2,8 @@
2
2
 
3
3
  class Case
4
4
  def close(uniques)
5
+ # Invoked from check_cases!
6
+
5
7
  fails = 0
6
8
  @uniques.each do |key|
7
9
  next unless uniques[key].include?(id) && uniques[key].count > 1
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../application"
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] || Application.instance.ialias.clone
17
- @global = args[:global] || Application.instance.global.clone
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
- i = my_execute(@action[:command], @action[:encoding])
34
- @result.exitstatus = i[:exitstatus]
35
- @result.content = i[: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
- # revise: @result.exitstatus = text.exitstatus
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,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require_relative "expect"
4
2
  require_relative "getset"
5
3
  require_relative "goto"
@@ -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[:alterations] = @result.alterations
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
- app = Application.instance
29
- c = app.letter[:bad]
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