teuton 2.9.6 → 2.10.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/docs/commands/README.md +6 -29
- data/docs/learn/13-feedback.md +8 -7
- data/lib/teuton/case/case.rb +5 -9
- data/lib/teuton/case/dsl/send.rb +13 -8
- data/lib/teuton/case_manager/dsl.rb +24 -17
- data/lib/teuton/case_manager/export_manager.rb +1 -3
- data/lib/teuton/case_manager/send_manager.rb +22 -6
- data/lib/teuton/report/formatter/formatter.rb +1 -0
- data/lib/teuton/report/report.rb +1 -5
- data/lib/teuton/utils/project.rb +4 -4
- data/lib/teuton/version.rb +1 -1
- metadata +32 -14
- data/docs/changelog/changelog.1.md +0 -119
- data/docs/changelog/changelog.2.md +0 -136
- data/docs/changelog/todo.md +0 -16
- data/lib/teuton/deprecated/application.rb +0 -80
- data/lib/teuton/deprecated/application_test.rb +0 -32
- data/lib/teuton/deprecated/runner.rb +0 -190
- data/lib/teuton/deprecated/utils.rb +0 -40
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7936417ce11de28acf3bddee94dcf41b4848742eae8266cce8bf70792ff4e592
|
|
4
|
+
data.tar.gz: bf8175c24a48e80c6257ab90898b52421157a471010ac1e730b3926962394ef9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a042452b9f025520bce19c4254e799ae9c51e5195804bc8a7d132c63d9271e7de3f03a9c14cb85b799635174a20cddc8a002bd43c565e91395d474059f82d1e
|
|
7
|
+
data.tar.gz: dd3051109b8b756709e34343bed5301140b33368f4fc3efed751f805960db29495ca9b84bfcaf36251715215a649e53be350cb4cee88e294d74285676a77e837
|
data/docs/commands/README.md
CHANGED
|
@@ -14,20 +14,9 @@ Available command functions:
|
|
|
14
14
|
|
|
15
15
|
Show help about command functions.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Commands:
|
|
21
|
-
teuton [run] [OPTIONS] DIRECTORY # Run test from directory
|
|
22
|
-
teuton check [OPTIONS] DIRECTORY # Check test and config file content
|
|
23
|
-
teuton config DIRECTORY # Suggest configuration
|
|
24
|
-
teuton help [COMMAND] # Describe available commands or one specific command
|
|
25
|
-
teuton new DIRECTORY # Create skeleton for a new project
|
|
26
|
-
teuton readme DIRECTORY # Show README extracted from test contents
|
|
27
|
-
teuton version # Show the program version
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Execute `teuton help FUNCTION_NAME` for more information.
|
|
17
|
+
Usage:
|
|
18
|
+
* `teuton help`
|
|
19
|
+
* `teuton help FUNCTION_NAME`
|
|
31
20
|
|
|
32
21
|
Alias: `teuton h`,`teuton -h`, `teuton --help`
|
|
33
22
|
|
|
@@ -37,13 +26,6 @@ Show current version.
|
|
|
37
26
|
|
|
38
27
|
Usage: `teuton version`
|
|
39
28
|
|
|
40
|
-
Example:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
$ teuton version
|
|
44
|
-
teuton (version 2.9.5)
|
|
45
|
-
```
|
|
46
|
-
|
|
47
29
|
Alias: `teuton v`, `teuton -v`, `teuton --version`
|
|
48
30
|
|
|
49
31
|
# 3. Create new test
|
|
@@ -75,7 +57,7 @@ Alias: `teuton n foo`, `teuton -n foo`, `teuton --new foo`
|
|
|
75
57
|
|
|
76
58
|
# 4. Check test
|
|
77
59
|
|
|
78
|
-
Check test and config files
|
|
60
|
+
Check test and config files from DIRPATH folder.
|
|
79
61
|
|
|
80
62
|
Usage: `teuton check DIRPATH`
|
|
81
63
|
|
|
@@ -100,11 +82,6 @@ Create a readme file for the exercise.
|
|
|
100
82
|
|
|
101
83
|
Usage: `teuton readme DIRPATH > README.md`
|
|
102
84
|
|
|
103
|
-
This function reads test and config files, and generate Markdown output with guidelines and target descriptions.
|
|
104
|
-
|
|
105
|
-
Students will need this information to resolv the proposed problem/exercise into their machines.
|
|
85
|
+
This function reads test and config files, and generate Markdown output with guidelines and target descriptions about the exercise.
|
|
106
86
|
|
|
107
|
-
Alias:
|
|
108
|
-
* `teuton r DIRPATH`
|
|
109
|
-
* `teuton -r DIRPATH`
|
|
110
|
-
* `teuton --readme DIRPATH`
|
|
87
|
+
Alias: `teuton r DIRPATH`, `teuton -r DIRPATH`, `teuton --readme DIRPATH`
|
data/docs/learn/13-feedback.md
CHANGED
|
@@ -37,12 +37,13 @@ Executing `teuton run examples/13-feedback`, we get this output:
|
|
|
37
37
|
|
|
38
38
|
```
|
|
39
39
|
GROUPS
|
|
40
|
-
-
|
|
40
|
+
- Hide feedback messages from output
|
|
41
41
|
01 (1.0/1.0)
|
|
42
|
-
Description :
|
|
43
|
-
Command :
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
Description : Service SSH disabled
|
|
43
|
+
Command : *********************
|
|
44
|
+
Output : *********
|
|
45
|
+
Duration : 0.011 (local)
|
|
46
|
+
Alterations : **********************
|
|
47
|
+
Expected : **************
|
|
48
|
+
Result : ********
|
|
48
49
|
```
|
data/lib/teuton/case/case.rb
CHANGED
|
@@ -15,15 +15,11 @@ class Case
|
|
|
15
15
|
include DSL
|
|
16
16
|
include Verbose
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
attr_accessor :result
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
attr_reader :id
|
|
24
|
-
attr_reader :config # Readed by ExecuteManager
|
|
25
|
-
attr_reader :uniques
|
|
26
|
-
attr_reader :skip
|
|
18
|
+
# Updated by ExecuteManager
|
|
19
|
+
attr_accessor :action, :result, :sessions, :conn_status
|
|
20
|
+
# Readed by ExecuteManager
|
|
21
|
+
attr_reader :id, :config, :uniques, :skip
|
|
22
|
+
|
|
27
23
|
@@id = "01" # First case ID value
|
|
28
24
|
|
|
29
25
|
def initialize(config)
|
data/lib/teuton/case/dsl/send.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module DSL
|
|
4
4
|
# * send, tempfile, tempdir, remote_tempdir, remote_tempfile
|
|
5
|
-
def send(args = {})
|
|
5
|
+
def send(logfile, args = {})
|
|
6
6
|
return if skip?
|
|
7
7
|
|
|
8
8
|
return unless args[:copy_to]
|
|
@@ -10,10 +10,10 @@ module DSL
|
|
|
10
10
|
host = args[:copy_to].to_s
|
|
11
11
|
return unless @conn_status[host].nil?
|
|
12
12
|
|
|
13
|
-
ip = get(
|
|
14
|
-
username = get(
|
|
15
|
-
password = get(
|
|
16
|
-
port = get(
|
|
13
|
+
ip = get(:"#{host}_ip")
|
|
14
|
+
username = get(:"#{host}_username").to_s
|
|
15
|
+
password = get(:"#{host}_password").to_s
|
|
16
|
+
port = get(:"#{host}_port").to_i
|
|
17
17
|
port = 22 if port.zero?
|
|
18
18
|
|
|
19
19
|
filename = "#{@report.filename}.#{@report.format}"
|
|
@@ -32,11 +32,16 @@ module DSL
|
|
|
32
32
|
Net::SFTP.start(ip, username, password: password, port: port) do |sftp|
|
|
33
33
|
sftp.upload!(localfilepath, remotefilepath)
|
|
34
34
|
end
|
|
35
|
-
msg = Rainbow("==> Case #{get(:tt_members)}: report (#{remotefilepath}) copy to (#{ip})").green
|
|
35
|
+
msg = Rainbow("==> [ OK ] Case #{get(:tt_members)}: report (#{remotefilepath}) copy to (#{ip})").green
|
|
36
36
|
verboseln(msg)
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
logfile.write "#{msg}\n"
|
|
38
|
+
logfile.flush
|
|
39
|
+
rescue => e
|
|
40
|
+
msg = Rainbow("==> [FAIL] Case #{get(:tt_members)}: 'scp #{localfilepath}' to #{remotefilepath}").red
|
|
41
|
+
msg += "\n--> [ERROR] #{e}"
|
|
39
42
|
verboseln(msg)
|
|
43
|
+
logfile.write "#{msg}\n"
|
|
44
|
+
logfile.flush
|
|
40
45
|
end
|
|
41
46
|
end
|
|
42
47
|
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
require_relative "../utils/project"
|
|
2
2
|
require_relative "case_manager"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
begin
|
|
11
|
-
require_relative findfiles.first
|
|
12
|
-
Project.value[:uses] << File.basename(findfiles.first)
|
|
13
|
-
rescue
|
|
14
|
-
puts "[ERROR] Unknown file : #{filename}"
|
|
15
|
-
puts " Check line : use '#{filename}'"
|
|
16
|
-
exit 1
|
|
17
|
-
end
|
|
18
|
-
end
|
|
4
|
+
# DSL instructions that apply equally to all cases.
|
|
5
|
+
# Therefore, they are stored globally in the case manager.
|
|
6
|
+
# * define_macro
|
|
7
|
+
# * group
|
|
8
|
+
# * play
|
|
9
|
+
# * use
|
|
19
10
|
|
|
20
11
|
def define_macro(name, *args, &block)
|
|
21
|
-
Project.value[:macros][name] = {args: args, block: block}
|
|
12
|
+
Project.value[:macros][name] = { args: args, block: block }
|
|
22
13
|
end
|
|
23
14
|
alias def_macro define_macro
|
|
24
15
|
alias defmacro define_macro
|
|
@@ -27,7 +18,7 @@ alias defmacro define_macro
|
|
|
27
18
|
# @param name (String) Group name
|
|
28
19
|
# @param block (Block) Tests code
|
|
29
20
|
def group(name, &block)
|
|
30
|
-
Project.value[:groups] << {name: name, block: block}
|
|
21
|
+
Project.value[:groups] << { name: name, block: block }
|
|
31
22
|
end
|
|
32
23
|
alias task group
|
|
33
24
|
|
|
@@ -36,3 +27,19 @@ def play(&block)
|
|
|
36
27
|
CaseManager.new.play(&block)
|
|
37
28
|
end
|
|
38
29
|
alias start play
|
|
30
|
+
|
|
31
|
+
def use(filename)
|
|
32
|
+
filename += ".rb"
|
|
33
|
+
rbfiles = File.join(Project.value[:project_path], "**", filename)
|
|
34
|
+
files = Dir.glob(rbfiles)
|
|
35
|
+
findfiles = []
|
|
36
|
+
files.sort.each { |f| findfiles << f if f.include?(filename) }
|
|
37
|
+
begin
|
|
38
|
+
require_relative findfiles.first
|
|
39
|
+
Project.value[:uses] << File.basename(findfiles.first)
|
|
40
|
+
rescue StandardError
|
|
41
|
+
puts "[ERROR] Unknown file : #{filename}"
|
|
42
|
+
puts " Check line : use '#{filename}'"
|
|
43
|
+
exit 1
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
require "rainbow"
|
|
2
2
|
|
|
3
3
|
class SendManager
|
|
4
|
+
def initialize
|
|
5
|
+
logpath = File.join(Project.value[:output_basedir], Project.value[:test_name], "send.log")
|
|
6
|
+
@logfile = File.open(logpath, "a")
|
|
7
|
+
end
|
|
8
|
+
|
|
4
9
|
##
|
|
5
|
-
# Execute "send" order:
|
|
10
|
+
# Execute "send" order: Copy every case report to remote hosts
|
|
6
11
|
# @param args (Hash) Send options
|
|
7
12
|
def call(cases, args)
|
|
8
13
|
threads = []
|
|
9
14
|
puts ""
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
write("-" * 70, :green)
|
|
16
|
+
write("Started at #{Time.new}", :green)
|
|
17
|
+
write("Sending reports to reachable hosts. Options=#{args}", :green)
|
|
18
|
+
|
|
19
|
+
cases.each { |c| threads << Thread.new { c.send(@logfile, args) } }
|
|
13
20
|
threads.each(&:join)
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
|
|
22
|
+
write("Finished!", :green)
|
|
23
|
+
puts Rainbow("-" * 70).green
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def write(msg, color)
|
|
29
|
+
puts Rainbow(msg).color(color)
|
|
30
|
+
@logfile.write "#{msg}\n"
|
|
31
|
+
@logfile.flush
|
|
16
32
|
end
|
|
17
33
|
end
|
data/lib/teuton/report/report.rb
CHANGED
|
@@ -3,11 +3,7 @@ require_relative "../utils/settings"
|
|
|
3
3
|
require_relative "formatter/formatter"
|
|
4
4
|
|
|
5
5
|
class Report
|
|
6
|
-
attr_accessor :id, :filename, :output_dir
|
|
7
|
-
attr_accessor :head
|
|
8
|
-
attr_accessor :lines
|
|
9
|
-
attr_accessor :tail
|
|
10
|
-
attr_accessor :format
|
|
6
|
+
attr_accessor :id, :filename, :output_dir, :head, :lines, :tail, :format
|
|
11
7
|
attr_reader :history
|
|
12
8
|
|
|
13
9
|
def initialize(id = "00")
|
data/lib/teuton/utils/project.rb
CHANGED
|
@@ -63,9 +63,9 @@ class Project
|
|
|
63
63
|
value[:config_path] = finder.config_path
|
|
64
64
|
value[:test_name] = finder.test_name
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
return if value[:options]["case"].nil?
|
|
67
|
+
|
|
68
|
+
numbers = value[:options]["case"].split(",")
|
|
69
|
+
value[:options]["case"] = numbers.collect!(&:to_i)
|
|
70
70
|
end
|
|
71
71
|
end
|
data/lib/teuton/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: teuton
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Vargas Ruiz
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rainbow
|
|
@@ -107,6 +107,34 @@ dependencies:
|
|
|
107
107
|
- - "~>"
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: '4.0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: ed25519
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '1.2'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '1.2'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: bcrypt_pbkdf
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '1.0'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '1.0'
|
|
110
138
|
description: |2
|
|
111
139
|
Intrastructure test, useful for:
|
|
112
140
|
(1) Sysadmin teachers to evaluate students remote machines.
|
|
@@ -121,11 +149,8 @@ executables:
|
|
|
121
149
|
- teuton
|
|
122
150
|
extensions: []
|
|
123
151
|
extra_rdoc_files:
|
|
124
|
-
- README.md
|
|
125
152
|
- LICENSE
|
|
126
|
-
-
|
|
127
|
-
- docs/changelog/changelog.2.md
|
|
128
|
-
- docs/changelog/todo.md
|
|
153
|
+
- README.md
|
|
129
154
|
- docs/commands/README.md
|
|
130
155
|
- docs/commands/check-example.md
|
|
131
156
|
- docs/commands/howto-run-tests.md
|
|
@@ -190,9 +215,6 @@ files:
|
|
|
190
215
|
- LICENSE
|
|
191
216
|
- README.md
|
|
192
217
|
- bin/teuton
|
|
193
|
-
- docs/changelog/changelog.1.md
|
|
194
|
-
- docs/changelog/changelog.2.md
|
|
195
|
-
- docs/changelog/todo.md
|
|
196
218
|
- docs/commands/README.md
|
|
197
219
|
- docs/commands/check-example.md
|
|
198
220
|
- docs/commands/howto-run-tests.md
|
|
@@ -308,10 +330,6 @@ files:
|
|
|
308
330
|
- lib/teuton/check/main.rb
|
|
309
331
|
- lib/teuton/check/show.rb
|
|
310
332
|
- lib/teuton/cli.rb
|
|
311
|
-
- lib/teuton/deprecated/application.rb
|
|
312
|
-
- lib/teuton/deprecated/application_test.rb
|
|
313
|
-
- lib/teuton/deprecated/runner.rb
|
|
314
|
-
- lib/teuton/deprecated/utils.rb
|
|
315
333
|
- lib/teuton/files/README.md
|
|
316
334
|
- lib/teuton/files/config.yaml
|
|
317
335
|
- lib/teuton/files/start.rb
|
|
@@ -368,7 +386,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
368
386
|
- !ruby/object:Gem::Version
|
|
369
387
|
version: '0'
|
|
370
388
|
requirements: []
|
|
371
|
-
rubygems_version: 3.
|
|
389
|
+
rubygems_version: 3.7.2
|
|
372
390
|
specification_version: 4
|
|
373
391
|
summary: Teuton (Infrastructure test)
|
|
374
392
|
test_files: []
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
[<< back](../CHANGELOG.md)
|
|
2
|
-
|
|
3
|
-
# CHANGELOG
|
|
4
|
-
|
|
5
|
-
## [0.22.1] June 2017
|
|
6
|
-
|
|
7
|
-
* Now it's posible to use config files with YAML and JSON format
|
|
8
|
-
* Preparing migration of CLI command to use Thor gem
|
|
9
|
-
|
|
10
|
-
## [1.0.0] July 2017
|
|
11
|
-
|
|
12
|
-
* New stable version
|
|
13
|
-
|
|
14
|
-
## 2019
|
|
15
|
-
|
|
16
|
-
## [1.10.0] Janyary 2019
|
|
17
|
-
|
|
18
|
-
* SysadminGame change his name by TEUTON. "project" command replaced by "teuton".
|
|
19
|
-
* Challenges (Teuton scripts) moved to "teuton-challenges" github repository.
|
|
20
|
-
* Execute "rake get_challenges" to get sample teuton challenges
|
|
21
|
-
|
|
22
|
-
## [2.0.4] August 2019
|
|
23
|
-
|
|
24
|
-
* TEUTON project grew up and was divided into the folowing repositories: teuton, challenges, panel, resources and vagrant.
|
|
25
|
-
* Documentation has been moved into respository teuton wiki. Only maintain English docs.
|
|
26
|
-
|
|
27
|
-
## [2.1.0]
|
|
28
|
-
|
|
29
|
-
**Export grades on csv file using Moodle format**
|
|
30
|
-
|
|
31
|
-
* Automaticaly exports `moodle.csv` file with all cases grades, using adecuate format so it could be imported directly into Moodle platform.
|
|
32
|
-
* We need to configure some params like this:
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
---
|
|
36
|
-
:global:
|
|
37
|
-
:cases:
|
|
38
|
-
- :tt_members: ...
|
|
39
|
-
:tt_moodle_id: User Moodle Identity
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**readme keyword**
|
|
43
|
-
|
|
44
|
-
We currently use the "teuton readme pry-folder" command to export README file from the challenge.
|
|
45
|
-
|
|
46
|
-
* This example shows how to use readme keyword to add group description or target description:
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
group "GROUPNAME" do
|
|
50
|
-
readme "Description for this group"
|
|
51
|
-
|
|
52
|
-
target "target1"
|
|
53
|
-
readme "Description for this target"
|
|
54
|
-
goto :host, :exec => 'id root'
|
|
55
|
-
expec_one 'root'
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
**Installation process**
|
|
59
|
-
|
|
60
|
-
* Use Bundler to install gems instead of rake.
|
|
61
|
-
* It will be usefull use sysadming-game as gem? And install it with `gem install teuton`.
|
|
62
|
-
* Vagrant: test how to use vagrant machines as case hosts.
|
|
63
|
-
|
|
64
|
-
**Info sobre novedades de la versión 2.1**
|
|
65
|
-
|
|
66
|
-
1. Teuton readme y dsl readme
|
|
67
|
-
2. Macros de define macro
|
|
68
|
-
3. Export yaml y html
|
|
69
|
-
4. Teuton --no-color
|
|
70
|
-
5. teuton run --case
|
|
71
|
-
6. teuton run --cname
|
|
72
|
-
7. teuton run --cpath
|
|
73
|
-
8. actualizar formatos de salida
|
|
74
|
-
9. instalación mediante gemas
|
|
75
|
-
10. teuton panel
|
|
76
|
-
11. teuton client y server
|
|
77
|
-
12. nuevos nombres de comandos...
|
|
78
|
-
13. cambio de goto a run
|
|
79
|
-
|
|
80
|
-
## [2.2.0]
|
|
81
|
-
|
|
82
|
-
**New features**
|
|
83
|
-
|
|
84
|
-
* Let's see new features examples:
|
|
85
|
-
* 10 result and moodle_id
|
|
86
|
-
* 11 get_vars
|
|
87
|
-
* 12 alias
|
|
88
|
-
* 13 include (tt_include config param)
|
|
89
|
-
* 14 macros
|
|
90
|
-
|
|
91
|
-
**Configuration file**
|
|
92
|
-
|
|
93
|
-
* Por defecto los valores de clave de los ficheros de configuración serán Strings en lugar de símbolos, aunque lo símbolos seguirán funcionando.
|
|
94
|
-
|
|
95
|
-
**get_vars: To think - We are not sure about this***
|
|
96
|
-
|
|
97
|
-
* "get" keyword simplification: Simplify getting and setting params process. For example: `_username_`, may be alias for `get(:username)`. Then
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
target "Create user #{_username_}"
|
|
101
|
-
run "id #{_username_}"
|
|
102
|
-
expect_one _username_
|
|
103
|
-
```
|
|
104
|
-
Same as
|
|
105
|
-
|
|
106
|
-
```
|
|
107
|
-
target "Create user "+get(:username)
|
|
108
|
-
run "id " + get(:username)
|
|
109
|
-
expect_one get(:username)
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
* Promocinar el proyecto:
|
|
113
|
-
* Documentar y hacer videos.
|
|
114
|
-
* Charlas y talleres
|
|
115
|
-
|
|
116
|
-
**Fixed**
|
|
117
|
-
|
|
118
|
-
* Solucionar fallo en --cname
|
|
119
|
-
* Revisar doc options como cpanel
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
## [2.3.9]
|
|
3
|
-
|
|
4
|
-
- FIX: Remove warnings from linter
|
|
5
|
-
- FIX: Remove warning about thor gem version. Upgrade gem to 1.2
|
|
6
|
-
|
|
7
|
-
## [2.3.11]
|
|
8
|
-
|
|
9
|
-
- Issue #18
|
|
10
|
-
|
|
11
|
-
## [2.4.0]
|
|
12
|
-
|
|
13
|
-
New features:
|
|
14
|
-
- Hide feedback from reports: `export feedback: false`
|
|
15
|
-
- Add new DSL keyword: expect_last, expect_fisrt
|
|
16
|
-
- Remove os gem.
|
|
17
|
-
- Change test output colors to green as use others test tools.
|
|
18
|
-
- Change show DSL params. Accepts one param "verbose: NUMBER" to adjust verbosity output level on screen.
|
|
19
|
-
|
|
20
|
-
New doc and example:
|
|
21
|
-
- 14-alias
|
|
22
|
-
- 16-exit_codes
|
|
23
|
-
|
|
24
|
-
Bug fixed:
|
|
25
|
-
- All "expect*" keywords must require 2 arguments. The second is optional.
|
|
26
|
-
|
|
27
|
-
Revise
|
|
28
|
-
- Remove colors to log text
|
|
29
|
-
- teuton readme: macros, getvars, expect_last, expect_first
|
|
30
|
-
|
|
31
|
-
## [2.4.2]
|
|
32
|
-
|
|
33
|
-
- Fix bug with result.grep_v(Array)
|
|
34
|
-
|
|
35
|
-
## [2.4.3]
|
|
36
|
-
|
|
37
|
-
- Fix: "expect_none" without params works as "expect result.count.eq 0"
|
|
38
|
-
- Add: "expect_nothing" that works as "expect result.count.eq 0".
|
|
39
|
-
|
|
40
|
-
## [2.4.4]
|
|
41
|
-
|
|
42
|
-
-- Modify: teuton check output colors and exit codes.
|
|
43
|
-
exit code 0 = check OK
|
|
44
|
-
exit code 1 = check error
|
|
45
|
-
-- Fix teuton check docs.
|
|
46
|
-
|
|
47
|
-
## [2.4.5]
|
|
48
|
-
|
|
49
|
-
-- FIX: "expect_nothing" was always TRUE when SSH/Telnet connections fails!
|
|
50
|
-
Now when SSH/Telnet connections fails result contains "SSH: NO CONNECTION!"
|
|
51
|
-
So "expect_nothing" will fail.
|
|
52
|
-
|
|
53
|
-
## [2.5.0]
|
|
54
|
-
|
|
55
|
-
- ADD: "tt_moodle_max_score" global configuration param. Teuton grades (0-100) are divided by this value when exporting data into "moodle.csv" output file.
|
|
56
|
-
- UPDATE: Revise documentation. Doc learn 10,11, 12,13 y 14. 10 result and moodle_id, 12 alias, 13 include, 14 macro, Doc tt_include
|
|
57
|
-
- UPDATE: Internal changes. Remove Colorize gem and replace with Rainbow.
|
|
58
|
-
|
|
59
|
-
## [2.6.0]
|
|
60
|
-
|
|
61
|
-
- [ADD] When running local or SSH commands, stdout and stderr are captured and readed by "expect" sentence.
|
|
62
|
-
|
|
63
|
-
## [2.7.0]
|
|
64
|
-
|
|
65
|
-
New features:
|
|
66
|
-
- [ADD] "teuton config PROJECTPATH" will suggest suitable configuration for the project.
|
|
67
|
-
- [ADD] Every one line command output is registered into reports.
|
|
68
|
-
- [ADD] "expect_exit 1", check last command exit code is equal to 1.
|
|
69
|
-
|
|
70
|
-
Internal changes:
|
|
71
|
-
* Application class splited into Settings and Project classes
|
|
72
|
-
* Create SendManager similar to ExportManager
|
|
73
|
-
|
|
74
|
-
## [2.7.1]
|
|
75
|
-
|
|
76
|
-
- [FIX] Fixed an issue that appeared when executing test and fail connection to remote computer.
|
|
77
|
-
|
|
78
|
-
## [2.7.2] 20230607
|
|
79
|
-
|
|
80
|
-
- [FIX] Fixed an issue that appeared when exporting reports without feedback after failing to connect to remote computer.
|
|
81
|
-
|
|
82
|
-
## [2.7.3] 20230607
|
|
83
|
-
|
|
84
|
-
- [FIX] Hall of fame now use Project class instead of Application.
|
|
85
|
-
|
|
86
|
-
## [2.8.0] 20230630
|
|
87
|
-
|
|
88
|
-
DSL expect:
|
|
89
|
-
- [ADD] "expect_ok" as "expect_exit 0 ".
|
|
90
|
-
- [ADD] "expect_fail" as "expect_exit NUMBER" where NUMBER > 0.
|
|
91
|
-
- [FIX] expect evaluation fail when there is no remote connection.
|
|
92
|
-
|
|
93
|
-
DSL send:
|
|
94
|
-
- [UPDATE] Rename "remote_dir" send param to "dir".
|
|
95
|
-
- [UPDATE] send output messages
|
|
96
|
-
|
|
97
|
-
## [2.9.0] 20230726
|
|
98
|
-
|
|
99
|
-
- [ADD] "expect_sequence" that check if sequence is present
|
|
100
|
-
- [ADD] New DSL "run_script". Example: `run_script script, on: :host1`, upload script to host1 and then execute it on remote.
|
|
101
|
-
- [ADD] New DSL "upload". Upload local file to remote host. Example `upload "localfile", to: :host1`
|
|
102
|
-
- [ADD] `teuton check` works with `expect_sequence`, `run_script` and `upload`.
|
|
103
|
-
- [FIX] `teuton check` works fine with `macros`.
|
|
104
|
-
- [ADD] `teuton readme` works with `expect_sequence`, `run_script` and `upload`.
|
|
105
|
-
- [FIX] `teuton readme` works fine with `macros`.
|
|
106
|
-
|
|
107
|
-
## [2.9.1] 20231117
|
|
108
|
-
|
|
109
|
-
- [FIX] Config option `tt_include` doubled readed data on Windows platforms.
|
|
110
|
-
|
|
111
|
-
## [2.9.2] 20231201
|
|
112
|
-
|
|
113
|
-
- [FIX] Change error message when running a non-existent challenge
|
|
114
|
-
```
|
|
115
|
-
❯ teuton run example/foo
|
|
116
|
-
[ERROR] Cannot find main file!
|
|
117
|
-
/home/username/example/foo/start.rb
|
|
118
|
-
or /home/username/example/foo.rb
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## [2.9.3] 20250402
|
|
122
|
-
|
|
123
|
-
- [FIX] Error with telnet connections.
|
|
124
|
-
|
|
125
|
-
## [2.9.4] 20250410
|
|
126
|
-
|
|
127
|
-
- [FIX] Improve the markdown output of the readme.
|
|
128
|
-
- [FIX] Telnet exitcode
|
|
129
|
-
|
|
130
|
-
## [2.9.5] 20250514
|
|
131
|
-
|
|
132
|
-
- [FIX] `require "json_pure"`is deprecated. Use `json` gem instead of `json_pure`.
|
|
133
|
-
|
|
134
|
-
## [2.9.6] 20251106
|
|
135
|
-
|
|
136
|
-
- [FIX] Problem with `export preserve: true`. It was using old class Application. Now use Project class.
|
data/docs/changelog/todo.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
## TO-DO
|
|
3
|
-
|
|
4
|
-
New features:
|
|
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
|
-
|
|
9
|
-
Revise:
|
|
10
|
-
* verify get(:key) and get('key') works fine!
|
|
11
|
-
* Formatter: xml
|
|
12
|
-
|
|
13
|
-
Internal changes:
|
|
14
|
-
* Laboratory to Checker
|
|
15
|
-
* Unify messages ERROR, INFO, WARN. etc
|
|
16
|
-
* Add tt_label as alias of tt_members
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
require "singleton"
|
|
2
|
-
require_relative "name_file_finder"
|
|
3
|
-
|
|
4
|
-
class Application
|
|
5
|
-
include Singleton
|
|
6
|
-
|
|
7
|
-
attr_reader :letter
|
|
8
|
-
attr_reader :running_basedir, :output_basedir
|
|
9
|
-
attr_reader :default
|
|
10
|
-
attr_accessor :options
|
|
11
|
-
attr_accessor :verbose
|
|
12
|
-
attr_accessor :global # Global configuration params
|
|
13
|
-
attr_accessor :ialias # Internal alias
|
|
14
|
-
attr_accessor :uses # Array of uses
|
|
15
|
-
attr_accessor :project_path, :script_path, :config_path, :test_name
|
|
16
|
-
|
|
17
|
-
def initialize
|
|
18
|
-
reset
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def reset
|
|
22
|
-
@letter = {
|
|
23
|
-
good: ".",
|
|
24
|
-
bad: "F",
|
|
25
|
-
error: "?",
|
|
26
|
-
none: " ",
|
|
27
|
-
ok: "\u{2714}",
|
|
28
|
-
cross: "\u{2716}"
|
|
29
|
-
}
|
|
30
|
-
@running_basedir = Dir.getwd
|
|
31
|
-
@output_basedir = "var"
|
|
32
|
-
@default = {name: "teuton", format: :txt, debug: false}
|
|
33
|
-
@options = {
|
|
34
|
-
"lang" => "en",
|
|
35
|
-
"color" => true,
|
|
36
|
-
"panel" => false
|
|
37
|
-
}
|
|
38
|
-
@verbose = true
|
|
39
|
-
|
|
40
|
-
@global = {}
|
|
41
|
-
@ialias = {}
|
|
42
|
-
@uses = [] # TODO
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def debug
|
|
46
|
-
@default[:debug]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def name
|
|
50
|
-
@default[:name]
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def quiet?
|
|
54
|
-
return true if Application.instance.options["quiet"]
|
|
55
|
-
return true unless Application.instance.verbose
|
|
56
|
-
|
|
57
|
-
false
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
##
|
|
61
|
-
# Preprocess input options:
|
|
62
|
-
# * Convert input case options String to an Array of integers
|
|
63
|
-
# * Read color input option
|
|
64
|
-
def add_input_params(projectpath, options)
|
|
65
|
-
@options.merge! options
|
|
66
|
-
Rainbow.enabled = @options["color"]
|
|
67
|
-
|
|
68
|
-
finder = NameFileFinder.new(@options)
|
|
69
|
-
finder.find_filenames_for(projectpath)
|
|
70
|
-
@project_path = finder.project_path
|
|
71
|
-
@script_path = finder.script_path
|
|
72
|
-
@config_path = finder.config_path
|
|
73
|
-
@test_name = finder.test_name
|
|
74
|
-
|
|
75
|
-
unless @options["case"].nil?
|
|
76
|
-
numbers = @options["case"].split(",")
|
|
77
|
-
@options["case"] = numbers.collect!(&:to_i)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
require "test/unit"
|
|
2
|
-
require_relative "../../lib/teuton/utils/application"
|
|
3
|
-
|
|
4
|
-
class ApplicationTest < Test::Unit::TestCase
|
|
5
|
-
def setup
|
|
6
|
-
@app = Application.instance
|
|
7
|
-
@app.reset
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def test_init_params
|
|
11
|
-
assert_equal ".", @app.letter[:good]
|
|
12
|
-
assert_equal "F", @app.letter[:bad]
|
|
13
|
-
assert_equal "?", @app.letter[:error]
|
|
14
|
-
assert_equal " ", @app.letter[:none]
|
|
15
|
-
assert_equal "var", @app.output_basedir
|
|
16
|
-
assert_equal false, @app.debug
|
|
17
|
-
assert_equal true, @app.verbose
|
|
18
|
-
|
|
19
|
-
assert_equal true, @app.global == {}
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def test_quiet?
|
|
23
|
-
@app.verbose = false
|
|
24
|
-
assert_equal false, @app.verbose
|
|
25
|
-
assert_equal true, Application.instance.quiet?
|
|
26
|
-
@app.verbose = true
|
|
27
|
-
assert_equal true, @app.verbose
|
|
28
|
-
assert_equal false, Application.instance.quiet?
|
|
29
|
-
@app.options["quiet"] = true
|
|
30
|
-
assert_equal true, Application.instance.quiet?
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
require "net/ssh"
|
|
2
|
-
require "net/sftp"
|
|
3
|
-
require "net/telnet"
|
|
4
|
-
require_relative "dsl/log"
|
|
5
|
-
|
|
6
|
-
class Case
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
# READ: @config
|
|
10
|
-
# WRITE: @action, @result, @session
|
|
11
|
-
def run_cmd_on(host)
|
|
12
|
-
protocol = @config.get(:"#{host}_protocol")
|
|
13
|
-
ip = @config.get(:"#{host}_ip")
|
|
14
|
-
|
|
15
|
-
if protocol.to_s.downcase == "local" || host.to_s == "localhost"
|
|
16
|
-
# Protocol force => local
|
|
17
|
-
run_cmd_localhost
|
|
18
|
-
elsif protocol.to_s.downcase == "ssh"
|
|
19
|
-
# Protocol force => ssh
|
|
20
|
-
run_cmd_remote_ssh(host)
|
|
21
|
-
elsif protocol.to_s.downcase == "telnet"
|
|
22
|
-
# Protocol force => telnet
|
|
23
|
-
run_cmd_remote_telnet(host)
|
|
24
|
-
elsif ip.to_s.downcase == "localhost" || ip.to_s.include?("127.0.0.")
|
|
25
|
-
run_cmd_localhost
|
|
26
|
-
elsif ip == "NODATA"
|
|
27
|
-
log("#{host} IP not found!", :error)
|
|
28
|
-
else
|
|
29
|
-
run_cmd_remote_ssh host
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def run_cmd_localhost
|
|
34
|
-
@action[:conn_type] = :local
|
|
35
|
-
resp = my_execute(@action[:command], @action[:encoding])
|
|
36
|
-
@result.exitcode = resp[:exitcode]
|
|
37
|
-
@result.content = resp[:content]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def run_cmd_remote(input_hostname)
|
|
41
|
-
# @param input_hostname (Symbol or String)
|
|
42
|
-
hostname = input_hostname.to_s
|
|
43
|
-
i = (hostname + "_protocol").to_sym
|
|
44
|
-
protocol = @config.get(i) if @config.get(i)
|
|
45
|
-
protocol = :ssh if protocol.nil? || protocol == "NODATA"
|
|
46
|
-
protocol = protocol.to_sym
|
|
47
|
-
case protocol
|
|
48
|
-
when :ssh
|
|
49
|
-
run_cmd_remote_ssh(input_hostname)
|
|
50
|
-
when :telnet
|
|
51
|
-
run_cmd_remote_telnet(input_hostname)
|
|
52
|
-
when :local
|
|
53
|
-
run_cmd_localhost
|
|
54
|
-
else
|
|
55
|
-
log("Protocol #{protocol} unknown! Use ssh or telnet.", :error)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def run_cmd_remote_ssh(input_hostname)
|
|
60
|
-
@action[:conn_type] = :ssh
|
|
61
|
-
hostname = input_hostname.to_s
|
|
62
|
-
ip = @config.get(:"#{hostname}_ip").to_s
|
|
63
|
-
username = @config.get(:"#{hostname}_username").to_s
|
|
64
|
-
password = @config.get(:"#{hostname}_password").to_s
|
|
65
|
-
port = @config.get(:"#{hostname}_port").to_i
|
|
66
|
-
port = 22 if port.zero?
|
|
67
|
-
|
|
68
|
-
unless @config.get(:"#{hostname}_route") == "NODATA"
|
|
69
|
-
# Reconfigure command with gateway. Example host1_route: IP.
|
|
70
|
-
# hostname2 = hostname ¿not used?
|
|
71
|
-
ip2 = ip
|
|
72
|
-
username2 = username
|
|
73
|
-
password2 = password
|
|
74
|
-
command2 = @action[:command]
|
|
75
|
-
hostname = @config.get(:"#{hostname}_route")
|
|
76
|
-
ip = @config.get(:"#{hostname}_ip").to_s
|
|
77
|
-
username = @config.get(:"#{hostname}_username").to_s
|
|
78
|
-
password = @config.get(:"#{hostname}_password").to_s
|
|
79
|
-
ostype = @config.get(:"#{hostname}_ostype").to_s
|
|
80
|
-
|
|
81
|
-
@action[:command] = if ostype.downcase.start_with? "win"
|
|
82
|
-
"echo y | plink #{username2}@#{ip2} -ssh -pw #{password2} \"#{command2}\""
|
|
83
|
-
else
|
|
84
|
-
"sshpass -p #{password2} #{username2}@#{ip2} #{command2}"
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
text = ""
|
|
89
|
-
exitcode = 0
|
|
90
|
-
begin
|
|
91
|
-
if @sessions[hostname].nil?
|
|
92
|
-
@sessions[hostname] = Net::SSH.start(
|
|
93
|
-
ip,
|
|
94
|
-
username,
|
|
95
|
-
port: port,
|
|
96
|
-
password: password,
|
|
97
|
-
keepalive: true,
|
|
98
|
-
timeout: 30,
|
|
99
|
-
non_interactive: true
|
|
100
|
-
)
|
|
101
|
-
end
|
|
102
|
-
text = if @sessions[hostname].instance_of? Net::SSH::Connection::Session
|
|
103
|
-
@sessions[hostname].exec!(@action[:command])
|
|
104
|
-
else
|
|
105
|
-
"SSH: NO CONNECTION!"
|
|
106
|
-
end
|
|
107
|
-
exitcode = text.exitstatus
|
|
108
|
-
rescue Errno::EHOSTUNREACH
|
|
109
|
-
@sessions[hostname] = :nosession
|
|
110
|
-
@conn_status[hostname] = :host_unreachable
|
|
111
|
-
exitcode = -1
|
|
112
|
-
log("Host #{ip} unreachable!", :error)
|
|
113
|
-
rescue Net::SSH::AuthenticationFailed
|
|
114
|
-
@sessions[hostname] = :nosession
|
|
115
|
-
@conn_status[hostname] = :error_authentication_failed
|
|
116
|
-
exitcode = -1
|
|
117
|
-
log("SSH::AuthenticationFailed!", :error)
|
|
118
|
-
rescue Net::SSH::HostKeyMismatch
|
|
119
|
-
@sessions[hostname] = :nosession
|
|
120
|
-
@conn_status[hostname] = :host_key_mismatch
|
|
121
|
-
exitcode = -1
|
|
122
|
-
log("SSH::HostKeyMismatch!", :error)
|
|
123
|
-
log("* The destination server's fingerprint is not matching " \
|
|
124
|
-
"what is in your local known_hosts file.", :error)
|
|
125
|
-
log("* Remove the existing entry in your local known_hosts file", :error)
|
|
126
|
-
log("* Try this => ssh-keygen -f '/home/USERNAME/.ssh/known_hosts' " \
|
|
127
|
-
"-R #{ip}", :error)
|
|
128
|
-
rescue => e
|
|
129
|
-
@sessions[hostname] = :nosession
|
|
130
|
-
@conn_status[hostname] = :error
|
|
131
|
-
exitcode = -1
|
|
132
|
-
log("[#{e.class}] SSH on <#{username}@#{ip}>" \
|
|
133
|
-
" exec: #{@action[:command]}", :error)
|
|
134
|
-
end
|
|
135
|
-
output = encode_and_split(@action[:encoding], text)
|
|
136
|
-
@result.exitcode = exitcode
|
|
137
|
-
@result.content = output
|
|
138
|
-
@result.content.compact!
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def run_cmd_remote_telnet(input_hostname)
|
|
142
|
-
@action[:conn_type] = :telnet
|
|
143
|
-
# app = Application.instance ¿not used?
|
|
144
|
-
hostname = input_hostname.to_s
|
|
145
|
-
ip = @config.get((hostname + "_ip").to_sym)
|
|
146
|
-
username = @config.get((hostname + "_username").to_sym).to_s
|
|
147
|
-
password = @config.get((hostname + "_password").to_sym).to_s
|
|
148
|
-
text = ""
|
|
149
|
-
begin
|
|
150
|
-
if @sessions[hostname].nil? || @sessions[hostname] == :ok
|
|
151
|
-
h = Net::Telnet.new(
|
|
152
|
-
"Host" => ip,
|
|
153
|
-
"Timeout" => 30,
|
|
154
|
-
"Prompt" => /login|teuton|[$%#>]/
|
|
155
|
-
)
|
|
156
|
-
# "Prompt" => Regexp.new(username[1, 40]))
|
|
157
|
-
# "Prompt" => /[$%#>] \z/n)
|
|
158
|
-
h.login(username, password)
|
|
159
|
-
h.cmd(@action[:command]) { |i| text << i }
|
|
160
|
-
h.close
|
|
161
|
-
@sessions[hostname] = :ok
|
|
162
|
-
else
|
|
163
|
-
text = "TELNET: NO CONNECTION!"
|
|
164
|
-
end
|
|
165
|
-
rescue Net::OpenTimeout
|
|
166
|
-
@sessions[hostname] = :nosession
|
|
167
|
-
@conn_status[hostname] = :open_timeout
|
|
168
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
169
|
-
log(" ExceptionType=<Net::OpenTimeout> doing <telnet #{ip}>", :error)
|
|
170
|
-
log(" └── Revise host IP!", :warn)
|
|
171
|
-
rescue Net::ReadTimeout
|
|
172
|
-
@sessions[hostname] = :nosession
|
|
173
|
-
@conn_status[hostname] = :read_timeout
|
|
174
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
175
|
-
log(" ExceptionType=<Net::ReadTimeout> doing <telnet #{ip}>", :error)
|
|
176
|
-
rescue => e
|
|
177
|
-
@sessions[hostname] = :nosession
|
|
178
|
-
@conn_status[hostname] = :error
|
|
179
|
-
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
180
|
-
log(" ExceptionType=<#{e.class}> doing telnet on <#{username}@#{ip}>" \
|
|
181
|
-
" exec: #{@action[:command]}", :error)
|
|
182
|
-
log(" └── username=<#{username}>, password=<#{password}>," \
|
|
183
|
-
" ip=<#{ip}>, HOSTID=<#{hostname}>", :warn)
|
|
184
|
-
end
|
|
185
|
-
output = encode_and_split(@action[:encoding], text)
|
|
186
|
-
@result.exitcode = -1
|
|
187
|
-
@result.content = output
|
|
188
|
-
@result.content.compact!
|
|
189
|
-
end
|
|
190
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|