pdk-akerl 1.9.1.1 → 1.14.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +180 -0
- data/README.md +43 -4
- data/lib/pdk.rb +4 -2
- data/lib/pdk/analytics.rb +44 -0
- data/lib/pdk/analytics/client/google_analytics.rb +141 -0
- data/lib/pdk/analytics/client/noop.rb +23 -0
- data/lib/pdk/analytics/util.rb +17 -0
- data/lib/pdk/answer_file.rb +4 -1
- data/lib/pdk/cli.rb +50 -3
- data/lib/pdk/cli/build.rb +10 -4
- data/lib/pdk/cli/bundle.rb +10 -8
- data/lib/pdk/cli/config.rb +20 -0
- data/lib/pdk/cli/config/get.rb +24 -0
- data/lib/pdk/cli/console.rb +148 -0
- data/lib/pdk/cli/convert.rb +7 -2
- data/lib/pdk/cli/exec.rb +22 -190
- data/lib/pdk/cli/exec/command.rb +238 -0
- data/lib/pdk/cli/exec/interactive_command.rb +114 -0
- data/lib/pdk/cli/exec_group.rb +6 -6
- data/lib/pdk/cli/module/build.rb +0 -2
- data/lib/pdk/cli/module/generate.rb +4 -2
- data/lib/pdk/cli/new.rb +2 -0
- data/lib/pdk/cli/new/class.rb +2 -2
- data/lib/pdk/cli/new/defined_type.rb +4 -2
- data/lib/pdk/cli/new/module.rb +5 -0
- data/lib/pdk/cli/new/provider.rb +4 -2
- data/lib/pdk/cli/new/task.rb +4 -1
- data/lib/pdk/cli/new/test.rb +53 -0
- data/lib/pdk/cli/new/transport.rb +27 -0
- data/lib/pdk/cli/test.rb +0 -1
- data/lib/pdk/cli/test/unit.rb +18 -13
- data/lib/pdk/cli/update.rb +25 -3
- data/lib/pdk/cli/util.rb +111 -14
- data/lib/pdk/cli/util/interview.rb +10 -2
- data/lib/pdk/cli/util/option_validator.rb +4 -0
- data/lib/pdk/cli/util/spinner.rb +13 -0
- data/lib/pdk/cli/validate.rb +16 -5
- data/lib/pdk/config.rb +121 -0
- data/lib/pdk/config/analytics_schema.json +26 -0
- data/lib/pdk/config/errors.rb +5 -0
- data/lib/pdk/config/json.rb +34 -0
- data/lib/pdk/config/json_schema_namespace.rb +143 -0
- data/lib/pdk/config/json_schema_setting.rb +53 -0
- data/lib/pdk/config/json_with_schema.rb +50 -0
- data/lib/pdk/config/namespace.rb +332 -0
- data/lib/pdk/config/setting.rb +132 -0
- data/lib/pdk/config/yaml.rb +43 -0
- data/lib/pdk/config/yaml_with_schema.rb +59 -0
- data/lib/pdk/generate.rb +10 -3
- data/lib/pdk/generate/defined_type.rb +1 -0
- data/lib/pdk/generate/module.rb +62 -35
- data/lib/pdk/generate/provider.rb +0 -5
- data/lib/pdk/generate/puppet_class.rb +1 -0
- data/lib/pdk/generate/puppet_object.rb +88 -41
- data/lib/pdk/generate/transport.rb +87 -0
- data/lib/pdk/logger.rb +21 -1
- data/lib/pdk/module.rb +2 -2
- data/lib/pdk/module/build.rb +103 -10
- data/lib/pdk/module/convert.rb +85 -19
- data/lib/pdk/module/metadata.rb +17 -12
- data/lib/pdk/module/templatedir.rb +108 -40
- data/lib/pdk/module/update.rb +27 -15
- data/lib/pdk/module/update_manager.rb +23 -15
- data/lib/pdk/report.rb +4 -3
- data/lib/pdk/report/event.rb +8 -6
- data/lib/pdk/template_file.rb +1 -1
- data/lib/pdk/tests/unit.rb +48 -21
- data/lib/pdk/util.rb +29 -63
- data/lib/pdk/util/bundler.rb +19 -15
- data/lib/pdk/util/filesystem.rb +64 -1
- data/lib/pdk/util/git.rb +52 -1
- data/lib/pdk/util/puppet_strings.rb +123 -0
- data/lib/pdk/util/puppet_version.rb +27 -12
- data/lib/pdk/util/ruby_version.rb +30 -7
- data/lib/pdk/util/template_uri.rb +281 -0
- data/lib/pdk/util/vendored_file.rb +28 -24
- data/lib/pdk/util/version.rb +7 -8
- data/lib/pdk/util/windows.rb +1 -0
- data/lib/pdk/util/windows/api_types.rb +0 -7
- data/lib/pdk/util/windows/file.rb +1 -1
- data/lib/pdk/util/windows/string.rb +1 -1
- data/lib/pdk/validate/base_validator.rb +12 -14
- data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -4
- data/lib/pdk/validate/metadata/metadata_syntax.rb +5 -3
- data/lib/pdk/validate/metadata_validator.rb +0 -2
- data/lib/pdk/validate/puppet/puppet_epp.rb +137 -0
- data/lib/pdk/validate/puppet/puppet_lint.rb +0 -3
- data/lib/pdk/validate/puppet/puppet_syntax.rb +5 -5
- data/lib/pdk/validate/puppet_validator.rb +2 -3
- data/lib/pdk/validate/ruby/rubocop.rb +1 -6
- data/lib/pdk/validate/ruby_validator.rb +0 -2
- data/lib/pdk/validate/tasks/metadata_lint.rb +9 -5
- data/lib/pdk/validate/tasks/name.rb +5 -3
- data/lib/pdk/validate/tasks_validator.rb +0 -2
- data/lib/pdk/validate/yaml/syntax.rb +6 -4
- data/lib/pdk/validate/yaml_validator.rb +0 -2
- data/lib/pdk/version.rb +1 -1
- data/locales/pdk.pot +634 -307
- metadata +100 -45
@@ -72,11 +72,6 @@ module PDK
|
|
72
72
|
def target_type_spec_path
|
73
73
|
@target_type_spec_path ||= File.join(module_dir, 'spec', 'unit', 'puppet', 'type', object_name) + '_spec.rb'
|
74
74
|
end
|
75
|
-
|
76
|
-
# transform a object name into a ruby class name
|
77
|
-
def self.class_name_from_object_name(object_name)
|
78
|
-
object_name.to_s.split('_').map(&:capitalize).join
|
79
|
-
end
|
80
75
|
end
|
81
76
|
end
|
82
77
|
end
|
@@ -1,12 +1,3 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
require 'pdk'
|
4
|
-
require 'pdk/logger'
|
5
|
-
require 'pdk/module/metadata'
|
6
|
-
require 'pdk/module/templatedir'
|
7
|
-
require 'pdk/template_file'
|
8
|
-
require 'pdk/util/filesystem'
|
9
|
-
|
10
1
|
module PDK
|
11
2
|
module Generate
|
12
3
|
class PuppetObject
|
@@ -29,7 +20,7 @@ module PDK
|
|
29
20
|
# @param options [Hash{Symbol => Object}]
|
30
21
|
#
|
31
22
|
# @api public
|
32
|
-
def initialize(module_dir, object_name, options
|
23
|
+
def initialize(module_dir, object_name, options)
|
33
24
|
@module_dir = module_dir
|
34
25
|
@options = options
|
35
26
|
@object_name = object_name
|
@@ -45,6 +36,10 @@ module PDK
|
|
45
36
|
end
|
46
37
|
end
|
47
38
|
|
39
|
+
def spec_only?
|
40
|
+
@options[:spec_only]
|
41
|
+
end
|
42
|
+
|
48
43
|
# @abstract Subclass and implement {#template_data} to provide data to
|
49
44
|
# the templates during rendering. Implementations of this method should
|
50
45
|
# return a Hash!{Symbol => Object}.
|
@@ -81,6 +76,13 @@ module PDK
|
|
81
76
|
nil
|
82
77
|
end
|
83
78
|
|
79
|
+
# @abstract Subclass and implement {#target_device_path}. Implementations
|
80
|
+
# of this method should return a String containing the destination path
|
81
|
+
# of the device class being generated.
|
82
|
+
def target_device_path
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
84
86
|
# Retrieves the type of the object being generated, e.g. :class,
|
85
87
|
# :defined_type, etc. This is specified in the subclass' OBJECT_TYPE
|
86
88
|
# constant.
|
@@ -92,6 +94,37 @@ module PDK
|
|
92
94
|
self.class::OBJECT_TYPE
|
93
95
|
end
|
94
96
|
|
97
|
+
# Retrieves the type of the object being generated as represented in
|
98
|
+
# the JSON output of puppet-strings.
|
99
|
+
#
|
100
|
+
# @return [String] the type of the object being generated or nil if
|
101
|
+
# there is no mapping.
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
def self.puppet_strings_type
|
105
|
+
return nil unless const_defined?(:PUPPET_STRINGS_TYPE)
|
106
|
+
|
107
|
+
self::PUPPET_STRINGS_TYPE
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns an array of possible target path strings.
|
111
|
+
def targets
|
112
|
+
targets = [
|
113
|
+
target_spec_path,
|
114
|
+
target_type_spec_path,
|
115
|
+
]
|
116
|
+
|
117
|
+
unless spec_only?
|
118
|
+
targets += [
|
119
|
+
target_object_path,
|
120
|
+
target_type_path,
|
121
|
+
target_device_path,
|
122
|
+
]
|
123
|
+
end
|
124
|
+
|
125
|
+
targets.compact
|
126
|
+
end
|
127
|
+
|
95
128
|
# Check preconditions of this template group. By default this only makes sure that the target files do not
|
96
129
|
# already exist. Override this (and call super) to add your own preconditions.
|
97
130
|
#
|
@@ -99,16 +132,30 @@ module PDK
|
|
99
132
|
#
|
100
133
|
# @api public
|
101
134
|
def check_preconditions
|
102
|
-
|
103
|
-
|
135
|
+
require 'pdk/util/filesystem'
|
136
|
+
|
137
|
+
targets.each do |target_file|
|
138
|
+
next unless PDK::Util::Filesystem.exist?(target_file)
|
104
139
|
|
105
140
|
raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % {
|
106
141
|
file: target_file,
|
107
|
-
object_type: object_type,
|
142
|
+
object_type: spec_only? ? 'unit test' : object_type,
|
108
143
|
}
|
109
144
|
end
|
110
145
|
end
|
111
146
|
|
147
|
+
# Check the preconditions of this template group, behaving as a
|
148
|
+
# predicate rather than raising an exception.
|
149
|
+
#
|
150
|
+
# @return [Boolean] true if the generator is safe to run, otherwise
|
151
|
+
# false.
|
152
|
+
def can_run?
|
153
|
+
check_preconditions
|
154
|
+
true
|
155
|
+
rescue PDK::CLI::ExitWithError
|
156
|
+
false
|
157
|
+
end
|
158
|
+
|
112
159
|
# Check that the templates can be rendered. Find an appropriate template
|
113
160
|
# and create the target files from the template. This is the main entry
|
114
161
|
# point for the class.
|
@@ -123,8 +170,9 @@ module PDK
|
|
123
170
|
with_templates do |template_path, config_hash|
|
124
171
|
data = template_data.merge(configs: config_hash)
|
125
172
|
|
126
|
-
render_file(target_object_path, template_path[:object], data)
|
173
|
+
render_file(target_object_path, template_path[:object], data) unless spec_only?
|
127
174
|
render_file(target_type_path, template_path[:type], data) if template_path[:type]
|
175
|
+
render_file(target_device_path, template_path[:device], data) if template_path[:device]
|
128
176
|
render_file(target_spec_path, template_path[:spec], data) if template_path[:spec]
|
129
177
|
render_file(target_type_spec_path, template_path[:type_spec], data) if template_path[:type_spec]
|
130
178
|
end
|
@@ -148,6 +196,8 @@ module PDK
|
|
148
196
|
#
|
149
197
|
# @api private
|
150
198
|
def render_file(dest_path, template_path, data)
|
199
|
+
require 'pdk/template_file'
|
200
|
+
|
151
201
|
write_file(dest_path) do
|
152
202
|
PDK::TemplateFile.new(template_path, data).render
|
153
203
|
end
|
@@ -168,12 +218,15 @@ module PDK
|
|
168
218
|
#
|
169
219
|
# @api private
|
170
220
|
def write_file(dest_path)
|
221
|
+
require 'pdk/logger'
|
222
|
+
require 'pdk/util/filesystem'
|
223
|
+
|
171
224
|
PDK.logger.info(_("Creating '%{file}' from template.") % { file: dest_path })
|
172
225
|
|
173
226
|
file_content = yield
|
174
227
|
|
175
228
|
begin
|
176
|
-
|
229
|
+
PDK::Util::Filesystem.mkdir_p(File.dirname(dest_path))
|
177
230
|
rescue SystemCallError => e
|
178
231
|
raise PDK::CLI::FatalError, _("Unable to create directory '%{path}': %{message}") % {
|
179
232
|
path: File.dirname(dest_path),
|
@@ -204,13 +257,17 @@ module PDK
|
|
204
257
|
#
|
205
258
|
# @api private
|
206
259
|
def with_templates
|
260
|
+
require 'pdk/logger'
|
261
|
+
require 'pdk/module/templatedir'
|
262
|
+
require 'pdk/util/template_uri'
|
263
|
+
|
207
264
|
templates.each do |template|
|
208
|
-
if template[:
|
209
|
-
PDK.logger.debug(_('No %{dir_type} template
|
265
|
+
if template[:uri].nil?
|
266
|
+
PDK.logger.debug(_('No %{dir_type} template found; trying next template directory.') % { dir_type: template[:type] })
|
210
267
|
next
|
211
268
|
end
|
212
269
|
|
213
|
-
PDK::Module::TemplateDir.new(template[:
|
270
|
+
PDK::Module::TemplateDir.new(PDK::Util::TemplateURI.new(template[:uri])) do |template_dir|
|
214
271
|
template_paths = template_dir.object_template_for(object_type)
|
215
272
|
|
216
273
|
if template_paths
|
@@ -219,9 +276,9 @@ module PDK
|
|
219
276
|
# TODO: refactor to a search-and-execute form instead
|
220
277
|
return # work is done # rubocop:disable Lint/NonLocalExitFromIterator
|
221
278
|
elsif template[:allow_fallback]
|
222
|
-
PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: object_type, url: template[:
|
279
|
+
PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: object_type, url: template[:uri] })
|
223
280
|
else
|
224
|
-
raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: object_type, url: template[:
|
281
|
+
raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: object_type, url: template[:uri] }
|
225
282
|
end
|
226
283
|
end
|
227
284
|
end
|
@@ -250,38 +307,28 @@ module PDK
|
|
250
307
|
#
|
251
308
|
# @api private
|
252
309
|
def templates
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
{ type: 'default', url: PDK::Util.default_template_url, allow_fallback: false },
|
257
|
-
]
|
310
|
+
require 'pdk/util/template_uri'
|
311
|
+
|
312
|
+
@templates ||= PDK::Util::TemplateURI.templates(@options)
|
258
313
|
end
|
259
314
|
|
260
315
|
# Retrieves the name of the module (without the forge username) from the
|
261
316
|
# module metadata.
|
262
317
|
#
|
263
|
-
# @raise (see #module_metadata)
|
264
318
|
# @return [String] The name of the module.
|
265
319
|
#
|
266
320
|
# @api private
|
267
321
|
def module_name
|
268
|
-
|
322
|
+
require 'pdk/util'
|
323
|
+
|
324
|
+
@module_name ||= PDK::Util.module_metadata['name'].rpartition('-').last
|
325
|
+
rescue ArgumentError => e
|
326
|
+
raise PDK::CLI::FatalError, e
|
269
327
|
end
|
270
328
|
|
271
|
-
#
|
272
|
-
|
273
|
-
|
274
|
-
# can not be read, or contains invalid metadata.
|
275
|
-
#
|
276
|
-
# @return [PDK::Module::Metadata] the parsed module metadata.
|
277
|
-
#
|
278
|
-
# @api private
|
279
|
-
def module_metadata
|
280
|
-
@module_metadata ||= begin
|
281
|
-
PDK::Module::Metadata.from_file(File.join(module_dir, 'metadata.json'))
|
282
|
-
rescue ArgumentError => e
|
283
|
-
raise PDK::CLI::FatalError, _("'%{dir}' does not contain valid Puppet module metadata: %{msg}") % { dir: module_dir, msg: e.message }
|
284
|
-
end
|
329
|
+
# transform a object name into a ruby class name
|
330
|
+
def self.class_name_from_object_name(object_name)
|
331
|
+
object_name.to_s.split('_').map(&:capitalize).join
|
285
332
|
end
|
286
333
|
end
|
287
334
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'pdk/generate/puppet_object'
|
2
|
+
|
3
|
+
module PDK
|
4
|
+
module Generate
|
5
|
+
class Transport < PuppetObject
|
6
|
+
OBJECT_TYPE = :transport
|
7
|
+
|
8
|
+
# Prepares the data needed to render the new defined type template.
|
9
|
+
#
|
10
|
+
# @return [Hash{Symbol => Object}] a hash of information that will be
|
11
|
+
# provided to the defined type and defined type spec templates during
|
12
|
+
# rendering.
|
13
|
+
def template_data
|
14
|
+
data = {
|
15
|
+
name: object_name,
|
16
|
+
transport_class: Transport.class_name_from_object_name(object_name),
|
17
|
+
}
|
18
|
+
|
19
|
+
data
|
20
|
+
end
|
21
|
+
|
22
|
+
def raise_precondition_error(error)
|
23
|
+
raise PDK::CLI::ExitWithError, _('%{error}: Creating a transport needs some local configuration in your module.' \
|
24
|
+
' Please follow the docs at https://github.com/puppetlabs/puppet-resource_api#getting-started.') % { error: error }
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_preconditions
|
28
|
+
super
|
29
|
+
# These preconditions can be removed once the pdk-templates are carrying the puppet-resource_api gem by default, and have switched
|
30
|
+
# the default mock_with value.
|
31
|
+
sync_path = PDK::Util.find_upwards('.sync.yml')
|
32
|
+
if sync_path.nil?
|
33
|
+
raise_precondition_error(_('.sync.yml not found'))
|
34
|
+
end
|
35
|
+
sync = YAML.load_file(sync_path)
|
36
|
+
if !sync.is_a? Hash
|
37
|
+
raise_precondition_error(_('.sync.yml contents is not a Hash'))
|
38
|
+
elsif !sync.key? 'Gemfile'
|
39
|
+
raise_precondition_error(_('Gemfile configuration not found'))
|
40
|
+
elsif !sync['Gemfile'].key? 'optional'
|
41
|
+
raise_precondition_error(_('Gemfile.optional configuration not found'))
|
42
|
+
elsif !sync['Gemfile']['optional'].key? ':development'
|
43
|
+
raise_precondition_error(_('Gemfile.optional.:development configuration not found'))
|
44
|
+
elsif sync['Gemfile']['optional'][':development'].none? { |g| g['gem'] == 'puppet-resource_api' }
|
45
|
+
raise_precondition_error(_('puppet-resource_api not found in the Gemfile config'))
|
46
|
+
elsif !sync.key? 'spec/spec_helper.rb'
|
47
|
+
raise_precondition_error(_('spec/spec_helper.rb configuration not found'))
|
48
|
+
elsif !sync['spec/spec_helper.rb'].key? 'mock_with'
|
49
|
+
raise_precondition_error(_('spec/spec_helper.rb.mock_with configuration not found'))
|
50
|
+
elsif !sync['spec/spec_helper.rb']['mock_with'] == ':rspec'
|
51
|
+
raise_precondition_error(_('spec/spec_helper.rb.mock_with not set to \':rspec\''))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String] the path where the new transport will be written.
|
56
|
+
def target_object_path
|
57
|
+
@target_object_path ||= File.join(module_dir, 'lib', 'puppet', 'transport', object_name) + '.rb'
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [String] the path where the new schema will be written.
|
61
|
+
def target_type_path
|
62
|
+
@target_type_path ||= File.join(module_dir, 'lib', 'puppet', 'transport', 'schema', object_name) + '.rb'
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [String] the path where the deviceshim for the transport will be written.
|
66
|
+
def target_device_path
|
67
|
+
@target_device_path ||= File.join(module_dir, 'lib', 'puppet', 'util', 'network_device', object_name, 'device.rb')
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [String] the path where the tests for the new transport
|
71
|
+
# will be written.
|
72
|
+
def target_spec_path
|
73
|
+
@target_spec_path ||= File.join(module_dir, 'spec', 'unit', 'puppet', 'transport', object_name) + '_spec.rb'
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [String] the path where the tests for the new schema will be written.
|
77
|
+
def target_type_spec_path
|
78
|
+
@target_type_spec_path ||= File.join(module_dir, 'spec', 'unit', 'puppet', 'transport', 'schema', object_name) + '_spec.rb'
|
79
|
+
end
|
80
|
+
|
81
|
+
# transform a object name into a ruby class name
|
82
|
+
def self.class_name_from_object_name(object_name)
|
83
|
+
object_name.to_s.split('_').map(&:capitalize).join
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/pdk/logger.rb
CHANGED
@@ -6,17 +6,37 @@ module PDK
|
|
6
6
|
end
|
7
7
|
|
8
8
|
class Logger < ::Logger
|
9
|
+
WRAP_COLUMN_LIMIT = 78
|
10
|
+
|
9
11
|
def initialize
|
10
12
|
super(STDERR)
|
13
|
+
@sent_messages = {}
|
11
14
|
|
12
15
|
# TODO: Decide on output format.
|
13
16
|
self.formatter = proc do |severity, _datetime, _progname, msg|
|
14
|
-
"pdk (#{severity}):
|
17
|
+
prefix = "pdk (#{severity}): "
|
18
|
+
if msg.is_a?(Hash)
|
19
|
+
if msg.fetch(:wrap, false)
|
20
|
+
wrap_pattern = %r{(.{1,#{WRAP_COLUMN_LIMIT - prefix.length}})(\s+|\Z)}
|
21
|
+
"#{prefix}#{msg[:text].gsub(wrap_pattern, "\\1\n#{' ' * prefix.length}")}\n"
|
22
|
+
else
|
23
|
+
"#{prefix}#{msg[:text]}\n"
|
24
|
+
end
|
25
|
+
else
|
26
|
+
"#{prefix}#{msg}\n"
|
27
|
+
end
|
15
28
|
end
|
16
29
|
|
17
30
|
self.level = ::Logger::INFO
|
18
31
|
end
|
19
32
|
|
33
|
+
def warn_once(*args)
|
34
|
+
hash = args.inspect.hash
|
35
|
+
return if (@sent_messages[::Logger::WARN] ||= {}).key?(hash)
|
36
|
+
@sent_messages[::Logger::WARN][hash] = true
|
37
|
+
warn(*args)
|
38
|
+
end
|
39
|
+
|
20
40
|
def enable_debug_output
|
21
41
|
self.level = ::Logger::DEBUG
|
22
42
|
end
|
data/lib/pdk/module.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'pathspec'
|
2
|
-
|
3
1
|
module PDK
|
4
2
|
module Module
|
5
3
|
DEFAULT_IGNORED = [
|
@@ -13,6 +11,8 @@ module PDK
|
|
13
11
|
].freeze
|
14
12
|
|
15
13
|
def default_ignored_pathspec(ignore_dotfiles = true)
|
14
|
+
require 'pathspec'
|
15
|
+
|
16
16
|
PathSpec.new(DEFAULT_IGNORED).tap do |ps|
|
17
17
|
ps.add('.*') if ignore_dotfiles
|
18
18
|
end
|
data/lib/pdk/module/build.rb
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'minitar'
|
3
|
-
require 'zlib'
|
4
|
-
require 'pathspec'
|
5
|
-
require 'find'
|
6
|
-
require 'pdk/module'
|
7
|
-
require 'pdk/tests/unit'
|
8
|
-
|
9
1
|
module PDK
|
10
2
|
module Module
|
11
3
|
class Build
|
@@ -26,6 +18,8 @@ module PDK
|
|
26
18
|
#
|
27
19
|
# @return [Hash{String => Object}] The hash of metadata values.
|
28
20
|
def metadata
|
21
|
+
require 'pdk/module/metadata'
|
22
|
+
|
29
23
|
@metadata ||= PDK::Module::Metadata.from_file(File.join(module_dir, 'metadata.json')).data
|
30
24
|
end
|
31
25
|
|
@@ -71,6 +65,8 @@ module PDK
|
|
71
65
|
#
|
72
66
|
# If the directory already exists, remove it first.
|
73
67
|
def create_build_dir
|
68
|
+
require 'fileutils'
|
69
|
+
|
74
70
|
cleanup_build_dir
|
75
71
|
|
76
72
|
FileUtils.mkdir_p(build_dir)
|
@@ -80,6 +76,8 @@ module PDK
|
|
80
76
|
#
|
81
77
|
# @return nil.
|
82
78
|
def cleanup_build_dir
|
79
|
+
require 'fileutils'
|
80
|
+
|
83
81
|
FileUtils.rm_rf(build_dir, secure: true)
|
84
82
|
end
|
85
83
|
|
@@ -99,6 +97,8 @@ module PDK
|
|
99
97
|
#
|
100
98
|
# @return nil
|
101
99
|
def stage_module_in_build_dir
|
100
|
+
require 'find'
|
101
|
+
|
102
102
|
Find.find(module_dir) do |path|
|
103
103
|
next if path == module_dir
|
104
104
|
|
@@ -112,6 +112,9 @@ module PDK
|
|
112
112
|
#
|
113
113
|
# @return nil.
|
114
114
|
def stage_path(path)
|
115
|
+
require 'pathname'
|
116
|
+
require 'fileutils'
|
117
|
+
|
115
118
|
relative_path = Pathname.new(path).relative_path_from(Pathname.new(module_dir))
|
116
119
|
dest_path = File.join(build_dir, relative_path)
|
117
120
|
|
@@ -120,8 +123,14 @@ module PDK
|
|
120
123
|
elsif File.symlink?(path)
|
121
124
|
warn_symlink(path)
|
122
125
|
else
|
126
|
+
validate_ustar_path!(relative_path.to_path)
|
123
127
|
FileUtils.cp(path, dest_path, preserve: true)
|
124
128
|
end
|
129
|
+
rescue ArgumentError => e
|
130
|
+
raise PDK::CLI::ExitWithError, _(
|
131
|
+
'%{message} Rename the file or exclude it from the package ' \
|
132
|
+
'by adding it to the .pdkignore file in your module.',
|
133
|
+
) % { message: e.message }
|
125
134
|
end
|
126
135
|
|
127
136
|
# Check if the given path matches one of the patterns listed in the
|
@@ -143,6 +152,8 @@ module PDK
|
|
143
152
|
#
|
144
153
|
# @return nil.
|
145
154
|
def warn_symlink(path)
|
155
|
+
require 'pathname'
|
156
|
+
|
146
157
|
symlink_path = Pathname.new(path)
|
147
158
|
module_path = Pathname.new(module_dir)
|
148
159
|
|
@@ -152,6 +163,58 @@ module PDK
|
|
152
163
|
}
|
153
164
|
end
|
154
165
|
|
166
|
+
# Checks if the path length will fit into the POSIX.1-1998 (ustar) tar
|
167
|
+
# header format.
|
168
|
+
#
|
169
|
+
# POSIX.1-2001 (which allows paths of infinite length) was adopted by GNU
|
170
|
+
# tar in 2004 and is supported by minitar 0.7 and above. Unfortunately
|
171
|
+
# much of the Puppet ecosystem still uses minitar 0.6.1.
|
172
|
+
#
|
173
|
+
# POSIX.1-1998 tar format does not allow for paths greater than 256 bytes,
|
174
|
+
# or paths that can't be split into a prefix of 155 bytes (max) and
|
175
|
+
# a suffix of 100 bytes (max).
|
176
|
+
#
|
177
|
+
# This logic was pretty much copied from the private method
|
178
|
+
# {Archive::Tar::Minitar::Writer#split_name}.
|
179
|
+
#
|
180
|
+
# @param path [String] the relative path to be added to the tar file.
|
181
|
+
#
|
182
|
+
# @raise [ArgumentError] if the path is too long or could not be split.
|
183
|
+
#
|
184
|
+
# @return [nil]
|
185
|
+
def validate_ustar_path!(path)
|
186
|
+
if path.bytesize > 256
|
187
|
+
raise ArgumentError, _("The path '%{path}' is longer than 256 bytes.") % {
|
188
|
+
path: path,
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
192
|
+
if path.bytesize <= 100
|
193
|
+
prefix = ''
|
194
|
+
else
|
195
|
+
parts = path.split(File::SEPARATOR)
|
196
|
+
newpath = parts.pop
|
197
|
+
nxt = ''
|
198
|
+
|
199
|
+
loop do
|
200
|
+
nxt = parts.pop || ''
|
201
|
+
break if newpath.bytesize + 1 + nxt.bytesize >= 100
|
202
|
+
newpath = File.join(nxt, newpath)
|
203
|
+
end
|
204
|
+
|
205
|
+
prefix = File.join(*parts, nxt)
|
206
|
+
path = newpath
|
207
|
+
end
|
208
|
+
|
209
|
+
return unless path.bytesize > 100 || prefix.bytesize > 155
|
210
|
+
|
211
|
+
raise ArgumentError, _(
|
212
|
+
"'%{path}' could not be split at a directory separator into two " \
|
213
|
+
'parts, the first having a maximum length of 155 bytes and the ' \
|
214
|
+
'second having a maximum length of 100 bytes.',
|
215
|
+
) % { path: path }
|
216
|
+
end
|
217
|
+
|
155
218
|
# Creates a gzip compressed tarball of the build directory.
|
156
219
|
#
|
157
220
|
# If the destination package already exists, it will be removed before
|
@@ -159,11 +222,38 @@ module PDK
|
|
159
222
|
#
|
160
223
|
# @return nil.
|
161
224
|
def build_package
|
225
|
+
require 'fileutils'
|
226
|
+
require 'zlib'
|
227
|
+
require 'minitar'
|
228
|
+
require 'find'
|
229
|
+
|
162
230
|
FileUtils.rm_f(package_file)
|
163
231
|
|
164
232
|
Dir.chdir(target_dir) do
|
165
|
-
|
166
|
-
|
233
|
+
begin
|
234
|
+
gz = Zlib::GzipWriter.new(File.open(package_file, 'wb'))
|
235
|
+
tar = Minitar::Output.new(gz)
|
236
|
+
Find.find(release_name) do |entry|
|
237
|
+
entry_meta = {
|
238
|
+
name: entry,
|
239
|
+
}
|
240
|
+
|
241
|
+
orig_mode = File.stat(entry).mode
|
242
|
+
min_mode = Minitar.dir?(entry) ? 0o755 : 0o644
|
243
|
+
|
244
|
+
entry_meta[:mode] = orig_mode | min_mode
|
245
|
+
|
246
|
+
if entry_meta[:mode] != orig_mode
|
247
|
+
PDK.logger.debug(_('Updated permissions of packaged \'%{entry}\' to %{new_mode}') % {
|
248
|
+
entry: entry,
|
249
|
+
new_mode: (entry_meta[:mode] & 0o7777).to_s(8),
|
250
|
+
})
|
251
|
+
end
|
252
|
+
|
253
|
+
Minitar.pack_file(entry_meta, tar)
|
254
|
+
end
|
255
|
+
ensure
|
256
|
+
tar.close
|
167
257
|
end
|
168
258
|
end
|
169
259
|
end
|
@@ -188,6 +278,9 @@ module PDK
|
|
188
278
|
#
|
189
279
|
# @return [PathSpec] The populated ignore path matcher.
|
190
280
|
def ignored_files
|
281
|
+
require 'pdk/module'
|
282
|
+
require 'pathspec'
|
283
|
+
|
191
284
|
@ignored_files ||=
|
192
285
|
begin
|
193
286
|
ignored = if ignore_file.nil?
|