pulumi/sdk/go/common/resource/alias.go

57 lines
1.6 KiB
Go
Raw Permalink Normal View History

// Copyright 2022-2024, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package resource
import (
"fmt"
"strings"
)
type Alias struct {
[engine] Fix aliasing children There is an issue with how the engine computes the aliases when the resource is a child and doesn't have `Parent` set on the alias spec (and the parent doesn't have any aliases). ```python class FooResource(pulumi.ComponentResource): def __init__(self, name, opts=None): super().__init__("my:module:FooResource", name, None, opts) class ComponentResource(pulumi.ComponentResource): def __init__(self, name, opts=None): super().__init__("my:module:ComponentResource", name, None, opts) FooResource("childrenamed", pulumi.ResourceOptions( parent=self, aliases=[pulumi.Alias(name="child")] )) ``` In the example above, `ComponentResource` has a child `FooResource` which was renamed from `child` to `childrenamed`. The engine does not compute the correct alias: ``` expected: urn:pulumi:stack::project::my:module:ComponentResource$my:module:FooResource::child actual: urn:pulumi:stack::project::my:module:FooResource::child ``` The problem is due to: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/pkg/resource/deploy/step_generator.go#L370-L382 ... and: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/sdk/go/common/resource/alias.go#L24-L26 Because the alias spec doesn't have `parent` specified, the parent type is not being included the computed alias URN. Existing tests such as https://github.com/pulumi/pulumi/tree/master/tests/integration/aliases/python/rename_component_and_child didn't catch the problem because the alias specifies both the `name` and `parent`: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/tests/integration/aliases/python/rename_component_and_child/step2/__main__.py#L15 In this case, specifying `parent` on the alias shouldn't be necessary. However, even after removing `parent` from the alias spec, the test still succeeds because the parent itself has an alias: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/tests/integration/aliases/python/rename_component_and_child/step2/__main__.py#L18 ... and parent aliases are inherited as part of a child's aliases, so we still get an alias that works from the inheritance. If we change the test to make no changes to the parent such that it doesn't have any aliases, then we get the failure as we'd expect. A similar problem will happen when retyping a child. **Fix** The fix involves using the child's parent in the calculated alias URN when `Parent` isn't specified for the alias. As part of this, we need to properly handled `NoParent` because right now the engine is not correctly using it. The struct representing an alias in the engine does not have a `NoParent` field: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/sdk/go/common/resource/alias.go#L8-L15 And therefore does not copy it over in the gRPC request: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/pkg/resource/deploy/source_eval.go#L1082-L1088 Instead, the `Alias` struct has an incorrect `NoParent` method which returns `true` if the `Parent` field has a value of `""`: https://github.com/pulumi/pulumi/blob/117955ce14b6cf2dd093f8356ec7e26427aca4bf/sdk/go/common/resource/alias.go#L24-L26
2023-05-01 21:36:32 +00:00
URN URN
Name string
Type string
Project string
Stack string
Parent URN
NoParent bool
}
func (a *Alias) GetURN() URN {
if a.URN != "" {
return a.URN
}
return CreateURN(a.Name, a.Type, a.Parent, a.Project, a.Stack)
}
// CreateURN computes a URN from the combination of a resource name, resource type, and optional parent,
func CreateURN(name string, t string, parent URN, project string, stack string) URN {
createURN := func(parent URN, stack string, project string, t string, name string) URN {
parentString := string(parent)
var parentPrefix string
if parent == "" {
parentPrefix = "urn:pulumi:" + stack + "::" + project + "::"
} else {
ix := strings.LastIndex(parentString, "::")
if ix == -1 {
panic(fmt.Sprintf("Expected 'parent' string '%s' to contain '::'", parent))
}
parentPrefix = parentString[0:ix] + "$"
}
return URN(parentPrefix + t + "::" + name)
}
return createURN(parent, stack, project, t, name)
}