pdk 1.9.0 → 3.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 (163) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +744 -711
  3. data/README.md +23 -21
  4. data/lib/pdk/answer_file.rb +3 -112
  5. data/lib/pdk/bolt.rb +20 -0
  6. data/lib/pdk/cli/build.rb +51 -54
  7. data/lib/pdk/cli/bundle.rb +33 -29
  8. data/lib/pdk/cli/console.rb +148 -0
  9. data/lib/pdk/cli/convert.rb +46 -37
  10. data/lib/pdk/cli/env.rb +51 -0
  11. data/lib/pdk/cli/errors.rb +4 -3
  12. data/lib/pdk/cli/exec/command.rb +285 -0
  13. data/lib/pdk/cli/exec/interactive_command.rb +109 -0
  14. data/lib/pdk/cli/exec.rb +32 -201
  15. data/lib/pdk/cli/exec_group.rb +79 -43
  16. data/lib/pdk/cli/get/config.rb +26 -0
  17. data/lib/pdk/cli/get.rb +22 -0
  18. data/lib/pdk/cli/new/class.rb +20 -22
  19. data/lib/pdk/cli/new/defined_type.rb +21 -21
  20. data/lib/pdk/cli/new/fact.rb +27 -0
  21. data/lib/pdk/cli/new/function.rb +27 -0
  22. data/lib/pdk/cli/new/module.rb +40 -29
  23. data/lib/pdk/cli/new/provider.rb +18 -18
  24. data/lib/pdk/cli/new/task.rb +23 -22
  25. data/lib/pdk/cli/new/test.rb +52 -0
  26. data/lib/pdk/cli/new/transport.rb +27 -0
  27. data/lib/pdk/cli/new.rb +15 -9
  28. data/lib/pdk/cli/release/prep.rb +39 -0
  29. data/lib/pdk/cli/release/publish.rb +46 -0
  30. data/lib/pdk/cli/release.rb +185 -0
  31. data/lib/pdk/cli/remove/config.rb +83 -0
  32. data/lib/pdk/cli/remove.rb +22 -0
  33. data/lib/pdk/cli/set/config.rb +121 -0
  34. data/lib/pdk/cli/set.rb +22 -0
  35. data/lib/pdk/cli/test/unit.rb +71 -69
  36. data/lib/pdk/cli/test.rb +9 -8
  37. data/lib/pdk/cli/update.rb +38 -21
  38. data/lib/pdk/cli/util/command_redirector.rb +13 -3
  39. data/lib/pdk/cli/util/interview.rb +25 -9
  40. data/lib/pdk/cli/util/option_normalizer.rb +6 -6
  41. data/lib/pdk/cli/util/option_validator.rb +19 -9
  42. data/lib/pdk/cli/util/spinner.rb +13 -0
  43. data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
  44. data/lib/pdk/cli/util.rb +105 -48
  45. data/lib/pdk/cli/validate.rb +96 -111
  46. data/lib/pdk/cli.rb +134 -87
  47. data/lib/pdk/config/errors.rb +5 -0
  48. data/lib/pdk/config/ini_file.rb +184 -0
  49. data/lib/pdk/config/ini_file_setting.rb +35 -0
  50. data/lib/pdk/config/json.rb +35 -0
  51. data/lib/pdk/config/json_schema_namespace.rb +137 -0
  52. data/lib/pdk/config/json_schema_setting.rb +51 -0
  53. data/lib/pdk/config/json_with_schema.rb +47 -0
  54. data/lib/pdk/config/namespace.rb +362 -0
  55. data/lib/pdk/config/setting.rb +134 -0
  56. data/lib/pdk/config/task_schema.json +116 -0
  57. data/lib/pdk/config/validator.rb +31 -0
  58. data/lib/pdk/config/yaml.rb +41 -0
  59. data/lib/pdk/config/yaml_with_schema.rb +51 -0
  60. data/lib/pdk/config.rb +304 -0
  61. data/lib/pdk/context/control_repo.rb +61 -0
  62. data/lib/pdk/context/module.rb +28 -0
  63. data/lib/pdk/context/none.rb +22 -0
  64. data/lib/pdk/context.rb +98 -0
  65. data/lib/pdk/control_repo.rb +89 -0
  66. data/lib/pdk/generate/defined_type.rb +27 -33
  67. data/lib/pdk/generate/fact.rb +26 -0
  68. data/lib/pdk/generate/function.rb +49 -0
  69. data/lib/pdk/generate/module.rb +160 -153
  70. data/lib/pdk/generate/provider.rb +16 -69
  71. data/lib/pdk/generate/puppet_class.rb +27 -32
  72. data/lib/pdk/generate/puppet_object.rb +100 -159
  73. data/lib/pdk/generate/task.rb +34 -51
  74. data/lib/pdk/generate/transport.rb +34 -0
  75. data/lib/pdk/generate.rb +21 -8
  76. data/lib/pdk/logger.rb +24 -6
  77. data/lib/pdk/module/build.rb +125 -37
  78. data/lib/pdk/module/convert.rb +146 -65
  79. data/lib/pdk/module/metadata.rb +72 -71
  80. data/lib/pdk/module/release.rb +255 -0
  81. data/lib/pdk/module/update.rb +48 -37
  82. data/lib/pdk/module/update_manager.rb +75 -39
  83. data/lib/pdk/module.rb +10 -2
  84. data/lib/pdk/monkey_patches.rb +268 -0
  85. data/lib/pdk/report/event.rb +36 -48
  86. data/lib/pdk/report.rb +35 -22
  87. data/lib/pdk/template/fetcher/git.rb +84 -0
  88. data/lib/pdk/template/fetcher/local.rb +29 -0
  89. data/lib/pdk/template/fetcher.rb +100 -0
  90. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +108 -0
  91. data/lib/pdk/template/renderer/v1/renderer.rb +131 -0
  92. data/lib/pdk/template/renderer/v1/template_file.rb +100 -0
  93. data/lib/pdk/template/renderer/v1.rb +25 -0
  94. data/lib/pdk/template/renderer.rb +97 -0
  95. data/lib/pdk/template/template_dir.rb +67 -0
  96. data/lib/pdk/template.rb +52 -0
  97. data/lib/pdk/tests/unit.rb +101 -51
  98. data/lib/pdk/util/bundler.rb +44 -42
  99. data/lib/pdk/util/changelog_generator.rb +138 -0
  100. data/lib/pdk/util/env.rb +48 -0
  101. data/lib/pdk/util/filesystem.rb +139 -2
  102. data/lib/pdk/util/git.rb +108 -8
  103. data/lib/pdk/util/json_finder.rb +86 -0
  104. data/lib/pdk/util/puppet_strings.rb +125 -0
  105. data/lib/pdk/util/puppet_version.rb +71 -87
  106. data/lib/pdk/util/ruby_version.rb +49 -25
  107. data/lib/pdk/util/template_uri.rb +283 -0
  108. data/lib/pdk/util/vendored_file.rb +34 -42
  109. data/lib/pdk/util/version.rb +11 -10
  110. data/lib/pdk/util/windows/api_types.rb +74 -44
  111. data/lib/pdk/util/windows/file.rb +31 -27
  112. data/lib/pdk/util/windows/process.rb +74 -0
  113. data/lib/pdk/util/windows/string.rb +19 -12
  114. data/lib/pdk/util/windows.rb +2 -0
  115. data/lib/pdk/util.rb +111 -124
  116. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
  117. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
  118. data/lib/pdk/validate/external_command_validator.rb +213 -0
  119. data/lib/pdk/validate/internal_ruby_validator.rb +101 -0
  120. data/lib/pdk/validate/invokable_validator.rb +238 -0
  121. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +84 -0
  122. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +76 -0
  123. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
  124. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +131 -0
  125. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
  126. data/lib/pdk/validate/puppet/puppet_plan_syntax_validator.rb +38 -0
  127. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +135 -0
  128. data/lib/pdk/validate/puppet/puppet_validator_group.rb +22 -0
  129. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +79 -0
  130. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
  131. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +83 -0
  132. data/lib/pdk/validate/tasks/tasks_name_validator.rb +45 -0
  133. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
  134. data/lib/pdk/validate/validator.rb +120 -0
  135. data/lib/pdk/validate/validator_group.rb +107 -0
  136. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +86 -0
  137. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
  138. data/lib/pdk/validate.rb +86 -12
  139. data/lib/pdk/version.rb +2 -2
  140. data/lib/pdk.rb +60 -10
  141. metadata +138 -100
  142. data/lib/pdk/cli/module/build.rb +0 -14
  143. data/lib/pdk/cli/module/generate.rb +0 -45
  144. data/lib/pdk/cli/module.rb +0 -14
  145. data/lib/pdk/i18n.rb +0 -4
  146. data/lib/pdk/module/templatedir.rb +0 -321
  147. data/lib/pdk/template_file.rb +0 -95
  148. data/lib/pdk/validate/base_validator.rb +0 -215
  149. data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -86
  150. data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -109
  151. data/lib/pdk/validate/metadata_validator.rb +0 -30
  152. data/lib/pdk/validate/puppet/puppet_lint.rb +0 -67
  153. data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -112
  154. data/lib/pdk/validate/puppet_validator.rb +0 -30
  155. data/lib/pdk/validate/ruby/rubocop.rb +0 -77
  156. data/lib/pdk/validate/ruby_validator.rb +0 -29
  157. data/lib/pdk/validate/tasks/metadata_lint.rb +0 -126
  158. data/lib/pdk/validate/tasks/name.rb +0 -88
  159. data/lib/pdk/validate/tasks_validator.rb +0 -33
  160. data/lib/pdk/validate/yaml/syntax.rb +0 -109
  161. data/lib/pdk/validate/yaml_validator.rb +0 -31
  162. data/locales/config.yaml +0 -21
  163. data/locales/pdk.pot +0 -1291
