puppet-check 1.5.0 → 2.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.
@@ -4,8 +4,6 @@ require_relative '../puppet-check'
4
4
  class DataParser
5
5
  # checks yaml (.yaml/.yml)
6
6
  def self.yaml(files)
7
- return if files.empty?
8
-
9
7
  require 'yaml'
10
8
 
11
9
  files.each do |file|
@@ -18,7 +16,7 @@ class DataParser
18
16
  warnings = []
19
17
 
20
18
  # perform some rudimentary hiera checks if data exists and is hieradata
21
- warnings = hiera(parsed, file) unless (parsed.class.to_s == 'NilClass') || (File.basename(file) == 'hiera.yaml')
19
+ warnings = hiera(parsed, file) if parsed && (File.basename(file) != 'hiera.yaml')
22
20
 
23
21
  next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.join("\n")}") unless warnings.empty?
24
22
  PuppetCheck.settings[:clean_files].push(file.to_s)
@@ -28,15 +26,19 @@ class DataParser
28
26
 
29
27
  # checks eyaml (.eyaml/.eyml)
30
28
  def self.eyaml(files, public, private)
31
- return if files.empty?
32
-
33
29
  require 'openssl'
34
30
 
35
31
  # keys specified?
36
- return warn 'Public X509 and/or Private RSA PKCS7 certs were not specified. EYAML checks will not be executed.' if public.nil? || private.nil?
32
+ if public.nil? || private.nil?
33
+ PuppetCheck.settings[:ignored_files].concat(files)
34
+ return warn 'Public X509 and/or Private RSA PKCS7 certs were not specified. EYAML checks will not be executed.'
35
+ end
37
36
 
38
37
  # keys exist?
39
- return warn 'Specified Public X509 and/or Private RSA PKCS7 certs do not exist. EYAML checks will not be executed.' unless File.file?(public) && File.file?(private)
38
+ unless File.file?(public) && File.file?(private)
39
+ PuppetCheck.settings[:ignored_files].concat(files)
40
+ return warn 'Specified Public X509 and/or Private RSA PKCS7 certs do not exist. EYAML checks will not be executed.'
41
+ end
40
42
 
41
43
  # setup decryption
42
44
  rsa = OpenSSL::PKey::RSA.new(File.read(private))
@@ -52,14 +54,14 @@ class DataParser
52
54
 
53
55
  # check yaml syntax
54
56
  begin
55
- parsed = YAML.safe_load(decrypted)
57
+ parsed = YAML.load_file(decrypted)
56
58
  rescue StandardError => err
