pdk 3.0.1 → 3.3.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/lib/pdk/cli/build.rb +6 -5
  4. data/lib/pdk/cli/bundle.rb +0 -2
  5. data/lib/pdk/cli/console.rb +0 -2
  6. data/lib/pdk/cli/convert.rb +3 -3
  7. data/lib/pdk/cli/env.rb +0 -2
  8. data/lib/pdk/cli/exec/command.rb +0 -2
  9. data/lib/pdk/cli/new/class.rb +0 -2
  10. data/lib/pdk/cli/new/defined_type.rb +0 -2
  11. data/lib/pdk/cli/new/fact.rb +0 -2
  12. data/lib/pdk/cli/new/function.rb +0 -2
  13. data/lib/pdk/cli/new/module.rb +0 -2
  14. data/lib/pdk/cli/new/provider.rb +0 -2
  15. data/lib/pdk/cli/new/task.rb +0 -2
  16. data/lib/pdk/cli/new/test.rb +0 -2
  17. data/lib/pdk/cli/release/prep.rb +0 -2
  18. data/lib/pdk/cli/release/publish.rb +0 -2
  19. data/lib/pdk/cli/release.rb +0 -9
  20. data/lib/pdk/cli/test/unit.rb +0 -2
  21. data/lib/pdk/cli/update.rb +3 -3
  22. data/lib/pdk/cli/util.rb +0 -38
  23. data/lib/pdk/cli/validate.rb +0 -7
  24. data/lib/pdk/cli.rb +0 -2
  25. data/lib/pdk/config/namespace.rb +3 -3
  26. data/lib/pdk/config/setting.rb +3 -3
  27. data/lib/pdk/config.rb +0 -80
  28. data/lib/pdk/module/convert.rb +8 -3
  29. data/lib/pdk/module/metadata.rb +18 -10
  30. data/lib/pdk/module/release.rb +9 -6
  31. data/lib/pdk/module/update_manager.rb +29 -3
  32. data/lib/pdk/report/event.rb +1 -1
  33. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +10 -13
  34. data/lib/pdk/template/renderer/v1/renderer.rb +3 -1
  35. data/lib/pdk/template.rb +0 -3
  36. data/lib/pdk/tests/unit.rb +3 -3
  37. data/lib/pdk/util/filesystem.rb +10 -0
  38. data/lib/pdk/util.rb +1 -0
  39. data/lib/pdk/version.rb +2 -2
  40. data/lib/pdk.rb +0 -14
  41. metadata +63 -98
  42. data/lib/pdk/analytics/client/google_analytics.rb +0 -141
  43. data/lib/pdk/analytics/client/noop.rb +0 -25
  44. data/lib/pdk/analytics/util.rb +0 -18
  45. data/lib/pdk/analytics.rb +0 -30
  46. data/lib/pdk/config/analytics_schema.json +0 -26
  47. data/lib/pdk/module/build.rb +0 -302
  48. data/lib/pdk/monkey_patches.rb +0 -268
