pdk 2.3.0 → 2.4.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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1329 -1321
  3. data/LICENSE +201 -201
  4. data/README.md +163 -163
  5. data/exe/pdk +10 -10
  6. data/lib/pdk/analytics/client/google_analytics.rb +143 -143
  7. data/lib/pdk/analytics/client/noop.rb +25 -25
  8. data/lib/pdk/analytics/util.rb +19 -19
  9. data/lib/pdk/analytics.rb +30 -30
  10. data/lib/pdk/answer_file.rb +12 -12
  11. data/lib/pdk/bolt.rb +19 -19
  12. data/lib/pdk/cli/build.rb +82 -82
  13. data/lib/pdk/cli/bundle.rb +48 -48
  14. data/lib/pdk/cli/config/get.rb +26 -26
  15. data/lib/pdk/cli/config.rb +22 -22
  16. data/lib/pdk/cli/console.rb +148 -148
  17. data/lib/pdk/cli/convert.rb +52 -52
  18. data/lib/pdk/cli/env.rb +52 -52
  19. data/lib/pdk/cli/errors.rb +25 -25
  20. data/lib/pdk/cli/exec/command.rb +293 -293
  21. data/lib/pdk/cli/exec/interactive_command.rb +114 -114
  22. data/lib/pdk/cli/exec.rb +84 -84
  23. data/lib/pdk/cli/exec_group.rb +104 -104
  24. data/lib/pdk/cli/get/config.rb +24 -24
  25. data/lib/pdk/cli/get.rb +20 -20
  26. data/lib/pdk/cli/module/build.rb +12 -12
  27. data/lib/pdk/cli/module/generate.rb +47 -47
  28. data/lib/pdk/cli/module.rb +14 -14
  29. data/lib/pdk/cli/new/class.rb +32 -32
  30. data/lib/pdk/cli/new/defined_type.rb +32 -32
  31. data/lib/pdk/cli/new/fact.rb +29 -29
  32. data/lib/pdk/cli/new/function.rb +29 -29
  33. data/lib/pdk/cli/new/module.rb +53 -53
  34. data/lib/pdk/cli/new/provider.rb +29 -29
  35. data/lib/pdk/cli/new/task.rb +34 -34
  36. data/lib/pdk/cli/new/test.rb +52 -52
  37. data/lib/pdk/cli/new/transport.rb +27 -27
  38. data/lib/pdk/cli/new.rb +21 -21
  39. data/lib/pdk/cli/release/prep.rb +39 -39
  40. data/lib/pdk/cli/release/publish.rb +50 -50
  41. data/lib/pdk/cli/release.rb +194 -194
  42. data/lib/pdk/cli/remove/config.rb +80 -80
  43. data/lib/pdk/cli/remove.rb +20 -20
  44. data/lib/pdk/cli/set/config.rb +119 -119
  45. data/lib/pdk/cli/set.rb +20 -20
  46. data/lib/pdk/cli/test/unit.rb +90 -90
  47. data/lib/pdk/cli/test.rb +11 -11
  48. data/lib/pdk/cli/update.rb +64 -64
  49. data/lib/pdk/cli/util/command_redirector.rb +27 -27
  50. data/lib/pdk/cli/util/interview.rb +72 -72
  51. data/lib/pdk/cli/util/option_normalizer.rb +55 -55
  52. data/lib/pdk/cli/util/option_validator.rb +68 -68
  53. data/lib/pdk/cli/util/spinner.rb +13 -13
  54. data/lib/pdk/cli/util/update_manager_printer.rb +82 -82
  55. data/lib/pdk/cli/util.rb +305 -305
  56. data/lib/pdk/cli/validate.rb +116 -116
  57. data/lib/pdk/cli.rb +175 -175
  58. data/lib/pdk/config/analytics_schema.json +26 -26
  59. data/lib/pdk/config/errors.rb +5 -5
  60. data/lib/pdk/config/ini_file.rb +183 -183
  61. data/lib/pdk/config/ini_file_setting.rb +39 -39
  62. data/lib/pdk/config/json.rb +34 -34
  63. data/lib/pdk/config/json_schema_namespace.rb +142 -142
  64. data/lib/pdk/config/json_schema_setting.rb +53 -53
  65. data/lib/pdk/config/json_with_schema.rb +49 -49
  66. data/lib/pdk/config/namespace.rb +354 -354
  67. data/lib/pdk/config/setting.rb +135 -135
  68. data/lib/pdk/config/validator.rb +31 -31
  69. data/lib/pdk/config/yaml.rb +46 -46
  70. data/lib/pdk/config/yaml_with_schema.rb +59 -59
  71. data/lib/pdk/config.rb +390 -390
  72. data/lib/pdk/context/control_repo.rb +60 -60
  73. data/lib/pdk/context/module.rb +28 -28
  74. data/lib/pdk/context/none.rb +22 -22
  75. data/lib/pdk/context.rb +99 -99
  76. data/lib/pdk/control_repo.rb +90 -90
  77. data/lib/pdk/generate/defined_type.rb +43 -43
  78. data/lib/pdk/generate/fact.rb +25 -25
  79. data/lib/pdk/generate/function.rb +48 -48
  80. data/lib/pdk/generate/module.rb +352 -352
  81. data/lib/pdk/generate/provider.rb +28 -28
  82. data/lib/pdk/generate/puppet_class.rb +43 -43
  83. data/lib/pdk/generate/puppet_object.rb +232 -232
  84. data/lib/pdk/generate/task.rb +68 -68
  85. data/lib/pdk/generate/transport.rb +33 -33
  86. data/lib/pdk/generate.rb +24 -24
  87. data/lib/pdk/i18n.rb +4 -4
  88. data/lib/pdk/logger.rb +45 -45
  89. data/lib/pdk/module/build.rb +322 -322
  90. data/lib/pdk/module/convert.rb +296 -296
  91. data/lib/pdk/module/metadata.rb +202 -202
  92. data/lib/pdk/module/release.rb +260 -260
  93. data/lib/pdk/module/update.rb +131 -131
  94. data/lib/pdk/module/update_manager.rb +227 -227
  95. data/lib/pdk/module.rb +30 -30
  96. data/lib/pdk/report/event.rb +370 -370
  97. data/lib/pdk/report.rb +121 -121
  98. data/lib/pdk/template/fetcher/git.rb +85 -85
  99. data/lib/pdk/template/fetcher/local.rb +28 -28
  100. data/lib/pdk/template/fetcher.rb +98 -98
  101. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +116 -116
  102. data/lib/pdk/template/renderer/v1/renderer.rb +132 -132
  103. data/lib/pdk/template/renderer/v1/template_file.rb +102 -102
  104. data/lib/pdk/template/renderer/v1.rb +25 -25
  105. data/lib/pdk/template/renderer.rb +96 -96
  106. data/lib/pdk/template/template_dir.rb +67 -67
  107. data/lib/pdk/template.rb +59 -59
  108. data/lib/pdk/tests/unit.rb +252 -252
  109. data/lib/pdk/util/bundler.rb +259 -259
  110. data/lib/pdk/util/changelog_generator.rb +137 -137
  111. data/lib/pdk/util/env.rb +47 -47
  112. data/lib/pdk/util/filesystem.rb +138 -138
  113. data/lib/pdk/util/git.rb +179 -179
  114. data/lib/pdk/util/json_finder.rb +85 -85
  115. data/lib/pdk/util/puppet_strings.rb +125 -125
  116. data/lib/pdk/util/puppet_version.rb +266 -266
  117. data/lib/pdk/util/ruby_version.rb +179 -179
  118. data/lib/pdk/util/template_uri.rb +295 -295
  119. data/lib/pdk/util/vendored_file.rb +93 -93
  120. data/lib/pdk/util/version.rb +43 -43
  121. data/lib/pdk/util/windows/api_types.rb +82 -82
  122. data/lib/pdk/util/windows/file.rb +36 -36
  123. data/lib/pdk/util/windows/process.rb +79 -79
  124. data/lib/pdk/util/windows/string.rb +16 -16
  125. data/lib/pdk/util/windows.rb +15 -15
  126. data/lib/pdk/util.rb +278 -277
  127. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -23
  128. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -98
  129. data/lib/pdk/validate/external_command_validator.rb +208 -208
  130. data/lib/pdk/validate/internal_ruby_validator.rb +100 -100
  131. data/lib/pdk/validate/invokable_validator.rb +228 -228
  132. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +86 -86
  133. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +78 -78
  134. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -20
  135. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +133 -133
  136. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -66
  137. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +137 -137
  138. data/lib/pdk/validate/puppet/puppet_validator_group.rb +21 -21
  139. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +80 -80
  140. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -19
  141. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +88 -88
  142. data/lib/pdk/validate/tasks/tasks_name_validator.rb +50 -50
  143. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -20
  144. data/lib/pdk/validate/validator.rb +118 -118
  145. data/lib/pdk/validate/validator_group.rb +104 -104
  146. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +95 -95
  147. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -19
  148. data/lib/pdk/validate.rb +94 -94
  149. data/lib/pdk/version.rb +4 -4
  150. data/lib/pdk.rb +76 -76
  151. data/locales/config.yaml +21 -21
  152. data/locales/pdk.pot +2094 -2094
  153. metadata +5 -6
