Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map Amazon labels to tags #14436

Merged
merged 7 commits into from
Mar 27, 2017
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion app/models/ems_refresh/save_inventory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def save_vms_inventory(ems, hashes, target = nil)
[]
end

child_keys = [:operating_system, :hardware, :custom_attributes, :snapshots, :advanced_settings, :labels]
child_keys = [:operating_system, :hardware, :custom_attributes, :snapshots, :advanced_settings, :labels, :tags]
extra_infra_keys = [:host, :ems_cluster, :storage, :storages, :storage_profile, :raw_power_state, :parent_vm]
extra_cloud_keys = [
:flavor,
Expand Down Expand Up @@ -181,6 +181,26 @@ def save_vms_inventory(ems, hashes, target = nil)
end
end

# Convert all mapped hashes into actual tags and associate them with the object.
# The collection or collection[:tags] object should be an array of hashes, probably
# created by the ContainerLabelTagMapping.map_labels method. Each hash in the array
# should have the following basic structure:
#
# {:category_tag_id=>139, :entry_name=>"foo", :entry_description=>"bar"}
#
# The +collection+ argument can either be a Hash, in which case the argument
# should have a single :tags key, or a simple Array of hashes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little surprised you need to deal with {:tags => ...} form, IIUC ManageIQ/manageiq-providers-amazon#183 creates :labels and :tags on same level, you have :labels and :tags in child keys on same level, and save_child_inventory calls save_#{k}_inventory on hashes[k] so I'd expect save_tags_inventory to not see the :tags, just the value.

But I don't mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cben This is something we plan to refactor in the future, i.e. generate the tags on the core side rather than the refresher side.

#
def save_tags_inventory(object, collection, _target = nil)
return if collection.blank?
tags = collection.is_a?(Hash) ? collection[:tags] : collection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we actually use the Hash somewhere? The saving code should also pass it as a child, so collection[:tags] should be always passed, right?

ContainerLabelTagMapping.retag_entity(object, tags)
rescue => err
raise if EmsRefresh.debug_failures
_log.error("Auto-tagging failed on #{object.class} [#{object.name}] with error [#{err}].")
_log.log_backtrace(err)
end

def save_operating_system_inventory(parent, hash)
return if hash.nil?

Expand Down
12 changes: 1 addition & 11 deletions app/models/ems_refresh/save_inventory_container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def save_container_groups_inventory(ems, hashes, target = nil)
h[:container_node_id] = h.fetch_path(:container_node, :id)
h[:container_replicator_id] = h.fetch_path(:container_replicator, :id)
h[:container_project_id] = h.fetch_path(:project, :id)
h[:container_build_pod_id] = ems.container_build_pods.find_by(:name =>
h[:container_build_pod_id] = ems.container_build_pods.find_by(:name =>
h[:build_pod_name]).try(:id)
end

Expand Down Expand Up @@ -424,16 +424,6 @@ def save_docker_labels_inventory(entity, hashes, target = nil)
save_custom_attribute_attribute_inventory(entity, :docker_labels, hashes, target)
end

def save_tags_inventory(entity, hashes, _target = nil)
return if hashes.nil?

ContainerLabelTagMapping.retag_entity(entity, hashes) # Keeps user-assigned tags.
rescue => err
raise if EmsRefresh.debug_failures
_log.error("Auto-tagging failed on #{entity.class} [#{entity.name}] with error [#{err}].")
_log.log_backtrace(err)
end

def save_selector_parts_inventory(entity, hashes, target = nil)
return if hashes.nil?

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
context "save_tags_inventory" do
before(:each) do
@zone = FactoryGirl.create(:zone)
@ems = FactoryGirl.create(:ems_amazon, :zone => @zone)

@vm = FactoryGirl.create(:vm, :ext_management_system => @ems)
@node = FactoryGirl.create(:container_node, :ext_management_system => @ems)

@tag1 = FactoryGirl.create(:tag, :name => '/managed/amazon:vm:owner')
@tag2 = FactoryGirl.create(:tag, :name => '/managed/kubernetes:container_node:stuff')
@tag3 = FactoryGirl.create(:tag, :name => '/managed/kubernetes:foo') # All
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Completely doesn't matter in this test: An actual "All" mapping would use /managed/kubernetes::foo with double colon.]


@cat1 = FactoryGirl.create(:category, :description => 'amazon_vm_owner', :tag => @tag1)
@cat2 = FactoryGirl.create(:category, :description => 'department', :tag => @tag2)
@cat3 = FactoryGirl.create(:category, :description => 'location', :tag => @tag3)
end

# This is what ContainerLabelTagMapping.map_labels(cache, 'Type', labels) would
# return in the refresh parser. Note that we don't explicitly test the mapping
# creation here, the assumption is that these were the generated mappings.
#
let(:data) do
{:tags =>
[
{
:category_tag_id => @cat1.tag_id,
:entry_name => 'owner',
:entry_description => 'Daniel'
},
{
:category_tag_id => @cat2.tag_id,
:entry_name => 'stuff',
:entry_description => 'Ladas'
},
{
:category_tag_id => @cat3.tag_id,
:entry_name => 'foo',
:entry_description => 'Bronagh'
}
]
}
end

# Note that in these tests we're explicitly passing the object, so that's
# why the object type may not match what you would expect from the tag
# name type above.

it "creates the expected number of taggings" do
EmsRefresh.save_tags_inventory(@vm, data)
taggings = Tagging.all
expect(taggings.size).to eql(3)
expect(@vm.tags.size).to eql(3)
end

it "creates the expected taggings for a VM" do
EmsRefresh.save_tags_inventory(@vm, data)
taggings = Tagging.all
expect(taggings.all? { |e| e.taggable_id == @vm.id }).to be true
expect(taggings.map(&:taggable_type).all? { |e| e == 'VmOrTemplate' }).to be true
expect(@vm.tags.map(&:id).sort).to eql(taggings.map(&:tag_id).sort)
end

it "creates the expected taggings for a container node" do
EmsRefresh.save_tags_inventory(@node, data)
taggings = Tagging.all
expect(taggings.all? { |e| e.taggable_id == @node.id }).to be true
expect(taggings.map(&:taggable_type).all? { |e| e == 'ContainerNode' }).to be true
expect(@node.tags.map(&:id).sort).to eql(taggings.map(&:tag_id).sort)
end
end