Skip to content

Commit 9fa0cb8

Browse files
committed
feat(container): add env key to specify env vars for containers
Also removed the `variables` key from the base test spec schema, and instead added the `env` key to the `generic` test spec schema (which is inherited by the `container` schema). BREAKING CHANGE: The `tests[].variables` config key has been removed from the `garden.yml` configuration file schema.
1 parent a5096ee commit 9fa0cb8

File tree

21 files changed

+127
-95
lines changed

21 files changed

+127
-95
lines changed

docs/reference/config.md

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,13 @@ module:
271271
target:
272272

273273

274+
# Key/value map of environment variables. Keys must be valid POSIX environment variable names
275+
# (must be uppercase, may not start with `GARDEN`) and values must be primitives.
276+
#
277+
# Optional.
278+
env:
279+
{}
280+
274281
# A list of tests to run in the module.
275282
#
276283
# Optional.
@@ -290,12 +297,6 @@ module:
290297
-
291298

292299

293-
# Map of key/value pairs that are available during the test execution.
294-
#
295-
# Optional.
296-
variables:
297-
{}
298-
299300
# Maximum duration (in seconds) of the test run.
300301
#
301302
# Optional.
@@ -305,7 +306,15 @@ module:
305306
#
306307
# Optional.
307308
command:
308-
-
309+
-
310+
311+
312+
# Key/value map of environment variables. Keys must be valid POSIX environment variable
313+
# names (must be uppercase, may not start with `GARDEN`) and values must be primitives.
314+
#
315+
# Optional.
316+
env:
317+
{}
309318

310319
```
311320

@@ -387,43 +396,6 @@ module:
387396
target:
388397

389398

390-
# A list of tests to run in the module.
391-
#
392-
# Optional.
393-
tests:
394-
# The test specification of a generic module.
395-
#
396-
# Optional.
397-
- # The name of the test.
398-
#
399-
# Required.
400-
name:
401-
402-
# The names of services that must be running before the test is run.
403-
#
404-
# Optional.
405-
dependencies:
406-
-
407-
408-
409-
# Map of key/value pairs that are available during the test execution.
410-
#
411-
# Optional.
412-
variables:
413-
{}
414-
415-
# Maximum duration (in seconds) of the test run.
416-
#
417-
# Optional.
418-
timeout:
419-
420-
# The command to run in the module build context in order to test it.
421-
#
422-
# Optional.
423-
command:
424-
-
425-
426-
427399
# Specify build arguments when building the container image.
428400
#
429401
# Optional.
@@ -499,6 +471,13 @@ module:
499471
port:
500472

501473

474+
# Key/value map of environment variables. Keys must be valid POSIX environment variable
475+
# names (must be uppercase, may not start with `GARDEN`) and values must be primitives.
476+
#
477+
# Optional.
478+
env:
479+
{}
480+
502481
# Specify how the service's health should be checked after deploying.
503482
#
504483
# Optional.
@@ -578,5 +557,44 @@ module:
578557

579558
hostPath:
580559

560+
561+
# A list of tests to run in the module.
562+
#
563+
# Optional.
564+
tests:
565+
# The test specification of a generic module.
566+
#
567+
# Optional.
568+
- # The name of the test.
569+
#
570+
# Required.
571+
name:
572+
573+
# The names of services that must be running before the test is run.
574+
#
575+
# Optional.
576+
dependencies:
577+
-
578+
579+
580+
# Maximum duration (in seconds) of the test run.
581+
#
582+
# Optional.
583+
timeout:
584+
585+
# The command to run in the module build context in order to test it.
586+
#
587+
# Optional.
588+
command:
589+
-
590+
591+
592+
# Key/value map of environment variables. Keys must be valid POSIX environment variable
593+
# names (must be uppercase, may not start with `GARDEN`) and values must be primitives.
594+
#
595+
# Optional.
596+
env:
597+
{}
598+
581599
```
582600

examples/hello-world/services/hello-container/garden.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ module:
1616
port: http
1717
dependencies:
1818
- hello-function
19+
env:
20+
FUNCTION_ENDPOINT: ${dependencies.hello-function.outputs.endpoint}
1921
build:
2022
dependencies:
2123
- hello-npm-package

src/plugins/container.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from "../types/module"
1616
import { LogSymbolType } from "../logger/types"
1717
import {
18+
joiEnvVars,
1819
joiIdentifier,
1920
joiArray,
2021
validate,
@@ -43,12 +44,7 @@ import {
4344
import { DEFAULT_PORT_PROTOCOL } from "../constants"
4445
import { splitFirst } from "../util/util"
4546
import { keyBy } from "lodash"
46-
import {
47-
genericModuleSpecSchema,
48-
GenericModuleSpec,
49-
GenericTestSpec,
50-
genericTestSchema,
51-
} from "./generic"
47+
import { genericTestSchema, GenericTestSpec } from "./generic"
5248

5349
export interface ServiceEndpointSpec {
5450
paths?: string[]
@@ -87,6 +83,7 @@ export interface ContainerServiceSpec extends BaseServiceSpec {
8783
command: string[],
8884
daemon: boolean
8985
endpoints: ServiceEndpointSpec[],
86+
env: PrimitiveMap,
9087
healthCheck?: ServiceHealthCheckSpec,
9188
ports: ServicePortSpec[],
9289
volumes: ServiceVolumeSpec[],
@@ -168,6 +165,7 @@ const serviceSchema = baseServiceSchema
168165
.description("Whether to run the service as a daemon (to ensure only one runs per node)."),
169166
endpoints: joiArray(endpointSchema)
170167
.description("List of endpoints that the service exposes."),
168+
env: joiEnvVars(),
171169
healthCheck: healthCheckSchema
172170
.description("Specify how the service's health should be checked after deploying."),
173171
ports: joiArray(portSchema)
@@ -178,11 +176,17 @@ const serviceSchema = baseServiceSchema
178176
.description("List of volumes that should be mounted when deploying the container."),
179177
})
180178

179+
export class ContainerService extends Service<ContainerModule> { }
180+
181+
export interface ContainerTestSpec extends GenericTestSpec { }
182+
183+
export const containerTestSchema = genericTestSchema
184+
181185
export interface ContainerModuleSpec extends ModuleSpec {
182186
buildArgs: PrimitiveMap,
183187
image?: string,
184188
services: ContainerServiceSpec[],
185-
tests: GenericTestSpec[],
189+
tests: ContainerTestSpec[],
186190
}
187191

188192
export type ContainerModuleConfig = ModuleConfig<ContainerModuleSpec>
@@ -203,17 +207,15 @@ export const containerModuleSpecSchema = Joi.object()
203207
services: joiArray(serviceSchema)
204208
.unique("name")
205209
.description("List of services to deploy from this container module."),
206-
tests: joiArray(genericTestSchema)
210+
tests: joiArray(containerTestSchema)
207211
.description("A list of tests to run in the module."),
208212
})
209213
.description("Configuration for a container module.")
210214

211-
export class ContainerService extends Service<ContainerModule> { }
212-
213215
export class ContainerModule<
214216
M extends ContainerModuleSpec = ContainerModuleSpec,
215217
S extends ContainerServiceSpec = ContainerServiceSpec,
216-
T extends GenericTestSpec = GenericTestSpec,
218+
T extends ContainerTestSpec = ContainerTestSpec,
217219
> extends Module<M, S, T> { }
218220

219221
export async function getImage(module: ContainerModule) {
@@ -327,7 +329,6 @@ export async function parseContainerModule({ moduleConfig }: ParseModuleParams<C
327329
dependencies: t.dependencies,
328330
spec: t,
329331
timeout: t.timeout,
330-
variables: <PrimitiveMap>t.variables,
331332
}))
332333

333334
// make sure we can build the thing

src/plugins/generic.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ export const name = "generic"
4747

4848
export interface GenericTestSpec extends BaseTestSpec {
4949
command: string[],
50+
env: PrimitiveMap,
5051
}
5152

5253
export const genericTestSchema = baseTestSpecSchema
5354
.keys({
5455
command: Joi.array().items(Joi.string())
5556
.description("The command to run in the module build context in order to test it."),
57+
env: joiEnvVars(),
5658
})
5759
.description("The test specification of a generic module.")
5860

@@ -85,7 +87,6 @@ export async function parseGenericModule(
8587
dependencies: t.dependencies,
8688
spec: t,
8789
timeout: t.timeout,
88-
variables: t.variables,
8990
})),
9091
}
9192
}
@@ -120,7 +121,7 @@ export async function testGenericModule({ module, testConfig }: TestModuleParams
120121
command.slice(1),
121122
{
122123
cwd: module.path,
123-
env: { ...process.env, ...module.spec.env },
124+
env: { ...process.env, ...module.spec.env, ...testConfig.spec.env },
124125
ignoreError: true,
125126
},
126127
)

