diff options
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.rb | 236 |
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 |