pdk 1.9.0 → 3.2.0

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