diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 03aa68c6a..12b2bb751 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,8 +2,21 @@ "version": "2.0.0", "tasks": [ { - "label": "Custom che-operator Minikube", - "command": "./bin/run server:deploy -n che -m -p minikube --che-operator-image=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-operator:nightly --cheimage=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-server:nightly", + "label": "[Minikube] Install Che", + "command": "./bin/run server:deploy -n che -m -p minikube", + "type": "shell", + "args": [], + "problemMatcher": [ + "$tsc" + ], + "presentation": { + "reveal": "always" + }, + "group": "build" + }, + { + "label": "[Minikube] Install Che with custom che-operator image", + "command": "./bin/run server:deploy -n che -m -p minikube --che-operator-image=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-operator:nightly", "type": "shell", "args": [], "problemMatcher": [ @@ -15,7 +28,7 @@ "group": "build" }, { - "label": "Custom che-operator and che-server Minikube", + "label": "[Minikube] Install Che with custom che-operator and che-server images", "command": "./bin/run server:deploy -n che -m -p minikube --che-operator-image=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-operator:nightly --cheimage=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-server:nightly", "type": "shell", "args": [], @@ -28,7 +41,20 @@ "group": "build" }, { - "label": "Custom che-operator Openshift", + "label": "[Openshift] Install Che", + "command": "./bin/run server:deploy -n che -m -p openshift", + "type": "shell", + "args": [], + "problemMatcher": [ + "$tsc" + ], + "presentation": { + "reveal": "always" + }, + "group": "build" + }, + { + "label": "[Openshift] Install Che with custom che-operator image", "command": "./bin/run server:deploy -n che -m -p openshift -a operator --che-operator-image=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-operator:nightly", "type": "shell", "args": [], @@ -41,7 +67,7 @@ "group": "build" }, { - "label": "Custom che-operator and che-server Openshift", + "label": "[Openshift] Install Che with custom che-operator and che-server images", "command": "./bin/run server:deploy -n che -m -p openshift -a operator --che-operator-image=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-operator:nightly --cheimage=${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-server:nightly", "type": "shell", "args": [], @@ -91,6 +117,32 @@ "reveal": "always" }, "group": "build" + }, + { + "label": "Fix tslint", + "command": "yarn run tslint-fix", + "type": "shell", + "args": [], + "problemMatcher": [ + "$tsc" + ], + "presentation": { + "reveal": "always" + }, + "group": "build" + }, + { + "label": "Pack binaries", + "command": "yarn run pack-binaries", + "type": "shell", + "args": [], + "problemMatcher": [ + "$tsc" + ], + "presentation": { + "reveal": "always" + }, + "group": "build" } ] } diff --git a/src/api/kube.ts b/src/api/kube.ts index 22fe4ca9b..e3e0e721f 100644 --- a/src/api/kube.ts +++ b/src/api/kube.ts @@ -1261,9 +1261,7 @@ export class KubeHelper { } } - async createCheClusterFromFile(filePath: string, flags: any, ctx: any, useDefaultCR: boolean): Promise { - let yamlCr = this.safeLoadFromYamlFile(filePath) - + async createCheCluster(cheClusterCR: any, flags: any, ctx: any, useDefaultCR: boolean): Promise { const cheNamespace = flags.chenamespace if (useDefaultCR) { // If we don't use an explicitly provided CheCluster CR, @@ -1272,70 +1270,70 @@ export class KubeHelper { const cheImage = flags.cheimage if (cheImage) { const imageAndTag = cheImage.split(':', 2) - yamlCr.spec.server.cheImage = imageAndTag[0] - yamlCr.spec.server.cheImageTag = imageAndTag.length === 2 ? imageAndTag[1] : 'latest' + cheClusterCR.spec.server.cheImage = imageAndTag[0] + cheClusterCR.spec.server.cheImageTag = imageAndTag.length === 2 ? imageAndTag[1] : 'latest' } if ((flags.installer === 'olm' && !flags['catalog-source-yaml']) || (flags['catalog-source-yaml'] && flags['olm-channel'] === OLM_STABLE_CHANNEL_NAME)) { // use default image tag for `olm` to install stable Che, because we don't have nightly channel for OLM catalog. - yamlCr.spec.server.cheImageTag = '' + cheClusterCR.spec.server.cheImageTag = '' } - yamlCr.spec.server.cheDebug = flags.debug ? flags.debug.toString() : 'false' + cheClusterCR.spec.server.cheDebug = flags.debug ? flags.debug.toString() : 'false' - if (isKubernetesPlatformFamily(flags.platform) || !yamlCr.spec.auth.openShiftoAuth) { - yamlCr.spec.auth.updateAdminPassword = true + if (isKubernetesPlatformFamily(flags.platform) || !cheClusterCR.spec.auth.openShiftoAuth) { + cheClusterCR.spec.auth.updateAdminPassword = true } - if (!yamlCr.spec.k8s) { - yamlCr.spec.k8s = {} + if (!cheClusterCR.spec.k8s) { + cheClusterCR.spec.k8s = {} } if (flags.tls) { - yamlCr.spec.server.tlsSupport = flags.tls - if (!yamlCr.spec.k8s.tlsSecretName) { - yamlCr.spec.k8s.tlsSecretName = 'che-tls' + cheClusterCR.spec.server.tlsSupport = flags.tls + if (!cheClusterCR.spec.k8s.tlsSecretName) { + cheClusterCR.spec.k8s.tlsSecretName = 'che-tls' } } if (flags.domain) { - yamlCr.spec.k8s.ingressDomain = flags.domain + cheClusterCR.spec.k8s.ingressDomain = flags.domain } const pluginRegistryUrl = flags['plugin-registry-url'] if (pluginRegistryUrl) { - yamlCr.spec.server.pluginRegistryUrl = pluginRegistryUrl - yamlCr.spec.server.externalPluginRegistry = true + cheClusterCR.spec.server.pluginRegistryUrl = pluginRegistryUrl + cheClusterCR.spec.server.externalPluginRegistry = true } const devfileRegistryUrl = flags['devfile-registry-url'] if (devfileRegistryUrl) { - yamlCr.spec.server.devfileRegistryUrl = devfileRegistryUrl - yamlCr.spec.server.externalDevfileRegistry = true + cheClusterCR.spec.server.devfileRegistryUrl = devfileRegistryUrl + cheClusterCR.spec.server.externalDevfileRegistry = true } - yamlCr.spec.storage.postgresPVCStorageClassName = flags['postgres-pvc-storage-class-name'] - yamlCr.spec.storage.workspacePVCStorageClassName = flags['workspace-pvc-storage-class-name'] + cheClusterCR.spec.storage.postgresPVCStorageClassName = flags['postgres-pvc-storage-class-name'] + cheClusterCR.spec.storage.workspacePVCStorageClassName = flags['workspace-pvc-storage-class-name'] if (flags.cheimage === DEFAULT_CHE_IMAGE && - yamlCr.spec.server.cheImageTag !== 'nightly' && - yamlCr.spec.server.cheImageTag !== 'latest') { + cheClusterCR.spec.server.cheImageTag !== 'nightly' && + cheClusterCR.spec.server.cheImageTag !== 'latest') { // We obviously are using a release version of chectl with the default `cheimage` // => We should use the operator defaults for docker images - yamlCr.spec.server.cheImage = '' - yamlCr.spec.server.cheImageTag = '' - yamlCr.spec.server.pluginRegistryImage = '' - yamlCr.spec.server.devfileRegistryImage = '' - yamlCr.spec.auth.identityProviderImage = '' + cheClusterCR.spec.server.cheImage = '' + cheClusterCR.spec.server.cheImageTag = '' + cheClusterCR.spec.server.pluginRegistryImage = '' + cheClusterCR.spec.server.devfileRegistryImage = '' + cheClusterCR.spec.auth.identityProviderImage = '' } } // override default values if (ctx.CRPatch) { - merge(yamlCr, ctx.CRPatch) + merge(cheClusterCR, ctx.CRPatch) } // Back off some configuration properties(chectl estimated them like not working or not desired) - merge(yamlCr, ctx.CROverrides) + merge(cheClusterCR, ctx.CROverrides) const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi) try { - const { body } = await customObjectsApi.createNamespacedCustomObject('org.eclipse.che', 'v1', cheNamespace, 'checlusters', yamlCr) + const { body } = await customObjectsApi.createNamespacedCustomObject('org.eclipse.che', 'v1', cheNamespace, 'checlusters', cheClusterCR) return body } catch (e) { throw this.wrapK8sClientError(e) @@ -1723,7 +1721,7 @@ export class KubeHelper { if (installPlan.status && installPlan.status.conditions) { for (const condition of installPlan.status.conditions) { if (condition.type === 'Installed' && condition.status === 'True') { - resolve() + resolve(installPlan) } } } @@ -1741,6 +1739,11 @@ export class KubeHelper { }) } + async getCSV(csvName: string, namespace: string): Promise { + const csvs = await this.getClusterServiceVersions(namespace) + return csvs.items.find(item => item.metadata.name === csvName) + } + async getClusterServiceVersions(namespace: string): Promise { const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi) try { diff --git a/src/api/typings/olm.d.ts b/src/api/typings/olm.d.ts index c9e336101..982624f9a 100644 --- a/src/api/typings/olm.d.ts +++ b/src/api/typings/olm.d.ts @@ -43,6 +43,7 @@ export interface SubscriptionSpec { export interface SubscriptionStatus { conditions: SubscriptionStatusCondition[] currentCSV: string + installedCSV?: string installplan: InstallPlan state: string } @@ -119,7 +120,7 @@ export interface CatalogSourceSpec { mediatype?: string sourceType: string image: string - updateStrategy: CatalogSourceUpdateStrategy + updateStrategy?: CatalogSourceUpdateStrategy } export interface CatalogSourceUpdateStrategy { diff --git a/src/commands/server/deploy.ts b/src/commands/server/deploy.ts index a15986ddc..bb838f7a3 100644 --- a/src/commands/server/deploy.ts +++ b/src/commands/server/deploy.ts @@ -12,14 +12,13 @@ import { Command, flags } from '@oclif/command' import { boolean, string } from '@oclif/parser/lib/flags' import { cli } from 'cli-ux' import * as fs from 'fs-extra' -import * as yaml from 'js-yaml' import * as Listr from 'listr' import * as notifier from 'node-notifier' import * as os from 'os' import * as path from 'path' import { KubeHelper } from '../../api/kube' -import { cheDeployment, cheNamespace, cheOperatorCRPatchYaml, CHE_OPERATOR_CR_PATCH_YAML_KEY, devWorkspaceControllerNamespace, listrRenderer, skipKubeHealthzCheck as skipK8sHealthCheck } from '../../common-flags' +import { cheDeployment, cheNamespace, cheOperatorCRPatchYaml, cheOperatorCRYaml, CHE_OPERATOR_CR_PATCH_YAML_KEY, CHE_OPERATOR_CR_YAML_KEY, devWorkspaceControllerNamespace, listrRenderer, skipKubeHealthzCheck as skipK8sHealthCheck } from '../../common-flags' import { DEFAULT_CHE_OPERATOR_IMAGE, DEFAULT_DEV_WORKSPACE_CONTROLLER_IMAGE, DOCS_LINK_INSTALL_RUNNING_CHE_LOCALLY } from '../../constants' import { CheTasks } from '../../tasks/che' import { DevWorkspaceTasks } from '../../tasks/component-installers/devfile-workspace-operator-installer' @@ -28,7 +27,7 @@ import { InstallerTasks } from '../../tasks/installers/installer' import { ApiTasks } from '../../tasks/platforms/api' import { CommonPlatformTasks } from '../../tasks/platforms/common-platform-tasks' import { PlatformTasks } from '../../tasks/platforms/platform' -import { getCommandSuccessMessage, initializeContext, isOpenshiftPlatformFamily, readCRPatchFile } from '../../util' +import { getCommandSuccessMessage, initializeContext, isOpenshiftPlatformFamily, readCRFile } from '../../util' export default class Deploy extends Command { static description = 'start Eclipse Che server' @@ -118,10 +117,7 @@ export default class Deploy extends Command { description: 'Container image of the operator. This parameter is used only when the installer is the operator', default: DEFAULT_CHE_OPERATOR_IMAGE }), - 'che-operator-cr-yaml': string({ - description: 'Path to a yaml file that defines a CheCluster used by the operator. This parameter is used only when the installer is the \'operator\' or the \'olm\'.', - default: '' - }), + [CHE_OPERATOR_CR_YAML_KEY]: cheOperatorCRYaml, [CHE_OPERATOR_CR_PATCH_YAML_KEY]: cheOperatorCRPatchYaml, directory: string({ char: 'd', @@ -200,7 +196,7 @@ export default class Deploy extends Command { } async setPlaformDefaults(flags: any, ctx: any): Promise { - flags.tls = await this.checkTlsMode(flags, ctx) + flags.tls = await this.checkTlsMode(ctx) if (!flags.installer) { await this.setDefaultInstaller(flags) @@ -243,27 +239,22 @@ export default class Deploy extends Command { * Checks if TLS is disabled via operator custom resource. * Returns true if TLS is enabled (or omitted) and false if it is explicitly disabled. */ - async checkTlsMode(flags: any, ctx: any): Promise { + async checkTlsMode(ctx: any): Promise { const crPatch = ctx.CRPatch if (crPatch && crPatch.spec && crPatch.spec.server && crPatch.spec.server.tlsSupport === false) { return false } - if (flags['che-operator-cr-yaml']) { - const cheOperatorCrYamlPath = flags['che-operator-cr-yaml'] - if (fs.existsSync(cheOperatorCrYamlPath)) { - const cr: any = yaml.safeLoad(fs.readFileSync(cheOperatorCrYamlPath).toString()) - if (cr && cr.spec && cr.spec.server && cr.spec.server.tlsSupport === false) { - return false - } - } + const customCR = ctx.customCR + if (customCR && customCR.spec && customCR.spec.server && customCR.spec.server.tlsSupport === false) { + return false } return true } checkPlatformCompatibility(flags: any) { - if (flags.installer === 'operator' && flags['che-operator-cr-yaml']) { + if (flags.installer === 'operator' && flags[CHE_OPERATOR_CR_YAML_KEY]) { const ignoredFlags = [] flags['plugin-registry-url'] && ignoredFlags.push('--plugin-registry-url') flags['devfile-registry-url'] && ignoredFlags.push('--devfile-registry-url') @@ -276,11 +267,11 @@ export default class Deploy extends Command { flags.multiuser && ignoredFlags.push('--multiuser') if (ignoredFlags.length) { - this.warn(`--che-operator-cr-yaml is used. The following flag(s) will be ignored: ${ignoredFlags.join('\t')}`) + this.warn(`--${CHE_OPERATOR_CR_YAML_KEY} is used. The following flag(s) will be ignored: ${ignoredFlags.join('\t')}`) } } - if (flags.domain && !flags['che-operator-cr-yaml'] && isOpenshiftPlatformFamily(flags.platform)) { + if (flags.domain && !flags[CHE_OPERATOR_CR_YAML_KEY] && isOpenshiftPlatformFamily(flags.platform)) { this.warn('"--domain" flag is ignored for Openshift family infrastructures. It should be done on the cluster level.') } @@ -343,7 +334,8 @@ export default class Deploy extends Command { ctx.directory = path.resolve(flags.directory ? flags.directory : path.resolve(os.tmpdir(), 'chectl-logs', Date.now().toString())) const listrOptions: Listr.ListrOptions = { renderer: (flags['listr-renderer'] as any), collapse: false, showSubtasks: true } as Listr.ListrOptions ctx.listrOptions = listrOptions - ctx.CRPatch = readCRPatchFile(flags, this) + ctx.customCR = readCRFile(flags, CHE_OPERATOR_CR_YAML_KEY , this) + ctx.CRPatch = readCRFile(flags, CHE_OPERATOR_CR_PATCH_YAML_KEY, this) if (flags['self-signed-cert']) { this.warn('"self-signed-cert" flag is deprecated and has no effect. Autodetection is used instead.') diff --git a/src/commands/server/update.ts b/src/commands/server/update.ts index a57a3205b..3c641e86b 100644 --- a/src/commands/server/update.ts +++ b/src/commands/server/update.ts @@ -25,7 +25,7 @@ import { InstallerTasks } from '../../tasks/installers/installer' import { ApiTasks } from '../../tasks/platforms/api' import { CommonPlatformTasks } from '../../tasks/platforms/common-platform-tasks' import { PlatformTasks } from '../../tasks/platforms/platform' -import { getCommandSuccessMessage, getImageTag, initializeContext, isKubernetesPlatformFamily, readCRPatchFile } from '../../util' +import { getCommandSuccessMessage, getImageTag, initializeContext, isKubernetesPlatformFamily, readCRFile } from '../../util' export default class Update extends Command { static description = 'Update Eclipse Che server.' @@ -96,7 +96,7 @@ export default class Update extends Command { const ctx = initializeContext() const listrOptions: Listr.ListrOptions = { renderer: (flags['listr-renderer'] as any), collapse: false } as Listr.ListrOptions ctx.listrOptions = listrOptions - ctx.CRPatch = readCRPatchFile(flags, this) + ctx.CRPatch = readCRFile(flags, CHE_OPERATOR_CR_PATCH_YAML_KEY, this) const cheTasks = new CheTasks(flags) const kubeHelper = new KubeHelper(flags) diff --git a/src/common-flags.ts b/src/common-flags.ts index e05b09787..418437a6f 100644 --- a/src/common-flags.ts +++ b/src/common-flags.ts @@ -60,6 +60,12 @@ export const cheOperatorCRPatchYaml = string({ default: '' }) +export const CHE_OPERATOR_CR_YAML_KEY = 'che-operator-cr-yaml' +export const cheOperatorCRYaml = string({ + description: 'Path to a yaml file that defines a CheCluster used by the operator. This parameter is used only when the installer is the \'operator\' or the \'olm\'.', + default: '' +}) + export const USERNAME_KEY = 'username' export const username = string({ char: 'u', diff --git a/src/tasks/installers/common-tasks.ts b/src/tasks/installers/common-tasks.ts index 1d2f54b26..735ddc980 100644 --- a/src/tasks/installers/common-tasks.ts +++ b/src/tasks/installers/common-tasks.ts @@ -64,33 +64,29 @@ async function copyCheOperatorResources(templatesDir: string, cacheDir: string): export function createEclipseCheCluster(flags: any, kube: KubeHelper): Listr.ListrTask { return { title: `Create the Custom Resource of type ${CHE_CLUSTER_CRD} in the namespace ${flags.chenamespace}`, + enabled: ctx => !!ctx.customCR || !!ctx.defaultCR, task: async (ctx: any, task: any) => { - const cheCluster = await kube.getCheCluster(flags.chenamespace) - if (cheCluster) { - task.title = `${task.title}...It already exists.` - } else { - ctx.isCheDeployed = true - ctx.isPostgresDeployed = true - ctx.isKeycloakDeployed = true - - // plugin and devfile registry will be deployed only when external ones are not configured - ctx.isPluginRegistryDeployed = !(flags['plugin-registry-url'] as boolean) - ctx.isDevfileRegistryDeployed = !(flags['devfile-registry-url'] as boolean) - - const yamlFilePath = flags['che-operator-cr-yaml'] === '' ? ctx.resourcesPath + 'crds/org_v1_che_cr.yaml' : flags['che-operator-cr-yaml'] - const cr = await kube.createCheClusterFromFile(yamlFilePath, flags, ctx, flags['che-operator-cr-yaml'] === '') - ctx.cr = cr - ctx.isKeycloakReady = ctx.isKeycloakReady || cr.spec.auth.externalIdentityProvider - ctx.isPostgresReady = ctx.isPostgresReady || cr.spec.database.externalDb - ctx.isDevfileRegistryReady = ctx.isDevfileRegistryReady || cr.spec.server.externalDevfileRegistry - ctx.isPluginRegistryReady = ctx.isPluginRegistryReady || cr.spec.server.externalPluginRegistry - - if (cr.spec.server.customCheProperties && cr.spec.server.customCheProperties.CHE_MULTIUSER === 'false') { - flags.multiuser = false - } + ctx.isCheDeployed = true + ctx.isPostgresDeployed = true + ctx.isKeycloakDeployed = true - task.title = `${task.title}...done.` + // plugin and devfile registry will be deployed only when external ones are not configured + ctx.isPluginRegistryDeployed = !(flags['plugin-registry-url'] as boolean) + ctx.isDevfileRegistryDeployed = !(flags['devfile-registry-url'] as boolean) + + const cheClusterCR = ctx.customCR || ctx.defaultCR + const cr = await kube.createCheCluster(cheClusterCR, flags, ctx, !ctx.customCR) + + ctx.isKeycloakReady = ctx.isKeycloakReady || cr.spec.auth.externalIdentityProvider + ctx.isPostgresReady = ctx.isPostgresReady || cr.spec.database.externalDb + ctx.isDevfileRegistryReady = ctx.isDevfileRegistryReady || cr.spec.server.externalDevfileRegistry + ctx.isPluginRegistryReady = ctx.isPluginRegistryReady || cr.spec.server.externalPluginRegistry + + if (cr.spec.server.customCheProperties && cr.spec.server.customCheProperties.CHE_MULTIUSER === 'false') { + flags.multiuser = false } + + task.title = `${task.title}...done.` } } } diff --git a/src/tasks/installers/olm.ts b/src/tasks/installers/olm.ts index f69d7d267..14e2adb1b 100644 --- a/src/tasks/installers/olm.ts +++ b/src/tasks/installers/olm.ts @@ -10,6 +10,7 @@ import Command from '@oclif/command' import { cli } from 'cli-ux' +import * as yaml from 'js-yaml' import Listr = require('listr') import { KubeHelper } from '../../api/kube' @@ -17,7 +18,7 @@ import { CatalogSource, Subscription } from '../../api/typings/olm' import { CUSTOM_CATALOG_SOURCE_NAME, CVS_PREFIX, DEFAULT_CHE_OLM_PACKAGE_NAME, DEFAULT_OLM_KUBERNETES_NAMESPACE, DEFAULT_OPENSHIFT_MARKET_PLACE_NAMESPACE, KUBERNETES_OLM_CATALOG, NIGHTLY_CATALOG_SOURCE_NAME, OLM_NIGHTLY_CHANNEL_NAME, OLM_STABLE_CHANNEL_NAME, OPENSHIFT_OLM_CATALOG, OPERATOR_GROUP_NAME, SUBSCRIPTION_NAME } from '../../constants' import { isKubernetesPlatformFamily, isStableVersion } from '../../util' -import { copyOperatorResources, createEclipseCheCluster, createNamespaceTask, updateEclipseCheCluster } from './common-tasks' +import { createEclipseCheCluster, createNamespaceTask, updateEclipseCheCluster } from './common-tasks' export class OLMTasks { /** @@ -27,7 +28,6 @@ export class OLMTasks { const kube = new KubeHelper(flags) return new Listr([ this.isOlmPreInstalledTask(command, kube), - copyOperatorResources(flags, command.config.cacheDir), createNamespaceTask(flags.chenamespace, flags.platform), { title: 'Create operator group', @@ -150,6 +150,22 @@ export class OLMTasks { task.title = `${task.title}... changed to ${flags['che-operator-image']}.` } }, + { + title: 'Prepare Eclipse Che cluster CR', + task: async (ctx: any, task: any) => { + const cheCluster = await kube.getCheCluster(flags.chenamespace) + if (cheCluster) { + task.title = `${task.title}...It already exists..` + return + } + + if (!ctx.customCR) { + ctx.defaultCR = await this.getCRFromCSV(kube, flags.chenamespace) + } + + task.title = `${task.title}...Done.` + } + }, createEclipseCheCluster(flags, kube) ], { renderer: flags['listr-renderer'] as any }) } @@ -338,4 +354,16 @@ export class OLMTasks { } } } + + private async getCRFromCSV(kube: KubeHelper, cheNamespace: string): Promise { + const subscription: Subscription = await kube.getOperatorSubscription(SUBSCRIPTION_NAME, cheNamespace) + const currentCSV = subscription.status!.currentCSV + const csv = await kube.getCSV(currentCSV, cheNamespace) + if (csv && csv.metadata.annotations) { + const CRRaw = csv.metadata.annotations!['alm-examples'] + return (yaml.safeLoad(CRRaw) as Array)[0] + } else { + throw new Error(`Unable to retrieve Che cluster CR definition from CSV: ${currentCSV}`) + } + } } diff --git a/src/tasks/installers/operator.ts b/src/tasks/installers/operator.ts index 69f9c8fd6..5d2a47649 100644 --- a/src/tasks/installers/operator.ts +++ b/src/tasks/installers/operator.ts @@ -157,6 +157,23 @@ export class OperatorTasks { title: 'Operator pod bootstrap', task: () => kubeTasks.podStartTasks(OperatorTasks.CHE_OPERATOR_SELECTOR, flags.chenamespace) }, + { + title: 'Prepare Eclipse Che cluster CR', + task: async (ctx: any, task: any) => { + const cheCluster = await kube.getCheCluster(flags.chenamespace) + if (cheCluster) { + task.title = `${task.title}...It already exists..` + return + } + + if (!ctx.customCR) { + const yamlFilePath = ctx.resourcesPath + 'crds/org_v1_che_cr.yaml' + ctx.defaultCR = yaml.safeLoad(fs.readFileSync(yamlFilePath).toString()) + } + + task.title = `${task.title}...Done.` + } + }, createEclipseCheCluster(flags, kube) ], { renderer: flags['listr-renderer'] as any }) } diff --git a/src/tasks/platforms/common-platform-tasks.ts b/src/tasks/platforms/common-platform-tasks.ts index bbcacd8c3..44c543ed2 100644 --- a/src/tasks/platforms/common-platform-tasks.ts +++ b/src/tasks/platforms/common-platform-tasks.ts @@ -9,10 +9,8 @@ **********************************************************************/ import ansi = require('ansi-colors') -import * as fs from 'fs-extra' import * as http from 'http' import * as https from 'https' -import * as yaml from 'js-yaml' import * as Listr from 'listr' import { KubeHelper } from '../../api/kube' @@ -83,7 +81,7 @@ export namespace CommonPlatformTasks { let kube = new KubeHelper(flags) return { title: 'Verify Openshift oauth.', - enabled: ctx => isOpenshiftPlatformFamily(flags.platform) && isOAuthEnabled(flags, ctx), + enabled: ctx => isOpenshiftPlatformFamily(flags.platform) && isOAuthEnabled(ctx), task: async (ctx: any, task: any) => { if (await kube.isOpenShift4()) { const providers = await kube.getOpenshiftAuthProviders() @@ -106,20 +104,15 @@ export namespace CommonPlatformTasks { * Checks if Openshift oAuth enabled in Che configuration. * Returns true if Openshift oAuth is enabled (or omitted) and false if it is explicitly disabled. */ - function isOAuthEnabled(flags: any, ctx: any): boolean { + function isOAuthEnabled(ctx: any): boolean { const crPatch = ctx.CRPatch if (crPatch && crPatch.spec && crPatch.spec.auth && typeof crPatch.spec.auth.openShiftoAuth === 'boolean') { return crPatch.spec.auth.openShiftoAuth } - if (flags['che-operator-cr-yaml']) { - const cheOperatorCrYamlPath = flags['che-operator-cr-yaml'] - if (fs.existsSync(cheOperatorCrYamlPath)) { - const cr: any = yaml.safeLoad(fs.readFileSync(cheOperatorCrYamlPath).toString()) - if (cr && cr.spec && cr.spec.auth && typeof cr.spec.auth.openShiftoAuth === 'boolean') { - return cr.spec.auth.openShiftoAuth - } - } + const customCR = ctx.customCR + if (customCR && customCR.spec && customCR.spec.auth && typeof customCR.spec.auth.openShiftoAuth === 'boolean') { + return customCR.spec.auth.openShiftoAuth } return true diff --git a/src/util.ts b/src/util.ts index 25a62a036..b882c7fc1 100644 --- a/src/util.ts +++ b/src/util.ts @@ -13,7 +13,6 @@ import * as commandExists from 'command-exists' import { existsSync, readFileSync } from 'fs-extra' import * as yaml from 'js-yaml' -import { CHE_OPERATOR_CR_PATCH_YAML_KEY } from './common-flags' import { DEFAULT_CHE_OPERATOR_IMAGE } from './constants' export const KUBERNETES_CLI = 'kubectl' @@ -111,21 +110,22 @@ export function initializeContext(): any { } /** - * Returns CR patch file content. Throws an error, if file doesn't exist. + * Returns CR file content. Throws an error, if file doesn't exist. * @param flags - parent command flags + * @param CRKey - key for CR file flag * @param command - parent command */ -export function readCRPatchFile(flags: any, command: Command): any { - const cheOperatorCrPatchYamlPath = flags[CHE_OPERATOR_CR_PATCH_YAML_KEY] - if (!cheOperatorCrPatchYamlPath) { +export function readCRFile(flags: any, CRKey: string, command: Command): any { + const CRFilePath = flags[CRKey] + if (!CRFilePath) { return } - if (existsSync(cheOperatorCrPatchYamlPath)) { - return yaml.safeLoad(readFileSync(cheOperatorCrPatchYamlPath).toString()) + if (existsSync(CRFilePath)) { + return yaml.safeLoad(readFileSync(CRFilePath).toString()) } - command.error(`Unable to find patch file defined in the flag '--${CHE_OPERATOR_CR_PATCH_YAML_KEY}'`) + command.error(`Unable to find file defined in the flag '--${CRKey}'`) } /**