Class: PDK::Generate::PuppetObject

Inherits:
Object
  • Object
show all
Defined in:
lib/pdk/generate/puppet_object.rb

Direct Known Subclasses

DefinedType, Provider, PuppetClass, Task, Transport

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(module_dir, object_name, options) ⇒ PuppetObject

Initialises the PDK::Generate::PuppetObject object.

In general, this object should never be instantiated directly. Instead, one of the subclasses should be used e.g. PDK::Generate::Klass.

New subclasses generally only need to inherit this class, set the OBJECT_TYPE constant and implement the #template_data, #target_object_path and #target_spec_path methods.

Parameters:

  • module_dir (String)

    The path to the module directory that the will contain the object.

  • object_name (String)

    The name of the object.

  • options (Hash{Symbol => Object})


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/pdk/generate/puppet_object.rb', line 23

def initialize(module_dir, object_name, options)
  @module_dir = module_dir
  @options = options
  @object_name = object_name

  if [:class, :defined_type].include?(object_type) # rubocop:disable Style/GuardClause
    object_name_parts = object_name.split('::')

    @object_name = if object_name_parts.first == module_name
                     object_name
                   else
                     [module_name, object_name].join('::')
                   end
  end
end

Instance Attribute Details

#module_dirObject (readonly)

Returns the value of attribute module_dir.



4
5
6
# File 'lib/pdk/generate/puppet_object.rb', line 4

def module_dir
  @module_dir
end

#object_nameObject (readonly)

Returns the value of attribute object_name.



5
6
7
# File 'lib/pdk/generate/puppet_object.rb', line 5

def object_name
  @object_name
end

#optionsObject (readonly)

Returns the value of attribute options.



6
7
8
# File 'lib/pdk/generate/puppet_object.rb', line 6

def options
  @options
end

Class Method Details

.class_name_from_object_name(object_name) ⇒ Object

transform a object name into a ruby class name



330
331
332
# File 'lib/pdk/generate/puppet_object.rb', line 330

def self.class_name_from_object_name(object_name)
  object_name.to_s.split('_').map(&:capitalize).join
end

.puppet_strings_typeString

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.

Retrieves the type of the object being generated as represented in the JSON output of puppet-strings.

Returns:

  • (String)

    the type of the object being generated or nil if there is no mapping.



104
105
106
107
108
# File 'lib/pdk/generate/puppet_object.rb', line 104

def self.puppet_strings_type
  return nil unless const_defined?(:PUPPET_STRINGS_TYPE)

  self::PUPPET_STRINGS_TYPE
end

Instance Method Details

#can_run?Boolean

Check the preconditions of this template group, behaving as a predicate rather than raising an exception.

Returns:

  • (Boolean)

    true if the generator is safe to run, otherwise false.



152
153
154
155
156
157
# File 'lib/pdk/generate/puppet_object.rb', line 152

def can_run?
  check_preconditions
  true
rescue PDK::CLI::ExitWithError
  false
end

#check_preconditionsObject

Check preconditions of this template group. By default this only makes sure that the target files do not already exist. Override this (and call super) to add your own preconditions.

Raises:



134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/pdk/generate/puppet_object.rb', line 134

def check_preconditions
  require 'pdk/util/filesystem'

  targets.each do |target_file|
    next unless PDK::Util::Filesystem.exist?(target_file)

    raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % {
      file:        target_file,
      object_type: spec_only? ? 'unit test' : object_type,
    }
  end
end

#module_nameString

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.

Retrieves the name of the module (without the forge username) from the module metadata.

Returns:

  • (String)

    The name of the module.



321
322
323
324
325
326
327
# File 'lib/pdk/generate/puppet_object.rb', line 321

def module_name
  require 'pdk/util'

  @module_name ||= PDK::Util.['name'].rpartition('-').last
rescue ArgumentError => e
  raise PDK::CLI::FatalError, e
end

#object_typeSymbol

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.

Retrieves the type of the object being generated, e.g. :class, :defined_type, etc. This is specified in the subclass’ OBJECT_TYPE constant.

Returns:

  • (Symbol)

    the type of the object being generated.



93
94
95
# File 'lib/pdk/generate/puppet_object.rb', line 93

def object_type
  self.class::OBJECT_TYPE
end

#render_file(dest_path, template_path, data) ⇒ 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.

Render a file using the provided template and write it to disk.

Parameters:

  • dest_path (String)

    The path that the rendered file should be written to. Any necessary directories will be automatically created.

  • template_path (String)

    The path on disk to the file containing the template.

  • data (Hash{Object => Object})

    The data to be provided to the template when rendering.

Raises:



198
199
200
201
202
203
204
# File 'lib/pdk/generate/puppet_object.rb', line 198

def render_file(dest_path, template_path, data)
  require 'pdk/template_file'

  write_file(dest_path) do
    PDK::TemplateFile.new(template_path, data).render
  end
end

#runObject

Check that the templates can be rendered. Find an appropriate template and create the target files from the template. This is the main entry point for the class.

Raises:



167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/pdk/generate/puppet_object.rb', line 167

def run
  check_preconditions

  with_templates do |template_path, config_hash|
    data = template_data.merge(configs: config_hash)

    render_file(target_object_path, template_path[:object], data) unless spec_only?
    render_file(target_type_path, template_path[:type], data) if template_path[:type]
    render_file(target_device_path, template_path[:device], data) if template_path[:device]
    render_file(target_spec_path, template_path[:spec], data) if template_path[:spec]
    render_file(target_type_spec_path, template_path[:type_spec], data) if template_path[:type_spec]
  end
end

#spec_only?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/pdk/generate/puppet_object.rb', line 39

def spec_only?
  @options[:spec_only]
