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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-19 10:33:21 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-19 10:33:21 +0300
commit36a59d088eca61b834191dacea009677a96c052f (patch)
treee4f33972dab5d8ef79e3944a9f403035fceea43f /app/assets/javascripts/clusters
parenta1761f15ec2cae7c7f7bbda39a75494add0dfd6f (diff)
Add latest changes from gitlab-org/gitlab@15-0-stable-eev15.0.0-rc42
Diffstat (limited to 'app/assets/javascripts/clusters')
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_events_list.vue16
-rw-r--r--app/assets/javascripts/clusters/agents/components/revoke_token_button.vue201
-rw-r--r--app/assets/javascripts/clusters/agents/components/show.vue2
-rw-r--r--app/assets/javascripts/clusters/agents/components/token_table.vue11
-rw-r--r--app/assets/javascripts/clusters/agents/constants.js2
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/cache_update.js22
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/mutations/revoke_token.mutation.graphql5
-rw-r--r--app/assets/javascripts/clusters/components/new_cluster.vue8
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue2
-rw-r--r--app/assets/javascripts/clusters/forms/components/integration_form.vue2
-rw-r--r--app/assets/javascripts/clusters/gke_cluster_namespace/index.js37
-rw-r--r--app/assets/javascripts/clusters/new_cluster.js8
-rw-r--r--app/assets/javascripts/clusters/stores/new_cluster/index.js12
-rw-r--r--app/assets/javascripts/clusters/stores/new_cluster/state.js3
14 files changed, 295 insertions, 36 deletions
diff --git a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
index 6567ce203bc..18c6503bfb2 100644
--- a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
+++ b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
@@ -28,17 +28,17 @@ export default {
},
i18n: {
emptyText: s__(
- 'ClusterAgents|See Agent activity updates such as tokens created or revoked and clusters connected or not connected.',
+ 'ClusterAgents|See agent activity updates, like tokens created or revoked and clusters connected or not connected.',
),
- emptyTooltip: s__('ClusterAgents|What is GitLab Agent activity?'),
+ emptyTooltip: s__('ClusterAgents|What is agent activity?'),
error: s__(
- 'ClusterAgents|An error occurred while retrieving GitLab Agent activity. Reload the page to try again.',
+ 'ClusterAgents|An error occurred while retrieving agent activity. Reload the page to try again.',
),
today: __('Today'),
yesterday: __('Yesterday'),
},
- emptyHelpLink: helpPagePath('user/clusters/agent/install/index', {
- anchor: 'view-agent-activity',
+ emptyHelpLink: helpPagePath('user/clusters/agent/work_with_agent', {
+ anchor: 'view-an-agents-activity-information',
}),
borderClasses: 'gl-border-b-1 gl-border-b-solid gl-border-b-gray-100',
apollo: {
@@ -68,8 +68,8 @@ export default {
},
emptyStateTitle() {
return n__(
- "ClusterAgents|There's no activity from the past day",
- "ClusterAgents|There's no activity from the past %d days",
+ 'ClusterAgents|No activity occurred in the past day',
+ 'ClusterAgents|No activity occurred in the past %d days',
EVENTS_STORED_DAYS,
);
},
@@ -124,7 +124,7 @@ export default {
<template>
<div>
- <gl-loading-icon v-if="isLoading" size="md" />
+ <gl-loading-icon v-if="isLoading" size="lg" />
<div v-else-if="hasEvents">
<div
diff --git a/app/assets/javascripts/clusters/agents/components/revoke_token_button.vue b/app/assets/javascripts/clusters/agents/components/revoke_token_button.vue
new file mode 100644
index 00000000000..7d36cbb170d
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/components/revoke_token_button.vue
@@ -0,0 +1,201 @@
+<script>
+import {
+ GlButton,
+ GlModalDirective,
+ GlTooltip,
+ GlModal,
+ GlFormGroup,
+ GlFormInput,
+ GlSprintf,
+} from '@gitlab/ui';
+import { s__, __, sprintf } from '~/locale';
+import { REVOKE_TOKEN_MODAL_ID, TOKEN_STATUS_ACTIVE } from '../constants';
+import revokeAgentToken from '../graphql/mutations/revoke_token.mutation.graphql';
+import getClusterAgentQuery from '../graphql/queries/get_cluster_agent.query.graphql';
+import { removeTokenFromStore } from '../graphql/cache_update';
+
+export default {
+ components: {
+ GlButton,
+ GlTooltip,
+ GlModal,
+ GlFormGroup,
+ GlFormInput,
+ GlSprintf,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ inject: ['agentName', 'projectPath', 'canAdminCluster'],
+ props: {
+ token: {
+ required: true,
+ type: Object,
+ validator: (value) => ['id', 'name'].every((prop) => value[prop]),
+ },
+ cursor: {
+ required: true,
+ type: Object,
+ },
+ },
+ i18n: {
+ revokeButton: s__('ClusterAgents|Revoke token'),
+ dropdownDisabledHint: s__(
+ 'ClusterAgents|Requires a Maintainer or greater role to perform this action',
+ ),
+ modalTitle: s__('ClusterAgents|Revoke access token?'),
+ modalBody: s__(
+ 'ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action.',
+ ),
+ modalInputLabel: s__('ClusterAgents|To revoke the token, type %{name} to confirm:'),
+ modalCancel: __('Cancel'),
+ successMessage: s__('ClusterAgents|%{name} successfully revoked'),
+ defaultError: __('An error occurred. Please try again.'),
+ },
+ data() {
+ return {
+ loading: false,
+ error: null,
+ revokeConfirmText: null,
+ tokenName: null,
+ variables: {
+ agentName: this.agentName,
+ projectPath: this.projectPath,
+ tokenStatus: TOKEN_STATUS_ACTIVE,
+ ...this.cursor,
+ },
+ };
+ },
+ computed: {
+ revokeBtnDisabled() {
+ return this.loading || !this.canAdminCluster;
+ },
+ modalId() {
+ return sprintf(REVOKE_TOKEN_MODAL_ID, {
+ tokenName: this.token.name,
+ });
+ },
+ primaryModalProps() {
+ return {
+ text: this.$options.i18n.revokeButton,
+ attributes: [
+ { disabled: this.loading || this.disableModalSubmit, loading: this.loading },
+ { variant: 'danger' },
+ ],
+ };
+ },
+ cancelModalProps() {
+ return {
+ text: this.$options.i18n.modalCancel,
+ attributes: [],
+ };
+ },
+ disableModalSubmit() {
+ return this.revokeConfirmText !== this.token.name;
+ },
+ },
+ methods: {
+ async revokeToken() {
+ if (this.disableModalSubmit || this.loading) {
+ return;
+ }
+
+ this.loading = true;
+ this.error = null;
+ this.tokenName = this.token.name;
+
+ try {
+ const { errors } = await this.revokeTokenMutation();
+
+ if (errors.length) {
+ throw new Error(errors[0]);
+ }
+ } catch (error) {
+ this.error = error?.message || this.$options.i18n.defaultError;
+ } finally {
+ this.loading = false;
+ const successMessage = sprintf(this.$options.i18n.successMessage, {
+ name: this.tokenName,
+ });
+
+ this.$toast.show(this.error || successMessage);
+
+ this.hideModal();
+ }
+ },
+ revokeTokenMutation() {
+ return this.$apollo
+ .mutate({
+ mutation: revokeAgentToken,
+ variables: {
+ input: {
+ id: this.token.id,
+ },
+ },
+ update: (store) => {
+ removeTokenFromStore(store, this.token, getClusterAgentQuery, this.variables);
+ },
+ })
+
+ .then(({ data: { clusterAgentTokenRevoke } }) => {
+ return clusterAgentTokenRevoke;
+ });
+ },
+ resetModal() {
+ this.loading = false;
+ this.error = null;
+ this.revokeConfirmText = null;
+ },
+ hideModal() {
+ this.resetModal();
+ this.$refs.modal.hide();
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div ref="revokeToken" class="gl-display-inline-block">
+ <gl-button
+ v-gl-modal-directive="modalId"
+ icon="remove"
+ category="secondary"
+ variant="danger"
+ :disabled="revokeBtnDisabled"
+ :title="$options.i18n.revokeButton"
+ :aria-label="$options.i18n.revokeButton"
+ />
+
+ <gl-tooltip
+ v-if="!canAdminCluster"
+ :target="() => $refs.revokeToken"
+ :title="$options.i18n.dropdownDisabledHint"
+ />
+ </div>
+
+ <gl-modal
+ ref="modal"
+ :modal-id="modalId"
+ :title="$options.i18n.modalTitle"
+ :action-primary="primaryModalProps"
+ :action-cancel="cancelModalProps"
+ size="sm"
+ @primary="revokeToken"
+ @hide="hideModal"
+ >
+ <p>{{ $options.i18n.modalBody }}</p>
+
+ <gl-form-group>
+ <template #label>
+ <gl-sprintf :message="$options.i18n.modalInputLabel">
+ <template #name>
+ <code>{{ token.name }}</code>
+ </template>
+ </gl-sprintf>
+ </template>
+ <gl-form-input v-model="revokeConfirmText" @keydown.enter="revokeToken" />
+ </gl-form-group>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters/agents/components/show.vue b/app/assets/javascripts/clusters/agents/components/show.vue
index 5df3e0811a5..e3de8339325 100644
--- a/app/assets/javascripts/clusters/agents/components/show.vue
+++ b/app/assets/javascripts/clusters/agents/components/show.vue
@@ -140,7 +140,7 @@ export default {
</span>
</template>
- <gl-loading-icon v-if="isLoading" size="md" class="gl-m-3" />
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
<div v-else>
<token-table :tokens="tokens" :cluster-agent-id="clusterAgent.id" :cursor="cursor" />
diff --git a/app/assets/javascripts/clusters/agents/components/token_table.vue b/app/assets/javascripts/clusters/agents/components/token_table.vue
index fbb39c28d78..9e64c9da712 100644
--- a/app/assets/javascripts/clusters/agents/components/token_table.vue
+++ b/app/assets/javascripts/clusters/agents/components/token_table.vue
@@ -3,6 +3,7 @@ import { GlEmptyState, GlTable, GlTooltip, GlTruncate } from '@gitlab/ui';
import { s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import CreateTokenButton from './create_token_button.vue';
+import RevokeTokenButton from './revoke_token_button.vue';
export default {
components: {
@@ -12,6 +13,7 @@ export default {
GlTruncate,
TimeAgoTooltip,
CreateTokenButton,
+ RevokeTokenButton,
},
i18n: {
createdBy: s__('ClusterAgents|Created by'),
@@ -66,6 +68,11 @@ export default {
label: this.$options.i18n.description,
tdAttr: { 'data-testid': 'agent-token-description' },
},
+ {
+ key: 'actions',
+ label: '',
+ tdAttr: { 'data-testid': 'agent-token-revoke' },
+ },
];
},
},
@@ -119,6 +126,10 @@ export default {
</gl-tooltip>
</div>
</template>
+
+ <template #cell(actions)="{ item }">
+ <revoke-token-button :token="item" :cluster-agent-id="clusterAgentId" :cursor="cursor" />
+ </template>
</gl-table>
</div>
diff --git a/app/assets/javascripts/clusters/agents/constants.js b/app/assets/javascripts/clusters/agents/constants.js
index 50d8f5e9e40..962fa243903 100644
--- a/app/assets/javascripts/clusters/agents/constants.js
+++ b/app/assets/javascripts/clusters/agents/constants.js
@@ -44,3 +44,5 @@ export const EVENT_ACTIONS_OPEN = 'open_modal';
export const EVENT_ACTIONS_CLICK = 'click_button';
export const TOKEN_NAME_LIMIT = 255;
+
+export const REVOKE_TOKEN_MODAL_ID = 'revoke-token-%{tokenName}';
diff --git a/app/assets/javascripts/clusters/agents/graphql/cache_update.js b/app/assets/javascripts/clusters/agents/graphql/cache_update.js
index 0219c4150eb..8db79c82708 100644
--- a/app/assets/javascripts/clusters/agents/graphql/cache_update.js
+++ b/app/assets/javascripts/clusters/agents/graphql/cache_update.js
@@ -22,3 +22,25 @@ export function addAgentTokenToStore(store, clusterAgentTokenCreate, query, vari
});
}
}
+
+export function removeTokenFromStore(store, revokeToken, query, variables) {
+ if (!hasErrors(revokeToken)) {
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftData) => {
+ draftData.project.clusterAgent.tokens.nodes = draftData.project.clusterAgent.tokens.nodes.filter(
+ ({ id }) => id !== revokeToken.id,
+ );
+ draftData.project.clusterAgent.tokens.count -= 1;
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+ }
+}
diff --git a/app/assets/javascripts/clusters/agents/graphql/mutations/revoke_token.mutation.graphql b/app/assets/javascripts/clusters/agents/graphql/mutations/revoke_token.mutation.graphql
new file mode 100644
index 00000000000..6f1c6a66690
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/graphql/mutations/revoke_token.mutation.graphql
@@ -0,0 +1,5 @@
+mutation revokeAgentToken($input: ClusterAgentTokenRevokeInput!) {
+ clusterAgentTokenRevoke(input: $input) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/clusters/components/new_cluster.vue b/app/assets/javascripts/clusters/components/new_cluster.vue
index 8f3e2916270..41a33a8459f 100644
--- a/app/assets/javascripts/clusters/components/new_cluster.vue
+++ b/app/assets/javascripts/clusters/components/new_cluster.vue
@@ -1,6 +1,6 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
-import { mapState } from 'vuex';
+import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
export default {
@@ -10,13 +10,11 @@ export default {
'ClusterIntegration|Enter details about your cluster. %{linkStart}How do I use a certificate to connect to my cluster?%{linkEnd}',
),
},
+ clusterConnectHelpPath: helpPagePath('user/project/clusters/add_existing_cluster'),
components: {
GlLink,
GlSprintf,
},
- computed: {
- ...mapState(['clusterConnectHelpPath']),
- },
};
</script>
@@ -26,7 +24,7 @@ export default {
<p>
<gl-sprintf :message="$options.i18n.information">
<template #link="{ content }">
- <gl-link :href="clusterConnectHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.clusterConnectHelpPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index 98db620e3ab..dca89133931 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -159,7 +159,7 @@ export default {
)
}}</span>
<template #modal-footer>
- <gl-button variant="secondary" @click="handleCancel">{{ __('Cancel') }}</gl-button>
+ <gl-button @click="handleCancel">{{ __('Cancel') }}</gl-button>
<template v-if="confirmCleanup">
<gl-button
:disabled="!canSubmit"
diff --git a/app/assets/javascripts/clusters/forms/components/integration_form.vue b/app/assets/javascripts/clusters/forms/components/integration_form.vue
index 3f61a1b18a7..b2a8381f937 100644
--- a/app/assets/javascripts/clusters/forms/components/integration_form.vue
+++ b/app/assets/javascripts/clusters/forms/components/integration_form.vue
@@ -140,7 +140,7 @@ export default {
<div v-if="editable" class="form group gl-display-flex gl-justify-content-end">
<gl-button
category="primary"
- variant="success"
+ variant="confirm"
type="submit"
:disabled="!canSubmit"
:aria-disabled="!canSubmit"
diff --git a/app/assets/javascripts/clusters/gke_cluster_namespace/index.js b/app/assets/javascripts/clusters/gke_cluster_namespace/index.js
new file mode 100644
index 00000000000..2b3dfb99328
--- /dev/null
+++ b/app/assets/javascripts/clusters/gke_cluster_namespace/index.js
@@ -0,0 +1,37 @@
+/**
+ * Disables & hides the namespace inputs when the gitlab-managed checkbox is checked/unchecked.
+ */
+
+const setDisabled = (el, isDisabled) => {
+ if (isDisabled) {
+ el.classList.add('hidden');
+ el.querySelector('input').setAttribute('disabled', true);
+ } else {
+ el.classList.remove('hidden');
+ el.querySelector('input').removeAttribute('disabled');
+ }
+};
+
+const setState = (glManagedCheckbox) => {
+ const glManaged = document.querySelector('.js-namespace-prefixed');
+ const selfManaged = document.querySelector('.js-namespace');
+
+ if (glManagedCheckbox.checked) {
+ setDisabled(glManaged, false);
+ setDisabled(selfManaged, true);
+ } else {
+ setDisabled(glManaged, true);
+ setDisabled(selfManaged, false);
+ }
+};
+
+const initGkeNamespace = () => {
+ const glManagedCheckbox = document.querySelector('.js-gl-managed');
+
+ if (glManagedCheckbox) {
+ setState(glManagedCheckbox); // this is needed in order to set the initial state
+ glManagedCheckbox.addEventListener('change', () => setState(glManagedCheckbox));
+ }
+};
+
+export default initGkeNamespace;
diff --git a/app/assets/javascripts/clusters/new_cluster.js b/app/assets/javascripts/clusters/new_cluster.js
index 71f585fd307..4df6872bcc1 100644
--- a/app/assets/javascripts/clusters/new_cluster.js
+++ b/app/assets/javascripts/clusters/new_cluster.js
@@ -1,17 +1,15 @@
import Vue from 'vue';
import NewCluster from './components/new_cluster.vue';
-import { createStore } from './stores/new_cluster';
export default () => {
- const entryPoint = document.querySelector('#js-cluster-new');
+ const el = document.querySelector('#js-cluster-new');
- if (!entryPoint) {
+ if (!el) {
return null;
}
return new Vue({
- el: '#js-cluster-new',
- store: createStore(entryPoint.dataset),
+ el,
render(createElement) {
return createElement(NewCluster);
},
diff --git a/app/assets/javascripts/clusters/stores/new_cluster/index.js b/app/assets/javascripts/clusters/stores/new_cluster/index.js
deleted file mode 100644
index 87f1c05fdf9..00000000000
--- a/app/assets/javascripts/clusters/stores/new_cluster/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import state from './state';
-
-Vue.use(Vuex);
-
-export const createStore = (initialState) =>
- new Vuex.Store({
- state: state(initialState),
- });
-
-export default createStore;
diff --git a/app/assets/javascripts/clusters/stores/new_cluster/state.js b/app/assets/javascripts/clusters/stores/new_cluster/state.js
deleted file mode 100644
index 1ca1ac8de18..00000000000
--- a/app/assets/javascripts/clusters/stores/new_cluster/state.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default (initialState = {}) => ({
- clusterConnectHelpPath: initialState.clusterConnectHelpPath,
-});