Class: Installation::AutoinstProfile::SectionWithAttributes

Inherits:
Object
  • Object
show all
Includes:
Yast::Logger
Defined in:
library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb

Overview

Abstract base class to be used when dealing with AutoYaST profiles

Motivation

Historically, AutoYaST has used hash objects to handle the profile data. The import method expects to receive a hash with the profile content while the export method returns a hash. For simple cases, it is just fine. However, for complex scenarios (like storage or networking settings), using a hash can be somewhat limiting.

Features

This class offers a starting point for a better API when working with AutoYaST profiles, abstracting some details. The idea is that by creating a derived class and specifying the known profile elements (attributes) you get a basic class that you can extend to offer a convenient API.

These classes would be responsible for:

Scope

Validation or setting default values is out of the scope of these classes, as it belongs to the code which imports the profile data. However, nothing is set in stone and we could change this decision in the future if needed.

Limitations

This class only handles scalar data types. If you need to deal with arrays, you must extend your derived class. The reason is that, usually, those arrays are composed of other sections like partitions, network interfaces, etc. Take into account that you will need to write code import and export those structures. Check the partitions and network interfaces examples to find out the details.

Examples

Examples:

Custom section definition

class SignatureHandlingSection < SectionWithAttributes
  class << self
    def attributes
     [
       { name: :accept_file_without_checksum },
       { name: :accept_usigned_file }
     ]
    end
  end
end

Importing a section from the profile

def import(settings)
  section = SignatureHandlingSection.new_from_hashes(settings)
  # Do whatever you need to do with the section content.
end

Exporting the values from the system

def export
  section = SignatureHandlingSection.new_from_system(signature_handling)
  section.to_hashes
end

Adding a query API method

class SignatureHandlingSection < SectionWithAttributes
  # Omiting attributes definition for simplicity reasons.

  # Determines whether the signature checking is completely disabled
  #
  # @return [Boolean]
  def disabled?
    accept_file_without_checksum && accept_unsigned_file
  end
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil) ⇒ SectionWithAttributes

Constructor

Parameters:



180
181
182
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 180

def initialize(parent = nil)
  @parent = parent
end

Instance Attribute Details

#parent#parent, #section_name (readonly)

This value only makes sense when new_from_hashes is used.

Returns:



175
176
177
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 175

def parent
  @parent
end

Class Method Details

.attributesArray<Hash>

Description of the attributes in the section.

To be defined by each subclass. Each entry contains a hash with:

  • :name : (mandatory) name of the attribute.
  • :xml_name : (optional) name of the attribute in the xml profile. This is useful when the attribute is required to be called different to the its xml name.
  • :allow_blank : (optional, false by default) whether blank values (i.e, "" or []) are allowed. If set to false, then the value of the attribute will be nil when a blank is detected.

Returns:

  • (Array<Hash>)


136
137
138
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 136

def attributes
  []
end

.define_attr_accessorsObject (protected)

Macro used in the subclasses to define accessors for all the attributes defined by attributes



165
166
167
168
169
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 165

def define_attr_accessors
  attributes.each do |attrib|
    attr_accessor attrib[:name]
  end
end

.new_from_hashes(hash, parent = nil) ⇒ SectionWithAttributes

Creates an instance based on the profile representation used by the AutoYaST modules (nested arrays and hashes).

This method provides no extra validation, type conversion or initialization to default values. Those responsibilities belong to the AutoYaST modules. The hash is expected to be valid and contain the relevant information. Attributes are set to nil for missing keys and for blank values.