@@ -1,302 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Module
5
- class Build
6
- def self.invoke(options = {})
7
- new(options).build
8
- end
9
-
10
- attr_reader :module_dir, :target_dir
11
-
12
- def initialize(options = {})
13
- @module_dir = PDK::Util::Filesystem.expand_path(options[:module_dir] || Dir.pwd)
14
- @target_dir = PDK::Util::Filesystem.expand_path(options[:'target-dir'] || File.join(module_dir, 'pkg'))
15
- end
16
-
17
- # Read and parse the values from metadata.json for the module that is
18
- # being built.
19
- #
20
- # @return [Hash{String => Object}] The hash of metadata values.
21
- def metadata
22
- require 'pdk/module/metadata'
23
-
24
- @metadata ||= PDK::Module::Metadata.from_file(File.join(module_dir, 'metadata.json')).data
25
- end
26
-
27
- # Return the path where the built package file will be written to.
28
- def package_file
29
- @package_file ||= File.join(target_dir, "#{release_name}.tar.gz")
30
- end
31
-
32
- # Build a module package from a module directory.
33
- #
34
- # @return [String] The path to the built package file.
35
- def build
36
- create_build_dir
37
-
38
- stage_module_in_build_dir
39
- build_package
40
-
41
- package_file
42
- ensure
43
- cleanup_build_dir
44
- end
45
-
46
- # Verify if there is an existing package in the target directory and prompts
47
- # the user if they want to overwrite it.
48
- def package_already_exists?
49
- PDK::Util::Filesystem.exist?(package_file)
50
- end
51
-
52
- # Check if the module is PDK Compatible. If not, then prompt the user if
53
- # they want to run PDK Convert.
54
- def module_pdk_compatible?
55
- ['pdk-version', 'template-url'].any? { |key| metadata.key?(key) }
56
- end
57
-
58
- # Return the path to the temporary build directory, which will be placed
59
- # inside the target directory and match the release name (see #release_name).
60
- def build_dir
61
- @build_dir ||= File.join(target_dir, release_name)
62
- end
63
-
64
- # Create a temporary build directory where the files to be included in
65
- # the package will be staged before building the tarball.
66
- #
67
- # If the directory already exists, remove it first.
68
- def create_build_dir
69
- cleanup_build_dir
70
-
71
- PDK::Util::Filesystem.mkdir_p(build_dir)
72
- end
73
-
74
- # Remove the temporary build directory and all its contents from disk.
75
- #
76
- # @return nil.
77
- def cleanup_build_dir
78
- PDK::Util::Filesystem.rm_rf(build_dir, secure: true)
79
- end
80
-
81
- # Combine the module name and version into a Forge-compatible dash
82
- # separated string.
83
- #
84
- # @return [String] The module name and version, joined by a dash.
85
- def release_name
86
- @release_name ||= [
87
- metadata['name'],
88
- metadata['version']
89
- ].join('-')
90
- end
91
-
92
- # Iterate through all the files and directories in the module and stage
93
- # them into the temporary build directory (unless ignored).
94
- #
95
- # @return nil
96
- def stage_module_in_build_dir
97
- require 'find'
98
-
99
- Find.find(module_dir) do |path|
100
- next if path == module_dir
101
-
102
- ignored_path?(path) ? Find.prune : stage_path(path)
103
- end
104
- end
105
-
106
- # Stage a file or directory from the module into the build directory.
107
- #
108
- # @param path [String] The path to the file or directory.
109
- #
110
- # @return nil.
111
- def stage_path(path)
112
- require 'pathname'
113
-
114
- relative_path = Pathname.new(path).relative_path_from(Pathname.new(module_dir))
115
- dest_path = File.join(build_dir, relative_path)
116
-
117
- validate_path_encoding!(relative_path.to_path)
118
-
119
- if PDK::Util::Filesystem.directory?(path)
120
- PDK::Util::Filesystem.mkdir_p(dest_path, mode: PDK::Util::Filesystem.stat(path).mode)
121
- elsif PDK::Util::Filesystem.symlink?(path)
122
- warn_symlink(path)
123
- else
124
- validate_ustar_path!(relative_path.to_path)
125
- PDK::Util::Filesystem.cp(path, dest_path, preserve: true)
126
- end
127
- rescue ArgumentError => e
128
- raise PDK::CLI::ExitWithError, format('%{message} Rename the file or exclude it from the package ' \
129
- 'by adding it to the .pdkignore file in your module.', message: e.message)
130
- end
131
-
132
- # Check if the given path matches one of the patterns listed in the
133
- # ignore file.
134
- #
135
- # @param path [String] The path to be checked.
136
- #
137
- # @return [Boolean] true if the path matches and should be ignored.
138
- def ignored_path?(path)
139
- path = "#{path}/" if PDK::Util::Filesystem.directory?(path)
140
-
141
- !ignored_files.match_paths([path], module_dir).empty?
142
- end
143
-
144
- # Warn the user about a symlink that would have been included in the
145
- # built package.
146
- #
147
- # @param path [String] The relative or absolute path to the symlink.
148
- #
149
- # @return nil.
150
- def warn_symlink(path)
151
- require 'pathname'
152
-
153
- symlink_path = Pathname.new(path)
154
- module_path = Pathname.new(module_dir)
155
-
156
- PDK.logger.warn format('Symlinks in modules are not supported and will not be included in the package. Please investigate symlink %{from} -> %{to}.',
157
- from: symlink_path.relative_path_from(module_path), to: symlink_path.realpath.relative_path_from(module_path))
158
- end
159
-
160
- # Checks if the path length will fit into the POSIX.1-1998 (ustar) tar
161
- # header format.
162
- #
163
- # POSIX.1-2001 (which allows paths of infinite length) was adopted by GNU
164
- # tar in 2004 and is supported by minitar 0.7 and above. Unfortunately
165
- # much of the Puppet ecosystem still uses minitar 0.6.1.
166
- #
167
- # POSIX.1-1998 tar format does not allow for paths greater than 256 bytes,
168
- # or paths that can't be split into a prefix of 155 bytes (max) and
169
- # a suffix of 100 bytes (max).
170
- #
171
- # This logic was pretty much copied from the private method
172
- # {Archive::Tar::Minitar::Writer#split_name}.
173
- #
174
- # @param path [String] the relative path to be added to the tar file.
175
- #
176
- # @raise [ArgumentError] if the path is too long or could not be split.
177
- #
178
- # @return [nil]
179
- def validate_ustar_path!(path)
180
- raise ArgumentError, format("The path '%{path}' is longer than 256 bytes.", path: path) if path.bytesize > 256
181
-
182
- if path.bytesize <= 100
183
- prefix = ''
184
- else
185
- parts = path.split(File::SEPARATOR)
186
- newpath = parts.pop
187
- nxt = ''
188
-
189
- loop do
190
- nxt = parts.pop || ''
191
- break if newpath.bytesize + 1 + nxt.bytesize >= 100
192
-
193
- newpath = File.join(nxt, newpath)
194
- end
195
-
196
- prefix = File.join(*parts, nxt)
197
- path = newpath
198
- end
199
-
200
- return unless path.bytesize > 100 || prefix.bytesize > 155
201
-
202
- raise ArgumentError,
203
- format("'%{path}' could not be split at a directory separator into two " \
204
- 'parts, the first having a maximum length of 155 bytes and the ' \
205
- 'second having a maximum length of 100 bytes.', path: path)
206
- end
207
-
208
- # Checks if the path contains any non-ASCII characters.
209
- #
210
- # Java will throw an error when it encounters a path containing
211
- # characters that are not supported by the hosts locale. In order to
212
- # maximise compatibility we limit the paths to contain only ASCII
213
- # characters, which should be part of any locale character set.
214
- #
215
- # @param path [String] the relative path to be added to the tar file.
216
- #
217
- # @raise [ArgumentError] if the path contains non-ASCII characters.
218
- #
219
- # @return [nil]
220
- def validate_path_encoding!(path)
221
- return unless /[^\x00-\x7F]/.match?(path)
222
-
223
- raise ArgumentError, format("'%{path}' can only include ASCII characters in its path or " \
224
- 'filename in order to be compatible with a wide range of hosts.', path: path)
225
- end
226
-
227
- # Creates a gzip compressed tarball of the build directory.
228
- #
229
- # If the destination package already exists, it will be removed before
230
- # creating the new tarball.
231
- #
232
- # @return nil.
233
- def build_package
234
- require 'zlib'
235
- require 'minitar'
236
- require 'find'
237
-
238
- PDK::Util::Filesystem.rm_f(package_file)
239
-
240
- Dir.chdir(target_dir) do
241
- gz = Zlib::GzipWriter.new(File.open(package_file, 'wb')) # rubocop:disable PDK/FileOpen
242
- tar = Minitar::Output.new(gz)
243
- Find.find(release_name) do |entry|
244
- entry_meta = {
245
- name: entry
246
- }
247
-
248
- orig_mode = PDK::Util::Filesystem.stat(entry).mode
249
- min_mode = Minitar.dir?(entry) ? 0o755 : 0o644
250
-
251
- entry_meta[:mode] = orig_mode | min_mode
252
-
253
- PDK.logger.debug(format('Updated permissions of packaged \'%{entry}\' to %{new_mode}', entry: entry, new_mode: (entry_meta[:mode] & 0o7777).to_s(8))) if entry_meta[:mode] != orig_mode
254
-
255
- Minitar.pack_file(entry_meta, tar)
256
- end
257
- ensure
258
- tar.close
259
- end
260
- end
261
-
262
- # Select the most appropriate ignore file in the module directory.
263
- #
264
- # In order of preference, we first try `.pdkignore`, then `.pmtignore`
265
- # and finally `.gitignore`.
266
- #
267
- # @return [String] The path to the file containing the patterns of file
268
- # paths to ignore.
269
- def ignore_file
270
- @ignore_file ||= [
271
- File.join(module_dir, '.pdkignore'),
272
- File.join(module_dir, '.pmtignore'),
273
- File.join(module_dir, '.gitignore')
274
- ].find { |file| PDK::Util::Filesystem.file?(file) && PDK::Util::Filesystem.readable?(file) }
275
- end
276
-
277
- # Instantiate a new PathSpec class and populate it with the pattern(s) of
278
- # files to be ignored.
279
- #
280
- # @return [PathSpec] The populated ignore path matcher.
281
- def ignored_files
282
- require 'pdk/module'
283
- require 'pathspec'
284
-
285
- @ignored_files ||=
286
- begin
287
- ignored = if ignore_file.nil?
288
- PathSpec.new
289
- else
290
- PathSpec.new(PDK::Util::Filesystem.read_file(ignore_file, open_args: 'rb:UTF-8'))
291
- end
292
-
293
- ignored = ignored.add("/#{File.basename(target_dir)}/") if File.realdirpath(target_dir).start_with?(File.realdirpath(module_dir))
294
-
295
- PDK::Module::DEFAULT_IGNORED.each { |r| ignored.add(r) }
296
-
297
- ignored
298
- end
299
- end
300
- end
301
- end
302
- end
@@ -1,268 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OS
4
- # Os detection: Are we on Windows?
5
- def self.windows?
6
- (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
7
- end
8
- end
9
-
10
- # Patch childprocess so that it is Ruby 3 compliant.
11
- # This could be removed if the following PR is ever merged
12
- # and released:
13
- # https://github.com/enkessler/childprocess/pull/185
14
- module ChildProcess
15
- class << self
16
- def build(*args)
17
- case os
18
- when :macosx, :linux, :solaris, :bsd, :cygwin, :aix
19
- if posix_spawn?
20
- Unix::PosixSpawnProcess.new(*args)
21
- elsif jruby?
22
- JRuby::Process.new(*args)
23
- else
24
- Unix::ForkExecProcess.new(*args)
25
- end
26
- when :windows
27
- Windows::Process.new(*args)
28
- else
29
- raise Error, "unsupported platform #{platform_name.inspect}"
30
- end
31
- end
32
- end
33
-
34
- class AbstractProcess
35
- def initialize(*args)
36
- raise ArgumentError, "all arguments must be String: #{args.inspect}" unless args.all?(String)
37
-
38
- @args = args
39
- @started = false
40
- @exit_code = nil
41
- @io = nil
42
- @cwd = nil
43
- @detach = false
44
- @duplex = false
45
- @leader = false
46
- @environment = {}
47
- end
48
- end
49
-
50
- if OS.windows?
51
- module Windows
52
- module Lib
53
- extend FFI::Library
54
- def self.msvcrt_name
55
- RbConfig::CONFIG['RUBY_SO_NAME'][/msvc\w+/] || 'ucrtbase'
56
- end
57
-
58
- ffi_lib 'kernel32', msvcrt_name
59
- ffi_convention :stdcall
60
-
61
- # We have to redefine the function declarations so that they are available
62
- # with the patched ffi_lib.
63
- enum :wait_status, [
64
- :wait_object_0, 0, # rubocop:disable Naming/VariableNumber
65
- :wait_timeout, 0x102,
66
- :wait_abandoned, 0x80,
67
- :wait_failed, 0xFFFFFFFF
68
- ]
69
-
70
- #
71
- # BOOL WINAPI CreateProcess(
72
- # __in_opt LPCTSTR lpApplicationName,
73
- # __inout_opt LPTSTR lpCommandLine,
74
- # __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
75
- # __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
76
- # __in BOOL bInheritHandles,
77
- # __in DWORD dwCreationFlags,
78
- # __in_opt LPVOID lpEnvironment,
79
- # __in_opt LPCTSTR lpCurrentDirectory,
80
- # __in LPSTARTUPINFO lpStartupInfo,
81
- # __out LPPROCESS_INFORMATION lpProcessInformation
82
- # );
83
- #
84
-
85
- attach_function :create_process, :CreateProcessW, [
86
- :pointer,
87
- :buffer_inout,
88
- :pointer,
89
- :pointer,
90
- :bool,
91
- :ulong,
92
- :pointer,
93
- :pointer,
94
- :pointer,
95
- :pointer
96
- ], :bool
97
-
98
- #
99
- # DWORD WINAPI FormatMessage(
100
- # __in DWORD dwFlags,
101
- # __in_opt LPCVOID lpSource,
102
- # __in DWORD dwMessageId,
103
- # __in DWORD dwLanguageId,
104
- # __out LPTSTR lpBuffer,
105
- # __in DWORD nSize,
106
- # __in_opt va_list *Arguments
107
- # );
108
- #
109
-
110
- attach_function :format_message, :FormatMessageA, [
111
- :ulong,
112
- :pointer,
113
- :ulong,
114
- :ulong,
115
- :pointer,
116
- :ulong,
117
- :pointer
118
- ], :ulong
119
-
120
- attach_function :close_handle, :CloseHandle, [:pointer], :bool
121
-
122
- #
123
- # HANDLE WINAPI OpenProcess(
124
- # __in DWORD dwDesiredAccess,
125
- # __in BOOL bInheritHandle,
126
- # __in DWORD dwProcessId
127
- # );
128
- #
129
-
130
- attach_function :open_process, :OpenProcess, [:ulong, :bool, :ulong], :pointer
131
-
132
- #
133
- # HANDLE WINAPI CreateJobObject(
134
- # _In_opt_ LPSECURITY_ATTRIBUTES lpJobAttributes,
135
- # _In_opt_ LPCTSTR lpName
136
- # );
137
- #
138
-
139
- attach_function :create_job_object, :CreateJobObjectA, [:pointer, :pointer], :pointer
140
-
141
- #
142
- # BOOL WINAPI AssignProcessToJobObject(
143
- # _In_ HANDLE hJob,
144
- # _In_ HANDLE hProcess
145
- # );
146
-
147
- attach_function :assign_process_to_job_object, :AssignProcessToJobObject, [:pointer, :pointer], :bool
148
-
149
- #
150
- # BOOL WINAPI SetInformationJobObject(
151
- # _In_ HANDLE hJob,
152
- # _In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
153
- # _In_ LPVOID lpJobObjectInfo,
154
- # _In_ DWORD cbJobObjectInfoLength
155
- # );
156
- #
157
-
158
- attach_function :set_information_job_object, :SetInformationJobObject, [:pointer, :int, :pointer, :ulong], :bool
159
-
160
- #
161
- #
162
- # DWORD WINAPI WaitForSingleObject(
163
- # __in HANDLE hHandle,
164
- # __in DWORD dwMilliseconds
165
- # );
166
- #
167
-
168
- attach_function :wait_for_single_object, :WaitForSingleObject, [:pointer, :ulong], :wait_status, blocking: true
169
-
170
- #
171
- # BOOL WINAPI GetExitCodeProcess(
172
- # __in HANDLE hProcess,
173
- # __out LPDWORD lpExitCode
174
- # );
175
- #
176
-
177
- attach_function :get_exit_code, :GetExitCodeProcess, [:pointer, :pointer], :bool
178
-
179
- #
180
- # BOOL WINAPI GenerateConsoleCtrlEvent(
181
- # __in DWORD dwCtrlEvent,
182
- # __in DWORD dwProcessGroupId
183
- # );
184
- #
185
-
186
- attach_function :generate_console_ctrl_event, :GenerateConsoleCtrlEvent, [:ulong, :ulong], :bool
187
-
188
- #
189
- # BOOL WINAPI TerminateProcess(
190
- # __in HANDLE hProcess,
191
- # __in UINT uExitCode
192
- # );
193
- #
194
-
195
- attach_function :terminate_process, :TerminateProcess, [:pointer, :uint], :bool
196
-
197
- #
198
- # intptr_t _get_osfhandle(
199
- # int fd
200
- # );
201
- #
202
-
203
- attach_function :get_osfhandle, :_get_osfhandle, [:int], :intptr_t
204
-
205
- #
206
- # int _open_osfhandle (
207
- # intptr_t osfhandle,
208
- # int flags
209
- # );
210
- #
211
-
212
- attach_function :open_osfhandle, :_open_osfhandle, [:pointer, :int], :int
213
-
214
- # BOOL WINAPI SetHandleInformation(
215
- # __in HANDLE hObject,
216
- # __in DWORD dwMask,
217
- # __in DWORD dwFlags
218
- # );
219
-
220
- attach_function :set_handle_information, :SetHandleInformation, [:pointer, :ulong, :ulong], :bool
221
-
222
- # BOOL WINAPI GetHandleInformation(
223
- # __in HANDLE hObject,
224
- # __out LPDWORD lpdwFlags
225
- # );
226
-
227
- attach_function :get_handle_information, :GetHandleInformation, [:pointer, :pointer], :bool
228
-
229
- # BOOL WINAPI CreatePipe(
230
- # __out PHANDLE hReadPipe,
231
- # __out PHANDLE hWritePipe,
232
- # __in_opt LPSECURITY_ATTRIBUTES lpPipeAttributes,
233
- # __in DWORD nSize
234
- # );
235
-
236
- attach_function :create_pipe, :CreatePipe, [:pointer, :pointer, :pointer, :ulong], :bool
237
-
238
- #
239
- # HANDLE WINAPI GetCurrentProcess(void);
240
- #
241
-
242
- attach_function :current_process, :GetCurrentProcess, [], :pointer
243
-
244
- #
245
- # BOOL WINAPI DuplicateHandle(
246
- # __in HANDLE hSourceProcessHandle,
247
- # __in HANDLE hSourceHandle,
248
- # __in HANDLE hTargetProcessHandle,
249
- # __out LPHANDLE lpTargetHandle,
250
- # __in DWORD dwDesiredAccess,
251
- # __in BOOL bInheritHandle,
252
- # __in DWORD dwOptions
253
- # );
254
- #
255
-
256
- attach_function :_duplicate_handle, :DuplicateHandle, [
257
- :pointer,
258
- :pointer,
259
- :pointer,
260
- :pointer,
261
- :ulong,
262
- :bool,
263
- :ulong
264
- ], :bool
265
- end
266
- end
267
- end
268
- end