teuton 2.1.10 → 2.3.1

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