From fd58037996a52240b2a820b8b6923bac2545a6df Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Tue, 20 Aug 2019 13:24:36 +0200 Subject: [PATCH] feat(container): add build.timeout option --- docs/reference/module-types/container.md | 11 +++++ .../reference/module-types/maven-container.md | 11 +++++ garden-service/src/plugins/container/build.ts | 3 +- .../src/plugins/container/config.ts | 5 +++ .../src/plugins/container/container.ts | 1 - .../src/plugins/container/helpers.ts | 8 +++- .../src/plugins/kubernetes/container/build.ts | 5 +-- .../local/local-google-cloud-functions.ts | 2 + garden-service/src/plugins/openfaas/config.ts | 5 +++ .../unit/src/plugins/container/container.ts | 44 ++++++++++++++----- .../unit/src/plugins/container/helpers.ts | 12 +++-- 11 files changed, 87 insertions(+), 20 deletions(-) diff --git a/docs/reference/module-types/container.md b/docs/reference/module-types/container.md index 278398f0e9..393c537183 100644 --- a/docs/reference/module-types/container.md +++ b/docs/reference/module-types/container.md @@ -214,6 +214,16 @@ For multi-stage Dockerfiles, specify which image to build (see https://docs.dock | -------- | -------- | | `string` | No | +### `build.timeout` + +[build](#build) > timeout + +Maximum time in seconds to wait for build to finish. + +| Type | Required | Default | +| -------- | -------- | ------- | +| `number` | No | `1200` | + ### `buildArgs` Specify build arguments to use when building the container image. @@ -969,6 +979,7 @@ build: - source: target: targetImage: + timeout: 1200 buildArgs: {} extraFlags: image: diff --git a/docs/reference/module-types/maven-container.md b/docs/reference/module-types/maven-container.md index 4e3c3c67b1..c4d7574ac0 100644 --- a/docs/reference/module-types/maven-container.md +++ b/docs/reference/module-types/maven-container.md @@ -219,6 +219,16 @@ For multi-stage Dockerfiles, specify which image to build (see https://docs.dock | -------- | -------- | | `string` | No | +### `build.timeout` + +[build](#build) > timeout + +Maximum time in seconds to wait for build to finish. + +| Type | Required | Default | +| -------- | -------- | ------- | +| `number` | No | `1200` | + ### `buildArgs` Specify build arguments to use when building the container image. @@ -1004,6 +1014,7 @@ build: - source: target: targetImage: + timeout: 1200 buildArgs: {} extraFlags: image: diff --git a/garden-service/src/plugins/container/build.ts b/garden-service/src/plugins/container/build.ts index a75cffa765..0668f15319 100644 --- a/garden-service/src/plugins/container/build.ts +++ b/garden-service/src/plugins/container/build.ts @@ -63,7 +63,8 @@ export async function buildContainerModule({ module, log }: BuildModuleParams ({ moduleActions: { container: { diff --git a/garden-service/src/plugins/container/helpers.ts b/garden-service/src/plugins/container/helpers.ts index 10c0ee326e..94362ef7ec 100644 --- a/garden-service/src/plugins/container/helpers.ts +++ b/garden-service/src/plugins/container/helpers.ts @@ -13,6 +13,7 @@ import { splitFirst, spawn, splitLast } from "../../util/util" import { ModuleConfig } from "../../config/module" import { ContainerModule, ContainerRegistryConfig, defaultTag, defaultNamespace, ContainerModuleConfig } from "./config" +export const DEFAULT_BUILD_TIMEOUT = 600 export const minDockerVersion = "17.07.0" interface ParsedImageId { @@ -248,13 +249,16 @@ const helpers = { helpers.dockerVersionChecked = true }, - async dockerCli(module: ContainerModule, args: string[]) { + async dockerCli( + module: ContainerModule, args: string[], + { timeout = DEFAULT_BUILD_TIMEOUT }: { timeout?: number } = {}, + ) { await helpers.checkDockerVersion() const cwd = module.buildPath try { - const res = await spawn("docker", args, { cwd }) + const res = await spawn("docker", args, { cwd, timeout }) return res.output || "" } catch (err) { throw new RuntimeError( diff --git a/garden-service/src/plugins/kubernetes/container/build.ts b/garden-service/src/plugins/kubernetes/container/build.ts index c1fab72513..3e32c4c1ef 100644 --- a/garden-service/src/plugins/kubernetes/container/build.ts +++ b/garden-service/src/plugins/kubernetes/container/build.ts @@ -30,8 +30,6 @@ import { getPortForward } from "../port-forward" const dockerDaemonDeploymentName = "garden-docker-daemon" const dockerDaemonContainerName = "docker-daemon" -// TODO: make build timeout configurable -const buildTimeout = 600 // Note: v0.9.0 appears to be completely broken: https://github.com/GoogleContainerTools/kaniko/issues/268 const kanikoImage = "gcr.io/kaniko-project/executor:v0.8.0" const registryPort = 5000 @@ -176,6 +174,7 @@ const remoteBuild: BuildHandler = async (params) => { // Execute the build const podName = await getBuilderPodName(provider, log) + const buildTimeout = module.spec.build.timeout const buildRes = await execInBuilder({ provider, log, args, timeout: buildTimeout, podName }) buildLog = buildRes.stdout + buildRes.stderr @@ -325,6 +324,6 @@ async function runKaniko(provider: KubernetesProvider, log: LogEntry, module: Co }], }, podName, - timeout: buildTimeout, + timeout: module.spec.build.timeout, }) } diff --git a/garden-service/src/plugins/local/local-google-cloud-functions.ts b/garden-service/src/plugins/local/local-google-cloud-functions.ts index 83836b3889..520fb6d298 100644 --- a/garden-service/src/plugins/local/local-google-cloud-functions.ts +++ b/garden-service/src/plugins/local/local-google-cloud-functions.ts @@ -15,6 +15,7 @@ import { ContainerModuleConfig } from "../container/config" import { ContainerServiceSpec, ServicePortProtocol } from "../container/config" import { ConfigureProviderParams } from "../../types/plugin/provider/configureProvider" import { ConfigureModuleParams } from "../../types/plugin/module/configure" +import { DEFAULT_BUILD_TIMEOUT } from "../container/helpers" const pluginName = "local-google-cloud-functions" const emulatorModuleName = "local-gcf-container" @@ -39,6 +40,7 @@ export const gardenPlugin = (): GardenPlugin => ({ spec: { build: { dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, }, buildArgs: {}, extraFlags: [], diff --git a/garden-service/src/plugins/openfaas/config.ts b/garden-service/src/plugins/openfaas/config.ts index 80d4a5d687..0ded0835f9 100644 --- a/garden-service/src/plugins/openfaas/config.ts +++ b/garden-service/src/plugins/openfaas/config.ts @@ -24,6 +24,7 @@ import { ConfigureModuleParams, ConfigureModuleResult } from "../../types/plugin import { getNamespace } from "../kubernetes/namespace" import { LogEntry } from "../../logger/log-entry" import { baseBuildSpecSchema } from "../../config/module" +import { DEFAULT_BUILD_TIMEOUT } from "../container/helpers" export interface OpenFaasModuleSpec extends ExecModuleSpec { handler: string @@ -115,6 +116,10 @@ export function getContainerModule(module: OpenFaasModule): ContainerModule { ...module, spec: { ...module.spec, + build: { + ...module.spec.build, + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, dockerfile: "Dockerfile", extraFlags: [], diff --git a/garden-service/test/unit/src/plugins/container/container.ts b/garden-service/test/unit/src/plugins/container/container.ts index a9228617ff..e84d558394 100644 --- a/garden-service/test/unit/src/plugins/container/container.ts +++ b/garden-service/test/unit/src/plugins/container/container.ts @@ -19,7 +19,11 @@ import { ContainerModuleConfig, defaultContainerLimits, } from "../../../../../src/plugins/container/config" -import { containerHelpers as helpers, minDockerVersion } from "../../../../../src/plugins/container/helpers" +import { + containerHelpers as helpers, + minDockerVersion, + DEFAULT_BUILD_TIMEOUT, +} from "../../../../../src/plugins/container/helpers" describe("plugins.container", () => { const projectRoot = resolve(dataDir, "test-project-container") @@ -44,7 +48,10 @@ describe("plugins.container", () => { type: "container", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: [], @@ -96,7 +103,10 @@ describe("plugins.container", () => { type: "container", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: [{ @@ -174,7 +184,10 @@ describe("plugins.container", () => { type: "container", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: @@ -304,7 +317,10 @@ describe("plugins.container", () => { type: "test", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: [{ @@ -366,7 +382,10 @@ describe("plugins.container", () => { type: "test", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: [{ @@ -422,7 +441,10 @@ describe("plugins.container", () => { type: "test", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: [{ @@ -517,7 +539,8 @@ describe("plugins.container", () => { details: { identifier: "some/image" }, }) - td.verify(dockerCli(module, ["build", "-t", "some/image", module.buildPath])) + const cmdArgs = ["build", "-t", "some/image", module.buildPath] + td.verify(dockerCli(module, cmdArgs, { timeout: DEFAULT_BUILD_TIMEOUT })) }) it("should set build target image parameter if configured", async () => { @@ -540,7 +563,8 @@ describe("plugins.container", () => { details: { identifier: "some/image" }, }) - td.verify(dockerCli(module, ["build", "-t", "some/image", "--target", "foo", module.buildPath])) + const cmdArgs = ["build", "-t", "some/image", "--target", "foo", module.buildPath] + td.verify(dockerCli(module, cmdArgs, { timeout: DEFAULT_BUILD_TIMEOUT })) }) it("should build image using the user specified Dockerfile path", async () => { @@ -572,7 +596,7 @@ describe("plugins.container", () => { join(module.buildPath, relDockerfilePath), module.buildPath, ] - td.verify(dockerCli(module, cmdArgs)) + td.verify(dockerCli(module, cmdArgs, { timeout: DEFAULT_BUILD_TIMEOUT })) }) }) diff --git a/garden-service/test/unit/src/plugins/container/helpers.ts b/garden-service/test/unit/src/plugins/container/helpers.ts index 6139c71040..8e1906a053 100644 --- a/garden-service/test/unit/src/plugins/container/helpers.ts +++ b/garden-service/test/unit/src/plugins/container/helpers.ts @@ -18,7 +18,7 @@ import { ContainerModuleSpec, ContainerModuleConfig, } from "../../../../../src/plugins/container/config" -import { containerHelpers as helpers } from "../../../../../src/plugins/container/helpers" +import { containerHelpers as helpers, DEFAULT_BUILD_TIMEOUT } from "../../../../../src/plugins/container/helpers" describe("containerHelpers", () => { const projectRoot = resolve(dataDir, "test-project-container") @@ -40,7 +40,10 @@ describe("containerHelpers", () => { type: "container", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], services: [], @@ -233,7 +236,10 @@ describe("containerHelpers", () => { type: "container", spec: { - build: { dependencies: [] }, + build: { + dependencies: [], + timeout: DEFAULT_BUILD_TIMEOUT, + }, buildArgs: {}, extraFlags: [], image: "some/image",