Skip to content

Commit

Permalink
Fixes #36735 - Add a notication on RHEL lifecycle expiry
Browse files Browse the repository at this point in the history
  • Loading branch information
lfu committed Oct 6, 2023
1 parent 8199f33 commit 06cf003
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 42 deletions.
11 changes: 11 additions & 0 deletions app/jobs/create_host_lifecycle_expire_soon_notifications.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateHostLifecycleExpireSoonNotifications < ApplicationJob
def perform
Katello::UINotifications::Hosts::LifecycleExpireSoon.deliver!
ensure
self.class.set(:wait => 1.week).perform_later
end

def humanized_name
_('Host lifecycle support expiration notification')
end
end
16 changes: 0 additions & 16 deletions app/models/katello/concerns/host_managed_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -493,22 +493,6 @@ def rhel_lifecycle_status_label
@rhel_lifecycle_status_label ||= get_status(::Katello::RhelLifecycleStatus).to_label
end

def full_support_end_date
::Katello::RhelLifecycleStatus.full_support_end_dates[rhel_eos_schedule_index]
end

def maintenance_support_end_date
::Katello::RhelLifecycleStatus.maintenance_support_end_dates[rhel_eos_schedule_index]
end

def extended_support_end_date
::Katello::RhelLifecycleStatus.extended_support_end_dates[rhel_eos_schedule_index]
end

def end_of_support_date
::Katello::RhelLifecycleStatus.eos_date(eos_schedule_index: rhel_eos_schedule_index)
end

def traces_status
@traces_status ||= get_status(::Katello::TraceStatus).status
end
Expand Down
10 changes: 9 additions & 1 deletion app/models/katello/rhel_lifecycle_status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,15 @@ def self.status_map
end

def self.approaching_end_of_category(eos_schedule_index:)
RHEL_EOS_SCHEDULE[eos_schedule_index].select { |_k, v| (Time.now.utc..Time.now.utc + EOS_WARNING_THRESHOLD).cover?(v) }
lifecycles_expire_soon[eos_schedule_index]
end

def self.lifecycles_expire_soon
expiring = RHEL_EOS_SCHEDULE.collect do |index, schedules|
expire_soon = schedules.except("full_support").select { |_k, v| (Time.now.utc..Time.now.utc + EOS_WARNING_THRESHOLD).cover?(v) }
{index => expire_soon} if expire_soon.present?
end
expiring.compact.reduce(:update) || {}
end

def self.to_status(rhel_eos_schedule_index: nil)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module Katello
module UINotifications
module Hosts
class LifecycleExpireSoon
def self.deliver!
::Katello::RhelLifecycleStatus.lifecycles_expire_soon.each do |release, schedule|
schedule.each do |lifecycle, end_date|
count = hosts_with_index(release).count
next if count == 0

message = message(count: count, release: release, lifecycle: lifecycle, end_date: end_date)
if (notification = existing_notification(release))
/[^:]+: (?<number_of_hosts>\d+) hosts/ =~ notification.message
next if number_of_hosts == count.to_s
notification.update(message: message)
else
::Notification.create!(
:initiator => User.anonymous_admin,
:audience => Notification::AUDIENCE_GLOBAL,
:message => message,
:expired_at => end_date.strftime('%Y-%m-%d'),
:notification_blueprint => blueprint
)
end
end
end
end

def self.existing_notification(release)
blueprint.notifications.where("message like ?", "#{release}%").first
end

def self.message(options)
::UINotifications::StringParser.new(
blueprint.message,
:number_of_hosts => options[:count],
:release => options[:release],
:lifecycle => options[:lifecycle].gsub(/_/, " "),
:end_date => options[:end_date].strftime('%Y-%m-%d'),
:audience => Notification::AUDIENCE_GLOBAL
)
end

def self.hosts_with_index(release)
/RHEL(?<major>\d+)/ =~ release
::Host::Managed.joins(:operatingsystem, :fact_values, :fact_names)
.where(fact_names: {name: "distribution::name"})
.where("fact_values.value like ?", "Red Hat Enterprise Linux%")
.where(operatingsystem: {major: major})
end

