summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/clusters
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/clusters')
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js221
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue478
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue662
-rw-r--r--app/assets/javascripts/clusters/components/crossplane_provider_stack.vue93
-rw-r--r--app/assets/javascripts/clusters/components/knative_domain_editor.vue232
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_button.vue36
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue101
-rw-r--r--app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue66
-rw-r--r--app/assets/javascripts/clusters/constants.js57
-rw-r--r--app/assets/javascripts/clusters/services/application_state_machine.js250
-rw-r--r--app/assets/javascripts/clusters/services/clusters_service.js26
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js207
12 files changed, 5 insertions, 2424 deletions
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index 762b37a8216..c2c035963f4 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,18 +1,14 @@
import { GlToast } from '@gitlab/ui';
import Visibility from 'visibilityjs';
import Vue from 'vue';
+import createFlash from '~/flash';
import AccessorUtilities from '~/lib/utils/accessor';
import initProjectSelectDropdown from '~/project_select';
-import initServerlessSurveyBanner from '~/serverless/survey_banner';
-import { deprecatedCreateFlash as Flash } from '../flash';
import Poll from '../lib/utils/poll';
-import { s__, sprintf } from '../locale';
+import { s__ } from '../locale';
import PersistentUserCallout from '../persistent_user_callout';
import initSettingsPanels from '../settings_panels';
-import Applications from './components/applications.vue';
import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
-import { APPLICATION_STATUS, CROSSPLANE, KNATIVE } from './constants';
-import eventHub from './event_hub';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
@@ -20,46 +16,20 @@ const Environments = () => import('ee_component/clusters/components/environments
Vue.use(GlToast);
-/**
- * Cluster page has 2 separate parts:
- * Toggle button and applications section
- *
- * - Polling status while creating or scheduled
- * - Update status area with the response result
- */
-
export default class Clusters {
constructor() {
const {
statusPath,
- installHelmPath,
- installIngressPath,
- installCertManagerPath,
- installRunnerPath,
- installJupyterPath,
- installKnativePath,
- updateKnativePath,
- installElasticStackPath,
- installCrossplanePath,
- installPrometheusPath,
- managePrometheusPath,
clusterEnvironmentsPath,
hasRbac,
providerType,
- preInstalledKnative,
- clusterType,
clusterStatus,
clusterStatusReason,
helpPath,
- helmHelpPath,
- ingressHelpPath,
- ingressDnsHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
- cloudRunHelpPath,
clusterId,
- ciliumHelpPath,
} = document.querySelector('.js-edit-cluster-form').dataset;
this.clusterId = clusterId;
@@ -69,38 +39,19 @@ export default class Clusters {
this.store = new ClustersStore();
this.store.setHelpPaths({
helpPath,
- helmHelpPath,
- ingressHelpPath,
- ingressDnsHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
- cloudRunHelpPath,
- ciliumHelpPath,
});
- this.store.setManagePrometheusPath(managePrometheusPath);
this.store.updateStatus(clusterStatus);
this.store.updateStatusReason(clusterStatusReason);
this.store.updateProviderType(providerType);
- this.store.updatePreInstalledKnative(preInstalledKnative);
this.store.updateRbac(hasRbac);
this.service = new ClustersService({
endpoint: statusPath,
- installHelmEndpoint: installHelmPath,
- installIngressEndpoint: installIngressPath,
- installCertManagerEndpoint: installCertManagerPath,
- installCrossplaneEndpoint: installCrossplanePath,
- installRunnerEndpoint: installRunnerPath,
- installPrometheusEndpoint: installPrometheusPath,
- installJupyterEndpoint: installJupyterPath,
- installKnativeEndpoint: installKnativePath,
- updateKnativeEndpoint: updateKnativePath,
- installElasticStackEndpoint: installElasticStackPath,
clusterEnvironmentsEndpoint: clusterEnvironmentsPath,
});
- this.installApplication = this.installApplication.bind(this);
-
this.errorContainer = document.querySelector('.js-cluster-error');
this.successContainer = document.querySelector('.js-cluster-success');
this.creatingContainer = document.querySelector('.js-cluster-creating');
@@ -109,14 +60,12 @@ export default class Clusters {
'.js-cluster-authentication-failure',
);
this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason');
- this.successApplicationContainer = document.querySelector('.js-cluster-application-notice');
this.tokenField = document.querySelector('.js-cluster-token');
initProjectSelectDropdown();
Clusters.initDismissableCallout();
initSettingsPanels();
- this.initApplications(clusterType);
this.initEnvironments();
if (clusterEnvironmentsPath && this.environments) {
@@ -143,38 +92,6 @@ export default class Clusters {
this.initRemoveClusterActions();
}
- initApplications(type) {
- const { store } = this;
- const el = document.querySelector('#js-cluster-applications');
-
- this.applications = new Vue({
- el,
- data() {
- return {
- state: store.state,
- };
- },
- render(createElement) {
- return createElement(Applications, {
- props: {
- type,
- applications: this.state.applications,
- helpPath: this.state.helpPath,
- helmHelpPath: this.state.helmHelpPath,
- ingressHelpPath: this.state.ingressHelpPath,
- managePrometheusPath: this.state.managePrometheusPath,
- ingressDnsHelpPath: this.state.ingressDnsHelpPath,
- cloudRunHelpPath: this.state.cloudRunHelpPath,
- providerType: this.state.providerType,
- preInstalledKnative: this.state.preInstalledKnative,
- rbac: this.state.rbac,
- ciliumHelpPath: this.state.ciliumHelpPath,
- },
- });
- },
- });
- }
-
initEnvironments() {
const { store } = this;
const el = document.querySelector('#js-cluster-environments');
@@ -242,30 +159,11 @@ export default class Clusters {
}
addListeners() {
- eventHub.$on('installApplication', this.installApplication);
- eventHub.$on('updateApplication', (data) => this.updateApplication(data));
- eventHub.$on('saveKnativeDomain', (data) => this.saveKnativeDomain(data));
- eventHub.$on('setKnativeDomain', (data) => this.setKnativeDomain(data));
- eventHub.$on('uninstallApplication', (data) => this.uninstallApplication(data));
- eventHub.$on('setCrossplaneProviderStack', (data) => this.setCrossplaneProviderStack(data));
// Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
}
- removeListeners() {
- eventHub.$off('installApplication', this.installApplication);
- eventHub.$off('updateApplication', this.updateApplication);
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('saveKnativeDomain');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('setKnativeDomain');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('setCrossplaneProviderStack');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('uninstallApplication');
- }
-
initPolling(method, successCallback, errorCallback) {
this.poll = new Poll({
resource: this.service,
@@ -298,21 +196,17 @@ export default class Clusters {
}
static handleError() {
- Flash(s__('ClusterIntegration|Something went wrong on our end.'));
+ createFlash({
+ message: s__('ClusterIntegration|Something went wrong on our end.'),
+ });
}
handleClusterStatusSuccess(data) {
const prevStatus = this.store.state.status;
- const prevApplicationMap = { ...this.store.state.applications };
this.store.updateStateFromServer(data.data);
- this.checkForNewInstalls(prevApplicationMap, this.store.state.applications);
this.updateContainer(prevStatus, this.store.state.status, this.store.state.statusReason);
-
- if (this.store.state.applications[KNATIVE]?.status === APPLICATION_STATUS.INSTALLED) {
- initServerlessSurveyBanner();
- }
}
hideAll() {
@@ -323,27 +217,6 @@ export default class Clusters {
this.authenticationFailureContainer.classList.add('hidden');
}
- checkForNewInstalls(prevApplicationMap, newApplicationMap) {
- const appTitles = Object.keys(newApplicationMap)
- .filter(
- (appId) =>
- newApplicationMap[appId].status === APPLICATION_STATUS.INSTALLED &&
- prevApplicationMap[appId].status !== APPLICATION_STATUS.INSTALLED &&
- prevApplicationMap[appId].status !== null,
- )
- .map((appId) => newApplicationMap[appId].title);
-
- if (appTitles.length > 0) {
- const text = sprintf(
- s__('ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster'),
- {
- appList: appTitles.join(', '),
- },
- );
- Flash(text, 'notice', this.successApplicationContainer);
- }
- }
-
setBannerDismissedState(status, isDismissed) {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
window.localStorage.setItem(this.clusterBannerDismissedKey, `${status}_${isDismissed}`);
@@ -416,91 +289,9 @@ export default class Clusters {
}
}
- installApplication({ id: appId, params }) {
- return Clusters.validateInstallation(appId, params)
- .then(() => {
- this.store.updateAppProperty(appId, 'requestReason', null);
- this.store.updateAppProperty(appId, 'statusReason', null);
- this.store.installApplication(appId);
-
- // eslint-disable-next-line promise/no-nesting
- this.service.installApplication(appId, params).catch(() => {
- this.store.notifyInstallFailure(appId);
- this.store.updateAppProperty(
- appId,
- 'requestReason',
- s__('ClusterIntegration|Request to begin installing failed'),
- );
- });
- })
- .catch((error) => this.store.updateAppProperty(appId, 'validationError', error));
- }
-
- static validateInstallation(appId, params) {
- return new Promise((resolve, reject) => {
- if (appId === CROSSPLANE && !params.stack) {
- reject(s__('ClusterIntegration|Select a stack to install Crossplane.'));
- return;
- }
-
- if (appId === KNATIVE && !params.hostname && !params.pages_domain_id) {
- reject(s__('ClusterIntegration|You must specify a domain before you can install Knative.'));
- return;
- }
-
- resolve();
- });
- }
-
- uninstallApplication({ id: appId }) {
- this.store.updateAppProperty(appId, 'requestReason', null);
- this.store.updateAppProperty(appId, 'statusReason', null);
-
- this.store.uninstallApplication(appId);
-
- return this.service.uninstallApplication(appId).catch(() => {
- this.store.notifyUninstallFailure(appId);
- this.store.updateAppProperty(
- appId,
- 'requestReason',
- s__('ClusterIntegration|Request to begin uninstalling failed'),
- );
- });
- }
-
- updateApplication({ id: appId, params }) {
- this.store.updateApplication(appId);
- this.service.installApplication(appId, params).catch(() => {
- this.store.notifyUpdateFailure(appId);
- });
- }
-
- saveKnativeDomain(data) {
- const appId = data.id;
- this.store.updateApplication(appId);
- this.service.updateApplication(appId, data.params).catch(() => {
- this.store.notifyUpdateFailure(appId);
- });
- }
-
- setKnativeDomain({ id: appId, domain, domainId }) {
- this.store.updateAppProperty(appId, 'isEditingDomain', true);
- this.store.updateAppProperty(appId, 'hostname', domain);
- this.store.updateAppProperty(appId, 'pagesDomain', domainId ? { id: domainId, domain } : null);
- this.store.updateAppProperty(appId, 'validationError', null);
- }
-
- setCrossplaneProviderStack(data) {
- const appId = data.id;
- this.store.updateAppProperty(appId, 'stack', data.stack.code);
- this.store.updateAppProperty(appId, 'validationError', null);
- }
-
destroy() {
this.destroyed = true;
- this.removeListeners();
-
if (this.poll) {
this.poll.stop();
}
@@ -508,7 +299,5 @@ export default class Clusters {
if (this.environments) {
this.environments.$destroy();
}
-
- this.applications.$destroy();
}
}
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
deleted file mode 100644
index a53b63ea592..00000000000
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ /dev/null
@@ -1,478 +0,0 @@
-<script>
-import { GlLink, GlModalDirective, GlSprintf, GlButton, GlAlert } from '@gitlab/ui';
-import { s__, __, sprintf } from '~/locale';
-import identicon from '../../vue_shared/components/identicon.vue';
-import { APPLICATION_STATUS, ELASTIC_STACK } from '../constants';
-import eventHub from '../event_hub';
-import UninstallApplicationButton from './uninstall_application_button.vue';
-import UninstallApplicationConfirmationModal from './uninstall_application_confirmation_modal.vue';
-import UpdateApplicationConfirmationModal from './update_application_confirmation_modal.vue';
-
-export default {
- components: {
- GlButton,
- identicon,
- GlLink,
- GlAlert,
- GlSprintf,
- UninstallApplicationButton,
- UninstallApplicationConfirmationModal,
- UpdateApplicationConfirmationModal,
- },
- directives: {
- GlModalDirective,
- },
- props: {
- id: {
- type: String,
- required: true,
- },
- title: {
- type: String,
- required: true,
- },
- titleLink: {
- type: String,
- required: false,
- default: '',
- },
- manageLink: {
- type: String,
- required: false,
- default: '',
- },
- logoUrl: {
- type: String,
- required: false,
- default: '',
- },
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- installable: {
- type: Boolean,
- required: false,
- default: true,
- },
- uninstallable: {
- type: Boolean,
- required: false,
- default: false,
- },
- status: {
- type: String,
- required: false,
- default: '',
- },
- statusReason: {
- type: String,
- required: false,
- default: '',
- },
- requestReason: {
- type: String,
- required: false,
- default: '',
- },
- installed: {
- type: Boolean,
- required: false,
- default: false,
- },
- installFailed: {
- type: Boolean,
- required: false,
- default: false,
- },
- version: {
- type: String,
- required: false,
- default: '',
- },
- chartRepo: {
- type: String,
- required: false,
- default: '',
- },
- updateAvailable: {
- type: Boolean,
- required: false,
- },
- updateable: {
- type: Boolean,
- default: true,
- required: false,
- },
- updateSuccessful: {
- type: Boolean,
- required: false,
- default: false,
- },
- updateFailed: {
- type: Boolean,
- required: false,
- default: false,
- },
- uninstallFailed: {
- type: Boolean,
- required: false,
- default: false,
- },
- uninstallSuccessful: {
- type: Boolean,
- required: false,
- default: false,
- },
- installApplicationRequestParams: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- },
- computed: {
- isUnknownStatus() {
- return !this.isKnownStatus && this.status !== null;
- },
- isKnownStatus() {
- return Object.values(APPLICATION_STATUS).includes(this.status);
- },
- isInstalling() {
- return this.status === APPLICATION_STATUS.INSTALLING;
- },
- isExternallyInstalled() {
- return this.status === APPLICATION_STATUS.EXTERNALLY_INSTALLED;
- },
- canInstall() {
- return (
- this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
- this.status === APPLICATION_STATUS.INSTALLABLE ||
- this.status === APPLICATION_STATUS.UNINSTALLED ||
- this.isUnknownStatus
- );
- },
- hasLogo() {
- return Boolean(this.logoUrl);
- },
- identiconId() {
- // generate a deterministic integer id for the identicon background
- return this.id.charCodeAt(0);
- },
- rowJsClass() {
- return `js-cluster-application-row-${this.id}`;
- },
- displayUninstallButton() {
- return this.installed && this.uninstallable;
- },
- displayInstallButton() {
- return !this.installed || !this.uninstallable;
- },
- installButtonLoading() {
- return !this.status || this.isInstalling;
- },
- installButtonDisabled() {
- // Applications installed through the management project can
- // only be installed through the CI pipeline. Installation should
- // be disable in all states.
- if (!this.installable) return true;
-
- // Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but
- // we already made a request to install and are just waiting for the real-time
- // to sync up.
- if (this.isInstalling) return true;
-
- if (!this.isKnownStatus) return false;
-
- return (
- this.status !== APPLICATION_STATUS.INSTALLABLE && this.status !== APPLICATION_STATUS.ERROR
- );
- },
- installButtonLabel() {
- let label;
- if (this.canInstall) {
- label = __('Install');
- } else if (this.isInstalling) {
- label = __('Installing');
- } else if (this.installed) {
- label = __('Installed');
- } else if (this.isExternallyInstalled) {
- label = __('Externally installed');
- }
-
- return label;
- },
- buttonGridCellClass() {
- return this.showManageButton || this.status === APPLICATION_STATUS.EXTERNALLY_INSTALLED
- ? 'section-25'
- : 'section-15';
- },
- showManageButton() {
- return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
- },
- manageButtonLabel() {
- return __('Manage');
- },
- hasError() {
- return this.installFailed || this.uninstallFailed;
- },
- generalErrorDescription() {
- let errorDescription;
-
- if (this.installFailed) {
- errorDescription = s__('ClusterIntegration|Something went wrong while installing %{title}');
- } else if (this.uninstallFailed) {
- errorDescription = s__(
- 'ClusterIntegration|Something went wrong while uninstalling %{title}',
- );
- }
-
- return sprintf(errorDescription, { title: this.title });
- },
- updateFailureDescription() {
- return s__('ClusterIntegration|Update failed. Please check the logs and try again.');
- },
- updateSuccessDescription() {
- return sprintf(s__('ClusterIntegration|%{title} updated successfully.'), {
- title: this.title,
- });
- },
- updateButtonLabel() {
- let label;
- if (this.updateAvailable && !this.updateFailed && !this.isUpdating) {
- label = __('Update');
- } else if (this.isUpdating) {
- label = __('Updating');
- } else if (this.updateFailed) {
- label = __('Retry update');
- }
-
- return label;
- },
- updatingNeedsConfirmation() {
- if (this.version) {
- const majorVersion = parseInt(this.version.split('.')[0], 10);
-
- if (!Number.isNaN(majorVersion)) {
- return this.id === ELASTIC_STACK && majorVersion < 3;
- }
- }
-
- return false;
- },
- isUpdating() {
- // Since upgrading is handled asynchronously on the backend we need this check to prevent any delay on the frontend
- return this.status === APPLICATION_STATUS.UPDATING;
- },
- shouldShowUpdateDetails() {
- // This method only returns true when;
- // Update was successful OR Update failed
- // AND new update is unavailable AND version information is present.
- return (this.updateSuccessful || this.updateFailed) && !this.updateAvailable && this.version;
- },
- uninstallSuccessDescription() {
- return sprintf(s__('ClusterIntegration|%{title} uninstalled successfully.'), {
- title: this.title,
- });
- },
- updateModalId() {
- return `update-${this.id}`;
- },
- uninstallModalId() {
- return `uninstall-${this.id}`;
- },
- },
- watch: {
- updateSuccessful(updateSuccessful) {
- if (updateSuccessful) {
- this.$toast.show(this.updateSuccessDescription);
- }
- },
- uninstallSuccessful(uninstallSuccessful) {
- if (uninstallSuccessful) {
- this.$toast.show(this.uninstallSuccessDescription);
- }
- },
- },
- methods: {
- installClicked() {
- if (this.disabled || this.installButtonDisabled) return;
-
- eventHub.$emit('installApplication', {
- id: this.id,
- params: this.installApplicationRequestParams,
- });
- },
- updateConfirmed() {
- if (this.isUpdating) return;
-
- eventHub.$emit('updateApplication', {
- id: this.id,
- params: this.installApplicationRequestParams,
- });
- },
- uninstallConfirmed() {
- eventHub.$emit('uninstallApplication', {
- id: this.id,
- });
- },
- },
-};
-</script>
-
-<template>
- <div
- :class="[
- rowJsClass,
- installed && 'cluster-application-installed',
- disabled && 'cluster-application-disabled',
- ]"
- class="cluster-application-row gl-responsive-table-row gl-responsive-table-row-col-span"
- :data-qa-selector="id"
- >
- <div class="gl-responsive-table-row-layout" role="row">
- <div class="table-section gl-mr-3 section-align-top" role="gridcell">
- <img
- v-if="hasLogo"
- :src="logoUrl"
- :alt="`${title} logo`"
- class="cluster-application-logo avatar s40"
- />
- <identicon v-else :entity-id="identiconId" :entity-name="title" size-class="s40" />
- </div>
- <div class="table-section cluster-application-description section-wrap" role="gridcell">
- <strong>
- <a
- v-if="titleLink"
- :href="titleLink"
- target="_blank"
- rel="noopener noreferrer"
- class="js-cluster-application-title"
- >{{ title }}</a
- >
- <span v-else class="js-cluster-application-title">{{ title }}</span>
- </strong>
- <slot name="installed-via"></slot>
- <div>
- <slot name="description"></slot>
- </div>
- <div v-if="hasError" class="cluster-application-error text-danger gl-mt-3">
- <p class="js-cluster-application-general-error-message gl-mb-0">
- {{ generalErrorDescription }}
- </p>
- <ul v-if="statusReason || requestReason">
- <li v-if="statusReason" class="js-cluster-application-status-error-message">
- {{ statusReason }}
- </li>
- <li v-if="requestReason" class="js-cluster-application-request-error-message">
- {{ requestReason }}
- </li>
- </ul>
- </div>
-
- <div v-if="updateable">
- <div
- v-if="shouldShowUpdateDetails"
- class="form-text text-muted label p-0 js-cluster-application-update-details"
- >
- <template v-if="updateFailed">{{ __('Update failed') }}</template>
- <template v-else-if="isUpdating">{{ __('Updating') }}</template>
- <template v-else>
- <gl-sprintf :message="__('Updated to %{linkStart}chart v%{linkEnd}')">
- <template #link="{ content }">
- <gl-link
- :href="chartRepo"
- target="_blank"
- class="js-cluster-application-update-version"
- >{{ content }}{{ version }}</gl-link
- >
- </template>
- </gl-sprintf>
- </template>
- </div>
-
- <gl-alert
- v-if="updateFailed && !isUpdating"
- variant="danger"
- :dismissible="false"
- class="gl-mt-3 gl-mb-0 js-cluster-application-update-details"
- >
- {{ updateFailureDescription }}
- </gl-alert>
- <template v-if="updateAvailable || updateFailed || isUpdating">
- <template v-if="updatingNeedsConfirmation">
- <gl-button
- v-gl-modal-directive="updateModalId"
- class="js-cluster-application-update-button mt-2"
- variant="info"
- category="primary"
- :loading="isUpdating"
- :disabled="isUpdating"
- data-qa-selector="update_button_with_confirmation"
- :data-qa-application="id"
- >
- {{ updateButtonLabel }}
- </gl-button>
- <update-application-confirmation-modal
- :application="id"
- :application-title="title"
- @confirm="updateConfirmed()"
- />
- </template>
-
- <gl-button
- v-else
- class="js-cluster-application-update-button mt-2"
- variant="info"
- category="primary"
- :loading="isUpdating"
- :disabled="isUpdating"
- data-qa-selector="update_button"
- :data-qa-application="id"
- @click="updateConfirmed"
- >
- {{ updateButtonLabel }}
- </gl-button>
- </template>
- </div>
- </div>
- <div
- :class="[buttonGridCellClass, 'table-section', 'table-button-footer', 'section-align-top']"
- role="gridcell"
- >
- <div v-if="showManageButton" class="btn-group table-action-buttons">
- <a :href="manageLink" :class="{ disabled: disabled }" class="btn">{{
- manageButtonLabel
- }}</a>
- </div>
- <div class="btn-group table-action-buttons">
- <gl-button
- v-if="displayInstallButton"
- :loading="installButtonLoading"
- :disabled="disabled || installButtonDisabled"
- class="js-cluster-application-install-button"
- variant="default"
- data-qa-selector="install_button"
- :data-qa-application="id"
- @click="installClicked"
- >
- {{ installButtonLabel }}
- </gl-button>
- <uninstall-application-button
- v-if="displayUninstallButton"
- v-gl-modal-directive="uninstallModalId"
- :status="status"
- data-qa-selector="uninstall_button"
- :data-qa-application="id"
- class="js-cluster-application-uninstall-button"
- />
- <uninstall-application-confirmation-modal
- :application="id"
- :application-title="title"
- @confirm="uninstallConfirmed()"
- />
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
deleted file mode 100644
index ddee1711975..00000000000
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ /dev/null
@@ -1,662 +0,0 @@
-<script>
-import { GlLoadingIcon, GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
-import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
-import crossplaneLogo from 'images/cluster_app_logos/crossplane.png';
-import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png';
-import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
-import helmLogo from 'images/cluster_app_logos/helm.png';
-import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
-import knativeLogo from 'images/cluster_app_logos/knative.png';
-import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png';
-import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
-import eventHub from '~/clusters/event_hub';
-import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
-import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
-import applicationRow from './application_row.vue';
-import CrossplaneProviderStack from './crossplane_provider_stack.vue';
-import KnativeDomainEditor from './knative_domain_editor.vue';
-
-export default {
- components: {
- applicationRow,
- clipboardButton,
- GlLoadingIcon,
- GlSprintf,
- GlLink,
- KnativeDomainEditor,
- CrossplaneProviderStack,
- GlAlert,
- },
- props: {
- type: {
- type: String,
- required: false,
- default: CLUSTER_TYPE.PROJECT,
- },
- applications: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- helpPath: {
- type: String,
- required: false,
- default: '',
- },
- helmHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- ingressHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- ingressDnsHelpPath: {
- type: String,
- required: false,
- default: '',
- },
-
- cloudRunHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- managePrometheusPath: {
- type: String,
- required: false,
- default: '',
- },
- providerType: {
- type: String,
- required: false,
- default: '',
- },
- preInstalledKnative: {
- type: Boolean,
- required: false,
- default: false,
- },
- rbac: {
- type: Boolean,
- required: false,
- default: false,
- },
- ciliumHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- ingressId() {
- return INGRESS;
- },
- ingressInstalled() {
- return this.applications.ingress.status === APPLICATION_STATUS.INSTALLED;
- },
- ingressExternalEndpoint() {
- return this.applications.ingress.externalIp || this.applications.ingress.externalHostname;
- },
- certManagerInstalled() {
- return this.applications.cert_manager.status === APPLICATION_STATUS.INSTALLED;
- },
- jupyterInstalled() {
- return this.applications.jupyter.status === APPLICATION_STATUS.INSTALLED;
- },
- jupyterHostname() {
- return this.applications.jupyter.hostname;
- },
- knative() {
- return this.applications.knative;
- },
- crossplane() {
- return this.applications.crossplane;
- },
- cloudRun() {
- return this.providerType === PROVIDER_TYPE.GCP && this.preInstalledKnative;
- },
- ingress() {
- return this.applications.ingress;
- },
- },
- methods: {
- saveKnativeDomain() {
- eventHub.$emit('saveKnativeDomain', {
- id: 'knative',
- params: {
- hostname: this.applications.knative.hostname,
- pages_domain_id: this.applications.knative.pagesDomain?.id,
- },
- });
- },
- setKnativeDomain({ domainId, domain }) {
- eventHub.$emit('setKnativeDomain', {
- id: 'knative',
- domainId,
- domain,
- });
- },
- setCrossplaneProviderStack(stack) {
- eventHub.$emit('setCrossplaneProviderStack', {
- id: 'crossplane',
- stack,
- });
- },
- },
- logos: {
- gitlabLogo,
- helmLogo,
- jupyterhubLogo,
- kubernetesLogo,
- certManagerLogo,
- crossplaneLogo,
- knativeLogo,
- prometheusLogo,
- elasticStackLogo,
- },
-};
-</script>
-
-<template>
- <section id="cluster-applications">
- <p class="gl-mb-0">
- {{
- s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.`)
- }}
- <gl-link :href="helpPath">{{ __('More information') }}</gl-link>
- </p>
-
- <div class="cluster-application-list gl-mt-3">
- <application-row
- v-if="applications.helm.installed || applications.helm.uninstalling"
- id="helm"
- :logo-url="$options.logos.helmLogo"
- :title="applications.helm.title"
- :status="applications.helm.status"
- :status-reason="applications.helm.statusReason"
- :request-status="applications.helm.requestStatus"
- :request-reason="applications.helm.requestReason"
- :installed="applications.helm.installed"
- :install-failed="applications.helm.installFailed"
- :uninstallable="applications.helm.uninstallable"
- :uninstall-successful="applications.helm.uninstallSuccessful"
- :uninstall-failed="applications.helm.uninstallFailed"
- title-link="https://v2.helm.sh/"
- >
- <template #description>
- <p>
- {{
- s__(`ClusterIntegration|Can be safely removed. Prior to GitLab
- 13.2, GitLab used a remote Tiller server to manage the
- applications. GitLab no longer uses this server.
- Uninstalling this server will not affect your other
- applications. This row will disappear afterwards.`)
- }}
- <gl-link :href="helmHelpPath">{{ __('More information') }}</gl-link>
- </p>
- </template>
- </application-row>
- <application-row
- :id="ingressId"
- :logo-url="$options.logos.kubernetesLogo"
- :title="applications.ingress.title"
- :status="applications.ingress.status"
- :status-reason="applications.ingress.statusReason"
- :request-status="applications.ingress.requestStatus"
- :request-reason="applications.ingress.requestReason"
- :installed="applications.ingress.installed"
- :install-failed="applications.ingress.installFailed"
- :uninstallable="applications.ingress.uninstallable"
- :uninstall-successful="applications.ingress.uninstallSuccessful"
- :uninstall-failed="applications.ingress.uninstallFailed"
- :updateable="false"
- title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
- >
- <template #description>
- <p>
- {{
- s__(`ClusterIntegration|Ingress gives you a way to route
- requests to services based on the request host or path,
- centralizing a number of services into a single entrypoint.`)
- }}
- </p>
-
- <template v-if="ingressInstalled">
- <div class="form-group">
- <label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
- <div class="input-group">
- <template v-if="ingressExternalEndpoint">
- <input
- id="ingress-endpoint"
- :value="ingressExternalEndpoint"
- type="text"
- class="form-control js-endpoint"
- readonly
- />
- <span class="input-group-append">
- <clipboard-button
- :text="ingressExternalEndpoint"
- :title="s__('ClusterIntegration|Copy Ingress Endpoint')"
- class="input-group-text js-clipboard-btn"
- />
- </span>
- </template>
- <template v-else>
- <input type="text" class="form-control js-endpoint" readonly />
- <gl-loading-icon
- class="position-absolute align-self-center ml-2 js-ingress-ip-loading-icon"
- />
- </template>
- </div>
- <p class="form-text text-muted">
- {{
- s__(`ClusterIntegration|Point a wildcard DNS to this
- generated endpoint in order to access
- your application after it has been deployed.`)
- }}
- <gl-link :href="ingressDnsHelpPath" target="_blank">
- {{ __('More information') }}
- </gl-link>
- </p>
- </div>
-
- <p v-if="!ingressExternalEndpoint" class="settings-message js-no-endpoint-message">
- {{
- s__(`ClusterIntegration|The endpoint is in
- the process of being assigned. Please check your Kubernetes
- cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
- }}
- <gl-link :href="ingressDnsHelpPath" target="_blank">
- {{ __('More information') }}
- </gl-link>
- </p>
- </template>
- <template v-else>
- <gl-alert variant="info" :dismissible="false">
- <span data-testid="ingressCostWarning">
- <gl-sprintf
- :message="
- s__(
- 'ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{linkStart}pricing%{linkEnd}.',
- )
- "
- >
- <template #link="{ content }">
- <gl-link href="https://cloud.google.com/compute/pricing#lb" target="_blank">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
- </span>
- </gl-alert>
- </template>
- </template>
- </application-row>
- <application-row
- id="cert_manager"
- :logo-url="$options.logos.certManagerLogo"
- :title="applications.cert_manager.title"
- :status="applications.cert_manager.status"
- :status-reason="applications.cert_manager.statusReason"
- :request-status="applications.cert_manager.requestStatus"
- :request-reason="applications.cert_manager.requestReason"
- :installed="applications.cert_manager.installed"
- :install-failed="applications.cert_manager.installFailed"
- :install-application-request-params="{ email: applications.cert_manager.email }"
- :uninstallable="applications.cert_manager.uninstallable"
- :uninstall-successful="applications.cert_manager.uninstallSuccessful"
- :uninstall-failed="applications.cert_manager.uninstallFailed"
- title-link="https://cert-manager.readthedocs.io/en/latest/#"
- >
- <template #description>
- <p data-testid="certManagerDescription">
- <gl-sprintf
- :message="
- s__(`ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates.
- Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates
- are valid and up-to-date.`)
- "
- >
- <template #link="{ content }">
- <gl-link href="https://letsencrypt.org/" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- <div class="form-group">
- <label for="cert-manager-issuer-email">
- {{ s__('ClusterIntegration|Issuer Email') }}
- </label>
- <div class="input-group">
- <!-- eslint-disable vue/no-mutating-props -->
- <input
- id="cert-manager-issuer-email"
- v-model="applications.cert_manager.email"
- :readonly="certManagerInstalled"
- type="text"
- class="form-control js-email"
- />
- <!-- eslint-enable vue/no-mutating-props -->
- </div>
- <p class="form-text text-muted">
- {{
- s__(`ClusterIntegration|Issuers represent a certificate authority.
- You must provide an email address for your Issuer.`)
- }}
- <gl-link
- href="http://docs.cert-manager.io/en/latest/reference/issuers.html?highlight=email"
- target="_blank"
- >{{ __('More information') }}</gl-link
- >
- </p>
- </div>
- </template>
- </application-row>
- <application-row
- id="prometheus"
- :logo-url="$options.logos.prometheusLogo"
- :title="applications.prometheus.title"
- :manage-link="managePrometheusPath"
- :status="applications.prometheus.status"
- :status-reason="applications.prometheus.statusReason"
- :request-status="applications.prometheus.requestStatus"
- :request-reason="applications.prometheus.requestReason"
- :installed="applications.prometheus.installed"
- :install-failed="applications.prometheus.installFailed"
- :uninstallable="applications.prometheus.uninstallable"
- :uninstall-successful="applications.prometheus.uninstallSuccessful"
- :uninstall-failed="applications.prometheus.uninstallFailed"
- title-link="https://prometheus.io/docs/introduction/overview/"
- >
- <template #description>
- <span data-testid="prometheusDescription">
- <gl-sprintf
- :message="
- s__(`ClusterIntegration|Prometheus is an open-source monitoring system
- with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications.`)
- "
- >
- <template #link="{ content }">
- <gl-link
- href="https://docs.gitlab.com/ee/user/project/integrations/prometheus.html"
- target="_blank"
- >{{ content }}</gl-link
- >
- </template>
- </gl-sprintf>
- </span>
- </template>
- </application-row>
- <application-row
- id="runner"
- :logo-url="$options.logos.gitlabLogo"
- :title="applications.runner.title"
- :status="applications.runner.status"
- :status-reason="applications.runner.statusReason"
- :request-status="applications.runner.requestStatus"
- :request-reason="applications.runner.requestReason"
- :version="applications.runner.version"
- :chart-repo="applications.runner.chartRepo"
- :update-available="applications.runner.updateAvailable"
- :installed="applications.runner.installed"
- :install-failed="applications.runner.installFailed"
- :update-successful="applications.runner.updateSuccessful"
- :update-failed="applications.runner.updateFailed"
- :uninstallable="applications.runner.uninstallable"
- :uninstall-successful="applications.runner.uninstallSuccessful"
- :uninstall-failed="applications.runner.uninstallFailed"
- title-link="https://docs.gitlab.com/runner/"
- >
- <template #description>
- {{
- s__(`ClusterIntegration|GitLab Runner connects to the
- repository and executes CI/CD jobs,
- pushing results back and deploying
- applications to production.`)
- }}
- </template>
- </application-row>
- <application-row
- id="crossplane"
- :logo-url="$options.logos.crossplaneLogo"
- :title="applications.crossplane.title"
- :status="applications.crossplane.status"
- :status-reason="applications.crossplane.statusReason"
- :request-status="applications.crossplane.requestStatus"
- :request-reason="applications.crossplane.requestReason"
- :installed="applications.crossplane.installed"
- :install-failed="applications.crossplane.installFailed"
- :uninstallable="applications.crossplane.uninstallable"
- :uninstall-successful="applications.crossplane.uninstallSuccessful"
- :uninstall-failed="applications.crossplane.uninstallFailed"
- :install-application-request-params="{ stack: applications.crossplane.stack }"
- title-link="https://crossplane.io"
- >
- <template #description>
- <p data-testid="crossplaneDescription">
- <gl-sprintf
- :message="
- s__(
- `ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}.
- Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`,
- )
- "
- >
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- <template #link="{ content }">
- <gl-link
- href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane"
- target="_blank"
- >{{ content }}</gl-link
- >
- </template>
- </gl-sprintf>
- </p>
- <div class="form-group">
- <CrossplaneProviderStack :crossplane="crossplane" @set="setCrossplaneProviderStack" />
- </div>
- </template>
- </application-row>
-
- <application-row
- id="jupyter"
- :logo-url="$options.logos.jupyterhubLogo"
- :title="applications.jupyter.title"
- :status="applications.jupyter.status"
- :status-reason="applications.jupyter.statusReason"
- :request-status="applications.jupyter.requestStatus"
- :request-reason="applications.jupyter.requestReason"
- :installed="applications.jupyter.installed"
- :install-failed="applications.jupyter.installFailed"
- :uninstallable="applications.jupyter.uninstallable"
- :uninstall-successful="applications.jupyter.uninstallSuccessful"
- :uninstall-failed="applications.jupyter.uninstallFailed"
- :install-application-request-params="{ hostname: applications.jupyter.hostname }"
- title-link="https://jupyterhub.readthedocs.io/en/stable/"
- >
- <template #description>
- <p>
- {{
- s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
- manages, and proxies multiple instances of the single-user
- Jupyter notebook server. JupyterHub can be used to serve
- notebooks to a class of students, a corporate data science group,
- or a scientific research group.`)
- }}
- <gl-sprintf
- :message="
- s__(
- 'ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed.',
- )
- "
- >
- <template #bold="{ content }">
- <b>{{ content }}</b>
- </template>
- </gl-sprintf>
- </p>
-
- <template v-if="ingressExternalEndpoint">
- <div class="form-group">
- <label for="jupyter-hostname">{{ s__('ClusterIntegration|Jupyter Hostname') }}</label>
-
- <div class="input-group">
- <!-- eslint-disable vue/no-mutating-props -->
- <input
- id="jupyter-hostname"
- v-model="applications.jupyter.hostname"
- :readonly="jupyterInstalled"
- type="text"
- class="form-control js-hostname"
- />
- <!-- eslint-enable vue/no-mutating-props -->
- <span class="input-group-append">
- <clipboard-button
- :text="jupyterHostname"
- :title="s__('ClusterIntegration|Copy Jupyter Hostname')"
- class="js-clipboard-btn"
- />
- </span>
- </div>
-
- <p v-if="ingressInstalled" class="form-text text-muted">
- {{
- s__(`ClusterIntegration|Replace this with your own hostname if you want.
- If you do so, point hostname to Ingress IP Address from above.`)
- }}
- <gl-link :href="ingressDnsHelpPath" target="_blank">
- {{ __('More information') }}
- </gl-link>
- </p>
- </div>
- </template>
- </template>
- </application-row>
- <application-row
- id="knative"
- :logo-url="$options.logos.knativeLogo"
- :title="applications.knative.title"
- :status="applications.knative.status"
- :status-reason="applications.knative.statusReason"
- :request-status="applications.knative.requestStatus"
- :request-reason="applications.knative.requestReason"
- :installed="applications.knative.installed"
- :install-failed="applications.knative.installFailed"
- :install-application-request-params="{
- hostname: applications.knative.hostname,
- pages_domain_id: applications.knative.pagesDomain && applications.knative.pagesDomain.id,
- }"
- :uninstallable="applications.knative.uninstallable"
- :uninstall-successful="applications.knative.uninstallSuccessful"
- :uninstall-failed="applications.knative.uninstallFailed"
- :updateable="false"
- v-bind="applications.knative"
- title-link="https://github.com/knative/docs"
- >
- <template #description>
- <gl-alert v-if="!rbac" variant="info" class="rbac-notice gl-my-3" :dismissible="false">
- {{
- s__(`ClusterIntegration|You must have an RBAC-enabled cluster
- to install Knative.`)
- }}
- <gl-link :href="helpPath" target="_blank">{{ __('More information') }}</gl-link>
- </gl-alert>
- <p>
- {{
- s__(`ClusterIntegration|Knative extends Kubernetes to provide
- a set of middleware components that are essential to build modern,
- source-centric, and container-based applications that can run
- anywhere: on premises, in the cloud, or even in a third-party data center.`)
- }}
- </p>
-
- <knative-domain-editor
- v-if="(knative.installed || rbac) && !preInstalledKnative"
- :knative="knative"
- :ingress-dns-help-path="ingressDnsHelpPath"
- @save="saveKnativeDomain"
- @set="setKnativeDomain"
- />
- </template>
- <template v-if="cloudRun" #installed-via>
- <span data-testid="installed-via">
- <gl-sprintf
- :message="s__('ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}')"
- >
- <template #link="{ content }">
- <gl-link :href="cloudRunHelpPath" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </span>
- </template>
- </application-row>
- <application-row
- id="elastic_stack"
- :logo-url="$options.logos.elasticStackLogo"
- :title="applications.elastic_stack.title"
- :status="applications.elastic_stack.status"
- :status-reason="applications.elastic_stack.statusReason"
- :request-status="applications.elastic_stack.requestStatus"
- :request-reason="applications.elastic_stack.requestReason"
- :version="applications.elastic_stack.version"
- :chart-repo="applications.elastic_stack.chartRepo"
- :update-available="applications.elastic_stack.updateAvailable"
- :installed="applications.elastic_stack.installed"
- :install-failed="applications.elastic_stack.installFailed"
- :update-successful="applications.elastic_stack.updateSuccessful"
- :update-failed="applications.elastic_stack.updateFailed"
- :uninstallable="applications.elastic_stack.uninstallable"
- :uninstall-successful="applications.elastic_stack.uninstallSuccessful"
- :uninstall-failed="applications.elastic_stack.uninstallFailed"
- title-link="https://gitlab.com/gitlab-org/charts/elastic-stack"
- >
- <template #description>
- <p>
- {{
- s__(
- `ClusterIntegration|The elastic stack collects logs from all pods in your cluster`,
- )
- }}
- </p>
- </template>
- </application-row>
-
- <div class="gl-mt-7 gl-border-1 gl-border-t-solid gl-border-gray-100">
- <!-- This empty div serves as a separator. The applications below can be externally installed using a cluster-management project. -->
- </div>
-
- <application-row
- id="cilium"
- :title="applications.cilium.title"
- :logo-url="$options.logos.gitlabLogo"
- :status="applications.cilium.status"
- :status-reason="applications.cilium.statusReason"
- :installable="applications.cilium.installable"
- :uninstallable="applications.cilium.uninstallable"
- :installed="applications.cilium.installed"
- :install-failed="applications.cilium.installFailed"
- :title-link="ciliumHelpPath"
- >
- <template #description>
- <p data-testid="ciliumDescription">
- <gl-sprintf
- :message="
- s__(
- 'ClusterIntegration|Protect your clusters with GitLab Container Network Policies by enforcing how pods communicate with each other and other network endpoints. %{linkStart}Learn more about configuring Network Policies here.%{linkEnd}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link :href="ciliumHelpPath" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </template>
- </application-row>
- </div>
- </section>
-</template>
diff --git a/app/assets/javascripts/clusters/components/crossplane_provider_stack.vue b/app/assets/javascripts/clusters/components/crossplane_provider_stack.vue
deleted file mode 100644
index 6b99bb09504..00000000000
--- a/app/assets/javascripts/clusters/components/crossplane_provider_stack.vue
+++ /dev/null
@@ -1,93 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
-import { s__ } from '../../locale';
-
-export default {
- name: 'CrossplaneProviderStack',
- components: {
- GlDropdown,
- GlDropdownItem,
- GlIcon,
- },
- props: {
- stacks: {
- type: Array,
- required: false,
- default: () => [
- {
- name: s__('Google Cloud Platform'),
- code: 'gcp',
- },
- {
- name: s__('Amazon Web Services'),
- code: 'aws',
- },
- {
- name: s__('Microsoft Azure'),
- code: 'azure',
- },
- {
- name: s__('Rook'),
- code: 'rook',
- },
- ],
- },
- crossplane: {
- type: Object,
- required: true,
- },
- },
- computed: {
- dropdownText() {
- const result = this.stacks.reduce((map, obj) => {
- // eslint-disable-next-line no-param-reassign
- map[obj.code] = obj.name;
- return map;
- }, {});
- const { stack } = this.crossplane;
- if (stack !== '') {
- return result[stack];
- }
- return s__('Select Stack');
- },
- validationError() {
- return this.crossplane.validationError;
- },
- },
- methods: {
- selectStack(stack) {
- this.$emit('set', stack);
- },
- },
-};
-</script>
-
-<template>
- <div>
- <label>
- {{ s__('ClusterIntegration|Enabled stack') }}
- </label>
- <gl-dropdown
- :disabled="crossplane.installed"
- :text="dropdownText"
- toggle-class="dropdown-menu-toggle gl-field-error-outline"
- class="w-100"
- :class="{ 'gl-show-field-errors': validationError }"
- >
- <gl-dropdown-item v-for="stack in stacks" :key="stack.code" @click="selectStack(stack)">
- <span class="ml-1">{{ stack.name }}</span>
- </gl-dropdown-item>
- </gl-dropdown>
- <span v-if="validationError" class="gl-field-error">{{ validationError }}</span>
- <p class="form-text text-muted">
- {{ s__(`You must select a stack for configuring your cloud provider. Learn more about`) }}
- <a
- href="https://crossplane.io/docs/master/stacks-guide.html"
- target="_blank"
- rel="noopener noreferrer"
- >{{ __('Crossplane') }}
- <gl-icon name="external-link" class="vertical-align-middle" />
- </a>
- </p>
- </div>
-</template>
diff --git a/app/assets/javascripts/clusters/components/knative_domain_editor.vue b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
deleted file mode 100644
index 89446680173..00000000000
--- a/app/assets/javascripts/clusters/components/knative_domain_editor.vue
+++ /dev/null
@@ -1,232 +0,0 @@
-<script>
-import {
- GlDropdown,
- GlDropdownDivider,
- GlDropdownItem,
- GlLoadingIcon,
- GlSearchBoxByType,
- GlSprintf,
- GlButton,
- GlAlert,
-} from '@gitlab/ui';
-import { APPLICATION_STATUS } from '~/clusters/constants';
-import { __, s__ } from '~/locale';
-
-import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
-
-const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
-
-export default {
- components: {
- GlButton,
- ClipboardButton,
- GlLoadingIcon,
- GlDropdown,
- GlDropdownDivider,
- GlDropdownItem,
- GlSearchBoxByType,
- GlSprintf,
- GlAlert,
- },
- props: {
- knative: {
- type: Object,
- required: true,
- },
- ingressDnsHelpPath: {
- type: String,
- default: '',
- required: false,
- },
- },
- data() {
- return {
- searchQuery: '',
- };
- },
- computed: {
- saveButtonDisabled() {
- return [UNINSTALLING, UPDATING].includes(this.knative.status);
- },
- saving() {
- return [UPDATING].includes(this.knative.status);
- },
- saveButtonLabel() {
- return this.saving ? __('Saving') : __('Save changes');
- },
- knativeInstalled() {
- return this.knative.installed;
- },
- knativeExternalEndpoint() {
- return this.knative.externalIp || this.knative.externalHostname;
- },
- knativeUpdateSuccessful() {
- return this.knative.updateSuccessful;
- },
- knativeHostname: {
- get() {
- return this.knative.hostname;
- },
- set(hostname) {
- this.selectCustomDomain(hostname);
- },
- },
- domainDropdownText() {
- return this.knativeHostname || s__('ClusterIntegration|Select existing domain or use new');
- },
- availableDomains() {
- return this.knative.availableDomains || [];
- },
- filteredDomains() {
- const query = this.searchQuery.toLowerCase();
- return this.availableDomains.filter(({ domain }) => domain.toLowerCase().includes(query));
- },
- showDomainsDropdown() {
- return this.availableDomains.length > 0;
- },
- validationError() {
- return this.knative.validationError;
- },
- },
- watch: {
- knativeUpdateSuccessful(updateSuccessful) {
- if (updateSuccessful) {
- this.$toast.show(s__('ClusterIntegration|Knative domain name was updated successfully.'));
- }
- },
- },
- methods: {
- selectDomain({ id, domain }) {
- this.$emit('set', { domain, domainId: id });
- },
- selectCustomDomain(domain) {
- this.$emit('set', { domain, domainId: null });
- },
- },
-};
-</script>
-
-<template>
- <div class="row">
- <gl-alert
- v-if="knative.updateFailed"
- class="gl-mb-5 col-12 js-cluster-knative-domain-name-failure-message"
- variant="danger"
- >
- {{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
- </gl-alert>
-
- <div
- :class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
- class="form-group col-sm-12 mb-0"
- >
- <label for="knative-domainname">
- <strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
- </label>
-
- <gl-dropdown
- v-if="showDomainsDropdown"
- :text="domainDropdownText"
- toggle-class="dropdown-menu-toggle"
- class="w-100 mb-2"
- >
- <gl-search-box-by-type
- v-model.trim="searchQuery"
- :placeholder="s__('ClusterIntegration|Search domains')"
- />
- <gl-dropdown-item
- v-for="domain in filteredDomains"
- :key="domain.id"
- @click="selectDomain(domain)"
- >
- <span class="ml-1">{{ domain.domain }}</span>
- </gl-dropdown-item>
- <template v-if="searchQuery">
- <gl-dropdown-divider />
- <gl-dropdown-item key="custom-domain" @click="selectCustomDomain(searchQuery)">
- <span class="ml-1">
- <gl-sprintf :message="s__('ClusterIntegration|Use %{query}')">
- <template #query>
- <code>{{ searchQuery }}</code>
- </template>
- </gl-sprintf>
- </span>
- </gl-dropdown-item>
- </template>
- </gl-dropdown>
-
- <input
- v-else
- id="knative-domainname"
- v-model="knativeHostname"
- type="text"
- class="form-control js-knative-domainname"
- />
-
- <span v-if="validationError" class="gl-field-error">{{ validationError }}</span>
- </div>
-
- <template v-if="knativeInstalled">
- <div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
- <label for="knative-endpoint">
- <strong>{{ s__('ClusterIntegration|Knative Endpoint:') }}</strong>
- </label>
- <div v-if="knativeExternalEndpoint" class="input-group">
- <input
- id="knative-endpoint"
- :value="knativeExternalEndpoint"
- type="text"
- class="form-control js-knative-endpoint"
- readonly
- />
- <span class="input-group-append">
- <clipboard-button
- :text="knativeExternalEndpoint"
- :title="s__('ClusterIntegration|Copy Knative Endpoint')"
- class="input-group-text js-knative-endpoint-clipboard-btn"
- />
- </span>
- </div>
- <div v-else class="input-group">
- <input type="text" class="form-control js-endpoint" readonly />
- <gl-loading-icon
- class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
- />
- </div>
- </div>
-
- <p class="form-text text-muted col-12">
- {{
- s__(
- `ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
- )
- }}
- <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{
- __('More information')
- }}</a>
- </p>
-
- <p
- v-if="!knativeExternalEndpoint"
- class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
- >
- {{
- s__(`ClusterIntegration|The endpoint is in
- the process of being assigned. Please check your Kubernetes
- cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
- }}
- </p>
-
- <gl-button
- class="js-knative-save-domain-button gl-mt-5 gl-ml-5"
- variant="success"
- category="primary"
- :loading="saving"
- :disabled="saveButtonDisabled"
- @click="$emit('save')"
- >
- {{ saveButtonLabel }}
- </gl-button>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_button.vue b/app/assets/javascripts/clusters/components/uninstall_application_button.vue
deleted file mode 100644
index 73191d6d84d..00000000000
--- a/app/assets/javascripts/clusters/components/uninstall_application_button.vue
+++ /dev/null
@@ -1,36 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-import { APPLICATION_STATUS } from '~/clusters/constants';
-import { __ } from '~/locale';
-
-const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
-
-export default {
- components: {
- GlButton,
- },
- props: {
- status: {
- type: String,
- required: true,
- },
- },
- computed: {
- disabled() {
- return [UNINSTALLING, UPDATING].includes(this.status);
- },
- loading() {
- return this.status === UNINSTALLING;
- },
- label() {
- return this.loading ? __('Uninstalling') : __('Uninstall');
- },
- },
-};
-</script>
-
-<template>
- <gl-button :disabled="disabled" variant="default" :loading="loading">
- {{ label }}
- </gl-button>
-</template>
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
deleted file mode 100644
index 2a197e40b60..00000000000
--- a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
+++ /dev/null
@@ -1,101 +0,0 @@
-<script>
-import { GlModal, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click';
-import { sprintf, s__ } from '~/locale';
-import {
- HELM,
- INGRESS,
- CERT_MANAGER,
- PROMETHEUS,
- RUNNER,
- KNATIVE,
- JUPYTER,
- ELASTIC_STACK,
-} from '../constants';
-
-const CUSTOM_APP_WARNING_TEXT = {
- [HELM]: sprintf(
- s__(
- 'ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored. Your other applications will remain unaffected.',
- ),
- {
- gitlabManagedAppsNamespace: '<code>gitlab-managed-apps</code>',
- },
- false,
- ),
- [INGRESS]: s__(
- 'ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored.',
- ),
- [CERT_MANAGER]: s__(
- 'ClusterIntegration|The associated private key will be deleted and cannot be restored.',
- ),
- [PROMETHEUS]: s__('ClusterIntegration|All data will be deleted and cannot be restored.'),
- [RUNNER]: s__('ClusterIntegration|Any running pipelines will be canceled.'),
- [KNATIVE]: s__(
- 'ClusterIntegration|The associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications.',
- ),
- [JUPYTER]: s__(
- 'ClusterIntegration|All data not committed to GitLab will be deleted and cannot be restored.',
- ),
- [ELASTIC_STACK]: s__('ClusterIntegration|All data will be deleted and cannot be restored.'),
-};
-
-export default {
- components: {
- GlModal,
- },
- directives: {
- SafeHtml,
- },
- mixins: [trackUninstallButtonClickMixin],
- props: {
- application: {
- type: String,
- required: true,
- },
- applicationTitle: {
- type: String,
- required: true,
- },
- },
- computed: {
- title() {
- return sprintf(s__('ClusterIntegration|Uninstall %{appTitle}'), {
- appTitle: this.applicationTitle,
- });
- },
- warningText() {
- return sprintf(
- s__('ClusterIntegration|You are about to uninstall %{appTitle} from your cluster.'),
- {
- appTitle: this.applicationTitle,
- },
- );
- },
- customAppWarningText() {
- return CUSTOM_APP_WARNING_TEXT[this.application];
- },
- modalId() {
- return `uninstall-${this.application}`;
- },
- },
- methods: {
- confirmUninstall() {
- this.trackUninstallButtonClick(this.application);
- this.$emit('confirm');
- },
- },
-};
-</script>
-<template>
- <gl-modal
- ok-variant="danger"
- cancel-variant="light"
- :ok-title="title"
- :modal-id="modalId"
- :title="title"
- @ok="confirmUninstall()"
- >
- {{ warningText }} <span v-safe-html="customAppWarningText"></span>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
deleted file mode 100644
index 0aedc6e84fa..00000000000
--- a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-<script>
-/* eslint-disable vue/no-v-html */
-import { GlModal } from '@gitlab/ui';
-import { sprintf, s__ } from '~/locale';
-import { ELASTIC_STACK } from '../constants';
-
-const CUSTOM_APP_WARNING_TEXT = {
- [ELASTIC_STACK]: s__(
- 'ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days.',
- ),
-};
-
-export default {
- components: {
- GlModal,
- },
- props: {
- application: {
- type: String,
- required: true,
- },
- applicationTitle: {
- type: String,
- required: true,
- },
- },
- computed: {
- title() {
- return sprintf(s__('ClusterIntegration|Update %{appTitle}'), {
- appTitle: this.applicationTitle,
- });
- },
- warningText() {
- return sprintf(
- s__('ClusterIntegration|You are about to update %{appTitle} on your cluster.'),
- {
- appTitle: this.applicationTitle,
- },
- );
- },
- customAppWarningText() {
- return CUSTOM_APP_WARNING_TEXT[this.application];
- },
- modalId() {
- return `update-${this.application}`;
- },
- },
- methods: {
- confirmUpdate() {
- this.$emit('confirm');
- },
- },
-};
-</script>
-<template>
- <gl-modal
- ok-variant="danger"
- cancel-variant="light"
- :ok-title="title"
- :modal-id="modalId"
- :title="title"
- @ok="confirmUpdate()"
- >
- {{ warningText }} <span v-html="customAppWarningText"></span>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index 846e5950b8b..c6ca895778d 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -10,64 +10,7 @@ export const PROVIDER_TYPE = {
GCP: 'gcp',
};
-// These need to match what is returned from the server
-export const APPLICATION_STATUS = {
- NO_STATUS: null,
- NOT_INSTALLABLE: 'not_installable',
- INSTALLABLE: 'installable',
- SCHEDULED: 'scheduled',
- INSTALLING: 'installing',
- INSTALLED: 'installed',
- UPDATING: 'updating',
- UPDATED: 'updated',
- UPDATE_ERRORED: 'update_errored',
- UNINSTALLING: 'uninstalling',
- UNINSTALL_ERRORED: 'uninstall_errored',
- ERROR: 'errored',
- PRE_INSTALLED: 'pre_installed',
- UNINSTALLED: 'uninstalled',
- EXTERNALLY_INSTALLED: 'externally_installed',
-};
-
-/*
- * The application cannot be in any of the following states without
- * not being installed.
- */
-export const APPLICATION_INSTALLED_STATUSES = [
- APPLICATION_STATUS.INSTALLED,
- APPLICATION_STATUS.UPDATING,
- APPLICATION_STATUS.UNINSTALLING,
- APPLICATION_STATUS.PRE_INSTALLED,
-];
-
// These are only used client-side
-export const UPDATE_EVENT = 'update';
-export const INSTALL_EVENT = 'install';
-export const UNINSTALL_EVENT = 'uninstall';
-
-export const HELM = 'helm';
-export const INGRESS = 'ingress';
-export const JUPYTER = 'jupyter';
-export const KNATIVE = 'knative';
-export const RUNNER = 'runner';
-export const CERT_MANAGER = 'cert_manager';
-export const CROSSPLANE = 'crossplane';
-export const PROMETHEUS = 'prometheus';
-export const ELASTIC_STACK = 'elastic_stack';
-
-export const APPLICATIONS = [
- HELM,
- INGRESS,
- JUPYTER,
- KNATIVE,
- RUNNER,
- CERT_MANAGER,
- PROMETHEUS,
- ELASTIC_STACK,
-];
-
-export const INGRESS_DOMAIN_SUFFIX = '.nip.io';
-
export const LOGGING_MODE = 'logging';
export const BLOCKING_MODE = 'blocking';
diff --git a/app/assets/javascripts/clusters/services/application_state_machine.js b/app/assets/javascripts/clusters/services/application_state_machine.js
deleted file mode 100644
index 2ff604af9a7..00000000000
--- a/app/assets/javascripts/clusters/services/application_state_machine.js
+++ /dev/null
@@ -1,250 +0,0 @@
-import { APPLICATION_STATUS, UPDATE_EVENT, INSTALL_EVENT, UNINSTALL_EVENT } from '../constants';
-
-const {
- NO_STATUS,
- SCHEDULED,
- NOT_INSTALLABLE,
- INSTALLABLE,
- INSTALLING,
- INSTALLED,
- ERROR,
- UPDATING,
- UPDATED,
- UPDATE_ERRORED,
- UNINSTALLING,
- UNINSTALL_ERRORED,
- PRE_INSTALLED,
- UNINSTALLED,
- EXTERNALLY_INSTALLED,
-} = APPLICATION_STATUS;
-
-const applicationStateMachine = {
- /* When the application initially loads, it will have `NO_STATUS`
- * It will transition from `NO_STATUS` once the async backend call is completed
- */
- [NO_STATUS]: {
- on: {
- [SCHEDULED]: {
- target: INSTALLING,
- },
- [NOT_INSTALLABLE]: {
- target: NOT_INSTALLABLE,
- },
- [INSTALLABLE]: {
- target: INSTALLABLE,
- },
- [INSTALLING]: {
- target: INSTALLING,
- },
- [INSTALLED]: {
- target: INSTALLED,
- },
- [ERROR]: {
- target: INSTALLABLE,
- effects: {
- installFailed: true,
- },
- },
- [UPDATING]: {
- target: UPDATING,
- },
- [UPDATED]: {
- target: INSTALLED,
- },
- [UPDATE_ERRORED]: {
- target: INSTALLED,
- effects: {
- updateFailed: true,
- },
- },
- [UNINSTALLING]: {
- target: UNINSTALLING,
- },
- [UNINSTALL_ERRORED]: {
- target: INSTALLED,
- effects: {
- uninstallFailed: true,
- },
- },
- [PRE_INSTALLED]: {
- target: PRE_INSTALLED,
- },
- [UNINSTALLED]: {
- target: UNINSTALLED,
- },
- [EXTERNALLY_INSTALLED]: {
- target: EXTERNALLY_INSTALLED,
- },
- },
- },
- [NOT_INSTALLABLE]: {
- on: {
- [INSTALLABLE]: {
- target: INSTALLABLE,
- },
- },
- },
- [INSTALLABLE]: {
- on: {
- [INSTALL_EVENT]: {
- target: INSTALLING,
- effects: {
- installFailed: false,
- },
- },
- [NOT_INSTALLABLE]: {
- target: NOT_INSTALLABLE,
- },
- [INSTALLED]: {
- target: INSTALLED,
- effects: {
- installFailed: false,
- },
- },
- [UNINSTALLED]: {
- target: UNINSTALLED,
- effects: {
- installFailed: false,
- },
- },
- },
- },
- [INSTALLING]: {
- on: {
- [INSTALLED]: {
- target: INSTALLED,
- },
- [ERROR]: {
- target: INSTALLABLE,
- effects: {
- installFailed: true,
- },
- },
- },
- },
- [INSTALLED]: {
- on: {
- [UPDATE_EVENT]: {
- target: UPDATING,
- effects: {
- updateFailed: false,
- updateSuccessful: false,
- },
- },
- [NOT_INSTALLABLE]: {
- target: NOT_INSTALLABLE,
- },
- [UNINSTALL_EVENT]: {
- target: UNINSTALLING,
- effects: {
- uninstallFailed: false,
- uninstallSuccessful: false,
- },
- },
- [UNINSTALLED]: {
- target: UNINSTALLED,
- },
- [ERROR]: {
- target: INSTALLABLE,
- effects: {
- installFailed: true,
- },
- },
- },
- },
- [PRE_INSTALLED]: {
- on: {
- [UPDATE_EVENT]: {
- target: UPDATING,
- effects: {
- updateFailed: false,
- updateSuccessful: false,
- },
- },
- [NOT_INSTALLABLE]: {
- target: NOT_INSTALLABLE,
- },
- [UNINSTALL_EVENT]: {
- target: UNINSTALLING,
- effects: {
- uninstallFailed: false,
- uninstallSuccessful: false,
- },
- },
- },
- },
- [UPDATING]: {
- on: {
- [UPDATED]: {
- target: INSTALLED,
- effects: {
- updateSuccessful: true,
- },
- },
- [UPDATE_ERRORED]: {
- target: INSTALLED,
- effects: {
- updateFailed: true,
- },
- },
- },
- },
- [UNINSTALLING]: {
- on: {
- [INSTALLABLE]: {
- target: INSTALLABLE,
- effects: {
- uninstallSuccessful: true,
- },
- },
- [NOT_INSTALLABLE]: {
- target: NOT_INSTALLABLE,
- effects: {
- uninstallSuccessful: true,
- },
- },
- [UNINSTALL_ERRORED]: {
- target: INSTALLED,
- effects: {
- uninstallFailed: true,
- },
- },
- },
- },
- [UNINSTALLED]: {
- on: {
- [INSTALLED]: {
- target: INSTALLED,
- },
- [ERROR]: {
- target: INSTALLABLE,
- effects: {
- installFailed: true,
- },
- },
- },
- },
-};
-
-/**
- * Determines an application new state based on the application current state
- * and an event. If the application current state cannot handle a given event,
- * the current state is returned.
- *
- * @param {*} application
- * @param {*} event
- */
-const transitionApplicationState = (application, event) => {
- const stateMachine = applicationStateMachine[application.status];
- const newState = stateMachine !== undefined ? stateMachine.on[event] : false;
-
- return newState
- ? {
- ...application,
- status: newState.target,
- ...newState.effects,
- }
- : application;
-};
-
-export default transitionApplicationState;
diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js
index 333fb293a15..7300bb3137a 100644
--- a/app/assets/javascripts/clusters/services/clusters_service.js
+++ b/app/assets/javascripts/clusters/services/clusters_service.js
@@ -3,38 +3,12 @@ import axios from '../../lib/utils/axios_utils';
export default class ClusterService {
constructor(options = {}) {
this.options = options;
- this.appInstallEndpointMap = {
- helm: this.options.installHelmEndpoint,
- ingress: this.options.installIngressEndpoint,
- cert_manager: this.options.installCertManagerEndpoint,
- crossplane: this.options.installCrossplaneEndpoint,
- runner: this.options.installRunnerEndpoint,
- prometheus: this.options.installPrometheusEndpoint,
- jupyter: this.options.installJupyterEndpoint,
- knative: this.options.installKnativeEndpoint,
- elastic_stack: this.options.installElasticStackEndpoint,
- };
- this.appUpdateEndpointMap = {
- knative: this.options.updateKnativeEndpoint,
- };
}
fetchClusterStatus() {
return axios.get(this.options.endpoint);
}
- installApplication(appId, params) {
- return axios.post(this.appInstallEndpointMap[appId], params);
- }
-
- updateApplication(appId, params) {
- return axios.patch(this.appUpdateEndpointMap[appId], params);
- }
-
- uninstallApplication(appId, params) {
- return axios.delete(this.appInstallEndpointMap[appId], params);
- }
-
fetchClusterEnvironments() {
return axios.get(this.options.clusterEnvironmentsEndpoint);
}
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 50689a6142f..db6e7bad6cc 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -1,112 +1,16 @@
import { parseBoolean } from '../../lib/utils/common_utils';
-import { s__ } from '../../locale';
-import {
- INGRESS,
- JUPYTER,
- KNATIVE,
- CERT_MANAGER,
- CROSSPLANE,
- RUNNER,
- APPLICATION_INSTALLED_STATUSES,
- APPLICATION_STATUS,
- INSTALL_EVENT,
- UPDATE_EVENT,
- UNINSTALL_EVENT,
- ELASTIC_STACK,
-} from '../constants';
-import transitionApplicationState from '../services/application_state_machine';
-
-const isApplicationInstalled = (appStatus) => APPLICATION_INSTALLED_STATUSES.includes(appStatus);
-
-const applicationInitialState = {
- status: null,
- statusReason: null,
- requestReason: null,
- installable: true,
- installed: false,
- installFailed: false,
- uninstallable: false,
- uninstallFailed: false,
- uninstallSuccessful: false,
- validationError: null,
-};
export default class ClusterStore {
constructor() {
this.state = {
helpPath: null,
- helmHelpPath: null,
- ingressHelpPath: null,
environmentsHelpPath: null,
clustersHelpPath: null,
deployBoardsHelpPath: null,
- cloudRunHelpPath: null,
status: null,
providerType: null,
- preInstalledKnative: false,
rbac: false,
statusReason: null,
- applications: {
- helm: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Legacy Helm Tiller server'),
- },
- ingress: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Ingress'),
- externalIp: null,
- externalHostname: null,
- updateFailed: false,
- updateAvailable: false,
- },
- cert_manager: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Cert-Manager'),
- email: null,
- },
- crossplane: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Crossplane'),
- stack: null,
- },
- runner: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|GitLab Runner'),
- version: null,
- chartRepo: 'https://gitlab.com/gitlab-org/charts/gitlab-runner',
- updateAvailable: null,
- updateSuccessful: false,
- updateFailed: false,
- },
- prometheus: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Prometheus'),
- },
- jupyter: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|JupyterHub'),
- hostname: null,
- },
- knative: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Knative'),
- hostname: null,
- isEditingDomain: false,
- externalIp: null,
- externalHostname: null,
- updateSuccessful: false,
- updateFailed: false,
- },
- elastic_stack: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Elastic Stack'),
- },
- cilium: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|GitLab Container Network Policies'),
- installable: false,
- },
- },
environments: [],
fetchingEnvironments: false,
};
@@ -118,10 +22,6 @@ export default class ClusterStore {
});
}
- setManagePrometheusPath(managePrometheusPath) {
- this.state.managePrometheusPath = managePrometheusPath;
- }
-
updateStatus(status) {
this.state.status = status;
}
@@ -130,10 +30,6 @@ export default class ClusterStore {
this.state.providerType = providerType;
}
- updatePreInstalledKnative(preInstalledKnative) {
- this.state.preInstalledKnative = parseBoolean(preInstalledKnative);
- }
-
updateRbac(rbac) {
this.state.rbac = parseBoolean(rbac);
}
@@ -142,112 +38,9 @@ export default class ClusterStore {
this.state.statusReason = reason;
}
- installApplication(appId) {
- this.handleApplicationEvent(appId, INSTALL_EVENT);
- }
-
- notifyInstallFailure(appId) {
- this.handleApplicationEvent(appId, APPLICATION_STATUS.ERROR);
- }
-
- updateApplication(appId) {
- this.handleApplicationEvent(appId, UPDATE_EVENT);
- }
-
- notifyUpdateFailure(appId) {
- this.handleApplicationEvent(appId, APPLICATION_STATUS.UPDATE_ERRORED);
- }
-
- uninstallApplication(appId) {
- this.handleApplicationEvent(appId, UNINSTALL_EVENT);
- }
-
- notifyUninstallFailure(appId) {
- this.handleApplicationEvent(appId, APPLICATION_STATUS.UNINSTALL_ERRORED);
- }
-
- handleApplicationEvent(appId, event) {
- const currentAppState = this.state.applications[appId];
-
- this.state.applications[appId] = transitionApplicationState(currentAppState, event);
- }
-
- updateAppProperty(appId, prop, value) {
- this.state.applications[appId][prop] = value;
- }
-
updateStateFromServer(serverState = {}) {
this.state.status = serverState.status;
this.state.statusReason = serverState.status_reason;
-
- serverState.applications.forEach((serverAppEntry) => {
- const {
- name: appId,
- status,
- status_reason: statusReason,
- version,
- update_available: updateAvailable,
- can_uninstall: uninstallable,
- } = serverAppEntry;
- const currentApplicationState = this.state.applications[appId] || {};
- const nextApplicationState = transitionApplicationState(currentApplicationState, status);
-
- this.state.applications[appId] = {
- ...currentApplicationState,
- ...nextApplicationState,
- statusReason,
- installed: isApplicationInstalled(nextApplicationState.status),
- uninstallable,
- };
-
- if (appId === INGRESS) {
- this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
- this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname;
- this.state.applications.ingress.updateAvailable = updateAvailable;
- } else if (appId === CERT_MANAGER) {
- this.state.applications.cert_manager.email =
- this.state.applications.cert_manager.email || serverAppEntry.email;
- } else if (appId === CROSSPLANE) {
- this.state.applications.crossplane.stack =
- this.state.applications.crossplane.stack || serverAppEntry.stack;
- } else if (appId === JUPYTER) {
- this.state.applications.jupyter.hostname = this.updateHostnameIfUnset(
- this.state.applications.jupyter.hostname,
- serverAppEntry.hostname,
- 'jupyter',
- );
- } else if (appId === KNATIVE) {
- if (serverAppEntry.available_domains) {
- this.state.applications.knative.availableDomains = serverAppEntry.available_domains;
- }
- if (!this.state.applications.knative.isEditingDomain) {
- this.state.applications.knative.pagesDomain =
- serverAppEntry.pages_domain || this.state.applications.knative.pagesDomain;
- this.state.applications.knative.hostname =
- serverAppEntry.hostname || this.state.applications.knative.hostname;
- }
- this.state.applications.knative.externalIp =
- serverAppEntry.external_ip || this.state.applications.knative.externalIp;
- this.state.applications.knative.externalHostname =
- serverAppEntry.external_hostname || this.state.applications.knative.externalHostname;
- } else if (appId === RUNNER) {
- this.state.applications.runner.version = version;
- this.state.applications.runner.updateAvailable = updateAvailable;
- } else if (appId === ELASTIC_STACK) {
- this.state.applications.elastic_stack.version = version;
- this.state.applications.elastic_stack.updateAvailable = updateAvailable;
- }
- });
- }
-
- updateHostnameIfUnset(current, updated, fallback) {
- return (
- current ||
- updated ||
- (this.state.applications.ingress.externalIp
- ? `${fallback}.${this.state.applications.ingress.externalIp}.nip.io`
- : '')
- );
}
toggleFetchEnvironments(isFetching) {