pdk 1.17.0 → 1.18.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 (63) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +71 -2
  3. data/lib/pdk/cli/convert.rb +7 -9
  4. data/lib/pdk/cli/new/class.rb +2 -1
  5. data/lib/pdk/cli/new/defined_type.rb +2 -1
  6. data/lib/pdk/cli/new/provider.rb +2 -1
  7. data/lib/pdk/cli/new/task.rb +2 -1
  8. data/lib/pdk/cli/new/test.rb +2 -1
  9. data/lib/pdk/cli/new/transport.rb +2 -1
  10. data/lib/pdk/cli/remove/config.rb +80 -0
  11. data/lib/pdk/cli/remove.rb +20 -0
  12. data/lib/pdk/cli/set/config.rb +119 -0
  13. data/lib/pdk/cli/set.rb +20 -0
  14. data/lib/pdk/cli/update.rb +6 -8
  15. data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
  16. data/lib/pdk/cli/util.rb +1 -0
  17. data/lib/pdk/cli.rb +2 -0
  18. data/lib/pdk/config.rb +96 -13
  19. data/lib/pdk/context.rb +8 -5
  20. data/lib/pdk/generate/defined_type.rb +25 -32
  21. data/lib/pdk/generate/module.rb +11 -10
  22. data/lib/pdk/generate/provider.rb +16 -65
  23. data/lib/pdk/generate/puppet_class.rb +25 -31
  24. data/lib/pdk/generate/puppet_object.rb +83 -187
  25. data/lib/pdk/generate/resource_api_object.rb +55 -0
  26. data/lib/pdk/generate/task.rb +28 -46
  27. data/lib/pdk/generate/transport.rb +21 -75
  28. data/lib/pdk/generate.rb +1 -0
  29. data/lib/pdk/module/convert.rb +41 -23
  30. data/lib/pdk/module/release.rb +1 -1
  31. data/lib/pdk/module/update.rb +6 -10
  32. data/lib/pdk/module/update_manager.rb +7 -0
  33. data/lib/pdk/module.rb +0 -1
  34. data/lib/pdk/template/fetcher/git.rb +85 -0
  35. data/lib/pdk/template/fetcher/local.rb +28 -0
  36. data/lib/pdk/template/fetcher.rb +98 -0
  37. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +116 -0
  38. data/lib/pdk/template/renderer/v1/renderer.rb +132 -0
  39. data/lib/pdk/template/renderer/v1/template_file.rb +102 -0
  40. data/lib/pdk/template/renderer/v1.rb +25 -0
  41. data/lib/pdk/template/renderer.rb +96 -0
  42. data/lib/pdk/template/template_dir.rb +67 -0
  43. data/lib/pdk/template.rb +59 -0
  44. data/lib/pdk/tests/unit.rb +5 -0
  45. data/lib/pdk/util/json_finder.rb +84 -0
  46. data/lib/pdk/util/puppet_strings.rb +3 -3
  47. data/lib/pdk/util/template_uri.rb +4 -6
  48. data/lib/pdk/util.rb +4 -35
  49. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
  50. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
  51. data/lib/pdk/validate/invokable_validator.rb +2 -3
  52. data/lib/pdk/validate/validator.rb +7 -0
  53. data/lib/pdk/validate/validator_group.rb +1 -0
  54. data/lib/pdk/validate.rb +17 -10
  55. data/lib/pdk/version.rb +1 -1
  56. data/lib/pdk.rb +1 -1
  57. data/locales/pdk.pot +356 -228
  58. metadata +33 -12
  59. data/lib/pdk/module/template_dir/base.rb +0 -268
  60. data/lib/pdk/module/template_dir/git.rb +0 -91
  61. data/lib/pdk/module/template_dir/local.rb +0 -21
  62. data/lib/pdk/module/template_dir.rb +0 -115
  63. data/lib/pdk/template_file.rb +0 -96
