pdk 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1336 -1329
  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 -278
  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 +2111 -2094
  153. metadata +3 -3
@@ -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