teuton 2.1.8 → 2.1.9

Sign up to get free protection for your applications and to get access to all the features.
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}>," \