teuton 2.1.11 → 2.2.2
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 +15 -12
- data/bin/check_teuton +0 -2
- data/docs/changelog/ideas.md +132 -0
- data/docs/changelog/v2.1.md +14 -122
- data/docs/changelog/v2.2.md +52 -28
- data/docs/changelog/version2.1.md +4 -0
- data/docs/commands/README.md +58 -15
- data/docs/commands/example_check.md +0 -4
- data/docs/commands/example_run.md +0 -4
- data/docs/dsl/README.md +1 -1
- data/docs/dsl/definition/result.md +1 -0
- data/docs/dsl/definition/run_remote.md +12 -6
- data/docs/dsl/definition/target.md +9 -10
- data/docs/install/README.md +13 -18
- data/docs/install/vagrant_docker.md +1 -1
- data/docs/learn/README.md +8 -8
- data/docs/learn/example-01-target.md +25 -25
- data/docs/learn/example-02-config.md +38 -49
- data/docs/learn/example-03-remote-hosts.md +22 -22
- data/docs/learn/{example-11-first-test.md → example-04-new-test.md} +23 -24
- data/docs/learn/{example-04-use.md → example-05-use.md} +6 -6
- data/docs/learn/{example-05-debug.md → example-06-debug.md} +8 -8
- data/docs/learn/{example-06-log.md → example-07-log.md} +7 -7
- data/docs/learn/{example-07-readme.md → example-08-readme.md} +10 -10
- data/docs/learn/{example-08-preserve.md → example-09-preserve.md} +6 -6
- data/docs/videos.md +19 -0
- data/lib/teuton/application.rb +22 -3
- data/lib/teuton/case_manager/case/dsl/goto.rb +2 -2
- data/lib/teuton/case_manager/case/dsl/macro.rb +1 -0
- data/lib/teuton/case_manager/case/dsl/send.rb +2 -1
- data/lib/teuton/case_manager/case/play.rb +2 -0
- data/lib/teuton/case_manager/case/result/ext_compare.rb +16 -0
- data/lib/teuton/case_manager/case/result/result.rb +1 -1
- data/lib/teuton/case_manager/case/runner.rb +30 -4
- data/lib/teuton/case_manager/case_manager.rb +1 -1
- data/lib/teuton/case_manager/export_manager.rb +21 -11
- data/lib/teuton/case_manager/utils.rb +1 -1
- data/lib/teuton/{project/laboratory → check}/builtin.rb +0 -0
- data/lib/teuton/{project/laboratory → check}/dsl.rb +40 -28
- data/lib/teuton/{project/laboratory → check}/laboratory.rb +3 -8
- data/lib/teuton/{project/laboratory → check}/show.rb +53 -59
- data/lib/teuton/cli.rb +85 -14
- data/lib/teuton/{project/readme → readme}/dsl.rb +0 -0
- data/lib/teuton/{project/readme → readme}/lang.rb +1 -1
- data/lib/teuton/{project/readme → readme}/readme.rb +22 -18
- data/lib/teuton/report/formatter/array_formatter.rb +13 -1
- data/lib/teuton/report/formatter/base_formatter.rb +18 -5
- data/lib/teuton/{project/skeleton.rb → skeleton.rb} +7 -19
- data/lib/teuton/utils/configfile_reader.rb +121 -0
- data/lib/teuton/{project → utils}/name_file_finder.rb +46 -26
- data/lib/teuton/version.rb +8 -0
- data/lib/teuton.rb +39 -32
- metadata +107 -65
- data/lib/teuton/cli/check.rb +0 -38
- data/lib/teuton/cli/main.rb +0 -6
- data/lib/teuton/cli/play.rb +0 -38
- data/lib/teuton/cli/readme.rb +0 -26
- data/lib/teuton/cli/version.rb +0 -12
- data/lib/teuton/files/gitignore +0 -2
- data/lib/teuton/project/configfile_reader.rb +0 -49
- data/lib/teuton/project/project.rb +0 -80
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'terminal-table'
|
2
2
|
require 'rainbow'
|
3
3
|
|
4
|
-
require_relative '
|
5
|
-
require_relative '../configfile_reader'
|
4
|
+
require_relative '../application'
|
5
|
+
require_relative '../utils/configfile_reader'
|
6
6
|
|
7
7
|
# Laboratory
|
8
8
|
# * show_dsl
|
@@ -10,68 +10,23 @@ require_relative '../configfile_reader'
|
|
10
10
|
# * show_config
|
11
11
|
class Laboratory
|
12
12
|
##
|
13
|
-
# Display DSL on screen
|
14
|
-
def
|
13
|
+
# Display DSL checking on screen
|
14
|
+
def show
|
15
15
|
@verbose = true
|
16
16
|
process_content
|
17
17
|
show_stats
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
##
|
22
|
-
# Display stats on screen
|
23
|
-
def show_stats
|
24
|
-
@stats[:hosts] = 0
|
25
|
-
@hosts.each_pair { |_k, v| @stats[:hosts] += v }
|
26
|
-
|
27
|
-
my_screen_table = Terminal::Table.new do |st|
|
28
|
-
st.add_row ['DSL Stats', 'Count']
|
29
|
-
st.add_separator
|
30
|
-
st.add_row ['Groups', @stats[:groups]]
|
31
|
-
st.add_row ['Targets', @stats[:targets]]
|
32
|
-
st.add_row ['Goto', @stats[:hosts]]
|
33
|
-
@hosts.each_pair { |k, v| st.add_row [" * #{k}", v] }
|
34
|
-
st.add_row ['Uniques', @stats[:uniques]]
|
35
|
-
st.add_row ['Logs', @stats[:uniques]]
|
36
|
-
st.add_row [' ', ' ']
|
37
|
-
|
38
|
-
st.add_row ['Gets', @stats[:gets]]
|
39
|
-
if @gets.count > 0
|
40
|
-
list = @gets.sort_by { |_k, v| v }
|
41
|
-
list.reverse_each { |item| st.add_row [" * #{item[0]}", item[1].to_s] }
|
42
|
-
end
|
43
|
-
|
44
|
-
st.add_row ['Sets', @stats[:sets]]
|
45
|
-
if @sets.count > 0
|
46
|
-
@sets.each_pair { |k, v| st.add_row [" * #{k}", v.to_s] }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
verboseln my_screen_table.to_s + "\n"
|
18
|
+
revise_config_content
|
50
19
|
end
|
51
20
|
|
52
21
|
##
|
53
|
-
# Display config on screen
|
54
|
-
def
|
22
|
+
# Display config for teuton panel on screen
|
23
|
+
def show_panelconfig
|
55
24
|
@verbose = false
|
56
25
|
process_content
|
57
26
|
@verbose = true
|
58
|
-
|
27
|
+
recomended_panelconfig_content
|
59
28
|
end
|
60
29
|
|
61
|
-
# def show_requests
|
62
|
-
# @verbose = false
|
63
|
-
# process_content
|
64
|
-
# @verbose = true
|
65
|
-
# my_screen_table = Terminal::Table.new do |st|
|
66
|
-
# st.add_row ['Lines', 'REQUEST description']
|
67
|
-
# st.add_separator
|
68
|
-
# @requests.each_with_index do |line, index|
|
69
|
-
# st.add_row ['%03d' % index, line]
|
70
|
-
# end
|
71
|
-
# end
|
72
|
-
# verboseln my_screen_table
|
73
|
-
# end
|
74
|
-
|
75
30
|
private
|
76
31
|
|
77
32
|
def verbose(text)
|
@@ -84,14 +39,16 @@ class Laboratory
|
|
84
39
|
|
85
40
|
def process_content
|
86
41
|
groups = Application.instance.groups
|
42
|
+
option = Application.instance.options
|
43
|
+
|
87
44
|
verboseln ''
|
88
45
|
groups.each do |t|
|
89
46
|
@stats[:groups] += 1
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
47
|
+
unless option[:panel]
|
48
|
+
msg = "GROUP: #{t[:name]}"
|
49
|
+
my_screen_table = Terminal::Table.new { |st| st.add_row [msg] }
|
50
|
+
verboseln my_screen_table
|
51
|
+
end
|
95
52
|
instance_eval(&t[:block])
|
96
53
|
end
|
97
54
|
end
|
@@ -127,10 +84,16 @@ class Laboratory
|
|
127
84
|
verboseln YAML.dump(output)
|
128
85
|
end
|
129
86
|
|
87
|
+
def recomended_panelconfig_content
|
88
|
+
output = { global: {}, cases: nil }
|
89
|
+
script_vars = find_script_vars
|
90
|
+
script_vars.each { |i| output[:global][i] = 'VALUE' }
|
91
|
+
verboseln YAML.dump(output)
|
92
|
+
end
|
93
|
+
|
130
94
|
##
|
131
95
|
# Revive and check config content
|
132
96
|
def revise_config_content
|
133
|
-
@verbose = true
|
134
97
|
my_screen_table = Terminal::Table.new do |st|
|
135
98
|
st.add_row ['Revising CONFIG file']
|
136
99
|
end
|
@@ -166,4 +129,35 @@ class Laboratory
|
|
166
129
|
end
|
167
130
|
end
|
168
131
|
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Display stats on screen
|
135
|
+
def show_stats
|
136
|
+
@stats[:hosts] = 0
|
137
|
+
@hosts.each_pair { |_k, v| @stats[:hosts] += v }
|
138
|
+
|
139
|
+
my_screen_table = Terminal::Table.new do |st|
|
140
|
+
st.add_row ['DSL Stats', 'Count']
|
141
|
+
st.add_separator
|
142
|
+
st.add_row ['Groups', @stats[:groups]]
|
143
|
+
st.add_row ['Targets', @stats[:targets]]
|
144
|
+
st.add_row ['Goto', @stats[:hosts]]
|
145
|
+
@hosts.each_pair { |k, v| st.add_row [" * #{k}", v] }
|
146
|
+
st.add_row ['Uniques', @stats[:uniques]]
|
147
|
+
st.add_row ['Logs', @stats[:uniques]]
|
148
|
+
st.add_row [' ', ' ']
|
149
|
+
|
150
|
+
st.add_row ['Gets', @stats[:gets]]
|
151
|
+
if @gets.count > 0
|
152
|
+
list = @gets.sort_by { |_k, v| v }
|
153
|
+
list.reverse_each { |item| st.add_row [" * #{item[0]}", item[1].to_s] }
|
154
|
+
end
|
155
|
+
|
156
|
+
st.add_row ['Sets', @stats[:sets]]
|
157
|
+
if @sets.count > 0
|
158
|
+
@sets.each_pair { |k, v| st.add_row [" * #{k}", v.to_s] }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
verboseln my_screen_table.to_s + "\n"
|
162
|
+
end
|
169
163
|
end
|
data/lib/teuton/cli.rb
CHANGED
@@ -1,39 +1,110 @@
|
|
1
|
+
|
1
2
|
require 'thor'
|
2
|
-
require_relative '
|
3
|
-
require_relative '
|
4
|
-
require_relative 'project/skeleton.rb'
|
5
|
-
require_relative 'cli/main'
|
3
|
+
require_relative 'version'
|
4
|
+
require_relative '../teuton'
|
6
5
|
|
7
|
-
##
|
8
|
-
# Command Line User Interface
|
9
6
|
class CLI < Thor
|
10
7
|
map ['h', '-h', '--help'] => 'help'
|
11
8
|
|
12
|
-
map ['
|
9
|
+
map ['v', '-v', '--version'] => 'version'
|
10
|
+
desc 'version', 'Show the program version'
|
11
|
+
def version
|
12
|
+
puts "#{Teuton::APPNAME} (version #{Teuton::VERSION})"
|
13
|
+
end
|
14
|
+
|
15
|
+
map ['n', '-n', '--new'] => 'new'
|
13
16
|
desc 'new DIRECTORY', 'Create skeleton for a new project'
|
14
17
|
long_desc <<-LONGDESC
|
15
18
|
Create files for a new project.
|
19
|
+
LONGDESC
|
20
|
+
def new(projectpath)
|
21
|
+
Teuton.create(projectpath)
|
22
|
+
end
|
23
|
+
|
24
|
+
map ['c', '-c', '--check'] => 'check'
|
25
|
+
option :panelconfig, type: :boolean
|
26
|
+
option :cname, type: :string
|
27
|
+
option :cpath, type: :string
|
28
|
+
desc 'check [OPTIONS] DIRECTORY',
|
29
|
+
'Check test and config file content'
|
30
|
+
long_desc <<-LONGDESC
|
31
|
+
|
32
|
+
(1) teuton check path/to/dir/foo
|
33
|
+
, Check content of start.rb and config.yaml files.
|
16
34
|
|
17
|
-
|
35
|
+
(2) teuton check path/to/dir/foo --cname=demo
|
36
|
+
, Check content of start.rb and demo.yaml files.
|
37
|
+
|
38
|
+
(3) teuton check path/to/file/foo.rb
|
39
|
+
, Check content of foo.rb and foo.yaml files.
|
40
|
+
|
41
|
+
(4) teuton check path/to/file/foo.rb --cname=demo
|
42
|
+
, Check content of foo.rb and demo.yaml files.
|
18
43
|
|
19
|
-
#{$PROGRAM_NAME} create dir/foo
|
20
44
|
LONGDESC
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
45
|
+
def check(projectpath)
|
46
|
+
Teuton.check(projectpath, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
map ['--run', 'run'] => 'play'
|
50
|
+
option :export, type: :string
|
51
|
+
option :cname, type: :string
|
52
|
+
option :cpath, type: :string
|
53
|
+
option :case, type: :string
|
54
|
+
option :color, type: :boolean
|
55
|
+
option :quiet, type: :boolean
|
56
|
+
desc '[run] [OPTIONS] DIRECTORY',
|
57
|
+
'Run test from directory'
|
58
|
+
long_desc <<-LONGDESC
|
59
|
+
This function execute challenge from specified directory.
|
60
|
+
By default, show progress on the screen.
|
61
|
+
|
62
|
+
Let's see others options:
|
63
|
+
|
64
|
+
(1) teuton foo, run challenge from foo/start.rb with foo/config.yaml config file.
|
65
|
+
|
66
|
+
(2) teuton run foo, same as (1).
|
67
|
+
|
68
|
+
(3) teuton run --export=json foo, run challenge and export using json format.
|
69
|
+
Others output formats availables are: txt, html, yaml, json and colored_text.
|
70
|
+
|
71
|
+
(4) teuton run --cname=demo foo, run challenge from foo/start.rb with foo/demo.yaml config file.
|
72
|
+
|
73
|
+
(5) teuton foo/demo.rb, Run challenge from foo/demo.rb with foo/demo.yaml config file.
|
74
|
+
|
75
|
+
LONGDESC
|
76
|
+
def play(filepath)
|
77
|
+
Teuton.run(filepath, options)
|
78
|
+
end
|
79
|
+
|
80
|
+
map ['--readme'] => 'readme'
|
81
|
+
option :lang, type: :string
|
82
|
+
desc 'readme DIRECTORY',
|
83
|
+
'Show README extracted from test contents'
|
84
|
+
long_desc <<-LONGDESC
|
85
|
+
|
86
|
+
(1) teuton readme foo
|
87
|
+
, Create README.md from foo/start.rb.
|
88
|
+
|
89
|
+
(2) teuton readme foo/demo.rb
|
90
|
+
, Create README.md from foo/demo.rb.
|
91
|
+
LONGDESC
|
92
|
+
|
93
|
+
def readme(projectpath)
|
94
|
+
# Create README from teuton test
|
95
|
+
Teuton.readme(projectpath, options)
|
25
96
|
end
|
26
97
|
|
27
98
|
##
|
28
99
|
# These inputs are equivalents:
|
29
100
|
# * teuton dir/foo
|
30
101
|
# * teuton run dir/foo
|
31
|
-
# * teuton play dir/foo
|
32
102
|
def method_missing(method, *_args, &_block)
|
33
103
|
play(method.to_s)
|
34
104
|
end
|
35
105
|
|
36
106
|
def respond_to_missing?(method_name, include_private = false)
|
107
|
+
# Respond to missing methods name
|
37
108
|
super
|
38
109
|
end
|
39
110
|
end
|
File without changes
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative '../configfile_reader'
|
5
|
-
require_relative '
|
3
|
+
require_relative '../application'
|
4
|
+
require_relative '../utils/configfile_reader'
|
5
|
+
require_relative '../case_manager/case/result/result'
|
6
6
|
require_relative 'dsl'
|
7
7
|
require_relative 'lang'
|
8
8
|
|
@@ -44,6 +44,19 @@ class Readme
|
|
44
44
|
reset
|
45
45
|
end
|
46
46
|
|
47
|
+
##
|
48
|
+
# Show README on screen
|
49
|
+
def show
|
50
|
+
process_content
|
51
|
+
show_head
|
52
|
+
show_content
|
53
|
+
show_tail
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
##
|
59
|
+
# Reset attributes
|
47
60
|
def reset
|
48
61
|
app = Application.instance
|
49
62
|
@config = ConfigFileReader.read(app.config_path)
|
@@ -73,13 +86,6 @@ class Readme
|
|
73
86
|
@action = { readme: [] }
|
74
87
|
end
|
75
88
|
|
76
|
-
def show
|
77
|
-
process_content
|
78
|
-
show_head
|
79
|
-
show_content
|
80
|
-
show_tail
|
81
|
-
end
|
82
|
-
|
83
89
|
##
|
84
90
|
# Show README head
|
85
91
|
def show_head
|
@@ -97,23 +103,21 @@ class Readme
|
|
97
103
|
puts Lang::get(:hosts)
|
98
104
|
puts "\n"
|
99
105
|
puts '| ID | Host | Configuration |'
|
100
|
-
puts '|
|
106
|
+
puts '| --- | --- | --- |'
|
101
107
|
@required_hosts.each_pair do |k, v|
|
102
108
|
c = []
|
103
109
|
v.each_pair { |k2,v2| c << "#{k2}=#{v2}" }
|
104
|
-
puts "
|
110
|
+
puts "| #{i} | #{k.upcase} | #{c.join(', ')} |"
|
105
111
|
i += 1
|
106
112
|
end
|
107
113
|
puts "\n> NOTE: SSH Service installation is required on every host."
|
108
114
|
end
|
109
115
|
|
110
116
|
unless @cases_params.empty?
|
111
|
-
@cases_params.
|
117
|
+
@cases_params.sort!
|
112
118
|
puts Lang::get(:params)
|
113
119
|
@cases_params.uniq.each { |i| puts format('* %s', i) }
|
114
|
-
puts "\n> NOTE:"
|
115
|
-
puts "> * Teuton software must known this information!"
|
116
|
-
puts "> * Save every ':param: value' into config file."
|
120
|
+
puts "\n> NOTE: Save every ':param: value' into config file."
|
117
121
|
end
|
118
122
|
end
|
119
123
|
|
@@ -156,13 +160,13 @@ class Readme
|
|
156
160
|
puts Lang::get(:global)
|
157
161
|
puts "\n"
|
158
162
|
puts '| Global param | Value |'
|
159
|
-
puts '|
|
163
|
+
puts '| --- | --- |'
|
160
164
|
@global_params.each_pair { |k,v| puts "|#{k}|#{v}|" }
|
161
165
|
puts "\n\#\# Created params"
|
162
166
|
puts Lang::get(:created)
|
163
167
|
puts "\n"
|
164
168
|
puts '| Created params | Value |'
|
165
|
-
puts '|
|
169
|
+
puts '| --- | --- |'
|
166
170
|
@setted_params.each_pair { |k,v| puts "|#{k}|#{v}|" }
|
167
171
|
end
|
168
172
|
end
|
@@ -2,13 +2,19 @@
|
|
2
2
|
|
3
3
|
require_relative 'base_formatter'
|
4
4
|
|
5
|
+
##
|
5
6
|
# ArrayFormatter class: format report data into an array
|
6
7
|
class ArrayFormatter < BaseFormatter
|
8
|
+
##
|
9
|
+
# Initialize class
|
10
|
+
# @param report (Report) Format report data into Array
|
7
11
|
def initialize(report)
|
8
12
|
super(report)
|
9
13
|
@data = {}
|
10
14
|
end
|
11
15
|
|
16
|
+
##
|
17
|
+
# Execute format action
|
12
18
|
def process
|
13
19
|
build_data
|
14
20
|
w @data.to_s # Write data into ouput file
|
@@ -28,6 +34,8 @@ class ArrayFormatter < BaseFormatter
|
|
28
34
|
@data[:config] = head
|
29
35
|
end
|
30
36
|
|
37
|
+
# rubocop:disable Metrics/AbcSize
|
38
|
+
# rubocop:disable Metrics/MethodLength
|
31
39
|
def build_history_data
|
32
40
|
@data[:logs] = []
|
33
41
|
groups = []
|
@@ -46,7 +54,8 @@ class ArrayFormatter < BaseFormatter
|
|
46
54
|
end
|
47
55
|
|
48
56
|
target = {}
|
49
|
-
target[:target_id] = format('%02d', i[:id])
|
57
|
+
# target[:target_id] = format('%02d', i[:id])
|
58
|
+
target[:target_id] = format('%<id>02d', id: i[:id])
|
50
59
|
target[:check] = i[:check]
|
51
60
|
target[:score] = value
|
52
61
|
target[:weight] = i[:weight]
|
@@ -66,6 +75,8 @@ class ArrayFormatter < BaseFormatter
|
|
66
75
|
groups << { title: title, targets: targets } unless title.nil?
|
67
76
|
@data[:groups] = groups
|
68
77
|
end
|
78
|
+
# rubocop:enable Metrics/AbcSize
|
79
|
+
# rubocop:enable Metrics/MethodLength
|
69
80
|
|
70
81
|
def build_final_data
|
71
82
|
tail = {}
|
@@ -77,6 +88,7 @@ class ArrayFormatter < BaseFormatter
|
|
77
88
|
app = Application.instance
|
78
89
|
@data[:hall_of_fame] = {}
|
79
90
|
return if app.options[:case_number] < 3
|
91
|
+
|
80
92
|
fame = {}
|
81
93
|
app.hall_of_fame.each { |line| fame[line[0]] = line[1] }
|
82
94
|
@data[:hall_of_fame] = fame
|
@@ -2,25 +2,38 @@
|
|
2
2
|
|
3
3
|
# BaseFormatter class
|
4
4
|
class BaseFormatter
|
5
|
+
##
|
6
|
+
# Initialize class
|
7
|
+
# @param report (Report) Format report data
|
5
8
|
def initialize(report)
|
6
9
|
@head = report.head
|
7
10
|
@lines = report.lines
|
8
11
|
@tail = report.tail
|
9
12
|
end
|
10
13
|
|
14
|
+
##
|
15
|
+
# Execute format action
|
16
|
+
def process
|
17
|
+
raise 'Empty method!'
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates new output file
|
22
|
+
# @param filename (String) Path to output file
|
11
23
|
def init(filename)
|
12
24
|
@filename = filename
|
13
25
|
@file = File.open(@filename, 'w')
|
14
26
|
end
|
15
27
|
|
28
|
+
##
|
29
|
+
# Write data into output file
|
30
|
+
# @param text (String) Text data to write into output file
|
16
31
|
def w(text)
|
17
|
-
@file.write text.to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
def process
|
21
|
-
raise 'Empty method!'
|
32
|
+
@file.write text.to_s
|
22
33
|
end
|
23
34
|
|
35
|
+
##
|
36
|
+
# Close open output file
|
24
37
|
def deinit
|
25
38
|
@file.close
|
26
39
|
end
|
@@ -3,13 +3,7 @@
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'rainbow'
|
5
5
|
|
6
|
-
# Skeleton
|
7
|
-
# * create
|
8
|
-
# * create_main_dir_and_files
|
9
|
-
# * create_assets_dir_and_files
|
10
|
-
# * create_dir
|
11
|
-
# * create_dirs
|
12
|
-
# * copyfile
|
6
|
+
# Skeleton module
|
13
7
|
module Skeleton
|
14
8
|
##
|
15
9
|
# Create teuton project skeleton
|
@@ -17,7 +11,7 @@ module Skeleton
|
|
17
11
|
def self.create(project_dir)
|
18
12
|
project_name = File.basename(project_dir)
|
19
13
|
puts "\n[INFO] Creating #{Rainbow(project_name).bright} project skeleton"
|
20
|
-
source_basedir = File.
|
14
|
+
source_basedir = File.dirname(__FILE__)
|
21
15
|
create_dir project_dir
|
22
16
|
create_main_dir_and_files(project_dir, source_basedir)
|
23
17
|
end
|
@@ -26,12 +20,11 @@ module Skeleton
|
|
26
20
|
# Create main dir and files
|
27
21
|
# @param project_dir (String)
|
28
22
|
# @param source_basedir (String)
|
29
|
-
def self.create_main_dir_and_files(project_dir, source_basedir)
|
23
|
+
private_class_method def self.create_main_dir_and_files(project_dir, source_basedir)
|
30
24
|
# Directory and files: Ruby script, Configfile, gitignore
|
31
25
|
items = [
|
32
26
|
{ source: 'files/config.yaml', target: 'config.yaml' },
|
33
27
|
{ source: 'files/start.rb', target: 'start.rb' }
|
34
|
-
# { source: 'files/gitignore', target: '.gitignore' }
|
35
28
|
]
|
36
29
|
items.each do |item|
|
37
30
|
source = File.join(source_basedir, item[:source])
|
@@ -43,7 +36,7 @@ module Skeleton
|
|
43
36
|
##
|
44
37
|
# Create dir
|
45
38
|
# @param dirpath (String)
|
46
|
-
def self.create_dir(dirpath)
|
39
|
+
private_class_method def self.create_dir(dirpath)
|
47
40
|
if Dir.exist? dirpath
|
48
41
|
puts "* Exists dir! => #{Rainbow(dirpath).yellow}"
|
49
42
|
else
|
@@ -56,18 +49,12 @@ module Skeleton
|
|
56
49
|
end
|
57
50
|
end
|
58
51
|
|
59
|
-
##
|
60
|
-
# Create dirs
|
61
|
-
# @param args (Array)
|
62
|
-
def self.create_dirs(*args)
|
63
|
-
args.each { |arg| create_dir arg }
|
64
|
-
end
|
65
|
-
|
66
52
|
##
|
67
53
|
# Copy file
|
68
54
|
# @param source (String) Source file
|
69
55
|
# @param dest (String) Dest file
|
70
|
-
|
56
|
+
# rubocop:disable Metrics/MethodLength
|
57
|
+
private_class_method def self.copyfile(source, dest)
|
71
58
|
if File.exist? dest
|
72
59
|
puts "* Exists file! => #{Rainbow(dest).yellow}"
|
73
60
|
else
|
@@ -80,4 +67,5 @@ module Skeleton
|
|
80
67
|
end
|
81
68
|
end
|
82
69
|
end
|
70
|
+
# rubocop:enable Metrics/MethodLength
|
83
71
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'json/pure'
|
5
|
+
|
6
|
+
##
|
7
|
+
# Functions that read data from ConfigFile using YAML or JSON formats
|
8
|
+
module ConfigFileReader
|
9
|
+
##
|
10
|
+
# Read config file
|
11
|
+
# @param filepath (String) Path to config file
|
12
|
+
# @return Hash with config data
|
13
|
+
def self.read(filepath)
|
14
|
+
unless File.exist?(filepath)
|
15
|
+
data = {}
|
16
|
+
data[:global] = {}
|
17
|
+
data[:alias] = {}
|
18
|
+
data[:cases] = [{ tt_members: 'anonymous' }]
|
19
|
+
return data
|
20
|
+
end
|
21
|
+
return read_yaml(filepath) if File.extname(filepath) == '.yaml'
|
22
|
+
|
23
|
+
return read_json(filepath) if File.extname(filepath) == '.json'
|
24
|
+
|
25
|
+
raise "[ERROR] ConfigFileReader: #{filepath}"
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Read YAML config file
|
30
|
+
# @param filepath (String) Path to YAML config file
|
31
|
+
# @return Hash with config data
|
32
|
+
# rubocop:disable Metrics/MethodLength
|
33
|
+
# rubocop:disable Metrics/AbcSize
|
34
|
+
# rubocop:disable Security/YAMLLoad
|
35
|
+
def self.read_yaml(filepath)
|
36
|
+
begin
|
37
|
+
data = YAML.load(File.open(filepath))
|
38
|
+
rescue StandardError => e
|
39
|
+
puts "\n" + ('=' * 80)
|
40
|
+
puts "[ERROR] ConfigFileReader#read <#{filepath}>"
|
41
|
+
puts ' I suggest to revise file format!'
|
42
|
+
puts " #{e.message}\n" + ('=' * 80)
|
43
|
+
raise "[ERROR] ConfigFileReader <#{e}>"
|
44
|
+
end
|
45
|
+
data = convert_string_keys_to_symbol(data)
|
46
|
+
data[:global] = data[:global] || {}
|
47
|
+
data[:alias] = data[:alias] || {}
|
48
|
+
data[:cases] = data[:cases] || []
|
49
|
+
read_included_files!(filepath, data)
|
50
|
+
data
|
51
|
+
end
|
52
|
+
# rubocop:enable Metrics/MethodLength
|
53
|
+
# rubocop:enable Metrics/AbcSize
|
54
|
+
# rubocop:enable Security/YAMLLoad
|
55
|
+
|
56
|
+
##
|
57
|
+
# Read JSON config file
|
58
|
+
# @param filepath (String) Path to JSON config file
|
59
|
+
# @return Hash with config data
|
60
|
+
def self.read_json(filepath)
|
61
|
+
data = JSON.parse(File.read(filepath), symbolize_names: true)
|
62
|
+
data = convert_string_keys_to_symbol(data)
|
63
|
+
data[:global] = data[:global] || {}
|
64
|
+
data[:alias] = data[:alias] || {}
|
65
|
+
data[:cases] = data[:cases] || []
|
66
|
+
read_included_files!(filepath, data)
|
67
|
+
data
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Read all configuration files from "filepath" folder.
|
72
|
+
# @param filepath (String) Folder with config files
|
73
|
+
# @param data (Hash) Input configuration
|
74
|
+
# rubocop:disable Security/YAMLLoad
|
75
|
+
private_class_method def self.read_included_files!(filepath, data)
|
76
|
+
return if data[:global][:tt_include].nil?
|
77
|
+
|
78
|
+
include_dir = data[:global][:tt_include]
|
79
|
+
if include_dir == File.absolute_path(include_dir)
|
80
|
+
basedir = include_dir
|
81
|
+
else
|
82
|
+
basedir = File.join(File.dirname(filepath), data[:global][:tt_include])
|
83
|
+
end
|
84
|
+
files = Dir.glob(File.join(basedir, '**/*.yaml'))
|
85
|
+
files += Dir.glob(File.join(basedir, '**/*.yml'))
|
86
|
+
files.each { |file|
|
87
|
+
begin
|
88
|
+
data[:cases] << YAML.load(File.open(file))
|
89
|
+
rescue StandardError => e
|
90
|
+
puts "\n" + ('=' * 80)
|
91
|
+
puts "[ERROR] ConfigFileReader#read <#{file}>"
|
92
|
+
puts ' I suggest to revise file format!'
|
93
|
+
puts " #{e.message}\n" + ('=' * 80)
|
94
|
+
end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
# rubocop:enable Security/YAMLLoad
|
98
|
+
|
99
|
+
# rubocop:disable Metrics/MethodLength
|
100
|
+
# rubocop:disable Metrics/AbcSize
|
101
|
+
private_class_method def self.convert_string_keys_to_symbol(input)
|
102
|
+
return input if input.class != Hash
|
103
|
+
|
104
|
+
output = {}
|
105
|
+
input.each_pair do |key, value|
|
106
|
+
key2 = key
|
107
|
+
key2 = key.to_sym if key.class
|
108
|
+
value2 = value
|
109
|
+
if value.class == Hash
|
110
|
+
value2 = convert_string_keys_to_symbol(value)
|
111
|
+
elsif value.class == Array
|
112
|
+
value2 = []
|
113
|
+
value.each { |i| value2 << convert_string_keys_to_symbol(i) }
|
114
|
+
end
|
115
|
+
output[key2] = value2
|
116
|
+
end
|
117
|
+
output
|
118
|
+
end
|
119
|
+
# rubocop:enable Metrics/MethodLength
|
120
|
+
# rubocop:enable Metrics/AbcSize
|
121
|
+
end
|