def self.blueprint
@blueprint ||= NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon')
end
end
end
end
end
6 changes: 6 additions & 0 deletions db/seeds.d/109-katello-notification-blueprints.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
blueprints = [
{
group: N_('Hosts'),
name: 'host_lifecycle_expire_soon',
message: N_('%{release}: %{number_of_hosts} hosts are approaching end of %{lifecycle} on %{end_date}. Please upgrade them before support expires. Check Report Host - Statuses for detail.'),
level: 'warning'
},
{
group: N_('Proxies'),
name: 'pulp_low_disk_space',
Expand Down
2 changes: 1 addition & 1 deletion lib/katello/scheduled_jobs.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# First, we check if there's a job already enqueued for any notifications
::Foreman::Application.dynflow.config.on_init do |world|
[CreateExpiredManifestNotifications, CreatePulpDiskSpaceNotifications, SendExpireSoonNotifications].each do |job_class|
[CreateExpiredManifestNotifications, CreateHostLifecycleExpireSoonNotifications, CreatePulpDiskSpaceNotifications, SendExpireSoonNotifications].each do |job_class|
job_class.spawn_if_missing(world)
end
end
24 changes: 0 additions & 24 deletions test/models/concerns/host_managed_extensions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -459,30 +459,6 @@ def test_rhel_eos_schedule_index_non_rhel
host.expects(:facts).returns({'distribution::name' => 'CentOS Stream'})
assert_nil host.rhel_eos_schedule_index
end

def test_full_support_end_dates
host.expects(:rhel_eos_schedule_index).returns('RHEL9')
expected_date = ::Katello::RhelLifecycleStatus.full_support_end_dates['RHEL9']
assert_equal expected_date, host.full_support_end_date
end

def test_maintenance_support_end_dates
host.expects(:rhel_eos_schedule_index).returns('RHEL9')
expected_date = ::Katello::RhelLifecycleStatus.maintenance_support_end_dates['RHEL9']
assert_equal expected_date, host.maintenance_support_end_date
end

def test_extended_support_end_dates
host.expects(:rhel_eos_schedule_index).returns('RHEL9')
expected_date = ::Katello::RhelLifecycleStatus.extended_support_end_dates['RHEL9']
assert_equal expected_date, host.extended_support_end_date
end

def test_end_of_support_dates
host.expects(:rhel_eos_schedule_index).returns('RHEL9')
expected_date = ::Katello::RhelLifecycleStatus.eos_date(eos_schedule_index: 'RHEL9')
assert_equal expected_date, host.end_of_support_date
end
end

class HostManagedExtensionsKickstartTest < ActiveSupport::TestCase
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
require 'katello_test_helper'

# 'RHEL9' => {
# 'maintenance_support' => end_of_day('2032-05-31'),
# 'extended_support' => end_of_day('2035-05-31')
# },
# 'RHEL8' => {
# 'maintenance_support' => end_of_day('2029-05-31'),
# 'extended_support' => end_of_day('2032-05-31')
# },
# 'RHEL7' => {
# 'maintenance_support' => end_of_day('2024-06-30'),
# 'extended_support' => end_of_day('2028-06-30')
# },
# 'RHEL6' => {
# 'maintenance_support' => end_of_day('2020-11-30'),
# 'extended_support' => end_of_day('2024-06-30')
# },

module Katello
module UINotifications
module Hosts
class LifecycleExpireSoonTest < ::ActiveSupport::TestCase
def setup
blueprint = FactoryBot.create(:notification_blueprint, :name => 'host_lifecycle_expire_soon')
@subject = Katello::UINotifications::Hosts::LifecycleExpireSoon
@subject.stubs(:blueprint).returns(blueprint)
end

def teardown
NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.destroy_all
end

def test_with_year_2024_1_1
Time.stubs(:now).returns(Time.utc(2024, 1, 1))
@subject.expects(:hosts_with_index).with("RHEL6").returns([mock('rhel6')])
@subject.expects(:hosts_with_index).with("RHEL7").returns([mock('rhel7')])
@subject.deliver!
assert_equal 2, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2025_1_1
Time.stubs(:now).returns(Time.utc(2025, 1, 1))
@subject.deliver!
assert_equal 0, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2026_6_1
Time.stubs(:now).returns(Time.utc(2026, 6, 1))
@subject.deliver!
assert_equal 0, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2027_7_1
Time.stubs(:now).returns(Time.utc(2027, 7, 1))
@subject.expects(:hosts_with_index).with("RHEL7").returns([mock('rhel7')])
@subject.deliver!
assert_equal 1, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2028_6_1
Time.stubs(:now).returns(Time.utc(2028, 6, 1))
@subject.expects(:hosts_with_index).with("RHEL7").returns([mock('rhel7')])
@subject.expects(:hosts_with_index).with("RHEL8").returns([mock('rhel8')])
@subject.deliver!
assert_equal 2, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2029_6_1
Time.stubs(:now).returns(Time.utc(2029, 6, 1))
@subject.deliver!
assert_equal 0, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2030_6_1
Time.stubs(:now).returns(Time.utc(2030, 6, 1))
@subject.deliver!
assert_equal 0, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end

def test_with_year_2031_6_1
Time.stubs(:now).returns(Time.utc(2031, 6, 1))
@subject.expects(:hosts_with_index).with("RHEL8").returns([mock('rhel8')])
@subject.expects(:hosts_with_index).with("RHEL9").returns([mock('rhel9')])
@subject.deliver!
assert_equal 2, NotificationBlueprint.find_by(name: 'host_lifecycle_expire_soon').notifications.count
end
end
end
end
end

0 comments on commit 06cf003

Please sign in to comment.