teuton 2.1.10 → 2.3.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -12
  3. data/bin/check_teuton +0 -2
  4. data/docs/changelog/ideas.md +132 -0
  5. data/docs/changelog/v2.1.md +14 -122
  6. data/docs/changelog/v2.2.md +52 -28
  7. data/docs/changelog/version2.1.md +4 -0
  8. data/docs/commands/README.md +58 -15
  9. data/docs/commands/example_check.md +0 -4
  10. data/docs/commands/example_run.md +0 -4
  11. data/docs/dsl/README.md +1 -1
  12. data/docs/dsl/definition/result.md +1 -0
  13. data/docs/dsl/definition/run_remote.md +12 -6
  14. data/docs/dsl/definition/target.md +9 -10
  15. data/docs/dsl/execution/export.md +27 -20
  16. data/docs/install/README.md +13 -18
  17. data/docs/install/vagrant_docker.md +1 -1
  18. data/docs/learn/README.md +8 -8
  19. data/docs/learn/example-01-target.md +25 -25
  20. data/docs/learn/example-02-config.md +38 -49
  21. data/docs/learn/example-03-remote-hosts.md +22 -22
  22. data/docs/learn/{example-11-first-test.md → example-04-new-test.md} +23 -24
  23. data/docs/learn/{example-04-use.md → example-05-use.md} +6 -6
  24. data/docs/learn/{example-05-debug.md → example-06-debug.md} +8 -8
  25. data/docs/learn/{example-06-log.md → example-07-log.md} +7 -7
  26. data/docs/learn/example-08-readme.md +59 -0
  27. data/docs/learn/example-09-preserve.md +41 -0
  28. data/docs/videos.md +19 -0
  29. data/lib/teuton/application.rb +22 -3
  30. data/lib/teuton/case_manager/case/builtin/main.rb +3 -19
  31. data/lib/teuton/case_manager/case/builtin/package.rb +7 -6
  32. data/lib/teuton/case_manager/case/builtin/service.rb +9 -8
  33. data/lib/teuton/case_manager/case/builtin/teuton_file.rb +28 -0
  34. data/lib/teuton/case_manager/case/builtin/teuton_host.rb +31 -0
  35. data/lib/teuton/case_manager/case/builtin/user.rb +8 -7
  36. data/lib/teuton/case_manager/case/case.rb +1 -1
  37. data/lib/teuton/case_manager/case/dsl/goto.rb +2 -2
  38. data/lib/teuton/case_manager/case/dsl/log.rb +1 -1
  39. data/lib/teuton/case_manager/case/dsl/macro.rb +4 -1
  40. data/lib/teuton/case_manager/case/dsl/send.rb +2 -1
  41. data/lib/teuton/case_manager/case/play.rb +2 -0
  42. data/lib/teuton/case_manager/case/result/ext_compare.rb +16 -0
  43. data/lib/teuton/case_manager/case/result/result.rb +1 -1
  44. data/lib/teuton/case_manager/case/runner.rb +30 -4
  45. data/lib/teuton/case_manager/case_manager.rb +1 -1
  46. data/lib/teuton/case_manager/dsl.rb +10 -0
  47. data/lib/teuton/case_manager/export_manager.rb +24 -5
  48. data/lib/teuton/case_manager/utils.rb +1 -1
  49. data/lib/teuton/{project/laboratory → check}/builtin.rb +0 -0
  50. data/lib/teuton/{project/laboratory → check}/dsl.rb +40 -28
  51. data/lib/teuton/{project/laboratory → check}/laboratory.rb +3 -8
  52. data/lib/teuton/{project/laboratory → check}/show.rb +53 -59
  53. data/lib/teuton/cli.rb +85 -14
  54. data/lib/teuton/{project/readme → readme}/dsl.rb +0 -0
  55. data/lib/teuton/{project/readme → readme}/lang.rb +1 -1
  56. data/lib/teuton/{project/readme → readme}/readme.rb +22 -18
  57. data/lib/teuton/report/formatter/array_formatter.rb +13 -1
  58. data/lib/teuton/report/formatter/base_formatter.rb +18 -5
  59. data/lib/teuton/{project/skeleton.rb → skeleton.rb} +7 -18
  60. data/lib/teuton/utils/configfile_reader.rb +121 -0
  61. data/lib/teuton/{project → utils}/name_file_finder.rb +46 -26
  62. data/lib/teuton/version.rb +8 -0
  63. data/lib/teuton.rb +39 -32
  64. metadata +109 -62
  65. data/lib/teuton/case_manager/case/dsl/deprecated.rb +0 -14
  66. data/lib/teuton/cli/check.rb +0 -38
  67. data/lib/teuton/cli/main.rb +0 -6
  68. data/lib/teuton/cli/play.rb +0 -38
  69. data/lib/teuton/cli/readme.rb +0 -26
  70. data/lib/teuton/cli/version.rb +0 -12
  71. data/lib/teuton/files/gitignore +0 -2
  72. data/lib/teuton/project/configfile_reader.rb +0 -49
  73. data/lib/teuton/project/project.rb +0 -80
