pulumi/pkg/codegen/pcl
Zaid Ajaj b3546c9fa4
[cli/import] Fix undefined variable errors in code generation when imported resources use a parent or provider (#16786)
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,
});
```
2024-07-25 13:53:44 +00:00
..
binder.go Clean up uses of .Error() (#14965) 2023-12-20 15:54:06 +00:00
binder_component.go fix: close files in PCL binder (#15961) 2024-05-07 23:36:10 +00:00
binder_nodes.go Allow null literal as a default value for config variables 2023-05-04 00:38:38 +02:00
binder_resource.go Add support for `DeletedWith` to `pulumi convert` (#12011) 2024-07-19 14:17:45 +00:00
binder_resource_test.go pcl/options: Support retainOnDelete 2023-03-03 10:29:59 -08:00
binder_schema.go [docs] Fix generating constructor examples for resources that have numeric enums as input (#16223) 2024-05-30 22:43:12 +00:00
binder_schema_test.go all: Assert => Assertf 2023-03-03 14:37:43 -08:00
binder_test.go [cli/import] Fix undefined variable errors in code generation when imported resources use a parent or provider (#16786) 2024-07-25 13:53:44 +00:00
component.go lint 2023-07-27 16:32:06 +02:00
config.go Implement description as comments or docstring for config variables in program-gen 2023-03-21 15:01:16 +01:00
diagnostics.go Extend SkipResourceTypechecking to allow generating unknown resources 2023-06-14 19:02:56 +02:00
functions.go Add StackReference conformance test (#15935) 2024-04-16 11:13:25 +00:00
functions_test.go [program-gen] Fix stack overflow when binding invoke that resolves to promise (#15463) 2024-02-20 15:49:08 +00:00
intrinsics.go all: Assert => Assertf 2023-03-03 14:37:43 -08:00
invoke.go Update golangci-lint (#14624) 2023-11-21 15:16:13 +00:00
local.go Do not panic when the type of PCL local variable isn't known 2023-04-13 20:05:16 +02:00
output.go codegen: preserve externally visible names of a resources and outputs (#9464) 2022-04-25 15:07:25 -07:00
program.go Use slice.Prealloc instead of make([]T, 0, ...) 2023-06-29 11:27:50 +01:00
resource.go Add support for `DeletedWith` to `pulumi convert` (#12011) 2024-07-19 14:17:45 +00:00
rewrite_apply.go Vendor the inflector library (#16421) 2024-06-20 09:04:33 +00:00
rewrite_apply_test.go [program-gen] Emit Output-returning JSON serialization methods without rewriting applies (#15371) 2024-02-20 15:48:46 +00:00
rewrite_convert.go [program-gen] Fix enum resolution from types of the form Union[string, Enum] and emit fully qualified enum cases (#15696) 2024-03-15 17:49:12 +00:00
rewrite_convert_test.go Fixes panic when generating go from pulumi yaml (#10047) 2022-07-07 13:15:47 -07:00
rewrite_properties.go all: Assert => Assertf 2023-03-03 14:37:43 -08:00
type.go [codegen] simplify opaque types to string newtype (#9770) 2022-06-13 11:13:03 -07:00
utilities.go lint 2023-07-28 20:47:36 +02:00
utilities_test.go lint 2023-05-25 22:16:00 +02:00