Commit eb759513 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch '4925-open-issues-based-on-prometheus-alerts-controller' into 'master'

Expose and manage incident management settings

See merge request gitlab-org/gitlab-ee!9773
parents 1c3e0ea4 6ca79ae4
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
module Projects module Projects
module Settings module Settings
class OperationsController < Projects::ApplicationController class OperationsController < Projects::ApplicationController
before_action :check_license
before_action :authorize_update_environment! before_action :authorize_update_environment!
helper_method :error_tracking_setting helper_method :error_tracking_setting
...@@ -65,10 +64,6 @@ module Projects ...@@ -65,10 +64,6 @@ module Projects
] ]
} }
end end
def check_license
render_404 unless helpers.settings_operations_available?
end
end end
end end
end end
......
...@@ -25,7 +25,7 @@ module EE ...@@ -25,7 +25,7 @@ module EE
end end
end end
helper_method :tracing_setting helper_method :tracing_setting, :incident_management_available?
private private
...@@ -45,11 +45,37 @@ module EE ...@@ -45,11 +45,37 @@ module EE
def tracing_setting def tracing_setting
@tracing_setting ||= project.tracing_setting || project.build_tracing_setting @tracing_setting ||= project.tracing_setting || project.build_tracing_setting
end end
def has_tracing_license?
project.feature_available?(:tracing, current_user)
end
def has_incident_management_license?
project.feature_available?(:incident_management, current_user)
end
def incident_management_feature_enabled?
::Feature.enabled?(:incident_management)
end
def incident_management_available?
incident_management_feature_enabled? && has_incident_management_license?
end
end end
override :permitted_project_params override :permitted_project_params
def permitted_project_params def permitted_project_params
super.merge(tracing_setting_attributes: [:external_url]) permitted_params = super
if has_tracing_license?
permitted_params[:tracing_setting_attributes] = [:external_url]
end
if incident_management_available?
permitted_params[:incident_management_setting_attributes] = [:create_issue, :send_email, :issue_template_key]
end
permitted_params
end end
override :render_update_response override :render_update_response
......
...@@ -214,5 +214,10 @@ module EE ...@@ -214,5 +214,10 @@ module EE
@project.feature_available?(:tracing, current_user) && can?(current_user, :read_environment, @project) @project.feature_available?(:tracing, current_user) && can?(current_user, :read_environment, @project)
end end
def project_incident_management_setting
@project_incident_management_setting ||= @project.incident_management_setting ||
@project.build_incident_management_setting
end
end end
end end
...@@ -123,6 +123,7 @@ module EE ...@@ -123,6 +123,7 @@ module EE
accepts_nested_attributes_for :tracing_setting, update_only: true, allow_destroy: true accepts_nested_attributes_for :tracing_setting, update_only: true, allow_destroy: true
accepts_nested_attributes_for :alerting_setting, update_only: true accepts_nested_attributes_for :alerting_setting, update_only: true
accepts_nested_attributes_for :incident_management_setting, update_only: true
alias_attribute :fallback_approvals_required, :approvals_before_merge alias_attribute :fallback_approvals_required, :approvals_before_merge
end end
......
...@@ -95,6 +95,7 @@ class License < ActiveRecord::Base ...@@ -95,6 +95,7 @@ class License < ActiveRecord::Base
tracing tracing
insights insights
web_ide_terminal web_ide_terminal
incident_management
] ]
EEU_FEATURES.freeze EEU_FEATURES.freeze
......
...@@ -12,6 +12,7 @@ module EE ...@@ -12,6 +12,7 @@ module EE
super super
.merge(tracing_setting_params) .merge(tracing_setting_params)
.merge(alerting_setting_params) .merge(alerting_setting_params)
.merge(incident_management_setting_params)
end end
private private
...@@ -41,6 +42,10 @@ module EE ...@@ -41,6 +42,10 @@ module EE
{ alerting_setting_attributes: attr } { alerting_setting_attributes: attr }
end end
def incident_management_setting_params
params.slice(:incident_management_setting_attributes)
end
end end
end end
end end
......
---
title: Add an incident management settings form and create issues from alertmanager
alerts
merge_request: 9773
author:
type: added
...@@ -10,12 +10,11 @@ describe Projects::Settings::OperationsController do ...@@ -10,12 +10,11 @@ describe Projects::Settings::OperationsController do
end end
describe 'GET show' do describe 'GET show' do
shared_examples 'user without read access' do |project_visibility| shared_examples 'user without read access' do |project_visibility, project_role|
let(:project) { create(:project, project_visibility) } let(:project) { create(:project, project_visibility) }
%w[guest reporter developer].each do |role|
before do before do
project.public_send("add_#{role}", user) project.add_role(user, project_role)
end end
it 'returns 404' do it 'returns 404' do
...@@ -24,7 +23,6 @@ describe Projects::Settings::OperationsController do ...@@ -24,7 +23,6 @@ describe Projects::Settings::OperationsController do
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
end end
end
shared_examples 'user with read access' do |project_visibility| shared_examples 'user with read access' do |project_visibility|
let(:project) { create(:project, project_visibility) } let(:project) { create(:project, project_visibility) }
...@@ -53,7 +51,7 @@ describe Projects::Settings::OperationsController do ...@@ -53,7 +51,7 @@ describe Projects::Settings::OperationsController do
context 'with a license' do context 'with a license' do
before do before do
stub_licensed_features(tracing: true) stub_licensed_features(tracing: true, incident_management: true)
end end
context 'with maintainer role' do context 'with maintainer role' do
...@@ -63,9 +61,11 @@ describe Projects::Settings::OperationsController do ...@@ -63,9 +61,11 @@ describe Projects::Settings::OperationsController do
end end
context 'without maintainer role' do context 'without maintainer role' do
it_behaves_like 'user without read access', :public %w[guest reporter developer].each do |role|
it_behaves_like 'user without read access', :private it_behaves_like 'user without read access', :public, role
it_behaves_like 'user without read access', :internal it_behaves_like 'user without read access', :private, role
it_behaves_like 'user without read access', :internal, role
end
end end
context 'when user not logged in' do context 'when user not logged in' do
...@@ -73,7 +73,7 @@ describe Projects::Settings::OperationsController do ...@@ -73,7 +73,7 @@ describe Projects::Settings::OperationsController do
sign_out(user) sign_out(user)
end end
it_behaves_like 'user without read access', :public it_behaves_like 'user without read access', :public, :maintainer
it_behaves_like 'user needs to login', :private it_behaves_like 'user needs to login', :private
it_behaves_like 'user needs to login', :internal it_behaves_like 'user needs to login', :internal
...@@ -82,12 +82,12 @@ describe Projects::Settings::OperationsController do ...@@ -82,12 +82,12 @@ describe Projects::Settings::OperationsController do
context 'without license' do context 'without license' do
before do before do
stub_licensed_features(tracing: false) stub_licensed_features(tracing: false, incident_management: false)
end end
it_behaves_like 'user without read access', :public it_behaves_like 'user with read access', :public
it_behaves_like 'user without read access', :private it_behaves_like 'user with read access', :private
it_behaves_like 'user without read access', :internal it_behaves_like 'user with read access', :internal
end end
end end
...@@ -96,25 +96,75 @@ describe Projects::Settings::OperationsController do ...@@ -96,25 +96,75 @@ describe Projects::Settings::OperationsController do
let(:private_project) { create(:project, :private) } let(:private_project) { create(:project, :private) }
let(:internal_project) { create(:project, :internal) } let(:internal_project) { create(:project, :internal) }
let(:incident_management_settings) do
{
create_issue: true,
send_email: true,
issue_template_key: 'some-key'
}
end
before do before do
public_project.add_maintainer(user) public_project.add_maintainer(user)
private_project.add_maintainer(user) private_project.add_maintainer(user)
internal_project.add_maintainer(user) internal_project.add_maintainer(user)
end end
shared_examples 'user without write access' do |project_visibility| shared_examples 'user without write access' do |project_visibility, project_role|
let(:project) { create(:project, project_visibility) } let(:project) { create(:project, project_visibility) }
%w[guest reporter developer].each do |role|
before do before do
project.public_send("add_#{role}", user) project.add_role(user, project_role)
end end
it 'does not update tracing external_url' do it 'does not create tracing_setting' do
update_project(project, external_url: 'https://gitlab.com') update_project(
project,
tracing_params: { external_url: 'https://gitlab.com' }
)
expect(project.tracing_setting).to be_nil expect(project.tracing_setting).to be_nil
end end
it 'does not create incident_management_setting' do
update_project(
project,
incident_management_params: incident_management_settings
)
expect(project.incident_management_setting).to be_nil
end
context 'with existing incident_management_setting' do
let(:new_incident_management_settings) do
{
create_issue: false,
send_email: false,
issue_template_key: 'some-other-template'
}
end
let!(:incident_management_setting) do
create(:project_incident_management_setting,
project: project,
**incident_management_settings)
end
it 'does not update incident_management_setting' do
update_project(project,
incident_management_params: new_incident_management_settings)
setting = project.incident_management_setting
expect(setting.create_issue).to(
eq(incident_management_settings[:create_issue])
)
expect(setting.send_email).to(
eq(incident_management_settings[:send_email])
)
expect(setting.issue_template_key).to(
eq(incident_management_settings[:issue_template_key])
)
end
end end
end end
...@@ -134,7 +184,7 @@ describe Projects::Settings::OperationsController do ...@@ -134,7 +184,7 @@ describe Projects::Settings::OperationsController do
end end
it 'shows a notice' do it 'shows a notice' do
update_project(project, { external_url: 'http://gitlab.com' }) update_project(project, tracing_params: { external_url: 'http://gitlab.com' })
expect(response).to redirect_to(project_settings_operations_url(project)) expect(response).to redirect_to(project_settings_operations_url(project))
expect(flash[:notice]).to eq _('Your changes have been saved') expect(flash[:notice]).to eq _('Your changes have been saved')
...@@ -147,7 +197,7 @@ describe Projects::Settings::OperationsController do ...@@ -147,7 +197,7 @@ describe Projects::Settings::OperationsController do
end end
it 'renders show page' do it 'renders show page' do
update_project(project, { external_url: 'http://gitlab.com' }) update_project(project, tracing_params: { external_url: 'http://gitlab.com' })
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show) expect(response).to render_template(:show)
...@@ -157,33 +207,77 @@ describe Projects::Settings::OperationsController do ...@@ -157,33 +207,77 @@ describe Projects::Settings::OperationsController do
context 'with a license' do context 'with a license' do
before do before do
stub_licensed_features(tracing: true) stub_licensed_features(tracing: true, incident_management: true)
end end
shared_examples 'user with write access' do |project_visibility, value_to_set, value_to_check| shared_examples 'user with write access' do |project_visibility|
let(:project) { create(:project, project_visibility) } let(:project) { create(:project, project_visibility) }
let(:tracing_url) { 'https://gitlab.com' }
before do before do
project.add_maintainer(user) project.add_maintainer(user)
end end
it 'updates tracing external_url' do it 'creates tracing setting' do
update_project(project, external_url: value_to_set) update_project(
project,
tracing_params: { external_url: tracing_url }
)
expect(project.tracing_setting.external_url).to eq(tracing_url)
end
it 'creates incident management settings' do
update_project(
project,
incident_management_params: incident_management_settings
)
expect(project.incident_management_setting.create_issue).to(
eq(incident_management_settings.dig(:create_issue))
)
expect(project.incident_management_setting.send_email).to(
eq(incident_management_settings.dig(:send_email))
)
expect(project.incident_management_setting.issue_template_key).to(
eq(incident_management_settings.dig(:issue_template_key))
)
end
it 'creates tracing and incident management settings' do
update_project(
project,
tracing_params: { external_url: tracing_url },
incident_management_params: incident_management_settings
)
expect(project.tracing_setting.external_url).to eq(value_to_check) expect(project.tracing_setting.external_url).to eq(tracing_url)
expect(project.incident_management_setting.create_issue).to(
eq(incident_management_settings.dig(:create_issue))
)
expect(project.incident_management_setting.send_email).to(
eq(incident_management_settings.dig(:send_email))
)
expect(project.incident_management_setting.issue_template_key).to(
eq(incident_management_settings.dig(:issue_template_key))
)
end end
end end
context 'with maintainer role' do context 'with maintainer role' do
it_behaves_like 'user with write access', :public, 'https://gitlab.com', 'https://gitlab.com' it_behaves_like 'user with write access', :public
it_behaves_like 'user with write access', :private, 'https://gitlab.com', 'https://gitlab.com' it_behaves_like 'user with write access', :private
it_behaves_like 'user with write access', :internal, 'https://gitlab.com', 'https://gitlab.com' it_behaves_like 'user with write access', :internal
end end
context 'with non maintainer roles' do context 'with non maintainer roles' do
it_behaves_like 'user without write access', :public %w[guest reporter developer].each do |role|
it_behaves_like 'user without write access', :private context "with #{role} role" do
it_behaves_like 'user without write access', :internal it_behaves_like 'user without write access', :public, role
it_behaves_like 'user without write access', :private, role
it_behaves_like 'user without write access', :internal, role
end
end
end end
context 'with anonymous user' do context 'with anonymous user' do
...@@ -191,9 +285,9 @@ describe Projects::Settings::OperationsController do ...@@ -191,9 +285,9 @@ describe Projects::Settings::OperationsController do
sign_out(user) sign_out(user)
end end
it_behaves_like 'user without write access', :public it_behaves_like 'user without write access', :public, :maintainer
it_behaves_like 'user without write access', :private it_behaves_like 'user without write access', :private, :maintainer
it_behaves_like 'user without write access', :internal it_behaves_like 'user without write access', :internal, :maintainer
end end
context 'with existing tracing_setting' do context 'with existing tracing_setting' do
...@@ -205,26 +299,26 @@ describe Projects::Settings::OperationsController do ...@@ -205,26 +299,26 @@ describe Projects::Settings::OperationsController do
end end
it 'unsets external_url with nil' do it 'unsets external_url with nil' do
update_project(project, external_url: nil) update_project(project, tracing_params: { external_url: nil })
expect(project.tracing_setting).to be_nil expect(project.tracing_setting).to be_nil
end end
it 'unsets external_url with empty string' do it 'unsets external_url with empty string' do
update_project(project, external_url: '') update_project(project, tracing_params: { external_url: '' })
expect(project.tracing_setting).to be_nil expect(project.tracing_setting).to be_nil
end end
it 'fails validation with invalid url' do it 'fails validation with invalid url' do
expect do expect do
update_project(project, external_url: "invalid") update_project(project, tracing_params: { external_url: "invalid" })
end.not_to change(project.tracing_setting, :external_url) end.not_to change(project.tracing_setting, :external_url)
end end
it 'does not set external_url if not present in params' do it 'does not set external_url if not present in params' do
expect do expect do
update_project(project, some_param: 'some_value') update_project(project, tracing_params: { some_param: 'some_value' })
end.not_to change(project.tracing_setting, :external_url) end.not_to change(project.tracing_setting, :external_url)
end end
end end
...@@ -237,33 +331,85 @@ describe Projects::Settings::OperationsController do ...@@ -237,33 +331,85 @@ describe Projects::Settings::OperationsController do
end end
it 'fails validation with invalid url' do it 'fails validation with invalid url' do
update_project(project, external_url: "invalid") update_project(project, tracing_params: { external_url: "invalid" })
expect(project.tracing_setting).to be_nil expect(project.tracing_setting).to be_nil
end end
it 'does not set external_url if not present in params' do it 'does not set external_url if not present in params' do
update_project(project, some_param: 'some_value') update_project(project, tracing_params: { some_param: 'some_value' })
expect(project.tracing_setting).to be_nil expect(project.tracing_setting).to be_nil
end end
end end
context 'with existing incident management setting' do
let(:project) { create(:project) }
let(:new_incident_management_settings) do
{
create_issue: false,
send_email: false,
issue_template_key: 'some-other-template'
}
end
let!(:incident_management_setting) do
create(:project_incident_management_setting,
project: project,
**incident_management_settings)
end
before do
project.add_maintainer(user)
end
it 'updates incident management setting' do
update_project(project,
incident_management_params: new_incident_management_settings)
setting = project.incident_management_setting
expect(setting.create_issue).to(
eq(new_incident_management_settings[:create_issue])
)
expect(setting.send_email).to(
eq(new_incident_management_settings[:send_email])
)
expect(setting.issue_template_key).to(
eq(new_incident_management_settings[:issue_template_key])
)
end
end
end end
context 'without a license' do context 'without a license' do
before do before do
stub_licensed_features(tracing: false) stub_licensed_features(tracing: false, incident_management: false)
end
it_behaves_like 'user without write access', :public, :maintainer
it_behaves_like 'user without write access', :private, :maintainer
it_behaves_like 'user without write access', :internal, :maintainer
end
context 'with incident_management feature flag disabled' do
before do
stub_feature_flags(incident_management: false)
end end
it_behaves_like 'user without write access', :public it_behaves_like 'user without write access', :public, :maintainer
it_behaves_like 'user without write access', :private it_behaves_like 'user without write access', :private, :maintainer
it_behaves_like 'user without write access', :internal it_behaves_like 'user without write access', :internal, :maintainer
end end
private private
def update_project(project, params) def update_project(project, tracing_params: nil, incident_management_params: nil)
patch :update, params: project_params(project, params) patch :update, params: project_params(
project,
tracing_params: tracing_params,
incident_management_params: incident_management_params
)
project.reload project.reload
end end
...@@ -372,12 +518,13 @@ describe Projects::Settings::OperationsController do ...@@ -372,12 +518,13 @@ describe Projects::Settings::OperationsController do
private private
def project_params(project, params = {}) def project_params(project, tracing_params: nil, incident_management_params: nil)
{ {
namespace_id: project.namespace, namespace_id: project.namespace,
project_id: project, project_id: project,
project: { project: {
tracing_setting_attributes: params tracing_setting_attributes: tracing_params,
incident_management_setting_attributes: incident_management_params
} }
} }
end end
......
# frozen_string_literal: true
require 'spec_helper'
describe ProjectsHelper do
describe '#project_incident_management_setting' do
set(:project) { create(:project) }
before do
helper.instance_variable_set(:@project, project)
end
context 'when incident_management_setting exists' do
let(:project_incident_management_setting) do
create(:project_incident_management_setting, project: project)
end
it 'return project_incident_management_setting' do
expect(helper.project_incident_management_setting).to(
eq(project_incident_management_setting)
)
end
end
context 'when incident_management_setting does not exist' do
it 'builds incident_management_setting' do
expect(helper.project_incident_management_setting.persisted?).to be(false)
expect(helper.project_incident_management_setting.send_email).to be(true)
expect(helper.project_incident_management_setting.create_issue).to be(false)
expect(helper.project_incident_management_setting.issue_template_key).to be(nil)
end
end
end
end
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