Deprecate deps maps when using output values
When output values are being sent to a provider, there's no need to also send the dependencies map, because the output values themselves contain the dependencies. This allows for a simpler implementation in the provider.
This commit is contained in:
parent
7888623aca
commit
7487e99d94
|
@ -631,13 +631,16 @@ func (rm *resmon) Call(ctx context.Context, req *pulumirpc.CallRequest) (*pulumi
|
|||
return nil, errors.Wrapf(err, "failed to unmarshal %v args", tok)
|
||||
}
|
||||
|
||||
argDependencies := map[resource.PropertyKey][]resource.URN{}
|
||||
for name, deps := range req.GetArgDependencies() {
|
||||
urns := make([]resource.URN, len(deps.Urns))
|
||||
for i, urn := range deps.Urns {
|
||||
urns[i] = resource.URN(urn)
|
||||
var argDependencies map[resource.PropertyKey][]resource.URN
|
||||
if len(req.GetArgDependencies()) > 0 {
|
||||
argDependencies = map[resource.PropertyKey][]resource.URN{}
|
||||
for name, deps := range req.GetArgDependencies() {
|
||||
urns := make([]resource.URN, len(deps.Urns))
|
||||
for i, urn := range deps.Urns {
|
||||
urns[i] = resource.URN(urn)
|
||||
}
|
||||
argDependencies[resource.PropertyKey(name)] = urns
|
||||
}
|
||||
argDependencies[resource.PropertyKey(name)] = urns
|
||||
}
|
||||
|
||||
info := plugin.CallInfo{
|
||||
|
@ -853,6 +856,7 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
replaceOnChanges := req.GetReplaceOnChanges()
|
||||
id := resource.ID(req.GetImportId())
|
||||
customTimeouts := req.GetCustomTimeouts()
|
||||
hasOutputs := req.GetHasOutputs()
|
||||
|
||||
// Custom resources must have a three-part type so that we can 1) identify if they are providers and 2) retrieve the
|
||||
// provider responsible for managing a particular resource (based on the type's Package).
|
||||
|
@ -913,7 +917,7 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
KeepResources: true,
|
||||
// To initially scope the use of this new feature, we only keep output values when unmarshaling
|
||||
// properties for RegisterResource (when remote is true for multi-lang components) and Call.
|
||||
KeepOutputValues: remote,
|
||||
KeepOutputValues: remote || hasOutputs,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -993,11 +997,14 @@ func (rm *resmon) RegisterResource(ctx context.Context,
|
|||
|
||||
// Invoke the provider's Construct RPC method.
|
||||
options := plugin.ConstructOptions{
|
||||
Aliases: aliases,
|
||||
Dependencies: dependencies,
|
||||
Protect: protect,
|
||||
PropertyDependencies: propertyDependencies,
|
||||
Providers: providerRefs,
|
||||
Aliases: aliases,
|
||||
Dependencies: dependencies,
|
||||
Protect: protect,
|
||||
Providers: providerRefs,
|
||||
}
|
||||
if !hasOutputs {
|
||||
// Only include property dependencies when we don't have output values in the properties.
|
||||
options.PropertyDependencies = propertyDependencies
|
||||
}
|
||||
constructResult, err := provider.Construct(rm.constructInfo, t, name, parent, props, options)
|
||||
if err != nil {
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver"
|
||||
|
@ -1125,14 +1126,24 @@ func (p *provider) Construct(info ConstructInfo, typ tokens.Type, name tokens.QN
|
|||
dependencies[i] = string(dep)
|
||||
}
|
||||
|
||||
// Marshal the property dependencies.
|
||||
inputDependencies := map[string]*pulumirpc.ConstructRequest_PropertyDependencies{}
|
||||
for name, dependencies := range options.PropertyDependencies {
|
||||
urns := make([]string, len(dependencies))
|
||||
for i, urn := range dependencies {
|
||||
urns[i] = string(urn)
|
||||
// If the provider accepts outputs, the marshaled inputs will have output values with dependencies,
|
||||
// so there's no need to specify the dependencies map.
|
||||
var inputDependencies map[string]*pulumirpc.ConstructRequest_PropertyDependencies
|
||||
if !p.acceptOutputs {
|
||||
// If the provider doesn't accept outputs, pass along the dependencies map.
|
||||
dependenciesMap := options.PropertyDependencies
|
||||
if len(dependenciesMap) == 0 {
|
||||
// If the dependencies map is empty, "polyfill" it based on dependencies gathered from the inputs.
|
||||
dependenciesMap = gatherDependenciesMap(inputs)
|
||||
}
|
||||
inputDependencies = make(map[string]*pulumirpc.ConstructRequest_PropertyDependencies, len(dependenciesMap))
|
||||
for name, dependencies := range dependenciesMap {
|
||||
urns := make([]string, len(dependencies))
|
||||
for i, urn := range dependencies {
|
||||
urns[i] = string(urn)
|
||||
}
|
||||
inputDependencies[string(name)] = &pulumirpc.ConstructRequest_PropertyDependencies{Urns: urns}
|
||||
}
|
||||
inputDependencies[string(name)] = &pulumirpc.ConstructRequest_PropertyDependencies{Urns: urns}
|
||||
}
|
||||
|
||||
// Marshal the config.
|
||||
|
@ -1367,14 +1378,24 @@ func (p *provider) Call(tok tokens.ModuleMember, args resource.PropertyMap, info
|
|||
return CallResult{}, err
|
||||
}
|
||||
|
||||
// Marshal the arg dependencies.
|
||||
argDependencies := map[string]*pulumirpc.CallRequest_ArgumentDependencies{}
|
||||
for name, dependencies := range options.ArgDependencies {
|
||||
urns := make([]string, len(dependencies))
|
||||
for i, urn := range dependencies {
|
||||
urns[i] = string(urn)
|
||||
// If the provider accepts outputs, the marshaled args will have output values with dependencies,
|
||||
// so there's no need to specify the dependencies map.
|
||||
var argDependencies map[string]*pulumirpc.CallRequest_ArgumentDependencies
|
||||
if !p.acceptOutputs {
|
||||
// If the provider doesn't accept outputs, pass along the dependencies map.
|
||||
dependenciesMap := options.ArgDependencies
|
||||
if len(dependenciesMap) == 0 {
|
||||
// If the dependencies map is empty, "polyfill" it based on dependencies gathered from the args.
|
||||
dependenciesMap = gatherDependenciesMap(args)
|
||||
}
|
||||
argDependencies = make(map[string]*pulumirpc.CallRequest_ArgumentDependencies, len(dependenciesMap))
|
||||
for name, dependencies := range dependenciesMap {
|
||||
urns := make([]string, len(dependencies))
|
||||
for i, urn := range dependencies {
|
||||
urns[i] = string(urn)
|
||||
}
|
||||
argDependencies[string(name)] = &pulumirpc.CallRequest_ArgumentDependencies{Urns: urns}
|
||||
}
|
||||
argDependencies[string(name)] = &pulumirpc.CallRequest_ArgumentDependencies{Urns: urns}
|
||||
}
|
||||
|
||||
// Marshal the config.
|
||||
|
@ -1613,3 +1634,55 @@ func decorateProviderSpans(span opentracing.Span, method string, req, resp inter
|
|||
span.SetTag("pulumi-decorator", req.(*pulumirpc.InvokeRequest).Tok)
|
||||
}
|
||||
}
|
||||
|
||||
// gatherDependenciesMap deeply gathers dependencies in the input's output values and resource
|
||||
// references to "polyfill" a dependencies map for providers that don't accept output values.
|
||||
func gatherDependenciesMap(inputs resource.PropertyMap) map[resource.PropertyKey][]resource.URN {
|
||||
type urnSet = map[resource.URN]struct{}
|
||||
|
||||
add := func(s urnSet, urn resource.URN) {
|
||||
s[urn] = struct{}{}
|
||||
}
|
||||
|
||||
sortedValues := func(s urnSet) []resource.URN {
|
||||
sorted := make([]resource.URN, 0, len(s))
|
||||
for k := range s {
|
||||
sorted = append(sorted, k)
|
||||
}
|
||||
sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
|
||||
return sorted
|
||||
}
|
||||
|
||||
var gatherDeps func(v resource.PropertyValue, deps urnSet)
|
||||
gatherDeps = func(v resource.PropertyValue, deps urnSet) {
|
||||
switch {
|
||||
case v.IsSecret():
|
||||
gatherDeps(v.SecretValue().Element, deps)
|
||||
case v.IsComputed():
|
||||
gatherDeps(v.Input().Element, deps)
|
||||
case v.IsOutput():
|
||||
for _, urn := range v.OutputValue().Dependencies {
|
||||
add(deps, urn)
|
||||
}
|
||||
gatherDeps(v.OutputValue().Element, deps)
|
||||
case v.IsResourceReference():
|
||||
add(deps, v.ResourceReferenceValue().URN)
|
||||
case v.IsArray():
|
||||
for _, e := range v.ArrayValue() {
|
||||
gatherDeps(e, deps)
|
||||
}
|
||||
case v.IsObject():
|
||||
for _, e := range v.ObjectValue() {
|
||||
gatherDeps(e, deps)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result := make(map[resource.PropertyKey][]resource.URN, len(inputs))
|
||||
for k, v := range inputs {
|
||||
deps := urnSet{}
|
||||
gatherDeps(v, deps)
|
||||
result[k] = sortedValues(deps)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue