Skip to content

Commit

Permalink
Merge pull request ManageIQ#545 from GilbertCherrie/fix_automation_ar…
Browse files Browse the repository at this point in the history
…rays

Fix automation array values
  • Loading branch information
Fryguy authored Jun 28, 2024
2 parents ac85c9f + c54ce45 commit 7707684
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 38 deletions.
33 changes: 24 additions & 9 deletions lib/miq_automation_engine/engine/miq_ae_engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def self.create_automation_attribute_name(object)

def self.create_automation_attribute_key(object, attr_name = nil)
klass_name = create_automation_attribute_class_name(object)
return klass_name.to_s if automation_attribute_is_array?(klass_name)
return klass_name.to_s if automation_attribute_is_array?(klass_name, object)

attr_name ||= create_automation_attribute_name(object)
"#{klass_name}::#{attr_name}"
Expand All @@ -222,8 +222,12 @@ def self.create_automation_attribute_value(object)
object.id
end

def self.automation_attribute_is_array?(attr)
attr.to_s.downcase.starts_with?("array::")
def self.automation_attribute_is_array?(attr, object = nil)
if !object.nil? && !object.kind_of?(String) && object.has_attribute?(:options) && !object.options.nil? && !object.options[:dialog].nil?
object[:options][:dialog][attr].kind_of?(Array)
else
attr.to_s.downcase.starts_with?("array::")
end
end

def self.create_automation_attributes_string(hash)
Expand Down Expand Up @@ -254,13 +258,13 @@ def self.create_automation_attribute(key, value)
end

def self.create_automation_attribute_array_key(key)
"Array::#{key}"
key
end

def self.create_automation_attribute_array_value(value)
value.collect do |obj|
obj.kind_of?(ActiveRecord::Base) ? "#{obj.class.name}::#{obj.id}" : obj.to_s
end.join("\x1F")
obj.kind_of?(ActiveRecord::Base) ? obj.id.to_s : obj.to_s
end
end

def self.set_automation_attributes_from_objects(objects, attrs_hash)
Expand Down Expand Up @@ -311,9 +315,20 @@ def self.create_ae_attrs(attrs, name, vmdb_object, objects = [MiqServer.my_serve
ae_attrs["MiqRequest::miq_request"] = vmdb_object.id if vmdb_object.kind_of?(MiqRequest)
ae_attrs['vmdb_object_type'] = create_automation_attribute_name(vmdb_object) unless vmdb_object.nil?

array_objects = ae_attrs.keys.find_all { |key| automation_attribute_is_array?(key) }
array_objects.each do |o|
ae_attrs[o] = ae_attrs[o].first if ae_attrs[o].kind_of?(Array)
# Sends array attributes to the miq_ae_object as strings with \x1F between each array item.
array_objects = ae_attrs.keys.find_all { |key| ae_attrs[key].kind_of?(Array) }
array_objects.each do |array_object|
# Each array attribute is tagged with Array:: before the attribute key unless it already starts with Array::
array_attr_key = array_object
if !array_object.starts_with?("Array::")
array_attr_key = "Array::#{array_object}"
end
ae_attrs[array_attr_key] = ae_attrs[array_object].collect do |obj|
obj.kind_of?(ActiveRecord::Base) ? "#{obj.class.name}::#{obj.id}" : obj.to_s
end.join("\x1F")
if !array_object.starts_with?("Array::")
ae_attrs.delete(array_object)
end
end
ae_attrs
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def user_info_attributes(user)
end

def process_args_as_attributes(args = {})
args.keys.each { |k| MiqAeEngine.automation_attribute_is_array?(k) ? process_args_array(args, k) : process_args_attribute(args, k) }
args.keys.each { |k| attribute_is_array?(k) ? process_args_array(args, k) : process_args_attribute(args, k) }
@attributes.merge!(args)
end

Expand All @@ -264,6 +264,10 @@ def process_args_array(args, args_key)
args[key.downcase] = load_array_objects_from_string(value)
end

def attribute_is_array?(attr)
attr.to_s.downcase.starts_with?("array::")
end

def process_args_attribute(args, args_key)
# process MiqServer::svr => 2
if args_key.include?(CLASS_SEPARATOR)
Expand Down
62 changes: 34 additions & 28 deletions spec/miq_ae_engine_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,11 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil)
end

it "will process an array of objects" do
FactoryBot.create(:host)
FactoryBot.create(:host)
hash = {"hosts" => Host.all}
attrs = {"Array::my_hosts" => hash["hosts"].collect { |h| "Host::#{h.id}" }}
result_str = "Array%3A%3Amy_hosts=" + hash["hosts"].collect { |h| "Host%3A%3A#{h.id}" }.join(",")
result_str = "Array%3A%3Amy_hosts=#{hash["hosts"].collect { |h| "Host%3A%3A#{h.id}" }.join("%1F")}" # After URL encoding the separator "\x1F" is converted to %1F
extras = "MiqServer%3A%3Amiq_server=#{miq_server_id}"
uri = "/System/Process/AUTOMATION?#{result_str}&#{extras}&object_name=AUTOMATION"
expect(MiqAeEngine.create_automation_object("AUTOMATION", attrs)).to eq(uri)
Expand Down Expand Up @@ -374,26 +375,28 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil)
end