src/plugins/google/google-app-engine.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const gardenPlugin = (): GardenPlugin => ({
6767
const appYaml: any = {
6868
runtime: "custom",
6969
env: "flex",
70-
env_variables: runtimeContext.envVars,
70+
env_variables: { ...runtimeContext.envVars, ...service.spec.env },
7171
}
7272

7373
if (config.healthCheck) {

src/plugins/google/google-cloud-functions.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ export async function parseGcfModule(
9393
tests: moduleConfig.spec.tests.map(t => ({
9494
name: t.name,
9595
dependencies: t.dependencies,
96-
variables: t.variables,
9796
timeout: t.timeout,
9897
spec: t,
9998
})),

src/plugins/kubernetes/actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ export async function testModule(
288288
): Promise<TestResult> {
289289
const testName = testConfig.name
290290
const command = testConfig.spec.command
291-
runtimeContext.envVars = { ...runtimeContext.envVars, ...testConfig.variables }
291+
runtimeContext.envVars = { ...runtimeContext.envVars, ...testConfig.spec.env }
292292
const timeout = testConfig.timeout || DEFAULT_TEST_TIMEOUT
293293

294294
const result = await runModule({ ctx, provider, env, module, command, interactive, runtimeContext, silent, timeout })

src/plugins/kubernetes/deployment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export async function createDeployment(service: ContainerService, runtimeContext
117117
},
118118
}
119119

120-
const envVars = extend({}, runtimeContext.envVars)
120+
const envVars = { ...runtimeContext.envVars, ...service.spec.env }
121121

122122
const labels = {
123123
// tier: service.tier,

src/plugins/local/local-docker-swarm.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export const gardenPlugin = (): GardenPlugin => ({
6464
}
6565
})
6666

67-
const envVars = map(runtimeContext.envVars, (v, k) => `${k}=${v}`)
67+
const envVars = map({ ...runtimeContext.envVars, ...service.spec.env }, (v, k) => `${k}=${v}`)
6868

6969
const volumeMounts = service.spec.volumes.map(v => {
7070
// TODO-LOW: Support named volumes

src/plugins/local/local-google-cloud-functions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const gardenPlugin = (): GardenPlugin => ({
5757
endpoints: [{
5858
port: "http",
5959
}],
60+
env: {},
6061
healthCheck: { tcpPort: "http" },
6162
ports: [
6263
{

src/types/common.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const joiPrimitive = () => Joi.alternatives().try(Joi.number(), Joi.strin
3030
.description("Number, string or boolean")
3131

3232
export const identifierRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/
33-
export const envVarRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/
33+
export const envVarRegex = /^(?!GARDEN)[A-Z_][A-Z0-9_]*$/
3434

3535
export const joiIdentifier = () => Joi
3636
.string().regex(identifierRegex)
@@ -47,18 +47,24 @@ export const joiIdentifierMap = (valueSchema: JoiObject) => Joi
4747
export const joiVariables = () => Joi
4848
.object().pattern(/[\w\d]+/i, joiPrimitive())
4949
.default(() => ({}), "{}")
50+
.unknown(false)
5051
.description("Key/value map, keys may contain letters and numbers, and values must be primitives.")
5152

5253
export const joiEnvVarName = () => Joi
5354
.string().regex(envVarRegex)
5455
.description(
55-
"Valid POSIX environment variable name (may contain letters, numbers and underscores and must start with a letter.",
56+
"Valid POSIX environment variable name (may contain letters, numbers and underscores and must start with a " +
57+
"letter). Must be uppercase, and must not start with `GARDEN`.",
5658
)
5759

5860
export const joiEnvVars = () => Joi
5961
.object().pattern(envVarRegex, joiPrimitive())
6062
.default(() => ({}), "{}")
61-
.description("Key/value map, keys must be valid POSIX environment variable names, and values must be primitives.")
63+
.unknown(false)
64+
.description(
65+
"Key/value map of environment variables. Keys must be valid POSIX environment variable names " +
66+
"(must be uppercase, may not start with `GARDEN`) and values must be primitives.",
67+
)
6268

6369
export const joiArray = (schema) => Joi
6470
.array().items(schema)

0 commit comments

Comments
 (0)