teuton 2.1.8 → 2.1.9

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -8
  3. data/bin/check_teuton +43 -0
  4. data/docs/changelog/contributions.md +32 -0
  5. data/docs/changelog/v2.1.md +22 -0
  6. data/docs/changelog/v2.2.md +29 -0
  7. data/docs/commands/README.md +105 -7
  8. data/docs/commands/example_check.md +54 -0
  9. data/docs/commands/example_run.md +112 -0
  10. data/docs/dsl/README.md +11 -9
  11. data/docs/dsl/definition/expect.md +25 -21
  12. data/docs/dsl/definition/group.md +5 -1
  13. data/docs/dsl/definition/result.md +45 -34
  14. data/docs/dsl/definition/run_local.md +34 -0
  15. data/docs/dsl/definition/run_remote.md +119 -0
  16. data/docs/dsl/definition/target.md +6 -0
  17. data/docs/dsl/execution/export.md +27 -19
  18. data/docs/dsl/execution/play.md +4 -0
  19. data/docs/dsl/execution/send.md +21 -2
  20. data/docs/dsl/execution/show.md +13 -8
  21. data/docs/dsl/setting/get.md +24 -8
  22. data/docs/dsl/setting/set.md +8 -3
  23. data/docs/install/README.md +19 -26
  24. data/docs/install/modes_of_use.md +27 -26
  25. data/docs/install/scripts.md +53 -36
  26. data/docs/install/vagrant_docker.md +56 -0
  27. data/docs/learn/README.md +13 -6
  28. data/docs/learn/example-01-target.md +78 -61
  29. data/docs/learn/example-02-config.md +152 -0
  30. data/docs/learn/example-03-remote-hosts.md +31 -25
  31. data/docs/learn/example-04-use.md +23 -17
  32. data/docs/learn/example-05-debug.md +24 -17
  33. data/docs/learn/example-06-log.md +70 -0
  34. data/lib/teuton/application.rb +7 -4
  35. data/lib/teuton/case_manager/case/case.rb +4 -1
  36. data/lib/teuton/case_manager/case/dsl/expect.rb +3 -1
  37. data/lib/teuton/case_manager/case/dsl/goto.rb +12 -7
  38. data/lib/teuton/case_manager/case/dsl/macro.rb +38 -0
  39. data/lib/teuton/case_manager/case/dsl/main.rb +1 -2
  40. data/lib/teuton/case_manager/case/dsl/target.rb +1 -1
  41. data/lib/teuton/case_manager/case/runner.rb +7 -7
  42. data/lib/teuton/case_manager/case_manager.rb +1 -20
  43. data/lib/teuton/case_manager/check_cases.rb +12 -2
  44. data/lib/teuton/case_manager/dsl.rb +4 -6
  45. data/lib/teuton/case_manager/export_manager.rb +29 -3
  46. data/lib/teuton/case_manager/report.rb +29 -8
  47. data/lib/teuton/case_manager/show.rb +8 -4
  48. data/lib/teuton/cli.rb +1 -0
  49. data/lib/teuton/cli/play.rb +1 -0
  50. data/lib/teuton/cli/version.rb +1 -4
  51. data/lib/teuton/files/config.yaml +0 -1
  52. data/lib/teuton/files/start.rb +1 -1
  53. data/lib/teuton/files/template/case.html +135 -0
  54. data/lib/teuton/files/template/resume.html +115 -0
  55. data/lib/teuton/project/laboratory/builtin.rb +2 -1
  56. data/lib/teuton/project/laboratory/dsl.rb +13 -15
  57. data/lib/teuton/project/laboratory/laboratory.rb +5 -1
  58. data/lib/teuton/project/laboratory/show.rb +21 -13
  59. data/lib/teuton/project/name_file_finder.rb +6 -1
  60. data/lib/teuton/project/project.rb +7 -3
  61. data/lib/teuton/project/readme/dsl.rb +3 -1
  62. data/lib/teuton/project/readme/readme.rb +37 -26
  63. data/lib/teuton/project/skeleton.rb +20 -4
  64. data/lib/teuton/report/close.rb +15 -11
  65. data/lib/teuton/report/formatter/formatter_factory.rb +10 -6
  66. data/lib/teuton/report/formatter/html_formatter.rb +16 -79
  67. data/lib/teuton/report/formatter/resume_html_formatter.rb +39 -0
  68. data/lib/teuton/report/formatter/resume_yaml_formatter.rb +7 -1
  69. data/lib/teuton/report/report.rb +5 -4
  70. data/lib/teuton/report/show.rb +55 -26
  71. metadata +26 -39
  72. data/docs/changelog/todo.md +0 -46
  73. data/docs/commands/create_skeleton.md +0 -31
  74. data/docs/commands/help.md +0 -13
  75. data/docs/commands/revise_test.md +0 -46
  76. data/docs/commands/run_test_unit.md +0 -78
  77. data/docs/commands/show_version.md +0 -9
  78. data/docs/developers/01-telnet.md +0 -121
  79. data/docs/developers/02-ssh.md +0 -93
  80. data/docs/developers/03-encoding.md +0 -153
  81. data/docs/developers/comparative.md +0 -17
  82. data/docs/dsl/_Sidebar.md +0 -30
  83. data/docs/dsl/definition/goto.md +0 -112
  84. data/docs/dsl/definition/run.md +0 -23
  85. data/docs/install/tested_os.md +0 -25
  86. data/docs/install/vagrant.md +0 -9
  87. data/docs/learn/example-02-configfile.md +0 -174
  88. data/docs/learn/quick-demo.md +0 -170
  89. data/lib/teuton/case_manager/case/dsl/check.rb +0 -24
  90. data/lib/teuton/case_manager/case/dsl/missing.rb +0 -12
  91. 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 learn/learn-04-use