it "with an array of Vms" do
hash = {"vms" => Vm.all}
result_str = "Array::vms=#{hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("\x1F")}"
result_arr = hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("\x1F")
result = MiqAeEngine.create_automation_attributes(hash)
result_arr = []
hash = {"vms" => Vm.all}
result_str = "vms=#{hash["vms"].collect { |v| v.id.to_s }.join("=")}"
hash["vms"].collect { |v| result_arr.push(v.id.to_s) }
result = MiqAeEngine.create_automation_attributes(hash)
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str)
expect(result["Array::vms"]).to eq(result_arr)
expect(result["vms"]).to eq(result_arr)
end

it "with an array containing a single Vm" do
hash = {"vms" => [Vm.first]}
result_str = "Array::vms=#{hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("\x1F")}"
result_arr = hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("\x1F")
result = MiqAeEngine.create_automation_attributes(hash)
result_arr = []
hash = {"vms" => [Vm.first]}
result_str = "vms=#{hash["vms"].collect { |v| v.id.to_s }.join("=")}"
hash["vms"].collect { |v| result_arr.push(v.id.to_s) }
result = MiqAeEngine.create_automation_attributes(hash)
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str)
expect(result["Array::vms"]).to eq(result_arr)
expect(result["vms"]).to eq(result_arr)
end

it "with an empty array" do
result = MiqAeEngine.create_automation_attributes("vms" => [])
expect(result["Array::vms"]).to eq("")
expect(result["vms"]).to eq([])
end

it "with a hash containing a single Vm" do
Expand All @@ -405,24 +408,27 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil)
end

it "with an array of Hosts" do
result_arr = []
hash = {"hosts" => Host.all}
result_str = "Array::hosts=#{hash["hosts"].collect { |h| "Host::#{h.id}" }.join("\x1F")}"
result_arr = hash["hosts"].collect { |h| "Host::#{h.id}" }.join("\x1F")
result = MiqAeEngine.create_automation_attributes(hash)
result_str = "hosts=#{hash["hosts"].collect { |h| h.id.to_s }.join("=")}"
hash["hosts"].collect { |h| result_arr.push(h.id.to_s) }
result = MiqAeEngine.create_automation_attributes(hash)
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str)
expect(result["Array::hosts"]).to eq(result_arr)
expect(result["hosts"]).to eq(result_arr)
end

it "with multiple arrays" do
vm_result_arr = []
host_result_arr = []
hash = {"vms" => Vm.all}
vm_result_str = "Array::vms=#{hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("\x1F")}"
vm_result_arr = hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("\x1F")
vm_result_str = "vms=#{hash["vms"].collect { |v| v.id.to_s }.join("=")}"
hash["vms"].collect { |v| vm_result_arr.push(v.id.to_s) }
hash["hosts"] = Host.all
host_result_str = "Array::hosts=#{hash["hosts"].collect { |h| "Host::#{h.id}" }.join("\x1F")}"
host_result_arr = hash["hosts"].collect { |h| "Host::#{h.id}" }.join("\x1F")
result = MiqAeEngine.create_automation_attributes(hash)
expect(result["Array::vms"]).to eq(vm_result_arr)
expect(result["Array::hosts"]).to eq(host_result_arr)
host_result_str = "hosts=#{hash["hosts"].collect { |h| h.id.to_s }.join("=")}"
hash["hosts"].collect { |h| host_result_arr.push(h.id.to_s) }
result = MiqAeEngine.create_automation_attributes(hash)
expect(result["vms"]).to eq(vm_result_arr)
expect(result["hosts"]).to eq(host_result_arr)
result_str = MiqAeEngine.create_automation_attributes_string(hash)
expect(result_str).to include(vm_result_str)
expect(result_str).to include(host_result_str)
Expand All @@ -431,16 +437,16 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil)
it "with invalid object references" do
hash = {"vms" => ["bogus::12"]}
result = MiqAeEngine.create_automation_attributes(hash)
expect(result["Array::vms"]).to eq("bogus::12")
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq("Array::vms=bogus::12")
expect(result["vms"]).to eq(["bogus::12"])
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq("vms=bogus::12")
end

it "with garbage values" do
hash = {"vms" => ["bogus::12,garbage::moreso,notevenclose"]}
bogus_arr = "bogus::12,garbage::moreso,notevenclose"
bogus_arr = ["bogus::12,garbage::moreso,notevenclose"]
result = MiqAeEngine.create_automation_attributes(hash)
expect(result["Array::vms"]).to eq(bogus_arr)
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq("Array::vms=bogus::12,garbage::moreso,notevenclose")
expect(result["vms"]).to eq(bogus_arr)
expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq("vms=bogus::12,garbage::moreso,notevenclose")
end

it "with a string value" do
Expand Down

0 comments on commit 7707684

Please sign in to comment.