summaryrefslogtreecommitdiff
path: root/spec/services/alert_management/process_prometheus_alert_service_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/alert_management/process_prometheus_alert_service_spec.rb')
-rw-r--r--spec/services/alert_management/process_prometheus_alert_service_spec.rb236
1 files changed, 30 insertions, 206 deletions
diff --git a/spec/services/alert_management/process_prometheus_alert_service_spec.rb b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
index 9bd71ea6f64..86a6cdee52d 100644
--- a/spec/services/alert_management/process_prometheus_alert_service_spec.rb
+++ b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
@@ -5,38 +5,27 @@ require 'spec_helper'
RSpec.describe AlertManagement::ProcessPrometheusAlertService do
let_it_be(:project, reload: true) { create(:project, :repository) }
- before do
- allow(ProjectServiceWorker).to receive(:perform_async)
- end
+ let(:service) { described_class.new(project, payload) }
describe '#execute' do
- let(:service) { described_class.new(project, payload) }
- let(:source) { 'Prometheus' }
- let(:auto_close_incident) { true }
- let(:create_issue) { true }
- let(:send_email) { true }
- let(:incident_management_setting) do
- double(
- auto_close_incident?: auto_close_incident,
- create_issue?: create_issue,
- send_email?: send_email
- )
- end
+ include_context 'incident management settings enabled'
+
+ subject(:execute) { service.execute }
before do
- allow(service)
- .to receive(:incident_management_setting)
- .and_return(incident_management_setting)
+ stub_licensed_features(oncall_schedules: false, generic_alert_fingerprinting: false)
end
- subject(:execute) { service.execute }
-
context 'when alert payload is valid' do
- let(:parsed_payload) { Gitlab::AlertManagement::Payload.parse(project, payload, monitoring_tool: source) }
- let(:fingerprint) { parsed_payload.gitlab_fingerprint }
+ let_it_be(:starts_at) { '2020-04-27T10:10:22.265949279Z' }
+ let_it_be(:title) { 'Alert title' }
+ let_it_be(:fingerprint) { [starts_at, title, 'vector(1)'].join('/') }
+ let_it_be(:source) { 'Prometheus' }
+
+ let(:prometheus_status) { 'firing' }
let(:payload) do
{
- 'status' => status,
+ 'status' => prometheus_status,
'labels' => {
'alertname' => 'GitalyFileServerDown',
'channel' => 'gitaly',
@@ -46,196 +35,32 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
'annotations' => {
'description' => 'Alert description',
'runbook' => 'troubleshooting/gitaly-down.md',
- 'title' => 'Alert title'
+ 'title' => title
},
- 'startsAt' => '2020-04-27T10:10:22.265949279Z',
+ 'startsAt' => starts_at,
'endsAt' => '2020-04-27T10:20:22.265949279Z',
- 'generatorURL' => 'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1',
- 'fingerprint' => 'b6ac4d42057c43c1'
+ 'generatorURL' => 'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1'
}
end
- let(:status) { 'firing' }
-
- context 'when Prometheus alert status is firing' do
- context 'when alert with the same fingerprint already exists' do
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
-
- it_behaves_like 'adds an alert management alert event'
- it_behaves_like 'processes incident issues'
- it_behaves_like 'Alert Notification Service sends notification email'
-
- context 'existing alert is resolved' do
- let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
-
- it_behaves_like 'creates an alert management alert'
- it_behaves_like 'Alert Notification Service sends notification email'
- end
-
- context 'existing alert is ignored' do
- let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: fingerprint) }
-
- it_behaves_like 'adds an alert management alert event'
- it_behaves_like 'Alert Notification Service sends no notifications'
- end
-
- context 'existing alert is acknowledged' do
- let!(:alert) { create(:alert_management_alert, :acknowledged, project: project, fingerprint: fingerprint) }
-
- it_behaves_like 'adds an alert management alert event'
- it_behaves_like 'Alert Notification Service sends no notifications'
- end
-
- context 'two existing alerts, one resolved one open' do
- let!(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
-
- it_behaves_like 'adds an alert management alert event'
- it_behaves_like 'Alert Notification Service sends notification email'
- end
-
- context 'when auto-creation of issues is disabled' do
- let(:create_issue) { false }
-
- it_behaves_like 'does not process incident issues'
- end
-
- context 'when emails are disabled' do
- let(:send_email) { false }
-
- it_behaves_like 'Alert Notification Service sends no notifications'
- end
- end
-
- context 'when alert does not exist' do
- context 'when alert can be created' do
- it_behaves_like 'creates an alert management alert'
- it_behaves_like 'Alert Notification Service sends notification email'
- it_behaves_like 'processes incident issues'
-
- it_behaves_like 'creates single system note based on the source of the alert'
-
- context 'when auto-alert creation is disabled' do
- let(:create_issue) { false }
-
- it_behaves_like 'does not process incident issues'
- end
-
- context 'when emails are disabled' do
- let(:send_email) { false }
-
- it_behaves_like 'Alert Notification Service sends no notifications'
- end
- end
-
- context 'when alert cannot be created' do
- let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] })}
-
- before do
- allow(service).to receive(:alert).and_call_original
- allow(service).to receive_message_chain(:alert, :save).and_return(false)
- allow(service).to receive_message_chain(:alert, :errors).and_return(errors)
- end
-
- it_behaves_like 'Alert Notification Service sends no notifications', http_status: :bad_request
- it_behaves_like 'does not process incident issues due to error', http_status: :bad_request
-
- it 'writes a warning to the log' do
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Unable to create AlertManagement::Alert from Prometheus',
- project_id: project.id,
- alert_errors: { hosts: ['hosts array is over 255 chars'] }
- )
-
- execute
- end
- end
-
- it { is_expected.to be_success }
- end
- end
-
- context 'when Prometheus alert status is resolved' do
- let(:status) { 'resolved' }
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint, monitoring_tool: source) }
-
- context 'when auto_resolve_incident set to true' do
- context 'when status can be changed' do
- it_behaves_like 'Alert Notification Service sends notification email'
- it_behaves_like 'does not process incident issues'
-
- it 'resolves an existing alert without error' do
- expect(Gitlab::AppLogger).not_to receive(:warn)
- expect { execute }.to change { alert.reload.resolved? }.to(true)
- end
-
- it_behaves_like 'creates status-change system note for an auto-resolved alert'
-
- context 'existing issue' do
- let!(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint) }
-
- it 'closes the issue' do
- issue = alert.issue
-
- expect { execute }
- .to change { issue.reload.state }
- .from('opened')
- .to('closed')
- end
-
- it 'creates a resource state event' do
- expect { execute }.to change(ResourceStateEvent, :count).by(1)
- end
- end
- end
-
- context 'when status change did not succeed' do
- before do
- allow(AlertManagement::Alert).to receive(:for_fingerprint).and_return([alert])
- allow(alert).to receive(:resolve).and_return(false)
- end
-
- it 'writes a warning to the log' do
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Unable to update AlertManagement::Alert status to resolved',
- project_id: project.id,
- alert_id: alert.id
- )
-
- execute
- end
-
- it_behaves_like 'Alert Notification Service sends notification email'
- end
-
- it { is_expected.to be_success }
- end
+ it_behaves_like 'processes new firing alert'
- context 'when auto_resolve_incident set to false' do
- let(:auto_close_incident) { false }
+ context 'with resolving payload' do
+ let(:prometheus_status) { 'resolved' }
- it 'does not resolve an existing alert' do
- expect { execute }.not_to change { alert.reload.resolved? }
- end
-
- it_behaves_like 'creates single system note based on the source of the alert'
- end
-
- context 'when emails are disabled' do
- let(:send_email) { false }
-
- it_behaves_like 'Alert Notification Service sends no notifications'
- end
+ it_behaves_like 'processes recovery alert'
end
context 'environment given' do
let(:environment) { create(:environment, project: project) }
+ let(:alert) { project.alert_management_alerts.last }
- it 'sets the environment' do
+ before do
payload['labels']['gitlab_environment_name'] = environment.name
- execute
+ end
- alert = project.alert_management_alerts.last
+ it 'sets the environment' do
+ execute
expect(alert.environment).to eq(environment)
end
@@ -243,12 +68,14 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'prometheus alert given' do
let(:prometheus_alert) { create(:prometheus_alert, project: project) }
+ let(:alert) { project.alert_management_alerts.last }
- it 'sets the prometheus alert and environment' do
+ before do
payload['labels']['gitlab_alert_id'] = prometheus_alert.prometheus_metric_id
- execute
+ end
- alert = project.alert_management_alerts.last
+ it 'sets the prometheus alert and environment' do
+ execute
expect(alert.prometheus_alert).to eq(prometheus_alert)
expect(alert.environment).to eq(prometheus_alert.environment)
@@ -259,10 +86,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when alert payload is invalid' do
let(:payload) { {} }
- it 'responds with bad_request' do
- expect(execute).to be_error
- expect(execute.http_status).to eq(:bad_request)
- end
+ it_behaves_like 'alerts service responds with an error and takes no actions', :bad_request
end
end
end