2021-02-14 13:09:20 -05:00
|
|
|
import { GlToast } from '@gitlab/ui';
|
2017-10-24 00:56:39 -04:00
|
|
|
import Visibility from 'visibilityjs';
|
|
|
|
import Vue from 'vue';
|
2021-06-21 23:07:55 -04:00
|
|
|
import createFlash from '~/flash';
|
2019-12-09 07:07:58 -05:00
|
|
|
import AccessorUtilities from '~/lib/utils/accessor';
|
2021-02-01 10:08:56 -05:00
|
|
|
import initProjectSelectDropdown from '~/project_select';
|
2022-03-31 08:08:17 -04:00
|
|
|
import Poll from '~/lib/utils/poll';
|
|
|
|
import { s__ } from '~/locale';
|
|
|
|
import PersistentUserCallout from '~/persistent_user_callout';
|
|
|
|
import initSettingsPanels from '~/settings_panels';
|
2021-02-14 13:09:20 -05:00
|
|
|
import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
|
2017-10-24 00:56:39 -04:00
|
|
|
import ClustersService from './services/clusters_service';
|
|
|
|
import ClustersStore from './stores/clusters_store';
|
|
|
|
|
2019-09-04 13:03:05 -04:00
|
|
|
const Environments = () => import('ee_component/clusters/components/environments.vue');
|
|
|
|
|
2019-04-25 10:50:57 -04:00
|
|
|
Vue.use(GlToast);
|
|
|
|
|
2017-10-24 00:56:39 -04:00
|
|
|
export default class Clusters {
|
|
|
|
constructor() {
|
|
|
|
const {
|
|
|
|
statusPath,
|
2019-09-13 09:26:31 -04:00
|
|
|
clusterEnvironmentsPath,
|
2018-12-13 10:39:44 -05:00
|
|
|
hasRbac,
|
2019-09-22 20:06:29 -04:00
|
|
|
providerType,
|
2017-10-24 00:56:39 -04:00
|
|
|
clusterStatus,
|
|
|
|
clusterStatusReason,
|
|
|
|
helpPath,
|
2019-09-04 13:03:05 -04:00
|
|
|
environmentsHelpPath,
|
|
|
|
clustersHelpPath,
|
|
|
|
deployBoardsHelpPath,
|
2019-05-27 04:23:17 -04:00
|
|
|
clusterId,
|
2017-10-24 00:56:39 -04:00
|
|
|
} = document.querySelector('.js-edit-cluster-form').dataset;
|
|
|
|
|
2019-05-27 04:23:17 -04:00
|
|
|
this.clusterId = clusterId;
|
2019-08-02 16:08:53 -04:00
|
|
|
this.clusterNewlyCreatedKey = `cluster_${this.clusterId}_newly_created`;
|
|
|
|
this.clusterBannerDismissedKey = `cluster_${this.clusterId}_banner_dismissed`;
|
|
|
|
|
2017-10-24 00:56:39 -04:00
|
|
|
this.store = new ClustersStore();
|
2020-11-18 04:09:02 -05:00
|
|
|
this.store.setHelpPaths({
|
2019-09-04 13:03:05 -04:00
|
|
|
helpPath,
|
|
|
|
environmentsHelpPath,
|
|
|
|
clustersHelpPath,
|
|
|
|
deployBoardsHelpPath,
|
2020-11-18 04:09:02 -05:00
|
|
|
});
|
2017-10-24 00:56:39 -04:00
|
|
|
this.store.updateStatus(clusterStatus);
|
|
|
|
this.store.updateStatusReason(clusterStatusReason);
|
2019-09-22 20:06:29 -04:00
|
|
|
this.store.updateProviderType(providerType);
|
2018-12-13 10:39:44 -05:00
|
|
|
this.store.updateRbac(hasRbac);
|
2017-10-24 00:56:39 -04:00
|
|
|
this.service = new ClustersService({
|
|
|
|
endpoint: statusPath,
|
2019-09-13 09:26:31 -04:00
|
|
|
clusterEnvironmentsEndpoint: clusterEnvironmentsPath,
|
2017-10-24 00:56:39 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
this.errorContainer = document.querySelector('.js-cluster-error');
|
|
|
|
this.successContainer = document.querySelector('.js-cluster-success');
|
|
|
|
this.creatingContainer = document.querySelector('.js-cluster-creating');
|
2019-05-27 04:23:17 -04:00
|
|
|
this.unreachableContainer = document.querySelector('.js-cluster-api-unreachable');
|
|
|
|
this.authenticationFailureContainer = document.querySelector(
|
|
|
|
'.js-cluster-authentication-failure',
|
|
|
|
);
|
2017-10-24 00:56:39 -04:00
|
|
|
this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason');
|
2017-11-09 06:47:08 -05:00
|
|
|
this.tokenField = document.querySelector('.js-cluster-token');
|
2017-10-24 00:56:39 -04:00
|
|
|
|
2019-11-04 04:06:21 -05:00
|
|
|
initProjectSelectDropdown();
|
2018-12-06 08:41:20 -05:00
|
|
|
Clusters.initDismissableCallout();
|
2017-10-24 00:56:39 -04:00
|
|
|
initSettingsPanels();
|
2019-11-04 04:06:21 -05:00
|
|
|
|
2019-09-04 13:03:05 -04:00
|
|
|
this.initEnvironments();
|
2017-10-24 00:56:39 -04:00
|
|
|
|
2019-09-18 10:02:45 -04:00
|
|
|
if (clusterEnvironmentsPath && this.environments) {
|
|
|
|
this.store.toggleFetchEnvironments(true);
|
|
|
|
|
|
|
|
this.initPolling(
|
|
|
|
'fetchClusterEnvironments',
|
2020-12-23 16:10:24 -05:00
|
|
|
(data) => this.handleClusterEnvironmentsSuccess(data),
|
2019-09-18 10:02:45 -04:00
|
|
|
() => this.handleEnvironmentsPollError(),
|
|
|
|
);
|
2019-09-13 09:26:31 -04:00
|
|
|
}
|
|
|
|
|
2019-08-02 16:08:53 -04:00
|
|
|
this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
|
2017-10-24 00:56:39 -04:00
|
|
|
|
|
|
|
this.addListeners();
|
2019-09-04 13:03:05 -04:00
|
|
|
if (statusPath && !this.environments) {
|
2019-09-18 10:02:45 -04:00
|
|
|
this.initPolling(
|
|
|
|
'fetchClusterStatus',
|
2020-12-23 16:10:24 -05:00
|
|
|
(data) => this.handleClusterStatusSuccess(data),
|
2019-09-18 10:02:45 -04:00
|
|
|
() => this.handlePollError(),
|
|
|
|
);
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
2019-12-17 04:07:48 -05:00
|
|
|
|
|
|
|
this.initRemoveClusterActions();
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
|
2019-09-04 13:03:05 -04:00
|
|
|
initEnvironments() {
|
|
|
|
const { store } = this;
|
|
|
|
const el = document.querySelector('#js-cluster-environments');
|
|
|
|
|
|
|
|
if (!el) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.environments = new Vue({
|
|
|
|
el,
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
state: store.state,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
render(createElement) {
|
|
|
|
return createElement(Environments, {
|
|
|
|
props: {
|
2019-09-13 09:26:31 -04:00
|
|
|
isFetching: this.state.fetchingEnvironments,
|
2019-09-04 13:03:05 -04:00
|
|
|
environments: this.state.environments,
|
|
|
|
environmentsHelpPath: this.state.environmentsHelpPath,
|
|
|
|
clustersHelpPath: this.state.clustersHelpPath,
|
|
|
|
deployBoardsHelpPath: this.state.deployBoardsHelpPath,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-17 04:07:48 -05:00
|
|
|
initRemoveClusterActions() {
|
|
|
|
const el = document.querySelector('#js-cluster-remove-actions');
|
|
|
|
if (el && el.dataset) {
|
2020-07-07 08:09:16 -04:00
|
|
|
const { clusterName, clusterPath, hasManagementProject } = el.dataset;
|
2019-12-17 04:07:48 -05:00
|
|
|
|
|
|
|
this.removeClusterAction = new Vue({
|
|
|
|
el,
|
|
|
|
render(createElement) {
|
|
|
|
return createElement(RemoveClusterConfirmation, {
|
|
|
|
props: {
|
|
|
|
clusterName,
|
|
|
|
clusterPath,
|
2020-07-07 08:09:16 -04:00
|
|
|
hasManagementProject,
|
2019-12-17 04:07:48 -05:00
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-18 10:02:45 -04:00
|
|
|
handleClusterEnvironmentsSuccess(data) {
|
|
|
|
this.store.toggleFetchEnvironments(false);
|
|
|
|
this.store.updateEnvironments(data.data);
|
2019-09-13 09:26:31 -04:00
|
|
|
}
|
|
|
|
|
2018-12-06 08:41:20 -05:00
|
|
|
static initDismissableCallout() {
|
|
|
|
const callout = document.querySelector('.js-cluster-security-warning');
|
2019-02-21 01:05:09 -05:00
|
|
|
PersistentUserCallout.factory(callout);
|
2018-12-06 08:41:20 -05:00
|
|
|
}
|
|
|
|
|
2019-05-27 04:23:17 -04:00
|
|
|
addBannerCloseHandler(el, status) {
|
2020-09-04 05:08:38 -04:00
|
|
|
el.querySelector('.js-close').addEventListener('click', () => {
|
2019-05-27 04:23:17 -04:00
|
|
|
el.classList.add('hidden');
|
|
|
|
this.setBannerDismissedState(status, true);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-24 00:56:39 -04:00
|
|
|
addListeners() {
|
2019-05-27 04:23:17 -04:00
|
|
|
// Add event listener to all the banner close buttons
|
|
|
|
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
|
|
|
|
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
|
2019-09-18 10:02:45 -04:00
|
|
|
initPolling(method, successCallback, errorCallback) {
|
2017-10-24 00:56:39 -04:00
|
|
|
this.poll = new Poll({
|
|
|
|
resource: this.service,
|
2019-09-18 10:02:45 -04:00
|
|
|
method,
|
|
|
|
successCallback,
|
|
|
|
errorCallback,
|
2017-10-24 00:56:39 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
if (!Visibility.hidden()) {
|
|
|
|
this.poll.makeRequest();
|
|
|
|
}
|
|
|
|
|
|
|
|
Visibility.change(() => {
|
|
|
|
if (!Visibility.hidden() && !this.destroyed) {
|
|
|
|
this.poll.restart();
|
|
|
|
} else {
|
|
|
|
this.poll.stop();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-18 10:02:45 -04:00
|
|
|
handlePollError() {
|
|
|
|
this.constructor.handleError();
|
|
|
|
}
|
|
|
|
|
|
|
|
handleEnvironmentsPollError() {
|
|
|
|
this.store.toggleFetchEnvironments(false);
|
|
|
|
|
|
|
|
this.handlePollError();
|
|
|
|
}
|
|
|
|
|
2017-10-24 00:56:39 -04:00
|
|
|
static handleError() {
|
2021-06-17 20:10:29 -04:00
|
|
|
createFlash({
|
|
|
|
message: s__('ClusterIntegration|Something went wrong on our end.'),
|
|
|
|
});
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
|
2019-09-18 10:02:45 -04:00
|
|
|
handleClusterStatusSuccess(data) {
|
2017-11-06 09:48:44 -05:00
|
|
|
const prevStatus = this.store.state.status;
|
2017-11-06 11:07:19 -05:00
|
|
|
|
2017-10-24 00:56:39 -04:00
|
|
|
this.store.updateStateFromServer(data.data);
|
2017-11-06 11:07:19 -05:00
|
|
|
|
|
|
|
this.updateContainer(prevStatus, this.store.state.status, this.store.state.statusReason);
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
hideAll() {
|
|
|
|
this.errorContainer.classList.add('hidden');
|
|
|
|
this.successContainer.classList.add('hidden');
|
|
|
|
this.creatingContainer.classList.add('hidden');
|
2019-05-27 04:23:17 -04:00
|
|
|
this.unreachableContainer.classList.add('hidden');
|
|
|
|
this.authenticationFailureContainer.classList.add('hidden');
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
|
2019-05-27 04:23:17 -04:00
|
|
|
setBannerDismissedState(status, isDismissed) {
|
2021-09-16 14:11:32 -04:00
|
|
|
if (AccessorUtilities.canUseLocalStorage()) {
|
2019-08-02 16:08:53 -04:00
|
|
|
window.localStorage.setItem(this.clusterBannerDismissedKey, `${status}_${isDismissed}`);
|
2019-05-27 04:23:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isBannerDismissed(status) {
|
|
|
|
let bannerState;
|
2021-09-16 14:11:32 -04:00
|
|
|
if (AccessorUtilities.canUseLocalStorage()) {
|
2019-08-02 16:08:53 -04:00
|
|
|
bannerState = window.localStorage.getItem(this.clusterBannerDismissedKey);
|
2019-05-27 04:23:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return bannerState === `${status}_true`;
|
|
|
|
}
|
|
|
|
|
2019-08-02 16:08:53 -04:00
|
|
|
setClusterNewlyCreated(state) {
|
2021-09-16 14:11:32 -04:00
|
|
|
if (AccessorUtilities.canUseLocalStorage()) {
|
2019-08-02 16:08:53 -04:00
|
|
|
window.localStorage.setItem(this.clusterNewlyCreatedKey, Boolean(state));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isClusterNewlyCreated() {
|
|
|
|
// once this is true, it will always be true for a given page load
|
|
|
|
if (!this.isNewlyCreated) {
|
|
|
|
let newlyCreated;
|
2021-09-16 14:11:32 -04:00
|
|
|
if (AccessorUtilities.canUseLocalStorage()) {
|
2019-08-02 16:08:53 -04:00
|
|
|
newlyCreated = window.localStorage.getItem(this.clusterNewlyCreatedKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.isNewlyCreated = newlyCreated === 'true';
|
|
|
|
}
|
|
|
|
return this.isNewlyCreated;
|
|
|
|
}
|
2017-11-06 11:07:19 -05:00
|
|
|
|
2019-08-02 16:08:53 -04:00
|
|
|
updateContainer(prevStatus, status, error) {
|
|
|
|
if (status !== 'created' && this.isBannerDismissed(status)) {
|
2019-05-27 04:23:17 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.setBannerDismissedState(status, false);
|
|
|
|
|
2019-08-02 16:08:53 -04:00
|
|
|
if (prevStatus !== status) {
|
|
|
|
this.hideAll();
|
|
|
|
|
2017-11-06 11:07:19 -05:00
|
|
|
switch (status) {
|
|
|
|
case 'created':
|
2019-08-02 16:08:53 -04:00
|
|
|
if (this.isClusterNewlyCreated()) {
|
|
|
|
this.setClusterNewlyCreated(false);
|
|
|
|
this.successContainer.classList.remove('hidden');
|
|
|
|
} else if (prevStatus) {
|
|
|
|
this.setClusterNewlyCreated(true);
|
|
|
|
window.location.reload();
|
|
|
|
}
|
2017-11-06 11:07:19 -05:00
|
|
|
break;
|
|
|
|
case 'errored':
|
|
|
|
this.errorContainer.classList.remove('hidden');
|
|
|
|
this.errorReasonContainer.textContent = error;
|
|
|
|
break;
|
2019-05-27 04:23:17 -04:00
|
|
|
case 'unreachable':
|
|
|
|
this.unreachableContainer.classList.remove('hidden');
|
|
|
|
break;
|
|
|
|
case 'authentication_failure':
|
|
|
|
this.authenticationFailureContainer.classList.remove('hidden');
|
|
|
|
break;
|
2017-11-06 11:07:19 -05:00
|
|
|
case 'scheduled':
|
|
|
|
case 'creating':
|
|
|
|
this.creatingContainer.classList.remove('hidden');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
}
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
destroy() {
|
|
|
|
this.destroyed = true;
|
|
|
|
|
|
|
|
if (this.poll) {
|
|
|
|
this.poll.stop();
|
|
|
|
}
|
|
|
|
|
2019-09-04 13:03:05 -04:00
|
|
|
if (this.environments) {
|
|
|
|
this.environments.$destroy();
|
|
|
|
}
|
2017-10-24 00:56:39 -04:00
|
|
|
}
|
|
|
|
}
|