Go aliases (#3853)
This commit is contained in:
parent
5bf490228a
commit
cea807a244
|
@ -16,6 +16,8 @@ CHANGELOG
|
|||
[#3822](https://github.com/pulumi/pulumi/pull/3822)
|
||||
|
||||
- Update `SummaryEvent` to include the actual name and local file path for locally-executed policy packs.
|
||||
- Add support for aliases in the Go SDK
|
||||
[3853](https://github.com/pulumi/pulumi/pull/3853)
|
||||
|
||||
- Fix Python Dynamic Providers on Windows. [#3855](https://github.com/pulumi/pulumi/pull/3855)
|
||||
|
||||
|
|
113
sdk/go/pulumi/alias.go
Normal file
113
sdk/go/pulumi/alias.go
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2016-2020, 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 pulumi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Alias is a partial description of prior named used for a resource. It can be processed in the
|
||||
// context of a resource creation to determine what the full aliased URN would be.
|
||||
type Alias struct {
|
||||
// Optional URN that uniquely identifies a resource. If specified, it takes preference and
|
||||
// other members of the struct are ignored.
|
||||
URN URNInput
|
||||
// The previous name of the resource. If not provided, the current name of the resource is used.
|
||||
Name StringInput
|
||||
// The previous type of the resource. If not provided, the current type of the resource is used.
|
||||
Type StringInput
|
||||
// The previous parent of the resource. If not provided, the current parent of the resource is used.
|
||||
Parent Resource
|
||||
// The previous parent of the resource in URN format, mutually exclusive to 'Parent'
|
||||
ParentURN URNInput
|
||||
// The name of the previous stack of the resource. If not provided, defaults to `context.GetStack()
|
||||
Stack StringInput
|
||||
// The previous project of the resource. If not provided, defaults to `context.GetProject()`.
|
||||
Project StringInput
|
||||
}
|
||||
|
||||
func (a Alias) collapseToURN(defaultName, defaultType string, defaultParent Resource,
|
||||
defaultProject, defaultStack string) (URNOutput, error) {
|
||||
|
||||
if a.URN != nil {
|
||||
return a.URN.ToURNOutput(), nil
|
||||
}
|
||||
|
||||
n := a.Name
|
||||
if n == nil {
|
||||
n = String(defaultName)
|
||||
}
|
||||
t := a.Type
|
||||
if t == nil {
|
||||
t = String(defaultType)
|
||||
}
|
||||
|
||||
var parent StringInput
|
||||
if a.Parent != nil && a.ParentURN != nil {
|
||||
return URNOutput{}, errors.New("alias can specify either Parent or ParentURN but not both")
|
||||
}
|
||||
if a.Parent != nil {
|
||||
parent = a.Parent.URN()
|
||||
}
|
||||
if a.ParentURN != nil {
|
||||
parent = a.ParentURN.ToURNOutput()
|
||||
}
|
||||
|
||||
project := a.Project
|
||||
if project == nil {
|
||||
project = String(defaultProject)
|
||||
}
|
||||
stack := a.Stack
|
||||
if stack == nil {
|
||||
stack = String(defaultStack)
|
||||
}
|
||||
|
||||
return CreateURN(n, t, parent, project, stack), nil
|
||||
}
|
||||
|
||||
// CreateURN computes a URN from the combination of a resource name, resource type, and optional parent,
|
||||
func CreateURN(name, t, parent, project, stack StringInput) URNOutput {
|
||||
var parentPrefix StringInput
|
||||
if parent != nil {
|
||||
parentPrefix = parent.ToStringOutput().ApplyString(func(p string) string {
|
||||
return p[0:strings.LastIndex(p, "::")] + "$"
|
||||
})
|
||||
} else {
|
||||
parentPrefix = All(stack, project).ApplyString(func(a []interface{}) string {
|
||||
return "urn:pulumi:" + a[0].(string) + "::" + a[1].(string) + "::"
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return All(parentPrefix, t, name).ApplyURN(func(a []interface{}) URN {
|
||||
return URN(a[0].(string) + a[1].(string) + "::" + a[2].(string))
|
||||
})
|
||||
}
|
||||
|
||||
// inheritedChildAlias computes the alias that should be applied to a child based on an alias applied to it's parent.
|
||||
// This may involve changing the name of the resource in cases where the resource has a named derived from the name of
|
||||
// the parent, and the parent name changed.
|
||||
func inheritedChildAlias(childName, parentName, childType, project, stack string, parentURN URNOutput) URNOutput {
|
||||
aliasName := StringInput(String(childName))
|
||||
if strings.HasPrefix(childName, parentName) {
|
||||
aliasName = parentURN.ApplyString(func(urn URN) string {
|
||||
parentPrefix := urn[strings.LastIndex(string(urn), "::")+2:]
|
||||
return string(parentPrefix) + childName[len(parentName):]
|
||||
})
|
||||
}
|
||||
return CreateURN(aliasName, String(childType), parentURN, String(project), String(stack))
|
||||
}
|
|
@ -271,13 +271,22 @@ func (ctx *Context) ReadResource(
|
|||
options.Parent = ctx.stack
|
||||
}
|
||||
|
||||
// Collapse aliases to URNs.
|
||||
aliasURNs, err := ctx.collapseAliases(options.Aliases, t, name, options.Parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Note that we're about to make an outstanding RPC request, so that we can rendezvous during shutdown.
|
||||
if err := ctx.beginRPC(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Merge providers.
|
||||
providers := mergeProviders(t, options.Parent, options.Provider, options.Providers)
|
||||
|
||||
// Create resolvers for the resource's outputs.
|
||||
res := makeResourceState(t, resource, mergeProviders(t, options.Parent, options.Provider, options.Providers))
|
||||
res := makeResourceState(t, name, resource, providers, aliasURNs)
|
||||
|
||||
// Kick off the resource read operation. This will happen asynchronously and resolve the above properties.
|
||||
go func() {
|
||||
|
@ -297,7 +306,7 @@ func (ctx *Context) ReadResource(
|
|||
}
|
||||
|
||||
// Prepare the inputs for an impending operation.
|
||||
inputs, err = ctx.prepareResourceInputs(props, t, res.providers, options)
|
||||
inputs, err = ctx.prepareResourceInputs(props, t, options, res)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -310,6 +319,7 @@ func (ctx *Context) ReadResource(
|
|||
Properties: inputs.rpcProps,
|
||||
Provider: inputs.provider,
|
||||
Id: string(idToRead),
|
||||
Aliases: inputs.aliases,
|
||||
})
|
||||
if err != nil {
|
||||
logging.V(9).Infof("ReadResource(%s, %s): error: %v", t, name, err)
|
||||
|
@ -381,13 +391,22 @@ func (ctx *Context) RegisterResource(
|
|||
options.Parent = ctx.stack
|
||||
}
|
||||
|
||||
// Collapse aliases to URNs.
|
||||
aliasURNs, err := ctx.collapseAliases(options.Aliases, t, name, options.Parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Note that we're about to make an outstanding RPC request, so that we can rendezvous during shutdown.
|
||||
if err := ctx.beginRPC(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Merge providers.
|
||||
providers := mergeProviders(t, options.Parent, options.Provider, options.Providers)
|
||||
|
||||
// Create resolvers for the resource's outputs.
|
||||
res := makeResourceState(t, resource, mergeProviders(t, options.Parent, options.Provider, options.Providers))
|
||||
res := makeResourceState(t, name, resource, providers, aliasURNs)
|
||||
|
||||
// Kick off the resource registration. If we are actually performing a deployment, the resulting properties
|
||||
// will be resolved asynchronously as the RPC operation completes. If we're just planning, values won't resolve.
|
||||
|
@ -403,7 +422,7 @@ func (ctx *Context) RegisterResource(
|
|||
}()
|
||||
|
||||
// Prepare the inputs for an impending operation.
|
||||
inputs, err = ctx.prepareResourceInputs(props, t, res.providers, options)
|
||||
inputs, err = ctx.prepareResourceInputs(props, t, options, res)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -423,6 +442,7 @@ func (ctx *Context) RegisterResource(
|
|||
ImportId: inputs.importID,
|
||||
CustomTimeouts: inputs.customTimeouts,
|
||||
IgnoreChanges: inputs.ignoreChanges,
|
||||
Aliases: inputs.aliases,
|
||||
})
|
||||
if err != nil {
|
||||
logging.V(9).Infof("RegisterResource(%s, %s): error: %v", t, name, err)
|
||||
|
@ -448,6 +468,8 @@ func (ctx *Context) RegisterComponentResource(
|
|||
type resourceState struct {
|
||||
outputs map[string]Output
|
||||
providers map[string]ProviderResource
|
||||
aliases []URNOutput
|
||||
name string
|
||||
}
|
||||
|
||||
// checks all possible sources of providers and merges them with preference given to the most specific
|
||||
|
@ -485,9 +507,34 @@ func getPackage(t string) string {
|
|||
return components[0]
|
||||
}
|
||||
|
||||
// collapseAliases collapses a list of Aliases into alist of URNs.
|
||||
func (ctx *Context) collapseAliases(aliases []Alias, t, name string, parent Resource) ([]URNOutput, error) {
|
||||
project, stack := ctx.Project(), ctx.Stack()
|
||||
|
||||
var aliasURNs []URNOutput
|
||||
if parent != nil {
|
||||
for _, alias := range parent.getAliases() {
|
||||
urn := inheritedChildAlias(name, parent.getName(), t, project, stack, alias)
|
||||
aliasURNs = append(aliasURNs, urn)
|
||||
}
|
||||
}
|
||||
|
||||
for _, alias := range aliases {
|
||||
urn, err := alias.collapseToURN(name, t, parent, project, stack)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error collapsing alias to URN")
|
||||
}
|
||||
aliasURNs = append(aliasURNs, urn)
|
||||
}
|
||||
|
||||
return aliasURNs, nil
|
||||
}
|
||||
|
||||
// makeResourceState creates a set of resolvers that we'll use to finalize state, for URNs, IDs, and output
|
||||
// properties.
|
||||
func makeResourceState(t string, resourceV Resource, providers map[string]ProviderResource) *resourceState {
|
||||
func makeResourceState(t, name string, resourceV Resource, providers map[string]ProviderResource,
|
||||
aliases []URNOutput) *resourceState {
|
||||
|
||||
resource := reflect.ValueOf(resourceV)
|
||||
|
||||
typ := resource.Type()
|
||||
|
@ -552,6 +599,10 @@ func makeResourceState(t string, resourceV Resource, providers map[string]Provid
|
|||
rs.providers = providers
|
||||
rs.urn = URNOutput{newOutputState(urnType, resourceV)}
|
||||
state.outputs["urn"] = rs.urn
|
||||
state.name = name
|
||||
rs.name = name
|
||||
state.aliases = aliases
|
||||
rs.aliases = aliases
|
||||
|
||||
return state
|
||||
}
|
||||
|
@ -619,11 +670,14 @@ type resourceInputs struct {
|
|||
importID string
|
||||
customTimeouts *pulumirpc.RegisterResourceRequest_CustomTimeouts
|
||||
ignoreChanges []string
|
||||
aliases []string
|
||||
}
|
||||
|
||||
// prepareResourceInputs prepares the inputs for a resource operation, shared between read and register.
|
||||
func (ctx *Context) prepareResourceInputs(props Input, t string,
|
||||
providers map[string]ProviderResource, opts *resourceOptions) (*resourceInputs, error) {
|
||||
opts *resourceOptions, resource *resourceState) (*resourceInputs, error) {
|
||||
|
||||
providers := resource.providers
|
||||
|
||||
// Get the parent and dependency URNs from the options, in addition to the protection bit. If there wasn't an
|
||||
// explicit parent, and a root stack resource exists, we will automatically parent to that.
|
||||
|
@ -677,6 +731,16 @@ func (ctx *Context) prepareResourceInputs(props Input, t string,
|
|||
}
|
||||
sort.Strings(deps)
|
||||
|
||||
// Await alias URNs
|
||||
aliases := make([]string, len(resource.aliases))
|
||||
for i, alias := range resource.aliases {
|
||||
urn, _, err := alias.awaitURN(context.Background())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error waiting for alias URN to resolve")
|
||||
}
|
||||
aliases[i] = string(urn)
|
||||
}
|
||||
|
||||
return &resourceInputs{
|
||||
parent: string(parent),
|
||||
deps: deps,
|
||||
|
@ -689,6 +753,7 @@ func (ctx *Context) prepareResourceInputs(props Input, t string,
|
|||
importID: string(importID),
|
||||
customTimeouts: getTimeouts(opts.CustomTimeouts),
|
||||
ignoreChanges: ignoreChanges,
|
||||
aliases: aliases,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@ type ResourceState struct {
|
|||
urn URNOutput `pulumi:"urn"`
|
||||
|
||||
providers map[string]ProviderResource
|
||||
|
||||
aliases []URNOutput
|
||||
|
||||
name string
|
||||
}
|
||||
|
||||
func (s ResourceState) URN() URNOutput {
|
||||
|
@ -46,6 +50,14 @@ func (s ResourceState) getProviders() map[string]ProviderResource {
|
|||
return s.providers
|
||||
}
|
||||
|
||||
func (s ResourceState) getAliases() []URNOutput {
|
||||
return s.aliases
|
||||
}
|
||||
|
||||
func (s ResourceState) getName() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
func (ResourceState) isResource() {}
|
||||
|
||||
type CustomResourceState struct {
|
||||
|
@ -78,6 +90,12 @@ type Resource interface {
|
|||
// getProviders returns the provider map for this resource.
|
||||
getProviders() map[string]ProviderResource
|
||||
|
||||
// getAliases returns the list of aliases for this resource
|
||||
getAliases() []URNOutput
|
||||
|
||||
// getName returns the name of the resource
|
||||
getName() string
|
||||
|
||||
// isResource() is a marker method used to ensure that all Resource types embed a ResourceState.
|
||||
isResource()
|
||||
}
|
||||
|
@ -137,6 +155,8 @@ type resourceOptions struct {
|
|||
CustomTimeouts *CustomTimeouts
|
||||
// Ignore changes to any of the specified properties.
|
||||
IgnoreChanges []string
|
||||
// Aliases is an optional list of identifiers used to find and use existing resources.
|
||||
Aliases []Alias
|
||||
}
|
||||
|
||||
type invokeOptions struct {
|
||||
|
@ -266,3 +286,10 @@ func IgnoreChanges(o []string) ResourceOption {
|
|||
ro.IgnoreChanges = o
|
||||
})
|
||||
}
|
||||
|
||||
// Aliases applies a list of identifiers to find and use existing resources.
|
||||
func Aliases(o []Alias) ResourceOption {
|
||||
return resourceOption(func(ro *resourceOptions) {
|
||||
ro.Aliases = o
|
||||
})
|
||||
}
|
||||
|
|
|
@ -261,7 +261,7 @@ type testResource struct {
|
|||
|
||||
func TestResourceState(t *testing.T) {
|
||||
var theResource testResource
|
||||
state := makeResourceState("", &theResource, nil)
|
||||
state := makeResourceState("", "", &theResource, nil, nil)
|
||||
|
||||
resolved, _, _, _ := marshalInputs(&testResourceInputs{
|
||||
Any: String("foo"),
|
||||
|
|
|
@ -80,3 +80,23 @@ func TestDotNetAliases(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoAliases(t *testing.T) {
|
||||
for _, dir := range dirs {
|
||||
d := filepath.Join("go", dir)
|
||||
t.Run(d, func(t *testing.T) {
|
||||
integration.ProgramTest(t, &integration.ProgramTestOptions{
|
||||
Dir: filepath.Join(d, "step1"),
|
||||
Dependencies: []string{"Pulumi"},
|
||||
Quick: true,
|
||||
EditDirs: []integration.EditDir{
|
||||
{
|
||||
Dir: filepath.Join(d, "step2"),
|
||||
ExpectNoChanges: true,
|
||||
Additive: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
name: aliases_adopt_into_component
|
||||
description: A program that replaces a resource with a new name and alias.
|
||||
runtime: go
|
109
tests/integration/aliases/go/adopt_into_component/step1/main.go
Normal file
109
tests/integration/aliases/go/adopt_into_component/step1/main.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
// FooComponent is a component resource
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent2 struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent3 struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent4 struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func NewFooComponent2(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent2, error) {
|
||||
fooComp := &FooComponent2{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent2", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func NewFooComponent3(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent3, error) {
|
||||
fooComp := &FooComponent3{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent3", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = NewFooComponent2(ctx, name+"-child", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func NewFooComponent4(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent4, error) {
|
||||
fooComp := &FooComponent4{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent4", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
_, err := NewFooResource(ctx, "res2")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
comp2, err := NewFooComponent(ctx, "comp2")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = NewFooComponent2(ctx, "unparented")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = NewFooComponent3(ctx, "parentedbystack")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pbcOpt := pulumi.Parent(comp2)
|
||||
_, err = NewFooComponent3(ctx, "parentedbycomponent", pbcOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dupeOpt := pulumi.Parent(comp2)
|
||||
_, err = NewFooComponent4(ctx, "duplicateAliases", dupeOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
141
tests/integration/aliases/go/adopt_into_component/step2/main.go
Normal file
141
tests/integration/aliases/go/adopt_into_component/step2/main.go
Normal file
|
@ -0,0 +1,141 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
// FooComponent is a component resource
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent2 struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent3 struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent4 struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var nilInput pulumi.StringInput
|
||||
aliasURN := pulumi.CreateURN(
|
||||
pulumi.StringInput(pulumi.String("res2")),
|
||||
pulumi.StringInput(pulumi.String("my:module:FooResource")),
|
||||
nilInput,
|
||||
pulumi.StringInput(pulumi.String(ctx.Project())),
|
||||
pulumi.StringInput(pulumi.String(ctx.Stack())))
|
||||
alias := &pulumi.Alias{
|
||||
URN: aliasURN,
|
||||
}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooResource(ctx, name+"-child", aliasOpt, parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func NewFooComponent2(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent2, error) {
|
||||
fooComp := &FooComponent2{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent2", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func NewFooComponent3(ctx *pulumi.Context,
|
||||
name string,
|
||||
childAliasParent pulumi.Resource,
|
||||
opts ...pulumi.ResourceOption) (*FooComponent3, error) {
|
||||
fooComp := &FooComponent3{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent3", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alias := &pulumi.Alias{
|
||||
Parent: childAliasParent,
|
||||
}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooComponent2(ctx, name+"-child", aliasOpt, parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func NewFooComponent4(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent4, error) {
|
||||
fooComp := &FooComponent4{}
|
||||
alias := &pulumi.Alias{
|
||||
Parent: nil,
|
||||
}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias, *alias})
|
||||
o := []pulumi.ResourceOption{aliasOpt}
|
||||
o = append(o, opts...)
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent4", name, fooComp, o...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
comp2, err := NewFooComponent(ctx, "comp2")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alias := &pulumi.Alias{
|
||||
Parent: nil,
|
||||
}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
parentOpt := pulumi.Parent(comp2)
|
||||
_, err = NewFooComponent2(ctx, "unparented", aliasOpt, parentOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = NewFooComponent3(ctx, "parentedbystack", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pbcOpt := pulumi.Parent(comp2)
|
||||
_, err = NewFooComponent3(ctx, "parentedbycomponent", comp2, pbcOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dupeOpt := pulumi.Parent(comp2)
|
||||
_, err = NewFooComponent4(ctx, "duplicateAliases", dupeOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
3
tests/integration/aliases/go/rename/step1/Pulumi.yaml
Normal file
3
tests/integration/aliases/go/rename/step1/Pulumi.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
name: aliases_rename
|
||||
description: A program that replaces a resource with a new name and alias.
|
||||
runtime: go
|
19
tests/integration/aliases/go/rename/step1/main.go
Normal file
19
tests/integration/aliases/go/rename/step1/main.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
// FooComponent is a component resource
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
fooComponent := &FooComponent{}
|
||||
return ctx.RegisterComponentResource("foo:component", "foo", fooComponent)
|
||||
})
|
||||
}
|
23
tests/integration/aliases/go/rename/step2/main.go
Normal file
23
tests/integration/aliases/go/rename/step2/main.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
// FooComponent is a component resource
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
fooComponent := &FooComponent{}
|
||||
alias := &pulumi.Alias{
|
||||
Name: pulumi.String("foo"),
|
||||
}
|
||||
opts := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
return ctx.RegisterComponentResource("foo:component", "newfoo", fooComponent, opts)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
name: aliases_rename_component
|
||||
description: A program that replaces a resource with a new name and alias.
|
||||
runtime: go
|
57
tests/integration/aliases/go/rename_component/step1/main.go
Normal file
57
tests/integration/aliases/go/rename_component/step1/main.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
// FooComponent is a component resource
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
// Scenario #3 - rename a component (and all it's children)
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent42", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Note that both un-prefixed and parent-name-prefixed child names are supported. For the later, the implicit
|
||||
// alias inherited from the parent alias will include replacing the name prefix to match the parent alias name.
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooResource(ctx, name+"-child", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = NewFooResource(ctx, "otherchild", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
_, err := NewFooComponent(ctx, "comp3")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
60
tests/integration/aliases/go/rename_component/step2/main.go
Normal file
60
tests/integration/aliases/go/rename_component/step2/main.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
// Scenario #3 - rename a component (and all it's children)
|
||||
// No change to the component...
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent42", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Note that both un-prefixed and parent-name-prefixed child names are supported. For the later, the implicit
|
||||
// alias inherited from the parent alias will include replacing the name prefix to match the parent alias name.
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooResource(ctx, name+"-child", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = NewFooResource(ctx, "otherchild", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
// ...but applying an alias to the instance successfully renames both the component and the children.
|
||||
alias := &pulumi.Alias{Name: pulumi.StringInput(pulumi.String("comp3"))}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
_, err := NewFooComponent(ctx, "newcomp3", aliasOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
name: aliases_rename_component_and_child
|
||||
description: A program that replaces a resource with a new name and alias.
|
||||
runtime: go
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
// Scenario #5 - composing #1 and #3 and making both changes at the same time
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent43", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooResource(ctx, "otherchild", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
_, err := NewFooComponent(ctx, "comp5")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
// Scenario #5 - composing #1 and #3 and making both changes at the same time
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent43", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
alias := &pulumi.Alias{
|
||||
Name: pulumi.StringInput(pulumi.String("otherchild")),
|
||||
Parent: fooComp,
|
||||
}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
_, err = NewFooResource(ctx, "otherchildrenamed", parentOpt, aliasOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
alias := &pulumi.Alias{Name: pulumi.StringInput(pulumi.String("comp5"))}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
_, err := NewFooComponent(ctx, "newcomp5", aliasOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
name: aliases_retype_component
|
||||
description: A program that replaces a resource with a new name and alias.
|
||||
runtime: go
|
50
tests/integration/aliases/go/retype_component/step1/main.go
Normal file
50
tests/integration/aliases/go/retype_component/step1/main.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
// Scenario #4 - change the type of a component
|
||||
func NewFooComponent(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooComponent44", name, fooComp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooResource(ctx, "otherchild", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
_, err := NewFooComponent(ctx, "comp4")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
54
tests/integration/aliases/go/retype_component/step2/main.go
Normal file
54
tests/integration/aliases/go/retype_component/step2/main.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pulumi/pulumi/sdk/go/pulumi"
|
||||
)
|
||||
|
||||
type FooResource struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
type FooComponent struct {
|
||||
pulumi.ResourceState
|
||||
}
|
||||
|
||||
func NewFooResource(ctx *pulumi.Context, name string, opts ...pulumi.ResourceOption) (*FooResource, error) {
|
||||
fooRes := &FooResource{}
|
||||
err := ctx.RegisterComponentResource("my:module:FooResource", name, fooRes, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooRes, nil
|
||||
}
|
||||
|
||||
// Scenario #4 - change the type of a component
|
||||
func NewFooComponent(ctx *pulumi.Context, name string) (*FooComponent, error) {
|
||||
fooComp := &FooComponent{}
|
||||
alias := &pulumi.Alias{
|
||||
Type: pulumi.StringInput(pulumi.String("my:module:FooComponent44")),
|
||||
}
|
||||
aliasOpt := pulumi.Aliases([]pulumi.Alias{*alias})
|
||||
err := ctx.RegisterComponentResource("my:diffmodule:FooComponent55DiffType", name, fooComp, aliasOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentOpt := pulumi.Parent(fooComp)
|
||||
_, err = NewFooResource(ctx, "otherchild", parentOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fooComp, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
pulumi.Run(func(ctx *pulumi.Context) error {
|
||||
_, err := NewFooComponent(ctx, "comp4")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue