pdk 0.6.0 → 1.0.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 +24 -0
- data/README.md +50 -250
- data/lib/pdk/cli.rb +2 -1
- data/lib/pdk/cli/exec.rb +47 -38
- data/lib/pdk/cli/exec_group.rb +53 -0
- data/lib/pdk/cli/new/class.rb +1 -5
- data/lib/pdk/cli/util.rb +11 -0
- data/lib/pdk/cli/util/interview.rb +1 -0
- data/lib/pdk/cli/validate.rb +17 -5
- data/lib/pdk/generators/module.rb +36 -18
- data/lib/pdk/generators/puppet_class.rb +1 -4
- data/lib/pdk/generators/puppet_object.rb +1 -1
- data/lib/pdk/logger.rb +4 -0
- data/lib/pdk/module/metadata.rb +1 -0
- data/lib/pdk/module/templatedir.rb +9 -3
- data/lib/pdk/monkey_patches.rb +13 -0
- data/lib/pdk/report/event.rb +4 -2
- data/lib/pdk/util.rb +14 -0
- data/lib/pdk/util/bundler.rb +5 -11
- data/lib/pdk/validators/base_validator.rb +67 -6
- data/lib/pdk/validators/metadata/metadata_json_lint.rb +3 -3
- data/lib/pdk/validators/metadata/metadata_syntax.rb +33 -13
- data/lib/pdk/validators/puppet/puppet_lint.rb +1 -1
- data/lib/pdk/validators/puppet/puppet_syntax.rb +1 -1
- data/lib/pdk/validators/ruby/rubocop.rb +5 -1
- data/lib/pdk/version.rb +1 -1
- data/locales/pdk.pot +240 -117
- metadata +9 -8
- data/locales/de/pdk.po +0 -604
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'tty-spinner'
|
2
|
+
require 'tty-which'
|
3
|
+
|
4
|
+
require 'pdk/util'
|
5
|
+
|
6
|
+
module PDK
|
7
|
+
module CLI
|
8
|
+
class ExecGroup
|
9
|
+
attr_reader :commands
|
10
|
+
|
11
|
+
def initialize(message, opts = {})
|
12
|
+
@options = opts.merge(PDK::CLI::Util.spinner_opts_for_platform)
|
13
|
+
|
14
|
+
unless PDK.logger.debug?
|
15
|
+
@multi_spinner = TTY::Spinner::Multi.new("[:spinner] #{message}", @options)
|
16
|
+
@multi_spinner.auto_spin
|
17
|
+
end
|
18
|
+
|
19
|
+
@threads = []
|
20
|
+
@exit_codes = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def register
|
24
|
+
raise PDK::CLI::FatalError, 'No block registered' unless block_given?
|
25
|
+
|
26
|
+
@threads << Thread.new do
|
27
|
+
GettextSetup.initialize(File.absolute_path('../../../locales', File.dirname(__FILE__)))
|
28
|
+
GettextSetup.negotiate_locale!(GettextSetup.candidate_locales)
|
29
|
+
@exit_codes << yield
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_spinner(message, opts = {})
|
34
|
+
return if PDK.logger.debug?
|
35
|
+
@multi_spinner.register("[:spinner] #{message}", @options.merge(opts).merge(PDK::CLI::Util.spinner_opts_for_platform))
|
36
|
+
end
|
37
|
+
|
38
|
+
def exit_code
|
39
|
+
@threads.each(&:join)
|
40
|
+
|
41
|
+
exit_code = @exit_codes.max
|
42
|
+
|
43
|
+
if exit_code.zero? && @multi_spinner
|
44
|
+
@multi_spinner.success
|
45
|
+
elsif @multi_spinner
|
46
|
+
@multi_spinner.error
|
47
|
+
end
|
48
|
+
|
49
|
+
exit_code
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/pdk/cli/new/class.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module PDK::CLI
|
2
2
|
@new_class_cmd = @new_cmd.define_command do
|
3
3
|
name 'class'
|
4
|
-
usage _('class [options] <class_name>
|
4
|
+
usage _('class [options] <class_name>')
|
5
5
|
summary _('Create a new class named <class_name> using given options')
|
6
6
|
|
7
7
|
PDK::CLI.template_url_option(self)
|
@@ -23,10 +23,6 @@ module PDK::CLI
|
|
23
23
|
raise PDK::CLI::FatalError, _("'%{name}' is not a valid class name") % { name: class_name }
|
24
24
|
end
|
25
25
|
|
26
|
-
if args.length > 1
|
27
|
-
opts[:params] = args[1..-1].map { |r| Util::OptionNormalizer.parameter_specification(r) }
|
28
|
-
end
|
29
|
-
|
30
26
|
PDK::Generate::PuppetClass.new(module_dir, class_name, opts).run
|
31
27
|
end
|
32
28
|
end
|
data/lib/pdk/cli/util.rb
CHANGED
@@ -10,6 +10,17 @@ module PDK
|
|
10
10
|
raise PDK::CLI::FatalError, message if PDK::Util.module_root.nil?
|
11
11
|
end
|
12
12
|
module_function :ensure_in_module!
|
13
|
+
|
14
|
+
def spinner_opts_for_platform
|
15
|
+
windows_opts = {
|
16
|
+
success_mark: '*',
|
17
|
+
error_mark: 'X',
|
18
|
+
}
|
19
|
+
|
20
|
+
return windows_opts if Gem.win_platform?
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
module_function :spinner_opts_for_platform
|
13
24
|
end
|
14
25
|
end
|
15
26
|
end
|
data/lib/pdk/cli/validate.rb
CHANGED
@@ -15,6 +15,7 @@ module PDK::CLI
|
|
15
15
|
|
16
16
|
flag nil, :list, _('list all available validators')
|
17
17
|
flag :a, 'auto-correct', _('automatically correct problems (where possible)')
|
18
|
+
flag nil, :parallel, _('run validations in parallel')
|
18
19
|
|
19
20
|
run do |opts, args, _cmd|
|
20
21
|
if args == ['help']
|
@@ -76,14 +77,25 @@ module PDK::CLI
|
|
76
77
|
options = targets.empty? ? {} : { targets: targets }
|
77
78
|
options[:auto_correct] = true if opts.key?(:'auto-correct')
|
78
79
|
|
79
|
-
exit_code = 0
|
80
|
-
|
81
80
|
# Ensure that the bundle is installed and tools are available before running any validations.
|
82
81
|
PDK::Util::Bundler.ensure_bundle!
|
83
82
|
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
exit_code = 0
|
84
|
+
if opts[:parallel]
|
85
|
+
exec_group = PDK::CLI::ExecGroup.new(_('Validating module using %{num_of_threads} threads' % { num_of_threads: validators.count }), opts)
|
86
|
+
|
87
|
+
validators.each do |validator|
|
88
|
+
exec_group.register do
|
89
|
+
validator.invoke(report, options.merge(exec_group: exec_group))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
exit_code = exec_group.exit_code
|
94
|
+
else
|
95
|
+
validators.each do |validator|
|
96
|
+
validator_exit_code = validator.invoke(report, options.dup)
|
97
|
+
exit_code = validator_exit_code if validator_exit_code != 0
|
98
|
+
end
|
87
99
|
end
|
88
100
|
|
89
101
|
report_formats.each do |format|
|
@@ -15,7 +15,15 @@ require 'pdk/util/version'
|
|
15
15
|
module PDK
|
16
16
|
module Generate
|
17
17
|
class Module
|
18
|
-
|
18
|
+
def self.default_template_url
|
19
|
+
if !PDK.answers['template-url'].nil?
|
20
|
+
PDK.answers['template-url']
|
21
|
+
elsif PDK::Util.package_install?
|
22
|
+
'file://' + File.join(PDK::Util.package_cachedir, 'pdk-module-template.git')
|
23
|
+
else
|
24
|
+
'https://github.com/puppetlabs/pdk-module-template'
|
25
|
+
end
|
26
|
+
end
|
19
27
|
|
20
28
|
def self.invoke(opts = {})
|
21
29
|
target_dir = File.expand_path(opts[:target_dir])
|
@@ -42,9 +50,9 @@ module PDK
|
|
42
50
|
|
43
51
|
prepare_module_directory(temp_target_dir)
|
44
52
|
|
45
|
-
template_url = opts.fetch(:'template-url',
|
53
|
+
template_url = opts.fetch(:'template-url', default_template_url)
|
46
54
|
|
47
|
-
PDK::Module::TemplateDir.new(template_url) do |templates|
|
55
|
+
PDK::Module::TemplateDir.new(template_url, metadata.data) do |templates|
|
48
56
|
templates.render do |file_path, file_content|
|
49
57
|
file = Pathname.new(temp_target_dir) + file_path
|
50
58
|
file.dirname.mkpath
|
@@ -79,7 +87,7 @@ module PDK
|
|
79
87
|
login_clean = 'username' if login_clean.empty?
|
80
88
|
|
81
89
|
if login_clean != login
|
82
|
-
PDK.logger.warn _('
|
90
|
+
PDK.logger.warn _('Your username is not a valid Forge username, proceeding with the username %{username}. You can fix this afterwards in metadata.json.') % {
|
83
91
|
username: login_clean,
|
84
92
|
}
|
85
93
|
end
|
@@ -96,6 +104,9 @@ module PDK
|
|
96
104
|
'dependencies' => [
|
97
105
|
{ 'name' => 'puppetlabs-stdlib', 'version_requirement' => '>= 4.13.1 < 5.0.0' },
|
98
106
|
],
|
107
|
+
'requirements' => [
|
108
|
+
{ 'name' => 'puppet', 'version_requirement' => '>= 4.7.0 < 6.0.0' },
|
109
|
+
],
|
99
110
|
}
|
100
111
|
defaults['author'] = PDK.answers['author'] unless PDK.answers['author'].nil?
|
101
112
|
defaults['license'] = PDK.answers['license'] unless PDK.answers['license'].nil?
|
@@ -130,8 +141,8 @@ module PDK
|
|
130
141
|
questions = [
|
131
142
|
{
|
132
143
|
name: 'name',
|
133
|
-
question: _('
|
134
|
-
help: _('
|
144
|
+
question: _('If you have a Puppet Forge username, add it here.'),
|
145
|
+
help: _('We can use this to upload your module to the Forge when it\'s complete.'),
|
135
146
|
required: true,
|
136
147
|
validate_pattern: %r{\A[a-z0-9]+\Z}i,
|
137
148
|
validate_message: _('Forge usernames can only contain lowercase letters and numbers'),
|
@@ -149,7 +160,7 @@ module PDK
|
|
149
160
|
{
|
150
161
|
name: 'author',
|
151
162
|
question: _('Who wrote this module?'),
|
152
|
-
help: _('
|
163
|
+
help: _('This will be used to credit the module\'s author.'),
|
153
164
|
required: true,
|
154
165
|
default: metadata.data['author'],
|
155
166
|
},
|
@@ -162,28 +173,28 @@ module PDK
|
|
162
173
|
},
|
163
174
|
{
|
164
175
|
name: 'summary',
|
165
|
-
question: _('
|
166
|
-
help: _('
|
176
|
+
question: _('Please summarize the purpose of this module in a single sentence.'),
|
177
|
+
help: _('This will help other Puppet users understand what the module does.'),
|
167
178
|
required: true,
|
168
179
|
default: metadata.data['summary'],
|
169
180
|
},
|
170
181
|
{
|
171
182
|
name: 'source',
|
172
|
-
question: _(
|
173
|
-
help: _('
|
183
|
+
question: _('If there is a source code repository for this module, enter the URL here.'),
|
184
|
+
help: _('Skip this if none exists yet, you can update this later in the metadata.json.'),
|
174
185
|
required: true,
|
175
186
|
default: metadata.data['source'],
|
176
187
|
},
|
177
188
|
{
|
178
189
|
name: 'project_page',
|
179
|
-
question: _('
|
180
|
-
help: _('
|
190
|
+
question: _('If there is a URL where others can learn more about this module, enter it here.'),
|
191
|
+
help: _('Optional. As with all questions above, you can update this later in the metadata.json.'),
|
181
192
|
default: metadata.data['project_page'],
|
182
193
|
},
|
183
194
|
{
|
184
195
|
name: 'issues_url',
|
185
|
-
question: _('
|
186
|
-
help: _('
|
196
|
+
question: _('If there is a public issue tracker for this module, enter its URL here.'),
|
197
|
+
help: _('Optional. As with all questions above, you can update this later in the metadata.json.'),
|
187
198
|
default: metadata.data['issues_url'],
|
188
199
|
},
|
189
200
|
]
|
@@ -197,8 +208,11 @@ module PDK
|
|
197
208
|
interview.add_questions(questions)
|
198
209
|
|
199
210
|
puts _(
|
200
|
-
"\nWe need to create a metadata.json file for this module, so we're going to ask you %{count} quick
|
201
|
-
"
|
211
|
+
"\nWe need to create a metadata.json file for this module, so we\'re going to ask you %{count} quick " \
|
212
|
+
"questions.\n" \
|
213
|
+
'If the question is not applicable to this module, simply leave the answer blank and skip. A default option ' \
|
214
|
+
'is shown after each question. You can modify this or any other answers at any time by manually updating ' \
|
215
|
+
"the metadata.json file.\n\n",
|
202
216
|
) % { count: interview.num_questions }
|
203
217
|
|
204
218
|
answers = interview.run
|
@@ -220,7 +234,11 @@ module PDK
|
|
220
234
|
puts '-' * 40
|
221
235
|
puts
|
222
236
|
|
223
|
-
|
237
|
+
continue = prompt.yes?(_('About to generate this module; continue?')) do |q|
|
238
|
+
q.validate(proc { |value| [true, false].include?(value) || value =~ %r{\A(?:yes|y|no|n)\Z}i }, 'Please answer "yes" or "no"')
|
239
|
+
end
|
240
|
+
|
241
|
+
unless continue
|
224
242
|
PDK.logger.info _('Module not generated.')
|
225
243
|
exit 0
|
226
244
|
end
|
@@ -11,10 +11,7 @@ module PDK
|
|
11
11
|
# provided to the class and class spec templates during rendering.
|
12
12
|
def template_data
|
13
13
|
data = { name: object_name }
|
14
|
-
|
15
|
-
data[:params] = @options[:params]
|
16
|
-
data[:max_type_length] = @options[:params].map { |r| r[:type].length }.max
|
17
|
-
end
|
14
|
+
|
18
15
|
data
|
19
16
|
end
|
20
17
|
|
@@ -197,7 +197,7 @@ module PDK
|
|
197
197
|
@templates ||= [
|
198
198
|
{ type: 'CLI', url: @options[:'template-url'], allow_fallback: false },
|
199
199
|
{ type: 'metadata', url: module_metadata.data['template-url'], allow_fallback: true },
|
200
|
-
{ type: 'default', url: PDK::Generate::Module
|
200
|
+
{ type: 'default', url: PDK::Generate::Module.default_template_url, allow_fallback: false },
|
201
201
|
]
|
202
202
|
end
|
203
203
|
|
data/lib/pdk/logger.rb
CHANGED
data/lib/pdk/module/metadata.rb
CHANGED
@@ -15,6 +15,8 @@ module PDK
|
|
15
15
|
#
|
16
16
|
# @param path_or_url [String] The path to a directory to use as the
|
17
17
|
# template or a URL to a git repository.
|
18
|
+
# @param module_metadata [Hash] A Hash containing the module metadata.
|
19
|
+
# Defaults to an empty Hash.
|
18
20
|
# @yieldparam self [PDK::Module::TemplateDir] The initialised object with
|
19
21
|
# the template available on disk.
|
20
22
|
#
|
@@ -34,7 +36,7 @@ module PDK
|
|
34
36
|
# @raise [ArgumentError] (see #validate_module_template!)
|
35
37
|
#
|
36
38
|
# @api public
|
37
|
-
def initialize(path_or_url)
|
39
|
+
def initialize(path_or_url, module_metadata = {})
|
38
40
|
if File.directory?(path_or_url)
|
39
41
|
@path = path_or_url
|
40
42
|
else
|
@@ -61,6 +63,8 @@ module PDK
|
|
61
63
|
@object_dir = File.join(@path, 'object_templates')
|
62
64
|
validate_module_template!
|
63
65
|
|
66
|
+
@module_metadata = module_metadata
|
67
|
+
|
64
68
|
yield self
|
65
69
|
ensure
|
66
70
|
# If we cloned a git repo to get the template, remove the clone once
|
@@ -81,7 +85,7 @@ module PDK
|
|
81
85
|
def metadata
|
82
86
|
return {} unless @repo
|
83
87
|
|
84
|
-
ref_result = PDK::CLI::Exec.git('--git-dir', File.join(@path, '.git'), 'describe', '--all', '--long')
|
88
|
+
ref_result = PDK::CLI::Exec.git('--git-dir', File.join(@path, '.git'), 'describe', '--all', '--long', '--always')
|
85
89
|
if ref_result[:exit_code].zero?
|
86
90
|
{ 'template-url' => @repo, 'template-ref' => ref_result[:stdout].strip }
|
87
91
|
else
|
@@ -231,7 +235,9 @@ module PDK
|
|
231
235
|
end
|
232
236
|
|
233
237
|
file_config = @config.fetch(:global, {})
|
234
|
-
file_config
|
238
|
+
file_config['module_metadata'] = @module_metadata
|
239
|
+
file_config.merge!(@config.fetch(dest_path, {})) unless dest_path.nil?
|
240
|
+
file_config
|
235
241
|
end
|
236
242
|
end
|
237
243
|
end
|
data/lib/pdk/report/event.rb
CHANGED
@@ -96,7 +96,7 @@ module PDK
|
|
96
96
|
location = nil if location.empty?
|
97
97
|
|
98
98
|
# TODO: maybe add trace
|
99
|
-
[
|
99
|
+
[severity, source, location, message].compact.join(': ')
|
100
100
|
end
|
101
101
|
|
102
102
|
# Renders the event as a JUnit XML testcase.
|
@@ -170,7 +170,9 @@ module PDK
|
|
170
170
|
|
171
171
|
if path.absolute?
|
172
172
|
module_root = Pathname.new(PDK::Util.module_root)
|
173
|
-
path.relative_path_from(module_root).to_path
|
173
|
+
path = path.relative_path_from(module_root).to_path
|
174
|
+
path << '/' if path == '.'
|
175
|
+
path
|
174
176
|
else
|
175
177
|
path.to_path
|
176
178
|
end
|
data/lib/pdk/util.rb
CHANGED
@@ -152,5 +152,19 @@ module PDK
|
|
152
152
|
json_result
|
153
153
|
end
|
154
154
|
module_function :find_valid_json_in
|
155
|
+
|
156
|
+
# Returns the targets' paths relative to the working directory
|
157
|
+
#
|
158
|
+
# @return [Array<String>] The absolute or path to the target
|
159
|
+
def targets_relative_to_pwd(targets)
|
160
|
+
targets.map do |t|
|
161
|
+
if Pathname.new(t).absolute?
|
162
|
+
Pathname.new(t).relative_path_from(Pathname.pwd)
|
163
|
+
else
|
164
|
+
t
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
module_function :targets_relative_to_pwd
|
155
169
|
end
|
156
170
|
end
|
data/lib/pdk/util/bundler.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
require 'fileutils'
|
3
|
-
require 'tty-spinner'
|
4
3
|
require 'pdk/util'
|
5
4
|
require 'pdk/cli/exec'
|
6
5
|
|
@@ -83,8 +82,7 @@ module PDK
|
|
83
82
|
result = bundle_command(*argv).execute!
|
84
83
|
|
85
84
|
unless result[:exit_code].zero?
|
86
|
-
|
87
|
-
$stderr.puts result[:stderr]
|
85
|
+
PDK.logger.debug(result.values_at(:stdout, :stderr).join("\n"))
|
88
86
|
end
|
89
87
|
|
90
88
|
result[:exit_code].zero?
|
@@ -98,15 +96,14 @@ module PDK
|
|
98
96
|
result = command.execute!
|
99
97
|
|
100
98
|
unless result[:exit_code].zero?
|
101
|
-
|
102
|
-
$stderr.puts result[:stderr]
|
99
|
+
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n"))
|
103
100
|
end
|
104
101
|
|
105
102
|
result[:exit_code].zero?
|
106
103
|
end
|
107
104
|
|
108
105
|
def install!
|
109
|
-
argv = ['install', "--gemfile=#{gemfile}"]
|
106
|
+
argv = ['install', "--gemfile=#{gemfile}", '-j4']
|
110
107
|
argv << "--path=#{bundle_cachedir}" if PDK::Util.gem_install?
|
111
108
|
|
112
109
|
command = bundle_command(*argv).tap do |c|
|
@@ -116,8 +113,7 @@ module PDK
|
|
116
113
|
result = command.execute!
|
117
114
|
|
118
115
|
unless result[:exit_code].zero?
|
119
|
-
|
120
|
-
$stderr.puts result[:stderr]
|
116
|
+
PDK.logger.fatal(result.values_at(:stdout, :stderr).join("\n"))
|
121
117
|
end
|
122
118
|
|
123
119
|
result[:exit_code].zero?
|
@@ -132,9 +128,7 @@ module PDK
|
|
132
128
|
result = command.execute!
|
133
129
|
|
134
130
|
unless result[:exit_code].zero?
|
135
|
-
PDK.logger.
|
136
|
-
$stderr.puts result[:stdout]
|
137
|
-
$stderr.puts result[:stderr]
|
131
|
+
PDK.logger.fatal(_("Failed to generate binstubs for '%{gems}':\n%{output}") % { gems: gems.join(' '), output: result.values_at(:stdout, :stderr).join("\n") })
|
138
132
|
end
|
139
133
|
|
140
134
|
result[:exit_code].zero?
|