Add replaceOnChanges
resource option (#7226)
Adds a new resource option to force replacement when certain properties report changes, even if the resource provider itself does not require a replacement. Fixes #6753. Co-authored-by: Levi Blackstone <levi@pulumi.com>
This commit is contained in:
parent
2781cf03fe
commit
eb32039013
|
@ -1,6 +1,7 @@
|
|||
|
||||
### Improvements
|
||||
|
||||
|
||||
- [sdk] - Add `replaceOnChanges` resource option.
|
||||
[#7226](https://github.com/pulumi/pulumi/pull/722
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
|
|
@ -722,3 +722,81 @@ func TestProviderInheritanceGolangLifecycle(t *testing.T) {
|
|||
}
|
||||
p.Run(t, nil)
|
||||
}
|
||||
|
||||
// This test validates the wiring of the ReplaceOnChanges prop in the go SDK.
|
||||
// It doesn't attempt to validate underlying behavior.
|
||||
func TestReplaceOnChangesGolangLifecycle(t *testing.T) {
|
||||
var expectedReplaceOnChanges []string
|
||||
|
||||
loaders := []*deploytest.ProviderLoader{
|
||||
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
||||
return &deploytest.Provider{
|
||||
CreateF: func(urn resource.URN, news resource.PropertyMap, timeout float64,
|
||||
preview bool) (resource.ID, resource.PropertyMap, resource.Status, error) {
|
||||
|
||||
return "created-id", news, resource.StatusOK, nil
|
||||
},
|
||||
ReadF: func(urn resource.URN, id resource.ID,
|
||||
inputs, state resource.PropertyMap) (plugin.ReadResult, resource.Status, error) {
|
||||
return plugin.ReadResult{Inputs: inputs, Outputs: state}, resource.StatusOK, nil
|
||||
},
|
||||
DiffF: func(urn resource.URN, id resource.ID,
|
||||
olds, news resource.PropertyMap, replaceOnChanges []string) (plugin.DiffResult, error) {
|
||||
// just verify that the ReplaceOnChanges prop made it through
|
||||
assert.Equal(t, expectedReplaceOnChanges, replaceOnChanges)
|
||||
return plugin.DiffResult{}, nil
|
||||
},
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
setupAndRunProgram := func(replaceOnChanges []string) *deploy.Snapshot {
|
||||
program := deploytest.NewLanguageRuntime(func(info plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
ctx, err := pulumi.NewContext(context.Background(), pulumi.RunInfo{
|
||||
Project: info.Project,
|
||||
Stack: info.Stack,
|
||||
Parallel: info.Parallel,
|
||||
DryRun: info.DryRun,
|
||||
MonitorAddr: info.MonitorAddress,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
return pulumi.RunWithContext(ctx, func(ctx *pulumi.Context) error {
|
||||
var res pulumi.CustomResourceState
|
||||
err := ctx.RegisterResource("pkgA:m:typA", "resA", nil, &res, pulumi.ReplaceOnChanges(replaceOnChanges))
|
||||
assert.NoError(t, err)
|
||||
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
||||
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
||||
p := &TestPlan{
|
||||
Options: UpdateOptions{Host: host},
|
||||
Steps: []TestStep{
|
||||
{
|
||||
Op: Update,
|
||||
Validate: func(project workspace.Project, target deploy.Target, entries JournalEntries,
|
||||
events []Event, res result.Result) result.Result {
|
||||
for _, event := range events {
|
||||
if event.Type == ResourcePreEvent {
|
||||
payload := event.Payload().(ResourcePreEventPayload)
|
||||
assert.Equal(t, []deploy.StepOp{deploy.OpCreate}, []deploy.StepOp{payload.Metadata.Op})
|
||||
}
|
||||
}
|
||||
return res
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return p.Run(t, nil)
|
||||
}
|
||||
|
||||
// replace on changes specified
|
||||
replaceOnChanges := []string{"b"}
|
||||
setupAndRunProgram(replaceOnChanges)
|
||||
|
||||
// replace on changes empty
|
||||
replaceOnChanges = []string{}
|
||||
setupAndRunProgram(replaceOnChanges)
|
||||
}
|
||||
|
|
|
@ -942,6 +942,158 @@ func TestSingleResourceIgnoreChanges(t *testing.T) {
|
|||
}, []string{"a", "b"}, []deploy.StepOp{deploy.OpUpdate})
|
||||
}
|
||||
|
||||
func objectDiffToDetailedDiff(prefix string, d *resource.ObjectDiff) map[string]plugin.PropertyDiff {
|
||||
ret := map[string]plugin.PropertyDiff{}
|
||||
for k, vd := range d.Updates {
|
||||
var nestedPrefix string
|
||||
if prefix == "" {
|
||||
nestedPrefix = string(k)
|
||||
} else {
|
||||
nestedPrefix = fmt.Sprintf("%s.%s", prefix, string(k))
|
||||
}
|
||||
for kk, pd := range valueDiffToDetailedDiff(nestedPrefix, vd) {
|
||||
ret[kk] = pd
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func arrayDiffToDetailedDiff(prefix string, d *resource.ArrayDiff) map[string]plugin.PropertyDiff {
|
||||
ret := map[string]plugin.PropertyDiff{}
|
||||
for i, vd := range d.Updates {
|
||||
for kk, pd := range valueDiffToDetailedDiff(fmt.Sprintf("%s[%d]", prefix, i), vd) {
|
||||
ret[kk] = pd
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func valueDiffToDetailedDiff(prefix string, vd resource.ValueDiff) map[string]plugin.PropertyDiff {
|
||||
ret := map[string]plugin.PropertyDiff{}
|
||||
if vd.Object != nil {
|
||||
for kk, pd := range objectDiffToDetailedDiff(prefix, vd.Object) {
|
||||
ret[kk] = pd
|
||||
}
|
||||
} else if vd.Array != nil {
|
||||
for kk, pd := range arrayDiffToDetailedDiff(prefix, vd.Array) {
|
||||
ret[kk] = pd
|
||||
}
|
||||
} else {
|
||||
ret[prefix] = plugin.PropertyDiff{Kind: plugin.DiffUpdate}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func TestReplaceOnChanges(t *testing.T) {
|
||||
loaders := []*deploytest.ProviderLoader{
|
||||
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
||||
return &deploytest.Provider{
|
||||
DiffF: func(urn resource.URN, id resource.ID,
|
||||
olds, news resource.PropertyMap, ignoreChanges []string) (plugin.DiffResult, error) {
|
||||
|
||||
diff := olds.Diff(news)
|
||||
if diff == nil {
|
||||
return plugin.DiffResult{Changes: plugin.DiffNone}, nil
|
||||
}
|
||||
detailedDiff := objectDiffToDetailedDiff("", diff)
|
||||
var changedKeys []resource.PropertyKey
|
||||
for _, k := range diff.Keys() {
|
||||
if diff.Changed(k) {
|
||||
changedKeys = append(changedKeys, k)
|
||||
}
|
||||
}
|
||||
return plugin.DiffResult{
|
||||
Changes: plugin.DiffSome,
|
||||
ChangedKeys: changedKeys,
|
||||
DetailedDiff: detailedDiff,
|
||||
}, nil
|
||||
},
|
||||
UpdateF: func(urn resource.URN, id resource.ID, olds, news resource.PropertyMap, timeout float64,
|
||||
ignoreChanges []string, preview bool) (resource.PropertyMap, resource.Status, error) {
|
||||
return news, resource.StatusOK, nil
|
||||
},
|
||||
CreateF: func(urn resource.URN, inputs resource.PropertyMap, timeout float64,
|
||||
preview bool) (resource.ID, resource.PropertyMap, resource.Status, error) {
|
||||
return resource.ID("id123"), inputs, resource.StatusOK, nil
|
||||
},
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
updateProgramWithProps := func(snap *deploy.Snapshot, props resource.PropertyMap, replaceOnChanges []string,
|
||||
allowedOps []deploy.StepOp) *deploy.Snapshot {
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, deploytest.ResourceOptions{
|
||||
Inputs: props,
|
||||
ReplaceOnChanges: replaceOnChanges,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
||||
p := &TestPlan{
|
||||
Options: UpdateOptions{Host: host},
|
||||
Steps: []TestStep{
|
||||
{
|
||||
Op: Update,
|
||||
Validate: func(project workspace.Project, target deploy.Target, entries JournalEntries,
|
||||
events []Event, res result.Result) result.Result {
|
||||
for _, event := range events {
|
||||
if event.Type == ResourcePreEvent {
|
||||
payload := event.Payload().(ResourcePreEventPayload)
|
||||
assert.Subset(t, allowedOps, []deploy.StepOp{payload.Metadata.Op})
|
||||
}
|
||||
}
|
||||
return res
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return p.Run(t, snap)
|
||||
}
|
||||
|
||||
snap := updateProgramWithProps(nil, resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"a": 1,
|
||||
"b": map[string]interface{}{
|
||||
"c": "foo",
|
||||
},
|
||||
}), []string{"a", "b.c"}, []deploy.StepOp{deploy.OpCreate})
|
||||
|
||||
// Ensure that a change to a replaceOnChange property results in an OpReplace
|
||||
snap = updateProgramWithProps(snap, resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"a": 2,
|
||||
"b": map[string]interface{}{
|
||||
"c": "foo",
|
||||
},
|
||||
}), []string{"a"}, []deploy.StepOp{deploy.OpReplace, deploy.OpCreateReplacement, deploy.OpDeleteReplaced})
|
||||
|
||||
// Ensure that a change to a nested replaceOnChange property results in an OpReplace
|
||||
snap = updateProgramWithProps(snap, resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"a": 2,
|
||||
"b": map[string]interface{}{
|
||||
"c": "bar",
|
||||
},
|
||||
}), []string{"b.c"}, []deploy.StepOp{deploy.OpReplace, deploy.OpCreateReplacement, deploy.OpDeleteReplaced})
|
||||
|
||||
// Ensure that a change to any property of a "*" replaceOnChange results in an OpReplace
|
||||
snap = updateProgramWithProps(snap, resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"a": 3,
|
||||
"b": map[string]interface{}{
|
||||
"c": "baz",
|
||||
},
|
||||
}), []string{"*"}, []deploy.StepOp{deploy.OpReplace, deploy.OpCreateReplacement, deploy.OpDeleteReplaced})
|
||||
|
||||
// Ensure that a change to an non-replaceOnChange property results in an OpUpdate
|
||||
snap = updateProgramWithProps(snap, resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"a": 4,
|
||||
"b": map[string]interface{}{
|
||||
"c": "qux",
|
||||
},
|
||||
}), nil, []deploy.StepOp{deploy.OpUpdate})
|
||||
|
||||
_ = snap
|
||||
}
|
||||
|
||||
// Resource is an abstract representation of a resource graph
|
||||
type Resource struct {
|
||||
t tokens.Type
|
||||
|
|
|
@ -95,6 +95,7 @@ type ResourceOptions struct {
|
|||
DeleteBeforeReplace *bool
|
||||
Version string
|
||||
IgnoreChanges []string
|
||||
ReplaceOnChanges []string
|
||||
Aliases []resource.URN
|
||||
ImportID resource.ID
|
||||
CustomTimeouts *resource.CustomTimeouts
|
||||
|
@ -185,6 +186,7 @@ func (rm *ResourceMonitor) RegisterResource(t tokens.Type, name string, custom b
|
|||
CustomTimeouts: &timeouts,
|
||||
SupportsPartialValues: supportsPartialValues,
|
||||
Remote: opts.Remote,
|
||||
ReplaceOnChanges: opts.ReplaceOnChanges,
|
||||
}
|
||||
|
||||
// submit request
|
||||
|
|
|
@ -305,7 +305,7 @@ func (d *defaultProviders) newRegisterDefaultProviderEvent(
|
|||
event := ®isterResourceEvent{
|
||||
goal: resource.NewGoal(
|
||||
providers.MakeProviderType(req.Package()),
|
||||
req.Name(), true, inputs, "", false, nil, "", nil, nil, nil, nil, nil, nil, "", nil),
|
||||
req.Name(), true, inputs, "", false, nil, "", nil, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
done: done,
|
||||
}
|
||||
return event, done, nil
|
||||
|
@ -843,6 +843,7 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
protect := req.GetProtect()
|
||||
deleteBeforeReplaceValue := req.GetDeleteBeforeReplace()
|
||||
ignoreChanges := req.GetIgnoreChanges()
|
||||
replaceOnChanges := req.GetReplaceOnChanges()
|
||||
id := resource.ID(req.GetImportId())
|
||||
customTimeouts := req.GetCustomTimeouts()
|
||||
|
||||
|
@ -967,9 +968,9 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
logging.V(5).Infof(
|
||||
"ResourceMonitor.RegisterResource received: t=%v, name=%v, custom=%v, #props=%v, parent=%v, protect=%v, "+
|
||||
"provider=%v, deps=%v, deleteBeforeReplace=%v, ignoreChanges=%v, aliases=%v, customTimeouts=%v, "+
|
||||
"providers=%v",
|
||||
"providers=%v, replaceOnChanges=%v",
|
||||
t, name, custom, len(props), parent, protect, providerRef, dependencies, deleteBeforeReplace, ignoreChanges,
|
||||
aliases, timeouts, providerRefs)
|
||||
aliases, timeouts, providerRefs, replaceOnChanges)
|
||||
|
||||
// If this is a remote component, fetch its provider and issue the construct call. Otherwise, register the resource.
|
||||
var result *RegisterResult
|
||||
|
@ -1006,7 +1007,7 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
step := ®isterResourceEvent{
|
||||
goal: resource.NewGoal(t, name, custom, props, parent, protect, dependencies,
|
||||
providerRef.String(), nil, propertyDependencies, deleteBeforeReplace, ignoreChanges,
|
||||
additionalSecretOutputs, aliases, id, &timeouts),
|
||||
additionalSecretOutputs, aliases, id, &timeouts, replaceOnChanges),
|
||||
done: make(chan *RegisterResult),
|
||||
}
|
||||
|
||||
|
|
|
@ -149,16 +149,16 @@ func TestRegisterNoDefaultProviders(t *testing.T) {
|
|||
// Register a component resource.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal(componentURN.Type(), componentURN.Name(), false, resource.PropertyMap{}, "", false,
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
// Register a couple resources using provider A.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:index:typA", "res1", true, resource.PropertyMap{}, componentURN, false, nil,
|
||||
providerARef.String(), []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
providerARef.String(), []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:index:typA", "res2", true, resource.PropertyMap{}, componentURN, false, nil,
|
||||
providerARef.String(), []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
providerARef.String(), []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
// Register two more providers.
|
||||
newProviderEvent("pkgA", "providerB", nil, ""),
|
||||
|
@ -166,11 +166,11 @@ func TestRegisterNoDefaultProviders(t *testing.T) {
|
|||
// Register a few resources that use the new providers.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:index:typB", "res3", true, resource.PropertyMap{}, "", false, nil,
|
||||
providerBRef.String(), []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
providerBRef.String(), []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:index:typC", "res4", true, resource.PropertyMap{}, "", false, nil,
|
||||
providerCRef.String(), []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
providerCRef.String(), []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -233,25 +233,25 @@ func TestRegisterDefaultProviders(t *testing.T) {
|
|||
// Register a component resource.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal(componentURN.Type(), componentURN.Name(), false, resource.PropertyMap{}, "", false,
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
// Register a couple resources from package A.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:m:typA", "res1", true, resource.PropertyMap{},
|
||||
componentURN, false, nil, "", []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
componentURN, false, nil, "", []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:m:typA", "res2", true, resource.PropertyMap{},
|
||||
componentURN, false, nil, "", []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
componentURN, false, nil, "", []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
// Register a few resources from other packages.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:m:typB", "res3", true, resource.PropertyMap{}, "", false,
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:m:typC", "res4", true, resource.PropertyMap{}, "", false,
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil),
|
||||
nil, "", []string{}, nil, nil, nil, nil, nil, "", nil, nil),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2018, Pulumi Corporation.
|
||||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -524,7 +524,15 @@ func (sg *stepGenerator) generateStepsFromDiff(
|
|||
"unrecognized diff state for %s: %d", urn, diff.Changes)
|
||||
}
|
||||
|
||||
// If there were changes, check for a replacement vs. an in-place update.
|
||||
hasInitErrors := len(old.InitErrors) > 0
|
||||
|
||||
// Update the diff to apply any replaceOnChanges annotations and to include initErrors in the diff.
|
||||
diff, err = sg.applyReplaceOnChanges(diff, goal.ReplaceOnChanges, hasInitErrors)
|
||||
if err != nil {
|
||||
return nil, result.FromError(err)
|
||||
}
|
||||
|
||||
// If there were changes check for a replacement vs. an in-place update.
|
||||
if diff.Changes == plugin.DiffSome {
|
||||
if diff.Replace() {
|
||||
// If the goal state specified an ID, issue an error: the replacement will change the ID, and is
|
||||
|
@ -557,8 +565,8 @@ func (sg *stepGenerator) generateStepsFromDiff(
|
|||
}
|
||||
|
||||
if logging.V(7) {
|
||||
logging.V(7).Infof("Planner decided to replace '%v' (oldprops=%v inputs=%v)",
|
||||
urn, oldInputs, new.Inputs)
|
||||
logging.V(7).Infof("Planner decided to replace '%v' (oldprops=%v inputs=%v replaceKeys=%v)",
|
||||
urn, oldInputs, new.Inputs, diff.ReplaceKeys)
|
||||
}
|
||||
|
||||
// We have two approaches to performing replacements:
|
||||
|
@ -638,7 +646,7 @@ func (sg *stepGenerator) generateStepsFromDiff(
|
|||
// If we fell through, it's an update.
|
||||
sg.updates[urn] = true
|
||||
if logging.V(7) {
|
||||
logging.V(7).Infof("Planner decided to update '%v' (oldprops=%v inputs=%v", urn, oldInputs, new.Inputs)
|
||||
logging.V(7).Infof("Planner decided to update '%v' (oldprops=%v inputs=%v)", urn, oldInputs, new.Inputs)
|
||||
}
|
||||
return []Step{
|
||||
NewUpdateStep(sg.deployment, event, old, new, diff.StableKeys, diff.ChangedKeys, diff.DetailedDiff,
|
||||
|
@ -648,11 +656,12 @@ func (sg *stepGenerator) generateStepsFromDiff(
|
|||
|
||||
// If resource was unchanged, but there were initialization errors, generate an empty update
|
||||
// step to attempt to "continue" awaiting initialization.
|
||||
if len(old.InitErrors) > 0 {
|
||||
if hasInitErrors {
|
||||
sg.updates[urn] = true
|
||||
return []Step{NewUpdateStep(sg.deployment, event, old, new, diff.StableKeys, nil, nil, nil)}, nil
|
||||
}
|
||||
|
||||
// Else there are no changes needed
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -1180,6 +1189,101 @@ func (sg *stepGenerator) getProviderResource(urn resource.URN, provider string)
|
|||
return result
|
||||
}
|
||||
|
||||
// initErrorSpecialKey is a special property key used to indicate that a diff is due to
|
||||
// initialization errors existing in the old state instead of due to a specific property
|
||||
// diff between old and new states.
|
||||
const initErrorSpecialKey = "#initerror"
|
||||
|
||||
// applyReplaceOnChanges adjusts a DiffResult returned from a provider to apply the ReplaceOnChange
|
||||
// settings in the desired state and init errors from the previous state.
|
||||
func (sg *stepGenerator) applyReplaceOnChanges(diff plugin.DiffResult,
|
||||
replaceOnChanges []string, hasInitErrors bool) (plugin.DiffResult, error) {
|
||||
|
||||
// No further work is necessary for DiffNone unless init errors are present.
|
||||
if diff.Changes != plugin.DiffSome && !hasInitErrors {
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
var replaceOnChangePaths []resource.PropertyPath
|
||||
for _, p := range replaceOnChanges {
|
||||
path, err := resource.ParsePropertyPath(p)
|
||||
if err != nil {
|
||||
return diff, err
|
||||
}
|
||||
replaceOnChangePaths = append(replaceOnChangePaths, path)
|
||||
}
|
||||
|
||||
// Calculate the new DetailedDiff
|
||||
modifiedDiff := map[string]plugin.PropertyDiff{}
|
||||
for p, v := range diff.DetailedDiff {
|
||||
diffPath, err := resource.ParsePropertyPath(p)
|
||||
if err != nil {
|
||||
return diff, err
|
||||
}
|
||||
changeToReplace := false
|
||||
for _, replaceOnChangePath := range replaceOnChangePaths {
|
||||
if replaceOnChangePath.Contains(diffPath) {
|
||||
changeToReplace = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if changeToReplace {
|
||||
v = v.ToReplace()
|
||||
}
|
||||
modifiedDiff[p] = v
|
||||
}
|
||||
|
||||
// Calculate the new ReplaceKeys
|
||||
modifiedReplaceKeysMap := map[resource.PropertyKey]struct{}{}
|
||||
for _, k := range diff.ReplaceKeys {
|
||||
modifiedReplaceKeysMap[k] = struct{}{}
|
||||
}
|
||||
for _, k := range diff.ChangedKeys {
|
||||
for _, replaceOnChangePath := range replaceOnChangePaths {
|
||||
keyPath, err := resource.ParsePropertyPath(string(k))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if replaceOnChangePath.Contains(keyPath) {
|
||||
modifiedReplaceKeysMap[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
var modifiedReplaceKeys []resource.PropertyKey
|
||||
for k := range modifiedReplaceKeysMap {
|
||||
modifiedReplaceKeys = append(modifiedReplaceKeys, k)
|
||||
}
|
||||
|
||||
// Add init errors to modified diff results
|
||||
modifiedChanges := diff.Changes
|
||||
if hasInitErrors {
|
||||
for _, replaceOnChangePath := range replaceOnChangePaths {
|
||||
initErrPath, err := resource.ParsePropertyPath(initErrorSpecialKey)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if replaceOnChangePath.Contains(initErrPath) {
|
||||
modifiedReplaceKeys = append(modifiedReplaceKeys, initErrorSpecialKey)
|
||||
modifiedDiff[initErrorSpecialKey] = plugin.PropertyDiff{
|
||||
Kind: plugin.DiffUpdateReplace,
|
||||
InputDiff: false,
|
||||
}
|
||||
// If an init error is present on a path that causes replacement, then trigger a replacement.
|
||||
modifiedChanges = plugin.DiffSome
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return plugin.DiffResult{
|
||||
DetailedDiff: modifiedDiff,
|
||||
ReplaceKeys: modifiedReplaceKeys,
|
||||
ChangedKeys: diff.ChangedKeys,
|
||||
Changes: modifiedChanges,
|
||||
DeleteBeforeReplace: diff.DeleteBeforeReplace,
|
||||
StableKeys: diff.StableKeys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type dependentReplace struct {
|
||||
res *resource.State
|
||||
keys []resource.PropertyKey
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Pulumi.ResourceOptions.ReplaceOnChanges.get -> System.Collections.Generic.List<string>
|
||||
Pulumi.ResourceOptions.ReplaceOnChanges.set -> void
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
@ -92,6 +92,20 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public string? Urn { get; set; }
|
||||
|
||||
private List<string>? _replaceOnChanges;
|
||||
|
||||
/// <summary>
|
||||
/// Changes to any of these property paths will force a replacement. If this list
|
||||
/// includes `"*"`, changes to any properties will force a replacement. Initialization
|
||||
/// errors from previous deployments will require replacement instead of update only if
|
||||
/// `"*"` is passed.
|
||||
/// </summary>
|
||||
public List<string> ReplaceOnChanges
|
||||
{
|
||||
get => _replaceOnChanges ??= new List<string>();
|
||||
set => _replaceOnChanges = value;
|
||||
}
|
||||
|
||||
internal abstract ResourceOptions Clone();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -18,6 +18,7 @@ namespace Pulumi
|
|||
IgnoreChanges = options.IgnoreChanges.ToList(),
|
||||
Protect = options.Protect,
|
||||
Provider = options.Provider,
|
||||
ReplaceOnChanges = options.ReplaceOnChanges.ToList(),
|
||||
ResourceTransformations = options.ResourceTransformations.ToList(),
|
||||
Urn = options.Urn,
|
||||
Version = options.Version
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
|
@ -17,7 +17,8 @@ namespace Pulumi
|
|||
options1.IgnoreChanges.AddRange(options2.IgnoreChanges);
|
||||
options1.ResourceTransformations.AddRange(options2.ResourceTransformations);
|
||||
options1.Aliases.AddRange(options2.Aliases);
|
||||
|
||||
options1.ReplaceOnChanges.AddRange(options2.ReplaceOnChanges);
|
||||
|
||||
options1.DependsOn = options1.DependsOn.Concat(options2.DependsOn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,28 @@ func (d DiffKind) IsReplace() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// AsReplace converts a DiffKind into the equivalent replacement if it not already
|
||||
// a replacement.
|
||||
func (d DiffKind) AsReplace() DiffKind {
|
||||
switch d {
|
||||
case DiffAdd:
|
||||
return DiffAddReplace
|
||||
case DiffAddReplace:
|
||||
return DiffAddReplace
|
||||
case DiffDelete:
|
||||
return DiffDeleteReplace
|
||||
case DiffDeleteReplace:
|
||||
return DiffDeleteReplace
|
||||
case DiffUpdate:
|
||||
return DiffUpdateReplace
|
||||
case DiffUpdateReplace:
|
||||
return DiffUpdateReplace
|
||||
default:
|
||||
contract.Failf("Unknown diff kind %v", int(d))
|
||||
return DiffUpdateReplace
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// DiffAdd indicates that the property was added.
|
||||
DiffAdd DiffKind = 0
|
||||
|
@ -176,6 +198,15 @@ type PropertyDiff struct {
|
|||
InputDiff bool // True if this is a diff between old and new inputs rather than old state and new inputs.
|
||||
}
|
||||
|
||||
// ToReplace converts the kind of a PropertyDiff into the equivalent replacement if it not already
|
||||
// a replacement.
|
||||
func (p PropertyDiff) ToReplace() PropertyDiff {
|
||||
return PropertyDiff{
|
||||
InputDiff: p.InputDiff,
|
||||
Kind: p.Kind.AsReplace(),
|
||||
}
|
||||
}
|
||||
|
||||
// DiffResult indicates whether an operation should replace or update an existing resource.
|
||||
type DiffResult struct {
|
||||
Changes DiffChanges // true if this diff represents a changed resource.
|
||||
|
|
|
@ -37,13 +37,15 @@ type Goal struct {
|
|||
Aliases []URN // additional URNs that should be aliased to this resource.
|
||||
ID ID // the expected ID of the resource, if any.
|
||||
CustomTimeouts CustomTimeouts // an optional config object for resource options
|
||||
ReplaceOnChanges []string // a list of property paths that if changed should force a replacement.
|
||||
}
|
||||
|
||||
// NewGoal allocates a new resource goal state.
|
||||
func NewGoal(t tokens.Type, name tokens.QName, custom bool, props PropertyMap,
|
||||
parent URN, protect bool, dependencies []URN, provider string, initErrors []string,
|
||||
propertyDependencies map[PropertyKey][]URN, deleteBeforeReplace *bool, ignoreChanges []string,
|
||||
additionalSecretOutputs []PropertyKey, aliases []URN, id ID, customTimeouts *CustomTimeouts) *Goal {
|
||||
additionalSecretOutputs []PropertyKey, aliases []URN, id ID, customTimeouts *CustomTimeouts,
|
||||
replaceOnChanges []string) *Goal {
|
||||
|
||||
g := &Goal{
|
||||
Type: t,
|
||||
|
@ -61,6 +63,7 @@ func NewGoal(t tokens.Type, name tokens.QName, custom bool, props PropertyMap,
|
|||
AdditionalSecretOutputs: additionalSecretOutputs,
|
||||
Aliases: aliases,
|
||||
ID: id,
|
||||
ReplaceOnChanges: replaceOnChanges,
|
||||
}
|
||||
|
||||
if customTimeouts != nil {
|
||||
|
|
|
@ -610,6 +610,7 @@ func (ctx *Context) registerResource(
|
|||
AdditionalSecretOutputs: inputs.additionalSecretOutputs,
|
||||
Version: inputs.version,
|
||||
Remote: remote,
|
||||
ReplaceOnChanges: inputs.replaceOnChanges,
|
||||
})
|
||||
if err != nil {
|
||||
logging.V(9).Infof("RegisterResource(%s, %s): error: %v", t, name, err)
|
||||
|
@ -931,6 +932,7 @@ type resourceInputs struct {
|
|||
aliases []string
|
||||
additionalSecretOutputs []string
|
||||
version string
|
||||
replaceOnChanges []string
|
||||
}
|
||||
|
||||
// prepareResourceInputs prepares the inputs for a resource operation, shared between read and register.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation.
|
||||
// Copyright 2016-2021, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -205,6 +205,10 @@ type resourceOptions struct {
|
|||
Provider ProviderResource
|
||||
// Providers is an optional map of package to provider resource for a component resource.
|
||||
Providers map[string]ProviderResource
|
||||
// ReplaceOnChanges will force a replacement when any of these property paths are set. If this list includes `"*"`,
|
||||
// changes to any properties will force a replacement. Initialization errors from previous deployments will
|
||||
// require replacement instead of update only if `"*"` is passed.
|
||||
ReplaceOnChanges []string
|
||||
// Transformations is an optional list of transformations to apply to this resource during construction.
|
||||
// The transformations are applied in order, and are applied prior to transformation and to parents
|
||||
// walking from the resource up to the stack.
|
||||
|
@ -367,6 +371,15 @@ func Providers(o ...ProviderResource) ResourceOption {
|
|||
return ProviderMap(m)
|
||||
}
|
||||
|
||||
// ReplaceOnChanges will force a replacement when any of these property paths are set. If this list includes `"*"`,
|
||||
// changes to any properties will force a replacement. Initialization errors from previous deployments will
|
||||
// require replacement instead of update only if `"*"` is passed.
|
||||
func ReplaceOnChanges(o []string) ResourceOption {
|
||||
return resourceOption(func(ro *resourceOptions) {
|
||||
ro.ReplaceOnChanges = append(ro.ReplaceOnChanges, o...)
|
||||
})
|
||||
}
|
||||
|
||||
// Timeouts is an optional configuration block used for CRUD operations
|
||||
func Timeouts(o *CustomTimeouts) ResourceOption {
|
||||
return resourceOption(func(ro *resourceOptions) {
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
// Copyright 2016-2021, 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 (
|
||||
|
@ -280,3 +294,26 @@ func assertTransformations(t *testing.T, t1 []ResourceTransformation, t2 []Resou
|
|||
assert.Equal(t, p1, p2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceOptionMergingReplaceOnChanges(t *testing.T) {
|
||||
// ReplaceOnChanges arrays are always appended together
|
||||
i1 := "a"
|
||||
i2 := "b"
|
||||
i3 := "c"
|
||||
|
||||
// two singleton options
|
||||
opts := merge(ReplaceOnChanges([]string{i1}), ReplaceOnChanges([]string{i2}))
|
||||
assert.Equal(t, []string{i1, i2}, opts.ReplaceOnChanges)
|
||||
|
||||
// nil i1
|
||||
opts = merge(ReplaceOnChanges(nil), ReplaceOnChanges([]string{i2}))
|
||||
assert.Equal(t, []string{i2}, opts.ReplaceOnChanges)
|
||||
|
||||
// nil i2
|
||||
opts = merge(ReplaceOnChanges([]string{i1}), ReplaceOnChanges(nil))
|
||||
assert.Equal(t, []string{i1}, opts.ReplaceOnChanges)
|
||||
|
||||
// multivalue arrays
|
||||
opts = merge(ReplaceOnChanges([]string{i1, i2}), ReplaceOnChanges([]string{i2, i3}))
|
||||
assert.Equal(t, []string{i1, i2, i2, i3}, opts.ReplaceOnChanges)
|
||||
}
|
||||
|
|
|
@ -1230,7 +1230,7 @@ proto.pulumirpc.ReadResourceResponse.prototype.hasProperties = function() {
|
|||
* @private {!Array<number>}
|
||||
* @const
|
||||
*/
|
||||
proto.pulumirpc.RegisterResourceRequest.repeatedFields_ = [7,12,14,15];
|
||||
proto.pulumirpc.RegisterResourceRequest.repeatedFields_ = [7,12,14,15,23];
|
||||
|
||||
|
||||
|
||||
|
@ -1284,7 +1284,8 @@ proto.pulumirpc.RegisterResourceRequest.toObject = function(includeInstance, msg
|
|||
supportspartialvalues: jspb.Message.getBooleanFieldWithDefault(msg, 19, false),
|
||||
remote: jspb.Message.getBooleanFieldWithDefault(msg, 20, false),
|
||||
acceptresources: jspb.Message.getBooleanFieldWithDefault(msg, 21, false),
|
||||
providersMap: (f = msg.getProvidersMap()) ? f.toObject(includeInstance, undefined) : []
|
||||
providersMap: (f = msg.getProvidersMap()) ? f.toObject(includeInstance, undefined) : [],
|
||||
replaceonchangesList: (f = jspb.Message.getRepeatedField(msg, 23)) == null ? undefined : f
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
|
@ -1415,6 +1416,10 @@ proto.pulumirpc.RegisterResourceRequest.deserializeBinaryFromReader = function(m
|
|||
jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readString, null, "", "");
|
||||
});
|
||||
break;
|
||||
case 23:
|
||||
var value = /** @type {string} */ (reader.readString());
|
||||
msg.addReplaceonchanges(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
|
@ -1594,6 +1599,13 @@ proto.pulumirpc.RegisterResourceRequest.serializeBinaryToWriter = function(messa
|
|||
if (f && f.getLength() > 0) {
|
||||
f.serializeBinary(22, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString);
|
||||
}
|
||||
f = message.getReplaceonchangesList();
|
||||
if (f.length > 0) {
|
||||
writer.writeRepeatedString(
|
||||
23,
|
||||
f
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -2461,6 +2473,43 @@ proto.pulumirpc.RegisterResourceRequest.prototype.clearProvidersMap = function()
|
|||
return this;};
|
||||
|
||||
|
||||
/**
|
||||
* repeated string replaceOnChanges = 23;
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
proto.pulumirpc.RegisterResourceRequest.prototype.getReplaceonchangesList = function() {
|
||||
return /** @type {!Array<string>} */ (jspb.Message.getRepeatedField(this, 23));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Array<string>} value
|
||||
* @return {!proto.pulumirpc.RegisterResourceRequest} returns this
|
||||
*/
|
||||
proto.pulumirpc.RegisterResourceRequest.prototype.setReplaceonchangesList = function(value) {
|
||||
return jspb.Message.setField(this, 23, value || []);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @param {number=} opt_index
|
||||
* @return {!proto.pulumirpc.RegisterResourceRequest} returns this
|
||||
*/
|
||||
proto.pulumirpc.RegisterResourceRequest.prototype.addReplaceonchanges = function(value, opt_index) {
|
||||
return jspb.Message.addToRepeatedField(this, 23, value, opt_index);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the list making it empty but non-null.
|
||||
* @return {!proto.pulumirpc.RegisterResourceRequest} returns this
|
||||
*/
|
||||
proto.pulumirpc.RegisterResourceRequest.prototype.clearReplaceonchangesList = function() {
|
||||
return this.setReplaceonchangesList([]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* List of repeated fields within this message type.
|
||||
|
|
|
@ -491,6 +491,12 @@ export interface ResourceOptions {
|
|||
* Ignore changes to any of the specified properties.
|
||||
*/
|
||||
ignoreChanges?: string[];
|
||||
/**
|
||||
* Changes to any of these property paths will force a replacement. If this list includes `"*"`, changes to any
|
||||
* properties will force a replacement. Initialization errors from previous deployments will require replacement
|
||||
* instead of update only if `"*"` is passed.
|
||||
*/
|
||||
replaceOnChanges?: string[];
|
||||
/**
|
||||
* An optional version, corresponding to the version of the provider plugin that should be used when operating on
|
||||
* this resource. This version overrides the version information inferred from the current package and should
|
||||
|
|
|
@ -316,6 +316,7 @@ export function registerResource(res: Resource, t: string, name: string, custom:
|
|||
req.setImportid(resop.import || "");
|
||||
req.setSupportspartialvalues(true);
|
||||
req.setRemote(remote);
|
||||
req.setReplaceonchangesList(opts.replaceOnChanges || []);
|
||||
|
||||
const customTimeouts = new resproto.RegisterResourceRequest.CustomTimeouts();
|
||||
if (opts.customTimeouts != null) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// This tests the replaceOnChanges ResourceOption.
|
||||
|
||||
let pulumi = require("../../../../../");
|
||||
|
||||
class MyResource extends pulumi.CustomResource {
|
||||
constructor(name, opts) {
|
||||
super("test:index:MyResource", name, {}, opts);
|
||||
}
|
||||
}
|
||||
|
||||
new MyResource("testResource", { replaceOnChanges: ["foo"] });
|
|
@ -53,7 +53,10 @@ interface RunCase {
|
|||
};
|
||||
registerResource?: (ctx: any, dryrun: boolean, t: string, name: string, res: any, dependencies?: string[],
|
||||
custom?: boolean, protect?: boolean, parent?: string, provider?: string,
|
||||
propertyDeps?: any, ignoreChanges?: string[], version?: string, importID?: string) => { urn: URN | undefined, id: ID | undefined, props: any | undefined };
|
||||
propertyDeps?: any, ignoreChanges?: string[], version?: string, importID?: string,
|
||||
replaceOnChanges?: string[]) => {
|
||||
urn: URN | undefined, id: ID | undefined, props: any | undefined,
|
||||
};
|
||||
registerResourceOutputs?: (ctx: any, dryrun: boolean, urn: URN,
|
||||
t: string, name: string, res: any, outputs: any | undefined) => void;
|
||||
log?: (ctx: any, severity: any, message: string, urn: URN, streamId: number) => void;
|
||||
|
@ -808,7 +811,9 @@ describe("rpc", () => {
|
|||
expectResourceCount: 3,
|
||||
registerResource: (ctx: any, dryrun: boolean, t: string, name: string, res: any, dependencies?: string[],
|
||||
custom?: boolean, protect?: boolean, parent?: string, provider?: string,
|
||||
propertyDeps?: any, ignoreChanges?: string[], version?: string) => {
|
||||
propertyDeps?: any, ignoreChanges?: string[], version?: string, importID?: string,
|
||||
replaceOnChanges?: string[],
|
||||
) => {
|
||||
switch (name) {
|
||||
case "testResource":
|
||||
assert.strictEqual("0.19.1", version);
|
||||
|
@ -1157,6 +1162,25 @@ describe("rpc", () => {
|
|||
};
|
||||
},
|
||||
},
|
||||
"replace_on_changes": {
|
||||
program: path.join(base, "066.replace_on_changes"),
|
||||
expectResourceCount: 1,
|
||||
registerResource: (
|
||||
ctx: any, dryrun: boolean, t: string, name: string, res: any, dependencies?: string[],
|
||||
custom?: boolean, protect?: boolean, parent?: string, provider?: string,
|
||||
propertyDeps?: any, ignoreChanges?: string[], version?: string, importID?: string,
|
||||
replaceOnChanges?: string[],
|
||||
) => {
|
||||
if (name === "testResource") {
|
||||
assert.deepStrictEqual(replaceOnChanges, ["foo"]);
|
||||
}
|
||||
return {
|
||||
urn: makeUrn(t, name),
|
||||
id: name,
|
||||
props: {},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
for (const casename of Object.keys(cases)) {
|
||||
|
@ -1224,6 +1248,7 @@ describe("rpc", () => {
|
|||
const parent: string = req.getParent();
|
||||
const provider: string = req.getProvider();
|
||||
const ignoreChanges: string[] = req.getIgnorechangesList().sort();
|
||||
const replaceOnChanges: string[] = req.getReplaceonchangesList().sort();
|
||||
const propertyDeps: any = Array.from(req.getPropertydependenciesMap().entries())
|
||||
.reduce((o: any, [key, value]: any) => {
|
||||
return { ...o, [key]: value.getUrnsList().sort() };
|
||||
|
@ -1231,7 +1256,7 @@ describe("rpc", () => {
|
|||
const version: string = req.getVersion();
|
||||
const importID: string = req.getImportid();
|
||||
const { urn, id, props } = opts.registerResource(ctx, dryrun, t, name, res, deps,
|
||||
custom, protect, parent, provider, propertyDeps, ignoreChanges, version, importID);
|
||||
custom, protect, parent, provider, propertyDeps, ignoreChanges, version, importID, replaceOnChanges);
|
||||
resp.setUrn(urn);
|
||||
resp.setId(id);
|
||||
resp.setObject(gstruct.Struct.fromJavaScript(props));
|
||||
|
|
|
@ -306,6 +306,7 @@ type RegisterResourceRequest struct {
|
|||
Remote bool `protobuf:"varint,20,opt,name=remote,proto3" json:"remote,omitempty"`
|
||||
AcceptResources bool `protobuf:"varint,21,opt,name=acceptResources,proto3" json:"acceptResources,omitempty"`
|
||||
Providers map[string]string `protobuf:"bytes,22,rep,name=providers,proto3" json:"providers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
ReplaceOnChanges []string `protobuf:"bytes,23,rep,name=replaceOnChanges,proto3" json:"replaceOnChanges,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
@ -490,6 +491,13 @@ func (m *RegisterResourceRequest) GetProviders() map[string]string {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *RegisterResourceRequest) GetReplaceOnChanges() []string {
|
||||
if m != nil {
|
||||
return m.ReplaceOnChanges
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PropertyDependencies describes the resources that a particular property depends on.
|
||||
type RegisterResourceRequest_PropertyDependencies struct {
|
||||
Urns []string `protobuf:"bytes,1,rep,name=urns,proto3" json:"urns,omitempty"`
|
||||
|
@ -784,70 +792,71 @@ func init() {
|
|||
func init() { proto.RegisterFile("resource.proto", fileDescriptor_d1b72f771c35e3b8) }
|
||||
|
||||
var fileDescriptor_d1b72f771c35e3b8 = []byte{
|
||||
// 995 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x4f, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0x8f, 0xed, 0xd4, 0xb1, 0x5f, 0x52, 0x27, 0x4c, 0x52, 0x67, 0xba, 0xa0, 0x10, 0x16, 0x0e,
|
||||
0x86, 0x83, 0xd3, 0x04, 0xa4, 0xa6, 0xa8, 0x80, 0x44, 0x5a, 0x50, 0x0f, 0xa5, 0x65, 0x83, 0x10,
|
||||
0x20, 0x81, 0x34, 0xd9, 0x7d, 0x49, 0x97, 0xac, 0x77, 0xb6, 0x33, 0xb3, 0x91, 0x7c, 0x83, 0xef,
|
||||
0xc1, 0x85, 0xaf, 0x82, 0xf8, 0x60, 0x68, 0x66, 0x76, 0xdc, 0x5d, 0xef, 0x3a, 0x71, 0xca, 0x6d,
|
||||
0xdf, 0x7f, 0xcf, 0xef, 0xfd, 0xde, 0x9b, 0x31, 0x0c, 0x04, 0x4a, 0x9e, 0x8b, 0x10, 0xc7, 0x99,
|
||||
0xe0, 0x8a, 0x93, 0x7e, 0x96, 0x27, 0xf9, 0x24, 0x16, 0x59, 0xe8, 0xbd, 0x7b, 0xc1, 0xf9, 0x45,
|
||||
0x82, 0x07, 0xc6, 0x70, 0x96, 0x9f, 0x1f, 0xe0, 0x24, 0x53, 0x53, 0xeb, 0xe7, 0xbd, 0x37, 0x6f,
|
||||
0x94, 0x4a, 0xe4, 0xa1, 0x2a, 0xac, 0x83, 0x4c, 0xf0, 0xab, 0x38, 0x42, 0x61, 0x65, 0x7f, 0x04,
|
||||
0xc3, 0xd3, 0x3c, 0xcb, 0xb8, 0x50, 0xf2, 0x1b, 0x64, 0x2a, 0x17, 0x18, 0xe0, 0xeb, 0x1c, 0xa5,
|
||||
0x22, 0x03, 0x68, 0xc7, 0x11, 0x6d, 0xed, 0xb7, 0x46, 0xfd, 0xa0, 0x1d, 0x47, 0xfe, 0x23, 0xd8,
|
||||
0xad, 0x79, 0xca, 0x8c, 0xa7, 0x12, 0xc9, 0x1e, 0xc0, 0x2b, 0x26, 0x0b, 0xab, 0x09, 0xe9, 0x05,
|
||||
0x25, 0x8d, 0xff, 0x57, 0x07, 0xb6, 0x03, 0x64, 0x51, 0x50, 0x9c, 0x68, 0x41, 0x09, 0x42, 0x60,
|
||||
0x55, 0x4d, 0x33, 0xa4, 0x6d, 0xa3, 0x31, 0xdf, 0x5a, 0x97, 0xb2, 0x09, 0xd2, 0x8e, 0xd5, 0xe9,
|
||||
0x6f, 0x32, 0x84, 0x6e, 0xc6, 0x04, 0xa6, 0x8a, 0xae, 0x1a, 0x6d, 0x21, 0x91, 0x87, 0x00, 0x99,
|
||||
0xe0, 0x19, 0x0a, 0x15, 0xa3, 0xa4, 0x77, 0xf6, 0x5b, 0xa3, 0xf5, 0xa3, 0xdd, 0xb1, 0xc5, 0x63,
|
||||
0xec, 0xf0, 0x18, 0x9f, 0x1a, 0x3c, 0x82, 0x92, 0x2b, 0xf1, 0x61, 0x23, 0xc2, 0x0c, 0xd3, 0x08,
|
||||
0xd3, 0x50, 0x87, 0x76, 0xf7, 0x3b, 0xa3, 0x7e, 0x50, 0xd1, 0x11, 0x0f, 0x7a, 0x0e, 0x3b, 0xba,
|
||||
0x66, 0xca, 0xce, 0x64, 0x42, 0x61, 0xed, 0x0a, 0x85, 0x8c, 0x79, 0x4a, 0x7b, 0xc6, 0xe4, 0x44,
|
||||
0xf2, 0x11, 0xdc, 0x65, 0x61, 0x88, 0x99, 0x3a, 0xc5, 0x50, 0xa0, 0x92, 0xb4, 0x6f, 0xd0, 0xa9,
|
||||
0x2a, 0xc9, 0x31, 0xec, 0xb2, 0x28, 0x8a, 0x55, 0xcc, 0x53, 0x96, 0x58, 0xe5, 0x8b, 0x5c, 0x65,
|
||||
0xb9, 0x92, 0x14, 0xcc, 0x4f, 0x59, 0x64, 0xd6, 0x95, 0x59, 0x12, 0x33, 0x89, 0x92, 0xae, 0x1b,
|
||||
0x4f, 0x27, 0x92, 0x11, 0x6c, 0xda, 0x22, 0x0e, 0x75, 0x49, 0x37, 0x4c, 0xed, 0x79, 0xb5, 0xcf,
|
||||
0x60, 0xa7, 0xda, 0x9d, 0xa2, 0xad, 0x5b, 0xd0, 0xc9, 0x45, 0x5a, 0xf4, 0x47, 0x7f, 0xce, 0x01,
|
||||
0xdc, 0x5e, 0x1a, 0x60, 0xff, 0x6f, 0x80, 0xdd, 0x00, 0x2f, 0x62, 0xa9, 0x50, 0xcc, 0xb3, 0xc0,
|
||||
0x75, 0xbd, 0xd5, 0xd0, 0xf5, 0x76, 0x63, 0xd7, 0x3b, 0x95, 0xae, 0x0f, 0xa1, 0x1b, 0xe6, 0x52,
|
||||
0xf1, 0x89, 0x61, 0x43, 0x2f, 0x28, 0x24, 0x72, 0x00, 0x5d, 0x7e, 0xf6, 0x3b, 0x86, 0xea, 0x26,
|
||||
0x26, 0x14, 0x6e, 0x1a, 0x4b, 0x6d, 0xd2, 0x11, 0x5d, 0x93, 0xc9, 0x89, 0x35, 0x7e, 0xac, 0xdd,
|
||||
0xc0, 0x8f, 0xde, 0x1c, 0x3f, 0x32, 0xd8, 0x29, 0xc0, 0x98, 0x3e, 0x29, 0xe7, 0xe9, 0xef, 0x77,
|
||||
0x46, 0xeb, 0x47, 0x8f, 0xc7, 0xb3, 0xd1, 0x1e, 0x2f, 0x00, 0x69, 0xfc, 0xb2, 0x21, 0xfc, 0x69,
|
||||
0xaa, 0xc4, 0x34, 0x68, 0xcc, 0x4c, 0x1e, 0xc0, 0x76, 0x84, 0x09, 0x2a, 0xfc, 0x1a, 0xcf, 0xb9,
|
||||
0x1e, 0xd5, 0x2c, 0x61, 0x21, 0x52, 0x30, 0xe7, 0x6a, 0x32, 0x95, 0x39, 0xbc, 0x5e, 0xe3, 0x70,
|
||||
0x7c, 0x91, 0x72, 0x81, 0x27, 0xaf, 0x58, 0x7a, 0x61, 0x78, 0xa4, 0x8f, 0x5f, 0x55, 0xd6, 0x99,
|
||||
0x7e, 0xf7, 0x96, 0x4c, 0x1f, 0x2c, 0xcd, 0xf4, 0xcd, 0x2a, 0xd3, 0x3d, 0xe8, 0xc5, 0x13, 0xbd,
|
||||
0x68, 0x9e, 0x45, 0x74, 0xcb, 0x22, 0xef, 0x64, 0xf2, 0x33, 0x0c, 0x2c, 0x1d, 0x7e, 0x88, 0x27,
|
||||
0xc8, 0x75, 0x99, 0x77, 0x0c, 0x19, 0x0e, 0x97, 0xc0, 0xfc, 0xa4, 0x12, 0x18, 0xcc, 0x25, 0x22,
|
||||
0x5f, 0x82, 0xd7, 0x80, 0xe3, 0x13, 0x3c, 0x8f, 0x53, 0x8c, 0x28, 0x31, 0xa7, 0xbf, 0xc6, 0x83,
|
||||
0x7c, 0x06, 0xf7, 0x64, 0xb1, 0x50, 0x5f, 0x32, 0xa1, 0x62, 0x96, 0xfc, 0xc8, 0x92, 0x1c, 0x25,
|
||||
0xdd, 0x36, 0xa1, 0xcd, 0x46, 0xcd, 0x76, 0x81, 0x13, 0xae, 0x90, 0xee, 0x58, 0xb6, 0x5b, 0xa9,
|
||||
0x69, 0xdc, 0xef, 0x35, 0x8e, 0x3b, 0x79, 0x01, 0x7d, 0x47, 0x4c, 0x49, 0x87, 0x86, 0x81, 0x87,
|
||||
0xcb, 0x31, 0xd0, 0xc6, 0x58, 0xda, 0xbd, 0xc9, 0xe1, 0x7d, 0x02, 0x3b, 0x4d, 0xf4, 0xd4, 0x43,
|
||||
0x9c, 0x8b, 0x54, 0xd2, 0x96, 0x69, 0x97, 0xf9, 0xf6, 0x7e, 0x82, 0x41, 0x15, 0x56, 0x33, 0xbe,
|
||||
0x02, 0x99, 0x72, 0x0b, 0xa0, 0x90, 0xb4, 0x3e, 0xcf, 0x22, 0xad, 0xb7, 0x4b, 0xa0, 0x90, 0xb4,
|
||||
0xde, 0x82, 0xea, 0xd6, 0x80, 0x95, 0xbc, 0x3f, 0x5a, 0x70, 0x7f, 0xe1, 0x94, 0xe8, 0x5d, 0x76,
|
||||
0x89, 0x53, 0xb7, 0xcb, 0x2e, 0x71, 0x4a, 0x9e, 0xc3, 0x9d, 0x2b, 0x0d, 0x69, 0xb1, 0xc6, 0x1e,
|
||||
0xbe, 0xe5, 0x10, 0x06, 0x36, 0xcb, 0xe7, 0xed, 0xe3, 0x96, 0xf7, 0x18, 0x06, 0x55, 0x94, 0x1a,
|
||||
0xca, 0xee, 0x94, 0xcb, 0xf6, 0x4b, 0xd1, 0xfe, 0x3f, 0x1d, 0xa0, 0xf5, 0xca, 0x0b, 0x77, 0xb1,
|
||||
0xbd, 0x3c, 0xdb, 0xb3, 0xcb, 0xf3, 0xcd, 0xba, 0xeb, 0x2c, 0xb7, 0xee, 0x86, 0xd0, 0x95, 0x8a,
|
||||
0x9d, 0x25, 0xe8, 0xf6, 0xa6, 0x95, 0xf4, 0xa0, 0xd9, 0x2f, 0x7d, 0x85, 0x9a, 0x41, 0x2b, 0x44,
|
||||
0xf2, 0x7a, 0xc1, 0x1a, 0xeb, 0x1a, 0x12, 0x7d, 0x71, 0x2d, 0x82, 0xf6, 0x1c, 0xb7, 0xdd, 0x63,
|
||||
0xb7, 0xe2, 0xd6, 0x9f, 0xb7, 0x64, 0xc0, 0x77, 0x55, 0x06, 0x1c, 0xbf, 0xed, 0xef, 0x2f, 0x37,
|
||||
0x11, 0x61, 0x6f, 0x3e, 0xb6, 0x58, 0x60, 0xee, 0xba, 0xab, 0x77, 0xf2, 0x10, 0xd6, 0x78, 0xb1,
|
||||
0x03, 0x6f, 0xb8, 0x52, 0x9d, 0xdf, 0xd1, 0xbf, 0xab, 0xb0, 0xe9, 0xf2, 0x3f, 0xe7, 0x69, 0xac,
|
||||
0xb8, 0x20, 0xbf, 0xc0, 0xe6, 0xdc, 0x03, 0x8d, 0x7c, 0x50, 0x3a, 0x52, 0xf3, 0x33, 0xcf, 0xf3,
|
||||
0xaf, 0x73, 0xb1, 0x87, 0xf6, 0x57, 0xc8, 0x57, 0xd0, 0x7d, 0x96, 0x5e, 0xf1, 0x4b, 0x24, 0xb4,
|
||||
0xe4, 0x6f, 0x55, 0x2e, 0xd3, 0xfd, 0x06, 0xcb, 0x2c, 0xc1, 0xb7, 0xb0, 0x71, 0xaa, 0x04, 0xb2,
|
||||
0xc9, 0xff, 0x4a, 0xf3, 0xa0, 0x45, 0x1e, 0xc1, 0xea, 0x09, 0x4b, 0x12, 0x32, 0x2c, 0xb9, 0x69,
|
||||
0x85, 0x0b, 0xdf, 0xad, 0xe9, 0x67, 0xbf, 0xe1, 0x7b, 0xd8, 0x28, 0xbf, 0x73, 0xc8, 0x5e, 0xa5,
|
||||
0xe1, 0xb5, 0xe7, 0xa9, 0xf7, 0xfe, 0x42, 0xfb, 0x2c, 0xe5, 0xaf, 0xb0, 0x35, 0xdf, 0x6e, 0xe2,
|
||||
0xdf, 0xbc, 0x49, 0xbc, 0x0f, 0x97, 0xe0, 0x9a, 0xbf, 0x42, 0x7e, 0xab, 0xbf, 0x9a, 0xdc, 0x75,
|
||||
0xf8, 0xf1, 0x35, 0x19, 0xaa, 0x8c, 0xf3, 0x86, 0x35, 0x3a, 0x3d, 0xd5, 0xff, 0x17, 0xfc, 0x95,
|
||||
0xb3, 0xae, 0xd1, 0x7c, 0xfa, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x91, 0x5b, 0x6c,
|
||||
0x0c, 0x00, 0x00,
|
||||
// 1010 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x5f, 0x6f, 0x1b, 0x45,
|
||||
0x10, 0x8f, 0xed, 0xd4, 0xb1, 0x27, 0xa9, 0x13, 0x36, 0xa9, 0xbd, 0x3d, 0x50, 0x08, 0x07, 0x0f,
|
||||
0xa6, 0x0f, 0x4e, 0x13, 0x90, 0x9a, 0xa2, 0x02, 0x12, 0x69, 0x41, 0x7d, 0x28, 0x29, 0x17, 0x84,
|
||||
0x00, 0x09, 0xa4, 0x8d, 0x6f, 0x92, 0x1e, 0x39, 0xdf, 0x5e, 0x77, 0xf7, 0x22, 0xf9, 0x0d, 0xbe,
|
||||
0x07, 0x9f, 0x06, 0xf1, 0xca, 0x77, 0x42, 0xbb, 0x7b, 0xeb, 0xde, 0xf9, 0xce, 0x89, 0xd3, 0xbe,
|
||||
0xdd, 0xfc, 0xe6, 0x9f, 0x77, 0xe6, 0x37, 0xb3, 0x6b, 0xe8, 0x09, 0x94, 0x3c, 0x13, 0x63, 0x1c,
|
||||
0xa5, 0x82, 0x2b, 0x4e, 0xba, 0x69, 0x16, 0x67, 0x93, 0x48, 0xa4, 0x63, 0xef, 0xfd, 0x0b, 0xce,
|
||||
0x2f, 0x62, 0xdc, 0x37, 0x8a, 0xb3, 0xec, 0x7c, 0x1f, 0x27, 0xa9, 0x9a, 0x5a, 0x3b, 0xef, 0x83,
|
||||
0x79, 0xa5, 0x54, 0x22, 0x1b, 0xab, 0x5c, 0xdb, 0x4b, 0x05, 0xbf, 0x8a, 0x42, 0x14, 0x56, 0xf6,
|
||||
0x87, 0xd0, 0x3f, 0xcd, 0xd2, 0x94, 0x0b, 0x25, 0xbf, 0x45, 0xa6, 0x32, 0x81, 0x01, 0xbe, 0xce,
|
||||
0x50, 0x2a, 0xd2, 0x83, 0x66, 0x14, 0xd2, 0xc6, 0x5e, 0x63, 0xd8, 0x0d, 0x9a, 0x51, 0xe8, 0x3f,
|
||||
0x86, 0x41, 0xc5, 0x52, 0xa6, 0x3c, 0x91, 0x48, 0x76, 0x01, 0x5e, 0x31, 0x99, 0x6b, 0x8d, 0x4b,
|
||||
0x27, 0x28, 0x20, 0xfe, 0xdf, 0x2d, 0xd8, 0x0e, 0x90, 0x85, 0x41, 0x7e, 0xa2, 0x05, 0x29, 0x08,
|
||||
0x81, 0x55, 0x35, 0x4d, 0x91, 0x36, 0x0d, 0x62, 0xbe, 0x35, 0x96, 0xb0, 0x09, 0xd2, 0x96, 0xc5,
|
||||
0xf4, 0x37, 0xe9, 0x43, 0x3b, 0x65, 0x02, 0x13, 0x45, 0x57, 0x0d, 0x9a, 0x4b, 0xe4, 0x11, 0x40,
|
||||
0x2a, 0x78, 0x8a, 0x42, 0x45, 0x28, 0xe9, 0x9d, 0xbd, 0xc6, 0x70, 0xfd, 0x70, 0x30, 0xb2, 0xf5,
|
||||
0x18, 0xb9, 0x7a, 0x8c, 0x4e, 0x4d, 0x3d, 0x82, 0x82, 0x29, 0xf1, 0x61, 0x23, 0xc4, 0x14, 0x93,
|
||||
0x10, 0x93, 0xb1, 0x76, 0x6d, 0xef, 0xb5, 0x86, 0xdd, 0xa0, 0x84, 0x11, 0x0f, 0x3a, 0xae, 0x76,
|
||||
0x74, 0xcd, 0xa4, 0x9d, 0xc9, 0x84, 0xc2, 0xda, 0x15, 0x0a, 0x19, 0xf1, 0x84, 0x76, 0x8c, 0xca,
|
||||
0x89, 0xe4, 0x13, 0xb8, 0xcb, 0xc6, 0x63, 0x4c, 0xd5, 0x29, 0x8e, 0x05, 0x2a, 0x49, 0xbb, 0xa6,
|
||||
0x3a, 0x65, 0x90, 0x1c, 0xc1, 0x80, 0x85, 0x61, 0xa4, 0x22, 0x9e, 0xb0, 0xd8, 0x82, 0x27, 0x99,
|
||||
0x4a, 0x33, 0x25, 0x29, 0x98, 0x9f, 0xb2, 0x48, 0xad, 0x33, 0xb3, 0x38, 0x62, 0x12, 0x25, 0x5d,
|
||||
0x37, 0x96, 0x4e, 0x24, 0x43, 0xd8, 0xb4, 0x49, 0x5c, 0xd5, 0x25, 0xdd, 0x30, 0xb9, 0xe7, 0x61,
|
||||
0x9f, 0xc1, 0x4e, 0xb9, 0x3b, 0x79, 0x5b, 0xb7, 0xa0, 0x95, 0x89, 0x24, 0xef, 0x8f, 0xfe, 0x9c,
|
||||
0x2b, 0x70, 0x73, 0xe9, 0x02, 0xfb, 0xff, 0x01, 0x0c, 0x02, 0xbc, 0x88, 0xa4, 0x42, 0x31, 0xcf,
|
||||
0x02, 0xd7, 0xf5, 0x46, 0x4d, 0xd7, 0x9b, 0xb5, 0x5d, 0x6f, 0x95, 0xba, 0xde, 0x87, 0xf6, 0x38,
|
||||
0x93, 0x8a, 0x4f, 0x0c, 0x1b, 0x3a, 0x41, 0x2e, 0x91, 0x7d, 0x68, 0xf3, 0xb3, 0x3f, 0x70, 0xac,
|
||||
0x6e, 0x62, 0x42, 0x6e, 0xa6, 0x6b, 0xa9, 0x55, 0xda, 0xa3, 0x6d, 0x22, 0x39, 0xb1, 0xc2, 0x8f,
|
||||
0xb5, 0x1b, 0xf8, 0xd1, 0x99, 0xe3, 0x47, 0x0a, 0x3b, 0x79, 0x31, 0xa6, 0x4f, 0x8b, 0x71, 0xba,
|
||||
0x7b, 0xad, 0xe1, 0xfa, 0xe1, 0x93, 0xd1, 0x6c, 0xb4, 0x47, 0x0b, 0x8a, 0x34, 0x7a, 0x59, 0xe3,
|
||||
0xfe, 0x2c, 0x51, 0x62, 0x1a, 0xd4, 0x46, 0x26, 0x0f, 0x61, 0x3b, 0xc4, 0x18, 0x15, 0x7e, 0x83,
|
||||
0xe7, 0x5c, 0x8f, 0x6a, 0x1a, 0xb3, 0x31, 0x52, 0x30, 0xe7, 0xaa, 0x53, 0x15, 0x39, 0xbc, 0x5e,
|
||||
0xe1, 0x70, 0x74, 0x91, 0x70, 0x81, 0xc7, 0xaf, 0x58, 0x72, 0x61, 0x78, 0xa4, 0x8f, 0x5f, 0x06,
|
||||
0xab, 0x4c, 0xbf, 0x7b, 0x4b, 0xa6, 0xf7, 0x96, 0x66, 0xfa, 0x66, 0x99, 0xe9, 0x1e, 0x74, 0xa2,
|
||||
0x89, 0x5e, 0x34, 0xcf, 0x43, 0xba, 0x65, 0x2b, 0xef, 0x64, 0xf2, 0x0b, 0xf4, 0x2c, 0x1d, 0x7e,
|
||||
0x8c, 0x26, 0xc8, 0x75, 0x9a, 0xf7, 0x0c, 0x19, 0x0e, 0x96, 0xa8, 0xf9, 0x71, 0xc9, 0x31, 0x98,
|
||||
0x0b, 0x44, 0xbe, 0x02, 0xaf, 0xa6, 0x8e, 0x4f, 0xf1, 0x3c, 0x4a, 0x30, 0xa4, 0xc4, 0x9c, 0xfe,
|
||||
0x1a, 0x0b, 0xf2, 0x39, 0xdc, 0x93, 0xf9, 0x42, 0x7d, 0xc9, 0x84, 0x8a, 0x58, 0xfc, 0x13, 0x8b,
|
||||
0x33, 0x94, 0x74, 0xdb, 0xb8, 0xd6, 0x2b, 0x35, 0xdb, 0x05, 0x4e, 0xb8, 0x42, 0xba, 0x63, 0xd9,
|
||||
0x6e, 0xa5, 0xba, 0x71, 0xbf, 0x57, 0x3b, 0xee, 0xe4, 0x04, 0xba, 0x8e, 0x98, 0x92, 0xf6, 0x0d,
|
||||
0x03, 0x0f, 0x96, 0x63, 0xa0, 0xf5, 0xb1, 0xb4, 0x7b, 0x13, 0x83, 0x3c, 0x80, 0x2d, 0x61, 0x8f,
|
||||
0x76, 0x92, 0x38, 0x8a, 0x0c, 0x4c, 0x8b, 0x2a, 0xb8, 0xf7, 0x00, 0x76, 0xea, 0xa8, 0xac, 0x07,
|
||||
0x3e, 0x13, 0x89, 0xa4, 0x0d, 0xe3, 0x67, 0xbe, 0xbd, 0x9f, 0xa1, 0x57, 0x6e, 0x81, 0x19, 0x75,
|
||||
0x81, 0x4c, 0xb9, 0x65, 0x91, 0x4b, 0x1a, 0xcf, 0xd2, 0x50, 0xe3, 0x76, 0x61, 0xe4, 0x92, 0xc6,
|
||||
0x6d, 0x03, 0xdc, 0xca, 0xb0, 0x92, 0xf7, 0x67, 0x03, 0xee, 0x2f, 0x9c, 0x28, 0xbd, 0xf7, 0x2e,
|
||||
0x71, 0xea, 0xf6, 0xde, 0x25, 0x4e, 0xc9, 0x0b, 0xb8, 0x73, 0xa5, 0xcb, 0x9f, 0xaf, 0xbc, 0x47,
|
||||
0x6f, 0x39, 0xb0, 0x81, 0x8d, 0xf2, 0x45, 0xf3, 0xa8, 0xe1, 0x3d, 0x81, 0x5e, 0xb9, 0xa2, 0x35,
|
||||
0x69, 0x77, 0x8a, 0x69, 0xbb, 0x05, 0x6f, 0xff, 0x9f, 0x16, 0xd0, 0x6a, 0xe6, 0x85, 0x7b, 0xdb,
|
||||
0x5e, 0xb4, 0xcd, 0xd9, 0x45, 0xfb, 0x66, 0x35, 0xb6, 0x96, 0x5b, 0x8d, 0x7d, 0x68, 0x4b, 0xc5,
|
||||
0xce, 0x62, 0x74, 0x3b, 0xd6, 0x4a, 0x7a, 0x28, 0xed, 0x97, 0xbe, 0x6e, 0xcd, 0x50, 0xe6, 0x22,
|
||||
0x79, 0xbd, 0x60, 0xe5, 0xb5, 0x0d, 0xe1, 0xbe, 0xbc, 0xb6, 0x82, 0xf6, 0x1c, 0xb7, 0xdd, 0x79,
|
||||
0xb7, 0xe2, 0xd6, 0x5f, 0xb7, 0x64, 0xc0, 0xf7, 0x65, 0x06, 0x1c, 0xbd, 0xed, 0xef, 0x2f, 0x36,
|
||||
0x11, 0x61, 0x77, 0xde, 0x37, 0x5f, 0x76, 0xee, 0x6a, 0xac, 0x76, 0xf2, 0x00, 0xd6, 0x78, 0xbe,
|
||||
0x2f, 0x6f, 0xb8, 0x7e, 0x9d, 0xdd, 0xe1, 0xbf, 0xab, 0xb0, 0xe9, 0xe2, 0xbf, 0xe0, 0x49, 0xa4,
|
||||
0xb8, 0x20, 0xbf, 0xc2, 0xe6, 0xdc, 0x63, 0x8e, 0x7c, 0x54, 0x38, 0x52, 0xfd, 0x93, 0xd0, 0xf3,
|
||||
0xaf, 0x33, 0xb1, 0x87, 0xf6, 0x57, 0xc8, 0xd7, 0xd0, 0x7e, 0x9e, 0x5c, 0xf1, 0x4b, 0x24, 0xb4,
|
||||
0x60, 0x6f, 0x21, 0x17, 0xe9, 0x7e, 0x8d, 0x66, 0x16, 0xe0, 0x3b, 0xd8, 0x38, 0x55, 0x02, 0xd9,
|
||||
0xe4, 0x9d, 0xc2, 0x3c, 0x6c, 0x90, 0xc7, 0xb0, 0x7a, 0xcc, 0xe2, 0x98, 0xf4, 0x0b, 0x66, 0x1a,
|
||||
0x70, 0xee, 0x83, 0x0a, 0x3e, 0xfb, 0x0d, 0x3f, 0xc0, 0x46, 0xf1, 0x4d, 0x44, 0x76, 0x4b, 0x0d,
|
||||
0xaf, 0x3c, 0x65, 0xbd, 0x0f, 0x17, 0xea, 0x67, 0x21, 0x7f, 0x83, 0xad, 0xf9, 0x76, 0x13, 0xff,
|
||||
0xe6, 0x4d, 0xe2, 0x7d, 0xbc, 0x04, 0xd7, 0xfc, 0x15, 0xf2, 0x7b, 0xf5, 0x85, 0xe5, 0xae, 0xce,
|
||||
0x4f, 0xaf, 0x89, 0x50, 0x66, 0x9c, 0xd7, 0xaf, 0xd0, 0xe9, 0x99, 0xfe, 0x6f, 0xe1, 0xaf, 0x9c,
|
||||
0xb5, 0x0d, 0xf2, 0xd9, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x1f, 0xaf, 0x2d, 0x98, 0x0c,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -104,6 +104,7 @@ message RegisterResourceRequest {
|
|||
bool remote = 20; // true if the resource is a plugin-managed component resource.
|
||||
bool acceptResources = 21; // when true operations should return resource references as strongly typed.
|
||||
map<string, string> providers = 22; // an optional reference to the provider map to manage this resource's CRUD operations.
|
||||
repeated string replaceOnChanges = 23; // a list of properties that if changed should force a replacement.
|
||||
}
|
||||
|
||||
// RegisterResourceResponse is returned by the engine after a resource has finished being initialized. It includes the
|
||||
|
|
|
@ -381,6 +381,13 @@ class ResourceOptions:
|
|||
The URN of a previously-registered resource of this type to read from the engine.
|
||||
"""
|
||||
|
||||
replace_on_changes: Optional[List[str]]
|
||||
"""
|
||||
Changes to any of these property paths will force a replacement. If this list includes `"*"`, changes
|
||||
to any properties will force a replacement. Initialization errors from previous deployments will
|
||||
require replacement instead of update only if `"*"` is passed.
|
||||
"""
|
||||
|
||||
# pylint: disable=redefined-builtin
|
||||
def __init__(self,
|
||||
parent: Optional['Resource'] = None,
|
||||
|
@ -397,7 +404,8 @@ class ResourceOptions:
|
|||
import_: Optional[str] = None,
|
||||
custom_timeouts: Optional['CustomTimeouts'] = None,
|
||||
transformations: Optional[List[ResourceTransformation]] = None,
|
||||
urn: Optional[str] = None) -> None:
|
||||
urn: Optional[str] = None,
|
||||
replace_on_changes: Optional[List[str]] = None) -> None:
|
||||
"""
|
||||
:param Optional[Resource] parent: If provided, the currently-constructing resource should be the child of
|
||||
the provided parent resource.
|
||||
|
@ -430,6 +438,9 @@ class ResourceOptions:
|
|||
:param Optional[List[ResourceTransformation]] transformations: If provided, a list of transformations to apply
|
||||
to this resource during construction.
|
||||
:param Optional[str] urn: The URN of a previously-registered resource of this type to read from the engine.
|
||||
:param Optional[List[str]] replace_on_changes: Changes to any of these property paths will force a replacement.
|
||||
If this list includes `"*"`, changes to any properties will force a replacement. Initialization errors
|
||||
from previous deployments will require replacement instead of update only if `"*"` is passed.
|
||||
"""
|
||||
|
||||
# Expose 'merge' again this this object, but this time as an instance method.
|
||||
|
@ -452,6 +463,7 @@ class ResourceOptions:
|
|||
self.import_ = import_
|
||||
self.transformations = transformations
|
||||
self.urn = urn
|
||||
self.replace_on_changes = replace_on_changes
|
||||
|
||||
if depends_on is not None:
|
||||
for dep in depends_on:
|
||||
|
@ -511,6 +523,7 @@ class ResourceOptions:
|
|||
dest.providers = _merge_lists(dest.providers, source.providers)
|
||||
dest.depends_on = _merge_lists(dest.depends_on, source.depends_on)
|
||||
dest.ignore_changes = _merge_lists(dest.ignore_changes, source.ignore_changes)
|
||||
dest.replace_on_changes = _merge_lists(dest.replace_on_changes, source.replace_on_changes)
|
||||
dest.aliases = _merge_lists(dest.aliases, source.aliases)
|
||||
dest.additional_secret_outputs = _merge_lists(dest.additional_secret_outputs, source.additional_secret_outputs)
|
||||
dest.transformations = _merge_lists(dest.transformations, source.transformations)
|
||||
|
|
|
@ -21,7 +21,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
|
|||
package='pulumirpc',
|
||||
syntax='proto3',
|
||||
serialized_options=None,
|
||||
serialized_pb=b'\n\x0eresource.proto\x12\tpulumirpc\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x0eprovider.proto\"$\n\x16SupportsFeatureRequest\x12\n\n\x02id\x18\x01 \x01(\t\"-\n\x17SupportsFeatureResponse\x12\x12\n\nhasSupport\x18\x01 \x01(\x08\"\x95\x02\n\x13ReadResourceRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0e\n\x06parent\x18\x04 \x01(\t\x12+\n\nproperties\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x14\n\x0c\x64\x65pendencies\x18\x06 \x03(\t\x12\x10\n\x08provider\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\x08 \x01(\t\x12\x15\n\racceptSecrets\x18\t \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\n \x03(\t\x12\x0f\n\x07\x61liases\x18\x0b \x03(\t\x12\x17\n\x0f\x61\x63\x63\x65ptResources\x18\x0c \x01(\x08\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xc0\x07\n\x17RegisterResourceRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06parent\x18\x03 \x01(\t\x12\x0e\n\x06\x63ustom\x18\x04 \x01(\x08\x12\'\n\x06object\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0f\n\x07protect\x18\x06 \x01(\x08\x12\x14\n\x0c\x64\x65pendencies\x18\x07 \x03(\t\x12\x10\n\x08provider\x18\x08 \x01(\t\x12Z\n\x14propertyDependencies\x18\t \x03(\x0b\x32<.pulumirpc.RegisterResourceRequest.PropertyDependenciesEntry\x12\x1b\n\x13\x64\x65leteBeforeReplace\x18\n \x01(\x08\x12\x0f\n\x07version\x18\x0b \x01(\t\x12\x15\n\rignoreChanges\x18\x0c \x03(\t\x12\x15\n\racceptSecrets\x18\r \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\x0e \x03(\t\x12\x0f\n\x07\x61liases\x18\x0f \x03(\t\x12\x10\n\x08importId\x18\x10 \x01(\t\x12I\n\x0e\x63ustomTimeouts\x18\x11 \x01(\x0b\x32\x31.pulumirpc.RegisterResourceRequest.CustomTimeouts\x12\"\n\x1a\x64\x65leteBeforeReplaceDefined\x18\x12 \x01(\x08\x12\x1d\n\x15supportsPartialValues\x18\x13 \x01(\x08\x12\x0e\n\x06remote\x18\x14 \x01(\x08\x12\x17\n\x0f\x61\x63\x63\x65ptResources\x18\x15 \x01(\x08\x12\x44\n\tproviders\x18\x16 \x03(\x0b\x32\x31.pulumirpc.RegisterResourceRequest.ProvidersEntry\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1a@\n\x0e\x43ustomTimeouts\x12\x0e\n\x06\x63reate\x18\x01 \x01(\t\x12\x0e\n\x06update\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\t\x1at\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x46\n\x05value\x18\x02 \x01(\x0b\x32\x37.pulumirpc.RegisterResourceRequest.PropertyDependencies:\x02\x38\x01\x1a\x30\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xf7\x02\n\x18RegisterResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\'\n\x06object\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0e\n\x06stable\x18\x04 \x01(\x08\x12\x0f\n\x07stables\x18\x05 \x03(\t\x12[\n\x14propertyDependencies\x18\x06 \x03(\x0b\x32=.pulumirpc.RegisterResourceResponse.PropertyDependenciesEntry\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1au\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.pulumirpc.RegisterResourceResponse.PropertyDependencies:\x02\x38\x01\"W\n\x1eRegisterResourceOutputsRequest\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12(\n\x07outputs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct2\xc4\x04\n\x0fResourceMonitor\x12Z\n\x0fSupportsFeature\x12!.pulumirpc.SupportsFeatureRequest\x1a\".pulumirpc.SupportsFeatureResponse\"\x00\x12?\n\x06Invoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x12G\n\x0cStreamInvoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x30\x01\x12\x39\n\x04\x43\x61ll\x12\x16.pulumirpc.CallRequest\x1a\x17.pulumirpc.CallResponse\"\x00\x12Q\n\x0cReadResource\x12\x1e.pulumirpc.ReadResourceRequest\x1a\x1f.pulumirpc.ReadResourceResponse\"\x00\x12]\n\x10RegisterResource\x12\".pulumirpc.RegisterResourceRequest\x1a#.pulumirpc.RegisterResourceResponse\"\x00\x12^\n\x17RegisterResourceOutputs\x12).pulumirpc.RegisterResourceOutputsRequest\x1a\x16.google.protobuf.Empty\"\x00\x62\x06proto3'
|
||||
serialized_pb=b'\n\x0eresource.proto\x12\tpulumirpc\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x0eprovider.proto\"$\n\x16SupportsFeatureRequest\x12\n\n\x02id\x18\x01 \x01(\t\"-\n\x17SupportsFeatureResponse\x12\x12\n\nhasSupport\x18\x01 \x01(\x08\"\x95\x02\n\x13ReadResourceRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0e\n\x06parent\x18\x04 \x01(\t\x12+\n\nproperties\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x14\n\x0c\x64\x65pendencies\x18\x06 \x03(\t\x12\x10\n\x08provider\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\x08 \x01(\t\x12\x15\n\racceptSecrets\x18\t \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\n \x03(\t\x12\x0f\n\x07\x61liases\x18\x0b \x03(\t\x12\x17\n\x0f\x61\x63\x63\x65ptResources\x18\x0c \x01(\x08\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xda\x07\n\x17RegisterResourceRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06parent\x18\x03 \x01(\t\x12\x0e\n\x06\x63ustom\x18\x04 \x01(\x08\x12\'\n\x06object\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0f\n\x07protect\x18\x06 \x01(\x08\x12\x14\n\x0c\x64\x65pendencies\x18\x07 \x03(\t\x12\x10\n\x08provider\x18\x08 \x01(\t\x12Z\n\x14propertyDependencies\x18\t \x03(\x0b\x32<.pulumirpc.RegisterResourceRequest.PropertyDependenciesEntry\x12\x1b\n\x13\x64\x65leteBeforeReplace\x18\n \x01(\x08\x12\x0f\n\x07version\x18\x0b \x01(\t\x12\x15\n\rignoreChanges\x18\x0c \x03(\t\x12\x15\n\racceptSecrets\x18\r \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\x0e \x03(\t\x12\x0f\n\x07\x61liases\x18\x0f \x03(\t\x12\x10\n\x08importId\x18\x10 \x01(\t\x12I\n\x0e\x63ustomTimeouts\x18\x11 \x01(\x0b\x32\x31.pulumirpc.RegisterResourceRequest.CustomTimeouts\x12\"\n\x1a\x64\x65leteBeforeReplaceDefined\x18\x12 \x01(\x08\x12\x1d\n\x15supportsPartialValues\x18\x13 \x01(\x08\x12\x0e\n\x06remote\x18\x14 \x01(\x08\x12\x17\n\x0f\x61\x63\x63\x65ptResources\x18\x15 \x01(\x08\x12\x44\n\tproviders\x18\x16 \x03(\x0b\x32\x31.pulumirpc.RegisterResourceRequest.ProvidersEntry\x12\x18\n\x10replaceOnChanges\x18\x17 \x03(\t\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1a@\n\x0e\x43ustomTimeouts\x12\x0e\n\x06\x63reate\x18\x01 \x01(\t\x12\x0e\n\x06update\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\t\x1at\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x46\n\x05value\x18\x02 \x01(\x0b\x32\x37.pulumirpc.RegisterResourceRequest.PropertyDependencies:\x02\x38\x01\x1a\x30\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xf7\x02\n\x18RegisterResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\'\n\x06object\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0e\n\x06stable\x18\x04 \x01(\x08\x12\x0f\n\x07stables\x18\x05 \x03(\t\x12[\n\x14propertyDependencies\x18\x06 \x03(\x0b\x32=.pulumirpc.RegisterResourceResponse.PropertyDependenciesEntry\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1au\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.pulumirpc.RegisterResourceResponse.PropertyDependencies:\x02\x38\x01\"W\n\x1eRegisterResourceOutputsRequest\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12(\n\x07outputs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct2\xc4\x04\n\x0fResourceMonitor\x12Z\n\x0fSupportsFeature\x12!.pulumirpc.SupportsFeatureRequest\x1a\".pulumirpc.SupportsFeatureResponse\"\x00\x12?\n\x06Invoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x12G\n\x0cStreamInvoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x30\x01\x12\x39\n\x04\x43\x61ll\x12\x16.pulumirpc.CallRequest\x1a\x17.pulumirpc.CallResponse\"\x00\x12Q\n\x0cReadResource\x12\x1e.pulumirpc.ReadResourceRequest\x1a\x1f.pulumirpc.ReadResourceResponse\"\x00\x12]\n\x10RegisterResource\x12\".pulumirpc.RegisterResourceRequest\x1a#.pulumirpc.RegisterResourceResponse\"\x00\x12^\n\x17RegisterResourceOutputs\x12).pulumirpc.RegisterResourceOutputsRequest\x1a\x16.google.protobuf.Empty\"\x00\x62\x06proto3'
|
||||
,
|
||||
dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,provider__pb2.DESCRIPTOR,])
|
||||
|
||||
|
@ -262,8 +262,8 @@ _REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIES = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1242,
|
||||
serialized_end=1278,
|
||||
serialized_start=1268,
|
||||
serialized_end=1304,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCEREQUEST_CUSTOMTIMEOUTS = _descriptor.Descriptor(
|
||||
|
@ -306,8 +306,8 @@ _REGISTERRESOURCEREQUEST_CUSTOMTIMEOUTS = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1280,
|
||||
serialized_end=1344,
|
||||
serialized_start=1306,
|
||||
serialized_end=1370,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
|
||||
|
@ -343,8 +343,8 @@ _REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1346,
|
||||
serialized_end=1462,
|
||||
serialized_start=1372,
|
||||
serialized_end=1488,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCEREQUEST_PROVIDERSENTRY = _descriptor.Descriptor(
|
||||
|
@ -380,8 +380,8 @@ _REGISTERRESOURCEREQUEST_PROVIDERSENTRY = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1464,
|
||||
serialized_end=1512,
|
||||
serialized_start=1490,
|
||||
serialized_end=1538,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
|
||||
|
@ -545,6 +545,13 @@ _REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
|
|||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='replaceOnChanges', full_name='pulumirpc.RegisterResourceRequest.replaceOnChanges', index=22,
|
||||
number=23, type=9, cpp_type=9, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
|
@ -558,7 +565,7 @@ _REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
|
|||
oneofs=[
|
||||
],
|
||||
serialized_start=552,
|
||||
serialized_end=1512,
|
||||
serialized_end=1538,
|
||||
)
|
||||
|
||||
|
||||
|
@ -588,8 +595,8 @@ _REGISTERRESOURCERESPONSE_PROPERTYDEPENDENCIES = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1242,
|
||||
serialized_end=1278,
|
||||
serialized_start=1268,
|
||||
serialized_end=1304,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCERESPONSE_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
|
||||
|
@ -625,8 +632,8 @@ _REGISTERRESOURCERESPONSE_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1773,
|
||||
serialized_end=1890,
|
||||
serialized_start=1799,
|
||||
serialized_end=1916,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCERESPONSE = _descriptor.Descriptor(
|
||||
|
@ -690,8 +697,8 @@ _REGISTERRESOURCERESPONSE = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1515,
|
||||
serialized_end=1890,
|
||||
serialized_start=1541,
|
||||
serialized_end=1916,
|
||||
)
|
||||
|
||||
|
||||
|
@ -728,8 +735,8 @@ _REGISTERRESOURCEOUTPUTSREQUEST = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1892,
|
||||
serialized_end=1979,
|
||||
serialized_start=1918,
|
||||
serialized_end=2005,
|
||||
)
|
||||
|
||||
_READRESOURCEREQUEST.fields_by_name['properties'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT
|
||||
|
@ -866,8 +873,8 @@ _RESOURCEMONITOR = _descriptor.ServiceDescriptor(
|
|||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
serialized_start=1982,
|
||||
serialized_end=2562,
|
||||
serialized_start=2008,
|
||||
serialized_end=2588,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name='SupportsFeature',
|
||||
|
|
|
@ -288,6 +288,19 @@ def _translate_additional_secret_outputs(res: 'Resource',
|
|||
return additional_secret_outputs
|
||||
|
||||
|
||||
def _translate_replace_on_changes(res: 'Resource',
|
||||
typ: Optional[type],
|
||||
replace_on_changes: Optional[List[str]]) -> Optional[List[str]]:
|
||||
if replace_on_changes is not None:
|
||||
if typ is not None:
|
||||
# If `typ` is specified, use its type/name metadata for translation.
|
||||
input_names = _types.input_type_py_to_pulumi_names(typ)
|
||||
replace_on_changes = list(map(lambda k: input_names.get(k) or k, replace_on_changes))
|
||||
elif res.translate_input_property is not None:
|
||||
replace_on_changes = list(map(res.translate_input_property, replace_on_changes))
|
||||
return replace_on_changes
|
||||
|
||||
|
||||
def read_resource(res: 'CustomResource',
|
||||
ty: str,
|
||||
name: str,
|
||||
|
@ -439,6 +452,7 @@ def register_resource(res: 'Resource',
|
|||
|
||||
ignore_changes = _translate_ignore_changes(res, typ, opts.ignore_changes)
|
||||
additional_secret_outputs = _translate_additional_secret_outputs(res, typ, opts.additional_secret_outputs)
|
||||
replace_on_changes = _translate_replace_on_changes(res, typ, opts.replace_on_changes)
|
||||
|
||||
# Translate the CustomTimeouts object.
|
||||
custom_timeouts = None
|
||||
|
@ -487,6 +501,7 @@ def register_resource(res: 'Resource',
|
|||
aliases=resolver.aliases,
|
||||
supportsPartialValues=True,
|
||||
remote=remote,
|
||||
replaceOnChanges=replace_on_changes,
|
||||
)
|
||||
|
||||
from ..resource import create_urn # pylint: disable=import-outside-toplevel
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -16,26 +16,25 @@ from pulumi.asset import FileAsset, StringAsset, RemoteAsset
|
|||
from ..util import LanghostTest
|
||||
|
||||
|
||||
|
||||
class AssetTest(LanghostTest):
|
||||
def test_asset(self):
|
||||
self.run_test(
|
||||
program=path.join(self.base_path(), "asset"),
|
||||
expected_resource_count=4)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
if name == "file":
|
||||
self.assertIsInstance(resource["asset"], FileAsset)
|
||||
self.assertEqual(path.normpath(resource["asset"].path), "testfile.txt")
|
||||
self.assertIsInstance(_resource["asset"], FileAsset)
|
||||
self.assertEqual(path.normpath(_resource["asset"].path), "testfile.txt")
|
||||
elif name == "string":
|
||||
self.assertIsInstance(resource["asset"], StringAsset)
|
||||
self.assertEqual(resource["asset"].text, "its a string")
|
||||
self.assertIsInstance(_resource["asset"], StringAsset)
|
||||
self.assertEqual(_resource["asset"].text, "its a string")
|
||||
elif name == "remote":
|
||||
self.assertIsInstance(resource["asset"], RemoteAsset)
|
||||
self.assertEqual(resource["asset"].uri, "https://pulumi.com")
|
||||
self.assertIsInstance(_resource["asset"], RemoteAsset)
|
||||
self.assertEqual(_resource["asset"].uri, "https://pulumi.com")
|
||||
else:
|
||||
self.fail("unexpected resource name: " + name)
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -30,12 +30,12 @@ class ChainedFailureTest(LanghostTest):
|
|||
expected_error="Program exited with non-zero exit code: 1",
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, res, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if ty == "test:index:ResourceA":
|
||||
self.assertEqual(name, "resourceA")
|
||||
self.assertDictEqual(res, {"inprop": 777})
|
||||
self.assertDictEqual(_resource, {"inprop": 777})
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
|
@ -45,5 +45,5 @@ class ChainedFailureTest(LanghostTest):
|
|||
}
|
||||
|
||||
if ty == "test:index:ResourceB":
|
||||
self.fail(f"we should never have gotten here! {res}")
|
||||
self.fail(f"we should never have gotten here! {_resource}")
|
||||
self.fail(f"unknown resource type: {ty}")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -29,10 +29,10 @@ class ComponentResourceListOfProvidersTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "component_resource_list_of_providers"),
|
||||
expected_resource_count=240)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, custom, protect, provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
if custom and not ty.startswith("pulumi:providers:"):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if _custom and not ty.startswith("pulumi:providers:"):
|
||||
expect_protect = False
|
||||
expect_provider_name = ""
|
||||
|
||||
|
@ -59,7 +59,7 @@ class ComponentResourceListOfProvidersTest(LanghostTest):
|
|||
|
||||
# "provider" is a provider reference. To get the provider name (technically its ID, but this test
|
||||
# uses names as IDs), get the first string before the double-colon.
|
||||
provider_name = provider.split("::")[-1]
|
||||
provider_name = _provider.split("::")[-1]
|
||||
self.assertEqual(f"{name}.protect: {protect}", f"{name}.protect: {expect_protect}")
|
||||
self.assertEqual(f"{name}.provider: {provider_name}", f"{name}.provider: {expect_provider_name}")
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -29,10 +29,10 @@ class ComponentResourceSingleProviderTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "component_resource_single_provider"),
|
||||
expected_resource_count=240)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, custom, protect, provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
if custom and not ty.startswith("pulumi:providers:"):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if _custom and not ty.startswith("pulumi:providers:"):
|
||||
expect_protect = False
|
||||
expect_provider_name = ""
|
||||
|
||||
|
@ -59,7 +59,7 @@ class ComponentResourceSingleProviderTest(LanghostTest):
|
|||
|
||||
# "provider" is a provider reference. To get the provider name (technically its ID, but this test
|
||||
# uses names as IDs), get the first string before the double-colon.
|
||||
provider_name = provider.split("::")[-1]
|
||||
provider_name = _provider.split("::")[-1]
|
||||
self.assertEqual(f"{name}.protect: {protect}", f"{name}.protect: {expect_protect}")
|
||||
self.assertEqual(f"{name}.provider: {provider_name}", f"{name}.provider: {expect_provider_name}")
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -27,9 +27,9 @@ class ConfigTest(LanghostTest):
|
|||
},
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
self.assertEqual("myname", name)
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -19,16 +19,16 @@ class DeleteBeforeReplaceTest(LanghostTest):
|
|||
"""
|
||||
Tests that DBRed resources correctly pass the "DBR" boolean to the engine.
|
||||
"""
|
||||
def test_protect(self):
|
||||
def test_delete_before_replace(self):
|
||||
self.run_test(
|
||||
program=path.join(self.base_path(), "delete_before_replace"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("foo", name)
|
||||
self.assertTrue(delete_before_replace)
|
||||
self.assertTrue(_delete_before_replace)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -28,13 +28,13 @@ class FirstClassProviderTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "first_class_provider"),
|
||||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if name == "testprov":
|
||||
# Provider resource.
|
||||
self.assertEqual("pulumi:providers:test", ty)
|
||||
self.assertEqual("", provider)
|
||||
self.assertEqual("", _provider)
|
||||
self.prov_urn = self.make_urn(ty, name)
|
||||
self.prov_id = "testid"
|
||||
return {
|
||||
|
@ -50,10 +50,9 @@ class FirstClassProviderTest(LanghostTest):
|
|||
|
||||
# The provider reference is created by concatenating the URN and ID of the referenced provider.
|
||||
# The language host is responsible for doing this, since the engine will parse this identifier.
|
||||
self.assertEqual(f"{self.prov_urn}::{self.prov_id}", provider)
|
||||
self.assertEqual(f"{self.prov_urn}::{self.prov_id}", _provider)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name)
|
||||
}
|
||||
|
||||
self.fail(f"unexpected resource: {name} ({ty})")
|
||||
return None
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -29,7 +29,6 @@ class TestFirstClassProviderInvoke(LanghostTest):
|
|||
program=path.join(self.base_path(), "first_class_provider_invoke"),
|
||||
expected_resource_count=4)
|
||||
|
||||
|
||||
def invoke(self, _ctx, token, args, provider, _version):
|
||||
# MyFunction explicitly receives a provider reference.
|
||||
if token == "test:index:MyFunction":
|
||||
|
@ -52,9 +51,9 @@ class TestFirstClassProviderInvoke(LanghostTest):
|
|||
"value": args["value"] + 1
|
||||
}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if name == "testprov":
|
||||
self.assertEqual("pulumi:providers:test", ty)
|
||||
self.prov_urn = self.make_urn(ty, name)
|
||||
|
@ -66,11 +65,11 @@ class TestFirstClassProviderInvoke(LanghostTest):
|
|||
|
||||
if name == "resourceA":
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
self.assertEqual(resource["value"], 9001)
|
||||
self.assertEqual(_resource["value"], 9001)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource,
|
||||
"object": _resource,
|
||||
}
|
||||
|
||||
if name == "resourceB":
|
||||
|
@ -81,11 +80,11 @@ class TestFirstClassProviderInvoke(LanghostTest):
|
|||
|
||||
if name == "resourceC":
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
self.assertEqual(resource["value"], 42)
|
||||
self.assertEqual(_resource["value"], 42)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource,
|
||||
"object": _resource,
|
||||
}
|
||||
|
||||
self.fail(f"unexpected resource: {name}")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -30,15 +30,15 @@ class FirstClassProviderUnknown(LanghostTest):
|
|||
program=path.join(self.base_path(), "first_class_provider_unknown"),
|
||||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, _ctx, dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if name == "testprov":
|
||||
self.assertEqual("pulumi:providers:test", ty)
|
||||
# Only provide an ID when doing an update. When doing a preview the ID will be unknown
|
||||
# and resources referencing this resource will need to use the unknown sentinel to do so.
|
||||
self.prov_urn = self.make_urn(ty, name)
|
||||
if dry_run:
|
||||
if _dry_run:
|
||||
return {
|
||||
"urn": self.prov_urn
|
||||
}
|
||||
|
@ -51,16 +51,16 @@ class FirstClassProviderUnknown(LanghostTest):
|
|||
|
||||
if name == "res":
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
if dry_run:
|
||||
if _dry_run:
|
||||
# During a preview, the ID of the pulumi:providers:test resource is unknown.
|
||||
self.assertEqual(f"{self.prov_urn}::{rpc.UNKNOWN}", provider)
|
||||
self.assertEqual(f"{self.prov_urn}::{rpc.UNKNOWN}", _provider)
|
||||
else:
|
||||
# Otherwise, it's known to be exactly the above provider's ID.
|
||||
self.assertEqual(f"{self.prov_urn}::{self.prov_id}", provider)
|
||||
self.assertEqual(f"{self.prov_urn}::{self.prov_id}", _provider)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource
|
||||
"object": _resource
|
||||
}
|
||||
|
||||
self.fail(f"unknown resource: {name} ({ty})")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -26,12 +26,12 @@ class TestFutureFailure(LanghostTest):
|
|||
self.assertEqual("test:index:MyFunction", token)
|
||||
return [], {}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource,
|
||||
"object": _resource,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -25,17 +25,17 @@ class FutureInputTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "future_input"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:FileResource")
|
||||
self.assertEqual(name, "file")
|
||||
self.assertDictEqual(resource, {
|
||||
self.assertDictEqual(_resource, {
|
||||
"contents": "here's a file"
|
||||
})
|
||||
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource
|
||||
"object": _resource
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -24,15 +24,15 @@ class TestIgnoreChanges(LanghostTest):
|
|||
program=path.join(self.base_path(), "ignore_changes"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
|
||||
# Note that here we expect to receive `ignoredProperty`, even though the user provided `ignored_property`.
|
||||
self.assertListEqual(ignore_changes, ["ignoredProperty", "ignored_property_other"])
|
||||
self.assertListEqual(_ignore_changes, ["ignoredProperty", "ignored_property_other"])
|
||||
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource
|
||||
"object": _resource
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -29,10 +29,10 @@ class InheritDefaultsTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "inherit_defaults"),
|
||||
expected_resource_count=240)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, custom, protect, provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
if custom and not ty.startswith("pulumi:providers:"):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if _custom and not ty.startswith("pulumi:providers:"):
|
||||
expect_protect = False
|
||||
expect_provider_name = ""
|
||||
|
||||
|
@ -59,7 +59,7 @@ class InheritDefaultsTest(LanghostTest):
|
|||
|
||||
# "provider" is a provider reference. To get the provider name (technically its ID, but this test
|
||||
# uses names as IDs), get the first string before the double-colon.
|
||||
provider_name = provider.split("::")[-1]
|
||||
provider_name = _provider.split("::")[-1]
|
||||
self.assertEqual(f"{name}.protect: {protect}", f"{name}.protect: {expect_protect}")
|
||||
self.assertEqual(f"{name}.provider: {provider_name}", f"{name}.provider: {expect_provider_name}")
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ class InheritanceTranslationTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "inheritance_translation"),
|
||||
expected_resource_count=4)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
|
|
|
@ -21,9 +21,9 @@ class InheritanceTypesTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "inheritance_types"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
|
|
|
@ -23,9 +23,9 @@ class InputTypeMismatchTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "input_type_mismatch"),
|
||||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
|
||||
policy = _resource["policy"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -23,13 +23,13 @@ class InvalidPropertyDependencyTest(LanghostTest):
|
|||
expected_error="Program exited with non-zero exit code: 1",
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_dependencies, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
if name == "resA":
|
||||
self.assertListEqual(_dependencies, [])
|
||||
self.assertDictEqual(_property_dependencies, {})
|
||||
self.assertDictEqual(_property_deps, {})
|
||||
else:
|
||||
self.fail(f"unexpected resource: {name} ({ty})")
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -33,16 +33,16 @@ class TestInvoke(LanghostTest):
|
|||
"value": args["value"] + 1
|
||||
}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
self.assertEqual(resource["value"], 42)
|
||||
self.assertEqual(_resource["value"], 42)
|
||||
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource,
|
||||
"object": _resource,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2020, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -42,25 +42,24 @@ class TestInvoke(LanghostTest):
|
|||
else:
|
||||
self.fail(f"unexpected token {token}")
|
||||
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if name == "resourceA":
|
||||
self.assertEqual({
|
||||
"first_value": "hellohello",
|
||||
"second_value": 43,
|
||||
}, resource)
|
||||
}, _resource)
|
||||
elif name == "resourceB":
|
||||
self.assertEqual({
|
||||
"first_value": "worldworld",
|
||||
"second_value": 101,
|
||||
}, resource)
|
||||
}, _resource)
|
||||
else:
|
||||
self.fail(f"unknown resource: {name}")
|
||||
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource,
|
||||
"object": _resource,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -20,15 +20,16 @@ from ..util import LanghostTest
|
|||
|
||||
long_string = "a" * 1024 * 1024 * 5
|
||||
|
||||
|
||||
class LargeResourceTest(LanghostTest):
|
||||
def test_large_resource(self):
|
||||
self.run_test(
|
||||
program=path.join(self.base_path(), "large_resource"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyLargeStringResource")
|
||||
self.assertEqual(name, "testResource1")
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -26,12 +26,12 @@ class TestMarshalFailure(LanghostTest):
|
|||
self.assertEqual("test:index:MyFunction", token)
|
||||
return [], {}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
"object": resource,
|
||||
"object": _resource,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -22,16 +22,16 @@ class OneComplexResourceTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "one_complex_resource"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "testres")
|
||||
self.assertEqual(resource["falseprop"], False)
|
||||
self.assertEqual(resource["trueprop"], True)
|
||||
self.assertEqual(resource["intprop"], 42)
|
||||
self.assertListEqual(resource["listprop"], [1, 2, "string", False])
|
||||
self.assertDictEqual(resource["mapprop"], {
|
||||
self.assertEqual(_resource["falseprop"], False)
|
||||
self.assertEqual(_resource["trueprop"], True)
|
||||
self.assertEqual(_resource["intprop"], 42)
|
||||
self.assertListEqual(_resource["listprop"], [1, 2, "string", False])
|
||||
self.assertDictEqual(_resource["mapprop"], {
|
||||
"foo": ["bar", "baz"]
|
||||
})
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -21,9 +21,9 @@ class OneResourceTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "one_resource"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "testResource1")
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -23,9 +23,9 @@ class OutputAllTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "output_all"),
|
||||
expected_resource_count=4)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
number = 0
|
||||
if name == "testResource1":
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
|
@ -37,14 +37,14 @@ class OutputAllTest(LanghostTest):
|
|||
self.assertEqual(ty, "test:index:FinalResource")
|
||||
# The source program uses Output.apply to merge outputs from the above two resources.
|
||||
# The 5 is produced by adding 2 and 3 in the source program.
|
||||
self.assertEqual(resource["number"], 5)
|
||||
number = resource["number"]
|
||||
self.assertEqual(_resource["number"], 5)
|
||||
number = _resource["number"]
|
||||
elif name == "testResource4":
|
||||
self.assertEqual(ty, "test:index:FinalResource")
|
||||
# The source program uses Output.apply to merge outputs from the above two resources.
|
||||
# The 5 is produced by adding 2 and 3 in the source program.
|
||||
self.assertEqual(resource["number"], 5)
|
||||
number = resource["number"]
|
||||
self.assertEqual(_resource["number"], 5)
|
||||
number = _resource["number"]
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -21,9 +21,9 @@ class OutputNestedTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "output_nested"),
|
||||
expected_resource_count=3)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
nested_numbers = None
|
||||
if name == "testResource1":
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
|
@ -46,8 +46,8 @@ class OutputNestedTest(LanghostTest):
|
|||
# The source program uses Output.apply to merge outputs from the above two resources.
|
||||
# The 10 is produced by adding 9 and 1 in the source program, derived from nested properties of the
|
||||
# testResource1 nested_numbers property.
|
||||
self.assertEqual(resource["sum"], 10)
|
||||
nested_numbers = resource["sum"]
|
||||
self.assertEqual(_resource["sum"], 10)
|
||||
nested_numbers = _resource["sum"]
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -24,19 +24,19 @@ class PreviewTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "preview"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "foo")
|
||||
if dry_run:
|
||||
if _dry_run:
|
||||
self.assertDictEqual({
|
||||
"is_preview": True
|
||||
}, resource)
|
||||
}, _resource)
|
||||
else:
|
||||
self.assertDictEqual({
|
||||
"is_preview": False
|
||||
}, resource)
|
||||
}, _resource)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -22,33 +22,33 @@ class PropertyDependenciesTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "property_dependencies"),
|
||||
expected_resource_count=5)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_dependencies, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
if name == "resA":
|
||||
self.assertListEqual(_dependencies, [])
|
||||
self.assertDictEqual(_property_dependencies, {})
|
||||
self.assertDictEqual(_property_deps, {})
|
||||
elif name == "resB":
|
||||
self.assertListEqual(_dependencies, [ "resA" ])
|
||||
self.assertDictEqual(_property_dependencies, {})
|
||||
self.assertDictEqual(_property_deps, {})
|
||||
elif name == "resC":
|
||||
self.assertListEqual(_dependencies, [ "resA", "resB" ])
|
||||
self.assertDictEqual(_property_dependencies, {
|
||||
self.assertDictEqual(_property_deps, {
|
||||
"propA": [ "resA" ],
|
||||
"propB": [ "resB" ],
|
||||
"propC": [],
|
||||
})
|
||||
elif name == "resD":
|
||||
self.assertListEqual(_dependencies, [ "resA", "resB", "resC" ])
|
||||
self.assertDictEqual(_property_dependencies, {
|
||||
self.assertDictEqual(_property_deps, {
|
||||
"propA": [ "resA", "resB" ],
|
||||
"propB": [ "resC" ],
|
||||
"propC": [],
|
||||
})
|
||||
elif name == "resE":
|
||||
self.assertListEqual(_dependencies, [ "resA", "resB", "resC", "resD" ])
|
||||
self.assertDictEqual(_property_dependencies, {
|
||||
self.assertDictEqual(_property_deps, {
|
||||
"propA": [ "resC" ],
|
||||
"propB": [ "resA", "resB" ],
|
||||
"propC": [],
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -25,9 +25,9 @@ class PropertyRenamingTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "property_renaming"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, res, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
# Test:
|
||||
# 1. Everything that we receive from the running program is in camel-case. The engine never sees
|
||||
# the pre-translated names of the input properties.
|
||||
|
@ -35,12 +35,12 @@ class PropertyRenamingTest(LanghostTest):
|
|||
# to translate them back to snake case.
|
||||
self.assertEqual("test:index:TranslatedResource", ty)
|
||||
self.assertEqual("res", name)
|
||||
self.assertIn("engineProp", res)
|
||||
self.assertEqual("some string", res["engineProp"])
|
||||
self.assertIn("recursiveProp", res)
|
||||
self.assertIn("engineProp", _resource)
|
||||
self.assertEqual("some string", _resource["engineProp"])
|
||||
self.assertIn("recursiveProp", _resource)
|
||||
self.assertDictEqual({
|
||||
"recursiveKey": "value"
|
||||
}, res["recursiveProp"])
|
||||
}, _resource["recursiveProp"])
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
"id": name,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -24,9 +24,9 @@ class ProtectTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "protect"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("foo", name)
|
||||
self.assertTrue(protect)
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2019, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -21,16 +21,16 @@ class ReadTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "read"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "foo2")
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
}
|
||||
|
||||
def read_resource(self, ctx, ty, name, id, parent, state, dependencies, provider, version):
|
||||
def read_resource(self, ctx, ty, name, _id, parent, state, dependencies, provider, version):
|
||||
if name == "foo":
|
||||
self.assertDictEqual(state, {
|
||||
"a": "bar",
|
||||
|
@ -40,14 +40,14 @@ class ReadTest(LanghostTest):
|
|||
}
|
||||
})
|
||||
self.assertEqual(ty, "test:read:resource")
|
||||
self.assertEqual(id, "myresourceid")
|
||||
self.assertEqual(_id, "myresourceid")
|
||||
self.assertEqual(version, "0.17.9")
|
||||
elif name == "foo-with-parent":
|
||||
self.assertDictEqual(state, {
|
||||
"state": "foo",
|
||||
})
|
||||
self.assertEqual(ty, "test:read:resource")
|
||||
self.assertEqual(id, "myresourceid2")
|
||||
self.assertEqual(_id, "myresourceid2")
|
||||
self.assertEqual(parent, self.make_urn("test:index:MyResource", "foo2"))
|
||||
self.assertEqual(version, "0.17.9")
|
||||
return {
|
||||
|
|
13
sdk/python/lib/test/langhost/replace_on_changes/__init__.py
Normal file
13
sdk/python/lib/test/langhost/replace_on_changes/__init__.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Copyright 2016-2021, 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.
|
23
sdk/python/lib/test/langhost/replace_on_changes/__main__.py
Normal file
23
sdk/python/lib/test/langhost/replace_on_changes/__main__.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Copyright 2016-2021, 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.
|
||||
from pulumi import CustomResource, ResourceOptions, InvokeOptions
|
||||
from pulumi.runtime import invoke
|
||||
|
||||
|
||||
class MyResource(CustomResource):
|
||||
def __init__(self, name, opts=None):
|
||||
CustomResource.__init__(self, "test:index:MyResource", name, opts=opts)
|
||||
|
||||
|
||||
res = MyResource("testResource", opts=ResourceOptions(replace_on_changes=["a", "b"]))
|
|
@ -0,0 +1,37 @@
|
|||
# Copyright 2016-2021, 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.
|
||||
from os import path
|
||||
from ..util import LanghostTest
|
||||
|
||||
|
||||
class TestReplaceOnChanges(LanghostTest):
|
||||
"""
|
||||
Tests that Pulumi resources can accept replace_on_changes resource options.
|
||||
"""
|
||||
def test_replace_on_changes(self):
|
||||
self.run_test(
|
||||
program=path.join(self.base_path(), "replace_on_changes"),
|
||||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
|
||||
print(f'register_resource args: {locals()}')
|
||||
self.assertEqual("testResource", name)
|
||||
self.assertListEqual(_replace_on_changes, ["a", "b"])
|
||||
|
||||
return {
|
||||
"urn": self.make_urn(ty, name),
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -21,7 +21,7 @@ class UnhandledExceptionTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "resource_op_bad_inputs"),
|
||||
expected_error="Program exited with non-zero exit code: 1")
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, _ty, _name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
raise Exception("oh no")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -21,7 +21,7 @@ class UnhandledExceptionTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "resource_op_fail"),
|
||||
expected_error="Program exited with non-zero exit code: 1")
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, _ty, _name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
raise Exception("oh no")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -29,16 +29,16 @@ class ResourceThensTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "resource_thens"),
|
||||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, _ctx, dry_run, ty, name, res, deps,
|
||||
_parent, custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if ty == "test:index:ResourceA":
|
||||
self.assertEqual(name, "resourceA")
|
||||
self.assertDictEqual(res, {"inprop": 777, "inprop_2": 42})
|
||||
self.assertDictEqual(_resource, {"inprop": 777, "inprop_2": 42})
|
||||
urn = self.make_urn(ty, name)
|
||||
res_id = ""
|
||||
props = {}
|
||||
if not dry_run:
|
||||
if not _dry_run:
|
||||
res_id = name
|
||||
props["outprop"] = "output yeah"
|
||||
|
||||
|
@ -50,22 +50,22 @@ class ResourceThensTest(LanghostTest):
|
|||
|
||||
if ty == "test:index:ResourceB":
|
||||
self.assertEqual(name, "resourceB")
|
||||
self.assertListEqual(deps, ["test:index:ResourceA::resourceA"])
|
||||
if dry_run:
|
||||
self.assertDictEqual(res, {
|
||||
self.assertListEqual(_dependencies, ["test:index:ResourceA::resourceA"])
|
||||
if _dry_run:
|
||||
self.assertDictEqual(_resource, {
|
||||
# other_in is unknown, so it is not in the dictionary.
|
||||
# other_out is unknown, so it is not in the dictionary.
|
||||
# other_id is also unknown so it is not in the dictionary
|
||||
})
|
||||
else:
|
||||
self.assertDictEqual(res, {
|
||||
self.assertDictEqual(_resource, {
|
||||
"other_in": 777,
|
||||
"other_out": "output yeah",
|
||||
"other_id": "resourceA",
|
||||
})
|
||||
|
||||
res_id = ""
|
||||
if not dry_run:
|
||||
if not _dry_run:
|
||||
res_id = name
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -24,11 +24,11 @@ class TenResourcesTest(LanghostTest):
|
|||
program=path.join(self.base_path(), "ten_resources"),
|
||||
expected_resource_count=10)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace,
|
||||
_ignore_changes, _version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
if not dry_run:
|
||||
if not _dry_run:
|
||||
self.assertIsNone(
|
||||
self.seen.get(name),
|
||||
"Got multiple resources with the same name: " + name)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2020, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -22,9 +22,9 @@ class TestTypes(LanghostTest):
|
|||
program=path.join(self.base_path(), "types"),
|
||||
expected_resource_count=16)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if name in ["testres", "testres2", "testres3", "testres4"]:
|
||||
self.assertIn("additional", _resource)
|
||||
self.assertEqual({
|
||||
|
|
|
@ -98,16 +98,17 @@ class LanghostMockResourceMonitor(proto.ResourceMonitorServicer):
|
|||
ignore_changes = sorted(list(request.ignoreChanges))
|
||||
version = request.version
|
||||
import_ = request.importId
|
||||
replace_on_changes = sorted(list(request.replaceOnChanges))
|
||||
|
||||
property_dependencies = {}
|
||||
for key, value in request.propertyDependencies.items():
|
||||
property_dependencies[key] = sorted(list(value.urns))
|
||||
|
||||
outs = {}
|
||||
if type_ != "pulumi:pulumi:Stack":
|
||||
rrsig = signature(self.langhost_test.register_resource)
|
||||
args = [context, self.dryrun, type_, name, props, deps, parent, custom, protect, provider, property_dependencies, delete_before_replace, ignore_changes, version, import_]
|
||||
outs = self.langhost_test.register_resource(*args[0:len(rrsig.parameters)])
|
||||
outs = self.langhost_test.register_resource(
|
||||
context, self.dryrun, type_, name, props, deps, parent, custom, protect, provider,
|
||||
property_dependencies, delete_before_replace, ignore_changes, version, import_, replace_on_changes,
|
||||
)
|
||||
if outs.get("urn"):
|
||||
urn = outs["urn"]
|
||||
self.registrations[urn] = {
|
||||
|
@ -246,7 +247,7 @@ class LanghostTest(unittest.TestCase):
|
|||
|
||||
monitor.server.stop(0)
|
||||
|
||||
def invoke(self, _ctx, _token, _args, _provider):
|
||||
def invoke(self, _ctx, token, args, provider, _version):
|
||||
"""
|
||||
Method corresponding to the `Invoke` resource monitor RPC call.
|
||||
Override for custom behavior or assertions.
|
||||
|
@ -256,7 +257,7 @@ class LanghostTest(unittest.TestCase):
|
|||
"""
|
||||
return ([], {})
|
||||
|
||||
def read_resource(self, _ctx, _type, _name, _id, _parent, _state):
|
||||
def read_resource(self, ctx, ty, name, _id, parent, state, dependencies, provider, version):
|
||||
"""
|
||||
Method corresponding to the `ReadResource` resource monitor RPC call.
|
||||
Override for custom behavior or assertions.
|
||||
|
@ -265,8 +266,9 @@ class LanghostTest(unittest.TestCase):
|
|||
"""
|
||||
return {}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, _type, _name, _resource,
|
||||
_dependencies, _parent, _custom, _provider, _property_deps, _delete_before_replace, _import):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
"""
|
||||
Method corresponding to the `RegisterResource` resource monitor RPC call.
|
||||
Override for custom behavior or assertions.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2016-2018, Pulumi Corporation.
|
||||
# Copyright 2016-2021, Pulumi Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -21,15 +21,15 @@ class TestVersions(LanghostTest):
|
|||
program=path.join(self.base_path(), "versions"),
|
||||
expected_resource_count=3)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, version):
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource, _dependencies, _parent, _custom, protect,
|
||||
_provider, _property_deps, _delete_before_replace, _ignore_changes, _version, _import,
|
||||
_replace_on_changes):
|
||||
if name == "testres":
|
||||
self.assertEqual(version, "0.19.1")
|
||||
self.assertEqual(_version, "0.19.1")
|
||||
elif name == "testres2":
|
||||
self.assertEqual(version, "0.19.2")
|
||||
self.assertEqual(_version, "0.19.2")
|
||||
elif name == "testres3":
|
||||
self.assertEqual(version, "")
|
||||
self.assertEqual(_version, "")
|
||||
else:
|
||||
self.fail(f"unknown resource: {name}")
|
||||
return {
|
||||
|
|
Loading…
Reference in a new issue