diff --git a/src/api/che.ts b/src/api/che.ts index 13436fd25..7bf27a4aa 100644 --- a/src/api/che.ts +++ b/src/api/che.ts @@ -21,7 +21,7 @@ import * as os from 'os' import * as path from 'path' import { OpenShiftHelper } from '../api/openshift' -import { CHE_CLUSTER_CR_NAME, CHE_ROOT_CA_SECRET_NAME, DEFAULT_CA_CERT_FILE_NAME } from '../constants' +import { CHE_ROOT_CA_SECRET_NAME, DEFAULT_CA_CERT_FILE_NAME } from '../constants' import { base64Decode } from '../util' import { Devfile } from './devfile' @@ -150,7 +150,10 @@ export class CheHelper { let adminUsername let adminPassword - const cheCluster = await this.kube.getCheCluster(CHE_CLUSTER_CR_NAME, cheNamespace) + const cheCluster = await this.kube.getCheCluster(cheNamespace) + if (!cheCluster) { + return [] + } const keycloakCredentialsSecretName = cheCluster.spec.auth.identityProviderSecret if (keycloakCredentialsSecretName) { // Keycloak credentials are stored in secret diff --git a/src/api/kube.ts b/src/api/kube.ts index 1314e3505..1839e4467 100644 --- a/src/api/kube.ts +++ b/src/api/kube.ts @@ -20,7 +20,7 @@ import { merge } from 'lodash' import * as net from 'net' import { Writable } from 'stream' -import { DEFAULT_CHE_IMAGE } from '../constants' +import { CHE_CLUSTER_CRD, DEFAULT_CHE_IMAGE } from '../constants' import { getClusterClientCommand } from '../util' import { V1alpha2Certificate } from './typings/cert-manager' @@ -1205,21 +1205,46 @@ export class KubeHelper { } } - async getCheCluster(name: string, namespace: string): Promise { + /** + * Returns `checlusters.org.eclipse.che' in the given namespace. + */ + async getCheCluster(namespace: string): Promise { const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi) try { - const { body } = await customObjectsApi.getNamespacedCustomObject('org.eclipse.che', 'v1', namespace, 'checlusters', name) - return body - } catch { - return + const { body } = await customObjectsApi.listNamespacedCustomObject('org.eclipse.che', 'v1', namespace, 'checlusters') + if (!body.items) { + return + } + + const crs = body.items as any[] + if (crs.length === 0) { + return + } else if (crs.length !== 1) { + throw new Error(`Too many resources '${CHE_CLUSTER_CRD}' found in the namespace '${namespace}'`) + } + + return crs[0] + } catch (e) { + throw this.wrapK8sClientError(e) } } - async deleteCheCluster(name = '', namespace = '') { + /** + * Deletes `checlusters.org.eclipse.che' resources in the given namespace. + */ + async deleteCheCluster(namespace: string) { const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi) try { - const options = new V1DeleteOptions() - await customObjectsApi.deleteNamespacedCustomObject('org.eclipse.che', 'v1', namespace, 'checlusters', name, options) + const { body } = await customObjectsApi.listNamespacedCustomObject('org.eclipse.che', 'v1', namespace, 'checlusters') + if (!body.items) { + return + } + + const crs = body.items as any[] + for (const cr of crs) { + const options = new V1DeleteOptions() + await customObjectsApi.deleteNamespacedCustomObject('org.eclipse.che', 'v1', namespace, 'checlusters', cr.metadata.name, options) + } } catch (e) { throw this.wrapK8sClientError(e) } diff --git a/src/commands/server/update.ts b/src/commands/server/update.ts index d55ecf0c9..c90ac7126 100644 --- a/src/commands/server/update.ts +++ b/src/commands/server/update.ts @@ -18,7 +18,7 @@ import * as path from 'path' import { KubeHelper } from '../../api/kube' import { cheDeployment, cheNamespace, listrRenderer, skipKubeHealthzCheck } from '../../common-flags' -import { CHE_CLUSTER_CR_NAME, DEFAULT_CHE_OPERATOR_IMAGE } from '../../constants' +import { DEFAULT_CHE_OPERATOR_IMAGE } from '../../constants' import { CheTasks } from '../../tasks/che' import { getPrintHighlightedMessagesTask } from '../../tasks/installers/common-tasks' import { InstallerTasks } from '../../tasks/installers/installer' @@ -173,7 +173,7 @@ export default class Update extends Command { async setDomainFlag(flags: any): Promise { const kubeHelper = new KubeHelper(flags) - const cheCluster = await kubeHelper.getCheCluster(CHE_CLUSTER_CR_NAME, flags.chenamespace) + const cheCluster = await kubeHelper.getCheCluster(flags.chenamespace) if (cheCluster && cheCluster.spec.k8s && cheCluster.spec.k8s.ingressDomain) { flags.domain = cheCluster.spec.k8s.ingressDomain } diff --git a/src/constants.ts b/src/constants.ts index 5e752b4ff..c2e4a70d3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -21,9 +21,8 @@ export const CERT_MANAGER_NAMESPACE_NAME = 'cert-manager' export const CHE_TLS_SECRET_NAME = 'che-tls' export const CHE_ROOT_CA_SECRET_NAME = 'self-signed-certificate' export const DEFAULT_CA_CERT_FILE_NAME = 'cheCA.crt' - -export const operatorCheCluster = 'eclipse-che' export const CHE_CLUSTER_CR_NAME = 'eclipse-che' +export const CHE_CLUSTER_CRD = 'checlusters.org.eclipse.che' export const defaultOpenshiftMarketPlaceNamespace = 'openshift-marketplace' export const defaultOLMKubernetesNamespace = 'olm' diff --git a/src/tasks/installers/common-tasks.ts b/src/tasks/installers/common-tasks.ts index 09dca029f..fbcef9362 100644 --- a/src/tasks/installers/common-tasks.ts +++ b/src/tasks/installers/common-tasks.ts @@ -17,7 +17,7 @@ import * as path from 'path' import { CheHelper } from '../../api/che' import { KubeHelper } from '../../api/kube' -import { CHE_CLUSTER_CR_NAME, DOCS_LINK_IMPORT_CA_CERT_INTO_BROWSER } from '../../constants' +import { CHE_CLUSTER_CRD, DOCS_LINK_IMPORT_CA_CERT_INTO_BROWSER } from '../../constants' import { isKubernetesPlatformFamily, isOpenshiftPlatformFamily } from '../../util' export function createNamespaceTask(flags: any): Listr.ListrTask { @@ -62,9 +62,9 @@ async function copyCheOperatorResources(templatesDir: string, cacheDir: string): export function createEclipseCheCluster(flags: any, kube: KubeHelper): Listr.ListrTask { return { - title: `Create Eclipse Che cluster ${CHE_CLUSTER_CR_NAME} in namespace ${flags.chenamespace}`, + title: `Create the Custom Resource of type ${CHE_CLUSTER_CRD} in the namespace ${flags.chenamespace}`, task: async (ctx: any, task: any) => { - const cheCluster = await kube.getCheCluster(CHE_CLUSTER_CR_NAME, flags.chenamespace) + const cheCluster = await kube.getCheCluster(flags.chenamespace) if (cheCluster) { task.title = `${task.title}...It already exists.` } else { diff --git a/src/tasks/installers/operator.ts b/src/tasks/installers/operator.ts index 5b5307a38..ef402457f 100644 --- a/src/tasks/installers/operator.ts +++ b/src/tasks/installers/operator.ts @@ -15,7 +15,7 @@ import * as yaml from 'js-yaml' import * as Listr from 'listr' import { KubeHelper } from '../../api/kube' -import { CHE_CLUSTER_CR_NAME } from '../../constants' +import { CHE_CLUSTER_CRD } from '../../constants' import { isStableVersion } from '../../util' import { checkTlsCertificate, copyOperatorResources, createEclipseCheCluster, createNamespaceTask } from './common-tasks' @@ -309,16 +309,11 @@ export class OperatorTasks { deleteTasks(flags: any): ReadonlyArray { let kh = new KubeHelper(flags) return [{ - title: `Delete the CR ${CHE_CLUSTER_CR_NAME} of type ${this.cheClusterCrd}`, + title: `Delete the Custom Resource of type ${CHE_CLUSTER_CRD}`, task: async (_ctx: any, task: any) => { - if (await kh.crdExist(this.cheClusterCrd) && - await kh.getCheCluster(CHE_CLUSTER_CR_NAME, flags.chenamespace)) { - await kh.deleteCheCluster(CHE_CLUSTER_CR_NAME, flags.chenamespace) - await cli.wait(2000) //wait a couple of secs for the finalizers to be executed - task.title = await `${task.title}...OK` - } else { - task.title = await `${task.title}...CR not found` - } + await kh.deleteCheCluster(flags.chenamespace) + await cli.wait(2000) //wait a couple of secs for the finalizers to be executed + task.title = await `${task.title}...OK` } }, { diff --git a/yarn.lock b/yarn.lock index cd21b822e..3d22654e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1529,7 +1529,7 @@ ecc-jsbn@~0.1.1: "eclipse-che@git://github.com/eclipse/che#master": version "0.0.0" - resolved "git://github.com/eclipse/che#fb063a970d0999915f18a8d4a19835a38a4a74b5" + resolved "git://github.com/eclipse/che#7bcf1d3e930ea4b993a09b3eae12a1bd22cdc351" editorconfig@^0.15.0: version "0.15.3"