Skip to content

Commit

Permalink
fix(pulumi): use correct template context
Browse files Browse the repository at this point in the history
This fixes an oversight in the logic around Pulumi plugin commands where
we forgot to create a new plugin context with a template context
specific to the module being processed by Pulumi plugin commands.
  • Loading branch information
thsig committed Oct 4, 2022
1 parent d4f6885 commit 475862e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 41 deletions.
20 changes: 6 additions & 14 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ Examples:
| `--local-mode` | `-local` | array:string | [EXPERIMENTAL] The name(s) of the service(s) to be started locally with local mode enabled. Use comma as a separator to specify multiple services. Use * to deploy all services with local mode enabled. When this option is used, the command is run in persistent mode.
This always takes the precedence over the dev mode if there are any conflicts, i.e. if the same services are passed to both `--dev` and `--local` options.
| `--skip` | | array:string | The name(s) of services you'd like to skip when deploying.
| `--skip-dependencies` | `-nodeps` | boolean | Deploy the specified services, but don't deploy any additional services that they depend on or run any tasks that they depend on. This option can only be used when a list of service names is passed as CLI arguments. This can be useful e.g. when your stack has already been deployed, and you want to deploy a subset of services in dev mode without redeploying any service dependencies that may have changed since you last deployed.
| `--skip-dependencies` | `-no-deps` | boolean | Deploy the specified services, but don't deploy any additional services that they depend on or run any tasks that they depend on. This option can only be used when a list of service names is passed as CLI arguments. This can be useful e.g. when your stack has already been deployed, and you want to deploy a subset of services in dev mode without redeploying any service dependencies that may have changed since you last deployed.
| `--forward` | | boolean | Create port forwards and leave process running without watching for changes. Ignored if --watch/-w flag is set or when in dev or hot-reload mode.