57
59
  PuppetCheck.settings[:error_files].push("#{file}:\n#{err.to_s.gsub("(#{file}): ", '')}")
58
60
  else
59
61
  warnings = []
60
62
 
61
63
  # perform some rudimentary hiera checks if data exists and is hieradata
62
- warnings = hiera(parsed, file) unless (parsed.class.to_s == 'NilClass') || (File.basename(file) == 'hiera.yaml')
64
+ warnings = hiera(parsed, file) if parsed
63
65
 
64
66
  next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.join("\n")}") unless warnings.empty?
65
67
  PuppetCheck.settings[:clean_files].push(file.to_s)
@@ -69,8 +71,6 @@ class DataParser
69
71
 
70
72
  # checks json (.json)
71
73
  def self.json(files)
72
- return if files.empty?
73
-
74
74
  require 'json'
75
75
 
76
76
  files.each do |file|
@@ -85,7 +85,7 @@ class DataParser
85
85
  # check metadata.json
86
86
  if File.basename(file) == 'metadata.json'
87
87
  # metadata-json-lint has issues and is essentially no longer maintained, so here is an improved and leaner version of it
88
- require 'spdx-licenses'
88
+ require 'rubygems/util/licenses'
89
89
 
90
90
  # check for errors
91
91
  errors = []
@@ -97,9 +97,8 @@ class DataParser
97
97
 
98
98
  # check requirements and dependencies keys
99
99
  %w[requirements dependencies].each do |key|
100
- # skip if key is missing or or value is an empty string, array, or hash
101
- next unless parsed.key?(key)
102
- next if parsed[key].empty?
100
+ # skip if key is missing or value is an empty string, array, or hash
101
+ next if !parsed.key?(key) || parsed[key].empty?
103
102
 
104
103
  # check that dependencies and requirements are an array of hashes
105
104
  next errors.push("Field '#{key}' is not an array of hashes.") unless (parsed[key].is_a? Array) && (parsed[key][0].is_a? Hash)
@@ -113,14 +112,14 @@ class DataParser
113
112
  names << name
114
113
 
115
114
  # warn and skip if key is missing
116
- next warnings.push("'#{req_dep['name']}' is missing a 'version_requirement' key.") if req_dep['version_requirement'].class.to_s == 'NilClass'
115
+ next warnings.push("'#{req_dep['name']}' is missing a 'version_requirement' key.") if req_dep['version_requirement'].nil?
117
116
 
118
117
  # warn and skip if no upper bound
119
118
  next warnings.push("'#{req_dep['name']}' is missing an upper bound.") unless req_dep['version_requirement'].include?('<')
120
119
 
121
120
  # check for semantic versioning
122
- if key == 'dependencies'
123
- warnings.push("'#{req_dep['name']}' has non-semantic versioning in its 'version_requirement' key.") unless req_dep['version_requirement'] =~ /\d\.\d\.\d.*\d\.\d\.\d/
121
+ if key == 'dependencies' && req_dep['version_requirement'] !~ /\d+\.\d+\.\d+.*\d+\.\d+\.\d+/
122
+ warnings.push("'#{req_dep['name']}' has non-semantic versioning in its 'version_requirement' key.")
124
123
  end
125
124
  end
126
125
  end
@@ -161,14 +160,38 @@ class DataParser
161
160
  warnings.push('Recommended field \'operatingsystem_support\' not found.')
162
161
  end
163
162
 
164
- # check for spdx license (rubygems/util/licenses for rubygems >= 2.5 in the far future)
165
- if parsed.key?('license') && !SpdxLicenses.exist?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
163
+ # check for spdx license
164
+ if parsed.key?('license') && !Gem::Licenses.match?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
166
165
  warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/")
167
166
  end
168
- # assume this is hieradata
169
- else
167
+ # assume this is task metadata if it has this key
168
+ elsif parsed.key?('description')
169
+ # check that description is a string
170
+ warnings.push('description value is not a String') unless parsed['description'].is_a?(String)
171
+ # check that input_method is one of three possible values
172
+ if parsed.key?('input_method')
173
+ if parsed['input_method'].is_a?(String)
174
+ warnings.push('input_method value is not one of environment, stdin, or powershell') unless %w[environment stdin powershell].include?(parsed['input_method'])
175
+ else
176
+ warnings.push('input_method value is not a String')
177
+ end
178
+ end
179
+ # check that parameters is a hash
180
+ if parsed.key?('parameters') && !parsed['parameters'].is_a?(Hash)
181
+ warnings.push('parameters value is not a Hash')
182
+ end
183
+ # check that puppet_task_version is an integer
184
+ if parsed.key?('puppet_task_version') && !parsed['puppet_task_version'].is_a?(Integer)
185
+ warnings.push('puppet_task_version value is not an Integer')
186
+ end
187
+ # check that supports_noop is a boolean
188
+ if parsed.key?('supports_noop') && !(parsed['supports_noop'].is_a?(TrueClass) || parsed['supports_noop'].is_a?(FalseClass))
189
+ warnings.push('supports_noop value is not a Boolean')
190
+ end
191
+ # assume this is hieradata and ensure it is non-empty
192
+ elsif parsed
170
193
  # perform some rudimentary hiera checks if data exists
171
- warnings = hiera(parsed, file) unless parsed.class.to_s == 'NilClass'
194
+ warnings = hiera(parsed, file)
172
195
  end
173
196
  next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.join("\n")}") unless warnings.empty?