@@ -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 # write into output file
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 class
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.join(File.dirname(__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,7 +20,7 @@ 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' },
@@ -42,7 +36,7 @@ module Skeleton
42
36
  ##
43
37
  # Create dir
44
38
  # @param dirpath (String)
45
- def self.create_dir(dirpath)
39
+ private_class_method def self.create_dir(dirpath)
46
40
  if Dir.exist? dirpath
47
41
  puts "* Exists dir! => #{Rainbow(dirpath).yellow}"
48
42
  else
@@ -55,18 +49,12 @@ module Skeleton
55
49
  end
56
50
  end
57
51
 
58
- ##
59
- # Create dirs
60
- # @param args (Array)
61
- def self.create_dirs(*args)
62
- args.each { |arg| create_dir arg }
63
- end
64
-
65
52
  ##
66
53
  # Copy file
67
54
  # @param source (String) Source file
68
55
  # @param dest (String) Dest file
69
- def self.copyfile(source, dest)
56
+ # rubocop:disable Metrics/MethodLength
57
+ private_class_method def self.copyfile(source, dest)
70
58
  if File.exist? dest
71
59
  puts "* Exists file! => #{Rainbow(dest).yellow}"
72
60
  else
@@ -79,4 +67,5 @@ module Skeleton
79
67
  end
80
68
  end
81
69
  end
70
+ # rubocop:enable Metrics/MethodLength
82
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
@@ -3,8 +3,9 @@
3
3
  require 'rainbow'
4
4
  require_relative '../application'
5
5
 
6
- # Project:
7
- # * find_filenames_for, verbose, verboseln
6
+ ##
7
+ # NameFileFinder module
8
+ # Methods: find_filenames_for, verbose, verboseln
8
9
  module NameFileFinder
9
10
  ##
10
11
  # Find project filenames from input project relative path
@@ -28,6 +29,8 @@ module NameFileFinder
28
29
  ##
29
30
  # Find project filenames from input folder path
30
31
  # @param folder_path (String)
32
+ # rubocop:disable Metrics/AbcSize
33
+ # rubocop:disable Metrics/MethodLength
31
34
  def self.find_filenames_from_directory(folder_path)
32
35
  # COMPLEX MODE: We use start.rb as main RB file
33
36
  script_path = File.join(folder_path, 'start.rb')
@@ -45,15 +48,20 @@ module NameFileFinder
45
48
 
46
49
  find_configfilename_from_directory(folder_path)
47
50
  end
51
+ # rubocop:enable Metrics/AbcSize
52
+ # rubocop:enable Metrics/MethodLength
48
53
 
49
54
  ##
50
55
  # Find project config filename from input folder path
51
56
  # @param folder_path (String)
57
+ # rubocop:disable Metrics/AbcSize
58
+ # rubocop:disable Metrics/MethodLength
59
+ # rubocop:disable Style/IfUnlessModifier
52
60
  def self.find_configfilename_from_directory(folder_path)
53
61
  # COMPLEX MODE: We use config.yaml by default
54
62
  app = Application.instance
55
-
56
63
  config_path = ''
64
+
57
65
  if app.options['cpath'].nil?
58
66
  config_name = 'config'
59
67
  # Config name file is introduced by cname arg option from teuton command
@@ -68,7 +76,12 @@ module NameFileFinder
68
76
  end
69
77
  app.config_path = config_path
70
78
  end
79
+ # rubocop:enable Metrics/AbcSize
80
+ # rubocop:enable Metrics/MethodLength
81
+ # rubocop:enable Style/IfUnlessModifier
71
82
 
83
+ # rubocop:disable Metrics/AbcSize
84
+ # rubocop:disable Metrics/MethodLength
72
85
  def self.find_filenames_from_rb(script_path)
73
86
  # SIMPLE MODE: We use script_path as main RB file
74
87
  # This must be fullpath to DSL script file
@@ -86,7 +99,12 @@ module NameFileFinder
86
99
 
87
100
  find_configfilenames_from_rb(script_path)
88
101
  end
102
+ # rubocop:enable Metrics/AbcSize
103
+ # rubocop:enable Metrics/MethodLength
89
104
 
105
+ # rubocop:disable Metrics/MethodLength
106
+ # rubocop:disable Metrics/AbcSize
107
+ # rubocop:disable Style/IfUnlessModifier
90
108
  def self.find_configfilenames_from_rb(script_path)
91
109
  # SIMPLE MODE: We use script_path as main RB file
92
110
  # This must be fullpath to DSL script file
@@ -108,32 +126,33 @@ module NameFileFinder
108
126
  end
109
127
  app.config_path = config_path
110
128
  end
111
-
112
- def self.puts_input_info_on_screen
113
- app = Application.instance
114
-
115
- verbose Rainbow('[INFO] ScriptPath => ').blue
116
- verboseln Rainbow(trim(app.script_path)).blue.bright
117
- verbose Rainbow('[INFO] ConfigPath => ').blue
118
- verboseln Rainbow(trim(app.config_path)).blue.bright
119
- verbose Rainbow('[INFO] Pwd => ').blue
120
- verboseln Rainbow(app.running_basedir).blue.bright
121
- verbose Rainbow('[INFO] TestName => ').blue
122
- verboseln Rainbow(trim(app.test_name)).blue.bright
123
- end
129
+ # rubocop:enable Metrics/MethodLength
130
+ # rubocop:enable Metrics/AbcSize
131
+ # rubocop:enable Style/IfUnlessModifier
132
+
133
+ # def self.puts_input_info_on_screen
134
+ # app = Application.instance
135
+ #
136
+ # verbose Rainbow('[INFO] ScriptPath => ').blue
137
+ # verboseln Rainbow(trim(app.script_path)).blue.bright
138
+ # verbose Rainbow('[INFO] ConfigPath => ').blue
139
+ # verboseln Rainbow(trim(app.config_path)).blue.bright
140
+ # verbose Rainbow('[INFO] Pwd => ').blue
141
+ # verboseln Rainbow(app.running_basedir).blue.bright
142
+ # verbose Rainbow('[INFO] TestName => ').blue
143
+ # verboseln Rainbow(trim(app.test_name)).blue.bright
144
+ # end
124
145
 
125
146
  ##
126
147
  # Trim string text when is too long
127
- # @param input (String)
128
- # @return String
129
- def self.trim(input)
130
- return input unless input.to_s.start_with? Dir.pwd.to_s
131
-
132
- output = input.to_s
133
- offset = (Dir.pwd).length + 1
134
- output = "#{input[offset, input.size]}"
135
- output.to_s
136
- end
148
+ # def self.trim(input)
149
+ # return input unless input.to_s.start_with? Dir.pwd.to_s
150
+ #
151
+ # output = input.to_s
152
+ # offset = (Dir.pwd).length + 1
153
+ # output = "#{input[offset, input.size]}"
154
+ # output.to_s
155
+ # end
137
156
 
138
157
  def self.verboseln(text)
139
158
  verbose(text + "\n")
@@ -142,6 +161,7 @@ module NameFileFinder
142
161
  def self.verbose(text)
143
162
  return unless Application.instance.verbose
144
163
  return if Application.instance.options['quiet']
164
+
145
165
  print text
146
166
  end
147
167
  end
@@ -0,0 +1,8 @@
1
+
2
+ module Teuton
3
+ VERSION = '2.3.1'
4
+ APPNAME = 'teuton'
5
+ GEMNAME = 'teuton'
6
+ DOCKERNAME = "dvarrui/#{GEMNAME}"
7
+ HOMEPAGE = "https://github.com/teuton-software/teuton"
8
+ end
data/lib/teuton.rb CHANGED
@@ -1,47 +1,54 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'teuton/application'
2
- require_relative 'teuton/project/project'
3
- require_relative 'teuton/project/skeleton'
4
+ require_relative 'teuton/skeleton'
4
5
 
5
- ##
6
- # Main Teuton functions
7
6
  module Teuton
8
- ##
9
- # Create new Teuton project
10
7
  def self.create(path_to_new_dir)
11
8
  Skeleton.create(path_to_new_dir)
12
9
  end
13
10
 
14
- ##
15
- # Play (run) Teuton project.
16
- # @param path_to_rb_file [String] Path to main rb file.
17
- # @param options [Hash] Options like
18
- # * :export [String]
19
- # * :cname [String]
20
- # * :cpath [String]
21
- # * :case [String]
22
- # * :quiet [Boolean]
23
- def self.play(path_to_rb_file, options = {})
24
- Project.play(path_to_rb_file, options)
11
+ # Run test
12
+ # @param projectpath (String) Path to teuton test
13
+ # @param options (Array) Array of input options
14
+ def self.run(projectpath, options = {})
15
+ Application.instance.add_input_params(projectpath, options)
16
+ require_dsl_and_script('teuton/case_manager/dsl') # Define DSL keywords
25
17
  end
26
18
 
27
- ##
28
- # Generate readme for Teuton project.
29
- # @param path_to_rb_file [String] Path to main rb file.
30
- def self.readme(path_to_rb_file)
31
- Project.readme(path_to_rb_file, options)
19
+ # Create Readme file for a test
20
+ # @param projectpath (String) Path to teuton test
21
+ # @param options (Array) Array of input options
22
+ def self.readme(projectpath, options = {})
23
+ Application.instance.add_input_params(projectpath, options)
24
+ require_dsl_and_script('teuton/readme/readme') # Define DSL keywords
25
+
26
+ app = Application.instance
27
+ readme = Readme.new(app.script_path, app.config_path)
28
+ readme.show
32
29
  end
33
30
 
34
- ##
35
- # Simulate play Teuton project, check syntax and display stats.
36
- # @param path_to_rb_file [String] Path to main rb file.
37
- def self.check(path_to_rb_file)
38
- Project.check(path_to_rb_file, options)
31
+ # Check teuton test syntax
32
+ # @param projectpath (String) Path to teuton test
33
+ # @param options (Array) Array of input options
34
+ def self.check(projectpath, options = {})
35
+ Application.instance.add_input_params(projectpath, options)
36
+ require_dsl_and_script('teuton/check/laboratory') # Define DSL keywords
37
+
38
+ app = Application.instance
39
+ lab = Laboratory.new(app.script_path, app.config_path)
40
+ lab.show unless options[:panelconfig]
41
+ lab.show_panelconfig if options[:panelconfig]
39
42
  end
40
43
 
41
- ##
42
- # Display Teuton version
43
- def self.version
44
- print Rainbow(Application::NAME).bright.blue
45
- puts ' (version ' + Rainbow(Application::VERSION).green + ')'
44
+ private_class_method def self.require_dsl_and_script(dslpath)
45
+ app = Application.instance
46
+ require_relative dslpath
47
+ begin
48
+ require_relative app.script_path
49
+ rescue SyntaxError => e
50
+ puts e.to_s
51
+ puts Rainbow.new("[ FAIL ] SyntaxError into file #{app.script_path}").red
52
+ end
46
53
  end
47
54
  end