Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
df5a8953
Commit
df5a8953
authored
Apr 29, 2021
by
Sarah Yasonik
Committed by
Arturo Herrero
Apr 29, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor alert processing specs for uniformity
parent
e8aec7f5
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
903 additions
and
775 deletions
+903
-775
ee/spec/services/alert_management/network_alert_service_spec.rb
...c/services/alert_management/network_alert_service_spec.rb
+47
-119
ee/spec/services/alert_management/process_prometheus_alert_service_spec.rb
...alert_management/process_prometheus_alert_service_spec.rb
+17
-10
ee/spec/services/projects/alerting/notify_service_spec.rb
ee/spec/services/projects/alerting/notify_service_spec.rb
+19
-4
ee/spec/services/projects/prometheus/alerts/notify_service_spec.rb
...ervices/projects/prometheus/alerts/notify_service_spec.rb
+4
-3
ee/spec/support/shared_examples/alert_notification_service_shared_examples.rb
...ed_examples/alert_notification_service_shared_examples.rb
+0
-19
ee/spec/support/shared_examples/incident_management/oncall_notifications_shared_examples.rb
...cident_management/oncall_notifications_shared_examples.rb
+0
-43
ee/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
...nagement/alert_processing/alert_firing_shared_examples.rb
+35
-0
ee/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
...gement/alert_processing/alert_recovery_shared_examples.rb
+65
-0
ee/spec/support/shared_examples/services/alert_management/alert_processing/oncall_notifications_shared_examples.rb
.../alert_processing/oncall_notifications_shared_examples.rb
+36
-0
spec/services/alert_management/process_prometheus_alert_service_spec.rb
...alert_management/process_prometheus_alert_service_spec.rb
+30
-206
spec/services/projects/alerting/notify_service_spec.rb
spec/services/projects/alerting/notify_service_spec.rb
+63
-195
spec/services/projects/prometheus/alerts/notify_service_spec.rb
...ervices/projects/prometheus/alerts/notify_service_spec.rb
+40
-43
spec/support/shared_examples/alert_notification_service_shared_examples.rb
...ed_examples/alert_notification_service_shared_examples.rb
+0
-44
spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
...nagement/alert_processing/alert_firing_shared_examples.rb
+161
-0
spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
...gement/alert_processing/alert_recovery_shared_examples.rb
+177
-0
spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb
...ent/alert_processing/incident_creation_shared_examples.rb
+52
-0
spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb
...t/alert_processing/incident_resolution_shared_examples.rb
+44
-0
spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb
...agement/alert_processing/notifications_shared_examples.rb
+34
-0
spec/support/shared_examples/services/alert_management/alert_processing/system_notes_shared_examples.rb
...nagement/alert_processing/system_notes_shared_examples.rb
+34
-0
spec/support/shared_examples/services/alert_management_shared_examples.rb
...red_examples/services/alert_management_shared_examples.rb
+45
-89
No files found.
ee/spec/services/alert_management/network_alert_service_spec.rb
View file @
df5a8953
...
@@ -6,37 +6,23 @@ RSpec.describe AlertManagement::NetworkAlertService do
...
@@ -6,37 +6,23 @@ RSpec.describe AlertManagement::NetworkAlertService do
let_it_be
(
:project
,
reload:
true
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:project
,
reload:
true
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:environment
)
{
create
(
:environment
,
project:
project
)
}
let_it_be
(
:environment
)
{
create
(
:environment
,
project:
project
)
}
describe
'#execute'
do
let
(
:payload_raw
)
{
build
(
:network_alert_payload
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
let
(
:tool
)
{
Gitlab
::
AlertManagement
::
Payload
::
MONITORING_TOOLS
[
:cilium
]
}
let
(
:starts_at
)
{
Time
.
current
.
change
(
usec:
0
)
}
let
(
:ended_at
)
{
nil
}
let
(
:fingerprint
)
{
'test'
}
let
(
:domain
)
{
'threat_monitoring'
}
let
(
:incident_management_setting
)
{
double
(
auto_close_incident?:
auto_close_enabled
)
}
let
(
:auto_close_enabled
)
{
true
}
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
before
do
describe
'#execute'
do
allow
(
service
).
to
receive
(
:incident_management_setting
).
and_return
(
include_context
'incident management settings enabled'
incident_management_setting
)
end
subject
(
:execute
)
{
service
.
execute
}
subject
(
:execute
)
{
service
.
execute
}
context
'with valid payload'
do
shared_examples
'never-before-seen network alert'
do
let
(
:payload_raw
)
{
build
(
:network_alert_payload
)
}
it_behaves_like
'creates an alert management alert or errors'
it_behaves_like
'creates expected system notes for alert'
,
:new_alert
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
it_behaves_like
'does not send alert notification emails'
it_behaves_like
'does not process incident issues'
let
(
:last_alert_attributes
)
do
AlertManagement
::
Alert
.
last
.
attributes
.
except
(
'id'
,
'iid'
,
'created_at'
,
'updated_at'
)
.
with_indifferent_access
end
it
'
create alert and assigns
properties'
do
it
'
assigns the correct
properties'
do
subject
subject
expect
(
last_alert_attributes
).
to
match
(
a_hash_including
({
expect
(
last_alert_attributes
).
to
match
(
a_hash_including
({
...
@@ -57,125 +43,67 @@ RSpec.describe AlertManagement::NetworkAlertService do
...
@@ -57,125 +43,67 @@ RSpec.describe AlertManagement::NetworkAlertService do
title:
'Cilium Alert'
title:
'Cilium Alert'
}))
}))
end
end
end
it
'creates a system note corresponding to alert creation'
do
shared_examples
'existing network alert'
do
expect
{
subject
}.
to
change
(
Note
,
:count
).
by
(
1
)
it_behaves_like
'adds an alert management alert event'
expect
(
Note
.
last
.
note
).
to
include
(
'Cilium'
)
it_behaves_like
'does not create a system note for alert'
end
it_behaves_like
'does not send alert notification emails'
it_behaves_like
'does not process incident issues'
context
'when alert exists'
do
end
let!
(
:alert
)
do
create
(
:alert_management_alert
,
project:
project
,
domain: :threat_monitoring
,
fingerprint:
'89269ffa3902af37f036a77bc9ea57cdee3a52c2'
)
end
it_behaves_like
'does not an create alert management alert'
context
'with valid payload'
do
let
(
:source
)
{
Gitlab
::
AlertManagement
::
Payload
::
MONITORING_TOOLS
[
:cilium
]
}
let
(
:last_alert_attributes
)
do
AlertManagement
::
Alert
.
last
.
attributes
.
except
(
'id'
,
'iid'
,
'created_at'
,
'updated_at'
)
.
with_indifferent_access
end
end
context
'existing alert with same fingerprint'
do
it_behaves_like
'never-before-seen network alert'
let
(
:fingerprint_sha
)
{
'89269ffa3902af37f036a77bc9ea57cdee3a52c2'
}
let!
(
:alert
)
do
create
(
:alert_management_alert
,
domain: :threat_monitoring
,
project:
project
,
fingerprint:
fingerprint_sha
)
end
it_behaves_like
'adds an alert management alert event'
context
'end time given
'
do
context
'for an existing alert with the same fingerprint
'
do
let
(
:ended_at
)
{
Time
.
current
.
change
(
nsec:
0
)
}
let_it_be
(
:fingerprint_sha
)
{
'89269ffa3902af37f036a77bc9ea57cdee3a52c2'
}
context
'auto_close disabled'
do
context
'which is triggered'
do
let
(
:auto_close_enabled
)
{
false
}
let_it_be
(
:alert
)
do
create
(
:alert_management_alert
,
:triggered
,
domain: :threat_monitoring
,
project:
project
,
fingerprint:
fingerprint_sha
)
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'
end
end
context
'existing alert is resolved'
do
let!
(
:alert
)
do
create
(
:alert_management_alert
,
:resolved
,
project:
project
,
domain: :threat_monitoring
,
fingerprint:
fingerprint_sha
)
end
end
it_behaves_like
'creates an alert management alert'
it_behaves_like
'existing network alert'
end
context
'with an additional existing resolved alert'
do
before
do
create
(
:alert_management_alert
,
:resolved
,
domain: :threat_monitoring
,
project:
project
,
fingerprint:
fingerprint_sha
)
end
context
'existing alert is ignored'
do
it_behaves_like
'existing network alert'
let!
(
:alert
)
do
create
(
:alert_management_alert
,
:ignored
,
project:
project
,
domain: :threat_monitoring
,
fingerprint:
fingerprint_sha
)
end
end
it_behaves_like
'adds an alert management alert event'
end
end
context
'two existing alerts, one resolved one open'
do
context
'which is resolved'
do
let!
(
:resolved_existing_alert
)
do
let_it_be
(
:alert
)
do
create
(
create
(
:alert_management_alert
,
:resolved
,
domain: :threat_monitoring
,
project:
project
,
fingerprint:
fingerprint_sha
)
:alert_management_alert
,
:resolved
,
project:
project
,
fingerprint:
fingerprint_sha
)
end
let!
(
:alert
)
do
create
(
:alert_management_alert
,
domain: :threat_monitoring
,
project:
project
,
fingerprint:
fingerprint_sha
)
end
end
it_behaves_like
'
adds an alert management alert even
t'
it_behaves_like
'
never-before-seen network aler
t'
end
end
end
end
end
end
context
'with overlong payload'
do
context
'with overlong payload'
do
let
(
:deep_size_object
)
{
instance_double
(
Gitlab
::
Utils
::
DeepSize
,
valid?:
false
)
}
let
(
:deep_size_object
)
{
instance_double
(
Gitlab
::
Utils
::
DeepSize
,
valid?:
false
)
}
let
(
:payload
)
{
ActionController
::
Parameters
.
new
({}).
permit!
}
before
do
before
do
allow
(
Gitlab
::
Utils
::
DeepSize
).
to
receive
(
:new
).
and_return
(
deep_size_object
)
allow
(
Gitlab
::
Utils
::
DeepSize
).
to
receive
(
:new
).
and_return
(
deep_size_object
)
end
end
it_behaves_like
'does not process incident issues due to error'
,
http_status: :bad_request
it_behaves_like
'alerts service responds with an error and takes no actions'
,
:bad_request
it_behaves_like
'does not an create alert management alert'
end
context
'error duing save'
do
let
(
:payload_raw
)
{
build
(
:network_alert_payload
)
}
let
(
:logger
)
{
double
(
warn:
{})
}
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
it
'logs warning'
do
expect_any_instance_of
(
AlertManagement
::
Alert
).
to
receive
(
:save
).
and_return
(
false
)
expect_any_instance_of
(
described_class
).
to
receive
(
:logger
).
and_return
(
logger
)
subject
expect
(
logger
).
to
have_received
(
:warn
).
with
(
hash_including
(
message:
"Unable to create AlertManagement::Alert from
#{
tool
}
"
,
project_id:
project
.
id
,
alert_errors:
{}
)
)
end
end
end
end
end
end
end
ee/spec/services/alert_management/process_prometheus_alert_service_spec.rb
View file @
df5a8953
...
@@ -5,25 +5,23 @@ require 'spec_helper'
...
@@ -5,25 +5,23 @@ require 'spec_helper'
RSpec
.
describe
AlertManagement
::
ProcessPrometheusAlertService
do
RSpec
.
describe
AlertManagement
::
ProcessPrometheusAlertService
do
let_it_be
(
:project
,
refind:
true
)
{
create
(
:project
)
}
let_it_be
(
:project
,
refind:
true
)
{
create
(
:project
)
}
before
do
allow
(
ProjectServiceWorker
).
to
receive
(
:perform_async
)
end
describe
'#execute'
do
describe
'#execute'
do
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
subject
(
:execute
)
{
service
.
execute
}
subject
(
:execute
)
{
service
.
execute
}
context
'when alert payload is valid'
do
context
'when alert payload is valid'
do
let
(
:parsed_payload
)
{
Gitlab
::
AlertManagement
::
Payload
.
parse
(
project
,
payload
,
monitoring_tool:
'Prometheus'
)
}
let_it_be
(
:starts_at
)
{
'2020-04-27T10:10:22.265949279Z'
}
let
(
:fingerprint
)
{
parsed_payload
.
gitlab_fingerprint
}
let_it_be
(
:title
)
{
'Alert title'
}
let_it_be
(
:gitlab_fingerprint
)
{
Digest
::
SHA1
.
hexdigest
([
starts_at
,
title
,
'vector(1)'
].
join
(
'/'
))
}
let
(
:payload
)
{
raw_payload
}
let
(
:payload
)
{
raw_payload
}
let
(
:raw_payload
)
do
let
(
:raw_payload
)
do
{
{
'status'
=>
'firing'
,
'status'
=>
'firing'
,
'labels'
=>
{
'alertname'
=>
'GitalyFileServerDown'
},
'labels'
=>
{
'alertname'
=>
'GitalyFileServerDown'
},
'annotations'
=>
{
'title'
=>
'Alert title'
},
'annotations'
=>
{
'title'
=>
title
},
'startsAt'
=>
'2020-04-27T10:10:22.265949279Z'
,
'startsAt'
=>
starts_at
,
'endsAt'
=>
'2020-04-27T10:20:22.265949279Z'
,
'endsAt'
=>
'2020-04-27T10:20:22.265949279Z'
,
'generatorURL'
=>
'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1'
'generatorURL'
=>
'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1'
}
}
...
@@ -33,10 +31,19 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
...
@@ -33,10 +31,19 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
let_it_be
(
:schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
)
}
let_it_be
(
:schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
)
}
let_it_be
(
:rotation
)
{
create
(
:incident_management_oncall_rotation
,
schedule:
schedule
)
}
let_it_be
(
:rotation
)
{
create
(
:incident_management_oncall_rotation
,
schedule:
schedule
)
}
let_it_be
(
:participant
)
{
create
(
:incident_management_oncall_participant
,
:with_developer_access
,
rotation:
rotation
)
}
let_it_be
(
:participant
)
{
create
(
:incident_management_oncall_participant
,
:with_developer_access
,
rotation:
rotation
)
}
let
(
:resolving_payload
)
{
raw_payload
.
merge
(
'status'
=>
'resolved'
)
}
let
(
:users
)
{
[
participant
.
user
]
}
let
(
:users
)
{
[
participant
.
user
]
}
it_behaves_like
'oncall users are correctly notified'
before
do
stub_licensed_features
(
oncall_schedules:
project
)
end
include_examples
'oncall users are correctly notified of firing alert'
context
'with resolving payload'
do
let
(
:payload
)
{
raw_payload
.
merge
(
'status'
=>
'resolved'
)
}
include_examples
'oncall users are correctly notified of Prometheus recovery alert'
end
end
end
end
end
end
end
...
...
ee/spec/services/projects/alerting/notify_service_spec.rb
View file @
df5a8953
...
@@ -69,13 +69,28 @@ RSpec.describe Projects::Alerting::NotifyService do
...
@@ -69,13 +69,28 @@ RSpec.describe Projects::Alerting::NotifyService do
let_it_be
(
:schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
)
}
let_it_be
(
:schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
)
}
let_it_be
(
:rotation
)
{
create
(
:incident_management_oncall_rotation
,
schedule:
schedule
)
}
let_it_be
(
:rotation
)
{
create
(
:incident_management_oncall_rotation
,
schedule:
schedule
)
}
let_it_be
(
:participant
)
{
create
(
:incident_management_oncall_participant
,
:with_developer_access
,
rotation:
rotation
)
}
let_it_be
(
:participant
)
{
create
(
:incident_management_oncall_participant
,
:with_developer_access
,
rotation:
rotation
)
}
let_it_be
(
:fingerprint
)
{
'fingerprint'
}
let_it_be
(
:gitlab_fingerprint
)
{
Digest
::
SHA1
.
hexdigest
(
fingerprint
)
}
let
(
:payload
)
{
{
'fingerprint'
=>
'fingerprint'
}
}
let
(
:payload
)
{
{
'fingerprint'
=>
fingerprint
}
}
let
(
:resolving_payload
)
{
{
'fingerprint'
=>
'fingerprint'
,
"end_time"
:
Time
.
current
.
iso8601
}
}
let
(
:users
)
{
[
participant
.
user
]
}
let
(
:users
)
{
[
participant
.
user
]
}
let
(
:fingerprint
)
{
Digest
::
SHA1
.
hexdigest
(
'fingerprint'
)
}
it_behaves_like
'oncall users are correctly notified'
before
do
stub_licensed_features
(
oncall_schedules:
project
)
end
include_examples
'oncall users are correctly notified of firing alert'
context
'with resolving payload'
do
let
(
:payload
)
do
{
'fingerprint'
=>
fingerprint
,
'end_time'
=>
Time
.
current
.
iso8601
}
end
include_examples
'oncall users are correctly notified of recovery alert'
end
end
end
end
end
end
end
ee/spec/services/projects/prometheus/alerts/notify_service_spec.rb
View file @
df5a8953
...
@@ -10,7 +10,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -10,7 +10,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
let
(
:token_input
)
{
'token'
}
let
(
:token_input
)
{
'token'
}
let
!
(
:setting
)
do
let
_it_be
(
:setting
)
do
create
(
:project_incident_management_setting
,
project:
project
,
send_email:
true
,
create_issue:
true
)
create
(
:project_incident_management_setting
,
project:
project
,
send_email:
true
,
create_issue:
true
)
end
end
...
@@ -23,6 +23,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -23,6 +23,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
let
(
:payload_alert_firing
)
{
payload_raw
[
'alerts'
].
first
}
let
(
:payload_alert_firing
)
{
payload_raw
[
'alerts'
].
first
}
let
(
:token
)
{
'token'
}
let
(
:token
)
{
'token'
}
let
(
:source
)
{
'Prometheus'
}
context
'with environment specific clusters'
do
context
'with environment specific clusters'
do
let
(
:prd_cluster
)
do
let
(
:prd_cluster
)
do
...
@@ -51,11 +52,11 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -51,11 +52,11 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
context
'without token'
do
context
'without token'
do
let
(
:token_input
)
{
nil
}
let
(
:token_input
)
{
nil
}
i
t_behaves_like
'Alert Notification Service sends notification email
'
i
nclude_examples
'processes one firing and one resolved prometheus alerts
'
end
end
context
'with token'
do
context
'with token'
do
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unauthorized
it_behaves_like
'
alerts service responds with an error'
,
:unauthorized
end
end
end
end
end
end
...
...
ee/spec/support/shared_examples/alert_notification_service_shared_examples.rb
deleted
100644 → 0
View file @
e8aec7f5
# frozen_string_literal: true
# Requires `users` and `fingerprint` to be defined
RSpec
.
shared_examples
'Alert Notification Service sends notification email to on-call users'
do
let
(
:notification_service
)
{
instance_double
(
NotificationService
)
}
it
'sends a notification'
do
expect
(
NotificationService
).
to
receive
(
:new
).
and_return
(
notification_service
)
expect
(
notification_service
)
.
to
receive_message_chain
(
:async
,
:notify_oncall_users_of_alert
)
.
with
(
users
,
having_attributes
(
class:
AlertManagement
::
Alert
,
fingerprint:
fingerprint
)
)
expect
(
subject
).
to
be_success
end
end
ee/spec/support/shared_examples/incident_management/oncall_notifications_shared_examples.rb
deleted
100644 → 0
View file @
e8aec7f5
# frozen_string_literal: true
# Requires `project`, `users`, `fingerprint`, and `resolving_payload`
RSpec
.
shared_examples
'oncall users are correctly notified'
do
context
'with feature enabled'
do
before
do
stub_licensed_features
(
oncall_schedules:
project
)
end
it_behaves_like
'Alert Notification Service sends notification email to on-call users'
context
'when alert with the same fingerprint already exists'
do
let!
(
:alert
)
{
create
(
:alert_management_alert
,
status
,
fingerprint:
fingerprint
,
project:
project
)
}
it_behaves_like
'Alert Notification Service sends notification email to on-call users'
do
let
(
:status
)
{
:triggered
}
end
it_behaves_like
'Alert Notification Service sends no notifications'
do
let
(
:status
)
{
:acknowledged
}
end
it_behaves_like
'Alert Notification Service sends notification email to on-call users'
do
let
(
:status
)
{
:resolved
}
end
it_behaves_like
'Alert Notification Service sends no notifications'
do
let
(
:status
)
{
:ignored
}
end
context
'with resolving payload'
do
let
(
:status
)
{
:triggered
}
let
(
:payload
)
{
resolving_payload
}
it_behaves_like
'Alert Notification Service sends notification email to on-call users'
end
end
end
context
'with feature disabled'
do
it_behaves_like
'Alert Notification Service sends no notifications'
end
end
ee/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# This shared_example requires the following variables:
# - `project`, expected project for an incoming alert
# - `users`, users expected to receive on-call notifications
# - `gitlab_fingerprint`, sha which is used to uniquely identify the alert
RSpec
.
shared_examples
'oncall users are correctly notified of firing alert'
do
it_behaves_like
'sends on-call notification if enabled'
context
'when alert with the same fingerprint already exists'
do
context
'which is triggered'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:triggered
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is acknowledged'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:acknowledged
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'does not send on-call notification'
end
context
'which is resolved'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:resolved
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is ignored'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:ignored
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'does not send on-call notification'
end
end
end
ee/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# This shared_example requires the following variables:
# - `project`, expected project for an incoming alert
# - `users`, users expected to receive on-call notifications
# - `gitlab_fingerprint`, sha which is used to uniquely identify the alert
RSpec
.
shared_examples
'oncall users are correctly notified of recovery alert'
do
it_behaves_like
'sends on-call notification if enabled'
context
'when alert with the same fingerprint already exists'
do
context
'which is triggered'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:triggered
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is acknowledged'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:acknowledged
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is resolved'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:resolved
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is ignored'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:ignored
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
end
end
RSpec
.
shared_examples
'oncall users are correctly notified of Prometheus recovery alert'
do
it_behaves_like
'does not send on-call notification'
context
'when alert with the same fingerprint already exists'
do
context
'which is triggered'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:triggered
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is acknowledged'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:acknowledged
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
context
'which is resolved'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:resolved
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'does not send on-call notification'
end
context
'which is ignored'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:ignored
,
fingerprint:
gitlab_fingerprint
,
project:
project
)
}
it_behaves_like
'sends on-call notification if enabled'
end
end
end
ee/spec/support/shared_examples/services/alert_management/alert_processing/oncall_notifications_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# This shared_example requires the following variables:
# - `users`, users expected to receive on-call notifications
# - `gitlab_fingerprint`, SHA which is used to uniquely identify the alert
RSpec
.
shared_examples
'sends on-call notification if enabled'
do
context
'with on-call schedules enabled'
do
let
(
:notification_async
)
{
double
(
NotificationService
::
Async
)
}
it
'sends on-call notification'
do
allow
(
NotificationService
).
to
receive_message_chain
(
:new
,
:async
).
and_return
(
notification_async
)
expect
(
notification_async
).
to
receive
(
:notify_oncall_users_of_alert
).
with
(
users
,
having_attributes
(
class:
AlertManagement
::
Alert
,
fingerprint:
gitlab_fingerprint
)
)
subject
end
end
context
'with on-call schedules disabled'
do
before
do
stub_licensed_features
(
oncall_schedules:
false
)
end
it_behaves_like
'does not send on-call notification'
end
end
RSpec
.
shared_examples
'does not send on-call notification'
do
specify
do
expect
(
NotificationService
).
not_to
receive
(
:new
)
subject
end
end
spec/services/alert_management/process_prometheus_alert_service_spec.rb
View file @
df5a8953
This diff is collapsed.
Click to expand it.
spec/services/projects/alerting/notify_service_spec.rb
View file @
df5a8953
This diff is collapsed.
Click to expand it.
spec/services/projects/prometheus/alerts/notify_service_spec.rb
View file @
df5a8953
...
@@ -6,25 +6,26 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -6,25 +6,26 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
include
PrometheusHelpers
include
PrometheusHelpers
using
RSpec
::
Parameterized
::
TableSyntax
using
RSpec
::
Parameterized
::
TableSyntax
let_it_be
(
:project
,
reload:
true
)
{
create
(
:project
)
}
let_it_be_with_reload
(
:project
)
{
create
(
:project
)
}
let_it_be_with_reload
(
:setting
)
do
create
(
:project_incident_management_setting
,
project:
project
,
send_email:
true
,
create_issue:
true
)
end
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
payload
)
}
let
(
:token_input
)
{
'token'
}
let
(
:token_input
)
{
'token'
}
let!
(
:setting
)
do
subject
{
service
.
execute
(
token_input
)
}
create
(
:project_incident_management_setting
,
project:
project
,
send_email:
true
,
create_issue:
true
)
end
let
(
:subject
)
{
service
.
execute
(
token_input
)
}
context
'with valid payload'
do
context
'with valid payload'
do
let_it_be
(
:alert_firing
)
{
create
(
:prometheus_alert
,
project:
project
)
}
let_it_be
(
:alert_firing
)
{
create
(
:prometheus_alert
,
project:
project
)
}
let_it_be
(
:alert_resolved
)
{
create
(
:prometheus_alert
,
project:
project
)
}
let_it_be
(
:alert_resolved
)
{
create
(
:prometheus_alert
,
project:
project
)
}
let_it_be
(
:cluster
)
{
create
(
:cluster
,
:provided_by_user
,
projects:
[
project
])
}
let_it_be
(
:cluster
,
reload:
true
)
{
create
(
:cluster
,
:provided_by_user
,
projects:
[
project
])
}
let
(
:payload_raw
)
{
prometheus_alert_payload
(
firing:
[
alert_firing
],
resolved:
[
alert_resolved
])
}
let
(
:payload_raw
)
{
prometheus_alert_payload
(
firing:
[
alert_firing
],
resolved:
[
alert_resolved
])
}
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
let
(
:payload
)
{
ActionController
::
Parameters
.
new
(
payload_raw
).
permit!
}
let
(
:payload_alert_firing
)
{
payload_raw
[
'alerts'
].
first
}
let
(
:payload_alert_firing
)
{
payload_raw
[
'alerts'
].
first
}
let
(
:token
)
{
'token'
}
let
(
:token
)
{
'token'
}
let
(
:source
)
{
'Prometheus'
}
context
'with environment specific clusters'
do
context
'with environment specific clusters'
do
let
(
:prd_cluster
)
do
let
(
:prd_cluster
)
do
...
@@ -53,11 +54,11 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -53,11 +54,11 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
context
'without token'
do
context
'without token'
do
let
(
:token_input
)
{
nil
}
let
(
:token_input
)
{
nil
}
i
t_behaves_like
'Alert Notification Service sends notification email
'
i
nclude_examples
'processes one firing and one resolved prometheus alerts
'
end
end
context
'with token'
do
context
'with token'
do
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unauthorized
it_behaves_like
'
alerts service responds with an error and takes no actions'
,
:unauthorized
end
end
end
end
...
@@ -87,9 +88,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -87,9 +88,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
case
result
=
params
[
:result
]
case
result
=
params
[
:result
]
when
:success
when
:success
i
t_behaves_like
'Alert Notification Service sends notification email
'
i
nclude_examples
'processes one firing and one resolved prometheus alerts
'
when
:failure
when
:failure
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unauthorized
it_behaves_like
'
alerts service responds with an error and takes no actions'
,
:unauthorized
else
else
raise
"invalid result:
#{
result
.
inspect
}
"
raise
"invalid result:
#{
result
.
inspect
}
"
end
end
...
@@ -97,9 +98,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -97,9 +98,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
end
context
'without project specific cluster'
do
context
'without project specific cluster'
do
let
!
(
:cluster
)
{
create
(
:cluster
,
enabled:
true
)
}
let
_it_be
(
:cluster
)
{
create
(
:cluster
,
enabled:
true
)
}
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unauthorized
it_behaves_like
'
alerts service responds with an error and takes no actions'
,
:unauthorized
end
end
context
'with manual prometheus installation'
do
context
'with manual prometheus installation'
do
...
@@ -126,9 +127,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -126,9 +127,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
case
result
=
params
[
:result
]
case
result
=
params
[
:result
]
when
:success
when
:success
it_behaves_like
'
Alert Notification Service sends notification email
'
it_behaves_like
'
processes one firing and one resolved prometheus alerts
'
when
:failure
when
:failure
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unauthorized
it_behaves_like
'
alerts service responds with an error and takes no actions'
,
:unauthorized
else
else
raise
"invalid result:
#{
result
.
inspect
}
"
raise
"invalid result:
#{
result
.
inspect
}
"
end
end
...
@@ -150,50 +151,53 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -150,50 +151,53 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
let
(
:token_input
)
{
public_send
(
token
)
if
token
}
let
(
:token_input
)
{
public_send
(
token
)
if
token
}
let
(
:integration
)
{
create
(
:alert_management_http_integration
,
active
,
project:
project
)
if
active
}
let
(
:integration
)
{
create
(
:alert_management_http_integration
,
active
,
project:
project
)
if
active
}
let
(
:subject
)
{
service
.
execute
(
token_input
,
integration
)
}
subject
{
service
.
execute
(
token_input
,
integration
)
}
case
result
=
params
[
:result
]
case
result
=
params
[
:result
]
when
:success
when
:success
it_behaves_like
'
Alert Notification Service sends notification email
'
it_behaves_like
'
processes one firing and one resolved prometheus alerts
'
when
:failure
when
:failure
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unauthorized
it_behaves_like
'
alerts service responds with an error and takes no actions'
,
:unauthorized
else
else
raise
"invalid result:
#{
result
.
inspect
}
"
raise
"invalid result:
#{
result
.
inspect
}
"
end
end
end
end
end
end
context
'
alert email
s'
do
context
'
incident setting
s'
do
before
do
before
do
create
(
:prometheus_service
,
project:
project
)
create
(
:prometheus_service
,
project:
project
)
create
(
:project_alerting_setting
,
project:
project
,
token:
token
)
create
(
:project_alerting_setting
,
project:
project
,
token:
token
)
end
end
context
'when incident_management_setting does not exist'
do
it_behaves_like
'processes one firing and one resolved prometheus alerts'
let!
(
:setting
)
{
nil
}
it
'does not send notification email'
,
:sidekiq_might_not_need_inline
do
expect_any_instance_of
(
NotificationService
)
.
not_to
receive
(
:async
)
expect
(
subject
).
to
be_success
context
'when incident_management_setting does not exist'
do
before
do
setting
.
destroy!
end
end
end
context
'when incident_management_setting.send_email is true'
do
it
{
is_expected
.
to
be_success
}
it_behaves_like
'Alert Notification Service sends notification email'
include_examples
'does not send alert notification emails'
include_examples
'does not process incident issues'
end
end
context
'incident_management_setting.send_email is false'
do
context
'incident_management_setting.send_email is false'
do
let!
(
:setting
)
do
before
do
create
(
:project_incident_management_setting
,
send_email:
false
,
project:
project
)
setting
.
update!
(
send_email:
false
)
end
end
it
'does not send notification'
do
it
{
is_expected
.
to
be_success
}
expect
(
NotificationService
).
not_to
receive
(
:new
)
include_examples
'does not send alert notification emails'
end
expect
(
subject
).
to
be_success
context
'incident_management_setting.create_issue is false'
do
before
do
setting
.
update!
(
create_issue:
false
)
end
end
it
{
is_expected
.
to
be_success
}
include_examples
'does not process incident issues'
end
end
end
end
...
@@ -233,7 +237,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -233,7 +237,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
.
and_return
(
false
)
.
and_return
(
false
)
end
end
it_behaves_like
'
Alert Notification Service sends no notifications'
,
http_status:
:unprocessable_entity
it_behaves_like
'
alerts service responds with an error and takes no actions'
,
:unprocessable_entity
end
end
context
'when the payload is too big'
do
context
'when the payload is too big'
do
...
@@ -244,14 +248,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
...
@@ -244,14 +248,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
allow
(
Gitlab
::
Utils
::
DeepSize
).
to
receive
(
:new
).
and_return
(
deep_size_object
)
allow
(
Gitlab
::
Utils
::
DeepSize
).
to
receive
(
:new
).
and_return
(
deep_size_object
)
end
end
it_behaves_like
'Alert Notification Service sends no notifications'
,
http_status: :bad_request
it_behaves_like
'alerts service responds with an error and takes no actions'
,
:bad_request
it
'does not process Prometheus alerts'
do
expect
(
AlertManagement
::
ProcessPrometheusAlertService
)
.
not_to
receive
(
:new
)
subject
end
end
end
end
end
...
...
spec/support/shared_examples/alert_notification_service_shared_examples.rb
deleted
100644 → 0
View file @
e8aec7f5
# frozen_string_literal: true
RSpec
.
shared_examples
'Alert Notification Service sends notification email'
do
let
(
:notification_service
)
{
spy
}
it
'sends a notification'
do
expect
(
NotificationService
)
.
to
receive
(
:new
)
.
and_return
(
notification_service
)
expect
(
notification_service
)
.
to
receive_message_chain
(
:async
,
:prometheus_alerts_fired
)
expect
(
subject
).
to
be_success
end
end
RSpec
.
shared_examples
'Alert Notification Service sends no notifications'
do
|
http_status:
nil
|
it
'does not notify'
do
expect
(
NotificationService
).
not_to
receive
(
:new
)
if
http_status
.
present?
expect
(
subject
).
to
be_error
expect
(
subject
.
http_status
).
to
eq
(
http_status
)
else
expect
(
subject
).
to
be_success
end
end
end
RSpec
.
shared_examples
'creates status-change system note for an auto-resolved alert'
do
it
'has 2 new system notes'
do
expect
{
subject
}.
to
change
(
Note
,
:count
).
by
(
2
)
expect
(
Note
.
last
.
note
).
to
include
(
'Resolved'
)
end
end
# Requires `source` to be defined
RSpec
.
shared_examples
'creates single system note based on the source of the alert'
do
it
'has one new system note'
do
expect
{
subject
}.
to
change
(
Note
,
:count
).
by
(
1
)
expect
(
Note
.
last
.
note
).
to
include
(
source
)
end
end
spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
0 → 100644
View file @
df5a8953
# 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
it
{
is_expected
.
to
be_success
}
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_services
)
end
subject
end
context
'and fails to save'
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
'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 from
#{
source
}
"
,
project_id:
project
.
id
,
alert_errors:
{
hosts:
[
'hosts array is over 255 chars'
]
}
)
subject
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_services
)
expect
{
subject
}.
to
change
{
alert
.
reload
.
events
}.
by
(
1
)
expect
(
subject
).
to
be_success
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
spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# This shared_example requires the following variables:
# - `alert`, the alert to be resolved
RSpec
.
shared_examples
'resolves an existing alert management alert'
do
it
'sets the end time and status'
do
expect
(
Gitlab
::
AppLogger
).
not_to
receive
(
:warn
)
expect
{
subject
}
.
to
change
{
alert
.
reload
.
resolved?
}.
to
(
true
)
.
and
change
{
alert
.
ended_at
.
present?
}.
to
(
true
)
expect
(
subject
).
to
be_success
end
end
# This shared_example requires the following variables:
# - `alert`, the alert not to be updated
RSpec
.
shared_examples
'does not change the alert end time'
do
specify
do
expect
{
subject
}.
not_to
change
{
alert
.
reload
.
ended_at
}
end
end
# This shared_example requires the following variables:
# - `project`, expected project for an incoming alert
# - `service`, a service which includes AlertManagement::AlertProcessing
# - `alert` (optional), the alert which should fail to resolve. If not
# included, the log is expected to correspond to a new alert
RSpec
.
shared_examples
'writes a warning to the log for a failed alert status update'
do
before
do
allow
(
service
).
to
receive
(
:alert
).
and_call_original
allow
(
service
).
to
receive_message_chain
(
:alert
,
:resolve
).
and_return
(
false
)
end
specify
do
expect
(
Gitlab
::
AppLogger
).
to
receive
(
:warn
).
with
(
message:
'Unable to update AlertManagement::Alert status to resolved'
,
project_id:
project
.
id
,
alert_id:
alert
?
alert
.
id
:
(
last_alert_id
+
1
)
)
# Failure to resolve a recovery alert is not a critical failure
expect
(
subject
).
to
be_success
end
private
def
last_alert_id
AlertManagement
::
Alert
.
connection
.
select_value
(
"SELECT nextval('
#{
AlertManagement
::
Alert
.
sequence_name
}
')"
)
end
end
RSpec
.
shared_examples
'processes recovery alert'
do
context
'seen for the first time'
do
let
(
:alert
)
{
AlertManagement
::
Alert
.
last
}
include_examples
'processes never-before-seen recovery alert'
end
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
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'resolves an existing alert management alert'
it_behaves_like
'creates expected system notes for alert'
,
:recovery_alert
,
:resolve_alert
it_behaves_like
'sends alert notification emails if enabled'
it_behaves_like
'closes related incident if enabled'
it_behaves_like
'writes a warning to the log for a failed alert status update'
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
context
'which is ignored'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:ignored
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'resolves an existing alert management alert'
it_behaves_like
'creates expected system notes for alert'
,
:recovery_alert
,
:resolve_alert
it_behaves_like
'sends alert notification emails if enabled'
it_behaves_like
'closes related incident if enabled'
it_behaves_like
'writes a warning to the log for a failed alert status update'
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
context
'which is acknowledged'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:acknowledged
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'resolves an existing alert management alert'
it_behaves_like
'creates expected system notes for alert'
,
:recovery_alert
,
:resolve_alert
it_behaves_like
'sends alert notification emails if enabled'
it_behaves_like
'closes related incident if enabled'
it_behaves_like
'writes a warning to the log for a failed alert status update'
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
context
'which is resolved'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:resolved
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
include_examples
'processes never-before-seen recovery alert'
end
end
end
RSpec
.
shared_examples
'processes prometheus recovery alert'
do
context
'seen for the first time'
do
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not send alert notification emails'
it_behaves_like
'does not process incident issues'
end
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
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'resolves an existing alert management alert'
it_behaves_like
'creates expected system notes for alert'
,
:recovery_alert
,
:resolve_alert
it_behaves_like
'sends alert notification emails if enabled'
it_behaves_like
'closes related incident if enabled'
it_behaves_like
'writes a warning to the log for a failed alert status update'
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
context
'which is ignored'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:ignored
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'resolves an existing alert management alert'
it_behaves_like
'creates expected system notes for alert'
,
:recovery_alert
,
:resolve_alert
it_behaves_like
'sends alert notification emails if enabled'
it_behaves_like
'closes related incident if enabled'
it_behaves_like
'writes a warning to the log for a failed alert status update'
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
context
'which is acknowledged'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:acknowledged
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'resolves an existing alert management alert'
it_behaves_like
'creates expected system notes for alert'
,
:recovery_alert
,
:resolve_alert
it_behaves_like
'sends alert notification emails if enabled'
it_behaves_like
'closes related incident if enabled'
it_behaves_like
'writes a warning to the log for a failed alert status update'
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
context
'which is resolved'
do
let_it_be
(
:alert
)
{
create
(
:alert_management_alert
,
:resolved
,
project:
project
,
fingerprint:
gitlab_fingerprint
,
monitoring_tool:
source
)
}
it_behaves_like
'does not create an alert management alert'
it_behaves_like
'does not send alert notification emails'
it_behaves_like
'does not change the alert end time'
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not add an alert management alert event'
end
end
end
spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# Expects usage of 'incident settings enabled' context.
#
# This shared_example includes the following option:
# - with_issue: includes a test for when the defined `alert` has an associated issue
#
# This shared_example requires the following variables:
# - `alert`, required if :with_issue is true
RSpec
.
shared_examples
'processes incident issues if enabled'
do
|
with_issue:
false
|
include_examples
'processes incident issues'
,
with_issue
context
'with incident setting disabled'
do
let
(
:create_issue
)
{
false
}
it_behaves_like
'does not process incident issues'
end
end
RSpec
.
shared_examples
'processes incident issues'
do
|
with_issue:
false
|
before
do
allow_next_instance_of
(
AlertManagement
::
Alert
)
do
|
alert
|
allow
(
alert
).
to
receive
(
:execute_services
)
end
end
specify
do
expect
(
IncidentManagement
::
ProcessAlertWorker
)
.
to
receive
(
:perform_async
)
.
with
(
nil
,
nil
,
kind_of
(
Integer
))
Sidekiq
::
Testing
.
inline!
do
expect
(
subject
).
to
be_success
end
end
context
'with issue'
,
if:
with_issue
do
before
do
alert
.
update!
(
issue:
create
(
:issue
,
project:
project
))
end
it_behaves_like
'does not process incident issues'
end
end
RSpec
.
shared_examples
'does not process incident issues'
do
specify
do
expect
(
IncidentManagement
::
ProcessAlertWorker
).
not_to
receive
(
:perform_async
)
subject
end
end
spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# Expects usage of 'incident settings enabled' context.
#
# This shared_example requires the following variables:
# - `alert`, alert for which related incidents should be closed
# - `project`, project of the alert
RSpec
.
shared_examples
'closes related incident if enabled'
do
context
'with issue'
do
before
do
alert
.
update!
(
issue:
create
(
:issue
,
project:
project
))
end
it
{
expect
{
subject
}.
to
change
{
alert
.
issue
.
reload
.
closed?
}.
from
(
false
).
to
(
true
)
}
it
{
expect
{
subject
}.
to
change
(
ResourceStateEvent
,
:count
).
by
(
1
)
}
end
context
'without issue'
do
it
{
expect
{
subject
}.
not_to
change
{
alert
.
reload
.
issue
}
}
it
{
expect
{
subject
}.
not_to
change
(
ResourceStateEvent
,
:count
)
}
end
context
'with incident setting disabled'
do
let
(
:auto_close_incident
)
{
false
}
it_behaves_like
'does not close related incident'
end
end
RSpec
.
shared_examples
'does not close related incident'
do
context
'with issue'
do
before
do
alert
.
update!
(
issue:
create
(
:issue
,
project:
project
))
end
it
{
expect
{
subject
}.
not_to
change
{
alert
.
issue
.
reload
.
state
}
}
it
{
expect
{
subject
}.
not_to
change
(
ResourceStateEvent
,
:count
)
}
end
context
'without issue'
do
it
{
expect
{
subject
}.
not_to
change
{
alert
.
reload
.
issue
}
}
it
{
expect
{
subject
}.
not_to
change
(
ResourceStateEvent
,
:count
)
}
end
end
spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# Expects usage of 'incident settings enabled' context.
#
# This shared_example includes the following option:
# - count: number of notifications expected to be sent
RSpec
.
shared_examples
'sends alert notification emails if enabled'
do
|
count:
1
|
include_examples
'sends alert notification emails'
,
count
context
'with email setting disabled'
do
let
(
:send_email
)
{
false
}
it_behaves_like
'does not send alert notification emails'
end
end
RSpec
.
shared_examples
'sends alert notification emails'
do
|
count:
1
|
let
(
:notification_async
)
{
double
(
NotificationService
::
Async
)
}
specify
do
allow
(
NotificationService
).
to
receive_message_chain
(
:new
,
:async
).
and_return
(
notification_async
)
expect
(
notification_async
).
to
receive
(
:prometheus_alerts_fired
).
exactly
(
count
).
times
subject
end
end
RSpec
.
shared_examples
'does not send alert notification emails'
do
specify
do
expect
(
NotificationService
).
not_to
receive
(
:new
)
subject
end
end
spec/support/shared_examples/services/alert_management/alert_processing/system_notes_shared_examples.rb
0 → 100644
View file @
df5a8953
# frozen_string_literal: true
# This shared_example includes the following option:
# - notes: any of [:new_alert, :recovery_alert, :resolve_alert].
# Represents which notes are expected to be created.
#
# This shared_example requires the following variables:
# - `source` (optional), the monitoring tool or integration name
# expected in the applicable system notes
RSpec
.
shared_examples
'creates expected system notes for alert'
do
|*
notes
|
let
(
:expected_note_count
)
{
expected_notes
.
length
}
let
(
:new_notes
)
{
Note
.
last
(
expected_note_count
).
pluck
(
:note
)
}
let
(
:expected_notes
)
do
{
new_alert:
source
,
recovery_alert:
source
,
resolve_alert:
'Resolved'
}.
slice
(
*
notes
)
end
it
"for
#{
notes
.
join
(
', '
)
}
"
do
expect
{
subject
}.
to
change
(
Note
,
:count
).
by
(
expected_note_count
)
expected_notes
.
each_value
.
with_index
do
|
value
,
index
|
expect
(
new_notes
[
index
]).
to
include
(
value
)
end
end
end
RSpec
.
shared_examples
'does not create a system note for alert'
do
specify
do
expect
{
subject
}.
not_to
change
(
Note
,
:count
)
end
end
spec/support/shared_examples/services/alert_management_shared_examples.rb
View file @
df5a8953
# frozen_string_literal: true
# frozen_string_literal: true
RSpec
.
shared_examples
'
creates an alert management alert'
do
RSpec
.
shared_examples
'
alerts service responds with an error and takes no actions'
do
|
http_status
|
i
t
{
is_expected
.
to
be_success
}
i
nclude_examples
'alerts service responds with an error'
,
http_status
it
'creates AlertManagement::Alert'
do
it_behaves_like
'does not create an alert management alert'
expect
{
subject
}.
to
change
(
AlertManagement
::
Alert
,
:count
).
by
(
1
)
it_behaves_like
'does not create a system note for alert'
end
it_behaves_like
'does not process incident issues'
it_behaves_like
'does not send alert notification emails'
it
'executes the alert service hooks'
do
end
expect_next_instance_of
(
AlertManagement
::
Alert
)
do
|
alert
|
expect
(
alert
).
to
receive
(
:execute_services
)
end
subject
RSpec
.
shared_examples
'alerts service responds with an error'
do
|
http_status
|
specify
do
expect
(
subject
).
to
be_error
expect
(
subject
.
http_status
).
to
eq
(
http_status
)
end
end
end
end
# This shared_example requires the following variables:
# This shared_example requires the following variables:
# - last_alert_attributes, last created alert
# - `service`, a service which includes ::IncidentManagement::Settings
# - project, project that alert created
RSpec
.
shared_context
'incident management settings enabled'
do
# - payload_raw, hash representation of payload
let
(
:auto_close_incident
)
{
true
}
# - environment, project's environment
let
(
:create_issue
)
{
true
}
# - fingerprint, fingerprint hash
let
(
:send_email
)
{
true
}
RSpec
.
shared_examples
'assigns the alert properties'
do
it
'ensures that created alert has all data properly assigned'
do
let
(
:incident_management_setting
)
do
subject
double
(
auto_close_incident?:
auto_close_incident
,
expect
(
last_alert_attributes
).
to
match
(
create_issue?:
create_issue
,
project_id:
project
.
id
,
send_email?:
send_email
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:
domain
,
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
end
end
RSpec
.
shared_examples
'does not an create alert management alert'
do
before
do
it
'does not create alert'
do
allow
(
ProjectServiceWorker
).
to
receive
(
:perform_async
)
expect
{
subject
}.
not_to
change
(
AlertManagement
::
Alert
,
:count
)
allow
(
service
)
.
to
receive
(
:incident_management_setting
)
.
and_return
(
incident_management_setting
)
end
end
end
end
RSpec
.
shared_examples
'adds an alert management alert event'
do
RSpec
.
shared_examples
'processes never-before-seen alert'
do
it
{
is_expected
.
to
be_success
}
it_behaves_like
'creates an alert management alert or errors'
it_behaves_like
'creates expected system notes for alert'
,
:new_alert
it
'does not create an alert'
do
it_behaves_like
'processes incident issues if enabled'
expect
{
subject
}.
not_to
change
(
AlertManagement
::
Alert
,
:count
)
it_behaves_like
'sends alert notification emails if enabled'
end
it
'increases alert events count'
do
expect
{
subject
}.
to
change
{
alert
.
reload
.
events
}.
by
(
1
)
end
it
'does not executes the alert service hooks'
do
expect
(
alert
).
not_to
receive
(
:execute_services
)
subject
end
end
end
RSpec
.
shared_examples
'processes incident issues'
do
RSpec
.
shared_examples
'processes never-before-seen recovery alert'
do
let
(
:create_incident_service
)
{
spy
}
it_behaves_like
'creates an alert management alert or errors'
it_behaves_like
'creates expected system notes for alert'
,
:new_alert
before
do
it_behaves_like
'sends alert notification emails if enabled'
allow_any_instance_of
(
AlertManagement
::
Alert
).
to
receive
(
:execute_services
)
it_behaves_like
'processes incident issues if enabled'
end
it
'processes issues'
do
expect
(
IncidentManagement
::
ProcessAlertWorker
)
.
to
receive
(
:perform_async
)
.
with
(
nil
,
nil
,
kind_of
(
Integer
))
.
once
Sidekiq
::
Testing
.
inline!
do
expect
(
subject
).
to
be_success
end
end
end
end
RSpec
.
shared_examples
'does not process incident issues'
do
RSpec
.
shared_examples
'processes one firing and one resolved prometheus alerts'
do
it
'does not process issues'
do
it
'creates AlertManagement::Alert'
do
expect
(
IncidentManagement
::
ProcessAlertWorker
)
expect
(
Gitlab
::
AppLogger
).
not_to
receive
(
:warn
)
.
not_to
receive
(
:perform_async
)
expect
(
subject
).
to
be_success
expect
{
subject
}
.
to
change
(
AlertManagement
::
Alert
,
:count
).
by
(
1
)
.
and
change
(
Note
,
:count
).
by
(
1
)
end
end
end
RSpec
.
shared_examples
'does not process incident issues due to error'
do
|
http_status
:|
it
'does not process issues'
do
expect
(
IncidentManagement
::
ProcessAlertWorker
)
.
not_to
receive
(
:perform_async
)
expect
(
subject
).
to
be_error
it_behaves_like
'processes incident issues'
expect
(
subject
.
http_status
).
to
eq
(
http_status
)
it_behaves_like
'sends alert notification emails'
,
count:
1
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment