diff --git a/core/src/cli/cli.ts b/core/src/cli/cli.ts index 03153cc34e..8ed1b82aa7 100644 --- a/core/src/cli/cli.ts +++ b/core/src/cli/cli.ts @@ -40,6 +40,7 @@ import { GardenPluginCallback } from "../types/plugin/plugin" import { renderError } from "../logger/renderers" import { EnterpriseApi } from "../enterprise/api" import chalk = require("chalk") +import { registerSession } from "../enterprise/session-lifecycle" export async function makeDummyGarden(root: string, gardenOpts: GardenOpts) { const environments = gardenOpts.environmentName @@ -282,6 +283,20 @@ ${renderCommands(commands)} const runningServers = await dashboardEventStream.updateTargets() if (persistent && command.server) { + if (enterpriseApi) { + // TODO: provide the environment & namespace IDs returned by this helper to `this.bufferedEventStream`, + // and include them in all log/event batches once the API is ready for / expects that. + await registerSession({ + log, + enterpriseApi, + sessionId, + commandInfo, + localServerPort: command.server.port, + projectId: enterpriseApi.projectId, + environment: garden.environmentName, + namespace: garden.namespace, + }) + } // If there is an explicit `garden dashboard` process running for the current project+env, and a server // is started in this Command, we show the URL to the external dashboard. Otherwise the built-in one. const dashboardProcess = GardenProcess.getDashboardProcess(runningServers, { diff --git a/core/src/enterprise/session-lifecycle.ts b/core/src/enterprise/session-lifecycle.ts new file mode 100644 index 0000000000..636ba723c3 --- /dev/null +++ b/core/src/enterprise/session-lifecycle.ts @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018-2021 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 { LogEntry } from "../logger/log-entry" +import { CommandInfo } from "../plugin-context" +import { deline } from "../util/string" +import { EnterpriseApi, isGotError } from "./api" + +export interface RegisterSessionParams { + enterpriseApi: EnterpriseApi + sessionId: string + commandInfo: CommandInfo + localServerPort?: number + projectId: string + environment: string + namespace: string + log: LogEntry +} + +export interface RegisterSessionResponse { + environmentId: number + namespaceId: number +} + +// TODO: Read this from the `api-types` package once the session registration logic has been released in Cloud. +/** + * Registers a session for a persistent command with Garden Cloud/Enterprise. This is to help the Cloud/Enterprise + * UI communicate with the locally running Core process. + */ +export async function registerSession({ + enterpriseApi, + sessionId, + commandInfo, + localServerPort, + projectId, + environment, + namespace, + log, +}: RegisterSessionParams): Promise { + try { + const body = { + sessionId, + commandInfo, + localServerPort, + projectUid: projectId, + environment, + namespace, + } + const res: RegisterSessionResponse = await enterpriseApi.post("sessions", { + body, + retry: true, + retryDescription: "Registering session", + }) + return res + } catch (err) { + if (isGotError(err, 422)) { + const errMsg = deline` + Session registration failed due to mismatch between CLI and API versions. Please make sure your Garden CLI + version is compatible with your version of Garden Enterprise. + ` + log.error(errMsg) + } else { + log.error(`An error occurred while registering the session: ${err.message}`) + } + // We don't want the command to fail when an error occurs during session registration. + return null + } +}