Add support for explicit delete-before-replace (#2415)
These changes add a new flag to the various `ResourceOptions` types that indicates that a resource should be deleted before it is replaced, even if the provider does not require this behavior. The usual delete-before-replace cascade semantics apply. Fixes #1620.
This commit is contained in:
parent
128afe3323
commit
6e90ab0341
|
@ -20,6 +20,10 @@ Diagnostics:
|
|||
|
||||
We appologize for the regression. (fixes [pulumi/pulumi#2414](https://github.com/pulumi/pulumi/issues/2414))
|
||||
|
||||
### Improvements
|
||||
|
||||
- Individual resources may now be explicitly marked as requiring delete-before-replace behavior. This can be used e.g. to handle explicitly-named resources that may not be able to be replaced in the usual manner.
|
||||
|
||||
## 0.16.13 (Released January 31th, 2019)
|
||||
|
||||
### Major Changes
|
||||
|
|
|
@ -191,6 +191,34 @@ func (j *Journal) Snap(base *deploy.Snapshot) *deploy.Snapshot {
|
|||
return deploy.NewSnapshot(manifest, resources, operations)
|
||||
}
|
||||
|
||||
func (j *Journal) SuccessfulSteps() []deploy.Step {
|
||||
var steps []deploy.Step
|
||||
for _, entry := range j.Entries {
|
||||
if entry.Kind == JournalEntrySuccess {
|
||||
steps = append(steps, entry.Step)
|
||||
}
|
||||
}
|
||||
return steps
|
||||
}
|
||||
|
||||
type StepSummary struct {
|
||||
Op deploy.StepOp
|
||||
URN resource.URN
|
||||
}
|
||||
|
||||
func AssertSameSteps(t *testing.T, expected []StepSummary, actual []deploy.Step) bool {
|
||||
assert.Equal(t, len(expected), len(actual))
|
||||
for _, exp := range expected {
|
||||
act := actual[0]
|
||||
actual = actual[1:]
|
||||
|
||||
if !assert.Equal(t, exp.Op, act.Op()) || !assert.Equal(t, exp.URN, act.URN()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func newJournal() *Journal {
|
||||
j := &Journal{
|
||||
events: make(chan JournalEntry),
|
||||
|
@ -512,7 +540,7 @@ func TestSingleResourceDefaultProviderLifecycle(t *testing.T) {
|
|||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
@ -534,7 +562,7 @@ func TestSingleResourceExplicitProviderLifecycle(t *testing.T) {
|
|||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
provURN, provID, _, err := monitor.RegisterResource(providers.MakeProviderType("pkgA"), "provA", true, "",
|
||||
false, nil, "", resource.PropertyMap{}, nil)
|
||||
false, nil, "", resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if provID == "" {
|
||||
|
@ -545,7 +573,7 @@ func TestSingleResourceExplicitProviderLifecycle(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
_, _, _, err = monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, provRef.String(),
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return nil
|
||||
|
@ -568,7 +596,7 @@ func TestSingleResourceDefaultProviderUpgrade(t *testing.T) {
|
|||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
@ -669,7 +697,7 @@ func TestSingleResourceDefaultProviderReplace(t *testing.T) {
|
|||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
@ -748,7 +776,7 @@ func TestSingleResourceExplicitProviderReplace(t *testing.T) {
|
|||
}
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
provURN, provID, _, err := monitor.RegisterResource(providers.MakeProviderType("pkgA"), "provA", true, "",
|
||||
false, nil, "", providerInputs, nil)
|
||||
false, nil, "", providerInputs, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if provID == "" {
|
||||
|
@ -759,7 +787,7 @@ func TestSingleResourceExplicitProviderReplace(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
_, _, _, err = monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, provRef.String(),
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return nil
|
||||
|
@ -835,7 +863,7 @@ func TestSingleResourceExplicitProviderDeleteBeforeReplace(t *testing.T) {
|
|||
}
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
provURN, provID, _, err := monitor.RegisterResource(providers.MakeProviderType("pkgA"), "provA", true, "",
|
||||
false, nil, "", providerInputs, nil)
|
||||
false, nil, "", providerInputs, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if provID == "" {
|
||||
|
@ -846,7 +874,7 @@ func TestSingleResourceExplicitProviderDeleteBeforeReplace(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
_, _, _, err = monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, provRef.String(),
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return nil
|
||||
|
@ -936,7 +964,7 @@ func TestSingleResourceDiffUnavailable(t *testing.T) {
|
|||
|
||||
inputs := resource.PropertyMap{}
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", inputs, nil)
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", inputs, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
@ -1129,19 +1157,19 @@ func TestParallelRefresh(t *testing.T) {
|
|||
// it.
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
resA, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
resB, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resB", true, "", false, []resource.URN{resA}, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
resC, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resC", true, "", false, []resource.URN{resB}, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, _, _, err = monitor.RegisterResource("pkgA:m:typA", "resD", true, "", false, []resource.URN{resC}, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return nil
|
||||
|
@ -1255,7 +1283,7 @@ func TestRefreshInitFailure(t *testing.T) {
|
|||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
@ -1342,7 +1370,7 @@ func TestCheckFailureRecord(t *testing.T) {
|
|||
}
|
||||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", nil, nil)
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", nil, nil, false)
|
||||
assert.Error(t, err)
|
||||
return err
|
||||
})
|
||||
|
@ -1390,7 +1418,7 @@ func TestCheckFailureInvalidPropertyRecord(t *testing.T) {
|
|||
}
|
||||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", nil, nil)
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", nil, nil, false)
|
||||
assert.Error(t, err)
|
||||
return err
|
||||
})
|
||||
|
@ -1445,7 +1473,7 @@ func TestRefreshWithDelete(t *testing.T) {
|
|||
}
|
||||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", nil, nil)
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "", nil, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return err
|
||||
})
|
||||
|
@ -1938,7 +1966,8 @@ func TestBadResourceType(t *testing.T) {
|
|||
}
|
||||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, mon *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := mon.RegisterResource("very:bad", "resA", true, "", false, nil, "", resource.PropertyMap{}, nil)
|
||||
_, _, _, err := mon.RegisterResource(
|
||||
"very:bad", "resA", true, "", false, nil, "", resource.PropertyMap{}, nil, false)
|
||||
assert.Error(t, err)
|
||||
rpcerr, ok := rpcerror.FromError(err)
|
||||
assert.True(t, ok)
|
||||
|
@ -1954,11 +1983,11 @@ func TestBadResourceType(t *testing.T) {
|
|||
|
||||
// Component resources may have any format type.
|
||||
_, _, _, noErr := mon.RegisterResource(
|
||||
"a:component", "resB", false /* custom */, "", false, nil, "", resource.PropertyMap{}, nil)
|
||||
"a:component", "resB", false /* custom */, "", false, nil, "", resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, noErr)
|
||||
|
||||
_, _, _, noErr = mon.RegisterResource(
|
||||
"singlename", "resC", false /* custom */, "", false, nil, "", resource.PropertyMap{}, nil)
|
||||
"singlename", "resC", false /* custom */, "", false, nil, "", resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, noErr)
|
||||
|
||||
return err
|
||||
|
@ -2022,7 +2051,7 @@ func TestProviderCancellation(t *testing.T) {
|
|||
for i := 0; i < resourceCount; i++ {
|
||||
go func(idx int) {
|
||||
_, _, _, errors[idx] = monitor.RegisterResource("pkgA:m:typA", fmt.Sprintf("res%d", idx), true, "",
|
||||
false, nil, "", resource.PropertyMap{}, nil)
|
||||
false, nil, "", resource.PropertyMap{}, nil, false)
|
||||
resources.Done()
|
||||
}(i)
|
||||
}
|
||||
|
@ -2087,7 +2116,7 @@ func TestPreviewWithPendingOperations(t *testing.T) {
|
|||
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.PropertyMap{}, nil)
|
||||
resource.PropertyMap{}, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
@ -2132,7 +2161,7 @@ func TestUpdatePartialFailure(t *testing.T) {
|
|||
_, _, _, err := mon.RegisterResource("pkgA:m:typA", "resA", true, "", false, nil, "",
|
||||
resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"input_prop": "new inputs",
|
||||
}), nil)
|
||||
}), nil, false)
|
||||
|
||||
return err
|
||||
})
|
||||
|
@ -2202,7 +2231,7 @@ func TestStackReference(t *testing.T) {
|
|||
_, _, state, err := mon.RegisterResource("pulumi:pulumi:StackReference", "other", true, "", false, nil, "",
|
||||
resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"name": "other",
|
||||
}), nil)
|
||||
}), nil, false)
|
||||
assert.NoError(t, err)
|
||||
if !info.DryRun {
|
||||
assert.Equal(t, "bar", state["outputs"].ObjectValue()["foo"].StringValue())
|
||||
|
@ -2273,7 +2302,7 @@ func TestStackReference(t *testing.T) {
|
|||
_, _, _, err := mon.RegisterResource("pulumi:pulumi:StackReference", "other", true, "", false, nil, "",
|
||||
resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"name": "rehto",
|
||||
}), nil)
|
||||
}), nil, false)
|
||||
assert.Error(t, err)
|
||||
return err
|
||||
})
|
||||
|
@ -2291,7 +2320,7 @@ func TestStackReference(t *testing.T) {
|
|||
resource.NewPropertyMapFromMap(map[string]interface{}{
|
||||
"name": "other",
|
||||
"foo": "bar",
|
||||
}), nil)
|
||||
}), nil, false)
|
||||
assert.Error(t, err)
|
||||
return err
|
||||
})
|
||||
|
@ -2522,7 +2551,7 @@ func TestDeleteBeforeReplace(t *testing.T) {
|
|||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
register := func(urn resource.URN, provider string, inputs resource.PropertyMap) resource.ID {
|
||||
_, id, _, err := monitor.RegisterResource(urn.Type(), string(urn.Name()), true, "", false, nil, provider,
|
||||
inputs, nil)
|
||||
inputs, nil, false)
|
||||
assert.NoError(t, err)
|
||||
return id
|
||||
}
|
||||
|
@ -2595,7 +2624,7 @@ func TestPropertyDependenciesAdapter(t *testing.T) {
|
|||
dependencies []resource.URN) resource.URN {
|
||||
|
||||
urn, _, _, err := monitor.RegisterResource(resType, name, true, "", false, dependencies, "", inputs,
|
||||
inputDeps)
|
||||
inputDeps, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return urn
|
||||
|
@ -2644,3 +2673,146 @@ func TestPropertyDependenciesAdapter(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExplicitDeleteBeforeReplace(t *testing.T) {
|
||||
p := &TestPlan{}
|
||||
|
||||
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) (plugin.DiffResult, error) {
|
||||
|
||||
if !olds["A"].DeepEquals(news["A"]) {
|
||||
return plugin.DiffResult{ReplaceKeys: []resource.PropertyKey{"A"}}, nil
|
||||
}
|
||||
return plugin.DiffResult{}, nil
|
||||
},
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
const resType = "pkgA:index:typ"
|
||||
|
||||
inputsA := resource.NewPropertyMapFromMap(map[string]interface{}{"A": "foo"})
|
||||
dbrA := false
|
||||
inputsB := resource.NewPropertyMapFromMap(map[string]interface{}{"A": "foo"})
|
||||
|
||||
var provURN, urnA, urnB resource.URN
|
||||
var provID resource.ID
|
||||
var err error
|
||||
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
||||
provURN, provID, _, err = monitor.RegisterResource(
|
||||
providers.MakeProviderType("pkgA"), "provA", true, "", false, nil, "", nil, nil, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if provID == "" {
|
||||
provID = providers.UnknownID
|
||||
}
|
||||
provRef, err := providers.NewReference(provURN, provID)
|
||||
assert.NoError(t, err)
|
||||
provA := provRef.String()
|
||||
|
||||
urnA, _, _, err = monitor.RegisterResource(resType, "resA", true, "", false, nil, provA, inputsA, nil, dbrA)
|
||||
assert.NoError(t, err)
|
||||
|
||||
inputDepsB := map[resource.PropertyKey][]resource.URN{"A": {urnA}}
|
||||
urnB, _, _, err = monitor.RegisterResource(resType, "resB", true, "", false, []resource.URN{urnA}, provA,
|
||||
inputsB, inputDepsB, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
p.Options.host = deploytest.NewPluginHost(nil, nil, program, loaders...)
|
||||
p.Steps = []TestStep{{Op: Update}}
|
||||
snap := p.Run(t, nil)
|
||||
|
||||
// Change the value of resA.A. Only resA should be replaced, and the replacement should be create-before-delete.
|
||||
inputsA["A"] = resource.NewStringProperty("bar")
|
||||
p.Steps = []TestStep{{
|
||||
Op: Update,
|
||||
|
||||
Validate: func(project workspace.Project, target deploy.Target, j *Journal, evts []Event, err error) error {
|
||||
assert.NoError(t, err)
|
||||
|
||||
AssertSameSteps(t, []StepSummary{
|
||||
{Op: deploy.OpSame, URN: provURN},
|
||||
{Op: deploy.OpCreateReplacement, URN: urnA},
|
||||
{Op: deploy.OpReplace, URN: urnA},
|
||||
{Op: deploy.OpSame, URN: urnB},
|
||||
{Op: deploy.OpDeleteReplaced, URN: urnA},
|
||||
}, j.SuccessfulSteps())
|
||||
|
||||
return err
|
||||
},
|
||||
}}
|
||||
snap = p.Run(t, snap)
|
||||
|
||||
// Change the registration of resA such that it requires delete-before-replace and change the value of resA.A. Both
|
||||
// resA and resB should be replaced, and the replacements should be delete-before-replace.
|
||||
dbrA, inputsA["A"] = true, resource.NewStringProperty("baz")
|
||||
p.Steps = []TestStep{{
|
||||
Op: Update,
|
||||
|
||||
Validate: func(project workspace.Project, target deploy.Target, j *Journal, evts []Event, err error) error {
|
||||
assert.NoError(t, err)
|
||||
|
||||
AssertSameSteps(t, []StepSummary{
|
||||
{Op: deploy.OpSame, URN: provURN},
|
||||
{Op: deploy.OpDeleteReplaced, URN: urnB},
|
||||
{Op: deploy.OpDeleteReplaced, URN: urnA},
|
||||
{Op: deploy.OpReplace, URN: urnA},
|
||||
{Op: deploy.OpCreateReplacement, URN: urnA},
|
||||
{Op: deploy.OpReplace, URN: urnB},
|
||||
{Op: deploy.OpCreateReplacement, URN: urnB},
|
||||
}, j.SuccessfulSteps())
|
||||
|
||||
return err
|
||||
},
|
||||
}}
|
||||
snap = p.Run(t, snap)
|
||||
|
||||
// Change the value of resB.A. Only resB should be replaced, and the replacement should be create-before-delete.
|
||||
inputsB["A"] = resource.NewStringProperty("qux")
|
||||
p.Steps = []TestStep{{
|
||||
Op: Update,
|
||||
|
||||
Validate: func(project workspace.Project, target deploy.Target, j *Journal, evts []Event, err error) error {
|
||||
assert.NoError(t, err)
|
||||
|
||||
AssertSameSteps(t, []StepSummary{
|
||||
{Op: deploy.OpSame, URN: provURN},
|
||||
{Op: deploy.OpSame, URN: urnA},
|
||||
{Op: deploy.OpCreateReplacement, URN: urnB},
|
||||
{Op: deploy.OpReplace, URN: urnB},
|
||||
{Op: deploy.OpDeleteReplaced, URN: urnB},
|
||||
}, j.SuccessfulSteps())
|
||||
|
||||
return err
|
||||
},
|
||||
}}
|
||||
snap = p.Run(t, snap)
|
||||
|
||||
// Change the registration of resA such that it no longer requires delete-before-replace and change the value of
|
||||
// resA.A. Only resA should be replaced, and the replacement should be delete-before-replace.
|
||||
dbrA, inputsA["A"] = false, resource.NewStringProperty("zam")
|
||||
p.Steps = []TestStep{{
|
||||
Op: Update,
|
||||
|
||||
Validate: func(project workspace.Project, target deploy.Target, j *Journal, evts []Event, err error) error {
|
||||
assert.NoError(t, err)
|
||||
|
||||
AssertSameSteps(t, []StepSummary{
|
||||
{Op: deploy.OpSame, URN: provURN},
|
||||
{Op: deploy.OpCreateReplacement, URN: urnA},
|
||||
{Op: deploy.OpReplace, URN: urnA},
|
||||
{Op: deploy.OpSame, URN: urnB},
|
||||
{Op: deploy.OpDeleteReplaced, URN: urnA},
|
||||
}, j.SuccessfulSteps())
|
||||
|
||||
return err
|
||||
},
|
||||
}}
|
||||
p.Run(t, snap)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ type ResourceMonitor struct {
|
|||
|
||||
func (rm *ResourceMonitor) RegisterResource(t tokens.Type, name string, custom bool, parent resource.URN, protect bool,
|
||||
dependencies []resource.URN, provider string, inputs resource.PropertyMap,
|
||||
propertyDeps map[resource.PropertyKey][]resource.URN) (resource.URN, resource.ID, resource.PropertyMap, error) {
|
||||
propertyDeps map[resource.PropertyKey][]resource.URN,
|
||||
deleteBeforeReplace bool) (resource.URN, resource.ID, resource.PropertyMap, error) {
|
||||
|
||||
// marshal inputs
|
||||
ins, err := plugin.MarshalProperties(inputs, plugin.MarshalOptions{KeepUnknowns: true})
|
||||
|
@ -65,6 +66,7 @@ func (rm *ResourceMonitor) RegisterResource(t tokens.Type, name string, custom b
|
|||
Provider: provider,
|
||||
Object: ins,
|
||||
PropertyDependencies: inputDeps,
|
||||
DeleteBeforeReplace: deleteBeforeReplace,
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
|
|
|
@ -256,7 +256,7 @@ func (d *defaultProviders) newRegisterDefaultProviderEvent(
|
|||
// Create the result channel and the event.
|
||||
done := make(chan *RegisterResult)
|
||||
event := ®isterResourceEvent{
|
||||
goal: resource.NewGoal(providers.MakeProviderType(pkg), "default", true, inputs, "", false, nil, "", nil, nil),
|
||||
goal: resource.NewGoal(providers.MakeProviderType(pkg), "default", true, inputs, "", false, nil, "", nil, nil, false),
|
||||
done: done,
|
||||
}
|
||||
return event, done, nil
|
||||
|
@ -569,6 +569,7 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
custom := req.GetCustom()
|
||||
parent := resource.URN(req.GetParent())
|
||||
protect := req.GetProtect()
|
||||
deleteBeforeReplace := req.GetDeleteBeforeReplace()
|
||||
var t tokens.Type
|
||||
|
||||
// Custom resources must have a three-part type so that we can 1) identify if they are providers and 2) retrieve the
|
||||
|
@ -625,13 +626,13 @@ 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",
|
||||
t, name, custom, len(props), parent, protect, provider, dependencies)
|
||||
"provider=%v, deps=%v, deleteBeforeReplace=%v",
|
||||
t, name, custom, len(props), parent, protect, provider, dependencies, deleteBeforeReplace)
|
||||
|
||||
// Send the goal state to the engine.
|
||||
step := ®isterResourceEvent{
|
||||
goal: resource.NewGoal(t, name, custom, props, parent, protect, dependencies, provider, nil,
|
||||
propertyDependencies),
|
||||
propertyDependencies, deleteBeforeReplace),
|
||||
done: make(chan *RegisterResult),
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ func fixedProgram(steps []RegisterResourceEvent) deploytest.ProgramFunc {
|
|||
for _, s := range steps {
|
||||
g := s.Goal()
|
||||
urn, id, outs, err := resmon.RegisterResource(g.Type, string(g.Name), g.Custom, g.Parent, g.Protect,
|
||||
g.Dependencies, g.Provider, g.Properties, g.PropertyDependencies)
|
||||
g.Dependencies, g.Provider, g.Properties, g.PropertyDependencies, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -143,16 +143,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, "", []string{}, nil, false),
|
||||
},
|
||||
// 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),
|
||||
providerARef.String(), []string{}, nil, false),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:index:typA", "res2", true, resource.PropertyMap{}, componentURN, false, nil,
|
||||
providerARef.String(), []string{}, nil),
|
||||
providerARef.String(), []string{}, nil, false),
|
||||
},
|
||||
// Register two more providers.
|
||||
newProviderEvent("pkgA", "providerB", nil, ""),
|
||||
|
@ -160,11 +160,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),
|
||||
providerBRef.String(), []string{}, nil, false),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:index:typC", "res4", true, resource.PropertyMap{}, "", false, nil,
|
||||
providerCRef.String(), []string{}, nil),
|
||||
providerCRef.String(), []string{}, nil, false),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -227,25 +227,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, "", []string{}, nil, false),
|
||||
},
|
||||
// Register a couple resources from package A.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:m:typA", "res1", true, resource.PropertyMap{},
|
||||
componentURN, false, nil, "", []string{}, nil),
|
||||
componentURN, false, nil, "", []string{}, nil, false),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgA:m:typA", "res2", true, resource.PropertyMap{},
|
||||
componentURN, false, nil, "", []string{}, nil),
|
||||
componentURN, false, nil, "", []string{}, nil, false),
|
||||
},
|
||||
// Register a few resources from other packages.
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:m:typB", "res3", true, resource.PropertyMap{}, "", false,
|
||||
nil, "", []string{}, nil),
|
||||
nil, "", []string{}, nil, false),
|
||||
},
|
||||
&testRegEvent{
|
||||
goal: resource.NewGoal("pkgB:m:typC", "res4", true, resource.PropertyMap{}, "", false,
|
||||
nil, "", []string{}, nil),
|
||||
nil, "", []string{}, nil, false),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ func (sg *stepGenerator) GenerateSteps(event RegisterResourceEvent) ([]Step, *re
|
|||
//
|
||||
// The provider is responsible for requesting which of these two modes to use.
|
||||
|
||||
if diff.DeleteBeforeReplace {
|
||||
if diff.DeleteBeforeReplace || goal.DeleteBeforeReplace {
|
||||
logging.V(7).Infof("Planner decided to delete-before-replacement for resource '%v'", urn)
|
||||
contract.Assert(sg.plan.depGraph != nil)
|
||||
|
||||
|
|
|
@ -31,12 +31,13 @@ type Goal struct {
|
|||
Provider string // the provider to use for this resource.
|
||||
InitErrors []string // errors encountered as we attempted to initialize the resource.
|
||||
PropertyDependencies map[PropertyKey][]URN // the set of dependencies that affect each property.
|
||||
DeleteBeforeReplace bool // true if this resource should be deleted prior to 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) *Goal {
|
||||
propertyDependencies map[PropertyKey][]URN, deleteBeforeReplace bool) *Goal {
|
||||
|
||||
return &Goal{
|
||||
Type: t,
|
||||
|
@ -49,5 +50,6 @@ func NewGoal(t tokens.Type, name tokens.QName, custom bool, props PropertyMap,
|
|||
Provider: provider,
|
||||
InitErrors: initErrors,
|
||||
PropertyDependencies: propertyDependencies,
|
||||
DeleteBeforeReplace: deleteBeforeReplace,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -292,6 +292,7 @@ func (ctx *Context) RegisterResource(
|
|||
Dependencies: inputs.deps,
|
||||
Provider: inputs.provider,
|
||||
PropertyDependencies: inputs.rpcPropertyDeps,
|
||||
DeleteBeforeReplace: inputs.deleteBeforeReplace,
|
||||
})
|
||||
if err != nil {
|
||||
glog.V(9).Infof("RegisterResource(%s, %s): error: %v", t, name, err)
|
||||
|
@ -404,19 +405,20 @@ func (outputs *resourceOutputs) resolve(dryrun bool, err error, inputs map[strin
|
|||
|
||||
// resourceInputs reflects all of the inputs necessary to perform core resource RPC operations.
|
||||
type resourceInputs struct {
|
||||
parent string
|
||||
deps []string
|
||||
protect bool
|
||||
provider string
|
||||
rpcProps *structpb.Struct
|
||||
rpcPropertyDeps map[string]*pulumirpc.RegisterResourceRequest_PropertyDependencies
|
||||
parent string
|
||||
deps []string
|
||||
protect bool
|
||||
provider string
|
||||
rpcProps *structpb.Struct
|
||||
rpcPropertyDeps map[string]*pulumirpc.RegisterResourceRequest_PropertyDependencies
|
||||
deleteBeforeReplace bool
|
||||
}
|
||||
|
||||
// prepareResourceInputs prepares the inputs for a resource operation, shared between read and register.
|
||||
func (ctx *Context) prepareResourceInputs(props map[string]interface{}, opts ...ResourceOpt) (*resourceInputs, error) {
|
||||
// Get the parent and dependency URNs from the options, in addition to the protection bit. If there wasn't an
|
||||
// explicit parent, and a root stack resource exists, we will automatically parent to that.
|
||||
parent, optDeps, protect, provider, err := ctx.getOpts(opts...)
|
||||
parent, optDeps, protect, provider, deleteBeforeReplace, err := ctx.getOpts(opts...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "resolving options")
|
||||
}
|
||||
|
@ -457,12 +459,13 @@ func (ctx *Context) prepareResourceInputs(props map[string]interface{}, opts ...
|
|||
sort.Strings(deps)
|
||||
|
||||
return &resourceInputs{
|
||||
parent: string(parent),
|
||||
deps: deps,
|
||||
protect: protect,
|
||||
provider: provider,
|
||||
rpcProps: rpcProps,
|
||||
rpcPropertyDeps: rpcPropertyDeps,
|
||||
parent: string(parent),
|
||||
deps: deps,
|
||||
protect: protect,
|
||||
provider: provider,
|
||||
rpcProps: rpcProps,
|
||||
rpcPropertyDeps: rpcPropertyDeps,
|
||||
deleteBeforeReplace: deleteBeforeReplace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -474,11 +477,12 @@ type resourceOutput struct {
|
|||
|
||||
// getOpts returns a set of resource options from an array of them. This includes the parent URN, any dependency URNs,
|
||||
// a boolean indicating whether the resource is to be protected, and the URN and ID of the resource's provider, if any.
|
||||
func (ctx *Context) getOpts(opts ...ResourceOpt) (URN, []URN, bool, string, error) {
|
||||
func (ctx *Context) getOpts(opts ...ResourceOpt) (URN, []URN, bool, string, bool, error) {
|
||||
var parent Resource
|
||||
var deps []Resource
|
||||
var protect bool
|
||||
var provider ProviderResource
|
||||
var deleteBeforeReplace bool
|
||||
for _, opt := range opts {
|
||||
if parent == nil && opt.Parent != nil {
|
||||
parent = opt.Parent
|
||||
|
@ -492,6 +496,9 @@ func (ctx *Context) getOpts(opts ...ResourceOpt) (URN, []URN, bool, string, erro
|
|||
if provider == nil && opt.Provider != nil {
|
||||
provider = opt.Provider
|
||||
}
|
||||
if !deleteBeforeReplace && opt.DeleteBeforeReplace {
|
||||
deleteBeforeReplace = true
|
||||
}
|
||||
}
|
||||
|
||||
var parentURN URN
|
||||
|
@ -500,7 +507,7 @@ func (ctx *Context) getOpts(opts ...ResourceOpt) (URN, []URN, bool, string, erro
|
|||
} else {
|
||||
urn, err := parent.URN().Value()
|
||||
if err != nil {
|
||||
return "", nil, false, "", err
|
||||
return "", nil, false, "", false, err
|
||||
}
|
||||
parentURN = urn
|
||||
}
|
||||
|
@ -511,7 +518,7 @@ func (ctx *Context) getOpts(opts ...ResourceOpt) (URN, []URN, bool, string, erro
|
|||
for i, r := range deps {
|
||||
urn, err := r.URN().Value()
|
||||
if err != nil {
|
||||
return "", nil, false, "", err
|
||||
return "", nil, false, "", false, err
|
||||
}
|
||||
depURNs[i] = urn
|
||||
}
|
||||
|
@ -521,12 +528,12 @@ func (ctx *Context) getOpts(opts ...ResourceOpt) (URN, []URN, bool, string, erro
|
|||
if provider != nil {
|
||||
pr, err := ctx.resolveProviderReference(provider)
|
||||
if err != nil {
|
||||
return "", nil, false, "", err
|
||||
return "", nil, false, "", false, err
|
||||
}
|
||||
providerRef = pr
|
||||
}
|
||||
|
||||
return parentURN, depURNs, protect, providerRef, nil
|
||||
return parentURN, depURNs, protect, providerRef, false, nil
|
||||
}
|
||||
|
||||
func (ctx *Context) resolveProviderReference(provider ProviderResource) (string, error) {
|
||||
|
|
|
@ -60,6 +60,8 @@ type ResourceOpt struct {
|
|||
Protect bool
|
||||
// Provider is an optional provider resource to use for this resource's CRUD operations.
|
||||
Provider ProviderResource
|
||||
// DeleteBeforeReplace, when set to true, ensures that this resource is deleted prior to replacement.
|
||||
DeleteBeforeReplace bool
|
||||
}
|
||||
|
||||
// InvokeOpt contains optional settings that control an invoke's behavior.
|
||||
|
|
|
@ -610,7 +610,8 @@ proto.pulumirpc.RegisterResourceRequest.toObject = function(includeInstance, msg
|
|||
protect: jspb.Message.getFieldWithDefault(msg, 6, false),
|
||||
dependenciesList: jspb.Message.getRepeatedField(msg, 7),
|
||||
provider: jspb.Message.getFieldWithDefault(msg, 8, ""),
|
||||
propertydependenciesMap: (f = msg.getPropertydependenciesMap()) ? f.toObject(includeInstance, proto.pulumirpc.RegisterResourceRequest.PropertyDependencies.toObject) : []
|
||||
propertydependenciesMap: (f = msg.getPropertydependenciesMap()) ? f.toObject(includeInstance, proto.pulumirpc.RegisterResourceRequest.PropertyDependencies.toObject) : [],
|
||||
deletebeforereplace: jspb.Message.getFieldWithDefault(msg, 10, false)
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
|
@ -686,6 +687,10 @@ proto.pulumirpc.RegisterResourceRequest.deserializeBinaryFromReader = function(m
|
|||
jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readMessage, proto.pulumirpc.RegisterResourceRequest.PropertyDependencies.deserializeBinaryFromReader);
|
||||
});
|
||||
break;
|
||||
case 10:
|
||||
var value = /** @type {boolean} */ (reader.readBool());
|
||||
msg.setDeletebeforereplace(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
|
@ -776,6 +781,13 @@ proto.pulumirpc.RegisterResourceRequest.serializeBinaryToWriter = function(messa
|
|||
if (f && f.getLength() > 0) {
|
||||
f.serializeBinary(9, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeMessage, proto.pulumirpc.RegisterResourceRequest.PropertyDependencies.serializeBinaryToWriter);
|
||||
}
|
||||
f = message.getDeletebeforereplace();
|
||||
if (f) {
|
||||
writer.writeBool(
|
||||
10,
|
||||
f
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -1113,6 +1125,23 @@ proto.pulumirpc.RegisterResourceRequest.prototype.clearPropertydependenciesMap =
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* optional bool deleteBeforeReplace = 10;
|
||||
* Note that Boolean fields may be set to 0/1 when serialized from a Java server.
|
||||
* You should avoid comparisons like {@code val === true/false} in those cases.
|
||||
* @return {boolean}
|
||||
*/
|
||||
proto.pulumirpc.RegisterResourceRequest.prototype.getDeletebeforereplace = function() {
|
||||
return /** @type {boolean} */ (jspb.Message.getFieldWithDefault(this, 10, false));
|
||||
};
|
||||
|
||||
|
||||
/** @param {boolean} value */
|
||||
proto.pulumirpc.RegisterResourceRequest.prototype.setDeletebeforereplace = function(value) {
|
||||
jspb.Message.setProto3BooleanField(this, 10, value);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generated by JsPbCodeGenerator.
|
||||
|
|
|
@ -169,6 +169,12 @@ export interface CustomResourceOptions extends ResourceOptions {
|
|||
* provider bag (see also ComponentResourceOptions.providers).
|
||||
*/
|
||||
provider?: ProviderResource;
|
||||
|
||||
/**
|
||||
* When set to true, deleteBeforeReplace indicates that this resource should be deleted before its replacement
|
||||
* is created when replacement is necessary.
|
||||
*/
|
||||
deleteBeforeReplace?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -137,6 +137,7 @@ export function registerResource(res: Resource, t: string, name: string, custom:
|
|||
req.setProtect(opts.protect);
|
||||
req.setProvider(resop.providerRef);
|
||||
req.setDependenciesList(Array.from(resop.dependencies));
|
||||
req.setDeletebeforereplace((<any>opts).deleteBeforeReplace || false);
|
||||
|
||||
const propertyDependencies = req.getPropertydependenciesMap();
|
||||
for (const key of Object.keys(resop.propertyDependencies)) {
|
||||
|
|
|
@ -43,7 +43,7 @@ func (m *ReadResourceRequest) Reset() { *m = ReadResourceRequest{} }
|
|||
func (m *ReadResourceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReadResourceRequest) ProtoMessage() {}
|
||||
func (*ReadResourceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_resource_814328246bd928d7, []int{0}
|
||||
return fileDescriptor_resource_03e51d5764cd9ae8, []int{0}
|
||||
}
|
||||
func (m *ReadResourceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ReadResourceRequest.Unmarshal(m, b)
|
||||
|
@ -125,7 +125,7 @@ func (m *ReadResourceResponse) Reset() { *m = ReadResourceResponse{} }
|
|||
func (m *ReadResourceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReadResourceResponse) ProtoMessage() {}
|
||||
func (*ReadResourceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_resource_814328246bd928d7, []int{1}
|
||||
return fileDescriptor_resource_03e51d5764cd9ae8, []int{1}
|
||||
}
|
||||
func (m *ReadResourceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ReadResourceResponse.Unmarshal(m, b)
|
||||
|
@ -170,6 +170,7 @@ type RegisterResourceRequest struct {
|
|||
Dependencies []string `protobuf:"bytes,7,rep,name=dependencies" json:"dependencies,omitempty"`
|
||||
Provider string `protobuf:"bytes,8,opt,name=provider" json:"provider,omitempty"`
|
||||
PropertyDependencies map[string]*RegisterResourceRequest_PropertyDependencies `protobuf:"bytes,9,rep,name=propertyDependencies" json:"propertyDependencies,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
DeleteBeforeReplace bool `protobuf:"varint,10,opt,name=deleteBeforeReplace" json:"deleteBeforeReplace,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
@ -179,7 +180,7 @@ func (m *RegisterResourceRequest) Reset() { *m = RegisterResourceRequest
|
|||
func (m *RegisterResourceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RegisterResourceRequest) ProtoMessage() {}
|
||||
func (*RegisterResourceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_resource_814328246bd928d7, []int{2}
|
||||
return fileDescriptor_resource_03e51d5764cd9ae8, []int{2}
|
||||
}
|
||||
func (m *RegisterResourceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RegisterResourceRequest.Unmarshal(m, b)
|
||||
|
@ -262,6 +263,13 @@ func (m *RegisterResourceRequest) GetPropertyDependencies() map[string]*Register
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *RegisterResourceRequest) GetDeleteBeforeReplace() bool {
|
||||
if m != nil {
|
||||
return m.DeleteBeforeReplace
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PropertyDependencies describes the resources that a particular property depends on.
|
||||
type RegisterResourceRequest_PropertyDependencies struct {
|
||||
Urns []string `protobuf:"bytes,1,rep,name=urns" json:"urns,omitempty"`
|
||||
|
@ -278,7 +286,7 @@ func (m *RegisterResourceRequest_PropertyDependencies) String() string {
|
|||
}
|
||||
func (*RegisterResourceRequest_PropertyDependencies) ProtoMessage() {}
|
||||
func (*RegisterResourceRequest_PropertyDependencies) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_resource_814328246bd928d7, []int{2, 0}
|
||||
return fileDescriptor_resource_03e51d5764cd9ae8, []int{2, 0}
|
||||
}
|
||||
func (m *RegisterResourceRequest_PropertyDependencies) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RegisterResourceRequest_PropertyDependencies.Unmarshal(m, b)
|
||||
|
@ -322,7 +330,7 @@ func (m *RegisterResourceResponse) Reset() { *m = RegisterResourceRespon
|
|||
func (m *RegisterResourceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RegisterResourceResponse) ProtoMessage() {}
|
||||
func (*RegisterResourceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_resource_814328246bd928d7, []int{3}
|
||||
return fileDescriptor_resource_03e51d5764cd9ae8, []int{3}
|
||||
}
|
||||
func (m *RegisterResourceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RegisterResourceResponse.Unmarshal(m, b)
|
||||
|
@ -390,7 +398,7 @@ func (m *RegisterResourceOutputsRequest) Reset() { *m = RegisterResource
|
|||
func (m *RegisterResourceOutputsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RegisterResourceOutputsRequest) ProtoMessage() {}
|
||||
func (*RegisterResourceOutputsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_resource_814328246bd928d7, []int{4}
|
||||
return fileDescriptor_resource_03e51d5764cd9ae8, []int{4}
|
||||
}
|
||||
func (m *RegisterResourceOutputsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RegisterResourceOutputsRequest.Unmarshal(m, b)
|
||||
|
@ -605,45 +613,46 @@ var _ResourceMonitor_serviceDesc = grpc.ServiceDesc{
|
|||
Metadata: "resource.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("resource.proto", fileDescriptor_resource_814328246bd928d7) }
|
||||
func init() { proto.RegisterFile("resource.proto", fileDescriptor_resource_03e51d5764cd9ae8) }
|
||||
|
||||
var fileDescriptor_resource_814328246bd928d7 = []byte{
|
||||
// 577 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x95, 0xcd, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0xc7, 0x6b, 0xa7, 0x75, 0xda, 0x69, 0x15, 0xaa, 0x25, 0x6a, 0x5d, 0x83, 0x4a, 0x65, 0x2e,
|
||||
0xc0, 0xc1, 0x11, 0xe1, 0x50, 0x84, 0x90, 0xb8, 0xd0, 0x03, 0x87, 0x0a, 0x30, 0x67, 0x90, 0x1c,
|
||||
0x67, 0x88, 0x4c, 0x13, 0xef, 0xb2, 0x1f, 0x91, 0x72, 0xe3, 0x45, 0x10, 0x6f, 0xc6, 0x89, 0x07,
|
||||
0x61, 0xd7, 0x6b, 0x87, 0x38, 0x76, 0x9a, 0x8a, 0x53, 0xe6, 0x6b, 0xff, 0x3b, 0xfb, 0xdb, 0x59,
|
||||
0x07, 0x7a, 0x1c, 0x05, 0x55, 0x3c, 0xc5, 0x88, 0x71, 0x2a, 0x29, 0x39, 0x60, 0x6a, 0xaa, 0x66,
|
||||
0x19, 0x67, 0x69, 0xf0, 0x60, 0x42, 0xe9, 0x64, 0x8a, 0x83, 0x22, 0x31, 0x52, 0x5f, 0x07, 0x38,
|
||||
0x63, 0x72, 0x61, 0xeb, 0x82, 0x87, 0xeb, 0x49, 0x21, 0xb9, 0x4a, 0x65, 0x99, 0xed, 0xe9, 0x9f,
|
||||
0x79, 0x36, 0x46, 0x6e, 0xfd, 0xf0, 0xb7, 0x03, 0xf7, 0x63, 0x4c, 0xc6, 0x71, 0xb9, 0x59, 0x8c,
|
||||
0xdf, 0x15, 0x0a, 0x49, 0x7a, 0xe0, 0x66, 0x63, 0xdf, 0xb9, 0x70, 0x9e, 0x1c, 0xc4, 0xda, 0x22,
|
||||
0x04, 0x76, 0xe5, 0x82, 0xa1, 0xef, 0x16, 0x91, 0xc2, 0x36, 0xb1, 0x3c, 0x99, 0xa1, 0xdf, 0xb1,
|
||||
0x31, 0x63, 0x93, 0x13, 0xf0, 0x58, 0xc2, 0x31, 0x97, 0xfe, 0x6e, 0x11, 0x2d, 0x3d, 0x72, 0x09,
|
||||
0xa0, 0x37, 0x64, 0xc8, 0x65, 0x86, 0xc2, 0xdf, 0xd3, 0xb9, 0xc3, 0xe1, 0x69, 0x64, 0x5b, 0x8d,
|
||||
0xaa, 0x56, 0xa3, 0x4f, 0x45, 0xab, 0xf1, 0x4a, 0x29, 0x09, 0xe1, 0x68, 0x8c, 0x0c, 0xf3, 0x31,
|
||||
0xe6, 0xa9, 0x59, 0xea, 0x5d, 0x74, 0xb4, 0x6c, 0x2d, 0x46, 0x02, 0xd8, 0xaf, 0x8e, 0xe5, 0x77,
|
||||
0x8b, 0x6d, 0x97, 0x7e, 0x98, 0x40, 0xbf, 0x7e, 0x3e, 0xc1, 0x68, 0x2e, 0x90, 0x1c, 0x43, 0x47,
|
||||
0xf1, 0xbc, 0x3c, 0xa1, 0x31, 0xd7, 0x5a, 0x74, 0xef, 0xdc, 0x62, 0xf8, 0x73, 0x17, 0x4e, 0x63,
|
||||
0x9c, 0x64, 0x42, 0x22, 0x5f, 0xe7, 0x58, 0x71, 0x73, 0x5a, 0xb8, 0xb9, 0xad, 0xdc, 0x3a, 0x35,
|
||||
0x6e, 0x3a, 0x9e, 0x2a, 0x21, 0xe9, 0xac, 0xe0, 0xb9, 0x1f, 0x97, 0x1e, 0x19, 0x80, 0x47, 0x47,
|
||||
0xdf, 0x30, 0x95, 0xdb, 0x58, 0x96, 0x65, 0xc4, 0x87, 0xae, 0x49, 0x99, 0x15, 0x5e, 0xa1, 0x54,
|
||||
0xb9, 0x0d, 0xc2, 0xdd, 0x2d, 0x84, 0xf7, 0xeb, 0x84, 0x09, 0x83, 0x7e, 0x09, 0x63, 0xf1, 0x76,
|
||||
0x55, 0xe7, 0x40, 0xeb, 0x1c, 0x0e, 0x5f, 0x47, 0xcb, 0xb9, 0x8d, 0x36, 0x40, 0x8a, 0x3e, 0xb4,
|
||||
0x2c, 0xbf, 0xca, 0x25, 0x5f, 0xc4, 0xad, 0xca, 0xc1, 0x33, 0xe8, 0xb7, 0x2d, 0x31, 0x60, 0xf5,
|
||||
0x45, 0x0a, 0x0d, 0xdb, 0x9c, 0xa0, 0xb0, 0x83, 0x1f, 0x0e, 0x9c, 0x6d, 0xd4, 0x37, 0x53, 0x70,
|
||||
0x83, 0x8b, 0x6a, 0x0a, 0xb4, 0x49, 0xae, 0x61, 0x6f, 0x9e, 0x4c, 0x15, 0x96, 0x03, 0x70, 0xf9,
|
||||
0x9f, 0xed, 0xc7, 0x56, 0xe5, 0x95, 0xfb, 0xd2, 0x09, 0x7f, 0x39, 0xe0, 0x37, 0xd7, 0x6e, 0x9c,
|
||||
0x43, 0xfb, 0xf4, 0xdc, 0xe5, 0xd3, 0xfb, 0x77, 0xd5, 0x9d, 0xbb, 0x5d, 0xb5, 0x9e, 0x19, 0x21,
|
||||
0x93, 0xd1, 0x14, 0xab, 0x99, 0xb1, 0x9e, 0x19, 0x01, 0x6b, 0x99, 0x07, 0x68, 0x08, 0x55, 0x6e,
|
||||
0x88, 0x70, 0xbe, 0xde, 0xe0, 0x7b, 0x25, 0x99, 0x92, 0xa2, 0x9a, 0xe3, 0x66, 0x9b, 0xcf, 0xa1,
|
||||
0x4b, 0x6d, 0xcd, 0xb6, 0xb7, 0x52, 0xd5, 0x0d, 0xff, 0xb8, 0x70, 0xaf, 0xd2, 0xbf, 0xa6, 0x79,
|
||||
0x26, 0x29, 0x27, 0x6f, 0xc0, 0x7b, 0x97, 0xcf, 0xe9, 0x8d, 0x6e, 0x6f, 0x05, 0xb5, 0x0d, 0x95,
|
||||
0x9b, 0x07, 0x67, 0x2d, 0x19, 0x8b, 0x2f, 0xdc, 0x21, 0x1f, 0xe1, 0x68, 0xf5, 0x81, 0x93, 0xf3,
|
||||
0xda, 0x8d, 0x35, 0xbe, 0x6c, 0xc1, 0xa3, 0x8d, 0xf9, 0xa5, 0xe4, 0x67, 0x38, 0x5e, 0xc7, 0x41,
|
||||
0xc2, 0xed, 0x83, 0x10, 0x3c, 0xbe, 0xb5, 0x66, 0x29, 0xff, 0xa5, 0xf9, 0xb9, 0x28, 0x69, 0x93,
|
||||
0xa7, 0xb7, 0x28, 0xd4, 0x6f, 0x24, 0x38, 0x69, 0xe0, 0xbe, 0x32, 0xff, 0x02, 0xe1, 0xce, 0xc8,
|
||||
0x2b, 0x22, 0x2f, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x12, 0x2a, 0xc4, 0xa0, 0x42, 0x06, 0x00,
|
||||
0x00,
|
||||
var fileDescriptor_resource_03e51d5764cd9ae8 = []byte{
|
||||
// 601 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0xae, 0x9d, 0xd6, 0x49, 0xa6, 0x55, 0xa8, 0xb6, 0x51, 0xeb, 0x1a, 0x54, 0x2a, 0x73, 0x01,
|
||||
0x0e, 0x0e, 0x84, 0x43, 0x11, 0x42, 0x42, 0x42, 0xf4, 0xc0, 0xa1, 0x02, 0xcc, 0x19, 0x24, 0xc7,
|
||||
0x9e, 0x46, 0xa6, 0x8e, 0x77, 0x59, 0xaf, 0x23, 0xe5, 0xc6, 0x9b, 0xf0, 0x48, 0xbc, 0x01, 0x27,
|
||||
0x1e, 0x84, 0x5d, 0xaf, 0x1d, 0xe2, 0xd8, 0x69, 0x2a, 0x4e, 0x99, 0xbf, 0xfd, 0x76, 0xe6, 0x9b,
|
||||
0x6f, 0x1d, 0x18, 0x70, 0xcc, 0x68, 0xce, 0x43, 0xf4, 0x18, 0xa7, 0x82, 0x92, 0x3e, 0xcb, 0x93,
|
||||
0x7c, 0x16, 0x73, 0x16, 0x3a, 0xf7, 0xa7, 0x94, 0x4e, 0x13, 0x1c, 0x15, 0x89, 0x49, 0x7e, 0x3d,
|
||||
0xc2, 0x19, 0x13, 0x0b, 0x5d, 0xe7, 0x3c, 0x58, 0x4f, 0x66, 0x82, 0xe7, 0xa1, 0x28, 0xb3, 0x03,
|
||||
0xf9, 0x33, 0x8f, 0x23, 0xe4, 0xda, 0x77, 0x7f, 0x1b, 0x70, 0xe4, 0x63, 0x10, 0xf9, 0xe5, 0x65,
|
||||
0x3e, 0x7e, 0xcf, 0x31, 0x13, 0x64, 0x00, 0x66, 0x1c, 0xd9, 0xc6, 0xb9, 0xf1, 0xb8, 0xef, 0x4b,
|
||||
0x8b, 0x10, 0xd8, 0x15, 0x0b, 0x86, 0xb6, 0x59, 0x44, 0x0a, 0x5b, 0xc5, 0xd2, 0x60, 0x86, 0x76,
|
||||
0x47, 0xc7, 0x94, 0x4d, 0x8e, 0xc1, 0x62, 0x01, 0xc7, 0x54, 0xd8, 0xbb, 0x45, 0xb4, 0xf4, 0xc8,
|
||||
0x05, 0x80, 0xbc, 0x90, 0x21, 0x17, 0x31, 0x66, 0xf6, 0x9e, 0xcc, 0xed, 0x8f, 0x4f, 0x3c, 0xdd,
|
||||
0xaa, 0x57, 0xb5, 0xea, 0x7d, 0x2e, 0x5a, 0xf5, 0x57, 0x4a, 0x89, 0x0b, 0x07, 0x11, 0x32, 0x4c,
|
||||
0x23, 0x4c, 0x43, 0x75, 0xd4, 0x3a, 0xef, 0x48, 0xd8, 0x5a, 0x8c, 0x38, 0xd0, 0xab, 0xc6, 0xb2,
|
||||
0xbb, 0xc5, 0xb5, 0x4b, 0xdf, 0x0d, 0x60, 0x58, 0x9f, 0x2f, 0x63, 0x34, 0xcd, 0x90, 0x1c, 0x42,
|
||||
0x27, 0xe7, 0x69, 0x39, 0xa1, 0x32, 0xd7, 0x5a, 0x34, 0xef, 0xdc, 0xa2, 0xfb, 0x6b, 0x17, 0x4e,
|
||||
0x7c, 0x9c, 0xc6, 0x99, 0x40, 0xbe, 0xce, 0x63, 0xc5, 0x9b, 0xd1, 0xc2, 0x9b, 0xd9, 0xca, 0x5b,
|
||||
0xa7, 0xc6, 0x9b, 0x8c, 0x87, 0x79, 0x26, 0xe8, 0xac, 0xe0, 0xb3, 0xe7, 0x97, 0x1e, 0x19, 0x81,
|
||||
0x45, 0x27, 0xdf, 0x30, 0x14, 0xdb, 0xb8, 0x2c, 0xcb, 0x88, 0x0d, 0x5d, 0x95, 0x52, 0x27, 0xac,
|
||||
0x02, 0xa9, 0x72, 0x1b, 0x0c, 0x77, 0xb7, 0x30, 0xdc, 0xab, 0x33, 0x4c, 0x18, 0x0c, 0x4b, 0x32,
|
||||
0x16, 0xef, 0x56, 0x71, 0xfa, 0x12, 0x67, 0x7f, 0xfc, 0xda, 0x5b, 0xea, 0xd6, 0xdb, 0x40, 0x92,
|
||||
0xf7, 0xb1, 0xe5, 0xf8, 0x65, 0x2a, 0xf8, 0xc2, 0x6f, 0x45, 0x26, 0xcf, 0xe0, 0x28, 0xc2, 0x04,
|
||||
0x05, 0xbe, 0xc5, 0x6b, 0xca, 0x25, 0x0c, 0x4b, 0x82, 0x10, 0x6d, 0x28, 0xe6, 0x6a, 0x4b, 0x39,
|
||||
0x4f, 0x61, 0xd8, 0x76, 0x89, 0x5a, 0x85, 0x5c, 0x7d, 0x26, 0xd7, 0xa3, 0x66, 0x2e, 0x6c, 0xe7,
|
||||
0x87, 0x01, 0xa7, 0x1b, 0x3b, 0x52, 0xba, 0xb9, 0xc1, 0x45, 0xa5, 0x1b, 0x69, 0x92, 0x2b, 0xd8,
|
||||
0x9b, 0x07, 0x49, 0x8e, 0xa5, 0x64, 0x2e, 0xfe, 0x73, 0x60, 0x5f, 0xa3, 0xbc, 0x32, 0x5f, 0x1a,
|
||||
0xee, 0x4f, 0x03, 0xec, 0xe6, 0xd9, 0x8d, 0xca, 0xd5, 0x8f, 0xd5, 0x5c, 0x3e, 0xd6, 0x7f, 0xe2,
|
||||
0xe8, 0xdc, 0x4d, 0x1c, 0x52, 0x65, 0x99, 0x08, 0x26, 0x09, 0x56, 0x2a, 0xd3, 0x9e, 0x12, 0x8d,
|
||||
0xb6, 0xd4, 0x93, 0x55, 0x0c, 0x55, 0xae, 0x8b, 0x70, 0xb6, 0xde, 0xe0, 0x87, 0x5c, 0xb0, 0x5c,
|
||||
0x64, 0x95, 0xf2, 0x9b, 0x6d, 0x3e, 0x87, 0x2e, 0xd5, 0x35, 0xdb, 0x5e, 0x57, 0x55, 0x37, 0xfe,
|
||||
0x63, 0xc2, 0xbd, 0x0a, 0xff, 0x8a, 0xa6, 0xb1, 0xa0, 0x9c, 0xbc, 0x01, 0xeb, 0x7d, 0x3a, 0xa7,
|
||||
0x37, 0xb2, 0xbd, 0x15, 0xaa, 0x75, 0xa8, 0xbc, 0xdc, 0x39, 0x6d, 0xc9, 0x68, 0xfa, 0xdc, 0x1d,
|
||||
0xf2, 0x09, 0x0e, 0x56, 0x3f, 0x09, 0xe4, 0xac, 0xb6, 0xb1, 0xc6, 0xb7, 0xd0, 0x79, 0xb8, 0x31,
|
||||
0xbf, 0x84, 0xfc, 0x02, 0x87, 0xeb, 0x74, 0x10, 0x77, 0xbb, 0x10, 0x9c, 0x47, 0xb7, 0xd6, 0x2c,
|
||||
0xe1, 0xbf, 0x36, 0x3f, 0x30, 0x25, 0xdb, 0xe4, 0xc9, 0x2d, 0x08, 0xf5, 0x8d, 0x38, 0xc7, 0x0d,
|
||||
0xba, 0x2f, 0xd5, 0xff, 0x86, 0xbb, 0x33, 0xb1, 0x8a, 0xc8, 0x8b, 0xbf, 0x01, 0x00, 0x00, 0xff,
|
||||
0xff, 0x00, 0xdf, 0xec, 0x9d, 0x74, 0x06, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ message RegisterResourceRequest {
|
|||
bool protect = 6; // true if the resource should be marked protected.
|
||||
repeated string dependencies = 7; // a list of URNs that this resource depends on, as observed by the language host.
|
||||
string provider = 8; // an optional reference to the provider to manage this resource's CRUD operations.
|
||||
|
||||
map<string, PropertyDependencies> propertyDependencies = 9; // a map from property keys to the dependencies of the property.
|
||||
bool deleteBeforeReplace = 10; // true if this resource should be deleted before replacement.
|
||||
}
|
||||
|
||||
// RegisterResourceResponse is returned by the engine after a resource has finished being initialized. It includes the
|
||||
|
|
|
@ -43,6 +43,11 @@ class ResourceOptions:
|
|||
If provided and True, this resource is not allowed to be deleted.
|
||||
"""
|
||||
|
||||
delete_before_replace: Optional[bool]
|
||||
"""
|
||||
If provided and True, this resource must be deleted before it is replaced.
|
||||
"""
|
||||
|
||||
provider: Optional['ProviderResource']
|
||||
"""
|
||||
An optional provider to use for this resource's CRUD operations. If no provider is supplied, the default
|
||||
|
@ -61,7 +66,8 @@ class ResourceOptions:
|
|||
depends_on: Optional[List['Resource']] = None,
|
||||
protect: Optional[bool] = None,
|
||||
provider: Optional['ProviderResource'] = None,
|
||||
providers: Optional[Mapping[str, 'ProviderResource']] = None) -> None:
|
||||
providers: Optional[Mapping[str, 'ProviderResource']] = None,
|
||||
delete_before_replace: Optional[bool] = None) -> None:
|
||||
"""
|
||||
:param Optional[Resource] parent: If provided, the currently-constructing resource should be the child of
|
||||
the provided parent resource.
|
||||
|
@ -73,13 +79,14 @@ class ResourceOptions:
|
|||
provider is pulled from the parent's provider bag.
|
||||
:param Optional[Mapping[str,ProviderResource]] providers: An optional set of providers to use for child resources. Keyed
|
||||
by package name (e.g. "aws")
|
||||
:param Optional[bool] delete_before_replace: If provided and True, this resource must be deleted before it is replaced.
|
||||
"""
|
||||
self.parent = parent
|
||||
self.depends_on = depends_on
|
||||
self.protect = protect
|
||||
self.provider = provider
|
||||
self.providers = providers
|
||||
|
||||
self.delete_before_replace = delete_before_replace
|
||||
|
||||
class Resource:
|
||||
"""
|
||||
|
|
|
@ -22,7 +22,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\"\xa2\x01\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\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xaf\x03\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\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\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\"}\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\"W\n\x1eRegisterResourceOutputsRequest\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12(\n\x07outputs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct2\xe4\x02\n\x0fResourceMonitor\x12?\n\x06Invoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\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\"\xa2\x01\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\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xcc\x03\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\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\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\"}\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\"W\n\x1eRegisterResourceOutputsRequest\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12(\n\x07outputs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct2\xe4\x02\n\x0fResourceMonitor\x12?\n\x06Invoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\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,])
|
||||
|
||||
|
@ -166,8 +166,8 @@ _REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIES = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=629,
|
||||
serialized_end=665,
|
||||
serialized_start=658,
|
||||
serialized_end=694,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
|
||||
|
@ -203,8 +203,8 @@ _REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=667,
|
||||
serialized_end=783,
|
||||
serialized_start=696,
|
||||
serialized_end=812,
|
||||
)
|
||||
|
||||
_REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
|
||||
|
@ -277,6 +277,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='deleteBeforeReplace', full_name='pulumirpc.RegisterResourceRequest.deleteBeforeReplace', index=9,
|
||||
number=10, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
|
@ -290,7 +297,7 @@ _REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
|
|||
oneofs=[
|
||||
],
|
||||
serialized_start=352,
|
||||
serialized_end=783,
|
||||
serialized_end=812,
|
||||
)
|
||||
|
||||
|
||||
|
@ -348,8 +355,8 @@ _REGISTERRESOURCERESPONSE = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=785,
|
||||
serialized_end=910,
|
||||
serialized_start=814,
|
||||
serialized_end=939,
|
||||
)
|
||||
|
||||
|
||||
|
@ -386,8 +393,8 @@ _REGISTERRESOURCEOUTPUTSREQUEST = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=912,
|
||||
serialized_end=999,
|
||||
serialized_start=941,
|
||||
serialized_end=1028,
|
||||
)
|
||||
|
||||
_READRESOURCEREQUEST.fields_by_name['properties'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT
|
||||
|
@ -466,8 +473,8 @@ _RESOURCEMONITOR = _descriptor.ServiceDescriptor(
|
|||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
serialized_start=1002,
|
||||
serialized_end=1358,
|
||||
serialized_start=1031,
|
||||
serialized_end=1387,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name='Invoke',
|
||||
|
|
|
@ -182,7 +182,8 @@ def register_resource(res: 'Resource', ty: str, name: str, custom: bool, props:
|
|||
protect=opts.protect,
|
||||
provider=resolver.provider_ref,
|
||||
dependencies=resolver.dependencies,
|
||||
propertyDependencies=property_dependencies
|
||||
propertyDependencies=property_dependencies,
|
||||
deleteBeforeReplace=opts.delete_before_replace
|
||||
)
|
||||
|
||||
def do_rpc_call():
|
||||
|
|
|
@ -24,7 +24,7 @@ class AssetTest(LanghostTest):
|
|||
expected_resource_count=3)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
if name == "file":
|
||||
self.assertIsInstance(resource["asset"], FileAsset)
|
||||
|
|
|
@ -31,7 +31,7 @@ class ChainedFailureTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, res, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps):
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
if ty == "test:index:ResourceA":
|
||||
self.assertEqual(name, "resourceA")
|
||||
self.assertDictEqual(res, {"inprop": 777})
|
||||
|
|
|
@ -28,7 +28,7 @@ class ConfigTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
self.assertEqual("myname", name)
|
||||
return {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# Copyright 2016-2018, 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.
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright 2016-2018, 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
|
||||
|
||||
class MyResource(CustomResource):
|
||||
def __init__(self, name, opts=None):
|
||||
CustomResource.__init__(self, "test:index:MyResource", name, opts=opts)
|
||||
|
||||
res = MyResource("foo", opts=ResourceOptions(delete_before_replace=True))
|
|
@ -0,0 +1,33 @@
|
|||
# Copyright 2016-2018, 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 DeleteBeforeReplaceTest(LanghostTest):
|
||||
"""
|
||||
Tests that DBRed resources correctly pass the "DBR" boolean to the engine.
|
||||
"""
|
||||
def test_protect(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):
|
||||
self.assertEqual("foo", name)
|
||||
self.assertTrue(delete_before_replace)
|
||||
return {
|
||||
"urn": self.make_urn(ty, name)
|
||||
}
|
|
@ -29,7 +29,7 @@ class FirstClassProviderTest(LanghostTest):
|
|||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, provider, _property_deps, _delete_before_replace):
|
||||
if name == "testprov":
|
||||
# Provider resource.
|
||||
self.assertEqual("pulumi:providers:test", ty)
|
||||
|
|
|
@ -53,7 +53,7 @@ class TestFirstClassProviderInvoke(LanghostTest):
|
|||
}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps):
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
if name == "testprov":
|
||||
self.assertEqual("pulumi:providers:test", ty)
|
||||
self.prov_urn = self.make_urn(ty, name)
|
||||
|
|
|
@ -31,7 +31,7 @@ class FirstClassProviderUnknown(LanghostTest):
|
|||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, _ctx, dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, provider, _property_deps):
|
||||
_parent, _custom, _protect, provider, _property_deps, _delete_before_replace):
|
||||
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
|
||||
|
|
|
@ -26,7 +26,7 @@ class FutureInputTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps):
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual(ty, "test:index:FileResource")
|
||||
self.assertEqual(name, "file")
|
||||
self.assertDictEqual(resource, {
|
||||
|
|
|
@ -30,7 +30,7 @@ class InheritDefaultsTest(LanghostTest):
|
|||
expected_resource_count=240)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, custom, protect, provider, _property_deps):
|
||||
_dependencies, _parent, custom, protect, provider, _property_deps, _delete_before_replace):
|
||||
if custom and not ty.startswith("pulumi:providers:"):
|
||||
expect_protect = False
|
||||
expect_provider_name = ""
|
||||
|
|
|
@ -33,7 +33,7 @@ class TestInvoke(LanghostTest):
|
|||
}
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps):
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
self.assertEqual("resourceA", name)
|
||||
self.assertEqual(resource["value"], 42)
|
||||
|
|
|
@ -23,7 +23,7 @@ class OneComplexResourceTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "testres")
|
||||
self.assertEqual(resource["falseprop"], False)
|
||||
|
|
|
@ -22,7 +22,7 @@ class OneResourceTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "testResource1")
|
||||
return {
|
||||
|
|
|
@ -24,7 +24,7 @@ class OutputAllTest(LanghostTest):
|
|||
expected_resource_count=3)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
number = 0
|
||||
if name == "testResource1":
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
|
|
|
@ -22,7 +22,7 @@ class OutputNestedTest(LanghostTest):
|
|||
expected_resource_count=3)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
nested_numbers = None
|
||||
if name == "testResource1":
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
|
|
|
@ -25,7 +25,7 @@ class PreviewTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
self.assertEqual(name, "foo")
|
||||
if dry_run:
|
||||
|
|
|
@ -23,7 +23,7 @@ class PropertyDependenciesTest(LanghostTest):
|
|||
expected_resource_count=5)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_dependencies):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_dependencies, _delete_before_replace):
|
||||
self.assertEqual(ty, "test:index:MyResource")
|
||||
if name == "resA":
|
||||
self.assertListEqual(_dependencies, [])
|
||||
|
|
|
@ -26,7 +26,7 @@ class PropertyRenamingTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, res, _deps,
|
||||
_parent, _custom, _protect, _provider, _property_deps):
|
||||
_parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
# 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.
|
||||
|
|
|
@ -25,7 +25,7 @@ class ProtectTest(LanghostTest):
|
|||
expected_resource_count=1)
|
||||
|
||||
def register_resource(self, _ctx, _dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual("foo", name)
|
||||
self.assertTrue(protect)
|
||||
return {
|
||||
|
|
|
@ -22,5 +22,5 @@ class UnhandledExceptionTest(LanghostTest):
|
|||
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):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
raise Exception("oh no")
|
||||
|
|
|
@ -30,7 +30,7 @@ class ResourceThensTest(LanghostTest):
|
|||
expected_resource_count=2)
|
||||
|
||||
def register_resource(self, _ctx, dry_run, ty, name, res, deps,
|
||||
_parent, custom, _protect, _provider, _property_deps):
|
||||
_parent, custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
if ty == "test:index:ResourceA":
|
||||
self.assertEqual(name, "resourceA")
|
||||
self.assertDictEqual(res, {"inprop": 777})
|
||||
|
|
|
@ -25,7 +25,7 @@ class TenResourcesTest(LanghostTest):
|
|||
expected_resource_count=10)
|
||||
|
||||
def register_resource(self, ctx, dry_run, ty, name, _resource,
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps):
|
||||
_dependencies, _parent, _custom, _protect, _provider, _property_deps, _delete_before_replace):
|
||||
self.assertEqual("test:index:MyResource", ty)
|
||||
if not dry_run:
|
||||
self.assertIsNone(
|
||||
|
|
|
@ -19,6 +19,7 @@ import asyncio
|
|||
import unittest
|
||||
from collections import namedtuple
|
||||
from concurrent import futures
|
||||
from inspect import signature
|
||||
import logging
|
||||
import subprocess
|
||||
from os import path
|
||||
|
@ -87,6 +88,7 @@ class LanghostMockResourceMonitor(proto.ResourceMonitorServicer):
|
|||
custom = request.custom
|
||||
protect = request.protect
|
||||
provider = request.provider
|
||||
delete_before_replace = request.deleteBeforeReplace
|
||||
|
||||
property_dependencies = {}
|
||||
for key, value in request.propertyDependencies.items():
|
||||
|
@ -95,7 +97,7 @@ class LanghostMockResourceMonitor(proto.ResourceMonitorServicer):
|
|||
outs = {}
|
||||
if type_ != "pulumi:pulumi:Stack":
|
||||
outs = self.langhost_test.register_resource(
|
||||
context, self.dryrun, type_, name, props, deps, parent, custom, protect, provider, property_dependencies)
|
||||
context, self.dryrun, type_, name, props, deps, parent, custom, protect, provider, property_dependencies, delete_before_replace)
|
||||
if outs.get("urn"):
|
||||
urn = outs["urn"]
|
||||
self.registrations[urn] = {
|
||||
|
|
|
@ -32,6 +32,10 @@ func TestDeleteBeforeCreate(t *testing.T) {
|
|||
Dir: "step5",
|
||||
Additive: true,
|
||||
},
|
||||
{
|
||||
Dir: "step6",
|
||||
Additive: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ export class Provider implements dynamic.ResourceProvider {
|
|||
return {
|
||||
changes: true,
|
||||
replaces: ["state"],
|
||||
deleteBeforeReplace: true,
|
||||
deleteBeforeReplace: news.noDBR ? false : true,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ export class Resource extends pulumi.dynamic.Resource {
|
|||
public state: pulumi.Output<number>;
|
||||
public noReplace?: pulumi.Output<number>;
|
||||
|
||||
constructor(name: string, props: ResourceProps, opts?: pulumi.ResourceOptions) {
|
||||
constructor(name: string, props: ResourceProps, opts?: pulumi.CustomResourceOptions) {
|
||||
super(Provider.instance, name, props, opts);
|
||||
}
|
||||
}
|
||||
|
@ -55,4 +55,5 @@ export interface ResourceProps {
|
|||
readonly uniqueKey?: pulumi.Input<number>;
|
||||
readonly state: pulumi.Input<number>;
|
||||
readonly noReplace?: pulumi.Input<number>;
|
||||
readonly noDBR?: pulumi.Input<boolean>;
|
||||
}
|
||||
|
|
13
tests/integration/delete_before_create/step6/index.ts
Normal file
13
tests/integration/delete_before_create/step6/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016-2018, Pulumi Corporation. All rights reserved.
|
||||
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import { Resource } from "./resource";
|
||||
|
||||
// Base should not be delete-before-replaced, but should still be replaced.
|
||||
const a = new Resource("base", { uniqueKey: 1, state: 42, noDBR: true });
|
||||
|
||||
// Base-2 should not be delete-before-replaced, but should still be replaced.
|
||||
const b = new Resource("base-2", { uniqueKey: 2, state: 42, noDBR: true });
|
||||
|
||||
// Dependent should be delete-before-replaced.
|
||||
const c = new Resource("dependent", { state: pulumi.all([a.state, b.state]).apply(([astate, bstate]) => astate + bstate), noDBR: true }, { deleteBeforeReplace: true });
|
Loading…
Reference in a new issue