teuton 0.0.1
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 +7 -0
- data/bin/teuton +4 -0
- data/lib/teuton/application.rb +53 -0
- data/lib/teuton/case_manager/case/builtin/main.rb +24 -0
- data/lib/teuton/case_manager/case/builtin/package.rb +20 -0
- data/lib/teuton/case_manager/case/builtin/service.rb +32 -0
- data/lib/teuton/case_manager/case/builtin/user.rb +20 -0
- data/lib/teuton/case_manager/case/case.rb +114 -0
- data/lib/teuton/case_manager/case/close.rb +29 -0
- data/lib/teuton/case_manager/case/config.rb +76 -0
- data/lib/teuton/case_manager/case/dsl/check.rb +24 -0
- data/lib/teuton/case_manager/case/dsl/deprecated.rb +14 -0
- data/lib/teuton/case_manager/case/dsl/expect.rb +78 -0
- data/lib/teuton/case_manager/case/dsl/getset.rb +22 -0
- data/lib/teuton/case_manager/case/dsl/goto.rb +35 -0
- data/lib/teuton/case_manager/case/dsl/log.rb +14 -0
- data/lib/teuton/case_manager/case/dsl/main.rb +11 -0
- data/lib/teuton/case_manager/case/dsl/missing.rb +12 -0
- data/lib/teuton/case_manager/case/dsl/send.rb +69 -0
- data/lib/teuton/case_manager/case/dsl/target.rb +16 -0
- data/lib/teuton/case_manager/case/dsl/unique.rb +11 -0
- data/lib/teuton/case_manager/case/main.rb +7 -0
- data/lib/teuton/case_manager/case/play.rb +59 -0
- data/lib/teuton/case_manager/case/result/ext_array.rb +43 -0
- data/lib/teuton/case_manager/case/result/ext_compare.rb +147 -0
- data/lib/teuton/case_manager/case/result/ext_filter.rb +68 -0
- data/lib/teuton/case_manager/case/result/result.rb +73 -0
- data/lib/teuton/case_manager/case/runner.rb +134 -0
- data/lib/teuton/case_manager/case_manager.rb +76 -0
- data/lib/teuton/case_manager/check_cases.rb +73 -0
- data/lib/teuton/case_manager/dsl.rb +31 -0
- data/lib/teuton/case_manager/export_manager.rb +20 -0
- data/lib/teuton/case_manager/hall_of_fame.rb +28 -0
- data/lib/teuton/case_manager/main.rb +6 -0
- data/lib/teuton/case_manager/report.rb +52 -0
- data/lib/teuton/case_manager/show.rb +19 -0
- data/lib/teuton/case_manager/utils.rb +57 -0
- data/lib/teuton/command/create.rb +20 -0
- data/lib/teuton/command/download.rb +26 -0
- data/lib/teuton/command/main.rb +9 -0
- data/lib/teuton/command/play.rb +34 -0
- data/lib/teuton/command/readme.rb +23 -0
- data/lib/teuton/command/test.rb +35 -0
- data/lib/teuton/command/update.rb +27 -0
- data/lib/teuton/command/version.rb +13 -0
- data/lib/teuton/files/start.rb +13 -0
- data/lib/teuton/project/configfile_reader.rb +49 -0
- data/lib/teuton/project/laboratory/builtin.rb +23 -0
- data/lib/teuton/project/laboratory/dsl.rb +117 -0
- data/lib/teuton/project/laboratory/laboratory.rb +55 -0
- data/lib/teuton/project/laboratory/show.rb +161 -0
- data/lib/teuton/project/name_file_finder.rb +129 -0
- data/lib/teuton/project/project.rb +62 -0
- data/lib/teuton/project/project_creator.rb +79 -0
- data/lib/teuton/project/readme/dsl.rb +109 -0
- data/lib/teuton/project/readme/lang.rb +30 -0
- data/lib/teuton/project/readme/readme.rb +156 -0
- data/lib/teuton/rake_function/check.rb +39 -0
- data/lib/teuton/rake_function/install.rb +36 -0
- data/lib/teuton/report/close.rb +34 -0
- data/lib/teuton/report/formatter/array_formatter.rb +84 -0
- data/lib/teuton/report/formatter/base_formatter.rb +33 -0
- data/lib/teuton/report/formatter/csv_formatter.rb +31 -0
- data/lib/teuton/report/formatter/formatter_factory.rb +73 -0
- data/lib/teuton/report/formatter/html_formatter.rb +81 -0
- data/lib/teuton/report/formatter/json_formatter.rb +17 -0
- data/lib/teuton/report/formatter/list_formatter.rb +71 -0
- data/lib/teuton/report/formatter/moodle_csv_formatter.rb +28 -0
- data/lib/teuton/report/formatter/resume_array_formatter.rb +49 -0
- data/lib/teuton/report/formatter/resume_json_formatter.rb +16 -0
- data/lib/teuton/report/formatter/resume_list_formatter.rb +62 -0
- data/lib/teuton/report/formatter/resume_txt_formatter.rb +102 -0
- data/lib/teuton/report/formatter/resume_yaml_formatter.rb +16 -0
- data/lib/teuton/report/formatter/txt_formatter.rb +102 -0
- data/lib/teuton/report/formatter/xml_formatter.rb +42 -0
- data/lib/teuton/report/formatter/yaml_formatter.rb +18 -0
- data/lib/teuton/report/report.rb +55 -0
- data/lib/teuton/report/show.rb +111 -0
- data/lib/teuton/utils/verbose.rb +15 -0
- data/lib/teuton.rb +17 -0
- metadata +263 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 3d55a24ec355421cd07d663355e689bc8edd0d4c80c498510d018a629580eb90
|
|
4
|
+
data.tar.gz: e640a71a276ce35f26aa4fc6412c836e4405df58a6c08e212f9046639280e486
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6008a3dbeef623139d4e6cbe73b54755e055756ce643d5bb3b8e46c42ecf1cba349cd3cd88274d8b188a94de89d06a03182269d8783ebfa8b13ad79669bbd865
|
|
7
|
+
data.tar.gz: 69128f5748c9cef8fa9b13c84c7c134dfb085709ba7c2c43b7d40033f974c2e088d6f28e8cbb67f37bd97ccae6be530bf9779dcc4fd30fec3795b36ca6988dcf
|
data/bin/teuton
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
|
|
3
|
+
# This Singleton contains application params
|
|
4
|
+
class Application
|
|
5
|
+
include Singleton
|
|
6
|
+
|
|
7
|
+
VERSION = '2.1.0'
|
|
8
|
+
NAME = 'teuton'
|
|
9
|
+
|
|
10
|
+
attr_reader :letter
|
|
11
|
+
attr_reader :running_basedir, :output_basedir
|
|
12
|
+
attr_reader :default
|
|
13
|
+
attr_accessor :options
|
|
14
|
+
attr_accessor :verbose
|
|
15
|
+
attr_accessor :global, :ialias
|
|
16
|
+
attr_accessor :checks, :groups, :uses
|
|
17
|
+
attr_accessor :hall_of_fame
|
|
18
|
+
attr_accessor :project_path, :script_path, :config_path, :test_name
|
|
19
|
+
|
|
20
|
+
def initialize
|
|
21
|
+
reset
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def reset
|
|
25
|
+
@letter = { good: '.', bad: 'F', error: '?', none: ' ' }
|
|
26
|
+
@running_basedir = Dir.getwd
|
|
27
|
+
@output_basedir = 'var'
|
|
28
|
+
@default = { name: 'teuton', format: :txt, debug: false }
|
|
29
|
+
@options = { 'lang' => 'en' }
|
|
30
|
+
@verbose = true
|
|
31
|
+
|
|
32
|
+
@global = {}
|
|
33
|
+
@ialias = {}
|
|
34
|
+
@checks = {}
|
|
35
|
+
@groups = []
|
|
36
|
+
@uses = [] # TODO
|
|
37
|
+
@hall_of_fame = []
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def debug
|
|
41
|
+
@default[:debug]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def name
|
|
45
|
+
@default[:name]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def quiet?
|
|
49
|
+
return true if Application.instance.options['quiet']
|
|
50
|
+
return true unless Application.instance.verbose
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
require_relative 'package'
|
|
3
|
+
require_relative 'service'
|
|
4
|
+
require_relative 'user'
|
|
5
|
+
|
|
6
|
+
class Case
|
|
7
|
+
def package(param)
|
|
8
|
+
@package = @package || Package.new(self)
|
|
9
|
+
@package.param = param
|
|
10
|
+
@package
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def service(param)
|
|
14
|
+
@service = @service || Service.new(self)
|
|
15
|
+
@service.param = param
|
|
16
|
+
@service
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def user(param)
|
|
20
|
+
@user = @user || User.new(self)
|
|
21
|
+
@user.param = param
|
|
22
|
+
@user
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
class Package
|
|
3
|
+
attr_accessor :param
|
|
4
|
+
|
|
5
|
+
def initialize(parent)
|
|
6
|
+
@parent = parent
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def installed?
|
|
10
|
+
@parent.target("Package #{@param} installed?")
|
|
11
|
+
@parent.run "whereis #{@param}"
|
|
12
|
+
@parent.expect_one [ 'bin', @param ]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def not_installed?
|
|
16
|
+
@parent.target("Package #{@param} not installed?")
|
|
17
|
+
@parent.run "whereis #{@param}"
|
|
18
|
+
@parent.expect_none [ 'bin' , @param ]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
class Service
|
|
3
|
+
attr_accessor :param
|
|
4
|
+
|
|
5
|
+
def initialize(parent)
|
|
6
|
+
@parent = parent
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def is_running?
|
|
10
|
+
@parent.target("Service #{@param} is running?")
|
|
11
|
+
@parent.run "systemctl status #{@param}"
|
|
12
|
+
@parent.expect_one ['Active:', 'running' ]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def is_inactive?
|
|
16
|
+
@parent.target("Service #{@param} is inactive?")
|
|
17
|
+
@parent.run "systemctl status #{@param}"
|
|
18
|
+
@parent.expect_one ['Active:', 'inactive' ]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def is_enable?
|
|
22
|
+
@parent.target("Service #{@param} is enable?")
|
|
23
|
+
@parent.run "systemctl status #{@param}"
|
|
24
|
+
@parent.expect_one ['Loaded:', 'enable' ]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def is_disable?
|
|
28
|
+
@parent.target("Service #{@param} is disable?")
|
|
29
|
+
@parent.run "systemctl status #{@param}"
|
|
30
|
+
@parent.expect_one ['Loaded:', 'disable' ]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
class User
|
|
3
|
+
attr_accessor :param
|
|
4
|
+
|
|
5
|
+
def initialize(parent)
|
|
6
|
+
@parent = parent
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def exists?
|
|
10
|
+
@parent.target("User #{@param} exists?")
|
|
11
|
+
@parent.run "id #{@param}"
|
|
12
|
+
@parent.expect_one @param
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def is_member_of?(groupname)
|
|
16
|
+
@parent.target("User #{@param} is member of #{groupname}?")
|
|
17
|
+
@parent.run "id #{@param}"
|
|
18
|
+
@parent.expect_one [@param, groupname]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../application'
|
|
4
|
+
require_relative '../../report/report'
|
|
5
|
+
require_relative '../utils'
|
|
6
|
+
require_relative 'main'
|
|
7
|
+
require_relative 'result/result'
|
|
8
|
+
require_relative 'builtin/main'
|
|
9
|
+
|
|
10
|
+
# TODO: split Case class into several classes:
|
|
11
|
+
# * Case, Action?, Session?, RunCommand class
|
|
12
|
+
|
|
13
|
+
# Case class
|
|
14
|
+
# * initialize
|
|
15
|
+
# * export
|
|
16
|
+
# * filename
|
|
17
|
+
# * grade
|
|
18
|
+
# * members
|
|
19
|
+
# * skip
|
|
20
|
+
# * show
|
|
21
|
+
# * read_filename ???
|
|
22
|
+
class Case
|
|
23
|
+
include DSL
|
|
24
|
+
include Utils
|
|
25
|
+
|
|
26
|
+
attr_accessor :result
|
|
27
|
+
attr_accessor :action # TODO: why not reader only???
|
|
28
|
+
attr_reader :id, :config, :uniques, :conn_status
|
|
29
|
+
@@id = 1
|
|
30
|
+
|
|
31
|
+
def initialize(config)
|
|
32
|
+
app = Application.instance
|
|
33
|
+
@config = Case::Config.new(local: config, global: app.global)
|
|
34
|
+
@groups = app.groups
|
|
35
|
+
|
|
36
|
+
@id = @@id
|
|
37
|
+
@@id += 1
|
|
38
|
+
|
|
39
|
+
# Define Case Report
|
|
40
|
+
@report = Report.new(@id)
|
|
41
|
+
@report.output_dir = File.join('var', @config.global[:tt_testname])
|
|
42
|
+
ensure_dir @report.output_dir
|
|
43
|
+
|
|
44
|
+
# Default configuration
|
|
45
|
+
@skip = false
|
|
46
|
+
@skip = get(:tt_skip) unless get(:tt_skip) == 'NODATA'
|
|
47
|
+
unless app.options['case'].nil?
|
|
48
|
+
@skip = true
|
|
49
|
+
@skip = false if app.options['case'].include? @id
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
@conn_status = {}
|
|
53
|
+
@tmpdir = File.join('var', @config.get(:tt_testname), 'tmp', @id.to_s)
|
|
54
|
+
# ensure_dir @tmpdir # REVISE: When we will need this? Samba?
|
|
55
|
+
@remote_tmpdir = File.join('/', 'tmp')
|
|
56
|
+
|
|
57
|
+
@unique_values = {}
|
|
58
|
+
@result = Result.new
|
|
59
|
+
|
|
60
|
+
@debug = Application.instance.debug
|
|
61
|
+
@verbose = Application.instance.verbose
|
|
62
|
+
|
|
63
|
+
@action_counter = 0
|
|
64
|
+
@action = { id: 0,
|
|
65
|
+
weight: 1.0,
|
|
66
|
+
description: 'No description!',
|
|
67
|
+
groupname: nil }
|
|
68
|
+
@uniques = []
|
|
69
|
+
@sessions = {} # Store opened sessions for this case
|
|
70
|
+
tempfile :default
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def export(format)
|
|
74
|
+
return if skip?
|
|
75
|
+
@report.export format
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def filename
|
|
79
|
+
@report.filename #+ '.' + @report.format.to_s
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def grade
|
|
83
|
+
return 0.0 if skip
|
|
84
|
+
@report.tail[:grade]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def members
|
|
88
|
+
return '-' if skip
|
|
89
|
+
@report.head[:tt_members] || 'noname'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def skip
|
|
93
|
+
@skip
|
|
94
|
+
end
|
|
95
|
+
alias skip? skip
|
|
96
|
+
|
|
97
|
+
def show
|
|
98
|
+
@report.show
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def read_filename(filename)
|
|
104
|
+
begin
|
|
105
|
+
file = File.open(filename, 'r')
|
|
106
|
+
item = file.readlines
|
|
107
|
+
file.close
|
|
108
|
+
item.map! { |i| i.sub(/\n/, '') }
|
|
109
|
+
return item
|
|
110
|
+
rescue StandardError
|
|
111
|
+
return []
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Class Case#close
|
|
4
|
+
class Case
|
|
5
|
+
def close(uniques)
|
|
6
|
+
fails = 0
|
|
7
|
+
@uniques.each do |key|
|
|
8
|
+
next unless uniques[key].include?(id) && uniques[key].count > 1
|
|
9
|
+
|
|
10
|
+
fails += 1
|
|
11
|
+
log_unique_message(key, uniques[key])
|
|
12
|
+
end
|
|
13
|
+
@report.tail[:unique_fault] = fails
|
|
14
|
+
@report.close
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def log_unique_message(key, value)
|
|
20
|
+
log('UNIQUE:', :error)
|
|
21
|
+
begin
|
|
22
|
+
log(" ├── Value => #{key}", :error)
|
|
23
|
+
log(" └── Conflicts => #{value}", :error)
|
|
24
|
+
rescue StandardError => e
|
|
25
|
+
log(key, :error)
|
|
26
|
+
log(e.to_s, :error)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../application'
|
|
4
|
+
|
|
5
|
+
# Class Case::Config
|
|
6
|
+
# * get
|
|
7
|
+
# * set
|
|
8
|
+
# * unset
|
|
9
|
+
# * missing_method
|
|
10
|
+
class Case
|
|
11
|
+
# This class manage configuration for only one case
|
|
12
|
+
class Config
|
|
13
|
+
attr_reader :ialias, :global, :local, :running
|
|
14
|
+
|
|
15
|
+
def initialize(args)
|
|
16
|
+
@ialias = args[:alias] || Application.instance.ialias.clone
|
|
17
|
+
@global = args[:global] || Application.instance.global.clone
|
|
18
|
+
@local = args[:local] || {}
|
|
19
|
+
@running = {}
|
|
20
|
+
|
|
21
|
+
# Set defaults values
|
|
22
|
+
@local[:tt_skip] = @local[:tt_skip] || false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Read param Option from [running, config or global] Hash data
|
|
26
|
+
def get(option, level = 0)
|
|
27
|
+
return 'NODATA' if level > 3
|
|
28
|
+
|
|
29
|
+
return @running[option] if @running[option]
|
|
30
|
+
|
|
31
|
+
return @local[option] if @local[option]
|
|
32
|
+
|
|
33
|
+
return @global[option] if @global[option]
|
|
34
|
+
|
|
35
|
+
search_alias option, level + 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def set(key, value)
|
|
39
|
+
@running[key] = value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def unset(key)
|
|
43
|
+
@running.delete(key)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def search_alias(key, level)
|
|
49
|
+
return search_array_alias(@ialias[key],level) if @ialias[key].class == Array
|
|
50
|
+
|
|
51
|
+
return get(@ialias[key]) if [Integer, String, Symbol].include? @ialias[key].class
|
|
52
|
+
|
|
53
|
+
words = key.to_s.split('_')
|
|
54
|
+
return 'NODATA' if words.size < 2
|
|
55
|
+
|
|
56
|
+
return 'NODATA' unless %w[ip hostname username password].include? words[1]
|
|
57
|
+
|
|
58
|
+
key2 = @ialias[words[0].to_sym]
|
|
59
|
+
return 'NODATA' unless key2
|
|
60
|
+
|
|
61
|
+
get("#{key2}_#{words[1]}".to_sym, level)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def search_array_alias(keys,level)
|
|
65
|
+
values = []
|
|
66
|
+
keys.each do |k|
|
|
67
|
+
if k.class == Symbol
|
|
68
|
+
values << get(k, level + 1)
|
|
69
|
+
else
|
|
70
|
+
values << k
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
values.join('')
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative '../../../application'
|
|
3
|
+
|
|
4
|
+
# DSL#call
|
|
5
|
+
module DSL
|
|
6
|
+
def check(name, input = {})
|
|
7
|
+
checks = Application.instance.checks
|
|
8
|
+
unless checks[name]
|
|
9
|
+
log("Check #{name} not found!", :error)
|
|
10
|
+
return
|
|
11
|
+
end
|
|
12
|
+
input.each_pair { |k, v| set(k, v) }
|
|
13
|
+
errors = []
|
|
14
|
+
checks[name][:args].each do |i|
|
|
15
|
+
errors << i if get(i) == 'NODATA'
|
|
16
|
+
end
|
|
17
|
+
if errors.count > 0
|
|
18
|
+
log("Check #{name} => required params #{errors.join(',')}",:error)
|
|
19
|
+
else
|
|
20
|
+
instance_eval(&checks[name][:block])
|
|
21
|
+
end
|
|
22
|
+
input.each_pair { |k, v| unset(k) }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DSL#request, DSL#target2
|
|
4
|
+
module DSL
|
|
5
|
+
def request(text)
|
|
6
|
+
raise "Deprecated request #{text}"
|
|
7
|
+
# do nothing by now
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def command(p_command, args = {})
|
|
11
|
+
@action[:command] = p_command
|
|
12
|
+
tempfile(args[:tempfile]) if args[:tempfile]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DSL module:
|
|
4
|
+
# * expect_none
|
|
5
|
+
# * expect_one
|
|
6
|
+
# * expect_any
|
|
7
|
+
# * expect
|
|
8
|
+
# * expect2
|
|
9
|
+
# * weight
|
|
10
|
+
module DSL
|
|
11
|
+
def expect_none(input)
|
|
12
|
+
if input.class == Array
|
|
13
|
+
input.each { |i| result.find(i) }
|
|
14
|
+
else
|
|
15
|
+
result.find(input)
|
|
16
|
+
end
|
|
17
|
+
expect2 result.count.eq(0)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def expect_one(input)
|
|
21
|
+
if input.class == Array
|
|
22
|
+
input.each { |i| result.find(i) }
|
|
23
|
+
else
|
|
24
|
+
result.find(input)
|
|
25
|
+
end
|
|
26
|
+
expect2 result.count.eq(1)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def expect_any(input)
|
|
30
|
+
if input.class == Array
|
|
31
|
+
input.each { |i| result.find(i) }
|
|
32
|
+
else
|
|
33
|
+
result.find(input)
|
|
34
|
+
end
|
|
35
|
+
expect2 result.count.gt(0)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# expect <condition>, :weight => <value>
|
|
39
|
+
def expect(input, args = {})
|
|
40
|
+
if input.class == TrueClass || input.class == FalseClass
|
|
41
|
+
expect2(input, args)
|
|
42
|
+
elsif input.class == String || input.class == Regexp || input.class == Array
|
|
43
|
+
expect_any input
|
|
44
|
+
else
|
|
45
|
+
puts "[ERROR] expect #{input} (#{input.class})"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def expect2(cond, args = {})
|
|
50
|
+
@action_counter += 1
|
|
51
|
+
@action[:id] = @action_counter
|
|
52
|
+
@action[:check] = cond
|
|
53
|
+
@action[:result] = @result.value
|
|
54
|
+
|
|
55
|
+
@action[:alterations] = @result.alterations
|
|
56
|
+
@action[:expected] = @result.expected
|
|
57
|
+
@action[:expected] = args[:expected] if args[:expected]
|
|
58
|
+
|
|
59
|
+
@report.lines << @action.clone
|
|
60
|
+
weight(1.0)
|
|
61
|
+
|
|
62
|
+
app = Application.instance
|
|
63
|
+
c = app.letter[:bad]
|
|
64
|
+
c = app.letter[:good] if cond
|
|
65
|
+
verbose c
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Set weight value for the action
|
|
69
|
+
def weight(value = nil)
|
|
70
|
+
if value.nil?
|
|
71
|
+
@action[:weight]
|
|
72
|
+
elsif value == :default
|
|
73
|
+
@action[:weight] = 1.0
|
|
74
|
+
else
|
|
75
|
+
@action[:weight] = value.to_f
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DSL#get and DSL#set
|
|
4
|
+
module DSL
|
|
5
|
+
# Read param option from [running, config or global] Hash data
|
|
6
|
+
def get(option)
|
|
7
|
+
@config.get(option)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def gett(option)
|
|
11
|
+
value = get(option)
|
|
12
|
+
"#{value} (#{option})"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def set(key, value)
|
|
16
|
+
@config.set(key, value)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def unset(key)
|
|
20
|
+
@config.unset(key)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../runner'
|
|
4
|
+
|
|
5
|
+
# Case->DSL#goto
|
|
6
|
+
module DSL
|
|
7
|
+
# Run command from the host identify as pHostname
|
|
8
|
+
# goto :host1, :execute => "command"
|
|
9
|
+
def goto(host = :localhost, args = {})
|
|
10
|
+
@result.reset
|
|
11
|
+
@action[:command] = args[:execute] if args[:execute]
|
|
12
|
+
@action[:command] = args[:exec] if args[:exec]
|
|
13
|
+
tempfile(args[:tempfile]) if args[:tempfile]
|
|
14
|
+
@action[:encoding] = args[:encoding] || 'UTF-8'
|
|
15
|
+
|
|
16
|
+
protocol = @config.get("#{host}_protocol".to_sym)
|
|
17
|
+
ip = @config.get("#{host}_ip".to_sym)
|
|
18
|
+
start_time = Time.now
|
|
19
|
+
if (protocol == 'NODATA' || protocol.nil?) &&
|
|
20
|
+
(host.to_s == 'localhost' || host.to_s.include?('127.0.0.') || ip.include?('127.0.0.'))
|
|
21
|
+
run_local_cmd
|
|
22
|
+
elsif ip == 'NODATA'
|
|
23
|
+
log("#{host} IP not found!", :error)
|
|
24
|
+
else
|
|
25
|
+
run_remote_cmd host
|
|
26
|
+
end
|
|
27
|
+
@action[:duration] = (Time.now - start_time).round(3)
|
|
28
|
+
end
|
|
29
|
+
alias on goto
|
|
30
|
+
|
|
31
|
+
def run(command, args = {})
|
|
32
|
+
args[:exec] = command.to_s
|
|
33
|
+
goto(:localhost, args)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DSL#log
|
|
4
|
+
module DSL
|
|
5
|
+
def log(text = '', type = :info)
|
|
6
|
+
s = ''
|
|
7
|
+
s = Rainbow('WARN!').color(:yellow) if type == :warn
|
|
8
|
+
s = Rainbow('ERROR').bg(:red) if type == :error
|
|
9
|
+
t = Time.now
|
|
10
|
+
f = format('%02d:%02d:%02d', t.hour, t.min, t.sec)
|
|
11
|
+
@report.lines << "[#{f}] #{s}: #{text}"
|
|
12
|
+
end
|
|
13
|
+
alias msg log
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'check'
|
|
4
|
+
require_relative 'expect'
|
|
5
|
+
require_relative 'getset'
|
|
6
|
+
require_relative 'goto'
|
|
7
|
+
require_relative 'log'
|
|
8
|
+
require_relative 'missing'
|
|
9
|
+
require_relative 'send'
|
|
10
|
+
require_relative 'target'
|
|
11
|
+
require_relative 'unique'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DSL#missing_method
|
|
4
|
+
module DSL
|
|
5
|
+
# If a method call is missing, then delegate to concept parent.
|
|
6
|
+
def method_missing(method, args = {})
|
|
7
|
+
a = method.to_s
|
|
8
|
+
return instance_eval("get(:#{a[0, a.size - 1]})") if a[a.size - 1] == '?'
|
|
9
|
+
return check a[6, a.size], args if a[0,6]=='check_'
|
|
10
|
+
check a, args
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Case->DSL#
|
|
4
|
+
# * send
|
|
5
|
+
# * tempfile
|
|
6
|
+
# * tempdir
|
|
7
|
+
# * remote_tempdir
|
|
8
|
+
# * remote_tempfile
|
|
9
|
+
module DSL
|
|
10
|
+
def send(args = {})
|
|
11
|
+
return if skip?
|
|
12
|
+
|
|
13
|
+
return unless args[:copy_to]
|
|
14
|
+
|
|
15
|
+
host = args[:copy_to].to_s
|
|
16
|
+
return unless @conn_status[host].nil?
|
|
17
|
+
|
|
18
|
+
ip = get((host + '_ip').to_sym)
|
|
19
|
+
username = get((host + '_username').to_sym).to_s
|
|
20
|
+
password = get((host + '_password').to_sym).to_s
|
|
21
|
+
|
|
22
|
+
filename = @report.filename + '.' + @report.format.to_s
|
|
23
|
+
localfilepath = File.join(@report.output_dir, filename)
|
|
24
|
+
filename = args[:prefix].to_s + filename if args[:prefix]
|
|
25
|
+
|
|
26
|
+
if args[:remote_dir]
|
|
27
|
+
remotefilepath = File.join(args[:remote_dir], filename)
|
|
28
|
+
else
|
|
29
|
+
# remotefilepath = File.join(remote_tempdir, filename)
|
|
30
|
+
remotefilepath = File.join('.', filename)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Upload a file or directory to the remote host
|
|
34
|
+
begin
|
|
35
|
+
Net::SFTP.start(ip, username, password: password) do |sftp|
|
|
36
|
+
sftp.upload!(localfilepath, remotefilepath)
|
|
37
|
+
end
|
|
38
|
+
verboseln("=> [ OK ] #{(get(:tt_members)[0,15]).ljust(16)} : #{remotefilepath}")
|
|
39
|
+
rescue
|
|
40
|
+
verboseln("=> [ERROR] #{(get(:tt_members)[0,15]).ljust(16)} : scp #{localfilepath} => #{remotefilepath}")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def tempfile(input = nil)
|
|
45
|
+
return @action[:tempfile] if input.nil?
|
|
46
|
+
|
|
47
|
+
name = input
|
|
48
|
+
name = 'teuton.tmp' if input == :default
|
|
49
|
+
|
|
50
|
+
@action[:tempfile] = File.join(@tmpdir, name)
|
|
51
|
+
@action[:remote_tempfile] = File.join(@remote_tmpdir, name)
|
|
52
|
+
|
|
53
|
+
@action[:tempfile]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def tempdir
|
|
57
|
+
# puts '[WARN] Using DSL.tempdir'
|
|
58
|
+
@tmpdir
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def remote_tempfile
|
|
62
|
+
# puts '[WARN] Using DSL.tempfile'
|
|
63
|
+
@action[:remote_tempfile]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def remote_tempdir
|
|
67
|
+
@remote_tmpdir
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DSL#target
|
|
4
|
+
module DSL
|
|
5
|
+
def readme(_text)
|
|
6
|
+
# Usefull for "teuton reamde" action.
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def target(desc, args = {})
|
|
10
|
+
@action[:description] = desc.to_s
|
|
11
|
+
@action[:asset] = args[:asset].to_s if args[:asset]
|
|
12
|
+
w = args[:weight] || 1.0
|
|
13
|
+
weight(w)
|
|
14
|
+
end
|
|
15
|
+
alias goal target
|
|
16
|
+
end
|