end

#target_device_pathObject

This method is abstract.

Subclass and implement #target_device_path. Implementations of this method should return a String containing the destination path of the device class being generated.



82
83
84
# File 'lib/pdk/generate/puppet_object.rb', line 82

def target_device_path
  nil
end

#target_object_pathObject

This method is abstract.

Subclass and implement #target_object_path. Implementations of this method should return a String containing the destination path of the object being generated.

Raises:

  • (NotImplementedError)


53
54
55
# File 'lib/pdk/generate/puppet_object.rb', line 53

def target_object_path
  raise NotImplementedError
end

#target_spec_pathObject

This method is abstract.

Subclass and implement #target_spec_path. Implementations of this method should return a String containing the destination path of the tests for the object being generated.

Raises:

  • (NotImplementedError)


68
69
70
# File 'lib/pdk/generate/puppet_object.rb', line 68

def target_spec_path
  raise NotImplementedError
end

#target_type_pathString

This method is abstract.

Subclass and implement #target_type_path. Implementations of this method should return a String containing the destination path of the additional object file being generated.

Returns nil if there is no additional object file

Returns:

  • (String)

    returns nil if there is no additional object file



61
62
63
# File 'lib/pdk/generate/puppet_object.rb', line 61

def target_type_path
  nil
end

#target_type_spec_pathObject

This method is abstract.

Subclass and implement #target_type_spec_path. Implementations of this method should return a String containing the destination path of the tests for the object being generated.



75
76
77
# File 'lib/pdk/generate/puppet_object.rb', line 75

def target_type_spec_path
  nil
end

#targetsObject

Returns an array of possible target path strings.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/pdk/generate/puppet_object.rb', line 111

def targets
  targets = [
    target_spec_path,
    target_type_spec_path,
  ]

  unless spec_only?
    targets += [
      target_object_path,
      target_type_path,
      target_device_path,
    ]
  end

  targets.compact
end

#template_dataObject

This method is abstract.

Subclass and implement #template_data to provide data to the templates during rendering. Implementations of this method should return a Hash{Symbol => Object}.

Raises:

  • (NotImplementedError)


46
47
48
# File 'lib/pdk/generate/puppet_object.rb', line 46

def template_data
  raise NotImplementedError
end

#templatesArray<Hash{Symbol => 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.

Provides the possible template directory locations in the order in which they should be searched for a valid template.

If a template-url has been specified on in the options hash (e.g. from a CLI parameter), then this template directory will be checked first and we do not fall back to the next possible template directory.

If we have not been provided a specific template directory to use, we try the template specified in the module metadata (as set during PDK::Generate::Module) and fall back to the default template if necessary.

Returns:

  • (Array<Hash{Symbol => Object}>)

    an array of hashes. Each hash contains 3 keys: :type contains a String that describes the template directory, :url contains a String with the URL to the template directory, and :allow_fallback contains a Boolean that specifies if the lookup process should proceed to the next template directory if the template file is not in this template directory.



309
310
311
312
313
# File 'lib/pdk/generate/puppet_object.rb', line 309

def templates
  require 'pdk/util/template_uri'

  @templates ||= PDK::Util::TemplateURI.templates(@options)
end

#with_templates {|template_paths, config_hash| ... } ⇒ 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.

Search the possible template directories in order of preference to find a template that can be used to render a new object of the specified type.

Yield Parameters:

  • template_paths (Hash{Symbol => String})

    :object contains the path on disk to the template file for the object, :spec contains the path on disk to the template file for the tests for the object (if it exists).

  • config_hash (Hash{Object => Object})

    the contents of the :global key in the config_defaults.yml file.

Raises:



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/pdk/generate/puppet_object.rb', line 259

def with_templates
  require 'pdk/logger'
  require 'pdk/module/templatedir'
  require 'pdk/util/template_uri'

  templates.each do |template|
    if template[:uri].nil?
      PDK.logger.debug(_('No %{dir_type} template found; trying next template directory.') % { dir_type: template[:type] })
      next
    end

    PDK::Module::TemplateDir.new(PDK::Util::TemplateURI.new(template[:uri])) do |template_dir|
      template_paths = template_dir.object_template_for(object_type)

      if template_paths
        config_hash = template_dir.object_config
        yield template_paths, config_hash
        # TODO: refactor to a search-and-execute form instead
        return # work is done # rubocop:disable Lint/NonLocalExitFromIterator
      elsif template[:allow_fallback]
        PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: object_type, url: template[:uri] })
      else
        raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: object_type, url: template[:uri] }
      end
    end
  end
rescue ArgumentError => e
  raise PDK::CLI::ExitWithError, e
end

#write_file(dest_path) ⇒ 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.

Write the result of the block to disk.

Parameters:

  • dest_path (String)

    The path that the rendered file should be written to. Any necessary directories will be automatically created.

  • &block (String)

    The content to be written

Raises:



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/pdk/generate/puppet_object.rb', line 220

def write_file(dest_path)
  require 'pdk/logger'
  require 'pdk/util/filesystem'

  PDK.logger.info(_("Creating '%{file}' from template.") % { file: dest_path })

  file_content = yield

  begin
    PDK::Util::Filesystem.mkdir_p(File.dirname(dest_path))
  rescue SystemCallError => e
    raise PDK::CLI::FatalError, _("Unable to create directory '%{path}': %{message}") % {
      path:    File.dirname(dest_path),
      message: e.message,
    }
  end

  PDK::Util::Filesystem.write_file(dest_path, file_content)
rescue SystemCallError => e
  raise PDK::CLI::FatalError, _("Unable to write to file '%{path}': %{message}") % {
    path:    dest_path,
    message: e.message,
  }
end