Parameters:

  • hash (Hash, Array<Hash>)

    content of the corresponding section of the profile. Each element of the hash corresponds to one of the attributes defined in the section. When the section is a list, the method can receive an array containing one hash per each element.

  • parent (#parent, #section_name) (defaults to: nil)

    parent section

Returns:



155
156
157
158
159
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 155

def new_from_hashes(hash, parent = nil)
  result = new(parent)
  result.init_from_hashes(hash) if hash.is_a?(Enumerable)
  result
end

Instance Method Details

#attrib(key) ⇒ Object (protected)



268
269
270
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 268

def attrib(key)
  attributes.find { |a| a[:xml_name] == key.to_sym || a[:name] == key.to_sym }
end

#attrib_key(attrib) ⇒ Object (protected)



284
285
286
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 284

def attrib_key(attrib)
  (attrib[:xml_name] || attrib[:name]).to_s
end

#attrib_name(key) ⇒ Object (protected)



301
302
303
304
305
306
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 301

def attrib_name(key)
  attrib = attrib(key)
  return nil unless attrib

  attrib[:name]
end

#attrib_scalar(element) ⇒ Object (protected)



297
298
299
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 297

def attrib_scalar(element)
  element.respond_to?(:to_hashes) ? element.to_hashes : element
end

#attrib_skip?(key, value) ⇒ Boolean (protected)

Whether an attribute must be skipped during import/export.

Returns:

  • (Boolean)

    true is the attribute allows to skip and its value is blank



275
276
277
278
279
280
281
282
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 275

def attrib_skip?(key, value)
  attrib = attrib(key)

  return true unless attrib
  return false if attrib[:allow_blank]

  value.nil? || value == [] || value == ""
end

#attrib_value(attrib) ⇒ Object (protected)



288
289
290
291
292
293
294
295
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 288

def attrib_value(attrib)
  value = send(attrib[:name])
  if value.is_a?(Array)
    value.map { |v| attrib_scalar(v) }
  else
    attrib_scalar(value)
  end
end

#attributesObject (protected)



264
265
266
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 264

def attributes
  self.class.attributes
end

#collection_nameString?

Returns the collection name

If the section belongs to a collection, returns its name. Otherwise, it returns nil.

Returns:

  • (String, nil)

    Collection name



235
236
237
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 235

def collection_name
  nil
end

#indexInteger?

Returns the position within the collection

Returns:

  • (Integer, nil)

    Index or nil if it does not belong to a collection or the parent is not set.



243
244
245
246
247
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 243

def index
  return nil unless collection_name && parent

  parent.send(collection_name).index(self)
end

#init_from_hashes(hash) ⇒ Object

Method used by new_from_hashes to populate the attributes.

By default, it simply assigns the non-empty hash values to the corresponding attributes, logging unknown keys. The subclass is expected to refine this behavior if needed.

Parameters:



191
192
193
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 191

def init_from_hashes(hash)
  init_scalars_from_hash(hash)
end

#init_scalars_from_hash(hash) ⇒ Object (protected)



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 308

def init_scalars_from_hash(hash)
  hash.each_pair do |key, value|
    name = attrib_name(key)

    if name.nil?
      log.warn "Attribute #{key} not recognized by #{self.class}. Check the XML schema."
      next
    end

    # This method only reads scalar values
    next if value.is_a?(Array) || value.is_a?(Hash)

    if attrib_skip?(key, value)
      log.debug "Ignored blank value (#{value}) for #{key}"
      next
    end

    send(:"#{name}=", value)
  end
end

#section_nameString

Returns the section name

In some cases, the section name does not match with the XML name and this method should be redefined.

Examples:

section = PartitioningSection.new
section.section_name #=> "partitioning"

Returns:

  • (String)

    Section name



222
223
224
225
226
227
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 222

def section_name
  klass_name = self.class.name.split("::").last
  klass_name
    .gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase
    .chomp("_section")
end

#section_pathElementPath

Returns the section's path

Returns:



252
253
254
255
256
257
258
259
260
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 252

def section_path
  return ElementPath.new(section_name) if parent.nil?

  if collection_name
    parent.section_path.join(collection_name, index)
  else
    parent.section_path.join(section_name)
  end
end

#to_hashesHash

Content of the section in the format used by the AutoYaST modules (nested arrays and hashes).

Returns:

  • (Hash)

    each element of the hash corresponds to one of the attributes defined in the section. Blank attributes are not included.



201
202
203
204
205
206
207
208
209
210
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 201

def to_hashes
  attributes.each_with_object({}) do |attrib, result|
    key = attrib_key(attrib)
    value = attrib_value(attrib)

    next if attrib_skip?(key, value)

    result[key] = value
  end
end