Skip to content

Commit

Permalink
Split server:deploy and server:start commands
Browse files Browse the repository at this point in the history
Signed-off-by: Anatolii Bazko <abazko@redhat.com>
  • Loading branch information
tolusha committed Nov 17, 2020
1 parent 42965c4 commit 300e892
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 109 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@
"e2e-minikube-helm": "export PLATFORM=minikube && export INSTALLER=helm && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
"e2e-minikube-operator": "export PLATFORM=minikube && export INSTALLER=operator && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
"e2e-minishift": "export PLATFORM=minishift && export INSTALLER=operator && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
"e2e-openshift": "export PLATFORM=openshift && export INSTALLER=operator && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'", "prepack": "rm -rf lib && rm -rf tsconfig.tsbuildinfo && tsc -b && oclif-dev manifest && oclif-dev readme",
"e2e-openshift": "export PLATFORM=openshift && export INSTALLER=operator && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
"prepack": "rm -rf lib && rm -rf tsconfig.tsbuildinfo && tsc -b && oclif-dev manifest && oclif-dev readme",
"pack-binaries": "oclif-dev pack",
"postpack": "rm -f oclif.manifest.json",
"format": "tsfmt -r --useTsfmt tsfmt.json",
Expand Down
78 changes: 20 additions & 58 deletions src/commands/server/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { cli } from 'cli-ux'
import * as fs from 'fs-extra'
import * as Listr from 'listr'
import * as notifier from 'node-notifier'
import * as os from 'os'
import * as path from 'path'

import { DEFAULT_K8S_POD_ERROR_RECHECK_TIMEOUT, DEFAULT_K8S_POD_TIMEOUT, KubeHelper } from '../../api/kube'
Expand All @@ -27,11 +26,10 @@ 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 } from '../../util'
import { getCommandFailMessage, getCommandSuccessMessage, initializeContext, isOpenshiftPlatformFamily } from '../../util'

