Go aliases (#3853)

This commit is contained in:
Evan Boyle 2020-02-06 12:02:13 -08:00 committed by GitHub
parent 5bf490228a
commit cea807a244
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 869 additions and 7 deletions

View file

@ -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
View 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))
}

View file

@ -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
}

View file

@ -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
})
}

View file

@ -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"),

View file

@ -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,
},
},
})
})
}
}

View file

@ -0,0 +1,3 @@
name: aliases_adopt_into_component
description: A program that replaces a resource with a new name and alias.
runtime: go

View 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
})
}

View 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
})
}

View file

@ -0,0 +1,3 @@
name: aliases_rename
description: A program that replaces a resource with a new name and alias.
runtime: go

View 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)
})
}

View 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)
})
}

View file

@ -0,0 +1,3 @@
name: aliases_rename_component
description: A program that replaces a resource with a new name and alias.
runtime: go

View 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
})
}

View 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
})
}

View file

@ -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

View 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 #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
})
}

View file

@ -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
})
}

View file

@ -0,0 +1,3 @@
name: aliases_retype_component
description: A program that replaces a resource with a new name and alias.
runtime: go

View 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
})
}

View 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
})
}