Skip to content

Commit

Permalink
feat(k8s): use pod spec fields in tasks and tests
Browse files Browse the repository at this point in the history
For `helm` and `kubernetes` modules, we now use most pod spec fields from
the service resource when running the task/test (based on a fixed
whitelist of pod spec fields).

This allows tasks/tests to e.g. use custom service accounts, node
selectors etc.
  • Loading branch information
thsig authored and edvald committed Feb 3, 2021
1 parent 4ac311d commit ce1e8ed
Show file tree
Hide file tree
Showing 14 changed files with 734 additions and 115 deletions.
17 changes: 13 additions & 4 deletions core/src/plugins/kubernetes/config.ts
Expand Up @@ -27,6 +27,7 @@ import { baseTaskSpecSchema, BaseTaskSpec, cacheResultSchema } from "../../confi
import { baseTestSpecSchema, BaseTestSpec } from "../../config/test"
import { ArtifactSpec } from "../../config/validation"
import { V1Toleration } from "@kubernetes/client-node"
import { runPodSpecWhitelist } from "./run"

export const DEFAULT_KANIKO_IMAGE = "gcr.io/kaniko-project/executor:debug-v1.2.0"
export interface ProviderSecretRef {
Expand Down Expand Up @@ -642,13 +643,18 @@ export const hotReloadArgsSchema = () =>
.description("If specified, overrides the arguments for the main container when running in hot-reload mode.")
.example(["nodemon", "my-server.js"])

const runPodSpecWhitelistDescription = runPodSpecWhitelist.map((f) => `* \`${f}\``).join("\n")

export const kubernetesTaskSchema = () =>
baseTaskSpecSchema()
.keys({
resource: serviceResourceSchema().description(
deline`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this task.
dedent`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this task.
If not specified, the \`serviceResource\` configured on the module will be used. If neither is specified,
an error will be thrown.`
an error will be thrown.
The following pod spec fields from the service resource will be used (if present) when executing the task:
${runPodSpecWhitelistDescription}`
),
cacheResult: cacheResultSchema(),
command: joi
Expand All @@ -670,9 +676,12 @@ export const kubernetesTestSchema = () =>
baseTestSpecSchema()
.keys({
resource: serviceResourceSchema().description(
deline`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this test suite.
dedent`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this test suite.
If not specified, the \`serviceResource\` configured on the module will be used. If neither is specified,
an error will be thrown.`
an error will be thrown.
The following pod spec fields from the service resource will be used (if present) when executing the test suite:
${runPodSpecWhitelistDescription}`
),
command: joi
.array()
Expand Down
19 changes: 14 additions & 5 deletions core/src/plugins/kubernetes/helm/config.ts
Expand Up @@ -35,6 +35,7 @@ import {
hotReloadArgsSchema,
} from "../config"
import { posix } from "path"
import { runPodSpecWhitelist } from "../run"

export const defaultHelmTimeout = 300

Expand Down Expand Up @@ -82,7 +83,7 @@ export const helmModuleOutputsSchema = () =>
const helmServiceResourceSchema = () =>
serviceResourceSchema().keys({
name: joi.string().description(
deline`The name of the resource to sync to. If the chart contains a single resource of the specified Kind,
dedent`The name of the resource to sync to. If the chart contains a single resource of the specified Kind,
this can be omitted.
This can include a Helm template string, e.g. '{{ template "my-chart.fullname" . }}'.
Expand All @@ -94,21 +95,29 @@ const helmServiceResourceSchema = () =>
hotReloadArgs: hotReloadArgsSchema(),
})

const runPodSpecWhitelistDescription = runPodSpecWhitelist.map((f) => `* \`${f}\``).join("\n")

const helmTaskSchema = () =>
kubernetesTaskSchema().keys({
resource: helmServiceResourceSchema().description(
deline`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this task.
dedent`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this task.
If not specified, the \`serviceResource\` configured on the module will be used. If neither is specified,
an error will be thrown.`
an error will be thrown.
The following pod spec fields from the service resource will be used (if present) when executing the task:
${runPodSpecWhitelistDescription}`
),
})

const helmTestSchema = () =>
kubernetesTestSchema().keys({
resource: helmServiceResourceSchema().description(
deline`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this test suite.
dedent`The Deployment, DaemonSet or StatefulSet that Garden should use to execute this test suite.
If not specified, the \`serviceResource\` configured on the module will be used. If neither is specified,
an error will be thrown.`
an error will be thrown.
The following pod spec fields from the service resource will be used (if present) when executing the test suite:
${runPodSpecWhitelistDescription}`
),
})

Expand Down
9 changes: 8 additions & 1 deletion core/src/plugins/kubernetes/helm/run.ts
Expand Up @@ -9,7 +9,13 @@
import { HelmModule } from "./config"
import { PodRunner, runAndCopy } from "../run"
import { getChartResources, getBaseModule } from "./common"
import { findServiceResource, getResourceContainer, getServiceResourceSpec, makePodName } from "../util"
import {
findServiceResource,
getResourceContainer,
getResourcePodSpec,
getServiceResourceSpec,
makePodName,
} from "../util"
import { ConfigurationError } from "../../../exceptions"
import { KubernetesPluginContext } from "../config"
import { storeTaskResult } from "../task-results"
Expand Down Expand Up @@ -137,6 +143,7 @@ export async function runHelmTask(params: RunTaskParams<HelmModule>): Promise<Ru
const res = await runAndCopy({
...params,
container,
podSpec: getResourcePodSpec(target),
command,
args,
artifacts: task.spec.artifacts,
Expand Down
9 changes: 8 additions & 1 deletion core/src/plugins/kubernetes/helm/test.ts
Expand Up @@ -14,7 +14,13 @@ import { getChartResources, getBaseModule } from "./common"
import { KubernetesPluginContext } from "../config"
import { TestModuleParams } from "../../../types/plugin/module/testModule"
import { TestResult } from "../../../types/plugin/module/getTestResult"
import { getServiceResourceSpec, findServiceResource, getResourceContainer, makePodName } from "../util"
import {
getServiceResourceSpec,
findServiceResource,
getResourceContainer,
makePodName,
getResourcePodSpec,
} from "../util"
import { getModuleNamespace } from "../namespace"

export async function testHelmModule(params: TestModuleParams<HelmModule>): Promise<TestResult> {
Expand Down Expand Up @@ -42,6 +48,7 @@ export async function testHelmModule(params: TestModuleParams<HelmModule>): Prom
const result = await runAndCopy({
...params,
container,
podSpec: getResourcePodSpec(target),
command,
args,
artifacts: testConfig.spec.artifacts,
Expand Down
9 changes: 8 additions & 1 deletion core/src/plugins/kubernetes/kubernetes-module/run.ts
Expand Up @@ -8,7 +8,13 @@

import { KubernetesModule } from "./config"
import { runAndCopy } from "../run"
import { findServiceResource, getResourceContainer, getServiceResourceSpec, makePodName } from "../util"
import {
findServiceResource,
getResourceContainer,
getResourcePodSpec,
getServiceResourceSpec,
makePodName,
} from "../util"
import { KubernetesPluginContext } from "../config"
import { storeTaskResult } from "../task-results"
import { RunTaskParams, RunTaskResult } from "../../../types/plugin/task/runTask"
Expand Down Expand Up @@ -45,6 +51,7 @@ export async function runKubernetesTask(params: RunTaskParams<KubernetesModule>)
const res = await runAndCopy({
...params,
container,
podSpec: getResourcePodSpec(target),
command,
args,
artifacts: task.spec.artifacts,
Expand Down
9 changes: 8 additions & 1 deletion core/src/plugins/kubernetes/kubernetes-module/test.ts
Expand Up @@ -16,7 +16,13 @@ import { TestResult } from "../../../types/plugin/module/getTestResult"
import { getModuleNamespace } from "../namespace"
import { KubeApi } from "../api"
import { getManifests } from "./common"
import { getServiceResourceSpec, findServiceResource, getResourceContainer, makePodName } from "../util"
import {
getServiceResourceSpec,
findServiceResource,
getResourceContainer,
makePodName,
getResourcePodSpec,
} from "../util"

export async function testKubernetesModule(params: TestModuleParams<KubernetesModule>): Promise<TestResult> {
const { ctx, log, module, testConfig, testVersion } = params
Expand All @@ -43,6 +49,7 @@ export async function testKubernetesModule(params: TestModuleParams<KubernetesMo
const result = await runAndCopy({
...params,
container,
podSpec: getResourcePodSpec(target),
command,
args,
artifacts: testConfig.spec.artifacts,
Expand Down

0 comments on commit ce1e8ed

Please sign in to comment.