Skip to content

Commit

Permalink
feat: Improve messages in server:update command (#1022)
Browse files Browse the repository at this point in the history
* Improve messages in server:update command

Signed-off-by: Anatolii Bazko <abazko@redhat.com>
  • Loading branch information
tolusha committed Dec 11, 2020
1 parent 0af053a commit 934da65
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 58 deletions.
138 changes: 112 additions & 26 deletions src/commands/server/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { string } from '@oclif/parser/lib/flags'
import { cli } from 'cli-ux'
import * as fs from 'fs-extra'
import * as Listr from 'listr'
import { merge } from 'lodash'
import * as path from 'path'

import { ChectlContext } from '../../api/context'
Expand All @@ -23,11 +24,20 @@ import { getPrintHighlightedMessagesTask } from '../../tasks/installers/common-t
import { InstallerTasks } from '../../tasks/installers/installer'
import { ApiTasks } from '../../tasks/platforms/api'
import { CommonPlatformTasks } from '../../tasks/platforms/common-platform-tasks'
import { getCommandErrorMessage, getCommandSuccessMessage, getImageTag, notifyCommandCompletedSuccessfully } from '../../util'
import { getCommandErrorMessage, getCommandSuccessMessage, getCurrentChectlName, getCurrentChectlVersion, getImageTag, getLatestChectlVersion, notifyCommandCompletedSuccessfully } from '../../util'

export default class Update extends Command {
static description = 'Update Eclipse Che server.'

static examples = [
'# Update Eclipse Che:\n' +
'chectl server:update',
'\n\n# Update Eclipse Che in \'eclipse-che\' namespace:' +
'chectl server:update -n eclipse-che',
'\n\n# Update Eclipse Che and update its configuration in the custom resource:' +
`chectl server:update --${CHE_OPERATOR_CR_PATCH_YAML_KEY} patch.yaml`,
]

static flags: flags.Input<any> = {
installer: string({
char: 'a',
Expand Down Expand Up @@ -110,40 +120,116 @@ export default class Update extends Command {

try {
await preUpdateTasks.run(ctx)
} catch (err) {
this.error(getCommandErrorMessage(err))
}

if (!flags.yes) {
cli.info(`Existed Eclipse Che operator: ${ctx.deployedCheOperatorImage}:${ctx.deployedCheOperatorTag}.`)
cli.info(`New Eclipse Che operator : ${ctx.newCheOperatorImage}:${ctx.newCheOperatorTag}.`)
if (flags.installer === 'operator') {
const existedOperatorImage = `${ctx.deployedCheOperatorImage}:${ctx.deployedCheOperatorTag}`
const newOperatorImage = `${ctx.newCheOperatorImage}:${ctx.newCheOperatorTag}`
cli.info(`Existed Eclipse Che operator: ${existedOperatorImage}.`)
cli.info(`New Eclipse Che operator : ${newOperatorImage}.`)

if (flags['che-operator-image'] !== DEFAULT_CHE_OPERATOR_IMAGE) {
cli.warn(`This command updates Eclipse Che to ${getImageTag(DEFAULT_CHE_OPERATOR_IMAGE)} version, but custom operator image is specified.`)
cli.warn('Make sure that the new version of the Eclipse Che is corresponding to the version of the tool you use.')
cli.warn('Consider using \'chectl update [stable|next]\' to update to the latest version of chectl.')
}
const defaultOperatorImageTag = getImageTag(DEFAULT_CHE_OPERATOR_IMAGE)
const chectlChannel = defaultOperatorImageTag === 'nightly' ? 'next' : 'stable'
const currentChectlVersion = getCurrentChectlVersion()
const latestChectlVersion = await getLatestChectlVersion(chectlChannel)
const chectlName = getCurrentChectlName()

const cheCluster = await kubeHelper.getCheCluster(flags.chenamespace)
if (cheCluster.spec.server.cheImage
|| cheCluster.spec.server.cheImageTag
|| cheCluster.spec.server.devfileRegistryImage
|| cheCluster.spec.database.postgresImage
|| cheCluster.spec.server.pluginRegistryImage
|| cheCluster.spec.auth.identityProviderImage) {
cli.warn(`In order to update Eclipse Che the images defined in the '${cheCluster.metadata.name}'
Custom Resource of the namespace '${flags.chenamespace}' will be cleaned up:`)
cheCluster.spec.server.cheImageTag && cli.warn(`Eclipse Che server image tag [${cheCluster.spec.server.cheImageTag}]`)
cheCluster.spec.server.cheImage && cli.warn(`Eclipse Che server [${cheCluster.spec.server.cheImage}]`)
cheCluster.spec.database.postgresImage && cli.warn(`Database [${cheCluster.spec.database.postgresImage}]`)
cheCluster.spec.server.devfileRegistryImage && cli.warn(`Devfile registry [${cheCluster.spec.server.devfileRegistryImage}]`)
cheCluster.spec.server.pluginRegistryImage && cli.warn(`Plugin registry [${cheCluster.spec.server.pluginRegistryImage}]`)
cheCluster.spec.auth.identityProviderImage && cli.warn(`Identity provider [${cheCluster.spec.auth.identityProviderImage}]`)
// the same version is already installed
if (newOperatorImage === existedOperatorImage) {
if (chectlName === 'chectl' && latestChectlVersion) {
// suggest update chectl first
if (currentChectlVersion !== latestChectlVersion) {
cli.warn(`It is not possible to update Eclipse Che to a newer version
using the current '${currentChectlVersion}' version of chectl. Please, update 'chectl'
to a newer version '${latestChectlVersion}' with the command 'chectl update ${chectlChannel}'
and then try again.`)
} else if (!flags[CHE_OPERATOR_CR_PATCH_YAML_KEY]) {
// same version, no patch then nothing to update
cli.info('Eclipse Che is already up to date.')
this.exit(0)
}
} else {
// unknown project, no patch file then suggest to update
if (!flags[CHE_OPERATOR_CR_PATCH_YAML_KEY]) {
cli.warn(`It is not possible to update Eclipse Che to a newer version
using the current '${currentChectlVersion}' version of '${getCurrentChectlName()}'.
Please, update '${getCurrentChectlName()}' and then try again.`)
this.exit(0)
}
}
// custom operator image is used
} else if (newOperatorImage !== DEFAULT_CHE_OPERATOR_IMAGE) {
cli.warn(`Eclipse Che operator deployment will be updated with the provided image,
but other Eclipse Che components will be updated to the ${defaultOperatorImageTag} version.
Consider removing '--che-operator-image' to update Eclipse Che operator to the same version.`)
}

if (!flags.yes && !await cli.confirm('If you want to continue - press Y')) {
cli.info('Update cancelled by user.')
this.exit(0)
}
}

const cheCluster = await kubeHelper.getCheCluster(flags.chenamespace)
if (cheCluster.spec.server.cheImage
|| cheCluster.spec.server.cheImageTag
|| cheCluster.spec.server.devfileRegistryImage
|| cheCluster.spec.database.postgresImage
|| cheCluster.spec.server.pluginRegistryImage
|| cheCluster.spec.auth.identityProviderImage) {
let imagesListMsg = ''

const crPatch = ctx[ChectlContext.CR_PATCH] || {}
if (cheCluster.spec.server.pluginRegistryImage
&& (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.pluginRegistryImage)) {
imagesListMsg += `\n - Plugin registry image: ${cheCluster.spec.server.pluginRegistryImage}`
merge(crPatch, { spec: { server: { pluginRegistryImage: '' } } })
}

const confirmed = await cli.confirm('If you want to continue - press Y')
if (!confirmed) {
if (cheCluster.spec.server.devfileRegistryImage
&& (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.devfileRegistryImage)) {
imagesListMsg += `\n - Devfile registry image: ${cheCluster.spec.server.devfileRegistryImage}`
merge(crPatch, { spec: { server: { devfileRegistryImage: '' } } })
}

if (cheCluster.spec.server.postgresImage
&& (!crPatch.spec || !crPatch.spec.database || !crPatch.spec.database.postgresImage)) {
imagesListMsg += `\n - Postgres image: ${cheCluster.spec.database.postgresImage}`
merge(crPatch, { spec: { database: { postgresImage: '' } } })
}

if (cheCluster.spec.server.identityProviderImage
&& (!crPatch.spec || !crPatch.spec.auth || !crPatch.spec.auth.identityProviderImage)) {
imagesListMsg += `\n - Identity provider image: ${cheCluster.spec.auth.identityProviderImage}`
merge(crPatch, { spec: { auth: { identityProviderImage: '' } } })
}

if (cheCluster.spec.server.cheImage
&& (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.cheImage)) {
imagesListMsg += `\n - Eclipse Che server image name: ${cheCluster.spec.server.cheImage}`
merge(crPatch, { spec: { server: { cheImage: '' } } })
}

if (cheCluster.spec.server.cheImageTag
&& (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.cheImageTag)) {
imagesListMsg += `\n - Eclipse Che server image tag: ${cheCluster.spec.server.cheImageTag}`
merge(crPatch, { spec: { server: { cheImageTag: '' } } })
}
ctx[ChectlContext.CR_PATCH] = crPatch

if (imagesListMsg) {
cli.warn(`In order to update Eclipse Che to a newer version the fields defining the images in the '${cheCluster.metadata.name}'
Custom Resource in the '${flags.chenamespace}' namespace will be cleaned up:${imagesListMsg}`)
if (!flags.yes && !await cli.confirm('If you want to continue - press Y')) {
cli.info('Update cancelled by user.')
this.exit(0)
}
}
}

try {
await updateTasks.run(ctx)
await postUpdateTasks.run(ctx)

Expand Down
31 changes: 7 additions & 24 deletions src/tasks/installers/common-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import Command from '@oclif/command'
import ansi = require('ansi-colors')
import { copy, mkdirp, remove } from 'fs-extra'
import * as Listr from 'listr'
import { merge } from 'lodash'
import { isEmpty } from 'lodash'
import * as path from 'path'

import { CheHelper } from '../../api/che'
import { ChectlContext } from '../../api/context'
import { KubeHelper } from '../../api/kube'
import { CHE_CLUSTER_CRD, DOCS_LINK_IMPORT_CA_CERT_INTO_BROWSER } from '../../constants'

Expand Down Expand Up @@ -97,34 +98,16 @@ export function createEclipseCheCluster(flags: any, kube: KubeHelper): Listr.Lis
* @param kube - kubeHelper util
* @param command - parent command
*/
export function updateEclipseCheCluster(flags: any, kube: KubeHelper, command: Command): Listr.ListrTask {
export function patchingEclipseCheCluster(flags: any, kube: KubeHelper, command: Command): Listr.ListrTask {
return {
title: `Update the Custom Resource of type ${CHE_CLUSTER_CRD} in the namespace ${flags.chenamespace}`,
title: `Patching the Custom Resource of type '${CHE_CLUSTER_CRD}' in the namespace '${flags.chenamespace}'`,
skip: (ctx: any) => isEmpty(ctx[ChectlContext.CR_PATCH]),
task: async (ctx: any, task: any) => {
let crPatch: any = ctx.crPatch || {}

const cheCluster = await kube.getCheCluster(flags.chenamespace)
if (!cheCluster) {
command.error(`Eclipse Che cluster CR was not found in the namespace ${flags.chenamespace}`)
}

if (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.pluginRegistryImage) {
merge(crPatch, { spec: { server: { pluginRegistryImage: '' } } })
}
if (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.devfileRegistryImage) {
merge(crPatch, { spec: { server: { devfileRegistryImage: '' } } })
command.error(`Eclipse Che cluster CR is not found in the namespace '${flags.chenamespace}'`)
}
if (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.identityProviderImage) {
merge(crPatch, { spec: { server: { identityProviderImage: '' } } })
}
if (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.cheImage) {
merge(crPatch, { spec: { server: { cheImage: '' } } })
}
if (!crPatch.spec || !crPatch.spec.server || !crPatch.spec.server.cheImageTag) {
merge(crPatch, { spec: { server: { cheImageTag: '' } } })
}

await kube.patchCheCluster(cheCluster.metadata.name, flags.chenamespace, crPatch)
await kube.patchCheCluster(cheCluster.metadata.name, flags.chenamespace, ctx[ChectlContext.CR_PATCH])
task.title = `${task.title}...done.`
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/installers/olm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,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 { createEclipseCheCluster, createNamespaceTask, updateEclipseCheCluster } from './common-tasks'
import { createEclipseCheCluster, createNamespaceTask, patchingEclipseCheCluster } from './common-tasks'

export class OLMTasks {
prometheusRoleName = 'prometheus-k8s'
Expand Down Expand Up @@ -269,7 +269,7 @@ export class OLMTasks {
task.title = `${task.title}...done.`
}
},
updateEclipseCheCluster(flags, kube, command)
patchingEclipseCheCluster(flags, kube, command)
], { renderer: flags['listr-renderer'] as any })
}

Expand Down
4 changes: 2 additions & 2 deletions src/tasks/installers/operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { CHE_CLUSTER_CRD, CHE_OPERATOR_SELECTOR, OPERATOR_DEPLOYMENT_NAME } from
import { isStableVersion } from '../../util'
import { KubeTasks } from '../kube'

import { copyOperatorResources, createEclipseCheCluster, createNamespaceTask, updateEclipseCheCluster } from './common-tasks'
import { copyOperatorResources, createEclipseCheCluster, createNamespaceTask, patchingEclipseCheCluster } from './common-tasks'

export class OperatorTasks {
operatorServiceAccount = 'che-operator'
Expand Down Expand Up @@ -380,7 +380,7 @@ export class OperatorTasks {
await kube.waitLatestReplica(OPERATOR_DEPLOYMENT_NAME, flags.chenamespace)
}
},
updateEclipseCheCluster(flags, kube, command),
patchingEclipseCheCluster(flags, kube, command),
], { renderer: flags['listr-renderer'] as any })
}

Expand Down
38 changes: 38 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import axios from 'axios'
import * as commandExists from 'command-exists'
import * as fs from 'fs-extra'
import * as https from 'https'
import * as yaml from 'js-yaml'
import * as notifier from 'node-notifier'

import * as pjson from '../package.json'

import { ChectlContext } from './api/context'
import { DEFAULT_CHE_OPERATOR_IMAGE } from './constants'

Expand Down Expand Up @@ -174,3 +178,37 @@ export function getCommandErrorMessage(err: Error): string {

return message
}

/**
* Returns current chectl version defined in package.json.
*/
export function getCurrentChectlVersion(): string {
return pjson.version
}

/**
* Returns current chectl version defined in package.json.
*/
export function getCurrentChectlName(): string {
return pjson.name
}

/**
* Returns latest chectl version for the given channel.
*/
export async function getLatestChectlVersion(channel: string): Promise<string | undefined> {
if (getCurrentChectlName() !== 'chectl') {
return
}

const axiosInstance = axios.create({
httpsAgent: new https.Agent({})
})

try {
const { data } = await axiosInstance.get(`https://che-incubator.github.io/chectl/channels/${channel}/linux-x64`)
return data.version
} catch {
return
}
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"module": "commonjs",
"moduleResolution": "node",
"target": "es6",
"sourceMap": true
"sourceMap": true,
"resolveJsonModule": true
},
"include": [
"src"
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2126,19 +2126,19 @@ ecc-jsbn@~0.1.1:

"eclipse-che-devfile-workspace-operator@git://github.com/devfile/devworkspace-operator#master":
version "0.0.0"
resolved "git://github.com/devfile/devworkspace-operator#55769df6e901c37b38384dc231e4abc5fbcdb96e"
resolved "git://github.com/devfile/devworkspace-operator#488c2a00590dab1378e4eb498ff889021c4268ba"

"eclipse-che-minishift@git://github.com/minishift/minishift#master":
version "0.0.0"
resolved "git://github.com/minishift/minishift#4b58f8954421fcbb7996ca67cba7ed8c58092a88"

"eclipse-che-operator@git://github.com/eclipse/che-operator#master":
version "0.0.0"
resolved "git://github.com/eclipse/che-operator#ed3df35359b648d19a5a775f3a2e140f5da96933"
resolved "git://github.com/eclipse/che-operator#9eee2bfc6f7791e85675bc95d76d556025132cb5"

"eclipse-che@git://github.com/eclipse/che#master":
version "0.0.0"
resolved "git://github.com/eclipse/che#6e6b773e060bd04d876b150fa7470637496e675f"
resolved "git://github.com/eclipse/che#7061f06ab1e13b947967878b0a96391ad29d7e59"

editorconfig@^0.15.0:
version "0.15.3"
Expand Down

0 comments on commit 934da65

Please sign in to comment.