diff --git a/garden-service/src/actions.ts b/garden-service/src/actions.ts index 6733f2ab64..b4db998b8a 100644 --- a/garden-service/src/actions.ts +++ b/garden-service/src/actions.ts @@ -37,9 +37,9 @@ import { TestResult, PluginActionOutputs, PublishResult, - RunTaskResult, TaskActionOutputs, HotReloadServiceResult, + RunTaskResult, } from "./types/plugin/outputs" import { BuildModuleParams, @@ -70,6 +70,7 @@ import { PluginTaskActionParamsBase, RunTaskParams, TaskActionParams, + GetTaskResultParams, } from "./types/plugin/params" import { Service, ServiceStatus, getServiceRuntimeContext } from "./types/service" import { mapValues, values, keyBy, omit, pickBy, fromPairs } from "lodash" @@ -329,6 +330,14 @@ export class ActionHelper implements TypeGuard { return this.callTaskHandler({ params, actionType: "runTask" }) } + async getTaskResult(params: TaskActionHelperParams): Promise { + return this.callTaskHandler({ + params, + actionType: "getTaskResult", + defaultHandler: async () => null, + }) + } + //endregion //=========================================================================== diff --git a/garden-service/src/commands/run/task.ts b/garden-service/src/commands/run/task.ts index 6ec1543710..ae81afa23d 100644 --- a/garden-service/src/commands/run/task.ts +++ b/garden-service/src/commands/run/task.ts @@ -59,7 +59,7 @@ export class RunTaskCommand extends Command { await garden.actions.prepareEnvironment({ log }) - const taskTask = new TaskTask({ garden, graph, task, log, force: true, forceBuild: opts["force-build"] }) + const taskTask = await TaskTask.factory({ garden, graph, task, log, force: true, forceBuild: opts["force-build"] }) await garden.addTask(taskTask) const result = (await garden.processTasks())[taskTask.getBaseKey()] diff --git a/garden-service/src/commands/run/test.ts b/garden-service/src/commands/run/test.ts index ebbc563220..acd13705bc 100644 --- a/garden-service/src/commands/run/test.ts +++ b/garden-service/src/commands/run/test.ts @@ -25,6 +25,7 @@ import dedent = require("dedent") import { prepareRuntimeContext } from "../../types/service" import { logHeader } from "../../logger/util" import { PushTask } from "../../tasks/push" +import { getTestVersion } from "../../tasks/test" const runArgs = { module: new StringParameter({ @@ -101,6 +102,8 @@ export class RunTestCommand extends Command { printRuntimeContext(log, runtimeContext) + const testVersion = await getTestVersion(garden, graph, module, testConfig) + const result = await garden.actions.testModule({ log, module, @@ -108,6 +111,7 @@ export class RunTestCommand extends Command { runtimeContext, silent: false, testConfig, + testVersion, }) return { result } diff --git a/garden-service/src/plugins/kubernetes/container/handlers.ts b/garden-service/src/plugins/kubernetes/container/handlers.ts index c39b671659..c3a41c2213 100644 --- a/garden-service/src/plugins/kubernetes/container/handlers.ts +++ b/garden-service/src/plugins/kubernetes/container/handlers.ts @@ -19,6 +19,7 @@ import { getContainerServiceStatus } from "./status" import { getTestResult } from "../test" import { ContainerModule } from "../../container/config" import { configureMavenContainerModule, MavenContainerModule } from "../../maven-container/maven-container" +import { getTaskResult } from "../task-results" async function configure(params: ConfigureModuleParams) { const config = await configureContainerModule(params) @@ -46,6 +47,7 @@ export const containerHandlers = { runModule: runContainerModule, runService: runContainerService, runTask: runContainerTask, + getTaskResult, testModule: testContainerModule, } diff --git a/garden-service/src/plugins/kubernetes/container/run.ts b/garden-service/src/plugins/kubernetes/container/run.ts index 8832559278..c4a25d88c7 100644 --- a/garden-service/src/plugins/kubernetes/container/run.ts +++ b/garden-service/src/plugins/kubernetes/container/run.ts @@ -23,6 +23,7 @@ import { getContainerServiceStatus } from "./status" import { runPod } from "../run" import { containerHelpers } from "../../container/helpers" import { KubernetesPluginContext, KubernetesProvider } from "../kubernetes" +import { storeTaskResult } from "../task-results" export async function execInService(params: ExecInServiceParams) { const { ctx, service, command, interactive } = params @@ -115,7 +116,7 @@ export async function runContainerService( } export async function runContainerTask( - { ctx, log, module, task, interactive, runtimeContext }: RunTaskParams, + { ctx, log, module, task, taskVersion, interactive, runtimeContext }: RunTaskParams, ): Promise { extend(runtimeContext.envVars, task.spec.env || {}) @@ -124,7 +125,7 @@ export async function runContainerTask( const namespace = await getAppNamespace(ctx, provider) const image = await containerHelpers.getDeploymentImageId(module, provider.config.deploymentRegistry) - const result = await runPod({ + const res = await runPod({ context, namespace, module, @@ -139,8 +140,14 @@ export async function runContainerTask( log, }) - return { - ...result, + const result = { ...res, taskName: task.name } + + await storeTaskResult({ + ctx, + result, + taskVersion, taskName: task.name, - } + }) + + return result } diff --git a/garden-service/src/plugins/kubernetes/container/test.ts b/garden-service/src/plugins/kubernetes/container/test.ts index b10c9560b7..b7fed88b01 100644 --- a/garden-service/src/plugins/kubernetes/container/test.ts +++ b/garden-service/src/plugins/kubernetes/container/test.ts @@ -14,7 +14,7 @@ import { runContainerModule } from "./run" import { storeTestResult } from "../test" export async function testContainerModule( - { ctx, interactive, module, runtimeContext, testConfig, log }: + { ctx, interactive, module, runtimeContext, testConfig, testVersion, log }: TestModuleParams, ): Promise { const testName = testConfig.name @@ -32,5 +32,5 @@ export async function testContainerModule( log, }) - return storeTestResult({ ctx, module, testName, result }) + return storeTestResult({ ctx, module, testName, testVersion, result }) } diff --git a/garden-service/src/plugins/kubernetes/helm/run.ts b/garden-service/src/plugins/kubernetes/helm/run.ts index d593fbc488..194359aaf2 100644 --- a/garden-service/src/plugins/kubernetes/helm/run.ts +++ b/garden-service/src/plugins/kubernetes/helm/run.ts @@ -16,6 +16,7 @@ import { PluginContext } from "../../../plugin-context" import { LogEntry } from "../../../logger/log-entry" import { ConfigurationError } from "../../../exceptions" import { KubernetesPluginContext } from "../kubernetes" +import { storeTaskResult } from "../task-results" export async function runHelmModule( { @@ -52,7 +53,7 @@ export async function runHelmModule( } export async function runHelmTask( - { ctx, log, module, task, interactive, runtimeContext, timeout }: RunTaskParams, + { ctx, log, module, task, taskVersion, interactive, runtimeContext, timeout }: RunTaskParams, ): Promise { const k8sCtx = ctx const context = k8sCtx.provider.config.context @@ -74,10 +75,16 @@ export async function runHelmTask( log, }) - return { + const result = { ...res, taskName: task.name } + + await storeTaskResult({ + ctx, + result, + taskVersion, taskName: task.name, - ...res, - } + }) + + return result } async function getImage(ctx: PluginContext, module: HelmModule, log: LogEntry, resourceSpec: HelmResourceSpec) { diff --git a/garden-service/src/plugins/kubernetes/helm/test.ts b/garden-service/src/plugins/kubernetes/helm/test.ts index ea06fb904a..e4e3b76d76 100644 --- a/garden-service/src/plugins/kubernetes/helm/test.ts +++ b/garden-service/src/plugins/kubernetes/helm/test.ts @@ -17,7 +17,7 @@ import { findServiceResource, getChartResources, getResourceContainer, getServic import { KubernetesPluginContext } from "../kubernetes" export async function testHelmModule( - { ctx, log, interactive, module, runtimeContext, testConfig }: + { ctx, log, interactive, module, runtimeContext, testConfig, testVersion }: TestModuleParams, ): Promise { const testName = testConfig.name @@ -48,5 +48,5 @@ export async function testHelmModule( log, }) - return storeTestResult({ ctx: k8sCtx, module, testName, result }) + return storeTestResult({ ctx: k8sCtx, module, testName, testVersion, result }) } diff --git a/garden-service/src/plugins/kubernetes/task-results.ts b/garden-service/src/plugins/kubernetes/task-results.ts new file mode 100644 index 0000000000..82138b70fc --- /dev/null +++ b/garden-service/src/plugins/kubernetes/task-results.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { GetTaskResultParams } from "../../types/plugin/params" +import { ContainerModule } from "../container/config" +import { HelmModule } from "./helm/config" +import { ModuleVersion } from "../../vcs/base" +import { KubernetesPluginContext, KubernetesProvider } from "./kubernetes" +import { KubeApi } from "./api" +import { getMetadataNamespace } from "./namespace" +import { RunTaskResult } from "../../types/plugin/outputs" +import { deserializeValues, serializeValues } from "../../util/util" +import { PluginContext } from "../../plugin-context" + +export async function getTaskResult( + { ctx, task, taskVersion }: GetTaskResultParams, +): Promise { + const k8sCtx = ctx + const api = new KubeApi(k8sCtx.provider.config.context) + const ns = await getMetadataNamespace(k8sCtx, k8sCtx.provider) + const resultKey = getTaskResultKey(task.name, taskVersion) + + try { + const res = await api.core.readNamespacedConfigMap(resultKey, ns) + return deserializeValues(res.body.data) + } catch (err) { + if (err.code === 404) { + return null + } else { + throw err + } + } +} + +export function getTaskResultKey(taskName: string, version: ModuleVersion) { + return `task-result--${taskName}--${version.versionString}` +} + +/** + * Store a task run result as a ConfigMap in the cluster. + * + * TODO: Implement a CRD for this. + */ +export async function storeTaskResult( + { ctx, taskName, taskVersion, result }: + { ctx: PluginContext, taskName: string, taskVersion: ModuleVersion, result: RunTaskResult }, +): Promise { + const provider = ctx.provider + const api = new KubeApi(provider.config.context) + const ns = await getMetadataNamespace(ctx, provider) + const resultKey = getTaskResultKey(taskName, taskVersion) + + const body = { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + name: resultKey, + annotations: { + "garden.io/generated": "true", + }, + }, + data: serializeValues(result), + } + + try { + await api.core.createNamespacedConfigMap(ns, body) + } catch (err) { + if (err.code === 409) { + await api.core.patchNamespacedConfigMap(resultKey, ns, body) + } else { + throw err + } + } + + return result +} diff --git a/garden-service/src/plugins/kubernetes/test.ts b/garden-service/src/plugins/kubernetes/test.ts index 59a8406293..7ee8a249cd 100644 --- a/garden-service/src/plugins/kubernetes/test.ts +++ b/garden-service/src/plugins/kubernetes/test.ts @@ -19,12 +19,12 @@ import { PluginContext } from "../../plugin-context" import { KubernetesPluginContext } from "./kubernetes" export async function getTestResult( - { ctx, module, testName, version }: GetTestResultParams, -) { + { ctx, module, testName, testVersion }: GetTestResultParams, +): Promise { const k8sCtx = ctx const api = new KubeApi(k8sCtx.provider.config.context) const ns = await getMetadataNamespace(k8sCtx, k8sCtx.provider) - const resultKey = getTestResultKey(module, testName, version) + const resultKey = getTestResultKey(module, testName, testVersion) try { const res = await api.core.readNamespacedConfigMap(resultKey, ns) @@ -48,9 +48,9 @@ export function getTestResultKey(module: Module, testName: string, version: Modu * TODO: Implement a CRD for this. */ export async function storeTestResult( - { ctx, module, testName, result }: - { ctx: PluginContext, module: Module, testName: string, result: RunResult }, -) { + { ctx, module, testName, testVersion, result }: + { ctx: PluginContext, module: Module, testName: string, testVersion: ModuleVersion, result: RunResult }, +): Promise { const k8sCtx = ctx const api = new KubeApi(k8sCtx.provider.config.context) @@ -60,7 +60,7 @@ export async function storeTestResult( } const ns = await getMetadataNamespace(k8sCtx, k8sCtx.provider) - const resultKey = getTestResultKey(module, testName, result.version) + const resultKey = getTestResultKey(module, testName, testVersion) const body = { apiVersion: "v1", kind: "ConfigMap", diff --git a/garden-service/src/tasks/deploy.ts b/garden-service/src/tasks/deploy.ts index a098de98a1..1c4f0d82c0 100644 --- a/garden-service/src/tasks/deploy.ts +++ b/garden-service/src/tasks/deploy.ts @@ -72,13 +72,13 @@ export class DeployTask extends BaseTask { if (this.fromWatch && includes(this.hotReloadServiceNames, this.service.name)) { return deployTasks } else { - const taskTasks = deps.task.map(task => { - return new TaskTask({ + const taskTasks = await Bluebird.map(deps.task, (task) => { + return TaskTask.factory({ task, garden: this.garden, log: this.log, graph: this.graph, - force: false, + force: this.force, forceBuild: this.forceBuild, }) }) diff --git a/garden-service/src/tasks/task.ts b/garden-service/src/tasks/task.ts index 3a294925b0..1557184b9d 100644 --- a/garden-service/src/tasks/task.ts +++ b/garden-service/src/tasks/task.ts @@ -6,8 +6,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import * as Bluebird from "bluebird" import chalk from "chalk" -import { BaseTask } from "../tasks/base" +import { BaseTask, TaskParams } from "../tasks/base" import { Garden } from "../garden" import { Task } from "../types/task" import { PushTask } from "./push" @@ -16,6 +17,7 @@ import { LogEntry } from "../logger/log-entry" import { RunTaskResult } from "../types/plugin/outputs" import { prepareRuntimeContext } from "../types/service" import { DependencyGraphNodeType, ConfigGraph } from "../config-graph" +import { ModuleVersion } from "../vcs/base" export interface TaskTaskParams { garden: Garden @@ -34,13 +36,20 @@ export class TaskTask extends BaseTask { // ... to be renamed soon. private task: Task private forceBuild: boolean - constructor({ garden, log, graph, task, force, forceBuild }: TaskTaskParams) { - super({ garden, log, force, version: task.module.version }) + constructor({ garden, log, graph, task, version, force, forceBuild }: TaskTaskParams & TaskParams) { + super({ garden, log, force, version }) this.graph = graph this.task = task + this.force = force this.forceBuild = forceBuild } + static async factory(initArgs: TaskTaskParams): Promise { + const { garden, graph, task } = initArgs + const version = await getTaskVersion(garden, graph, task) + return new TaskTask({ ...initArgs, version }) + } + async getDependencies(): Promise { const pushTask = new PushTask({ @@ -64,8 +73,8 @@ export class TaskTask extends BaseTask { // ... to be renamed soon. }) }) - const taskTasks = deps.task.map(task => { - return new TaskTask({ + const taskTasks = await Bluebird.map(deps.task, (task) => { + return TaskTask.factory({ task, log: this.log, garden: this.garden, @@ -91,6 +100,18 @@ export class TaskTask extends BaseTask { // ... to be renamed soon. const task = this.task const module = task.module + // TODO: Re-enable this logic when we've started providing task graph results to process methods. + + // const cachedResult = await this.getTaskReosult() + + // if (cachedResult && cachedResult.success) { + // this.log.info({ + // section: task.name, + // }).setSuccess({ msg: chalk.green("Already run") }) + + // return cachedResult + // } + const log = this.log.info({ section: task.name, msg: "Running", @@ -108,6 +129,7 @@ export class TaskTask extends BaseTask { // ... to be renamed soon. log, runtimeContext, interactive: false, + taskVersion: this.version, }) } catch (err) { log.setError() @@ -120,4 +142,27 @@ export class TaskTask extends BaseTask { // ... to be renamed soon. } + // private async getTaskResult(): Promise { + // if (this.force) { + // return null + // } + + // return this.garden.actions.getTaskResult({ + // log: this.log, + // task: this.task, + // taskVersion: this.version, + // }) + // } + +} + +/** + * Determine the version of the task run, based on the version of the module and each of its dependencies. + */ +export async function getTaskVersion( + garden: Garden, graph: ConfigGraph, task: Task, +): Promise { + const { module } = task + const moduleDeps = await graph.resolveDependencyModules(module.build.dependencies, task.config.dependencies) + return garden.resolveVersion(module.name, moduleDeps) } diff --git a/garden-service/src/tasks/test.ts b/garden-service/src/tasks/test.ts index 392a722daa..0970afa4a3 100644 --- a/garden-service/src/tasks/test.ts +++ b/garden-service/src/tasks/test.ts @@ -130,6 +130,7 @@ export class TestTask extends BaseTask { runtimeContext, silent: true, testConfig: this.testConfig, + testVersion: this.version, }) } catch (err) { log.setError() @@ -145,7 +146,7 @@ export class TestTask extends BaseTask { return result } - private async getTestResult() { + private async getTestResult(): Promise { if (this.force) { return null } @@ -154,7 +155,7 @@ export class TestTask extends BaseTask { log: this.log, module: this.module, testName: this.testConfig.name, - version: this.version, + testVersion: this.version, }) } } @@ -192,7 +193,7 @@ async function getTestDependencies(graph: ConfigGraph, testConfig: TestConfig) { /** * Determine the version of the test run, based on the version of the module and each of its dependencies. */ -async function getTestVersion( +export async function getTestVersion( garden: Garden, graph: ConfigGraph, module: Module, testConfig: TestConfig, ): Promise { const moduleDeps = await graph.resolveDependencyModules(module.build.dependencies, testConfig.dependencies) diff --git a/garden-service/src/types/plugin/outputs.ts b/garden-service/src/types/plugin/outputs.ts index a1c8ca502b..3b7fe228b7 100644 --- a/garden-service/src/types/plugin/outputs.ts +++ b/garden-service/src/types/plugin/outputs.ts @@ -302,16 +302,7 @@ export const runTaskResultSchema = Joi.object() .description("The output log from the run."), }) -export interface TaskStatus { - done: boolean -} - -export const taskStatusSchema = Joi.object() - .keys({ - done: Joi.boolean() - .required() - .description("Whether the task has been successfully executed for the module's current version."), - }) +export const getTaskResultSchema = runTaskResultSchema.allow(null) export interface PluginActionOutputs { configureProvider: Promise @@ -336,8 +327,8 @@ export interface ServiceActionOutputs { } export interface TaskActionOutputs { - getTaskStatus: Promise runTask: Promise + getTaskResult: Promise } export interface ModuleActionOutputs extends ServiceActionOutputs { diff --git a/garden-service/src/types/plugin/params.ts b/garden-service/src/types/plugin/params.ts index 6ca0f1a662..75b1d76c8b 100644 --- a/garden-service/src/types/plugin/params.ts +++ b/garden-service/src/types/plugin/params.ts @@ -20,6 +20,7 @@ import { moduleConfigSchema } from "../../config/module" import { testConfigSchema } from "../../config/test" import { taskSchema } from "../../config/task" import { ProviderConfig, projectNameSchema, providerConfigBaseSchema } from "../../config/project" +import { deline } from "../../util/string" export interface PluginActionContextParams { ctx: PluginContext @@ -196,26 +197,30 @@ export const runModuleParamsSchema = runModuleBaseSchema .description("The command to run in the module."), }) +export const testVersionSchema = moduleVersionSchema + .description(deline` + The test run's version. In addition to the parent module's version, this also + factors in the module versions of the test's runtime dependencies (if any).`) + export interface TestModuleParams extends PluginModuleActionParamsBase { interactive: boolean runtimeContext: RuntimeContext silent: boolean testConfig: T["testConfigs"][0] + testVersion: ModuleVersion } export const testModuleParamsSchema = runModuleBaseSchema - .keys({ - testConfig: testConfigSchema, - }) + .keys({ testConfig: testConfigSchema, testVersion: testVersionSchema }) export interface GetTestResultParams extends PluginModuleActionParamsBase { testName: string - version: ModuleVersion + testVersion: ModuleVersion } export const getTestResultParamsSchema = moduleActionParamsSchema .keys({ testName: Joi.string() .description("A unique name to identify the test run."), - version: moduleVersionSchema, + testVersion: testVersionSchema, }) /** @@ -319,16 +324,27 @@ export const runServiceParamsSchema = serviceActionParamsSchema /** * Task actions */ -export interface GetTaskStatusParams extends PluginTaskActionParamsBase { } -export const getTaskStatusParamsSchema = taskActionParamsSchema + +export const taskVersionSchema = moduleVersionSchema + .description(deline` + The task run's version. In addition to the parent module's version, this also + factors in the module versions of the tasks's runtime dependencies (if any).`) + +export interface GetTaskResultParams extends PluginTaskActionParamsBase { + taskVersion: ModuleVersion +} +export const getTaskResultParamsSchema = taskActionParamsSchema + .keys({ taskVersion: taskVersionSchema }) export interface RunTaskParams extends PluginTaskActionParamsBase { interactive: boolean runtimeContext: RuntimeContext + taskVersion: ModuleVersion timeout?: number } export const runTaskParamsSchema = taskActionParamsSchema .keys(runBaseParams) + .keys({ taskVersion: taskVersionSchema }) export interface ServiceActionParams { getServiceStatus: GetServiceStatusParams @@ -341,7 +357,7 @@ export interface ServiceActionParams { } export interface TaskActionParams { - getTaskStatus: GetTaskStatusParams + getTaskResult: GetTaskResultParams runTask: RunTaskParams } diff --git a/garden-service/src/types/plugin/plugin.ts b/garden-service/src/types/plugin/plugin.ts index 426eeed600..b9f99eae5d 100644 --- a/garden-service/src/types/plugin/plugin.ts +++ b/garden-service/src/types/plugin/plugin.ts @@ -44,7 +44,7 @@ import { testModuleParamsSchema, getTestResultParamsSchema, publishModuleParamsSchema, - getTaskStatusParamsSchema, + getTaskResultParamsSchema, runTaskParamsSchema, configureProviderParamsSchema, } from "./params" @@ -71,8 +71,8 @@ import { testResultSchema, configureModuleResultSchema, publishModuleResultSchema, - taskStatusSchema, runTaskResultSchema, + getTaskResultSchema, configureProviderResultSchema, } from "./outputs" @@ -263,13 +263,17 @@ export const serviceActionDescriptions: { [P in ServiceActionName]: PluginAction export const taskActionDescriptions: { [P in TaskActionName]: PluginActionDescription } = { // TODO: see if this is actually necessary or useful - getTaskStatus: { + getTaskResult: { description: dedent` - Check and return the execution status of a task, i.e. whether the task has been successfully - completed for the module's current version. + Retrieve the task result for the specified version. Use this along with the \`runTask\` handler + to avoid running the same task repeatedly when its dependencies haven't changed. + + Note that the version string provided to this handler may be a hash of the module's version, as + well as any runtime dependencies configured for the task, so it may not match the current version + of the module itself. `, - paramsSchema: getTaskStatusParamsSchema, - resultSchema: taskStatusSchema, + paramsSchema: getTaskResultParamsSchema, + resultSchema: getTaskResultSchema, }, runTask: { description: dedent` diff --git a/garden-service/test/unit/src/actions.ts b/garden-service/test/unit/src/actions.ts index 962d1b3ada..921455df88 100644 --- a/garden-service/test/unit/src/actions.ts +++ b/garden-service/test/unit/src/actions.ts @@ -27,7 +27,7 @@ import { execInServiceParamsSchema, getServiceLogsParamsSchema, runServiceParamsSchema, - getTaskStatusParamsSchema, + getTaskResultParamsSchema, runTaskParamsSchema, getEnvironmentStatusParamsSchema, prepareEnvironmentParamsSchema, @@ -218,6 +218,7 @@ describe("ActionHelper", () => { timeout: 1234, spec: {}, }, + testVersion: module.version, }) expect(result).to.eql({ moduleName: module.name, @@ -238,7 +239,7 @@ describe("ActionHelper", () => { log, module, testName: "test", - version: module.version, + testVersion: module.version, }) expect(result).to.eql({ moduleName: module.name, @@ -331,6 +332,7 @@ describe("ActionHelper", () => { envVars: { FOO: "bar" }, dependencies: {}, }, + taskVersion: task.module.version, }) expect(result).to.eql({ moduleName: task.module.name, @@ -582,10 +584,18 @@ const testPlugin: PluginFactory = async () => ({ } }, - getTaskStatus: async (params) => { - validate(params, getTaskStatusParamsSchema) + getTaskResult: async (params) => { + validate(params, getTaskResultParamsSchema) + const module = params.task.module return { - done: true, + moduleName: module.name, + taskName: params.task.name, + command: ["foo"], + completedAt: now, + output: "bla bla", + success: true, + startedAt: now, + version: params.module.version, } },