summaryrefslogtreecommitdiff
path: root/spec/controllers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-27 21:07:53 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-27 21:07:53 +0000
commitf50b93c373428d624cc2cabe98e4022dce846e67 (patch)
tree0349e25d3d106aabd6b520afa96ebd35578ab38b /spec/controllers
parente20baee820ea2c76ee16980a98e8080f255d9035 (diff)
downloadgitlab-ce-f50b93c373428d624cc2cabe98e4022dce846e67.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/controllers')
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb12
-rw-r--r--spec/controllers/projects/prometheus/alerts_controller_spec.rb394
2 files changed, 406 insertions, 0 deletions
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index 88c14e03fd8..a220c1bff95 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -16,6 +16,18 @@ describe Projects::MergeRequests::DiffsController do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'when the merge_request_diff.id is blank' do
+ it 'returns 404' do
+ allow_next_instance_of(MergeRequest) do |instance|
+ allow(instance).to receive(:merge_request_diff).and_return(MergeRequestDiff.new(merge_request_id: instance.id))
+
+ go
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
end
shared_examples 'forked project with submodules' do
diff --git a/spec/controllers/projects/prometheus/alerts_controller_spec.rb b/spec/controllers/projects/prometheus/alerts_controller_spec.rb
new file mode 100644
index 00000000000..e215f4b68fa
--- /dev/null
+++ b/spec/controllers/projects/prometheus/alerts_controller_spec.rb
@@ -0,0 +1,394 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::Prometheus::AlertsController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:environment) { create(:environment, project: project) }
+ let_it_be(:metric) { create(:prometheus_metric, project: project) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ shared_examples 'unprivileged' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns not_found' do
+ make_request
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ shared_examples 'project non-specific environment' do |status|
+ let(:other) { create(:environment) }
+
+ it "returns #{status}" do
+ make_request(environment_id: other)
+
+ expect(response).to have_gitlab_http_status(status)
+ end
+
+ if status == :ok
+ it 'returns no prometheus alerts' do
+ make_request(environment_id: other)
+
+ expect(json_response).to be_empty
+ end
+ end
+ end
+
+ shared_examples 'project non-specific metric' do |status|
+ let(:other) { create(:prometheus_alert) }
+
+ it "returns #{status}" do
+ make_request(id: other.prometheus_metric_id)
+
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
+ describe 'GET #index' do
+ def make_request(opts = {})
+ get :index, params: request_params(opts, environment_id: environment)
+ end
+
+ context 'when project has no prometheus alert' do
+ it 'returns an empty response' do
+ make_request
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'when project has prometheus alerts' do
+ let(:production) { create(:environment, project: project) }
+ let(:staging) { create(:environment, project: project) }
+ let(:json_alert_ids) { json_response.map { |alert| alert['id'] } }
+
+ let!(:production_alerts) do
+ create_list(:prometheus_alert, 2, project: project, environment: production)
+ end
+
+ let!(:staging_alerts) do
+ create_list(:prometheus_alert, 1, project: project, environment: staging)
+ end
+
+ it 'contains prometheus alerts only for the production environment' do
+ make_request(environment_id: production)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(2)
+ expect(json_alert_ids).to eq(production_alerts.map(&:id))
+ end
+
+ it 'contains prometheus alerts only for the staging environment' do
+ make_request(environment_id: staging)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(1)
+ expect(json_alert_ids).to eq(staging_alerts.map(&:id))
+ end
+
+ it 'does not return prometheus alerts without environment' do
+ make_request(environment_id: nil)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+ end
+
+ it_behaves_like 'unprivileged'
+ it_behaves_like 'project non-specific environment', :ok
+ end
+
+ describe 'GET #show' do
+ let(:alert) do
+ create(:prometheus_alert,
+ project: project,
+ environment: environment,
+ prometheus_metric: metric)
+ end
+
+ def make_request(opts = {})
+ get :show, params: request_params(
+ opts,
+ id: alert.prometheus_metric_id,
+ environment_id: environment
+ )
+ end
+
+ context 'when alert does not exist' do
+ it 'returns not_found' do
+ make_request(id: 0)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when alert exists' do
+ let(:alert_params) do
+ {
+ 'id' => alert.id,
+ 'title' => alert.title,
+ 'query' => alert.query,
+ 'operator' => alert.computed_operator,
+ 'threshold' => alert.threshold,
+ 'alert_path' => alert_path(alert)
+ }
+ end
+
+ it 'renders the alert' do
+ make_request
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(alert_params)
+ end
+
+ it_behaves_like 'unprivileged'
+ it_behaves_like 'project non-specific environment', :not_found
+ it_behaves_like 'project non-specific metric', :not_found
+ end
+ end
+
+ describe 'POST #notify' do
+ let(:notify_service) { spy }
+
+ before do
+ sign_out(user)
+
+ expect(Projects::Prometheus::Alerts::NotifyService)
+ .to receive(:new)
+ .with(project, nil, duck_type(:permitted?))
+ .and_return(notify_service)
+ end
+
+ it 'returns ok if notification succeeds' do
+ expect(notify_service).to receive(:execute).and_return(true)
+
+ post :notify, params: project_params, session: { as: :json }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns unprocessable entity if notification fails' do
+ expect(notify_service).to receive(:execute).and_return(false)
+
+ post :notify, params: project_params, session: { as: :json }
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+
+ context 'bearer token' do
+ context 'when set' do
+ it 'extracts bearer token' do
+ request.headers['HTTP_AUTHORIZATION'] = 'Bearer some token'
+
+ expect(notify_service).to receive(:execute).with('some token')
+
+ post :notify, params: project_params, as: :json
+ end
+
+ it 'pass nil if cannot extract a non-bearer token' do
+ request.headers['HTTP_AUTHORIZATION'] = 'some token'
+
+ expect(notify_service).to receive(:execute).with(nil)
+
+ post :notify, params: project_params, as: :json
+ end
+ end
+
+ context 'when missing' do
+ it 'passes nil' do
+ expect(notify_service).to receive(:execute).with(nil)
+
+ post :notify, params: project_params, as: :json
+ end
+ end
+ end
+ end
+
+ describe 'POST #create' do
+ let(:schedule_update_service) { spy }
+
+ let(:alert_params) do
+ {
+ 'title' => metric.title,
+ 'query' => metric.query,
+ 'operator' => '>',
+ 'threshold' => 1.0
+ }
+ end
+
+ def make_request(opts = {})
+ post :create, params: request_params(
+ opts,
+ operator: '>',
+ threshold: '1',
+ environment_id: environment,
+ prometheus_metric_id: metric
+ )
+ end
+
+ it 'creates a new prometheus alert' do
+ allow(::Clusters::Applications::ScheduleUpdateService)
+ .to receive(:new).and_return(schedule_update_service)
+
+ make_request
+
+ expect(schedule_update_service).to have_received(:execute)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(alert_params)
+ end
+
+ it 'returns no_content for an invalid metric' do
+ make_request(prometheus_metric_id: 'invalid')
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it_behaves_like 'unprivileged'
+ it_behaves_like 'project non-specific environment', :no_content
+ end
+
+ describe 'PUT #update' do
+ let(:schedule_update_service) { spy }
+
+ let(:alert) do
+ create(:prometheus_alert,
+ project: project,
+ environment: environment,
+ prometheus_metric: metric)
+ end
+
+ let(:alert_params) do
+ {
+ 'id' => alert.id,
+ 'title' => alert.title,
+ 'query' => alert.query,
+ 'operator' => '<',
+ 'threshold' => alert.threshold,
+ 'alert_path' => alert_path(alert)
+ }
+ end
+
+ before do
+ allow(::Clusters::Applications::ScheduleUpdateService)
+ .to receive(:new).and_return(schedule_update_service)
+ end
+
+ def make_request(opts = {})
+ put :update, params: request_params(
+ opts,
+ id: alert.prometheus_metric_id,
+ operator: '<',
+ environment_id: alert.environment
+ )
+ end
+
+ it 'updates an already existing prometheus alert' do
+ expect { make_request(operator: '<') }
+ .to change { alert.reload.operator }.to('lt')
+
+ expect(schedule_update_service).to have_received(:execute)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(alert_params)
+ end
+
+ it_behaves_like 'unprivileged'
+ it_behaves_like 'project non-specific environment', :not_found
+ it_behaves_like 'project non-specific metric', :not_found
+ end
+
+ describe 'DELETE #destroy' do
+ let(:schedule_update_service) { spy }
+
+ let!(:alert) do
+ create(:prometheus_alert, project: project, prometheus_metric: metric)
+ end
+
+ before do
+ allow(::Clusters::Applications::ScheduleUpdateService)
+ .to receive(:new).and_return(schedule_update_service)
+ end
+
+ def make_request(opts = {})
+ delete :destroy, params: request_params(
+ opts,
+ id: alert.prometheus_metric_id,
+ environment_id: alert.environment
+ )
+ end
+
+ it 'destroys the specified prometheus alert' do
+ expect { make_request }.to change { PrometheusAlert.count }.by(-1)
+
+ expect(schedule_update_service).to have_received(:execute)
+ end
+
+ it_behaves_like 'unprivileged'
+ it_behaves_like 'project non-specific environment', :not_found
+ it_behaves_like 'project non-specific metric', :not_found
+ end
+
+ describe 'GET #metrics_dashboard' do
+ let!(:alert) do
+ create(:prometheus_alert,
+ project: project,
+ environment: environment,
+ prometheus_metric: metric)
+ end
+
+ it 'returns a json object with the correct keys' do
+ get :metrics_dashboard, params: request_params(id: metric.id, environment_id: alert.environment.id), format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.keys).to contain_exactly('dashboard', 'status')
+ end
+
+ it 'is the correct embed' do
+ get :metrics_dashboard, params: request_params(id: metric.id, environment_id: alert.environment.id), format: :json
+
+ title = json_response['dashboard']['panel_groups'][0]['panels'][0]['title']
+
+ expect(title).to eq(metric.title)
+ end
+
+ it 'finds the first alert embed without environment_id' do
+ get :metrics_dashboard, params: request_params(id: metric.id), format: :json
+
+ title = json_response['dashboard']['panel_groups'][0]['panels'][0]['title']
+
+ expect(title).to eq(metric.title)
+ end
+
+ it 'returns 404 for non-existant alerts' do
+ get :metrics_dashboard, params: request_params(id: 0), format: :json
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ def project_params(opts = {})
+ opts.reverse_merge(namespace_id: project.namespace, project_id: project)
+ end
+
+ def request_params(opts = {}, defaults = {})
+ project_params(opts.reverse_merge(defaults))
+ end
+
+ def alert_path(alert)
+ project_prometheus_alert_path(
+ project,
+ alert.prometheus_metric_id,
+ environment_id: alert.environment,
+ format: :json
+ )
+ end
+end