Skip to content

Commit

Permalink
feat(openfaas): add log streaming to openfaas plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
edvald committed Dec 4, 2018
1 parent 432e6dc commit 53131b5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
7 changes: 2 additions & 5 deletions garden-service/src/plugins/kubernetes/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@

import * as Bluebird from "bluebird"
import * as execa from "execa"
import * as split from "split"
import { includes } from "lodash"
import moment = require("moment")

import { DeploymentError, ConfigurationError } from "../../exceptions"
import { GetServiceLogsResult, HotReloadResult, RunResult, TestResult } from "../../types/plugin/outputs"
import { HotReloadResult, RunResult, TestResult } from "../../types/plugin/outputs"
import {
ExecInServiceParams,
GetServiceLogsParams,
GetServiceOutputsParams,
GetTestResultParams,
HotReloadParams,
Expand All @@ -28,7 +25,7 @@ import {
} from "../../types/plugin/params"
import { ModuleVersion } from "../../vcs/base"
import { ContainerModule, helpers, validateContainerModule } from "../container"
import { deserializeValues, serializeValues, splitFirst } from "../../util/util"
import { deserializeValues, serializeValues } from "../../util/util"
import { KubeApi } from "./api"
import { getAppNamespace, getMetadataNamespace } from "./namespace"
import { kubectl } from "./kubectl"
Expand Down
48 changes: 27 additions & 21 deletions garden-service/src/plugins/kubernetes/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,35 @@

import * as split from "split"
import moment = require("moment")
import Stream from "ts-stream"

import { GetServiceLogsResult, ServiceLogEntry } from "../../types/plugin/outputs"
import { GetServiceLogsResult } from "../../types/plugin/outputs"
import { GetServiceLogsParams } from "../../types/plugin/params"
import { ContainerModule } from "../container"
import { getAppNamespace } from "./namespace"
import { splitFirst } from "../../util/util"
import { BinaryCmd } from "../../util/ext-tools"
import { kubectl } from "./kubectl"
import { ContainerService } from "../../../tmp/dist/build/plugins/container"
import { LogEntry } from "../../logger/log-entry"

export async function getServiceLogs(
{ ctx, log, service, stream, tail }: GetServiceLogsParams<ContainerModule>,
) {
interface GetKubernetesLogsParams extends GetServiceLogsParams {
context: string
namespace: string
selector: string
}

export async function getServiceLogs(params: GetServiceLogsParams<ContainerModule>) {
const { ctx, service } = params
const context = ctx.provider.config.context
const namespace = await getAppNamespace(ctx, ctx.provider)
const selector = `service=${service.name}`

return getKubernetesLogs({ ...params, context, namespace, selector })
}

const proc = tail
? await tailLogs(context, namespace, service, stream, log)
: await getLogs(context, namespace, service, stream)
export async function getKubernetesLogs(params: GetKubernetesLogsParams) {
// Currently Stern doesn't support just returning the logs and exiting, it can only follow
const proc = params.tail
? await tailLogs(params)
: await getLogs(params)

return new Promise<GetServiceLogsResult>((resolve, reject) => {
proc.on("error", reject)
Expand All @@ -39,20 +47,16 @@ export async function getServiceLogs(
})
}

async function tailLogs(
context: string, namespace: string, service: ContainerService, stream: Stream<ServiceLogEntry>, log: LogEntry,
) {
async function tailLogs({ context, namespace, service, selector, stream, log }: GetKubernetesLogsParams) {
const args = [
"--color", "never",
"--context", context,
"--namespace", namespace,
"--output", "json",
"--selector", `service=${service.name}`,
"--selector", selector,
"--timestamps",
]

console.log(args.join(" "))

const proc = await stern.spawn({ args, log })
let timestamp: Date | undefined

Expand All @@ -73,11 +77,13 @@ async function tailLogs(
return proc
}

async function getLogs(
context: string, namespace: string, service: ContainerService, stream: Stream<ServiceLogEntry>,
) {
const resourceType = service.spec.daemon ? "daemonset" : "deployment"
const kubectlArgs = ["logs", `${resourceType}/${service.name}`, "--timestamps=true"]
async function getLogs({ context, namespace, service, selector, stream }: GetKubernetesLogsParams) {
// TODO: do this via API instead of kubectl
const kubectlArgs = [
"logs",
"--selector", selector,
"--timestamps=true",
]

const proc = kubectl(context, namespace).spawn(kubectlArgs)
let timestamp: Date
Expand Down
11 changes: 11 additions & 0 deletions garden-service/src/plugins/openfaas/openfaas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
GetEnvironmentStatusParams,
ValidateModuleParams,
DeleteServiceParams,
GetServiceLogsParams,
} from "../../types/plugin/params"
import {
ServiceStatus,
Expand Down Expand Up @@ -53,6 +54,7 @@ import { Provider, providerConfigBaseSchema } from "../../config/project"
import { faasCli } from "./faas-cli"
import { CleanupEnvironmentParams } from "../../types/plugin/params"
import dedent = require("dedent")
import { getKubernetesLogs } from "../kubernetes/logs"

const systemProjectPath = join(STATIC_DIR, "openfaas", "system")
export const stackFilename = "stack.yml"
Expand Down Expand Up @@ -209,6 +211,15 @@ export function gardenPlugin({ config }: { config: OpenFaasConfig }): GardenPlug
}
},

async getServiceLogs(params: GetServiceLogsParams<OpenFaasModule>) {
const { ctx, service } = params
const k8sProvider = getK8sProvider(ctx)
const context = k8sProvider.config.context
const namespace = await getAppNamespace(ctx, k8sProvider)
const selector = `faas_function=${service.name}`
return getKubernetesLogs({ ...params, context, namespace, selector })
},

async deployService(params: DeployServiceParams<OpenFaasModule>): Promise<ServiceStatus> {
const { ctx, module, service, log, runtimeContext } = params

Expand Down

0 comments on commit 53131b5

Please sign in to comment.