18
- learn/learn-04-require
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 examples.
30
+ * `README.md` and `config.yaml` are the same as previous example.
27
31
 
28
- ## Execution (play section)
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
- ## Definitions (user section)
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
- target "Exist user <#{get(:username)}>"
54
- goto :host1, :exec => "net user"
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
- ## Definitions (network section)
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 "Hostname is <#{get(:host1_hostname)}>"
70
- goto :host1, :exec => "hostname"
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 OK"
74
- goto :host1, :exec => "nslookup www.nba.es"
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
- learn/learn-05-debug
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 (play section)
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
- ## Debugging: Testing rb files
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`. Let's see an example:
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
- teuton check examples/learn-01-target
48
- [INFO] ScriptPath => .../teuton.d/teuton/examples/learn-01-target/start.rb
49
- [INFO] ConfigPath => ...uton.d/teuton/examples/learn-01-target/config.yaml
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: learn-01-target |
54
- +------------------------+
55
- (001) target Create user <david>
59
+ +----------------------------+
60
+ | GROUP: Learn about targets |
61
+ +----------------------------+
62
+ (001) target Create user david
56
63
  weight 1.0
57
- goto localhost and {:exec=>"id david"}
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
- ## Debugging: Result content
93
+ ## Debug
87
94
 
88
- Every time we invoke `goto` or `run` keywork, an OS command is executed and the output showed on screen is captured by Teuton and saved into `result` internal object.
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 rb file. Let's see an example from `external.rb.rb` file:
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 "ping #{get(:windows1_ip)} -c 1"
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 "nmap -Pn #{get(:windows1_ip)}"
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
+ ```
@@ -6,7 +6,7 @@ require 'singleton'
6
6
  class Application
7
7
  include Singleton
8
8
 
9
- VERSION = '2.1.8' # Application version
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, :ialias
18
- attr_accessor :checks, :groups, :uses
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
- @checks = {}
44
+ @macros = {}
42
45
  @groups = []
43
46
  @uses = [] # TODO
44
47
  @hall_of_fame = []
@@ -82,8 +82,11 @@ class Case
82
82
  @report.export format
83
83
  end
84
84
 
85
+ ##
86
+ # Return case report filename
87
+ # @return String
85
88
  def filename
86
- @report.filename #+ '.' + @report.format.to_s
89
+ @report.filename
87
90
  end
88
91
 
89
92
  ##
@@ -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(&macros[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 'missing'
7
+ require_relative 'macro'
9
8
  require_relative 'send'
10
9
  require_relative 'target'
11
10
  require_relative 'unique'
@@ -3,7 +3,7 @@
3
3
  # DSL#target
4
4
  module DSL
5
5
  def readme(_text)
6
- # Usefull for "teuton reamde" action.
6
+ # Usefull only for "teuton reamde" command action.
7
7
  end
8
8
 
9
9
  def target(desc, args = {})
@@ -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}>," \