export default class Deploy extends Command {
static description = 'start Eclipse Che server'
static aliases = ['server:start']
static description = 'Deploy Eclipse Che server'

static flags: flags.Input<any> = {
help: flags.help({ char: 'h' }),
Expand Down Expand Up @@ -250,18 +248,6 @@ export default class Deploy extends Command {
}
}

/**
* Determine if a directory is empty.
*/
async isDirEmpty(dirname: string): Promise<boolean> {
try {
return fs.readdirSync(dirname).length === 0
// Fails in case if directory doesn't exist
} catch {
return true
}
}

/**
* Checks if TLS is disabled via operator custom resource.
* Returns true if TLS is enabled (or omitted) and false if it is explicitly disabled.
Expand Down Expand Up @@ -352,18 +338,8 @@ export default class Deploy extends Command {
}

async run() {
if (process.argv.indexOf('server:start') > -1) {
this.warn('\'server:start\' command is deprecated. Use \'server:deploy\' instead.')
}

const { flags } = this.parse(Deploy)
const ctx = await initializeContext(flags)
ctx.directory = path.resolve(flags.directory ? flags.directory : path.resolve(os.tmpdir(), 'chectl-logs', Date.now().toString()))

if (flags.installer === 'olm' && flags['olm-suggested-namespace']) {
flags.chenamespace = DEFAULT_OLM_SUGGESTED_NAMESPACE
cli.info(` ❕olm-suggested-namespace flag is turned on. Eclipse Che will be deployed in namespace: ${DEFAULT_OLM_SUGGESTED_NAMESPACE}.`)
}

if (flags['self-signed-cert']) {
this.warn('"self-signed-cert" flag is deprecated and has no effect. Autodetection is used instead.')
Expand All @@ -388,18 +364,19 @@ export default class Deploy extends Command {
})

await this.setPlaformDefaults(flags, ctx)
let installTasks = new Listr(installerTasks.installTasks(flags, this), ctx.listrOptions)

const startDeployedCheTasks = new Listr([{
title: '👀 Starting already deployed Eclipse Che',
task: () => new Listr(cheTasks.scaleCheUpTasks(this))
}], ctx.listrOptions)
if (flags.installer === 'olm' && flags['olm-suggested-namespace']) {
flags.chenamespace = DEFAULT_OLM_SUGGESTED_NAMESPACE
cli.info(` ❕olm-suggested-namespace flag is turned on. Eclipse Che will be deployed in namespace: ${DEFAULT_OLM_SUGGESTED_NAMESPACE}.`)
}

let installTasks = new Listr(installerTasks.installTasks(flags, this), ctx.listrOptions)

// Post Install Checks
const postInstallTasks = new Listr([
{
title: '✅ Post installation checklist',
task: () => new Listr(cheTasks.waitDeployedChe(flags, this))
task: () => new Listr(cheTasks.waitDeployedChe())
},
{
title: '🧪 DevWorkspace engine (experimental / technology preview) 🚨',
Expand All @@ -414,44 +391,29 @@ export default class Deploy extends Command {
], ctx.listrOptions)

const logsTasks = new Listr([{
title: 'Start following logs',
title: 'Start following Eclipse Che logs',
task: () => new Listr(cheTasks.serverLogsTasks(flags, true))
}], ctx.listrOptions)

const eventTasks = new Listr([{
title: 'Start following events',
task: () => new Listr(cheTasks.namespaceEventsTask(flags.chenamespace, this, true))
}], ctx.listrOptions)

try {
await preInstallTasks.run(ctx)

if (!ctx.isCheDeployed) {
if (ctx.isCheDeployed) {
let message = 'Eclipse Che has been already deployed.'
if (!ctx.isCheReady) {
message += ' Use server:start command to start a stopped instance.'
}
cli.warn(message)
} else {
this.checkPlatformCompatibility(flags)
await platformCheckTasks.run(ctx)
await logsTasks.run(ctx)
await eventTasks.run(ctx)
await installTasks.run(ctx)
} else if (!ctx.isCheReady
|| (ctx.isPostgresDeployed && !ctx.isPostgresReady)
|| (ctx.isKeycloakDeployed && !ctx.isKeycloakReady)
|| (ctx.isPluginRegistryDeployed && !ctx.isPluginRegistryReady)
|| (ctx.isDevfileRegistryDeployed && !ctx.isDevfileRegistryReady)) {
if (flags.platform || flags.installer) {
this.warn('Deployed Eclipse Che is found and the specified installation parameters will be ignored')
}
// perform Eclipse Che start task if there is any component that is not ready
await startDeployedCheTasks.run(ctx)
await postInstallTasks.run(ctx)
this.log(getCommandSuccessMessage(this, ctx))
}

await postInstallTasks.run(ctx)
this.log(getCommandSuccessMessage(this, ctx))
} catch (err) {
const isDirEmpty = await this.isDirEmpty(ctx.directory)
if (isDirEmpty) {
this.error(`${err}\nInstallation failed. Error log: ${this.config.errlog}`)
}
this.error(`${err}\nInstallation failed. Error log: ${this.config.errlog}. Eclipse Che logs: ${ctx.directory}`)
this.error(`${err}\n${getCommandFailMessage(this, ctx)}`)
}

notifier.notify({
Expand Down
4 changes: 0 additions & 4 deletions src/commands/server/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import { Command, flags } from '@oclif/command'
import { string } from '@oclif/parser/lib/flags'
import * as Listr from 'listr'
import * as notifier from 'node-notifier'
import * as os from 'os'
import * as path from 'path'

import { cheDeployment, cheNamespace, listrRenderer, skipKubeHealthzCheck } from '../../common-flags'
import { CheTasks } from '../../tasks/che'
Expand All @@ -39,15 +37,13 @@ export default class Logs extends Command {
async run() {
const { flags } = this.parse(Logs)
const ctx = await initializeContext(flags)
ctx.directory = path.resolve(flags.directory ? flags.directory : path.resolve(os.tmpdir(), 'chectl-logs', Date.now().toString()))
const cheTasks = new CheTasks(flags)
const apiTasks = new ApiTasks()
const tasks = new Listr([], { renderer: flags['listr-renderer'] as any })

tasks.add(apiTasks.testApiTasks(flags, this))
tasks.add(cheTasks.verifyCheNamespaceExistsTask(flags, this))
tasks.add(cheTasks.serverLogsTasks(flags, false))
tasks.add(cheTasks.namespaceEventsTask(flags.chenamespace, this, false))

try {
this.log(`Eclipse Che logs will be available in '${ctx.directory}'`)
Expand Down
85 changes: 45 additions & 40 deletions src/tasks/che.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,15 @@ export class CheTasks {
*
* @see che.checkIfCheIsInstalledTasks
*/
waitDeployedChe(flags: any, _command: Command): ReadonlyArray<Listr.ListrTask> {
waitDeployedChe(): ReadonlyArray<Listr.ListrTask> {
return [
{
title: 'PostgreSQL pod bootstrap',
skip: () => !flags.multiuser,
enabled: ctx => ctx.isPostgresDeployed && !ctx.isPostgresReady,
task: () => this.kubeTasks.podStartTasks(this.postgresSelector, this.cheNamespace)
},
{
title: 'Keycloak pod bootstrap',
skip: () => !flags.multiuser,
enabled: ctx => ctx.isKeycloakDeployed && !ctx.isKeycloakReady,
task: () => this.kubeTasks.podStartTasks(this.keycloakSelector, this.cheNamespace)
},
Expand Down Expand Up @@ -207,43 +205,54 @@ export class CheTasks {
}

/**
* Returns tasks list which scale down all Eclipse Che components which are deployed.
* Returns tasks list which scale up all Eclipse Che components which are deployed.
* It requires {@link this#checkIfCheIsInstalledTasks} to be executed before.
*
* @see [CheTasks](#checkIfCheIsInstalledTasks)
*/
scaleCheUpTasks(_command: Command): ReadonlyArray<Listr.ListrTask> {
scaleCheUpTasks(): ReadonlyArray<Listr.ListrTask> {
return [
{
title: 'Scaling up Eclipse Che Deployments',
enabled: (ctx: any) => ctx.isCheDeployed,
task: async (ctx: any, task: any) => {
if (ctx.isPostgresDeployed) {
await this.kube.scaleDeployment(this.postgresDeploymentName, this.cheNamespace, 1)
}
if (ctx.isKeycloakDeployed) {
await this.kube.scaleDeployment(this.keycloakDeploymentName, this.cheNamespace, 1)
}
if (ctx.isPluginRegistryDeployed) {
await this.kube.scaleDeployment(this.pluginRegistryDeploymentName, this.cheNamespace, 1)
}
if (ctx.isDevfileRegistryDeployed) {
await this.kube.scaleDeployment(this.devfileRegistryDeploymentName, this.cheNamespace, 1)
}
await this.kube.scaleDeployment(this.cheDeploymentName, this.cheNamespace, 1)
task.title = `${task.title}...done.`
title: 'PostgreSQL pod bootstrap',
enabled: ctx => ctx.isPostgresDeployed && !ctx.isPostgresReady,
task: async () => {
await this.kube.scaleDeployment(this.postgresDeploymentName, this.cheNamespace, 1)
return this.kubeTasks.podStartTasks(this.postgresSelector, this.cheNamespace)
}
},
{
title: `Eclipse Che is already running in namespace \"${this.cheNamespace}\".`,
enabled: (ctx: any) => (ctx.isCheDeployed && ctx.isCheAvailable),
task: async (ctx: any, task: any) => {
ctx.cheDeploymentExist = true
ctx.cheIsAlreadyRunning = true
ctx.cheURL = await this.che.cheURL(this.cheNamespace)
task.title = await `${task.title}...it's URL is ${ctx.cheURL}`
title: 'Keycloak pod bootstrap',
enabled: ctx => ctx.isKeycloakDeployed && !ctx.isKeycloakReady,
task: async () => {
await this.kube.scaleDeployment(this.keycloakDeploymentName, this.cheNamespace, 1)
return this.kubeTasks.podStartTasks(this.keycloakSelector, this.cheNamespace)
}
}
},
{
title: 'Devfile registry pod bootstrap',
enabled: ctx => ctx.isDevfileRegistryDeployed && !ctx.isDevfileRegistryReady,
task: async () => {
await this.kube.scaleDeployment(this.devfileRegistryDeploymentName, this.cheNamespace, 1)
return this.kubeTasks.podStartTasks(this.devfileRegistrySelector, this.cheNamespace)
}
},
{
title: 'Plugin registry pod bootstrap',
enabled: ctx => ctx.isPluginRegistryDeployed && !ctx.isPluginRegistryReady,
task: async () => {
await this.kube.scaleDeployment(this.pluginRegistryDeploymentName, this.cheNamespace, 1)
return this.kubeTasks.podStartTasks(this.pluginRegistrySelector, this.cheNamespace)
}
},
{
title: 'Eclipse Che pod bootstrap',
enabled: ctx => ctx.isCheDeployed && !ctx.isCheReady,
task: async () => {
await this.kube.scaleDeployment(this.cheDeploymentName, this.cheNamespace, 1)
return this.kubeTasks.podStartTasks(this.cheSelector, this.cheNamespace)
}
},
...this.checkEclipseCheStatus()
]
}

Expand Down Expand Up @@ -525,14 +534,14 @@ export class CheTasks {
return [
{
title: `${follow ? 'Start following' : 'Read'} Operator logs`,
skip: () => flags.installer !== 'operator' && flags.installer !== 'olm',
skip: () => flags.installer === 'helm',
task: async (ctx: any, task: any) => {
await this.che.readPodLog(flags.chenamespace, CHE_OPERATOR_SELECTOR, ctx.directory, follow)
task.title = `${task.title}...done`
}
},
{
title: `${follow ? 'Start following' : 'Read'} Eclipse Che logs`,
title: `${follow ? 'Start following' : 'Read'} Eclipse Che server logs`,
task: async (ctx: any, task: any) => {
await this.che.readPodLog(flags.chenamespace, this.cheSelector, ctx.directory, follow)
task.title = await `${task.title}...done`
Expand Down Expand Up @@ -565,16 +574,11 @@ export class CheTasks {
await this.che.readPodLog(flags.chenamespace, this.devfileRegistrySelector, ctx.directory, follow)
task.title = await `${task.title}...done`
}
}
]
}

namespaceEventsTask(namespace: string, command: Command, follow: boolean): ReadonlyArray<Listr.ListrTask> {
return [
},
{
title: `${follow ? 'Start following' : 'Read'} namespace events`,
task: async (ctx: any, task: any) => {
await this.che.readNamespaceEvents(namespace, ctx.directory, follow).catch(e => command.error(e.message))
await this.che.readNamespaceEvents(flags.chenamespace, ctx.directory, follow)
task.title = await `${task.title}...done`
}
}
Expand Down Expand Up @@ -667,8 +671,9 @@ export class CheTasks {
return [
{
title: 'Eclipse Che status check',
task: async ctx => {
task: async (ctx, task) => {
const cheApi = CheApiClient.getInstance(ctx.cheURL + '/api')
task.title = `${task.title}...done`
return cheApi.isCheServerReady()
}
}
Expand Down
33 changes: 30 additions & 3 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

import { Command } from '@oclif/command'
import * as commandExists from 'command-exists'
import { existsSync, readFileSync } from 'fs-extra'
import * as fs from 'fs-extra'
import * as yaml from 'js-yaml'
import Listr = require('listr')
import * as os from 'os'
import * as path from 'path'

import { KubeHelper } from './api/kube'
import { CHE_OPERATOR_CR_PATCH_YAML_KEY, CHE_OPERATOR_CR_YAML_KEY } from './common-flags'
Expand Down Expand Up @@ -114,6 +116,7 @@ export async function initializeContext(flags?: any): Promise<any> {
ctx.startTime = Date.now()
ctx.customCR = readCRFile(flags, CHE_OPERATOR_CR_YAML_KEY)
ctx.crPatch = readCRFile(flags, CHE_OPERATOR_CR_PATCH_YAML_KEY)
ctx.directory = path.resolve(flags.directory ? flags.directory : path.resolve(os.tmpdir(), 'chectl-logs', Date.now().toString()))
if (flags['listr-renderer'] as any) {
ctx.listrOptions = { renderer: (flags['listr-renderer'] as any), collapse: false } as Listr.ListrOptions
}
Expand All @@ -132,8 +135,8 @@ export function readCRFile(flags: any, CRKey: string): any {
return
}

if (existsSync(CRFilePath)) {
return yaml.safeLoad(readFileSync(CRFilePath).toString())
if (fs.existsSync(CRFilePath)) {
return yaml.safeLoad(fs.readFileSync(CRFilePath).toString())
}

throw new Error(`Unable to find file defined in the flag '--${CRKey}'`)
Expand All @@ -158,3 +161,27 @@ export function getCommandSuccessMessage(command: Command, ctx: any): string {

return `Command ${command.id} has completed successfully.`
}

/**
* Determine if a directory is empty.
*/
export function isDirEmpty(dirname: string): boolean {
try {
return fs.readdirSync(dirname).length === 0
// Fails in case if directory doesn't exist
} catch {
return true
}
}

/**
* Returns command success message with execution time.
*/
export function getCommandFailMessage(command: Command, ctx: any): string {
let message = `Command ${command.id} failed. Error log: ${command.config.errlog}`
if (ctx.directory && isDirEmpty(ctx.directory)) {
message += ` Eclipse Che logs: ${ctx.directory}`
}

return message
}
Loading

0 comments on commit 300e892

Please sign in to comment.