pdk 0.1.0 → 0.2.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/README.md +3 -9
  4. data/exe/pdk +1 -1
  5. data/lib/pdk.rb +5 -4
  6. data/lib/pdk/cli.rb +62 -59
  7. data/lib/pdk/cli/errors.rb +1 -1
  8. data/lib/pdk/cli/exec.rb +154 -29
  9. data/lib/pdk/cli/input.rb +2 -2
  10. data/lib/pdk/cli/new.rb +12 -27
  11. data/lib/pdk/cli/new/class.rb +28 -41
  12. data/lib/pdk/cli/new/module.rb +30 -41
  13. data/lib/pdk/cli/test.rb +9 -20
  14. data/lib/pdk/cli/test/unit.rb +38 -0
  15. data/lib/pdk/cli/util/option_normalizer.rb +45 -19
  16. data/lib/pdk/cli/util/option_validator.rb +24 -20
  17. data/lib/pdk/cli/validate.rb +65 -65
  18. data/lib/pdk/generate.rb +5 -0
  19. data/lib/pdk/generators/module.rb +37 -33
  20. data/lib/pdk/generators/puppet_class.rb +1 -1
  21. data/lib/pdk/generators/puppet_object.rb +19 -20
  22. data/lib/pdk/logger.rb +1 -1
  23. data/lib/pdk/module/metadata.rb +35 -18
  24. data/lib/pdk/module/templatedir.rb +40 -33
  25. data/lib/pdk/report.rb +76 -19
  26. data/lib/pdk/report/event.rb +276 -0
  27. data/lib/pdk/template_file.rb +8 -6
  28. data/lib/pdk/tests/unit.rb +8 -3
  29. data/lib/pdk/util.rb +65 -0
  30. data/lib/pdk/util/bundler.rb +167 -0
  31. data/lib/pdk/util/version.rb +34 -0
  32. data/lib/pdk/validate.rb +3 -4
  33. data/lib/pdk/validators/base_validator.rb +60 -4
  34. data/lib/pdk/validators/metadata.rb +29 -0
  35. data/lib/pdk/validators/puppet/puppet_lint.rb +47 -0
  36. data/lib/pdk/validators/puppet/puppet_parser.rb +34 -0
  37. data/lib/pdk/validators/puppet_validator.rb +30 -0
  38. data/lib/pdk/validators/ruby/rubocop.rb +59 -0
  39. data/lib/pdk/validators/ruby_validator.rb +29 -0
  40. data/lib/pdk/version.rb +1 -1
  41. data/lib/puppet/util/windows.rb +14 -0
  42. data/lib/puppet/util/windows/api_types.rb +278 -0
  43. data/lib/puppet/util/windows/file.rb +488 -0
  44. data/lib/puppet/util/windows/string.rb +16 -0
  45. data/locales/de/pdk.po +263 -78
  46. data/locales/pdk.pot +224 -65
  47. metadata +60 -8
  48. data/lib/pdk/cli/tests/unit.rb +0 -52
  49. data/lib/pdk/validators/puppet_lint.rb +0 -17
  50. data/lib/pdk/validators/puppet_parser.rb +0 -17
  51. data/lib/pdk/validators/ruby_lint.rb +0 -17
@@ -16,7 +16,7 @@ module PDK
16
16
  def initialize(template_file, data = {})
17
17
  @template_file = template_file
18
18
 
19
- if data.has_key?(:configs)
19
+ if data.key?(:configs)
20
20
  @configs = data[:configs]
21
21
  end
22
22
 
@@ -37,13 +37,15 @@ module PDK
37
37
  # @api public
38
38
  def render
39
39
  case File.extname(@template_file)
40
- when ".erb"
40
+ when '.erb'
41
41
  render_erb
42
42
  else
43
43
  render_plain
44
44
  end
45
45
  end
46
- private
46
+
47
+ private
48
+
47
49
  # Reads the content of the template file into memory.
