pdk 1.9.0 → 3.2.0
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 +744 -711
- data/README.md +23 -21
- data/lib/pdk/answer_file.rb +3 -112
- data/lib/pdk/bolt.rb +20 -0
- data/lib/pdk/cli/build.rb +51 -54
- data/lib/pdk/cli/bundle.rb +33 -29
- data/lib/pdk/cli/console.rb +148 -0
- data/lib/pdk/cli/convert.rb +46 -37
- data/lib/pdk/cli/env.rb +51 -0
- data/lib/pdk/cli/errors.rb +4 -3
- data/lib/pdk/cli/exec/command.rb +285 -0
- data/lib/pdk/cli/exec/interactive_command.rb +109 -0
- data/lib/pdk/cli/exec.rb +32 -201
- data/lib/pdk/cli/exec_group.rb +79 -43
- data/lib/pdk/cli/get/config.rb +26 -0
- data/lib/pdk/cli/get.rb +22 -0
- data/lib/pdk/cli/new/class.rb +20 -22
- data/lib/pdk/cli/new/defined_type.rb +21 -21
- data/lib/pdk/cli/new/fact.rb +27 -0
- data/lib/pdk/cli/new/function.rb +27 -0
- data/lib/pdk/cli/new/module.rb +40 -29
- data/lib/pdk/cli/new/provider.rb +18 -18
- data/lib/pdk/cli/new/task.rb +23 -22
- data/lib/pdk/cli/new/test.rb +52 -0
- data/lib/pdk/cli/new/transport.rb +27 -0
- data/lib/pdk/cli/new.rb +15 -9
- data/lib/pdk/cli/release/prep.rb +39 -0
- data/lib/pdk/cli/release/publish.rb +46 -0
- data/lib/pdk/cli/release.rb +185 -0
- data/lib/pdk/cli/remove/config.rb +83 -0
- data/lib/pdk/cli/remove.rb +22 -0
- data/lib/pdk/cli/set/config.rb +121 -0
- data/lib/pdk/cli/set.rb +22 -0
- data/lib/pdk/cli/test/unit.rb +71 -69
- data/lib/pdk/cli/test.rb +9 -8
- data/lib/pdk/cli/update.rb +38 -21
- data/lib/pdk/cli/util/command_redirector.rb +13 -3
- data/lib/pdk/cli/util/interview.rb +25 -9
- data/lib/pdk/cli/util/option_normalizer.rb +6 -6
- data/lib/pdk/cli/util/option_validator.rb +19 -9
- data/lib/pdk/cli/util/spinner.rb +13 -0
- data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
- data/lib/pdk/cli/util.rb +105 -48
- data/lib/pdk/cli/validate.rb +96 -111
- data/lib/pdk/cli.rb +134 -87
- data/lib/pdk/config/errors.rb +5 -0
- data/lib/pdk/config/ini_file.rb +184 -0
- data/lib/pdk/config/ini_file_setting.rb +35 -0
- data/lib/pdk/config/json.rb +35 -0
- data/lib/pdk/config/json_schema_namespace.rb +137 -0
- data/lib/pdk/config/json_schema_setting.rb +51 -0
- data/lib/pdk/config/json_with_schema.rb +47 -0
- data/lib/pdk/config/namespace.rb +362 -0
- data/lib/pdk/config/setting.rb +134 -0
- data/lib/pdk/config/task_schema.json +116 -0
- data/lib/pdk/config/validator.rb +31 -0
- data/lib/pdk/config/yaml.rb +41 -0
- data/lib/pdk/config/yaml_with_schema.rb +51 -0
- data/lib/pdk/config.rb +304 -0
- data/lib/pdk/context/control_repo.rb +61 -0
- data/lib/pdk/context/module.rb +28 -0
- data/lib/pdk/context/none.rb +22 -0
- data/lib/pdk/context.rb +98 -0
- data/lib/pdk/control_repo.rb +89 -0
- data/lib/pdk/generate/defined_type.rb +27 -33
- data/lib/pdk/generate/fact.rb +26 -0
- data/lib/pdk/generate/function.rb +49 -0
- data/lib/pdk/generate/module.rb +160 -153
- data/lib/pdk/generate/provider.rb +16 -69
- data/lib/pdk/generate/puppet_class.rb +27 -32
- data/lib/pdk/generate/puppet_object.rb +100 -159
- data/lib/pdk/generate/task.rb +34 -51
- data/lib/pdk/generate/transport.rb +34 -0
- data/lib/pdk/generate.rb +21 -8
- data/lib/pdk/logger.rb +24 -6
- data/lib/pdk/module/build.rb +125 -37
- data/lib/pdk/module/convert.rb +146 -65
- data/lib/pdk/module/metadata.rb +72 -71
- data/lib/pdk/module/release.rb +255 -0
- data/lib/pdk/module/update.rb +48 -37
- data/lib/pdk/module/update_manager.rb +75 -39
- data/lib/pdk/module.rb +10 -2
- data/lib/pdk/monkey_patches.rb +268 -0
- data/lib/pdk/report/event.rb +36 -48
- data/lib/pdk/report.rb +35 -22
- data/lib/pdk/template/fetcher/git.rb +84 -0
- data/lib/pdk/template/fetcher/local.rb +29 -0
- data/lib/pdk/template/fetcher.rb +100 -0
- data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +108 -0
- data/lib/pdk/template/renderer/v1/renderer.rb +131 -0
- data/lib/pdk/template/renderer/v1/template_file.rb +100 -0
- data/lib/pdk/template/renderer/v1.rb +25 -0
- data/lib/pdk/template/renderer.rb +97 -0
- data/lib/pdk/template/template_dir.rb +67 -0
- data/lib/pdk/template.rb +52 -0
- data/lib/pdk/tests/unit.rb +101 -51
- data/lib/pdk/util/bundler.rb +44 -42
- data/lib/pdk/util/changelog_generator.rb +138 -0
- data/lib/pdk/util/env.rb +48 -0
- data/lib/pdk/util/filesystem.rb +139 -2
- data/lib/pdk/util/git.rb +108 -8
- data/lib/pdk/util/json_finder.rb +86 -0
- data/lib/pdk/util/puppet_strings.rb +125 -0
- data/lib/pdk/util/puppet_version.rb +71 -87
- data/lib/pdk/util/ruby_version.rb +49 -25
- data/lib/pdk/util/template_uri.rb +283 -0
- data/lib/pdk/util/vendored_file.rb +34 -42
- data/lib/pdk/util/version.rb +11 -10
- data/lib/pdk/util/windows/api_types.rb +74 -44
- data/lib/pdk/util/windows/file.rb +31 -27
- data/lib/pdk/util/windows/process.rb +74 -0
- data/lib/pdk/util/windows/string.rb +19 -12
- data/lib/pdk/util/windows.rb +2 -0
- data/lib/pdk/util.rb +111 -124
- data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
- data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
- data/lib/pdk/validate/external_command_validator.rb +213 -0
- data/lib/pdk/validate/internal_ruby_validator.rb +101 -0
- data/lib/pdk/validate/invokable_validator.rb +238 -0
- data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +84 -0
- data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +76 -0
- data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
- data/lib/pdk/validate/puppet/puppet_epp_validator.rb +131 -0
- data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
- data/lib/pdk/validate/puppet/puppet_plan_syntax_validator.rb +38 -0
- data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +135 -0
- data/lib/pdk/validate/puppet/puppet_validator_group.rb +22 -0
- data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +79 -0
- data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
- data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +83 -0
- data/lib/pdk/validate/tasks/tasks_name_validator.rb +45 -0
- data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
- data/lib/pdk/validate/validator.rb +120 -0
- data/lib/pdk/validate/validator_group.rb +107 -0
- data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +86 -0
- data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
- data/lib/pdk/validate.rb +86 -12
- data/lib/pdk/version.rb +2 -2
- data/lib/pdk.rb +60 -10
- metadata +138 -100
- data/lib/pdk/cli/module/build.rb +0 -14
- data/lib/pdk/cli/module/generate.rb +0 -45
- data/lib/pdk/cli/module.rb +0 -14
- data/lib/pdk/i18n.rb +0 -4
- data/lib/pdk/module/templatedir.rb +0 -321
- data/lib/pdk/template_file.rb +0 -95
- data/lib/pdk/validate/base_validator.rb +0 -215
- data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -86
- data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -109
- data/lib/pdk/validate/metadata_validator.rb +0 -30
- data/lib/pdk/validate/puppet/puppet_lint.rb +0 -67
- data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -112
- data/lib/pdk/validate/puppet_validator.rb +0 -30
- data/lib/pdk/validate/ruby/rubocop.rb +0 -77
- data/lib/pdk/validate/ruby_validator.rb +0 -29
- data/lib/pdk/validate/tasks/metadata_lint.rb +0 -126
- data/lib/pdk/validate/tasks/name.rb +0 -88
- data/lib/pdk/validate/tasks_validator.rb +0 -33
- data/lib/pdk/validate/yaml/syntax.rb +0 -109
- data/lib/pdk/validate/yaml_validator.rb +0 -31
- data/locales/config.yaml +0 -21
- data/locales/pdk.pot +0 -1291
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Metadata
|
|
6
|
+
class MetadataSyntaxValidator < InternalRubyValidator
|
|
7
|
+
def name
|
|
8
|
+
'metadata-syntax'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def pattern
|
|
12
|
+
contextual_pattern(['metadata.json', 'tasks/*.json'])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def spinner_text
|
|
16
|
+
format('Checking metadata syntax (%{patterns}).', patterns: pattern.join(' '))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def invoke(report)
|
|
20
|
+
super
|
|
21
|
+
ensure
|
|
22
|
+
JSON.parser = JSON::Ext::Parser if defined?(JSON::Ext::Parser)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def before_validation
|
|
26
|
+
# The pure ruby JSON parser gives much nicer parse error messages than
|
|
27
|
+
# the C extension at the cost of slightly slower parsing. We require it
|
|
28
|
+
# here and restore the C extension at the end of the method (if it was
|
|
29
|
+
# being used).
|
|
30
|
+
require 'json/pure'
|
|
31
|
+
JSON.parser = JSON::Pure::Parser
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def validate_target(report, target)
|
|
35
|
+
unless PDK::Util::Filesystem.readable?(target)
|
|
36
|
+
report.add_event(
|
|
37
|
+
file: target,
|
|
38
|
+
source: name,
|
|
39
|
+
state: :failure,
|
|
40
|
+
severity: 'error',
|
|
41
|
+
message: 'Could not be read.'
|
|
42
|
+
)
|
|
43
|
+
return 1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
JSON.parse(PDK::Util::Filesystem.read_file(target))
|
|
48
|
+
|
|
49
|
+
report.add_event(
|
|
50
|
+
file: target,
|
|
51
|
+
source: name,
|
|
52
|
+
state: :passed,
|
|
53
|
+
severity: 'ok'
|
|
54
|
+
)
|
|
55
|
+
0
|
|
56
|
+
rescue JSON::ParserError => e
|
|
57
|
+
# Because the message contains a raw segment of the file, we use
|
|
58
|
+
# String#dump here to unescape any escape characters like newlines.
|
|
59
|
+
# We then strip out the surrounding quotes and the exclaimation
|
|
60
|
+
# point that json_pure likes to put in exception messages.
|
|
61
|
+
sane_message = e.message.dump[/\A"(.+?)!?"\Z/, 1]
|
|
62
|
+
|
|
63
|
+
report.add_event(
|
|
64
|
+
file: target,
|
|
65
|
+
source: name,
|
|
66
|
+
state: :failure,
|
|
67
|
+
severity: 'error',
|
|
68
|
+
message: sane_message
|
|
69
|
+
)
|
|
70
|
+
1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Metadata
|
|
6
|
+
class MetadataValidatorGroup < ValidatorGroup
|
|
7
|
+
def name
|
|
8
|
+
'metadata'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def validators
|
|
12
|
+
[
|
|
13
|
+
MetadataSyntaxValidator,
|
|
14
|
+
MetadataJSONLintValidator
|
|
15
|
+
].freeze
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Puppet
|
|
6
|
+
class PuppetEPPValidator < ExternalCommandValidator
|
|
7
|
+
# In Puppet >= 5.3.4, the error context formatting was changed to facilitate localization
|
|
8
|
+
ERROR_CONTEXT = /(?:file:\s(?<file>.+?)|line:\s(?<line>.+?)|column:\s(?<column>.+?))/.freeze
|
|
9
|
+
# In Puppet < 5.3.3, the error context was formatted in these variations:
|
|
10
|
+
# - "at file_path:line_num:col_num"
|
|
11
|
+
# - "at file_path:line_num"
|
|
12
|
+
# - "at line line_num"
|
|
13
|
+
# - "in file_path"
|
|
14
|
+
ERROR_CONTEXT_LEGACY = /(?:at\sline\s(?<line>\d+)|at\s(?<file>.+?):(?<line>\d+):(?<column>\d+)|at\s(?<file>.+?):(?<line>\d+)|in\s(?<file>.+?))/.freeze
|
|
15
|
+
|
|
16
|
+
PUPPET_LOGGER_PREFIX = /^(debug|info|notice|warning|error|alert|critical):\s.+?$/i.freeze
|
|
17
|
+
PUPPET_SYNTAX_PATTERN = /^
|
|
18
|
+
(?<severity>.+?):\s
|
|
19
|
+
(?<message>.+?)
|
|
20
|
+
(?:
|
|
21
|
+
\s\(#{ERROR_CONTEXT}(,\s#{ERROR_CONTEXT})*\)| # attempt to match the new localisation friendly location
|
|
22
|
+
\s#{ERROR_CONTEXT_LEGACY}| # attempt to match the old " at file:line:column" location
|
|
23
|
+
$ # handle cases where the output has no location
|
|
24
|
+
)
|
|
25
|
+
$/x.freeze
|
|
26
|
+
|
|
27
|
+
def name
|
|
28
|
+
'puppet-epp'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def cmd
|
|
32
|
+
'puppet'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def pattern
|
|
36
|
+
contextual_pattern('**/*.epp')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def spinner_text_for_targets(_targets)
|
|
40
|
+
format('Checking Puppet EPP syntax (%{pattern}).', pattern: pattern.join(' '))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def parse_options(targets)
|
|
44
|
+
# Due to PDK-1266 we need to run `puppet parser validate` with an empty
|
|
45
|
+
# modulepath. On *nix, Ruby treats `/dev/null` as an empty directory
|
|
46
|
+
# however it doesn't do so with `NUL` on Windows. The workaround for
|
|
47
|
+
# this to ensure consistent behaviour is to create an empty temporary
|
|
48
|
+
# directory and use that as the modulepath.
|
|
49
|
+
['epp', 'validate', '--config', null_file, '--modulepath', validate_tmpdir].concat(targets)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def invoke(report)
|
|
53
|
+
super
|
|
54
|
+
ensure
|
|
55
|
+
remove_validate_tmpdir
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def validate_tmpdir
|
|
59
|
+
require 'tmpdir'
|
|
60
|
+
|
|
61
|
+
@validate_tmpdir ||= Dir.mktmpdir('puppet-epp-validate')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def remove_validate_tmpdir
|
|
65
|
+
return unless @validate_tmpdir
|
|
66
|
+
return unless PDK::Util::Filesystem.directory?(@validate_tmpdir)
|
|
67
|
+
|
|
68
|
+
PDK::Util::Filesystem.remove_entry_secure(@validate_tmpdir)
|
|
69
|
+
@validate_tmpdir = nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def null_file
|
|
73
|
+
Gem.win_platform? ? 'NUL' : '/dev/null'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def parse_output(report, result, targets)
|
|
77
|
+
# Due to PUP-7504, we will have to programmatically construct the json
|
|
78
|
+
# object from the text output for now.
|
|
79
|
+
output = result[:stderr].split(/\r?\n/).reject(&:empty?)
|
|
80
|
+
|
|
81
|
+
results_data = []
|
|
82
|
+
output.each do |offense|
|
|
83
|
+
offense_data = parse_offense(offense)
|
|
84
|
+
results_data << offense_data
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# puppet parser validate does not include files without problems in its
|
|
88
|
+
# output, so we need to go through the list of targets and add passing
|
|
89
|
+
# events to the report for any target not listed in the output.
|
|
90
|
+
targets.reject { |target| results_data.any? { |j| j[:file] =~ /#{target}/ } }.each do |target|
|
|
91
|
+
report.add_event(
|
|
92
|
+
file: target,
|
|
93
|
+
source: name,
|
|
94
|
+
severity: :ok,
|
|
95
|
+
state: :passed
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
results_data.each do |offense|
|
|
100
|
+
report.add_event(offense)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def parse_offense(offense)
|
|
105
|
+
sanitize_console_output(offense)
|
|
106
|
+
|
|
107
|
+
offense_data = {
|
|
108
|
+
source: name,
|
|
109
|
+
state: :failure
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if offense.match(PUPPET_LOGGER_PREFIX)
|
|
113
|
+
attributes = offense.match(PUPPET_SYNTAX_PATTERN)
|
|
114
|
+
|
|
115
|
+
attributes&.names&.each do |name|
|
|
116
|
+
offense_data[name.to_sym] = attributes[name] unless attributes[name].nil?
|
|
117
|
+
end
|
|
118
|
+
else
|
|
119
|
+
offense_data[:message] = offense
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
offense_data
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def sanitize_console_output(line)
|
|
126
|
+
line.gsub!(/\e\[([;\d]+)?m/, '')
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Puppet
|
|
6
|
+
class PuppetLintValidator < ExternalCommandValidator
|
|
7
|
+
def name
|
|
8
|
+
'puppet-lint'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cmd
|
|
12
|
+
'puppet-lint'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pattern
|
|
16
|
+
contextual_pattern('**/*.pp')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def spinner_text_for_targets(_targets)
|
|
20
|
+
format('Checking Puppet manifest style (%{pattern}).', pattern: pattern.join(' '))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def parse_options(targets)
|
|
24
|
+
cmd_options = ['--json', '--relative']
|
|
25
|
+
|
|
26
|
+
cmd_options << '--fix' if options[:auto_correct]
|
|
27
|
+
|
|
28
|
+
cmd_options.concat(targets)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parse_output(report, result, targets)
|
|
32
|
+
begin
|
|
33
|
+
json_data = JSON.parse(result[:stdout]).flatten
|
|
34
|
+
rescue JSON::ParserError
|
|
35
|
+
raise PDK::Validate::ParseOutputError, result[:stdout]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# puppet-lint does not include files without problems in its JSON
|
|
39
|
+
# output, so we need to go through the list of targets and add passing
|
|
40
|
+
# events to the report for any target not listed in the JSON output.
|
|
41
|
+
targets.reject { |target| json_data.any? { |j| j['path'] == target } }.each do |target|
|
|
42
|
+
report.add_event(
|
|
43
|
+
file: target,
|
|
44
|
+
source: name,
|
|
45
|
+
severity: 'ok',
|
|
46
|
+
state: :passed
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
json_data.each do |offense|
|
|
51
|
+
report.add_event({
|
|
52
|
+
file: offense['path'],
|
|
53
|
+
source: name,
|
|
54
|
+
line: offense['line'],
|
|
55
|
+
column: offense['column'],
|
|
56
|
+
message: offense['message'],
|
|
57
|
+
test: offense['check'],
|
|
58
|
+
severity: offense['kind'] == 'fixed' ? 'corrected' : offense['kind'],
|
|
59
|
+
state: :failure
|
|
60
|
+
})
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Puppet
|
|
6
|
+
class PuppetPlanSyntaxValidator < PuppetSyntaxValidator
|
|
7
|
+
def name
|
|
8
|
+
'puppet-plan-syntax'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def pattern
|
|
12
|
+
contextual_pattern('plans/**/*.pp')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pattern_ignore; end
|
|
16
|
+
|
|
17
|
+
def spinner_text_for_targets(_targets)
|
|
18
|
+
format('Checking Puppet plan syntax (%{pattern}).', pattern: pattern.join(' '))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parse_options(targets)
|
|
22
|
+
# Due to PDK-1266 we need to run `puppet parser validate` with an empty
|
|
23
|
+
# modulepath. On *nix, Ruby treats `/dev/null` as an empty directory
|
|
24
|
+
# however it doesn't do so with `NUL` on Windows. The workaround for
|
|
25
|
+
# this to ensure consistent behaviour is to create an empty temporary
|
|
26
|
+
# directory and use that as the modulepath.
|
|
27
|
+
['parser', 'validate', '--tasks', '--config', null_file, '--modulepath', validate_tmpdir].concat(targets)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def validate_tmpdir
|
|
31
|
+
require 'tmpdir'
|
|
32
|
+
|
|
33
|
+
@validate_tmpdir ||= Dir.mktmpdir('puppet-plan-parser-validate')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Puppet
|
|
6
|
+
class PuppetSyntaxValidator < ExternalCommandValidator
|
|
7
|
+
# In Puppet >= 5.3.4, the error context formatting was changed to facilitate localization
|
|
8
|
+
ERROR_CONTEXT = /(?:file:\s(?<file>.+?)|line:\s(?<line>.+?)|column:\s(?<column>.+?))/.freeze
|
|
9
|
+
# In Puppet < 5.3.3, the error context was formatted in these variations:
|
|
10
|
+
# - "at file_path:line_num:col_num"
|
|
11
|
+
# - "at file_path:line_num"
|
|
12
|
+
# - "at line line_num"
|
|
13
|
+
# - "in file_path"
|
|
14
|
+
ERROR_CONTEXT_LEGACY = /(?:at\sline\s(?<line>\d+)|at\s(?<file>.+?):(?<line>\d+):(?<column>\d+)|at\s(?<file>.+?):(?<line>\d+)|in\s(?<file>.+?))/.freeze
|
|
15
|
+
|
|
16
|
+
PUPPET_LOGGER_PREFIX = /^(debug|info|notice|warning|error|alert|critical):\s.+?$/i.freeze
|
|
17
|
+
PUPPET_SYNTAX_PATTERN = /^
|
|
18
|
+
(?<severity>.+?):\s
|
|
19
|
+
(?<message>.+?)
|
|
20
|
+
(?:
|
|
21
|
+
\s\(#{ERROR_CONTEXT}(,\s#{ERROR_CONTEXT})*\)| # attempt to match the new localisation friendly location
|
|
22
|
+
\s#{ERROR_CONTEXT_LEGACY}| # attempt to match the old " at file:line:column" location
|
|
23
|
+
$ # handle cases where the output has no location
|
|
24
|
+
)
|
|
25
|
+
$/x.freeze
|
|
26
|
+
|
|
27
|
+
def name
|
|
28
|
+
'puppet-syntax'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def cmd
|
|
32
|
+
'puppet'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def pattern
|
|
36
|
+
contextual_pattern('**/*.pp')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def pattern_ignore
|
|
40
|
+
contextual_pattern('plans/**/*.pp')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def spinner_text_for_targets(_targets)
|
|
44
|
+
format('Checking Puppet manifest syntax (%{pattern}).', pattern: pattern.join(' '))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def parse_options(targets)
|
|
48
|
+
# Due to PDK-1266 we need to run `puppet parser validate` with an empty
|
|
49
|
+
# modulepath. On *nix, Ruby treats `/dev/null` as an empty directory
|
|
50
|
+
# however it doesn't do so with `NUL` on Windows. The workaround for
|
|
51
|
+
# this to ensure consistent behaviour is to create an empty temporary
|
|
52
|
+
# directory and use that as the modulepath.
|
|
53
|
+
['parser', 'validate', '--config', null_file, '--modulepath', validate_tmpdir].concat(targets)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def invoke(report)
|
|
57
|
+
super
|
|
58
|
+
ensure
|
|
59
|
+
remove_validate_tmpdir
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def validate_tmpdir
|
|
63
|
+
require 'tmpdir'
|
|
64
|
+
|
|
65
|
+
@validate_tmpdir ||= Dir.mktmpdir('puppet-parser-validate')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def remove_validate_tmpdir
|
|
69
|
+
return unless @validate_tmpdir
|
|
70
|
+
return unless PDK::Util::Filesystem.directory?(@validate_tmpdir)
|
|
71
|
+
|
|
72
|
+
PDK::Util::Filesystem.remove_entry_secure(@validate_tmpdir)
|
|
73
|
+
@validate_tmpdir = nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def null_file
|
|
77
|
+
Gem.win_platform? ? 'NUL' : '/dev/null'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def parse_output(report, result, targets)
|
|
81
|
+
# Due to PUP-7504, we will have to programmatically construct the json
|
|
82
|
+
# object from the text output for now.
|
|
83
|
+
output = result[:stderr].split(/\r?\n/).reject(&:empty?)
|
|
84
|
+
|
|
85
|
+
results_data = []
|
|
86
|
+
output.each do |offense|
|
|
87
|
+
offense_data = parse_offense(offense)
|
|
88
|
+
results_data << offense_data
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# puppet parser validate does not include files without problems in its
|
|
92
|
+
# output, so we need to go through the list of targets and add passing
|
|
93
|
+
# events to the report for any target not listed in the output.
|
|
94
|
+
targets.reject { |target| results_data.any? { |j| j[:file] =~ /#{target}/ } }.each do |target|
|
|
95
|
+
report.add_event(
|
|
96
|
+
file: target,
|
|
97
|
+
source: name,
|
|
98
|
+
severity: :ok,
|
|
99
|
+
state: :passed
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
results_data.each do |offense|
|
|
104
|
+
report.add_event(offense)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def parse_offense(offense)
|
|
109
|
+
sanitize_console_output(offense)
|
|
110
|
+
|
|
111
|
+
offense_data = {
|
|
112
|
+
source: name,
|
|
113
|
+
state: :failure
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if offense.match(PUPPET_LOGGER_PREFIX)
|
|
117
|
+
attributes = offense.match(PUPPET_SYNTAX_PATTERN)
|
|
118
|
+
|
|
119
|
+
attributes&.names&.each do |name|
|
|
120
|
+
offense_data[name.to_sym] = attributes[name] unless attributes[name].nil?
|
|
121
|
+
end
|
|
122
|
+
else
|
|
123
|
+
offense_data[:message] = offense
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
offense_data
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def sanitize_console_output(line)
|
|
130
|
+
line.gsub!(/\e\[([;\d]+)?m/, '')
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Puppet
|
|
6
|
+
class PuppetValidatorGroup < ValidatorGroup
|
|
7
|
+
def name
|
|
8
|
+
'puppet'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def validators
|
|
12
|
+
[
|
|
13
|
+
PuppetSyntaxValidator,
|
|
14
|
+
PuppetPlanSyntaxValidator,
|
|
15
|
+
PuppetLintValidator,
|
|
16
|
+
PuppetEPPValidator
|
|
17
|
+
].freeze
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Ruby
|
|
6
|
+
class RubyRubocopValidator < ExternalCommandValidator
|
|
7
|
+
def allow_empty_targets?
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
'rubocop'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def cmd
|
|
16
|
+
'rubocop'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pattern
|
|
20
|
+
if context.is_a?(PDK::Context::ControlRepo)
|
|
21
|
+
['Puppetfile', '**/**.rb']
|
|
22
|
+
else
|
|
23
|
+
'**/**.rb'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def spinner_text_for_targets(_targets)
|
|
28
|
+
format('Checking Ruby code style (%{pattern}).', pattern: pattern)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parse_options(targets)
|
|
32
|
+
cmd_options = ['--format', 'json']
|
|
33
|
+
|
|
34
|
+
cmd_options << '--auto-correct' if options[:auto_correct]
|
|
35
|
+
|
|
36
|
+
cmd_options.concat(targets)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def parse_output(report, result, _targets)
|
|
40
|
+
return if result[:stdout].empty?
|
|
41
|
+
|
|
42
|
+
begin
|
|
43
|
+
json_data = JSON.parse(result[:stdout])
|
|
44
|
+
rescue JSON::ParserError
|
|
45
|
+
raise PDK::Validate::ParseOutputError, result[:stdout]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
return unless json_data.key?('files')
|
|
49
|
+
|
|
50
|
+
json_data['files'].each do |file_info|
|
|
51
|
+
next unless file_info.key?('offenses')
|
|
52
|
+
|
|
53
|
+
result = {
|
|
54
|
+
file: file_info['path'],
|
|
55
|
+
source: 'rubocop'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if file_info['offenses'].empty?
|
|
59
|
+
report.add_event(result.merge(state: :passed, severity: :ok))
|
|
60
|
+
else
|
|
61
|
+
file_info['offenses'].each do |offense|
|
|
62
|
+
report.add_event(
|
|
63
|
+
result.merge(
|
|
64
|
+
line: offense['location']['line'],
|
|
65
|
+
column: offense['location']['column'],
|
|
66
|
+
message: offense['message'],
|
|
67
|
+
severity: offense['corrected'] ? 'corrected' : offense['severity'],
|
|
68
|
+
test: offense['cop_name'],
|
|
69
|
+
state: :failure
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'pdk'
|
|
2
|
+
|
|
3
|
+
module PDK
|
|
4
|
+
module Validate
|
|
5
|
+
module Tasks
|
|
6
|
+
class TasksMetadataLintValidator < InternalRubyValidator
|
|
7
|
+
def name
|
|
8
|
+
'task-metadata-lint'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def pattern
|
|
12
|
+
contextual_pattern('tasks/*.json')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def spinner_text
|
|
16
|
+
format('Checking task metadata style (%{pattern}).', pattern: pattern.join(' '))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def schema_file
|
|
20
|
+
require 'pdk/config'
|
|
21
|
+
|
|
22
|
+
path = PDK::Config.json_schema('task')
|
|
23
|
+
schema = PDK::Util::Filesystem.read_file(path)
|
|
24
|
+
|
|
25
|
+
JSON.parse(schema)
|
|
26
|
+
rescue JSON::ParserError
|
|
27
|
+
raise PDK::CLI::FatalError, 'Failed to parse Task Metadata Schema file.'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def validate_target(report, target)
|
|
31
|
+
unless PDK::Util::Filesystem.readable?(target)
|
|
32
|
+
report.add_event(
|
|
33
|
+
file: target,
|
|
34
|
+
source: name,
|
|
35
|
+
state: :failure,
|
|
36
|
+
severity: 'error',
|
|
37
|
+
message: 'Could not be read.'
|
|
38
|
+
)
|
|
39
|
+
return 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
require 'json-schema'
|
|
43
|
+
begin
|
|
44
|
+
# Need to set the JSON Parser and State Generator to the Native one to be
|
|
45
|
+
# compatible with the multi_json adapter.
|
|
46
|
+
JSON.parser = JSON::Ext::Parser if defined?(JSON::Ext::Parser)
|
|
47
|
+
JSON.generator = JSON::Ext::Generator if defined?(JSON::Ext::Generator)
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
errors = JSON::Validator.fully_validate(schema_file, PDK::Util::Filesystem.read_file(target)) || []
|
|
51
|
+
rescue JSON::Schema::SchemaError => e
|
|
52
|
+
raise PDK::CLI::FatalError, format('Unable to validate Task Metadata. %{error}.', error: e.message)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if errors.empty?
|
|
56
|
+
report.add_event(
|
|
57
|
+
file: target,
|
|
58
|
+
source: name,
|
|
59
|
+
state: :passed,
|
|
60
|
+
severity: 'ok'
|
|
61
|
+
)
|
|
62
|
+
0
|
|
63
|
+
else
|
|
64
|
+
errors.each do |error|
|
|
65
|
+
# strip off the trailing parts that aren't relevant
|
|
66
|
+
error = error.split('in schema').first if error.include? 'in schema'
|
|
67
|
+
|
|
68
|
+
report.add_event(
|
|
69
|
+
file: target,
|
|
70
|
+
source: name,
|
|
71
|
+
state: :failure,
|
|
72
|
+
severity: 'error',
|
|
73
|
+
message: error
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
1
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|