174
197
  PuppetCheck.settings[:clean_files].push(file.to_s)
@@ -181,15 +204,19 @@ class DataParser
181
204
  private_class_method :method
182
205
  warnings = []
183
206
 
184
- data.each do |key, value|
185
- # check for nil values in the data (nil keys are fine)
186
- if (value.is_a?(Hash) && value.values.any?(&:nil?)) || (value.class.to_s == 'NilClass')
187
- warnings.push("Value(s) missing in key '#{key}'.")
207
+ # disregard nil/undef value data check if default values (common)
208
+ unless file =~ /^common/
209
+ # unless /^common/.match?(file) TODO: use when ruby >= 2.4
210
+ data.each do |key, value|
211
+ # check for nil values in the data (nil keys are fine)
212
+ if (value.is_a?(Hash) && value.values.any?(&:nil?)) || value.nil?
213
+ warnings.push("Value(s) missing in key '#{key}'.")
214
+ end
188
215
  end
189
216
  end
190
217
 
191
218
  # check that '---' does not show up more than once in the hieradata
192
- warnings.push('The string --- appears more than once in this data and Hiera will fail to parse it correctly.') if File.read(file).scan(/---/).count >= 2
219
+ warnings.push('The string --- appears more than once in this data and Hiera may fail to parse it correctly.') if File.read(file).scan(/---/).count >= 2
193
220
 
194
221
  warnings
195
222
  end
@@ -22,7 +22,7 @@ class OutputResults
22
22
  end
23
23
 
24
24
  # output the results as yaml or json
25
- def self.markup
25
+ def self.markup(settings)
26
26
  # generate output hash
27
27
  hash = {}
28
28
  hash['errors'] = PuppetCheck.settings[:error_files] unless PuppetCheck.settings[:error_files].empty?
@@ -31,14 +31,15 @@ class OutputResults
31
31
  hash['ignored'] = PuppetCheck.settings[:ignored_files] unless PuppetCheck.settings[:ignored_files].empty?
32
32
 
33
33
  # convert hash to markup language
34
- if PuppetCheck.settings[:output_format] == 'yaml'
34
+ case settings[:output_format]
35
+ when 'yaml'
35
36
  require 'yaml'
36
37
  puts Psych.dump(hash, indentation: 2)
37
- elsif PuppetCheck.settings[:output_format] == 'json'
38
+ when 'json'
38
39
  require 'json'
39
40
  puts JSON.pretty_generate(hash)
40
41
  else
41
- raise "puppet-check: Unsupported output format '#{PuppetCheck.settings[:output_format]}' was specified."
42
+ raise "puppet-check: Unsupported output format '#{settings[:output_format]}' was specified."
42
43
  end
43
44
  end
44
45
  end
@@ -4,33 +4,53 @@ require_relative '../puppet-check'
4
4
  # executes diagnostics on puppet files
5
5
  class PuppetParser
6
6
  # checks puppet (.pp)
7
- def self.manifest(files, future, style, pl_args)
8
- return if files.empty?
9
-
7
+ def self.manifest(files, style, pl_args)
10
8
  require 'puppet/face'
11
9
 
12
10
  # prepare the Puppet settings for the error checking
13
11
  Puppet.initialize_settings unless Puppet.settings.app_defaults_initialized?
14
- Puppet[:parser] = 'future' if future && (Puppet::PUPPETVERSION.to_i < 4)
15
12
 
16
13
  files.each do |file|
17
- # setup error logging and collection
14
+ # setup error logging and collection; warnings logged for all versions, but errors for only puppet < 6.5
18
15
  errors = []
19
16
  Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(errors))
20
17
 
21
18
  # check puppet syntax
22
19
  begin
