Class: Installation::AutoinstProfile::SectionWithAttributes
- Inherits:
-
Object
- Object
- Installation::AutoinstProfile::SectionWithAttributes
- 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:
Converting profile related information from/to hash objects. It includes logic to support old-style profiles (renaming attributes and so on).
Generating a section from the running system. See PartitioningSection#new_from_storage or NetworkingSection#new_from_network to take some inspiration. Bear in mind that the former does not inherit from SectionWithAttributes, but relies on other classes that do so.
Offering convenient query methods when needed. See PartitioningSection#disk_drives or PartitionSection#used? as examples.
Interpreting some values like the dash (-) in networking route sections.
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
Instance Attribute Summary collapse
-
#parent ⇒ #parent, #section_name
readonly
This value only makes sense when SectionWithAttributes.new_from_hashes is used.
Class Method Summary collapse
-
.attributes ⇒ Array<Hash>
Description of the attributes in the section.
-
.define_attr_accessors ⇒ Object
protected
Macro used in the subclasses to define accessors for all the attributes defined by SectionWithAttributes.attributes.
-
.new_from_hashes(hash, parent = nil) ⇒ SectionWithAttributes
Creates an instance based on the profile representation used by the AutoYaST modules (nested arrays and hashes).
Instance Method Summary collapse
- #attrib(key) ⇒ Object protected
- #attrib_key(attrib) ⇒ Object protected
- #attrib_name(key) ⇒ Object protected
- #attrib_scalar(element) ⇒ Object protected
-
#attrib_skip?(key, value) ⇒ Boolean
protected
Whether an attribute must be skipped during import/export.
- #attrib_value(attrib) ⇒ Object protected
- #attributes ⇒ Object protected
-
#collection_name ⇒ String?
Returns the collection name.
-
#index ⇒ Integer?
Returns the position within the collection.
-
#init_from_hashes(hash) ⇒ Object
Method used by SectionWithAttributes.new_from_hashes to populate the attributes.
- #init_scalars_from_hash(hash) ⇒ Object protected
-
#initialize(parent = nil) ⇒ SectionWithAttributes
constructor
Constructor.
-
#section_name ⇒ String
Returns the section name.
-
#section_path ⇒ ElementPath
Returns the section's path.
-
#to_hashes ⇒ Hash
Content of the section in the format used by the AutoYaST modules (nested arrays and hashes).
Constructor Details
#initialize(parent = nil) ⇒ SectionWithAttributes
Constructor
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.
175 176 177 |
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 175 def parent @parent end |
Class Method Details
.attributes ⇒ Array<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.
136 137 138 |
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 136 def attributes [] end |
.define_attr_accessors ⇒ Object (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.
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.
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 |
#attributes ⇒ Object (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_name ⇒ String?
Returns the collection name
If the section belongs to a collection, returns its name. Otherwise, it returns nil.
235 236 237 |
# File 'library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb', line 235 def collection_name nil end |
#index ⇒ Integer?
Returns the position within the collection
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.
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_name ⇒ String
Returns the section name
In some cases, the section name does not match with the XML name and this method should be redefined.
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_path ⇒ ElementPath
Returns the section's path
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_hashes ⇒ Hash
Content of the section in the format used by the AutoYaST modules (nested arrays and hashes).
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 |