teuton 2.8.0 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/docs/changelog/changelog.1.md +119 -0
  4. data/docs/changelog/changelog.2.md +109 -0
  5. data/docs/diagram.md +10 -10
  6. data/docs/dsl/expect.md +76 -25
  7. data/docs/dsl/result.md +24 -30
  8. data/docs/learn/02-target.md +32 -27
  9. data/docs/learn/25-expect-result.md +39 -0
  10. data/docs/learn/26-expect_sequence.md +79 -0
  11. data/docs/learn/27-run_script.md +91 -0
  12. data/docs/learn/28-upload.md +55 -0
  13. data/docs/learn/README.md +4 -15
  14. data/docs/videos.md +14 -8
  15. data/lib/teuton/case/case.rb +3 -2
  16. data/lib/teuton/case/config.rb +0 -5
  17. data/lib/teuton/case/dsl/all.rb +5 -1
  18. data/lib/teuton/case/dsl/expect.rb +13 -42
  19. data/lib/teuton/case/dsl/expect_exitcode.rb +31 -0
  20. data/lib/teuton/case/dsl/expect_sequence.rb +173 -0
  21. data/lib/teuton/case/dsl/getset.rb +0 -1
  22. data/lib/teuton/case/dsl/host.rb +5 -0
  23. data/lib/teuton/case/dsl/macro.rb +7 -3
  24. data/lib/teuton/case/dsl/run_script.rb +35 -0
  25. data/lib/teuton/case/dsl/upload.rb +42 -0
  26. data/lib/teuton/case/dsl/weight.rb +12 -0
  27. data/lib/teuton/case/host.rb +68 -0
  28. data/lib/teuton/case/play.rb +2 -6
  29. data/lib/teuton/{utils → case}/result/ext_array.rb +0 -1
  30. data/lib/teuton/{utils → case}/result/ext_compare.rb +0 -1
  31. data/lib/teuton/{utils → case}/result/ext_filter.rb +0 -2
  32. data/lib/teuton/{utils → case}/result/result.rb +13 -21
  33. data/lib/teuton/check/checker.rb +82 -0
  34. data/lib/teuton/check/dsl/all.rb +37 -0
  35. data/lib/teuton/check/{builtin.rb → dsl/builtin.rb} +1 -3
  36. data/lib/teuton/check/dsl/expect.rb +90 -0
  37. data/lib/teuton/check/dsl/expect_sequence.rb +29 -0
  38. data/lib/teuton/check/dsl/getset.rb +23 -0
  39. data/lib/teuton/check/dsl/run.rb +35 -0
  40. data/lib/teuton/check/main.rb +29 -0
  41. data/lib/teuton/check/show.rb +75 -100
  42. data/lib/teuton/deprecated/application_test.rb +32 -0
  43. data/lib/teuton/readme/dsl/all.rb +32 -0
  44. data/lib/teuton/readme/dsl/expect.rb +29 -0
  45. data/lib/teuton/readme/dsl/getset.rb +33 -0
  46. data/lib/teuton/readme/dsl/run.rb +51 -0
  47. data/lib/teuton/readme/lang.rb +8 -10
  48. data/lib/teuton/readme/main.rb +27 -0
  49. data/lib/teuton/readme/readme.rb +31 -58
  50. data/lib/teuton/readme/result.rb +7 -0
  51. data/lib/teuton/utils/configfile_reader.rb +25 -10
  52. data/lib/teuton/utils/logger.rb +32 -0
  53. data/lib/teuton/utils/verbose.rb +1 -1
  54. data/lib/teuton/version.rb +1 -1
  55. data/lib/teuton.rb +6 -5
  56. metadata +45 -39
  57. data/docs/CHANGELOG.md +0 -10
  58. data/docs/changelog/v2.0.md +0 -18
  59. data/docs/changelog/v2.1.md +0 -54
  60. data/docs/changelog/v2.2.md +0 -42
  61. data/docs/changelog/v2.3.md +0 -10
  62. data/docs/changelog/v2.4.md +0 -41
  63. data/docs/changelog/v2.5.md +0 -6
  64. data/docs/changelog/v2.6.md +0 -4
  65. data/docs/changelog/v2.7.md +0 -23
  66. data/docs/changelog/v2.8.md +0 -11
  67. data/docs/changelog/version2.1.md +0 -4
  68. data/docs/learn/videos.md +0 -13
  69. data/lib/teuton/case/execute/copy_ssh.rb +0 -70
  70. data/lib/teuton/check/dsl.rb +0 -112
  71. data/lib/teuton/check/laboratory.rb +0 -59
  72. data/lib/teuton/readme/dsl.rb +0 -126
  73. /data/lib/teuton/case/dsl/{goto.rb → run.rb} +0 -0
  74. /data/lib/teuton/{utils → deprecated}/application.rb +0 -0
  75. /data/lib/teuton/{case/deprecated → deprecated}/runner.rb +0 -0
  76. /data/lib/teuton/{case/deprecated → deprecated}/utils.rb +0 -0
