From f0a7677a3b7af84c158a1dd9d2ed8cdf8dfb2b5b Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Wed, 24 Jun 2020 14:26:00 +0200 Subject: [PATCH] improvement(core): always require a namespace and simply env config We now always require a namespace for all environments, and make the default simply "default". You can override the default namespace with `environments[].defaultNamespace` as before. This reduces code branching significantly, especially in the enterprise UI, and simplifies our configuration as well. BREAKING CHANGE: The default namespace in the `kubernetes` provider is now `.` (previously it was just the project name). Users need to override this to `"${project.name}"` if they would like to revert to the previous default. --- docs/reference/config.md | 58 +++--------- docs/reference/providers/kubernetes.md | 22 +---- docs/reference/providers/local-kubernetes.md | 13 --- garden-service/src/cli/cli.ts | 4 +- garden-service/src/config/project.ts | 49 +++------- garden-service/src/docs/generate.ts | 2 + garden-service/src/garden.ts | 6 +- .../src/plugins/conftest/conftest.ts | 3 +- .../src/plugins/container/config.ts | 2 +- .../src/plugins/container/helpers.ts | 10 +- .../src/plugins/kubernetes/config.ts | 6 +- .../src/plugins/kubernetes/system.ts | 3 +- .../plugins/conftest/conftest-container.ts | 4 +- .../integ/src/plugins/conftest/conftest.ts | 4 +- .../integ/src/plugins/hadolint/hadolint.ts | 4 +- .../volume/persistentvolumeclaim.ts | 4 +- garden-service/test/unit/src/actions.ts | 20 ++-- .../test/unit/src/commands/get/get-outputs.ts | 4 +- .../test/unit/src/commands/get/get-status.ts | 4 +- .../test/unit/src/commands/run/workflow.ts | 6 +- .../test/unit/src/commands/tools.ts | 3 +- garden-service/test/unit/src/commands/util.ts | 5 +- .../test/unit/src/config/project.ts | 92 +++++++++---------- .../test/unit/src/config/workflow.ts | 35 ++----- garden-service/test/unit/src/garden.ts | 78 ++++++---------- garden-service/test/unit/src/outputs.ts | 4 +- garden-service/test/unit/src/tasks/deploy.ts | 4 +- .../test/unit/src/tasks/get-service-status.ts | 4 +- .../test/unit/src/tasks/resolve-provider.ts | 3 +- garden-service/test/unit/src/tasks/task.ts | 4 +- 30 files changed, 168 insertions(+), 292 deletions(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index 426961138f0..22fbfb21bc2 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -37,27 +37,13 @@ environments: - # The name of the environment. name: - # Control if and how this environment should support namespaces. If set to "optional" (the default), users can - # set a namespace for the environment. This is useful for any shared environments, e.g. testing and development - # environments, where namespaces separate different users or code versions within an environment. Users then - # specify an environment with `--env .`, e.g. `--env alice.dev` or - # `--env my-branch.testing`. + # Set the default namespace to use. This can be templated to be user-specific, or to use an environment variable + # (e.g. in CI). # - # If set to "required", this namespace separation is enforced, and an error is thrown if a namespace is not - # specified with the `--env` parameter. - # - # If set to "disabled", an error is thrown if a namespace is specified. This makes sense for e.g. production or - # staging environments, where you don't want to split the environment between users or code versions. - # - # When specified, namespaces must be a valid DNS-style label, much like other identifiers. - namespacing: optional - - # Set a default namespace to use, when `namespacing` is `required` or `optional`. This can be templated to be - # user-specific, or to use an environment variable (e.g. in CI). - # - # If this is set, users can specify `--env ` and skip the namespace part, even when `namespacing` is - # `required` for the environment. - defaultNamespace: + # You can also set this to `null`, in order to require an explicit namespace to be set on usage. This may be + # advisable for shared environments, but you may also be able to achieve the desired result by templating this + # field, as mentioned above. + defaultNamespace: default # Flag the environment as a production environment. # @@ -232,39 +218,17 @@ environments: - name: "dev" ``` -### `environments[].namespacing` - -[environments](#environments) > namespacing - -Control if and how this environment should support namespaces. If set to "optional" (the default), users can -set a namespace for the environment. This is useful for any shared environments, e.g. testing and development -environments, where namespaces separate different users or code versions within an environment. Users then -specify an environment with `--env .`, e.g. `--env alice.dev` or -`--env my-branch.testing`. - -If set to "required", this namespace separation is enforced, and an error is thrown if a namespace is not -specified with the `--env` parameter. - -If set to "disabled", an error is thrown if a namespace is specified. This makes sense for e.g. production or -staging environments, where you don't want to split the environment between users or code versions. - -When specified, namespaces must be a valid DNS-style label, much like other identifiers. - -| Type | Default | Required | -| -------- | ------------ | -------- | -| `string` | `"optional"` | No | - ### `environments[].defaultNamespace` [environments](#environments) > defaultNamespace -Set a default namespace to use, when `namespacing` is `required` or `optional`. This can be templated to be user-specific, or to use an environment variable (e.g. in CI). +Set the default namespace to use. This can be templated to be user-specific, or to use an environment variable (e.g. in CI). -If this is set, users can specify `--env ` and skip the namespace part, even when `namespacing` is `required` for the environment. +You can also set this to `null`, in order to require an explicit namespace to be set on usage. This may be advisable for shared environments, but you may also be able to achieve the desired result by templating this field, as mentioned above. -| Type | Required | -| -------- | -------- | -| `string` | No | +| Type | Default | Required | +| -------- | ----------- | -------- | +| `string` | `"default"` | No | Example: diff --git a/docs/reference/providers/kubernetes.md b/docs/reference/providers/kubernetes.md index 57ee012920b..f43a859ddfe 100644 --- a/docs/reference/providers/kubernetes.md +++ b/docs/reference/providers/kubernetes.md @@ -62,9 +62,6 @@ providers: # A default hostname to use when no hostname is explicitly configured for a service. defaultHostname: - # Set a default username (used for namespacing within a cluster). - defaultUsername: - # Defines the strategy for deploying the project services. # Default is "rolling update" and there is experimental support for "blue/green" deployment. # The feature only supports modules of type `container`: other types will just deploy using the default strategy. @@ -314,10 +311,9 @@ providers: # Path to kubeconfig file to use instead of the system default. Must be a POSIX-style path. kubeconfig: - # Specify which namespace to deploy services to. Defaults to the environment namespace, if specified and enabled, - # otherwise the project name. + # Specify which namespace to deploy services to. Defaults to `-`. # - # Note that the framework generates other namespaces as well with this name as a prefix. + # Note that the framework may generate other namespaces as well with this name as a prefix. namespace: # Set this to `nginx` to install/enable the NGINX ingress controller. @@ -431,16 +427,6 @@ providers: - defaultHostname: "api.mydomain.com" ``` -### `providers[].defaultUsername` - -[providers](#providers) > defaultUsername - -Set a default username (used for namespacing within a cluster). - -| Type | Required | -| -------- | -------- | -| `string` | No | - ### `providers[].deploymentStrategy` [providers](#providers) > deploymentStrategy @@ -1467,9 +1453,9 @@ Path to kubeconfig file to use instead of the system default. Must be a POSIX-st [providers](#providers) > namespace -Specify which namespace to deploy services to. Defaults to the environment namespace, if specified and enabled, otherwise the project name. +Specify which namespace to deploy services to. Defaults to `-`. -Note that the framework generates other namespaces as well with this name as a prefix. +Note that the framework may generate other namespaces as well with this name as a prefix. | Type | Required | | -------- | -------- | diff --git a/docs/reference/providers/local-kubernetes.md b/docs/reference/providers/local-kubernetes.md index 68070d56c95..b1c4131c8b4 100644 --- a/docs/reference/providers/local-kubernetes.md +++ b/docs/reference/providers/local-kubernetes.md @@ -58,9 +58,6 @@ providers: # A default hostname to use when no hostname is explicitly configured for a service. defaultHostname: - # Set a default username (used for namespacing within a cluster). - defaultUsername: - # Defines the strategy for deploying the project services. # Default is "rolling update" and there is experimental support for "blue/green" deployment. # The feature only supports modules of type `container`: other types will just deploy using the default strategy. @@ -397,16 +394,6 @@ providers: - defaultHostname: "api.mydomain.com" ``` -### `providers[].defaultUsername` - -[providers](#providers) > defaultUsername - -Set a default username (used for namespacing within a cluster). - -| Type | Required | -| -------- | -------- | -| `string` | No | - ### `providers[].deploymentStrategy` [providers](#providers) > deploymentStrategy diff --git a/garden-service/src/cli/cli.ts b/garden-service/src/cli/cli.ts index f6ae3cb095c..4caa8a42479 100644 --- a/garden-service/src/cli/cli.ts +++ b/garden-service/src/cli/cli.ts @@ -47,7 +47,7 @@ import { checkForUpdates, checkForStaticDir, } from "./helpers" -import { defaultEnvironments, ProjectConfig } from "../config/project" +import { defaultEnvironments, ProjectConfig, defaultNamespace } from "../config/project" import { ERROR_LOG_FILENAME, DEFAULT_API_VERSION, DEFAULT_GARDEN_DIR_NAME, LOGS_DIR_NAME } from "../constants" import stringify = require("json-stringify-safe") import { generateBasicDebugInfoReport } from "../commands/get/get-debug-info" @@ -70,7 +70,7 @@ const GLOBAL_OPTIONS_GROUP_NAME = "Global options" export async function makeDummyGarden(root: string, gardenOpts: GardenOpts = {}) { const environments = gardenOpts.environmentName - ? [{ name: gardenOpts.environmentName, variables: {} }] + ? [{ name: gardenOpts.environmentName, defaultNamespace, variables: {} }] : defaultEnvironments const config: ProjectConfig = { diff --git a/garden-service/src/config/project.ts b/garden-service/src/config/project.ts index e8809ee5ea1..40fa183f336 100644 --- a/garden-service/src/config/project.ts +++ b/garden-service/src/config/project.ts @@ -34,11 +34,13 @@ import { DEFAULT_API_VERSION, DOCS_BASE_URL } from "../constants" import { defaultDotIgnoreFiles } from "../util/fs" import { pathExists, readFile } from "fs-extra" import { resolve } from "path" +import chalk = require("chalk") export const defaultVarfilePath = "garden.env" export const defaultEnvVarfilePath = (environmentName: string) => `garden.${environmentName}.env` // These plugins are always loaded +export const defaultNamespace = "default" export const fixedPlugins = ["exec", "container"] export type EnvironmentNamespacing = "disabled" | "optional" | "required" @@ -48,12 +50,9 @@ export interface ParsedEnvironment { namespace?: string } -const defaultEnvironmentNamespacing: EnvironmentNamespacing = "optional" - export interface EnvironmentConfig { name: string - namespacing?: EnvironmentNamespacing - defaultNamespace?: string + defaultNamespace: string | null providers?: ProviderConfig[] // further validated by each plugin varfile?: string variables: DeepPrimitiveMap @@ -69,30 +68,14 @@ export const environmentNameSchema = () => export const environmentSchema = () => joi.object().keys({ name: environmentNameSchema(), - namespacing: joi - .string() - .allow("disabled", "optional", "required") - .default("optional").description(dedent` - Control if and how this environment should support namespaces. If set to "optional" (the default), users can - set a namespace for the environment. This is useful for any shared environments, e.g. testing and development - environments, where namespaces separate different users or code versions within an environment. Users then - specify an environment with \`--env .\`, e.g. \`--env alice.dev\` or - \`--env my-branch.testing\`. - - If set to "required", this namespace separation is enforced, and an error is thrown if a namespace is not - specified with the \`--env\` parameter. - - If set to "disabled", an error is thrown if a namespace is specified. This makes sense for e.g. production or - staging environments, where you don't want to split the environment between users or code versions. - - When specified, namespaces must be a valid DNS-style label, much like other identifiers. - `), defaultNamespace: joiIdentifier() + .allow(null) + .default(defaultNamespace) .description( dedent` - Set a default namespace to use, when \`namespacing\` is \`required\` or \`optional\`. This can be templated to be user-specific, or to use an environment variable (e.g. in CI). + Set the default namespace to use. This can be templated to be user-specific, or to use an environment variable (e.g. in CI). - If this is set, users can specify \`--env \` and skip the namespace part, even when \`namespacing\` is \`required\` for the environment. + You can also set this to \`null\`, in order to require an explicit namespace to be set on usage. This may be advisable for shared environments, but you may also be able to achieve the desired result by templating this field, as mentioned above. ` ) .example("user-${local.username}"), @@ -224,7 +207,7 @@ export interface ProjectResource extends ProjectConfig { export const defaultEnvironments: EnvironmentConfig[] = [ { name: "local", - namespacing: defaultEnvironmentNamespacing, + defaultNamespace, providers: [ { name: "local-kubernetes", @@ -572,23 +555,19 @@ export async function pickEnvironment(config: ProjectConfig, envString: string) * Validates that the value passed for `namespace` conforms with the namespacing setting in `environmentConfig`, * and returns `namespace` (or a default namespace, if appropriate). */ -export function getNamespace(environmentConfig: EnvironmentConfig, namespace: string | undefined): string | undefined { +export function getNamespace(environmentConfig: EnvironmentConfig, namespace: string | undefined): string { const envName = environmentConfig.name - if (namespace && environmentConfig.namespacing === "disabled") { - throw new ParameterError( - `Environment ${envName} does not allow namespacing, but namespace '${namespace}' was specified.`, - { environmentConfig, namespace } - ) - } - if (!namespace && environmentConfig.defaultNamespace) { namespace = environmentConfig.defaultNamespace } - if (!namespace && environmentConfig.namespacing === "required") { + if (!namespace) { + const envHighlight = chalk.white.bold(envName) + const exampleFlag = chalk.white(`--env=${chalk.bold("some-namespace.")}${envName}`) + throw new ParameterError( - `Environment ${envName} requires a namespace, but none was specified and no defaultNamespace is configured.`, + `Environment ${envHighlight} has defaultNamespace set to null, and no explicit namespace was specified. Please either set a defaultNamespace or explicitly set a namespace at runtime (e.g. ${exampleFlag}).`, { environmentConfig, } diff --git a/garden-service/src/docs/generate.ts b/garden-service/src/docs/generate.ts index 473c4ea92be..eb60e43d7f1 100644 --- a/garden-service/src/docs/generate.ts +++ b/garden-service/src/docs/generate.ts @@ -17,6 +17,7 @@ import { keyBy } from "lodash" import { writeFileSync } from "fs-extra" import { renderModuleTypeReference, moduleTypes } from "./module-type" import { renderProviderReference } from "./provider" +import { defaultNamespace } from "../config/project" export async function generateDocs(targetDir: string) { // tslint:disable: no-console @@ -49,6 +50,7 @@ export async function writeConfigReferenceDocs(docsRoot: string) { environments: [ { name: "default", + defaultNamespace, variables: {}, }, ], diff --git a/garden-service/src/garden.ts b/garden-service/src/garden.ts index 3314dba1b3d..438c3382cd6 100644 --- a/garden-service/src/garden.ts +++ b/garden-service/src/garden.ts @@ -122,7 +122,7 @@ export interface GardenParams { dotIgnoreFiles: string[] environmentName: string environmentConfigs: EnvironmentConfig[] - namespace?: string + namespace: string gardenDirPath: string log: LogEntry moduleIncludePatterns?: string[] @@ -178,7 +178,7 @@ export class Garden { public readonly projectName: string public readonly environmentName: string public readonly environmentConfigs: EnvironmentConfig[] - public readonly namespace?: string + public readonly namespace: string public readonly variables: DeepPrimitiveMap public readonly secrets: StringMap public readonly projectSources: SourceConfig[] @@ -1200,7 +1200,7 @@ export class DummyGarden extends Garden { export interface ConfigDump { environmentName: string // TODO: Remove this? allEnvironmentNames: string[] - namespace?: string + namespace: string providers: (Omit | ProviderConfig)[] variables: DeepPrimitiveMap moduleConfigs: ModuleConfig[] diff --git a/garden-service/src/plugins/conftest/conftest.ts b/garden-service/src/plugins/conftest/conftest.ts index 1d6dfed3e0b..da24312c698 100644 --- a/garden-service/src/plugins/conftest/conftest.ts +++ b/garden-service/src/plugins/conftest/conftest.ts @@ -293,7 +293,8 @@ export const gardenPlugin = createGardenPlugin({ { platform: "windows", architecture: "amd64", - url: "https://github.com/open-policy-agent/conftest/releases/download/v0.17.1/conftest_0.17.1_Windows_x86_64.zip", + url: + "https://github.com/open-policy-agent/conftest/releases/download/v0.17.1/conftest_0.17.1_Windows_x86_64.zip", sha256: "4c2df80420f2f148ec085bb75a8c5b92e1c665c6a041768a79924c81082527c3", extract: { format: "zip", diff --git a/garden-service/src/plugins/container/config.ts b/garden-service/src/plugins/container/config.ts index 497aed6a0d1..c24705c6698 100644 --- a/garden-service/src/plugins/container/config.ts +++ b/garden-service/src/plugins/container/config.ts @@ -557,7 +557,7 @@ export interface ContainerModuleSpec extends ModuleSpec { export interface ContainerModuleConfig extends ModuleConfig {} -export const defaultNamespace = "_" +export const defaultImageNamespace = "_" export const defaultTag = "latest" export const containerModuleSpecSchema = () => diff --git a/garden-service/src/plugins/container/helpers.ts b/garden-service/src/plugins/container/helpers.ts index 4ffb1eebeba..ec171dafb08 100644 --- a/garden-service/src/plugins/container/helpers.ts +++ b/garden-service/src/plugins/container/helpers.ts @@ -14,7 +14,13 @@ import isGlob from "is-glob" import { ConfigurationError, RuntimeError } from "../../exceptions" import { splitFirst, spawn, splitLast, SpawnOutput } from "../../util/util" import { ModuleConfig } from "../../config/module" -import { ContainerModule, ContainerRegistryConfig, defaultTag, defaultNamespace, ContainerModuleConfig } from "./config" +import { + ContainerModule, + ContainerRegistryConfig, + defaultTag, + defaultImageNamespace, + ContainerModuleConfig, +} from "./config" import { Writable } from "stream" import Bluebird from "bluebird" import { flatten, uniq, fromPairs } from "lodash" @@ -200,7 +206,7 @@ const helpers = { const name = parsed.tag ? `${parsed.repository}:${parsed.tag}` : parsed.repository if (parsed.host) { - return `${parsed.host}/${parsed.namespace || defaultNamespace}/${name}` + return `${parsed.host}/${parsed.namespace || defaultImageNamespace}/${name}` } else if (parsed.namespace) { return `${parsed.namespace}/${name}` } else { diff --git a/garden-service/src/plugins/kubernetes/config.ts b/garden-service/src/plugins/kubernetes/config.ts index 6b542a38a06..994d3f69afa 100644 --- a/garden-service/src/plugins/kubernetes/config.ts +++ b/garden-service/src/plugins/kubernetes/config.ts @@ -97,7 +97,6 @@ export interface KubernetesConfig extends ProviderConfig { } context: string defaultHostname?: string - defaultUsername?: string deploymentRegistry?: ContainerRegistryConfig deploymentStrategy?: DeploymentStrategy forceSsl: boolean @@ -349,7 +348,6 @@ export const kubernetesConfigBase = providerConfigBaseSchema().keys({ .string() .description("A default hostname to use when no hostname is explicitly configured for a service.") .example("api.mydomain.com"), - defaultUsername: joiIdentifier().description("Set a default username (used for namespacing within a cluster)."), deploymentStrategy: joi .string() .default("rolling") @@ -571,9 +569,9 @@ export const configSchema = kubernetesConfigBase .posixPath() .description("Path to kubeconfig file to use instead of the system default. Must be a POSIX-style path."), namespace: joi.string().description(dedent` - Specify which namespace to deploy services to. Defaults to the environment namespace, if specified and enabled, otherwise the project name. + Specify which namespace to deploy services to. Defaults to \`-\`. - Note that the framework generates other namespaces as well with this name as a prefix. + Note that the framework may generate other namespaces as well with this name as a prefix. `), setupIngressController: joi .string() diff --git a/garden-service/src/plugins/kubernetes/system.ts b/garden-service/src/plugins/kubernetes/system.ts index 875871dd245..68d1a085db0 100644 --- a/garden-service/src/plugins/kubernetes/system.ts +++ b/garden-service/src/plugins/kubernetes/system.ts @@ -27,6 +27,7 @@ import { KubernetesResource } from "./types" import { defaultDotIgnoreFiles } from "../../util/fs" import { LogLevel } from "../../logger/log-node" import { ConftestProviderConfig } from "../conftest/conftest" +import { defaultNamespace } from "../../config/project" const GARDEN_VERSION = getPackageVersion() const SYSTEM_NAMESPACE_MIN_VERSION = "0.9.0" @@ -79,7 +80,7 @@ export async function getSystemGarden( name: systemNamespace, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [sysProvider, conftest], variables, }, diff --git a/garden-service/test/integ/src/plugins/conftest/conftest-container.ts b/garden-service/test/integ/src/plugins/conftest/conftest-container.ts index 4ca087ccc0c..aa2a764010d 100644 --- a/garden-service/test/integ/src/plugins/conftest/conftest-container.ts +++ b/garden-service/test/integ/src/plugins/conftest/conftest-container.ts @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ProjectConfig } from "../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../../src/constants" import { Garden } from "../../../../../src/garden" import { getDataDir } from "../../../../helpers" @@ -22,7 +22,7 @@ describe("conftest-container provider", () => { path: projectRoot, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "conftest-container", policyPath: "dockerfile.rego" }], variables: {}, } diff --git a/garden-service/test/integ/src/plugins/conftest/conftest.ts b/garden-service/test/integ/src/plugins/conftest/conftest.ts index 529eb4e944f..f3638a0069a 100644 --- a/garden-service/test/integ/src/plugins/conftest/conftest.ts +++ b/garden-service/test/integ/src/plugins/conftest/conftest.ts @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ProjectConfig } from "../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../../src/constants" import { Garden } from "../../../../../src/garden" import { getDataDir } from "../../../../helpers" @@ -24,7 +24,7 @@ describe("conftest provider", () => { path: projectRoot, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "conftest", policyPath: "policy.rego" }], variables: {}, } diff --git a/garden-service/test/integ/src/plugins/hadolint/hadolint.ts b/garden-service/test/integ/src/plugins/hadolint/hadolint.ts index e66d7ed1387..eac3ed2e77f 100644 --- a/garden-service/test/integ/src/plugins/hadolint/hadolint.ts +++ b/garden-service/test/integ/src/plugins/hadolint/hadolint.ts @@ -7,7 +7,7 @@ */ import tmp from "tmp-promise" -import { ProjectConfig } from "../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../src/config/project" import execa = require("execa") import { DEFAULT_API_VERSION } from "../../../../../src/constants" import { Garden } from "../../../../../src/garden" @@ -39,7 +39,7 @@ describe("hadolint provider", () => { path: tmpPath, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "hadolint" }], variables: {}, } diff --git a/garden-service/test/integ/src/plugins/kubernetes/volume/persistentvolumeclaim.ts b/garden-service/test/integ/src/plugins/kubernetes/volume/persistentvolumeclaim.ts index dd8c7f4fbe5..072417d4831 100644 --- a/garden-service/test/integ/src/plugins/kubernetes/volume/persistentvolumeclaim.ts +++ b/garden-service/test/integ/src/plugins/kubernetes/volume/persistentvolumeclaim.ts @@ -7,7 +7,7 @@ */ import tmp from "tmp-promise" -import { ProjectConfig } from "../../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../../src/config/project" import execa = require("execa") import { DEFAULT_API_VERSION } from "../../../../../../src/constants" import { expect } from "chai" @@ -32,7 +32,7 @@ describe("persistentvolumeclaim", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "local-kubernetes", namespace: "default" }], variables: {}, } diff --git a/garden-service/test/unit/src/actions.ts b/garden-service/test/unit/src/actions.ts index f9b2b8a80d7..e8da1b3ff02 100644 --- a/garden-service/test/unit/src/actions.ts +++ b/garden-service/test/unit/src/actions.ts @@ -29,7 +29,7 @@ import { expect } from "chai" import { omit } from "lodash" import { joi } from "../../../src/config/common" import { validateSchema } from "../../../src/config/validation" -import { ProjectConfig } from "../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../src/constants" import { defaultProvider } from "../../../src/config/provider" import { RunTaskResult } from "../../../src/types/plugin/task/runTask" @@ -56,7 +56,7 @@ describe("ActionRouter", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "base" }, { name: "test-plugin" }, { name: "test-plugin-b" }], variables: {}, } @@ -790,7 +790,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "foo" }], variables: {}, }, @@ -843,7 +843,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "base" }, { name: "foo" }], variables: {}, }, @@ -908,7 +908,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [ { name: "base" }, // The order here matters, to verify that the dependency ordering works @@ -977,7 +977,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [ { name: "base" }, // The order here matters, since we use that as a "tie-breaker" @@ -1034,7 +1034,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "base" }, { name: "foo" }], variables: {}, }, @@ -1058,7 +1058,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "base" }, { name: "foo" }], variables: {}, } @@ -1200,7 +1200,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "base-a" }, { name: "base-b" }, { name: "foo" }], variables: {}, }, @@ -1292,7 +1292,7 @@ describe("ActionRouter", () => { path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "foo" }], variables: {}, }, diff --git a/garden-service/test/unit/src/commands/get/get-outputs.ts b/garden-service/test/unit/src/commands/get/get-outputs.ts index a4bb7f048a8..dff57c73dda 100644 --- a/garden-service/test/unit/src/commands/get/get-outputs.ts +++ b/garden-service/test/unit/src/commands/get/get-outputs.ts @@ -10,7 +10,7 @@ import { expect } from "chai" import tmp from "tmp-promise" import { withDefaultGlobalOpts, TestGarden } from "../../../../helpers" import { GetOutputsCommand } from "../../../../../src/commands/get/get-outputs" -import { ProjectConfig } from "../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../../src/constants" import { createGardenPlugin } from "../../../../../src/types/plugin/plugin" import { exec } from "../../../../../src/util/util" @@ -31,7 +31,7 @@ describe("GetOutputsCommand", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } diff --git a/garden-service/test/unit/src/commands/get/get-status.ts b/garden-service/test/unit/src/commands/get/get-status.ts index fbaf2f05d50..ffe3a549554 100644 --- a/garden-service/test/unit/src/commands/get/get-status.ts +++ b/garden-service/test/unit/src/commands/get/get-status.ts @@ -9,7 +9,7 @@ import tmp from "tmp-promise" import execa from "execa" -import { ProjectConfig } from "../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../../src/constants" import { createGardenPlugin } from "../../../../../src/types/plugin/plugin" import { joi } from "../../../../../src/config/common" @@ -37,7 +37,7 @@ describe("GetStatusCommand", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } diff --git a/garden-service/test/unit/src/commands/run/workflow.ts b/garden-service/test/unit/src/commands/run/workflow.ts index 5971d304db9..36f375f8670 100644 --- a/garden-service/test/unit/src/commands/run/workflow.ts +++ b/garden-service/test/unit/src/commands/run/workflow.ts @@ -15,7 +15,7 @@ import { RunWorkflowCommand } from "../../../../../src/commands/run/workflow" import { createGardenPlugin } from "../../../../../src/types/plugin/plugin" import { joi } from "../../../../../src/config/common" import { RunTaskParams } from "../../../../../src/types/plugin/task/runTask" -import { ProjectConfig } from "../../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../../src/config/project" import { join } from "path" import { remove, readFile, pathExists } from "fs-extra" import { defaultDotIgnoreFiles } from "../../../../../src/util/fs" @@ -249,7 +249,7 @@ describe("RunWorkflowCommand", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } @@ -338,7 +338,7 @@ describe("RunWorkflowCommand", () => { path: garden.projectRoot, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } diff --git a/garden-service/test/unit/src/commands/tools.ts b/garden-service/test/unit/src/commands/tools.ts index 769a2e61feb..de5c0e5d58f 100644 --- a/garden-service/test/unit/src/commands/tools.ts +++ b/garden-service/test/unit/src/commands/tools.ts @@ -26,6 +26,7 @@ import { LogLevel } from "../../../../src/logger/log-node" import { dedent } from "../../../../src/util/string" import { LogEntry } from "../../../../src/logger/log-entry" import { makeDummyGarden } from "../../../../src/cli/cli" +import { defaultNamespace } from "../../../../src/config/project" describe("ToolsCommand", () => { let tmpDir: TempDirectory @@ -100,7 +101,7 @@ describe("ToolsCommand", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a" }], variables: {}, }, diff --git a/garden-service/test/unit/src/commands/util.ts b/garden-service/test/unit/src/commands/util.ts index 3a60ab3305b..5bdb14f20f7 100644 --- a/garden-service/test/unit/src/commands/util.ts +++ b/garden-service/test/unit/src/commands/util.ts @@ -14,6 +14,7 @@ import { DEFAULT_API_VERSION, GARDEN_GLOBAL_PATH } from "../../../../src/constan import { createGardenPlugin } from "../../../../src/types/plugin/plugin" import { pick } from "lodash" import { join } from "path" +import { defaultNamespace } from "../../../../src/config/project" describe("FetchToolsCommand", () => { let tmpDir: TempDirectory @@ -55,7 +56,7 @@ describe("FetchToolsCommand", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, }, @@ -98,7 +99,7 @@ describe("FetchToolsCommand", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, }, diff --git a/garden-service/test/unit/src/config/project.ts b/garden-service/test/unit/src/config/project.ts index 7f0a527ecad..0871308c693 100644 --- a/garden-service/test/unit/src/config/project.ts +++ b/garden-service/test/unit/src/config/project.ts @@ -17,6 +17,7 @@ import { defaultVarfilePath, defaultEnvVarfilePath, parseEnvironment, + defaultNamespace, } from "../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../src/constants" import { expectError } from "../../../helpers" @@ -24,6 +25,7 @@ import { defaultDotIgnoreFiles } from "../../../../src/util/fs" import { realpath, writeFile } from "fs-extra" import { dedent } from "../../../../src/util/string" import { resolve } from "path" +import stripAnsi from "strip-ansi" describe("resolveProjectConfig", () => { it("should pass through a canonical project config", async () => { @@ -34,7 +36,7 @@ describe("resolveProjectConfig", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], outputs: [], providers: [{ name: "some-provider" }], variables: {}, @@ -45,7 +47,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", - namespacing: "optional", + defaultNamespace, production: false, providers: [], variables: {}, @@ -91,6 +93,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", + defaultNamespace, variables: { envVar: "${local.env.TEST_ENV_VAR}", }, @@ -115,7 +118,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", - namespacing: "optional", + defaultNamespace, production: false, providers: [], variables: { @@ -150,6 +153,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", + defaultNamespace, variables: { envVar: "foo", }, @@ -177,7 +181,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", - namespacing: "optional", + defaultNamespace, production: false, providers: [], variables: { @@ -262,6 +266,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", + defaultNamespace, variables: { envVar: "foo", }, @@ -288,7 +293,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", - namespacing: "optional", + defaultNamespace, production: false, providers: [], variables: { @@ -325,6 +330,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", + defaultNamespace, providers: [ { name: "provider-b", @@ -351,7 +357,7 @@ describe("resolveProjectConfig", () => { environments: [ { name: "default", - namespacing: "optional", + defaultNamespace, providers: [], production: false, variables: { @@ -399,7 +405,7 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, } @@ -415,14 +421,14 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, } expect(await pickEnvironment(config, "default")).to.eql({ environmentName: "default", - namespace: undefined, + namespace: "default", providers: [{ name: "exec" }, { name: "container" }], production: false, variables: {}, @@ -437,7 +443,7 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [ { name: "container", newKey: "foo" }, { name: "my-provider", a: "a" }, @@ -449,7 +455,7 @@ describe("pickEnvironment", () => { expect(await pickEnvironment(config, "default")).to.eql({ environmentName: "default", - namespace: undefined, + namespace: "default", providers: [{ name: "exec" }, { name: "container", newKey: "foo" }, { name: "my-provider", a: "c", b: "b" }], production: false, variables: {}, @@ -464,7 +470,7 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [ { name: "container", newKey: "foo" }, { name: "my-provider", a: "a" }, @@ -476,7 +482,7 @@ describe("pickEnvironment", () => { expect(await pickEnvironment(config, "default")).to.eql({ environmentName: "default", - namespace: undefined, + namespace: "default", providers: [{ name: "exec" }, { name: "container", newKey: "foo" }, { name: "my-provider", b: "b" }], production: false, variables: {}, @@ -494,6 +500,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, variables: { b: "env value B", c: "env value C", @@ -552,6 +559,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, variables: { b: "B", c: "c", @@ -591,6 +599,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, variables: {}, }, ], @@ -630,6 +639,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, variables: { b: "B", c: "c", @@ -670,6 +680,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, varfile: "foo.env", variables: {}, }, @@ -719,6 +730,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, // Precedence 2/4 variables: { c: "C", @@ -756,6 +768,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, variables: {}, }, ], @@ -781,6 +794,7 @@ describe("pickEnvironment", () => { environments: [ { name: "default", + defaultNamespace, varfile: "foo.env", variables: {}, }, @@ -795,7 +809,7 @@ describe("pickEnvironment", () => { ) }) - it("should set environment namespace if specified", async () => { + it("should set environment namespace if specified and defaultNamespace=null", async () => { const config: ProjectConfig = { apiVersion: DEFAULT_API_VERSION, kind: "Project", @@ -803,7 +817,7 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, } @@ -817,7 +831,7 @@ describe("pickEnvironment", () => { }) }) - it("should set defaultNamespace if set and no explicit namespace is specified", async () => { + it("should use explicit namespace if specified and there is a default", async () => { const config: ProjectConfig = { apiVersion: DEFAULT_API_VERSION, kind: "Project", @@ -825,21 +839,21 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", defaultNamespace: "default-ns", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, } - expect(await pickEnvironment(config, "default")).to.eql({ + expect(await pickEnvironment(config, "foo.default")).to.eql({ environmentName: "default", - namespace: "default-ns", + namespace: "foo", providers: [{ name: "exec" }, { name: "container" }], production: false, variables: {}, }) }) - it("should use explicit namespace if specified, if defaultNamespace is set", async () => { + it("should use defaultNamespace if set and no explicit namespace is specified", async () => { const config: ProjectConfig = { apiVersion: DEFAULT_API_VERSION, kind: "Project", @@ -847,14 +861,14 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", defaultNamespace: "default-ns", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, } - expect(await pickEnvironment(config, "foo.default")).to.eql({ + expect(await pickEnvironment(config, "default")).to.eql({ environmentName: "default", - namespace: "foo", + namespace: "default", providers: [{ name: "exec" }, { name: "container" }], production: false, variables: {}, @@ -869,7 +883,7 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [], variables: {}, } @@ -883,7 +897,7 @@ describe("pickEnvironment", () => { ) }) - it("should throw if environment requires namespace but none is specified and no defaultNamespace set", async () => { + it("should throw if environment requires namespace but none is specified and defaultNamespace=null", async () => { const config: ProjectConfig = { apiVersion: DEFAULT_API_VERSION, kind: "Project", @@ -891,7 +905,7 @@ describe("pickEnvironment", () => { path: "/tmp/foo", defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", namespacing: "required", variables: {} }], + environments: [{ name: "default", defaultNamespace: null, variables: {} }], providers: [], variables: {}, } @@ -899,30 +913,8 @@ describe("pickEnvironment", () => { await expectError( () => pickEnvironment(config, "default"), (err) => - expect(err.message).to.equal( - "Environment default requires a namespace, but none was specified and no defaultNamespace is configured." - ) - ) - }) - - it("should throw if environment doesn't allow namespacing but one is specified", async () => { - const config: ProjectConfig = { - apiVersion: DEFAULT_API_VERSION, - kind: "Project", - name: "my-project", - path: "/tmp/foo", - defaultEnvironment: "default", - dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", namespacing: "disabled", variables: {} }], - providers: [], - variables: {}, - } - - await expectError( - () => pickEnvironment(config, "foo.default"), - (err) => - expect(err.message).to.equal( - "Environment default does not allow namespacing, but namespace 'foo' was specified." + expect(stripAnsi(err.message)).to.equal( + "Environment default has defaultNamespace set to null, and no explicit namespace was specified. Please either set a defaultNamespace or explicitly set a namespace at runtime (e.g. --env=some-namespace.default)." ) ) }) diff --git a/garden-service/test/unit/src/config/workflow.ts b/garden-service/test/unit/src/config/workflow.ts index a6228d6d661..0a35d809fca 100644 --- a/garden-service/test/unit/src/config/workflow.ts +++ b/garden-service/test/unit/src/config/workflow.ts @@ -16,7 +16,8 @@ import { TriggerSpec, } from "../../../../src/config/workflow" import { defaultContainerLimits } from "../../../../src/plugins/container/config" -import { EnvironmentConfig } from "../../../../src/config/project" +import { EnvironmentConfig, defaultNamespace } from "../../../../src/config/project" +import stripAnsi from "strip-ansi" describe("resolveWorkflowConfig", () => { let garden: TestGarden @@ -44,7 +45,7 @@ describe("resolveWorkflowConfig", () => { triggers: [ { environment: "local", - namespace: undefined, + namespace: "default", events: ["pull-request"], branches: ["feature*"], ignoreBranches: ["feature-ignored*"], @@ -169,7 +170,7 @@ describe("resolveWorkflowConfig", () => { const environmentConfigs: EnvironmentConfig[] = [ { name: "test", - namespacing: "optional", + defaultNamespace, variables: {}, }, ] @@ -182,7 +183,7 @@ describe("resolveWorkflowConfig", () => { const environmentConfigs: EnvironmentConfig[] = [ { name: "test", - namespacing: "required", + defaultNamespace: null, variables: {}, }, ] @@ -190,28 +191,8 @@ describe("resolveWorkflowConfig", () => { expectError( () => populateNamespaceForTriggers({ ...config, triggers: [trigger] }, environmentConfigs), (err) => - expect(err.message).to.match( - /Invalid namespace in trigger for workflow workflow-a: Environment test requires a namespace/ - ) - ) - }) - - it("should throw if a trigger's environment does not allow namespaces, but one is specified", () => { - const environmentConfigs: EnvironmentConfig[] = [ - { - name: "test", - namespacing: "disabled", - variables: {}, - }, - ] - - const invalidTrigger = { ...trigger, namespace: "foo" } - - expectError( - () => populateNamespaceForTriggers({ ...config, triggers: [invalidTrigger] }, environmentConfigs), - (err) => - expect(err.message).to.match( - /Invalid namespace in trigger for workflow workflow-a: Environment test does not allow namespacing/ + expect(stripAnsi(err.message)).to.equal( + `Invalid namespace in trigger for workflow workflow-a: Environment test has defaultNamespace set to null, and no explicit namespace was specified. Please either set a defaultNamespace or explicitly set a namespace at runtime (e.g. --env=some-namespace.test).` ) ) }) @@ -220,7 +201,6 @@ describe("resolveWorkflowConfig", () => { const environmentConfigs: EnvironmentConfig[] = [ { name: "test", - namespacing: "optional", defaultNamespace: "foo", variables: {}, }, @@ -235,7 +215,6 @@ describe("resolveWorkflowConfig", () => { const environmentConfigs: EnvironmentConfig[] = [ { name: "test", - namespacing: "optional", defaultNamespace: "foo", variables: {}, }, diff --git a/garden-service/test/unit/src/garden.ts b/garden-service/test/unit/src/garden.ts index 32071b56a83..972383282af 100644 --- a/garden-service/test/unit/src/garden.ts +++ b/garden-service/test/unit/src/garden.ts @@ -33,7 +33,7 @@ import { ModuleVersion } from "../../../src/vcs/vcs" import { getModuleCacheContext } from "../../../src/types/module" import { createGardenPlugin } from "../../../src/types/plugin/plugin" import { ConfigureProviderParams } from "../../../src/types/plugin/provider/configureProvider" -import { ProjectConfig } from "../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../src/config/project" import { ModuleConfig, baseModuleSpecSchema, baseBuildSpecSchema } from "../../../src/config/module" import { DEFAULT_API_VERSION } from "../../../src/constants" import { providerConfigBaseSchema } from "../../../src/config/provider" @@ -64,7 +64,7 @@ describe("Garden", () => { path: pathFoo, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "foo" }], variables: {}, } @@ -275,7 +275,7 @@ describe("Garden", () => { path: pathFoo, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", namespacing: "required", defaultNamespace: "foo", variables: {} }], + environments: [{ name: "default", defaultNamespace: "foo", variables: {} }], providers: [{ name: "foo" }], variables: {}, } @@ -286,28 +286,6 @@ describe("Garden", () => { expect(garden.namespace).to.equal("foo") }) - it("should throw if a namespace is specified and the specified environment disables namespacing", async () => { - const config: ProjectConfig = { - apiVersion: DEFAULT_API_VERSION, - kind: "Project", - name: "test", - path: pathFoo, - defaultEnvironment: "default", - dotIgnoreFiles: [], - environments: [{ name: "default", namespacing: "disabled", variables: {} }], - providers: [{ name: "foo" }], - variables: {}, - } - - await expectError( - () => TestGarden.factory(pathFoo, { config, environmentName: "foo.default" }), - (err) => - expect(err.message).to.equal( - "Environment default does not allow namespacing, but namespace 'foo' was specified." - ) - ) - }) - it("should throw if a namespace is not specified and the specified environment requires namespacing", async () => { const config: ProjectConfig = { apiVersion: DEFAULT_API_VERSION, @@ -316,7 +294,7 @@ describe("Garden", () => { path: pathFoo, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", namespacing: "required", variables: {} }], + environments: [{ name: "default", defaultNamespace: null, variables: {} }], providers: [{ name: "foo" }], variables: {}, } @@ -324,8 +302,8 @@ describe("Garden", () => { await expectError( () => TestGarden.factory(pathFoo, { config, environmentName: "default" }), (err) => - expect(err.message).to.equal( - "Environment default requires a namespace, but none was specified and no defaultNamespace is configured." + expect(stripAnsi(err.message)).to.equal( + `Environment default has defaultNamespace set to null, and no explicit namespace was specified. Please either set a defaultNamespace or explicitly set a namespace at runtime (e.g. --env=some-namespace.default).` ) ) }) @@ -1425,7 +1403,7 @@ describe("Garden", () => { path: process.cwd(), defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: "bar" }], variables: {}, } @@ -1470,7 +1448,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: "${bla.ble}" }], variables: {}, } @@ -1499,7 +1477,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: "${providers.foo.config.bla}" }], variables: {}, } @@ -1520,7 +1498,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: "${secrets.missing}" }], // < ------ variables: {}, } @@ -1572,7 +1550,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: "bar" }], variables: {}, } @@ -1601,7 +1579,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a" }, { name: "test-b" }], variables: {}, } @@ -1631,7 +1609,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a" }], variables: {}, } @@ -1660,7 +1638,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [ { name: "test-a", foo: "${providers.test-b.outputs.foo}" }, { name: "test-b", foo: "${providers.test-a.outputs.foo}" }, @@ -1697,7 +1675,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a", foo: "${providers.test-b.outputs.foo}" }, { name: "test-b" }], variables: {}, } @@ -1730,7 +1708,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } @@ -1757,7 +1735,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: 123 }], variables: {}, } @@ -1795,7 +1773,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } @@ -1837,7 +1815,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a" }, { name: "test-b", foo: "${providers.test-a.outputs.foo}" }], variables: {}, } @@ -1875,8 +1853,8 @@ describe("Garden", () => { defaultEnvironment: "dev", dotIgnoreFiles: defaultDotIgnoreFiles, environments: [ - { name: "dev", variables: {} }, - { name: "prod", variables: {} }, + { name: "dev", defaultNamespace, variables: {} }, + { name: "prod", defaultNamespace, variables: {} }, ], providers: [ { name: "test-a", environments: ["prod"] }, @@ -1905,7 +1883,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: { "my-variable": "bar" } }], + environments: [{ name: "default", defaultNamespace, variables: { "my-variable": "bar" } }], providers: [{ name: "test-a", foo: "${var.my-variable}" }], variables: {}, } @@ -1948,7 +1926,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a" }, { name: "test-b" }], variables: {}, } @@ -1998,7 +1976,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-a" }, { name: "test-b" }, { name: "test-c" }], variables: {}, } @@ -2034,7 +2012,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test", foo: 123 }], variables: {}, } @@ -2078,7 +2056,7 @@ describe("Garden", () => { path: projectRootA, defaultEnvironment: "default", dotIgnoreFiles: defaultDotIgnoreFiles, - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } @@ -2326,7 +2304,7 @@ describe("Garden", () => { path: pathFoo, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: { some: { nested: { key: "my value" } } } }], + environments: [{ name: "default", defaultNamespace, variables: { some: { nested: { key: "my value" } } } }], providers: [{ name: "test" }], variables: {}, }, @@ -2376,7 +2354,7 @@ describe("Garden", () => { path: pathFoo, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: { some: { nested: { key: "my value" } } } }], + environments: [{ name: "default", defaultNamespace, variables: { some: { nested: { key: "my value" } } } }], providers: [{ name: "test" }], variables: {}, }, diff --git a/garden-service/test/unit/src/outputs.ts b/garden-service/test/unit/src/outputs.ts index 0e485b4510c..800c1dbad8e 100644 --- a/garden-service/test/unit/src/outputs.ts +++ b/garden-service/test/unit/src/outputs.ts @@ -12,7 +12,7 @@ import { resolveProjectOutputs } from "../../../src/outputs" import { expect } from "chai" import { realpath } from "fs-extra" import { createGardenPlugin } from "../../../src/types/plugin/plugin" -import { ProjectConfig } from "../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../src/constants" import { exec } from "../../../src/util/util" import { ServiceState } from "../../../src/types/service" @@ -34,7 +34,7 @@ describe("resolveProjectOutputs", () => { path: tmpPath, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } diff --git a/garden-service/test/unit/src/tasks/deploy.ts b/garden-service/test/unit/src/tasks/deploy.ts index ec638bd45db..5c4fd73555b 100644 --- a/garden-service/test/unit/src/tasks/deploy.ts +++ b/garden-service/test/unit/src/tasks/deploy.ts @@ -9,7 +9,7 @@ import tmp from "tmp-promise" import execa from "execa" -import { ProjectConfig } from "../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../src/constants" import { Garden } from "../../../../src/garden" import { ConfigGraph } from "../../../../src/config-graph" @@ -40,7 +40,7 @@ describe("DeployTask", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } diff --git a/garden-service/test/unit/src/tasks/get-service-status.ts b/garden-service/test/unit/src/tasks/get-service-status.ts index 3f03a886c42..43dfa5834b5 100644 --- a/garden-service/test/unit/src/tasks/get-service-status.ts +++ b/garden-service/test/unit/src/tasks/get-service-status.ts @@ -9,7 +9,7 @@ import tmp from "tmp-promise" import execa from "execa" -import { ProjectConfig } from "../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../src/constants" import { createGardenPlugin } from "../../../../src/types/plugin/plugin" import { joi } from "../../../../src/config/common" @@ -36,7 +36,7 @@ describe("GetServiceStatusTask", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, } diff --git a/garden-service/test/unit/src/tasks/resolve-provider.ts b/garden-service/test/unit/src/tasks/resolve-provider.ts index 7eeaccb6246..1e5dbd362e0 100644 --- a/garden-service/test/unit/src/tasks/resolve-provider.ts +++ b/garden-service/test/unit/src/tasks/resolve-provider.ts @@ -18,6 +18,7 @@ import { pathExists, writeFile, remove } from "fs-extra" import { join } from "path" import { serialize } from "v8" import moment from "moment" +import { defaultNamespace } from "../../../../src/config/project" describe("ResolveProviderTask", () => { let tmpDir: TempDirectory @@ -46,7 +47,7 @@ describe("ResolveProviderTask", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test-plugin" }], variables: {}, }, diff --git a/garden-service/test/unit/src/tasks/task.ts b/garden-service/test/unit/src/tasks/task.ts index b3e15d78ede..d33ca4175bd 100644 --- a/garden-service/test/unit/src/tasks/task.ts +++ b/garden-service/test/unit/src/tasks/task.ts @@ -9,7 +9,7 @@ import tmp from "tmp-promise" import { expect } from "chai" import { TestGarden } from "../../../helpers" -import { ProjectConfig } from "../../../../src/config/project" +import { ProjectConfig, defaultNamespace } from "../../../../src/config/project" import { DEFAULT_API_VERSION } from "../../../../src/constants" import execa from "execa" import { createGardenPlugin } from "../../../../src/types/plugin/plugin" @@ -35,7 +35,7 @@ describe("TaskTask", () => { path: tmpDir.path, defaultEnvironment: "default", dotIgnoreFiles: [], - environments: [{ name: "default", variables: {} }], + environments: [{ name: "default", defaultNamespace, variables: {} }], providers: [{ name: "test" }], variables: {}, }