mirror of https://github.com/pulumi/pulumi.git
8314293d6e
When executing a `--target`ed operation, Pulumi considers all providers to be "implicitly targeted", whether their URNs are mentioned or not. As a result, *all* Pulumi operations update provider resources, `--target`ed or not. This can lead to some tricky scenarios that Pulumi needs to handle or detect in order not to break the user's program or state. One such case is where a user tries to alter the provider of an untargeted resource. Consider the following starting program/state: ```typescript const parent = new sdk.Component("parent") const provider = new sdk.Provider("provider") const resource = new sdk.Resource("resource", { provider }) ``` Let us modify the program so that `provider` becomes a child of `parent`. In doing so, `provider`'s URN will be changed on the next update to include `parent`'s type (so e.g. `provider` will become something akin to `parent$provider`): ```typescript const parent = new sdk.Component("parent") const provider = new sdk.Provider("provider", { parent }) const resource = new sdk.Resource("resource", { provider }) ``` Now we run `pulumi up --target "**non-existent**"`. That is, we specify a target glob that will not target *any* of the resources in the program. Our update will proceed as follows: * A resource registration for `parent` is sent. `parent` is not targeted (it is not matched by the `--target` glob, and it is not a provider resource), so we emit a `SameStep` for it to copy it unchanged from the old state to the new state. * A resource registration for `provider` is sent, with a parent of `parent`. This resource *is* targeted since it is a provider, and thus is implicitly targeted. Pulumi constructs the URN `parent$provider` for the provider resource and looks to see if there is any old state for it. * Pulumi finds no old state (the existing provider state is registered under the URN `provider` [no `parent$`]) and so decides that `provider` must be `Create`d. It emits a `CreateStep` and moves on. * A resource registration for `resource` is sent. `resource` is not targeted (it is not matched by the `--target` glob, and it is not a provider resource), so we want to emit a `SameStep` for it to copy it unchanged from the old state to the new state. * *However*, as part of checking whether we can emit a `SameStep` for resource, we find that it references a provider that we have not seen a registration for (`provider` -- recall that we have only seen `parent$provider`). We thus abort with an error informing the user that they have to run an untargeted update to update their provider before targeted updates can proceed. If the user genuinely wants to rename the provider, and not actually delete the old one and create a new one whose parent happens to be `parent`, they can of course use an alias: ```typescript const parent = new sdk.Component("parent") const provider = new sdk.Provider( "provider", { parent, aliases: [new Alias({ parent: undefined })], } ) const resource = new sdk.Resource("resource", { provider }) ``` At least, that's what they might expect. Presently, attempting to do this will yield a `panic`, neither tripping the existing error machinery, nor successfully completing the `--target`ed operation. This commit fixes this panic by making it work. We'd previously considered making this case trigger the existing "no provider exists" error flow, but this is not in fact correct -- in the case an alias is supplied, the provider *does* exist and we should be able to find it and complete the rename. Here we make that so. Fixes #17719 |
||
---|---|---|
.. | ||
deploytest | ||
providers | ||
builtins.go | ||
builtins_test.go | ||
deployment.go | ||
deployment_executor.go | ||
deployment_executor_test.go | ||
deployment_test.go | ||
doc.go | ||
import.go | ||
import_test.go | ||
manifest.go | ||
manifest_test.go | ||
plan.go | ||
plan_test.go | ||
snapshot.go | ||
snapshot_test.go | ||
source.go | ||
source_error.go | ||
source_error_test.go | ||
source_eval.go | ||
source_eval_test.go | ||
source_null.go | ||
source_query.go | ||
source_query_test.go | ||
state_builder.go | ||
state_builder_test.go | ||
step.go | ||
step_executor.go | ||
step_executor_test.go | ||
step_generator.go | ||
step_generator_test.go | ||
step_test.go | ||
target.go | ||
target_test.go |