-
Notifications
You must be signed in to change notification settings - Fork 107
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
Implement tag mapping in graph refresh #382
Conversation
@juliancheal @Ladas This is still WIP but I think something like this... Depends on couple core changes: ManageIQ/manageiq#16734 |
rebased |
} | ||
|
||
attributes[:targeted_arel] = lambda do |inventory_collection| | ||
ids = inventory_collection.parent_inventory_collections.collect_concat(&:id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to "simplify" this to something like I did containers and avoid going through Vm.vm_and_template_taggings relation, just because it scared me.
But add_inventory_collection
requires :association => :foos
to be set, this determines the name of the persister.foos
accessor to the collection :-(
Anyway, now that I added that relation in ManageIQ/manageiq#16734 I should probably do what vm_and_template_labels does...
} | ||
|
||
attributes[:targeted_arel] = lambda do |inventory_collection| | ||
ids = inventory_collection.parent_inventory_collections.collect_concat(&:id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ids are not available here yet, so we need to use
manager_uuids = inventory_collection.parent_inventory_collections.collect(&:manager_uuids).map(&:to_a).flatten
manager uuids are :ems_ref columns of Vm in this case. So we need a nested query that transforms that to ids
ids = inventory_collection.parent_inventory_collections.collect_concat(&:id) | ||
Tagging.where( | ||
'taggable_type' => 'VmOrTemplate', | ||
'taggable_id' => ids |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so then here it would be
'taggable_id' => inventory_collection.parent.vm_and_templates.where(:ems_ref => manager_uuids)
Tagging.where( | ||
'taggable_type' => 'VmOrTemplate', | ||
'taggable_id' => ids | ||
).joins(:tag).merge(Tag.controlled_by_mapping) | ||
'taggable_id' => ems.vm_and_template_taggings.where(:ems_ref => manager_uuids) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just
ems.vm_and_templates.where(:ems_ref => manager_uuids)
since the manager uuids are fro ma table VmOrTemplate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, fixed
@@ -32,6 +33,7 @@ | |||
end | |||
|
|||
assert_common | |||
assert_mapped_tags_on_vm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we move this inside of the specific Vms asserts?
Especially assert_specific_vm_powered_on, assert_specific_vm_on_cloud_network_public_ip and assert_specific_vm_on_cloud_network
That way it will be automatically tested in old, new and targeted refresh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done for vms
For templates the only label I found at all is Name
😐
and both assert_specific_template*
have 0 labels (not even Name
) so only calling this function explicitly in some tests.
This means targeted image taggings refresh is not well tested.
# expect(vm.tags).to be_empty | ||
# end | ||
def assert_specific_labels_on_vm | ||
vm = ManageIQ::Providers::Amazon::CloudManager::Vm.find_by(:name => "ladas_test_5") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are usually testing only Vms having EmsRefreshSpec prefix, those are the ones nobody is touching (so we can re-record VCR easily)
# The order of the below methods doesn't matter since they refer to each other using only lazy links | ||
persister.collections[:tags_to_resolve] = @tag_mapper.tags_to_resolve_collection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool, you already use custom IC here, I was about to ask about it :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cben could we move the IC definition into the defaults, and the init into the Persitors? Like we do with :vm_and_template_taggings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could. Note that constructing the Mapper actually reads whole mappings table.
- Is it OK to do it each Persister initialization?
- Will it still be re-read each refresh? (eg. if it's only read once when refresh worker starts that would be bad, changing mapping would have no effect).
- Conversely, can re-reading it each targetted refresh be a performance problem?
- Will Persister initialization remain a good place with collector/persister split?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hum, ok, if it reads the whole mapping table, I will need to look on it more closely tomorrow. We will need to limit it only to Vms and Templates that are part of the targeted refresh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Is it OK to do it each Persister initialization?
Right now that would be the same as having it in parser, that is being called each refresh
- Will it still be re-read each refresh? (eg. if it's only read once when refresh worker starts that would be bad, changing mapping would have no effect).
Yes, right now, the persister defines ICs dynamically (that might change in the future, as some providers use static definition, but there can be always a dynamic part)
- Conversely, can re-reading it each targetted refresh be a performance problem?
Yes looking at this, it will definitely hit targeted refresh performance, with huge amount of tags present
- Will Persister initialization remain a good place with collector/persister split?
There will be some refactoring of the format, but the Persistor should remain mostly the same.
Hooray! I was stuck on mysterious hardware,disk,network count mismatches, turned out I dropped a line in merging conflicts 🤦♂️ |
PTAL. Added images, addressed most comments, except #382 (comment)
|
@cben yes, another copy of assert_specific_vm_powered_on. I think the specs are great now, we can ignore the other region specs |
# The order of the below methods doesn't matter since they refer to each other using only lazy links | ||
persister.collections[:tags_to_resolve] = @tag_mapper.tags_to_resolve_collection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cben ok, so continuing from #382 (comment)
lets move this to persister init, we can put shared method to ManageIQ::Providers::Amazon::Inventory::Persister and just call it in Cloud and TargetCollection Persisters for now
And we should there add a TODO for perf, that this will always load all ContainerLabelTagMapping (or other?). But this table is fairly small? It's the Tagging that is huge, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mapper init is reading ContainerLabelTagMapping.all. It's fairly small, 1 per mapping defined in UI, independent of inventory size and number of tags created/assigned.
Moving...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was about to ask about TargetCollection then saw you already anticipated that :-)
Done, PTAL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cben so lets just move the code as stated in https://github.com/ManageIQ/manageiq-providers-amazon/pull/382/files#r159611330
and I think we can merge. Just confirm that we are not loading the hugest table please. :-)
I believe the "targeting" of the targeted_arel is not really tested. It does create the expected taggings, but are we sure it doesn't delete other taggings? Targeted query, as diff from normal SELECT "taggings".* FROM "taggings"
INNER JOIN "tags" ON "tags"."id" = "taggings"."tag_id"
LEFT OUTER JOIN "classifications" ON "classifications"."tag_id" = "tags"."id"
INNER JOIN "vms" ON "taggings"."taggable_id" = "vms"."id"
WHERE "vms"."ems_id" = 12000000009214
AND "taggings"."taggable_type" = 'VmOrTemplate'
AND (("tags"."name" LIKE '/managed/amazon:%') OR ("tags"."name" LIKE '/managed/kubernetes:%'))
AND "classifications"."read_only" = 't'
AND ("classifications"."parent_id" != 0)
+ AND "taggings"."taggable_type" = 'VmOrTemplate'
+ AND "taggings"."taggable_id" IN (SELECT "vms"."id" FROM "vms" WHERE "vms"."ems_id" = 12000000009214) UPDATE: was a bug, fix below |
Hmm, that last SELECT seems wrong! I don't see a The |
Unneccessary for same reason as in vm_and_template_labels targeted_arel. Already covered by ems.vms_and_templates, which is :through => :vms_and_templates.
Was querying taggings of ALL vms, which would make targeted refresh delete most taggings.
Checked commits cben/manageiq-providers-amazon@6141841~...688cf2f with ruby 2.3.3, rubocop 0.47.1, haml-lint 0.20.0, and yamllint 1.10.0 app/models/manageiq/providers/amazon/inventory_collection_default/cloud_manager.rb
|
OK, this was silly. Turns out The reason associations accept args at all is side effect of a deprecated interface, good thing it's going away:
Fixed targeted query, again as diff from SELECT "taggings".* FROM "taggings"
INNER JOIN "tags" ON "tags"."id" = "taggings"."tag_id"
LEFT OUTER JOIN "classifications" ON "classifications"."tag_id" = "tags"."id"
INNER JOIN "vms" ON "taggings"."taggable_id" = "vms"."id"
WHERE "vms"."ems_id" = 12000000010061
AND "taggings"."taggable_type" = 'VmOrTemplate'
AND (("tags"."name" LIKE '/managed/amazon:%') OR ("tags"."name" LIKE '/managed/kubernetes:%'))
AND "classifications"."read_only" = 't'
AND ("classifications"."parent_id" != 0)
+ AND "taggings"."taggable_id" IN (SELECT "vms"."id" FROM "vms"
+ WHERE "vms"."ems_id" = 12000000010061
+ AND "vms"."ems_ref" IN ('i-c72af2f6', 'ami-2051294a')) I think this supports the need for a targeted-after-full-doesn't-delete spec :-), but will leave that to you. |
@@ -193,7 +193,7 @@ def vm_and_template_taggings(extra_attributes = {}) | |||
manager_uuids = inventory_collection.parent_inventory_collections.collect(&:manager_uuids).map(&:to_a).flatten | |||
ems = inventory_collection.parent | |||
ems.vm_and_template_taggings.where( | |||
'taggable_id' => ems.vms_and_templates(:ems_ref => manager_uuids) | |||
'taggable_id' => ems.vms_and_templates.where(:ems_ref => manager_uuids) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah :-o
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha that'll do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @cben this is awesome work. 👍 🥇 🎉
You are right, we should have specs to make sure targeted refresh doesn't delete anything out of it's scope. I think we can do simple spec just by combining existing full refresh with each targeted refresh spec we have. (so using existing VCRs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 thanks @cben !!
👍 thanks @cben |
Implement tag mapping in graph refresh (cherry picked from commit 53cc7b0) https://bugzilla.redhat.com/show_bug.cgi?id=1531291
Gaprindashvili backport details:
|
Subsumes #384, done with lots of help from Ladislav & Julian 🌍
https://bugzilla.redhat.com/show_bug.cgi?id=1506404
cc @bronaghs @djberg96 @Ladas @agrare (in case anybody still here, and happy holidays)