48
50
  #
49
51
  # @return [String] The content of the template file.
@@ -54,10 +56,10 @@ module PDK
54
56
  # @api private
55
57
  def template_content
56
58
  if File.file?(@template_file) && File.readable?(@template_file)
57
- File.read(@template_file)
58
- else
59
- raise ArgumentError, _("'%{template}' is not a readable file") % {:template => @template_file}
59
+ return File.read(@template_file)
60
60
  end
61
+
62
+ raise ArgumentError, _("'%{template}' is not a readable file") % { template: @template_file }
61
63
  end
62
64
 
63
65
  # Renders the content of the template file as an ERB template.
@@ -1,18 +1,23 @@
1
1
  require 'pdk'
2
2
  require 'pdk/cli/exec'
3
+ require 'pdk/util/bundler'
3
4
 
4
5
  module PDK
5
6
  module Test
6
7
  class Unit
7
- def self.cmd(tests)
8
+ def self.cmd(_tests)
8
9
  # TODO: actually run the tests
9
- #cmd = 'rake spec'
10
- #cmd += " #{tests}" if tests
10
+ # cmd = 'rake spec'
11
+ # cmd += " #{tests}" if tests
11
12
  cmd = 'pwd'
12
13
  cmd
13
14
  end
14
15
 
15
16
  def self.invoke(tests, report = nil)
17
+ PDK::Util::Bundler.ensure_bundle!
18
+
19
+ puts _('Running unit tests: %{tests}') % { tests: tests }
20
+
16
21
  output = PDK::CLI::Exec.execute(cmd(tests))
17
22
  report.write(output) if report
18
23
  end
data/lib/pdk/util.rb CHANGED
@@ -1,8 +1,28 @@
1
1
  require 'tmpdir'
2
2
  require 'tempfile'
3
+ require 'puppet/util/windows'
3
4
 
4
5
  module PDK
5
6
  module Util
7
+ # Searches upwards from current working directory for the given target file.
8
+ #
9
+ # @param target [String] Name of file to search for.
10
+ #
11
+ # @return [String, nil] Fully qualified path to the given target file if found,
12
+ # nil if the target file could not be found.
13
+ def find_upwards(target)
14
+ previous = nil
15
+ current = File.expand_path(Dir.pwd)
16
+
17
+ until !File.directory?(current) || current == previous
18
+ filename = File.join(current, target)
19
+ return filename if File.file?(filename)
20
+ previous = current
21
+ current = File.expand_path('..', current)
22
+ end
23
+ end
24
+ module_function :find_upwards
25
+
6
26
  # Generate a name for a temporary directory.
7
27
  #
8
28
  # @param base [String] A string to base the name generation off.
@@ -12,5 +32,50 @@ module PDK
12
32
  Dir::Tmpname.make_tmpname(File.join(Dir.tmpdir, base), nil)
13
33
  end
14
34
  module_function :make_tmpdir_name
35
+
36
+ # Return an expanded, absolute path
37
+ #
38
+ # @param path [String] Existing path that may not be canonical
39
+ #
40
+ # @return [String] Canonical path
41
+ def canonical_path(path)
42
+ if Gem.win_platform?
43
+ unless File.exist?(path)
44
+ raise PDK::CLI::FatalError, _("Cannot resolve a full path to '%{path}' as it does not currently exist") % { path: path }
45
+ end
46
+ Puppet::Util::Windows::File.get_long_pathname(path)
47
+ else
48
+ File.expand_path(path)
49
+ end
50
+ end
51
+ module_function :canonical_path
52
+
53
+ # Returns the fully qualified path to a per-user PDK cachedir.
54
+ #
55
+ # @return [String] Fully qualified path to per-user PDK cachedir.
56
+ def cachedir
57
+ basedir = if Gem.win_platform?
58
+ ENV['LOCALAPPDATA']
59
+ else
60
+ Dir.home
61
+ end
62
+
63
+ File.join(basedir, '.pdk', 'cache')
64
+ end
65
+ module_function :cachedir
66
+
67
+ # Returns path to the root of the module being worked on.
68
+ #
69
+ # @return [String, nil] Fully qualified base path to module, or nil if
70
+ # the current working dir does not appear to be within a module.
71
+ def module_root
72
+ metadata_path = find_upwards('metadata.json')
73
+ if metadata_path
74
+ File.dirname(metadata_path)
75
+ else
76
+ nil
77
+ end
78
+ end
79
+ module_function :module_root
15
80
  end
