mirror of https://github.com/pulumi/pulumi.git
b3546c9fa4
Fixes #15410 Fixes #13339 ## Problem Context When using `pulumi import` we generate code snippets for the resources that were imported. Sometimes the user specifies `--parent parentName=URN` or `--provider providerName=URN` which tweak the parent or provider that the imported resources uses. When using `--parent` or `--provider` the generated code emits a resource option `parent = parentName` (in case of using `--parent`) where `parentName` is an unbound variable. Usually unbound variables would result in a _bind_ error such as `error: undefined variable parentName` when type-checking the program however in the import code generation we specify the bind option `pcl.AllowMissingVariables` which turns that unbound variable errors into warnings and code generation can continue to emit code. This is all good and works as expected. However in the issues linked above, we do get an _error_ for unbound variables in generated code even though we specified `AllowMissingVariables`. The problem as it turns out is when we are trying to generate code via dynamically loaded `LangaugeRuntime` plugins. Specifically for NodeJS and Python, we load `pulumi-language-nodejs` or `pulumi-language-python` and call `GenerateProgram` to get the generated program. That function `GenerateProgram` takes the text _SOURCE_ of the a bound program (one that was bound using option `AllowMissingVariables`) and re-binds again inside the implementation of the language plugin. The second time we bind the program, we don't pass it the option `AllowMissingVariables` and so it fails with `unboud variable` error. I've verified that the issue above don't repro when doing an import for dotnet (probably same for java/yaml) because we use the statically linked function `codegen/{lang}/gen_program.go -> GenerateProgram` ## Solution The problem can be solved by propagating the bind options from the CLI to the language hosts during import so that they know how to bind the program. I've extended the gRPC interface in `GenerateProgramRequest` with a property `Strict` which follows the same logic from `pulumi convert --strict` and made it such that the import command sends `strict=false` to the language plugins when doing `GenerateProgram`. This is consistent with `GenerateProject` that uses the same flag. When `strict=false` we use `pcl.NonStrictBindOptions()` which includes `AllowMissingVariables` . ## Repro Once can test the before and after behaviour by running `pulumi up --yes` on the following TypeScript program: ```ts import * as pulumi from "@pulumi/pulumi"; import * as random from "@pulumi/random"; export class MyComponent extends pulumi.ComponentResource { public readonly randomPetId: pulumi.Output<string>; constructor(name: string, opts?: pulumi.ComponentResourceOptions) { super("example:index:MyComponent", name, {}, opts); const randomPet = new random.RandomPet("randomPet", {}, { parent: this }); this.randomPetId = randomPet.id; this.registerOutputs({ randomPetId: randomPet.id, }); } } const example = new MyComponent("example"); export const randomPetId = example.randomPetId; ``` Then running `pulumi import -f import.json` where `import.json` contains a resource to be imported under the created component (stack=`dev`, project=`importerrors`) ```ts { "nameTable": { "parentComponent": "urn:pulumi:dev::importerrors::example:index:MyComponent::example" }, "resources": [ { "type": "random:index/randomPassword:RandomPassword", "name": "randomPassword", "id": "supersecret", "parent": "parentComponent" } ] } ``` Running this locally I get the following generated code (which previously failed to generate) ```ts import * as pulumi from "@pulumi/pulumi"; import * as random from "@pulumi/random"; const randomPassword = new random.RandomPassword("randomPassword", { length: 11, lower: true, number: true, numeric: true, special: true, upper: true, }, { parent: parentComponent, }); ``` |
||
---|---|---|
.. | ||
testdata | ||
hcl2.go | ||
hcl2_test.go | ||
language.go | ||
language_test.go |