diff --git a/core/src/commands/plugins.ts b/core/src/commands/plugins.ts index f1a7d450a0..acf1026c31 100644 --- a/core/src/commands/plugins.ts +++ b/core/src/commands/plugins.ts @@ -103,7 +103,7 @@ export class PluginsCommand extends Command { printHeader(log, title, "⚙️") } - const provider = await garden.resolveProvider(log, args.plugin) + const provider = await garden.resolveProvider({ log, name: args.plugin }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) let graph = new ConfigGraph({ diff --git a/core/src/commands/validate.ts b/core/src/commands/validate.ts index 02f32eabdd..7918f743b1 100644 --- a/core/src/commands/validate.ts +++ b/core/src/commands/validate.ts @@ -56,7 +56,7 @@ export class ValidateCommand extends Command<{}, Opts> { async action({ garden, log, opts }: CommandParams<{}, Opts>): Promise { // This implicitly validates modules and actions. const { resolve } = opts - const graph = await garden.getConfigGraph({ log, emit: false }) + const graph = await garden.getConfigGraph({ log, emit: false, statusOnly: true }) if (resolve) { const actionsToResolve = getActionsToResolve(resolve, graph) await garden.resolveActions({ actions: actionsToResolve, graph, log }) diff --git a/core/src/garden.ts b/core/src/garden.ts index 87cb2f58fb..86065d98ff 100644 --- a/core/src/garden.ts +++ b/core/src/garden.ts @@ -242,6 +242,19 @@ interface GardenInstanceState { needsReload: boolean } +interface ResolveProvidersParams { + log: Log + forceInit?: boolean + statusOnly?: boolean + names?: string[] +} + +interface ResolveProviderParams { + log: Log + name: string + statusOnly?: boolean +} + @Profile() export class Garden { public log: Log @@ -712,7 +725,8 @@ export class Garden { : this.providerConfigs } - async resolveProvider(log: Log, name: string) { + async resolveProvider(params: ResolveProviderParams): Promise { + const { name, log, statusOnly } = params if (name === "_default") { return defaultProvider } @@ -723,7 +737,7 @@ export class Garden { this.log.silly(() => `Resolving provider ${name}`) - const providers = await this.resolveProviders(log, false, [name]) + const providers = await this.resolveProviders({ log, forceInit: false, statusOnly, names: [name] }) const provider = providers[name] if (!provider) { @@ -742,22 +756,23 @@ export class Garden { @OtelTraced({ name: "resolveProviders", }) - async resolveProviders(log: Log, forceInit = false, names?: string[]): Promise { + async resolveProviders(params: ResolveProvidersParams): Promise { + const { log, forceInit = false, statusOnly = false, names } = params // TODO: split this out of the Garden class let providers: Provider[] = [] + let providerNames = names await this.asyncLock.acquire("resolve-providers", async () => { const rawConfigs = this.getRawProviderConfigs({ names }) - - if (!names) { - names = getNames(rawConfigs) + if (!providerNames) { + providerNames = getNames(rawConfigs) } throwOnMissingSecretKeys(rawConfigs, this.secrets, "Provider", log) // As an optimization, we return immediately if all requested providers are already resolved - const alreadyResolvedProviders = names.map((name) => this.resolvedProviders[name]).filter(Boolean) - if (alreadyResolvedProviders.length === names.length) { + const alreadyResolvedProviders = providerNames.map((name) => this.resolvedProviders[name]).filter(Boolean) + if (alreadyResolvedProviders.length === providerNames.length) { providers = cloneDeep(alreadyResolvedProviders) return } @@ -824,7 +839,7 @@ export class Garden { }) // Process as many providers in parallel as possible - const taskResults = await this.processTasks({ tasks, log }) + const taskResults = await this.processTasks({ tasks, log, statusOnly }) const providerResults = Object.values(taskResults.results.getMap()) @@ -920,7 +935,7 @@ export class Garden { * Returns the reported status from all configured providers. */ async getEnvironmentStatus(log: Log) { - const providers = await this.resolveProviders(log) + const providers = await this.resolveProviders({ log }) return mapValues(providers, (p) => p.status) } @@ -961,7 +976,7 @@ export class Garden { } async getOutputConfigContext(log: Log, modules: GardenModule[], graphResults: GraphResults) { - const providers = await this.resolveProviders(log) + const providers = await this.resolveProviders({ log }) return new OutputConfigContext({ garden: this, resolvedProviders: providers, @@ -989,6 +1004,7 @@ export class Garden { graphResults, emit, actionModes = {}, + statusOnly, /** * If provided, this is used to perform partial module resolution. * TODO: also limit action resolution (less important because it's faster and more done on-demand) @@ -1003,7 +1019,7 @@ export class Garden { // TODO: split this out of the Garden class await this.scanAndAddConfigs() - const resolvedProviders = await this.resolveProviders(log) + const resolvedProviders = await this.resolveProviders({ log, forceInit: false, statusOnly }) const rawModuleConfigs = await this.getRawModuleConfigs() const graphLog = log.createLog({ name: "graph", showDuration: true }).info(`Resolving actions and modules...`) @@ -1693,7 +1709,7 @@ export class Garden { await this.scanAndAddConfigs() if (resolveProviders) { - providers = Object.values(await this.resolveProviders(log)) + providers = Object.values(await this.resolveProviders({ log })) } else { providers = this.getRawProviderConfigs() } @@ -2280,5 +2296,6 @@ export interface GetConfigGraphParams { graphResults?: GraphResults emit: boolean actionModes?: ActionModeMap + statusOnly?: boolean actionsFilter?: string[] } diff --git a/core/src/graph/nodes.ts b/core/src/graph/nodes.ts index 3528400e9b..421bf7dea9 100644 --- a/core/src/graph/nodes.ts +++ b/core/src/graph/nodes.ts @@ -325,7 +325,7 @@ export class ProcessTaskNode extends TaskNode { const processResult: TaskResultType = await this.task.process({ status, dependencyResults, - statusOnly: false, + statusOnly: this.statusOnly, }) this.task.emit("processed", { result: processResult }) if (processResult.state === "ready") { diff --git a/core/src/graph/solver.ts b/core/src/graph/solver.ts index 27b97322dc..831b57e635 100644 --- a/core/src/graph/solver.ts +++ b/core/src/graph/solver.ts @@ -418,7 +418,7 @@ export class GraphSolver extends TypedEventEmitter { // Status is either aborted or failed this.log.silly(() => `Request ${request.getKey()} status: ${resultToString(status)}`) this.completeTask({ ...status, node: request }) - } else if (request.statusOnly && status !== undefined) { + } else if (request.statusOnly && status !== undefined && status.result) { // Status is resolved, and that's all we need this.log.silly(() => `Request ${request.getKey()} is statusOnly and the status is available. Completing.`) this.completeTask({ ...status, node: request }) diff --git a/core/src/plugins/kubernetes/init.ts b/core/src/plugins/kubernetes/init.ts index 2ab1af1cad..6314fbc6e4 100644 --- a/core/src/plugins/kubernetes/init.ts +++ b/core/src/plugins/kubernetes/init.ts @@ -36,7 +36,6 @@ import { systemDockerAuthSecretName, dockerAuthSecretKey } from "./constants.js" import type { V1IngressClass, V1Secret, V1Toleration } from "@kubernetes/client-node" import type { KubernetesResource } from "./types.js" import type { PrimitiveMap } from "../../config/common.js" -import { mapValues } from "lodash-es" import { getIngressApiVersion, supportedIngressApiVersions } from "./container/ingress.js" import type { Log } from "../../logger/log-entry.js" import { ingressControllerInstall, ingressControllerReady } from "./nginx/ingress-controller.js" @@ -74,7 +73,7 @@ export async function getEnvironmentStatus({ const provider = k8sCtx.provider const api = await KubeApi.factory(log, ctx, provider) - const namespaces = await prepareNamespaces({ ctx, log }) + const namespace = await getNamespaceStatus({ ctx: k8sCtx, log, provider: k8sCtx.provider, skipCreate: true }) const detail: KubernetesEnvironmentDetail = { systemReady: true, @@ -82,22 +81,22 @@ export async function getEnvironmentStatus({ systemManagedCertificatesReady: true, } - const namespaceNames = mapValues(namespaces, (s) => s.namespaceName) const result: KubernetesEnvironmentStatus = { - ready: true, + ready: namespace.state === "ready", detail, outputs: { - ...namespaceNames, + "app-namespace": namespace.namespaceName, "default-hostname": provider.config.defaultHostname || null, }, } if (provider.config.setupIngressController === "nginx") { - log.info(`Ensuring ${styles.highlight("nginx")} Ingress Controller...`) const ingressControllerReadiness = await ingressControllerReady(ctx, log) - result.ready = ingressControllerReadiness + result.ready = ingressControllerReadiness && namespace.state === "ready" detail.systemReady = ingressControllerReadiness - log.info(`${styles.highlight("nginx")} Ingress Controller ready`) + log.info( + `${styles.highlight("nginx")} Ingress Controller ${ingressControllerReadiness ? "is ready" : "is not ready"}` + ) } else { // We only need to warn about missing ingress classes if we're not using garden installed nginx const ingressApiVersion = await getIngressApiVersion(log, api, supportedIngressApiVersions) @@ -145,7 +144,7 @@ export async function getIngressMisconfigurationWarnings( } /** - * Deploys system services (if any). + * Deploys system services (if any) and creates the default app namespace. */ export async function prepareEnvironment( params: PrepareEnvironmentParams @@ -154,7 +153,8 @@ export async function prepareEnvironment( const k8sCtx = ctx const provider = k8sCtx.provider const config = provider.config - + // create default app namespace if it doesn't exist + await prepareNamespaces({ ctx, log }) // make sure that the system namespace exists await getSystemNamespace(ctx, ctx.provider, log) diff --git a/core/src/router/base.ts b/core/src/router/base.ts index 595a22104b..88ad39a70a 100644 --- a/core/src/router/base.ts +++ b/core/src/router/base.ts @@ -71,7 +71,7 @@ export abstract class BaseRouter { templateContext: ConfigContext | undefined, events: PluginEventBroker | undefined ): Promise { - const provider = await this.garden.resolveProvider(log, handler.pluginName) + const provider = await this.garden.resolveProvider({ log, name: handler.pluginName }) const ctx = await this.garden.getPluginContext({ provider, templateContext, events }) @@ -291,7 +291,7 @@ export abstract class BaseActionRouter extends BaseRouter defaultHandler, }) - const providers = await this.garden.resolveProviders(log) + const providers = await this.garden.resolveProviders({ log }) const templateContext = action.isResolved() ? new ActionSpecContext({ diff --git a/core/src/router/provider.ts b/core/src/router/provider.ts index 5ec6eb9d5e..62e4874c04 100644 --- a/core/src/router/provider.ts +++ b/core/src/router/provider.ts @@ -178,7 +178,7 @@ export class ProviderRouter extends BaseRouter { log.info("Cleaning up environments...") const environmentStatuses: EnvironmentStatusMap = {} - const providers = await this.garden.resolveProviders(log) + const providers = await this.garden.resolveProviders({ log }) for (const provider of Object.values(providers)) { await this.cleanupEnvironment({ pluginName: provider.name, log, events: undefined }) environmentStatuses[provider.name] = { ready: false, outputs: {} } diff --git a/core/src/tasks/publish.ts b/core/src/tasks/publish.ts index dc888ee9dd..1503901b2e 100644 --- a/core/src/tasks/publish.ts +++ b/core/src/tasks/publish.ts @@ -100,7 +100,7 @@ export class PublishTask extends BaseActionTask extends BaseActionTask extends BaseActionTask extends BaseActionTask { } }, }) - async process({ dependencyResults }: TaskProcessParams) { + async process({ dependencyResults, statusOnly }: TaskProcessParams) { const providerResults = dependencyResults.getResultsByType(this).filter(isNotNull) const resolvedProviders: ProviderMap = keyBy(providerResults.map((r) => r.result).filter(isNotNull), "name") @@ -303,7 +303,8 @@ export class ResolveProviderTask extends BaseTask { moduleConfigs, status: defaultEnvironmentStatus, }) - const status = await this.ensurePrepared(tmpProvider) + + const status = await this.ensurePrepared(tmpProvider, statusOnly) return providerFromConfig({ plugin: this.plugin, @@ -379,7 +380,7 @@ export class ResolveProviderTask extends BaseTask { await writeFile(cachePath, serialize(cachedStatus)) } - private async ensurePrepared(tmpProvider: Provider) { + private async ensurePrepared(tmpProvider: Provider, statusOnly: boolean) { const pluginName = tmpProvider.name const providerLog = getProviderLog(pluginName, this.log) const actions = await this.garden.getActionRouter() @@ -416,7 +417,7 @@ export class ResolveProviderTask extends BaseTask { let status = await handler!({ ctx, log: providerLog }) - if (this.forceInit || !status.ready) { + if (!statusOnly && (this.forceInit || !status.ready)) { const statusMsg = status.ready ? `${styles.highlight("Ready")}, will ${styles.highlight("force re-initialize")}` : `${styles.highlight("Not ready")}, will initialize` @@ -433,12 +434,17 @@ export class ResolveProviderTask extends BaseTask { status = result.status } - if (!status.ready) { + if (!status.ready && !statusOnly) { providerLog.error("Failed initializing provider") throw new PluginError({ message: `Provider ${pluginName} reports status as not ready and could not prepare the configured environment.`, }) } + + if (!status.ready && statusOnly) { + providerLog.success("Provider not ready. Current command only checks status, not preparing environment") + return status + } providerLog.success("Provider ready") if (!status.disableCache) { diff --git a/core/src/util/testing.ts b/core/src/util/testing.ts index 03a1378666..2bb758e4a1 100644 --- a/core/src/util/testing.ts +++ b/core/src/util/testing.ts @@ -350,7 +350,7 @@ export class TestGarden extends Garden { name: string status: ActionStatus }) { - const providers = await this.resolveProviders(log) + const providers = await this.resolveProviders({ log }) if (providers["test-plugin"]) { set(providers["test-plugin"], ["_actionStatuses", kind, name], status) diff --git a/core/test/data/test-projects/project-with-default-namespace/garden.yml b/core/test/data/test-projects/project-with-default-namespace/garden.yml new file mode 100644 index 0000000000..32dceed1ad --- /dev/null +++ b/core/test/data/test-projects/project-with-default-namespace/garden.yml @@ -0,0 +1,8 @@ +apiVersion: garden.io/v1 +kind: Project +name: provider-handler-test +environments: + - name: local +providers: + - name: local-kubernetes + namespace: kubernetes-provider-handler-test \ No newline at end of file diff --git a/core/test/integ/src/plugins/container/container.ts b/core/test/integ/src/plugins/container/container.ts index f152ad5478..14b5c0b3b6 100644 --- a/core/test/integ/src/plugins/container/container.ts +++ b/core/test/integ/src/plugins/container/container.ts @@ -59,7 +59,7 @@ describe("plugins.container", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot, { plugins: [gardenPlugin()] }) log = createActionLog({ log: garden.log, actionName: "", actionKind: "" }) - containerProvider = await garden.resolveProvider(garden.log, "container") + containerProvider = await garden.resolveProvider({ log: garden.log, name: "container" }) ctx = await garden.getPluginContext({ provider: containerProvider, templateContext: undefined, events: undefined }) td.replace(garden.buildStaging, "syncDependencyProducts", () => null) }) diff --git a/core/test/integ/src/plugins/exec/exec.ts b/core/test/integ/src/plugins/exec/exec.ts index 56a136e37e..229537c731 100644 --- a/core/test/integ/src/plugins/exec/exec.ts +++ b/core/test/integ/src/plugins/exec/exec.ts @@ -46,7 +46,7 @@ describe("exec plugin", () => { describe("provider outputs", () => { it("the exec provider should have outputs for the initscript log", async () => { - const execProvider = await garden.resolveProvider(log, "exec") + const execProvider = await garden.resolveProvider({ log, name: "exec" }) expect((execProvider.outputs as ExecProviderOutputs).initScript.log).to.include( "this is a provider output message" ) diff --git a/core/test/integ/src/plugins/exec/resolve.ts b/core/test/integ/src/plugins/exec/resolve.ts index 274c45add2..00df3c5bff 100644 --- a/core/test/integ/src/plugins/exec/resolve.ts +++ b/core/test/integ/src/plugins/exec/resolve.ts @@ -7,12 +7,34 @@ */ import { expect } from "chai" -import fsExtra from "fs-extra" +import fsExtra, { pathExists, remove } from "fs-extra" const { readFile } = fsExtra import { join } from "node:path" import type { TestGarden } from "../../../../helpers.js" import { getDataDir, makeTestGarden } from "../../../../helpers.js" +describe("exec provider initialization statusOnly", () => { + let gardenOne: TestGarden + let tmpDir: string + let fileLocation: string + + beforeEach(async () => { + gardenOne = await makeTestGarden(getDataDir("exec-provider-cache"), { environmentString: "one" }) + + tmpDir = join(await gardenOne.getRepoRoot(), "project") + fileLocation = join(tmpDir, "theFile") + if (await pathExists(fileLocation)) { + await remove(fileLocation) + } + }) + it("should not execute the initScript when the provider is initialized with statusOnly", async () => { + await gardenOne.resolveProvider({ log: gardenOne.log, name: "exec", statusOnly: true }) + const fileExists = await pathExists(fileLocation) + + expect(fileExists).to.be.false + }) +}) + describe("exec provider initialization cache behaviour", () => { let gardenOne: TestGarden let tmpDir: string @@ -24,7 +46,7 @@ describe("exec provider initialization cache behaviour", () => { tmpDir = join(await gardenOne.getRepoRoot(), "project") fileLocation = join(tmpDir, "theFile") - await gardenOne.resolveProvider(gardenOne.log, "exec") + await gardenOne.resolveProvider({ log: gardenOne.log, name: "exec" }) }) it("writes the environment name to theFile as configured in the initScript", async () => { @@ -38,7 +60,7 @@ describe("exec provider initialization cache behaviour", () => { expect(contents).equal("one\n") const gardenTwo = await makeTestGarden(tmpDir, { environmentString: "two", noTempDir: true }) - await gardenTwo.resolveProvider(gardenTwo.log, "exec") + await gardenTwo.resolveProvider({ log: gardenTwo.log, name: "exec" }) contents = await readFile(fileLocation, { encoding: "utf-8" }) expect(contents).equal("two\n") @@ -49,13 +71,13 @@ describe("exec provider initialization cache behaviour", () => { expect(contents).equal("one\n") const gardenTwo = await makeTestGarden(tmpDir, { environmentString: "two", noTempDir: true }) - await gardenTwo.resolveProvider(gardenTwo.log, "exec") + await gardenTwo.resolveProvider({ log: gardenTwo.log, name: "exec" }) contents = await readFile(fileLocation, { encoding: "utf-8" }) expect(contents).equal("two\n") const gardenOneAgain = await makeTestGarden(tmpDir, { environmentString: "one", noTempDir: true }) - await gardenOneAgain.resolveProvider(gardenOneAgain.log, "exec") + await gardenOneAgain.resolveProvider({ log: gardenOneAgain.log, name: "exec" }) contents = await readFile(fileLocation, { encoding: "utf-8" }) expect(contents).equal("one\n") diff --git a/core/test/integ/src/plugins/kubernetes/api.ts b/core/test/integ/src/plugins/kubernetes/api.ts index a79485cd69..e59e10cd8e 100644 --- a/core/test/integ/src/plugins/kubernetes/api.ts +++ b/core/test/integ/src/plugins/kubernetes/api.ts @@ -38,7 +38,10 @@ describe("KubeApi", () => { before(async () => { const root = getDataDir("test-projects", "container") garden = await makeTestGarden(root) - provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as Provider + provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as Provider ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) api = await KubeApi.factory(garden.log, ctx, provider) namespace = await getAppNamespace(ctx as KubernetesPluginContext, garden.log, provider) 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 ca42e69449..9de8f0c0eb 100644 --- a/core/test/integ/src/plugins/kubernetes/commands/pull-image.ts +++ b/core/test/integ/src/plugins/kubernetes/commands/pull-image.ts @@ -36,7 +36,7 @@ describe.skip("pull-image plugin command", () => { const init = async (environmentName: string) => { ;({ garden, cleanup } = await getContainerTestGarden(environmentName, { remoteContainerAuth: true })) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) } diff --git a/core/test/integ/src/plugins/kubernetes/commands/sync.ts b/core/test/integ/src/plugins/kubernetes/commands/sync.ts index 87a3d5ee62..3def7d86f9 100644 --- a/core/test/integ/src/plugins/kubernetes/commands/sync.ts +++ b/core/test/integ/src/plugins/kubernetes/commands/sync.ts @@ -49,7 +49,7 @@ describe("sync plugin commands", () => { emit: false, actionModes: { sync: ["deploy.sync-mode"] }, }) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) log = garden.log const action = graph.getDeploy("sync-mode") diff --git a/core/test/integ/src/plugins/kubernetes/container/build/build.ts b/core/test/integ/src/plugins/kubernetes/container/build/build.ts index 73b386f932..4396e8a7d1 100644 --- a/core/test/integ/src/plugins/kubernetes/container/build/build.ts +++ b/core/test/integ/src/plugins/kubernetes/container/build/build.ts @@ -53,7 +53,7 @@ describe.skip("Kubernetes Container Build Extension", () => { ;({ garden, cleanup } = await getContainerTestGarden(environmentName, { remoteContainerAuth })) log = createActionLog({ log: garden.log, actionName: "", actionKind: "" }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = (await garden.getPluginContext({ provider, templateContext: undefined, @@ -598,7 +598,7 @@ describe("Ensure serviceAccount annotations for in-cluster building", () => { const init = async (environmentName: string, remoteContainerAuth = false) => { ;({ garden, cleanup } = await getContainerTestGarden(environmentName, { remoteContainerAuth })) log = createActionLog({ log: garden.log, actionName: "", actionKind: "" }) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = (await garden.getPluginContext({ provider, templateContext: undefined, diff --git a/core/test/integ/src/plugins/kubernetes/container/build/buildkit.ts b/core/test/integ/src/plugins/kubernetes/container/build/buildkit.ts index f0c8812539..094409fda2 100644 --- a/core/test/integ/src/plugins/kubernetes/container/build/buildkit.ts +++ b/core/test/integ/src/plugins/kubernetes/container/build/buildkit.ts @@ -56,7 +56,7 @@ describe.skip("ensureBuildkit", () => { }) beforeEach(async () => { - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = (await garden.getPluginContext({ provider, templateContext: undefined, diff --git a/core/test/integ/src/plugins/kubernetes/container/container.ts b/core/test/integ/src/plugins/kubernetes/container/container.ts index b83ca665e0..42f28bae8b 100644 --- a/core/test/integ/src/plugins/kubernetes/container/container.ts +++ b/core/test/integ/src/plugins/kubernetes/container/container.ts @@ -77,7 +77,9 @@ export async function getContainerTestGarden( if (needsInit) { // Load the test authentication for private registries - const localProvider = await localInstance.resolveProvider(localInstance.log, "local-kubernetes") + const localProvider = ( + await localInstance.resolveProvider({ log: localInstance.log, name: "local-kubernetes" }) + ) const api = await KubeApi.factory( garden.log, await garden.getPluginContext({ provider: localProvider, templateContext: undefined, events: undefined }), @@ -130,7 +132,7 @@ export async function getContainerTestGarden( await api.upsert({ kind: "Secret", namespace: "default", obj: credentialHelperAuth, log: garden.log }) } - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) if (needsInit) { @@ -155,7 +157,7 @@ describe("kubernetes container module handlers", () => { before(async () => { garden = await makeTestGarden(root) - // provider = await garden.resolveProvider(garden.log, "local-kubernetes") + // provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) }) beforeEach(async () => { diff --git a/core/test/integ/src/plugins/kubernetes/container/deployment.ts b/core/test/integ/src/plugins/kubernetes/container/deployment.ts index c6efb6cd14..fb202c485d 100644 --- a/core/test/integ/src/plugins/kubernetes/container/deployment.ts +++ b/core/test/integ/src/plugins/kubernetes/container/deployment.ts @@ -85,7 +85,7 @@ describe("kubernetes container deployment handlers", () => { const init = async (environmentName: string, remoteContainerAuth = false) => { ;({ garden, cleanup } = await getContainerTestGarden(environmentName, { remoteContainerAuth })) router = await garden.getActionRouter() - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) diff --git a/core/test/integ/src/plugins/kubernetes/container/ingress.ts b/core/test/integ/src/plugins/kubernetes/container/ingress.ts index 2717d62a86..614987ace8 100644 --- a/core/test/integ/src/plugins/kubernetes/container/ingress.ts +++ b/core/test/integ/src/plugins/kubernetes/container/ingress.ts @@ -312,7 +312,7 @@ describe("createIngressResources", () => { beforeEach(async () => { ;({ garden, cleanup } = await getContainerTestGarden()) - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" })) as KubernetesProvider context = provider.config.context td.replace(garden.buildStaging, "syncDependencyProducts", () => null) diff --git a/core/test/integ/src/plugins/kubernetes/container/logs.ts b/core/test/integ/src/plugins/kubernetes/container/logs.ts index e79116b1be..4812b456a5 100644 --- a/core/test/integ/src/plugins/kubernetes/container/logs.ts +++ b/core/test/integ/src/plugins/kubernetes/container/logs.ts @@ -34,7 +34,7 @@ describe("kubernetes", () => { const root = getDataDir("test-projects", "container") garden = await makeTestGarden(root) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) - provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + provider = (await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" })) as KubernetesProvider ctx = (await garden.getPluginContext({ provider, templateContext: undefined, diff --git a/core/test/integ/src/plugins/kubernetes/container/run.ts b/core/test/integ/src/plugins/kubernetes/container/run.ts index 7c80239156..d37d5665c5 100644 --- a/core/test/integ/src/plugins/kubernetes/container/run.ts +++ b/core/test/integ/src/plugins/kubernetes/container/run.ts @@ -30,7 +30,7 @@ describe("runContainerTask", () => { before(async () => { ;({ garden, cleanup } = await getContainerTestGarden()) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) }) after(async () => { diff --git a/core/test/integ/src/plugins/kubernetes/helm/common.ts b/core/test/integ/src/plugins/kubernetes/helm/common.ts index cef9963f06..9b110f1a16 100644 --- a/core/test/integ/src/plugins/kubernetes/helm/common.ts +++ b/core/test/integ/src/plugins/kubernetes/helm/common.ts @@ -97,7 +97,7 @@ describe("Helm common functions", () => { before(async () => { garden = await getHelmTestGarden() - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = (await garden.getPluginContext({ provider, templateContext: undefined, diff --git a/core/test/integ/src/plugins/kubernetes/helm/config.ts b/core/test/integ/src/plugins/kubernetes/helm/config.ts index 73f67105f6..3f8b404e26 100644 --- a/core/test/integ/src/plugins/kubernetes/helm/config.ts +++ b/core/test/integ/src/plugins/kubernetes/helm/config.ts @@ -35,7 +35,7 @@ describe("configureHelmModule", () => { before(async () => { garden = await getHelmTestGarden() - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await garden.resolveModules({ log: garden.log }) moduleConfigs = cloneDeep((garden).moduleConfigs) diff --git a/core/test/integ/src/plugins/kubernetes/helm/deployment.ts b/core/test/integ/src/plugins/kubernetes/helm/deployment.ts index 3b59a15a5d..27d0d81c3b 100644 --- a/core/test/integ/src/plugins/kubernetes/helm/deployment.ts +++ b/core/test/integ/src/plugins/kubernetes/helm/deployment.ts @@ -39,7 +39,7 @@ describe("helmDeploy in local-mode", () => { before(async () => { garden = await getHelmLocalModeTestGarden() - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) @@ -110,7 +110,7 @@ describe("helmDeploy", () => { before(async () => { garden = await getHelmTestGarden() - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) @@ -379,7 +379,9 @@ describe("helmDeploy", () => { const gardenWithCloudApi = await makeTestGarden(projectRoot, { cloudApi: fakeCloudApi, noCache: true }) graph = await gardenWithCloudApi.getConfigGraph({ log: gardenWithCloudApi.log, emit: false }) - const providerWithApi = await garden.resolveProvider(gardenWithCloudApi.log, "local-kubernetes") + const providerWithApi = ( + await garden.resolveProvider({ log: gardenWithCloudApi.log, name: "local-kubernetes" }) + ) const ctxWithCloudApi = await gardenWithCloudApi.getPluginContext({ provider: providerWithApi, templateContext: undefined, diff --git a/core/test/integ/src/plugins/kubernetes/helm/run.ts b/core/test/integ/src/plugins/kubernetes/helm/run.ts index e17d388078..6c9fa8ade0 100644 --- a/core/test/integ/src/plugins/kubernetes/helm/run.ts +++ b/core/test/integ/src/plugins/kubernetes/helm/run.ts @@ -44,7 +44,7 @@ describe("Helm Pod Run", () => { }) // Clear any existing Run result - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await clearRunResult({ ctx, log: garden.log, action }) @@ -84,7 +84,7 @@ describe("Helm Pod Run", () => { }) // Clear any existing Run result - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await clearRunResult({ ctx, log: garden.log, action }) diff --git a/core/test/integ/src/plugins/kubernetes/ingress-controller.ts b/core/test/integ/src/plugins/kubernetes/ingress-controller.ts index 7bd56c7514..6b7c5191dc 100644 --- a/core/test/integ/src/plugins/kubernetes/ingress-controller.ts +++ b/core/test/integ/src/plugins/kubernetes/ingress-controller.ts @@ -48,7 +48,7 @@ describe("It should manage ingress controller for respective cluster type", () = const init = async () => { ;({ garden } = await getContainerTestGarden()) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) diff --git a/core/test/integ/src/plugins/kubernetes/kubernetes-type/common.ts b/core/test/integ/src/plugins/kubernetes/kubernetes-type/common.ts index dcfeac6680..99cbecab44 100644 --- a/core/test/integ/src/plugins/kubernetes/kubernetes-type/common.ts +++ b/core/test/integ/src/plugins/kubernetes/kubernetes-type/common.ts @@ -49,7 +49,10 @@ describe("getManifests", () => { before(async () => { garden = await getKubernetesTestGarden() - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + const provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as KubernetesProvider ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) api = await KubeApi.factory(garden.log, ctx, provider) }) @@ -158,7 +161,10 @@ describe("getManifests", () => { before(async () => { garden = await makeTestGarden(exampleDir) - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + const provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as KubernetesProvider ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) api = await KubeApi.factory(garden.log, ctx, provider) }) @@ -231,7 +237,10 @@ describe("getManifests", () => { context("kubernetes manifest files resolution", () => { before(async () => { garden = await getKubernetesTestGarden() - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + const provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as KubernetesProvider ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) api = await KubeApi.factory(garden.log, ctx, provider) }) @@ -339,7 +348,10 @@ describe("getManifests", () => { context("resource patches", () => { before(async () => { garden = await getKubernetesTestGarden() - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + const provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as KubernetesProvider ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) api = await KubeApi.factory(garden.log, ctx, provider) }) diff --git a/core/test/integ/src/plugins/kubernetes/kubernetes-type/handlers.ts b/core/test/integ/src/plugins/kubernetes/kubernetes-type/handlers.ts index 84a161af5e..9790217149 100644 --- a/core/test/integ/src/plugins/kubernetes/kubernetes-type/handlers.ts +++ b/core/test/integ/src/plugins/kubernetes/kubernetes-type/handlers.ts @@ -140,7 +140,7 @@ describe("kubernetes-type handlers", () => { moduleConfigBackup = await garden.getRawModuleConfigs() log = garden.log actionLog = createActionLog({ log, actionName: "", actionKind: "" }) - const provider = await garden.resolveProvider(log, "local-kubernetes") + const provider = await garden.resolveProvider({ log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) diff --git a/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-run.ts b/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-run.ts index 5ab1469731..579774327d 100644 --- a/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-run.ts +++ b/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-run.ts @@ -40,7 +40,7 @@ describe("kubernetes-type exec Run", () => { }) // Clear any existing Run result - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await clearRunResult({ ctx, log: garden.log, action }) diff --git a/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-test.ts b/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-test.ts index 1027119bcb..19395b282f 100644 --- a/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-test.ts +++ b/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-exec-test.ts @@ -40,7 +40,7 @@ describe("kubernetes-type exec Test", () => { }) // Clear any existing Run result - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await clearRunResult({ ctx, log: garden.log, action }) diff --git a/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-pod-run.ts b/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-pod-run.ts index e47730a6ec..caddd29f86 100644 --- a/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-pod-run.ts +++ b/core/test/integ/src/plugins/kubernetes/kubernetes-type/kubernetes-pod-run.ts @@ -45,7 +45,7 @@ describe("kubernetes-type pod Run", () => { }) // Clear any existing Run result - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await clearRunResult({ ctx, log: garden.log, action }) @@ -86,7 +86,7 @@ describe("kubernetes-type pod Run", () => { }) // Clear any existing Run result - const provider = await garden.resolveProvider(garden.log, "local-kubernetes") + const provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await clearRunResult({ ctx, log: garden.log, action }) diff --git a/core/test/integ/src/plugins/kubernetes/local-mode.ts b/core/test/integ/src/plugins/kubernetes/local-mode.ts index 02aa77d311..d2d6f26b3c 100644 --- a/core/test/integ/src/plugins/kubernetes/local-mode.ts +++ b/core/test/integ/src/plugins/kubernetes/local-mode.ts @@ -61,7 +61,7 @@ describe("local mode deployments and ssh tunneling behavior", () => { noCache: true, actionModes: { local: ["deploy.local-mode"] }, }) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) diff --git a/core/test/integ/src/plugins/kubernetes/namespace.ts b/core/test/integ/src/plugins/kubernetes/namespace.ts index d1a7394fd7..6a65a2cd94 100644 --- a/core/test/integ/src/plugins/kubernetes/namespace.ts +++ b/core/test/integ/src/plugins/kubernetes/namespace.ts @@ -26,7 +26,7 @@ describe("Kubernetes Namespace helpers", () => { before(async () => { const root = getDataDir("test-projects", "container") const garden = await makeTestGarden(root) - provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as KubernetesProvider + provider = (await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" })) as KubernetesProvider ctx = await garden.getPluginContext({ provider, templateContext: undefined, diff --git a/core/test/integ/src/plugins/kubernetes/provider.ts b/core/test/integ/src/plugins/kubernetes/provider.ts new file mode 100644 index 0000000000..ba1de62d98 --- /dev/null +++ b/core/test/integ/src/plugins/kubernetes/provider.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018-2024 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import type { Log } from "../../../../../src/logger/log-entry.js" +import { expect } from "chai" + +import { KubeApi } from "../../../../../src/plugins/kubernetes/api.js" +import type { KubernetesPluginContext, KubernetesProvider } from "../../../../../src/plugins/kubernetes/config.js" + +import { getDataDir, makeTestGarden } from "../../../../helpers.js" +import { getEnvironmentStatus, prepareEnvironment } from "../../../../../src/plugins/kubernetes/init.js" +import type { PrepareEnvironmentParams } from "../../../../../src/plugin/handlers/Provider/prepareEnvironment.js" +import type { Garden } from "../../../../../src/index.js" + +async function ensureNamespaceDoesNotExist(api: KubeApi, namespaceName: string) { + if (!(await namespaceExists(api, namespaceName))) { + return + } + await api.core.deleteNamespace({ name: namespaceName }) + while (await namespaceExists(api, namespaceName)) { + await new Promise((resolve) => setTimeout(resolve, 1000)) + } +} + +async function namespaceExists(api: KubeApi, namespaceName: string) { + try { + await api.core.readNamespace({ name: namespaceName }) + return true + } catch (e) { + return false + } +} + +describe("kubernetes provider handlers", () => { + let log: Log + let ctx: KubernetesPluginContext + let api: KubeApi + let garden: Garden + const namespaceName = "kubernetes-provider-handler-test" + + before(async () => { + garden = await makeTestGarden(getDataDir("test-projects", "project-with-default-namespace")) + + log = garden.log + const provider = ( + await garden.resolveProvider({ log: garden.log, name: "local-kubernetes", statusOnly: false }) + ) + ctx = ( + await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) + ) + api = await KubeApi.factory(log, ctx, ctx.provider) + await ensureNamespaceDoesNotExist(api, namespaceName) + }) + afterEach(async () => { + await ensureNamespaceDoesNotExist(api, namespaceName) + }) + + describe("getEnvironmentStatus", () => { + it("should only return the environment status and not create any resources with the getEnvironmentStatus handler", async () => { + const envStatus = await getEnvironmentStatus({ ctx, log }) + expect(envStatus.ready).to.be.false + const namespaceStatus = await namespaceExists(api, namespaceName) + expect(namespaceStatus).to.be.false + }) + + it("should prepare the environment with the prepareEnvironment handler", async () => { + const status = await getEnvironmentStatus({ ctx, log }) + const params: PrepareEnvironmentParams = { + ctx, + log: garden.log, + status, + force: false, + } + const envStatus = await prepareEnvironment(params) + expect(envStatus.status.ready).to.be.true + const namespaceStatus = await namespaceExists(api, namespaceName) + expect(namespaceStatus).to.be.true + }) + }) +}) diff --git a/core/test/integ/src/plugins/kubernetes/run.ts b/core/test/integ/src/plugins/kubernetes/run.ts index de8706f051..7cdd579dac 100644 --- a/core/test/integ/src/plugins/kubernetes/run.ts +++ b/core/test/integ/src/plugins/kubernetes/run.ts @@ -65,7 +65,7 @@ describe("kubernetes Pod runner functions", () => { before(async () => { ;({ garden, cleanup } = await getContainerTestGarden()) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) namespace = provider.config.namespace!.name! api = await KubeApi.factory(garden.log, ctx, provider) @@ -593,7 +593,9 @@ describe("kubernetes Pod runner functions", () => { before(async () => { helmGarden = await getHelmTestGarden() - helmProvider = await helmGarden.resolveProvider(helmGarden.log, "local-kubernetes") + helmProvider = ( + await helmGarden.resolveProvider({ log: helmGarden.log, name: "local-kubernetes" }) + ) helmCtx = ( await helmGarden.getPluginContext({ provider: helmProvider, templateContext: undefined, events: undefined }) ) diff --git a/core/test/integ/src/plugins/kubernetes/sync-mode.ts b/core/test/integ/src/plugins/kubernetes/sync-mode.ts index 161a7b9fa5..b7cb7a6b91 100644 --- a/core/test/integ/src/plugins/kubernetes/sync-mode.ts +++ b/core/test/integ/src/plugins/kubernetes/sync-mode.ts @@ -87,7 +87,7 @@ describe("sync mode deployments and sync behavior", () => { sync: ["deploy.sync-mode"], }, }) - provider = await garden.resolveProvider(garden.log, "local-kubernetes") + provider = await garden.resolveProvider({ log: garden.log, name: "local-kubernetes" }) ctx = ( await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) ) diff --git a/core/test/integ/src/plugins/kubernetes/task-results.ts b/core/test/integ/src/plugins/kubernetes/task-results.ts index 92b2b51d81..b827cd6e09 100644 --- a/core/test/integ/src/plugins/kubernetes/task-results.ts +++ b/core/test/integ/src/plugins/kubernetes/task-results.ts @@ -23,7 +23,10 @@ describe("kubernetes Run results", () => { before(async () => { const root = getDataDir("test-projects", "container") garden = await makeTestGarden(root) - provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as Provider + provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as Provider }) after(async () => { diff --git a/core/test/integ/src/plugins/kubernetes/util.ts b/core/test/integ/src/plugins/kubernetes/util.ts index 3482e44a22..feb78c0c83 100644 --- a/core/test/integ/src/plugins/kubernetes/util.ts +++ b/core/test/integ/src/plugins/kubernetes/util.ts @@ -57,7 +57,7 @@ describe("util", () => { before(async () => { helmGarden = await getHelmTestGarden() log = helmGarden.log - const provider = await helmGarden.resolveProvider(log, "local-kubernetes") + const provider = await helmGarden.resolveProvider({ log, name: "local-kubernetes" }) ctx = (await helmGarden.getPluginContext({ provider, templateContext: undefined, @@ -130,7 +130,10 @@ describe("util", () => { it("should return workload pods", async () => { try { const graph = await garden.getConfigGraph({ log: garden.log, emit: false }) - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as Provider + const provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as Provider const rawAction = graph.getDeploy("simple-service") const action = await garden.resolveAction({ @@ -187,7 +190,10 @@ describe("util", () => { action, }) - const provider = (await garden.resolveProvider(garden.log, "local-kubernetes")) as Provider + const provider = (await garden.resolveProvider({ + log: garden.log, + name: "local-kubernetes", + })) as Provider await garden.processTasks({ tasks: [deployTask], throwOnError: true }) const namespace = await getAppNamespace(ctx, log, provider) diff --git a/core/test/unit/src/commands/test.ts b/core/test/unit/src/commands/test.ts index 46952ae3db..1594c05792 100644 --- a/core/test/unit/src/commands/test.ts +++ b/core/test/unit/src/commands/test.ts @@ -229,7 +229,7 @@ describe("TestCommand", () => { }) it("handles --interactive option if single test name is specified", async () => { - const provider = await garden.resolveProvider(garden.log, "test-plugin") + const provider = await garden.resolveProvider({ log: garden.log, name: "test-plugin" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await garden.stubRouterAction("Test", "run", async ({ interactive }) => { diff --git a/core/test/unit/src/commands/util/fetch-tools.ts b/core/test/unit/src/commands/util/fetch-tools.ts index bafcfb37e1..2333d327bd 100644 --- a/core/test/unit/src/commands/util/fetch-tools.ts +++ b/core/test/unit/src/commands/util/fetch-tools.ts @@ -76,7 +76,7 @@ describe("FetchToolsCommand", () => { }), }) - await garden.resolveProviders(garden.log) + await garden.resolveProviders({ log: garden.log }) const log = garden.log const command = new FetchToolsCommand() @@ -106,7 +106,7 @@ describe("FetchToolsCommand", () => { }), }) - await garden.resolveProviders(garden.log) + await garden.resolveProviders({ log: garden.log }) const log = garden.log const command = new FetchToolsCommand() @@ -133,7 +133,7 @@ describe("FetchToolsCommand", () => { garden.providerConfigs = [] garden.registeredPlugins = [plugin] - await garden.resolveProviders(garden.log) + await garden.resolveProviders({ log: garden.log }) const log = garden.log const command = new FetchToolsCommand() @@ -170,7 +170,7 @@ describe("FetchToolsCommand", () => { garden.providerConfigs = [] garden.registeredPlugins = [plugin] - await garden.resolveProviders(garden.log) + await garden.resolveProviders({ log: garden.log }) const log = garden.log const command = new FetchToolsCommand() diff --git a/core/test/unit/src/config/template-contexts/module.ts b/core/test/unit/src/config/template-contexts/module.ts index 2869f1afcc..631047293c 100644 --- a/core/test/unit/src/config/template-contexts/module.ts +++ b/core/test/unit/src/config/template-contexts/module.ts @@ -39,7 +39,7 @@ describe("ModuleConfigContext", () => { c = new ModuleConfigContext({ garden, - resolvedProviders: keyBy(await garden.resolveProviders(garden.log), "name"), + resolvedProviders: keyBy(await garden.resolveProviders({ log: garden.log }), "name"), variables: garden.variables, modules, buildPath: module.buildPath, diff --git a/core/test/unit/src/config/template-contexts/provider.ts b/core/test/unit/src/config/template-contexts/provider.ts index eab4448759..2059c3ae62 100644 --- a/core/test/unit/src/config/template-contexts/provider.ts +++ b/core/test/unit/src/config/template-contexts/provider.ts @@ -20,14 +20,14 @@ interface TestValues { describe("ProviderConfigContext", () => { it("should set an empty namespace and environment.fullName to environment.name if no namespace is set", async () => { const garden = await makeTestGarden(projectRootA, { environmentString: "local" }) - const c = new ProviderConfigContext(garden, await garden.resolveProviders(garden.log), garden.variables) + const c = new ProviderConfigContext(garden, await garden.resolveProviders({ log: garden.log }), garden.variables) expect(c.resolve({ key: ["environment", "name"], nodePath: [], opts: {} })).to.eql({ resolved: "local" }) }) it("should set environment.namespace and environment.fullName to properly if namespace is set", async () => { const garden = await makeTestGarden(projectRootA, { environmentString: "foo.local" }) - const c = new ProviderConfigContext(garden, await garden.resolveProviders(garden.log), garden.variables) + const c = new ProviderConfigContext(garden, await garden.resolveProviders({ log: garden.log }), garden.variables) expect(c.resolve({ key: ["environment", "name"], nodePath: [], opts: {} })).to.eql({ resolved: "local" }) expect(c.resolve({ key: ["environment", "namespace"], nodePath: [], opts: {} })).to.eql({ resolved: "foo" }) diff --git a/core/test/unit/src/garden.ts b/core/test/unit/src/garden.ts index e9530ae845..acf3486280 100644 --- a/core/test/unit/src/garden.ts +++ b/core/test/unit/src/garden.ts @@ -170,7 +170,7 @@ describe("Garden", () => { expect(garden.projectName).to.equal("test-project-a") - const providers = await garden.resolveProviders(garden.log) + const providers = await garden.resolveProviders({ log: garden.log }) const configs = mapValues(providers, (p) => p.config) expect(configs).to.eql({ @@ -220,7 +220,7 @@ describe("Garden", () => { delete process.env.TEST_PROVIDER_TYPE delete process.env.TEST_VARIABLE - const providers = await garden.resolveProviders(garden.log) + const providers = await garden.resolveProviders({ log: garden.log }) const configs = mapValues(providers, (p) => p.config) expect(configs).to.eql({ @@ -2109,7 +2109,7 @@ describe("Garden", () => { }), }) - await expectError(() => garden.resolveProviders(garden.log), { + await expectError(() => garden.resolveProviders({ log: garden.log }), { contains: "Configured provider 'test-plugin' has not been registered.", }) }) @@ -2133,7 +2133,7 @@ describe("Garden", () => { }, } - const providers = await garden.resolveProviders(garden.log) + const providers = await garden.resolveProviders({ log: garden.log }) const configs = mapValues(providers, (p) => p.config) expect(configs["test-plugin"]).to.eql(testPluginProvider.config) @@ -2172,7 +2172,7 @@ describe("Garden", () => { config: projectConfig, }) - const provider = await garden.resolveProvider(garden.log, "test") + const provider = await garden.resolveProvider({ log: garden.log, name: "test" }) expect(provider.config).to.eql({ name: "test", @@ -2195,7 +2195,7 @@ describe("Garden", () => { const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [test] }) await expectError( - () => garden.resolveProviders(garden.log), + () => garden.resolveProviders({ log: garden.log }), (err) => { expectFuzzyMatch(err.toString(), ["Failed resolving one or more providers:", "- test"]) } @@ -2213,7 +2213,7 @@ describe("Garden", () => { providers: [{ name: "test", foo: "${providers.foo.config.bla}" }], }) const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [test] }) - await expectError(() => garden.resolveProviders(garden.log)) + await expectError(() => garden.resolveProviders({ log: garden.log })) }) it("should add plugin modules if returned by the provider", async () => { @@ -2273,7 +2273,7 @@ describe("Garden", () => { const plugins = [testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - await expectError(() => garden.resolveProviders(garden.log), { + await expectError(() => garden.resolveProviders({ log: garden.log }), { contains: ["Found a circular dependency between registered plugins:", "test-a <- test-b <- test-a"], }) }) @@ -2292,7 +2292,7 @@ describe("Garden", () => { const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [testA] }) - await expectError(() => garden.resolveProviders(garden.log), { + await expectError(() => garden.resolveProviders({ log: garden.log }), { contains: ["Found a circular dependency between registered plugins:", "test-a <- test-a"], }) }) @@ -2317,7 +2317,7 @@ describe("Garden", () => { const plugins = [testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - await expectError(() => garden.resolveProviders(garden.log), { + await expectError(() => garden.resolveProviders({ log: garden.log }), { contains: [ "One or more circular dependencies found between providers or their configurations:", "test-a <- test-b <- test-a", @@ -2346,7 +2346,7 @@ describe("Garden", () => { const plugins = [testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - await expectError(() => garden.resolveProviders(garden.log), { + await expectError(() => garden.resolveProviders({ log: garden.log }), { contains: [ "One or more circular dependencies found between providers or their", "configurations:", @@ -2374,7 +2374,7 @@ describe("Garden", () => { const plugins = [testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - await expectError(() => garden.resolveProviders(garden.log), { + await expectError(() => garden.resolveProviders({ log: garden.log }), { contains: [ "One or more circular dependencies found between providers or their", "configurations:", @@ -2398,7 +2398,7 @@ describe("Garden", () => { }) const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [test] }) - const providers = keyBy(await garden.resolveProviders(garden.log), "name") + const providers = keyBy(await garden.resolveProviders({ log: garden.log }), "name") expect(providers.test).to.exist expect(providers.test.config["foo"]).to.equal("bar") @@ -2421,7 +2421,7 @@ describe("Garden", () => { const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [test] }) await expectError( - () => garden.resolveProviders(garden.log), + () => garden.resolveProviders({ log: garden.log }), (err) => { expectFuzzyMatch(err.toString(true), [ "Failed resolving one or more providers:", @@ -2455,7 +2455,7 @@ describe("Garden", () => { const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [test] }) await expectError( - () => garden.resolveProviders(garden.log), + () => garden.resolveProviders({ log: garden.log }), (err) => { expectFuzzyMatch(err.toString(true), [ "Failed resolving one or more providers:", @@ -2493,7 +2493,7 @@ describe("Garden", () => { const plugins = [testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - const providerB = await garden.resolveProvider(garden.log, "test-b") + const providerB = await garden.resolveProvider({ log: garden.log, name: "test-b" }) expect(providerB.config["foo"]).to.equal("bar") }) @@ -2532,7 +2532,7 @@ describe("Garden", () => { const plugins = [testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - const providerB = await garden.resolveProvider(garden.log, "test-b") + const providerB = await garden.resolveProvider({ log: garden.log, name: "test-b" }) expect(providerB.config["foo"]).to.equal("default") }) @@ -2552,7 +2552,7 @@ describe("Garden", () => { const plugins = [testA] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - const providerB = await garden.resolveProvider(garden.log, "test-a") + const providerB = await garden.resolveProvider({ log: garden.log, name: "test-a" }) expect(providerB.config["foo"]).to.equal("bar") }) @@ -2589,8 +2589,8 @@ describe("Garden", () => { const plugins = [baseA, testA, testB] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - const providerA = await garden.resolveProvider(garden.log, "test-a") - const providerB = await garden.resolveProvider(garden.log, "test-b") + const providerA = await garden.resolveProvider({ log: garden.log, name: "test-a" }) + const providerB = await garden.resolveProvider({ log: garden.log, name: "test-b" }) expect(providerB.dependencies).to.eql({ "test-a": providerA }) }) @@ -2633,9 +2633,9 @@ describe("Garden", () => { const plugins = [baseA, testA, testB, testC] const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins }) - const providerA = await garden.resolveProvider(garden.log, "test-a") - const providerB = await garden.resolveProvider(garden.log, "test-b") - const providerC = await garden.resolveProvider(garden.log, "test-c") + const providerA = await garden.resolveProvider({ log: garden.log, name: "test-a" }) + const providerB = await garden.resolveProvider({ log: garden.log, name: "test-b" }) + const providerC = await garden.resolveProvider({ log: garden.log, name: "test-c" }) expect(providerC.dependencies).to.eql({ "test-a": providerA, "test-b": providerB }) }) @@ -2663,7 +2663,7 @@ describe("Garden", () => { const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [base, test] }) await expectError( - () => garden.resolveProviders(garden.log), + () => garden.resolveProviders({ log: garden.log }), (err) => { expectFuzzyMatch(err.toString(true), [ "Failed resolving one or more providers:", @@ -2703,7 +2703,7 @@ describe("Garden", () => { const garden = await makeTestGarden(projectRootA, { config: projectConfig, plugins: [base, test] }) await expectError( - () => garden.resolveProviders(garden.log), + () => garden.resolveProviders({ log: garden.log }), (err) => { expectFuzzyMatch(err.toString(true), [ "Failed resolving one or more providers:", diff --git a/core/test/unit/src/plugins/container/build.ts b/core/test/unit/src/plugins/container/build.ts index ca6b127629..324ed7c194 100644 --- a/core/test/unit/src/plugins/container/build.ts +++ b/core/test/unit/src/plugins/container/build.ts @@ -37,7 +37,7 @@ context("build.ts", () => { garden = await makeTestGarden(projectRoot, { plugins: [gardenPlugin()] }) log = garden.log actionLog = createActionLog({ log, actionName: "", actionKind: "" }) - containerProvider = await garden.resolveProvider(garden.log, "container") + containerProvider = await garden.resolveProvider({ log: garden.log, name: "container" }) ctx = await garden.getPluginContext({ provider: containerProvider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log, emit: false }) }) diff --git a/core/test/unit/src/plugins/container/container.ts b/core/test/unit/src/plugins/container/container.ts index 00553a98a8..339e98758c 100644 --- a/core/test/unit/src/plugins/container/container.ts +++ b/core/test/unit/src/plugins/container/container.ts @@ -91,7 +91,7 @@ describe("plugins.container", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot, { plugins: [gardenPlugin()] }) log = garden.log - containerProvider = await garden.resolveProvider(garden.log, "container") + containerProvider = await garden.resolveProvider({ log: garden.log, name: "container" }) ctx = await garden.getPluginContext({ provider: containerProvider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log, emit: false }) td.replace(garden.buildStaging, "syncDependencyProducts", () => null) diff --git a/core/test/unit/src/plugins/container/helpers.ts b/core/test/unit/src/plugins/container/helpers.ts index 2424384653..d114b53580 100644 --- a/core/test/unit/src/plugins/container/helpers.ts +++ b/core/test/unit/src/plugins/container/helpers.ts @@ -76,7 +76,7 @@ describe("containerHelpers", () => { beforeEach(async () => { garden = await makeTestGarden(projectRoot, { plugins: [gardenPlugin()] }) log = garden.log - const provider = await garden.resolveProvider(garden.log, "container") + const provider = await garden.resolveProvider({ log: garden.log, name: "container" }) ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) td.replace(garden.buildStaging, "syncDependencyProducts", () => null) diff --git a/core/test/unit/src/plugins/exec/exec.ts b/core/test/unit/src/plugins/exec/exec.ts index 63e3209639..300a617336 100644 --- a/core/test/unit/src/plugins/exec/exec.ts +++ b/core/test/unit/src/plugins/exec/exec.ts @@ -64,7 +64,7 @@ describe("exec plugin", () => { beforeEach(async () => { garden = await makeTestGarden(testProjectRoot, { plugins: [plugin] }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) - execProvider = await garden.resolveProvider(garden.log, "exec") + execProvider = await garden.resolveProvider({ log: garden.log, name: "exec" }) ctx = await garden.getPluginContext({ provider: execProvider, templateContext: undefined, events: undefined }) log = createActionLog({ log: garden.log, actionName: "", actionKind: "" }) await garden.clearBuilds() @@ -96,7 +96,7 @@ describe("exec plugin", () => { }), }) - await expectError(() => _garden.resolveProviders(_garden.log), "plugin") + await expectError(() => _garden.resolveProviders({ log: _garden.log }), "plugin") }) it("should correctly parse exec modules", async () => { diff --git a/core/test/unit/src/router/provider.ts b/core/test/unit/src/router/provider.ts index 0a0195f9d4..d49de52f03 100644 --- a/core/test/unit/src/router/provider.ts +++ b/core/test/unit/src/router/provider.ts @@ -64,7 +64,7 @@ describe("provider actions", async () => { describe("augmentGraph", () => { it("should return modules and/or dependency relations to add to the stack graph", async () => { graph = await garden.getConfigGraph({ log: garden.log, emit: false }) - const providers = await garden.resolveProviders(garden.log) + const providers = await garden.resolveProviders({ log: garden.log }) const result = await actionRouter.provider.augmentGraph({ log, pluginName: "test-plugin-a", diff --git a/plugins/pulumi/src/commands.ts b/plugins/pulumi/src/commands.ts index 26643a4e4c..a9800c4484 100644 --- a/plugins/pulumi/src/commands.ts +++ b/plugins/pulumi/src/commands.ts @@ -377,7 +377,7 @@ function makePulumiCommand({ name, commandDescription, beforeFn, runFn, afterFn const pulumiProvider = ctx.provider as PulumiProvider const actions = graph.getDeploys({ names }).filter((a) => a.type === "pulumi") - const resolvedProviders = await garden.resolveProviders(log) + const resolvedProviders = await garden.resolveProviders({ log }) const tasks = await Promise.all( actions.map(async (action) => { diff --git a/plugins/pulumi/test/handlers.ts b/plugins/pulumi/test/handlers.ts index 309beb77c4..d9d88205d6 100644 --- a/plugins/pulumi/test/handlers.ts +++ b/plugins/pulumi/test/handlers.ts @@ -62,7 +62,7 @@ describe("pulumi plugin handlers", () => { const plugin = pulumiPlugin() garden = await makeTestGarden(projectRoot, { plugins: [plugin] }) log = garden.log - provider = (await garden.resolveProvider(log, "pulumi")) as PulumiProvider + provider = (await garden.resolveProvider({ log, name: "pulumi" })) as PulumiProvider ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getResolvedConfigGraph({ log, emit: false }) }) diff --git a/plugins/terraform/test/common.ts b/plugins/terraform/test/common.ts index fb850a5b32..1ccee9970f 100644 --- a/plugins/terraform/test/common.ts +++ b/plugins/terraform/test/common.ts @@ -55,7 +55,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { variableOverrides: { "tf-version": terraformVersion }, }) log = garden.log - provider = (await garden.resolveProvider(log, "terraform")) as TerraformProvider + provider = (await garden.resolveProvider({ log, name: "terraform" })) as TerraformProvider ctx = await garden.getPluginContext({ provider, events: undefined, templateContext: undefined }) root = join(garden.projectRoot, "tf") terraformDirPath = join(root, ".terraform") diff --git a/plugins/terraform/test/terraform.ts b/plugins/terraform/test/terraform.ts index 24cfcabbe1..893afaca9d 100644 --- a/plugins/terraform/test/terraform.ts +++ b/plugins/terraform/test/terraform.ts @@ -75,7 +75,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should warn if stack is not up-to-date", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const messages = getRootLogMessages(garden.log, (e) => e.level === LogLevel.warn) expect(messages).to.include( "Terraform stack is not up-to-date and autoApply is not enabled. Please run garden plugins terraform apply-root to make sure the stack is in the intended state." @@ -84,7 +84,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should expose outputs to template contexts after applying", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const applyRootCommand = findByName(getTerraformCommands(), "apply-root")! await applyRootCommand.handler({ @@ -100,7 +100,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], variableOverrides: { "tf-version": terraformVersion }, }) - const _provider = await _garden.resolveProvider(_garden.log, "terraform") + const _provider = await _garden.resolveProvider({ log: _garden.log, name: "terraform" }) expect(_provider.status.outputs).to.eql({ "my-output": "workspace: default, input: foo", @@ -110,7 +110,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("apply-root command", () => { it("calls terraform apply for the project root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const command = findByName(getTerraformCommands(), "apply-root")! @@ -124,7 +124,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("sets the workspace before running the command", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider provider.config.workspace = "foo" const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) @@ -145,7 +145,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("plan-root command", () => { it("calls terraform plan for the project root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const command = findByName(getTerraformCommands(), "plan-root")! @@ -159,7 +159,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("sets the workspace before running the command", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider provider.config.workspace = "foo" const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) @@ -180,7 +180,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("destroy-root command", () => { it("calls terraform destroy for the project root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const command = findByName(getTerraformCommands(), "destroy-root")! @@ -194,7 +194,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("sets the workspace before running the command", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider provider.config.workspace = "foo" const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) @@ -215,7 +215,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { context("allowDestroy=false", () => { it("doesn't call terraform destroy when calling the delete service handler", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) // This creates the test file @@ -239,16 +239,17 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) context("autoApply=true", () => { - before(async () => { + beforeEach(async () => { garden = await makeTestGarden(testRoot, { plugins: [gardenPlugin()], environmentString: "local", forceRefresh: true, variableOverrides: { "tf-version": terraformVersion }, }) - }) - - beforeEach(async () => { + tfRoot = join(garden.projectRoot, "tf") + stateDirPath = join(tfRoot, "terraform.tfstate") + stateDirPathWithWorkspaces = join(tfRoot, "terraform.tfstate.d") + testFilePath = join(tfRoot, "test.log") await reset() }) @@ -257,7 +258,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should apply a stack on init and use configured variables", async () => { - await garden.resolveProvider(garden.log, "terraform") + await garden.resolveProvider({ log: garden.log, name: "terraform" }) expect( garden.log.root .getLogEntries() @@ -269,6 +270,17 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { expect(testFileContent.toString()).to.equal("default") }) + it("should not apply a stack when the provider is resolved with statusOnly=true e.g. while running validate command", async () => { + await garden.resolveProvider({ log: garden.log, name: "terraform", statusOnly: true }) + expect( + garden.log.root + .getLogEntries() + .filter((l) => + resolveMsg(l)?.match(/Provider not ready. Current command only checks status, not preparing environment/) + ).length + ).to.be.greaterThan(0) + }) + it("sets the workspace before applying the stack", async () => { const _garden = await makeTestGarden(testRoot, { environmentString: "local", @@ -279,13 +291,13 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }, plugins: [gardenPlugin()], }) - await _garden.resolveProvider(garden.log, "terraform") + await _garden.resolveProvider({ log: garden.log, name: "terraform" }) const testFileContent = await readFile(testFilePath) expect(testFileContent.toString()).to.equal("foo") }) it("should expose outputs to template contexts", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) expect(provider.status.outputs).to.eql({ "my-output": "workspace: default, input: foo", "test-file-path": "./test.log", @@ -295,7 +307,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { context("allowDestroy=true", () => { it("calls terraform destroy when calling the delete service handler", async () => { // This implicitly creates the test file - await garden.resolveProvider(garden.log, "terraform") + await garden.resolveProvider({ log: garden.log, name: "terraform" }) // This should remove the file const actions = await garden.getActionRouter() @@ -311,6 +323,8 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { const testRoot = resolve(moduleDirName, "../../test/", "test-project-action") const tfRoot = join(testRoot, "tf") const stateDirPath = join(tfRoot, "terraform.tfstate") + const backupStateDirPath = join(tfRoot, "terraform.tfstate.backup") + const stateDirPathWithWorkspaces = join(tfRoot, "terraform.tfstate.d") const testFilePath = join(tfRoot, "test.log") let garden: TestGarden @@ -323,6 +337,12 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { if (stateDirPath && (await pathExists(stateDirPath))) { await remove(stateDirPath) } + if (stateDirPathWithWorkspaces && (await pathExists(stateDirPathWithWorkspaces))) { + await remove(stateDirPathWithWorkspaces) + } + if (backupStateDirPath && (await pathExists(backupStateDirPath))) { + await remove(backupStateDirPath) + } } beforeEach(async () => { @@ -390,7 +410,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("apply-action command", () => { it("calls terraform apply for the action", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) @@ -412,7 +432,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await setWorkspace({ ctx, provider, root: tfRoot, log: _garden.log, workspace: "default" }) @@ -435,7 +455,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("plan-action command", () => { it("calls terraform apply for the action root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) @@ -457,7 +477,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const _ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await setWorkspace({ ctx: _ctx, provider, root: tfRoot, log: _garden.log, workspace: "default" }) @@ -480,7 +500,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("destroy-action command", () => { it("calls terraform destroy for the action root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) @@ -502,7 +522,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(_garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: _garden.log, name: "terraform" })) as TerraformProvider const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await setWorkspace({ ctx, provider, root: tfRoot, log: _garden.log, workspace: "default" }) @@ -533,7 +553,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should expose runtime outputs to template contexts if stack had already been applied", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) const applyCommand = findByName(getTerraformCommands(), "apply-action")! @@ -553,7 +573,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should return outputs with the service status", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) const applyCommand = findByName(getTerraformCommands(), "apply-action")! @@ -596,7 +616,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = await _garden.resolveProvider(_garden.log, "terraform") + const provider = await _garden.resolveProvider({ log: _garden.log, name: "terraform" }) const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const _graph = await _garden.getConfigGraph({ log: _garden.log, emit: false }) const applyCommand = findByName(getTerraformCommands(), "apply-action")! @@ -731,7 +751,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(_garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: _garden.log, name: "terraform" })) as TerraformProvider const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const actions = await _garden.getActionRouter() const _graph = await _garden.getConfigGraph({ log: _garden.log, emit: false }) @@ -835,7 +855,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("apply-action command", () => { it("calls terraform apply for the action", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) @@ -857,7 +877,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await setWorkspace({ ctx, provider, root: tfRoot, log: _garden.log, workspace: "default" }) @@ -880,7 +900,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("plan-action command", () => { it("calls terraform apply for the action root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) @@ -902,7 +922,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const _ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await setWorkspace({ ctx: _ctx, provider, root: tfRoot, log: _garden.log, workspace: "default" }) @@ -925,7 +945,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { describe("destroy-action command", () => { it("calls terraform destroy for the action root", async () => { - const provider = (await garden.resolveProvider(garden.log, "terraform")) as TerraformProvider + const provider = (await garden.resolveProvider({ log: garden.log, name: "terraform" })) as TerraformProvider const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) @@ -947,7 +967,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(_garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: _garden.log, name: "terraform" })) as TerraformProvider const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) await setWorkspace({ ctx, provider, root: tfRoot, log: _garden.log, workspace: "default" }) @@ -978,7 +998,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should expose runtime outputs to template contexts if stack had already been applied", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) const applyCommand = findByName(getTerraformCommands(), "apply-action")! @@ -998,7 +1018,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { }) it("should return outputs with the service status", async () => { - const provider = await garden.resolveProvider(garden.log, "terraform") + const provider = await garden.resolveProvider({ log: garden.log, name: "terraform" }) const ctx = await garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) graph = await garden.getConfigGraph({ log: garden.log, emit: false }) const applyCommand = findByName(getTerraformCommands(), "apply-action")! @@ -1041,7 +1061,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = await _garden.resolveProvider(_garden.log, "terraform") + const provider = await _garden.resolveProvider({ log: _garden.log, name: "terraform" }) const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const _graph = await _garden.getConfigGraph({ log: _garden.log, emit: false }) const applyCommand = findByName(getTerraformCommands(), "apply-action")! @@ -1175,7 +1195,7 @@ for (const terraformVersion of ["0.13.3", defaultTerraformVersion]) { plugins: [gardenPlugin()], }) - const provider = (await _garden.resolveProvider(_garden.log, "terraform")) as TerraformProvider + const provider = (await _garden.resolveProvider({ log: _garden.log, name: "terraform" })) as TerraformProvider const ctx = await _garden.getPluginContext({ provider, templateContext: undefined, events: undefined }) const actions = await _garden.getActionRouter() const _graph = await _garden.getConfigGraph({ log: _garden.log, emit: false })