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 5, 2018
1 parent 53dd826 commit ba7597f
Show file tree
Hide file tree
Showing 91 changed files with 898 additions and 528 deletions.
61 changes: 32 additions & 29 deletions garden-service/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export interface ContextStatus {
}

export interface DeployServicesParams {
serviceNames?: string[],
log: LogEntry
serviceNames?: string[]
force?: boolean
forceBuild?: boolean
}
Expand All @@ -108,10 +109,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 @@ -121,11 +122,11 @@ 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)
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 @@ -153,13 +154,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 @@ -170,11 +171,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 @@ -263,13 +264,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 @@ -306,14 +307,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 @@ -323,16 +324,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) => getDeployTasks({
garden: this.garden,
log,
module,
serviceNames,
hotReloadServiceNames: [],
Expand All @@ -345,11 +348,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 @@ -368,7 +371,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 @@ -390,7 +393,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 @@ -403,7 +406,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 @@ -416,10 +419,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 All @@ -430,8 +433,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 @@ -449,8 +452,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
14 changes: 8 additions & 6 deletions garden-service/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { processModules } from "../process"
import { computeAutoReloadDependants, withDependants } from "../watch"
import { Module } from "../types/module"
import { hotReloadAndLog } from "./helpers"
import { logHeader } from "../logger/util"

const buildArguments = {
module: new StringsParameter({
Expand Down Expand Up @@ -56,7 +57,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 @@ -65,25 +66,26 @@ export class BuildCommand extends Command<BuildArguments, BuildOptions> {
const modules = await garden.getModules(args.module)
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) => {

if (module.spec.hotReload) {
await hotReloadAndLog(garden, module)
await hotReloadAndLog(garden, log, module)
}

return (await withDependants(garden, [module], autoReloadDependants))
.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
14 changes: 7 additions & 7 deletions garden-service/src/commands/create/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class CreateModuleCommand extends Command<Args, Opts> {
name = "module"
alias = "m"
help = "Creates a new Garden module."
header = { emoji: "house_with_garden", command: "create" }

description = dedent`
Creates a new Garden module of the given type
Expand All @@ -71,7 +72,7 @@ export class CreateModuleCommand extends Command<Args, Opts> {
arguments = createModuleArguments
options = createModuleOptions

async action({ garden, args, opts }: CommandParams<Args, Opts>): Promise<CreateModuleResult> {
async action({ garden, args, opts, log }: CommandParams<Args, Opts>): Promise<CreateModuleResult> {
let errors: GardenBaseError[] = []

const moduleRoot = join(garden.projectRoot, (args["module-dir"] || "").trim())
Expand All @@ -83,8 +84,7 @@ export class CreateModuleCommand extends Command<Args, Opts> {

await ensureDir(moduleRoot)

garden.log.header({ emoji: "house_with_garden", command: "create" })
garden.log.info(`Initializing new module ${moduleName}`)
log.info(`Initializing new module ${moduleName}`)

let type: ModuleType

Expand All @@ -96,18 +96,18 @@ export class CreateModuleCommand extends Command<Args, Opts> {
}
} else {
// Prompt for type
garden.log.info("---------")
garden.log.stop()
log.info("---------")
log.stop()
type = (await prompts.addConfigForModule(moduleName)).type
garden.log.info("---------")
log.info("---------")
if (!type) {
return { result: {} }
}
}

const module = prepareNewModuleConfig(moduleName, type, moduleRoot)
try {
await dumpConfig(module, moduleSchema, garden.log)
await dumpConfig(module, moduleSchema, log)
} catch (err) {
errors.push(err)
}
Expand Down
Loading

0 comments on commit ba7597f

Please sign in to comment.