Class: PDK::Module::TemplateDir
- Inherits:
-
Object
- Object
- PDK::Module::TemplateDir
- Defined in:
- lib/pdk/module/templatedir.rb
Instance Attribute Summary collapse
-
#module_metadata ⇒ Object
Returns the value of attribute module_metadata.
-
#uri ⇒ Object
readonly
Returns the value of attribute uri.
Class Method Summary collapse
-
.files_in_template(dirs) ⇒ Hash{String=>String}
Get a list of template files in the template directory.
Instance Method Summary collapse
- #cache_template_ref(path, ref = nil) ⇒ Object
- #checkout_template_ref(path, ref) ⇒ Object private
-
#clone_template_repo(uri) ⇒ String
private
Path to working directory into which template repo has been cloned and reset.
-
#config_for(dest_path, sync_config_path = nil) ⇒ Hash
private
Generate a hash of data to be used when rendering the specified template.
-
#initialize(uri, module_metadata = {}, init = false) {|self| ... } ⇒ TemplateDir
constructor
Initialises the TemplateDir object with the path or URL to the template and the block of code to run to be run while the template is available.
-
#metadata ⇒ Hash{String => String}
Retrieve identifying metadata for the template.
-
#object_config ⇒ Hash
private
Generate a hash of data to be used when rendering object templates.
-
#object_template_for(object_type) ⇒ Hash{Symbol => String}
Searches the template directory for template files that can be used to render files for the specified object type.
-
#read_config(loc) ⇒ Hash
private
Generates a hash of data from a given yaml file location.
-
#render {|dest_path, dest_content| ... } ⇒ void
Loop through the files in the template, yielding each rendered file to the supplied block.
-
#validate_module_template! ⇒ void
private
Validate the content of the template directory.
Constructor Details
#initialize(uri, module_metadata = {}, init = false) {|self| ... } ⇒ TemplateDir
Initialises the TemplateDir object with the path or URL to the template and the block of code to run to be run while the template is available.
The template directory is only guaranteed to be available on disk within the scope of the block passed to this method.
template or a URI to a git repository. Defaults to an empty Hash. the template available on disk.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/pdk/module/templatedir.rb', line 36 def initialize(uri, = {}, init = false) require 'pdk/analytics' require 'pdk/util/template_uri' require 'pdk/util/git' unless block_given? raise ArgumentError, _('%{class_name} must be initialized with a block.') % { class_name: self.class.name } end unless uri.is_a? PDK::Util::TemplateURI raise ArgumentError, _('PDK::Module::TemplateDir.new must be initialized with a PDK::Util::TemplateURI, got a %{uri_type}') % { uri_type: uri.class } end if PDK::Util::Git.repo?(uri.git_remote) # This is either a bare local repo or a remote. either way it needs cloning. @path = clone_template_repo(uri) temp_dir_clone = true else # if it is a local path & non-bare repo then we can use it directly. # Still have to check the branch. @path = uri.shell_path # We don't do a checkout of local-path repos. There are lots of edge # cases or user un-expectations. if PDK::Util::Git.work_tree?(@path) PDK.logger.warn _("Repository '%{repo}' has a work-tree; skipping git reset.") % { repo: @path, } end end @uri = uri @init = init @moduleroot_dir = File.join(@path, 'moduleroot') @moduleroot_init = File.join(@path, 'moduleroot_init') @dirs = [@moduleroot_dir] @dirs << @moduleroot_init if @init @object_dir = File.join(@path, 'object_templates') validate_module_template! @module_metadata = template_type = uri.default? ? 'default' : 'custom' PDK.analytics.event('TemplateDir', 'initialize', label: template_type) yield self ensure # If we cloned a git repo to get the template, remove the clone once # we're done with it. if temp_dir_clone require 'fileutils' FileUtils.remove_dir(@path) end end |
Instance Attribute Details
#module_metadata ⇒ Object
Returns the value of attribute module_metadata.
6 7 8 |
# File 'lib/pdk/module/templatedir.rb', line 6 def @module_metadata end |
#uri ⇒ Object (readonly)
Returns the value of attribute uri.
7 8 9 |
# File 'lib/pdk/module/templatedir.rb', line 7 def uri @uri end |
Class Method Details
.files_in_template(dirs) ⇒ Hash{String=>String}
Get a list of template files in the template directory.
value locations.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/pdk/module/templatedir.rb', line 241 def self.files_in_template(dirs) temp_paths = [] dirlocs = [] dirs.each do |dir| raise ArgumentError, _("The directory '%{dir}' doesn't exist") % { dir: dir } unless Dir.exist?(dir) temp_paths += Dir.glob(File.join(dir, '**', '*'), File::FNM_DOTMATCH).select do |template_path| if File.file?(template_path) && !File.symlink?(template_path) dirlocs << dir end end temp_paths.map do |template_path| template_path.sub!(%r{\A#{Regexp.escape(dir)}#{Regexp.escape(File::SEPARATOR)}}, '') end end Hash[temp_paths.zip dirlocs] end |
Instance Method Details
#cache_template_ref(path, ref = nil) ⇒ Object
384 385 386 387 388 |
# File 'lib/pdk/module/templatedir.rb', line 384 def cache_template_ref(path, ref = nil) require 'pdk/util/git' @template_ref ||= PDK::Util::Git.describe(File.join(path, '.git'), ref) end |
#checkout_template_ref(path, ref) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/pdk/module/templatedir.rb', line 365 def checkout_template_ref(path, ref) require 'pdk/util/git' if PDK::Util::Git.work_dir_clean?(path) Dir.chdir(path) do full_ref = PDK::Util::Git.ls_remote(path, ref) cache_template_ref(path, full_ref) reset_result = PDK::Util::Git.git('reset', '--hard', full_ref) return if reset_result[:exit_code].zero? PDK.logger.error reset_result[:stdout] PDK.logger.error reset_result[:stderr] raise PDK::CLI::FatalError, _("Unable to checkout '%{ref}' of git repository at '%{path}'.") % { ref: ref, path: path } end else PDK.logger.warn _("Uncommitted changes found when attempting to checkout '%{ref}' of git repository at '%{path}'; skipping git reset.") % { ref: ref, path: path } end end |
#clone_template_repo(uri) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns Path to working directory into which template repo has been cloned and reset.
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/pdk/module/templatedir.rb', line 340 def clone_template_repo(uri) # @todo When switching this over to using rugged, cache the cloned # template repo in `%AppData%` or `$XDG_CACHE_DIR` and update before # use. require 'pdk/util' require 'pdk/util/git' temp_dir = PDK::Util.make_tmpdir_name('pdk-templates') origin_repo = uri.git_remote git_ref = uri.git_ref clone_result = PDK::Util::Git.git('clone', origin_repo, temp_dir) if clone_result[:exit_code].zero? checkout_template_ref(temp_dir, git_ref) else PDK.logger.error clone_result[:stdout] PDK.logger.error clone_result[:stderr] raise PDK::CLI::FatalError, _("Unable to clone git repository at '%{repo}' into '%{dest}'.") % { repo: origin_repo, dest: temp_dir } end PDK::Util.canonical_path(temp_dir) end |
#config_for(dest_path, sync_config_path = nil) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Generate a hash of data to be used when rendering the specified template.
data is for, relative to the root of the module.
‘@configs` instance variable.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/pdk/module/templatedir.rb', line 268 def config_for(dest_path, sync_config_path = nil) require 'pdk/util' require 'pdk/analytics' module_root = PDK::Util.module_root sync_config_path ||= File.join(module_root, '.sync.yml') unless module_root.nil? config_path = File.join(@path, 'config_defaults.yml') if @config.nil? require 'deep_merge' conf_defaults = read_config(config_path) @sync_config = read_config(sync_config_path) unless sync_config_path.nil? @config = conf_defaults @config.deep_merge!(@sync_config, knockout_prefix: '---') unless @sync_config.nil? end file_config = @config.fetch(:global, {}) file_config['module_metadata'] = @module_metadata file_config.merge!(@config.fetch(dest_path, {})) unless dest_path.nil? file_config.merge!(@config).tap do |c| if uri.default? file_value = if c['unmanaged'] 'unmanaged' elsif c['delete'] 'deleted' elsif @sync_config && @sync_config.key?(dest_path) 'customized' else 'default' end PDK.analytics.event('TemplateDir', 'file', label: dest_path, value: file_value) end end end |
#metadata ⇒ Hash{String => String}
Retrieve identifying metadata for the template.
For git repositories, this will return the URL to the repository and a reference to the HEAD.
98 99 100 101 102 103 104 105 106 |
# File 'lib/pdk/module/templatedir.rb', line 98 def require 'pdk/util/version' { 'pdk-version' => PDK::Util::Version.version_string, 'template-url' => uri., 'template-ref' => cache_template_ref(@path), } end |
#object_config ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Generate a hash of data to be used when rendering object templates.
Read ‘config_defaults.yml` from the root of the template directory (if it exists) build a hash of values from the value of the `:global` key.
‘@configs` instance variable.
198 199 200 |
# File 'lib/pdk/module/templatedir.rb', line 198 def object_config config_for(nil) end |
#object_template_for(object_type) ⇒ Hash{Symbol => String}
Searches the template directory for template files that can be used to render files for the specified object type.
‘:defined_type`, `:fact`, etc).
template dir, otherwise ‘nil`. The returned hash can contain two keys, :object contains the path on disk to the template for the object, :spec contains the path on disk to the template for the object’s spec file (if available).
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/pdk/module/templatedir.rb', line 169 def object_template_for(object_type) object_path = File.join(@object_dir, "#{object_type}.erb") type_path = File.join(@object_dir, "#{object_type}_type.erb") device_path = File.join(@object_dir, "#{object_type}_device.erb") spec_path = File.join(@object_dir, "#{object_type}_spec.erb") type_spec_path = File.join(@object_dir, "#{object_type}_type_spec.erb") if File.file?(object_path) && File.readable?(object_path) result = { object: object_path } result[:type] = type_path if File.file?(type_path) && File.readable?(type_path) result[:spec] = spec_path if File.file?(spec_path) && File.readable?(spec_path) result[:device] = device_path if File.file?(device_path) && File.readable?(device_path) result[:type_spec] = type_spec_path if File.file?(type_spec_path) && File.readable?(type_spec_path) result else nil end end |
#read_config(loc) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Generates a hash of data from a given yaml file location.
if so.
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/pdk/module/templatedir.rb', line 313 def read_config(loc) if File.file?(loc) && File.readable?(loc) require 'yaml' begin YAML.safe_load(File.read(loc), [], [], true) rescue Psych::SyntaxError => e PDK.logger.warn _("'%{file}' is not a valid YAML file: %{problem} %{context} at line %{line} column %{column}") % { file: loc, problem: e.problem, context: e.context, line: e.line, column: e.column, } {} end else {} end end |
#render {|dest_path, dest_content| ... } ⇒ void
This method returns an undefined value.
Loop through the files in the template, yielding each rendered file to the supplied block.
relative to the root of the module. destination file.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/pdk/module/templatedir.rb', line 121 def render require 'pdk/template_file' PDK::Module::TemplateDir.files_in_template(@dirs).each do |template_file, template_loc| template_file = template_file.to_s PDK.logger.debug(_("Rendering '%{template}'...") % { template: template_file }) dest_path = template_file.sub(%r{\.erb\Z}, '') config = config_for(dest_path) dest_status = if template_loc.start_with?(@moduleroot_init) :init else :manage end if config['unmanaged'] dest_status = :unmanage elsif config['delete'] dest_status = :delete else begin dest_content = PDK::TemplateFile.new(File.join(template_loc, template_file), configs: config, template_dir: self).render rescue => error error_msg = _( "Failed to render template '%{template}'\n" \ '%{exception}: %{message}', ) % { template: template_file, exception: error.class, message: error. } raise PDK::CLI::FatalError, error_msg end end yield dest_path, dest_content, dest_status end end |
#validate_module_template! ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Validate the content of the template directory.
a directory called ‘moduleroot’.
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/pdk/module/templatedir.rb', line 211 def validate_module_template! # rubocop:disable Style/GuardClause unless File.directory?(@path) require 'pdk/util' if PDK::Util.package_install? && File.fnmatch?(File.join(PDK::Util.package_cachedir, '*'), @path) raise ArgumentError, _('The built-in template has substantially changed. Please run "pdk convert" on your module to continue.') else raise ArgumentError, _("The specified template '%{path}' is not a directory.") % { path: @path } end end unless File.directory?(@moduleroot_dir) raise ArgumentError, _("The template at '%{path}' does not contain a 'moduleroot/' directory.") % { path: @path } end unless File.directory?(@moduleroot_init) # rubocop:disable Metrics/LineLength raise ArgumentError, _("The template at '%{path}' does not contain a 'moduleroot_init/' directory, which indicates you are using an older style of template. Before continuing please use the --template-url flag when running the pdk new commands to pass a new style template.") % { path: @path } # rubocop:enable Metrics/LineLength Style/GuardClause end # rubocop:enable Style/GuardClause end |