pdk 1.7.1 → 1.8.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 +4 -4
- data/CHANGELOG.md +37 -0
- data/lib/pdk/answer_file.rb +4 -3
- data/lib/pdk/cli.rb +3 -1
- data/lib/pdk/cli/new/module.rb +1 -0
- data/lib/pdk/cli/test/unit.rb +3 -0
- data/lib/pdk/cli/validate.rb +4 -1
- data/lib/pdk/generate/module.rb +6 -2
- data/lib/pdk/generate/puppet_object.rb +2 -1
- data/lib/pdk/module.rb +21 -0
- data/lib/pdk/module/build.rb +2 -11
- data/lib/pdk/module/convert.rb +12 -9
- data/lib/pdk/module/metadata.rb +5 -4
- data/lib/pdk/module/update_manager.rb +3 -2
- data/lib/pdk/tests/unit.rb +9 -7
- data/lib/pdk/util.rb +4 -3
- data/lib/pdk/util/bundler.rb +3 -8
- data/lib/pdk/util/filesystem.rb +12 -0
- data/lib/pdk/util/puppet_version.rb +22 -5
- data/lib/pdk/util/vendored_file.rb +4 -3
- data/lib/pdk/validate.rb +2 -1
- data/lib/pdk/validate/base_validator.rb +36 -8
- data/lib/pdk/validate/metadata_validator.rb +1 -2
- data/lib/pdk/validate/puppet/puppet_syntax.rb +4 -0
- data/lib/pdk/validate/ruby/rubocop.rb +2 -0
- data/lib/pdk/validate/tasks/metadata_lint.rb +126 -0
- data/lib/pdk/validate/tasks/name.rb +88 -0
- data/lib/pdk/validate/tasks_validator.rb +33 -0
- data/lib/pdk/version.rb +1 -1
- data/locales/pdk.pot +155 -139
- metadata +7 -3
- data/lib/pdk/validate/metadata/task_metadata_lint.rb +0 -124
@@ -0,0 +1,12 @@
|
|
1
|
+
module PDK
|
2
|
+
module Util
|
3
|
+
module Filesystem
|
4
|
+
def write_file(path, content)
|
5
|
+
raise ArgumentError unless path.is_a?(String) || path.respond_to?(:to_path)
|
6
|
+
|
7
|
+
File.open(path, 'wb') { |f| f.write(content.encode(universal_newline: true)) }
|
8
|
+
end
|
9
|
+
module_function :write_file
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -42,7 +42,14 @@ module PDK
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def fetch_puppet_dev
|
45
|
+
# Check if the source is cloned and is a readable git repo
|
45
46
|
unless PDK::Util::Git.remote_repo? puppet_dev_path
|
47
|
+
# Check if the path has something in it already. Delete it and prepare for clone if so.
|
48
|
+
if File.exist? puppet_dev_path
|
49
|
+
File.delete(puppet_dev_path) if File.file? puppet_dev_path
|
50
|
+
FileUtils.rm_rf(puppet_dev_path) if File.directory? puppet_dev_path
|
51
|
+
end
|
52
|
+
|
46
53
|
FileUtils.mkdir_p puppet_dev_path
|
47
54
|
clone_result = PDK::Util::Git.git('clone', DEFAULT_PUPPET_DEV_URL, puppet_dev_path)
|
48
55
|
return if clone_result[:exit_code].zero?
|
@@ -52,12 +59,22 @@ module PDK
|
|
52
59
|
raise PDK::CLI::FatalError, _("Unable to clone git repository at '%{repo}'.") % { repo: DEFAULT_PUPPET_DEV_URL }
|
53
60
|
end
|
54
61
|
|
55
|
-
|
56
|
-
|
62
|
+
# Fetch Updates from remote repository
|
63
|
+
fetch_result = PDK::Util::Git.git('-C', puppet_dev_path, 'fetch', 'origin')
|
64
|
+
|
65
|
+
unless fetch_result[:exit_code].zero?
|
66
|
+
PDK.logger.error fetch_result[:stdout]
|
67
|
+
PDK.logger.error fetch_result[:stderr]
|
68
|
+
raise PDK::CLI::FatalError, _("Unable to fetch from git remote at '%{repo}'.") % { repo: DEFAULT_PUPPET_DEV_URL }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Reset local repo to latest
|
72
|
+
reset_result = PDK::Util::Git.git('-C', puppet_dev_path, 'reset', '--hard', 'origin/master')
|
73
|
+
return if reset_result[:exit_code].zero?
|
57
74
|
|
58
|
-
PDK.logger.error
|
59
|
-
PDK.logger.error
|
60
|
-
raise PDK::CLI::FatalError, _("Unable to
|
75
|
+
PDK.logger.error reset_result[:stdout]
|
76
|
+
PDK.logger.error reset_result[:stderr]
|
77
|
+
raise PDK::CLI::FatalError, _("Unable to update git repository at '%{cachedir}'.") % { repo: puppet_dev_path }
|
61
78
|
end
|
62
79
|
|
63
80
|
def find_gem_for(version_str)
|
@@ -2,6 +2,7 @@ require 'pdk/util'
|
|
2
2
|
require 'net/https'
|
3
3
|
require 'openssl'
|
4
4
|
require 'fileutils'
|
5
|
+
require 'pdk/util/filesystem'
|
5
6
|
|
6
7
|
module PDK
|
7
8
|
module Util
|
@@ -22,6 +23,8 @@ module PDK
|
|
22
23
|
attr_reader :file_name
|
23
24
|
attr_reader :url
|
24
25
|
|
26
|
+
include PDK::Util::Filesystem
|
27
|
+
|
25
28
|
def initialize(file_name, url)
|
26
29
|
@file_name = file_name
|
27
30
|
@url = url
|
@@ -36,9 +39,7 @@ module PDK
|
|
36
39
|
# TODO: should only write if it's valid JSON
|
37
40
|
# TODO: need a way to invalidate if out of date
|
38
41
|
FileUtils.mkdir_p(File.dirname(gem_vendored_path))
|
39
|
-
|
40
|
-
fd.write(content)
|
41
|
-
end
|
42
|
+
write_file(gem_vendored_path, content)
|
42
43
|
content
|
43
44
|
end
|
44
45
|
|
data/lib/pdk/validate.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'pdk/validate/metadata_validator'
|
2
2
|
require 'pdk/validate/puppet_validator'
|
3
3
|
require 'pdk/validate/ruby_validator'
|
4
|
+
require 'pdk/validate/tasks_validator'
|
4
5
|
|
5
6
|
module PDK
|
6
7
|
module Validate
|
7
8
|
def self.validators
|
8
|
-
@validators ||= [MetadataValidator, PuppetValidator, RubyValidator].freeze
|
9
|
+
@validators ||= [MetadataValidator, PuppetValidator, RubyValidator, TasksValidator].freeze
|
9
10
|
end
|
10
11
|
|
11
12
|
class ParseOutputError < StandardError; end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pdk'
|
2
2
|
require 'pdk/cli/exec'
|
3
|
+
require 'pdk/module'
|
3
4
|
|
4
5
|
module PDK
|
5
6
|
module Validate
|
@@ -12,6 +13,14 @@ module PDK
|
|
12
13
|
# separately.
|
13
14
|
INVOKE_STYLE = :once
|
14
15
|
|
16
|
+
# Controls how the validator behaves if not passed any targets.
|
17
|
+
#
|
18
|
+
# true - PDK will not pass the globbed targets to the validator command
|
19
|
+
# and it will instead rely on the underlying tool to find its
|
20
|
+
# own default targets.
|
21
|
+
# false - PDK will pass the globbed targets to the validator command.
|
22
|
+
ALLOW_EMPTY_TARGETS = false
|
23
|
+
|
15
24
|
def self.cmd_path
|
16
25
|
File.join(PDK::Util.module_root, 'bin', cmd)
|
17
26
|
end
|
@@ -30,13 +39,9 @@ module PDK
|
|
30
39
|
def self.parse_targets(options)
|
31
40
|
# If no targets are specified, then we will run validations from the
|
32
41
|
# base module directory.
|
33
|
-
targets = if options[:targets].nil? || options[:targets].empty?
|
34
|
-
[PDK::Util.module_root]
|
35
|
-
else
|
36
|
-
options[:targets]
|
37
|
-
end
|
38
42
|
|
39
|
-
|
43
|
+
targets = options.fetch(:targets, []).empty? ? [PDK::Util.module_root] : options[:targets]
|
44
|
+
|
40
45
|
targets.map! { |r| r.gsub(File::ALT_SEPARATOR, File::SEPARATOR) } if File::ALT_SEPARATOR
|
41
46
|
skipped = []
|
42
47
|
invalid = []
|
@@ -45,14 +50,16 @@ module PDK
|
|
45
50
|
if File.directory?(target)
|
46
51
|
target_root = PDK::Util.module_root
|
47
52
|
pattern_glob = Array(pattern).map { |p| Dir.glob(File.join(target_root, p)) }
|
48
|
-
pattern_glob = pattern_glob.flatten.reject { |file| File.fnmatch(fixtures_pattern, file) }
|
49
53
|
|
50
|
-
target_list = pattern_glob.map do |file|
|
54
|
+
target_list = pattern_glob.flatten.map do |file|
|
51
55
|
if File.fnmatch(File.join(File.expand_path(target), '*'), file)
|
52
56
|
Pathname.new(file).relative_path_from(Pathname.new(PDK::Util.module_root)).to_s
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
60
|
+
ignore_list = ignore_pathspec
|
61
|
+
target_list = target_list.reject { |file| ignore_list.match(file) }
|
62
|
+
|
56
63
|
skipped << target if target_list.flatten.empty?
|
57
64
|
target_list
|
58
65
|
elsif File.file?(target)
|
@@ -75,6 +82,18 @@ module PDK
|
|
75
82
|
[matched, skipped, invalid]
|
76
83
|
end
|
77
84
|
|
85
|
+
def self.ignore_pathspec
|
86
|
+
ignore_pathspec = PDK::Module.default_ignored_pathspec.dup
|
87
|
+
|
88
|
+
if respond_to?(:pattern_ignore)
|
89
|
+
Array(pattern_ignore).each do |pattern|
|
90
|
+
ignore_pathspec.add(pattern)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
ignore_pathspec
|
95
|
+
end
|
96
|
+
|
78
97
|
def self.parse_options(_options, targets)
|
79
98
|
targets
|
80
99
|
end
|
@@ -109,6 +128,10 @@ module PDK
|
|
109
128
|
end
|
110
129
|
end
|
111
130
|
|
131
|
+
def self.allow_empty_targets?
|
132
|
+
self::ALLOW_EMPTY_TARGETS == true
|
133
|
+
end
|
134
|
+
|
112
135
|
def self.invoke(report, options = {})
|
113
136
|
targets, skipped, invalid = parse_targets(options)
|
114
137
|
|
@@ -132,6 +155,10 @@ module PDK
|
|
132
155
|
options[:split_exec] = PDK::CLI::ExecGroup.new(spinner_text(targets), parallel: false)
|
133
156
|
end
|
134
157
|
|
158
|
+
if options.fetch(:targets, []).empty? && allow_empty_targets?
|
159
|
+
targets = [[]]
|
160
|
+
end
|
161
|
+
|
135
162
|
exit_codes = []
|
136
163
|
|
137
164
|
targets.each do |invokation_targets|
|
@@ -140,6 +167,7 @@ module PDK
|
|
140
167
|
|
141
168
|
command = PDK::CLI::Exec::Command.new(*cmd_argv).tap do |c|
|
142
169
|
c.context = :module
|
170
|
+
c.environment = { 'PUPPET_GEM_VERSION' => options[:puppet] } if options[:puppet]
|
143
171
|
unless options[:split_exec]
|
144
172
|
exec_group = options[:exec_group]
|
145
173
|
if exec_group
|
@@ -3,7 +3,6 @@ require 'pdk/cli/exec'
|
|
3
3
|
require 'pdk/validate/base_validator'
|
4
4
|
require 'pdk/validate/metadata/metadata_json_lint'
|
5
5
|
require 'pdk/validate/metadata/metadata_syntax'
|
6
|
-
require 'pdk/validate/metadata/task_metadata_lint'
|
7
6
|
|
8
7
|
module PDK
|
9
8
|
module Validate
|
@@ -13,7 +12,7 @@ module PDK
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def self.metadata_validators
|
16
|
-
[MetadataSyntax, MetadataJSONLint
|
15
|
+
[MetadataSyntax, MetadataJSONLint]
|
17
16
|
end
|
18
17
|
|
19
18
|
def self.invoke(report, options = {})
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'pdk'
|
2
|
+
require 'pdk/cli/exec'
|
3
|
+
require 'pdk/validate/base_validator'
|
4
|
+
require 'pdk/util'
|
5
|
+
require 'pathname'
|
6
|
+
require 'json-schema'
|
7
|
+
|
8
|
+
module PDK
|
9
|
+
module Validate
|
10
|
+
class Tasks
|
11
|
+
class MetadataLint < BaseValidator
|
12
|
+
FORGE_SCHEMA_URL = 'https://forgeapi.puppet.com/schemas/task.json'.freeze
|
13
|
+
|
14
|
+
def self.name
|
15
|
+
'task-metadata-lint'
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.pattern
|
19
|
+
'tasks/*.json'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.spinner_text(_targets = [])
|
23
|
+
_('Checking task metadata style (%{targets}).') % {
|
24
|
+
targets: pattern,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.create_spinner(targets = [], options = {})
|
29
|
+
return unless PDK::CLI::Util.interactive?
|
30
|
+
options = options.merge(PDK::CLI::Util.spinner_opts_for_platform)
|
31
|
+
|
32
|
+
exec_group = options[:exec_group]
|
33
|
+
@spinner = if exec_group
|
34
|
+
exec_group.add_spinner(spinner_text(targets), options)
|
35
|
+
else
|
36
|
+
TTY::Spinner.new("[:spinner] #{spinner_text(targets)}", options)
|
37
|
+
end
|
38
|
+
@spinner.auto_spin
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.stop_spinner(exit_code)
|
42
|
+
if exit_code.zero? && @spinner
|
43
|
+
@spinner.success
|
44
|
+
elsif @spinner
|
45
|
+
@spinner.error
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.schema_file
|
50
|
+
schema = PDK::Util::VendoredFile.new('task.json', FORGE_SCHEMA_URL).read
|
51
|
+
|
52
|
+
JSON.parse(schema)
|
53
|
+
rescue PDK::Util::VendoredFile::DownloadError => e
|
54
|
+
raise PDK::CLI::FatalError, e.message
|
55
|
+
rescue JSON::ParserError
|
56
|
+
raise PDK::CLI::FatalError, _('Failed to parse Task Metadata Schema file.')
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.invoke(report, options = {})
|
60
|
+
targets, skipped, invalid = parse_targets(options)
|
61
|
+
|
62
|
+
process_skipped(report, skipped)
|
63
|
+
process_invalid(report, invalid)
|
64
|
+
|
65
|
+
return 0 if targets.empty?
|
66
|
+
|
67
|
+
return_val = 0
|
68
|
+
create_spinner(targets, options)
|
69
|
+
|
70
|
+
targets.each do |target|
|
71
|
+
unless File.readable?(target)
|
72
|
+
report.add_event(
|
73
|
+
file: target,
|
74
|
+
source: name,
|
75
|
+
state: :failure,
|
76
|
+
severity: 'error',
|
77
|
+
message: _('Could not be read.'),
|
78
|
+
)
|
79
|
+
return_val = 1
|
80
|
+
next
|
81
|
+
end
|
82
|
+
|
83
|
+
begin
|
84
|
+
# Need to set the JSON Parser and State Generator to the Native one to be
|
85
|
+
# compatible with the multi_json adapter.
|
86
|
+
JSON.parser = JSON::Ext::Parser if defined?(JSON::Ext::Parser)
|
87
|
+
JSON.generator = JSON::Ext::Generator
|
88
|
+
|
89
|
+
begin
|
90
|
+
errors = JSON::Validator.fully_validate(schema_file, File.read(target)) || []
|
91
|
+
rescue JSON::Schema::SchemaError => e
|
92
|
+
raise PDK::CLI::FatalError, _('Unable to validate Task Metadata. %{error}.') % { error: e.message }
|
93
|
+
end
|
94
|
+
|
95
|
+
if errors.empty?
|
96
|
+
report.add_event(
|
97
|
+
file: target,
|
98
|
+
source: name,
|
99
|
+
state: :passed,
|
100
|
+
severity: 'ok',
|
101
|
+
)
|
102
|
+
else
|
103
|
+
errors.each do |error|
|
104
|
+
# strip off the trailing parts that aren't relevant
|
105
|
+
error = error.split('in schema').first if error.include? 'in schema'
|
106
|
+
|
107
|
+
report.add_event(
|
108
|
+
file: target,
|
109
|
+
source: name,
|
110
|
+
state: :failure,
|
111
|
+
severity: 'error',
|
112
|
+
message: error,
|
113
|
+
)
|
114
|
+
end
|
115
|
+
return_val = 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
stop_spinner(return_val)
|
121
|
+
return_val
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'pdk'
|
2
|
+
require 'pdk/validate/base_validator'
|
3
|
+
require 'pdk/util'
|
4
|
+
|
5
|
+
module PDK
|
6
|
+
module Validate
|
7
|
+
class Tasks
|
8
|
+
class Name < BaseValidator
|
9
|
+
INVALID_TASK_MSG = _(
|
10
|
+
'Invalid task name. Task names must start with a lowercase letter' \
|
11
|
+
'and can only contain lowercase letters, numbers, and underscores.',
|
12
|
+
)
|
13
|
+
|
14
|
+
def self.name
|
15
|
+
'task-name'
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.pattern
|
19
|
+
'tasks/**/*'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.spinner_text(_targets = [])
|
23
|
+
_('Checking task names (%{targets}).') % {
|
24
|
+
targets: pattern,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.create_spinner(targets = [], options = {})
|
29
|
+
return unless PDK::CLI::Util.interactive?
|
30
|
+
options = options.merge(PDK::CLI::Util.spinner_opts_for_platform)
|
31
|
+
|
32
|
+
exec_group = options[:exec_group]
|
33
|
+
@spinner = if exec_group
|
34
|
+
exec_group.add_spinner(spinner_text(targets), options)
|
35
|
+
else
|
36
|
+
TTY::Spinner.new("[:spinner] #{spinner_text(targets)}", options)
|
37
|
+
end
|
38
|
+
@spinner.auto_spin
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.stop_spinner(exit_code)
|
42
|
+
if exit_code.zero? && @spinner
|
43
|
+
@spinner.success
|
44
|
+
elsif @spinner
|
45
|
+
@spinner.error
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.invoke(report, options = {})
|
50
|
+
targets, skipped, invalid = parse_targets(options)
|
51
|
+
|
52
|
+
process_skipped(report, skipped)
|
53
|
+
process_invalid(report, invalid)
|
54
|
+
|
55
|
+
return 0 if targets.empty?
|
56
|
+
|
57
|
+
return_val = 0
|
58
|
+
create_spinner(targets, options)
|
59
|
+
|
60
|
+
targets.each do |target|
|
61
|
+
task_name = File.basename(target, File.extname(target))
|
62
|
+
if PDK::CLI::Util::OptionValidator.valid_task_name?(task_name)
|
63
|
+
report.add_event(
|
64
|
+
file: target,
|
65
|
+
source: name,
|
66
|
+
state: :passed,
|
67
|
+
severity: 'ok',
|
68
|
+
)
|
69
|
+
else
|
70
|
+
report.add_event(
|
71
|
+
file: target,
|
72
|
+
source: name,
|
73
|
+
state: :failure,
|
74
|
+
severity: 'error',
|
75
|
+
message: INVALID_TASK_MSG,
|
76
|
+
)
|
77
|
+
|
78
|
+
return_val = 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
stop_spinner(return_val)
|
83
|
+
return_val
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|