teuton 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|