Class: PDK::Generate::PuppetObject

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

Direct Known Subclasses

DefinedType, Fact, Function, Provider, PuppetClass, Task, Transport

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)


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

def initialize(context, object_name, options)
  raise ArgumentError, format('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.



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

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

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.



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

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)


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

def check_preconditions
  raise ArgumentError, format('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)


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

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.



212
213
214
215
216
217
218
219
# File 'lib/pdk/generate/puppet_object.rb', line 212

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.



136
137
138
# File 'lib/pdk/generate/puppet_object.rb', line 136

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:



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

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)


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

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.



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

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, format("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:



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

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)


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

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)


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

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.



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

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



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

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:



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

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

  templates.each do |template|
    if template[:uri].nil?
      PDK.logger.debug(format('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(format('Unable to find a %{type} template in %{url}; trying next template directory.', type: friendly_name, url: template[:uri]))
      else
        raise PDK::CLI::FatalError, format('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