16
81
  end
@@ -0,0 +1,167 @@
1
+ require 'bundler'
2
+ require 'tty-spinner'
3
+ require 'pdk/util'
4
+ require 'pdk/cli/exec'
5
+
6
+ module PDK
7
+ module Util
8
+ module Bundler
9
+ class BundleHelper; end
10
+
11
+ def self.ensure_bundle!
12
+ bundle = BundleHelper.new
13
+
14
+ if already_bundled?(bundle.gemfile)
15
+ PDK.logger.debug(_('Bundle has already been installed, skipping run'))
16
+ return
17
+ end
18
+
19
+ unless bundle.gemfile?
20
+ PDK.logger.debug(_("No Gemfile found in '%{cwd}', skipping bundler management") % { cwd: Dir.pwd })
21
+ return
22
+ end
23
+
24
+ unless bundle.locked?
25
+ unless bundle.lock!
26
+ raise PDK::CLI::FatalError, _('Unable to resolve Gemfile dependencies.')
27
+ end
28
+ end
29
+
30
+ unless bundle.installed?
31
+ unless bundle.install!
32
+ raise PDK::CLI::FatalError, _('Unable to install missing Gemfile dependencies.')
33
+ end
34
+ end
35
+
36
+ mark_as_bundled!(bundle.gemfile)
37
+ end
38
+
39
+ def self.already_bundled?(gemfile)
40
+ !(@bundled ||= {})[gemfile].nil?
41
+ end
42
+
43
+ def self.mark_as_bundled!(gemfile)
44
+ (@bundled ||= {})[gemfile] = true
45
+ end
46
+
47
+ def self.ensure_binstubs!(*gems)
48
+ bundle = BundleHelper.new
49
+
50
+ unless bundle.binstubs!(gems) # rubocop:disable Style/GuardClause
51
+ raise PDK::CLI::FatalError, _('Unable to install requested binstubs.')
52
+ end
53
+ end
54
+
55
+ class BundleHelper
56
+ def gemfile?
57
+ !gemfile.nil?
58
+ end
59
+
60
+ def locked?
61
+ !gemfile_lock.nil?
62
+ end
63
+
64
+ def installed?
65
+ output_start(_('Checking for missing Gemfile dependencies'))
66
+
67
+ result = invoke('check', "--gemfile=#{gemfile}", "--path=#{bundle_cachedir}")
68
+
69
+ output_end(:success)
70
+
71
+ result[:exit_code].zero?
72
+ end
73
+
74
+ def lock!
75
+ output_start(_('Resolving Gemfile dependencies'))
76
+
77
+ result = invoke('lock')
78
+
79
+ if result[:exit_code].zero?
80
+ output_end(:success)
81
+ else
82
+ output_end(:failure)
83
+ $stderr.puts result[:stdout]
84
+ $stderr.puts result[:stderr]
85
+ end
86
+
87
+ result[:exit_code].zero?
88
+ end
89
+
90
+ def install!
91
+ output_start(_('Installing missing Gemfile dependencies'))
92
+
93
+ result = invoke('install', "--gemfile=#{gemfile}", "--path=#{bundle_cachedir}")
94
+
95
+ if result[:exit_code].zero?
96
+ output_end(:success)
97
+ else
98
+ output_end(:failure)
99
+ $stderr.puts result[:stdout]
100
+ $stderr.puts result[:stderr]
101
+ end
102
+
103
+ result[:exit_code].zero?
104
+ end
105
+
106
+ def binstubs!(gems)
107
+ # FIXME: wrap in progress indicator
108
+ result = invoke('binstubs', gems.join(' '), '--force')
109
+
110
+ unless result[:exit_code].zero?
111
+ $stderr.puts result[:stdout]
112
+ $stderr.puts result[:stderr]
113
+ end
114
+
115
+ result[:exit_code].zero?
116
+ end
117
+
118
+ def gemfile
119
+ @gemfile ||= PDK::Util.find_upwards('Gemfile')
120
+ end
121
+
122
+ private
123
+
124
+ def invoke(*args)
125
+ bundle_bin = PDK::CLI::Exec.bundle_bin
126
+ command = PDK::CLI::Exec::Command.new(bundle_bin, *args).tap do |c|
127
+ c.context = :module
128
+ end
129
+
130
+ command.execute!
131
+ end
132
+
133
+ def gemfile_lock
134
+ @gemfile_lock ||= PDK::Util.find_upwards('Gemfile.lock')
135
+ end
136
+
137
+ def bundle_cachedir
138
+ @bundle_cachedir ||= File.join(PDK::Util.cachedir, 'bundler')
139
+ end
140
+
141
+ # These two output_* methods are just a way to not try to do the spinner stuff on Windows for now.
142
+ def output_start(message)
143
+ if Gem.win_platform?
144
+ $stderr.print "#{message}... "
145
+ else
146
+ @spinner = TTY::Spinner.new("[:spinner] #{message}")
147
+ @spinner.auto_spin
148
+ end
149
+ end
150
+
151
+ def output_end(state)
152
+ if Gem.win_platform?
153
+ $stderr.print((state == :success) ? _("done.\n") : _("FAILURE!\n"))
154
+ else
155
+ if state == :success
156
+ @spinner.success
157
+ else
158
+ @spinner.error
159
+ end
160
+
161
+ remove_instance_variable(:@spinner)
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,34 @@
1
+ require 'pdk/version'
2
+ require 'pdk/cli/exec'
3
+
4
+ module PDK
5
+ module Util
6
+ module Version
7
+ def self.version_string
8
+ "#{PDK::VERSION} #{pdk_ref}".strip.freeze
9
+ end
10
+
11
+ def self.pdk_ref
12
+ ref = "#{pkg_sha} #{git_ref}".strip
13
+ ref.empty? ? nil : "(#{ref})"
14
+ end
15
+
16
+ def self.pkg_sha
17
+ version_file = File.join(File.expand_path('../../..', File.dirname(__FILE__)), 'VERSION')
18
+
19
+ if File.exist? version_file
20
+ ver = File.read(version_file)
21
+ sha = ver.strip.split('.')[-1] unless ver.nil?
22
+ end
23
+
24
+ sha
25
+ end
26
+
27
+ def self.git_ref
28
+ ref_result = PDK::CLI::Exec.git('--git-dir', File.join(File.expand_path('../../..', File.dirname(__FILE__)), '.git'), 'describe', '--all', '--long')
29
+
30
+ ref_result[:stdout].strip if ref_result[:exit_code].zero?
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/pdk/validate.rb CHANGED
@@ -1,12 +1,11 @@
1
1
  require 'pdk/validators/metadata'