@@ -0,0 +1,131 @@
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(format("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(format("Rendering '%{template}'...", template: template_file))
75
+ dest_path = template_file.sub(/\.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 StandardError => e
92
+ error_msg = format("Failed to render template '%{template}'\n" \
93
+ '%{exception}: %{message}', template: template_file, exception: e.class, message: e.message)
94
+ raise PDK::CLI::FatalError, error_msg
95
+ end
96
+ end
97
+
98
+ dest_executable = config['manage_execute_permissions'] && PDK::Util::Filesystem.executable?(File.join(template_loc, template_file))
99
+
100
+ yield dest_path, dest_content, dest_status, dest_executable
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, format("The directory '%{dir}' doesn't exist", dir: dir) unless PDK::Util::Filesystem.directory?(dir)
117
+
118
+ temp_paths += PDK::Util::Filesystem.glob(File.join(dir, *glob_suffix), File::FNM_DOTMATCH).select do |template_path|
119
+ dirlocs << dir if PDK::Util::Filesystem.file?(template_path) && !PDK::Util::Filesystem.symlink?(template_path)
120
+ end
121
+ temp_paths.map do |template_path|
122
+ template_path.sub!(/\A#{Regexp.escape(dir)}#{Regexp.escape(File::SEPARATOR)}/, '')
123
+ end
124
+ end
125
+ (temp_paths.zip dirlocs).to_h
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,100 @@
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
+ @configs = data[:configs] if data.key?(:configs)
24
+
25
+ super(data)
26
+ end
27
+
28
+ # Renders the template by calling the appropriate engine based on the file
29
+ # extension.
30
+ #
31
+ # If the template has an `.erb` extension, the content of the template
32
+ # file will be treated as an ERB template. All other extensions are treated
33
+ # as plain text.
34
+ #
35
+ # @return [String] The rendered template
36
+ #
37
+ # @raise (see #template_content)
38
+ #
39
+ # @api public
40
+ def render
41
+ case File.extname(@template_file)
42
+ when '.erb'
43
+ render_erb
44
+ else
45
+ render_plain
46
+ end
47
+ end
48
+
49
+ def config_for(path)
50
+ return unless respond_to?(:template_dir)
51
+
52
+ template_dir.config_for(path)
53
+ end
54
+
55
+ private
56
+
57
+ # Reads the content of the template file into memory.
58
+ #
59
+ # @return [String] The content of the template file.
60
+ #
61
+ # @raise [ArgumentError] If the template file does not exist or can not be
62
+ # read.
63
+ #
64
+ # @api private
65
+ def template_content
66
+ return PDK::Util::Filesystem.read_file(@template_file) if PDK::Util::Filesystem.file?(@template_file) && PDK::Util::Filesystem.readable?(@template_file)
67
+
68
+ raise ArgumentError, format("'%{template}' is not a readable file", template: @template_file)
69
+ end
70
+
71
+ # Renders the content of the template file as an ERB template.
72
+ #
73
+ # @return [String] The rendered template.
74
+ #
75
+ # @raise (see #template_content)
76
+ #
77
+ # @api private
78
+ def render_erb
79
+ require 'erb'
80
+
81
+ renderer = ERB.new(template_content, trim_mode: '-')
82
+ renderer.filename = @template_file
83
+ renderer.result(binding)
84
+ end
85
+
86
+ # Renders the content of the template file as plain text.
87
+ #
88
+ # @return [String] The rendered template.
89
+ #
90
+ # @raise (see #template_content)
91
+ #
92
+ # @api private
93
+ def render_plain
94
+ template_content
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ 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
+ ['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,97 @@
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
+
18
+ nil
19
+ end
20
+
21
+ # An abstract class which all Template Renderers should subclass and implement. This class is responsible for
22
+ # rendering a template or a single item within a template directory
23
+ #
24
+ # To implement a new renderer:
25
+ # 1. Create a new class which subclasses AbstractRenderer and implements the public methods (has_single_item?, render and render_single_item)
26
+ # 2. Add class methods .compatible? and .instance which are used to detect if a template is compatible with the new renderer
27
+ # and create an instance of the new renderer respectively
28
+ # 3. Update the PDK::Template::Renderer.instance method to detect and create an instance of the new renderer (using the .compatible? and .instance methods
29
+ # created in step 2).
30
+ #
31
+ # See the PDK::Template::Renderer::V1 module and classes for an example on how to to this.
32
+ #
33
+ # @api private
34
+ # @abstract
35
+ class AbstractRenderer
36
+ # @return [String] The path to where the template exists on disk
37
+ attr_reader :template_root
38
+
39
+ # @return [PDK::Util::TemplateURI] The URI which points to the source location of the Template
40
+ attr_reader :template_uri
41
+
42
+ # @return context [PDK::Context] The context in which the redering will occur in
43
+ attr_reader :context
44
+
45
+ # @param template_root [String] The path to where the template exists on disk
46
+ # @param template_uri [PDK::Util::TemplateUri] A URI which points to the source location of the Template
47
+ # @param context [PDK::Context] The context in which the redering will occur in
48
+ def initialize(template_root, template_uri, context)
49
+ @template_root = template_root
50
+ @template_uri = template_uri
51
+ @context = context
52
+ end
53
+
54
+ # 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.
55
+ # Rendering a single item is different than redering an entire project, like a entire Puppet Module or Control Repo.
56
+ #
57
+ # @param item_path [String] The path to the item to check
58
+ #
59
+ # @return [Boolean] Whether the renderer can render the item
60
+ # @abstract
61
+ def has_single_item?(_item_path) # rubocop:disable Naming/PredicateName Changing the method name to `single_item?` will convey the wrong intent
62
+ false
63
+ end
64
+
65
+ # Loop through the files in the template type, yielding each rendered file to the supplied block.
66
+ #
67
+ # @param template_type [PDK::Template::*_TEMPLATE_TYPE] The type of template to render
68
+ # @param name [String] The name to use in the rendering process
69
+ # @param options [Hash{Object => Object}] A list of options to pass through to the renderer. See PDK::Template::TemplateDir helper methods for other options
70
+ # @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
71
+ # the expected behavior is that if the item already exists, it will not be rendererd again. Unlike normal items which
72
+ # are always rendered to keep them in-sync
73
+ #
74
+ # @yieldparam dest_path [String] The path of the destination file, relative to the root of the context.
75
+ # @yieldparam dest_content [String] The rendered content of the destination file.
76
+ # @yieldparam dest_status [Symbol] :unmanage, :delete, :init, :manage
77
+ #
78
+ # @see PDK::Template::TemplateDir.render
79
+ #
80
+ # @return [void]
81
+ # @abstract
82
+ def render(template_type, name, options = {}); end
83
+
84
+ # Render a single item and return the resulting string. This is used when rendering things like a new Task or a new Puppet Classes.
85
+ # Rendering a single item is different than redering an entire project, like a entire Puppet Module or Control Repo. This method is
86
+ # used in conjunction with .has_single_item?
87
+ #
88
+ # @param item_path [String] The path of the single item to render
89
+ # @param template_data_hash [Hash{Object => Object}] A hash of information which will be used in the rendering process
90
+ #
91
+ # @return [String, Nil] The rendered content, or nil of the file could not be rendered
92
+ # @abstract
93
+ def render_single_item(item_path, template_data_hash = {}); end
94
+ end
95
+ end
96
+ end
97
+ 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 format('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,52 @@
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
+ raise ArgumentError, format('%{class_name}.with must be passed a block.', class_name: name) unless block_given?
41
+ raise ArgumentError, format('%{class_name}.with must be passed a PDK::Util::TemplateURI, got a %{uri_type}', uri_type: uri.class, class_name: name) unless uri.is_a? PDK::Util::TemplateURI
42
+
43
+ Fetcher.with(uri) do |fetcher|
44
+ template_dir = TemplateDir.instance(uri, fetcher.path, context)
45
+ template_dir.metadata = fetcher.metadata
46
+
47
+ yield template_dir
48
+ end
49
+ nil
50
+ end
51
+ end
52
+ end