diff options
Diffstat (limited to 'spec/services/projects/alerting/notify_service_spec.rb')
-rw-r--r-- | spec/services/projects/alerting/notify_service_spec.rb | 258 |
1 files changed, 63 insertions, 195 deletions
diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb index c272ce13132..feae8f3967c 100644 --- a/spec/services/projects/alerting/notify_service_spec.rb +++ b/spec/services/projects/alerting/notify_service_spec.rb @@ -3,77 +3,49 @@ require 'spec_helper' RSpec.describe Projects::Alerting::NotifyService do - let_it_be_with_reload(:project) { create(:project, :repository) } + let_it_be_with_reload(:project) { create(:project) } + + let(:payload) { ActionController::Parameters.new(payload_raw).permit! } + let(:payload_raw) { {} } + + let(:service) { described_class.new(project, payload) } before do - allow(ProjectServiceWorker).to receive(:perform_async) + stub_licensed_features(oncall_schedules: false, generic_alert_fingerprinting: false) end describe '#execute' do - let(:token) { 'invalid-token' } - let(:starts_at) { Time.current.change(usec: 0) } - let(:fingerprint) { 'testing' } - let(:service) { described_class.new(project, payload) } - let_it_be(:environment) { create(:environment, project: project) } - let(:environment) { create(:environment, project: project) } - let(:ended_at) { nil } - let(:payload_raw) do - { - title: 'alert title', - start_time: starts_at.rfc3339, - end_time: ended_at&.rfc3339, - severity: 'low', - monitoring_tool: 'GitLab RSpec', - service: 'GitLab Test Suite', - description: 'Very detailed description', - hosts: ['1.1.1.1', '2.2.2.2'], - fingerprint: fingerprint, - gitlab_environment_name: environment.name - }.with_indifferent_access - end + include_context 'incident management settings enabled' - let(:payload) { ActionController::Parameters.new(payload_raw).permit! } + subject { service.execute(token, integration) } - subject { service.execute(token, nil) } + context 'with HTTP integration' do + let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project) } - shared_examples 'notifications are handled correctly' do context 'with valid token' do let(:token) { integration.token } - let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled, auto_close_incident?: auto_close_enabled) } - let(:email_enabled) { false } - let(:issue_enabled) { false } - let(:auto_close_enabled) { false } - - before do - allow(service) - .to receive(:incident_management_setting) - .and_return(incident_management_setting) - end context 'with valid payload' do - shared_examples 'assigns the alert properties' do - it 'ensure that created alert has all data properly assigned' 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), - status: AlertManagement::Alert.status_value(:triggered), - events: 1, - domain: 'operations', - hosts: payload_raw.fetch(:hosts), - payload: payload_raw.with_indifferent_access, - issue_id: nil, - description: payload_raw.fetch(:description), - monitoring_tool: payload_raw.fetch(:monitoring_tool), - service: payload_raw.fetch(:service), - fingerprint: Digest::SHA1.hexdigest(fingerprint), - environment_id: environment.id, - ended_at: nil, - prometheus_alert_id: nil - ) - end + let_it_be(:environment) { create(:environment, project: project) } + let_it_be(:fingerprint) { 'testing' } + let_it_be(:source) { 'GitLab RSpec' } + let_it_be(:starts_at) { Time.current.change(usec: 0) } + + let(:ended_at) { nil } + let(:domain) { 'operations' } + let(:payload_raw) do + { + title: 'alert title', + start_time: starts_at.rfc3339, + end_time: ended_at&.rfc3339, + severity: 'low', + monitoring_tool: source, + service: 'GitLab Test Suite', + description: 'Very detailed description', + hosts: ['1.1.1.1', '2.2.2.2'], + fingerprint: fingerprint, + gitlab_environment_name: environment.name + }.with_indifferent_access end let(:last_alert_attributes) do @@ -82,8 +54,8 @@ RSpec.describe Projects::Alerting::NotifyService do .with_indifferent_access end - it_behaves_like 'creates an alert management alert' - it_behaves_like 'assigns the alert properties' + it_behaves_like 'processes new firing alert' + it_behaves_like 'properly assigns the alert properties' it 'passes the integration to alert processing' do expect(Gitlab::AlertManagement::Payload) @@ -94,101 +66,18 @@ RSpec.describe Projects::Alerting::NotifyService do subject end - it 'creates a system note corresponding to alert creation' do - expect { subject }.to change(Note, :count).by(1) - expect(Note.last.note).to include(payload_raw.fetch(:monitoring_tool)) - end - - context 'existing alert with same fingerprint' do - let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) } - let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) } - - it_behaves_like 'adds an alert management alert event' - - context 'end time given' do - let(:ended_at) { Time.current.change(nsec: 0) } - - it 'does not resolve the alert' do - expect { subject }.not_to change { alert.reload.status } - end - - it 'does not set the ended at' do - subject - - expect(alert.reload.ended_at).to be_nil - end - - it_behaves_like 'does not an create alert management alert' - it_behaves_like 'creates single system note based on the source of the alert' - - context 'auto_close_enabled setting enabled' do - let(:auto_close_enabled) { true } - - it 'resolves the alert and sets the end time', :aggregate_failures do - subject - alert.reload - - expect(alert.resolved?).to eq(true) - expect(alert.ended_at).to eql(ended_at) - end - - it_behaves_like 'creates status-change system note for an auto-resolved alert' - - context 'related issue exists' do - let(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) } - let(:issue) { alert.issue } - - it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') } - it { expect { subject }.to change(ResourceStateEvent, :count).by(1) } - end - - context 'with issue enabled' do - let(:issue_enabled) { true } - - it_behaves_like 'does not process incident issues' - end - end - end - - context 'existing alert is resolved' do - let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) } - - it_behaves_like 'creates an alert management alert' - it_behaves_like 'assigns the alert properties' - end - - context 'existing alert is ignored' do - let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: fingerprint_sha) } - - it_behaves_like 'adds an alert management alert event' - end - - context 'two existing alerts, one resolved one open' do - let!(:resolved_existing_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) } - let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) } - - it_behaves_like 'adds an alert management alert event' - end - end - - context 'end time given' do - let(:ended_at) { Time.current } - - it_behaves_like 'creates an alert management alert' - it_behaves_like 'assigns the alert properties' - end - - context 'with a minimal payload' do - let(:payload_raw) do + context 'with partial payload' do + let_it_be(:source) { integration.name } + let_it_be(:payload_raw) do { title: 'alert title', start_time: starts_at.rfc3339 } end - it_behaves_like 'creates an alert management alert' + include_examples 'processes never-before-seen alert' - it 'created alert has all data properly assigned' do + it 'assigns the alert properties' do subject expect(last_alert_attributes).to match( @@ -212,7 +101,19 @@ RSpec.describe Projects::Alerting::NotifyService do ) end - it_behaves_like 'creates single system note based on the source of the alert' + context 'with existing alert with matching payload' do + let_it_be(:fingerprint) { payload_raw.except(:start_time).stringify_keys } + let_it_be(:gitlab_fingerprint) { Gitlab::AlertManagement::Fingerprint.generate(fingerprint) } + let_it_be(:alert) { create(:alert_management_alert, project: project, fingerprint: gitlab_fingerprint) } + + include_examples 'processes never-before-seen alert' + end + end + + context 'with resolving payload' do + let(:ended_at) { Time.current.change(usec: 0) } + + it_behaves_like 'processes recovery alert' end end @@ -223,63 +124,30 @@ RSpec.describe Projects::Alerting::NotifyService do allow(Gitlab::Utils::DeepSize).to receive(:new).and_return(deep_size_object) end - it_behaves_like 'does not process incident issues due to error', http_status: :bad_request - it_behaves_like 'does not an create alert management alert' + it_behaves_like 'alerts service responds with an error and takes no actions', :bad_request end - it_behaves_like 'does not process incident issues' - - context 'issue enabled' do - let(:issue_enabled) { true } - - it_behaves_like 'processes incident issues' - - context 'when alert already exists' do - let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) } - let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) } - - context 'when existing alert does not have an associated issue' do - it_behaves_like 'processes incident issues' - end - - context 'when existing alert has an associated issue' do - let!(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) } - - it_behaves_like 'does not process incident issues' - end + context 'with inactive integration' do + before do + integration.update!(active: false) end - end - context 'with emails turned on' do - let(:email_enabled) { true } - - it_behaves_like 'Alert Notification Service sends notification email' + it_behaves_like 'alerts service responds with an error and takes no actions', :forbidden end end context 'with invalid token' do - it_behaves_like 'does not process incident issues due to error', http_status: :unauthorized - it_behaves_like 'does not an create alert management alert' - end - end - - context 'with an HTTP Integration' do - let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project) } + let(:token) { 'invalid-token' } - subject { service.execute(token, integration) } - - it_behaves_like 'notifications are handled correctly' do - let(:source) { integration.name } + it_behaves_like 'alerts service responds with an error and takes no actions', :unauthorized end + end - context 'with deactivated HTTP Integration' do - before do - integration.update!(active: false) - end + context 'without HTTP integration' do + let(:integration) { nil } + let(:token) { nil } - it_behaves_like 'does not process incident issues due to error', http_status: :forbidden - it_behaves_like 'does not an create alert management alert' - end + it_behaves_like 'alerts service responds with an error and takes no actions', :forbidden end end end |