From 999141d02419bc102eff2c4c3efbb3e34106a909 Mon Sep 17 00:00:00 2001 From: Gilbert Cherrie Date: Thu, 15 Aug 2024 15:33:27 -0400 Subject: [PATCH] Fix ae engine tags --- .../engine/miq_ae_engine.rb | 22 +++++- .../engine/miq_ae_engine/miq_ae_object.rb | 26 ++++++- spec/miq_ae_engine_spec.rb | 78 ++++++++++++++----- 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/lib/miq_automation_engine/engine/miq_ae_engine.rb b/lib/miq_automation_engine/engine/miq_ae_engine.rb index 36ae02ba..d32c4f2f 100644 --- a/lib/miq_automation_engine/engine/miq_ae_engine.rb +++ b/lib/miq_automation_engine/engine/miq_ae_engine.rb @@ -262,8 +262,15 @@ def self.create_automation_attribute_array_key(key) end def self.create_automation_attribute_array_value(value) - value.collect do |obj| - obj.kind_of?(ActiveRecord::Base) ? obj.id.to_s : obj.to_s + # When array of length 1 just return the single object or id instead of an array + if value.length == 1 + obj = value[0] + obj.kind_of?(ActiveRecord::Base) ? "#{obj.class.name}::#{obj.id}" : obj.to_s + else + # Return an array of object references or ids + value.collect do |obj| + obj.kind_of?(ActiveRecord::Base) ? "#{obj.class.name}::#{obj.id}" : obj.to_s + end end end @@ -320,7 +327,13 @@ def self.create_ae_attrs(attrs, name, vmdb_object, objects = [MiqServer.my_serve 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::") + if !ae_attrs[array_object].empty? && ae_attrs[array_object].first.split("::").first == "Classification" + array_attr_key = if array_object.starts_with?("Array::") + "Tag#{array_object}" + else + "TagArray::#{array_object}" + end + elsif !array_object.starts_with?("Array::") array_attr_key = "Array::#{array_object}" end ae_attrs[array_attr_key] = ae_attrs[array_object].collect do |obj| @@ -329,6 +342,9 @@ def self.create_ae_attrs(attrs, name, vmdb_object, objects = [MiqServer.my_serve if !array_object.starts_with?("Array::") ae_attrs.delete(array_object) end + if !array_object.starts_with?("TagArray::") && array_attr_key.starts_with?("TagArray::") + 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 31cc4c42..344e8e78 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 @@ -258,19 +258,37 @@ def process_args_as_attributes(args = {}) end def process_args_array(args, args_key) - # process Array::servers => MiqServer::2,MiqServer::3,MiqServer::4 + # Process Array::servers => MiqServer::2,MiqServer::3,MiqServer::4 + # If no class seperator exists then return Array::servers => 2,3,4 key = args_key.split(CLASS_SEPARATOR).last value = args.delete(args_key) args[key.downcase] = load_array_objects_from_string(value) end def attribute_is_array?(attr) - attr.to_s.downcase.starts_with?("array::") + attr.to_s.downcase.starts_with?("array::") && !attr.to_s.downcase.starts_with?("tagarray") end def process_args_attribute(args, args_key) - # process MiqServer::svr => 2 - if args_key.include?(CLASS_SEPARATOR) + # Process TagArray::dialog_tags => , , + if args_key.to_s.downcase.starts_with?("tagarray") + tags = [] + args[args_key].split("\u001F").each do |tag| + # args_key: TagArray::dialog_param_test1 + # args[args_key]: , , + # tag: + key, klass = get_key_name_and_klass_from_key(tag) + tags.push(MiqAeObject.convert_value_based_on_datatype(key, klass)) + args["#{key}_id"] = tag if attribute_for_vmdb_object?(klass, args[args_key]) && !@attributes.key?(key) + end + args.delete(args_key) + key = args_key.split("::").last + if tags.length == 1 + tags = tags[0] + end + args[key] = tags + # Process MiqServer::svr => 2 + elsif args_key.include?(CLASS_SEPARATOR) key, klass = get_key_name_and_klass_from_key(args_key) value = args.delete(args_key) args["#{key}_id"] = value if attribute_for_vmdb_object?(klass, value) && !@attributes.key?(key) diff --git a/spec/miq_ae_engine_spec.rb b/spec/miq_ae_engine_spec.rb index 81c2debc..ad4d38b3 100644 --- a/spec/miq_ae_engine_spec.rb +++ b/spec/miq_ae_engine_spec.rb @@ -309,9 +309,8 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil) it "will process an array of objects with a server and user" do extras = "MiqServer%3A%3Amiq_server=12" - FactoryBot.create(:small_environment) - attrs = {"MiqServer::miq_server" => "12", "array::tag" => "Classification::1,Classification::2"} - result_str = "array%3A%3Atag=Classification%3A%3A1%2CClassification%3A%3A2" + attrs = {"MiqServer::miq_server" => "12", "Array::tags" => ["Classification::1,Classification::2"]} + result_str = "TagArray%3A%3Atags=Classification%3A%3A1%2CClassification%3A%3A2" uri = "/System/Process/AUTOMATION?#{extras}&#{result_str}&object_name=AUTOMATION" expect(MiqAeEngine.create_automation_object("AUTOMATION", attrs)).to eq(uri) end @@ -375,20 +374,22 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil) end it "with an array of Vms" do - 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_str = "vms=#{hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("=")}" result = MiqAeEngine.create_automation_attributes(hash) + result_arr = if hash["vms"].length == 1 + "ManageIQ::Providers::Vmware::InfraManager::Vm::#{hash["vms"][0].id}" + else + hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" } + end expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str) expect(result["vms"]).to eq(result_arr) end it "with an array containing a single Vm" do - 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_str = "vms=#{hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("=")}" + result_arr = "ManageIQ::Providers::Vmware::InfraManager::Vm::#{hash["vms"][0].id}" result = MiqAeEngine.create_automation_attributes(hash) expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str) expect(result["vms"]).to eq(result_arr) @@ -408,24 +409,33 @@ 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 = "hosts=#{hash["hosts"].collect { |h| h.id.to_s }.join("=")}" - hash["hosts"].collect { |h| result_arr.push(h.id.to_s) } + result_str = "hosts=#{hash["hosts"].collect { |h| "Host::#{h.id}" }.join("=")}" + result_arr = if hash["hosts"].length == 1 + "Host::#{hash["hosts"][0].id}" + else + hash["hosts"].collect { |h| "Host::#{h.id}" } + end result = MiqAeEngine.create_automation_attributes(hash) expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str) 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 = "vms=#{hash["vms"].collect { |v| v.id.to_s }.join("=")}" - hash["vms"].collect { |v| vm_result_arr.push(v.id.to_s) } + vm_result_str = "vms=#{hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" }.join("=")}" + vm_result_arr = if hash["vms"].length == 1 + "ManageIQ::Providers::Vmware::InfraManager::Vm::#{hash["vms"][0].id}" + else + hash["vms"].collect { |v| "ManageIQ::Providers::Vmware::InfraManager::Vm::#{v.id}" } + end hash["hosts"] = Host.all - 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) } + host_result_str = "hosts=#{hash["hosts"].collect { |h| "Host::#{h.id}" }.join("=")}" + host_result_arr = if hash["hosts"].length == 1 + "Host::#{hash["hosts"][0].id}" + else + hash["hosts"].collect { |h| "Host#{h.id}" } + end result = MiqAeEngine.create_automation_attributes(hash) expect(result["vms"]).to eq(vm_result_arr) expect(result["hosts"]).to eq(host_result_arr) @@ -434,16 +444,32 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil) expect(result_str).to include(host_result_str) end + it "with an array of Tags" do + FactoryBot.create(:classification) + FactoryBot.create(:classification) + FactoryBot.create(:classification) + hash = {"tags" => Classification.all} + result_str = "tags=#{hash["tags"].collect { |h| "Classification::#{h.id}" }.join("=")}" + result_arr = if hash["tags"].length == 1 + "Classification::#{hash["tags"][0].id}" + else + hash["tags"].collect { |h| "Classification::#{h.id}" } + end + result = MiqAeEngine.create_automation_attributes(hash) + expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq(result_str) + expect(result["tags"]).to eq(result_arr) + end + it "with invalid object references" do hash = {"vms" => ["bogus::12"]} result = MiqAeEngine.create_automation_attributes(hash) - expect(result["vms"]).to eq(["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["vms"]).to eq(bogus_arr) expect(MiqAeEngine.create_automation_attributes_string(hash)).to eq("vms=bogus::12,garbage::moreso,notevenclose") @@ -789,6 +815,18 @@ def call_automate(obj_type, obj_id, open_url_task_id = nil) my_objects_array.each { |o| o.kind_of?(MiqAeMethodService::MiqAeServiceModelBase) } end + it "processes tags array arguments properly" do + tag1 = FactoryBot.create(:classification) + tag2 = FactoryBot.create(:classification) + tag3 = FactoryBot.create(:classification) + + EvmSpecHelper.import_yaml_model(File.join(model_data_dir, "miq_ae_engine_spec5"), domain) + ws = MiqAeEngine.instantiate("/EVM/AUTOMATE/test1?TagArray::my_objects=Classification::#{tag1.id}\x1FClassification::#{tag2.id}\x1FClassification::#{tag3.id}", user) + my_objects_array = ws.root("my_objects") + expect(my_objects_array.length).to eq(3) + my_objects_array.each { |o| o.kind_of?(MiqAeMethodService::MiqAeServiceModelBase) } + end + it "processes an empty array properly" do EvmSpecHelper.import_yaml_model(File.join(model_data_dir, "miq_ae_engine_spec6"), domain) ws = MiqAeEngine.instantiate("/EVM/AUTOMATE/test1?Array::my_objects=", user)