#### Outputs
Expand Down Expand Up @@ -3493,7 +3493,7 @@ Examples:
| `--force-build` | | boolean | Force rebuild of module(s).
| `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-test.
| `--skip` | | array:string | The name(s) of tests you'd like to skip. Accepts glob patterns (e.g. integ* would skip both 'integ' and 'integration'). Applied after the 'name' filter.
| `--skip-dependencies` | `-nodeps` | boolean | Don't deploy any services or run any tasks that the requested tests depend on. This can be useful e.g. when your stack has already been deployed, and you want to run tests with runtime dependencies without redeploying any service dependencies that may have changed since you last deployed. Warning: Take great care when using this option in CI, since Garden won't ensure that the runtime dependencies of your test suites are up to date when this option is used.
| `--skip-dependencies` | `-no-deps` | boolean | Don't deploy any services or run any tasks that the requested tests depend on. This can be useful e.g. when your stack has already been deployed, and you want to run tests with runtime dependencies without redeploying any service dependencies that may have changed since you last deployed. Warning: Take great care when using this option in CI, since Garden won't ensure that the runtime dependencies of your test suites are up to date when this option is used.
| `--skip-dependants` | | boolean | When using the modules argument, only run tests for those modules (and skip tests in other modules with dependencies on those modules).

#### Outputs
Expand Down Expand Up @@ -3794,25 +3794,19 @@ Updates the remote sources declared in the project level `garden.yml` config fil

Examples:

garden update-remote sources --parallel # update all remote sources in parallel mode
garden update-remote sources # update all remote sources
garden update-remote sources my-source # update remote source my-source

#### Usage

garden update-remote sources [sources] [options]
garden update-remote sources [sources]

#### Arguments

| Argument | Required | Description |
| -------- | -------- | ----------- |
| `sources` | No | The name(s) of the remote source(s) to update. Use comma as a separator to specify multiple sources.

#### Options

| Argument | Alias | Type | Description |
| -------- | ----- | ---- | ----------- |
| `--parallel` | | boolean | Allow git updates to happen in parallel. This will automatically reject any Git prompt, such as username / password.

#### Outputs

Expand All @@ -3836,7 +3830,6 @@ in their `garden.yml` config that points to a remote repository.

Examples:

garden update-remote modules --parallel # update all remote modules in parallel mode
garden update-remote modules # update all remote modules in the project
garden update-remote modules my-module # update remote module my-module

Expand All @@ -3854,7 +3847,7 @@ Examples:

| Argument | Alias | Type | Description |
| -------- | ----- | ---- | ----------- |
| `--parallel` | | boolean | Allow git updates to happen in parallel. This will automatically reject any Git prompt, such as username / password.
| `--parallel` | | boolean | Allow git updates to happen in parallel. This will automatically reject any Git prompt, such as username / password

#### Outputs

Expand All @@ -3875,8 +3868,7 @@ sources:

Examples:

garden update-remote all --parallel # update all remote sources and modules in the project in parallel mode
garden update-remote all # update all remote sources and modules in the project
garden update-remote all # update all remote sources and modules in the project

#### Usage

Expand All @@ -3886,7 +3878,7 @@ Examples:

| Argument | Alias | Type | Description |
| -------- | ----- | ---- | ----------- |
| `--parallel` | | boolean | Allow git updates to happen in parallel. This will automatically reject any Git prompt, such as username / password.
| `--parallel` | | boolean | Allow git updates to happen in parallel

#### Outputs

Expand Down
6 changes: 3 additions & 3 deletions docs/reference/providers/pulumi.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ providers:

The version of pulumi to use. Set to `null` to use whichever version of `pulumi` is on your PATH.

| Type | Allowed Values | Default | Required |
| -------- | ------------------------ | ---------- | -------- |
| `string` | "3.25.1", "3.24.1", null | `"3.25.1"` | Yes |
| Type | Allowed Values | Default | Required |
| -------- | ---------------------------------- | ---------- | -------- |
| `string` | "3.40.0", "3.39.4", "3.25.1", null | `"3.40.0"` | Yes |

### `providers[].previewDir`

Expand Down
54 changes: 30 additions & 24 deletions plugins/pulumi/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,27 @@ const pulumiCommandSpecs: PulumiCommandSpec[] = [
},
]

const makePluginContextForService = async (
params: PulumiParamsWithService & { garden: Garden; graph: ConfigGraph }
) => {
const { log, garden, graph, service, provider, ctx } = params
const allProviders = await garden.resolveProviders(log)
const allModules = graph.getModules()
const templateContext = ModuleConfigContext.fromModule({
garden,
resolvedProviders: allProviders,
module: service.module,
modules: allModules,
partialRuntimeResolution: false,
})
const ctxForService = await garden.getPluginContext(provider, templateContext, ctx.events)
return ctxForService
}

interface PulumiPluginCommandTaskParams {
garden: Garden
graph: ConfigGraph
log: LogEntry
service: GardenService
commandName: string
commandDescription: string
runFn: PulumiRunFn
Expand All @@ -180,7 +196,6 @@ interface PulumiPluginCommandTaskParams {
class PulumiPluginCommandTask extends PluginTask {
graph: ConfigGraph
pulumiParams: PulumiParamsWithService
service: GardenService
commandName: string
commandDescription: string
runFn: PulumiRunFn
Expand All @@ -189,15 +204,13 @@ class PulumiPluginCommandTask extends PluginTask {
garden,
graph,
log,
service,
commandName,
commandDescription,
runFn,
pulumiParams,
}: PulumiPluginCommandTaskParams) {
super({ garden, log, force: false, version: service.version })
super({ garden, log, force: false, version: pulumiParams.service.version })
this.graph = graph
this.service = service
this.commandName = commandName
this.commandDescription = commandDescription
this.runFn = runFn
Expand All @@ -207,17 +220,17 @@ class PulumiPluginCommandTask extends PluginTask {
}

getName() {
return this.service.name
return this.pulumiParams.service.name
}

getDescription(): string {
return `running ${chalk.white(this.commandName)} for ${this.service.name}`
return `running ${chalk.white(this.commandName)} for ${this.pulumiParams.service.name}`
}

async resolveDependencies() {
// We process any build dependencies, since by default we don't have a build step for plugin tasks.
const buildDeps = flatten(
await Bluebird.map(Object.values(this.service.module.buildDependencies), async (depModule) => {
await Bluebird.map(Object.values(this.pulumiParams.service.module.buildDependencies), async (depModule) => {
return BuildTask.factory({
garden: this.garden,
graph: this.graph,
Expand All @@ -243,11 +256,10 @@ class PulumiPluginCommandTask extends PluginTask {
garden: this.garden,
graph: this.graph,
log: this.log,
service: depService,
commandName: this.commandName,
commandDescription: this.commandDescription,
runFn: this.runFn,
pulumiParams: { ...this.pulumiParams, module: depService.module },
pulumiParams: { ...this.pulumiParams, module: depService.module, service: depService },
})
})
return [...buildDeps, ...deployDeps]
Expand All @@ -261,7 +273,13 @@ class PulumiPluginCommandTask extends PluginTask {
})
try {
await selectStack(this.pulumiParams)
const result = await this.runFn(this.pulumiParams)
// We need to make sure that the template resolution context is specific to this service's module.
const ctxForService = await makePluginContextForService({
...this.pulumiParams,
garden: this.garden,
graph: this.graph,
})
const result = await this.runFn({ ...this.pulumiParams, ctx: ctxForService })
log.setSuccess({
msg: chalk.green(`Success (took ${log.getDuration(1)} sec)`),
})
Expand Down Expand Up @@ -299,23 +317,12 @@ function makePulumiCommand({ name, commandDescription, beforeFn, runFn, afterFn

beforeFn && (await beforeFn({ ctx, log }))

const allProviders = await garden.resolveProviders(log)
const allModules = graph.getModules()

const provider = ctx.provider as PulumiProvider
const services = graph.getServices({ names: serviceNames }).filter((s) => s.module.type === "pulumi")

const tasks = await Bluebird.map(services, async (service) => {
const templateContext = ModuleConfigContext.fromModule({
garden,
resolvedProviders: allProviders,
module: service.module,
modules: allModules,
partialRuntimeResolution: false,
})
const ctxForModule = await garden.getPluginContext(provider, templateContext, ctx.events)
const pulumiParams: PulumiParamsWithService = {
ctx: ctxForModule,
ctx,
provider,
log,
module: <PulumiModule>service.module,
Expand All @@ -327,7 +334,6 @@ function makePulumiCommand({ name, commandDescription, beforeFn, runFn, afterFn
garden,
graph,
log,
service,
commandName: name,
commandDescription,
runFn,
Expand Down

0 comments on commit 475862e

Please sign in to comment.