23
- Puppet::Face[:parser, :current].validate(file)
20
+ # initialize message
21
+ message = ''
22
+ # in puppet >= 6.5 the return of this method is a hash with the error
23
+ new_error = Puppet::Face[:parser, :current].validate(file)
24
+ # puppet 6.5 output format is now a hash from the face api
25
+ if Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('6.5.0') && new_error != {}
26
+ message = new_error.values.map(&:to_s).join("\n").gsub(/ \(file: #{File.absolute_path(file)}(, |\))/, '').gsub(/Could not parse.*: /, '')
27
+ end
24
28
  # this is the actual error that we need to rescue Puppet::Face from
25
29
  rescue SystemExit
26
- # puppet 5 can only do one error per line and outputs fake dir env info
27
- next PuppetCheck.settings[:error_files].push("#{file}:\n#{errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '').gsub(/Could not parse.*: /, '')}") if Puppet::PUPPETVERSION.to_i == 5
28
- # puppet < 5 parser output style
29
- next PuppetCheck.settings[:error_files].push("#{file}:\n#{errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '')}")
30
+ # puppet 5.4-6.4 has a new validator output format and eof errors have fake dir env info
31
+ if Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('5.4') && Gem::Version.new(Puppet::PUPPETVERSION) < Gem::Version.new('6.5')
32
+ message = errors.map(&:to_s).join("\n").gsub(/file: #{File.absolute_path(file)}(, |\))/, '').gsub(/Could not parse.*: /, '')
33
+ # puppet 5.0-5.2 can only do one error per line and outputs fake dir env info
34
+ elsif Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('5.0') && Gem::Version.new(Puppet::PUPPETVERSION) < Gem::Version.new('5.3')
35
+ message = errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '').gsub(/Could not parse.*: /, '')
36
+ end
37
+ # puppet < 5 and 5.3 parser output style
38
+ message = errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '')
30
39
  end
40
+ # output message
41
+ next PuppetCheck.settings[:error_files].push("#{file}:\n#{message}") unless message.empty?
31
42
 
32
43
  # initialize warnings with output from the parser if it exists, since the output is warnings if Puppet::Face did not trigger a SystemExit
33
- warnings = errors.empty? ? "#{file}:" : "#{file}:\n#{errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '')}"
44
+ warnings = "#{file}:"
45
+ unless errors.empty?
46
+ # puppet 5.4-5.x has a new validator output format
47
+ warnings << if Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('5.4')
48
+ "\n#{errors.map(&:to_s).join("\n").gsub("file: #{File.absolute_path(file)}, ", '')}"
49
+ # puppet <= 5.3 validator output format
50
+ else
51
+ "\n#{errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '')}"
52
+ end
53
+ end
34
54
  Puppet::Util::Log.close_all
35
55
 
36
56
  # check puppet style
@@ -62,14 +82,9 @@ class PuppetParser
62
82
 
63
83
  # checks puppet template (.epp)
64
84
  def self.template(files)
65
- return if files.empty?
66
-
67
85
  require 'puppet/pops'
68
86
 
69
87
  files.each do |file|
70
- # puppet before version 4 cannot check template syntax
71
- next PuppetCheck.settings[:ignored_files].push("#{file}: ignored due to Puppet < 4") if Puppet::PUPPETVERSION.to_i < 4
72
-
73
88
  # check puppet template syntax
74
89
  begin
75
90
  # credits to gds-operations/puppet-syntax for the parser function call
@@ -3,22 +3,22 @@ class RSpecPuppetSupport
3
3
  # code diagram:
4
4
  # 'puppetcheck:spec' task invokes 'run'
5
5
  # 'run' invokes 'file_setup' always and 'dependency_setup' if metadata.json exists
6
- # 'dependency_setup' invokes 'git/forge/hg' if dependencies exist and git/forge/hg is download option
6
+ # 'dependency_setup' invokes 'git/forge/svn/hg' if dependencies exist and git/forge/svn/hg is download option
7
7
  # 'git/forge/svn/hg' downloads module fixture appropriately
8
8
 
9
9
  # prepare the spec fixtures directory for rspec-puppet testing
10
10
  def self.run
11
11
  # ensure this method does not do anything inside module dependencies
12
12
  specdirs = Dir.glob('**/spec').reject { |dir| dir =~ /fixtures/ }
13
- return if specdirs.class.to_s == 'NilClass'
13
+ return if specdirs.empty?
14
14
 
15
15
  # setup fixtures for rspec-puppet testing
16
16
  specdirs.each do |specdir|
17
17
  # skip to next specdir if it does not seem like a puppet module
18
- next unless File.directory?(specdir + '/../manifests')
18
+ next unless File.directory?("#{specdir}/../manifests")
19
19
 
20
20
  # change to module directory
21
- Dir.chdir(specdir + '/..')
21
+ Dir.chdir("#{specdir}/..")
22
22
 
23
23
  # grab the module name from the directory name of the module to pass to file_setup
24
24
  file_setup(File.basename(Dir.pwd))
@@ -40,11 +40,21 @@ class RSpecPuppetSupport
40
40
  File.write('spec/fixtures/manifests/site.pp', '') unless File.file?('spec/fixtures/manifests/site.pp')
41
41
 
42
42
  # symlink the module into spec/fixtures/modules
43
- File.symlink("../../../#{module_name}", "spec/fixtures/modules/#{module_name}") unless File.exist?("spec/fixtures/modules/#{module_name}")
43
+ if File.exist?("spec/fixtures/modules/#{module_name}")
44
+ # check if target is a symlink
45
+ if File.symlink?("spec/fixtures/modules/#{module_name}")
46
+ # check if target is correct
47
+ warn "spec/fixtures/modules/#{module_name} is not a symlink to the correct source! Your tests may fail because of this!" unless File.readlink("spec/fixtures/modules/#{module_name}") == File.expand_path("../../../../#{module_name}")
48
+ else
49
+ warn "spec/fixtures/modules/#{module_name} is not a symlink! Your tests may fail because of this!"
50
+ end
51
+ else
52
+ File.symlink("../../../../#{module_name}", "spec/fixtures/modules/#{module_name}")
53
+ end
44
54
 
45
55
  # create spec_helper if missing
46
56
  return if File.file?('spec/spec_helper.rb')
47
- File.open('spec/spec_helper.rb', 'w') { |file| file.puts "require 'rspec-puppet'\n\nfixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))\n\nRSpec.configure do |c|\n c.module_path = File.join(fixture_path, 'modules')\n c.manifest_dir = File.join(fixture_path, 'manifests')\n c.manifest = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'manifests', 'site.pp')\n c.environmentpath = File.join(Dir.pwd, 'spec')\nend" }
57
+ File.open('spec/spec_helper.rb', 'w') { |file| file.puts "require 'rspec-puppet/spec_helper'\n" }
48
58
  end
49
59
 
50
60
  # setup the module dependencies for rspec-puppet testing
@@ -56,7 +66,7 @@ class RSpecPuppetSupport
56
66
  parsed = JSON.parse(File.read('metadata.json'))
57
67
 
58
68
  # grab dependencies if they exist
59
- return if parsed['dependencies'].empty?
69
+ return unless parsed.key?('dependencies')
60
70
  parsed['dependencies'].each do |dependency_hash|
61
71
  # determine how the user wants to download the module dependency
62
72
  if dependency_hash.key?('git')
@@ -71,6 +81,7 @@ class RSpecPuppetSupport
71
81
  warn "#{dependency_hash['name']} has an unspecified, or specified but unsupported, download method."
72
82
  end
73
83
  end
84
+ Process.waitall
74
85
  end
75
86
 
76
87
  # download external module dependency with git
@@ -79,7 +90,11 @@ class RSpecPuppetSupport
79
90
  # establish path to clone module to
80
91
  path = "spec/fixtures/modules/#{File.basename(git_url, '.git')}"
81
92
  # is the module present and already cloned with git? do a pull; otherwise, do a clone
82
- File.directory?("#{path}/.git") ? system("git -C #{path} pull") : system("git clone #{args} #{git_url} #{path}")
93
+ begin
94
+ File.directory?("#{path}/.git") ? spawn("git -C #{path} pull") : spawn("git clone #{args} #{git_url} #{path}")
95
+ rescue Errno::ENOENT
96
+ warn 'git is not installed and cannot be used to retrieve dependency modules'
97
+ end
83
98
  end
84
99
 
85
100
  # download external module dependency with forge
@@ -87,7 +102,7 @@ class RSpecPuppetSupport
87
102
  private_class_method :method
88
103
  # is the module present? do an upgrade; otherwise, do an install
89
104
  subcommand = File.directory?("spec/fixtures/modules/#{forge_name}") ? 'upgrade' : 'install'
90
- system("puppet module #{subcommand} --modulepath spec/fixtures/modules/ #{args} #{forge_name}")
105
+ spawn("puppet module #{subcommand} --modulepath spec/fixtures/modules/ #{args} #{forge_name}")
91
106
  end
92
107
 
93
108
  # download external module dependency with svn
@@ -96,7 +111,11 @@ class RSpecPuppetSupport
96
111
  # establish path to checkout module to
97
112
  path = "spec/fixtures/modules/#{File.basename(svn_url)}"
98
113
  # is the module present and already checked out with svn? do an update; otherwise, do a checkout
99
- File.directory?("#{path}/.svn") ? system("svn update #{path}") : system("svn co #{args} #{svn_url} #{path}")
114
+ begin
115
+ File.directory?("#{path}/.svn") ? spawn("svn update #{path}") : spawn("svn co #{args} #{svn_url} #{path}")
116
+ rescue Errno::ENOENT
117
+ warn 'subversion is not installed and cannot be used to retrieve dependency modules'
118
+ end
100
119
  end
101
120
 
102
121
  # download external module dependency with hg
@@ -105,6 +124,10 @@ class RSpecPuppetSupport
105
124
  # establish path to clone module to
106
125
  path = "spec/fixtures/modules/#{File.basename(hg_url)}"
107
126
  # is the module present and already cloned with hg? do a pull and update; otherwise do a clone
108
- File.directory?("#{path}/.hg") ? system("hg --cwd #{path} pull; hg --cwd #{path} update") : system("hg clone #{args} #{hg_url} #{path}")
127
+ begin
128
+ File.directory?("#{path}/.hg") ? spawn("hg --cwd #{path} pull; hg --cwd #{path} update") : spawn("hg clone #{args} #{hg_url} #{path}")
129
+ rescue Errno::ENOENT
130
+ warn 'mercurial is not installed and cannot be used to retrieve dependency modules'
131
+ end
109
132
  end
110
133
  end
@@ -9,7 +9,7 @@ class RubyParser
9
9
  # check ruby syntax
10
10
  begin
11
11
  # prevents ruby code from actually executing
12
- catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)}") }
12
+ catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)}", file) }
13
13
  rescue ScriptError, StandardError => err
