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>2020-02-05 12:08:43 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-05 12:08:43 +0300
commit26384c9a61da9922b8fa4b8351d4e42d51661b37 (patch)
treeef3decbed644db3c97dcdbb5b71d4ade77f3155d /app
parent79cbe31b18159ea394c6f6e3027c1dc69bdabb75 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/diffs/components/app.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue12
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue20
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue4
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue105
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue53
-rw-r--r--app/assets/javascripts/error_tracking/details.js2
-rw-r--r--app/assets/javascripts/error_tracking/queries/details.query.graphql40
-rw-r--r--app/assets/javascripts/error_tracking/store/details/actions.js25
-rw-r--r--app/assets/javascripts/error_tracking/store/details/mutation_types.js2
-rw-r--r--app/assets/javascripts/error_tracking/store/details/mutations.js6
-rw-r--r--app/assets/javascripts/error_tracking/store/details/state.js2
-rw-r--r--app/assets/javascripts/ide/components/nav_form.vue8
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue2
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss15
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/controllers/concerns/confirm_email_warning.rb2
-rw-r--r--app/controllers/confirmations_controller.rb2
-rw-r--r--app/controllers/dashboard/snippets_controller.rb4
-rw-r--r--app/controllers/projects/snippets_controller.rb4
-rw-r--r--app/controllers/registrations_controller.rb16
-rw-r--r--app/helpers/projects/error_tracking_helper.rb1
-rw-r--r--app/models/clusters/applications/knative.rb2
-rw-r--r--app/models/serverless/domain_cluster.rb5
-rw-r--r--app/models/user.rb7
-rw-r--r--app/services/clusters/kubernetes.rb2
-rw-r--r--app/services/clusters/kubernetes/configure_istio_ingress_service.rb108
-rw-r--r--app/services/snippets/count_service.rb77
-rw-r--r--app/views/dashboard/snippets/index.html.haml2
-rw-r--r--app/views/projects/snippets/index.html.haml2
-rw-r--r--app/views/snippets/_snippets_scope_menu.html.haml10
-rw-r--r--app/workers/all_queues.yml6
-rw-r--r--app/workers/cluster_configure_istio_worker.rb14
35 files changed, 363 insertions, 207 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 463d1427805..878b54f7d53 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -374,7 +374,7 @@ export default {
<div
:data-can-create-note="getNoteableData.current_user.can_create_note"
- class="files d-flex prepend-top-default"
+ class="files d-flex"
>
<div
v-show="showTreeList"
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 24542126b07..63ce43a193d 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,5 +1,4 @@
<script>
-/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
@@ -63,9 +62,6 @@ export default {
showDropdowns() {
return !this.commit && this.mergeRequestDiffs.length;
},
- fileTreeIcon() {
- return this.showTreeList ? 'collapse-left' : 'expand-left';
- },
toggleFileBrowserTitle() {
return this.showTreeList ? __('Hide file browser') : __('Show file browser');
},
@@ -91,7 +87,7 @@ export default {
</script>
<template>
- <div class="mr-version-controls border-top border-bottom">
+ <div class="mr-version-controls border-top">
<div
class="mr-version-menus-container content-block"
:class="{
@@ -108,17 +104,17 @@ export default {
:title="toggleFileBrowserTitle"
@click="toggleShowTreeList"
>
- <icon :name="fileTreeIcon" />
+ <icon name="file-tree" />
</button>
<div v-if="showDropdowns" class="d-flex align-items-center compare-versions-container">
- Changes between
+ {{ __('Compare') }}
<compare-versions-dropdown
:other-versions="mergeRequestDiffs"
:merge-request-version="mergeRequestDiff"
:show-commit-count="true"
class="mr-version-dropdown"
/>
- and
+ {{ __('and') }}
<compare-versions-dropdown
:other-versions="comparableDiffs"
:base-version-path="baseVersionPath"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index ee10a1e92fc..48114f9919c 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -224,7 +224,7 @@ export default {
<div
v-if="!diffFile.submodule && addMergeRequestButtons"
- class="file-actions d-none d-sm-block"
+ class="file-actions d-none d-sm-flex align-items-center flex-wrap"
>
<diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
<div class="btn-group" role="group">
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
index 0138790cf0e..9d362ceb429 100644
--- a/app/assets/javascripts/diffs/components/diff_stats.vue
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -22,7 +22,7 @@ export default {
},
computed: {
filesText() {
- return n__('File', 'Files', this.diffFilesLength);
+ return n__('file', 'files', this.diffFilesLength);
},
isCompareVersionsHeader() {
return Boolean(this.diffFilesLength);
@@ -44,13 +44,21 @@ export default {
>
<div v-if="hasDiffFiles" class="diff-stats-group">
<icon name="doc-code" class="diff-stats-icon text-secondary" />
- <strong>{{ diffFilesLength }} {{ filesText }}</strong>
+ <span class="text-secondary bold">{{ diffFilesLength }} {{ filesText }}</span>
</div>
- <div class="diff-stats-group cgreen">
- <icon name="file-addition" class="diff-stats-icon" /> <strong>{{ addedLines }}</strong>
+ <div
+ class="diff-stats-group cgreen d-flex align-items-center"
+ :class="{ bold: isCompareVersionsHeader }"
+ >
+ <span>+</span>
+ <span class="js-file-addition-line">{{ addedLines }}</span>
</div>
- <div class="diff-stats-group cred">
- <icon name="file-deletion" class="diff-stats-icon" /> <strong>{{ removedLines }}</strong>
+ <div
+ class="diff-stats-group cred d-flex align-items-center"
+ :class="{ bold: isCompareVersionsHeader }"
+ >
+ <span>-</span>
+ <span class="js-file-deletion-line">{{ removedLines }}</span>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index 30be2e68e76..b13619a5471 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -58,8 +58,8 @@ export default {
this.search = '';
},
},
- searchPlaceholder: sprintf(s__('MergeRequest|Filter files or search with %{modifier_key}+p'), {
- modifier_key: /Mac/i.test(navigator.userAgent) ? 'cmd' : 'ctrl',
+ searchPlaceholder: sprintf(s__('MergeRequest|Search files (%{modifier_key}P)'), {
+ modifier_key: /Mac/i.test(navigator.userAgent) ? '⌘' : 'Ctrl+',
}),
};
</script>
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 88861b7da0e..7abe3be3e99 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -54,10 +54,6 @@ export default {
type: String,
required: true,
},
- issueDetailsPath: {
- type: String,
- required: true,
- },
issueStackTracePath: {
type: String,
required: true,
@@ -72,7 +68,7 @@ export default {
},
},
apollo: {
- GQLerror: {
+ error: {
query,
variables() {
return {
@@ -81,19 +77,19 @@ export default {
};
},
pollInterval: 2000,
- update: data => data.project.sentryDetailedError,
+ update: data => data.project.sentryErrors.detailedError,
error: () => createFlash(__('Failed to load error details from Sentry.')),
result(res) {
- if (res.data.project?.sentryDetailedError) {
- this.$apollo.queries.GQLerror.stopPolling();
- this.setStatus(this.GQLerror.status);
+ if (res.data.project?.sentryErrors?.detailedError) {
+ this.$apollo.queries.error.stopPolling();
+ this.setStatus(this.error.status);
}
},
},
},
data() {
return {
- GQLerror: null,
+ error: null,
issueCreationInProgress: false,
isAlertVisible: false,
closedIssueId: null,
@@ -101,8 +97,6 @@ export default {
},
computed: {
...mapState('details', [
- 'error',
- 'loading',
'loadingStacktrace',
'stacktraceData',
'updatingResolveStatus',
@@ -114,28 +108,23 @@ export default {
return sprintf(
__('Reported %{timeAgo} by %{reportedBy}'),
{
- reportedBy: `<strong>${this.GQLerror.culprit}</strong>`,
+ reportedBy: `<strong>${this.error.culprit}</strong>`,
timeAgo: this.timeFormatted(this.stacktraceData.date_received),
},
false,
);
},
firstReleaseLink() {
- return `${this.error.external_base_url}/releases/${this.GQLerror.firstReleaseShortVersion}`;
+ return `${this.error.externalBaseUrl}/releases/${this.error.firstReleaseShortVersion}`;
},
lastReleaseLink() {
- return `${this.error.external_base_url}releases/${this.GQLerror.lastReleaseShortVersion}`;
- },
- showDetails() {
- return Boolean(
- !this.loading && !this.$apollo.queries.GQLerror.loading && this.error && this.GQLerror,
- );
+ return `${this.error.externalBaseUrl}/releases/${this.error.lastReleaseShortVersion}`;
},
showStacktrace() {
- return Boolean(!this.loadingStacktrace && this.stacktrace && this.stacktrace.length);
+ return Boolean(this.stacktrace?.length);
},
issueTitle() {
- return this.GQLerror.title;
+ return this.error.title;
},
issueDescription() {
return sprintf(
@@ -144,13 +133,13 @@ export default {
),
{
description: '# Error Details:\n',
- errorUrl: `${this.GQLerror.externalUrl}\n`,
- firstSeen: `\n${this.GQLerror.firstSeen}\n`,
- lastSeen: `${this.GQLerror.lastSeen}\n`,
- countLabel: n__('- Event', '- Events', this.GQLerror.count),
- count: `${this.GQLerror.count}\n`,
- userCountLabel: n__('- User', '- Users', this.GQLerror.userCount),
- userCount: `${this.GQLerror.userCount}\n`,
+ errorUrl: `${this.error.externalUrl}\n`,
+ firstSeen: `\n${this.error.firstSeen}\n`,
+ lastSeen: `${this.error.lastSeen}\n`,
+ countLabel: n__('- Event', '- Events', this.error.count),
+ count: `${this.error.count}\n`,
+ userCountLabel: n__('- User', '- Users', this.error.userCount),
+ userCount: `${this.error.userCount}\n`,
},
false,
);
@@ -171,12 +160,10 @@ export default {
},
},
mounted() {
- this.startPollingDetails(this.issueDetailsPath);
this.startPollingStacktrace(this.issueStackTracePath);
},
methods: {
...mapActions('details', [
- 'startPollingDetails',
'startPollingStacktrace',
'updateStatus',
'setStatus',
@@ -214,10 +201,10 @@ export default {
<template>
<div>
- <div v-if="$apollo.queries.GQLerror.loading || loading" class="py-3">
+ <div v-if="$apollo.queries.error.loading" class="py-3">
<gl-loading-icon :size="3" />
</div>
- <div v-else-if="showDetails" class="error-details">
+ <div v-else-if="error" class="error-details">
<gl-alert v-if="isAlertVisible" @dismiss="isAlertVisible = false">
<gl-sprintf
:message="
@@ -232,7 +219,7 @@ export default {
<div class="top-area align-items-center justify-content-between py-3">
<span v-if="!loadingStacktrace && stacktrace" v-html="reported"></span>
- <div class="d-inline-flex">
+ <div class="d-inline-flex ml-lg-auto">
<loading-button
:label="ignoreBtnLabel"
:loading="updatingIgnoreStatus"
@@ -247,10 +234,10 @@ export default {
@click="onResolveStatusUpdate"
/>
<gl-button
- v-if="error.gitlab_issue"
+ v-if="error.gitlabIssuePath"
class="ml-2"
data-qa-selector="view_issue_button"
- :href="error.gitlab_issue"
+ :href="error.gitlabIssuePath"
variant="success"
>
{{ __('View issue') }}
@@ -264,13 +251,13 @@ export default {
<gl-form-input class="hidden" name="issue[title]" :value="issueTitle" />
<input name="issue[description]" :value="issueDescription" type="hidden" />
<gl-form-input
- :value="GQLerror.sentryId"
+ :value="error.sentryId"
class="hidden"
name="issue[sentry_issue_attributes][sentry_issue_identifier]"
/>
<gl-form-input :value="csrfToken" class="hidden" name="authenticity_token" />
<loading-button
- v-if="!error.gitlab_issue"
+ v-if="!error.gitlabIssuePath"
class="btn-success"
:label="__('Create issue')"
:loading="issueCreationInProgress"
@@ -281,8 +268,8 @@ export default {
</div>
</div>
<div>
- <tooltip-on-truncate :title="GQLerror.title" truncate-target="child" placement="top">
- <h2 class="text-truncate">{{ GQLerror.title }}</h2>
+ <tooltip-on-truncate :title="error.title" truncate-target="child" placement="top">
+ <h2 class="text-truncate">{{ error.title }}</h2>
</tooltip-on-truncate>
<template v-if="error.tags">
<gl-badge
@@ -297,53 +284,51 @@ export default {
</gl-badge>
</template>
<ul>
- <li v-if="GQLerror.gitlabCommit">
+ <li v-if="error.gitlabCommit">
<strong class="bold">{{ __('GitLab commit') }}:</strong>
- <gl-link :href="GQLerror.gitlabCommitPath">
- <span>{{ GQLerror.gitlabCommit.substr(0, 10) }}</span>
+ <gl-link :href="error.gitlabCommitPath">
+ <span>{{ error.gitlabCommit.substr(0, 10) }}</span>
</gl-link>
</li>
- <li v-if="error.gitlab_issue">
+ <li v-if="error.gitlabIssuePath">
<strong class="bold">{{ __('GitLab Issue') }}:</strong>
- <gl-link :href="error.gitlab_issue">
- <span>{{ error.gitlab_issue }}</span>
+ <gl-link :href="error.gitlabIssuePath">
+ <span>{{ error.gitlabIssuePath }}</span>
</gl-link>
</li>
<li>
<strong class="bold">{{ __('Sentry event') }}:</strong>
<gl-link
- v-track-event="trackClickErrorLinkToSentryOptions(GQLerror.externalUrl)"
+ v-track-event="trackClickErrorLinkToSentryOptions(error.externalUrl)"
class="d-inline-flex align-items-center"
- :href="GQLerror.externalUrl"
+ :href="error.externalUrl"
target="_blank"
>
- <span class="text-truncate">{{ GQLerror.externalUrl }}</span>
+ <span class="text-truncate">{{ error.externalUrl }}</span>
<icon name="external-link" class="ml-1 flex-shrink-0" />
</gl-link>
</li>
- <li v-if="GQLerror.firstReleaseShortVersion">
+ <li v-if="error.firstReleaseShortVersion">
<strong class="bold">{{ __('First seen') }}:</strong>
- {{ formatDate(GQLerror.firstSeen) }}
+ {{ formatDate(error.firstSeen) }}
<gl-link :href="firstReleaseLink" target="_blank">
- <span>
- {{ __('Release') }}: {{ GQLerror.firstReleaseShortVersion.substr(0, 10) }}
- </span>
+ <span>{{ __('Release') }}: {{ error.firstReleaseShortVersion.substr(0, 10) }}</span>
</gl-link>
</li>
- <li v-if="GQLerror.lastReleaseShortVersion">
+ <li v-if="error.lastReleaseShortVersion">
<strong class="bold">{{ __('Last seen') }}:</strong>
- {{ formatDate(GQLerror.lastSeen) }}
+ {{ formatDate(error.lastSeen) }}
<gl-link :href="lastReleaseLink" target="_blank">
- <span>{{ __('Release') }}: {{ GQLerror.lastReleaseShortVersion.substr(0, 10) }}</span>
+ <span>{{ __('Release') }}: {{ error.lastReleaseShortVersion.substr(0, 10) }}</span>
</gl-link>
</li>
<li>
<strong class="bold">{{ __('Events') }}:</strong>
- <span>{{ GQLerror.count }}</span>
+ <span>{{ error.count }}</span>
</li>
<li>
<strong class="bold">{{ __('Users') }}:</strong>
- <span>{{ GQLerror.userCount }}</span>
+ <span>{{ error.userCount }}</span>
</li>
</ul>
@@ -351,7 +336,7 @@ export default {
<gl-loading-icon :size="3" />
</div>
- <template v-if="showStacktrace">
+ <template v-else-if="showStacktrace">
<h3 class="my-4">{{ __('Stack trace') }}</h3>
<stacktrace :entries="stacktrace" />
</template>
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
index 6f3a5f683f8..1c996cbc13b 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -13,6 +13,7 @@ import {
GlDropdownDivider,
GlTooltipDirective,
GlPagination,
+ GlButtonGroup,
} from '@gitlab/ui';
import AccessorUtils from '~/lib/utils/accessor';
import Icon from '~/vue_shared/components/icon.vue';
@@ -20,12 +21,16 @@ import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { __ } from '~/locale';
import _ from 'underscore';
-export const tableDataClass = 'table-col d-flex d-sm-table-cell';
+export const tableDataClass = 'table-col d-flex d-sm-table-cell align-items-center';
export default {
FIRST_PAGE: 1,
PREV_PAGE: 1,
NEXT_PAGE: 2,
+ statusButtons: [
+ { status: 'ignored', icon: 'eye-slash', title: __('Ignore') },
+ { status: 'resolved', icon: 'check-circle', title: __('Resolve') },
+ ],
fields: [
{
key: 'error',
@@ -48,20 +53,13 @@ export default {
{
key: 'lastSeen',
label: __('Last seen'),
- thClass: '',
+ thClass: 'w-15p',
tdClass: `${tableDataClass}`,
},
{
- key: 'ignore',
- label: '',
- thClass: 'w-3rem',
- tdClass: `${tableDataClass} pl-0`,
- },
- {
- key: 'resolved',
+ key: 'status',
label: '',
- thClass: 'w-3rem',
- tdClass: `${tableDataClass} pl-0`,
+ tdClass: `${tableDataClass} text-right`,
},
{
key: 'details',
@@ -88,6 +86,7 @@ export default {
Icon,
GlPagination,
TimeAgo,
+ GlButtonGroup,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -332,25 +331,19 @@ export default {
<time-ago :time="errors.item.lastSeen" class="text-secondary" />
</div>
</template>
- <template #cell(ignore)="errors">
- <gl-button
- ref="ignoreError"
- v-gl-tooltip.hover
- :title="__('Ignore')"
- @click="updateIssueStatus(errors.item.id, 'ignored')"
- >
- <gl-icon name="eye-slash" :size="12" />
- </gl-button>
- </template>
- <template #cell(resolved)="errors">
- <gl-button
- ref="resolveError"
- v-gl-tooltip
- :title="__('Resolve')"
- @click="updateIssueStatus(errors.item.id, 'resolved')"
- >
- <gl-icon name="check-circle" :size="12" />
- </gl-button>
+ <template #cell(status)="errors">
+ <gl-button-group>
+ <gl-button
+ v-for="button in $options.statusButtons"
+ :key="button.status"
+ :ref="button.title.toLowerCase() + 'Error'"
+ v-gl-tooltip.hover
+ :title="button.title"
+ @click="updateIssueStatus(errors.item.id, button.status)"
+ >
+ <gl-icon :name="button.icon" :size="12" />
+ </gl-button>
+ </gl-button-group>
</template>
<template #cell(details)="errors">
<gl-button
diff --git a/app/assets/javascripts/error_tracking/details.js b/app/assets/javascripts/error_tracking/details.js
index a5a7ddc907b..1a92681374b 100644
--- a/app/assets/javascripts/error_tracking/details.js
+++ b/app/assets/javascripts/error_tracking/details.js
@@ -26,7 +26,6 @@ export default () => {
issueId,
projectPath,
issueUpdatePath,
- issueDetailsPath,
issueStackTracePath,
projectIssuesPath,
} = domEl.dataset;
@@ -36,7 +35,6 @@ export default () => {
issueId,
projectPath,
issueUpdatePath,
- issueDetailsPath,
issueStackTracePath,
projectIssuesPath,
csrfToken: csrf.token,
diff --git a/app/assets/javascripts/error_tracking/queries/details.query.graphql b/app/assets/javascripts/error_tracking/queries/details.query.graphql
index 488a3ecc3ab..fa579c94257 100644
--- a/app/assets/javascripts/error_tracking/queries/details.query.graphql
+++ b/app/assets/javascripts/error_tracking/queries/details.query.graphql
@@ -1,21 +1,29 @@
query errorDetails($fullPath: ID!, $errorId: ID!) {
project(fullPath: $fullPath) {
- sentryDetailedError(id: $errorId) {
- id
- sentryId
- title
- userCount
- count
- status
- firstSeen
- lastSeen
- message
- culprit
- externalUrl
- firstReleaseShortVersion
- lastReleaseShortVersion
- gitlabCommit
- gitlabCommitPath
+ sentryErrors {
+ detailedError(id: $errorId) {
+ id
+ sentryId
+ title
+ userCount
+ count
+ status
+ firstSeen
+ lastSeen
+ message
+ culprit
+ tags {
+ level
+ logger
+ }
+ externalUrl
+ externalBaseUrl
+ firstReleaseShortVersion
+ lastReleaseShortVersion
+ gitlabCommit
+ gitlabCommitPath
+ gitlabIssuePath
+ }
}
}
}
diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js
index 2b216d910ce..5914a79f092 100644
--- a/app/assets/javascripts/error_tracking/store/details/actions.js
+++ b/app/assets/javascripts/error_tracking/store/details/actions.js
@@ -5,36 +5,11 @@ import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
let stackTracePoll;
-let detailPoll;
const stopPolling = poll => {
if (poll) poll.stop();
};
-export function startPollingDetails({ commit }, endpoint) {
- detailPoll = new Poll({
- resource: service,
- method: 'getSentryData',
- data: { endpoint },
- successCallback: ({ data }) => {
- if (!data) {
- return;
- }
-
- commit(types.SET_ERROR, data.error);
- commit(types.SET_LOADING, false);
-
- stopPolling(detailPoll);
- },
- errorCallback: () => {
- commit(types.SET_LOADING, false);
- createFlash(__('Failed to load error details from Sentry.'));
- },
- });
-
- detailPoll.makeRequest();
-}
-
export function startPollingStacktrace({ commit }, endpoint) {
stackTracePoll = new Poll({
resource: service,
diff --git a/app/assets/javascripts/error_tracking/store/details/mutation_types.js b/app/assets/javascripts/error_tracking/store/details/mutation_types.js
index a2592253a2d..0dd49e727e6 100644
--- a/app/assets/javascripts/error_tracking/store/details/mutation_types.js
+++ b/app/assets/javascripts/error_tracking/store/details/mutation_types.js
@@ -1,4 +1,2 @@
-export const SET_ERROR = 'SET_ERRORS';
-export const SET_LOADING = 'SET_LOADING';
export const SET_LOADING_STACKTRACE = 'SET_LOADING_STACKTRACE';
export const SET_STACKTRACE_DATA = 'SET_STACKTRACE_DATA';
diff --git a/app/assets/javascripts/error_tracking/store/details/mutations.js b/app/assets/javascripts/error_tracking/store/details/mutations.js
index 6f4720444e0..b2bde96c6a9 100644
--- a/app/assets/javascripts/error_tracking/store/details/mutations.js
+++ b/app/assets/javascripts/error_tracking/store/details/mutations.js
@@ -1,12 +1,6 @@
import * as types from './mutation_types';
export default {
- [types.SET_ERROR](state, data) {
- state.error = data;
- },
- [types.SET_LOADING](state, loading) {
- state.loading = loading;
- },
[types.SET_LOADING_STACKTRACE](state, data) {
state.loadingStacktrace = data;
},
diff --git a/app/assets/javascripts/error_tracking/store/details/state.js b/app/assets/javascripts/error_tracking/store/details/state.js
index f53cbe29c67..4a6bafe3114 100644
--- a/app/assets/javascripts/error_tracking/store/details/state.js
+++ b/app/assets/javascripts/error_tracking/store/details/state.js
@@ -1,7 +1,5 @@
export default () => ({
- error: {},
stacktraceData: {},
- loading: true,
loadingStacktrace: true,
updatingResolveStatus: false,
updatingIgnoreStatus: false,
diff --git a/app/assets/javascripts/ide/components/nav_form.vue b/app/assets/javascripts/ide/components/nav_form.vue
index 23c068f329d..2ccc84ea5d5 100644
--- a/app/assets/javascripts/ide/components/nav_form.vue
+++ b/app/assets/javascripts/ide/components/nav_form.vue
@@ -19,15 +19,15 @@ export default {
<tabs stop-propagation>
<tab active>
<template slot="title">
- {{ __('Merge Requests') }}
+ {{ __('Branches') }}
</template>
- <merge-request-search-list />
+ <branches-search-list />
</tab>
<tab>
<template slot="title">
- {{ __('Branches') }}
+ {{ __('Merge Requests') }}
</template>
- <branches-search-list />
+ <merge-request-search-list />
</tab>
</tabs>
</div>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index bcaaa8e09c2..b2fa020fb00 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -51,7 +51,7 @@ export default {
</script>
<template>
- <div class="ide-new-btn d-none">
+ <div class="ide-new-btn">
<div
:class="{
show: isOpen,
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 5eaff7702f6..7fa48c70f41 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -1224,6 +1224,8 @@ $ide-commit-header-height: 48px;
}
.ide-new-btn {
+ display: none;
+
.btn {
padding: 2px 5px;
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index d30f113c01f..24c6fec064a 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -14,9 +14,9 @@
cursor: pointer;
@media (min-width: map-get($grid-breakpoints, md)) {
- // The `-1` below is to prevent two borders from clashing up against eachother -
+ // The `+11` is to ensure the file header border shows when scrolled -
// the bottom of the compare-versions header and the top of the file header
- $mr-file-header-top: $mr-version-controls-height + $header-height + $mr-tabs-height - 1;
+ $mr-file-header-top: $mr-version-controls-height + $header-height + $mr-tabs-height + 11;
position: -webkit-sticky;
position: sticky;
@@ -547,7 +547,7 @@ table.code {
.diff-stats {
align-items: center;
- padding: 0 0.25rem;
+ padding: 0 1rem;
.diff-stats-group {
padding: 0 0.25rem;
@@ -559,7 +559,7 @@ table.code {
&.is-compare-versions-header {
.diff-stats-group {
- padding: 0 0.5rem;
+ padding: 0 0.25rem;
}
}
}
@@ -1054,8 +1054,8 @@ table.code {
.diff-tree-list {
position: -webkit-sticky;
position: sticky;
- $top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
- top: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
+ $top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 11px;
+ top: $top-pos;
max-height: calc(100vh - #{$top-pos});
z-index: 202;
@@ -1092,10 +1092,7 @@ table.code {
.tree-list-scroll {
max-height: 100%;
- padding-top: $grid-size;
padding-bottom: $grid-size;
- border-top: 1px solid $border-color;
- border-bottom: 1px solid $border-color;
overflow-y: scroll;
overflow-x: auto;
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index c023c9e5cbd..84daec4fb43 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -708,7 +708,7 @@
.mr-version-controls {
position: relative;
z-index: 203;
- background: $gray-light;
+ background: $white-light;
color: $gl-text-color;
margin-top: -1px;
@@ -732,7 +732,7 @@
}
.content-block {
- padding: $gl-padding-top $gl-padding;
+ padding: $gl-padding;
border-bottom: 0;
}
diff --git a/app/controllers/concerns/confirm_email_warning.rb b/app/controllers/concerns/confirm_email_warning.rb
index 32e1a46e580..f1c0bcd491d 100644
--- a/app/controllers/concerns/confirm_email_warning.rb
+++ b/app/controllers/concerns/confirm_email_warning.rb
@@ -10,7 +10,7 @@ module ConfirmEmailWarning
protected
def show_confirm_warning?
- html_request? && request.get? && Feature.enabled?(:soft_email_confirmation)
+ html_request? && request.get?
end
def set_confirm_warning
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb
index 21ee76d31b2..f99345fa99d 100644
--- a/app/controllers/confirmations_controller.rb
+++ b/app/controllers/confirmations_controller.rb
@@ -11,7 +11,7 @@ class ConfirmationsController < Devise::ConfirmationsController
protected
def after_resending_confirmation_instructions_path_for(resource)
- Feature.enabled?(:soft_email_confirmation) ? stored_location_for(resource) || dashboard_projects_path : users_almost_there_path
+ stored_location_for(resource) || dashboard_projects_path
end
def after_confirmation_path_for(resource_name, resource)
diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb
index 6feade3df03..aa09fcdbe61 100644
--- a/app/controllers/dashboard/snippets_controller.rb
+++ b/app/controllers/dashboard/snippets_controller.rb
@@ -7,6 +7,10 @@ class Dashboard::SnippetsController < Dashboard::ApplicationController
skip_cross_project_access_check :index
def index
+ @snippet_counts = Snippets::CountService
+ .new(current_user, author: current_user)
+ .execute
+
@snippets = SnippetsFinder.new(current_user, author: current_user, scope: params[:scope])
.execute
.page(params[:page])
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index d7ae6d2cbb4..b9c7468890b 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -30,6 +30,10 @@ class Projects::SnippetsController < Projects::ApplicationController
respond_to :html
def index
+ @snippet_counts = Snippets::CountService
+ .new(current_user, project: @project)
+ .execute
+
@snippets = SnippetsFinder.new(current_user, project: @project, scope: params[:scope])
.execute
.page(params[:page])
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index b40264bfdf4..29b0c6b29ae 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -53,7 +53,7 @@ class RegistrationsController < Devise::RegistrationsController
def welcome
return redirect_to new_user_registration_path unless current_user
- return redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) if current_user.role.present? && !current_user.setup_for_company.nil?
+ return redirect_to stored_location_or_dashboard(current_user) if current_user.role.present? && !current_user.setup_for_company.nil?
current_user.name = nil if current_user.name == current_user.username
end
@@ -65,7 +65,7 @@ class RegistrationsController < Devise::RegistrationsController
if result[:status] == :success
track_experiment_event(:signup_flow, 'end') # We want this event to be tracked when the user is _in_ the experimental group
set_flash_message! :notice, :signed_up
- redirect_to stored_location_or_dashboard_or_almost_there_path(current_user)
+ redirect_to stored_location_or_dashboard(current_user)
else
render :welcome
end
@@ -112,12 +112,12 @@ class RegistrationsController < Devise::RegistrationsController
return users_sign_up_welcome_path if experiment_enabled?(:signup_flow)
- stored_location_or_dashboard_or_almost_there_path(user)
+ stored_location_or_dashboard(user)
end
def after_inactive_sign_up_path_for(resource)
Gitlab::AppLogger.info(user_created_message)
- Feature.enabled?(:soft_email_confirmation) ? dashboard_projects_path : users_almost_there_path
+ dashboard_projects_path
end
private
@@ -179,18 +179,10 @@ class RegistrationsController < Devise::RegistrationsController
Gitlab::Utils.to_boolean(params[:terms_opt_in])
end
- def confirmed_or_unconfirmed_access_allowed(user)
- user.confirmed? || Feature.enabled?(:soft_email_confirmation) || experiment_enabled?(:signup_flow)
- end
-
def stored_location_or_dashboard(user)
stored_location_for(user) || dashboard_projects_path
end
- def stored_location_or_dashboard_or_almost_there_path(user)
- confirmed_or_unconfirmed_access_allowed(user) ? stored_location_or_dashboard(user) : users_almost_there_path
- end
-
# Part of an experiment to build a new sign up flow. Will be resolved
# with https://gitlab.com/gitlab-org/growth/engineering/issues/64
def choose_layout
diff --git a/app/helpers/projects/error_tracking_helper.rb b/app/helpers/projects/error_tracking_helper.rb
index 91fc18f4312..5be4f67bde8 100644
--- a/app/helpers/projects/error_tracking_helper.rb
+++ b/app/helpers/projects/error_tracking_helper.rb
@@ -22,7 +22,6 @@ module Projects::ErrorTrackingHelper
{
'issue-id' => issue_id,
'project-path' => project.full_path,
- 'issue-details-path' => details_project_error_tracking_index_path(*opts),
'issue-update-path' => update_project_error_tracking_index_path(*opts),
'project-issues-path' => project_issues_path(project),
'issue-stack-trace-path' => stack_trace_project_error_tracking_index_path(*opts)
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 2602bb2cf97..eebcbcba2d3 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -74,7 +74,7 @@ module Clusters
end
def ingress_service
- cluster.kubeclient.get_service('istio-ingressgateway', 'istio-system')
+ cluster.kubeclient.get_service('istio-ingressgateway', Clusters::Kubernetes::ISTIO_SYSTEM_NAMESPACE)
end
def uninstall_command
diff --git a/app/models/serverless/domain_cluster.rb b/app/models/serverless/domain_cluster.rb
index 9a1acf7e5c3..94d90d3e305 100644
--- a/app/models/serverless/domain_cluster.rb
+++ b/app/models/serverless/domain_cluster.rb
@@ -10,6 +10,11 @@ module Serverless
belongs_to :knative, class_name: 'Clusters::Applications::Knative', foreign_key: 'clusters_applications_knative_id'
belongs_to :creator, class_name: 'User', optional: true
+ attr_encrypted :key,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm'
+
validates :pages_domain, :knative, presence: true
validates :uuid, presence: true, uniqueness: true, length: { is: Gitlab::Serverless::Domain::UUID_LENGTH },
format: { with: HEX_REGEXP, message: 'only allows hex characters' }
diff --git a/app/models/user.rb b/app/models/user.rb
index d44e8162abe..a5ef03215d3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1638,13 +1638,6 @@ class User < ApplicationRecord
super
end
- # override from Devise::Confirmable
- def confirmation_period_valid?
- return false if Feature.disabled?(:soft_email_confirmation)
-
- super
- end
-
private
def default_private_profile_to_false
diff --git a/app/services/clusters/kubernetes.rb b/app/services/clusters/kubernetes.rb
index d29519999b2..aafea64c820 100644
--- a/app/services/clusters/kubernetes.rb
+++ b/app/services/clusters/kubernetes.rb
@@ -12,5 +12,7 @@ module Clusters
GITLAB_KNATIVE_SERVING_ROLE_BINDING_NAME = 'gitlab-knative-serving-rolebinding'
GITLAB_CROSSPLANE_DATABASE_ROLE_NAME = 'gitlab-crossplane-database-role'
GITLAB_CROSSPLANE_DATABASE_ROLE_BINDING_NAME = 'gitlab-crossplane-database-rolebinding'
+ KNATIVE_SERVING_NAMESPACE = 'knative-serving'
+ ISTIO_SYSTEM_NAMESPACE = 'istio-system'
end
end
diff --git a/app/services/clusters/kubernetes/configure_istio_ingress_service.rb b/app/services/clusters/kubernetes/configure_istio_ingress_service.rb
new file mode 100644
index 00000000000..fe577beaa8a
--- /dev/null
+++ b/app/services/clusters/kubernetes/configure_istio_ingress_service.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'openssl'
+
+module Clusters
+ module Kubernetes
+ class ConfigureIstioIngressService
+ PASSTHROUGH_RESOURCE = Kubeclient::Resource.new(
+ mode: 'PASSTHROUGH'
+ ).freeze
+
+ MTLS_RESOURCE = Kubeclient::Resource.new(
+ mode: 'MUTUAL',
+ privateKey: '/etc/istio/ingressgateway-certs/tls.key',
+ serverCertificate: '/etc/istio/ingressgateway-certs/tls.crt',
+ caCertificates: '/etc/istio/ingressgateway-ca-certs/cert.pem'
+ ).freeze
+
+ def initialize(cluster:)
+ @cluster = cluster
+ @platform = cluster.platform
+ @kubeclient = platform.kubeclient
+ @knative = cluster.application_knative
+ end
+
+ def execute
+ return configure_certificates if serverless_domain_cluster
+
+ configure_passthrough
+ end
+
+ private
+
+ attr_reader :cluster, :platform, :kubeclient, :knative
+
+ def serverless_domain_cluster
+ knative&.serverless_domain_cluster
+ end
+
+ def configure_certificates
+ create_or_update_istio_cert_and_key
+ set_gateway_wildcard_https(MTLS_RESOURCE)
+ end
+
+ def create_or_update_istio_cert_and_key
+ name = OpenSSL::X509::Name.parse("CN=#{knative.hostname}")
+
+ key = OpenSSL::PKey::RSA.new(2048)
+
+ cert = OpenSSL::X509::Certificate.new
+ cert.version = 2
+ cert.serial = 0
+ cert.not_before = Time.now
+ cert.not_after = Time.now + 1000.years
+
+ cert.public_key = key.public_key
+ cert.subject = name
+ cert.issuer = name
+ cert.sign(key, OpenSSL::Digest::SHA256.new)
+
+ serverless_domain_cluster.update!(
+ key: key.to_pem,
+ certificate: cert.to_pem
+ )
+
+ kubeclient.create_or_update_secret(istio_ca_certs_resource)
+ kubeclient.create_or_update_secret(istio_certs_resource)
+ end
+
+ def istio_ca_certs_resource
+ Gitlab::Kubernetes::GenericSecret.new(
+ 'istio-ingressgateway-ca-certs',
+ {
+ 'cert.pem': Base64.strict_encode64(serverless_domain_cluster.certificate)
+ },
+ Clusters::Kubernetes::ISTIO_SYSTEM_NAMESPACE
+ ).generate
+ end
+
+ def istio_certs_resource
+ Gitlab::Kubernetes::TlsSecret.new(
+ 'istio-ingressgateway-certs',
+ serverless_domain_cluster.certificate,
+ serverless_domain_cluster.key,
+ Clusters::Kubernetes::ISTIO_SYSTEM_NAMESPACE
+ ).generate
+ end
+
+ def set_gateway_wildcard_https(tls_resource)
+ gateway_resource = gateway
+ gateway_resource.spec.servers.each do |server|
+ next unless server.hosts == ['*'] && server.port.name == 'https'
+
+ server.tls = tls_resource
+ end
+ kubeclient.update_gateway(gateway_resource)
+ end
+
+ def configure_passthrough
+ set_gateway_wildcard_https(PASSTHROUGH_RESOURCE)
+ end
+
+ def gateway
+ kubeclient.get_gateway('knative-ingress-gateway', Clusters::Kubernetes::KNATIVE_SERVING_NAMESPACE)
+ end
+ end
+ end
+end
diff --git a/app/services/snippets/count_service.rb b/app/services/snippets/count_service.rb
new file mode 100644
index 00000000000..9a3d33c75cf
--- /dev/null
+++ b/app/services/snippets/count_service.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+# Service for calculating visible Snippet counts via one query
+# for the given user or project.
+#
+# Authorisation level checks will be included, ensuring the correct
+# counts will be returned for the given user (if any).
+#
+# Basic usage:
+#
+# user = User.find(1)
+#
+# Snippets::CountService.new(user, author: user).execute
+# #=> {
+# are_public: 1,
+# are_internal: 1,
+# are_private: 1,
+# all: 3
+# }
+#
+# Counts can be scoped to a project:
+#
+# user = User.find(1)
+# project = Project.find(1)
+#
+# Snippets::CountService.new(user, project: project).execute
+# #=> {
+# are_public: 1,
+# are_internal: 1,
+# are_private: 0,
+# all: 2
+# }
+#
+# Either a project or an author *must* be supplied.
+module Snippets
+ class CountService
+ def initialize(current_user, author: nil, project: nil)
+ if !author && !project
+ raise(
+ ArgumentError, 'Must provide either an author or a project'
+ )
+ end
+
+ @snippets_finder = SnippetsFinder.new(current_user, author: author, project: project)
+ end
+
+ def execute
+ counts = snippet_counts
+ return {} unless counts
+
+ counts.slice(
+ :are_public,
+ :are_private,
+ :are_internal,
+ :are_public_or_internal,
+ :total
+ )
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def snippet_counts
+ @snippets_finder.execute
+ .reorder(nil)
+ .select("
+ count(case when snippets.visibility_level=#{Snippet::PUBLIC} and snippets.secret is FALSE then 1 else null end) as are_public,
+ count(case when snippets.visibility_level=#{Snippet::INTERNAL} then 1 else null end) as are_internal,
+ count(case when snippets.visibility_level=#{Snippet::PRIVATE} then 1 else null end) as are_private,
+ count(case when visibility_level=#{Snippet::PUBLIC} OR visibility_level=#{Snippet::INTERNAL} then 1 else null end) as are_public_or_internal,
+ count(*) as total
+ ")
+ .first
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml
index 69155b6c04d..05214346496 100644
--- a/app/views/dashboard/snippets/index.html.haml
+++ b/app/views/dashboard/snippets/index.html.haml
@@ -5,7 +5,7 @@
= render 'dashboard/snippets_head'
- if current_user.snippets.exists?
- = render partial: 'snippets/snippets_scope_menu', locals: { include_private: true }
+ = render partial: 'snippets/snippets_scope_menu', locals: { include_private: true, counts: @snippet_counts }
- if current_user.snippets.exists?
= render partial: 'shared/snippets/list', locals: { link_project: true }
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index ed56cc8289c..a505b34f46c 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -5,7 +5,7 @@
- if current_user
.top-area
- include_private = @project.team.member?(current_user) || current_user.admin?
- = render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private }
+ = render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private, counts: @snippet_counts }
- if new_project_snippet_link.present?
.nav-controls
diff --git a/app/views/snippets/_snippets_scope_menu.html.haml b/app/views/snippets/_snippets_scope_menu.html.haml
index cb59b11ca2b..e9c9ca6e856 100644
--- a/app/views/snippets/_snippets_scope_menu.html.haml
+++ b/app/views/snippets/_snippets_scope_menu.html.haml
@@ -7,25 +7,25 @@
= _("All")
%span.badge.badge-pill
- if include_private
- = subject.snippets.count
+ = counts[:total]
- else
- = subject.snippets.public_and_internal_only.count
+ = counts[:are_public_or_internal]
- if include_private
%li{ class: active_when(params[:scope] == "are_private") }
= link_to subject_snippets_path(subject, scope: 'are_private') do
= _("Private")
%span.badge.badge-pill
- = subject.snippets.are_private.count
+ = counts[:are_private]
%li{ class: active_when(params[:scope] == "are_internal") }
= link_to subject_snippets_path(subject, scope: 'are_internal') do
= _("Internal")
%span.badge.badge-pill
- = subject.snippets.are_internal.count
+ = counts[:are_internal]
%li{ class: active_when(params[:scope] == "are_public") }
= link_to subject_snippets_path(subject, scope: 'are_public') do
= _("Public")
%span.badge.badge-pill
- = subject.snippets.are_public.count
+ = counts[:are_public]
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index c93c312438b..0426a0b8fbb 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -231,6 +231,12 @@
:latency_sensitive:
:resource_boundary: :unknown
:weight: 1
+- :name: gcp_cluster:cluster_configure_istio
+ :feature_category: :kubernetes_management
+ :has_external_dependencies: true
+ :latency_sensitive:
+ :resource_boundary: :unknown
+ :weight: 1
- :name: gcp_cluster:cluster_install_app
:feature_category: :kubernetes_management
:has_external_dependencies: true
diff --git a/app/workers/cluster_configure_istio_worker.rb b/app/workers/cluster_configure_istio_worker.rb
new file mode 100644
index 00000000000..dfdd408f286
--- /dev/null
+++ b/app/workers/cluster_configure_istio_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class ClusterConfigureIstioWorker
+ include ApplicationWorker
+ include ClusterQueue
+
+ worker_has_external_dependencies!
+
+ def perform(cluster_id)
+ Clusters::Cluster.find_by_id(cluster_id).try do |cluster|
+ Clusters::Kubernetes::ConfigureIstioIngressService.new(cluster: cluster).execute
+ end
+ end
+end