2
- require 'pdk/validators/puppet_lint'
3
- require 'pdk/validators/puppet_parser'
4
- require 'pdk/validators/ruby_lint'
2
+ require 'pdk/validators/puppet_validator'
3
+ require 'pdk/validators/ruby_validator'
5
4
 
6
5
  module PDK
7
6
  module Validate
8
7
  def self.validators
9
- @validators ||= [Metadata, PuppetLint, PuppetParser, RubyLint].freeze
8
+ @validators ||= [Metadata, PuppetValidator, RubyValidator].freeze
10
9
  end
11
10
  end
12
11
  end
@@ -4,10 +4,66 @@ require 'pdk/cli/exec'
4
4
  module PDK
5
5
  module Validate
6
6
  class BaseValidator
7
- def self.invoke(options = {})
8
- PDK.logger.info(_("Running %{cmd} with options: %{options}") % {cmd: cmd, options: options})
9
- result = PDK::CLI::Exec.execute(cmd, options)
10
- result
7
+ def self.cmd_path
8
+ File.join(PDK::Util.module_root, 'bin', cmd)
9
+ end
10
+
11
+ def self.parse_targets(options)
12
+ # If no targets are specified, then we will run validations from the
13
+ # base module directory.
14
+ targets = if options[:targets].nil? || options[:targets].empty?
15
+ [PDK::Util.module_root]
16
+ else
17
+ options[:targets]
18
+ end
19
+
20
+ targets.map { |target|
21
+ if respond_to?(:pattern)
22
+ if File.directory?(target)
23
+ files_glob = Array[pattern].flatten.map { |p| Dir.glob(File.join(target, p)) }
24
+ files_glob.flatten.empty? ? target : files_glob
25
+ else
26
+ target
27
+ end
28
+ else
29
+ target
30
+ end
31
+ }.flatten
32
+ end
33
+
34
+ def self.parse_options(_options, targets)
35
+ targets
36
+ end
37
+
38
+ def self.spinner_text
39
+ _('Invoking %{cmd}') % { cmd: cmd }
40
+ end
41
+
42
+ def self.invoke(report, options = {})
43
+ PDK::Util::Bundler.ensure_binstubs!(cmd)
44
+
45
+ targets = parse_targets(options)
46
+ cmd_argv = parse_options(options, targets).unshift(cmd_path)
47
+ cmd_argv.unshift('ruby') if Gem.win_platform?
48
+
49
+ PDK.logger.debug(_('Running %{cmd}') % { cmd: cmd_argv.join(' ') })
50
+
51
+ command = PDK::CLI::Exec::Command.new(*cmd_argv).tap do |c|
52
+ c.context = :module
53
+ c.add_spinner(spinner_text)
54
+ end
55
+
56
+ result = command.execute!
57
+
58
+ begin
59
+ json_data = JSON.parse(result[:stdout])
60
+ rescue JSON::ParserError
61
+ json_data = []
62
+ end
63
+
64
+ parse_output(report, json_data)
65
+
66
+ result[:exit_code]
11
67
  end
