diff --git a/lib/miq_automation_engine/engine/miq_ae_engine.rb b/lib/miq_automation_engine/engine/miq_ae_engine.rb index a3907693..36ae02ba 100644 --- a/lib/miq_automation_engine/engine/miq_ae_engine.rb +++ b/lib/miq_automation_engine/engine/miq_ae_engine.rb @@ -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}" @@ -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) @@ -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) @@ -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 diff --git a/lib/miq_automation_engine/engine/miq_ae_engine/miq_ae_object.rb b/lib/miq_automation_engine/engine/miq_ae_engine/miq_ae_object.rb index 0a252617..31cc4c42 100644 --- a/lib/miq_automation_engine/engine/miq_ae_engine/miq_ae_object.rb +++ b/lib/miq_automation_engine/engine/miq_ae_engine/miq_ae_object.rb @@ -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 @@ -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) diff --git a/spec/miq_ae_engine_spec.rb b/spec/miq_ae_engine_spec.rb index 93f2e5c2..81c2debc 100644 --- a/spec/miq_ae_engine_spec.rb +++ b/spec/miq_ae_engine_spec.rb @@ -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) @@ -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 @@ -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) @@ -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