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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +39 -4
- data/README.md +35 -50
- data/lib/puppet-check.rb +63 -47
- data/lib/puppet-check/cli.rb +21 -17
- data/lib/puppet-check/data_parser.rb +55 -28
- data/lib/puppet-check/output_results.rb +5 -4
- data/lib/puppet-check/puppet_parser.rb +31 -16
- data/lib/puppet-check/rspec_puppet_support.rb +34 -11
- data/lib/puppet-check/ruby_parser.rb +6 -8
- data/lib/puppet-check/tasks.rb +17 -13
- data/spec/fixtures/manifests/eof_syntax.pp +4 -0
- data/spec/fixtures/task_metadata/task_bad.json +10 -0
- data/spec/fixtures/task_metadata/task_good.json +16 -0
- data/spec/puppet-check/cli_spec.rb +9 -43
- data/spec/puppet-check/data_parser_spec.rb +27 -11
- data/spec/puppet-check/output_results_spec.rb +9 -18
- data/spec/puppet-check/puppet_parser_spec.rb +22 -18
- data/spec/puppet-check/regression_check_spec.rb +1 -3
- data/spec/puppet-check/rspec_puppet_support_spec.rb +5 -1
- data/spec/puppet-check/ruby_parser_spec.rb +8 -4
- data/spec/puppet-check/tasks_spec.rb +13 -3
- data/spec/puppet-check_spec.rb +11 -12
- data/spec/system/system_spec.rb +8 -14
- metadata +51 -32
@@ -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)
|
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
|
-
|
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
|
-
|
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.
|
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)
|
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 '
|
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
|
101
|
-
next
|
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'].
|
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.")
|
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
|
165
|
-
if parsed.key?('license') && !
|
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
|
169
|
-
|
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)
|
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
|
185
|
-
|
186
|
-
|
187
|
-
|
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
|
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
|
-
|
34
|
+
case settings[:output_format]
|
35
|
+
when 'yaml'
|
35
36
|
require 'yaml'
|
36
37
|
puts Psych.dump(hash, indentation: 2)
|
37
|
-
|
38
|
+
when 'json'
|
38
39
|
require 'json'
|
39
40
|
puts JSON.pretty_generate(hash)
|
40
41
|
else
|
41
|
-
raise "puppet-check: Unsupported output format '#{
|
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,
|
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
|
-
|
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
|
27
|
-
|
28
|
-
|
29
|
-
|
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 =
|
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.
|
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
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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?
|
data/lib/puppet-check/tasks.rb
CHANGED
@@ -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
|
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/
|
36
|
+
puts 'RSpec is not installed. The RSpec/RSpec-Puppet tasks will not be available.'
|
45
37
|
end
|
46
|
-
|
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 '
|
52
|
+
puts 'Beaker is not installed. The Beaker tasks will not be available.'
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|