12
68
  end
13
69
  end
@@ -1,6 +1,7 @@
1
1
  require 'pdk'
2
2
  require 'pdk/cli/exec'
3
3
  require 'pdk/validators/base_validator'
4
+ require 'pdk/util/bundler'
4
5
 
5
6
  module PDK
6
7
  module Validate
@@ -12,6 +13,34 @@ module PDK
12
13
  def self.cmd
13
14
  'metadata-json-lint'
14
15
  end
16
+
17
+ def self.parse_targets(_options)
18
+ [File.join(PDK::Util.module_root, 'metadata.json')]
19
+ end
20
+
21
+ def self.parse_options(_options, targets)
22
+ cmd_options = ['--format', 'json']
23
+
24
+ cmd_options.concat(targets)
25
+ end
26
+
27
+ def self.parse_output(report, json_data)
28
+ return if json_data.empty?
29
+
30
+ json_data.delete('result')
31
+ json_data.keys.each do |type|
32
+ json_data[type].each do |offense|
33
+ report.add_event(
34
+ file: 'metadata.json',
35
+ source: cmd,
36
+ message: offense['msg'],
37
+ test: offense['check'],
38
+ severity: type,
39
+ state: :failure,
40
+ )
41
+ end
42
+ end
43
+ end
15
44
  end
16
45
  end
17
46
  end