Skip to content

Commit

Permalink
Enhance post installation messages (#913)
Browse files Browse the repository at this point in the history
Signed-off-by: Anatolii Bazko <abazko@redhat.com>
  • Loading branch information
tolusha committed Oct 9, 2020
1 parent 4ecde0d commit 91d2751
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 54 deletions.
25 changes: 21 additions & 4 deletions src/api/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import execa = require('execa')
import Listr = require('listr')

import { CheTasks } from '../tasks/che'
import { getClusterClientCommand } from '../util'

import { KubeHelper } from './kube'
Expand Down Expand Up @@ -136,14 +137,30 @@ export namespace VersionHelper {
return stdout.split('\n').filter(value => value.startsWith(versionPrefix)).map(value => value.substring(versionPrefix.length))[0]
}

export async function getCheVersionFromPod(namespace: string, podName: string): Promise<string> {
/**
* Returns Eclipse Che version.
*/
export async function getCheVersion(flags: any): Promise<string> {
const kube = new KubeHelper(flags)
const cheTasks = new CheTasks(flags)
const cheCluster = await kube.getCheCluster(flags.chenamespace)
if (cheCluster && cheCluster.spec.server.cheFlavor !== 'che') {
return cheCluster.status.cheVersion
}

const chePodList = await kube.getPodListByLabel(flags.chenamespace, cheTasks.cheSelector)
const [chePodName] = chePodList.map(pod => pod.metadata && pod.metadata.name)
if (!chePodName) {
return 'UNKNOWN'
}

const command = getClusterClientCommand()
const args = ['exec', podName, '--namespace', namespace, 'cat', CHE_POD_MANIFEST_FILE]
const args = ['exec', chePodName, '--namespace', flags.chenamespace, 'cat', CHE_POD_MANIFEST_FILE]
try {
const { stdout } = await execa(command, args, { timeout: 60000 })
return stdout.split('\n').filter(value => value.startsWith(CHE_PREFFIX_VERSION)).map(value => value.substring(CHE_PREFFIX_VERSION.length))[0]
} catch (error) {
throw new Error(`E_COMMAND_FAILED: ${error}`)
} catch {
return 'UNKNOWN'
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/commands/server/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { MinishiftAddonTasks } from '../../tasks/installers/minishift-addon'
import { OLMTasks } from '../../tasks/installers/olm'
import { OperatorTasks } from '../../tasks/installers/operator'
import { ApiTasks } from '../../tasks/platforms/api'
import { getCommandSuccessMessage, initializeContext } from '../../util'

export default class Delete extends Command {
static description = 'delete any Eclipse Che related resource: Kubernetes/OpenShift/Helm'
Expand All @@ -44,6 +45,7 @@ export default class Delete extends Command {
}

async run() {
const ctx = initializeContext()
const { flags } = this.parse(Delete)

const notifier = require('node-notifier')
Expand Down Expand Up @@ -84,11 +86,16 @@ export default class Delete extends Command {
}
}

await tasks.run()
try {
await tasks.run()
cli.log(getCommandSuccessMessage(this, ctx))
} catch (error) {
cli.error(error)
}

notifier.notify({
title: 'chectl',
message: 'Command server:delete has completed.'
message: getCommandSuccessMessage(this, ctx)
})

this.exit(0)
Expand Down
11 changes: 5 additions & 6 deletions src/commands/server/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,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 { isOpenshiftPlatformFamily } from '../../util'
import { getCommandSuccessMessage, initializeContext, isOpenshiftPlatformFamily } from '../../util'

export default class Start extends Command {
static description = 'start Eclipse Che server'
Expand Down Expand Up @@ -343,12 +343,10 @@ export default class Start extends Command {

async run() {
const { flags } = this.parse(Start)
const ctx: any = {}
const ctx = initializeContext()
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
// Holds messages which should be printed at the end of chectl log
ctx.highlightedMessages = [] as string[]

if (flags['self-signed-cert']) {
this.warn('"self-signed-cert" flag is deprecated and has no effect. Autodetection is used instead.')
Expand Down Expand Up @@ -394,6 +392,7 @@ export default class Start extends Command {
},
getRetrieveKeycloakCredentialsTask(flags),
retrieveCheCaCertificateTask(flags),
...cheTasks.preparePostInstallationOutput(flags),
getPrintHighlightedMessagesTask(),
], listrOptions)

Expand Down Expand Up @@ -429,7 +428,7 @@ export default class Start extends Command {
}

await postInstallTasks.run(ctx)
this.log('Command server:start has completed successfully.')
this.log(getCommandSuccessMessage(this, ctx))
} catch (err) {
const isDirEmpty = await this.isDirEmpty(ctx.directory)
if (isDirEmpty) {
Expand All @@ -440,7 +439,7 @@ export default class Start extends Command {

notifier.notify({
title: 'chectl',
message: 'Command server:start has completed successfully.'
message: getCommandSuccessMessage(this, ctx)
})

this.exit(0)
Expand Down
13 changes: 3 additions & 10 deletions src/commands/server/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { CheHelper } from '../../api/che'
import { KubeHelper } from '../../api/kube'
import { VersionHelper } from '../../api/version'
import { cheNamespace } from '../../common-flags'
import { CheTasks } from '../../tasks/che'

export default class List extends Command {
// Implementation-Version it is a property from Manifest.ml inside of che server pod which indicate Eclipse Che build version.
static description = 'status Eclipse Che server'
Expand All @@ -30,24 +30,17 @@ export default class List extends Command {
const { flags } = this.parse(List)
const kube = new KubeHelper(flags)
const che = new CheHelper(flags)
const cheTask = new CheTasks(flags)

let openshiftOauth = 'No'
let cheVersion = 'UNKNOWN'

const cr = await kube.getCheCluster(flags.chenamespace)
if (cr && cr.spec && cr.spec.auth && cr.spec.auth.openShiftoAuth) {
openshiftOauth = 'Yes'
}

const chePodList = await kube.getPodListByLabel(flags.chenamespace, cheTask.cheSelector)
const [chePodName] = chePodList.map(pod => pod.metadata && pod.metadata.name)

if (chePodName) {
cheVersion = await VersionHelper.getCheVersionFromPod(flags.chenamespace, chePodName)
}
const cheVersion = await VersionHelper.getCheVersion(flags)

cli.log(`Eclipse Che Verion : ${cheVersion}`)
cli.log(`Eclipse Che Version : ${cheVersion}`)
cli.log(`Eclipse Che Url : ${await che.cheURL(flags.chenamespace)}`)
cli.log(`OpenShift OAuth enabled: ${openshiftOauth}\n`)

Expand Down
7 changes: 5 additions & 2 deletions src/commands/server/stop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@

import { Command, flags } from '@oclif/command'
import { string } from '@oclif/parser/lib/flags'
import { cli } from 'cli-ux'

import { accessToken, cheDeployment, cheNamespace, devWorkspaceControllerNamespace, listrRenderer, skipKubeHealthzCheck } from '../../common-flags'
import { CheTasks } from '../../tasks/che'
import { ApiTasks } from '../../tasks/platforms/api'
import { getCommandSuccessMessage, initializeContext } from '../../util'

export default class Stop extends Command {
static description = 'stop Eclipse Che server'
Expand All @@ -34,6 +36,7 @@ export default class Stop extends Command {
}

async run() {
const ctx = initializeContext()
const { flags } = this.parse(Stop)
const Listr = require('listr')
const notifier = require('node-notifier')
Expand Down Expand Up @@ -62,16 +65,16 @@ export default class Stop extends Command {
)
tasks.add(cheTasks.scaleCheDownTasks(this))
tasks.add(cheTasks.waitPodsDeletedTasks())

try {
await tasks.run()
cli.log(getCommandSuccessMessage(this, ctx))
} catch (err) {
this.error(err)
}

notifier.notify({
title: 'chectl',
message: 'Command server:stop has completed.'
message: getCommandSuccessMessage(this, ctx)
})

this.exit(0)
Expand Down
10 changes: 4 additions & 6 deletions src/commands/server/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { getImageTag, isKubernetesPlatformFamily } from '../../util'
import { getCommandSuccessMessage, getImageTag, initializeContext, isKubernetesPlatformFamily } from '../../util'

export default class Update extends Command {
static description = 'Update Eclipse Che server.'
Expand Down Expand Up @@ -92,11 +92,9 @@ export default class Update extends Command {

async run() {
const { flags } = this.parse(Update)
const ctx: any = {}
const ctx = initializeContext()
const listrOptions: Listr.ListrOptions = { renderer: (flags['listr-renderer'] as any), collapse: false } as Listr.ListrOptions
ctx.listrOptions = listrOptions
// Holds messages which should be printed at the end of chectl log
ctx.highlightedMessages = [] as string[]

const cheTasks = new CheTasks(flags)
const kubeHelper = new KubeHelper(flags)
Expand Down Expand Up @@ -176,14 +174,14 @@ export default class Update extends Command {
await updateTasks.run(ctx)
await postUpdateTasks.run(ctx)
}
this.log('Command server:update has completed successfully.')
this.log(getCommandSuccessMessage(this, ctx))
} catch (err) {
this.error(err)
}

notifier.notify({
title: 'chectl',
message: 'Command server:start has completed successfully.'
message: getCommandSuccessMessage(this, ctx)
})

this.exit(0)
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const CVS_PREFIX = 'eclipse-che'
export const NIGHTLY_CATALOG_SOURCE_NAME = 'eclipse-che-preview'

// Documentation links
export const DOC_LINK = 'https://www.eclipse.org/che/docs/'
export const DOC_LINK_RELEASE_NOTES = ''
export const DOCS_LINK_INSTALL_RUNNING_CHE_LOCALLY = 'https://www.eclipse.org/che/docs/che-7/overview/running-che-locally/'
export const DOCS_LINK_IMPORT_CA_CERT_INTO_BROWSER = 'https://www.eclipse.org/che/docs/che-7/overview/importing-certificates-to-browsers/'
export const DOCS_LINK_HOW_TO_ADD_IDENTITY_PROVIDER_OS4 = 'https://docs.openshift.com/container-platform/latest/authentication/understanding-identity-provider.html#identity-provider-overview_understanding-identity-provider'
Expand Down
42 changes: 36 additions & 6 deletions src/tasks/che.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { CheHelper } from '../api/che'
import { CheApiClient } from '../api/che-api-client'
import { KubeHelper } from '../api/kube'
import { OpenShiftHelper } from '../api/openshift'
import { DOC_LINK_OBTAIN_ACCESS_TOKEN, DOC_LINK_OBTAIN_ACCESS_TOKEN_OAUTH } from '../constants'
import { VersionHelper } from '../api/version'
import { DOC_LINK, DOC_LINK_OBTAIN_ACCESS_TOKEN, DOC_LINK_OBTAIN_ACCESS_TOKEN_OAUTH, DOC_LINK_RELEASE_NOTES } from '../constants'

import { KubeTasks } from './kube'

Expand Down Expand Up @@ -96,7 +97,6 @@ export class CheTasks {
enabled: ctx => !ctx.isCheReady,
task: () => this.kubeTasks.podStartTasks(command, this.cheSelector, this.cheNamespace)
},
...this.retrieveEclipseCheUrl(flags),
...this.checkEclipseCheStatus()
]
}
Expand Down Expand Up @@ -611,13 +611,43 @@ export class CheTasks {
]
}

retrieveEclipseCheUrl(flags: any): ReadonlyArray<Listr.ListrTask> {
preparePostInstallationOutput(flags: any): ReadonlyArray<Listr.ListrTask> {
return [
{
title: 'Retrieving Eclipse Che server URL',
title: 'Prepare post installation output',
task: async (ctx: any, task: any) => {
ctx.cheURL = await this.che.cheURL(flags.chenamespace)
task.title = `${task.title}... ${ctx.cheURL}`
const version = await VersionHelper.getCheVersion(flags)
ctx.highlightedMessages.push(`Eclipse Che ${version.trim()} has successfully installed.`)

const cheUrl = await this.che.cheURL(flags.chenamespace)
ctx.highlightedMessages.push(`Users can access the Dashboard at : ${cheUrl}`)

const cheConfigMap = await this.kube.getConfigMap('che', flags.chenamespace)
if (cheConfigMap && cheConfigMap.data) {
if (cheConfigMap.data.CHE_WORKSPACE_PLUGIN__REGISTRY__URL) {
ctx.highlightedMessages.push(`Plugins can be viewed at : ${cheConfigMap.data.CHE_WORKSPACE_PLUGIN__REGISTRY__URL}`)
}
if (cheConfigMap.data.CHE_WORKSPACE_DEVFILE__REGISTRY__URL) {
ctx.highlightedMessages.push(`Devfiles can be viewed at : ${cheConfigMap.data.CHE_WORKSPACE_DEVFILE__REGISTRY__URL}`)
}
if (cheConfigMap.data.CHE_KEYCLOAK_AUTH__SERVER__URL) {
ctx.highlightedMessages.push(`Identity provider can be accessed at: ${cheConfigMap.data.CHE_KEYCLOAK_AUTH__SERVER__URL}`)
}
ctx.highlightedMessages.push(`Product documentation is at : ${DOC_LINK}`)
if (DOC_LINK_RELEASE_NOTES) {
ctx.highlightedMessages.push(`Release Notes are at : ${DOC_LINK_RELEASE_NOTES}`)
}
}

const cheCluster = await this.kube.getCheCluster(flags.chenamespace)
if (cheCluster && cheCluster.spec.auth && cheCluster.spec.auth.updateAdminPassword) {
ctx.highlightedMessages.push('Eclipse Che admin credentials : "admin:admin". You will be asked to change default Che admin password on the first login.')
}
if (ctx.identityProviderUsername && ctx.identityProviderPassword) {
ctx.highlightedMessages.push(`Identity Provider credentials : "${ctx.identityProviderUsername}:${ctx.identityProviderPassword}".`)
}

task.title = `${task.title}...done`
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion src/tasks/component-installers/cert-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export class CertManagerTasks {
const cheCaCrt = base64Decode(cheSecret.data['ca.crt'])
const cheCaCertPath = await this.cheHelper.saveCheCaCert(cheCaCrt)

// We need to put self-signed CA certificate seprately into CHE_ROOT_CA_SECRET_NAME secret
// We need to put self-signed CA certificate separately into CHE_ROOT_CA_SECRET_NAME secret
await this.kubeHelper.createSecret(CHE_ROOT_CA_SECRET_NAME, { 'ca.crt': cheCaCrt }, flags.chenamespace)

ctx.highlightedMessages.push(getMessageImportCaCertIntoBrowser(cheCaCertPath))
Expand Down
16 changes: 6 additions & 10 deletions src/tasks/installers/common-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ export function createEclipseCheCluster(flags: any, kube: KubeHelper): Listr.Lis
flags.multiuser = false
}

if (cr.spec.auth && cr.spec.auth.updateAdminPassword) {
ctx.highlightedMessages.push('Eclipse Che admin credentials are: "admin:admin". You will be asked to change default Che admin password on the first login.')
}

task.title = `${task.title}...done.`
}
}
Expand All @@ -109,7 +105,7 @@ export function retrieveCheCaCertificateTask(flags: any): Listr.ListrTask {
if (cheCaCert) {
const targetFile = await che.saveCheCaCert(cheCaCert)

task.title = `${task.title }... is exported to ${targetFile}`
task.title = `${task.title }... done`
ctx.highlightedMessages.push(getMessageImportCaCertIntoBrowser(targetFile))
} else {
task.title = `${task.title }... commonly trusted certificate is used.`
Expand All @@ -120,7 +116,7 @@ export function retrieveCheCaCertificateTask(flags: any): Listr.ListrTask {
}

export function getMessageImportCaCertIntoBrowser(caCertFileLocation: string): string {
const message = `${ansi.yellow('[MANUAL ACTION REQUIRED]')} Please add Che self-signed CA certificate into your browser: ${caCertFileLocation}.\n` +
const message = `${ansi.yellow('[ACTION REQUIRED]')} Please add Che self-signed CA certificate into your browser: ${caCertFileLocation}.\n` +
`Documentation how to add a CA certificate into a browser: ${DOCS_LINK_IMPORT_CA_CERT_INTO_BROWSER}`
return message
}
Expand All @@ -133,11 +129,11 @@ export function getRetrieveKeycloakCredentialsTask(flags: any): Listr.ListrTask
const che = new CheHelper(flags)
const [login, password] = await che.retrieveKeycloakAdminCredentials(flags.chenamespace)
if (login && password) {
ctx.highlightedMessages.push(`Autogenerated Keycloak credentials are: "${login}:${password}".`)

task.title = `${task.title }... ${login}:${password}`
ctx.identityProviderUsername = login
ctx.identityProviderPassword = password
task.title = `${task.title }...done`
} else {
task.title = `${task.title }... Failed.`
task.title = `${task.title }...failed.`
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/tasks/installers/helm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,9 @@ error: E_COMMAND_FAILED`)

if (flags.multiuser) {
// Generate Keycloak admin password
const keycloakPassword = generatePassword(12)
setOptions.push(`--set che-keycloak.keycloakAdminUserPassword=${keycloakPassword}`)
ctx.highlightedMessages.push(`Autogenerated Keycloak credentials are: "admin:${keycloakPassword}"`)
ctx.identityProviderUsername = 'admin'
ctx.identityProviderPassword = generatePassword(12)
setOptions.push(`--set che-keycloak.keycloakAdminUserPassword=${ctx.identityProviderPassword}`)
}

setOptions.push(`--set global.ingressDomain=${flags.domain}`)
Expand Down
Loading

0 comments on commit 91d2751

Please sign in to comment.