@@ -0,0 +1,79 @@
1
+ [<<back](README.md)
2
+
3
+ # DSL: expect_sequence
4
+
5
+ Evaluate the occurrence of a certain sequence that takes place in different lines of the output.
6
+
7
+ > Example files at [examples/26-expect_sequence](../../examples/26-expect_sequence)
8
+
9
+ ## Description
10
+
11
+ In the classic target/run/expect, the expect statement works by locating lines from the output of the previous command that meet certain criteria.
12
+
13
+ We can even (using regular expressions) detect if there is any line in the output where a certain sequence appears.
14
+
15
+
16
+ ```ruby
17
+ # Example:
18
+ # expect with regular expression to detect [a, b, c] sequence
19
+ # within a line
20
+
21
+ expect /a.*?b.*?c/
22
+ ```
23
+
24
+ > Regular expressions are very powerful but they are also complex to use.
25
+
26
+ To evaluate the occurrence of a certain sequence that takes place in different lines of the output we will use the new "expect_sequence" instruction.
27
+
28
+
29
+ ```ruby
30
+ # Example:
31
+ # expect_sequence to detect [a, b, c] sequence
32
+
33
+ expect_sequence do
34
+ find "a"
35
+ find "b"
36
+ find "c"
37
+ end
38
+ ```
39
+
40
+ > NOTE: expect_sequence can be useful for evaluating iptables firewall configurations where permission assignment order is relevant.
41
+
42
+ ## Evaluating different sequences
43
+
44
+ * **Simple sequence**. Validate sequences where the elements are in order. Use `find` statement to find each element of the sequence.
45
+
46
+ ```ruby
47
+ # Examples: [A,B,C], [A,s,B,s,C], [x,A,B,s,C,x], etc.
48
+
49
+ expect_sequence do
50
+ find "A"
51
+ find "B"
52
+ find "C"
53
+ end
54
+ ```
55
+
56
+ * **Strict sequence**. validate sequences where the elements are in strict consecutive order. First use `find` to find an element in the sequence and then `next_to` for the next element in strict order.
57
+
58
+ ```ruby
59
+ # Examples: [A,B,C], [x,A,B,C,x], etc.
60
+
61
+ expect_sequence do
62
+ find "A"
63
+ next_to "B"
64
+ next_to "C"
65
+ end
66
+ ```
67
+
68
+ * **Strict sequence with jumps**. Use `ignore N` to indicate that there are N lines between 2 elements of the sequence.
69
+
70
+ ```ruby
71
+ # Examples: [A,B,s,s,C], [x,A,B,s,s,C,x], etc.
72
+
73
+ expect_sequence do
74
+ find "A"
75
+ next_to "B"
76
+ ignore 2
77
+ next_to "C"
78
+ end
79
+ ```
@@ -0,0 +1,91 @@
1
+ [<<back](README.md)
2
+
3
+ # DSL: run_script
4
+
5
+ You know the classic sequence `target/run/expect`, but sometimes you need to run our own script files on the remote computer. So you have to:
6
+
7
+ 1. Upload a copy of the script file to the remote host
8
+ 2. and then run it on remote host
9
+
10
+ **run_script** upload and execute your own local script on remote host.
11
+
12
+ > Example files at [examples/27-run_file](../../examples/27-run_script)
13
+
14
+ ## Example scripts
15
+
16
+ Suppose we have the following files:
17
+ ```
18
+ example
19
+ ├── config.yaml
20
+ ├── show.sh
21
+ └── start.rb
22
+ ```
23
+
24
+ Contents of the `show.sh` script:
25
+ ```bash
26
+ #!/usr/bin/env bash
27
+ MESSAGE=$1
28
+ echo $MESSAGE
29
+ exit 0
30
+ ```
31
+
32
+ ## Usage examples
33
+
34
+ `run_script` is the DSL keyword in charge of uploading the script to the remote computer and executing it. When invoking run_script we have two styles: compact or separate components. Let's see
35
+
36
+ **Compact invocation**: The "command" to execute contains the interpreter, the script, and the arguments.
37
+
38
+ ```ruby
39
+ target "Mode 1: Upload script and execute on remote host"
40
+ run_script "bash show.sh Hello", on: :host1
41
+ expect "Hello"
42
+ ```
43
+
44
+ **Separate components**: pass the name of the script, the interpreter in charge of processing it and its arguments through separate parameters.
45
+
46
+ ```ruby
47
+ target "Mode 2: Upload script and execute on remote host"
48
+ run_script "show.sh", shell: "bash", args: "Hello", on: :host1
49
+ expect "Hello"
50
+ ```
51
+
52
+ Or setting shell default value:
53
+
54
+ ```ruby
55
+ set(:shell, "bash")
56
+
57
+ target "Mode 2: Upload script and execute on remote host"
58
+ run_script "show.sh", args: "Hello", on: :host1
59
+ expect "Hello"
60
+ ```
61
+
62
+ ## Running example
63
+
64
+ ```
65
+ ------------------------------------
66
+ Started at 2023-07-23 13:46:11 +0100
67
+ ....uu..u.u.u.uu..u.!F!F!F!F
68
+ Finished in 30.457 seconds
69
+ ------------------------------------
70
+
71
+ CASE RESULTS
72
+ +------+-----------+-------+-------+
73
+ | CASE | MEMBERS | GRADE | STATE |
74
+ | 01 | Localhost | 100.0 | ✔ |
75
+ | 02 | Remote1 | 100.0 | ✔ |
76
+ | 03 | Remote2 | 100.0 | ✔ |
77
+ | 04 | Remote3 | 0.0 | ? |
78
+ +------+-----------+-------+-------+
79
+
80
+ CONN ERRORS
81
+ +------+---------+-------+------------------+
82
+ | CASE | MEMBERS | HOST | ERROR |
83
+ | 04 | Remote3 | host1 | host_unreachable |
84
+ +------+---------+-------+------------------+
85
+ ```
86
+
87
+ Meaning of progress symbols:
88
+ * `.`: check ok
89
+ * `F`: check fail
90
+ * `!`: connection fail
91
+ * `u`: upload ok
@@ -0,0 +1,55 @@
1
+ [<<back](README.md)
2
+
3
+ # DSL: upload
4
+
5
+ `upload` is a dsl instruction, whose purpose is to upload files to the remote host.
6
+
7
+ ```ruby
8
+ upload "FILENAME", to: :host1
9
+ ```
10
+
11
+ * `upload "FILENAME"`, upload local file to remote.
12
+ * `to: :host1`, specifies remote host.
13
+
14
+ > Example files at [examples/28-upload](../../examples/28-upload)
15
+
16
+ ## Other options
17
+
18
+ * Upload "LOCALDIR/FILENAME" to default remote dir into remote host:
19
+
20
+ ```ruby
21
+ upload "LOCALDIR/FILENAME", to: :host1
22
+ ```
23
+
24
+ * Upload "LOCALDIR/FILENAME" to remote dir into remote host:
25
+
26
+ ```ruby
27
+ upload "LOCALDIR/FILENAME", remotedir: "REMOTEDIR", to: :host1
28
+ ```
29
+
30
+ * Upload several local files from "LOCALDIR" to default remote dir into host:
31
+
32
+ ```ruby
33
+ upload "LOCALDIR/*", to: :host1
34
+ ```
35
+
36
+ * Upload several local files from "LOCALDIR" to remote host:
37
+
38
+ ```ruby
39
+ upload "LOCALDIR/*", remotedir: "REMOTEDIR", to: :host1
40
+ ```
41
+
42
+ ## Example
43
+
44
+ ```ruby
45
+ target "Upload file and then run it"
46
+ upload "script/show.sh", remotedir: "sh", to: :host1
47
+ run "bash sh/show.sh HelloWorld", on: :host1
48
+ expect "HelloWorld"
49
+ ```
50
+
51
+ Example steps:
52
+ 1. Describe target.
53
+ 2. Upload local file to remote host.
54
+ 3. Run script using Bash on remote host.
55
+ 4. Evaluate script output.
data/docs/learn/README.md CHANGED
@@ -28,20 +28,9 @@ Learn how write your own Teuton tests:
28
28
  1. [RESULT object](22-result.md)
