pdk 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/exe/pdk ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pdk/cli'
4
+
5
+ PDK::CLI.run(ARGV.dup)
@@ -0,0 +1,8 @@
1
+ require 'pdk/version'
2
+ require 'pdk/logger'
3
+ require 'pdk/i18n'
4
+ require 'pdk/generate'
5
+ require 'pdk/validate'
6
+ require 'pdk/report'
7
+
8
+ module PDK; end
@@ -0,0 +1,80 @@
1
+ require 'cri'
2
+
3
+ require 'pdk/cli/errors'
4
+ require 'pdk/cli/util/option_validator'
5
+ require 'pdk/cli/util/option_normalizer'
6
+ require 'pdk/logger'
7
+ require 'pdk/report'
8
+
9
+ require 'pdk/cli/new'
10
+ require 'pdk/cli/validate'
11
+ require 'pdk/cli/test'
12
+
13
+ module PDK
14
+ module CLI
15
+ def self.base_command
16
+ @base ||= Cri::Command.new.tap do |cmd|
17
+ cmd.modify do
18
+ name 'pdk'
19
+ usage _("pdk command [options]")
20
+ summary _("Puppet Development Kit")
21
+ description _("The shortest path to better modules.")
22
+
23
+ flag :h, :help, _("show help for this command") do |_, c|
24
+ puts c.help
25
+ exit 0
26
+ end
27
+
28
+ format_desc = _(
29
+ "Specify desired output format. Valid formats are '%{available_formats}'. " +
30
+ "You may also specify a file to which the formatted output will be directed, " +
31
+ "for example: '--format=junit:report.xml'. This option may be specified " +
32
+ "multiple times as long as each option specifies a distinct target file."
33
+ ) % {available_formats: PDK::Report.formats.join("', '")}
34
+
35
+ option :f, :format, format_desc, { argument: :required, multiple: true } do |values|
36
+ values.compact.each do |v|
37
+ if v.include?(':')
38
+ format = v.split(':', 2).first
39
+
40
+ PDK::CLI::Util::OptionValidator.enum(format, PDK::Report.formats)
41
+ else
42
+ PDK::CLI::Util::OptionValidator.enum(v, PDK::Report.formats)
43
+ end
44
+ end
45
+ end
46
+
47
+ flag :d, :debug, _("Enable debug output.") do |_, _|
48
+ PDK.logger.enable_debug_output
49
+ end
50
+ end
51
+
52
+ cmd.add_command(Cri::Command.new_basic_help)
53
+
54
+ cmd.add_command(PDK::CLI::New.command)
55
+ cmd.add_command(PDK::CLI::Validate.command)
56
+ cmd.add_command(PDK::CLI::Test.command)
57
+ end
58
+ end
59
+
60
+ def self.run(args)
61
+ base_command.run(args)
62
+ rescue PDK::CLI::FatalError => e
63
+ PDK.logger.fatal(e.message) if e.message
64
+
65
+ # If FatalError was raised as the result of another exception, send the
66
+ # details of that exception to the debug log. If there was no cause
67
+ # (FatalError raised on its own outside a rescue block), send the details
68
+ # of the FatalError exception to the debug log.
69
+ cause = e.cause
70
+ if cause.nil?
71
+ e.backtrace.each { |line| PDK.logger.debug(line) }
72
+ else
73
+ PDK.logger.debug("#{cause.class}: #{cause.message}")
74
+ cause.backtrace.each { |line| PDK.logger.debug(line) }
75
+ end
76
+
77
+ exit e.exit_code
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,12 @@
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"), exit_code=1)
7
+ @exit_code = exit_code
8
+ super(msg)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ require 'childprocess'
2
+ require 'tempfile'
3
+
4
+ module PDK
5
+ module CLI
6
+ module Exec
7
+ # TODO: decide how to handle multiple output targets when underlying tool doesn't support that
8
+ # TODO: decide what this method should return
9
+ # TODO: decide how/when to connect stdin to child process for things like pry
10
+ def self.execute(*cmd)
11
+ process = ChildProcess.build(*cmd)
12
+
13
+ process.io.stdout = Tempfile.new('stdout')
14
+ process.io.stderr = Tempfile.new('stderr')
15
+
16
+ begin
17
+ # start the process
18
+ process.start
19
+
20
+ # wait indefinitely for process to exit...
21
+ process.wait
22
+
23
+ stdout = process.io.stdout.open.read
24
+ stderr = process.io.stderr.open.read
25
+ ensure
26
+ process.io.stdout.close
27
+ process.io.stderr.close
28
+ end
29
+
30
+ {
31
+ :exit_code => process.exit_code,
32
+ :stdout => stdout,
33
+ :stderr => stderr
34
+ }
35
+ end
36
+
37
+ def self.pdk_basedir
38
+ @pdk_basedir ||= Gem.win_platform? ? 'C:/Program Files/Puppet Labs/DevelopmentKit' : '/opt/puppetlabs/sdk'
39
+ end
40
+
41
+ def self.git_bindir
42
+ @git_dir ||= File.join(pdk_basedir, 'private', 'git', 'bin')
43
+ end
44
+
45
+ def self.git(*args)
46
+ git_path = ENV['PDK_USE_SYSTEM_BINARIES'].nil? ? File.join(git_bindir, 'git') : 'git'
47
+ execute(git_path, *args)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ module PDK
2
+ module CLI
3
+ module Input
4
+ # Query the user for a value via STDIN.
5
+ #
6
+ # @param message [String] The message to be displayed to the user before
7
+ # accepting input.
8
+ # @param default [String] The default value to be used if the user
9
+ # provides a blank value.
10
+ #
11
+ # @return [String] The value provided by the user (or the supplied
12
+ # default value).
13
+ def self.get(message, default=nil)
14
+ print message
15
+ if default.nil?
16
+ print " [(none)]"
17
+ else
18
+ print " [#{default}]"
19
+ end
20
+
21
+ print "\n--> "
22
+ input = (STDIN.gets || '').chomp.strip
23
+ input = default if input == ''
24
+ input
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'cri'
2
+ require 'pdk/cli/new/module'
3
+ require 'pdk/cli/new/class'
4
+
5
+ module PDK
6
+ module CLI
7
+ module New
8
+ def self.command
9
+ @new ||= Cri::Command.new.tap do |cmd|
10
+ cmd.modify do
11
+ name 'new'
12
+ usage _("new <type> [options]")
13
+ summary _("create a new module, etc.")
14
+ description _("Creates a new instance of <type> using the options relevant to that type of thing")
15
+
16
+ # print the help text for the 'new' sub command if no type has been
17
+ # provided.
18
+ run do |opts, args, cmd|
19
+ puts command.help
20
+ exit 1
21
+ end
22
+ end
23
+
24
+ cmd.add_command(PDK::CLI::New::Module.command)
25
+ cmd.add_command(PDK::CLI::New::PuppetClass.command)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ require 'cri'
2
+ require 'pdk/cli/util/option_validator'
3
+
4
+ require 'pdk/generators/module'
5
+ require 'pdk/generators/puppet_class'
6
+
7
+ module PDK
8
+ module CLI
9
+ module New
10
+ class PuppetClass
11
+ include PDK::CLI::Util
12
+
13
+ def self.command
14
+ @puppet_class ||= Cri::Command.define do
15
+ name 'class'
16
+ usage _("class [options] <class_name> [parameter[:type]] [parameter[:type]] ...")
17
+ summary _("Create a new class named <class_name> using given options")
18
+
19
+ option nil, 'template-url', _("Specifies the URL to the template to use when creating the module. Defaults to the template used to create the module, otherwise %{default}") % {:default => PDK::Generate::Module::DEFAULT_TEMPLATE}, argument: :required
20
+
21
+ run do |opts, args, cmd|
22
+ class_name = args[0]
23
+ module_dir = Dir.pwd
24
+
25
+ if class_name.nil? || class_name.empty?
26
+ puts command.help
27
+ exit 1
28
+ end
29
+
30
+ unless PDK::CLI::Util::OptionValidator.is_valid_class_name?(class_name)
31
+ raise PDK::CLI::FatalError, _("'%{name}' is not a valid class name") % {name: class_name}
32
+ end
33
+
34
+ if args.length > 1
35
+ opts[:params] = args[1..-1].map { |r| PDK::CLI::Util::OptionNormalizer.parameter_specification(r) }
36
+ end
37
+
38
+ PDK::Generate::PuppetClass.new(module_dir, class_name, opts).run
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,55 @@
1
+ require 'cri'
2
+ require 'pdk/cli/util/option_validator'
3
+
4
+ require 'pdk/generators/module'
5
+
6
+ module PDK
7
+ module CLI
8
+ module New
9
+ class Module
10
+ include PDK::CLI::Util
11
+
12
+ def self.command
13
+ @module ||= Cri::Command.define do
14
+ name 'module'
15
+ usage _("module [options] <module_name> [target_dir]")
16
+ summary _("Create a new module named <module_name> using given options")
17
+
18
+ option nil, 'template-url', _("Specifies the URL to the template to use when creating the module. Defaults to %{default}") % {:default => PDK::Generate::Module::DEFAULT_TEMPLATE}, argument: :required
19
+
20
+ option nil, 'license', _("Specifies the license this module is written under. This should be a identifier from https://spdx.org/licenses/. Common values are 'Apache-2.0', 'MIT', or 'proprietary'."), argument: :required
21
+
22
+ option nil, 'vcs', _("Specifies the version control driver. Valid values: 'git', 'none'. Default: 'git'."), argument: :required
23
+
24
+ flag nil, 'skip-interview', _("When specified, skips interactive querying of metadata.")
25
+
26
+ run do |opts, args, cmd|
27
+ module_name = args[0]
28
+ target_dir = args[1]
29
+
30
+ if module_name.nil? || module_name.empty?
31
+ puts command.help
32
+ exit 1
33
+ end
34
+
35
+ unless OptionValidator.is_valid_module_name?(module_name)
36
+ error_msg = _(
37
+ "'%{module_name}' is not a valid module name.\n" +
38
+ "Module names must begin with a lowercase letter and can only include lowercase letters, digits, and underscores."
39
+ ) % {:module_name => module_name}
40
+ raise PDK::CLI::FatalError.new(error_msg)
41
+ end
42
+
43
+ opts[:name] = module_name
44
+ opts[:target_dir] = target_dir.nil? ? module_name : target_dir
45
+ opts[:vcs] ||= 'git'
46
+
47
+ PDK.logger.info(_("Creating new module: %{modname}") % {:modname => module_name})
48
+ PDK::Generate::Module.invoke(opts)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,23 @@
1
+ require 'cri'
2
+ require 'pdk/cli/tests/unit'
3
+ require 'pdk/report'
4
+
5
+
6
+ module PDK
7
+ module CLI
8
+ module Test
9
+
10
+ def self.command
11
+ @test ||= Cri::Command.new.tap do |cmd|
12
+ cmd.modify do
13
+ name 'test'
14
+ usage _("test [type] [options]")
15
+ summary _("Run tests.")
16
+ end
17
+
18
+ cmd.add_command(PDK::CLI::Test::Unit.command)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,52 @@
1
+ require 'cri'
2
+ require 'pdk/cli/util/option_validator'
3
+ require 'pdk/report'
4
+
5
+ require 'pdk/tests/unit'
6
+
7
+ module PDK
8
+ module CLI
9
+ module Test
10
+ class Unit
11
+ include PDK::CLI::Util
12
+
13
+ def self.command
14
+ @unit ||= Cri::Command.define do
15
+ name 'unit'
16
+ usage _("unit [options]")
17
+ summary _("Run unit tests.")
18
+
19
+ flag nil, :list, _("list all available unit tests and their descriptions")
20
+
21
+ option nil, :tests, _("a comma-separated list of tests to run"), argument: :required do |values|
22
+ OptionValidator.list(values)
23
+ end
24
+
25
+ option nil, :runner_options, _("options to pass through to the actual test-runner"), argument: :required
26
+
27
+ run do |opts, args, cmd|
28
+ report = nil
29
+
30
+ if opts[:list]
31
+ puts _("List of all available unit tests: (TODO)")
32
+ end
33
+
34
+ if opts[:tests]
35
+ tests = opts.fetch(:tests)
36
+ end
37
+
38
+ # Note: Reporting may be delegated to the validation tool itself.
39
+ if opts[:'report-file']
40
+ format = opts.fetch(:'report-format', PDK::Report.default_format)
41
+ report = Report.new(opts.fetch(:'report-file'), format)
42
+ end
43
+
44
+ puts _("Running unit tests: %{tests}") % {tests: tests}
45
+ PDK::Test::Unit.invoke(tests, report)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,44 @@
1
+ module PDK
2
+ module CLI
3
+ module Util
4
+ class OptionNormalizer
5
+ def self.comma_separated_list_to_array(list, options = {})
6
+ raise _("Error: expected comma separated list") unless OptionValidator.is_comma_separated_list?(list)
7
+ list.split(',').compact
8
+ end
9
+
10
+ # Parse one or more format:target pairs.
11
+ # @return [Array<Report>] An array of one or more Reports.
12
+ def self.report_formats(formats, options = {})
13
+ reports = []
14
+ formats.each do |f|
15
+ if f.include?(':')
16
+ format, target = f.split(':')
17
+ else
18
+ format, target = f, PDK::Report.default_target
19
+ end
20
+
21
+ reports << Report.new(target, format)
22
+ end
23
+
24
+ reports
25
+ end
26
+
27
+ def self.parameter_specification(value)
28
+ param_name, param_type = value.split(':', 2)
29
+ param_type = 'String' if param_type.nil?
30
+
31
+ unless PDK::CLI::Util::OptionValidator.is_valid_param_name?(param_name)
32
+ raise PDK::CLI::FatalError, _("'%{name}' is not a valid parameter name") % {name: param_name}
33
+ end
34
+
35
+ unless PDK::CLI::Util::OptionValidator.is_valid_data_type?(param_type)
36
+ raise PDK::CLI::FatalError, _("'%{type}' is not a valid data type") % {type: param_type}
37
+ end
38
+
39
+ {name: param_name, type: param_type}
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end