gitlab-org--gitlab-foss/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_example...

205 lines
7.0 KiB
Ruby

# frozen_string_literal: true
# This shared_example requires the following variables:
# - `service`, the service which includes AlertManagement::AlertProcessing
RSpec.shared_examples 'creates an alert management alert or errors' do
specify do
expect(subject).to be_success
expect(subject.payload).to match(alerts: all(a_kind_of(AlertManagement::Alert)))
end
it 'creates AlertManagement::Alert' do
expect(Gitlab::AppLogger).not_to receive(:warn)
expect { subject }.to change(AlertManagement::Alert, :count).by(1)
end
it 'executes the alert service hooks' do
expect_next_instance_of(AlertManagement::Alert) do |alert|
expect(alert).to receive(:execute_integrations)
end
subject
end
context 'and fails to save' do
before do
allow(AlertManagement::Alert).to receive(:new).and_wrap_original do |m, **args|
m.call(**args, hosts: ['a' * 256]) # hosts should be 255
end
end
it_behaves_like 'alerts service responds with an error', :bad_request
it 'writes a warning to the log' do
expect(Gitlab::AppLogger).to receive(:warn).with(
message: "Unable to create AlertManagement::Alert",
project_id: project.id,
alert_errors: { hosts: ['hosts array is over 255 chars'] },
alert_source: source
)
subject
end
end
end
RSpec.shared_examples 'handles race condition in alert creation' do
let(:other_alert) { create(:alert_management_alert, project: project) }
context 'when another alert is saved at the same time' do
before do
allow_next_instance_of(::AlertManagement::Alert) do |alert|
allow(alert).to receive(:save) do
other_alert.update!(fingerprint: alert.fingerprint)
raise ActiveRecord::RecordNotUnique
end
end
end
it 'finds the other alert and increments the counter' do
subject
expect(other_alert.reload.events).to eq(2)
end
end
context 'when another alert is saved before the validation runes' do
before do
allow_next_instance_of(::AlertManagement::Alert) do |alert|
allow(alert).to receive(:save).and_wrap_original do |method, *args|
other_alert.update!(fingerprint: alert.fingerprint)
method.call(*args)
end
end
end
it 'finds the other alert and increments the counter' do
subject
expect(other_alert.reload.events).to eq(2)
end
end
end
# This shared_example requires the following variables:
# - last_alert_attributes, last created alert
# - project, project that alert created
# - payload_raw, hash representation of payload
# - environment, project's environment
# - fingerprint, fingerprint hash
RSpec.shared_examples 'properly assigns the alert properties' do
specify do
subject
expect(last_alert_attributes).to match({
project_id: project.id,
title: payload_raw.fetch(:title),
started_at: Time.zone.parse(payload_raw.fetch(:start_time)),
severity: payload_raw.fetch(:severity, nil),
status: AlertManagement::Alert.status_value(:triggered),
events: 1,
domain: domain,
hosts: payload_raw.fetch(:hosts, nil),
payload: payload_raw.with_indifferent_access,
issue_id: nil,
description: payload_raw.fetch(:description, nil),
monitoring_tool: payload_raw.fetch(:monitoring_tool, nil),
service: payload_raw.fetch(:service, nil),
fingerprint: Digest::SHA1.hexdigest(fingerprint),
environment_id: environment.id,
ended_at: nil,
prometheus_alert_id: nil
}.with_indifferent_access)
end
end
RSpec.shared_examples 'does not create an alert management alert' do
specify do
expect { subject }.not_to change(AlertManagement::Alert, :count)
end
end
# This shared_example requires the following variables:
# - `alert`, the alert for which events should be incremented
RSpec.shared_examples 'adds an alert management alert event' do
specify do
expect(alert).not_to receive(:execute_integrations)
expect { subject }.to change { alert.reload.events }.by(1)
expect(subject).to be_success
expect(subject.payload).to match(alerts: all(a_kind_of(AlertManagement::Alert)))
end
it_behaves_like 'does not create an alert management alert'
end
# This shared_example requires the following variables:
# - `alert`, the alert for which events should not be incremented
RSpec.shared_examples 'does not add an alert management alert event' do
specify do
expect { subject }.not_to change { alert.reload.events }
end
end
RSpec.shared_examples 'processes new firing alert' do
include_examples 'processes never-before-seen alert'
context 'for an existing alert with the same fingerprint' do
let_it_be(:gitlab_fingerprint) { Digest::SHA1.hexdigest(fingerprint) }
context 'which is triggered' do
let_it_be(:alert) { create(:alert_management_alert, :triggered, fingerprint: gitlab_fingerprint, project: project) }
it_behaves_like 'adds an alert management alert event'
it_behaves_like 'sends alert notification emails if enabled'
it_behaves_like 'processes incident issues if enabled', with_issue: true
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not create a system note for alert'
context 'with an existing resolved alert as well' do
let_it_be(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: gitlab_fingerprint) }
it_behaves_like 'adds an alert management alert event'
it_behaves_like 'sends alert notification emails if enabled'
it_behaves_like 'processes incident issues if enabled', with_issue: true
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not create a system note for alert'
end
end
context 'which is acknowledged' do
let_it_be(:alert) { create(:alert_management_alert, :acknowledged, fingerprint: gitlab_fingerprint, project: project) }
it_behaves_like 'adds an alert management alert event'
it_behaves_like 'processes incident issues if enabled', with_issue: true
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not create a system note for alert'
it_behaves_like 'does not send alert notification emails'
end
context 'which is ignored' do
let_it_be(:alert) { create(:alert_management_alert, :ignored, fingerprint: gitlab_fingerprint, project: project) }
it_behaves_like 'adds an alert management alert event'
it_behaves_like 'processes incident issues if enabled', with_issue: true
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not create a system note for alert'
it_behaves_like 'does not send alert notification emails'
end
context 'which is resolved' do
let_it_be(:alert) { create(:alert_management_alert, :resolved, fingerprint: gitlab_fingerprint, project: project) }
include_examples 'processes never-before-seen alert'
end
end
end