pdk-akerl 1.8.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|