29
29
  1. [Test code](23-test-code.md)
30
30
  1. [Test SQL and database](24-test-sql.md)
31
+ 1. [expect vs result](25-expect-result.md) TODO
32
+ 1. [EXPECT_SEQUENCE](26-expect_sequence.md)
33
+ 1. [RUN_SCRIPT](27-run_script.md)
34
+ 1. [UPLOAD](28-upload.md)
31
35
 
32
36
  Mores examples at [teuton-tests](https://github.com/dvarrui/teuton-tests) GitHub repository.
33
-
34
- # Videos
35
-
36
- By now there are no English videos. We are sorry!
37
- But if you want to see Spanish videos, here you are:
38
-
39
- Teuton (v2.0):
40
- * [ES - CHAPI19: Charla Teuton](https://youtu.be/KFWQDfNAFxI?t=12221)
41
- * [ES - CHAPI19: Teuton demo](https://github.com/dvarrui/proyectos-de-ejemplo/tree/master/charlas/teuton)
42
-
43
- Sysadmingame (Teuton v1.0)
44
- * [Sysadmingame (1 de 3): Instalación del programa](https://youtu.be/dnyMq9_KDco)
45
- * [Sysadmingame (2 de 3): Crear un caso simple](https://youtu.be/0e2g5Izvc6c)
46
- * [Sysadmingame (3 de 3): Crear un caso complejo](https://youtu.be/ebEK6OXH8kQ)
47
- * [CHAPI16 - Charla sysadmingame](https://youtu.be/cNJaB5xzHHQ)
data/docs/videos.md CHANGED
@@ -7,14 +7,20 @@
7
7
 
8
8
  # Videos
9
9
 
10
- Teuton:
10
+ > By now there are no English videos. We are sorry!
11
+
12
+ Teuton v2.1:
11
13
  * [Apuntes FP Informática - I Congreso Virtual - Mayo 2020](https://youtu.be/RxIV26BAoGo)
12
- * [Teuton Software 2.1 - Tutorial - Oct 2020](https://youtu.be/cyBN-rOYQeY)
14
+ * [Teuton Software 2.1 - Tutorial - Abr 2020](https://youtu.be/cyBN-rOYQeY)
13
15
 
14
- Teuton en el 2016 se llamaba "sysadmingame".
15
- * ES -[CHAPI16 - Presentación sysadmingame chapi16 - Abril 2016](https://youtu.be/cNJaB5xzHHQ)
16
- * sysadmingame:
17
- 1. [Instalación del programa](https://youtu.be/dnyMq9_KDco)
18
- 2. [Crear un caso simple](https://youtu.be/0e2g5Izvc6c)
19
- 3. [Crear un caso complejo](https://youtu.be/ebEK6OXH8kQ)
16
+ Teuton v2.0:
17
+ * [ES - CHAPI19: Charla Teuton](https://youtu.be/KFWQDfNAFxI?t=12221)
18
+ * [ES - CHAPI19: Teuton demo](https://github.com/dvarrui/proyectos-de-ejemplo/tree/master/charlas/teuton)
20
19
 
20
+ Sysadmingame (Teuton v1.0):
21
+ * [Sysadmingame (1 de 3): Instalación del programa](https://youtu.be/dnyMq9_KDco)
22
+ * [Sysadmingame (2 de 3): Crear un caso simple](https://youtu.be/0e2g5Izvc6c)
23
+ * [Sysadmingame (3 de 3): Crear un caso complejo](https://youtu.be/ebEK6OXH8kQ)
24
+
25
+ Sysadmingame: En el 2016 el proyecto se llamaba "sysadmingame".
26
+ * ES -[CHAPI16 - Presentación sysadmingame chapi16 - Abril 2016](https://youtu.be/cNJaB5xzHHQ)
@@ -2,13 +2,14 @@
2
2
 
3
3
  require_relative "../utils/project"
4
4
  require_relative "../utils/verbose"
5
- require_relative "../utils/result/result"
6
5
  require_relative "../report/report"
7
6
  require_relative "dsl/all"
8
7
  require_relative "config"
9
8
  require_relative "close"
9
+ # require_relative "builtin/main"
10
+ require_relative "host"
10
11
  require_relative "play"
11
- require_relative "builtin/main"
12
+ require_relative "result/result"
12
13
 
13
14
  class Case
14
15
  include DSL
@@ -2,11 +2,6 @@
2
2
 
3
3
  require_relative "../utils/project"
4
4
 
5
- # Class Case::Config
6
- # * get
7
- # * set
8
- # * unset
9
- # * missing_method
10
5
  class Case
11
6
  class Config
12
7
  # This class manage configuration for only one case
@@ -1,8 +1,12 @@
1
1
  require_relative "expect"
2
2
  require_relative "getset"
3
- require_relative "goto"
3
+ require_relative "host"
4
4
  require_relative "log"
5
5
  require_relative "macro"
6
+ require_relative "run"
7
+ require_relative "run_script"
6
8
  require_relative "send"
7
9
  require_relative "target"
8
10
  require_relative "unique"
11
+ require_relative "upload"
12
+ require_relative "weight"
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DSL
4
- # expect, expect2, expect_any, expect_first, expect_last
5
- # expect_nothing, expect_none, expect_one
3
+ require_relative "expect_exitcode"
4
+ require_relative "expect_sequence"
6
5
 
7
- # expect <condition>, :weight => <value>
6
+ module DSL
7
+ # expect <condition>,
8
+ # value: RealValue,
9
+ # expected: ExpectedValue,
10
+ # weight: float
11
+ #
8
12
  def expect(input, args = {})
9
13
  if input.instance_of?(TrueClass) || input.instance_of?(FalseClass)
10
14
  expect2(input, args)
11
15
  elsif input.instance_of?(String) || input.instance_of?(Regexp) || input.instance_of?(Array)
12
16
  expect_any input
13
17
  else
14
- puts Rainbow("[TypeError] expect #{input} (#{input.class})").red
18
+ puts Rainbow("[ERROR] Case expect TypeError: expect #{input} (#{input.class})").red
15
19
  end
16
20
  end
17
21
 
@@ -45,30 +49,6 @@ module DSL
45
49
  expect2 result.count.gt(0), args
46
50
  end
47
51
 
48
- def expect_exit(value)
49
- @result.alterations = "Read exit code"
50
- real_value = result.exitcode
51
- cond = if value.is_a? Range
52
- expect_value = "With range #{value}"
53
- value.to_a.include? real_value
54
- elsif value.is_a? Array
55
- expect_value = "Inside list #{value}"
56
- value.include? real_value
57
- else
58
- expect_value = value
59
- (real_value == value.to_i)
60
- end
61
- expect2 cond, value: real_value, expected: expect_value
62
- end
63
-
64
- def expect_fail
65
- @result.alterations = "Read exit code"
66
- real_value = result.exitcode
67
- expect_value = "Greater than 0"
68
- cond = (real_value > 0)
69
- expect2 cond, value: real_value, expected: expect_value
70
- end
71
-
72
52
  def expect_first(input, args = {})
73
53
  @result.first
74
54
  output = input
@@ -107,18 +87,9 @@ module DSL
107
87
  expect2 result.count.eq(1), args
108
88
  end
109
89
 
110
- def expect_ok
111
- expect_exit 0
112
- end
113
-
114
- def weight(value = nil)
115
- # Set weight value for the action
116
- if value.nil?
117
- @action[:weight]
118
- elsif value == :default
119
- @action[:weight] = 1.0
120
- else
121
- @action[:weight] = value.to_f
122
- end
90
+ def expect_sequence(&block)
91
+ seq = ExpectSequence.new(result.content.dup)
92
+ cond = seq.is_valid?(&block)
93
+ expect2 cond, value: seq.real, expected: seq.expected
123
94
  end
124
95
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DSL
4
+ def expect_exit(value)
5
+ @result.alterations = "Read exit code"
6
+ real_value = result.exitcode
7
+ cond = if value.is_a? Range
8
+ expect_value = "With range #{value}"
9
+ value.to_a.include? real_value
10
+ elsif value.is_a? Array
11
+ expect_value = "Inside list #{value}"
12
+ value.include? real_value
13
+ else
14
+ expect_value = value
15
+ (real_value == value.to_i)
16
+ end
17
+ expect2 cond, value: real_value, expected: expect_value
18
+ end
19
+
20
+ def expect_fail
21
+ @result.alterations = "Read exit code"
22
+ real_value = result.exitcode
23
+ expect_value = "Greater than 0"
24
+ cond = (real_value > 0)
25
+ expect2 cond, value: real_value, expected: expect_value
26
+ end
27
+
28
+ def expect_ok
29
+ expect_exit 0
30
+ end
31
+ end
@@ -0,0 +1,173 @@
1
+ class ExpectSequence
2
+ attr_reader :result
3
+ attr_reader :states
4
+
5
+ def initialize(lines)
6
+ @lines = lines
7
+ end
8
+
9
+ def is_valid?(&block)
10
+ @expected = []
11
+ @states = [
12
+ {last_index: -1, steps: [], found: []}
13
+ ]
14
+ instance_eval(&block)
15
+ @result = find_best_state
16
+ @result[:ok]
17
+ end
18
+
19
+ def expected
20
+ @expected.join(">")
21
+ end
22
+
23
+ def real
24
+ # From final result return evaluation progress
25
+ text = []
26
+ @result[:steps].each do |step|
27
+ index = text.size
28
+ text << if step
29
+ @expected[index]
30
+ else
31
+ "not #{@expected[index]}"
32
+ end
33
+ end
34
+ text.join(">")
35
+ end
36
+
37
+ private
38
+
39
+ def find_best_state
40
+ @states.each do |state|
41
+ state[:score] = (state[:steps].select { _1 }).size
42
+ state[:fails] = (state[:steps].select { !_1 }).size
43
+ state[:ok] = (state[:fails] == 0)
44
+ end
45
+ best = @states[0]
46
+ @states.each { |state| best = state if state[:score] > best[:score] }
47
+ best
48
+ end
49
+
50
+ def find(value)
51
+ @expected << "find(#{value})"
52
+ newstates = []
53
+ @states.each do |state|
54
+ last_index = state[:last_index]
55
+
56
+ if last_index > (@lines.size - 1)
57
+ steps = state[:steps].clone
58
+ steps << false
59
+ newstates << {
60
+ last_index: last_index,
61
+ steps: steps,
62
+ found: state[:found].clone
63
+ }
64
+ next
65
+ end
66
+
67
+ findindexes = get_indexes(value: value, from: last_index)
68
+ findindexes.each do |findindex|
69
+ found = state[:found].clone
70
+ found << findindex
71
+ steps = state[:steps].clone
72
+ steps << true
73
+ newstates << {
74
+ last_index: findindex,
75
+ steps: steps,
76
+ found: found
77
+ }
78
+ end
79
+ end
80
+ @states = if newstates.size.zero?
81
+ @states.each { |state| state[:steps] << false }
82
+ else
83
+ newstates
84
+ end
85
+ end
86
+
87
+ def next_to(value)
88
+ @expected << "next_to(#{value})"
89
+ newstates = []
90
+
91
+ @states.each do |state|
92
+ last_index = state[:last_index]
93
+
94
+ if last_index > (@lines.size - 1)
95
+ steps = state[:steps].clone
96
+ steps << false
97
+ newstates << {
98
+ last_index: last_index,
99
+ steps: steps,
100
+ found: state[:found].clone
101
+ }
102
+ next
103
+ end
104
+
105
+ last_index += 1
106
+ found = state[:found].clone
107
+ steps = state[:steps].clone
108
+ line = @lines[last_index]
109
+ if line.include?(value)
110
+ found << last_index
111
+ steps << true
112
+ else
113
+ steps << false
114
+ end
115
+ newstates << {
116
+ last_index: last_index,
117
+ steps: steps,
118
+ found: found
119
+ }
120
+ end
121
+ @states = if newstates.size.zero?
122
+ @states.each { |state| state[:steps] << false }
123
+ else
124
+ newstates
125
+ end
126
+ end
127
+
128
+ def ignore(value)
129
+ @expected << "ignore(#{value})"
130
+ newstates = []
131
+ @states.each do |state|
132
+ last_index = state[:last_index] + value.to_i
133
+
134
+ steps = state[:steps].clone
135
+ steps << !(last_index > (@lines.size - 1))
136
+
137
+ newstates << {
138
+ last_index: last_index,
139
+ steps: steps,
140
+ found: state[:found].clone
141
+ }
142
+ end
143
+
144
+ @states = if newstates.size.zero?
145
+ @states.each { |state| state[:steps] << false }
146
+ else
147
+ newstates
148
+ end
149
+ end
150
+
151
+ def get_indexes(value:, from:)
152
+ indexes = []
153
+
154
+ @lines.each_with_index do |line, index|
155
+ next if index < from
156
+
157
+ indexes << index if line_include_value?(line: line, value: value)
158
+ end
159
+ indexes
160
+ end
161
+
162
+ def line_include_value?(line:, value:)
163
+ if value.is_a? String
164
+ return true if line.include? value
165
+ elsif value.is_a? Regexp
166
+ return true << index if value.match(line)
167
+ else
168
+ puts "[ERROR] expect_sequence #{value.class}"
169
+ exit 1
170
+ end
171
+ false
172
+ end
173
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # DSL#get and DSL#set
4
3
  module DSL
5
4
  # Read param option from [running, config or global] Hash data
6
5
  def get(option)
@@ -0,0 +1,5 @@
1
+ module DSL
2
+ def get_host(id)
3
+ Case::Host.new(config).get(id)
4
+ end
5
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../../utils/project"
4
+ require_relative "../../utils/logger"
4
5
 
5
6
  module DSL
6
7
  ##
@@ -10,7 +11,9 @@ module DSL
10
11
  def macro(name, input = {})
11
12
  macros = Project.value[:macros]
12
13
  unless macros[name]
13
- log("Macro #{name} not found!", :error)
14
+ msg = "DSL '#{name}' not found!"
15
+ log(msg, :error)
16
+ Logger.error("ERROR #{msg}")
14
17
  return
15
18
  end
16
19
  input.each_pair { |k, v| set(k, v) }
@@ -32,9 +35,10 @@ module DSL
32
35
  def method_missing(method, args = {})
33
36
  a = method.to_s
34
37
  if a.start_with?("_")
35
- return instance_eval("get(:#{a[1, a.size - 1]})", __FILE__, __LINE__)
38
+ return instance_eval("get(:#{a[1, a.size]})", __FILE__, __LINE__)
39
+ elsif a[0, 6] == "macro_"
40
+ return macro a[6, a.size], args
36
41
  end
37
- return macro a[6, a.size], args if a[0, 6] == "macro_"
38
42
  macro a, args
39
43
  end
40
44
 
@@ -0,0 +1,35 @@
1
+ require_relative "../../utils/project"
2
+ require_relative "../../utils/verbose"
3
+
4
+ module DSL
5
+ def run_script(script, args = {})
6
+ items = script.split(" ")
7
+ if items.size == 1
8
+ shell = args[:shell] || ((get(:shell) != "NODATA") ? get(:shell) : nil)
9
+ script = "#{shell} #{script}" if shell
10
+ script = "#{script} #{args[:args]} " if args[:args]
11
+ end
12
+
13
+ items = script.split(" ")
14
+ if items.size < 1
15
+ msg = Rainbow("==> [ERROR] run_script: Incorrect command '#{command}'").red
16
+ verboseln(msg)
17
+ return
18
+ end
19
+
20
+ host = get_host(args[:on])
21
+ if host.protocol == "local"
22
+ items[1] = File.join(Project.value[:project_path], items[1])
23
+ command = items.join(" ")
24
+ run(command, args)
25
+ elsif host.protocol == "ssh"
26
+ upload items[1], to: host.id
27
+ items[1] = File.basename(items[1])
28
+ command = items.join(" ")
29
+ run(command, args)
30
+ else
31
+ msg = Rainbow("==> [ERROR] run_script: Incorrect protocol(#{host.protocol})").red
32
+ verboseln(msg)
33
+ end
34
+ end
35
+ end