Skip to content

Commit

Permalink
fix: print json/yaml output after cli returns parse results
Browse files Browse the repository at this point in the history
  • Loading branch information
eysi09 committed May 15, 2018
1 parent b486fd8 commit eeadf16
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 52 deletions.
77 changes: 37 additions & 40 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const GLOBAL_OPTIONS = {
output: new ChoicesParameter({
alias: "o",
choices: Object.keys(OUTPUT_RENDERERS),
help: "output command result in specified format (note: disable progress logging)",
help: "output command result in specified format (note: disables progress logging)",
}),
}
const GLOBAL_OPTIONS_GROUP_NAME = "Global options"
Expand Down Expand Up @@ -144,7 +144,7 @@ export interface ParseResults {

interface SywacParseResults extends ParseResults {
output: string
details: any
details: { result: any }
}

function makeOptSynopsis(key: string, param: Parameter<any>): string {
Expand Down Expand Up @@ -292,7 +292,7 @@ export class GardenCli {
throw new PluginError(`Global option(s) ${dupKeys.join(" ")} cannot be redefined`, {})
}

const action = async argv => {
const action = async (argv, cliContext) => {
// Sywac returns positional args and options in a single object which we separate into args and opts
const argsForAction = filterByArray(argv, argKeys)
const optsForAction = filterByArray(argv, optKeys.concat(globalKeys))
Expand All @@ -315,32 +315,12 @@ export class GardenCli {

const garden = await Garden.factory(root, { env, logger })

try {
// TODO: enforce that commands always output DeepPrimitiveMap
const result = await command.action(garden.pluginContext, argsForAction, optsForAction)
// TODO: enforce that commands always output DeepPrimitiveMap
const result = await command.action(garden.pluginContext, argsForAction, optsForAction)

if (output && result !== undefined) {
const renderer = OUTPUT_RENDERERS[output]
console.log(renderer({ success: true, result }))
// Note: this circumvents an issue where the process exits before the output is fully flushed
await sleep(100)
}
// We attach the action result to cli context so that we can process it in the parse method
cliContext.details.result = result

return result

} catch (error) {
// TODO: we can likely do this better
const result = { error }

if (output) {
const renderer = OUTPUT_RENDERERS[output]
console.error(renderer(result))
// Note: this circumvents an issue where the process exits before the output is fully flushed
await sleep(100)
}

return result
}
}

// Command specific positional args and options are set inside the builder function
Expand All @@ -361,24 +341,41 @@ export class GardenCli {
}

async parse(): Promise<ParseResults> {
return this.program.parse().then((result: SywacParseResults) => {
const { argv, errors, code, output } = result

// --help or --version options were called
if (output && !(errors.length > 0)) {
this.logger.stop()
console.log(output)
process.exit(result.code)
}
const parseResult: SywacParseResults = await this.program.parse()
const { argv, details, errors, code, output: cliOutput } = parseResult
const { result } = details
const { output } = argv

// --help or --version options were called so we log the cli output and exit
if (cliOutput && errors.length < 1) {
this.logger.stop()
console.log(cliOutput)
process.exit(parseResult.code)
}

// --output option set and there is content to output
if (output && (result !== undefined || errors.length > 0)) {
const renderer = OUTPUT_RENDERERS[output]
if (errors.length > 0) {
errors.forEach(err => this.logger.error({ msg: err.message, error: err }))
const msg = errors.join("\n")
console.error(renderer({ result: msg }))
} else {
console.log(renderer({ success: true, result }))
}
// Note: this circumvents an issue where the process exits before the output is fully flushed
await sleep(100)
}

if (errors.length > 0) {
errors.forEach(err => this.logger.error({ msg: err.message, error: err }))

if (this.logger.writers.find(w => w instanceof FileWriter)) {
this.logger.info(`See ${ERROR_LOG_FILENAME} for detailed error message`)
}
}

this.logger.stop()
return { argv, code, errors }
})
this.logger.stop()
return { argv, code, errors }
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/kubernetes/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export async function destroyEnvironment({ ctx, provider }: DestroyEnvironmentPa
entry.setSuccess("Finished")
} catch (err) {
entry.setError(err.message)
const availableNamespaces = getAllAppNamespaces(context)
const availableNamespaces = await getAllAppNamespaces(context)
throw new NotFoundError(err, { namespace, availableNamespaces })
}
}
Expand Down
11 changes: 0 additions & 11 deletions src/plugins/kubernetes/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,6 @@ import {
import { name as providerName } from "./index"
import { AuthenticationError } from "../../exceptions"

export async function namespaceReady(context: string, namespace: string) {
/**
* This is an issue with kubernetes-client where it fetches all namespaces instead of the requested one.
* Is fixed in v4.0.0. See https://github.com/godaddy/kubernetes-client/issues/187 and
* https://github.com/godaddy/kubernetes-client/pull/190
*/
const allNamespaces = await apiGetOrNull(coreApi(context).namespaces, namespace)
const ns = allNamespaces.items.find(n => n.metadata.name === namespace)
return ns && ns.status.phase === "Active"
}

export async function createNamespace(context: string, namespace: string) {
await coreApi(context).namespaces.post({
body: {
Expand Down

0 comments on commit eeadf16

Please sign in to comment.