teuton 2.7.3 → 2.9.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.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/docs/changelog/changelog.1.md +119 -0
- data/docs/changelog/changelog.2.md +105 -0
- data/docs/diagram.md +10 -10
- data/docs/dsl/expect.md +76 -23
- data/docs/dsl/export.md +6 -3
- data/docs/dsl/result.md +24 -30
- data/docs/dsl/send.md +34 -23
- data/docs/learn/02-target.md +32 -27
- data/docs/learn/13-feedback.md +8 -9
- data/docs/learn/25-expect-result.md +39 -0
- data/docs/learn/26-expect_sequence.md +79 -0
- data/docs/learn/27-run_script.md +91 -0
- data/docs/learn/28-upload.md +55 -0
- data/docs/learn/README.md +4 -15
- data/docs/videos.md +14 -8
- data/lib/teuton/case/case.rb +3 -3
- data/lib/teuton/case/config.rb +0 -5
- data/lib/teuton/case/dsl/all.rb +5 -1
- data/lib/teuton/case/dsl/expect.rb +20 -33
- data/lib/teuton/case/dsl/expect_exitcode.rb +31 -0
- data/lib/teuton/case/dsl/expect_sequence.rb +173 -0
- data/lib/teuton/case/dsl/getset.rb +0 -1
- data/lib/teuton/case/dsl/host.rb +5 -0
- data/lib/teuton/case/dsl/macro.rb +7 -4
- data/lib/teuton/case/dsl/run_script.rb +35 -0
- data/lib/teuton/case/dsl/send.rb +3 -3
- data/lib/teuton/case/dsl/upload.rb +42 -0
- data/lib/teuton/case/dsl/weight.rb +12 -0
- data/lib/teuton/case/execute/execute_ssh.rb +11 -7
- data/lib/teuton/case/host.rb +68 -0
- data/lib/teuton/case/play.rb +2 -6
- data/lib/teuton/{utils → case}/result/ext_array.rb +0 -1
- data/lib/teuton/{utils → case}/result/ext_compare.rb +0 -1
- data/lib/teuton/{utils → case}/result/ext_filter.rb +0 -2
- data/lib/teuton/{utils → case}/result/result.rb +13 -21
- data/lib/teuton/check/checker.rb +82 -0
- data/lib/teuton/check/dsl/all.rb +37 -0
- data/lib/teuton/check/{builtin.rb → dsl/builtin.rb} +1 -3
- data/lib/teuton/check/dsl/expect.rb +90 -0
- data/lib/teuton/check/dsl/expect_sequence.rb +29 -0
- data/lib/teuton/check/dsl/getset.rb +23 -0
- data/lib/teuton/check/dsl/run.rb +35 -0
- data/lib/teuton/check/main.rb +29 -0
- data/lib/teuton/check/show.rb +75 -100
- data/lib/teuton/{utils → deprecated}/application.rb +0 -6
- data/lib/teuton/deprecated/application_test.rb +32 -0
- data/lib/teuton/readme/dsl/all.rb +32 -0
- data/lib/teuton/readme/dsl/expect.rb +29 -0
- data/lib/teuton/readme/dsl/getset.rb +33 -0
- data/lib/teuton/readme/dsl/run.rb +51 -0
- data/lib/teuton/readme/lang.rb +8 -10
- data/lib/teuton/readme/main.rb +27 -0
- data/lib/teuton/readme/readme.rb +31 -58
- data/lib/teuton/readme/result.rb +7 -0
- data/lib/teuton/report/formatter/default/txt.rb +2 -2
- data/lib/teuton/utils/configfile_reader.rb +8 -4
- data/lib/teuton/utils/logger.rb +32 -0
- data/lib/teuton/utils/verbose.rb +1 -1
- data/lib/teuton/version.rb +1 -1
- data/lib/teuton.rb +6 -5
- metadata +45 -37
- data/docs/CHANGELOG.md +0 -10
- data/docs/changelog/v2.0.md +0 -18
- data/docs/changelog/v2.1.md +0 -54
- data/docs/changelog/v2.2.md +0 -42
- data/docs/changelog/v2.3.md +0 -10
- data/docs/changelog/v2.4.md +0 -41
- data/docs/changelog/v2.5.md +0 -6
- data/docs/changelog/v2.6.md +0 -4
- data/docs/changelog/v2.7.md +0 -23
- data/docs/changelog/version2.1.md +0 -4
- data/docs/learn/videos.md +0 -13
- data/lib/teuton/case/execute/copy_ssh.rb +0 -70
- data/lib/teuton/check/dsl.rb +0 -112
- data/lib/teuton/check/laboratory.rb +0 -59
- data/lib/teuton/readme/dsl.rb +0 -126
- /data/lib/teuton/case/dsl/{goto.rb → run.rb} +0 -0
- /data/lib/teuton/{case/deprecated → deprecated}/runner.rb +0 -0
- /data/lib/teuton/{case/deprecated → deprecated}/utils.rb +0 -0
data/docs/changelog/v2.7.md
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
|
2
|
-
## [2.7.3] 20230607
|
3
|
-
|
4
|
-
- [FIX] Hall of fame now use Project class instead of Application.
|
5
|
-
|
6
|
-
## [2.7.2] 20230607
|
7
|
-
|
8
|
-
- [FIX] Fixed an issue that appeared when exporting reports without feedback after failing to connect to remote computer.
|
9
|
-
|
10
|
-
## [2.7.1]
|
11
|
-
|
12
|
-
- [FIX] Fixed an issue that appeared when executing test and fail connection to remote computer.
|
13
|
-
|
14
|
-
## [2.7.0]
|
15
|
-
|
16
|
-
New features:
|
17
|
-
- [ADD] "teuton config PROJECTPATH" will suggest suitable configuration for the project.
|
18
|
-
- [ADD] Every one line command output is registered into reports.
|
19
|
-
- [ADD] "expect_exit 1", check last command exit code is equal to 1.
|
20
|
-
|
21
|
-
Internal changes:
|
22
|
-
* Application class splited into Settings and Project classes
|
23
|
-
* Create SendManager similar to ExportManager
|
data/docs/learn/videos.md
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
|
2
|
-
By now there are no English videos. We are sorry!
|
3
|
-
But if you want to see Spanish videos, here you are:
|
4
|
-
|
5
|
-
Teuton (v2.0):
|
6
|
-
* [CHAPI19 - Charla Teuton](https://youtu.be/KFWQDfNAFxI?t=12221)
|
7
|
-
|
8
|
-
Sysadmingame (Teuton v1.0)
|
9
|
-
* [Sysadmingame (1 de 3): Instalación del programa](https://youtu.be/dnyMq9_KDco)
|
10
|
-
* [Sysadmingame (2 de 3): Crear un caso simple](https://youtu.be/0e2g5Izvc6c)
|
11
|
-
* [Sysadmingame (3 de 3): Crear un caso complejo](https://youtu.be/ebEK6OXH8kQ)
|
12
|
-
* [CHAPI16 - Charla sysadmingame](https://youtu.be/cNJaB5xzHHQ)
|
13
|
-
|
@@ -1,70 +0,0 @@
|
|
1
|
-
require "net/ssh"
|
2
|
-
require "net/sftp"
|
3
|
-
require "rainbow"
|
4
|
-
require_relative "../../utils/project"
|
5
|
-
require_relative "../../utils/verbose"
|
6
|
-
require_relative "execute_base"
|
7
|
-
|
8
|
-
class CopySSH < ExecuteBase
|
9
|
-
def call(host, localfilename)
|
10
|
-
# Check params
|
11
|
-
unless config.get("#{host}_route".to_sym) == "NODATA"
|
12
|
-
log("'copy script' requires direct host access!", :error)
|
13
|
-
return false
|
14
|
-
end
|
15
|
-
|
16
|
-
host = host.to_s
|
17
|
-
|
18
|
-
begin
|
19
|
-
if sessions[host].nil?
|
20
|
-
# Open new SSH session
|
21
|
-
ip = config.get("#{host}_ip".to_sym).to_s
|
22
|
-
username = config.get("#{host}_username".to_sym).to_s
|
23
|
-
password = config.get("#{host}_password".to_sym).to_s
|
24
|
-
port = config.get("#{host}_port".to_sym).to_i
|
25
|
-
port = 22 if port.zero?
|
26
|
-
|
27
|
-
sessions[host] = Net::SSH.start(
|
28
|
-
ip,
|
29
|
-
username,
|
30
|
-
port: port,
|
31
|
-
password: password,
|
32
|
-
keepalive: true,
|
33
|
-
timeout: 30,
|
34
|
-
non_interactive: true
|
35
|
-
)
|
36
|
-
end
|
37
|
-
if sessions[host].instance_of? Net::SSH::Connection::Session
|
38
|
-
copy_to(host, localfilename)
|
39
|
-
else
|
40
|
-
"SSH: NO CONNECTION!"
|
41
|
-
end
|
42
|
-
rescue => e
|
43
|
-
sessions[host] = :nosession
|
44
|
-
conn_status[host] = :error
|
45
|
-
log("[#{e.class}] SSH on <#{username}@#{ip}>", :error)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def copy_to(host, localfilename)
|
50
|
-
ip = get((host + "_ip").to_sym)
|
51
|
-
username = get((host + "_username").to_sym).to_s
|
52
|
-
password = get((host + "_password").to_sym).to_s
|
53
|
-
port = get((host + "_port").to_sym).to_i
|
54
|
-
port = 22 if port.zero?
|
55
|
-
|
56
|
-
localfilepath = File.join(Dir.pwd, localfilename)
|
57
|
-
remotefilepath = File.join(".", File.basename(localfilename))
|
58
|
-
|
59
|
-
# Upload a file or directory to the remote host
|
60
|
-
begin
|
61
|
-
Net::SFTP.start(ip, username, password: password, port: port) do |sftp|
|
62
|
-
sftp.upload!(localfilepath, remotefilepath)
|
63
|
-
end
|
64
|
-
rescue
|
65
|
-
log("copy file: #{localfilename} => #{remotefilepath}", :error)
|
66
|
-
return false
|
67
|
-
end
|
68
|
-
true
|
69
|
-
end
|
70
|
-
end
|
data/lib/teuton/check/dsl.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Laboratory
|
4
|
-
# Include Teuton DSL keywords into Laboratory class
|
5
|
-
def readme(_text)
|
6
|
-
# Usefull for "teuton readme" command action.
|
7
|
-
end
|
8
|
-
|
9
|
-
def target(desc, args = {})
|
10
|
-
@stats[:targets] += 1
|
11
|
-
@targetid += 1
|
12
|
-
weight = args[:weight] || 1.0
|
13
|
-
verboseln format("(%03<targetid>d) target %<desc>s", targetid: @targetid, desc: desc)
|
14
|
-
verboseln " weight #{weight}"
|
15
|
-
end
|
16
|
-
alias goal target
|
17
|
-
|
18
|
-
def expect(cond)
|
19
|
-
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
20
|
-
verboseln " expect #{cond} (#{cond.class})"
|
21
|
-
verboseln ""
|
22
|
-
end
|
23
|
-
|
24
|
-
def expect_first(cond)
|
25
|
-
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
26
|
-
verboseln " expect_first #{cond} (#{cond.class})"
|
27
|
-
verboseln ""
|
28
|
-
end
|
29
|
-
|
30
|
-
def expect_last(cond)
|
31
|
-
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
32
|
-
verboseln " expect_last #{cond} (#{cond.class})"
|
33
|
-
verboseln ""
|
34
|
-
end
|
35
|
-
|
36
|
-
def expect_none(cond)
|
37
|
-
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
38
|
-
verboseln " expect_none #{cond} (#{cond.class})"
|
39
|
-
verboseln ""
|
40
|
-
end
|
41
|
-
|
42
|
-
def expect_one(cond)
|
43
|
-
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
44
|
-
verboseln " expect_one #{cond} (#{cond.class})"
|
45
|
-
verboseln ""
|
46
|
-
end
|
47
|
-
|
48
|
-
def get(varname)
|
49
|
-
@stats[:gets] += 1
|
50
|
-
|
51
|
-
if @gets[varname]
|
52
|
-
@gets[varname] += 1
|
53
|
-
else
|
54
|
-
@gets[varname] = 1
|
55
|
-
end
|
56
|
-
|
57
|
-
"get(#{varname})"
|
58
|
-
end
|
59
|
-
|
60
|
-
def run(command, args = {})
|
61
|
-
args[:exec] = command
|
62
|
-
host = :localhost
|
63
|
-
host = args[:on] if args[:on]
|
64
|
-
goto(host, args)
|
65
|
-
end
|
66
|
-
|
67
|
-
def goto(host = :localhost, args = {})
|
68
|
-
result.reset
|
69
|
-
args[:on] = host unless args[:on]
|
70
|
-
|
71
|
-
if @hosts[host]
|
72
|
-
@hosts[host] += 1
|
73
|
-
else
|
74
|
-
@hosts[host] = 1
|
75
|
-
end
|
76
|
-
verboseln " run '#{args[:exec]}' on #{args[:on]}"
|
77
|
-
end
|
78
|
-
|
79
|
-
# Check macros and _get_vars
|
80
|
-
def method_missing(method, *args, &block)
|
81
|
-
a = method.to_s
|
82
|
-
if args.nil? && block.nil?
|
83
|
-
instance_eval("get(:#{a[0, a.size - 1]})", __FILE__, __LINE__) if a[a.size - 1] == "?"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def gett(option)
|
88
|
-
get(option)
|
89
|
-
end
|
90
|
-
|
91
|
-
def unique(key, _value)
|
92
|
-
@stats[:uniques] += 1
|
93
|
-
|
94
|
-
verboseln " ! Unique value for <#{key}>"
|
95
|
-
verboseln ""
|
96
|
-
end
|
97
|
-
|
98
|
-
def log(text = "", type = :info)
|
99
|
-
@stats[:logs] += 1
|
100
|
-
verboseln " log [#{type}]: " + text.to_s
|
101
|
-
end
|
102
|
-
|
103
|
-
def set(key, value)
|
104
|
-
@stats[:sets] += 1
|
105
|
-
|
106
|
-
key = ":" + key.to_s if key.instance_of? Symbol
|
107
|
-
value = ":" + value.to_s if value.instance_of? Symbol
|
108
|
-
|
109
|
-
@sets[key] = value
|
110
|
-
"set(#{key},#{value})"
|
111
|
-
end
|
112
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "../utils/project"
|
4
|
-
require_relative "../utils/result/result"
|
5
|
-
require_relative "show"
|
6
|
-
require_relative "dsl"
|
7
|
-
require_relative "builtin"
|
8
|
-
|
9
|
-
def use(filename)
|
10
|
-
filename += ".rb"
|
11
|
-
rbfiles = File.join(Project.value[:project_path], "**", filename)
|
12
|
-
files = Dir.glob(rbfiles)
|
13
|
-
use = []
|
14
|
-
files.sort.each { |f| use << f if f.include?(filename) }
|
15
|
-
require_relative use[0]
|
16
|
-
Project.value[:uses] << use[0]
|
17
|
-
end
|
18
|
-
|
19
|
-
def group(name, &block)
|
20
|
-
Project.value[:groups] << {name: name, block: block}
|
21
|
-
end
|
22
|
-
alias task group
|
23
|
-
|
24
|
-
def define_macro(name, *args, &block)
|
25
|
-
Project.value[:macros][name] = {args: args, block: block}
|
26
|
-
end
|
27
|
-
alias def_macro define_macro
|
28
|
-
alias defmacro define_macro
|
29
|
-
|
30
|
-
|
31
|
-
def start(&block)
|
32
|
-
# Don't do nothing. We are checking test not running it
|
33
|
-
end
|
34
|
-
alias play start
|
35
|
-
|
36
|
-
# Show objectives stats from RB script file
|
37
|
-
class Laboratory
|
38
|
-
attr_reader :result
|
39
|
-
|
40
|
-
def initialize(script_path, config_path)
|
41
|
-
@path = {}
|
42
|
-
@path[:script] = script_path
|
43
|
-
@path[:dirname] = File.dirname(script_path)
|
44
|
-
@path[:filename] = File.basename(script_path, ".rb")
|
45
|
-
@path[:config] = config_path
|
46
|
-
reset
|
47
|
-
end
|
48
|
-
|
49
|
-
def reset
|
50
|
-
@result = Result.new
|
51
|
-
@targetid = 0
|
52
|
-
@stats = {groups: 0, targets: 0, uniques: 0, gets: 0, logs: 0, sets: 0}
|
53
|
-
@gets = {}
|
54
|
-
@sets = {}
|
55
|
-
@hosts = {}
|
56
|
-
@requests = [] # REVISE this
|
57
|
-
@verbose = Project.value[:verbose]
|
58
|
-
end
|
59
|
-
end
|
data/lib/teuton/readme/dsl.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Readme
|
4
|
-
# readme, target, goto, run
|
5
|
-
# expect,
|
6
|
-
# gett, set, unique, log
|
7
|
-
class Readme
|
8
|
-
def readme(text)
|
9
|
-
if @action[:target].nil?
|
10
|
-
# It's a group readme
|
11
|
-
@current[:readme] << text
|
12
|
-
else
|
13
|
-
# It's a target readme
|
14
|
-
@action[:readme] << text
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def target(desc, args = {})
|
19
|
-
previous_host = @action[:host]
|
20
|
-
@action = {target: desc, host: previous_host, readme: []}
|
21
|
-
weight = 1.0
|
22
|
-
weight = args[:weight].to_f if args[:weight]
|
23
|
-
@action[:weight] = weight
|
24
|
-
end
|
25
|
-
alias goal target
|
26
|
-
|
27
|
-
def goto(host = :localhost, args = {})
|
28
|
-
unless host == :localhost
|
29
|
-
b = {}
|
30
|
-
a = "#{host}_ip".to_sym
|
31
|
-
if @config[:global][a].nil? && !@setted_params.include?(a)
|
32
|
-
@cases_params << a
|
33
|
-
end
|
34
|
-
b[:ip] = @config[:global][a] if @config[:global][a]
|
35
|
-
b[:ip] = @setted_params[a] if @setted_params[a]
|
36
|
-
|
37
|
-
a = "#{host}_username".to_sym
|
38
|
-
if @config[:global][a].nil? && !@setted_params.include?(a)
|
39
|
-
@cases_params << a
|
40
|
-
end
|
41
|
-
b[:username] = @config[:global][a] if @config[:global][a]
|
42
|
-
b[:username] = @setted_params[a] if @setted_params[a]
|
43
|
-
|
44
|
-
a = "#{host}_password".to_sym
|
45
|
-
if @config[:global][a].nil? && !@setted_params.include?(a)
|
46
|
-
@cases_params << a
|
47
|
-
end
|
48
|
-
b[:password] = @config[:global][a] if @config[:global][a]
|
49
|
-
b[:password] = @setted_params[a] if @setted_params[a]
|
50
|
-
|
51
|
-
@required_hosts[host.to_s] = b
|
52
|
-
end
|
53
|
-
@action[:host] = host
|
54
|
-
@action[:exec] = args[:exec] || "noexec"
|
55
|
-
end
|
56
|
-
|
57
|
-
def run(command, args = {})
|
58
|
-
args[:exec] = command
|
59
|
-
host = :localhost
|
60
|
-
host = args[:on] if args[:on]
|
61
|
-
goto(host, args)
|
62
|
-
end
|
63
|
-
|
64
|
-
def expect(_cond, _args = {})
|
65
|
-
@current[:actions] << @action
|
66
|
-
result.reset
|
67
|
-
end
|
68
|
-
alias expect_any expect
|
69
|
-
alias expect_first expect
|
70
|
-
alias expect_last expect
|
71
|
-
alias expect_none expect
|
72
|
-
alias expect_one expect
|
73
|
-
|
74
|
-
def get(value)
|
75
|
-
unless @config[:global][value].nil?
|
76
|
-
@global_params[value] = @config[:global][value]
|
77
|
-
return @config[:global][value]
|
78
|
-
end
|
79
|
-
|
80
|
-
return value.to_s.upcase if @setted_params.include? value
|
81
|
-
|
82
|
-
@cases_params << value
|
83
|
-
value.to_s.upcase
|
84
|
-
end
|
85
|
-
|
86
|
-
# If a method call is missing, then delegate to concept parent.
|
87
|
-
# def method_missing(method, args = {})
|
88
|
-
def method_missing(method, *args, &block)
|
89
|
-
m = method.to_s
|
90
|
-
if m[0] == "_"
|
91
|
-
instance_eval("get(:#{m[1, m.size - 1]})", __FILE__, __LINE__)
|
92
|
-
# elsif not Application.instance.macros[m].nil?
|
93
|
-
elsif not Project.value[:macros][m].nil?
|
94
|
-
puts "macro exec: #{m}"
|
95
|
-
code = ""
|
96
|
-
args[0].keys.each { |key| code += "set(:#{key}, '#{args[0][key]}')\n" }
|
97
|
-
puts code
|
98
|
-
# instance_eval(code)
|
99
|
-
# Application.instance.macros[m].call
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def respond_to_missing?(method_name, include_private = false)
|
104
|
-
true
|
105
|
-
end
|
106
|
-
|
107
|
-
def gett(value)
|
108
|
-
a = get(value)
|
109
|
-
return "[#{value}](\#required-params)" if @cases_params.include? value
|
110
|
-
return "[#{value}](\#created-params)" if @setted_params[value]
|
111
|
-
|
112
|
-
"[#{a}](\#global-params)" if @global_params.include? value
|
113
|
-
end
|
114
|
-
|
115
|
-
def set(key, value)
|
116
|
-
@setted_params[key] = value
|
117
|
-
end
|
118
|
-
|
119
|
-
def unique(_key, _value)
|
120
|
-
# don't do nothing
|
121
|
-
end
|
122
|
-
|
123
|
-
def log(text = "", type = :info)
|
124
|
-
@data[:logs] << "[#{type}]: " + text.to_s
|
125
|
-
end
|
126
|
-
end
|
File without changes
|
File without changes
|
File without changes
|