9b6a7a4397
- Add component ref coverage to the existing test - Add coverage for a downlevel SDK communicating with an engine that supports resource refs - Add coverage for a downlevel engine communicating with an SDK that supports resource refs As part of improving coverage, these changes add a knob to explicitly disable resource refs in the engine without the use of the environment variable. The environment variable is now only read by the CLI, and has been restored to its prior polarity (i.e. `PULUMI_ENABLE_RESOURCE_REFERENCES`).
222 lines
7.3 KiB
Go
222 lines
7.3 KiB
Go
//nolint:goconst
|
|
package lifecycletest
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/blang/semver"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
. "github.com/pulumi/pulumi/pkg/v2/engine"
|
|
"github.com/pulumi/pulumi/pkg/v2/resource/deploy/deploytest"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/resource"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/resource/plugin"
|
|
)
|
|
|
|
// TestResourceReferences tests that resource references can be marshaled between the engine, language host,
|
|
// resource providers, and statefile if each entity supports resource references.
|
|
func TestResourceReferences(t *testing.T) {
|
|
var urnA resource.URN
|
|
var urnB resource.URN
|
|
var idB resource.ID
|
|
|
|
loaders := []*deploytest.ProviderLoader{
|
|
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
|
v := &deploytest.Provider{
|
|
CreateF: func(urn resource.URN, news resource.PropertyMap,
|
|
timeout float64, preview bool) (resource.ID, resource.PropertyMap, resource.Status, error) {
|
|
|
|
id := "created-id"
|
|
if preview {
|
|
id = ""
|
|
}
|
|
|
|
if urn.Name() == "resC" {
|
|
assert.True(t, news.DeepEquals(resource.PropertyMap{
|
|
"resA": resource.MakeResourceReference(urnA, "", false, ""),
|
|
"resB": resource.MakeResourceReference(urnB, idB, true, ""),
|
|
}))
|
|
}
|
|
|
|
return resource.ID(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
|
|
},
|
|
}
|
|
return v, nil
|
|
}),
|
|
}
|
|
|
|
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
|
var err error
|
|
urnA, _, _, err = monitor.RegisterResource("component", "resA", false)
|
|
assert.NoError(t, err)
|
|
|
|
err = monitor.RegisterResourceOutputs(urnA, resource.PropertyMap{})
|
|
assert.NoError(t, err)
|
|
|
|
urnB, idB, _, err = monitor.RegisterResource("pkgA:m:typA", "resB", true)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, props, err := monitor.RegisterResource("pkgA:m:typA", "resC", true, deploytest.ResourceOptions{
|
|
Inputs: resource.PropertyMap{
|
|
"resA": resource.MakeResourceReference(urnA, "", false, ""),
|
|
"resB": resource.MakeResourceReference(urnB, idB, true, ""),
|
|
},
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, props.DeepEquals(resource.PropertyMap{
|
|
"resA": resource.MakeResourceReference(urnA, "", false, ""),
|
|
"resB": resource.MakeResourceReference(urnB, idB, true, ""),
|
|
}))
|
|
return nil
|
|
})
|
|
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
|
|
|
p := &TestPlan{
|
|
Options: UpdateOptions{Host: host},
|
|
Steps: MakeBasicLifecycleSteps(t, 4),
|
|
}
|
|
p.Run(t, nil)
|
|
}
|
|
|
|
// TestResourceReferences_DownlevelSDK tests that resource references are properly marshaled as URNs (for references to
|
|
// component resources) or IDs (for references to custom resources) if the SDK does not support resource references.
|
|
func TestResourceReferences_DownlevelSDK(t *testing.T) {
|
|
var urnA resource.URN
|
|
var urnB resource.URN
|
|
var idB resource.ID
|
|
|
|
loaders := []*deploytest.ProviderLoader{
|
|
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
|
v := &deploytest.Provider{
|
|
CreateF: func(urn resource.URN, news resource.PropertyMap,
|
|
timeout float64, preview bool) (resource.ID, resource.PropertyMap, resource.Status, error) {
|
|
|
|
id := "created-id"
|
|
if preview {
|
|
id = ""
|
|
}
|
|
|
|
state := resource.PropertyMap{}
|
|
if urn.Name() == "resC" {
|
|
state = resource.PropertyMap{
|
|
"resA": resource.MakeResourceReference(urnA, "", false, ""),
|
|
"resB": resource.MakeResourceReference(urnB, idB, true, ""),
|
|
}
|
|
}
|
|
|
|
return resource.ID(id), state, 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
|
|
},
|
|
}
|
|
return v, nil
|
|
}),
|
|
}
|
|
|
|
opts := deploytest.ResourceOptions{DisableResourceReferences: true}
|
|
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
|
var err error
|
|
urnA, _, _, err = monitor.RegisterResource("component", "resA", false, opts)
|
|
assert.NoError(t, err)
|
|
|
|
err = monitor.RegisterResourceOutputs(urnA, resource.PropertyMap{})
|
|
assert.NoError(t, err)
|
|
|
|
urnB, idB, _, err = monitor.RegisterResource("pkgA:m:typA", "resB", true, opts)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, props, err := monitor.RegisterResource("pkgA:m:typA", "resC", true, opts)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, props.DeepEquals(resource.PropertyMap{
|
|
"resA": resource.NewStringProperty(string(urnA)),
|
|
"resB": resource.NewStringProperty(string(idB)),
|
|
}))
|
|
return nil
|
|
})
|
|
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
|
|
|
p := &TestPlan{
|
|
Options: UpdateOptions{Host: host},
|
|
Steps: MakeBasicLifecycleSteps(t, 4),
|
|
}
|
|
p.Run(t, nil)
|
|
}
|
|
|
|
// TestResourceReferences_DownlevelEngine tests an SDK that supports resource references communicating with an engine
|
|
// that does not.
|
|
func TestResourceReferences_DownlevelEngine(t *testing.T) {
|
|
var urnA resource.URN
|
|
var urnB resource.URN
|
|
var idB resource.ID
|
|
|
|
loaders := []*deploytest.ProviderLoader{
|
|
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
|
v := &deploytest.Provider{
|
|
CreateF: func(urn resource.URN, news resource.PropertyMap,
|
|
timeout float64, preview bool) (resource.ID, resource.PropertyMap, resource.Status, error) {
|
|
|
|
id := "created-id"
|
|
if preview {
|
|
id = ""
|
|
}
|
|
|
|
// If we have resource references here, the engine has not properly disabled them.
|
|
if urn.Name() == "resC" {
|
|
assert.Equal(t, resource.NewStringProperty(string(urnA)), news["resA"])
|
|
assert.Equal(t, resource.NewStringProperty(string(idB)), news["resB"])
|
|
}
|
|
|
|
return resource.ID(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
|
|
},
|
|
}
|
|
return v, nil
|
|
}),
|
|
}
|
|
|
|
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
|
var err error
|
|
urnA, _, _, err = monitor.RegisterResource("component", "resA", false)
|
|
assert.NoError(t, err)
|
|
|
|
err = monitor.RegisterResourceOutputs(urnA, resource.PropertyMap{})
|
|
assert.NoError(t, err)
|
|
|
|
urnB, idB, _, err = monitor.RegisterResource("pkgA:m:typA", "resB", true)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, props, err := monitor.RegisterResource("pkgA:m:typA", "resC", true, deploytest.ResourceOptions{
|
|
Inputs: resource.PropertyMap{
|
|
"resA": resource.MakeResourceReference(urnA, "", false, ""),
|
|
"resB": resource.MakeResourceReference(urnB, idB, true, ""),
|
|
},
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, props.DeepEquals(resource.PropertyMap{
|
|
"resA": resource.NewStringProperty(string(urnA)),
|
|
"resB": resource.NewStringProperty(string(idB)),
|
|
}))
|
|
return nil
|
|
})
|
|
|
|
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
|
|
|
p := &TestPlan{
|
|
Options: UpdateOptions{Host: host, DisableResourceReferences: true},
|
|
Steps: MakeBasicLifecycleSteps(t, 4),
|
|
}
|
|
p.Run(t, nil)
|
|
}
|