@@ -1,293 +1,293 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module CLI
5
- module Exec
6
- class Command
7
- attr_reader :argv
8
- attr_reader :context
9
- attr_accessor :timeout
10
- attr_accessor :environment
11
- attr_writer :exec_group
12
-
13
- # The spinner for this command.
14
- # This should only be used for testing
15
- #
16
- # @return [TTY::Spinner, nil]
17
- #
18
- # @api private
19
- attr_reader :spinner
20
-
21
- TEMPFILE_MODE = File::RDWR | File::BINARY | File::CREAT | File::TRUNC
22
-
23
- def initialize(*argv)
24
- require 'childprocess'
25
- require 'tempfile'
26
-
27
- @argv = argv
28
-
29
- @process = ChildProcess.build(*@argv)
30
- # https://github.com/puppetlabs/pdk/issues/1083:
31
- # When @process.leader is set, childprocess will set the CREATE_BREAKAWAY_FROM_JOB
32
- # and JOB_OBJECT_LIMIT_BREAKAWAY_OK flags in the Win32 API calls. This will cause
33
- # issues on systems > Windows 7 / Server 2008, if the JOB_OBJECT_LIMIT_BREAKAWAY_OK
34
- # flag is set and the Task Scheduler is trying to kick off a job, it can sometimes
35
- # result in ACCESS_DENIED being returned by the Win32 API, depending on the permission
36
- # levels / user account this user.
37
- # The resolution for pdk/issues/1083 is to ensure @process.leader is not set.
38
- # This will potentially cause issues on older Windows systems, in which case we may
39
- # need to revisit and conditionally set this param depending on what OS we're on
40
- # @process.leader = true
41
-
42
- @stdout = Tempfile.new('stdout', mode: TEMPFILE_MODE).tap { |io| io.sync = true }
43
- @stderr = Tempfile.new('stderr', mode: TEMPFILE_MODE).tap { |io| io.sync = true }
44
-
45
- @process.io.stdout = @stdout
46
- @process.io.stderr = @stderr
47
-
48
- # Default to running things in the system context.
49
- @context = :system
50
-
51
- # Extra environment vars to add to base set.
52
- @environment = {}
53
-
54
- # Register the ExecGroup when running in parallel
55
- @exec_group = nil
56
- end
57
-
58
- def context=(new_context)
59
- unless [:system, :module, :pwd].include?(new_context)
60
- raise ArgumentError, _("Expected execution context to be :system or :module but got '%{context}'.") % { context: new_context }
61
- end
62
-
63
- @context = new_context
64
- end
65
-
66
- def register_spinner(spinner, opts = {})
67
- require 'pdk/cli/util'
68
-
69
- return unless PDK::CLI::Util.interactive?
70
- @success_message = opts.delete(:success)
71
- @failure_message = opts.delete(:failure)
72
-
73
- @spinner = spinner
74
- end
75
-
76
- def add_spinner(message, opts = {})
77
- require 'pdk/cli/util'
78
-
79
- return unless PDK::CLI::Util.interactive?
80
- @success_message = opts.delete(:success)
81
- @failure_message = opts.delete(:failure)
82
-
83
- require 'pdk/cli/util/spinner'
84
-
85
- @spinner = TTY::Spinner.new("[:spinner] #{message}", opts.merge(PDK::CLI::Util.spinner_opts_for_platform))
86
- end
87
-
88
- def update_environment(additional_env)
89
- @environment.merge!(additional_env)
90
- end
91
-
92
- # @return [Hash[Symbol => Object]] The result from executing the command
93
- # :stdout => String : The result of STDOUT
94
- # :stderr => String : The result of STDERR
95
- # :exit_code => Integer : The exit code from the command
96
- # :duration => Float : Number seconds it took to execute
97
- def execute!
98
- # Start spinning if configured.
99
- @spinner.auto_spin if @spinner
100
-
101
- # Set env for child process
102
- resolved_env_for_command.each { |k, v| @process.environment[k] = v }
103
-
104
- if [:module, :pwd].include?(context)
105
- require 'pdk/util'
106
- mod_root = PDK::Util.module_root
107
-
108
- unless mod_root
109
- @spinner.error if @spinner
110
-
111
- raise PDK::CLI::FatalError, _('Current working directory is not part of a module. (No metadata.json was found.)')
112
- end
113
-
114
- if Dir.pwd == mod_root || context == :pwd
115
- run_process_in_clean_env!
116
- else
117
- Dir.chdir(mod_root) do
118
- run_process_in_clean_env!
119
- end
120
- end
121
- else
122
- run_process!
123
- end
124
-
125
- # Stop spinning when done (if configured).
126
- stop_spinner
127
-
128
- @stdout.rewind
129
- @stderr.rewind
130
-
131
- process_data = {
132
- stdout: @stdout.read,
133
- stderr: @stderr.read,
134
- exit_code: @process.exit_code,
135
- duration: @duration,
136
- }
137
-
138
- PDK.logger.debug _('STDOUT: %{output}') % {
139
- output: process_data[:stdout].empty? ? 'N/A' : "\n#{process_data[:stdout]}",
140
- }
141
- PDK.logger.debug _('STDERR: %{output}') % {
142
- output: process_data[:stderr].empty? ? 'N/A' : "\n#{process_data[:stderr]}",
143
- }
144
-
145
- process_data
146
- ensure
147
- @stdout.close
148
- @stderr.close
149
- end
150
-
151
- protected
152
-
153
- def warn_on_legacy_env_vars!
154
- if PDK::Util::Env['PUPPET_GEM_VERSION']
155
- PDK.logger.warn_once _(
156
- 'PUPPET_GEM_VERSION is not supported by PDK. ' \
157
- 'Use the --puppet-version option on your PDK command ' \
158
- 'or set the PDK_PUPPET_VERSION environment variable instead',
159
- )
160
- end
161
-
162
- %w[FACTER HIERA].each do |gem|
163
- if PDK::Util::Env["#{gem}_GEM_VERSION"]
164
- PDK.logger.warn_once _('%{varname} is not supported by PDK.') % { varname: "#{gem}_GEM_VERSION" }
165
- end
166
- end
167
- end
168
-
169
- def resolved_env_for_command
170
- warn_on_legacy_env_vars!
171
-
172
- resolved_env = {}
173
-
174
- resolved_env['TERM'] = PDK::Util::Env['TERM']
175
- resolved_env['PUPPET_GEM_VERSION'] = nil
176
- resolved_env['FACTER_GEM_VERSION'] = nil
177
- resolved_env['HIERA_GEM_VERSION'] = nil
178
-
179
- resolved_env.merge!(@environment.dup)
180
-
181
- resolved_env['BUNDLE_IGNORE_CONFIG'] = '1'
182
-
183
- if [:module, :pwd].include?(context)
184
- require 'pdk/util'
185
- require 'pdk/util/git'
186
- require 'pdk/util/ruby_version'
187
-
188
- resolved_env['GEM_HOME'] = PDK::Util::RubyVersion.gem_home
189
- gem_path = PDK::Util::RubyVersion.gem_path
190
- resolved_env['GEM_PATH'] = gem_path.empty? ? resolved_env['GEM_HOME'] : gem_path
191
-
192
- # Make sure invocation of Ruby prefers our private installation.
193
- package_binpath = PDK::Util.package_install? ? File.join(PDK::Util.pdk_package_basedir, 'bin') : nil
194
-
195
- resolved_env['PATH'] = [
196
- PDK::Util::RubyVersion.bin_path,
197
- File.join(resolved_env['GEM_HOME'], 'bin'),
198
- PDK::Util::RubyVersion.gem_paths_raw.map { |gem_path_raw| File.join(gem_path_raw, 'bin') },
199
- package_binpath,
200
- PDK::Util.package_install? ? PDK::Util::Git.git_paths : nil,
201
- PDK::Util::Env['PATH'],
202
- ].compact.flatten.join(File::PATH_SEPARATOR)
203
- end
204
-
205
- resolved_env
206
- end
207
-
208
- def stop_spinner
209
- return unless @spinner
210
-
211
- # If it is a single spinner, we need to send it a success/error message
212
- if @process.exit_code.zero?
213
- @spinner.success(@success_message || '')
214
- else
215
- @spinner.error(@failure_message || '')
216
- end
217
- end
218
-
219
- def run_process_in_clean_env!
220
- require 'bundler'
221
-
222
- # Bundler 2.1.0 has deprecated the use of `Bundler.with_clean_env` in favour of
223
- # `Bundler.with_unbundled_env`. So prefer to use the newer method if it exists
224
- # otherwise revert back to the old method.
225
- if ::Bundler.respond_to?(:with_unbundled_env)
226
- run_process_with_unbundled_env!
227
- else
228
- run_process_with_clean_env!
229
- end
230
- end
231
-
232
- def run_process!
233
- command_string = argv.join(' ')
234
-
235
- PDK.logger.debug(_("Executing '%{command}'") % { command: command_string })
236
-
237
- if context == :module
238
- PDK.logger.debug(_('Command environment:'))
239
- @process.environment.each do |var, val|
240
- PDK.logger.debug(" #{var}: #{val}")
241
- end
242
- end
243
-
244
- start_time = Time.now
245
-
246
- begin
247
- @process.start
248
- rescue ChildProcess::LaunchError => e
249
- raise PDK::CLI::FatalError, _("Failed to execute '%{command}': %{message}") % { command: command_string, message: e.message }
250
- end
251
-
252
- if timeout
253
- begin
254
- @process.poll_for_exit(timeout)
255
- rescue ChildProcess::TimeoutError
256
- @process.stop # tries increasingly harsher methods to kill the process.
257
- end
258
- else
259
- # Wait indfinitely if no timeout set.
260
- @process.wait
261
- end
262
-
263
- @duration = Time.now - start_time
264
-
265
- PDK.logger.debug(_("Execution of '%{command}' complete (duration: %{duration_in_seconds}s; exit code: %{exit_code})") %
266
- { command: command_string, duration_in_seconds: @duration, exit_code: @process.exit_code })
267
- end
268
-
269
- private
270
-
271
- #:nocov:
272
- # These are just bundler helper methods and are tested via the public run_process_in_clean_env! method
273
- def run_process_with_unbundled_env!
274
- # Bundler 2.1.0 or greater
275
- ::Bundler.with_unbundled_env do
276
- run_process!
277
- end
278
- end
279
- #:nocov:
280
-
281
- #:nocov:
282
- # These are just bundler helper methods and are tested via the public run_process_in_clean_env! method
283
- def run_process_with_clean_env!
284
- # Bundler 2.0.2 or less
285
- ::Bundler.with_clean_env do
286
- run_process!
287
- end
288
- end
289
- #:nocov:
290
- end
291
- end
292
- end
293
- end
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module CLI
5
+ module Exec
6
+ class Command
7
+ attr_reader :argv
8
+ attr_reader :context
9
+ attr_accessor :timeout
10
+ attr_accessor :environment
11
+ attr_writer :exec_group
12
+
13
+ # The spinner for this command.
14
+ # This should only be used for testing
15
+ #
16
+ # @return [TTY::Spinner, nil]
17
+ #
18
+ # @api private
19
+ attr_reader :spinner
20
+
21
+ TEMPFILE_MODE = File::RDWR | File::BINARY | File::CREAT | File::TRUNC
22
+
23
+ def initialize(*argv)
24
+ require 'childprocess'
25
+ require 'tempfile'
26
+
27
+ @argv = argv
28
+
29
+ @process = ChildProcess.build(*@argv)
30
+ # https://github.com/puppetlabs/pdk/issues/1083:
31
+ # When @process.leader is set, childprocess will set the CREATE_BREAKAWAY_FROM_JOB
32
+ # and JOB_OBJECT_LIMIT_BREAKAWAY_OK flags in the Win32 API calls. This will cause
33
+ # issues on systems > Windows 7 / Server 2008, if the JOB_OBJECT_LIMIT_BREAKAWAY_OK
34
+ # flag is set and the Task Scheduler is trying to kick off a job, it can sometimes
35
+ # result in ACCESS_DENIED being returned by the Win32 API, depending on the permission
36
+ # levels / user account this user.
37
+ # The resolution for pdk/issues/1083 is to ensure @process.leader is not set.
38
+ # This will potentially cause issues on older Windows systems, in which case we may
39
+ # need to revisit and conditionally set this param depending on what OS we're on
40
+ # @process.leader = true
41
+
42
+ @stdout = Tempfile.new('stdout', mode: TEMPFILE_MODE).tap { |io| io.sync = true }
43
+ @stderr = Tempfile.new('stderr', mode: TEMPFILE_MODE).tap { |io| io.sync = true }
44
+
45
+ @process.io.stdout = @stdout
46
+ @process.io.stderr = @stderr
47
+
48
+ # Default to running things in the system context.
49
+ @context = :system
50
+
51
+ # Extra environment vars to add to base set.
52
+ @environment = {}
53
+
54
+ # Register the ExecGroup when running in parallel
55
+ @exec_group = nil
56
+ end
57
+
58
+ def context=(new_context)
59
+ unless [:system, :module, :pwd].include?(new_context)
60
+ raise ArgumentError, _("Expected execution context to be :system or :module but got '%{context}'.") % { context: new_context }
61
+ end
62
+
63
+ @context = new_context
64
+ end
65
+
66
+ def register_spinner(spinner, opts = {})
67
+ require 'pdk/cli/util'
68
+
69
+ return unless PDK::CLI::Util.interactive?
70
+ @success_message = opts.delete(:success)
71
+ @failure_message = opts.delete(:failure)
72
+
73
+ @spinner = spinner
74
+ end
75
+
76
+ def add_spinner(message, opts = {})
77
+ require 'pdk/cli/util'
78
+
79
+ return unless PDK::CLI::Util.interactive?
80
+ @success_message = opts.delete(:success)
81
+ @failure_message = opts.delete(:failure)
82
+
83
+ require 'pdk/cli/util/spinner'
84
+
85
+ @spinner = TTY::Spinner.new("[:spinner] #{message}", opts.merge(PDK::CLI::Util.spinner_opts_for_platform))
86
+ end
87
+
88
+ def update_environment(additional_env)
89
+ @environment.merge!(additional_env)
90
+ end
91
+
92
+ # @return [Hash[Symbol => Object]] The result from executing the command
93
+ # :stdout => String : The result of STDOUT
94
+ # :stderr => String : The result of STDERR
95
+ # :exit_code => Integer : The exit code from the command
96
+ # :duration => Float : Number seconds it took to execute
97
+ def execute!
98
+ # Start spinning if configured.
99
+ @spinner.auto_spin if @spinner
100
+
101
+ # Set env for child process
102
+ resolved_env_for_command.each { |k, v| @process.environment[k] = v }
103
+
104
+ if [:module, :pwd].include?(context)
105
+ require 'pdk/util'
106
+ mod_root = PDK::Util.module_root
107
+
108
+ unless mod_root
109
+ @spinner.error if @spinner
110
+
111
+ raise PDK::CLI::FatalError, _('Current working directory is not part of a module. (No metadata.json was found.)')
112
+ end
113
+
114
+ if Dir.pwd == mod_root || context == :pwd
115
+ run_process_in_clean_env!
116
+ else
117
+ Dir.chdir(mod_root) do
118
+ run_process_in_clean_env!
119
+ end
120
+ end
121
+ else
122
+ run_process!
123
+ end
124
+
125
+ # Stop spinning when done (if configured).
126
+ stop_spinner
127
+
128
+ @stdout.rewind
129
+ @stderr.rewind
130
+
131
+ process_data = {
132
+ stdout: @stdout.read,
133
+ stderr: @stderr.read,
134
+ exit_code: @process.exit_code,
135
+ duration: @duration,
136
+ }
137
+
138
+ PDK.logger.debug _('STDOUT: %{output}') % {
139
+ output: process_data[:stdout].empty? ? 'N/A' : "\n#{process_data[:stdout]}",
140
+ }
141
+ PDK.logger.debug _('STDERR: %{output}') % {
142
+ output: process_data[:stderr].empty? ? 'N/A' : "\n#{process_data[:stderr]}",
143
+ }
144
+
145
+ process_data
146
+ ensure
147
+ @stdout.close
148
+ @stderr.close
149
+ end
150
+
151
+ protected
152
+
153
+ def warn_on_legacy_env_vars!
154
+ if PDK::Util::Env['PUPPET_GEM_VERSION']
155
+ PDK.logger.warn_once _(
156
+ 'PUPPET_GEM_VERSION is not supported by PDK. ' \
157
+ 'Use the --puppet-version option on your PDK command ' \
158
+ 'or set the PDK_PUPPET_VERSION environment variable instead',
159
+ )
160
+ end
161
+
162
+ %w[FACTER HIERA].each do |gem|
163
+ if PDK::Util::Env["#{gem}_GEM_VERSION"]
164
+ PDK.logger.warn_once _('%{varname} is not supported by PDK.') % { varname: "#{gem}_GEM_VERSION" }
165
+ end
166
+ end
167
+ end
168
+
169
+ def resolved_env_for_command
170
+ warn_on_legacy_env_vars!
171
+
172
+ resolved_env = {}
173
+
174
+ resolved_env['TERM'] = PDK::Util::Env['TERM']
175
+ resolved_env['PUPPET_GEM_VERSION'] = nil
176
+ resolved_env['FACTER_GEM_VERSION'] = nil
177
+ resolved_env['HIERA_GEM_VERSION'] = nil
178
+
179
+ resolved_env.merge!(@environment.dup)
180
+
181
+ resolved_env['BUNDLE_IGNORE_CONFIG'] = '1'
182
+
183
+ if [:module, :pwd].include?(context)
184
+ require 'pdk/util'
185
+ require 'pdk/util/git'
186
+ require 'pdk/util/ruby_version'
187
+
188
+ resolved_env['GEM_HOME'] = PDK::Util::RubyVersion.gem_home
189
+ gem_path = PDK::Util::RubyVersion.gem_path
190
+ resolved_env['GEM_PATH'] = gem_path.empty? ? resolved_env['GEM_HOME'] : gem_path
191
+
192
+ # Make sure invocation of Ruby prefers our private installation.
193
+ package_binpath = PDK::Util.package_install? ? File.join(PDK::Util.pdk_package_basedir, 'bin') : nil
194
+
195
+ resolved_env['PATH'] = [
196
+ PDK::Util::RubyVersion.bin_path,
197
+ File.join(resolved_env['GEM_HOME'], 'bin'),
198
+ PDK::Util::RubyVersion.gem_paths_raw.map { |gem_path_raw| File.join(gem_path_raw, 'bin') },
199
+ package_binpath,
200
+ PDK::Util.package_install? ? PDK::Util::Git.git_paths : nil,
201
+ PDK::Util::Env['PATH'],
202
+ ].compact.flatten.join(File::PATH_SEPARATOR)
203
+ end
204
+
205
+ resolved_env
206
+ end
207
+
208
+ def stop_spinner
209
+ return unless @spinner
210
+
211
+ # If it is a single spinner, we need to send it a success/error message
212
+ if @process.exit_code.zero?
213
+ @spinner.success(@success_message || '')
214
+ else
215
+ @spinner.error(@failure_message || '')
216
+ end
217
+ end
218
+
219
+ def run_process_in_clean_env!
220
+ require 'bundler'
221
+
222
+ # Bundler 2.1.0 has deprecated the use of `Bundler.with_clean_env` in favour of
223
+ # `Bundler.with_unbundled_env`. So prefer to use the newer method if it exists
224
+ # otherwise revert back to the old method.
225
+ if ::Bundler.respond_to?(:with_unbundled_env)
226
+ run_process_with_unbundled_env!
227
+ else
228
+ run_process_with_clean_env!
229
+ end
230
+ end
231
+
232
+ def run_process!
233
+ command_string = argv.join(' ')
234
+
235
+ PDK.logger.debug(_("Executing '%{command}'") % { command: command_string })
236
+
237
+ if context == :module
238
+ PDK.logger.debug(_('Command environment:'))
239
+ @process.environment.each do |var, val|
240
+ PDK.logger.debug(" #{var}: #{val}")
241
+ end
242
+ end
243
+
244
+ start_time = Time.now
245
+
246
+ begin
247
+ @process.start
248
+ rescue ChildProcess::LaunchError => e
249
+ raise PDK::CLI::FatalError, _("Failed to execute '%{command}': %{message}") % { command: command_string, message: e.message }
250
+ end
251
+
252
+ if timeout
253
+ begin
254
+ @process.poll_for_exit(timeout)
255
+ rescue ChildProcess::TimeoutError
256
+ @process.stop # tries increasingly harsher methods to kill the process.
257
+ end
258
+ else
259
+ # Wait indfinitely if no timeout set.
260
+ @process.wait
261
+ end
262
+
263
+ @duration = Time.now - start_time
264
+
265
+ PDK.logger.debug(_("Execution of '%{command}' complete (duration: %{duration_in_seconds}s; exit code: %{exit_code})") %
266
+ { command: command_string, duration_in_seconds: @duration, exit_code: @process.exit_code })
267
+ end
268
+
269
+ private
270
+
271
+ #:nocov:
272
+ # These are just bundler helper methods and are tested via the public run_process_in_clean_env! method
273
+ def run_process_with_unbundled_env!
274
+ # Bundler 2.1.0 or greater
275
+ ::Bundler.with_unbundled_env do
276
+ run_process!
277
+ end
278
+ end
279
+ #:nocov:
280
+
281
+ #:nocov:
282
+ # These are just bundler helper methods and are tested via the public run_process_in_clean_env! method
283
+ def run_process_with_clean_env!
284
+ # Bundler 2.0.2 or less
285
+ ::Bundler.with_clean_env do
286
+ run_process!
287
+ end
288
+ end
289
+ #:nocov:
290
+ end
291
+ end
292
+ end
293
+ end