@@ -0,0 +1,116 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Template
5
+ module Renderer
6
+ module V1
7
+ # The old templating code in the PDK passed through a TemplateDir object. This class mimics the methods
8
+ # of that old class so that existing custom templates will still function with the newer refactor templating code.
9
+ # Methods which have no use in custom templates exist but do no nothing, for example `def render; end`
10
+ #
11
+ # @see https://raw.githubusercontent.com/puppetlabs/pdk/4ffd58062c77ad1e54d2fe16b16015f7207bcee8/lib/pdk/module/template_dir/base.rb
12
+ # :nocov: This class is tested in the packaging and acceptance testing suites
13
+ class LegacyTemplateDir
14
+ attr_accessor :module_metadata
15
+ attr_reader :uri
16
+
17
+ def initialize(context, uri, path, module_metadata = {})
18
+ @uri = uri
19
+ @module_metadata = module_metadata
20
+ @context = context
21
+ @path = path
22
+ end
23
+
24
+ def metadata; end
25
+
26
+ def render; end
27
+
28
+ def object_template_for; end
29
+
30
+ def object_config
31
+ config_for(nil)
32
+ end
33
+
34
+ # Generate a hash of data to be used when rendering the specified
35
+ # template.
36
+ #
37
+ # @param dest_path [String] The destination path of the file that the
38
+ # data is for, relative to the root of the module.
39
+ #
40
+ # @return [Hash] The data that will be available to the template via the
41
+ # `@configs` instance variable.
42
+ #
43
+ # @api private
44
+ def config_for(dest_path, sync_config_path = nil)
45
+ require 'pdk/util'
46
+ require 'pdk/analytics'
47
+
48
+ module_root = PDK::Util.module_root
49
+ sync_config_path ||= File.join(module_root, '.sync.yml') unless module_root.nil?
50
+ config_path = File.join(@path, 'config_defaults.yml')
51
+
52
+ if @config.nil?
53
+ require 'deep_merge'
54
+ conf_defaults = read_config(config_path)
55
+ @sync_config = read_config(sync_config_path) unless sync_config_path.nil?
56
+ @config = conf_defaults
57
+ @config.deep_merge!(@sync_config, knockout_prefix: '---') unless @sync_config.nil?
58
+ end
59
+ file_config = @config.fetch(:global, {})
60
+ file_config['module_metadata'] = @module_metadata
61
+ file_config.merge!(@config.fetch(dest_path, {})) unless dest_path.nil?
62
+ file_config.merge!(@config).tap do |c|
63
+ if uri.default?
64
+ file_value = if c['unmanaged']
65
+ 'unmanaged'
66
+ elsif c['delete']
67
+ 'deleted'
68
+ elsif @sync_config && @sync_config.key?(dest_path)
69
+ 'customized'
70
+ else
71
+ 'default'
72
+ end
73
+
74
+ PDK.analytics.event('TemplateDir', 'file', label: dest_path, value: file_value)
75
+ end
76
+ end
77
+ end
78
+
79
+ # Generates a hash of data from a given yaml file location.
80
+ #
81
+ # @param loc [String] The path of the yaml config file.
82
+ #
83
+ # @warn If the specified path is not a valid yaml file. Returns an empty Hash
84
+ # if so.
85
+ #
86
+ # @return [Hash] The data that has been read in from the given yaml file.
87
+ #
88
+ # @api private
89
+ def read_config(loc)
90
+ if PDK::Util::Filesystem.file?(loc) && PDK::Util::Filesystem.readable?(loc)
91
+ require 'yaml'
92
+
93
+ begin
94
+ YAML.safe_load(PDK::Util::Filesystem.read_file(loc), [], [], true)
95
+ rescue Psych::SyntaxError => e
96
+ PDK.logger.warn _("'%{file}' is not a valid YAML file: %{problem} %{context} at line %{line} column %{column}") % {
97
+ file: loc,
98
+ problem: e.problem,
99
+ context: e.context,
100
+ line: e.line,
101
+ column: e.column,
102
+ }
103
+ {}
104
+ end
105
+ else
106
+ {}
107
+ end
108
+ end
109
+
110
+ def template_path(_uri); end
111
+ end
112
+ # :nocov:
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,132 @@
1
+ require 'pdk'
2
+ require 'pdk/template/renderer'
3
+
4
+ module PDK
5
+ module Template
6
+ module Renderer
7
+ module V1
8
+ class Renderer < PDK::Template::Renderer::AbstractRenderer
9
+ # @see PDK::Template::Renderer::AbstractRenderer.render
10
+ def render(template_type, _name, options = {})
11
+ render_module(options) { |*args| yield(*args) } if template_type == PDK::Template::MODULE_TEMPLATE_TYPE
12
+ end
13
+
14
+ # @see PDK::Template::Renderer::AbstractRenderer.has_single_item?
15
+ def has_single_item?(item_path) # rubocop:disable Naming/PredicateName
16
+ PDK::Util::Filesystem.exist?(single_item_path(item_path))
17
+ end
18
+
19
+ # @see PDK::Template::Renderer::AbstractRenderer.render_single_item
20
+ def render_single_item(relative_file_path, template_data_hash)
21
+ template_file = single_item_path(relative_file_path)
22
+ return nil unless PDK::Util::Filesystem.file?(template_file) && PDK::Util::Filesystem.readable?(template_file)
23
+
24
+ PDK.logger.debug(_("Rendering '%{template}'...") % { template: template_file })
25
+ new_template_file(template_file, template_data_hash).render
26
+ end
27
+
28
+ # Returns the full path for a single item
29
+ #
30
+ # @param item_path [String] The path of the single item to render
31
+ # @return [String]
32
+ # @api private
33
+ #:nocov:
34
+ def single_item_path(item_path)
35
+ File.join(template_root, 'object_templates', item_path)
36
+ end
37
+ #:nocov:
38
+
39
+ # Helper method used during testing
40
+ #:nocov:
41
+ # @api private
42
+ def new_template_file(template_file, template_data_hash)
43
+ TemplateFile.new(template_file, template_data_hash)
44
+ end
45
+ #:nocov:
46
+
47
+ # Helper method used during testing
48
+ #:nocov:
49
+ # @api private
50
+ def new_legacy_template_dir(context, uri, path, module_metadata = {})
51
+ LegacyTemplateDir.new(context, uri, path, module_metadata)
52
+ end
53
+ #:nocov:
54
+
55
+ # Renders a new module
56
+ #
57
+ # @param options [Hash{Object => Object}] A list of options to pass through to the renderer. See PDK::Template::TemplateDir helper methods for other options
58
+ # @see #render
59
+ # @api private
60
+ #:nocov: This is tested in acceptance and packaging tests
61
+ def render_module(options = {})
62
+ require 'pdk/template/renderer/v1/template_file'
63
+
64
+ moduleroot_dir = File.join(template_root, 'moduleroot')
65
+ moduleroot_init = File.join(template_root, 'moduleroot_init')
66
+
67
+ dirs = [moduleroot_dir]
68
+ dirs << moduleroot_init if options[:include_first_time]
69
+
70
+ legacy_template_dir = new_legacy_template_dir(context, template_uri, template_root, options[:module_metadata] || {})
71
+
72
+ files_in_template(dirs).each do |template_file, template_loc|
73
+ template_file = template_file.to_s
74
+ PDK.logger.debug(_("Rendering '%{template}'...") % { template: template_file })
75
+ dest_path = template_file.sub(%r{\.erb\Z}, '')
76
+ config = legacy_template_dir.config_for(dest_path)
77
+
78
+ dest_status = if template_loc.start_with?(moduleroot_init)
79
+ :init
80
+ else
81
+ :manage
82
+ end
83
+
84
+ if config['unmanaged']
85
+ dest_status = :unmanage
86
+ elsif config['delete']
87
+ dest_status = :delete
88
+ else
89
+ begin
90
+ dest_content = new_template_file(File.join(template_loc, template_file), configs: config, template_dir: legacy_template_dir).render
91
+ rescue => error
92
+ error_msg = _(
93
+ "Failed to render template '%{template}'\n" \
94
+ '%{exception}: %{message}',
95
+ ) % { template: template_file, exception: error.class, message: error.message }
96
+ raise PDK::CLI::FatalError, error_msg
97
+ end
98
+ end
99
+
100
+ yield dest_path, dest_content, dest_status
101
+ end
102
+ end
103
+ #:nocov:
104
+
105
+ # Returns all files in the given template directories
106
+ #
107
+ # @param dirs [Array[String]] Directories to search in
108
+ # @param glob_suffix [Array[String]] File glob to use when searching for files. Defaults to ['**', '*']
109
+ #
110
+ # @return [Hash{String => String}] Key is the template file relative path and the value is the absolute path to the template directory
111
+ # @api private
112
+ def files_in_template(dirs, glob_suffix = ['**', '*'])
113
+ temp_paths = []
114
+ dirlocs = []
115
+ dirs.each do |dir|
116
+ raise ArgumentError, _("The directory '%{dir}' doesn't exist") % { dir: dir } unless PDK::Util::Filesystem.directory?(dir)
117
+ temp_paths += PDK::Util::Filesystem.glob(File.join(dir, *glob_suffix), File::FNM_DOTMATCH).select do |template_path|
118
+ if PDK::Util::Filesystem.file?(template_path) && !PDK::Util::Filesystem.symlink?(template_path)
119
+ dirlocs << dir
120
+ end
121
+ end
122
+ temp_paths.map do |template_path|
123
+ template_path.sub!(%r{\A#{Regexp.escape(dir)}#{Regexp.escape(File::SEPARATOR)}}, '')
124
+ end
125
+ end
126
+ Hash[temp_paths.zip dirlocs]
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,102 @@
1
+ require 'pdk'
2
+ require 'ostruct'
3
+
4
+ module PDK
5
+ module Template
6
+ module Renderer
7
+ module V1
8
+ class TemplateFile < OpenStruct
9
+ # Initialises the TemplateFile object with the path to the template file
10
+ # and the data to be used when rendering the template.
11
+ #
12
+ # @param template_file [String] The path on disk to the template file.
13
+ # @param data [Hash{Symbol => Object}] The data that should be provided to
14
+ # the template when rendering.
15
+ # @option data [Object] :configs The value of this key will be provided to
16
+ # the template as an instance variable `@configs` in order to maintain
17
+ # compatibility with modulesync.
18
+ #
19
+ # @api public
20
+ def initialize(template_file, data = {})
21
+ @template_file = template_file
22
+
23
+ if data.key?(:configs)
24
+ @configs = data[:configs]
25
+ end
26
+
27
+ super(data)
28
+ end
29
+
30
+ # Renders the template by calling the appropriate engine based on the file
31
+ # extension.
32
+ #
33
+ # If the template has an `.erb` extension, the content of the template
34
+ # file will be treated as an ERB template. All other extensions are treated
35
+ # as plain text.
36
+ #
37
+ # @return [String] The rendered template
38
+ #
39
+ # @raise (see #template_content)
40
+ #
41
+ # @api public
42
+ def render
43
+ case File.extname(@template_file)
44
+ when '.erb'
45
+ render_erb
46
+ else
47
+ render_plain
48
+ end
49
+ end
50
+
51
+ def config_for(path)
52
+ return unless respond_to?(:template_dir)
53
+
54
+ template_dir.config_for(path)
55
+ end
56
+
57
+ private
58
+
59
+ # Reads the content of the template file into memory.
60
+ #
61
+ # @return [String] The content of the template file.
62
+ #
63
+ # @raise [ArgumentError] If the template file does not exist or can not be
64
+ # read.
65
+ #
66
+ # @api private
67
+ def template_content
68
+ if PDK::Util::Filesystem.file?(@template_file) && PDK::Util::Filesystem.readable?(@template_file)
69
+ return PDK::Util::Filesystem.read_file(@template_file)
70
+ end
71
+
72
+ raise ArgumentError, _("'%{template}' is not a readable file") % { template: @template_file }
73
+ end
74
+
75
+ # Renders the content of the template file as an ERB template.
76
+ #
77
+ # @return [String] The rendered template.
78
+ #
79
+ # @raise (see #template_content)
80
+ #
81
+ # @api private
82
+ def render_erb
83
+ renderer = ERB.new(template_content, nil, '-')
84
+ renderer.filename = @template_file
85
+ renderer.result(binding)
86
+ end
87
+
88
+ # Renders the content of the template file as plain text.
89
+ #
90
+ # @return [String] The rendered template.
91
+ #
92
+ # @raise (see #template_content)
93
+ #
94
+ # @api private
95
+ def render_plain
96
+ template_content
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,25 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Template
5
+ module Renderer
6
+ module V1
7
+ autoload :LegacyTemplateDir, 'pdk/template/renderer/v1/legacy_template_dir'
8
+ autoload :Renderer, 'pdk/template/renderer/v1/renderer'
9
+ autoload :TemplateFile, 'pdk/template/renderer/v1/template_file'
10
+
11
+ # Whether the template directory and context are valid for the V1 renderer
12
+ # @see PDK::Template::Renderer.instance
13
+ def self.compatible?(template_root, _context)
14
+ %w[moduleroot moduleroot_init].all? { |dir| PDK::Util::Filesystem.directory?(File.join(template_root, dir)) }
15
+ end
16
+
17
+ # Creates an instance of the V1 Renderer
18
+ # @see PDK::Template::Renderer.instance
19
+ def self.instance(template_root, template_uri, context)
20
+ PDK::Template::Renderer::V1::Renderer.new(template_root, template_uri, context)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,96 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Template
5
+ module Renderer
6
+ autoload :V1, 'pdk/template/renderer/v1'
7
+
8
+ # Returns the most appropriate renderer for the given Template Directory and Context
9
+ #
10
+ # @param template_root [String] The path to where the template exists on disk
11
+ # @param template_uri [PDK::Util::TemplateUri] A URI which points to the source location of the Template
12
+ # @param context [PDK::Context] The context in which the redering will occur in
13
+ #
14
+ # @return [AbstractRenderer, nil] An instance of an AbstractRenderer subclass. Returns nil if no renderer could be found
15
+ def self.instance(template_uri, template_root, context)
16
+ return V1.instance(template_root, template_uri, context) if V1.compatible?(template_root, context)
17
+ nil
18
+ end
19
+
20
+ # An abstract class which all Template Renderers should subclass and implement. This class is responsible for
21
+ # rendering a template or a single item within a template directory
22
+ #
23
+ # To implement a new renderer:
24
+ # 1. Create a new class which subclasses AbstractRenderer and implements the public methods (has_single_item?, render and render_single_item)
25
+ # 2. Add class methods .compatible? and .instance which are used to detect if a template is compatible with the new renderer
26
+ # and create an instance of the new renderer respectively
27
+ # 3. Update the PDK::Template::Renderer.instance method to detect and create an instance of the new renderer (using the .compatible? and .instance methods
28
+ # created in step 2).
29
+ #
30
+ # See the PDK::Template::Renderer::V1 module and classes for an example on how to to this.
31
+ #
32
+ # @api private
33
+ # @abstract
34
+ class AbstractRenderer
35
+ # @return [String] The path to where the template exists on disk
36
+ attr_reader :template_root
37
+
38
+ # @return [PDK::Util::TemplateURI] The URI which points to the source location of the Template
39
+ attr_reader :template_uri
40
+
41
+ # @return context [PDK::Context] The context in which the redering will occur in
42
+ attr_reader :context
43
+
44
+ # @param template_root [String] The path to where the template exists on disk
45
+ # @param template_uri [PDK::Util::TemplateUri] A URI which points to the source location of the Template
46
+ # @param context [PDK::Context] The context in which the redering will occur in
47
+ def initialize(template_root, template_uri, context)
48
+ @template_root = template_root
49
+ @template_uri = template_uri
50
+ @context = context
51
+ end
52
+
53
+ # Whether the renderer supports rendering the a single item called 'item_path'. This is used when rendering things like a new Task or a new Puppet Classes.
54
+ # Rendering a single item is different than redering an entire project, like a entire Puppet Module or Control Repo.
55
+ #
56
+ # @param item_path [String] The path to the item to check
57
+ #
58
+ # @return [Boolean] Whether the renderer can render the item
59
+ # @abstract
60
+ def has_single_item?(_item_path) # rubocop:disable Naming/PredicateName Changing the method name to `single_item?` will convey the wrong intent
61
+ false
62
+ end
63
+
64
+ # Loop through the files in the template type, yielding each rendered file to the supplied block.
65
+ #
66
+ # @param template_type [PDK::Template::*_TEMPLATE_TYPE] The type of template to render
67
+ # @param name [String] The name to use in the rendering process
68
+ # @param options [Hash{Object => Object}] A list of options to pass through to the renderer. See PDK::Template::TemplateDir helper methods for other options
69
+ # @option options [Boolean] :include_first_time Whether to include "first time" items when rendering the project. While it is up to the renderer to implement this
70
+ # the expected behavior is that if the item already exists, it will not be rendererd again. Unlike normal items which
71
+ # are always rendered to keep them in-sync
72
+ #
73
+ # @yieldparam dest_path [String] The path of the destination file, relative to the root of the context.
74
+ # @yieldparam dest_content [String] The rendered content of the destination file.
75
+ # @yieldparam dest_status [Symbol] :unmanage, :delete, :init, :manage
76
+ #
77
+ # @see PDK::Template::TemplateDir.render
78
+ #
79
+ # @return [void]
80
+ # @abstract
81
+ def render(template_type, name, options = {}); end
82
+
83
+ # Render a single item and return the resulting string. This is used when rendering things like a new Task or a new Puppet Classes.
84
+ # Rendering a single item is different than redering an entire project, like a entire Puppet Module or Control Repo. This method is
85
+ # used in conjunction with .has_single_item?
86
+ #
87
+ # @param item_path [String] The path of the single item to render
88
+ # @param template_data_hash [Hash{Object => Object}] A hash of information which will be used in the rendering process
89
+ #
90
+ # @return [String, Nil] The rendered content, or nil of the file could not be rendered
91
+ # @abstract
92
+ def render_single_item(item_path, template_data_hash = {}); end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,67 @@
1
+ require 'pdk'
2
+ require 'forwardable'
3
+
4
+ module PDK
5
+ module Template
6
+ # A helper class representing an already fetched template on disk, with an appropriate renderer instance.
7
+ # @see PDK::Template.with
8
+ class TemplateDir
9
+ # Creates an instance of TemplateDir object
10
+ # @see TemplateDir.new
11
+ def self.instance(uri, path, context, renderer = nil)
12
+ new(uri, path, context, renderer)
13
+ end
14
+
15
+ extend Forwardable
16
+
17
+ # Helper methods for rendering
18
+ def_delegators :@renderer, :render, :render_single_item, :has_single_item?
19
+
20
+ # @return [PDK::Util::TemplateURI] The URI which points to the source location of the Template
21
+ attr_accessor :uri
22
+
23
+ # @return [String] The path to where the template exists on disk
24
+ attr_accessor :path
25
+
26
+ # @return [Hash{String => String}] A hash of information about the template
27
+ attr_accessor :metadata
28
+
29
+ # @param template_uri [PDK::Util::TemplateUri] A URI which points to the source location of the Template
30
+ # @param path [String] The path to where the template exists on disk
31
+ # @param context [PDK::Context] The context in which the redering will occur in
32
+ # @param renderer [PDK::Template::Renderer::AbstractRenderer] The an instance of a rendering class. If nil, a renderer will be created that's appropriate for the template and context
33
+ def initialize(uri, path, context, renderer = nil)
34
+ @uri = uri
35
+ @path = path
36
+ @metadata = {}
37
+
38
+ @renderer = renderer.nil? ? Renderer.instance(uri, path, context) : renderer
39
+ raise _('Could not find a compatible template renderer for %{path}') % { path: path } if @renderer.nil?
40
+ end
41
+
42
+ # Later additions may include Control Repo rendering, for example
43
+ #
44
+ # def render_control_repo(name, options = {})
45
+ # render(CONTROL_REPO_TEMPLATE_TYPE, name, options.merge(include_first_time: false)) { |*args| yield(*args) }
46
+ # end
47
+ #
48
+ # def render_new_control_repo(name, repo_metadata = {}, options = {})
49
+ # render(CONTROL_REPO_TEMPLATE_TYPE, name, options.merge(include_first_time: true, control_repo_metadata: repo_metadata)) { |*args| yield(*args) }
50
+ # end
51
+ #:nocov: These are just helper methods and are tested elsewhere.
52
+
53
+ # Render an existing module
54
+ # @see PDK::Template::Renderer::AbstractRenderer.render
55
+ def render_module(module_name, options = {})
56
+ @renderer.render(MODULE_TEMPLATE_TYPE, module_name, options.merge(include_first_time: false)) { |*args| yield(*args) }
57
+ end
58
+
59
+ # Render a new module
60
+ # @see PDK::Template::Renderer::AbstractRenderer.render
61
+ def render_new_module(module_name, module_metadata = {}, options = {})
62
+ @renderer.render(MODULE_TEMPLATE_TYPE, module_name, options.merge(include_first_time: true, module_metadata: module_metadata)) { |*args| yield(*args) }
63
+ end
64
+ #:nocov:
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,59 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Template
5
+ autoload :Fetcher, 'pdk/template/fetcher'
6
+ autoload :Renderer, 'pdk/template/renderer'
7
+ autoload :TemplateDir, 'pdk/template/template_dir'
8
+
9
+ MODULE_TEMPLATE_TYPE = :module_template
10
+
11
+ # Creates a TemplateDir object with the path or URL to the template
12
+ # and the block of code to run to be run while the template is available.
13
+ #
14
+ # The template directory is only guaranteed to be available on disk
15
+ # within the scope of the block passed to this method.
16
+ #
17
+ # @param uri [PDK::Util::TemplateURI] The path to a directory to use as the
18
+ # template or a URI to a git repository.
19
+ #
20
+ # @param context [PDK::Context::AbstractContext] The context in which the template will render to
21
+ #
22
+ # @yieldparam self [PDK::Template::TemplateDir] The initialised object with
23
+ # the template available on disk.
24
+ #
25
+ # @example Using a git repository as a template
26
+ # PDK::Template.with('https://github.com/puppetlabs/pdk-templates') do |t|
27
+ # t.render_module('module, PDK.context) do |filename, content, status|
28
+ # File.open(filename, 'w') do |file|
29
+ # ...
30
+ # end
31
+ # end
32
+ # end
33
+ #
34
+ # @raise [ArgumentError] If no block is given to this method.
35
+ # @raise [PDK::CLI::FatalError]
36
+ # @raise [ArgumentError]
37
+ #
38
+ # @api public
39
+ def self.with(uri, context)
40
+ unless block_given?
41
+ raise ArgumentError, _('%{class_name}.with must be passed a block.') % { class_name: name }
42
+ end
43
+ unless uri.is_a? PDK::Util::TemplateURI
44
+ raise ArgumentError, _('%{class_name}.with must be passed a PDK::Util::TemplateURI, got a %{uri_type}') % { uri_type: uri.class, class_name: name }
45
+ end
46
+
47
+ Fetcher.with(uri) do |fetcher|
48
+ template_dir = TemplateDir.instance(uri, fetcher.path, context)
49
+ template_dir.metadata = fetcher.metadata
50
+
51
+ template_type = uri.default? ? 'default' : 'custom'
52
+ PDK.analytics.event('TemplateDir', 'initialize', label: template_type)
53
+
54
+ yield template_dir
55
+ end
56
+ nil
57
+ end
58
+ end
59
+ end
@@ -89,6 +89,11 @@ module PDK
89
89
  setup
90
90
 
91
91
  tests = options[:tests]
92
+ # Due to how rake handles paths in the command line options, any backslashed path (Windows platforms) needs to be converted
93
+ # to forward slash. We can't use File.expand_path as the files aren't guaranteed to be on-disk
94
+ #
95
+ # Ref - https://github.com/puppetlabs/pdk/issues/828
96
+ tests.tr!('\\', '/') unless tests.nil?
92
97
 
93
98
  environment = { 'CI_SPEC_OPTIONS' => '--format j' }
94
99
  environment['PUPPET_GEM_VERSION'] = options[:puppet] if options[:puppet]