14
14
  PuppetCheck.settings[:error_files].push("#{file}:\n#{err}")
15
15
  else
@@ -18,7 +18,7 @@ class RubyParser
18
18
  require 'rubocop'
19
19
 
20
20
  # check RuboCop and collect warnings
21
- rubocop_warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--format', 'emacs', file]) }
21
+ rubocop_warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--require', 'rubocop-performance', '--format', 'emacs', file]) }
22
22
  warnings = rubocop_warnings == '' ? '' : rubocop_warnings.split("#{File.absolute_path(file)}:").join('')
23
23
 
24
24
  # check Reek and collect warnings
@@ -37,8 +37,6 @@ class RubyParser
37
37
 
38
38
  # checks ruby template (.erb)
39
39
  def self.template(files)
40
- return if files.empty?
41
-
42
40
  require 'erb'
43
41
 
44
42
  files.each do |file|
@@ -66,22 +64,22 @@ class RubyParser
66
64
  require 'rubocop'
67
65
  # cop named differently depending upon version
68
66
  filename_cop = RuboCop::Version::STRING.to_f >= 0.5 ? 'Naming/FileName' : 'Style/FileName'
67
+ # RuboCop is grumpy about non-snake_case filenames so disable the FileName check
68
+ rc_args.include?('--except') ? rc_args[rc_args.index('--except') + 1] = "#{rc_args[rc_args.index('--except') + 1]},#{filename_cop}" : rc_args.concat(['--except', filename_cop])
69
69
  end
