puppet-check 1.6.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/README.md +27 -24
- data/lib/puppet-check/cli.rb +5 -6
- data/lib/puppet-check/data_parser.rb +14 -22
- data/lib/puppet-check/output_results.rb +6 -5
- data/lib/puppet-check/puppet_parser.rb +24 -18
- data/lib/puppet-check/rspec_puppet_support.rb +21 -8
- data/lib/puppet-check/ruby_parser.rb +13 -8
- data/lib/puppet-check/tasks.rb +1 -1
- data/lib/{puppet-check.rb → puppet_check.rb} +23 -24
- data/spec/octocatalog-diff/{octocatalog-diff.cfg.rb → octocatalog_diff.cfg.rb} +6 -6
- data/spec/puppet-check/cli_spec.rb +3 -3
- data/spec/puppet-check/data_parser_spec.rb +41 -43
- data/spec/puppet-check/output_results_spec.rb +9 -18
- data/spec/puppet-check/puppet_parser_spec.rb +19 -17
- data/spec/puppet-check/regression_check_spec.rb +7 -9
- data/spec/puppet-check/rspec_puppet_support_spec.rb +13 -5
- data/spec/puppet-check/ruby_parser_spec.rb +18 -14
- data/spec/puppet-check/tasks_spec.rb +3 -3
- data/spec/{puppet-check_spec.rb → puppet_check_spec.rb} +9 -10
- data/spec/spec_helper.rb +7 -2
- data/spec/system/system_spec.rb +4 -4
- metadata +36 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f43468b01f25dba9ea6e997c982c632fb884d6cb8ec8faa31a670ac523a8ee8
|
4
|
+
data.tar.gz: 5baeb571e293b32c6120448d45c036523b96ffc0a325ba02c6f47e70323c1f3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0ff327a57b78229800e56dae894b863ff0217d9ae8f368d7ff9db048160b29c0b1365144fb4db596c3951fafa4b5569d0c5ad741e7d0b3fa1a3491ed64fed50
|
7
|
+
data.tar.gz: 7b15f95dc0876eb1d8a6b9fa5295c45858fc7eef02ba6a2924c68ad29dadf6fa179c62ed32eae167923f39172eb9b1464910f48e7072dfaf8e9d98328dd6739e
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,24 @@
|
|
1
|
-
### 1.
|
1
|
+
### 2.1.0 (Roadmap)
|
2
|
+
- Minimum supported version of Puppet bumped to 5.0.
|
3
|
+
- Minimum Ruby version bumped to 2.4.
|
4
|
+
- Official support for Puppet 7, Rubocop 1, and Reek 6.
|
5
|
+
- Fix Puppet message string transform conditionals.
|
6
|
+
|
7
|
+
### 2.0.1
|
8
|
+
- Check for existence of executables for dependency module retrieval.
|
9
|
+
- Beta support for Puppet 7, Rubocop 1, and Reek 6.
|
10
|
+
|
11
|
+
### 2.0.0
|
12
|
+
- Bump minimum version of Puppet to 4.0.0 and remove < 4 support code.
|
13
|
+
- Official support for Puppet 6.
|
14
|
+
- Minimum Ruby version bumped to 2.2.0.
|
15
|
+
- Bumped Rubocop and Reek minimum versions and fully migrated SPDX to Rubygems.
|
16
|
+
- Add rubocop-performance extension to Rubocop.
|
17
|
+
- Update manifest validation for breaking change in 6.5 API.
|
18
|
+
- Fix check on specified dependencies in metadata.
|
19
|
+
- Enable parallel module dependency retrieval.
|
20
|
+
|
21
|
+
### 1.6.1
|
2
22
|
- Removed check for hieradata nil/undef value for Hiera >= 5.
|
3
23
|
- Add rudimentary checks for task metadata.
|
4
24
|
- Preliminary support for Puppet 6.
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Puppet Check
|
2
|
-
[![Build Status](https://travis-ci.
|
2
|
+
[![Build Status](https://travis-ci.com/mschuchard/puppet-check.svg?branch=master)](https://travis-ci.com/mschuchard/puppet-check)
|
3
|
+
[![CircleCI](https://circleci.com/gh/mschuchard/puppet-check.svg?style=svg)](https://circleci.com/gh/mschuchard/puppet-check)
|
3
4
|
|
4
5
|
- [Description](#description)
|
5
6
|
- [Usage](#usage)
|
@@ -124,14 +125,16 @@ The following files have unrecognized formats and therefore were not processed:
|
|
124
125
|
### What About Puppet Development Kit?
|
125
126
|
The fairly recent release of the Puppet Development Kit (PDK) will hopefully eventually bring about the capability to test and validate your Puppet code and data in a streamlined, efficient, comprehensive, and accurate fashion comparable to Puppet Check. Unfortunately, the PDK has not yet achieved feature or efficiency parity with Puppet Check. The goal is for the PDK to one day replace Puppet Check and for Puppet Check to enter maintenance mode, but for now Puppet Check is still needed to lead Puppet testing.
|
126
127
|
|
128
|
+
### What About PDK now?
|
129
|
+
As of version 2.4.0 of the PDK, the PDK has essentially more or less achieved feature parity with Puppet Check. Although the PDK is not as efficient (including especially that Puppet Check executes significantly faster), it is still supported by Puppetlabs. Therefore, if you need an efficient and comprehensive Puppet validation solution, then you can still utilize Puppet Check, but the PDK is a recommended alternative for the future.
|
130
|
+
|
127
131
|
## Usage
|
128
|
-
Please see the [Gemspec](puppet-check.gemspec) for dependency information. All other dependencies should be fine with various versions. Puppet Check can be used with a CLI, Rake tasks, or API, from your system, rbenv, rvm, Docker, or Vagrant. Please note all interfaces (API by default, but can be modified) will ignore any directories named `fixtures
|
132
|
+
Please see the [Gemspec](puppet-check.gemspec) for dependency information. All other dependencies should be fine with various versions. Puppet Check can be used with a CLI, Rake tasks, or API, from your system, rbenv, rvm, Docker, or Vagrant. Please note all interfaces (API by default, but can be modified) will ignore any directories named `fixtures`, or specified paths with that directory during file checks and spec tests.
|
129
133
|
|
130
134
|
### CLI
|
131
135
|
```
|
132
136
|
usage: puppet-check [options] paths
|
133
137
|
--version Display the current version.
|
134
|
-
-f, --future Enable future parser
|
135
138
|
--fail-on-warnings Fail on warnings
|
136
139
|
-s, --style Enable style checks
|
137
140
|
--smoke Enable smoke testing
|
@@ -148,7 +151,7 @@ usage: puppet-check [options] paths
|
|
148
151
|
--rubocop arg_one,arg_two Arguments for Rubocop disabled cops
|
149
152
|
```
|
150
153
|
|
151
|
-
The command line interface enables the ability to select
|
154
|
+
The command line interface enables the ability to select additional style checks besides the syntax checks, and to specify PuppetLint and Rubocop checks to ignore. If you require a more robust interface to PuppetLint, Rubocop, and Reek, then please use `.puppet-lint.rc`, `.rubocop.yml` and `*.reek` config files. The `.puppet-lint.rc` can be specified with the `-c` argument. If it is not specified, then PuppetLint will automatically load one from `.puppet-lint.rc`, `~/.puppet-lint.rc`, or `/etc/puppet-lint.rc`, in that order of preference. The nearest `.rubocop.yml` and `*.reek` will be automatically respected.
|
152
155
|
|
153
156
|
Example:
|
154
157
|
```
|
@@ -167,15 +170,14 @@ rake puppetcheck:kitchen:* # Execute Test Kitchen acceptance tests
|
|
167
170
|
```
|
168
171
|
|
169
172
|
#### puppetcheck:file
|
170
|
-
You can add style, smoke, and regression checks to
|
173
|
+
You can add style, smoke, and regression checks to the `rake puppetcheck:file`, or change the output format, by adding the following after the require:
|
171
174
|
|
172
175
|
```ruby
|
173
176
|
# example of modifying Puppet Check behavior
|
174
|
-
PuppetCheck.settings[:
|
177
|
+
PuppetCheck.settings[:style] = true
|
175
178
|
PuppetCheck.settings[:fail_on_warnings] = true
|
176
|
-
PuppetCheck.settings[:
|
177
|
-
PuppetCheck.settings[:
|
178
|
-
PuppetCheck.settings[:regression_check] = true # in progress, do not use
|
179
|
+
PuppetCheck.settings[:smoke] = true
|
180
|
+
PuppetCheck.settings[:regression] = true # in progress, do not use
|
179
181
|
PuppetCheck.settings[:public] = 'public.pem'
|
180
182
|
PuppetCheck.settings[:private] = 'private.pem'
|
181
183
|
PuppetCheck.settings[:output_format] = 'yaml'
|
@@ -256,11 +258,10 @@ If you are performing your Puppet testing from within a Ruby script or your own
|
|
256
258
|
require 'puppet-check'
|
257
259
|
|
258
260
|
settings = {}
|
259
|
-
settings[:future_parser] = true # default false
|
260
261
|
settings[:fail_on_warnings] = true # default false
|
261
|
-
settings[:
|
262
|
-
settings[:
|
263
|
-
settings[:
|
262
|
+
settings[:style] = true # default false
|
263
|
+
settings[:smoke] = true # default false
|
264
|
+
settings[:regression] = true # in progress, do not use; default false
|
264
265
|
settings[:public] = 'public.pem' # default nil
|
265
266
|
settings[:private] = 'private.pem' # default nil
|
266
267
|
settings[:output_format] = 'yaml' # also 'json'; default 'text'
|
@@ -280,15 +281,15 @@ task.pattern = Dir.glob('**/{classes,defines,facter,functions,hosts,puppet,unit,
|
|
280
281
|
|
281
282
|
### Docker
|
282
283
|
|
283
|
-
You can also use Puppet Check inside of Docker for quick, portable, and disposable testing. Below is an example Dockerfile for this purpose:
|
284
|
+
You can also use Puppet Check inside of Docker for quick, portable, and disposable testing. Below is an example `Dockerfile` for this purpose:
|
284
285
|
|
285
286
|
```dockerfile
|
286
|
-
# a reliable and small container
|
287
|
-
FROM ubuntu:
|
287
|
+
# a reliable and small container; today should maybe use ruby:slim instead
|
288
|
+
FROM ubuntu:20.04
|
288
289
|
# you need ruby and any other extra dependencies that come from packages; in this example we install git to use it for downloading external module dependencies
|
289
290
|
RUN apt-get update && apt-get install ruby git -y
|
290
|
-
# you need puppet-check and any other extra dependencies that come from gems; in this example we install
|
291
|
-
RUN gem install --no-document puppet-check
|
291
|
+
# you need puppet-check and any other extra dependencies that come from gems; in this example we install rspec-puppet and rake for extra testing
|
292
|
+
RUN gem install --no-document puppet-check rspec-puppet rake
|
292
293
|
# this is needed for the ruby json parser to not flip out on fresh os installs for some reason (change encoding value as necessary)
|
293
294
|
ENV LANG en_US.UTF-8
|
294
295
|
# create the directory for your module, directory environment, etc. and change directory into it
|
@@ -299,24 +300,26 @@ COPY / .
|
|
299
300
|
ENTRYPOINT ["rake", "puppetcheck"]
|
300
301
|
```
|
301
302
|
|
302
|
-
You can also build your own general container for testing various Puppet situations by removing the last three lines. You can then test each module, directory environment, etc. on top of that container by merely adding and modifying the final three lines to a Dockerfile that uses the container you built from the first four lines. This is recommended usage due to being very efficient and stable.
|
303
|
+
You can also build your own general container image for testing various Puppet situations by removing the last three lines. You can then test each module, directory environment, etc. on top of that container by merely adding and modifying the final three lines to a `Dockerfile` that uses the container you built from the first four lines. This is recommended usage due to being very efficient and stable.
|
304
|
+
|
305
|
+
As an alternative to copying Puppet code and data into the image for testing, it is also recommended to bind volume mount the container to the directory with your Puppet code and data.
|
303
306
|
|
304
307
|
### Vagrant
|
305
308
|
|
306
|
-
As an alternative to Docker, you can also use Vagrant for quick and disposable testing, but it is not as portable as Docker for these testing purposes. Below is an example Vagrantfile for this purpose.
|
309
|
+
As an alternative to Docker, you can also use Vagrant for quick and disposable testing, but it is not as portable as Docker for these testing purposes. Below is an example `Vagrantfile` for this purpose.
|
307
310
|
|
308
311
|
```ruby
|
309
312
|
Vagrant.configure(2) do |config|
|
310
313
|
# a reliable and small box at the moment
|
311
|
-
config.vm.box = 'fedora/
|
314
|
+
config.vm.box = 'fedora/35-cloud-base'
|
312
315
|
|
313
316
|
config.vm.provision 'shell', inline: <<-SHELL
|
314
317
|
# cd to '/vagrant'
|
315
318
|
cd /vagrant
|
316
319
|
# you need ruby and any other extra dependencies that come from packages; in this example we install git to use it for downloading external module dependencies
|
317
320
|
sudo dnf install ruby rubygems git -y
|
318
|
-
# you need puppet-check and any other extra dependencies that come from gems; in this example we install
|
319
|
-
sudo gem install --no-document puppet-check
|
321
|
+
# you need puppet-check and any other extra dependencies that come from gems; in this example we install rspec-puppet and rake for extra testing
|
322
|
+
sudo gem install --no-document puppet-check rspec-puppet rake
|
320
323
|
# this is needed for the ruby json parser to not flip out on fresh os installs for some reason (change encoding value as necessary)
|
321
324
|
export LANG='en_US.UTF-8'
|
322
325
|
# execute your tests; in this example we are executing the full suite of tests
|
@@ -330,7 +333,7 @@ To overcome the lack of convenient portability, you could try spinning up the Va
|
|
330
333
|
### Exit Codes
|
331
334
|
- 0: PuppetCheck exited with no internal exceptions or errors in your code and data.
|
332
335
|
- 1: PuppetCheck exited with an internal exception (takes preference over other non-zero exit codes) or failed spec test(s).
|
333
|
-
- 2: PuppetCheck exited with one or more errors in your code and data. Alternatively, PuppetCheck exited with one or more warnings in your code and data and you specified to fail on warnings.
|
336
|
+
- 2: PuppetCheck exited with one or more errors in your code and data. Alternatively, PuppetCheck exited with one or more warnings in your code and data, and you specified to fail on warnings.
|
334
337
|
|
335
338
|
### Optional Dependencies
|
336
339
|
- **rake** (gem): install this if you want to use Puppet Check with `rake` tasks in addition to the CLI.
|
data/lib/puppet-check/cli.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'optparse'
|
2
|
-
require_relative '../
|
2
|
+
require_relative '../puppet_check'
|
3
3
|
|
4
4
|
# the command line interface for PuppetCheck
|
5
5
|
class PuppetCheck::CLI
|
@@ -27,16 +27,15 @@ class PuppetCheck::CLI
|
|
27
27
|
|
28
28
|
# base options
|
29
29
|
opts.on('--version', 'Display the current version.') do
|
30
|
-
puts 'puppet-check 1.
|
30
|
+
puts 'puppet-check 2.1.0'
|
31
31
|
exit 0
|
32
32
|
end
|
33
33
|
|
34
34
|
# bool options
|
35
|
-
opts.on('-f', '--future', 'Enable future parser') { settings[:future_parser] = true }
|
36
35
|
opts.on('--fail-on-warnings', 'Fail on warnings') { settings[:fail_on_warnings] = true }
|
37
|
-
opts.on('-s', '--style', 'Enable style checks') { settings[:
|
38
|
-
opts.on('--smoke', 'Enable smoke testing') { settings[:
|
39
|
-
opts.on('-r', '--regression', 'Enable regression testing (in progress, do not use)') { settings[:
|
36
|
+
opts.on('-s', '--style', 'Enable style checks') { settings[:style] = true }
|
37
|
+
opts.on('--smoke', 'Enable smoke testing') { settings[:smoke] = true }
|
38
|
+
opts.on('-r', '--regression', 'Enable regression testing (in progress, do not use)') { settings[:regression] = true }
|
40
39
|
|
41
40
|
# ssl key options for eyaml checks
|
42
41
|
opts.on('--public cert.pem', String, 'Public key for EYAML checks') { |arg| settings[:public] = arg }
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '../
|
1
|
+
require_relative '../puppet_check'
|
2
2
|
|
3
3
|
# executes diagnostics on data files
|
4
4
|
class DataParser
|
@@ -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,7 +97,7 @@ 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
|
100
|
+
# skip if key is missing or value is an empty string, array, or hash
|
101
101
|
next if !parsed.key?(key) || parsed[key].empty?
|
102
102
|
|
103
103
|
# check that dependencies and requirements are an array of hashes
|
@@ -118,8 +118,8 @@ class DataParser
|
|
118
118
|
next warnings.push("'#{req_dep['name']}' is missing an upper bound.") unless req_dep['version_requirement'].include?('<')
|
119
119
|
|
120
120
|
# check for semantic versioning
|
121
|
-
if key == 'dependencies'
|
122
|
-
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.")
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
@@ -161,16 +161,8 @@ class DataParser
|
|
161
161
|
end
|
162
162
|
|
163
163
|
# check for spdx license
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
if parsed.key?('license') && !Gem::Licenses.match?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
|
168
|
-
warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/")
|
169
|
-
end
|
170
|
-
rescue LoadError
|
171
|
-
if parsed.key?('license') && !SpdxLicenses.exist?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
|
172
|
-
warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/")
|
173
|
-
end
|
164
|
+
if parsed.key?('license') && !Gem::Licenses.match?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/
|
165
|
+
warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/")
|
174
166
|
end
|
175
167
|
# assume this is task metadata if it has this key
|
176
168
|
elsif parsed.key?('description')
|
@@ -185,16 +177,16 @@ class DataParser
|
|
185
177
|
end
|
186
178
|
end
|
187
179
|
# check that parameters is a hash
|
188
|
-
if parsed.key?('parameters')
|
189
|
-
warnings.push('parameters value is not a Hash')
|
180
|
+
if parsed.key?('parameters') && !parsed['parameters'].is_a?(Hash)
|
181
|
+
warnings.push('parameters value is not a Hash')
|
190
182
|
end
|
191
183
|
# check that puppet_task_version is an integer
|
192
|
-
if parsed.key?('puppet_task_version')
|
193
|
-
warnings.push('puppet_task_version value is not 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')
|
194
186
|
end
|
195
187
|
# check that supports_noop is a boolean
|
196
|
-
if parsed.key?('supports_noop')
|
197
|
-
warnings.push('supports_noop value is not 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')
|
198
190
|
end
|
199
191
|
# assume this is hieradata and ensure it is non-empty
|
200
192
|
elsif parsed
|
@@ -213,7 +205,7 @@ class DataParser
|
|
213
205
|
warnings = []
|
214
206
|
|
215
207
|
# disregard nil/undef value data check if default values (common)
|
216
|
-
unless
|
208
|
+
unless /^common/.match?(file)
|
217
209
|
data.each do |key, value|
|
218
210
|
# check for nil values in the data (nil keys are fine)
|
219
211
|
if (value.is_a?(Hash) && value.values.any?(&:nil?)) || value.nil?
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '../
|
1
|
+
require_relative '../puppet_check'
|
2
2
|
|
3
3
|
# class to handle outputting diagnostic results in desired format
|
4
4
|
class OutputResults
|
@@ -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(format)
|
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 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 '#{format}' was specified."
|
42
43
|
end
|
43
44
|
end
|
44
45
|
end
|
@@ -1,42 +1,51 @@
|
|
1
1
|
require 'puppet'
|
2
|
-
require_relative '../
|
2
|
+
require_relative '../puppet_check'
|
3
3
|
|
4
4
|
# executes diagnostics on puppet files
|
5
5
|
class PuppetParser
|
6
6
|
# checks puppet (.pp)
|
7
|
-
def self.manifest(files,
|
7
|
+
def self.manifest(files, style, pl_args)
|
8
8
|
require 'puppet/face'
|
9
9
|
|
10
10
|
# prepare the Puppet settings for the error checking
|
11
11
|
Puppet.initialize_settings unless Puppet.settings.app_defaults_initialized?
|
12
|
-
Puppet[:parser] = 'future' if future && (Puppet::PUPPETVERSION.to_i < 4)
|
13
12
|
|
14
13
|
files.each do |file|
|
15
|
-
# setup error logging and collection
|
14
|
+
# setup error logging and collection; warnings logged for all versions, but errors for only puppet < 6.5
|
16
15
|
errors = []
|
17
16
|
Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(errors))
|
18
17
|
|
19
18
|
# check puppet syntax
|
20
19
|
begin
|
21
|
-
|
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
|
22
28
|
# this is the actual error that we need to rescue Puppet::Face from
|
23
29
|
rescue SystemExit
|
24
|
-
# puppet 5.4-
|
25
|
-
if Puppet::PUPPETVERSION
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
# puppet 5.4-6.4 has a new validator output format and eof errors have fake dir env info
|
31
|
+
message = if Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('5.4') && Gem::Version.new(Puppet::PUPPETVERSION) < Gem::Version.new('6.5')
|
32
|
+
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
|
+
errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '').gsub(/Could not parse.*: /, '')
|
36
|
+
# puppet < 5 and 5.3 parser output style
|
37
|
+
else
|
38
|
+
errors.map(&:to_s).join("\n").gsub("#{File.absolute_path(file)}:", '')
|
39
|
+
end
|
33
40
|
end
|
41
|
+
# output message
|
42
|
+
next PuppetCheck.settings[:error_files].push("#{file}:\n#{message}") unless message.empty?
|
34
43
|
|
35
44
|
# initialize warnings with output from the parser if it exists, since the output is warnings if Puppet::Face did not trigger a SystemExit
|
36
45
|
warnings = "#{file}:"
|
37
46
|
unless errors.empty?
|
38
47
|
# puppet 5.4-5.x has a new validator output format
|
39
|
-
warnings << if Puppet::PUPPETVERSION
|
48
|
+
warnings << if Gem::Version.new(Puppet::PUPPETVERSION) >= Gem::Version.new('5.4')
|
40
49
|
"\n#{errors.map(&:to_s).join("\n").gsub("file: #{File.absolute_path(file)}, ", '')}"
|
41
50
|
# puppet <= 5.3 validator output format
|
42
51
|
else
|
@@ -77,9 +86,6 @@ class PuppetParser
|
|
77
86
|
require 'puppet/pops'
|
78
87
|
|
79
88
|
files.each do |file|
|
80
|
-
# puppet before version 4 cannot check template syntax
|
81
|
-
next PuppetCheck.settings[:ignored_files].push("#{file}: ignored due to Puppet < 4") if Puppet::PUPPETVERSION.to_i < 4
|
82
|
-
|
83
89
|
# check puppet template syntax
|
84
90
|
begin
|
85
91
|
# credits to gds-operations/puppet-syntax for the parser function call
|
@@ -3,7 +3,7 @@ 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
|
@@ -15,10 +15,10 @@ class RSpecPuppetSupport
|
|
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))
|
@@ -66,7 +66,7 @@ class RSpecPuppetSupport
|
|
66
66
|
parsed = JSON.parse(File.read('metadata.json'))
|
67
67
|
|
68
68
|
# grab dependencies if they exist
|
69
|
-
return
|
69
|
+
return unless parsed.key?('dependencies')
|
70
70
|
parsed['dependencies'].each do |dependency_hash|
|
71
71
|
# determine how the user wants to download the module dependency
|
72
72
|
if dependency_hash.key?('git')
|
@@ -81,6 +81,7 @@ class RSpecPuppetSupport
|
|
81
81
|
warn "#{dependency_hash['name']} has an unspecified, or specified but unsupported, download method."
|
82
82
|
end
|
83
83
|
end
|
84
|
+
Process.waitall
|
84
85
|
end
|
85
86
|
|
86
87
|
# download external module dependency with git
|
@@ -89,7 +90,11 @@ class RSpecPuppetSupport
|
|
89
90
|
# establish path to clone module to
|
90
91
|
path = "spec/fixtures/modules/#{File.basename(git_url, '.git')}"
|
91
92
|
# is the module present and already cloned with git? do a pull; otherwise, do a clone
|
92
|
-
|
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
|
93
98
|
end
|
94
99
|
|
95
100
|
# download external module dependency with forge
|
@@ -97,7 +102,7 @@ class RSpecPuppetSupport
|
|
97
102
|
private_class_method :method
|
98
103
|
# is the module present? do an upgrade; otherwise, do an install
|
99
104
|
subcommand = File.directory?("spec/fixtures/modules/#{forge_name}") ? 'upgrade' : 'install'
|
100
|
-
|
105
|
+
spawn("puppet module #{subcommand} --modulepath spec/fixtures/modules/ #{args} #{forge_name}")
|
101
106
|
end
|
102
107
|
|
103
108
|
# download external module dependency with svn
|
@@ -106,7 +111,11 @@ class RSpecPuppetSupport
|
|
106
111
|
# establish path to checkout module to
|
107
112
|
path = "spec/fixtures/modules/#{File.basename(svn_url)}"
|
108
113
|
# is the module present and already checked out with svn? do an update; otherwise, do a checkout
|
109
|
-
|
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
|
110
119
|
end
|
111
120
|
|
112
121
|
# download external module dependency with hg
|
@@ -115,6 +124,10 @@ class RSpecPuppetSupport
|
|
115
124
|
# establish path to clone module to
|
116
125
|
path = "spec/fixtures/modules/#{File.basename(hg_url)}"
|
117
126
|
# is the module present and already cloned with hg? do a pull and update; otherwise do a clone
|
118
|
-
|
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
|
119
132
|
end
|
120
133
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '../
|
1
|
+
require_relative '../puppet_check'
|
2
2
|
require_relative 'utils'
|
3
3
|
|
4
4
|
# executes diagnostics on ruby files
|
@@ -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
|
@@ -43,8 +43,14 @@ class RubyParser
|
|
43
43
|
# check ruby template syntax
|
44
44
|
begin
|
45
45
|
# need to eventually have this associated with a different binding during each iteration
|
46
|
-
|
47
|
-
|
46
|
+
# older usage throws extra warning and mixes with valid warnings confusingly
|
47
|
+
warnings = if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
|
48
|
+
Utils.capture_stderr { ERB.new(File.read(file), trim_mode: '-').result }
|
49
|
+
# ERB.new(File.read(file), trim_mode: '-').result(RubyParser.new.bind)
|
50
|
+
# and for extra fun it is incompatible with non-new ruby
|
51
|
+
else
|
52
|
+
Utils.capture_stderr { ERB.new(File.read(file), nil, '-').result }
|
53
|
+
end
|
48
54
|
rescue NameError, TypeError
|
49
55
|
# empty out warnings since it would contain an error if this pass triggers
|
50
56
|
warnings = ''
|
@@ -62,10 +68,9 @@ class RubyParser
|
|
62
68
|
# efficient var assignment prior to iterator
|
63
69
|
if style
|
64
70
|
require 'rubocop'
|
65
|
-
|
66
|
-
filename_cop = RuboCop::Version::STRING.to_f >= 0.5 ? 'Naming/FileName' : 'Style/FileName'
|
71
|
+
|
67
72
|
# 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]}
|
73
|
+
rc_args.include?('--except') ? rc_args[rc_args.index('--except') + 1] = "#{rc_args[rc_args.index('--except') + 1]},Naming/FileName" : rc_args.concat(['--except', 'Naming/FileName'])
|
69
74
|
end
|
70
75
|
|
71
76
|
files.each do |file|
|
@@ -79,7 +84,7 @@ class RubyParser
|
|
79
84
|
else
|
80
85
|
if style
|
81
86
|
# check Rubocop
|
82
|
-
warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--format', 'emacs', file]) }
|
87
|
+
warnings = Utils.capture_stdout { RuboCop::CLI.new.run(rc_args + ['--require', 'rubocop-performance', '--format', 'emacs', file]) }
|
83
88
|
|
84
89
|
# collect style warnings
|
85
90
|
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
@@ -3,7 +3,7 @@ begin
|
|
3
3
|
rescue LoadError
|
4
4
|
raise 'Rake is not installed and you are attempting to execute Rake tasks with Puppet Check. Please install Rake before continuing.'
|
5
5
|
end
|
6
|
-
require_relative '../
|
6
|
+
require_relative '../puppet_check'
|
7
7
|
|
8
8
|
# the rake interface for PuppetCheck
|
9
9
|
class PuppetCheck::Tasks < ::Rake::TaskLib
|