pdk 0.1.0 → 0.2.0

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