pulumi/sdk/go/common/resource/plugin
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
..
analyzer.go Allow anything in resource names (#14107) 2023-11-20 08:59:00 +00:00
analyzer_plugin.go Refactor: move plugin kind to apitype (#15946) 2024-04-25 17:30:30 +00:00
check.go Enable importas linter (#15167) 2024-01-17 14:56:37 +00:00
config_source.go [breaking] Changing the version of go.mod in sdk / pkg to be v3 2021-04-14 19:32:18 +01:00
context.go Actually save root on plugin.Context (#14684) 2023-11-29 14:30:52 +00:00
context_test.go Fix data race in plugin.Context 2023-03-31 07:15:11 -07:00
converter.go Plumb Remote, Component, and LogicalName into the import plugin system (#15199) 2024-01-24 17:15:30 +00:00
converter_plugin.go Refactor: move plugin kind to apitype (#15946) 2024-04-25 17:30:30 +00:00
converter_plugin_test.go Plumb Remote, Component, and LogicalName into the import plugin system (#15199) 2024-01-24 17:15:30 +00:00
converter_server.go Plumb Remote, Component, and LogicalName into the import plugin system (#15199) 2024-01-24 17:15:30 +00:00
converter_server_test.go Plumb Remote, Component, and LogicalName into the import plugin system (#15199) 2024-01-24 17:15:30 +00:00
diagnostic.go Make language-python it's own module (#13819) 2023-08-31 16:35:21 +00:00
diagnostic_test.go Allow converter plugins to return diagnostics 2023-06-05 17:38:59 +01:00
doc.go Provider implementer's guide draft (#6322) 2021-04-13 14:11:02 -07:00
host.go Normalize plugin.Provider methods to (Context, Request) -> (Response, error) (#16302) 2024-06-07 19:47:49 +00:00
host_server.go Enable importas linter (#15167) 2024-01-17 14:56:37 +00:00
host_test.go Lock access to the plugin loading channels 2023-08-10 23:40:23 +01:00
langruntime.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
langruntime_plugin.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
langruntime_test.go Add not-found markers to missing executables for packagemanagers (#16488) 2024-06-28 23:21:55 +00:00
plugin.go Python parameterized provider test (#16491) 2024-07-16 10:55:38 +00:00
plugin_test.go Revert "resource/plugin: Shut down plugins gracefully (#13795)" (#13844) 2023-08-31 16:29:55 +00:00
provider.go Python parameterized provider test (#16491) 2024-07-16 10:55:38 +00:00
provider_plugin.go Python parameterized provider test (#16491) 2024-07-16 10:55:38 +00:00
provider_plugin_test.go Test provider `Delete` parameter marshalling (#16645) 2024-07-12 11:19:32 +00:00
provider_server.go Set `Parameterize.Value` in `plugin.Provider` (#16726) 2024-07-20 09:15:33 +00:00
provider_server_test.go Normalize plugin.Provider methods to (Context, Request) -> (Response, error) (#16302) 2024-06-07 19:47:49 +00:00
provider_test.go Fix PropertyPaths generated by NewDetailedDiffFromObjectDiff (#14337) 2023-10-25 10:39:03 +00:00
provider_unimplemented.go Normalize plugin.Provider methods to (Context, Request) -> (Response, error) (#16302) 2024-06-07 19:47:49 +00:00
rpc.go Add asset/archive to conformance tests and fix engine working dir issues (#16100) 2024-05-02 11:32:54 +00:00
rpc_rapid_test.go Remove deprecated Protobufs imports (#15158) 2024-01-17 09:35:20 +00:00
rpc_test.go Fix upgrade with ResourceReference (#15377) 2024-02-06 08:22:46 +00:00
server.go Add mapping service to converter 2023-03-24 17:09:17 +00:00