Skip to content

Commit

Permalink
refactor: rename logEntry to log and require for tests, cmds and actions
Browse files Browse the repository at this point in the history
This leverages the recent changes to the logger that allow for empty
log entries.
  • Loading branch information
edvald authored and eysi09 committed Nov 27, 2018
1 parent 81ee88b commit 13cf263
Show file tree
Hide file tree
Showing 90 changed files with 908 additions and 542 deletions.
63 changes: 33 additions & 30 deletions garden-service/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ export interface ContextStatus {
}

export interface DeployServicesParams {
serviceNames?: string[],
log: LogEntry
serviceNames?: string[]
force?: boolean
forceBuild?: boolean
}
Expand Down Expand Up @@ -119,10 +120,10 @@ export class ActionHelper implements TypeGuard {
//===========================================================================

async getEnvironmentStatus(
{ pluginName }: ActionHelperParams<GetEnvironmentStatusParams>,
{ pluginName, log }: ActionHelperParams<GetEnvironmentStatusParams>,
): Promise<EnvironmentStatusMap> {
const handlers = this.garden.getActionHandlers("getEnvironmentStatus", pluginName)
return Bluebird.props(mapValues(handlers, h => h({ ...this.commonParams(h) })))
return Bluebird.props(mapValues(handlers, h => h({ ...this.commonParams(h, log) })))
}

/**
Expand All @@ -132,14 +133,14 @@ export class ActionHelper implements TypeGuard {
* run `garden init`
*/
async prepareEnvironment(
{ force = false, pluginName, logEntry, allowUserInput = false }:
{ force?: boolean, pluginName?: string, logEntry?: LogEntry, allowUserInput?: boolean },
{ force = false, pluginName, log, allowUserInput = false }:
{ force?: boolean, pluginName?: string, log: LogEntry, allowUserInput?: boolean },
) {
const handlers = this.garden.getActionHandlers("prepareEnvironment", pluginName)
// FIXME: We're calling getEnvironmentStatus before preparing the environment.
// Results in 404 errors for unprepared/missing services.
// See: https://github.com/garden-io/garden/issues/353
const statuses = await this.getEnvironmentStatus({ pluginName })
const statuses = await this.getEnvironmentStatus({ pluginName, log })

const needUserInput = Object.entries(statuses)
.map(([name, status]) => ({ ...status, name }))
Expand Down Expand Up @@ -167,13 +168,13 @@ export class ActionHelper implements TypeGuard {
continue
}

const envLogEntry = (logEntry || this.garden.log).info({
const envLogEntry = log.info({
status: "active",
section: name,
msg: "Preparing environment...",
})

await handler({ ...this.commonParams(handler), force, status, logEntry: envLogEntry })
await handler({ ...this.commonParams(handler, log), force, status, log: envLogEntry })

envLogEntry.setSuccess("Configured")

Expand All @@ -184,11 +185,11 @@ export class ActionHelper implements TypeGuard {
}

async cleanupEnvironment(
{ pluginName }: ActionHelperParams<CleanupEnvironmentParams>,
{ pluginName, log }: ActionHelperParams<CleanupEnvironmentParams>,
): Promise<EnvironmentStatusMap> {
const handlers = this.garden.getActionHandlers("cleanupEnvironment", pluginName)
await Bluebird.each(values(handlers), h => h({ ...this.commonParams(h) }))
return this.getEnvironmentStatus({ pluginName })
await Bluebird.each(values(handlers), h => h({ ...this.commonParams(h, log) }))
return this.getEnvironmentStatus({ pluginName, log })
}

async getSecret(params: RequirePluginName<ActionHelperParams<GetSecretParams>>): Promise<GetSecretResult> {
Expand Down Expand Up @@ -277,13 +278,13 @@ export class ActionHelper implements TypeGuard {
}

async deleteService(params: ServiceActionHelperParams<DeleteServiceParams>): Promise<ServiceStatus> {
const logEntry = this.garden.log.info({
const log = params.log.info({
section: params.service.name,
msg: "Deleting...",
status: "active",
})
return this.callServiceHandler({
params: { ...params, logEntry },
params: { ...params, log },
actionType: "deleteService",
defaultHandler: dummyDeleteServiceHandler,
})
Expand Down Expand Up @@ -330,14 +331,14 @@ export class ActionHelper implements TypeGuard {
return keyBy(dependencies, "name")
}

async getStatus(): Promise<ContextStatus> {
const envStatus: EnvironmentStatusMap = await this.getEnvironmentStatus({})
async getStatus({ log }: { log: LogEntry }): Promise<ContextStatus> {
const envStatus: EnvironmentStatusMap = await this.getEnvironmentStatus({ log })
const services = keyBy(await this.garden.getServices(), "name")

const serviceStatus = await Bluebird.props(mapValues(services, async (service: Service) => {
const serviceDependencies = await this.garden.getServices(service.config.dependencies)
const runtimeContext = await prepareRuntimeContext(this.garden, service.module, serviceDependencies)
return this.getServiceStatus({ service, runtimeContext })
const runtimeContext = await prepareRuntimeContext(this.garden, log, service.module, serviceDependencies)
return this.getServiceStatus({ log, service, runtimeContext })
}))

return {
Expand All @@ -347,16 +348,18 @@ export class ActionHelper implements TypeGuard {
}

async deployServices(
{ serviceNames, force = false, forceBuild = false }: DeployServicesParams,
{ serviceNames, force = false, forceBuild = false, log }: DeployServicesParams,
): Promise<ProcessResults> {
const services = await this.garden.getServices(serviceNames)

return processServices({
services,
garden: this.garden,
log,
watch: false,
handler: async (module) => getTasksForModule({
garden: this.garden,
log,
module,
hotReloadServiceNames: [],
force,
Expand All @@ -368,11 +371,11 @@ export class ActionHelper implements TypeGuard {
//endregion

// TODO: find a nicer way to do this (like a type-safe wrapper function)
private commonParams(handler, logEntry?: LogEntry): PluginActionParamsBase {
private commonParams(handler, log: LogEntry): PluginActionParamsBase {
return {
ctx: createPluginContext(this.garden, handler["pluginName"]),
// TODO: find a better way for handlers to log during execution
logEntry,
log,
}
}

Expand All @@ -391,7 +394,7 @@ export class ActionHelper implements TypeGuard {
defaultHandler,
})
const handlerParams: PluginActionParams[T] = {
...this.commonParams(handler),
...this.commonParams(handler, <any>params.log),
...<object>params,
}
return (<Function>handler)(handlerParams)
Expand All @@ -413,7 +416,7 @@ export class ActionHelper implements TypeGuard {
const buildDependencies = await this.getBuildDependencies(module)

const handlerParams: any = {
...this.commonParams(handler),
...this.commonParams(handler, <any>params.log),
...<object>params,
module: omit(module, ["_ConfigType"]),
buildDependencies,
Expand All @@ -426,7 +429,7 @@ export class ActionHelper implements TypeGuard {
{ params, actionType, defaultHandler }:
{ params: ServiceActionHelperParams<ServiceActionParams[T]>, actionType: T, defaultHandler?: ServiceActions[T] },
): Promise<ServiceActionOutputs[T]> {
const { service } = <any>params
const { log, service } = <any>params
const module = service.module

const handler = await this.garden.getModuleActionHandler({
Expand All @@ -439,10 +442,10 @@ export class ActionHelper implements TypeGuard {
// TODO: figure out why this doesn't compile without the casts
const buildDependencies = await this.getBuildDependencies(module)
const deps = await this.garden.getServices(service.config.dependencies)
const runtimeContext = ((<any>params).runtimeContext || await prepareRuntimeContext(this.garden, module, deps))
const runtimeContext = ((<any>params).runtimeContext || await prepareRuntimeContext(this.garden, log, module, deps))

const handlerParams: any = {
...this.commonParams(handler),
...this.commonParams(handler, log),
...<object>params,
module,
runtimeContext,
Expand Down Expand Up @@ -473,7 +476,7 @@ export class ActionHelper implements TypeGuard {
const buildDependencies = await this.getBuildDependencies(module)

const handlerParams: any = {
...this.commonParams(handler),
...this.commonParams(handler, <any>params.log),
...<object>params,
module,
task,
Expand All @@ -484,8 +487,8 @@ export class ActionHelper implements TypeGuard {
}
}

const dummyLogStreamer = async ({ service, logEntry }: GetServiceLogsParams) => {
logEntry && logEntry.warn({
const dummyLogStreamer = async ({ service, log }: GetServiceLogsParams) => {
log.warn({
section: service.name,
msg: chalk.yellow(`No handler for log retrieval available for module type ${service.module.type}`),
})
Expand All @@ -503,8 +506,8 @@ const dummyPublishHandler = async ({ module }) => {
}
}

const dummyDeleteServiceHandler = async ({ module, logEntry }: DeleteServiceParams) => {
const dummyDeleteServiceHandler = async ({ module, log }: DeleteServiceParams) => {
const msg = `No delete service handler available for module type ${module.type}`
logEntry && logEntry.setError(msg)
log.setError(msg)
return {}
}
3 changes: 3 additions & 0 deletions garden-service/src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,12 @@ export class GardenCli {
contextOpts.config = MOCK_CONFIG
}
garden = await Garden.factory(root, contextOpts)
// Indent -1 so that the children of this entry get printed with indent 0
const log = garden.log.info({ indent: -1 })
// TODO: enforce that commands always output DeepPrimitiveMap
result = await command.action({
garden,
log,
args: parsedArgs,
opts: parsedOpts,
})
Expand Down
9 changes: 6 additions & 3 deletions garden-service/src/commands/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { TaskResults } from "../task-graph"
import { LoggerType } from "../logger/logger"
import { ProcessResults } from "../process"
import { Garden } from "../garden"
import { LogEntry } from "../logger/log-entry"
import { logHeader } from "../logger/util"

export class ValidationError extends Error { }

Expand Down Expand Up @@ -188,6 +190,7 @@ export interface CommandParams<T extends Parameters = {}, U extends Parameters =
args: ParameterValues<T>
opts: ParameterValues<U>
garden: Garden
log: LogEntry
}

export abstract class Command<T extends Parameters = {}, U extends Parameters = {}> {
Expand Down Expand Up @@ -232,7 +235,7 @@ export abstract class Command<T extends Parameters = {}, U extends Parameters =
}

export async function handleTaskResults(
garden: Garden, taskType: string, results: ProcessResults,
log: LogEntry, taskType: string, results: ProcessResults,
): Promise<CommandResult<TaskResults>> {
const failed = Object.values(results.taskResults).filter(r => !!r.error).length

Expand All @@ -243,9 +246,9 @@ export async function handleTaskResults(
return { errors: [error] }
}

garden.log.info("")
log.info("")
if (!results.restartRequired) {
garden.log.header({ emoji: "heavy_check_mark", command: `Done!` })
logHeader({ log, emoji: "heavy_check_mark", command: `Done!` })
}
return {
result: results.taskResults,
Expand Down
12 changes: 7 additions & 5 deletions garden-service/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TaskResults } from "../task-graph"
import dedent = require("dedent")
import { processModules } from "../process"
import { Module } from "../types/module"
import { logHeader } from "../logger/util"

const buildArguments = {
module: new StringsParameter({
Expand Down Expand Up @@ -54,7 +55,7 @@ export class BuildCommand extends Command<BuildArguments, BuildOptions> {
options = buildOptions

async action(
{ args, opts, garden }: CommandParams<BuildArguments, BuildOptions>,
{ args, opts, garden, log }: CommandParams<BuildArguments, BuildOptions>,
): Promise<CommandResult<TaskResults>> {

await garden.clearBuilds()
Expand All @@ -63,21 +64,22 @@ export class BuildCommand extends Command<BuildArguments, BuildOptions> {
const dependencyGraph = await garden.getDependencyGraph()
const moduleNames = modules.map(m => m.name)

garden.log.header({ emoji: "hammer", command: "Build" })
logHeader({ log, emoji: "hammer", command: "Build" })

const results = await processModules({
garden,
log,
modules,
watch: opts.watch,
handler: async (module) => [new BuildTask({ garden, module, force: opts.force })],
handler: async (module) => [new BuildTask({ garden, log, module, force: opts.force })],
changeHandler: async (module: Module) => {
const dependantModules = (await dependencyGraph.getDependants("build", module.name, true)).build
return [module].concat(dependantModules)
.filter(m => moduleNames.includes(m.name))
.map(m => new BuildTask({ garden, module: m, force: true }))
.map(m => new BuildTask({ garden, log, module: m, force: true }))
},
})

return handleTaskResults(garden, "build", results)
return handleTaskResults(log, "build", results)
}
}
12 changes: 6 additions & 6 deletions garden-service/src/commands/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ export class CallCommand extends Command<Args> {

arguments = callArgs

async action({ garden, args }: CommandParams<Args>): Promise<CommandResult> {
async action({ garden, log, args }: CommandParams<Args>): Promise<CommandResult> {
let [serviceName, path] = splitFirst(args.serviceAndPath, "/")

// TODO: better error when service doesn't exist
const service = await garden.getService(serviceName)
const status = await garden.actions.getServiceStatus({ service })
const status = await garden.actions.getServiceStatus({ service, log })

if (!includes(["ready", "outdated"], status.state)) {
throw new RuntimeError(`Service ${service.name} is not running`, {
Expand Down Expand Up @@ -119,7 +119,7 @@ export class CallCommand extends Command<Args> {
// TODO: support POST requests with request body
const method = "get"

const entry = garden.log.info({
const entry = log.info({
msg: chalk.cyan(`Sending ${matchedIngress.protocol.toUpperCase()} GET request to `) + url + "\n",
status: "active",
})
Expand All @@ -141,18 +141,18 @@ export class CallCommand extends Command<Args> {
try {
res = await req
entry.setSuccess()
garden.log.info(chalk.green(`${res.status} ${res.statusText}\n`))
log.info(chalk.green(`${res.status} ${res.statusText}\n`))
} catch (err) {
res = err.response
entry.setError()
const error = res ? `${res.status} ${res.statusText}` : err.message
garden.log.info(chalk.red(error + "\n"))
log.info(chalk.red(error + "\n"))
return {}
}

const resStr = isObject(res.data) ? JSON.stringify(res.data, null, 2) : res.data

res.data && garden.log.info(chalk.white(resStr) + "\n")
res.data && log.info(chalk.white(resStr) + "\n")

return {
result: {
Expand Down
Loading

0 comments on commit 13cf263

Please sign in to comment.