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

Add timeline_options to expose event_streams OPTIONS to the API #21552

Merged
merged 1 commit into from
Nov 16, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
19 changes: 19 additions & 0 deletions app/models/ems_event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ class EmsEvent < EventStream
'Rename_Task',
]

def self.description
_("Management Events")
end

def self.group_names_and_levels
result = {:description => description}
event_groups.each_with_object(result) do |(group_name, group_details), hash|
hash[:group_names] ||= {}
hash[:group_names][group_name] = group_details[:name]

group_details.each_key do |level|
next if level == :name

hash[:group_levels] ||= {}
hash[:group_levels][level] ||= level.to_s.capitalize
end
end
end

def handle_event
EmsEventHelper.new(self).handle
rescue => err
Expand Down
18 changes: 18 additions & 0 deletions app/models/event_stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ class EventStream < ApplicationRecord

after_commit :emit_notifications, :on => :create

# TODO: Consider moving since this is EmsEvent specific. group, group_level and group_name exposed as a virtual columns for reports/api.
GROUP_LEVELS = %i(critical detail warning).freeze

def self.description
raise NotImplementedError, "Description must be implemented in a subclass"
end

def emit_notifications
Notification.emit_for_event(self)
rescue => err
_log.log_backtrace(err)
end

# TODO: Consider moving since this is EmsEvent specific. group, group_level and group_name exposed as a virtual columns for reports/api.
def self.event_groups
core_event_groups = ::Settings.event_handling.event_groups.to_hash
Settings.ems.each_with_object(core_event_groups) do |(_provider_type, provider_settings), event_groups|
Expand All @@ -56,6 +62,7 @@ def self.event_groups
end
end

# TODO: Consider moving since this is EmsEvent specific. group, group_level and group_name exposed as a virtual columns for reports/api.
def self.group_and_level(event_type)
level = :detail # the level is detail as default
egroups = event_groups
Expand All @@ -82,19 +89,30 @@ def self.group_name(group)
group.nil? ? 'Other' : group[:name]
end

# TODO: Consider moving since this is EmsEvent specific. group, group_level and group_name exposed as a virtual columns for reports/api.
def group
return @group unless @group.nil?
@group, @group_level = self.class.group_and_level(event_type)
@group
end

# TODO: Consider moving since this is EmsEvent specific. group, group_level and group_name exposed as a virtual columns for reports/api.
def group_level
return @group_level unless @group_level.nil?
@group, @group_level = self.class.group_and_level(event_type)
@group_level
end

# TODO: Consider moving since this is EmsEvent specific. group, group_level and group_name exposed as a virtual columns for reports/api.
def group_name
@group_name ||= self.class.group_name(group)
end

def self.timeline_classes
EventStream.subclasses.select { |e| e.respond_to?(:group_names_and_levels) }
end

def self.timeline_options
timeline_classes.map { |c| [c.name.to_sym, c.group_names_and_levels] }.to_h
Copy link
Member

Choose a reason for hiding this comment

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

Is this the only caller of timeline_classes? If so, then a) timeline_classes should be private and b) it might be cheaper to consolidate into something like:

Suggested change
timeline_classes.map { |c| [c.name.to_sym, c.group_names_and_levels] }.to_h
EventStream.subclasses.compact_map { |c| [c.name.to_sym, c.group_names_and_levels] if c.respond_to?(:group_names_and_levels) }.to_h

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, I can make it private.

I made it a method because timeline_classes describes what a class needs to do to implement timelines, namely, define group_names_and_levels. In the example b), it feels like we're mixing the concerns of "which classes support timelines" and "how to get the options for it".

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, no, I think it makes sense to be able to expose what classes support timelines.

end
end
11 changes: 11 additions & 0 deletions app/models/miq_event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ class MiqEvent < EventStream
ContainerReplicator, ContainerGroup, ContainerProject,
ContainerNode, ContainerImage, PhysicalServer].freeze

def self.description
_("Policy Events")
end

def self.group_names_and_levels
hash = {:description => description}
hash[:group_names] = MiqEventDefinitionSet.all.pluck(:name, :description).to_h.symbolize_keys
hash[:group_levels] = [MiqPolicy::CONDITION_SUCCESS, MiqPolicy::CONDITION_FAILURE].index_by { |c| c.downcase.to_sym }
hash
end

def self.raise_evm_event(target, raw_event, inputs = {}, options = {})
# Target may have been deleted if it's a worker
# Target, in that case will be the worker's server.
Expand Down
3 changes: 3 additions & 0 deletions app/models/miq_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class MiqPolicy < ApplicationRecord
PhysicalServer
Vm).freeze

CONDITION_SUCCESS = N_("Success")
CONDITION_FAILURE = N_("Failure")

def self.policy_towhat_applies_to_classes
TOWHAT_APPLIES_TO_CLASSES.index_with { |key| ui_lookup(:model => key) }
end
Expand Down
24 changes: 24 additions & 0 deletions spec/models/event_stream_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,28 @@
end
end
end

context "description" do
it "raises NotImplementedError, for subclasses to implement" do
expect { described_class.description }.to raise_error(NotImplementedError)
end
end

context "timeline_options" do
it "has correct structure" do
MiqEventDefinitionSet.seed
options = described_class.timeline_options
expect(options.keys.sort).to eq %i[EmsEvent MiqEvent]

expect(options[:EmsEvent].keys.sort).to eq %i[description group_levels group_names]
expect(options[:EmsEvent][:description]).to eq(EmsEvent.description)
expect(options[:EmsEvent][:group_levels].keys.sort).to eq %i[critical detail warning]
expect(options[:EmsEvent][:group_names].keys).to include(*%i[addition configuration console deletion devices])

expect(options[:MiqEvent].keys.sort).to eq %i[description group_levels group_names]
expect(options[:MiqEvent][:description]).to eq(MiqEvent.description)
expect(options[:MiqEvent][:group_levels].keys.sort).to eq %i[failure success]
expect(options[:MiqEvent][:group_names].keys).to include(*%i[auth_validation authentication compliance container_operations ems_operations evm_operations])
end
end
end