From 6247cef12e1595ac70919ac0b74fd8c13097ee71 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Tue, 9 Feb 2021 18:27:51 +0100 Subject: [PATCH] feat(helm): allow disabling atomic installs/upgrades This adds an `atomicInstall` option to `helm` modules. Set this to `false` if you prefer Helm not to automatically roll back. This is handy if you're trying to track down installation issues and want to inspect deployed resources and statuses. --- core/src/plugins/kubernetes/helm/config.ts | 17 ++++++++++++----- core/src/plugins/kubernetes/helm/deployment.ts | 16 +++++++--------- core/src/plugins/openfaas/openfaas.ts | 1 + .../plugins/kubernetes/commands/pull-image.ts | 16 ++++++++++------ .../integ/src/plugins/kubernetes/helm/config.ts | 2 ++ docs/misc/faq.md | 2 +- docs/reference/module-types/helm.md | 12 ++++++++++++ 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/core/src/plugins/kubernetes/helm/config.ts b/core/src/plugins/kubernetes/helm/config.ts index 83c32b0fd8..ab75390333 100644 --- a/core/src/plugins/kubernetes/helm/config.ts +++ b/core/src/plugins/kubernetes/helm/config.ts @@ -47,6 +47,7 @@ export interface HelmModule export type HelmModuleConfig = HelmModule["_config"] export interface HelmServiceSpec { + atomicInstall: boolean base?: string chart?: string chartPath: string @@ -123,6 +124,12 @@ const helmTestSchema = () => export const helmModuleSpecSchema = () => joi.object().keys({ + atomicInstall: joi + .boolean() + .default(true) + .description( + "Whether to set the --atomic flag during installs and upgrades. Set to false if e.g. you want to see more information about failures and then manually roll back, instead of having Helm do it automatically on failure." + ), base: joiUserIdentifier() .description( deline`The name of another \`helm\` module to use as a base for this one. Use this to re-use a Helm chart across @@ -175,12 +182,12 @@ export const helmModuleSpecSchema = () => Use this, for example, if the chart should only be used as a base for other modules.` ), include: joiModuleIncludeDirective(dedent` - If neither \`include\` nor \`exclude\` is set, and the module has local chart sources, Garden - automatically sets \`include\` to: \`["*", "charts/**/*", "templates/**/*"]\`. + If neither \`include\` nor \`exclude\` is set, and the module has local chart sources, Garden + automatically sets \`include\` to: \`["*", "charts/**/*", "templates/**/*"]\`. - If neither \`include\` nor \`exclude\` is set and the module specifies a remote chart, Garden - automatically sets \`ìnclude\` to \`[]\`. - `), + If neither \`include\` nor \`exclude\` is set and the module specifies a remote chart, Garden + automatically sets \`ìnclude\` to \`[]\`. + `), tasks: joiArray(helmTaskSchema()).description("The task definitions for this module."), tests: joiArray(helmTestSchema()).description("The test suite definitions for this module."), timeout: joi diff --git a/core/src/plugins/kubernetes/helm/deployment.ts b/core/src/plugins/kubernetes/helm/deployment.ts index dad5b51b57..9493c2907d 100644 --- a/core/src/plugins/kubernetes/helm/deployment.ts +++ b/core/src/plugins/kubernetes/helm/deployment.ts @@ -65,23 +65,21 @@ export async function deployHelmService({ ...(await getValueArgs(module, hotReload)), ] + if (module.spec.atomicInstall) { + // Make sure chart gets purged if it fails to install + commonArgs.push("--atomic") + } + if (releaseStatus.state === "missing") { log.silly(`Installing Helm release ${releaseName}`) - const installArgs = [ - "install", - releaseName, - chartPath, - // Make sure chart gets purged if it fails to install - "--atomic", - ...commonArgs, - ] + const installArgs = ["install", releaseName, chartPath, ...commonArgs] if (force && !ctx.production) { installArgs.push("--replace") } await helm({ ctx: k8sCtx, namespace, log, args: [...installArgs] }) } else { log.silly(`Upgrading Helm release ${releaseName}`) - const upgradeArgs = ["upgrade", releaseName, chartPath, "--install", "--atomic", ...commonArgs] + const upgradeArgs = ["upgrade", releaseName, chartPath, "--install", ...commonArgs] await helm({ ctx: k8sCtx, namespace, log, args: [...upgradeArgs] }) } diff --git a/core/src/plugins/openfaas/openfaas.ts b/core/src/plugins/openfaas/openfaas.ts index 3cf0ec5789..d2509d67fd 100644 --- a/core/src/plugins/openfaas/openfaas.ts +++ b/core/src/plugins/openfaas/openfaas.ts @@ -202,6 +202,7 @@ async function configureProvider({ testConfigs: [], type: "helm", spec: { + atomicInstall: true, repo: "https://openfaas.github.io/faas-netes/", chart: "openfaas", chartPath: ".", diff --git a/core/test/integ/src/plugins/kubernetes/commands/pull-image.ts b/core/test/integ/src/plugins/kubernetes/commands/pull-image.ts index adda0af6a9..168af56490 100644 --- a/core/test/integ/src/plugins/kubernetes/commands/pull-image.ts +++ b/core/test/integ/src/plugins/kubernetes/commands/pull-image.ts @@ -39,12 +39,16 @@ describe("pull-image plugin command", () => { async function removeImage(module: GardenModule) { const imageId = containerHelpers.getLocalImageId(module, module.version) - await containerHelpers.dockerCli({ - cwd: "/tmp", - args: ["rmi", imageId], - log: garden.log, - ctx, - }) + try { + await containerHelpers.dockerCli({ + cwd: "/tmp", + args: ["rmi", imageId], + log: garden.log, + ctx, + }) + } catch { + // This is fine, the image may not already be there + } } async function ensureImagePulled(module: GardenModule) { diff --git a/core/test/integ/src/plugins/kubernetes/helm/config.ts b/core/test/integ/src/plugins/kubernetes/helm/config.ts index 702d21b23c..186c66c97e 100644 --- a/core/test/integ/src/plugins/kubernetes/helm/config.ts +++ b/core/test/integ/src/plugins/kubernetes/helm/config.ts @@ -71,6 +71,7 @@ describe("configureHelmModule", () => { hotReloadable: true, sourceModuleName: "api-image", spec: { + atomicInstall: true, build: { dependencies: [], }, @@ -100,6 +101,7 @@ describe("configureHelmModule", () => { }, ], spec: { + atomicInstall: true, build: { dependencies: [], }, diff --git a/docs/misc/faq.md b/docs/misc/faq.md index c168e52bee..72a174fd8b 100644 --- a/docs/misc/faq.md +++ b/docs/misc/faq.md @@ -150,7 +150,7 @@ See [this section](https://docs.garden.io/guides/in-cluster-building#pulling-bas ### How do I use my own private registry in in-cluster build mode? -See [this section](https://docs.garden.io/guides/in-cluster-building#using-private-registries-for-deployments) of our docs. +See [this section](https://docs.garden.io/guides/in-cluster-building#configuring-a-deployment-registry) of our docs. ### How do I clean up the in-cluster registry and build sync volumes? diff --git a/docs/reference/module-types/helm.md b/docs/reference/module-types/helm.md index f8fa6924f9..99ea9d9c52 100644 --- a/docs/reference/module-types/helm.md +++ b/docs/reference/module-types/helm.md @@ -125,6 +125,10 @@ generateFiles: # The desired file contents as a string. value: +# Whether to set the --atomic flag during installs and upgrades. Set to false if e.g. you want to see more information +# about failures and then manually roll back, instead of having Helm do it automatically on failure. +atomicInstall: true + # The name of another `helm` module to use as a base for this one. Use this to re-use a Helm chart across multiple # services. For example, you might have an organization-wide base chart for certain types of services. # If set, this module will by default inherit the following properties from the base module: `serviceResource`, @@ -666,6 +670,14 @@ The desired file contents as a string. | -------- | -------- | | `string` | No | +### `atomicInstall` + +Whether to set the --atomic flag during installs and upgrades. Set to false if e.g. you want to see more information about failures and then manually roll back, instead of having Helm do it automatically on failure. + +| Type | Default | Required | +| --------- | ------- | -------- | +| `boolean` | `true` | No | + ### `base` The name of another `helm` module to use as a base for this one. Use this to re-use a Helm chart across multiple services. For example, you might have an organization-wide base chart for certain types of services.