Commit 6ad1b98a authored by Tetiana Chupryna's avatar Tetiana Chupryna

Merge branch '342730-add-alert-id-to-alert-response' into 'master'

Return alert IIDs and title in create response

See merge request gitlab-org/gitlab!73697
parents dc7d88dc b84b1252
...@@ -18,7 +18,11 @@ module Projects ...@@ -18,7 +18,11 @@ module Projects
token = extract_alert_manager_token(request) token = extract_alert_manager_token(request)
result = notify_service.execute(token, integration) result = notify_service.execute(token, integration)
head result.http_status if result.success?
render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status
else
head result.http_status
end
end end
private private
......
...@@ -30,7 +30,11 @@ module Projects ...@@ -30,7 +30,11 @@ module Projects
token = extract_alert_manager_token(request) token = extract_alert_manager_token(request)
result = notify_service.execute(token) result = notify_service.execute(token)
head result.http_status if result.success?
render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status
else
head result.http_status
end
end end
def create def create
......
# frozen_string_literal: true
module AlertManagement
class AlertEntity < Grape::Entity
expose :iid
expose :title
end
end
# frozen_string_literal: true
module AlertManagement
class AlertSerializer < BaseSerializer
entity AlertManagement::AlertEntity
end
end
...@@ -4,6 +4,7 @@ module AlertManagement ...@@ -4,6 +4,7 @@ module AlertManagement
class ProcessPrometheusAlertService class ProcessPrometheusAlertService
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
include ::AlertManagement::AlertProcessing include ::AlertManagement::AlertProcessing
include ::AlertManagement::Responses
def initialize(project, payload) def initialize(project, payload)
@project = project @project = project
...@@ -18,7 +19,7 @@ module AlertManagement ...@@ -18,7 +19,7 @@ module AlertManagement
complete_post_processing_tasks complete_post_processing_tasks
ServiceResponse.success success(alert)
end end
private private
...@@ -40,9 +41,5 @@ module AlertManagement ...@@ -40,9 +41,5 @@ module AlertManagement
def resolving_alert? def resolving_alert?
incoming_payload.resolved? incoming_payload.resolved?
end end
def bad_request
ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
end
end end
end end
# frozen_string_literal: true
module AlertManagement
# Module to hold common response logic for AlertManagement services.
module Responses
def success(alerts)
ServiceResponse.success(payload: { alerts: Array(alerts) })
end
def bad_request
ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
end
def unauthorized
ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
end
def unprocessable_entity
ServiceResponse.error(message: 'Unprocessable Entity', http_status: :unprocessable_entity)
end
def forbidden
ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
end
end
end
...@@ -5,6 +5,7 @@ module Projects ...@@ -5,6 +5,7 @@ module Projects
class NotifyService class NotifyService
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
include ::AlertManagement::AlertProcessing include ::AlertManagement::AlertProcessing
include ::AlertManagement::Responses
def initialize(project, payload) def initialize(project, payload)
@project = project @project = project
...@@ -23,7 +24,7 @@ module Projects ...@@ -23,7 +24,7 @@ module Projects
complete_post_processing_tasks complete_post_processing_tasks
ServiceResponse.success success(alert)
end end
private private
...@@ -46,18 +47,6 @@ module Projects ...@@ -46,18 +47,6 @@ module Projects
def valid_token?(token) def valid_token?(token)
token == integration.token token == integration.token
end end
def bad_request
ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
end
def unauthorized
ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
end
def forbidden
ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
end
end end
end end
end end
...@@ -6,6 +6,7 @@ module Projects ...@@ -6,6 +6,7 @@ module Projects
class NotifyService class NotifyService
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
include ::IncidentManagement::Settings include ::IncidentManagement::Settings
include ::AlertManagement::Responses
# This set of keys identifies a payload as a valid Prometheus # This set of keys identifies a payload as a valid Prometheus
# payload and thus processable by this service. See also # payload and thus processable by this service. See also
...@@ -27,9 +28,9 @@ module Projects ...@@ -27,9 +28,9 @@ module Projects
return unprocessable_entity unless self.class.processable?(payload) return unprocessable_entity unless self.class.processable?(payload)
return unauthorized unless valid_alert_manager_token?(token, integration) return unauthorized unless valid_alert_manager_token?(token, integration)
process_prometheus_alerts alert_responses = process_prometheus_alerts
ServiceResponse.success alert_response(alert_responses)
end end
def self.processable?(payload) def self.processable?(payload)
...@@ -128,23 +129,17 @@ module Projects ...@@ -128,23 +129,17 @@ module Projects
end end
def process_prometheus_alerts def process_prometheus_alerts
alerts.each do |alert| alerts.map do |alert|
AlertManagement::ProcessPrometheusAlertService AlertManagement::ProcessPrometheusAlertService
.new(project, alert.to_h) .new(project, alert.to_h)
.execute .execute
end end
end end
def bad_request def alert_response(alert_responses)
ServiceResponse.error(message: 'Bad Request', http_status: :bad_request) alerts = alert_responses.map { |resp| resp.payload[:alert] }.compact
end
def unauthorized
ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
end
def unprocessable_entity success(alerts)
ServiceResponse.error(message: 'Unprocessable Entity', http_status: :unprocessable_entity)
end end
end end
end end
......
...@@ -196,6 +196,25 @@ WARNING: ...@@ -196,6 +196,25 @@ WARNING:
Using your authorization key in the URL is insecure, as it's visible in server logs. We recommend Using your authorization key in the URL is insecure, as it's visible in server logs. We recommend
using one of the above header options if your tooling supports it. using one of the above header options if your tooling supports it.
## Response Body
The JSON response body contains a list of any alerts created within the request:
```json
[
{
"iid": 1,
"title": "Incident title"
},
{
"iid": 2,
"title": "Second Incident title"
}
]
```
Successful responses return a `200` response code.
## Triggering test alerts ## Triggering test alerts
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab in 13.2. > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab in 13.2.
......
...@@ -5,6 +5,7 @@ module AlertManagement ...@@ -5,6 +5,7 @@ module AlertManagement
class NetworkAlertService class NetworkAlertService
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
include ::AlertManagement::AlertProcessing include ::AlertManagement::AlertProcessing
include ::AlertManagement::Responses
MONITORING_TOOL = Gitlab::AlertManagement::Payload::MONITORING_TOOLS.fetch(:cilium) MONITORING_TOOL = Gitlab::AlertManagement::Payload::MONITORING_TOOLS.fetch(:cilium)
...@@ -20,7 +21,7 @@ module AlertManagement ...@@ -20,7 +21,7 @@ module AlertManagement
return bad_request unless alert.persisted? return bad_request unless alert.persisted?
ServiceResponse.success success(alert)
end end
private private
......
...@@ -16,7 +16,9 @@ RSpec.describe Projects::Alerting::NotificationsController do ...@@ -16,7 +16,9 @@ RSpec.describe Projects::Alerting::NotificationsController do
end end
shared_examples 'process alert payload' do |notify_service_class| shared_examples 'process alert payload' do |notify_service_class|
let(:service_response) { ServiceResponse.success } let(:alert_1) { build(:alert_management_alert, project: project) }
let(:alert_2) { build(:alert_management_alert, project: project) }
let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) }
let(:notify_service) { instance_double(notify_service_class, execute: service_response) } let(:notify_service) { instance_double(notify_service_class, execute: service_response) }
before do before do
...@@ -30,9 +32,13 @@ RSpec.describe Projects::Alerting::NotificationsController do ...@@ -30,9 +32,13 @@ RSpec.describe Projects::Alerting::NotificationsController do
context 'when notification service succeeds' do context 'when notification service succeeds' do
let(:permitted_params) { ActionController::Parameters.new(payload).permit! } let(:permitted_params) { ActionController::Parameters.new(payload).permit! }
it 'responds with ok' do it 'responds with the alert data' do
make_request make_request
expect(json_response).to contain_exactly(
{ 'iid' => alert_1.iid, 'title' => alert_1.title },
{ 'iid' => alert_2.iid, 'title' => alert_2.title }
)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
......
...@@ -160,7 +160,9 @@ RSpec.describe Projects::Prometheus::AlertsController do ...@@ -160,7 +160,9 @@ RSpec.describe Projects::Prometheus::AlertsController do
end end
describe 'POST #notify' do describe 'POST #notify' do
let(:service_response) { ServiceResponse.success } let(:alert_1) { build(:alert_management_alert, :prometheus, project: project) }
let(:alert_2) { build(:alert_management_alert, :prometheus, project: project) }
let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) }
let(:notify_service) { instance_double(Projects::Prometheus::Alerts::NotifyService, execute: service_response) } let(:notify_service) { instance_double(Projects::Prometheus::Alerts::NotifyService, execute: service_response) }
before do before do
...@@ -173,10 +175,15 @@ RSpec.describe Projects::Prometheus::AlertsController do ...@@ -173,10 +175,15 @@ RSpec.describe Projects::Prometheus::AlertsController do
end end
it 'returns ok if notification succeeds' do it 'returns ok if notification succeeds' do
expect(notify_service).to receive(:execute).and_return(ServiceResponse.success) expect(notify_service).to receive(:execute).and_return(service_response)
post :notify, params: project_params, session: { as: :json } post :notify, params: project_params, session: { as: :json }
expect(json_response).to contain_exactly(
{ 'iid' => alert_1.iid, 'title' => alert_1.title },
{ 'iid' => alert_2.iid, 'title' => alert_2.title }
)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
......
...@@ -218,8 +218,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do ...@@ -218,8 +218,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
.to receive(:new) .to receive(:new)
.with(project, kind_of(Hash)) .with(project, kind_of(Hash))
.exactly(3).times .exactly(3).times
.and_return(process_service) .and_call_original
expect(process_service).to receive(:execute).exactly(3).times
subject subject
end end
......
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
# This shared_example requires the following variables: # This shared_example requires the following variables:
# - `service`, the service which includes AlertManagement::AlertProcessing # - `service`, the service which includes AlertManagement::AlertProcessing
RSpec.shared_examples 'creates an alert management alert or errors' do RSpec.shared_examples 'creates an alert management alert or errors' do
it { is_expected.to be_success } specify do
expect(subject).to be_success
expect(subject.payload).to match(alerts: all(a_kind_of(AlertManagement::Alert)))
end
it 'creates AlertManagement::Alert' do it 'creates AlertManagement::Alert' do
expect(Gitlab::AppLogger).not_to receive(:warn) expect(Gitlab::AppLogger).not_to receive(:warn)
...@@ -89,6 +92,7 @@ RSpec.shared_examples 'adds an alert management alert event' do ...@@ -89,6 +92,7 @@ RSpec.shared_examples 'adds an alert management alert event' do
expect { subject }.to change { alert.reload.events }.by(1) expect { subject }.to change { alert.reload.events }.by(1)
expect(subject).to be_success expect(subject).to be_success
expect(subject.payload).to match(alerts: all(a_kind_of(AlertManagement::Alert)))
end end
it_behaves_like 'does not create an alert management alert' it_behaves_like 'does not create an alert management alert'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment