Class: PDK::Generate::PuppetObject

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

Direct Known Subclasses

DefinedType, PuppetClass, ResourceAPIObject, Task

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context, 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 root of module that the will contain the object.

  • object_name (String)

    The name of the object.

  • options (Hash{Symbol => Object})

Raises:

  • (ArgumentError)


23
24
25
26
27
28
# File 'lib/pdk/generate/puppet_object.rb', line 23

def initialize(context, object_name, options)
  raise ArgumentError, _('Expected PDK::Context::AbstractContext but got \'%{klass}\' for context') % { klass: context.class } unless context.is_a?(PDK::Context::AbstractContext)
  @context = context
  @options = options
  @object_name = object_name
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



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

def context
  @context
end

#object_nameObject (readonly)

Returns the value of attribute object_name.



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

def object_name
  @object_name
end

#optionsObject (readonly)

Returns the value of attribute options.



8
9
10
# File 'lib/pdk/generate/puppet_object.rb', line 8

def options
  @options
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.



70
71
72
73
74
75
# File 'lib/pdk/generate/puppet_object.rb', line 70

def can_run?
  check_preconditions
  true
rescue StandardError
  false
end

#check_preconditionsvoid

This method is abstract.

This method returns an undefined value.

Raises an error if any pre-conditions are not met

Raises:

  • (ArgumentError)


63
64
65
# File 'lib/pdk/generate/puppet_object.rb', line 63

def check_preconditions
  raise ArgumentError, _('Expected a module context but got %{context_name}') % { context_name: context.display_name } unless context.is_a?(PDK::Context::Module)
end

#friendly_nameObject

This method is abstract.

Subclass and implement #friendly_name to provide a nice name to show users in CLI

Returns:

  • String

Raises:

  • (NotImplementedError)


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

def friendly_name
  raise NotImplementedError
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.



215
216
217
218
219
220
221
222
# File 'lib/pdk/generate/puppet_object.rb', line 215

def module_name
  return nil unless context.is_a?(PDK::Context::Module)

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

#non_template_filesHash{String => 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.

This method is abstract.

A subclass may wish to stage files into the Update Manager, but the content is not templated. Subclasses can override this method to stage arbitrary files

Returns:

  • (Hash{String => String})

    A Hash with the relative file path as the key and the new file content as the value.



139
140
141
# File 'lib/pdk/generate/puppet_object.rb', line 139

def non_template_files
  {}
end

#run(update_manager = update_manager_instance) ⇒ PDK::Module::UpdateManager

Stages and then executes the changes for the templates to be rendereed. This is the main entry point for the class.

Returns:

See Also:



90
91
92
93
# File 'lib/pdk/generate/puppet_object.rb', line 90

def run(update_manager = update_manager_instance)
  stage_changes(update_manager).sync_changes!
  update_manager
end

#spec_only?Boolean

Whether the generator should only return test (spec) files

Returns:

  • (Boolean)


32
33
34
# File 'lib/pdk/generate/puppet_object.rb', line 32

def spec_only?
  @options[:spec_only]
end

#stage_change(relative_dest_path, content, update_manager) ⇒ 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.

Stages a single file into the Update Manager.



122
123
124
125
126
127
128
129
130
131
# File 'lib/pdk/generate/puppet_object.rb', line 122

def stage_change(relative_dest_path, content, update_manager)
  absolute_file_path = File.join(context.root_path, relative_dest_path)
  if PDK::Util::Filesystem.exist?(absolute_file_path)
    raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % {
      file:        absolute_file_path,
      object_type: spec_only? ? 'unit test' : friendly_name,
    }
  end
  update_manager.add_file(absolute_file_path, content)
end

#stage_changes(update_manager) ⇒ PDK::Module::UpdateManager

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

Returns:

Raises:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/pdk/generate/puppet_object.rb', line 103

def stage_changes(update_manager)
  check_preconditions

  with_templates do |template_dir|
    template_files.each do |source_file, relative_dest_path|
      new_content = template_dir.render_single_item(source_file, template_data)
      next if new_content.nil?

      stage_change(relative_dest_path, new_content, update_manager)
    end
  end
  non_template_files.each { |relative_dest_path, content| stage_change(relative_dest_path, content, update_manager) }

  update_manager
end

#template_dataObject

This method is abstract.

Subclass and implement #template_data to provide data to the templates during rendering.

Raises:

  • (NotImplementedError)


55
56
57
# File 'lib/pdk/generate/puppet_object.rb', line 55

def template_data
  raise NotImplementedError
end

#template_filesObject

This method is abstract.

Subclass and implement #template_files to provide the template files to

render. Implementations of this method should return a Hash!{String => String}.

Raises:

  • (NotImplementedError)


48
49
50
# File 'lib/pdk/generate/puppet_object.rb', line 48

def template_files
  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.



203
204
205
206
207
# File 'lib/pdk/generate/puppet_object.rb', line 203

def templates
  require 'pdk/util/template_uri'

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

#update_manager_instanceObject

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.

Creates an instance of an update manager



79
80
81
82
# File 'lib/pdk/generate/puppet_object.rb', line 79

def update_manager_instance
  require 'pdk/module/update_manager'
  PDK::Module::UpdateManager.new
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:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/pdk/generate/puppet_object.rb', line 157

def with_templates
  require 'pdk/logger'
  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::Template.with(PDK::Util::TemplateURI.new(template[:uri]), context) do |template_dir|
      if template_files.any? { |source_file, _| template_dir.has_single_item?(source_file) }
        yield template_dir
        # 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: friendly_name, url: template[:uri] })
      else
        raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: friendly_name, url: template[:uri] }
      end
    end
  end
rescue ArgumentError => e
  raise PDK::CLI::ExitWithError, e
end