diff options
20 files changed, 448 insertions, 61 deletions
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js index f43b6f3d777..51879f280e0 100644 --- a/app/assets/javascripts/contextual_sidebar.js +++ b/app/assets/javascripts/contextual_sidebar.js @@ -1,13 +1,9 @@ import $ from 'jquery'; import Cookies from 'js-cookie'; import _ from 'underscore'; -import bp from './breakpoints'; +import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils'; import { parseBoolean } from '~/lib/utils/common_utils'; -// NOTE: at 1200px nav sidebar should not overlap the content -// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/24555#note_134136110 -const NAV_SIDEBAR_BREAKPOINT = 1200; - export const SIDEBAR_COLLAPSED_CLASS = 'js-sidebar-collapsed'; export default class ContextualSidebar { @@ -50,9 +46,10 @@ export default class ContextualSidebar { $(window).on('resize', () => _.debounce(this.render(), 100)); } - // TODO: use the breakpoints from breakpoints.js once they have been updated for bootstrap 4 // See documentation: https://design.gitlab.com/regions/navigation#contextual-navigation - static isDesktopBreakpoint = () => bp.windowWidth() >= NAV_SIDEBAR_BREAKPOINT; + // NOTE: at 1200px nav sidebar should not overlap the content + // https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/24555#note_134136110 + static isDesktopBreakpoint = () => bp.windowWidth() >= breakpoints.xl; static setCollapsedCookie(value) { if (!ContextualSidebar.isDesktopBreakpoint()) { return; @@ -63,12 +60,13 @@ export default class ContextualSidebar { toggleSidebarNav(show) { const breakpoint = bp.getBreakpointSize(); const dbp = ContextualSidebar.isDesktopBreakpoint(); + const supportedSizes = ['xs', 'sm', 'md']; this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show); this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? show : false); this.$overlay.toggleClass( 'mobile-nav-open', - breakpoint === 'xs' || breakpoint === 'sm' ? show : false, + supportedSizes.includes(breakpoint) ? show : false, ); this.$sidebar.removeClass('sidebar-collapsed-desktop'); } @@ -76,13 +74,14 @@ export default class ContextualSidebar { toggleCollapsedSidebar(collapsed, saveCookie) { const breakpoint = bp.getBreakpointSize(); const dbp = ContextualSidebar.isDesktopBreakpoint(); + const supportedSizes = ['xs', 'sm', 'md']; if (this.$sidebar.length) { this.$sidebar.toggleClass(`sidebar-collapsed-desktop ${SIDEBAR_COLLAPSED_CLASS}`, collapsed); this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? !collapsed : false); this.$page.toggleClass( 'page-with-icon-sidebar', - breakpoint === 'xs' || breakpoint === 'sm' ? true : collapsed, + supportedSizes.includes(breakpoint) ? true : collapsed, ); } diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 9d81d3fad07..58f088c6335 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -6,10 +6,21 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController before_action :set_application_setting before_action :whitelist_query_limiting, only: [:usage_data] + before_action do + push_frontend_feature_flag(:self_monitoring_project) + end + VALID_SETTING_PANELS = %w(general integrations repository ci_cd reporting metrics_and_profiling network preferences).freeze + # The current size of a sidekiq job's jid is 24 characters. The size of the + # jid is an internal detail of Sidekiq, and they do not guarantee that it'll + # stay the same. We chose 50 to give us room in case the size of the jid + # increases. The jid is alphanumeric, so 50 is very generous. There is a spec + # that ensures that the constant value is more than the size of an actual jid. + PARAM_JOB_ID_MAX_SIZE = 50 + VALID_SETTING_PANELS.each do |action| define_method(action) { perform_update if submitted? } end @@ -62,8 +73,64 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController redirect_to ::Gitlab::LetsEncrypt.terms_of_service_url end + def create_self_monitoring_project + return self_monitoring_project_not_implemented unless Feature.enabled?(:self_monitoring_project) + + job_id = SelfMonitoringProjectCreateWorker.perform_async + + render status: :accepted, json: { + job_id: job_id, + monitor_status: status_create_self_monitoring_project_admin_application_settings_path + } + end + + def status_create_self_monitoring_project + return self_monitoring_project_not_implemented unless Feature.enabled?(:self_monitoring_project) + + job_id = params[:job_id].to_s + + unless job_id.length <= PARAM_JOB_ID_MAX_SIZE + return render status: :bad_request, json: { + message: _('Parameter "job_id" cannot exceed length of %{job_id_max_size}' % + { job_id_max_size: PARAM_JOB_ID_MAX_SIZE }) + } + end + + if Gitlab::CurrentSettings.instance_administration_project_id.present? + render status: :ok, json: self_monitoring_data + + elsif SelfMonitoringProjectCreateWorker.in_progress?(job_id) + ::Gitlab::PollingInterval.set_header(response, interval: 3_000) + + render status: :accepted, json: { message: _('Job is in progress') } + + else + render status: :bad_request, json: { + message: _('Self-monitoring project does not exist. Please check logs ' \ + 'for any error messages') + } + end + end + private + def self_monitoring_data + { + project_id: Gitlab::CurrentSettings.instance_administration_project_id, + project_full_path: Gitlab::CurrentSettings.instance_administration_project&.full_path + } + end + + def self_monitoring_project_not_implemented + render( + status: :not_implemented, + json: { + message: _('Self-monitoring is not enabled on this GitLab server, contact your administrator.'), + documentation_url: help_page_path('administration/monitoring/gitlab_instance_administration_project/index') + } + ) + end + def set_application_setting @application_setting = ApplicationSetting.current_without_cache end diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb index f212ae52ecc..c9c7ba1253f 100644 --- a/app/controllers/projects/prometheus/metrics_controller.rb +++ b/app/controllers/projects/prometheus/metrics_controller.rb @@ -23,7 +23,7 @@ module Projects private def prometheus_adapter - @prometheus_adapter ||= ::Prometheus::AdapterService.new(project, project.deployment_platform&.cluster).prometheus_adapter + @prometheus_adapter ||= ::Gitlab::Prometheus::Adapter.new(project, project.deployment_platform&.cluster).prometheus_adapter end def require_prometheus_metrics! diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 71e4195c50f..d9a91f72dca 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -334,6 +334,22 @@ module ApplicationSettingsHelper def omnibus_protected_paths_throttle? Rack::Attack.throttles.key?('protected paths') end + + def self_monitoring_project_data + { + 'create_self_monitoring_project_path' => + create_self_monitoring_project_admin_application_settings_path, + + 'status_create_self_monitoring_project_path' => + status_create_self_monitoring_project_admin_application_settings_path, + + 'self_monitoring_project_exists' => + Gitlab::CurrentSettings.instance_administration_project.present?, + + 'self_monitoring_project_full_path' => + Gitlab::CurrentSettings.instance_administration_project&.full_path + } + end end ApplicationSettingsHelper.prepend_if_ee('EE::ApplicationSettingsHelper') # rubocop: disable Cop/InjectEnterpriseEditionModule diff --git a/app/models/deployment_metrics.rb b/app/models/deployment_metrics.rb index 20f0ec3e9b6..c5f8b03f25b 100644 --- a/app/models/deployment_metrics.rb +++ b/app/models/deployment_metrics.rb @@ -34,20 +34,10 @@ class DeploymentMetrics def prometheus_adapter strong_memoize(:prometheus_adapter) do - service = project.find_or_initialize_service('prometheus') - - if service.can_query? - service - else - cluster_prometheus - end + Gitlab::Prometheus::Adapter.new(project, cluster).prometheus_adapter end end - def cluster_prometheus - cluster.application_prometheus if cluster&.application_prometheus_available? - end - def has_metrics_and_can_query? has_metrics? && prometheus_adapter.can_query? end diff --git a/app/models/environment.rb b/app/models/environment.rb index d54050cd156..2d480345b5a 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -225,11 +225,9 @@ class Environment < ApplicationRecord prometheus_adapter.query(:additional_metrics_environment, self, *args.map(&:to_f)) end - # rubocop: disable CodeReuse/ServiceClass def prometheus_adapter - @prometheus_adapter ||= Prometheus::AdapterService.new(project, deployment_platform&.cluster).prometheus_adapter + @prometheus_adapter ||= Gitlab::Prometheus::Adapter.new(project, deployment_platform&.cluster).prometheus_adapter end - # rubocop: enable CodeReuse/ServiceClass def slug super.presence || generate_slug diff --git a/app/services/prometheus/adapter_service.rb b/app/services/prometheus/adapter_service.rb deleted file mode 100644 index 5e8357a83f6..00000000000 --- a/app/services/prometheus/adapter_service.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -module Prometheus - class AdapterService - attr_reader :project, :cluster - - def initialize(project, cluster) - @project = project - @cluster = cluster - end - - def prometheus_adapter - @prometheus_adapter ||= if service_prometheus_adapter.can_query? - service_prometheus_adapter - else - cluster_prometheus_adapter - end - end - - def service_prometheus_adapter - project.find_or_initialize_service('prometheus') - end - - def cluster_prometheus_adapter - application = cluster&.application_prometheus - - application if application&.available? - end - end -end diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 34660358234..c58b74ecfec 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -116,6 +116,9 @@ namespace :admin do put :clear_repository_check_states match :general, :integrations, :repository, :ci_cd, :reporting, :metrics_and_profiling, :network, :preferences, via: [:get, :patch] get :lets_encrypt_terms_of_service + + post :create_self_monitoring_project + get :status_create_self_monitoring_project end resources :labels diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md new file mode 100644 index 00000000000..3e2f6caf328 --- /dev/null +++ b/doc/administration/instance_limits.md @@ -0,0 +1,20 @@ +--- +type: reference +--- + +# GitLab application limits + +GitLab, like most large applications, enforces limits within certain features to maintain a +minimum quality of performance. Allowing some features to be limitless could affect security, +performance, data, or could even exhaust the allocated resources for the application. + +## Number of comments per issue, merge request or commit + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/22388) in GitLab 12.4. + +There's a limit to the number of comments that can be submitted on an issue, +merge request, or commit. When the limit is reached, system notes can still be +added so that the history of events is not lost, but user-submitted comments +will fail. + +- **Max limit:** 5.000 comments diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md index 2e97849eda2..0c6caed4e55 100644 --- a/doc/administration/packages/container_registry.md +++ b/doc/administration/packages/container_registry.md @@ -398,6 +398,9 @@ To configure the `s3` storage driver in Omnibus: 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +NOTE: **Note:** +`your-s3-bucket` should only be the name of a bucket that exists, and can't include subdirectories. + **Installations from source** Configuring the storage driver is done in your registry config YML file created @@ -408,9 +411,9 @@ when you [deployed your docker registry](https://docs.docker.com/registry/deploy ```yml storage: s3: - accesskey: 'AKIAKIAKI' - secretkey: 'secret123' - bucket: 'gitlab-registry-bucket-AKIAKIAKI' + accesskey: 's3-access-key' + secretkey: 's3-secret-key-for-access-key' + bucket: 'your-s3-bucket' region: 'your-s3-region' regionendpoint: 'your-s3-regionendpoint' cache: @@ -419,6 +422,9 @@ storage: enabled: true ``` +NOTE: **Note:** +`your-s3-bucket` should only be the name of a bucket that exists, and can't include subdirectories. + ## Change the registry's internal port NOTE: **Note:** diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md index 79deda73d34..f6b7da384bc 100644 --- a/doc/user/admin_area/settings/continuous_integration.md +++ b/doc/user/admin_area/settings/continuous_integration.md @@ -78,6 +78,12 @@ This setting is set per job and can be overridden in [`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifactsexpire_in). To disable the expiration, set it to `0`. The default unit is in seconds. +NOTE: **Note** +Any changes to this setting will apply to new artifacts only. The expiration time will not +be updated for artifacts created before this setting was changed. +The administrator may need to manually search for and expire previously-created +artifacts, as described in the [troubleshooting documentation](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#remove-artifacts-more-than-a-week-old). + ## Shared Runners pipeline minutes quota **(STARTER ONLY)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/1078) diff --git a/lib/gitlab/prometheus/adapter.rb b/lib/gitlab/prometheus/adapter.rb new file mode 100644 index 00000000000..ed10ef2917f --- /dev/null +++ b/lib/gitlab/prometheus/adapter.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Gitlab + module Prometheus + class Adapter + attr_reader :project, :cluster + + def initialize(project, cluster) + @project = project + @cluster = cluster + end + + def prometheus_adapter + @prometheus_adapter ||= if service_prometheus_adapter.can_query? + service_prometheus_adapter + else + cluster_prometheus_adapter + end + end + + def cluster_prometheus_adapter + application = cluster&.application_prometheus + + application if application&.available? + end + + private + + def service_prometheus_adapter + project.find_or_initialize_service('prometheus') + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 02aa7a7933e..9830a6ce80d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -10197,6 +10197,9 @@ msgstr "" msgid "Job has wrong arguments format." msgstr "" +msgid "Job is in progress" +msgstr "" + msgid "Job is missing the `model_type` argument." msgstr "" @@ -12714,6 +12717,9 @@ msgstr "" msgid "Parameter" msgstr "" +msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}" +msgstr "" + msgid "Parent epic doesn't exist." msgstr "" @@ -16217,6 +16223,12 @@ msgstr "" msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user." msgstr "" +msgid "Self-monitoring is not enabled on this GitLab server, contact your administrator." +msgstr "" + +msgid "Self-monitoring project does not exist. Please check logs for any error messages" +msgstr "" + msgid "Send a separate email notification to Developers." msgstr "" diff --git a/spec/controllers/projects/prometheus/metrics_controller_spec.rb b/spec/controllers/projects/prometheus/metrics_controller_spec.rb index afdb8bbc983..157948de29d 100644 --- a/spec/controllers/projects/prometheus/metrics_controller_spec.rb +++ b/spec/controllers/projects/prometheus/metrics_controller_spec.rb @@ -85,7 +85,7 @@ describe Projects::Prometheus::MetricsController do end it 'calls prometheus adapter service' do - expect_next_instance_of(::Prometheus::AdapterService) do |instance| + expect_next_instance_of(::Gitlab::Prometheus::Adapter) do |instance| expect(instance).to receive(:prometheus_adapter) end diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb index dcf1b2045ab..d5644daebab 100644 --- a/spec/finders/projects/serverless/functions_finder_spec.rb +++ b/spec/finders/projects/serverless/functions_finder_spec.rb @@ -108,7 +108,7 @@ describe Projects::Serverless::FunctionsFinder do let(:finder) { described_class.new(project) } before do - allow(Prometheus::AdapterService).to receive(:new).and_return(double(prometheus_adapter: prometheus_adapter)) + allow(Gitlab::Prometheus::Adapter).to receive(:new).and_return(double(prometheus_adapter: prometheus_adapter)) allow(prometheus_adapter).to receive(:query).and_return(prometheus_empty_body('matrix')) end diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb index 8303c4eafbe..629ac34edc1 100644 --- a/spec/helpers/application_settings_helper_spec.rb +++ b/spec/helpers/application_settings_helper_spec.rb @@ -59,4 +59,54 @@ describe ApplicationSettingsHelper do expect(helper.integration_expanded?('plantuml_')).to be_falsey end end + + describe '.self_monitoring_project_data' do + context 'when self monitoring project does not exist' do + it 'returns create_self_monitoring_project_path' do + expect(helper.self_monitoring_project_data).to include( + 'create_self_monitoring_project_path' => + create_self_monitoring_project_admin_application_settings_path + ) + end + + it 'returns status_create_self_monitoring_project_path' do + expect(helper.self_monitoring_project_data).to include( + 'status_create_self_monitoring_project_path' => + status_create_self_monitoring_project_admin_application_settings_path + ) + end + + it 'returns self_monitoring_project_exists false' do + expect(helper.self_monitoring_project_data).to include( + 'self_monitoring_project_exists' => false + ) + end + + it 'returns nil for project full_path' do + expect(helper.self_monitoring_project_data).to include( + 'self_monitoring_project_full_path' => nil + ) + end + end + + context 'when self monitoring project exists' do + let(:project) { build(:project) } + + before do + stub_application_setting(instance_administration_project: project) + end + + it 'returns self_monitoring_project_exists true' do + expect(helper.self_monitoring_project_data).to include( + 'self_monitoring_project_exists' => true + ) + end + + it 'returns project full_path' do + expect(helper.self_monitoring_project_data).to include( + 'self_monitoring_project_full_path' => project.full_path + ) + end + end + end end diff --git a/spec/services/prometheus/adapter_service_spec.rb b/spec/lib/gitlab/prometheus/adapter_spec.rb index 3c075fc1581..202bf65f92b 100644 --- a/spec/services/prometheus/adapter_service_spec.rb +++ b/spec/lib/gitlab/prometheus/adapter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Prometheus::AdapterService do +describe Gitlab::Prometheus::Adapter do let_it_be(:project) { create(:project) } let_it_be(:cluster, reload: true) { create(:cluster, :provided_by_user, environment_scope: '*', projects: [project]) } diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 462e9a56f5c..af7ab24d7d6 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -1112,7 +1112,7 @@ describe Environment, :use_clean_rails_memory_store_caching do describe '#prometheus_adapter' do it 'calls prometheus adapter service' do - expect_next_instance_of(Prometheus::AdapterService) do |instance| + expect_next_instance_of(Gitlab::Prometheus::Adapter) do |instance| expect(instance).to receive(:prometheus_adapter) end diff --git a/spec/requests/self_monitoring_project_spec.rb b/spec/requests/self_monitoring_project_spec.rb new file mode 100644 index 00000000000..be701d74675 --- /dev/null +++ b/spec/requests/self_monitoring_project_spec.rb @@ -0,0 +1,175 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Self-Monitoring project requests' do + let(:admin) { create(:admin) } + + describe 'POST #create_self_monitoring_project' do + let(:worker_class) { SelfMonitoringProjectCreateWorker } + + subject { post create_self_monitoring_project_admin_application_settings_path } + + it_behaves_like 'not accessible to non-admin users' + + context 'with admin user' do + before do + login_as(admin) + end + + context 'with feature flag disabled' do + it_behaves_like 'not accessible if feature flag is disabled' + end + + context 'with feature flag enabled' do + it 'returns sidekiq job_id of expected length' do + subject + + job_id = json_response['job_id'] + + aggregate_failures do + expect(job_id).to be_present + expect(job_id.length).to be <= Admin::ApplicationSettingsController::PARAM_JOB_ID_MAX_SIZE + end + end + + it 'triggers async worker' do + expect(worker_class).to receive(:perform_async) + + subject + end + + it 'returns accepted response' do + subject + + aggregate_failures do + expect(response).to have_gitlab_http_status(:accepted) + expect(json_response.keys).to contain_exactly('job_id', 'monitor_status') + expect(json_response).to include( + 'monitor_status' => status_create_self_monitoring_project_admin_application_settings_path + ) + end + end + + it 'returns job_id' do + fake_job_id = 'b5b28910d97563e58c2fe55f' + expect(worker_class).to receive(:perform_async).and_return(fake_job_id) + + subject + response_job_id = json_response['job_id'] + + expect(response_job_id).to eq fake_job_id + end + end + end + end + + describe 'GET #status_create_self_monitoring_project' do + let(:worker_class) { SelfMonitoringProjectCreateWorker } + let(:job_id) { 'job_id' } + + subject do + get status_create_self_monitoring_project_admin_application_settings_path, + params: { job_id: job_id } + end + + it_behaves_like 'not accessible to non-admin users' + + context 'with admin user' do + before do + login_as(admin) + end + + context 'with feature flag disabled' do + it_behaves_like 'not accessible if feature flag is disabled' + end + + context 'with feature flag enabled' do + context 'with invalid job_id' do + it 'returns bad_request if job_id too long' do + get status_create_self_monitoring_project_admin_application_settings_path, + params: { job_id: 'a' * 51 } + + aggregate_failures do + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response).to eq('message' => 'Parameter "job_id" cannot ' \ + "exceed length of #{Admin::ApplicationSettingsController::PARAM_JOB_ID_MAX_SIZE}") + end + end + end + + context 'when self-monitoring project exists' do + let(:project) { build(:project) } + + before do + stub_application_setting(instance_administration_project_id: 1) + stub_application_setting(instance_administration_project: project) + end + + it 'does not need job_id' do + get status_create_self_monitoring_project_admin_application_settings_path + + aggregate_failures do + expect(response).to have_gitlab_http_status(:success) + expect(json_response).to eq( + 'project_id' => 1, + 'project_full_path' => project.full_path + ) + end + end + + it 'returns success' do + subject + + aggregate_failures do + expect(response).to have_gitlab_http_status(:success) + expect(json_response).to eq( + 'project_id' => 1, + 'project_full_path' => project.full_path + ) + end + end + end + + context 'when job is in progress' do + before do + allow(worker_class).to receive(:in_progress?) + .with(job_id) + .and_return(true) + end + + it 'sets polling header' do + expect(::Gitlab::PollingInterval).to receive(:set_header) + + subject + end + + it 'returns accepted' do + subject + + aggregate_failures do + expect(response).to have_gitlab_http_status(:accepted) + expect(json_response).to eq('message' => 'Job is in progress') + end + end + end + + context 'when self-monitoring project and job do not exist' do + let(:job_id) { nil } + + it 'returns bad_request' do + subject + + aggregate_failures do + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response).to eq( + 'message' => 'Self-monitoring project does not exist. Please check ' \ + 'logs for any error messages' + ) + end + end + end + end + end + end +end diff --git a/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb b/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb new file mode 100644 index 00000000000..6dea7fcda3c --- /dev/null +++ b/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'not accessible if feature flag is disabled' do + before do + stub_feature_flags(self_monitoring_project: false) + end + + it 'returns not_implemented' do + subject + + aggregate_failures do + expect(response).to have_gitlab_http_status(:not_implemented) + expect(json_response).to eq( + 'message' => _('Self-monitoring is not enabled on this GitLab server, contact your administrator.'), + 'documentation_url' => help_page_path('administration/monitoring/gitlab_instance_administration_project/index') + ) + end + end +end + +RSpec.shared_examples 'not accessible to non-admin users' do + context 'with unauthenticated user' do + it 'redirects to signin page' do + subject + + expect(response).to redirect_to(new_user_session_path) + end + end + + context 'with authenticated non-admin user' do + before do + login_as(create(:user)) + end + + it 'returns status not_found' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end +end |