-
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
Event parser can parse new format of target #160
Event parser can parse new format of target #160
Conversation
@durandom @kbrock @agrare @blomquisg @Fryguy so this is how the new target format could look like, so we don;t require a Target being created in our DB {"Vm" => {:manager_id => ems_id, :manager_ref => Set.new({:ems_ref => xy}, {:ems_ref => zz}) }} It would be probably worth to pack this to ManagerRefresh::Target, where .serialize would return the ^ hash, so it can be queued to the refresh and we could then get it back with ManagerRefresh::Target.new(class, manager_id:, manager_ref: , ..) then you could always get the records connected to the Target with: or any other way, which would be more effective, though we should not need to really instantiate it ourselves |
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 think it would be great if you could extract the parsing stuff into its own class.
For starters it could live here and be called Target
although this is probably not the final name.
Then you can write a spec for that object and not convolute the other specs
_guid, _server, zone = EvmSpecHelper.create_guid_miq_server_zone | ||
@ems = FactoryGirl.create(:ems_amazon, :zone => zone) | ||
|
||
allow_any_instance_of(EmsEvent).to receive(:handle_event) |
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.
allow_any_instance_of
is the root of all evil. Chris and JoeR try hard to get eliminate it. Can do without it? Maybe inject an instance of EmsEvent into somewhere?
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.
sure we can get rid of that if we will rewrite the code. The EmsEvent.add needs to have submethods, now it's all entangled together.
|
||
case event.full_data["event_source"] | ||
when :cloud_watch_api | ||
collect_cloudwatch_api_references!(available_targets, event.full_data.fetch_path("detail", "requestParameters") || {}) |
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.
all those bang methods. It's hard to tell what they actually modify.
This screams for extraction of an object 🛠
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.
well they do build available_targets
raise "Unsupported event source #{event["event_source"]}" | ||
end | ||
|
||
send("parse_#{event["event_source"]}_event!", event, event_hash) |
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.
chilly bang bang. What is modified by this method?
It would be much easier to follow if you return the modified version and assign it.
event_hash = send("parse_#{event["event_source"]}_event", event)
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.
but I just saw, this is already in the code :/
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.
yeah this would be probably nicer
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.
sigh
I like the Could you explain a bit, when and how this logic is triggered? |
@durandom so this logic is not trigered yet, but the workflow should be
|
Adding class for parsing targets from an Event
Adding specs for EmsEvent Target parsing
c7a8076
to
a84469f
Compare
@Ladas 🤘 for creating all in new classes |
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.
great iteration
next step should be the EventTarget
class extraction
And I still need to understand how this will be used when picked later from the event queue
|
||
context "AWS Config Event" do | ||
it "parses vm_ems_ref into event" do | ||
ems_event = create_ems_event("sqs_message.json") |
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.
Still, I would create an EmsEvent
via a factory here and not test the whole EmsEvent Stream stack.
But I get your integration spec needs. But shouldnt those parts of the code already be tested somewhere else?
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 really want to test this on real events, so using the actual jsons of the event. I don't really want to stub the middlelayers. I want to add like 40-80 main events for testing, would be dull and error prone to do the double stubbing
@@ -0,0 +1,139 @@ | |||
class ManageIQ::Providers::Amazon::CloudManager::EventTargetParser |
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.
👍 for this class
Now extract another class, e.g. EventTarget
which holds add_reference
and the available_targets
data. Then you have fully encapsulated that data you want to transport into a class and moved away from hashes.
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, ManagerRefresh::Target and ManagerRefresh::TargetCollection are being introduced as a dependency
Change EventTargetParser to use the ManagerRefresh target abstractions
Use ManagerRefresh::TargetCollection instead of the Amazon one
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.
this is looking nice.
I got the general idea behind this. My comments are only cosmetic
def collect_config_references!(target_collection, event_data) | ||
resource_type = event_data.fetch_path("configurationItem", "resourceType") | ||
resource_id = event_data.fetch_path("configurationItem", "resourceId") | ||
target_class = case resource_type |
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.
would it make sense to do a hash lookup here?
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.
possibly, but maybe the case is enough? Should be still pretty quick
end | ||
byebug |
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.
heh
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.
yaay :-)
collect_cloudwatch_api_references!(target_collection, x, depth + 1) | ||
end | ||
(event_data.fetch_path("instances") || []).each do |x| | ||
collect_cloudwatch_api_references!(target_collection, x, depth + 1) |
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.
would it make sense to expand this api? collect_cloud_watch_api_referenceses!
of course, naming is hard. Then again, do you ever collect_cloudwatch_api_references
with a single array?
collect_cloud_watch_api_referenceses!(target_collection, event_data.fetch_path("instances") || [], depth + 1)
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.
no usually the cloudwatch events have a nested arrays that contain references
@@ -30,49 +30,21 @@ def initialize(_manager, _target) | |||
|
|||
def initialize_inventory_sources | |||
@instances = [] | |||
@instances_refs = Set.new |
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.
yay.
I'm assuming this doesn't add any O(N) lookups
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.
the refs were moved to ManagerRefresh::TargetCollection
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.
Ooh, then that is very cool
end | ||
|
||
def infer_related_ems_refs! | ||
# We have a list of instances_refs collected from events. Now we want to look into our DB and API, and collect | ||
# ems_refs of every related object. Now this is not very nice fro ma design point of view, but we really want | ||
# to see changes in VM's associated objects, so the VM view is always consistent and have fresh data. The partial | ||
# reason for this is, that AWS doesn't send all the objects state change, | ||
changed_vms = manager.vms.where(:ems_ref => instances_refs.to_a).includes(:key_pairs, :network_ports, :floating_ips, | ||
:orchestration_stack) | ||
byebug |
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.
heh
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.
hehe
@@ -24,6 +24,10 @@ def initialize_inventory_collections | |||
|
|||
private | |||
|
|||
def references(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.
is this a generic method?
Can you get define it in somewhere like ManagerRefresh::Inventory::Collector
or highter?
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.
right, it's not really generic since it states :ems_ref, but maybe I could pack part of it to the TargetCollection
…Persister Use ManagerRefresh::TargetCollection collection for TargetCollection Persister
…Collector Use ManagerRefresh::TargetCollection collection for TargetCollection Collector
2d68ec5
to
f67259d
Compare
add_target! method was renamed to add_target
Fix EventTargetParser specs, it's broken due to core changes
Some comments on commits Ladas/manageiq-providers-amazon@308e47b~...50ee99e spec/models/manageiq/providers/amazon/cloud_manager/event_target_parser_spec.rb
|
Checked commits Ladas/manageiq-providers-amazon@308e47b~...50ee99e with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0 |
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.
👍 except for some refactoring suggestions
# | ||
# @return [Array] Array of ManagerRefresh::Target objects | ||
def parse | ||
parse_ems_event_targets(ems_event) |
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.
Now that you add ems_event
as a state (instance variable), I think you can also create target_collection
as an instance var and let collect_cloudwatch_api_references
operate on that.
attr_reader :load_balancers, :load_balancers_refs, :load_balancers_deleted | ||
attr_reader :stacks, :stacks_refs, :stacks_deleted | ||
attr_reader :cloud_volumes, :cloud_volumes_refs | ||
attr_reader :cloud_volume_snapshots, :cloud_volume_snapshots_refs |
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.
👏 for less attr_reader
s
@@ -3,24 +3,30 @@ def initialize(_manager, _target) | |||
super | |||
parse_targets! | |||
infer_related_ems_refs! | |||
|
|||
target.manager_refs_by_association_reset |
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.
This would be a perfect !
method
def parse_vm_target!(t) | ||
instances_refs << t.ems_ref if t.ems_ref | ||
target.add_target(:association => :vms, :manager_ref => {:ems_ref => t.ems_ref}) if t.ems_ref |
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.
If this is mostly always target.add_target
, you might also allow target.add
syntax
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.
How about renaming this to targets
or target_collection
Depends on:
Event parser can parse new format of target + specs