70
70
 
71
71
  files.each do |file|
72
72
  # check librarian puppet syntax
73
73
  begin
74
74
  # prevents ruby code from actually executing
75
- catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)}") }
75
+ catch(:good) { instance_eval("BEGIN {throw :good}; #{File.read(file)}", file) }
76
76
  rescue SyntaxError, LoadError, ArgumentError => err
77
77
  PuppetCheck.settings[:error_files].push("#{file}:\n#{err}")
78
78
  # check librarian puppet style
79
79
  else
80
80
  if style
81
81
  # check Rubocop
82
- # RuboCop is grumpy about non-snake_case filenames so disable the FileName check
83
- rc_args.include?('--except') ? rc_args[rc_args.index('--except') + 1] = "#{rc_args[rc_args.index('--except') + 1]},#{filename_cop}" : rc_args.concat(['--except', filename_cop])
84
- warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--format', 'emacs', file]) }
82
+ warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--require', 'rubocop-performance', '--format', 'emacs', file]) }
85
83
 
86
84
  # collect style warnings
87
85
  next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.split("#{File.absolute_path(file)}:").join('')}") unless warnings.empty?
@@ -14,10 +14,10 @@ class PuppetCheck::Tasks < ::Rake::TaskLib
14
14
  namespace :puppetcheck do
