Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-18 18:10:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-18 18:10:16 +0300
commitc8cc2fe990c52cabcb9912b2b01b5bf16b33d88f (patch)
tree101b52764100d09d0f49e9277cfd7ac5383e7aeb /app
parent38a1a6cb91bd4cd95d18db9a4bfd219bfb75401b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue58
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/constants.js17
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js17
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js (renamed from app/assets/javascripts/issuable_bulk_update_actions.js)6
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js (renamed from app/assets/javascripts/issuable_bulk_update_sidebar.js)13
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js (renamed from app/assets/javascripts/issuable_init_bulk_update_sidebar.js)0
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js (renamed from app/assets/javascripts/subscription_select.js)2
-rw-r--r--app/assets/javascripts/issuable_index.js2
-rw-r--r--app/assets/javascripts/issue_status_select.js27
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue4
-rw-r--r--app/assets/javascripts/labels_select.js2
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue1
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue13
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue2
-rw-r--r--app/controllers/chaos_controller.rb2
-rw-r--r--app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb2
-rw-r--r--app/controllers/metrics_controller.rb2
-rw-r--r--app/controllers/projects/environments/prometheus_api_controller.rb2
-rw-r--r--app/controllers/projects/import/jira_controller.rb6
-rw-r--r--app/controllers/projects/prometheus/metrics_controller.rb6
-rw-r--r--app/controllers/projects/runners_controller.rb14
-rw-r--r--app/controllers/projects/services_controller.rb4
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb2
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb2
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/update.rb2
-rw-r--r--app/graphql/resolvers/alert_management/integrations_resolver.rb2
-rw-r--r--app/graphql/resolvers/projects/jira_projects_resolver.rb6
-rw-r--r--app/graphql/types/alert_management/integration_type.rb2
-rw-r--r--app/helpers/custom_metrics_helper.rb2
-rw-r--r--app/helpers/operations_helper.rb2
-rw-r--r--app/models/clusters/integrations/prometheus.rb4
-rw-r--r--app/models/integration.rb4
-rw-r--r--app/models/integrations/base_monitoring.rb23
-rw-r--r--app/models/integrations/jira.rb4
-rw-r--r--app/models/integrations/mock_monitoring.rb25
-rw-r--r--app/models/integrations/prometheus.rb205
-rw-r--r--app/models/project.rb18
-rw-r--r--app/models/project_services/mock_monitoring_service.rb23
-rw-r--r--app/models/project_services/monitoring_service.rb21
-rw-r--r--app/models/project_services/prometheus_service.rb203
-rw-r--r--app/serializers/merge_request_diff_entity.rb1
-rw-r--r--app/services/ci/pipeline_schedules/calculate_next_run_service.rb9
-rw-r--r--app/services/jira/requests/base.rb12
-rw-r--r--app/services/jira/requests/projects/list_service.rb4
-rw-r--r--app/services/jira_import/users_importer.rb4
-rw-r--r--app/services/jira_import/users_mapper_service.rb6
-rw-r--r--app/services/metrics_service.rb2
-rw-r--r--app/services/projects/create_service.rb2
-rw-r--r--app/services/projects/operations/update_service.rb2
-rw-r--r--app/views/admin/dashboard/index.html.haml5
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml4
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--app/views/projects/import/jira/show.html.haml2
-rw-r--r--app/views/projects/issues/index.html.haml2
-rw-r--r--app/views/projects/prometheus/metrics/edit.html.haml2
-rw-r--r--app/views/projects/prometheus/metrics/new.html.haml2
-rw-r--r--app/views/shared/issuable/_bulk_update_sidebar.html.haml12
-rw-r--r--app/workers/projects/post_creation_worker.rb2
-rw-r--r--app/workers/prometheus/create_default_alerts_worker.rb2
62 files changed, 463 insertions, 371 deletions
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue b/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue
new file mode 100644
index 00000000000..9509399e91d
--- /dev/null
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue
@@ -0,0 +1,58 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { ISSUE_STATUS_SELECT_OPTIONS } from '../constants';
+
+export default {
+ name: 'StatusSelect',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ data() {
+ return {
+ status: null,
+ };
+ },
+ computed: {
+ dropdownText() {
+ return this.status?.text ?? this.$options.i18n.defaultDropdownText;
+ },
+ selectedValue() {
+ return this.status?.value;
+ },
+ },
+ methods: {
+ onDropdownItemClick(statusOption) {
+ // clear status if the currently checked status is clicked again
+ if (this.status?.value === statusOption.value) {
+ this.status = null;
+ } else {
+ this.status = statusOption;
+ }
+ },
+ },
+ i18n: {
+ dropdownTitle: __('Change status'),
+ defaultDropdownText: __('Select status'),
+ },
+ ISSUE_STATUS_SELECT_OPTIONS,
+};
+</script>
+<template>
+ <div>
+ <input type="hidden" name="update[state_event]" :value="selectedValue" />
+ <gl-dropdown :text="dropdownText" :title="$options.i18n.dropdownTitle" class="gl-w-full">
+ <gl-dropdown-item
+ v-for="statusOption in $options.ISSUE_STATUS_SELECT_OPTIONS"
+ :key="statusOption.value"
+ :is-checked="selectedValue === statusOption.value"
+ is-check-item
+ :title="statusOption.text"
+ @click="onDropdownItemClick(statusOption)"
+ >
+ {{ statusOption.text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js b/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js
new file mode 100644
index 00000000000..ad15b25f9cf
--- /dev/null
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js
@@ -0,0 +1,17 @@
+import { __ } from '~/locale';
+
+export const ISSUE_STATUS_MODIFIERS = {
+ REOPEN: 'reopen',
+ CLOSE: 'close',
+};
+
+export const ISSUE_STATUS_SELECT_OPTIONS = [
+ {
+ value: ISSUE_STATUS_MODIFIERS.REOPEN,
+ text: __('Open'),
+ },
+ {
+ value: ISSUE_STATUS_MODIFIERS.CLOSE,
+ text: __('Closed'),
+ },
+];
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js b/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js
new file mode 100644
index 00000000000..43179a86d70
--- /dev/null
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js
@@ -0,0 +1,17 @@
+import Vue from 'vue';
+import StatusSelect from './components/status_select.vue';
+
+export default function initIssueStatusSelect() {
+ const el = document.querySelector('.js-issue-status');
+
+ if (!el) {
+ return null;
+ }
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(StatusSelect);
+ },
+ });
+}
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js
index 911533457ac..463e0e5837e 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import { difference, intersection, union } from 'lodash';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
export default {
init({ form, issues, prefixId } = {}) {
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js
index 97d50dde9f7..a9d4548f8cf 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js
@@ -2,11 +2,12 @@
import $ from 'jquery';
import { property } from 'lodash';
+
+import issueableEventHub from '~/issues_list/eventhub';
+import LabelsSelect from '~/labels_select';
+import MilestoneSelect from '~/milestone_select';
+import initIssueStatusSelect from './init_issue_status_select';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
-import issueStatusSelect from './issue_status_select';
-import issueableEventHub from './issues_list/eventhub';
-import LabelsSelect from './labels_select';
-import MilestoneSelect from './milestone_select';
import subscriptionSelect from './subscription_select';
const HIDDEN_CLASS = 'hidden';
@@ -29,7 +30,7 @@ export default class IssuableBulkUpdateSidebar {
this.$sidebar = $('.right-sidebar');
this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
- this.$bulkEditSubmitBtn = $('.update-selected-issues');
+ this.$bulkEditSubmitBtn = $('.js-update-selected-issues');
this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
this.$otherFilters = $('.issues-other-filters');
this.$checkAllContainer = $('.check-all-holder');
@@ -56,7 +57,7 @@ export default class IssuableBulkUpdateSidebar {
initDropdowns() {
new LabelsSelect();
new MilestoneSelect();
- issueStatusSelect();
+ initIssueStatusSelect();
subscriptionSelect();
if (IS_EE) {
diff --git a/app/assets/javascripts/issuable_init_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js
index 179c2b83c6c..179c2b83c6c 100644
--- a/app/assets/javascripts/issuable_init_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js
diff --git a/app/assets/javascripts/subscription_select.js b/app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js
index 4a688d819b0..b12ac776b4f 100644
--- a/app/assets/javascripts/subscription_select.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { __ } from './locale';
+import { __ } from '~/locale';
export default function subscriptionSelect() {
$('.js-subscription-event').each((i, element) => {
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index cdeee68b762..5a57da292a0 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -1,4 +1,4 @@
-import issuableInitBulkUpdateSidebar from './issuable_init_bulk_update_sidebar';
+import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
export default class IssuableIndex {
constructor(pagePrefix = 'issuable_') {
diff --git a/app/assets/javascripts/issue_status_select.js b/app/assets/javascripts/issue_status_select.js
deleted file mode 100644
index 2ede0837930..00000000000
--- a/app/assets/javascripts/issue_status_select.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import $ from 'jquery';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { __ } from './locale';
-
-export default function issueStatusSelect() {
- $('.js-issue-status').each((i, el) => {
- const fieldName = $(el).data('fieldName');
- initDeprecatedJQueryDropdown($(el), {
- selectable: true,
- fieldName,
- toggleLabel(selected, element, instance) {
- let label = __('Author');
- const $item = instance.dropdown.find('.is-active');
- if ($item.length) {
- label = $item.text();
- }
- return label;
- },
- clicked(options) {
- return options.e.preventDefault();
- },
- id(obj, element) {
- return $(element).data('id');
- },
- });
- });
-}
diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue
index dbf7717b248..921af766796 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -450,7 +450,9 @@ export default {
},
async handleBulkUpdateClick() {
if (!this.hasInitBulkEdit) {
- const initBulkUpdateSidebar = await import('~/issuable_init_bulk_update_sidebar');
+ const initBulkUpdateSidebar = await import(
+ '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar'
+ );
initBulkUpdateSidebar.default.init('issuable_');
const usersSelect = await import('~/users_select');
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 3df806161f7..a62ab301227 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -5,11 +5,11 @@
import $ from 'jquery';
import { difference, isEqual, escape, sortBy, template, union } from 'lodash';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import IssuableBulkUpdateActions from '~/issuable_bulk_update_sidebar/issuable_bulk_update_actions';
import { isScopedLabel } from '~/lib/utils/common_utils';
import boardsStore from './boards/stores/boards_store';
import CreateLabelDropdown from './create_label';
import createFlash from './flash';
-import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
import axios from './lib/utils/axios_utils';
import { sprintf, __ } from './locale';
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index 76db578f6f9..342c054471d 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -1,5 +1,5 @@
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
+import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
import { mountIssuablesListApp } from '~/issues_list';
import initManualOrdering from '~/manual_ordering';
import { FILTERED_SEARCH } from '~/pages/constants';
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index 2f6f9bb16e1..02a0a50f984 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -1,6 +1,6 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
+import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
index 8fdc5ca78db..f3dd26b02cb 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
@@ -76,6 +76,7 @@ export default {
<template>
<security-report-download-dropdown
+ :title="s__('SecurityReports|Download results')"
:artifacts="reportArtifacts"
:loading="isLoadingReportArtifacts"
/>
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue
index 5d39d740c07..4178c5d1170 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue
@@ -21,6 +21,16 @@ export default {
required: false,
default: false,
},
+ text: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
methods: {
artifactText({ name }) {
@@ -35,7 +45,8 @@ export default {
<template>
<gl-dropdown
v-gl-tooltip
- :text="s__('SecurityReports|Download results')"
+ :text="text"
+ :title="title"
:loading="loading"
icon="download"
size="small"
diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
index d7a3d4e611e..3e0310e173e 100644
--- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
@@ -200,6 +200,7 @@ export default {
<template #action-buttons>
<security-report-download-dropdown
+ :text="s__('SecurityReports|Download results')"
:artifacts="reportArtifacts"
:loading="isLoadingReportArtifacts"
/>
@@ -228,6 +229,7 @@ export default {
<template #action-buttons>
<security-report-download-dropdown
+ :text="s__('SecurityReports|Download results')"
:artifacts="reportArtifacts"
:loading="isLoadingReportArtifacts"
/>
diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb
index 1cfcd2905f2..4e5af1945a4 100644
--- a/app/controllers/chaos_controller.rb
+++ b/app/controllers/chaos_controller.rb
@@ -31,7 +31,7 @@ class ChaosController < ActionController::Base
gc_stat = Gitlab::Chaos.run_gc
render json: {
- worker_id: Prometheus::PidProvider.worker_id,
+ worker_id: ::Prometheus::PidProvider.worker_id,
gc_stat: gc_stat
}
end
diff --git a/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb b/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb
index e0e3f628cc5..65237b552ca 100644
--- a/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb
+++ b/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb
@@ -16,7 +16,7 @@ module Metrics::Dashboard::PrometheusApiProxy
return error_response(variable_substitution_result)
end
- prometheus_result = Prometheus::ProxyService.new(
+ prometheus_result = ::Prometheus::ProxyService.new(
proxyable,
proxy_method,
proxy_path,
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index 1ef1e12bb02..a0c307a0a03 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -30,7 +30,7 @@ class MetricsController < ActionController::Base
def system_metrics
Gitlab::Metrics::System.summary.merge(
- worker_id: Prometheus::PidProvider.worker_id
+ worker_id: ::Prometheus::PidProvider.worker_id
)
end
end
diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb
index 97810d7d439..94fe67b5e85 100644
--- a/app/controllers/projects/environments/prometheus_api_controller.rb
+++ b/app/controllers/projects/environments/prometheus_api_controller.rb
@@ -14,6 +14,6 @@ class Projects::Environments::PrometheusApiController < Projects::ApplicationCon
end
def proxy_variable_substitution_service
- Prometheus::ProxyVariableSubstitutionService
+ ::Prometheus::ProxyVariableSubstitutionService
end
end
diff --git a/app/controllers/projects/import/jira_controller.rb b/app/controllers/projects/import/jira_controller.rb
index 8418a607659..46c4761b0ea 100644
--- a/app/controllers/projects/import/jira_controller.rb
+++ b/app/controllers/projects/import/jira_controller.rb
@@ -25,9 +25,9 @@ module Projects
false
end
- def jira_service
- strong_memoize(:jira_service) do
- @project.jira_service
+ def jira_integration
+ strong_memoize(:jira_integration) do
+ @project.jira_integration
end
end
diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb
index d70d29a341f..f3a3d22244c 100644
--- a/app/controllers/projects/prometheus/metrics_controller.rb
+++ b/app/controllers/projects/prometheus/metrics_controller.rb
@@ -66,7 +66,7 @@ module Projects
)
if @metric.persisted?
- redirect_to edit_project_service_path(project, ::PrometheusService),
+ redirect_to edit_project_service_path(project, ::Integrations::Prometheus),
notice: _('Metric was successfully added.')
else
render 'new'
@@ -77,7 +77,7 @@ module Projects
@metric = update_metrics_service(prometheus_metric).execute
if @metric.persisted?
- redirect_to edit_project_service_path(project, ::PrometheusService),
+ redirect_to edit_project_service_path(project, ::Integrations::Prometheus),
notice: _('Metric was successfully updated.')
else
render 'edit'
@@ -93,7 +93,7 @@ module Projects
respond_to do |format|
format.html do
- redirect_to edit_project_service_path(project, ::PrometheusService), status: :see_other
+ redirect_to edit_project_service_path(project, ::Integrations::Prometheus), status: :see_other
end
format.json do
head :ok
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index ec1f57f090a..5e96cd4f888 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -51,14 +51,14 @@ class Projects::RunnersController < Projects::ApplicationController
end
def toggle_shared_runners
- if !project.shared_runners_enabled && project.group && project.group.shared_runners_setting == 'disabled_and_unoverridable'
- render json: { error: _('Cannot enable shared runners because parent group does not allow it') }, status: :unauthorized
- return
- end
-
- project.toggle!(:shared_runners_enabled)
+ update_params = { shared_runners_enabled: !project.shared_runners_enabled }
+ result = Projects::UpdateService.new(project, current_user, update_params).execute
- render json: {}, status: :ok
+ if result[:status] == :success
+ render json: {}, status: :ok
+ else
+ render json: { error: result[:message] }, status: :unauthorized
+ end
end
def toggle_group_runners
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index cad13d7e708..7288cbd2a40 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -105,11 +105,11 @@ class Projects::ServicesController < Projects::ApplicationController
end
def redirect_deprecated_prometheus_service
- redirect_to edit_project_service_path(project, integration) if integration.is_a?(::PrometheusService) && Feature.enabled?(:settings_operations_prometheus_service, project)
+ redirect_to edit_project_service_path(project, integration) if integration.is_a?(::Integrations::Prometheus) && Feature.enabled?(:settings_operations_prometheus_service, project)
end
def set_deprecation_notice_for_prometheus_service
- return if !integration.is_a?(::PrometheusService) || !Feature.enabled?(:settings_operations_prometheus_service, project)
+ return if !integration.is_a?(::Integrations::Prometheus) || !Feature.enabled?(:settings_operations_prometheus_service, project)
operations_link_start = "<a href=\"#{project_settings_operations_path(project)}\">"
message = s_('PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page has been deprecated.') % { operations_link_start: operations_link_start, operations_link_end: "</a>" }
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
index cb243f49b33..d8678ea4d61 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
@@ -14,7 +14,7 @@ module Mutations
private
def find_object(id:)
- GitlabSchema.object_from_id(id, expected_class: ::PrometheusService)
+ GitlabSchema.object_from_id(id, expected_class: ::Integrations::Prometheus)
end
def response(integration, result)
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
index 428be091436..33a12405583 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
@@ -6,7 +6,7 @@ module Mutations
class ResetToken < PrometheusIntegrationBase
graphql_name 'PrometheusIntegrationResetToken'
- argument :id, Types::GlobalIDType[::PrometheusService],
+ argument :id, Types::GlobalIDType[::Integrations::Prometheus],
required: true,
description: "The ID of the integration to mutate."
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/update.rb b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
index 7594766176f..ddab1af908c 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/update.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
@@ -6,7 +6,7 @@ module Mutations
class Update < PrometheusIntegrationBase
graphql_name 'PrometheusIntegrationUpdate'
- argument :id, Types::GlobalIDType[::PrometheusService],
+ argument :id, Types::GlobalIDType[::Integrations::Prometheus],
required: true,
description: "The ID of the integration to mutate."
diff --git a/app/graphql/resolvers/alert_management/integrations_resolver.rb b/app/graphql/resolvers/alert_management/integrations_resolver.rb
index cb7e73c2d1a..38d0f9880ca 100644
--- a/app/graphql/resolvers/alert_management/integrations_resolver.rb
+++ b/app/graphql/resolvers/alert_management/integrations_resolver.rb
@@ -54,7 +54,7 @@ module Resolvers
def expected_integration_types
[].tap do |types|
types << ::AlertManagement::HttpIntegration if http_integrations_allowed?
- types << ::PrometheusService if prometheus_integrations_allowed?
+ types << ::Integrations::Prometheus if prometheus_integrations_allowed?
end
end
end
diff --git a/app/graphql/resolvers/projects/jira_projects_resolver.rb b/app/graphql/resolvers/projects/jira_projects_resolver.rb
index de85e8c42e6..864acb6d759 100644
--- a/app/graphql/resolvers/projects/jira_projects_resolver.rb
+++ b/app/graphql/resolvers/projects/jira_projects_resolver.rb
@@ -34,16 +34,16 @@ module Resolvers
private
- alias_method :jira_service, :object
+ alias_method :jira_integration, :object
def project
- jira_service&.project
+ jira_integration&.project
end
def jira_projects(name:)
args = { query: name }.compact
- Jira::Requests::Projects::ListService.new(project.jira_service, args).execute
+ Jira::Requests::Projects::ListService.new(project.jira_integration, args).execute
end
end
end
diff --git a/app/graphql/types/alert_management/integration_type.rb b/app/graphql/types/alert_management/integration_type.rb
index d26d7348765..6cbc17cdbfb 100644
--- a/app/graphql/types/alert_management/integration_type.rb
+++ b/app/graphql/types/alert_management/integration_type.rb
@@ -43,7 +43,7 @@ module Types
definition_methods do
def resolve_type(object, context)
- if object.is_a?(::PrometheusService)
+ if object.is_a?(::Integrations::Prometheus)
Types::AlertManagement::PrometheusIntegrationType
else
Types::AlertManagement::HttpIntegrationType
diff --git a/app/helpers/custom_metrics_helper.rb b/app/helpers/custom_metrics_helper.rb
index 5ea386e268d..9fbfe377c61 100644
--- a/app/helpers/custom_metrics_helper.rb
+++ b/app/helpers/custom_metrics_helper.rb
@@ -5,7 +5,7 @@ module CustomMetricsHelper
{
'custom-metrics-path' => url_for([project, metric]),
'metric-persisted' => metric.persisted?.to_s,
- 'edit-project-service-path' => edit_project_service_path(project, PrometheusService),
+ 'edit-project-service-path' => edit_project_service_path(project, ::Integrations::Prometheus),
'validate-query-path' => validate_query_project_prometheus_metrics_path(project),
'title' => metric.title.to_s,
'query' => metric.query.to_s,
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index fb410c46128..553bd0d2ebf 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -5,7 +5,7 @@ module OperationsHelper
def prometheus_service
strong_memoize(:prometheus_service) do
- @project.find_or_initialize_service(::PrometheusService.to_param)
+ @project.find_or_initialize_service(::Integrations::Prometheus.to_param)
end
end
diff --git a/app/models/clusters/integrations/prometheus.rb b/app/models/clusters/integrations/prometheus.rb
index 0a01ac5d1ce..be7ec72f785 100644
--- a/app/models/clusters/integrations/prometheus.rb
+++ b/app/models/clusters/integrations/prometheus.rb
@@ -47,12 +47,12 @@ module Clusters
def activate_project_services
::Clusters::Applications::ActivateServiceWorker
- .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
+ .perform_async(cluster_id, ::Integrations::Prometheus.to_param)
end
def deactivate_project_services
::Clusters::Applications::DeactivateServiceWorker
- .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
+ .perform_async(cluster_id, ::Integrations::Prometheus.to_param)
end
end
end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 333f3020736..363131dc03a 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -48,8 +48,12 @@ class Integration < ApplicationRecord
flowdock
hangouts_chat
irker
+ jenkins jira
packagist pipelines_email pivotaltracker pushover
mattermost mattermost_slash_commands microsoft_teams mock_ci mock_monitoring
+ redmine
+ slack slack_slash_commands
+ teamcity
].to_set.freeze
def self.renamed?(name)
diff --git a/app/models/integrations/base_monitoring.rb b/app/models/integrations/base_monitoring.rb
new file mode 100644
index 00000000000..280eeda7c6c
--- /dev/null
+++ b/app/models/integrations/base_monitoring.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# Base class for monitoring services
+#
+# These services integrate with a deployment solution like Prometheus
+# to provide additional features for environments.
+module Integrations
+ class BaseMonitoring < Integration
+ default_value_for :category, 'monitoring'
+
+ def self.supported_events
+ %w()
+ end
+
+ def can_query?
+ raise NotImplementedError
+ end
+
+ def query(_, *_)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index aa143cc28e1..40734a29724 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -272,6 +272,10 @@ module Integrations
test(nil)[:success]
end
+ def configured?
+ active? && valid_connection?
+ end
+
def test(_)
result = server_info
success = result.present?
diff --git a/app/models/integrations/mock_monitoring.rb b/app/models/integrations/mock_monitoring.rb
new file mode 100644
index 00000000000..235c8e6fefc
--- /dev/null
+++ b/app/models/integrations/mock_monitoring.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Integrations
+ class MockMonitoring < BaseMonitoring
+ def title
+ 'Mock monitoring'
+ end
+
+ def description
+ 'Mock monitoring service'
+ end
+
+ def self.to_param
+ 'mock_monitoring'
+ end
+
+ def metrics(environment)
+ Gitlab::Json.parse(File.read(Rails.root + 'spec/fixtures/metrics.json'))
+ end
+
+ def can_test?
+ false
+ end
+ end
+end
diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb
new file mode 100644
index 00000000000..f395579df3a
--- /dev/null
+++ b/app/models/integrations/prometheus.rb
@@ -0,0 +1,205 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Prometheus < BaseMonitoring
+ include PrometheusAdapter
+
+ # Access to prometheus is directly through the API
+ prop_accessor :api_url
+ prop_accessor :google_iap_service_account_json
+ prop_accessor :google_iap_audience_client_id
+ boolean_accessor :manual_configuration
+
+ # We need to allow the self-monitoring project to connect to the internal
+ # Prometheus instance.
+ # Since the internal Prometheus instance is usually a localhost URL, we need
+ # to allow localhost URLs when the following conditions are true:
+ # 1. project is the self-monitoring project.
+ # 2. api_url is the internal Prometheus URL.
+ with_options presence: true do
+ validates :api_url, public_url: true, if: ->(object) { object.manual_configuration? && !object.allow_local_api_url? }
+ validates :api_url, url: true, if: ->(object) { object.manual_configuration? && object.allow_local_api_url? }
+ end
+
+ before_save :synchronize_service_state
+
+ after_save :clear_reactive_cache!
+
+ after_commit :track_events
+
+ after_create_commit :create_default_alerts
+
+ scope :preload_project, -> { preload(:project) }
+ scope :with_clusters_with_cilium, -> { joins(project: [:clusters]).merge(Clusters::Cluster.with_available_cilium) }
+
+ def initialize_properties
+ if properties.nil?
+ self.properties = {}
+ end
+ end
+
+ def show_active_box?
+ false
+ end
+
+ def title
+ 'Prometheus'
+ end
+
+ def description
+ s_('PrometheusService|Monitor application health with Prometheus metrics and dashboards')
+ end
+
+ def self.to_param
+ 'prometheus'
+ end
+
+ def fields
+ [
+ {
+ type: 'checkbox',
+ name: 'manual_configuration',
+ title: s_('PrometheusService|Active'),
+ help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'api_url',
+ title: 'API URL',
+ placeholder: s_('PrometheusService|https://prometheus.example.com/'),
+ help: s_('PrometheusService|The Prometheus API base URL.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'google_iap_audience_client_id',
+ title: 'Google IAP Audience Client ID',
+ placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'),
+ help: s_('PrometheusService|PrometheusService|The ID of the IAP-secured resource.'),
+ autocomplete: 'off',
+ required: false
+ },
+ {
+ type: 'textarea',
+ name: 'google_iap_service_account_json',
+ title: 'Google IAP Service Account JSON',
+ placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'),
+ help: s_('PrometheusService|The contents of the credentials.json file of your service account.'),
+ required: false
+ }
+ ]
+ end
+
+ # Check we can connect to the Prometheus API
+ def test(*args)
+ prometheus_client.ping
+ { success: true, result: 'Checked API endpoint' }
+ rescue Gitlab::PrometheusClient::Error => err
+ { success: false, result: err }
+ end
+
+ def prometheus_client
+ return unless should_return_client?
+
+ options = prometheus_client_default_options.merge(
+ allow_local_requests: allow_local_api_url?
+ )
+
+ if behind_iap?
+ # Adds the Authorization header
+ options[:headers] = iap_client.apply({})
+ end
+
+ Gitlab::PrometheusClient.new(api_url, options)
+ end
+
+ def prometheus_available?
+ return false if template?
+ return false unless project
+
+ project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster|
+ cluster.integration_prometheus_available?
+ end
+ end
+
+ def allow_local_api_url?
+ allow_local_requests_from_web_hooks_and_services? ||
+ (self_monitoring_project? && internal_prometheus_url?)
+ end
+
+ def configured?
+ should_return_client?
+ end
+
+ private
+
+ def self_monitoring_project?
+ project && project.id == current_settings.self_monitoring_project_id
+ end
+
+ def internal_prometheus_url?
+ api_url.present? && api_url == ::Gitlab::Prometheus::Internal.uri
+ end
+
+ def allow_local_requests_from_web_hooks_and_services?
+ current_settings.allow_local_requests_from_web_hooks_and_services?
+ end
+
+ def should_return_client?
+ api_url.present? && manual_configuration? && active? && valid?
+ end
+
+ def current_settings
+ Gitlab::CurrentSettings.current_application_settings
+ end
+
+ def synchronize_service_state
+ self.active = prometheus_available? || manual_configuration?
+
+ true
+ end
+
+ def track_events
+ if enabled_manual_prometheus?
+ Gitlab::Tracking.event('cluster:services:prometheus', 'enabled_manual_prometheus')
+ elsif disabled_manual_prometheus?
+ Gitlab::Tracking.event('cluster:services:prometheus', 'disabled_manual_prometheus')
+ end
+
+ true
+ end
+
+ def enabled_manual_prometheus?
+ manual_configuration_changed? && manual_configuration?
+ end
+
+ def disabled_manual_prometheus?
+ manual_configuration_changed? && !manual_configuration?
+ end
+
+ def create_default_alerts
+ return unless project_id
+
+ ::Prometheus::CreateDefaultAlertsWorker.perform_async(project_id)
+ end
+
+ def behind_iap?
+ manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present?
+ end
+
+ def clean_google_iap_service_account
+ return unless google_iap_service_account_json
+
+ google_iap_service_account_json
+ .then { |json| Gitlab::Json.parse(json) }
+ .except('token_credential_uri')
+ end
+
+ def iap_client
+ @iap_client ||= Google::Auth::Credentials
+ .new(clean_google_iap_service_account, target_audience: google_iap_audience_client_id)
+ .client
+ end
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 5d71318dbef..ea88eda0959 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -172,25 +172,25 @@ class Project < ApplicationRecord
has_one :flowdock_integration, class_name: 'Integrations::Flowdock'
has_one :hangouts_chat_integration, class_name: 'Integrations::HangoutsChat'
has_one :irker_integration, class_name: 'Integrations::Irker'
- has_one :jenkins_service, class_name: 'Integrations::Jenkins'
- has_one :jira_service, class_name: 'Integrations::Jira'
+ has_one :jenkins_integration, class_name: 'Integrations::Jenkins'
+ has_one :jira_integration, class_name: 'Integrations::Jira'
has_one :mattermost_integration, class_name: 'Integrations::Mattermost'
has_one :mattermost_slash_commands_integration, class_name: 'Integrations::MattermostSlashCommands'
has_one :microsoft_teams_integration, class_name: 'Integrations::MicrosoftTeams'
has_one :mock_ci_integration, class_name: 'Integrations::MockCi'
- has_one :mock_monitoring_integration, class_name: 'MockMonitoringService'
+ has_one :mock_monitoring_integration, class_name: 'Integrations::MockMonitoring'
has_one :packagist_integration, class_name: 'Integrations::Packagist'
has_one :pipelines_email_integration, class_name: 'Integrations::PipelinesEmail'
has_one :pivotaltracker_integration, class_name: 'Integrations::Pivotaltracker'
+ has_one :prometheus_service, class_name: 'Integrations::Prometheus', inverse_of: :project
has_one :pushover_integration, class_name: 'Integrations::Pushover'
- has_one :redmine_service, class_name: 'Integrations::Redmine'
- has_one :slack_service, class_name: 'Integrations::Slack'
- has_one :slack_slash_commands_service, class_name: 'Integrations::SlackSlashCommands'
- has_one :teamcity_service, class_name: 'Integrations::Teamcity'
+ has_one :redmine_integration, class_name: 'Integrations::Redmine'
+ has_one :slack_integration, class_name: 'Integrations::Slack'
+ has_one :slack_slash_commands_integration, class_name: 'Integrations::SlackSlashCommands'
+ has_one :teamcity_integration, class_name: 'Integrations::Teamcity'
has_one :unify_circuit_service, class_name: 'Integrations::UnifyCircuit'
has_one :webex_teams_service, class_name: 'Integrations::WebexTeams'
has_one :youtrack_service, class_name: 'Integrations::Youtrack'
- has_one :prometheus_service, inverse_of: :project
has_one :root_of_fork_network,
foreign_key: 'root_project_id',
@@ -542,7 +542,7 @@ class Project < ApplicationRecord
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
scope :with_push, -> { joins(:events).merge(Event.pushed_action) }
scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') }
- scope :with_active_jira_services, -> { joins(:integrations).merge(::Integrations::Jira.active) }
+ scope :with_active_jira_integrations, -> { joins(:integrations).merge(::Integrations::Jira.active) }
scope :with_jira_dvcs_cloud, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: true)) }
scope :with_jira_dvcs_server, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false)) }
scope :inc_routes, -> { includes(:route, namespace: :route) }
diff --git a/app/models/project_services/mock_monitoring_service.rb b/app/models/project_services/mock_monitoring_service.rb
deleted file mode 100644
index 25ae0f6b60d..00000000000
--- a/app/models/project_services/mock_monitoring_service.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class MockMonitoringService < MonitoringService
- def title
- 'Mock monitoring'
- end
-
- def description
- 'Mock monitoring service'
- end
-
- def self.to_param
- 'mock_monitoring'
- end
-
- def metrics(environment)
- Gitlab::Json.parse(File.read(Rails.root + 'spec/fixtures/metrics.json'))
- end
-
- def can_test?
- false
- end
-end
diff --git a/app/models/project_services/monitoring_service.rb b/app/models/project_services/monitoring_service.rb
deleted file mode 100644
index ea65a200027..00000000000
--- a/app/models/project_services/monitoring_service.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-# Base class for monitoring services
-#
-# These services integrate with a deployment solution like Prometheus
-# to provide additional features for environments.
-class MonitoringService < Integration
- default_value_for :category, 'monitoring'
-
- def self.supported_events
- %w()
- end
-
- def can_query?
- raise NotImplementedError
- end
-
- def query(_, *_)
- raise NotImplementedError
- end
-end
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
deleted file mode 100644
index a289c1c2afb..00000000000
--- a/app/models/project_services/prometheus_service.rb
+++ /dev/null
@@ -1,203 +0,0 @@
-# frozen_string_literal: true
-
-class PrometheusService < MonitoringService
- include PrometheusAdapter
-
- # Access to prometheus is directly through the API
- prop_accessor :api_url
- prop_accessor :google_iap_service_account_json
- prop_accessor :google_iap_audience_client_id
- boolean_accessor :manual_configuration
-
- # We need to allow the self-monitoring project to connect to the internal
- # Prometheus instance.
- # Since the internal Prometheus instance is usually a localhost URL, we need
- # to allow localhost URLs when the following conditions are true:
- # 1. project is the self-monitoring project.
- # 2. api_url is the internal Prometheus URL.
- with_options presence: true do
- validates :api_url, public_url: true, if: ->(object) { object.manual_configuration? && !object.allow_local_api_url? }
- validates :api_url, url: true, if: ->(object) { object.manual_configuration? && object.allow_local_api_url? }
- end
-
- before_save :synchronize_service_state
-
- after_save :clear_reactive_cache!
-
- after_commit :track_events
-
- after_create_commit :create_default_alerts
-
- scope :preload_project, -> { preload(:project) }
- scope :with_clusters_with_cilium, -> { joins(project: [:clusters]).merge(Clusters::Cluster.with_available_cilium) }
-
- def initialize_properties
- if properties.nil?
- self.properties = {}
- end
- end
-
- def show_active_box?
- false
- end
-
- def title
- 'Prometheus'
- end
-
- def description
- s_('PrometheusService|Monitor application health with Prometheus metrics and dashboards')
- end
-
- def self.to_param
- 'prometheus'
- end
-
- def fields
- [
- {
- type: 'checkbox',
- name: 'manual_configuration',
- title: s_('PrometheusService|Active'),
- help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'),
- required: true
- },
- {
- type: 'text',
- name: 'api_url',
- title: 'API URL',
- placeholder: s_('PrometheusService|https://prometheus.example.com/'),
- help: s_('PrometheusService|The Prometheus API base URL.'),
- required: true
- },
- {
- type: 'text',
- name: 'google_iap_audience_client_id',
- title: 'Google IAP Audience Client ID',
- placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'),
- help: s_('PrometheusService|PrometheusService|The ID of the IAP-secured resource.'),
- autocomplete: 'off',
- required: false
- },
- {
- type: 'textarea',
- name: 'google_iap_service_account_json',
- title: 'Google IAP Service Account JSON',
- placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'),
- help: s_('PrometheusService|The contents of the credentials.json file of your service account.'),
- required: false
- }
- ]
- end
-
- # Check we can connect to the Prometheus API
- def test(*args)
- prometheus_client.ping
- { success: true, result: 'Checked API endpoint' }
- rescue Gitlab::PrometheusClient::Error => err
- { success: false, result: err }
- end
-
- def prometheus_client
- return unless should_return_client?
-
- options = prometheus_client_default_options.merge(
- allow_local_requests: allow_local_api_url?
- )
-
- if behind_iap?
- # Adds the Authorization header
- options[:headers] = iap_client.apply({})
- end
-
- Gitlab::PrometheusClient.new(api_url, options)
- end
-
- def prometheus_available?
- return false if template?
- return false unless project
-
- project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster|
- cluster.integration_prometheus_available?
- end
- end
-
- def allow_local_api_url?
- allow_local_requests_from_web_hooks_and_services? ||
- (self_monitoring_project? && internal_prometheus_url?)
- end
-
- def configured?
- should_return_client?
- end
-
- private
-
- def self_monitoring_project?
- project && project.id == current_settings.self_monitoring_project_id
- end
-
- def internal_prometheus_url?
- api_url.present? && api_url == ::Gitlab::Prometheus::Internal.uri
- end
-
- def allow_local_requests_from_web_hooks_and_services?
- current_settings.allow_local_requests_from_web_hooks_and_services?
- end
-
- def should_return_client?
- api_url.present? && manual_configuration? && active? && valid?
- end
-
- def current_settings
- Gitlab::CurrentSettings.current_application_settings
- end
-
- def synchronize_service_state
- self.active = prometheus_available? || manual_configuration?
-
- true
- end
-
- def track_events
- if enabled_manual_prometheus?
- Gitlab::Tracking.event('cluster:services:prometheus', 'enabled_manual_prometheus')
- elsif disabled_manual_prometheus?
- Gitlab::Tracking.event('cluster:services:prometheus', 'disabled_manual_prometheus')
- end
-
- true
- end
-
- def enabled_manual_prometheus?
- manual_configuration_changed? && manual_configuration?
- end
-
- def disabled_manual_prometheus?
- manual_configuration_changed? && !manual_configuration?
- end
-
- def create_default_alerts
- return unless project_id
-
- Prometheus::CreateDefaultAlertsWorker.perform_async(project_id)
- end
-
- def behind_iap?
- manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present?
- end
-
- def clean_google_iap_service_account
- return unless google_iap_service_account_json
-
- google_iap_service_account_json
- .then { |json| Gitlab::Json.parse(json) }
- .except('token_credential_uri')
- end
-
- def iap_client
- @iap_client ||= Google::Auth::Credentials
- .new(clean_google_iap_service_account, target_audience: google_iap_audience_client_id)
- .client
- end
-end
diff --git a/app/serializers/merge_request_diff_entity.rb b/app/serializers/merge_request_diff_entity.rb
index e197c3d0fbb..02b81b707b9 100644
--- a/app/serializers/merge_request_diff_entity.rb
+++ b/app/serializers/merge_request_diff_entity.rb
@@ -16,6 +16,7 @@ class MergeRequestDiffEntity < Grape::Entity
end
expose :created_at
+ expose :state
expose :commits_count
expose :latest?, as: :latest
diff --git a/app/services/ci/pipeline_schedules/calculate_next_run_service.rb b/app/services/ci/pipeline_schedules/calculate_next_run_service.rb
index 9978b2d4775..9c8f6b47288 100644
--- a/app/services/ci/pipeline_schedules/calculate_next_run_service.rb
+++ b/app/services/ci/pipeline_schedules/calculate_next_run_service.rb
@@ -12,15 +12,16 @@ module Ci
return fallback_method.call unless plan_cron&.cron_valid?
now = Time.zone.now
+ plan_min_run = plan_cron.next_time_from(now)
schedule_next_run = schedule_cron.next_time_from(now)
- return schedule_next_run if worker_cron.match?(schedule_next_run) && plan_cron.match?(schedule_next_run)
+ return schedule_next_run if worker_cron.match?(schedule_next_run) && plan_min_run <= schedule_next_run
- plan_next_run = plan_cron.next_time_from(now)
+ plan_next_run = plan_cron.next_time_from(schedule_next_run)
return plan_next_run if worker_cron.match?(plan_next_run)
- worker_next_run = worker_cron.next_time_from(now)
- return worker_next_run if plan_cron.match?(worker_next_run)
+ worker_next_run = worker_cron.next_time_from(schedule_next_run)
+ return worker_next_run if plan_min_run <= worker_next_run
worker_cron.next_time_from(plan_next_run)
end
diff --git a/app/services/jira/requests/base.rb b/app/services/jira/requests/base.rb
index bae8298d5c8..e4e2736ca2f 100644
--- a/app/services/jira/requests/base.rb
+++ b/app/services/jira/requests/base.rb
@@ -7,20 +7,20 @@ module Jira
JIRA_API_VERSION = 2
- def initialize(jira_service, params = {})
- @project = jira_service&.project
- @jira_service = jira_service
+ def initialize(jira_integration, params = {})
+ @project = jira_integration&.project
+ @jira_integration = jira_integration
end
def execute
- return ServiceResponse.error(message: _('Jira service not configured.')) unless jira_service&.active?
+ return ServiceResponse.error(message: _('Jira service not configured.')) unless jira_integration&.active?
request
end
private
- attr_reader :jira_service, :project
+ attr_reader :jira_integration, :project
# We have to add the context_path here because the Jira client is not taking it into account
def base_api_url
@@ -37,7 +37,7 @@ module Jira
end
def client
- @client ||= jira_service.client
+ @client ||= jira_integration.client
end
def request
diff --git a/app/services/jira/requests/projects/list_service.rb b/app/services/jira/requests/projects/list_service.rb
index 373c536974a..ac9e9bf0be9 100644
--- a/app/services/jira/requests/projects/list_service.rb
+++ b/app/services/jira/requests/projects/list_service.rb
@@ -6,8 +6,8 @@ module Jira
class ListService < Base
extend ::Gitlab::Utils::Override
- def initialize(jira_service, params = {})
- super(jira_service, params)
+ def initialize(jira_integration, params = {})
+ super(jira_integration, params)
@query = params[:query]
end
diff --git a/app/services/jira_import/users_importer.rb b/app/services/jira_import/users_importer.rb
index 5b2f91efc38..667a2836acc 100644
--- a/app/services/jira_import/users_importer.rb
+++ b/app/services/jira_import/users_importer.rb
@@ -32,9 +32,9 @@ module JiraImport
end
def user_mapper_service_factory
- if project.jira_service.data_fields.deployment_server?
+ if project.jira_integration.data_fields.deployment_server?
ServerUsersMapperService.new(user, project, start_at)
- elsif project.jira_service.data_fields.deployment_cloud?
+ elsif project.jira_integration.data_fields.deployment_cloud?
CloudUsersMapperService.new(user, project, start_at)
else
raise ArgumentError
diff --git a/app/services/jira_import/users_mapper_service.rb b/app/services/jira_import/users_mapper_service.rb
index 6c8610bfbf3..760f06a1cfb 100644
--- a/app/services/jira_import/users_mapper_service.rb
+++ b/app/services/jira_import/users_mapper_service.rb
@@ -13,7 +13,7 @@ module JiraImport
def initialize(current_user, project, start_at)
@current_user = current_user
@project = project
- @jira_service = project.jira_service
+ @jira_integration = project.jira_integration
@start_at = start_at
end
@@ -29,14 +29,14 @@ module JiraImport
private
- attr_reader :current_user, :project, :jira_service, :start_at
+ attr_reader :current_user, :project, :jira_integration, :start_at
def jira_users
@jira_users ||= client.get(url)
end
def client
- @client ||= jira_service.client
+ @client ||= jira_integration.client
end
def url
diff --git a/app/services/metrics_service.rb b/app/services/metrics_service.rb
index 222a5c8c79c..d27328f89cd 100644
--- a/app/services/metrics_service.rb
+++ b/app/services/metrics_service.rb
@@ -4,7 +4,7 @@ require 'prometheus/client/formats/text'
class MetricsService
def prometheus_metrics_text
- Prometheus::Client::Formats::Text.marshal_multiprocess(multiprocess_metrics_path)
+ ::Prometheus::Client::Formats::Text.marshal_multiprocess(multiprocess_metrics_path)
end
def metrics_text
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 7dd9280e5b1..e2bde27da63 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -193,7 +193,7 @@ module Projects
# Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/326665
def create_prometheus_service
- service = @project.find_or_initialize_service(::PrometheusService.to_param)
+ service = @project.find_or_initialize_service(::Integrations::Prometheus.to_param)
# If the service has already been inserted in the database, that
# means it came from a template, and there's nothing more to do.
diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb
index c0734171ee5..4fb2cede7ce 100644
--- a/app/services/projects/operations/update_service.rb
+++ b/app/services/projects/operations/update_service.rb
@@ -102,7 +102,7 @@ module Projects
def prometheus_integration_params
return {} unless attrs = params[:prometheus_integration_attributes]
- service = project.find_or_initialize_service(::PrometheusService.to_param)
+ service = project.find_or_initialize_service(::Integrations::Prometheus.to_param)
service.assign_attributes(attrs)
{ prometheus_service_attributes: service.attributes.except(*%w(id project_id created_at updated_at)) }
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 58c65bdc8c7..ec3daf6c494 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -3,15 +3,14 @@
- billable_users_url = help_page_path('subscriptions/self_managed/index', anchor: 'billable-users')
- billable_users_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer nofollow">'.html_safe % { url: billable_users_url }
+= render_if_exists 'shared/qrtly_reconciliation_alert'
+
- if @notices
- @notices.each do |notice|
.js-vue-alert{ 'v-cloak': true, data: { variant: notice[:type],
dismissible: true.to_s } }
= notice[:message].html_safe
-- if Gitlab.ee? && display_upcoming_reconciliation_alert?
- #js-qrtly-reconciliation-alert{ data: upcoming_reconciliation_hash }
-
- if @license.present?
.license-panel.gl-mt-5
= render_if_exists 'admin/licenses/summary'
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index 93e8b1241a8..bdd4b76bba0 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -12,6 +12,6 @@
'role-arn' => @aws_role.role_arn,
'instance-types' => @instance_types,
'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index'),
- 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'new-eks-cluster'),
- 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'new-eks-cluster'),
+ 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'create-a-new-certificate-based-eks-cluster'),
+ 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'create-a-new-certificate-based-eks-cluster'),
'external-link-icon' => sprite_icon('external-link') } }
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 628425bf463..76850f0a884 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -6,6 +6,8 @@
- if show_thanks_for_purchase_banner?
= render_if_exists 'shared/thanks_for_purchase_banner', plan_title: plan_title, quantity: params[:purchased_quantity].to_i
+= render_if_exists 'shared/qrtly_reconciliation_alert', group: @group
+
- if show_invite_banner?(@group)
= content_for :group_invite_members_banner do
.container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" }
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 2b63e2c647c..7eaa6190a05 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -19,6 +19,7 @@
= render_if_exists "layouts/header/ee_subscribable_banner"
= render_if_exists "shared/namespace_storage_limit_alert"
= render_if_exists "shared/new_user_signups_cap_reached_alert"
+ = yield :page_level_alert
= yield :customize_homepage_banner
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
diff --git a/app/views/projects/import/jira/show.html.haml b/app/views/projects/import/jira/show.html.haml
index 3c0664e4d5f..29296ce23c9 100644
--- a/app/views/projects/import/jira/show.html.haml
+++ b/app/views/projects/import/jira/show.html.haml
@@ -1,7 +1,7 @@
.js-jira-import-root{ data: { project_path: @project.full_path,
issues_path: project_issues_path(@project),
jira_integration_path: edit_project_service_path(@project, :jira),
- is_jira_configured: @project.jira_service&.active? && @project.jira_service&.valid_connection?.to_s,
+ is_jira_configured: @project.jira_integration&.configured?.to_s,
in_progress_illustration: image_path('illustrations/export-import.svg'),
project_id: @project.id,
setup_illustration: image_path('illustrations/manual_action.svg') } }
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 3e8442eee86..ecf10cd4821 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -9,7 +9,7 @@
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues")
.js-jira-issues-import-status{ data: { can_edit: can?(current_user, :admin_project, @project).to_s,
- is_jira_configured: @project.jira_service.present?.to_s,
+ is_jira_configured: @project.jira_integration.present?.to_s,
issues_path: project_issues_path(@project),
project_path: @project.full_path } }
diff --git a/app/views/projects/prometheus/metrics/edit.html.haml b/app/views/projects/prometheus/metrics/edit.html.haml
index 15a9c922ca6..d308824571e 100644
--- a/app/views/projects/prometheus/metrics/edit.html.haml
+++ b/app/views/projects/prometheus/metrics/edit.html.haml
@@ -1,6 +1,6 @@
- add_to_breadcrumbs _("Settings"), edit_project_path(@project)
- add_to_breadcrumbs _("Integrations"), project_settings_integrations_path(@project)
-- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, PrometheusService)
+- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, ::Integrations::Prometheus)
- breadcrumb_title s_('Metrics|Edit metric')
- page_title @metric.title, s_('Metrics|Edit metric')
= render 'form', project: @project, metric: @metric
diff --git a/app/views/projects/prometheus/metrics/new.html.haml b/app/views/projects/prometheus/metrics/new.html.haml
index fa925d090cb..8415ec9ee41 100644
--- a/app/views/projects/prometheus/metrics/new.html.haml
+++ b/app/views/projects/prometheus/metrics/new.html.haml
@@ -1,6 +1,6 @@
- add_to_breadcrumbs _("Settings"), edit_project_path(@project)
- add_to_breadcrumbs _("Integrations"), project_settings_integrations_path(@project)
-- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, PrometheusService)
+- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, ::Integrations::Prometheus)
- breadcrumb_title s_('Metrics|New metric')
- page_title s_('Metrics|New metric')
= render 'form', project: @project, metric: @metric
diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
index bbbb728d048..3a526a9f306 100644
--- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml
+++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
@@ -6,21 +6,13 @@
= form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do
.block.issuable-sidebar-header
.filter-item.inline.update-issues-btn.float-left
- = button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-confirm", disabled: true
+ = button_tag _('Update all'), class: "gl-button btn js-update-selected-issues btn-confirm", disabled: true
= button_tag _('Cancel'), class: "gl-button btn btn-default js-bulk-update-menu-hide float-right"
- if params[:state] != 'merged'
.block
.title
= _('Status')
- .filter-item
- = dropdown_tag(_("Select status"), options: { toggle_class: "js-issue-status", title: _("Change status"), dropdown_class: "dropdown-menu-status dropdown-menu-selectable", data: { field_name: "update[state_event]", default_label: _("Status") } } ) do
- %ul
- %li
- %a{ href: "#", data: { id: "reopen" } }
- = _('Open')
- %li
- %a{ href: "#", data: { id: "close" } }
- = _('Closed')
+ .js-issue-status
.block
.title
= _('Assignee')
diff --git a/app/workers/projects/post_creation_worker.rb b/app/workers/projects/post_creation_worker.rb
index 1970f79729f..9065bb90e82 100644
--- a/app/workers/projects/post_creation_worker.rb
+++ b/app/workers/projects/post_creation_worker.rb
@@ -21,7 +21,7 @@ module Projects
private
def create_prometheus_service(project)
- service = project.find_or_initialize_service(::PrometheusService.to_param)
+ service = project.find_or_initialize_service(::Integrations::Prometheus.to_param)
# If the service has already been inserted in the database, that
# means it came from a template, and there's nothing more to do.
diff --git a/app/workers/prometheus/create_default_alerts_worker.rb b/app/workers/prometheus/create_default_alerts_worker.rb
index 0dba752ced1..9d163cd828e 100644
--- a/app/workers/prometheus/create_default_alerts_worker.rb
+++ b/app/workers/prometheus/create_default_alerts_worker.rb
@@ -15,7 +15,7 @@ module Prometheus
return unless project
- result = Prometheus::CreateDefaultAlertsService.new(project: project).execute
+ result = ::Prometheus::CreateDefaultAlertsService.new(project: project).execute
log_info(result.message) if result.error?
end