From dd5aa3348b45ec28fcc0b02a035277b398ab8c14 Mon Sep 17 00:00:00 2001 From: lpichler Date: Fri, 9 Sep 2016 14:53:31 +0200 Subject: [PATCH 1/6] Changed spec for report with custom attributes to add special characters in custom attributes --- spec/models/miq_report_spec.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/spec/models/miq_report_spec.rb b/spec/models/miq_report_spec.rb index 25d29dbd4f5..908c0db2611 100644 --- a/spec/models/miq_report_spec.rb +++ b/spec/models/miq_report_spec.rb @@ -81,16 +81,16 @@ context "report with virtual dynamic custom attributes" do let(:options) { {:targets_hash => true, :userid => "admin"} } - let(:custom_column_key_1) { 'ATTR_Name_1' } - let(:custom_column_key_2) { 'ATTR_Name_2' } + let(:custom_column_key_1) { 'kubernetes.io/hostname' } + let(:custom_column_key_2) { 'manageiq.org' } let(:custom_column_key_3) { 'ATTR_Name_3' } let(:custom_column_value) { 'value1' } let(:user) { FactoryGirl.create(:user_with_group) } let(:ems) { FactoryGirl.create(:ems_vmware) } let!(:vm_1) { FactoryGirl.create(:vm_vmware) } let!(:vm_2) { FactoryGirl.create(:vm_vmware, :retired => false, :ext_management_system => ems) } - let(:virtual_column_key_1) { "#{CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX}ATTR_Name_1" } - let(:virtual_column_key_2) { "#{CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX}ATTR_Name_2" } + let(:virtual_column_key_1) { "#{CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX}kubernetes.io/hostname" } + let(:virtual_column_key_2) { "#{CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX}manageiq.org" } let(:virtual_column_key_3) { "#{CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX}ATTR_Name_3" } let(:miq_task) { FactoryGirl.create(:miq_task) } @@ -111,9 +111,9 @@ MiqReport.new( :name => "Custom VM report", :title => "Custom VM report", :rpt_group => "Custom", :rpt_type => "Custom", :db => "ManageIQ::Providers::InfraManager::Vm", - :cols => %w(name virtual_custom_attribute_ATTR_Name_1 virtual_custom_attribute_ATTR_Name_2), + :cols => %w(name virtual_custom_attribute_kubernetes.io/hostname virtual_custom_attribute_manageiq.org), :include => {:custom_attributes => {}}, - :col_order => %w(name virtual_custom_attribute_ATTR_Name_1 virtual_custom_attribute_ATTR_Name_2), + :col_order => %w(name virtual_custom_attribute_kubernetes.io/hostname virtual_custom_attribute_manageiq.org), :headers => ["Name", custom_column_key_1, custom_column_key_1], :order => "Ascending" ) @@ -151,6 +151,7 @@ end expected_results = ["name" => vm_1.name, virtual_column_key_1 => custom_column_value, virtual_column_key_2 => nil] + expect(report_result).to match_array(expected_results) end From 931b45bbd8733d932e790187ee3d81037942681d Mon Sep 17 00:00:00 2001 From: lpichler Date: Tue, 14 Mar 2017 18:48:33 +0100 Subject: [PATCH 2/6] Escape special characters in value2tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Field with virtual custom attributes don’t contains associations so it don’t contain “.” as separator it has always form: -virtual_custom_attribute_ After this we need to escape it back because there was dynamic method created with unescaped form, and such method will be called in evaluation. --- lib/miq_expression.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/miq_expression.rb b/lib/miq_expression.rb index 8e877663dcd..52602aad36e 100644 --- a/lib/miq_expression.rb +++ b/lib/miq_expression.rb @@ -1047,8 +1047,19 @@ def self.preprocess_managed_tag(tag) tag end + def self.escape_virtual_custom_attribute(attribute) + if attribute.include?(CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX) + uri_parser = URI::RFC2396_Parser.new + [uri_parser.escape(attribute, /[^A-Za-z0-9:\-_]/), true] + else + [attribute, false] + end + end + def self.value2tag(tag, val = nil) + tag, virtual_custom_attribute = escape_virtual_custom_attribute(tag) model, *values = tag.to_s.gsub(/[\.-]/, "/").split("/") # replace model path ".", column name "-" with "/" + values.map!{ |x| URI::RFC2396_Parser.new.unescape(x) } if virtual_custom_attribute case values.first when "user_tag" From 695a51684d22ed0c0c43c8f86b78b5700718ba8a Mon Sep 17 00:00:00 2001 From: lpichler Date: Wed, 15 Mar 2017 14:39:46 +0100 Subject: [PATCH 3/6] =?UTF-8?q?Remove=20=E2=80=98/virtual/=E2=80=99=20by?= =?UTF-8?q?=20pattern=20with=20gsub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit before: ns= ‘/virtual/parent_resource_pool/name’ predicate = ns.split("/") => ["", "virtual", "parent_resource_pool", "name"] predicate = ns.split(“/“)[2..-1] # throw away /virtual => ["parent_resource_pool", "name"] after: (same) ns= ‘/virtual/parent_resource_pool/name’ ns.gsub!("/virtual/","") # throw away /virtual => ‘parent_resource_pool/name’ predicate = ns.split("/") => ["parent_resource_pool", "name"] --- lib/extensions/ar_taggable.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/extensions/ar_taggable.rb b/lib/extensions/ar_taggable.rb index b34330abd1a..b19dccaecd6 100644 --- a/lib/extensions/ar_taggable.rb +++ b/lib/extensions/ar_taggable.rb @@ -189,7 +189,8 @@ def tag_list(options = {}) def vtag_list(options = {}) ns = Tag.get_namespace(options) - predicate = ns.split("/")[2..-1] # throw away /virtual + ns.gsub!('/virtual/','') # throw away /virtual + predicate = ns.split('/') # p "ns: [#{ns}]" # p "predicate: [#{predicate.inspect}]" From 140e822e641fa172dbd6754e0d168ceabaf921a5 Mon Sep 17 00:00:00 2001 From: lpichler Date: Wed, 15 Mar 2017 14:41:05 +0100 Subject: [PATCH 4/6] Escape special characters only for virtual custom attributes --- lib/extensions/ar_taggable.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/extensions/ar_taggable.rb b/lib/extensions/ar_taggable.rb index b19dccaecd6..f241e1fb3ab 100644 --- a/lib/extensions/ar_taggable.rb +++ b/lib/extensions/ar_taggable.rb @@ -190,7 +190,9 @@ def vtag_list(options = {}) ns = Tag.get_namespace(options) ns.gsub!('/virtual/','') # throw away /virtual + ns, virtual_custom_attribute = MiqExpression.escape_virtual_custom_attribute(ns) predicate = ns.split('/') + predicate.map!{ |x| URI::RFC2396_Parser.new.unescape(x) } if virtual_custom_attribute # p "ns: [#{ns}]" # p "predicate: [#{predicate.inspect}]" From 993aef86f0eef691624651bfe29e5767a14544fc Mon Sep 17 00:00:00 2001 From: lpichler Date: Thu, 16 Mar 2017 16:55:36 +0100 Subject: [PATCH 5/6] Change REGEX for covering virtual custom attributes with special characters now there is allowed to have special characters as `-` and `.` `/` --- lib/miq_expression/field.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/miq_expression/field.rb b/lib/miq_expression/field.rb index ccb3a74d2fa..59ee3984e45 100644 --- a/lib/miq_expression/field.rb +++ b/lib/miq_expression/field.rb @@ -2,14 +2,19 @@ class MiqExpression::Field FIELD_REGEX = / (?([[:upper:]][[:alnum:]]*(::)?)+) \.?(?[a-z_\.]+)* --(?[a-z]+(_[[:alnum:]]+)*) +- +(?: + (?#{CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX}[a-z]+[_\-.\/[:alnum:]]*)| + (?[a-z]+(_[[:alnum:]]+)*) +) /x ParseError = Class.new(StandardError) def self.parse(field) match = FIELD_REGEX.match(field) or raise ParseError, field - new(match[:model_name].constantize, match[:associations].to_s.split("."), match[:column]) + new(match[:model_name].constantize, match[:associations].to_s.split("."), match[:virtual_custom_column] || + match[:column]) end attr_reader :model, :associations, :column From c5bf37f872076bac35f6deb19dc208ade12e5b5e Mon Sep 17 00:00:00 2001 From: lpichler Date: Thu, 16 Mar 2017 17:29:59 +0100 Subject: [PATCH 6/6] Escape special characters only for virtual custom attributes --- app/models/miq_report.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/miq_report.rb b/app/models/miq_report.rb index 6b507a637ce..c5e2c1e33ff 100644 --- a/app/models/miq_report.rb +++ b/app/models/miq_report.rb @@ -124,9 +124,13 @@ def self.display_filter_details(cols, mode) return [] if cols.nil? cols.inject([]) do |r, c| # eg. c = ["Host.Hardware.Disks : File Name", "Host.hardware.disks-filename"] - parts = c.last.split(".") + field = c.last + field, virtual_custom_attribute = MiqExpression.escape_virtual_custom_attribute(field) + parts = field.split(".") parts[-1] = parts.last.split("-").first # Strip off field name from last element + parts.map!{ |x| URI::RFC2396_Parser.new.unescape(x) } if virtual_custom_attribute + if parts.last == "managed" next(r) unless mode == :tag parts.pop # Remove "managed" from tail andjust just evaluate relationship