pdk-akerl 1.8.0.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +826 -0
- data/LICENSE +201 -0
- data/README.md +133 -0
- data/exe/pdk +10 -0
- data/lib/pdk.rb +10 -0
- data/lib/pdk/answer_file.rb +121 -0
- data/lib/pdk/cli.rb +113 -0
- data/lib/pdk/cli/build.rb +76 -0
- data/lib/pdk/cli/bundle.rb +42 -0
- data/lib/pdk/cli/convert.rb +41 -0
- data/lib/pdk/cli/errors.rb +23 -0
- data/lib/pdk/cli/exec.rb +246 -0
- data/lib/pdk/cli/exec_group.rb +67 -0
- data/lib/pdk/cli/module.rb +14 -0
- data/lib/pdk/cli/module/build.rb +14 -0
- data/lib/pdk/cli/module/generate.rb +45 -0
- data/lib/pdk/cli/new.rb +17 -0
- data/lib/pdk/cli/new/class.rb +32 -0
- data/lib/pdk/cli/new/defined_type.rb +30 -0
- data/lib/pdk/cli/new/module.rb +41 -0
- data/lib/pdk/cli/new/provider.rb +27 -0
- data/lib/pdk/cli/new/task.rb +31 -0
- data/lib/pdk/cli/test.rb +12 -0
- data/lib/pdk/cli/test/unit.rb +88 -0
- data/lib/pdk/cli/update.rb +32 -0
- data/lib/pdk/cli/util.rb +193 -0
- data/lib/pdk/cli/util/command_redirector.rb +26 -0
- data/lib/pdk/cli/util/interview.rb +63 -0
- data/lib/pdk/cli/util/option_normalizer.rb +53 -0
- data/lib/pdk/cli/util/option_validator.rb +56 -0
- data/lib/pdk/cli/validate.rb +124 -0
- data/lib/pdk/generate.rb +11 -0
- data/lib/pdk/generate/defined_type.rb +49 -0
- data/lib/pdk/generate/module.rb +318 -0
- data/lib/pdk/generate/provider.rb +82 -0
- data/lib/pdk/generate/puppet_class.rb +48 -0
- data/lib/pdk/generate/puppet_object.rb +288 -0
- data/lib/pdk/generate/task.rb +86 -0
- data/lib/pdk/i18n.rb +4 -0
- data/lib/pdk/logger.rb +28 -0
- data/lib/pdk/module.rb +21 -0
- data/lib/pdk/module/build.rb +214 -0
- data/lib/pdk/module/convert.rb +209 -0
- data/lib/pdk/module/metadata.rb +193 -0
- data/lib/pdk/module/templatedir.rb +313 -0
- data/lib/pdk/module/update.rb +111 -0
- data/lib/pdk/module/update_manager.rb +210 -0
- data/lib/pdk/report.rb +112 -0
- data/lib/pdk/report/event.rb +357 -0
- data/lib/pdk/template_file.rb +89 -0
- data/lib/pdk/tests/unit.rb +213 -0
- data/lib/pdk/util.rb +271 -0
- data/lib/pdk/util/bundler.rb +253 -0
- data/lib/pdk/util/filesystem.rb +12 -0
- data/lib/pdk/util/git.rb +74 -0
- data/lib/pdk/util/puppet_version.rb +242 -0
- data/lib/pdk/util/ruby_version.rb +147 -0
- data/lib/pdk/util/vendored_file.rb +88 -0
- data/lib/pdk/util/version.rb +42 -0
- data/lib/pdk/util/windows.rb +13 -0
- data/lib/pdk/util/windows/api_types.rb +57 -0
- data/lib/pdk/util/windows/file.rb +36 -0
- data/lib/pdk/util/windows/string.rb +16 -0
- data/lib/pdk/validate.rb +14 -0
- data/lib/pdk/validate/base_validator.rb +209 -0
- data/lib/pdk/validate/metadata/metadata_json_lint.rb +86 -0
- data/lib/pdk/validate/metadata/metadata_syntax.rb +109 -0
- data/lib/pdk/validate/metadata_validator.rb +30 -0
- data/lib/pdk/validate/puppet/puppet_lint.rb +67 -0
- data/lib/pdk/validate/puppet/puppet_syntax.rb +112 -0
- data/lib/pdk/validate/puppet_validator.rb +30 -0
- data/lib/pdk/validate/ruby/rubocop.rb +77 -0
- data/lib/pdk/validate/ruby_validator.rb +29 -0
- data/lib/pdk/validate/tasks/metadata_lint.rb +126 -0
- data/lib/pdk/validate/tasks/name.rb +88 -0
- data/lib/pdk/validate/tasks_validator.rb +33 -0
- data/lib/pdk/version.rb +4 -0
- data/locales/config.yaml +21 -0
- data/locales/pdk.pot +1283 -0
- metadata +304 -0
data/lib/pdk/cli.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'cri'
|
2
|
+
|
3
|
+
require 'pdk/cli/errors'
|
4
|
+
require 'pdk/cli/util'
|
5
|
+
require 'pdk/cli/util/command_redirector'
|
6
|
+
require 'pdk/cli/util/option_normalizer'
|
7
|
+
require 'pdk/cli/util/option_validator'
|
8
|
+
require 'pdk/cli/exec_group'
|
9
|
+
require 'pdk/generate/module'
|
10
|
+
require 'pdk/i18n'
|
11
|
+
require 'pdk/logger'
|
12
|
+
require 'pdk/report'
|
13
|
+
require 'pdk/util/version'
|
14
|
+
require 'pdk/util/puppet_version'
|
15
|
+
|
16
|
+
module PDK::CLI
|
17
|
+
def self.run(args)
|
18
|
+
@base_cmd.run(args)
|
19
|
+
rescue PDK::CLI::ExitWithError => e
|
20
|
+
PDK.logger.send(e.log_level, e.message)
|
21
|
+
|
22
|
+
exit e.exit_code
|
23
|
+
rescue PDK::CLI::FatalError => e
|
24
|
+
PDK.logger.fatal(e.message) if e.message
|
25
|
+
|
26
|
+
# If FatalError was raised as the result of another exception, send the
|
27
|
+
# details of that exception to the debug log. If there was no cause
|
28
|
+
# (FatalError raised on its own outside a rescue block), send the details
|
29
|
+
# of the FatalError exception to the debug log.
|
30
|
+
cause = e.cause
|
31
|
+
if cause.nil?
|
32
|
+
e.backtrace.each { |line| PDK.logger.debug(line) }
|
33
|
+
else
|
34
|
+
PDK.logger.debug("#{cause.class}: #{cause.message}")
|
35
|
+
cause.backtrace.each { |line| PDK.logger.debug(line) }
|
36
|
+
end
|
37
|
+
|
38
|
+
exit e.exit_code
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.template_url_option(dsl)
|
42
|
+
desc = _('Specifies the URL to the template to use when creating new modules or classes. (default: %{default_url})') % { default_url: PDK::Util.default_template_url }
|
43
|
+
|
44
|
+
dsl.option nil, 'template-url', desc, argument: :required
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.skip_interview_option(dsl)
|
48
|
+
dsl.option nil, 'skip-interview', _('When specified, skips interactive querying of metadata.')
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.full_interview_option(dsl)
|
52
|
+
dsl.option nil, 'full-interview', _('When specified, interactive querying of metadata will include all optional questions.')
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.puppet_version_options(dsl)
|
56
|
+
dsl.option nil, 'puppet-version', _('Puppet version to run tests or validations against.'), argument: :required
|
57
|
+
dsl.option nil, 'pe-version', _('Puppet Enterprise version to run tests or validations against.'), argument: :required
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.puppet_dev_option(dsl)
|
61
|
+
dsl.option nil,
|
62
|
+
'puppet-dev',
|
63
|
+
_('When specified, PDK will validate or test against the current Puppet source from github.com. To use this option, you must have network access to https://github.com.')
|
64
|
+
end
|
65
|
+
|
66
|
+
@base_cmd = Cri::Command.define do
|
67
|
+
name 'pdk'
|
68
|
+
usage _('pdk command [options]')
|
69
|
+
summary _('Puppet Development Kit')
|
70
|
+
description _('The shortest path to better modules.')
|
71
|
+
default_subcommand 'help'
|
72
|
+
|
73
|
+
flag nil, :version, _('Show version of pdk.') do |_, _|
|
74
|
+
puts PDK::Util::Version.version_string
|
75
|
+
exit 0
|
76
|
+
end
|
77
|
+
|
78
|
+
flag :h, :help, _('Show help for this command.') do |_, c|
|
79
|
+
puts c.help
|
80
|
+
exit 0
|
81
|
+
end
|
82
|
+
|
83
|
+
format_desc = _(
|
84
|
+
"Specify desired output format. Valid formats are '%{available_formats}'. " \
|
85
|
+
'You may also specify a file to which the formatted output is sent, ' \
|
86
|
+
"for example: '--format=junit:report.xml'. This option may be specified " \
|
87
|
+
'multiple times if each option specifies a distinct target file.',
|
88
|
+
) % { available_formats: PDK::Report.formats.join("', '") }
|
89
|
+
|
90
|
+
option :f, :format, format_desc, argument: :required, multiple: true do |values|
|
91
|
+
PDK::CLI::Util::OptionNormalizer.report_formats(values.compact)
|
92
|
+
end
|
93
|
+
|
94
|
+
flag :d, :debug, _('Enable debug output.') do |_, _|
|
95
|
+
PDK.logger.enable_debug_output
|
96
|
+
end
|
97
|
+
|
98
|
+
option nil, 'answer-file', _('Path to an answer file.'), argument: :required, hidden: true do |value|
|
99
|
+
PDK.answer_file = value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
require 'pdk/cli/bundle'
|
104
|
+
require 'pdk/cli/build'
|
105
|
+
require 'pdk/cli/convert'
|
106
|
+
require 'pdk/cli/new'
|
107
|
+
require 'pdk/cli/test'
|
108
|
+
require 'pdk/cli/update'
|
109
|
+
require 'pdk/cli/validate'
|
110
|
+
require 'pdk/cli/module'
|
111
|
+
|
112
|
+
@base_cmd.add_command Cri::Command.new_basic_help
|
113
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'pdk/cli/util'
|
2
|
+
|
3
|
+
module PDK::CLI
|
4
|
+
@build_cmd = @base_cmd.define_command do
|
5
|
+
name 'build'
|
6
|
+
usage _('build [options]')
|
7
|
+
summary _('Builds a package from the module that can be published to the Puppet Forge.')
|
8
|
+
|
9
|
+
option nil, 'target-dir',
|
10
|
+
_('The target directory where you want PDK to write the package.'),
|
11
|
+
argument: :required, default: File.join(Dir.pwd, 'pkg')
|
12
|
+
|
13
|
+
option nil, 'force', _('Skips the prompts and builds the module package.')
|
14
|
+
|
15
|
+
run do |opts, _args, _cmd|
|
16
|
+
require 'pdk/module/build'
|
17
|
+
|
18
|
+
# Make sure build is being run in a valid module directory with a metadata.json
|
19
|
+
PDK::CLI::Util.ensure_in_module!(
|
20
|
+
message: _('`pdk build` can only be run from inside a valid module with a metadata.json.'),
|
21
|
+
log_level: :info,
|
22
|
+
)
|
23
|
+
|
24
|
+
module_metadata = PDK::Module::Metadata.from_file('metadata.json')
|
25
|
+
|
26
|
+
# TODO: Ensure forge metadata has been set, or call out to interview
|
27
|
+
# to set it.
|
28
|
+
#
|
29
|
+
unless module_metadata.forge_ready?
|
30
|
+
if opts[:force]
|
31
|
+
PDK.logger.error _('This module is missing required fields in the metadata.json. Re-run the build command without --force to add this information.')
|
32
|
+
exit 1
|
33
|
+
else
|
34
|
+
module_metadata.interview_for_forge!
|
35
|
+
module_metadata.write!('metadata.json')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
builder = PDK::Module::Build.new(opts)
|
40
|
+
|
41
|
+
unless opts[:force]
|
42
|
+
if builder.package_already_exists?
|
43
|
+
PDK.logger.info _("The file '%{package}' already exists.") % { package: builder.package_file }
|
44
|
+
|
45
|
+
unless PDK::CLI::Util.prompt_for_yes(_('Overwrite?'), default: false)
|
46
|
+
PDK.logger.info _('Build cancelled; exiting.')
|
47
|
+
exit 0
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
unless builder.module_pdk_compatible?
|
52
|
+
PDK.logger.info _('This module is not compatible with PDK, so PDK can not validate or test this build. ' \
|
53
|
+
'Unvalidated modules may have errors when uploading to the Forge. ' \
|
54
|
+
'To make this module PDK compatible and use validate features, cancel the build and run `pdk convert`.')
|
55
|
+
|
56
|
+
unless PDK::CLI::Util.prompt_for_yes(_('Continue build without converting?'))
|
57
|
+
PDK.logger.info _('Build cancelled; exiting.')
|
58
|
+
exit 0
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
PDK.logger.info _('Building %{module_name} version %{module_version}') % {
|
64
|
+
module_name: module_metadata.data['name'],
|
65
|
+
module_version: module_metadata.data['version'],
|
66
|
+
}
|
67
|
+
|
68
|
+
builder.build
|
69
|
+
|
70
|
+
PDK.logger.info _('Build of %{package_name} has completed successfully. Built package can be found here: %{package_path}') % {
|
71
|
+
package_name: module_metadata.data['name'],
|
72
|
+
package_path: builder.package_file,
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module PDK::CLI
|
3
|
+
@bundle_cmd = @base_cmd.define_command do
|
4
|
+
name 'bundle'
|
5
|
+
usage _('bundle [bundler_options]')
|
6
|
+
summary _('(Experimental) Command pass-through to bundler')
|
7
|
+
description _(<<-EOF
|
8
|
+
[experimental] For advanced users, pdk bundle runs arbitrary commands in the bundler environment that pdk manages.
|
9
|
+
Careless use of this command can lead to errors that pdk can't help recover from.
|
10
|
+
|
11
|
+
Note that for PowerShell the '--' needs to be escaped using a backtick: '`--' to avoid it being parsed by the shell.
|
12
|
+
EOF
|
13
|
+
)
|
14
|
+
skip_option_parsing
|
15
|
+
|
16
|
+
run do |_opts, args, _cmd|
|
17
|
+
PDK::CLI::Util.ensure_in_module!(
|
18
|
+
message: _('`pdk bundle` can only be run from inside a valid module directory.'),
|
19
|
+
)
|
20
|
+
|
21
|
+
PDK::CLI::Util.validate_puppet_version_opts({})
|
22
|
+
|
23
|
+
# Ensure that the correct Ruby is activated before running commend.
|
24
|
+
puppet_env = PDK::CLI::Util.puppet_from_opts_or_env({})
|
25
|
+
PDK::Util::RubyVersion.use(puppet_env[:ruby_version])
|
26
|
+
|
27
|
+
gemfile_env = PDK::Util::Bundler::BundleHelper.gemfile_env(puppet_env[:gemset])
|
28
|
+
|
29
|
+
command = PDK::CLI::Exec::Command.new(PDK::CLI::Exec.bundle_bin, *args).tap do |c|
|
30
|
+
c.context = :module
|
31
|
+
c.update_environment(gemfile_env)
|
32
|
+
end
|
33
|
+
|
34
|
+
result = command.execute!
|
35
|
+
|
36
|
+
$stderr.puts result[:stdout]
|
37
|
+
$stderr.puts result[:stderr]
|
38
|
+
|
39
|
+
exit result[:exit_code]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'pdk/cli/util'
|
2
|
+
|
3
|
+
module PDK::CLI
|
4
|
+
@convert_cmd = @base_cmd.define_command do
|
5
|
+
name 'convert'
|
6
|
+
usage _('convert [options]')
|
7
|
+
summary _('Convert an existing module to be compatible with the PDK.')
|
8
|
+
|
9
|
+
PDK::CLI.template_url_option(self)
|
10
|
+
PDK::CLI.skip_interview_option(self)
|
11
|
+
PDK::CLI.full_interview_option(self)
|
12
|
+
flag nil, :noop, _('Do not convert the module, just output what would be done.')
|
13
|
+
flag nil, :force, _('Convert the module automatically, with no prompts.')
|
14
|
+
|
15
|
+
run do |opts, _args, _cmd|
|
16
|
+
require 'pdk/module/convert'
|
17
|
+
|
18
|
+
PDK::CLI::Util.ensure_in_module!(
|
19
|
+
check_module_layout: true,
|
20
|
+
message: _('`pdk convert` can only be run from inside a valid module directory.'),
|
21
|
+
log_level: :info,
|
22
|
+
)
|
23
|
+
|
24
|
+
if opts[:noop] && opts[:force]
|
25
|
+
raise PDK::CLI::ExitWithError, _('You can not specify --noop and --force when converting a module')
|
26
|
+
end
|
27
|
+
|
28
|
+
if opts[:'skip-interview'] && opts[:'full-interview']
|
29
|
+
PDK.logger.info _('Ignoring --full-interview and continuing with --skip-interview.')
|
30
|
+
opts[:'full-interview'] = false
|
31
|
+
end
|
32
|
+
|
33
|
+
if opts[:force] && opts[:'full-interview']
|
34
|
+
PDK.logger.info _('Ignoring --full-interview and continuing with --force.')
|
35
|
+
opts[:'full-interview'] = false
|
36
|
+
end
|
37
|
+
|
38
|
+
PDK::Module::Convert.invoke(opts)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PDK
|
2
|
+
module CLI
|
3
|
+
class FatalError < StandardError
|
4
|
+
attr_reader :exit_code
|
5
|
+
|
6
|
+
def initialize(msg = _('An unexpected error has occurred. Try running the command again with --debug'), opts = {})
|
7
|
+
@exit_code = opts.fetch(:exit_code, 1)
|
8
|
+
super(msg)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ExitWithError < StandardError
|
13
|
+
attr_reader :exit_code
|
14
|
+
attr_reader :log_level
|
15
|
+
|
16
|
+
def initialize(msg, opts = {})
|
17
|
+
@exit_code = opts.fetch(:exit_code, 1)
|
18
|
+
@log_level = opts.fetch(:log_level, :error)
|
19
|
+
super(msg)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/pdk/cli/exec.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'childprocess'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'tty-spinner'
|
5
|
+
require 'tty-which'
|
6
|
+
|
7
|
+
require 'pdk/util'
|
8
|
+
require 'pdk/util/git'
|
9
|
+
require 'pdk/util/ruby_version'
|
10
|
+
|
11
|
+
module PDK
|
12
|
+
module CLI
|
13
|
+
module Exec
|
14
|
+
def self.execute(*cmd)
|
15
|
+
Command.new(*cmd).execute!
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.execute_with_env(env, *cmd)
|
19
|
+
Command.new(*cmd).tap { |c| c.environment = env }.execute!
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.ensure_bin_present!(bin_path, bin_name)
|
23
|
+
message = _('Unable to find `%{name}`. Check that it is installed and try again.') % {
|
24
|
+
name: bin_name,
|
25
|
+
}
|
26
|
+
|
27
|
+
raise PDK::CLI::FatalError, message unless TTY::Which.exist?(bin_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.bundle(*args)
|
31
|
+
ensure_bin_present!(bundle_bin, 'bundler')
|
32
|
+
|
33
|
+
execute(bundle_bin, *args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.bundle_bin
|
37
|
+
bundle_bin = Gem.win_platform? ? 'bundle.bat' : 'bundle'
|
38
|
+
vendored_bin_path = File.join('private', 'ruby', PDK::Util::RubyVersion.active_ruby_version, 'bin', bundle_bin)
|
39
|
+
|
40
|
+
try_vendored_bin(vendored_bin_path, bundle_bin)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.try_vendored_bin(vendored_bin_path, fallback)
|
44
|
+
unless PDK::Util.package_install?
|
45
|
+
PDK.logger.debug(_("PDK package installation not found. Trying '%{fallback}' from the system PATH instead.") % {
|
46
|
+
fallback: fallback,
|
47
|
+
})
|
48
|
+
return fallback
|
49
|
+
end
|
50
|
+
|
51
|
+
vendored_bin_full_path = File.join(PDK::Util.pdk_package_basedir, vendored_bin_path)
|
52
|
+
|
53
|
+
unless File.exist?(vendored_bin_full_path)
|
54
|
+
PDK.logger.debug(_("Could not find '%{vendored_bin}' in PDK package. Trying '%{fallback}' from the system PATH instead.") % {
|
55
|
+
fallback: fallback,
|
56
|
+
vendored_bin: vendored_bin_full_path,
|
57
|
+
})
|
58
|
+
return fallback
|
59
|
+
end
|
60
|
+
|
61
|
+
PDK.logger.debug(_("Using '%{vendored_bin}' from PDK package.") % { vendored_bin: vendored_bin_full_path })
|
62
|
+
vendored_bin_full_path
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO: decide how/when to connect stdin to child process for things like pry
|
66
|
+
# TODO: need a way to set callbacks on new stdout/stderr data
|
67
|
+
class Command
|
68
|
+
attr_reader :argv
|
69
|
+
attr_reader :context
|
70
|
+
attr_accessor :timeout
|
71
|
+
attr_accessor :environment
|
72
|
+
attr_writer :exec_group
|
73
|
+
|
74
|
+
def initialize(*argv)
|
75
|
+
@argv = argv
|
76
|
+
|
77
|
+
@process = ChildProcess.build(*@argv)
|
78
|
+
@process.leader = true
|
79
|
+
|
80
|
+
@stdout = Tempfile.new('stdout').tap { |io| io.sync = true }
|
81
|
+
@stderr = Tempfile.new('stderr').tap { |io| io.sync = true }
|
82
|
+
|
83
|
+
@process.io.stdout = @stdout
|
84
|
+
@process.io.stderr = @stderr
|
85
|
+
|
86
|
+
# Default to running things in the system context.
|
87
|
+
@context = :system
|
88
|
+
|
89
|
+
# Extra environment vars to add to base set.
|
90
|
+
@environment = {}
|
91
|
+
|
92
|
+
# Register the ExecGroup when running in parallel
|
93
|
+
@exec_group = nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def context=(new_context)
|
97
|
+
unless [:system, :module].include?(new_context)
|
98
|
+
raise ArgumentError, _("Expected execution context to be :system or :module but got '%{context}'.") % { context: new_context }
|
99
|
+
end
|
100
|
+
|
101
|
+
@context = new_context
|
102
|
+
end
|
103
|
+
|
104
|
+
def register_spinner(spinner, opts = {})
|
105
|
+
return unless PDK::CLI::Util.interactive?
|
106
|
+
@success_message = opts.delete(:success)
|
107
|
+
@failure_message = opts.delete(:failure)
|
108
|
+
|
109
|
+
@spinner = spinner
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_spinner(message, opts = {})
|
113
|
+
return unless PDK::CLI::Util.interactive?
|
114
|
+
@success_message = opts.delete(:success)
|
115
|
+
@failure_message = opts.delete(:failure)
|
116
|
+
|
117
|
+
@spinner = TTY::Spinner.new("[:spinner] #{message}", opts.merge(PDK::CLI::Util.spinner_opts_for_platform))
|
118
|
+
end
|
119
|
+
|
120
|
+
def update_environment(additional_env)
|
121
|
+
@environment.merge!(additional_env)
|
122
|
+
end
|
123
|
+
|
124
|
+
def execute!
|
125
|
+
# Start spinning if configured.
|
126
|
+
@spinner.auto_spin if @spinner
|
127
|
+
|
128
|
+
# Add custom env vars.
|
129
|
+
@environment.each do |k, v|
|
130
|
+
@process.environment[k] = v
|
131
|
+
end
|
132
|
+
|
133
|
+
@process.environment['BUNDLE_IGNORE_CONFIG'] = '1'
|
134
|
+
|
135
|
+
if context == :module
|
136
|
+
@process.environment['GEM_HOME'] = PDK::Util::RubyVersion.gem_home
|
137
|
+
@process.environment['GEM_PATH'] = PDK::Util::RubyVersion.gem_path
|
138
|
+
|
139
|
+
# Make sure invocation of Ruby prefers our private installation.
|
140
|
+
package_binpath = PDK::Util.package_install? ? File.join(PDK::Util.pdk_package_basedir, 'bin') : nil
|
141
|
+
@process.environment['PATH'] = [
|
142
|
+
PDK::Util::RubyVersion.bin_path,
|
143
|
+
File.join(@process.environment['GEM_HOME'], 'bin'),
|
144
|
+
PDK::Util::RubyVersion.gem_paths_raw.map { |gem_path| File.join(gem_path, 'bin') },
|
145
|
+
package_binpath,
|
146
|
+
ENV['PATH'],
|
147
|
+
PDK::Util.package_install? ? PDK::Util::Git.git_paths : nil,
|
148
|
+
].compact.flatten.join(File::PATH_SEPARATOR)
|
149
|
+
|
150
|
+
mod_root = PDK::Util.module_root
|
151
|
+
|
152
|
+
unless mod_root
|
153
|
+
@spinner.error if @spinner
|
154
|
+
|
155
|
+
raise PDK::CLI::FatalError, _('Current working directory is not part of a module. (No metadata.json was found.)')
|
156
|
+
end
|
157
|
+
|
158
|
+
if Dir.pwd == mod_root
|
159
|
+
run_process_in_clean_env!
|
160
|
+
else
|
161
|
+
Dir.chdir(mod_root) do
|
162
|
+
run_process_in_clean_env!
|
163
|
+
end
|
164
|
+
end
|
165
|
+
else
|
166
|
+
run_process!
|
167
|
+
end
|
168
|
+
|
169
|
+
# Stop spinning when done (if configured).
|
170
|
+
stop_spinner
|
171
|
+
|
172
|
+
@stdout.rewind
|
173
|
+
@stderr.rewind
|
174
|
+
|
175
|
+
process_data = {
|
176
|
+
stdout: @stdout.read,
|
177
|
+
stderr: @stderr.read,
|
178
|
+
exit_code: @process.exit_code,
|
179
|
+
duration: @duration,
|
180
|
+
}
|
181
|
+
|
182
|
+
return process_data
|
183
|
+
ensure
|
184
|
+
@stdout.close
|
185
|
+
@stderr.close
|
186
|
+
end
|
187
|
+
|
188
|
+
protected
|
189
|
+
|
190
|
+
def stop_spinner
|
191
|
+
return unless @spinner
|
192
|
+
|
193
|
+
# If it is a single spinner, we need to send it a success/error message
|
194
|
+
if @process.exit_code.zero?
|
195
|
+
@spinner.success(@success_message || '')
|
196
|
+
else
|
197
|
+
@spinner.error(@failure_message || '')
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def run_process_in_clean_env!
|
202
|
+
::Bundler.with_clean_env do
|
203
|
+
run_process!
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def run_process!
|
208
|
+
command_string = argv.join(' ')
|
209
|
+
|
210
|
+
PDK.logger.debug(_("Executing '%{command}'") % { command: command_string })
|
211
|
+
|
212
|
+
if context == :module
|
213
|
+
PDK.logger.debug(_('Command environment:'))
|
214
|
+
@process.environment.each do |var, val|
|
215
|
+
PDK.logger.debug(" #{var}: #{val}")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
start_time = Time.now
|
220
|
+
|
221
|
+
begin
|
222
|
+
@process.start
|
223
|
+
rescue ChildProcess::LaunchError => e
|
224
|
+
raise PDK::CLI::FatalError, _("Failed to execute '%{command}': %{message}") % { command: command_string, message: e.message }
|
225
|
+
end
|
226
|
+
|
227
|
+
if timeout
|
228
|
+
begin
|
229
|
+
@process.poll_for_exit(timeout)
|
230
|
+
rescue ChildProcess::TimeoutError
|
231
|
+
@process.stop # tries increasingly harsher methods to kill the process.
|
232
|
+
end
|
233
|
+
else
|
234
|
+
# Wait indfinitely if no timeout set.
|
235
|
+
@process.wait
|
236
|
+
end
|
237
|
+
|
238
|
+
@duration = Time.now - start_time
|
239
|
+
|
240
|
+
PDK.logger.debug(_("Execution of '%{command}' complete (duration: %{duration_in_seconds}s; exit code: %{exit_code})") %
|
241
|
+
{ command: command_string, duration_in_seconds: @duration, exit_code: @process.exit_code })
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|