15
15
  desc 'Execute Puppet-Check file checks'
16
16
  task :file do
17
- PuppetCheck.new.run(Dir.glob('*'))
17
+ PuppetCheck.new.run(PuppetCheck.settings, Dir.glob('*'))
18
18
  end
19
19
 
20
- # rspec, rspec-puppet, and beaker tasks
20
+ # rspec and rspec-puppet tasks
21
21
  begin
22
22
  require 'rspec/core/rake_task'
23
23
  require_relative 'rspec_puppet_support'
@@ -30,22 +30,26 @@ class PuppetCheck::Tasks < ::Rake::TaskLib
30
30
  task.pattern = spec_dirs.empty? ? 'skip_rspec' : spec_dirs
31
31
  task.rspec_opts = '-f json' if PuppetCheck.settings[:output_format] == 'json'
32
32
  end
33
-
34
- desc 'Execute Beaker acceptance tests'
35
- RSpec::Core::RakeTask.new(:beaker) do |task|
36
- # generate tasks for all recognized directories and ensure acceptance tests inside module dependencies are ignored
37
- acceptance_dirs = Dir.glob('**/acceptance').reject { |dir| dir =~ /fixtures/ }
38
- task.pattern = acceptance_dirs.empty? ? 'skip_beaker' : acceptance_dirs
39
- task.rspec_opts = '-f json' if PuppetCheck.settings[:output_format] == 'json'
40
- end
41
33
  rescue LoadError
42
34
  desc 'RSpec is not installed.'
43
35
  task :spec do
44
- puts 'RSpec is not installed. The RSpec/RSpecPuppet tasks will not be available.'
36
+ puts 'RSpec is not installed. The RSpec/RSpec-Puppet tasks will not be available.'
45
37
  end
46
- desc 'RSpec is not installed.'
38
+ end
39
+
40
+ # beaker tasks
41
+ begin
42
+ require 'beaker/tasks/quick_start'
43
+
44
+ desc 'Execute Beaker acceptance tests'
45
+ task :beaker, %i[hypervisor] do |_, args|
46
+ args[:hypervisor] = 'vagrant' if args[:hypervisor].nil?
47
+ Rake::Task["beaker_quickstart:run_test[#{args[:hypervisor]}]"].invoke
48
+ end
49
+ rescue LoadError
50
+ desc 'Beaker is not installed.'
47
51
  task :beaker do
48
- puts 'RSpec is not installed. The Beaker tasks will not be available.'
52
+ puts 'Beaker is not installed. The Beaker tasks will not be available.'
49
53
  end
50
54
  end
51
55