-
Notifications
You must be signed in to change notification settings - Fork 898
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17348 from slemrmartin/inventory-collection-builder
Inventory Collection Builder
- Loading branch information
Showing
12 changed files
with
1,339 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
248 changes: 248 additions & 0 deletions
248
app/models/manager_refresh/inventory_collection/builder.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
module ManagerRefresh | ||
class InventoryCollection | ||
# @see test in /spec/models/manager_refresh/inventory_collection/builder_spec.rb | ||
class Builder | ||
class MissingModelClassError < StandardError; end | ||
|
||
require_nested :CloudManager | ||
require_nested :InfraManager | ||
require_nested :AutomationManager | ||
require_nested :NetworkManager | ||
require_nested :StorageManager | ||
require_nested :PersisterHelper | ||
|
||
include ::ManagerRefresh::InventoryCollection::Builder::Shared | ||
|
||
# Default options for builder | ||
# :adv_settings | ||
# - values from Advanced settings (doesn't overwrite values specified in code) | ||
# - @see method ManagerRefresh::Inventory::Persister.make_builder_settings() | ||
# :shared_properties | ||
# - any properties applied if missing (not explicitly specified) | ||
def self.default_options | ||
{ | ||
:adv_settings => {}, | ||
:shared_properties => {}, | ||
} | ||
end | ||
|
||
# Entry point | ||
# Creates builder and builds data for inventory collection | ||
# @param name [Symbol] InventoryCollection.association value | ||
# (optional) method with this name also used for concrete inventory collection specific properties | ||
# @param persister_class [Class] used for "guessing" model_class | ||
# @param options [Hash] | ||
def self.prepare_data(name, persister_class, options = {}) | ||
options = default_options.merge(options) | ||
builder = new(name, persister_class, options) | ||
builder.construct_data | ||
|
||
yield(builder) if block_given? | ||
|
||
builder | ||
end | ||
|
||
# @see prepare_data() | ||
def initialize(name, persister_class, options = self.class.default_options) | ||
@name = name | ||
@persister_class = persister_class | ||
|
||
@properties = {} | ||
@inventory_object_attributes = [] | ||
@builder_params = {} | ||
@dependency_attributes = {} | ||
|
||
@options = options | ||
@options[:auto_inventory_attributes] = true if @options[:auto_inventory_attributes].nil? | ||
@options[:without_model_class] = false if @options[:without_model_class].nil? | ||
|
||
@adv_settings = options[:adv_settings] # Configuration/Advanced settings in GUI | ||
@shared_properties = options[:shared_properties] # From persister | ||
end | ||
|
||
# Builds data for InventoryCollection | ||
# Calls method @name (if exists) with specific properties | ||
# Yields for overwriting provider-specific properties | ||
def construct_data | ||
add_properties(:association => @name) | ||
add_properties(:model_class => auto_model_class) unless @options[:without_model_class] | ||
|
||
add_properties(@adv_settings, :if_missing) | ||
add_properties(@shared_properties, :if_missing) | ||
|
||
send(@name.to_sym) if respond_to?(@name.to_sym) | ||
|
||
add_inventory_attributes(auto_inventory_attributes) if @options[:auto_inventory_attributes] | ||
end | ||
|
||
# Creates InventoryCollection | ||
def to_inventory_collection | ||
if @properties[:model_class].nil? && !@options[:without_model_class] | ||
raise MissingModelClassError | ||
end | ||
|
||
::ManagerRefresh::InventoryCollection.new(to_hash) | ||
end | ||
|
||
# | ||
# Missing method | ||
# - add_some_property(value) | ||
# converted to: | ||
# - add_properties(:some_property => value) | ||
# | ||
def method_missing(method_name, *arguments, &block) | ||
if method_name.to_s.starts_with?('add_') | ||
add_properties( | ||
method_name.to_s.gsub('add_', '').to_sym => arguments[0] | ||
) | ||
else | ||
super | ||
end | ||
end | ||
|
||
def respond_to_missing?(method_name, _include_private = false) | ||
method_name.to_s.starts_with?('add_') | ||
end | ||
|
||
# Merges @properties | ||
# @see ManagerRefresh::InventoryCollection.initialize for list of properties | ||
# | ||
# @param props [Hash] | ||
# @param mode [Symbol] :overwrite | :if_missing | ||
def add_properties(props = {}, mode = :overwrite) | ||
@properties = merge_hashes(@properties, props, mode) | ||
end | ||
|
||
# Adds inventory object attributes (part of @properties) | ||
def add_inventory_attributes(array) | ||
@inventory_object_attributes += (array || []) | ||
end | ||
|
||
# Removes specified inventory object attributes | ||
def remove_inventory_attributes(array) | ||
@inventory_object_attributes -= (array || []) | ||
end | ||
|
||
# Clears all inventory object attributes | ||
def clear_inventory_attributes! | ||
@inventory_object_attributes = [] | ||
end | ||
|
||
# Adds key/values to builder params (part of @properties) | ||
def add_builder_params(params = {}, mode = :overwrite) | ||
@builder_params = merge_hashes(@builder_params, params, mode) | ||
end | ||
|
||
# Evaluates lambda blocks | ||
def evaluate_lambdas!(persister) | ||
evaluate_builder_params_lambdas!(persister) | ||
end | ||
|
||
# Adds key/values to dependency_attributes (part of @properties) | ||
def add_dependency_attributes(attrs = {}, mode = :overwrite) | ||
@dependency_attributes = merge_hashes(@dependency_attributes, attrs, mode) | ||
end | ||
|
||
# Returns whole InventoryCollection properties | ||
def to_hash | ||
@properties.merge( | ||
:inventory_object_attributes => @inventory_object_attributes, | ||
:builder_params => @builder_params, | ||
:dependency_attributes => @dependency_attributes | ||
) | ||
end | ||
|
||
protected | ||
|
||
# Extends source hash with | ||
# - a) all keys from dest (overwrite mode) | ||
# - b) missing keys (missing mode) | ||
# | ||
# @param mode [Symbol] :overwrite | :if_missing | ||
def merge_hashes(source, dest, mode) | ||
return source if source.nil? || dest.nil? | ||
|
||
if mode == :overwrite | ||
source.merge(dest) | ||
else | ||
dest.merge(source) | ||
end | ||
end | ||
|
||
# Derives model_class from persister class and @name | ||
# 1) searches for class in provider | ||
# 2) if not found, searches class in core | ||
# Can be disabled by options :auto_model_class => false | ||
# | ||
# @example derives model_class from amazon | ||
# | ||
# @persister_class = ManageIQ::Providers::Amazon::Inventory::Persister::CloudManager | ||
# @name = :vms | ||
# | ||
# returns - <provider_module>::<manager_module>::<@name.classify> | ||
# returns - ::ManageIQ::Providers::Amazon::CloudManager::Vm | ||
# | ||
# @example derives model_class from @name only | ||
# | ||
# @persister_class = ManagerRefresh::Inventory::Persister | ||
# @name = :vms | ||
# | ||
# returns ::Vm | ||
# | ||
# @return [Class | nil] when class doesn't exist, returns nil | ||
def auto_model_class | ||
model_class = begin | ||
# a) Provider specific class | ||
provider_module = ManageIQ::Providers::Inflector.provider_module(@persister_class).name | ||
manager_module = self.class.name.split('::').last | ||
|
||
class_name = "#{provider_module}::#{manager_module}::#{@name.to_s.classify}" | ||
class_name.safe_constantize | ||
rescue ::ManageIQ::Providers::Inflector::ObjectNotNamespacedError | ||
nil | ||
end | ||
|
||
if model_class | ||
model_class | ||
else | ||
# b) general class | ||
"::#{@name.to_s.classify}".safe_constantize | ||
end | ||
end | ||
|
||
# Inventory object attributes are derived from setters | ||
# | ||
# Can be disabled by options :auto_inventory_attributes => false | ||
# - attributes can be manually set via method add_inventory_attributes() | ||
def auto_inventory_attributes | ||
return if @properties[:model_class].nil? | ||
|
||
(@properties[:model_class].new.methods - ApplicationRecord.methods).grep(/^[\w]+?\=$/).collect do |setter| | ||
setter.to_s[0..setter.length - 2].to_sym | ||
end | ||
end | ||
|
||
# Evaluates lambda blocks in @builder_params | ||
def evaluate_builder_params_lambdas!(persister) | ||
if @builder_params | ||
@builder_params = @builder_params.transform_values do |value| | ||
if value.respond_to?(:call) | ||
value.call(persister) | ||
else | ||
value | ||
end | ||
end | ||
end | ||
end | ||
|
||
def network_manager_collections? | ||
self.class.network_manager_collections? | ||
end | ||
|
||
# InventoryCollection definitions for NetworkManager? | ||
def self.network_manager_collections? | ||
false | ||
end | ||
end | ||
end | ||
end |
58 changes: 58 additions & 0 deletions
58
app/models/manager_refresh/inventory_collection/builder/automation_manager.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
module ManagerRefresh | ||
class InventoryCollection | ||
class Builder | ||
# TODO: (mslemr) Remove /manager_refresh/inventory/[core, automation_manager, cloud_manager, ?middleware_manager?].rb | ||
# TODO: (mslemr) think about lib/generators/provider/templates/app/models/manageiq/providers/%provider_name%/inventory/persister/cloud_manager.rb | ||
class AutomationManager < ::ManagerRefresh::InventoryCollection::Builder | ||
def configuration_scripts | ||
default_manager_ref | ||
default_builder_params | ||
end | ||
|
||
def configuration_script_payloads | ||
add_properties( | ||
:manager_ref => %i(configuration_script_source manager_ref) | ||
) | ||
default_builder_params | ||
end | ||
|
||
def configuration_script_sources | ||
default_manager_ref | ||
default_builder_params | ||
end | ||
|
||
def configured_systems | ||
default_manager_ref | ||
default_builder_params | ||
end | ||
|
||
def credentials | ||
default_manager_ref | ||
add_builder_params( | ||
:resource => ->(persister) { persister.manager } | ||
) | ||
end | ||
|
||
def inventory_root_groups | ||
default_builder_params | ||
end | ||
|
||
def vms | ||
add_properties(:manager_ref => %i(uid_ems)) | ||
end | ||
|
||
protected | ||
|
||
def default_manager_ref | ||
add_properties(:manager_ref => %i(manager_ref)) | ||
end | ||
|
||
def default_builder_params | ||
add_builder_params( | ||
:manager => ->(persister) { persister.manager } | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.