From e77fc0a961c8fa827b3c09850571248fdab0196e Mon Sep 17 00:00:00 2001 From: evanboyle Date: Fri, 2 Oct 2020 14:29:47 -0700 Subject: [PATCH] only expose static create methods (and overloads) for Stack and LocalWorkspace --- .../tests/automation/localWorkspace.spec.ts | 44 ++-- sdk/nodejs/tests/testmode.spec.ts | 2 +- sdk/nodejs/x/automation/localWorkspace.ts | 215 ++++++++---------- sdk/nodejs/x/automation/stack.ts | 57 +++-- sdk/nodejs/x/automation/workspace.ts | 15 +- 5 files changed, 152 insertions(+), 181 deletions(-) diff --git a/sdk/nodejs/tests/automation/localWorkspace.spec.ts b/sdk/nodejs/tests/automation/localWorkspace.spec.ts index 202680621..74dedebcd 100644 --- a/sdk/nodejs/tests/automation/localWorkspace.spec.ts +++ b/sdk/nodejs/tests/automation/localWorkspace.spec.ts @@ -25,7 +25,7 @@ import { asyncTest } from "../util"; describe("LocalWorkspace", () => { it(`projectSettings from yaml/yml/json`, asyncTest(async () => { for (const ext of ["yaml", "yml", "json"]) { - const ws = new LocalWorkspace({ workDir: upath.joinSafe(__dirname, "data", ext) }); + const ws = await LocalWorkspace.create({ workDir: upath.joinSafe(__dirname, "data", ext) }); const settings = await ws.projectSettings(); assert(settings.name, "testproj"); assert(settings.runtime.name, "go"); @@ -36,7 +36,7 @@ describe("LocalWorkspace", () => { it(`stackSettings from yaml/yml/json`, asyncTest(async () => { for (const ext of ["yaml", "yml", "json"]) { - const ws = new LocalWorkspace({ workDir: upath.joinSafe(__dirname, "data", ext) }); + const ws = await LocalWorkspace.create({ workDir: upath.joinSafe(__dirname, "data", ext) }); const settings = await ws.stackSettings("dev"); assert.equal(settings.secretsProvider, "abc"); assert.equal(settings.config!["plain"].value, "plain"); @@ -48,24 +48,22 @@ describe("LocalWorkspace", () => { const projectSettings = new ProjectSettings(); projectSettings.name = "node_test"; projectSettings.runtime.name = "nodejs"; - const ws = new LocalWorkspace({ projectSettings }); - await ws.ready; + const ws = await LocalWorkspace.create({ projectSettings }); const stackName = `int_test${getTestSuffix()}`; await ws.createStack(stackName); await ws.selectStack(stackName); await ws.removeStack(stackName); })); - it(`Create/Select/Upsert Stack`, asyncTest(async () => { + it(`create/select/createOrSelect Stack`, asyncTest(async () => { const projectSettings = new ProjectSettings(); projectSettings.name = "node_test"; projectSettings.runtime.name = "nodejs"; - const ws = new LocalWorkspace({ projectSettings }); - await ws.ready; + const ws = await LocalWorkspace.create({ projectSettings }); const stackName = `int_test${getTestSuffix()}`; - await Stack.Create(stackName, ws); - await Stack.Select(stackName, ws); - await Stack.Upsert(stackName, ws); + await Stack.create(stackName, ws); + await Stack.select(stackName, ws); + await Stack.createOrSelect(stackName, ws); await ws.removeStack(stackName); })); it(`Config`, asyncTest(async () => { @@ -73,10 +71,9 @@ describe("LocalWorkspace", () => { const projectSettings = new ProjectSettings(); projectSettings.name = projectName; projectSettings.runtime.name = "nodejs"; - const ws = new LocalWorkspace({ projectSettings }); - await ws.ready; + const ws = await LocalWorkspace.create({ projectSettings }); const stackName = `int_test${getTestSuffix()}`; - const stack = await Stack.Create(stackName, ws); + const stack = await Stack.create(stackName, ws); const config = { plain: { value: "abc" }, @@ -116,14 +113,13 @@ describe("LocalWorkspace", () => { const projectSettings = new ProjectSettings(); projectSettings.name = `node_list_test${getTestSuffix()}`; projectSettings.runtime.name = "nodejs"; - const ws = new LocalWorkspace({ projectSettings }); - await ws.ready; + const ws = await LocalWorkspace.create({ projectSettings }); const stackNamer = () => `int_test${getTestSuffix()}`; const stackNames: string[] = []; for (let i = 0; i < 2; i++) { const stackName = stackNamer(); stackNames[i] = stackName; - await Stack.Create(stackName, ws); + await Stack.create(stackName, ws); const stackSummary = await ws.stack(); assert.equal(stackSummary?.current, true); const stacks = await ws.listStacks(); @@ -138,10 +134,9 @@ describe("LocalWorkspace", () => { const projectSettings = new ProjectSettings(); projectSettings.name = "node_test"; projectSettings.runtime.name = "nodejs"; - const ws = new LocalWorkspace({ projectSettings }); - await ws.ready; + const ws = await LocalWorkspace.create({ projectSettings }); const stackName = `int_test${getTestSuffix()}`; - const stack = await Stack.Create(stackName, ws); + const stack = await Stack.create(stackName, ws); const histroy = await stack.history(); assert.equal(histroy.length, 0); const info = await stack.info(); @@ -151,7 +146,7 @@ describe("LocalWorkspace", () => { it(`runs through the stack lifecycle with a local program`, asyncTest(async () => { const stackName = `int_test${getTestSuffix()}`; const workDir = upath.joinSafe(__dirname, "data", "testproj"); - const stack = await LocalWorkspace.NewStackLocalSource(stackName, workDir); + const stack = await LocalWorkspace.createStack({ stackName, workDir }); const config: ConfigMap = { "bar": { value: "abc" }, @@ -188,16 +183,17 @@ describe("LocalWorkspace", () => { await stack.getWorkspace().removeStack(stackName); })); it(`runs through the stack lifecycle with an inline program`, asyncTest(async () => { - const program = () => { + const program = async () => { const config = new Config(); - return Promise.resolve({ + return { exp_static: "foo", exp_cfg: config.get("bar"), exp_secret: config.getSecret("buzz"), - }); + }; }; const stackName = `int_test${getTestSuffix()}`; - const stack = await LocalWorkspace.NewStackInlineSource(stackName, "inline_node", program); + const projectName = "inline_node"; + const stack = await LocalWorkspace.createStack({ stackName, projectName, program }); const stackConfig: ConfigMap = { "bar": { value: "abc" }, diff --git a/sdk/nodejs/tests/testmode.spec.ts b/sdk/nodejs/tests/testmode.spec.ts index bb946fccc..88b1c7cd6 100644 --- a/sdk/nodejs/tests/testmode.spec.ts +++ b/sdk/nodejs/tests/testmode.spec.ts @@ -13,8 +13,8 @@ // limitations under the License. import * as assert from "assert"; -import { Output } from "../output"; import { CustomResource } from "../index"; +import { Output } from "../output"; import * as runtime from "../runtime"; import { asyncTest } from "./util"; diff --git a/sdk/nodejs/x/automation/localWorkspace.ts b/sdk/nodejs/x/automation/localWorkspace.ts index 476a3ee5e..968c0f821 100644 --- a/sdk/nodejs/x/automation/localWorkspace.ts +++ b/sdk/nodejs/x/automation/localWorkspace.ts @@ -24,77 +24,78 @@ import { StackSettings } from "./stackSettings"; import { PulumiFn, StackSummary, Workspace } from "./workspace"; export class LocalWorkspace implements Workspace { - ready: Promise; - private workDir: string; - private pulumiHome?: string; - private program?: PulumiFn; - private envVars: { [key: string]: string }; - private secretsProvider?: string; - public static async NewStackLocalSource( - stackName: string, workDir: string, opts?: LocalWorkspaceOpts, - ): Promise { - return this.localSourceStackHelper(stackName, workDir, Stack.Create, opts); + readonly workDir: string; + readonly pulumiHome?: string; + readonly secretsProvider?: string; + public program?: PulumiFn; + public envVars: { [key: string]: string }; + private ready: Promise; + public static async create(opts: LocalWorkspaceOptions): Promise { + const ws = new LocalWorkspace(opts); + await ws.ready; + return ws; } - public static async UpsertStackLocalSource( - stackName: string, workDir: string, opts?: LocalWorkspaceOpts, - ): Promise { - return this.localSourceStackHelper(stackName, workDir, Stack.Upsert, opts); + public static async createStack(args: LocalProgramArgs, opts?: LocalWorkspaceOptions): Promise; + public static async createStack(args: InlineProgramArgs, opts?: LocalWorkspaceOptions): Promise; + public static async createStack(args: InlineProgramArgs | LocalProgramArgs, opts?: LocalWorkspaceOptions): Promise { + if (isInlineProgramArgs(args)) { + return await this.inlineSourceStackHelper(args, Stack.create, opts); + } else if (isLocalProgramArgs(args)) { + return await this.localSourceStackHelper(args, Stack.create, opts); + } + throw new Error(`unexpected args: ${args}`); } - public static async SelectStackLocalSource( - stackName: string, workDir: string, opts?: LocalWorkspaceOpts, - ): Promise { - return this.localSourceStackHelper(stackName, workDir, Stack.Select, opts); + public static async selectStack(args: LocalProgramArgs, opts?: LocalWorkspaceOptions): Promise; + public static async selectStack(args: InlineProgramArgs, opts?: LocalWorkspaceOptions): Promise; + public static async selectStack(args: InlineProgramArgs | LocalProgramArgs, opts?: LocalWorkspaceOptions): Promise { + if (isInlineProgramArgs(args)) { + return await this.inlineSourceStackHelper(args, Stack.select, opts); + } else if (isLocalProgramArgs(args)) { + return await this.localSourceStackHelper(args, Stack.select, opts); + } + throw new Error(`unexpected args: ${args}`); + } + public static async createOrSelectStack(args: LocalProgramArgs, opts?: LocalWorkspaceOptions): Promise; + public static async createOrSelectStack(args: InlineProgramArgs, opts?: LocalWorkspaceOptions): Promise; + public static async createOrSelectStack(args: InlineProgramArgs | LocalProgramArgs, opts?: LocalWorkspaceOptions): Promise { + if (isInlineProgramArgs(args)) { + return await this.inlineSourceStackHelper(args, Stack.createOrSelect, opts); + } else if (isLocalProgramArgs(args)) { + return await this.localSourceStackHelper(args, Stack.createOrSelect, opts); + } + throw new Error(`unexpected args: ${args}`); } private static async localSourceStackHelper( - stackName: string, workDir: string, initFn: stackInitFunc, opts?: LocalWorkspaceOpts, + args: LocalProgramArgs, initFn: stackInitializer, opts?: LocalWorkspaceOptions, ): Promise { - let wsOpts = { workDir }; + let wsOpts = { workDir: args.workDir }; if (opts) { - wsOpts = { ...opts, workDir }; + wsOpts = { ...opts, workDir: args.workDir }; } const ws = new LocalWorkspace(wsOpts); await ws.ready; - const stack = await initFn(stackName, ws); - - return Promise.resolve(stack); - } - public static async NewStackInlineSource( - stackName: string, projectName: string, program: PulumiFn, opts?: LocalWorkspaceOpts, - ): Promise { - return this.inlineSourceStackHelper(stackName, projectName, program, Stack.Create, opts); - } - public static async UpsertStackInlineSource( - stackName: string, projectName: string, program: PulumiFn, opts?: LocalWorkspaceOpts, - ): Promise { - return this.inlineSourceStackHelper(stackName, projectName, program, Stack.Upsert, opts); - } - public static async SelectStackInlineSource( - stackName: string, projectName: string, program: PulumiFn, opts?: LocalWorkspaceOpts, - ): Promise { - return this.inlineSourceStackHelper(stackName, projectName, program, Stack.Select, opts); + return await initFn(args.stackName, ws); } private static async inlineSourceStackHelper( - stackName: string, projectName: string, program: PulumiFn, initFn: stackInitFunc, opts?: LocalWorkspaceOpts, + args: InlineProgramArgs, initFn: stackInitializer, opts?: LocalWorkspaceOptions, ): Promise { - let wsOpts: LocalWorkspaceOpts = { program }; + let wsOpts: LocalWorkspaceOptions = { program: args.program }; if (opts) { - wsOpts = { ...opts, program }; + wsOpts = { ...opts, program: args.program }; } if (!wsOpts.projectSettings) { - wsOpts.projectSettings = defaultProject(projectName); + wsOpts.projectSettings = defaultProject(args.projectName); } const ws = new LocalWorkspace(wsOpts); await ws.ready; - const stack = await initFn(stackName, ws); - - return Promise.resolve(stack); + return await initFn(args.stackName, ws); } - constructor(opts?: LocalWorkspaceOpts) { + private constructor(opts?: LocalWorkspaceOptions) { let dir = ""; let envs = {}; @@ -135,11 +136,11 @@ export class LocalWorkspace implements Workspace { if (!fs.existsSync(path)) { continue; } const contents = fs.readFileSync(path).toString(); if (isJSON) { - return Promise.resolve(ProjectSettings.fromJSON(JSON.parse(contents))); + return ProjectSettings.fromJSON(JSON.parse(contents)); } - return Promise.resolve(ProjectSettings.fromYAML(contents)); + return ProjectSettings.fromYAML(contents); } - return Promise.reject(new Error(`failed to find project settings file in workdir: ${this.workDir}`)); + throw new Error(`failed to find project settings file in workdir: ${this.workDir}`); } async saveProjectSettings(settings: ProjectSettings): Promise { let foundExt = ".yaml"; @@ -158,7 +159,7 @@ export class LocalWorkspace implements Workspace { else { contents = settings.toYAML(); } - return Promise.resolve(fs.writeFileSync(path, contents)); + return fs.writeFileSync(path, contents); } async stackSettings(stackName: string): Promise { const stackSettingsName = getStackSettingsName(stackName); @@ -168,11 +169,11 @@ export class LocalWorkspace implements Workspace { if (!fs.existsSync(path)) { continue; } const contents = fs.readFileSync(path).toString(); if (isJSON) { - return Promise.resolve(StackSettings.fromJSON(JSON.parse(contents))); + return StackSettings.fromJSON(JSON.parse(contents)); } - return Promise.resolve(StackSettings.fromYAML(contents)); + return StackSettings.fromYAML(contents); } - return Promise.reject(new Error(`failed to find stack settings file in workdir: ${this.workDir}`)); + throw new Error(`failed to find stack settings file in workdir: ${this.workDir}`); } async saveStackSettings(settings: StackSettings, stackName: string): Promise { const stackSettingsName = getStackSettingsName(stackName); @@ -192,53 +193,37 @@ export class LocalWorkspace implements Workspace { else { contents = settings.toYAML(); } - return Promise.resolve(fs.writeFileSync(path, contents)); + return fs.writeFileSync(path, contents); } async createStack(stackName: string): Promise { const args = ["stack", "init", stackName]; if (this.secretsProvider) { args.push("--secrets-provider", this.secretsProvider); } - try { - const result = await this.runPulumiCmd(args); - return Promise.resolve(); - } catch (error) { - return Promise.reject(error); - } + await this.runPulumiCmd(args); } async selectStack(stackName: string): Promise { - try { - const result = await this.runPulumiCmd(["stack", "select", stackName]); - return Promise.resolve(); - } catch (error) { - return Promise.reject(error); - } + await this.runPulumiCmd(["stack", "select", stackName]); } async removeStack(stackName: string): Promise { - try { - const result = await this.runPulumiCmd(["stack", "rm", "--yes", stackName]); - return Promise.resolve(); - } catch (error) { - return Promise.reject(error); - } + await this.runPulumiCmd(["stack", "rm", "--yes", stackName]); } async getConfig(stackName: string, key: string): Promise { await this.selectStack(stackName); const result = await this.runPulumiCmd(["config", "get", key, "--json"]); const val = JSON.parse(result.stdout); - return Promise.resolve(val); + return val; } async getAllConfig(stackName: string): Promise { await this.selectStack(stackName); const result = await this.runPulumiCmd(["config", "--show-secrets", "--json"]); const val = JSON.parse(result.stdout); - return Promise.resolve(val); + return val; } async setConfig(stackName: string, key: string, value: ConfigValue): Promise { await this.selectStack(stackName); const secretArg = value.secret ? "--secret" : "--plaintext"; await this.runPulumiCmd(["config", "set", key, value.value, secretArg]); - return Promise.resolve(); } async setAllConfig(stackName: string, config: ConfigMap): Promise { const promises: Promise[] = []; @@ -246,74 +231,48 @@ export class LocalWorkspace implements Workspace { promises.push(this.setConfig(stackName, key, value)); } await Promise.all(promises); - return Promise.resolve(); } async removeConfig(stackName: string, key: string): Promise { await this.selectStack(stackName); await this.runPulumiCmd(["config", "rm", key]); - return Promise.resolve(); } async removeAllConfig(stackName: string, keys: string[]): Promise { const promises: Promise[] = []; for (const key of keys) { promises.push(this.removeConfig(stackName, key)); } - return Promise.resolve({}); + await Promise.all(promises); } async refreshConfig(stackName: string): Promise { await this.selectStack(stackName); await this.runPulumiCmd(["config", "refresh", "--force"]); return this.getAllConfig(stackName); } - getEnvVars(): { [key: string]: string } { - return this.envVars; - } - setEnvVars(envs: { [key: string]: string }): void { - this.envVars = { ...this.envVars, ...envs }; - } - setEnvVar(key: string, value: string): void { - this.envVars[key] = value; - } - unsetEnvVar(key: string): void { - delete this.envVars[key]; - } - getWorkDir(): string { - return this.workDir; - } - getPulumiHome(): string | undefined { - return this.pulumiHome; - } async whoAmI(): Promise { const result = await this.runPulumiCmd(["whoami"]); - return Promise.resolve(result.stdout.trim()); + return result.stdout.trim(); } async stack(): Promise { const stacks = await this.listStacks(); for (const stack of stacks) { if (stack.current) { - return Promise.resolve(stack); + return stack; } } - return Promise.resolve(undefined); + return undefined; } async listStacks(): Promise { const result = await this.runPulumiCmd(["stack", "ls", "--json"]); const stacks: StackSummary[] = JSON.parse(result.stdout); - return Promise.resolve(stacks); + return stacks; } - getProgram(): PulumiFn | undefined { - return this.program; - } - setProgram(program: PulumiFn): void { - this.program = program; - } - serializeArgsForOp(_: string): Promise { + async serializeArgsForOp(_: string): Promise { // LocalWorkspace does not take advantage of this extensibility point. - return Promise.resolve([]); + return []; } - postCommandCallback(_: string): Promise { + async postCommandCallback(_: string): Promise { // LocalWorkspace does not take advantage of this extensibility point. - return Promise.resolve(); + return; } private async runPulumiCmd( args: string[], @@ -322,12 +281,23 @@ export class LocalWorkspace implements Workspace { if (this.pulumiHome) { envs["PULUMI_HOME"] = this.pulumiHome; } - envs = { ...envs, ...this.getEnvVars() }; + envs = { ...envs, ...this.envVars }; return runPulumiCmd(args, this.workDir, envs); } } -export type LocalWorkspaceOpts = { +export interface InlineProgramArgs { + stackName: string; + projectName: string; + program: PulumiFn; +} + +export interface LocalProgramArgs { + stackName: string; + workDir: string; +} + +export type LocalWorkspaceOptions = { workDir?: string, pulumiHome?: string, program?: PulumiFn, @@ -337,21 +307,30 @@ export type LocalWorkspaceOpts = { stackSettings?: { [key: string]: StackSettings }, }; +function isLocalProgramArgs(args: LocalProgramArgs | InlineProgramArgs): args is LocalProgramArgs { + return (args as LocalProgramArgs).workDir !== undefined; +} + +function isInlineProgramArgs(args: LocalProgramArgs | InlineProgramArgs): args is InlineProgramArgs { + return (args as InlineProgramArgs).projectName !== undefined && + (args as InlineProgramArgs).program !== undefined; +} + export const settingsExtensions = [".yaml", ".yml", ".json"]; -const getStackSettingsName = (name: string): string => { +function getStackSettingsName(name: string): string { const parts = name.split("/"); if (parts.length < 1) { return name; } return parts[parts.length - 1]; -}; +} -type stackInitFunc = (name: string, workspace: Workspace) => Promise; +type stackInitializer = (name: string, workspace: Workspace) => Promise; -const defaultProject = (projectName: string) => { +function defaultProject(projectName: string) { const settings = new ProjectSettings(); settings.name = projectName; settings.runtime.name = "nodejs"; return settings; -}; +} diff --git a/sdk/nodejs/x/automation/stack.ts b/sdk/nodejs/x/automation/stack.ts index f856639b8..a4b14508e 100644 --- a/sdk/nodejs/x/automation/stack.ts +++ b/sdk/nodejs/x/automation/stack.ts @@ -21,28 +21,26 @@ import { PulumiFn, Workspace } from "./workspace"; const langrpc = require("../../proto/language_grpc_pb.js"); -export type StackInitMode = "create" | "select" | "upsert"; - export class Stack { - ready: Promise; - private name: string; - private workspace: Workspace; - public static async Create(name: string, workspace: Workspace): Promise { + readonly name: string; + readonly workspace: Workspace; + private ready: Promise; + public static async create(name: string, workspace: Workspace): Promise { const stack = new Stack(name, workspace, "create"); await stack.ready; - return Promise.resolve(stack); + return stack; } - public static async Select(name: string, workspace: Workspace): Promise { + public static async select(name: string, workspace: Workspace): Promise { const stack = new Stack(name, workspace, "select"); await stack.ready; - return Promise.resolve(stack); + return stack; } - public static async Upsert(name: string, workspace: Workspace): Promise { - const stack = new Stack(name, workspace, "upsert"); + public static async createOrSelect(name: string, workspace: Workspace): Promise { + const stack = new Stack(name, workspace, "createOrSelect"); await stack.ready; - return Promise.resolve(stack); + return stack; } - constructor(name: string, workspace: Workspace, mode: StackInitMode) { + private constructor(name: string, workspace: Workspace, mode: StackInitMode) { this.name = name; this.workspace = workspace; @@ -53,7 +51,7 @@ export class Stack { case "select": this.ready = workspace.selectStack(name); return this; - case "upsert": + case "createOrSelect": // TODO update this based on structured errors (check for 409) this.ready = workspace.createStack(name).catch(() => { return workspace.selectStack(name); @@ -66,7 +64,7 @@ export class Stack { async up(opts?: UpOptions): Promise { const args = ["up", "--yes", "--skip-preview"]; let kind = execKind.local; - let program: PulumiFn | undefined = this.workspace.getProgram(); + let program = this.workspace.program; await this.workspace.selectStack(this.name); if (opts) { @@ -133,13 +131,13 @@ export class Stack { summary: status[0]!, outputs: status[1]!, }; - return Promise.resolve(result); + return result; } async preview(opts?: PreviewOptions): Promise { // TODO JSON const args = ["preview"]; let kind = execKind.local; - let program: PulumiFn | undefined = this.workspace.getProgram(); + let program = this.workspace.program; await this.workspace.selectStack(this.name); if (opts) { @@ -205,7 +203,7 @@ export class Stack { stderr: preResult.stderr, summary: summary!, }; - return Promise.resolve(result); + return result; } async refresh(opts?: RefreshOptions): Promise { const args = ["refresh", "--yes", "--skip-preview"]; @@ -235,7 +233,7 @@ export class Stack { stderr: refResult.stderr, summary: summary!, }; - return Promise.resolve(result); + return result; } async destroy(opts?: DestroyOptions): Promise { const args = ["destroy", "--yes", "--skip-preview"]; @@ -265,7 +263,7 @@ export class Stack { stderr: preResult.stderr, summary: summary!, }; - return Promise.resolve(result); + return result; } getName(): string { return this.name; } getWorkspace(): Workspace { return this.workspace; } @@ -304,34 +302,33 @@ export class Stack { outputs[key] = { value, secret }; } - return Promise.resolve(outputs); + return outputs; } async history(): Promise { const result = await this.runPulumiCmd(["history", "--json", "--show-secrets"]); const summaries: UpdateSummary[] = JSON.parse(result.stdout); - return Promise.resolve(summaries); + return summaries; } async info(): Promise { const history = await this.history(); if (!history || history.length === 0) { - return Promise.resolve(undefined); + return undefined; } - return Promise.resolve(history[0]); + return history[0]; } private async runPulumiCmd(args: string[], onOutput?: (out: string) => void): Promise { const ws = this.getWorkspace(); let envs: { [key: string]: string } = {}; - const pulumiHome = ws.getPulumiHome(); + const pulumiHome = ws.pulumiHome; if (pulumiHome) { envs["PULUMI_HOME"] = pulumiHome; } - const additionalEnvs = await ws.getEnvVars(); - envs = { ...envs, ...additionalEnvs }; + envs = { ...envs, ...ws.envVars }; const additionalArgs = await ws.serializeArgsForOp(this.name); args = [...args, ...additionalArgs]; - const result = await runPulumiCmd(args, ws.getWorkDir(), envs, onOutput); + const result = await runPulumiCmd(args, ws.workDir, envs, onOutput); await ws.postCommandCallback(this.name); - return Promise.resolve(result); + return result; } } @@ -440,3 +437,5 @@ const execKind = { local: "auto.local", inline: "auto.inline", }; + +type StackInitMode = "create" | "select" | "createOrSelect"; diff --git a/sdk/nodejs/x/automation/workspace.ts b/sdk/nodejs/x/automation/workspace.ts index 30431bfd8..bfe9aea36 100644 --- a/sdk/nodejs/x/automation/workspace.ts +++ b/sdk/nodejs/x/automation/workspace.ts @@ -17,6 +17,11 @@ import { ProjectSettings } from "./projectSettings"; import { StackSettings } from "./stackSettings"; export interface Workspace { + readonly workDir: string; + readonly pulumiHome?: string; + readonly secretsProvider?: string; + program?: PulumiFn; + envVars: { [key: string]: string }; projectSettings(): Promise; saveProjectSettings(settings: ProjectSettings): Promise; stackSettings(stackName: string): Promise; @@ -30,20 +35,12 @@ export interface Workspace { removeConfig(stackName: string, key: string): Promise; removeAllConfig(stackName: string, keys: string[]): Promise; refreshConfig(stackName: string): Promise; - getEnvVars(): { [key: string]: string }; - setEnvVars(envs: { [key: string]: string }): void; - setEnvVar(key: string, value: string): void; - unsetEnvVar(key: string): void; - getWorkDir(): string; - getPulumiHome(): string | undefined; whoAmI(): Promise; stack(): Promise; createStack(stackName: string): Promise; selectStack(stackName: string): Promise; removeStack(stackName: string): Promise; listStacks(): Promise; - getProgram(): PulumiFn | undefined; - setProgram(program: PulumiFn): void; // TODO import/export } @@ -56,4 +53,4 @@ export type StackSummary = { url?: string, }; -export type PulumiFn = () => Promise; +export type PulumiFn = () => Promise | void>;