Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Split functionality between server:deploy and server:star commands #990

Merged
merged 4 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ USAGE
* [`chectl server:delete`](#chectl-serverdelete)
* [`chectl server:deploy`](#chectl-serverdeploy)
* [`chectl server:logs`](#chectl-serverlogs)
* [`chectl server:start`](#chectl-serverstart)
* [`chectl server:status`](#chectl-serverstatus)
* [`chectl server:stop`](#chectl-serverstop)
* [`chectl server:update`](#chectl-serverupdate)
Expand Down Expand Up @@ -419,7 +420,7 @@ _See code: [src/commands/server/delete.ts](https://github.com/che-incubator/chec

## `chectl server:deploy`

start Eclipse Che server
Deploy Eclipse Che server

```
USAGE
Expand Down Expand Up @@ -571,9 +572,6 @@ OPTIONS

--workspace-pvc-storage-class-name=workspace-pvc-storage-class-name
persistent volume(s) storage class name to use to store Eclipse Che workspaces data

ALIASES
$ chectl server:start
```

_See code: [src/commands/server/deploy.ts](https://github.com/che-incubator/chectl/blob/v0.0.2/src/commands/server/deploy.ts)_
Expand All @@ -600,6 +598,40 @@ OPTIONS

_See code: [src/commands/server/logs.ts](https://github.com/che-incubator/chectl/blob/v0.0.2/src/commands/server/logs.ts)_

## `chectl server:start`

start Eclipse Che server

```
USAGE
$ chectl server:start

OPTIONS
-d, --directory=directory Directory to store logs into
-h, --help show CLI help

-n, --chenamespace=chenamespace [default: che] Kubernetes namespace where Eclipse Che server
is supposed to be deployed

--deployment-name=deployment-name [default: che] Eclipse Che deployment name

--k8spoddownloadimagetimeout=k8spoddownloadimagetimeout [default: 600000] Waiting time for Pod downloading image (in
milliseconds)

--k8spoderrorrechecktimeout=k8spoderrorrechecktimeout [default: 15000] Waiting time for Pod rechecking error (in
milliseconds)

--k8spodreadytimeout=k8spodreadytimeout [default: 600000] Waiting time for Pod Ready condition (in
milliseconds)

--k8spodwaittimeout=k8spodwaittimeout [default: 600000] Waiting time for Pod scheduled condition
(in milliseconds)

--skip-kubernetes-health-check Skip Kubernetes health check
```

_See code: [src/commands/server/start.ts](https://github.com/che-incubator/chectl/blob/v0.0.2/src/commands/server/start.ts)_

## `chectl server:status`

status Eclipse Che server
Expand Down
97 changes: 21 additions & 76 deletions src/commands/server/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ 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'
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 { KubeHelper } from '../../api/kube'
import { cheDeployment, cheNamespace, cheOperatorCRPatchYaml, cheOperatorCRYaml, CHE_OPERATOR_CR_PATCH_YAML_KEY, CHE_OPERATOR_CR_YAML_KEY, devWorkspaceControllerNamespace, k8sPodDownloadImageTimeout, K8SPODDOWNLOADIMAGETIMEOUT_KEY, k8sPodErrorRecheckTimeout, K8SPODERRORRECHECKTIMEOUT_KEY, k8sPodReadyTimeout, K8SPODREADYTIMEOUT_KEY, k8sPodWaitTimeout, K8SPODWAITTIMEOUT_KEY, listrRenderer, logsDirectory, LOG_DIRECTORY_KEY, skipKubeHealthzCheck as skipK8sHealthCheck } from '../../common-flags'
import { DEFAULT_CHE_OPERATOR_IMAGE, DEFAULT_DEV_WORKSPACE_CONTROLLER_IMAGE, DEFAULT_OLM_SUGGESTED_NAMESPACE, DOCS_LINK_INSTALL_RUNNING_CHE_LOCALLY } from '../../constants'
import { CheTasks } from '../../tasks/che'
import { DevWorkspaceTasks } from '../../tasks/component-installers/devfile-workspace-operator-installer'
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 { getCommandErrorMessage, 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 @@ -63,22 +61,11 @@ export default class Deploy extends Command {
required: true,
env: 'CHE_SERVER_BOOT_TIMEOUT'
}),
k8spodwaittimeout: string({
description: 'Waiting time for Pod scheduled condition (in milliseconds)',
default: `${DEFAULT_K8S_POD_TIMEOUT}`
}),
k8spoddownloadimagetimeout: string({
description: 'Waiting time for Pod downloading image (in milliseconds)',
default: `${DEFAULT_K8S_POD_TIMEOUT}`
}),
k8spodreadytimeout: string({
description: 'Waiting time for Pod Ready condition (in milliseconds)',
default: `${DEFAULT_K8S_POD_TIMEOUT}`
}),
k8spoderrorrechecktimeout: string({
description: 'Waiting time for Pod rechecking error (in milliseconds)',
default: `${DEFAULT_K8S_POD_ERROR_RECHECK_TIMEOUT}`
}),
[K8SPODWAITTIMEOUT_KEY]: k8sPodWaitTimeout,
[K8SPODREADYTIMEOUT_KEY]: k8sPodReadyTimeout,
[K8SPODDOWNLOADIMAGETIMEOUT_KEY]: k8sPodDownloadImageTimeout,
[K8SPODERRORRECHECKTIMEOUT_KEY]: k8sPodErrorRecheckTimeout,
[LOG_DIRECTORY_KEY]: logsDirectory,
multiuser: flags.boolean({
char: 'm',
description: 'Starts Eclipse Che in multi-user mode',
Expand Down Expand Up @@ -133,11 +120,6 @@ export default class Deploy extends Command {
description: 'Path to yaml file with Helm Chart values patch. The file format is identical to values.yaml from the chart.',
default: '',
}),
directory: string({
char: 'd',
description: 'Directory to store logs into',
env: 'CHE_LOGS'
}),
'workspace-pvc-storage-class-name': string({
description: 'persistent volume(s) storage class name to use to store Eclipse Che workspaces data',
env: 'CHE_INFRA_KUBERNETES_PVC_STORAGE__CLASS__NAME',
Expand Down Expand Up @@ -250,18 +232,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,13 +322,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['self-signed-cert']) {
this.warn('"self-signed-cert" flag is deprecated and has no effect. Autodetection is used instead.')
Expand Down Expand Up @@ -391,16 +356,11 @@ export default class Deploy extends Command {

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)

// 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 @@ -415,44 +375,29 @@ export default class Deploy extends Command {
], ctx.listrOptions)

const logsTasks = new Listr([{
title: 'Start following logs',
title: '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 Eclipse Che 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${getCommandErrorMessage(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
86 changes: 86 additions & 0 deletions src/commands/server/start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*********************************************************************
* Copyright (c) 2019 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { Command, flags } from '@oclif/command'
import { cli } from 'cli-ux'
import * as Listr from 'listr'
import * as notifier from 'node-notifier'

import { cheDeployment, cheNamespace, k8sPodDownloadImageTimeout, K8SPODDOWNLOADIMAGETIMEOUT_KEY, k8sPodErrorRecheckTimeout, K8SPODERRORRECHECKTIMEOUT_KEY, k8sPodReadyTimeout, K8SPODREADYTIMEOUT_KEY, k8sPodWaitTimeout, K8SPODWAITTIMEOUT_KEY, listrRenderer, logsDirectory, LOG_DIRECTORY_KEY, skipKubeHealthzCheck } from '../../common-flags'
import { CheTasks } from '../../tasks/che'
import { ApiTasks } from '../../tasks/platforms/api'
import { getCommandErrorMessage, getCommandSuccessMessage, initializeContext } from '../../util'

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

static flags: flags.Input<any> = {
help: flags.help({ char: 'h' }),
chenamespace: cheNamespace,
'listr-renderer': listrRenderer,
'deployment-name': cheDeployment,
[K8SPODWAITTIMEOUT_KEY]: k8sPodWaitTimeout,
[K8SPODREADYTIMEOUT_KEY]: k8sPodReadyTimeout,
[K8SPODDOWNLOADIMAGETIMEOUT_KEY]: k8sPodDownloadImageTimeout,
[K8SPODERRORRECHECKTIMEOUT_KEY]: k8sPodErrorRecheckTimeout,
[LOG_DIRECTORY_KEY]: logsDirectory,
'skip-kubernetes-health-check': skipKubeHealthzCheck,
}

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

const cheTasks = new CheTasks(flags)
const apiTasks = new ApiTasks()

// Checks if Eclipse Che is already deployed
const preInstallTasks = new Listr([
apiTasks.testApiTasks(flags, this),
{
title: '👀 Looking for an already existing Eclipse Che instance',
task: () => new Listr(cheTasks.checkIfCheIsInstalledTasks(flags, this))
}], ctx.listrOptions)

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

const startCheTasks = new Listr([{
title: 'Starting Eclipse Che',
task: () => new Listr(cheTasks.scaleCheUpTasks())
}], ctx.listrOptions)

try {
await preInstallTasks.run(ctx)

if (!ctx.isCheDeployed) {
cli.warn('Eclipse Che has not been deployed yet. Use server:deploy command to deploy a new Eclipse Che instance.')
} else if (ctx.isCheReady) {
cli.info('Eclipse Che has been already started.')
} else {
await logsTasks.run(ctx)
await startCheTasks.run(ctx)
this.log(getCommandSuccessMessage(this, ctx))
}
} catch (err) {
this.error(`${err}\n${getCommandErrorMessage(this, ctx)}`)
}

notifier.notify({
title: 'chectl',
message: getCommandSuccessMessage(this, ctx)
})

this.exit(0)
}

}
32 changes: 32 additions & 0 deletions src/common-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
**********************************************************************/
import { boolean, string } from '@oclif/parser/lib/flags'

import { DEFAULT_K8S_POD_ERROR_RECHECK_TIMEOUT, DEFAULT_K8S_POD_TIMEOUT } from './api/kube'
import { DEFAULT_DEV_WORKSPACE_CONTROLLER_NAMESPACE, DOC_LINK_OBTAIN_ACCESS_TOKEN, DOC_LINK_OBTAIN_ACCESS_TOKEN_OAUTH } from './constants'

export const cheNamespace = string({
Expand Down Expand Up @@ -81,3 +82,34 @@ export const username = string({
env: 'CHE_USER_NAME',
required: false,
})

export const K8SPODWAITTIMEOUT_KEY = 'k8spodwaittimeout'
export const k8sPodWaitTimeout = string({
description: 'Waiting time for Pod scheduled condition (in milliseconds)',
default: `${DEFAULT_K8S_POD_TIMEOUT}`
})

export const K8SPODDOWNLOADIMAGETIMEOUT_KEY = 'k8spoddownloadimagetimeout'
export const k8sPodDownloadImageTimeout = string({
description: 'Waiting time for Pod downloading image (in milliseconds)',
default: `${DEFAULT_K8S_POD_TIMEOUT}`
})

export const K8SPODREADYTIMEOUT_KEY = 'k8spodreadytimeout'
export const k8sPodReadyTimeout = string({
description: 'Waiting time for Pod Ready condition (in milliseconds)',
default: `${DEFAULT_K8S_POD_TIMEOUT}`
})

export const K8SPODERRORRECHECKTIMEOUT_KEY = 'k8spoderrorrechecktimeout'
export const k8sPodErrorRecheckTimeout = string({
description: 'Waiting time for Pod rechecking error (in milliseconds)',
default: `${DEFAULT_K8S_POD_ERROR_RECHECK_TIMEOUT}`
})

export const LOG_DIRECTORY_KEY = 'directory'
export const logsDirectory = string({
char: 'd',
description: 'Directory to store logs into',
env: 'CHE_LOGS'
})
Loading