Add support for serialized resource references. (#5041)

Resources are serialized as their URN, ID, and package version. Each
Pulumi package is expected to register itself with the SDK. The package
will be invoked to construct appropriate instances of rehydrated
resources. Packages are distinguished by their name and their version.

This is the foundation of cross-process resources.

Related to #2430.

Co-authored-by: Mikhail Shilkov <github@mikhail.io>
Co-authored-by: Luke Hoban <luke@pulumi.com>
Co-authored-by: Levi Blackstone <levi@pulumi.com>
This commit is contained in:
Pat Gavlin 2020-10-27 10:12:12 -07:00 committed by GitHub
parent 83f2aa613b
commit 3d2e31289a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 1476 additions and 476 deletions

1
.gitignore vendored
View file

@ -22,6 +22,7 @@ coverage.cov
# By default, we don't check in yarn.lock files
**/yarn.lock
# Turning on MyPy in VSCode creates this workspace local folder
.mypy_cache
# for goreleaser

View file

@ -414,6 +414,12 @@ func filterPropertyMap(propertyMap resource.PropertyMap, debug bool) resource.Pr
return resource.Output{
Element: filterPropertyValue(t.Element),
}
case resource.ResourceReference:
return resource.ResourceReference{
URN: resource.URN(filterValue(string(t.URN)).(string)),
ID: resource.ID(filterValue(string(t.ID)).(string)),
PackageVersion: filterValue(t.PackageVersion).(string),
}
}
// Next, see if it's an array, slice, pointer or struct, and handle each accordingly.

View file

@ -5527,6 +5527,57 @@ func TestSingleComponentDefaultProviderLifecycle(t *testing.T) {
p.Run(t, nil)
}
func TestResourceReferences(t *testing.T) {
var urnA resource.URN
var idA 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) {
if urn.Name() == "resB" {
propA, ok := news["resA"]
assert.True(t, ok)
assert.Equal(t, resource.MakeResourceReference(urnA, idA, ""), propA)
}
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
},
}
return v, nil
}),
}
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
var err error
urnA, idA, _, err = monitor.RegisterResource("pkgA:m:typA", "resA", true)
assert.NoError(t, err)
ins := resource.PropertyMap{
"resA": resource.MakeResourceReference(urnA, idA, ""),
}
_, _, props, err := monitor.RegisterResource("pkgA:m:typA", "resB", true, deploytest.ResourceOptions{
Inputs: ins,
})
assert.NoError(t, err)
assert.Equal(t, ins, props)
return nil
})
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
p := &TestPlan{
Options: UpdateOptions{Host: host},
Steps: MakeBasicLifecycleSteps(t, 3),
}
p.Run(t, nil)
}
type updateContext struct {
*deploytest.ResourceMonitor

View file

@ -88,7 +88,8 @@ func (rm *ResourceMonitor) RegisterResource(t tokens.Type, name string, custom b
// marshal inputs
ins, err := plugin.MarshalProperties(opts.Inputs, plugin.MarshalOptions{
KeepUnknowns: true,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return "", "", nil, err
@ -146,6 +147,7 @@ func (rm *ResourceMonitor) RegisterResource(t tokens.Type, name string, custom b
DeleteBeforeReplaceDefined: opts.DeleteBeforeReplace != nil,
IgnoreChanges: opts.IgnoreChanges,
AcceptSecrets: true,
AcceptResources: true,
Version: opts.Version,
Aliases: aliasStrings,
ImportId: string(opts.ImportID),
@ -161,7 +163,8 @@ func (rm *ResourceMonitor) RegisterResource(t tokens.Type, name string, custom b
}
// unmarshal outputs
outs, err := plugin.UnmarshalProperties(resp.Object, plugin.MarshalOptions{
KeepUnknowns: true,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return "", "", nil, err
@ -192,7 +195,8 @@ func (rm *ResourceMonitor) ReadResource(t tokens.Type, name string, id resource.
// marshal inputs
ins, err := plugin.MarshalProperties(inputs, plugin.MarshalOptions{
KeepUnknowns: true,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return "", nil, err
@ -214,7 +218,8 @@ func (rm *ResourceMonitor) ReadResource(t tokens.Type, name string, id resource.
// unmarshal outputs
outs, err := plugin.UnmarshalProperties(resp.Properties, plugin.MarshalOptions{
KeepUnknowns: true,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return "", nil, err
@ -228,7 +233,8 @@ func (rm *ResourceMonitor) Invoke(tok tokens.ModuleMember, inputs resource.Prope
// marshal inputs
ins, err := plugin.MarshalProperties(inputs, plugin.MarshalOptions{
KeepUnknowns: true,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return nil, nil, err
@ -252,7 +258,8 @@ func (rm *ResourceMonitor) Invoke(tok tokens.ModuleMember, inputs resource.Prope
// unmarshal outputs
outs, err := plugin.UnmarshalProperties(resp.Return, plugin.MarshalOptions{
KeepUnknowns: true,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return nil, nil, err

View file

@ -532,7 +532,7 @@ func (rm *resmon) SupportsFeature(ctx context.Context,
hasSupport := false
switch req.Id {
case "secrets":
case "secrets", "resourceReferences":
hasSupport = true
}
@ -560,9 +560,10 @@ func (rm *resmon) Invoke(ctx context.Context, req *pulumirpc.InvokeRequest) (*pu
args, err := plugin.UnmarshalProperties(
req.GetArgs(), plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal %v args", tok)
@ -575,8 +576,9 @@ func (rm *resmon) Invoke(ctx context.Context, req *pulumirpc.InvokeRequest) (*pu
return nil, errors.Wrapf(err, "invocation of %v returned an error", tok)
}
mret, err := plugin.MarshalProperties(ret, plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
Label: label,
KeepUnknowns: true,
KeepResources: true,
})
if err != nil {
return nil, errors.Wrapf(err, "failed to marshal %v return", tok)
@ -608,9 +610,10 @@ func (rm *resmon) StreamInvoke(
args, err := plugin.UnmarshalProperties(
req.GetArgs(), plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return errors.Wrapf(err, "failed to unmarshal %v args", tok)
@ -621,8 +624,9 @@ func (rm *resmon) StreamInvoke(
logging.V(5).Infof("ResourceMonitor.StreamInvoke received: tok=%v #args=%v", tok, len(args))
failures, err := prov.StreamInvoke(tok, args, func(event resource.PropertyMap) error {
mret, err := plugin.MarshalProperties(event, plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
Label: label,
KeepUnknowns: true,
KeepResources: req.GetAcceptResources(),
})
if err != nil {
return errors.Wrapf(err, "failed to marshal return")
@ -681,9 +685,10 @@ func (rm *resmon) ReadResource(ctx context.Context,
}
props, err := plugin.UnmarshalProperties(req.GetProperties(), plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
@ -723,9 +728,10 @@ func (rm *resmon) ReadResource(ctx context.Context,
contract.Assert(result != nil)
marshaled, err := plugin.MarshalProperties(result.State.Outputs, plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepSecrets: req.GetAcceptSecrets(),
Label: label,
KeepUnknowns: true,
KeepSecrets: req.GetAcceptSecrets(),
KeepResources: req.GetAcceptResources(),
})
if err != nil {
return nil, errors.Wrapf(err, "failed to marshal %s return state", result.State.URN)
@ -804,6 +810,7 @@ func (rm *resmon) RegisterResource(ctx context.Context,
KeepUnknowns: true,
ComputeAssetHashes: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
@ -942,9 +949,10 @@ func (rm *resmon) RegisterResource(ctx context.Context,
// Finally, unpack the response into properties that we can return to the language runtime. This mostly includes
// an ID, URN, and defaults and output properties that will all be blitted back onto the runtime object.
obj, err := plugin.MarshalProperties(outputs, plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepSecrets: req.GetAcceptSecrets(),
Label: label,
KeepUnknowns: true,
KeepSecrets: req.GetAcceptSecrets(),
KeepResources: req.GetAcceptResources(),
})
if err != nil {
return nil, err
@ -974,6 +982,7 @@ func (rm *resmon) RegisterResourceOutputs(ctx context.Context,
KeepUnknowns: true,
ComputeAssetHashes: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, errors.Wrapf(err, "cannot unmarshal output properties")

View file

@ -313,7 +313,12 @@ func (rm *queryResmon) Invoke(ctx context.Context, req *pulumirpc.InvokeRequest)
}
args, err := plugin.UnmarshalProperties(
req.GetArgs(), plugin.MarshalOptions{Label: label, KeepUnknowns: true})
req.GetArgs(), plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal %v args", tok)
}
@ -324,7 +329,11 @@ func (rm *queryResmon) Invoke(ctx context.Context, req *pulumirpc.InvokeRequest)
if err != nil {
return nil, errors.Wrapf(err, "invocation of %v returned an error", tok)
}
mret, err := plugin.MarshalProperties(ret, plugin.MarshalOptions{Label: label, KeepUnknowns: true})
mret, err := plugin.MarshalProperties(ret, plugin.MarshalOptions{
Label: label,
KeepUnknowns: true,
KeepResources: req.GetAcceptResources(),
})
if err != nil {
return nil, errors.Wrapf(err, "failed to marshal return")
}

View file

@ -370,6 +370,17 @@ func SerializePropertyValue(prop resource.PropertyValue, enc config.Encrypter,
return prop.ArchiveValue().Serialize(), nil
}
// We serialize resource references using a map-based representation similar to assets, archives, and secrets.
if prop.IsResourceReference() {
ref := prop.ResourceReferenceValue()
return map[string]interface{}{
resource.SigKey: resource.ResourceReferenceSig,
"urn": ref.URN,
"id": ref.ID,
"packageVersion": ref.PackageVersion,
}, nil
}
if prop.IsSecret() {
// Since we are going to encrypt property value, we can elide encrypting sub-elements. We'll mark them as
// "secret" so we retain that information when deserializaing the overall structure, but there is no
@ -543,6 +554,32 @@ func DeserializePropertyValue(v interface{}, dec config.Decrypter,
cachingCrypter.insert(prop.SecretValue(), plaintext, ciphertext)
}
return prop, nil
case resource.ResourceReferenceSig:
urnStr, ok := objmap["urn"].(string)
if !ok {
return resource.PropertyValue{}, errors.New("malformed resource value: missing urn")
}
urn := resource.URN(urnStr)
var id resource.ID
if idV, ok := objmap["id"]; ok {
idStr, ok := idV.(string)
if !ok {
return resource.PropertyValue{}, errors.New("malformed resource value: id must be a string")
}
id = resource.ID(idStr)
}
var packageVersion string
if packageVersionV, ok := objmap["packageVersion"]; ok {
packageVersion, ok = packageVersionV.(string)
if !ok {
return resource.PropertyValue{},
errors.New("malformed resource value: packageVersion must be a string")
}
}
return resource.MakeResourceReference(urn, id, packageVersion), nil
default:
return resource.PropertyValue{}, errors.Errorf("unrecognized signature '%v' in property map", sig)
}

View file

@ -32,7 +32,7 @@ namespace Pulumi.Tests.Serialization
{
var serializer = new Serializer(excessiveDebugOutput: false);
return Serializer.CreateValue(
await serializer.SerializeAsync(ctx: "", value).ConfigureAwait(false));
await serializer.SerializeAsync(ctx: "", value, true).ConfigureAwait(false));
}
}
}

View file

@ -1,6 +1,7 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Pulumi.Testing;
@ -51,6 +52,7 @@ namespace Pulumi
private readonly string _projectName;
private readonly string _stackName;
private readonly bool _isDryRun;
private readonly ConcurrentDictionary<string, bool> _featureSupport = new ConcurrentDictionary<string, bool>();
private readonly ILogger _logger;
private readonly IRunner _runner;
@ -131,5 +133,21 @@ namespace Pulumi
get => Stack;
set => Stack = value;
}
private async Task<bool> MonitorSupportsFeature(string feature)
{
if (!this._featureSupport.ContainsKey(feature))
{
var request = new Pulumirpc.SupportsFeatureRequest {Id = feature };
var response = await this.Monitor.SupportsFeatureAsync(request).ConfigureAwait(false);
this._featureSupport[feature] = response.HasSupport;
}
return this._featureSupport[feature];
}
internal Task<bool> MonitorSupportsResourceReferences()
{
return MonitorSupportsFeature("resourceReferences");
}
}
}

View file

@ -27,7 +27,9 @@ namespace Pulumi
// Wait for all values to be available, and then perform the RPC.
var argsDict = await args.ToDictionaryAsync().ConfigureAwait(false);
var serialized = await SerializeAllPropertiesAsync($"invoke:{token}", argsDict);
var serialized = await SerializeAllPropertiesAsync(
$"invoke:{token}",
argsDict, await this.MonitorSupportsResourceReferences().ConfigureAwait(false)).ConfigureAwait(false);
Log.Debug($"Invoke RPC prepared: token={token}" +
(_excessiveDebugOutput ? $", obj={serialized}" : ""));

View file

@ -31,7 +31,10 @@ namespace Pulumi
LogExcessive($"Serializing properties: t={type}, name={name}, custom={custom}");
var dictionary = await args.ToDictionaryAsync().ConfigureAwait(false);
var (serializedProps, propertyToDirectDependencies) =
await SerializeResourcePropertiesAsync(label, dictionary).ConfigureAwait(false);
await SerializeResourcePropertiesAsync(
label,
dictionary,
await this.MonitorSupportsResourceReferences().ConfigureAwait(false)).ConfigureAwait(false);
LogExcessive($"Serialized properties: t={type}, name={name}, custom={custom}");
// Wait for the parent to complete.

View file

@ -29,7 +29,7 @@ namespace Pulumi
var urn = await resource.Urn.GetValueAsync().ConfigureAwait(false);
var props = await outputs.GetValueAsync().ConfigureAwait(false);
var serialized = await SerializeAllPropertiesAsync(opLabel, props).ConfigureAwait(false);
var serialized = await SerializeAllPropertiesAsync(opLabel, props, true).ConfigureAwait(false);
Log.Debug($"RegisterResourceOutputs RPC prepared: urn={urn}" +
(_excessiveDebugOutput ? $", outputs ={JsonFormatter.Default.Format(serialized)}" : ""));

View file

@ -0,0 +1,15 @@
// Copyright 2016-2020, Pulumi Corporation
using System;
using Pulumi.Serialization;
namespace Pulumi
{
public partial class Deployment
{
public static void RegisterResourcePackage(string name, string version, IResourcePackage package)
{
ResourcePackages.RegisterResourcePackage(name, version, package);
}
}
}

View file

@ -21,16 +21,16 @@ namespace Pulumi
/// to registerResource.
/// </summary>
private static Task<SerializationResult> SerializeResourcePropertiesAsync(
string label, IDictionary<string, object?> args)
string label, IDictionary<string, object?> args, bool keepResources)
{
return SerializeFilteredPropertiesAsync(
label, args, key => key != Constants.IdPropertyName && key != Constants.UrnPropertyName);
label, args, key => key != Constants.IdPropertyName && key != Constants.UrnPropertyName, keepResources);
}
private static async Task<Struct> SerializeAllPropertiesAsync(
string label, IDictionary<string, object?> args)
string label, IDictionary<string, object?> args, bool keepResources)
{
var result = await SerializeFilteredPropertiesAsync(label, args, _ => true).ConfigureAwait(false);
var result = await SerializeFilteredPropertiesAsync(label, args, _ => true, keepResources).ConfigureAwait(false);
return result.Serialized;
}
@ -40,7 +40,7 @@ namespace Pulumi
/// creating a reasonable POCO object that can be remoted over to registerResource.
/// </summary>
private static async Task<SerializationResult> SerializeFilteredPropertiesAsync(
string label, IDictionary<string, object?> args, Predicate<string> acceptKey)
string label, IDictionary<string, object?> args, Predicate<string> acceptKey, bool keepResources)
{
var propertyToDependentResources = ImmutableDictionary.CreateBuilder<string, HashSet<Resource>>();
var result = ImmutableDictionary.CreateBuilder<string, object>();
@ -51,7 +51,7 @@ namespace Pulumi
{
// We treat properties with null values as if they do not exist.
var serializer = new Serializer(_excessiveDebugOutput);
var v = await serializer.SerializeAsync($"{label}.{key}", val).ConfigureAwait(false);
var v = await serializer.SerializeAsync($"{label}.{key}", val, keepResources).ConfigureAwait(false);
if (v != null)
{
result[key] = v;

View file

@ -19,6 +19,9 @@ namespace Pulumi
this._client = new ResourceMonitor.ResourceMonitorClient(new Channel(monitor, ChannelCredentials.Insecure, grpcChannelOptions));
}
public async Task<SupportsFeatureResponse> SupportsFeatureAsync(SupportsFeatureRequest request)
=> await this._client.SupportsFeatureAsync(request);
public async Task<InvokeResponse> InvokeAsync(InvokeRequest request)
=> await this._client.InvokeAsync(request);

View file

@ -7,6 +7,8 @@ namespace Pulumi
{
internal interface IMonitor
{
Task<SupportsFeatureResponse> SupportsFeatureAsync(SupportsFeatureRequest request);
Task<InvokeResponse> InvokeAsync(InvokeRequest request);
Task<ReadResourceResponse> ReadResourceAsync(Resource resource, ReadResourceRequest request);

View file

@ -173,6 +173,9 @@ Pulumi.ResourceTransformationResult
Pulumi.ResourceTransformationResult.Args.get -> Pulumi.ResourceArgs
Pulumi.ResourceTransformationResult.Options.get -> Pulumi.ResourceOptions
Pulumi.ResourceTransformationResult.ResourceTransformationResult(Pulumi.ResourceArgs args, Pulumi.ResourceOptions options) -> void
Pulumi.IResourcePackage
Pulumi.IResourcePackage.Construct(string name, string type, System.Collections.Generic.IDictionary<string, object> args, string urn) -> Pulumi.Resource
Pulumi.IResourcePackage.ConstructProvider(string name, string type, System.Collections.Generic.IDictionary<string, object> args, string urn) -> Pulumi.ProviderResource
Pulumi.Stack
Pulumi.Stack.Stack(Pulumi.StackOptions options = null) -> void
Pulumi.StackOptions
@ -226,6 +229,7 @@ override Pulumi.Union<T0, T1>.ToString() -> string
static Pulumi.ComponentResourceOptions.Merge(Pulumi.ComponentResourceOptions options1, Pulumi.ComponentResourceOptions options2) -> Pulumi.ComponentResourceOptions
static Pulumi.CustomResourceOptions.Merge(Pulumi.CustomResourceOptions options1, Pulumi.CustomResourceOptions options2) -> Pulumi.CustomResourceOptions
static Pulumi.Deployment.Instance.get -> Pulumi.DeploymentInstance
static Pulumi.Deployment.RegisterResourcePackage(string name, string version, Pulumi.IResourcePackage package) -> void
static Pulumi.Deployment.RunAsync(System.Action action) -> System.Threading.Tasks.Task<int>
static Pulumi.Deployment.RunAsync(System.Func<System.Collections.Generic.IDictionary<string, object>> func) -> System.Threading.Tasks.Task<int>
static Pulumi.Deployment.RunAsync(System.Func<System.Threading.Tasks.Task> func) -> System.Threading.Tasks.Task<int>

View file

@ -75,7 +75,7 @@ namespace Pulumi
return null;
var serializer = new Serializer(excessiveDebugOutput: false);
var obj = await serializer.SerializeAsync(context, input).ConfigureAwait(false);
var obj = await serializer.SerializeAsync(context, input, false).ConfigureAwait(false);
var value = Serializer.CreateValue(obj);
return JsonFormatter.Default.Format(value);
}

View file

@ -10,25 +10,30 @@ namespace Pulumi.Serialization
public const string UnknownValue = "04da6b54-80e4-46f7-96ec-b56ff0331ba9";
/// <summary>
/// SpecialSigKey is sometimes used to encode type identity inside of a map. See pkg/resource/properties.go.
/// SpecialSigKey is sometimes used to encode type identity inside of a map. See sdk/go/common/resource/properties.go.
/// </summary>
public const string SpecialSigKey = "4dabf18193072939515e22adb298388d";
/// <summary>
/// SpecialAssetSig is a randomly assigned hash used to identify assets in maps. See pkg/resource/asset.go.
/// SpecialAssetSig is a randomly assigned hash used to identify assets in maps. See sdk/go/common/resource/asset.go.
/// </summary>
public const string SpecialAssetSig = "c44067f5952c0a294b673a41bacd8c17";
/// <summary>
/// SpecialArchiveSig is a randomly assigned hash used to identify archives in maps. See pkg/resource/asset.go.
/// SpecialArchiveSig is a randomly assigned hash used to identify archives in maps. See sdk/go/common/resource/asset.go.
/// </summary>
public const string SpecialArchiveSig = "0def7320c3a5731c473e5ecbe6d01bc7";
/// <summary>
/// SpecialSecretSig is a randomly assigned hash used to identify secrets in maps. See pkg/resource/properties.go.
/// SpecialSecretSig is a randomly assigned hash used to identify secrets in maps. See sdk/go/common/resource/properties.go.
/// </summary>
public const string SpecialSecretSig = "1b47061264138c4ac30d75fd1eb44270";
/// <summary>
/// SpecialResourceSig is a randomly assigned hash used to identify resources in maps. See sdk/go/common/resource/properties.go.
/// </summary>
public const string SpecialResourceSig = "5cf8f73096256a8f31e491e813e4eb8e";
public const string SecretValueName = "value";
public const string AssetTextName = "text";
@ -37,6 +42,9 @@ namespace Pulumi.Serialization
public const string AssetOrArchivePathName = "path";
public const string AssetOrArchiveUriName = "uri";
public const string ResourceUrnName = "urn";
public const string ResourceVersionName = "version";
public const string IdPropertyName = "id";
public const string UrnPropertyName = "urn";
}

View file

@ -1,6 +1,7 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Google.Protobuf.Collections;
@ -26,6 +27,10 @@ namespace Pulumi.Serialization
{
return new OutputData<T>(ImmutableHashSet<Resource>.Empty, (T)(object)assetOrArchive, isKnown: true, isSecret);
}
else if (TryDeserializeResource(value, out var resource))
{
return new OutputData<T>(ImmutableHashSet<Resource>.Empty, (T)(object)resource, isKnown: true, isSecret);
}
var innerData = func(value);
return OutputData.Create(innerData.Resources, innerData.Value, innerData.IsKnown, isSecret || innerData.IsSecret);
@ -204,6 +209,53 @@ namespace Pulumi.Serialization
throw new InvalidOperationException("Value was marked as Asset, but did not conform to required shape.");
}
private static bool TryDeserializeResource(
Value value, [NotNullWhen(true)] out Resource? resource)
{
if (!IsSpecialStruct(value, out var sig) || sig != Constants.SpecialResourceSig)
{
resource = null;
return false;
}
string? urn;
if (!TryGetStringValue(value.StructValue.Fields, Constants.ResourceUrnName, out urn))
{
throw new InvalidOperationException("Value was marked as a Resource, but did not conform to required shape.");
}
string? version;
if (!TryGetStringValue(value.StructValue.Fields, Constants.ResourceVersionName, out version))
{
throw new InvalidOperationException("Value was marked as a Resource, but did not conform to required shape.");
}
var urnParts = urn.Split("::");
var qualifiedType = urnParts[2];
var qualifiedTypeParts = qualifiedType.Split('$');
var type = qualifiedTypeParts[qualifiedTypeParts.Length-1];
var typeParts = type.Split(':');
var pkgName = typeParts[0];
var modName = typeParts.Length > 1 ? typeParts[1] : "";
var typeName = typeParts.Length > 2 ? typeParts[2] : "";
var isProvider = pkgName == "pulumi" && modName == "providers";
if (isProvider) {
pkgName = typeName;
}
IResourcePackage? package;
if (!ResourcePackages.TryGetResourcePackage(pkgName, version, out package))
{
throw new InvalidOperationException($"Unable to deserialize resource URN {urn}, no resource package is registered for type {type}.");
}
var urnName = urnParts[3];
resource = !isProvider ?
package.Construct(urnName, type, null, urn) :
package.ConstructProvider(urnName, type, null, urn);
return true;
}
private static bool TryGetStringValue(
MapField<string, Value> fields, string keyName, [NotNullWhen(true)] out string? result)
{

View file

@ -0,0 +1,41 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Google.Protobuf.Collections;
using Google.Protobuf.WellKnownTypes;
namespace Pulumi
{
public interface IResourcePackage
{
Resource Construct(string name, string type, IDictionary<string, object?>? args, string urn);
ProviderResource ConstructProvider(string name, string type, IDictionary<string, object?>? args, string urn);
}
internal static class ResourcePackages
{
internal static ConcurrentDictionary<string, IResourcePackage> _resourcePackages = new ConcurrentDictionary<string, IResourcePackage>();
private static string PackageKey(string name, string version)
{
return $"{name}@{version}";
}
internal static bool TryGetResourcePackage(string name, string version, [NotNullWhen(true)] out IResourcePackage? package)
{
return _resourcePackages.TryGetValue(PackageKey(name, version), out package);
}
public static void RegisterResourcePackage(string name, string version, IResourcePackage package)
{
var key = PackageKey(name, version);
if (!_resourcePackages.TryAdd(key, package))
{
throw new InvalidOperationException($"Cannot re-register package {key}.");
}
}
}
}

View file

@ -65,7 +65,7 @@ namespace Pulumi.Serialization
/// </list>
/// No other result type are allowed to be returned.
/// </summary>
public async Task<object?> SerializeAsync(string ctx, object? prop)
public async Task<object?> SerializeAsync(string ctx, object? prop, bool keepResources)
{
// IMPORTANT:
// IMPORTANT: Keep this in sync with serializesPropertiesSync in invoke.ts
@ -85,10 +85,10 @@ namespace Pulumi.Serialization
}
if (prop is InputArgs args)
return await SerializeInputArgsAsync(ctx, args).ConfigureAwait(false);
return await SerializeInputArgsAsync(ctx, args, keepResources).ConfigureAwait(false);
if (prop is AssetOrArchive assetOrArchive)
return await SerializeAssetOrArchiveAsync(ctx, assetOrArchive).ConfigureAwait(false);
return await SerializeAssetOrArchiveAsync(ctx, assetOrArchive, keepResources).ConfigureAwait(false);
if (prop is Task)
{
@ -103,7 +103,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
Log.Debug($"Serialize property[{ctx}]: Recursing into IInput");
}
return await SerializeAsync(ctx, input.ToOutput()).ConfigureAwait(false);
return await SerializeAsync(ctx, input.ToOutput(), keepResources).ConfigureAwait(false);
}
if (prop is IUnion union)
@ -113,7 +113,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
Log.Debug($"Serialize property[{ctx}]: Recursing into IUnion");
}
return await SerializeAsync(ctx, union.Value).ConfigureAwait(false);
return await SerializeAsync(ctx, union.Value, keepResources).ConfigureAwait(false);
}
if (prop is JsonElement element)
@ -145,7 +145,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
if (!isKnown)
return Constants.UnknownValue;
var value = await SerializeAsync($"{ctx}.id", data.Value).ConfigureAwait(false);
var value = await SerializeAsync($"{ctx}.id", data.Value, keepResources).ConfigureAwait(false);
if (isSecret)
{
var builder = ImmutableDictionary.CreateBuilder<string, object?>();
@ -166,7 +166,15 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
}
this.DependentResources.Add(customResource);
return await SerializeAsync($"{ctx}.id", customResource.Id).ConfigureAwait(false);
if (keepResources)
{
var urn = await SerializeAsync($"{ctx}.urn", customResource.Urn, keepResources).ConfigureAwait(false);
var builder = ImmutableDictionary.CreateBuilder<string, object?>();
builder.Add(Constants.SpecialSigKey, Constants.SpecialResourceSig);
builder.Add(Constants.ResourceUrnName, urn);
return builder.ToImmutable();
}
return await SerializeAsync($"{ctx}.id", customResource.Id, keepResources).ConfigureAwait(false);
}
if (prop is ComponentResource componentResource)
@ -193,14 +201,22 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
Log.Debug($"Serialize property[{ctx}]: Encountered ComponentResource");
}
return await SerializeAsync($"{ctx}.urn", componentResource.Urn).ConfigureAwait(false);
var urn = await SerializeAsync($"{ctx}.urn", componentResource.Urn, keepResources).ConfigureAwait(false);
if (keepResources)
{
var builder = ImmutableDictionary.CreateBuilder<string, object?>();
builder.Add(Constants.SpecialSigKey, Constants.SpecialResourceSig);
builder.Add(Constants.ResourceUrnName, urn);
return builder.ToImmutable();
}
return urn;
}
if (prop is IDictionary dictionary)
return await SerializeDictionaryAsync(ctx, dictionary).ConfigureAwait(false);
return await SerializeDictionaryAsync(ctx, dictionary, keepResources).ConfigureAwait(false);
if (prop is IList list)
return await SerializeListAsync(ctx, list).ConfigureAwait(false);
return await SerializeListAsync(ctx, list, keepResources).ConfigureAwait(false);
throw new InvalidOperationException($"{prop.GetType().FullName} is not a supported argument type.\n\t{ctx}");
}
@ -246,7 +262,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
}
}
private async Task<ImmutableDictionary<string, object>> SerializeAssetOrArchiveAsync(string ctx, AssetOrArchive assetOrArchive)
private async Task<ImmutableDictionary<string, object>> SerializeAssetOrArchiveAsync(string ctx, AssetOrArchive assetOrArchive, bool keepResources)
{
if (_excessiveDebugOutput)
{
@ -254,7 +270,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
}
var propName = assetOrArchive.PropName;
var value = await SerializeAsync(ctx + "." + propName, assetOrArchive.Value).ConfigureAwait(false);
var value = await SerializeAsync(ctx + "." + propName, assetOrArchive.Value, keepResources).ConfigureAwait(false);
var builder = ImmutableDictionary.CreateBuilder<string, object>();
builder.Add(Constants.SpecialSigKey, assetOrArchive.SigKey);
@ -262,7 +278,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
return builder.ToImmutable();
}
private async Task<ImmutableDictionary<string, object>> SerializeInputArgsAsync(string ctx, InputArgs args)
private async Task<ImmutableDictionary<string, object>> SerializeInputArgsAsync(string ctx, InputArgs args, bool keepResources)
{
if (_excessiveDebugOutput)
{
@ -270,10 +286,10 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
}
var dictionary = await args.ToDictionaryAsync().ConfigureAwait(false);
return await SerializeDictionaryAsync(ctx, dictionary).ConfigureAwait(false);
return await SerializeDictionaryAsync(ctx, dictionary, keepResources).ConfigureAwait(false);
}
private async Task<ImmutableArray<object?>> SerializeListAsync(string ctx, IList list)
private async Task<ImmutableArray<object?>> SerializeListAsync(string ctx, IList list, bool keepResources)
{
if (_excessiveDebugOutput)
{
@ -288,13 +304,13 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
Log.Debug($"Serialize property[{ctx}]: array[{i}] element");
}
result.Add(await SerializeAsync($"{ctx}[{i}]", list[i]).ConfigureAwait(false));
result.Add(await SerializeAsync($"{ctx}[{i}]", list[i], keepResources).ConfigureAwait(false));
}
return result.MoveToImmutable();
}
private async Task<ImmutableDictionary<string, object>> SerializeDictionaryAsync(string ctx, IDictionary dictionary)
private async Task<ImmutableDictionary<string, object>> SerializeDictionaryAsync(string ctx, IDictionary dictionary, bool keepResources)
{
if (_excessiveDebugOutput)
{
@ -317,7 +333,7 @@ $"Tasks are not allowed inside ResourceArgs. Please wrap your Task in an Output:
// When serializing an object, we omit any keys with null values. This matches
// JSON semantics.
var v = await SerializeAsync($"{ctx}.{stringKey}", dictionary[stringKey]).ConfigureAwait(false);
var v = await SerializeAsync($"{ctx}.{stringKey}", dictionary[stringKey], keepResources).ConfigureAwait(false);
if (v != null)
{
result[stringKey] = v;

View file

@ -23,6 +23,12 @@ namespace Pulumi.Testing
_mocks = mocks;
}
public Task<SupportsFeatureResponse> SupportsFeatureAsync(SupportsFeatureRequest request)
{
var hasSupport = request.Id == "secrets" || request.Id == "resourceReferences";
return Task.FromResult(new SupportsFeatureResponse { HasSupport = hasSupport });
}
public async Task<InvokeResponse> InvokeAsync(InvokeRequest request)
{
var result = await _mocks.CallAsync(request.Tok, ToDictionary(request.Args), request.Provider)
@ -104,7 +110,7 @@ namespace Pulumi.Testing
private async Task<Struct> SerializeAsync(object o)
{
var dict = (o as IDictionary<string, object>)?.ToImmutableDictionary()
?? await _serializer.SerializeAsync("", o).ConfigureAwait(false) as ImmutableDictionary<string, object>
?? await _serializer.SerializeAsync("", o, true).ConfigureAwait(false) as ImmutableDictionary<string, object>
?? throw new InvalidOperationException($"{o.GetType().FullName} is not a supported argument type");
return Serializer.CreateStruct(dict);
}

View file

@ -60,7 +60,8 @@ type provider struct {
cfgerr error // non-nil if a configure call fails.
cfgknown bool // true if all configuration values are known.
cfgdone chan bool // closed when configuration has completed.
acceptSecrets bool // true if this plugin can consume strongly-typed secrets.
acceptSecrets bool // true if this plugin accepts strongly-typed secrets.
acceptResources bool // true if this plugin accepts strongly-typed resource refs.
supportsPreview bool // true if this plugin supports previews for Create and Update.
disableProviderPreview bool // true if previews for Create and Update are disabled.
}
@ -155,18 +156,20 @@ func (p *provider) CheckConfig(urn resource.URN, olds,
logging.V(7).Infof("%s executing (#olds=%d,#news=%d)", label, len(olds), len(news))
molds, err := MarshalProperties(olds, MarshalOptions{
Label: fmt.Sprintf("%s.olds", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.olds", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, nil, err
}
mnews, err := MarshalProperties(news, MarshalOptions{
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, nil, err
@ -198,6 +201,7 @@ func (p *provider) CheckConfig(urn resource.URN, olds,
KeepUnknowns: allowUnknowns,
RejectUnknowns: !allowUnknowns,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, nil, err
@ -256,18 +260,20 @@ func (p *provider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap,
label := fmt.Sprintf("%s.DiffConfig(%s)", p.label(), urn)
logging.V(7).Infof("%s executing (#olds=%d,#news=%d)", label, len(olds), len(news))
molds, err := MarshalProperties(olds, MarshalOptions{
Label: fmt.Sprintf("%s.olds", label),
KeepUnknowns: true,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.olds", label),
KeepUnknowns: true,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return DiffResult{}, err
}
mnews, err := MarshalProperties(news, MarshalOptions{
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: true,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: true,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return DiffResult{}, err
@ -430,7 +436,7 @@ func (p *provider) Configure(inputs resource.PropertyMap) error {
}
if v.ContainsUnknowns() {
p.cfgknown, p.acceptSecrets = false, false
p.cfgknown, p.acceptSecrets, p.acceptResources = false, false, false
close(p.cfgdone)
return nil
}
@ -452,9 +458,10 @@ func (p *provider) Configure(inputs resource.PropertyMap) error {
}
minputs, err := MarshalProperties(inputs, MarshalOptions{
Label: fmt.Sprintf("%s.inputs", label),
KeepUnknowns: true,
KeepSecrets: true,
Label: fmt.Sprintf("%s.inputs", label),
KeepUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
p.cfgerr = errors.Wrapf(err, "marshaling provider inputs")
@ -466,9 +473,10 @@ func (p *provider) Configure(inputs resource.PropertyMap) error {
// want to make forward progress, even as the configure call is happening.
go func() {
resp, err := p.clientRaw.Configure(p.ctx.Request(), &pulumirpc.ConfigureRequest{
AcceptSecrets: true,
Variables: config,
Args: minputs,
AcceptSecrets: true,
AcceptResources: true,
Variables: config,
Args: minputs,
})
if err != nil {
rpcError := rpcerror.Convert(err)
@ -476,7 +484,10 @@ func (p *provider) Configure(inputs resource.PropertyMap) error {
err = createConfigureError(rpcError)
}
// Acquire the lock, publish the results, and notify any waiters.
p.acceptSecrets, p.supportsPreview = resp.GetAcceptSecrets(), resp.GetSupportsPreview()
p.acceptSecrets = resp.GetAcceptSecrets()
p.acceptResources = resp.GetAcceptResources()
p.supportsPreview = resp.GetSupportsPreview()
p.cfgknown, p.cfgerr = true, err
close(p.cfgdone)
}()
@ -503,17 +514,19 @@ func (p *provider) Check(urn resource.URN,
}
molds, err := MarshalProperties(olds, MarshalOptions{
Label: fmt.Sprintf("%s.olds", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.olds", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, nil, err
}
mnews, err := MarshalProperties(news, MarshalOptions{
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, nil, err
@ -538,6 +551,7 @@ func (p *provider) Check(urn resource.URN,
KeepUnknowns: allowUnknowns,
RejectUnknowns: !allowUnknowns,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, nil, err
@ -595,14 +609,16 @@ func (p *provider) Diff(urn resource.URN, id resource.ID,
ElideAssetContents: true,
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return DiffResult{}, err
}
mnews, err := MarshalProperties(news, MarshalOptions{
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: allowUnknowns,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return DiffResult{}, err
@ -677,9 +693,10 @@ func (p *provider) Create(urn resource.URN, props resource.PropertyMap, timeout
contract.Assert(p.cfgknown)
mprops, err := MarshalProperties(props, MarshalOptions{
Label: fmt.Sprintf("%s.inputs", label),
KeepUnknowns: preview,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.inputs", label),
KeepUnknowns: preview,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return "", nil, resource.StatusOK, err
@ -714,9 +731,10 @@ func (p *provider) Create(urn resource.URN, props resource.PropertyMap, timeout
}
outs, err := UnmarshalProperties(liveObject, MarshalOptions{
Label: fmt.Sprintf("%s.outputs", label),
RejectUnknowns: true,
KeepSecrets: true,
Label: fmt.Sprintf("%s.outputs", label),
KeepUnknowns: preview,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return "", nil, resourceStatus, err
@ -768,6 +786,7 @@ func (p *provider) Read(urn resource.URN, id resource.ID,
Label: label,
ElideAssetContents: true,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return ReadResult{}, resource.StatusUnknown, err
@ -778,6 +797,7 @@ func (p *provider) Read(urn resource.URN, id resource.ID,
Label: label,
ElideAssetContents: true,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return ReadResult{}, resource.StatusUnknown, err
@ -819,6 +839,7 @@ func (p *provider) Read(urn resource.URN, id resource.ID,
Label: fmt.Sprintf("%s.outputs", label),
RejectUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return ReadResult{}, resourceStatus, err
@ -830,6 +851,7 @@ func (p *provider) Read(urn resource.URN, id resource.ID,
Label: label + ".inputs",
RejectUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return ReadResult{}, resourceStatus, err
@ -887,14 +909,16 @@ func (p *provider) Update(urn resource.URN, id resource.ID,
Label: fmt.Sprintf("%s.olds", label),
ElideAssetContents: true,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, resource.StatusOK, err
}
mnews, err := MarshalProperties(news, MarshalOptions{
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: preview,
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.news", label),
KeepUnknowns: preview,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, resource.StatusOK, err
@ -928,6 +952,7 @@ func (p *provider) Update(urn resource.URN, id resource.ID,
Label: fmt.Sprintf("%s.outputs", label),
RejectUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, resourceStatus, err
@ -960,6 +985,7 @@ func (p *provider) Delete(urn resource.URN, id resource.ID, props resource.Prope
Label: label,
ElideAssetContents: true,
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return resource.StatusOK, err
@ -1119,8 +1145,9 @@ func (p *provider) Invoke(tok tokens.ModuleMember, args resource.PropertyMap) (r
}
margs, err := MarshalProperties(args, MarshalOptions{
Label: fmt.Sprintf("%s.args", label),
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.args", label),
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, nil, err
@ -1138,6 +1165,7 @@ func (p *provider) Invoke(tok tokens.ModuleMember, args resource.PropertyMap) (r
Label: fmt.Sprintf("%s.returns", label),
RejectUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, nil, err
@ -1177,8 +1205,9 @@ func (p *provider) StreamInvoke(
}
margs, err := MarshalProperties(args, MarshalOptions{
Label: fmt.Sprintf("%s.args", label),
KeepSecrets: p.acceptSecrets,
Label: fmt.Sprintf("%s.args", label),
KeepSecrets: p.acceptSecrets,
KeepResources: p.acceptResources,
})
if err != nil {
return nil, err
@ -1206,6 +1235,7 @@ func (p *provider) StreamInvoke(
Label: fmt.Sprintf("%s.returns", label),
RejectUnknowns: true,
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err

View file

@ -36,6 +36,7 @@ type MarshalOptions struct {
ComputeAssetHashes bool // true if we are computing missing asset hashes on the fly.
KeepSecrets bool // true if we are keeping secrets (otherwise we replace them with their underlying value).
RejectAssets bool // true if we should return errors on Asset and Archive values.
KeepResources bool // true if we are keeping resoures (otherwise we return raw urn).
SkipInternalKeys bool // true to skip internal property keys (keys that start with "__") in the resulting map.
}
@ -161,6 +162,27 @@ func MarshalPropertyValue(v resource.PropertyValue, opts MarshalOptions) (*struc
"value": v.SecretValue().Element,
})
return MarshalPropertyValue(secret, opts)
} else if v.IsResourceReference() {
ref := v.ResourceReferenceValue()
if !opts.KeepResources {
val := string(ref.URN)
if ref.ID != "" {
val = string(ref.ID)
}
logging.V(5).Infof("marshalling resource value as raw URN or ID as opts.KeepResources is false")
return MarshalString(val, opts), nil
}
m := resource.PropertyMap{
resource.SigKey: resource.NewStringProperty(resource.ResourceReferenceSig),
"urn": resource.NewStringProperty(string(ref.URN)),
}
if ref.ID != "" {
m["id"] = resource.NewStringProperty(string(ref.ID))
}
if ref.PackageVersion != "" {
m["packageVersion"] = resource.NewStringProperty(ref.PackageVersion)
}
return MarshalPropertyValue(resource.NewObjectProperty(m), opts)
}
contract.Failf("Unrecognized property value in RPC[%s]: %v (type=%v)", opts.Label, v.V, reflect.TypeOf(v.V))
@ -345,6 +367,42 @@ func UnmarshalPropertyValue(v *structpb.Value, opts MarshalOptions) (*resource.P
}
s := resource.MakeSecret(value)
return &s, nil
case resource.ResourceReferenceSig:
urn, ok := obj["urn"]
if !ok {
return nil, errors.New("malformed resource reference: missing urn")
}
if !urn.IsString() {
return nil, errors.New("malformed resource reference: urn not a string")
}
var id string
if idProp, ok := obj["id"]; ok {
if !idProp.IsString() {
return nil, errors.New("malformed resource reference: id not a string")
}
id = idProp.StringValue()
}
var packageVersion string
if packageVersionProp, ok := obj["packageVersion"]; ok {
if !packageVersionProp.IsString() {
return nil, errors.New("malformed resource reference: packageVersion not a string")
}
packageVersion = packageVersionProp.StringValue()
}
if !opts.KeepResources {
value := urn.StringValue()
if id != "" {
value = id
}
r := resource.NewStringProperty(value)
return &r, nil
}
r := resource.MakeResourceReference(resource.URN(urn.StringValue()), resource.ID(id), packageVersion)
return &r, nil
default:
return nil, errors.Errorf("unrecognized signature '%v' in property map", sig)
}

View file

@ -285,3 +285,45 @@ func TestSkipInternalKeys(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expected, actual)
}
func TestResourceReference(t *testing.T) {
// Test round-trip
opts := MarshalOptions{KeepResources: true}
rawProp := resource.MakeResourceReference("fakeURN", "fakeID", "fakeVersion")
prop, err := MarshalPropertyValue(rawProp, opts)
assert.NoError(t, err)
actual, err := UnmarshalPropertyValue(prop, opts)
assert.NoError(t, err)
assert.Equal(t, rawProp, *actual)
// Test unmarshaling as an ID
opts.KeepResources = false
actual, err = UnmarshalPropertyValue(prop, opts)
assert.NoError(t, err)
assert.Equal(t, resource.NewStringProperty(string(rawProp.ResourceReferenceValue().ID)), *actual)
// Test marshaling as an ID
prop, err = MarshalPropertyValue(rawProp, opts)
assert.NoError(t, err)
opts.KeepResources = true
actual, err = UnmarshalPropertyValue(prop, opts)
assert.NoError(t, err)
assert.Equal(t, resource.NewStringProperty(string(rawProp.ResourceReferenceValue().ID)), *actual)
// Test unmarshaling as a URN
rawProp = resource.MakeResourceReference("fakeURN", "", "fakeVersion")
prop, err = MarshalPropertyValue(rawProp, opts)
assert.NoError(t, err)
opts.KeepResources = false
actual, err = UnmarshalPropertyValue(prop, opts)
assert.NoError(t, err)
assert.Equal(t, resource.NewStringProperty(string(rawProp.ResourceReferenceValue().URN)), *actual)
// Test marshaling as a URN
prop, err = MarshalPropertyValue(rawProp, opts)
assert.NoError(t, err)
opts.KeepResources = true
actual, err = UnmarshalPropertyValue(prop, opts)
assert.NoError(t, err)
assert.Equal(t, resource.NewStringProperty(string(rawProp.ResourceReferenceValue().URN)), *actual)
}

View file

@ -96,6 +96,16 @@ type Secret struct {
Element PropertyValue
}
// ResourceReference is a property value that represents a reference to a Resource. The reference captures the
// resource's URN, ID, and the version of its containing package.
//
//nolint: golint
type ResourceReference struct {
URN URN
ID ID
PackageVersion string
}
type ReqError struct {
K PropertyKey
}
@ -178,17 +188,18 @@ func (m PropertyMap) StableKeys() []PropertyKey {
return sorted
}
func NewNullProperty() PropertyValue { return PropertyValue{nil} }
func NewBoolProperty(v bool) PropertyValue { return PropertyValue{v} }
func NewNumberProperty(v float64) PropertyValue { return PropertyValue{v} }
func NewStringProperty(v string) PropertyValue { return PropertyValue{v} }
func NewArrayProperty(v []PropertyValue) PropertyValue { return PropertyValue{v} }
func NewAssetProperty(v *Asset) PropertyValue { return PropertyValue{v} }
func NewArchiveProperty(v *Archive) PropertyValue { return PropertyValue{v} }
func NewObjectProperty(v PropertyMap) PropertyValue { return PropertyValue{v} }
func NewComputedProperty(v Computed) PropertyValue { return PropertyValue{v} }
func NewOutputProperty(v Output) PropertyValue { return PropertyValue{v} }
func NewSecretProperty(v *Secret) PropertyValue { return PropertyValue{v} }
func NewNullProperty() PropertyValue { return PropertyValue{nil} }
func NewBoolProperty(v bool) PropertyValue { return PropertyValue{v} }
func NewNumberProperty(v float64) PropertyValue { return PropertyValue{v} }
func NewStringProperty(v string) PropertyValue { return PropertyValue{v} }
func NewArrayProperty(v []PropertyValue) PropertyValue { return PropertyValue{v} }
func NewAssetProperty(v *Asset) PropertyValue { return PropertyValue{v} }
func NewArchiveProperty(v *Archive) PropertyValue { return PropertyValue{v} }
func NewObjectProperty(v PropertyMap) PropertyValue { return PropertyValue{v} }
func NewComputedProperty(v Computed) PropertyValue { return PropertyValue{v} }
func NewOutputProperty(v Output) PropertyValue { return PropertyValue{v} }
func NewSecretProperty(v *Secret) PropertyValue { return PropertyValue{v} }
func NewResourceReferenceProperty(v ResourceReference) PropertyValue { return PropertyValue{v} }
func MakeComputed(v PropertyValue) PropertyValue {
return NewComputedProperty(Computed{Element: v})
@ -202,6 +213,10 @@ func MakeSecret(v PropertyValue) PropertyValue {
return NewSecretProperty(&Secret{Element: v})
}
func MakeResourceReference(urn URN, id ID, packageVersion string) PropertyValue {
return NewResourceReferenceProperty(ResourceReference{URN: urn, ID: id, PackageVersion: packageVersion})
}
// NewPropertyValue turns a value into a property value, provided it is of a legal "JSON-like" kind.
func NewPropertyValue(v interface{}) PropertyValue {
return NewPropertyValueRepl(v, nil, nil)
@ -255,6 +270,8 @@ func NewPropertyValueRepl(v interface{},
return NewOutputProperty(t)
case *Secret:
return NewSecretProperty(t)
case ResourceReference:
return NewResourceReferenceProperty(t)
}
// Next, see if it's an array, slice, pointer or struct, and handle each accordingly.
@ -382,6 +399,9 @@ func (v PropertyValue) OutputValue() Output { return v.V.(Output) }
// SecretValue fetches the underlying secret value (panicking if it isn't a secret).
func (v PropertyValue) SecretValue() *Secret { return v.V.(*Secret) }
// ResourceReferenceValue fetches the underlying resource reference value (panicking if it isn't a resource reference).
func (v PropertyValue) ResourceReferenceValue() ResourceReference { return v.V.(ResourceReference) }
// IsNull returns true if the underlying value is a null.
func (v PropertyValue) IsNull() bool {
return v.V == nil
@ -447,6 +467,12 @@ func (v PropertyValue) IsSecret() bool {
return is
}
// IsResourceReference returns true if the underlying value is a resource reference value.
func (v PropertyValue) IsResourceReference() bool {
_, is := v.V.(ResourceReference)
return is
}
// TypeString returns a type representation of the property value's holder type.
func (v PropertyValue) TypeString() string {
if v.IsNull() {
@ -471,6 +497,9 @@ func (v PropertyValue) TypeString() string {
return "output<" + v.OutputValue().Element.TypeString() + ">"
} else if v.IsSecret() {
return "secret<" + v.SecretValue().Element.TypeString() + ">"
} else if v.IsResourceReference() {
ref := v.ResourceReferenceValue()
return fmt.Sprintf("resourceReference(%q, %q, %q)", ref.URN, ref.ID, ref.PackageVersion)
}
contract.Failf("Unrecognized PropertyValue type")
return ""
@ -514,6 +543,8 @@ func (v PropertyValue) MapRepl(replk func(string) (string, bool),
return v.OutputValue()
} else if v.IsSecret() {
return v.SecretValue()
} else if v.IsResourceReference() {
return v.ResourceReferenceValue()
}
contract.Assertf(v.IsObject(), "v is not Object '%v' instead", v.TypeString())
return v.ObjectValue().MapRepl(replk, replv)
@ -550,6 +581,9 @@ func HasSig(obj PropertyMap, match string) bool {
// SecretSig is the unique secret signature.
const SecretSig = "1b47061264138c4ac30d75fd1eb44270"
// ResourceReferenceSig is the unique resource reference signature.
const ResourceReferenceSig = "5cf8f73096256a8f31e491e813e4eb8e"
// IsInternalPropertyKey returns true if the given property key is an internal key that should not be displayed to
// users.
func IsInternalPropertyKey(key PropertyKey) bool {

View file

@ -323,6 +323,17 @@ func (v PropertyValue) DeepEquals(other PropertyValue) bool {
return vs.Element.DeepEquals(os.Element)
}
// Resource references are equal if they refer to the same resource. The package version is ignored.
if v.IsResourceReference() {
if !other.IsResourceReference() {
return false
}
vr := v.ResourceReferenceValue()
or := other.ResourceReferenceValue()
return vr.URN == or.URN && vr.ID == or.ID
}
// For all other cases, primitives are equal if their values are equal.
return v.V == other.V
}

View file

@ -39,18 +39,19 @@ import (
// Context handles registration of resources and exposes metadata about the current deployment context.
type Context struct {
ctx context.Context
info RunInfo
stack Resource
exports map[string]Input
monitor pulumirpc.ResourceMonitorClient
monitorConn *grpc.ClientConn
engine pulumirpc.EngineClient
engineConn *grpc.ClientConn
rpcs int // the number of outstanding RPC requests.
rpcsDone *sync.Cond // an event signaling completion of RPCs.
rpcsLock *sync.Mutex // a lock protecting the RPC count and event.
rpcError error // the first error (if any) encountered during an RPC.
ctx context.Context
info RunInfo
stack Resource
exports map[string]Input
monitor pulumirpc.ResourceMonitorClient
monitorConn *grpc.ClientConn
engine pulumirpc.EngineClient
engineConn *grpc.ClientConn
keepResources bool // true if resources should be marshaled as strongly-typed references.
rpcs int // the number of outstanding RPC requests.
rpcsDone *sync.Cond // an event signaling completion of RPCs.
rpcsLock *sync.Mutex // a lock protecting the RPC count and event.
rpcError error // the first error (if any) encountered during an RPC.
Log Log // the logging interface for the Pulumi log stream.
}
@ -93,23 +94,35 @@ func NewContext(ctx context.Context, info RunInfo) (*Context, error) {
engine = &mockEngine{}
}
var keepResources bool
if monitor != nil {
supportsFeatureResp, err := monitor.SupportsFeature(ctx, &pulumirpc.SupportsFeatureRequest{
Id: "resourceReferences",
})
if err != nil {
return nil, fmt.Errorf("checking monitor features: %w", err)
}
keepResources = supportsFeatureResp.GetHasSupport()
}
mutex := &sync.Mutex{}
log := &logState{
engine: engine,
ctx: ctx,
}
return &Context{
ctx: ctx,
info: info,
exports: make(map[string]Input),
monitorConn: monitorConn,
monitor: monitor,
engineConn: engineConn,
engine: engine,
rpcs: 0,
rpcsLock: mutex,
rpcsDone: sync.NewCond(mutex),
Log: log,
ctx: ctx,
info: info,
exports: make(map[string]Input),
monitorConn: monitorConn,
monitor: monitor,
engineConn: engineConn,
engine: engine,
keepResources: keepResources,
rpcs: 0,
rpcsLock: mutex,
rpcsDone: sync.NewCond(mutex),
Log: log,
}, nil
}
@ -192,7 +205,7 @@ func (ctx *Context) Invoke(tok string, args interface{}, result interface{}, opt
keepUnknowns := ctx.DryRun()
rpcArgs, err := plugin.MarshalProperties(
resolvedArgsMap,
plugin.MarshalOptions{KeepUnknowns: keepUnknowns, KeepSecrets: true},
plugin.MarshalOptions{KeepUnknowns: keepUnknowns, KeepSecrets: true, KeepResources: ctx.keepResources},
)
if err != nil {
return fmt.Errorf("marshaling arguments: %w", err)
@ -228,10 +241,10 @@ func (ctx *Context) Invoke(tok string, args interface{}, result interface{}, opt
return ferr
}
// Otherwsie, simply unmarshal the output properties and return the result.
// Otherwise, simply unmarshal the output properties and return the result.
outProps, err := plugin.UnmarshalProperties(
resp.Return,
plugin.MarshalOptions{KeepSecrets: true, KeepUnknowns: keepUnknowns},
plugin.MarshalOptions{KeepSecrets: true, KeepResources: true, KeepUnknowns: keepUnknowns},
)
if err != nil {
return err
@ -718,7 +731,7 @@ func (state *resourceState) resolve(dryrun bool, err error, inputs *resourceInpu
if err == nil {
outprops, err = plugin.UnmarshalProperties(
result,
plugin.MarshalOptions{KeepSecrets: true, KeepUnknowns: dryrun},
plugin.MarshalOptions{KeepSecrets: true, KeepResources: true, KeepUnknowns: dryrun},
)
}
if err != nil {
@ -818,7 +831,7 @@ func (ctx *Context) prepareResourceInputs(props Input, t string,
keepUnknowns := ctx.DryRun()
rpcProps, err := plugin.MarshalProperties(
resolvedProps,
plugin.MarshalOptions{KeepUnknowns: keepUnknowns, KeepSecrets: true})
plugin.MarshalOptions{KeepSecrets: true, KeepUnknowns: keepUnknowns, KeepResources: ctx.keepResources})
if err != nil {
return nil, fmt.Errorf("marshaling properties: %w", err)
}
@ -1036,7 +1049,7 @@ func (ctx *Context) RegisterResourceOutputs(resource Resource, outs Map) error {
keepUnknowns := ctx.DryRun()
outsMarshalled, err := plugin.MarshalProperties(
outsResolved.ObjectValue(),
plugin.MarshalOptions{KeepUnknowns: keepUnknowns, KeepSecrets: true})
plugin.MarshalOptions{KeepSecrets: true, KeepUnknowns: keepUnknowns, KeepResources: ctx.keepResources})
if err != nil {
return
}

View file

@ -52,7 +52,10 @@ func (m *mockMonitor) SupportsFeature(ctx context.Context, in *pulumirpc.Support
func (m *mockMonitor) Invoke(ctx context.Context, in *pulumirpc.InvokeRequest,
opts ...grpc.CallOption) (*pulumirpc.InvokeResponse, error) {
args, err := plugin.UnmarshalProperties(in.GetArgs(), plugin.MarshalOptions{KeepSecrets: true})
args, err := plugin.UnmarshalProperties(in.GetArgs(), plugin.MarshalOptions{
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
}
@ -62,7 +65,10 @@ func (m *mockMonitor) Invoke(ctx context.Context, in *pulumirpc.InvokeRequest,
return nil, err
}
result, err := plugin.MarshalProperties(resultV, plugin.MarshalOptions{KeepSecrets: true})
result, err := plugin.MarshalProperties(resultV, plugin.MarshalOptions{
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
}
@ -81,7 +87,10 @@ func (m *mockMonitor) StreamInvoke(ctx context.Context, in *pulumirpc.InvokeRequ
func (m *mockMonitor) ReadResource(ctx context.Context, in *pulumirpc.ReadResourceRequest,
opts ...grpc.CallOption) (*pulumirpc.ReadResourceResponse, error) {
stateIn, err := plugin.UnmarshalProperties(in.GetProperties(), plugin.MarshalOptions{KeepSecrets: true})
stateIn, err := plugin.UnmarshalProperties(in.GetProperties(), plugin.MarshalOptions{
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
}
@ -91,7 +100,10 @@ func (m *mockMonitor) ReadResource(ctx context.Context, in *pulumirpc.ReadResour
return nil, err
}
stateOut, err := plugin.MarshalProperties(state, plugin.MarshalOptions{KeepSecrets: true})
stateOut, err := plugin.MarshalProperties(state, plugin.MarshalOptions{
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
}
@ -111,7 +123,10 @@ func (m *mockMonitor) RegisterResource(ctx context.Context, in *pulumirpc.Regist
}, nil
}
inputs, err := plugin.UnmarshalProperties(in.GetObject(), plugin.MarshalOptions{KeepSecrets: true})
inputs, err := plugin.UnmarshalProperties(in.GetObject(), plugin.MarshalOptions{
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
}
@ -121,7 +136,10 @@ func (m *mockMonitor) RegisterResource(ctx context.Context, in *pulumirpc.Regist
return nil, err
}
stateOut, err := plugin.MarshalProperties(state, plugin.MarshalOptions{KeepSecrets: true})
stateOut, err := plugin.MarshalProperties(state, plugin.MarshalOptions{
KeepSecrets: true,
KeepResources: true,
})
if err != nil {
return nil, err
}

View file

@ -19,10 +19,12 @@ import (
"fmt"
"reflect"
"strings"
"sync"
"golang.org/x/net/context"
"github.com/pulumi/pulumi/sdk/v2/go/common/resource"
"github.com/pulumi/pulumi/sdk/v2/go/common/tokens"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
)
@ -254,15 +256,30 @@ func marshalInputAndDetermineSecret(v interface{},
Path: v.Path(),
URI: v.URI(),
}), deps, secret, nil
case CustomResource:
case Resource:
deps = append(deps, v)
// Resources aren't serializable; instead, serialize a reference to ID, tracking as a dependency.
e, d, err := marshalInput(v.ID(), idType, await)
urn, known, secretURN, err := v.URN().awaitURN(context.Background())
if err != nil {
return resource.PropertyValue{}, nil, false, err
}
return e, append(deps, d...), secret, nil
contract.Assert(known)
contract.Assert(!secretURN)
var id ID
if custom, ok := v.(CustomResource); ok {
resID, known, secretID, err := custom.ID().awaitID(context.Background())
if err != nil {
return resource.PropertyValue{}, nil, false, err
}
contract.Assert(!secretID)
if !known {
return resource.MakeComputed(resource.NewStringProperty("")), deps, secret, nil
}
id = resID
}
return resource.MakeResourceReference(resource.URN(urn), resource.ID(id), ""), deps, secret, nil
}
contract.Assertf(valueType.AssignableTo(destType) || valueType.ConvertibleTo(destType),
@ -437,9 +454,39 @@ func unmarshalPropertyValue(v resource.PropertyValue) (interface{}, bool, error)
return NewFileArchive(archive.Path), secret, nil
case archive.IsURI():
return NewRemoteArchive(archive.URI), secret, nil
default:
}
return nil, false, errors.New("expected asset to be one of File, String, or Remote; got none")
case v.IsResourceReference():
ref := v.ResourceReferenceValue()
resName := ref.URN.Name()
resType := ref.URN.Type()
pkgName := resType.Package()
isProvider := false
if tokens.Token(resType).HasModuleMember() && resType.Module() == "pulumi:providers" {
pkgName, isProvider = tokens.Package(resType.Name()), true
}
resourcePackageV, ok := resourcePackages.Load(packageKey(string(pkgName), ref.PackageVersion))
if !ok {
err := fmt.Errorf("unable to deserialize resource URN %v, no resource package is registered for type %v",
ref.URN, pkgName)
return nil, false, err
}
resourcePackage := resourcePackageV.(ResourcePackage)
var resource Resource
var err error
if !isProvider {
resource, err = resourcePackage.Construct(string(resName), string(resType), nil, string(ref.URN))
} else {
resource, err = resourcePackage.ConstructProvider(string(resName), string(resType), nil, string(ref.URN))
}
if err != nil {
return nil, false, err
}
return resource, false, nil
default:
return v.V, false, nil
}
@ -491,6 +538,17 @@ func unmarshalOutput(v resource.PropertyValue, dest reflect.Value) (bool, error)
return false, err
}
return true, nil
case v.IsResourceReference():
res, secret, err := unmarshalPropertyValue(v)
if err != nil {
return false, err
}
resV := reflect.ValueOf(res).Elem()
if !resV.Type().AssignableTo(dest.Type()) {
return false, fmt.Errorf("expected a %s, got a resource of type %s", dest.Type(), resV.Type())
}
dest.Set(resV)
return secret, nil
}
// Unmarshal based on the desired type.
@ -619,3 +677,23 @@ func unmarshalOutput(v resource.PropertyValue, dest reflect.Value) (bool, error)
return false, fmt.Errorf("cannot unmarshal into type %v", dest.Type())
}
}
type ResourcePackage interface {
Construct(name, typ string, args map[string]interface{}, urn string) (Resource, error)
ConstructProvider(name, typ string, args map[string]interface{}, urn string) (ProviderResource, error)
}
var resourcePackages sync.Map // map[string]ResourcePackage
func packageKey(name, version string) string {
return fmt.Sprintf("%s@%s", name, version)
}
// RegisterResourcePackage register a resource package with the Pulumi runtime.
func RegisterResourcePackage(name, version string, pkg ResourcePackage) {
key := packageKey(name, version)
existing, hasExisting := resourcePackages.LoadOrStore(key, pkg)
if hasExisting {
panic(fmt.Errorf("a resource package for %v is already registered: %v", key, existing))
}
}

View file

@ -886,7 +886,8 @@ proto.pulumirpc.ConfigureRequest.toObject = function(includeInstance, msg) {
var f, obj = {
variablesMap: (f = msg.getVariablesMap()) ? f.toObject(includeInstance, undefined) : [],
args: (f = msg.getArgs()) && google_protobuf_struct_pb.Struct.toObject(includeInstance, f),
acceptsecrets: jspb.Message.getBooleanFieldWithDefault(msg, 3, false)
acceptsecrets: jspb.Message.getBooleanFieldWithDefault(msg, 3, false),
acceptresources: jspb.Message.getBooleanFieldWithDefault(msg, 4, false)
};
if (includeInstance) {
@ -938,6 +939,10 @@ proto.pulumirpc.ConfigureRequest.deserializeBinaryFromReader = function(msg, rea
var value = /** @type {boolean} */ (reader.readBool());
msg.setAcceptsecrets(value);
break;
case 4:
var value = /** @type {boolean} */ (reader.readBool());
msg.setAcceptresources(value);
break;
default:
reader.skipField();
break;
@ -986,6 +991,13 @@ proto.pulumirpc.ConfigureRequest.serializeBinaryToWriter = function(message, wri
f
);
}
f = message.getAcceptresources();
if (f) {
writer.writeBool(
4,
f
);
}
};
@ -1066,6 +1078,24 @@ proto.pulumirpc.ConfigureRequest.prototype.setAcceptsecrets = function(value) {
};
/**
* optional bool acceptResources = 4;
* @return {boolean}
*/
proto.pulumirpc.ConfigureRequest.prototype.getAcceptresources = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false));
};
/**
* @param {boolean} value
* @return {!proto.pulumirpc.ConfigureRequest} returns this
*/
proto.pulumirpc.ConfigureRequest.prototype.setAcceptresources = function(value) {
return jspb.Message.setProto3BooleanField(this, 4, value);
};
@ -1099,7 +1129,8 @@ proto.pulumirpc.ConfigureResponse.prototype.toObject = function(opt_includeInsta
proto.pulumirpc.ConfigureResponse.toObject = function(includeInstance, msg) {
var f, obj = {
acceptsecrets: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),
supportspreview: jspb.Message.getBooleanFieldWithDefault(msg, 2, false)
supportspreview: jspb.Message.getBooleanFieldWithDefault(msg, 2, false),
acceptresources: jspb.Message.getBooleanFieldWithDefault(msg, 3, false)
};
if (includeInstance) {
@ -1144,6 +1175,10 @@ proto.pulumirpc.ConfigureResponse.deserializeBinaryFromReader = function(msg, re
var value = /** @type {boolean} */ (reader.readBool());
msg.setSupportspreview(value);
break;
case 3:
var value = /** @type {boolean} */ (reader.readBool());
msg.setAcceptresources(value);
break;
default:
reader.skipField();
break;
@ -1187,6 +1222,13 @@ proto.pulumirpc.ConfigureResponse.serializeBinaryToWriter = function(message, wr
f
);
}
f = message.getAcceptresources();
if (f) {
writer.writeBool(
3,
f
);
}
};
@ -1226,6 +1268,24 @@ proto.pulumirpc.ConfigureResponse.prototype.setSupportspreview = function(value)
};
/**
* optional bool acceptResources = 3;
* @return {boolean}
*/
proto.pulumirpc.ConfigureResponse.prototype.getAcceptresources = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false));
};
/**
* @param {boolean} value
* @return {!proto.pulumirpc.ConfigureResponse} returns this
*/
proto.pulumirpc.ConfigureResponse.prototype.setAcceptresources = function(value) {
return jspb.Message.setProto3BooleanField(this, 3, value);
};
/**
* List of repeated fields within this message type.
@ -1581,7 +1641,8 @@ proto.pulumirpc.InvokeRequest.toObject = function(includeInstance, msg) {
tok: jspb.Message.getFieldWithDefault(msg, 1, ""),
args: (f = msg.getArgs()) && google_protobuf_struct_pb.Struct.toObject(includeInstance, f),
provider: jspb.Message.getFieldWithDefault(msg, 3, ""),
version: jspb.Message.getFieldWithDefault(msg, 4, "")
version: jspb.Message.getFieldWithDefault(msg, 4, ""),
acceptresources: jspb.Message.getBooleanFieldWithDefault(msg, 5, false)
};
if (includeInstance) {
@ -1635,6 +1696,10 @@ proto.pulumirpc.InvokeRequest.deserializeBinaryFromReader = function(msg, reader
var value = /** @type {string} */ (reader.readString());
msg.setVersion(value);
break;
case 5:
var value = /** @type {boolean} */ (reader.readBool());
msg.setAcceptresources(value);
break;
default:
reader.skipField();
break;
@ -1693,6 +1758,13 @@ proto.pulumirpc.InvokeRequest.serializeBinaryToWriter = function(message, writer
f
);
}
f = message.getAcceptresources();
if (f) {
writer.writeBool(
5,
f
);
}
};
@ -1787,6 +1859,24 @@ proto.pulumirpc.InvokeRequest.prototype.setVersion = function(value) {
};
/**
* optional bool acceptResources = 5;
* @return {boolean}
*/
proto.pulumirpc.InvokeRequest.prototype.getAcceptresources = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));
};
/**
* @param {boolean} value
* @return {!proto.pulumirpc.InvokeRequest} returns this
*/
proto.pulumirpc.InvokeRequest.prototype.setAcceptresources = function(value) {
return jspb.Message.setProto3BooleanField(this, 5, value);
};
/**
* List of repeated fields within this message type.

View file

@ -547,7 +547,8 @@ proto.pulumirpc.ReadResourceRequest.toObject = function(includeInstance, msg) {
version: jspb.Message.getFieldWithDefault(msg, 8, ""),
acceptsecrets: jspb.Message.getBooleanFieldWithDefault(msg, 9, false),
additionalsecretoutputsList: (f = jspb.Message.getRepeatedField(msg, 10)) == null ? undefined : f,
aliasesList: (f = jspb.Message.getRepeatedField(msg, 11)) == null ? undefined : f
aliasesList: (f = jspb.Message.getRepeatedField(msg, 11)) == null ? undefined : f,
acceptresources: jspb.Message.getBooleanFieldWithDefault(msg, 12, false)
};
if (includeInstance) {
@ -629,6 +630,10 @@ proto.pulumirpc.ReadResourceRequest.deserializeBinaryFromReader = function(msg,
var value = /** @type {string} */ (reader.readString());
msg.addAliases(value);
break;
case 12:
var value = /** @type {boolean} */ (reader.readBool());
msg.setAcceptresources(value);
break;
default:
reader.skipField();
break;
@ -736,6 +741,13 @@ proto.pulumirpc.ReadResourceRequest.serializeBinaryToWriter = function(message,
f
);
}
f = message.getAcceptresources();
if (f) {
writer.writeBool(
12,
f
);
}
};
@ -1013,6 +1025,24 @@ proto.pulumirpc.ReadResourceRequest.prototype.clearAliasesList = function() {
};
/**
* optional bool acceptResources = 12;
* @return {boolean}
*/
proto.pulumirpc.ReadResourceRequest.prototype.getAcceptresources = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 12, false));
};
/**
* @param {boolean} value
* @return {!proto.pulumirpc.ReadResourceRequest} returns this
*/
proto.pulumirpc.ReadResourceRequest.prototype.setAcceptresources = function(value) {
return jspb.Message.setProto3BooleanField(this, 12, value);
};
@ -1252,7 +1282,8 @@ proto.pulumirpc.RegisterResourceRequest.toObject = function(includeInstance, msg
customtimeouts: (f = msg.getCustomtimeouts()) && proto.pulumirpc.RegisterResourceRequest.CustomTimeouts.toObject(includeInstance, f),
deletebeforereplacedefined: jspb.Message.getBooleanFieldWithDefault(msg, 18, false),
supportspartialvalues: jspb.Message.getBooleanFieldWithDefault(msg, 19, false),
remote: jspb.Message.getBooleanFieldWithDefault(msg, 20, false)
remote: jspb.Message.getBooleanFieldWithDefault(msg, 20, false),
acceptresources: jspb.Message.getBooleanFieldWithDefault(msg, 21, false)
};
if (includeInstance) {
@ -1373,6 +1404,10 @@ proto.pulumirpc.RegisterResourceRequest.deserializeBinaryFromReader = function(m
var value = /** @type {boolean} */ (reader.readBool());
msg.setRemote(value);
break;
case 21:
var value = /** @type {boolean} */ (reader.readBool());
msg.setAcceptresources(value);
break;
default:
reader.skipField();
break;
@ -1541,6 +1576,13 @@ proto.pulumirpc.RegisterResourceRequest.serializeBinaryToWriter = function(messa
f
);
}
f = message.getAcceptresources();
if (f) {
writer.writeBool(
21,
f
);
}
};
@ -2368,6 +2410,24 @@ proto.pulumirpc.RegisterResourceRequest.prototype.setRemote = function(value) {
};
/**
* optional bool acceptResources = 21;
* @return {boolean}
*/
proto.pulumirpc.RegisterResourceRequest.prototype.getAcceptresources = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 21, false));
};
/**
* @param {boolean} value
* @return {!proto.pulumirpc.RegisterResourceRequest} returns this
*/
proto.pulumirpc.RegisterResourceRequest.prototype.setAcceptresources = function(value) {
return jspb.Message.setProto3BooleanField(this, 21, value);
};
/**
* List of repeated fields within this message type.

View file

@ -16,9 +16,9 @@ import * as asset from "../asset";
import { isGrpcError } from "../errors";
import * as log from "../log";
import { getAllResources, Input, Inputs, isUnknown, Output, unknown } from "../output";
import { ComponentResource, CustomResource, Resource, URN } from "../resource";
import { ComponentResource, CustomResource, ProviderResource, Resource, URN } from "../resource";
import { debuggablePromise, errorString, promiseDebugString } from "./debuggable";
import { excessiveDebugOutput, isDryRun, monitorSupportsSecrets } from "./settings";
import { excessiveDebugOutput, isDryRun, monitorSupportsResourceReferences, monitorSupportsSecrets } from "./settings";
const gstruct = require("google-protobuf/google/protobuf/struct_pb.js");
@ -87,7 +87,10 @@ export function transferProperties(onto: Resource, label: string, props: Inputs)
* be remoted over to registerResource.
*/
async function serializeFilteredProperties(
label: string, props: Inputs, acceptKey: (k: string) => boolean): Promise<[Record<string, any>, Map<string, Set<Resource>>]> {
label: string,
props: Inputs,
acceptKey: (k: string) => boolean,
): Promise<[Record<string, any>, Map<string, Set<Resource>>]> {
const propertyToDependentResources = new Map<string, Set<Resource>>();
@ -236,6 +239,10 @@ export const specialArchiveSig = "0def7320c3a5731c473e5ecbe6d01bc7";
* specialSecretSig is a randomly assigned hash used to identify secrets in maps. See pkg/resource/properties.go.
*/
export const specialSecretSig = "1b47061264138c4ac30d75fd1eb44270";
/**
* specialResourceSig is a randomly assigned hash used to identify resources in maps. See pkg/resource/properties.go.
*/
export const specialResourceSig = "5cf8f73096256a8f31e491e813e4eb8e";
/**
* serializeProperty serializes properties deeply. This understands how to wait on any unresolved promises, as
@ -243,7 +250,7 @@ export const specialSecretSig = "1b47061264138c4ac30d75fd1eb44270";
*/
export async function serializeProperty(ctx: string, prop: Input<any>, dependentResources: Set<Resource>): Promise<any> {
// IMPORTANT:
// IMPORTANT: Keep this in sync with serializesPropertiesSync in invoke.ts
// IMPORTANT: Keep this in sync with serializePropertiesSync in invoke.ts
// IMPORTANT:
if (prop === undefined ||
@ -323,13 +330,24 @@ export async function serializeProperty(ctx: string, prop: Input<any>, dependent
}
if (CustomResource.isInstance(prop)) {
// Resources aren't serializable; instead, we serialize them as references to the ID property.
if (excessiveDebugOutput) {
log.debug(`Serialize property [${ctx}]: custom resource id`);
log.debug(`Serialize property [${ctx}]: custom resource urn`);
}
dependentResources.add(prop);
return serializeProperty(`${ctx}.id`, prop.id, dependentResources);
const id = await serializeProperty(`${ctx}.id`, prop.id, dependentResources);
if (await monitorSupportsResourceReferences()) {
// If we are keeping resources, emit a stronly typed wrapper over the URN
const urn = await serializeProperty(`${ctx}.urn`, prop.urn, dependentResources);
return {
[specialSigKey]: specialResourceSig,
urn: urn,
id: id,
};
}
// Else, return the id for backward compatibility.
return id;
}
if (ComponentResource.isInstance(prop)) {
@ -348,9 +366,18 @@ export async function serializeProperty(ctx: string, prop: Input<any>, dependent
// and tracked in a reasonable manner, while not causing us to compute or embed information
// about it that is not needed, and which can lead to deadlocks.
if (excessiveDebugOutput) {
log.debug(`Serialize property [${ctx}]: component resource urnid`);
log.debug(`Serialize property [${ctx}]: component resource urn`);
}
if (await monitorSupportsResourceReferences()) {
// If we are keeping resources, emit a strongly typed wrapper over the URN
const urn = await serializeProperty(`${ctx}.urn`, prop.urn, dependentResources);
return {
[specialSigKey]: specialResourceSig,
urn: urn,
};
}
// Else, return the urn for backward compatibility.
return serializeProperty(`${ctx}.urn`, prop.urn, dependentResources);
}
@ -482,6 +509,32 @@ export function deserializeProperty(prop: any): any {
[specialSigKey]: specialSecretSig,
value: deserializeProperty(prop["value"]),
};
case specialResourceSig:
// Deserialize the resource into a live Resource reference
const urn = prop["urn"];
const version = prop["version"];
const urnParts = urn.split("::");
const qualifiedType = urnParts[2];
const type = qualifiedType.split("$").pop()!;
const typeParts = type.split(":");
let pkgName = typeParts[0];
const modName = typeParts.length > 1 ? typeParts[1] : "";
const typName = typeParts.length > 2 ? typeParts[2] : "";
const isProvider = pkgName === "pulumi" && modName === "providers";
if (isProvider) {
pkgName = typName;
}
const resourcePackage = resourcePackages.get(packageKey(pkgName, version || ""));
if (!resourcePackage) {
throw new Error(`Unable to deserialize resource URN ${urn}, no resource package is registered for type ${type}.`);
}
const urnName = urnParts[3];
return !isProvider ?
resourcePackage.construct(urnName, type, {}, { urn }) :
resourcePackage.constructProvider(urnName, type, {}, { urn });
default:
throw new Error(`Unrecognized signature '${sig}' when unmarshaling resource property`);
}
@ -521,3 +574,30 @@ export function suppressUnhandledGrpcRejections<T>(p: Promise<T>): Promise<T> {
});
return p;
}
/**
* A ResourcePackage is a package that understands how to construct resources given a name, type, args, and URN.
*/
export type ResourcePackage = {
construct(name: string, type: string, args: any, opts: { urn: string }): Resource;
constructProvider(name: string, type: string, args: any, opts: { urn: string }): ProviderResource;
};
const resourcePackages = new Map<string, ResourcePackage>();
function packageKey(name: string, version: string): string {
return `${name}@${version}`;
}
/**
* registerResourcePackage registers a resource package that will be used to construct resources for any URNs matching
* the package name and version that are deserialized by the current instance of the Pulumi JavaScript SDK.
*/
export function registerResourcePackage(pkgName: string, version: string, pkg: ResourcePackage) {
const key = packageKey(pkgName, version);
const existing = resourcePackages.get(key);
if (existing) {
throw new Error(`Cannot re-register package ${key}. Previous registration was ${existing}, new registration was ${pkg}.`);
}
resourcePackages.set(key, pkg);
}

View file

@ -490,3 +490,12 @@ export async function monitorSupportsFeature(feature: string): Promise<boolean>
export function monitorSupportsSecrets(): Promise<boolean> {
return monitorSupportsFeature("secrets");
}
/**
* monitorSupportsResourceReferences returns a promise that when resolved tells you if the resource monitor we are
* connected to is able to support resouece references aross its RPC interface. When it does, we marshal resources
* in a special way.
*/
export async function monitorSupportsResourceReferences(): Promise<boolean> {
return monitorSupportsFeature("resourceReferences");
}

View file

@ -92,6 +92,7 @@
"tests/runtime/tsClosureCases.ts",
"tests/runtime/props.spec.ts",
"tests/runtime/langhost/run.spec.ts",
"tests/automation/localWorkspace.spec.ts"
]
}

View file

@ -173,6 +173,7 @@ type ConfigureRequest struct {
Variables map[string]string `protobuf:"bytes,1,rep,name=variables,proto3" json:"variables,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Args *_struct.Struct `protobuf:"bytes,2,opt,name=args,proto3" json:"args,omitempty"`
AcceptSecrets bool `protobuf:"varint,3,opt,name=acceptSecrets,proto3" json:"acceptSecrets,omitempty"`
AcceptResources bool `protobuf:"varint,4,opt,name=acceptResources,proto3" json:"acceptResources,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -224,9 +225,17 @@ func (m *ConfigureRequest) GetAcceptSecrets() bool {
return false
}
func (m *ConfigureRequest) GetAcceptResources() bool {
if m != nil {
return m.AcceptResources
}
return false
}
type ConfigureResponse struct {
AcceptSecrets bool `protobuf:"varint,1,opt,name=acceptSecrets,proto3" json:"acceptSecrets,omitempty"`
SupportsPreview bool `protobuf:"varint,2,opt,name=supportsPreview,proto3" json:"supportsPreview,omitempty"`
AcceptResources bool `protobuf:"varint,3,opt,name=acceptResources,proto3" json:"acceptResources,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -271,6 +280,13 @@ func (m *ConfigureResponse) GetSupportsPreview() bool {
return false
}
func (m *ConfigureResponse) GetAcceptResources() bool {
if m != nil {
return m.AcceptResources
}
return false
}
// ConfigureErrorMissingKeys is sent as a Detail on an error returned from `ResourceProvider.Configure`.
type ConfigureErrorMissingKeys struct {
MissingKeys []*ConfigureErrorMissingKeys_MissingKey `protobuf:"bytes,1,rep,name=missingKeys,proto3" json:"missingKeys,omitempty"`
@ -363,6 +379,7 @@ type InvokeRequest struct {
Args *_struct.Struct `protobuf:"bytes,2,opt,name=args,proto3" json:"args,omitempty"`
Provider string `protobuf:"bytes,3,opt,name=provider,proto3" json:"provider,omitempty"`
Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
AcceptResources bool `protobuf:"varint,5,opt,name=acceptResources,proto3" json:"acceptResources,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -421,6 +438,13 @@ func (m *InvokeRequest) GetVersion() string {
return ""
}
func (m *InvokeRequest) GetAcceptResources() bool {
if m != nil {
return m.AcceptResources
}
return false
}
type InvokeResponse struct {
Return *_struct.Struct `protobuf:"bytes,1,opt,name=return,proto3" json:"return,omitempty"`
Failures []*CheckFailure `protobuf:"bytes,2,rep,name=failures,proto3" json:"failures,omitempty"`
@ -1662,111 +1686,112 @@ func init() {
func init() { proto.RegisterFile("provider.proto", fileDescriptor_c6a9f3c02af3d1c8) }
var fileDescriptor_c6a9f3c02af3d1c8 = []byte{
// 1651 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x4b, 0x73, 0x1b, 0x37,
0x12, 0xd6, 0x90, 0x14, 0x25, 0x36, 0x1f, 0xa6, 0xb0, 0x5e, 0x99, 0xa6, 0x75, 0x50, 0xcd, 0x6e,
0xd5, 0x6a, 0xed, 0x35, 0xa5, 0x95, 0x0f, 0xbb, 0x76, 0xc9, 0xe5, 0x95, 0x44, 0x4a, 0xab, 0xb2,
0x2d, 0x2b, 0x23, 0x3b, 0x8f, 0x93, 0x3d, 0x9e, 0x01, 0xa9, 0x89, 0x86, 0x33, 0x13, 0x0c, 0x86,
0x2e, 0xe5, 0x9c, 0x43, 0x4e, 0xb9, 0xe7, 0x47, 0xa4, 0x52, 0x95, 0x5f, 0x90, 0x1f, 0x92, 0x1c,
0x73, 0xcc, 0x21, 0x95, 0x3f, 0x90, 0xc2, 0x6b, 0x04, 0x90, 0xd4, 0x33, 0xae, 0xe4, 0x86, 0x46,
0x37, 0xfa, 0xf1, 0xa1, 0xd1, 0x68, 0x00, 0x1a, 0x09, 0x89, 0x47, 0x81, 0x8f, 0x49, 0x27, 0x21,
0x31, 0x8d, 0x51, 0x25, 0xc9, 0xc2, 0x6c, 0x18, 0x90, 0xc4, 0x6b, 0xd7, 0x92, 0x30, 0x1b, 0x04,
0x91, 0x60, 0xb4, 0xef, 0x0c, 0xe2, 0x78, 0x10, 0xe2, 0x55, 0x4e, 0xbd, 0xcd, 0xfa, 0xab, 0x78,
0x98, 0xd0, 0x13, 0xc9, 0x5c, 0x1a, 0x67, 0xa6, 0x94, 0x64, 0x1e, 0x15, 0x5c, 0xfb, 0x5f, 0xd0,
0xdc, 0xc5, 0xf4, 0xd0, 0x3b, 0xc2, 0x43, 0xd7, 0xc1, 0x9f, 0x65, 0x38, 0xa5, 0xa8, 0x05, 0x73,
0x23, 0x4c, 0xd2, 0x20, 0x8e, 0x5a, 0xd6, 0xb2, 0xb5, 0x32, 0xeb, 0x28, 0xd2, 0xbe, 0x07, 0x0b,
0x9a, 0x74, 0x9a, 0xc4, 0x51, 0x8a, 0xd1, 0x22, 0x94, 0x53, 0x3e, 0xc3, 0xa5, 0x2b, 0x8e, 0xa4,
0xec, 0x9f, 0x2d, 0x68, 0x6e, 0xc7, 0x51, 0x3f, 0x18, 0x64, 0x04, 0x2b, 0xdd, 0xff, 0x87, 0xca,
0xc8, 0x25, 0x81, 0xfb, 0x36, 0xc4, 0x69, 0xcb, 0x5a, 0x2e, 0xae, 0x54, 0xd7, 0xef, 0x76, 0xf2,
0xb8, 0x3a, 0xe3, 0xf2, 0x9d, 0x0f, 0x95, 0x70, 0x2f, 0xa2, 0xe4, 0xc4, 0x39, 0x5d, 0x8c, 0xee,
0x41, 0xc9, 0x25, 0x83, 0xb4, 0x55, 0x58, 0xb6, 0x56, 0xaa, 0xeb, 0xb7, 0x3a, 0x22, 0xcc, 0x8e,
0x0a, 0xb3, 0x73, 0xc8, 0xc3, 0x74, 0xb8, 0x10, 0xfa, 0x3b, 0xd4, 0x5d, 0xcf, 0xc3, 0x09, 0x3d,
0xc4, 0x1e, 0xc1, 0x34, 0x6d, 0x15, 0x97, 0xad, 0x95, 0x79, 0xc7, 0x9c, 0x6c, 0x6f, 0x40, 0xc3,
0xb4, 0x87, 0x9a, 0x50, 0x3c, 0xc6, 0x27, 0x32, 0x30, 0x36, 0x44, 0x37, 0x61, 0x76, 0xe4, 0x86,
0x19, 0xe6, 0x76, 0x2b, 0x8e, 0x20, 0x1e, 0x15, 0xfe, 0x6b, 0xd9, 0x1e, 0x2c, 0x68, 0xee, 0x4b,
0x70, 0x26, 0x0c, 0x5b, 0x53, 0x0c, 0xa3, 0x15, 0xb8, 0x91, 0x66, 0x49, 0x12, 0x13, 0x9a, 0x1e,
0x10, 0x3c, 0x0a, 0xf0, 0x3b, 0xae, 0x7e, 0xde, 0x19, 0x9f, 0xb6, 0xbf, 0xb3, 0xe0, 0x76, 0x6e,
0xa5, 0x47, 0x48, 0x4c, 0x9e, 0x07, 0x69, 0x1a, 0x44, 0x83, 0xa7, 0xf8, 0x24, 0x45, 0x1f, 0x40,
0x75, 0x78, 0x4a, 0x4a, 0x7c, 0x57, 0xa7, 0xe1, 0x3b, 0xbe, 0xb4, 0x73, 0x3a, 0x76, 0x74, 0x1d,
0xed, 0x2d, 0x80, 0x53, 0x16, 0x42, 0x50, 0x8a, 0xdc, 0x21, 0x96, 0x80, 0xf0, 0x31, 0x5a, 0x86,
0xaa, 0x8f, 0x53, 0x8f, 0x04, 0x09, 0x65, 0x29, 0x23, 0x70, 0xd1, 0xa7, 0xec, 0x2f, 0x2c, 0xa8,
0xef, 0x45, 0xa3, 0xf8, 0x38, 0x4f, 0x83, 0x26, 0x14, 0x69, 0x7c, 0xac, 0x70, 0xa5, 0xf1, 0xf1,
0xd5, 0xb6, 0xb3, 0x0d, 0xf3, 0xea, 0x6c, 0xf0, 0x9d, 0xac, 0x38, 0x39, 0xad, 0x67, 0x6f, 0x89,
0xb3, 0xf2, 0xec, 0x1d, 0x41, 0x43, 0x79, 0x21, 0x77, 0x67, 0x15, 0xca, 0x04, 0xd3, 0x8c, 0x88,
0x44, 0x3f, 0xc7, 0xac, 0x14, 0x43, 0x0f, 0x60, 0xbe, 0xef, 0x06, 0x61, 0x46, 0x30, 0xf3, 0xb4,
0xc8, 0x97, 0x68, 0xe8, 0x1e, 0x61, 0xef, 0x78, 0x47, 0xf0, 0x9d, 0x5c, 0xd0, 0xfe, 0x1c, 0x6a,
0x9c, 0xa3, 0x05, 0xaf, 0x4c, 0x56, 0x1c, 0x36, 0x64, 0xc1, 0xc7, 0xa1, 0x7f, 0x71, 0xf0, 0x4c,
0x88, 0x09, 0x47, 0xf8, 0x9d, 0x48, 0xe1, 0xf3, 0x84, 0x99, 0x90, 0x9d, 0x41, 0x5d, 0xda, 0x3e,
0x0d, 0x39, 0x88, 0x92, 0x4c, 0x66, 0xe2, 0x79, 0x21, 0x0b, 0xb1, 0xeb, 0x85, 0xbc, 0x25, 0x43,
0x96, 0x1c, 0xb9, 0x61, 0x09, 0x26, 0x54, 0x1d, 0xa6, 0x9c, 0x66, 0xf5, 0x83, 0x60, 0x37, 0xcd,
0x53, 0x47, 0x52, 0xf6, 0xb7, 0x16, 0x54, 0xbb, 0x41, 0xbf, 0xaf, 0x60, 0x6b, 0x40, 0x21, 0xf0,
0xe5, 0xea, 0x42, 0xe0, 0x2b, 0x18, 0x0b, 0x93, 0x30, 0x16, 0xaf, 0x02, 0x63, 0xe9, 0x12, 0x30,
0xb2, 0x63, 0x1c, 0x0c, 0xa2, 0x98, 0xe0, 0xed, 0x23, 0x37, 0x1a, 0xe0, 0xb4, 0x35, 0xbb, 0x5c,
0x5c, 0xa9, 0x38, 0xe6, 0xa4, 0xfd, 0xbd, 0x05, 0xb5, 0x03, 0x19, 0x16, 0xf3, 0x1c, 0xad, 0x41,
0xe9, 0x38, 0x88, 0x84, 0xd3, 0x8d, 0xf5, 0x25, 0x0d, 0x37, 0x5d, 0xac, 0xf3, 0x34, 0x88, 0x7c,
0x87, 0x4b, 0xa2, 0x25, 0xa8, 0x70, 0xdc, 0xd9, 0xbc, 0xac, 0x01, 0xa7, 0x13, 0xf6, 0x1b, 0x28,
0x31, 0x59, 0x34, 0x07, 0xc5, 0xcd, 0x6e, 0xb7, 0x39, 0x83, 0x6e, 0x40, 0x75, 0xb3, 0xdb, 0x7d,
0xed, 0xf4, 0x0e, 0x9e, 0x6d, 0x6e, 0xf7, 0x9a, 0x16, 0x02, 0x28, 0x77, 0x7b, 0xcf, 0x7a, 0x2f,
0x7b, 0xcd, 0x02, 0x42, 0xd0, 0x10, 0xe3, 0x9c, 0x5f, 0x64, 0xfc, 0x57, 0x07, 0xdd, 0xcd, 0x97,
0xbd, 0x66, 0x89, 0xf1, 0xc5, 0x38, 0xe7, 0xcf, 0xda, 0x3f, 0x16, 0xa1, 0x26, 0x40, 0x97, 0xf9,
0xd2, 0x86, 0x79, 0x82, 0x93, 0xd0, 0xf5, 0x64, 0xbd, 0xae, 0x38, 0x39, 0xcd, 0x8e, 0x5a, 0x4a,
0x45, 0x29, 0x2f, 0x70, 0x96, 0x22, 0xd1, 0x1a, 0xfc, 0xc5, 0xc7, 0x21, 0xa6, 0x78, 0x0b, 0xf7,
0x63, 0x56, 0x0e, 0xf9, 0x0a, 0x59, 0x75, 0xa7, 0xb1, 0xd0, 0x63, 0x98, 0xf3, 0x24, 0xb6, 0x25,
0x8e, 0xd6, 0xdf, 0x34, 0xb4, 0x74, 0x8f, 0x38, 0x21, 0x11, 0x77, 0xd4, 0x1a, 0x56, 0x96, 0xfd,
0xa0, 0xdf, 0x57, 0x1b, 0x23, 0x08, 0xf4, 0x1c, 0x6a, 0x3e, 0xa6, 0x6e, 0x10, 0x62, 0x9f, 0x03,
0x5a, 0xe6, 0xf9, 0xfb, 0xcf, 0x33, 0x35, 0x6b, 0xb2, 0xe2, 0xbe, 0x31, 0x96, 0xb3, 0x32, 0x7d,
0xe4, 0xa6, 0xba, 0x54, 0x6b, 0x4e, 0x94, 0xe9, 0xb1, 0xe9, 0xf6, 0xc7, 0xb0, 0x30, 0xa1, 0x6c,
0xca, 0x65, 0x72, 0x5f, 0xbf, 0x4c, 0xcc, 0x83, 0xa5, 0x27, 0x88, 0x7e, 0xcb, 0x3c, 0x16, 0x87,
0x42, 0x02, 0x80, 0x9a, 0x50, 0xeb, 0xee, 0xed, 0xec, 0xbc, 0x7e, 0xb5, 0xff, 0x74, 0xff, 0xc5,
0x47, 0xfb, 0xcd, 0x19, 0x54, 0x87, 0x0a, 0x9f, 0xd9, 0x7f, 0xb1, 0xcf, 0x12, 0x42, 0x91, 0x87,
0x2f, 0x9e, 0xf7, 0x9a, 0x05, 0xfb, 0x2b, 0x0b, 0xea, 0xdb, 0x04, 0xbb, 0x14, 0x9f, 0x5d, 0x8d,
0xfe, 0x03, 0x20, 0x0f, 0x67, 0x80, 0x2f, 0xac, 0x49, 0x9a, 0x28, 0xcb, 0x07, 0x1a, 0x0c, 0x71,
0x9c, 0x51, 0xbe, 0xd3, 0x96, 0xa3, 0x48, 0xc6, 0x49, 0xe4, 0xc5, 0x56, 0xe2, 0x88, 0x29, 0xd2,
0xfe, 0x04, 0x1a, 0xca, 0x1f, 0x99, 0x71, 0xe3, 0xe7, 0xfc, 0xba, 0xee, 0xd8, 0x5f, 0x5b, 0x50,
0x75, 0xb0, 0xeb, 0x5f, 0xbe, 0x80, 0x98, 0xa6, 0x8a, 0x97, 0x8f, 0xfc, 0xb4, 0xaa, 0x96, 0x2e,
0x55, 0x55, 0xed, 0x2f, 0x2d, 0xa8, 0x09, 0xdf, 0xde, 0x73, 0xd4, 0x9a, 0x2b, 0xc5, 0xcb, 0xb9,
0xf2, 0x93, 0x05, 0xf5, 0x57, 0x89, 0xaf, 0xa5, 0xc4, 0x9f, 0x59, 0x69, 0xb5, 0x1c, 0x9a, 0x35,
0x73, 0x68, 0xa2, 0x06, 0x97, 0xa7, 0xd4, 0x60, 0x3d, 0xd3, 0xe6, 0xcc, 0x4c, 0xdb, 0x83, 0x86,
0x0a, 0x53, 0x62, 0x6e, 0x62, 0x6c, 0x5d, 0x3e, 0xb3, 0x58, 0x43, 0xd3, 0xe5, 0x45, 0xec, 0x0f,
0xc8, 0x2d, 0x0d, 0x91, 0x92, 0x81, 0x88, 0xfd, 0x6b, 0x99, 0x77, 0xd8, 0xa2, 0xa1, 0xd7, 0xba,
0xf7, 0x84, 0xc4, 0x9f, 0x62, 0x8f, 0x4a, 0x77, 0x14, 0xc9, 0x6a, 0x64, 0x4a, 0x5d, 0xef, 0x58,
0xb5, 0xae, 0x9c, 0x40, 0x4f, 0xa0, 0xec, 0xf1, 0xae, 0xb0, 0x55, 0xe4, 0xd5, 0xf1, 0x1f, 0x66,
0xbb, 0x68, 0x28, 0x97, 0xfd, 0xa3, 0xa8, 0x8d, 0x72, 0x19, 0xbb, 0xbf, 0x7d, 0x72, 0xe2, 0x64,
0x91, 0x3c, 0xda, 0x92, 0xe2, 0x77, 0xbe, 0x4b, 0xdc, 0x30, 0xc4, 0x21, 0xdf, 0xca, 0x59, 0x27,
0xa7, 0x59, 0x25, 0x1d, 0xc6, 0x51, 0x40, 0x63, 0xd2, 0x8b, 0xfc, 0x24, 0x0e, 0x22, 0xda, 0x2a,
0x73, 0xa7, 0xc6, 0xa7, 0x59, 0xc7, 0x49, 0x4f, 0x12, 0xcc, 0x37, 0xb3, 0xe2, 0xf0, 0x71, 0xde,
0x85, 0xce, 0x6b, 0x5d, 0xe8, 0x22, 0x94, 0x13, 0x97, 0xe0, 0x88, 0xb6, 0x2a, 0xa2, 0x8b, 0x10,
0x94, 0x76, 0x1c, 0xe0, 0x72, 0xfd, 0xce, 0x1b, 0x58, 0x10, 0x17, 0x2e, 0x4e, 0x70, 0xe4, 0xe3,
0xc8, 0x63, 0xdb, 0x55, 0xe5, 0xd0, 0xac, 0x9f, 0x07, 0xcd, 0xde, 0xf8, 0x22, 0x81, 0xd2, 0xa4,
0x32, 0xb9, 0x43, 0x94, 0xed, 0x50, 0x4d, 0xa5, 0x28, 0x27, 0xd9, 0xeb, 0x48, 0xf5, 0xb1, 0x69,
0xab, 0x3e, 0xed, 0x75, 0x64, 0xda, 0x3c, 0x50, 0xc2, 0xf2, 0x75, 0x94, 0x2f, 0x66, 0x36, 0xdc,
0x30, 0x70, 0x53, 0x9c, 0xb6, 0x1a, 0xe2, 0x6a, 0x96, 0x24, 0xb2, 0xd9, 0x9d, 0xa8, 0x85, 0x76,
0x83, 0xb3, 0x8d, 0xb9, 0xf6, 0x5d, 0xb8, 0x99, 0xdf, 0x3f, 0xba, 0xe7, 0x08, 0x4a, 0x19, 0x89,
0x54, 0x23, 0xc0, 0xc7, 0xed, 0x87, 0x50, 0xd5, 0xb2, 0xe2, 0x2a, 0x2f, 0xa6, 0xf6, 0x08, 0x16,
0xa7, 0xa3, 0x36, 0x45, 0xcb, 0x8e, 0x79, 0x55, 0xae, 0x5d, 0x00, 0xcb, 0x84, 0xef, 0xba, 0xdd,
0x0d, 0x68, 0x98, 0xc8, 0x5d, 0xe9, 0x9d, 0xf7, 0x43, 0x81, 0x3f, 0xf4, 0x94, 0x49, 0x59, 0x4b,
0x26, 0xaf, 0xd1, 0xfb, 0xfc, 0xb8, 0x51, 0x7c, 0x51, 0xf1, 0x16, 0x52, 0xc8, 0x85, 0x05, 0x3e,
0x30, 0xf2, 0x4e, 0x1c, 0xc9, 0x07, 0xd3, 0x83, 0x95, 0x5d, 0xcb, 0xe1, 0xf8, 0x2a, 0x99, 0x78,
0x13, 0xda, 0xae, 0xb4, 0xad, 0xef, 0x60, 0x71, 0xba, 0xe2, 0x29, 0x58, 0xed, 0x9a, 0x7b, 0xf3,
0xef, 0x73, 0xdd, 0xbd, 0x60, 0x73, 0xec, 0x6f, 0x2c, 0xb8, 0xc5, 0x5f, 0xa7, 0x0e, 0x4e, 0xe3,
0x8c, 0x78, 0x78, 0x2f, 0x0a, 0xe8, 0x0e, 0x6f, 0xa5, 0xde, 0xdf, 0x25, 0xd9, 0x82, 0x39, 0xf1,
0xca, 0x10, 0x10, 0x57, 0x1c, 0x45, 0x5e, 0xf9, 0x26, 0x5f, 0xff, 0x65, 0x0e, 0x9a, 0xca, 0x55,
0x95, 0x55, 0xec, 0x20, 0xe7, 0x1f, 0x25, 0xe8, 0x8e, 0x86, 0xc7, 0xf8, 0x67, 0x4b, 0x7b, 0x69,
0x3a, 0x53, 0x80, 0x65, 0xcf, 0xa0, 0x2d, 0xa8, 0xf2, 0x97, 0x94, 0x38, 0x63, 0x68, 0xe2, 0xed,
0xa5, 0xf4, 0xb4, 0x26, 0x19, 0xb9, 0x8e, 0x27, 0x00, 0xbc, 0x67, 0x94, 0xf5, 0x7a, 0xa2, 0xfd,
0x15, 0x1a, 0x6e, 0x9d, 0xd1, 0x16, 0xdb, 0x33, 0x2c, 0x9c, 0xfc, 0xe7, 0xc0, 0x08, 0x67, 0xfc,
0xbf, 0xc6, 0x08, 0x67, 0xe2, 0x37, 0x84, 0xbb, 0x52, 0x16, 0x6f, 0x70, 0xa4, 0x3b, 0x6c, 0x7c,
0x0e, 0xb4, 0x6f, 0x4f, 0xe1, 0xe4, 0x0a, 0x76, 0xa1, 0x76, 0x48, 0x09, 0x76, 0x87, 0xbf, 0x4b,
0xcd, 0x9a, 0x85, 0x36, 0x60, 0x96, 0xe3, 0x74, 0x3d, 0x48, 0x1f, 0x42, 0x89, 0x3f, 0x09, 0xae,
0x01, 0xe6, 0x13, 0x28, 0x8b, 0x8e, 0xd7, 0xf0, 0xdd, 0x68, 0xca, 0x0d, 0xdf, 0xcd, 0xf6, 0x58,
0xd8, 0x66, 0xad, 0xa3, 0x61, 0x5b, 0xeb, 0x73, 0x0d, 0xdb, 0x7a, 0x8f, 0x29, 0x6c, 0x8b, 0x1e,
0xc8, 0xb0, 0x6d, 0x74, 0x7f, 0x86, 0x6d, 0xb3, 0x61, 0xb2, 0x67, 0xd0, 0x06, 0x94, 0x45, 0xe3,
0x63, 0x28, 0x30, 0x7a, 0xa1, 0xf6, 0xe2, 0xc4, 0x91, 0xe9, 0x0d, 0x13, 0x7a, 0x92, 0xe7, 0x91,
0x28, 0x08, 0xe3, 0x79, 0x64, 0x94, 0xf0, 0xf1, 0x3c, 0x32, 0x6b, 0x88, 0x3d, 0x83, 0x1e, 0x41,
0x79, 0xdb, 0x8d, 0x3c, 0x1c, 0xa2, 0x33, 0xac, 0x9d, 0xe3, 0xc5, 0xff, 0xa0, 0xbe, 0x8b, 0xe9,
0x01, 0xff, 0x41, 0xdd, 0x8b, 0xfa, 0xf1, 0x99, 0x2a, 0xfe, 0xaa, 0xbf, 0xc7, 0x72, 0x71, 0x7b,
0xe6, 0x6d, 0x99, 0x0b, 0x3e, 0xf8, 0x2d, 0x00, 0x00, 0xff, 0xff, 0xb4, 0x49, 0xd0, 0x38, 0xa2,
0x15, 0x00, 0x00,
// 1670 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xcd, 0x72, 0x1b, 0x45,
0x10, 0xf6, 0x4a, 0xb2, 0x6c, 0xb5, 0x7e, 0x22, 0x0f, 0xc1, 0x51, 0x14, 0x1f, 0x5c, 0x0b, 0x55,
0x98, 0x84, 0xc8, 0xc6, 0x39, 0x40, 0x52, 0x4e, 0x05, 0xdb, 0x92, 0x8d, 0x2b, 0x89, 0x63, 0xd6,
0x09, 0x3f, 0xa7, 0x64, 0xb3, 0x1a, 0xc9, 0x8b, 0xa5, 0xdd, 0x65, 0x76, 0x56, 0x29, 0x73, 0xe6,
0xc0, 0x05, 0xae, 0x14, 0x0f, 0x01, 0x54, 0xf1, 0x04, 0x3c, 0x08, 0x1c, 0x79, 0x00, 0x8a, 0x17,
0xa0, 0xe6, 0x6f, 0x3d, 0x23, 0xad, 0x7f, 0x49, 0xc1, 0x6d, 0x7b, 0xba, 0xa7, 0xa7, 0xfb, 0x9b,
0x9e, 0xfe, 0x59, 0xa8, 0x45, 0x24, 0x1c, 0xf9, 0x5d, 0x4c, 0x5a, 0x11, 0x09, 0x69, 0x88, 0x4a,
0x51, 0x32, 0x48, 0x86, 0x3e, 0x89, 0xbc, 0x66, 0x25, 0x1a, 0x24, 0x7d, 0x3f, 0x10, 0x8c, 0xe6,
0x8d, 0x7e, 0x18, 0xf6, 0x07, 0x78, 0x99, 0x53, 0x2f, 0x93, 0xde, 0x32, 0x1e, 0x46, 0xf4, 0x48,
0x32, 0x17, 0xc6, 0x99, 0x31, 0x25, 0x89, 0x47, 0x05, 0xd7, 0x7e, 0x0f, 0xea, 0xdb, 0x98, 0xee,
0x7b, 0x07, 0x78, 0xe8, 0x3a, 0xf8, 0xab, 0x04, 0xc7, 0x14, 0x35, 0x60, 0x66, 0x84, 0x49, 0xec,
0x87, 0x41, 0xc3, 0x5a, 0xb4, 0x96, 0xa6, 0x1d, 0x45, 0xda, 0xb7, 0x60, 0x4e, 0x93, 0x8e, 0xa3,
0x30, 0x88, 0x31, 0x9a, 0x87, 0x62, 0xcc, 0x57, 0xb8, 0x74, 0xc9, 0x91, 0x94, 0xfd, 0x43, 0x0e,
0xea, 0x9b, 0x61, 0xd0, 0xf3, 0xfb, 0x09, 0xc1, 0x4a, 0xf7, 0xc7, 0x50, 0x1a, 0xb9, 0xc4, 0x77,
0x5f, 0x0e, 0x70, 0xdc, 0xb0, 0x16, 0xf3, 0x4b, 0xe5, 0xd5, 0x9b, 0xad, 0xd4, 0xaf, 0xd6, 0xb8,
0x7c, 0xeb, 0x53, 0x25, 0xdc, 0x09, 0x28, 0x39, 0x72, 0x8e, 0x37, 0xa3, 0x5b, 0x50, 0x70, 0x49,
0x3f, 0x6e, 0xe4, 0x16, 0xad, 0xa5, 0xf2, 0xea, 0xb5, 0x96, 0x70, 0xb3, 0xa5, 0xdc, 0x6c, 0xed,
0x73, 0x37, 0x1d, 0x2e, 0x84, 0xde, 0x86, 0xaa, 0xeb, 0x79, 0x38, 0xa2, 0xfb, 0xd8, 0x23, 0x98,
0xc6, 0x8d, 0xfc, 0xa2, 0xb5, 0x34, 0xeb, 0x98, 0x8b, 0x68, 0x09, 0xae, 0x88, 0x05, 0x07, 0xc7,
0x61, 0x42, 0x3c, 0x1c, 0x37, 0x0a, 0x5c, 0x6e, 0x7c, 0xb9, 0xb9, 0x06, 0x35, 0xd3, 0x32, 0x54,
0x87, 0xfc, 0x21, 0x3e, 0x92, 0x10, 0xb0, 0x4f, 0x74, 0x15, 0xa6, 0x47, 0xee, 0x20, 0xc1, 0xdc,
0xc2, 0x92, 0x23, 0x88, 0x7b, 0xb9, 0x0f, 0x2d, 0xfb, 0x3b, 0x0b, 0xe6, 0x34, 0x4f, 0x25, 0x8e,
0x13, 0x36, 0x5a, 0x27, 0xd8, 0x18, 0x27, 0x51, 0x14, 0x12, 0x1a, 0xef, 0x11, 0x3c, 0xf2, 0xf1,
0x2b, 0xae, 0x7f, 0xd6, 0x19, 0x5f, 0xce, 0xf2, 0x26, 0x9f, 0xe9, 0x8d, 0xfd, 0xab, 0x05, 0xd7,
0x53, 0x7b, 0x3a, 0x84, 0x84, 0xe4, 0xb1, 0x1f, 0xc7, 0x7e, 0xd0, 0x7f, 0x88, 0x8f, 0x62, 0xf4,
0x09, 0x94, 0x87, 0xc7, 0xa4, 0xbc, 0xb4, 0xe5, 0xac, 0x4b, 0x1b, 0xdf, 0xda, 0x3a, 0xfe, 0x76,
0x74, 0x1d, 0xcd, 0x0d, 0x80, 0x63, 0x16, 0x42, 0x50, 0x08, 0xdc, 0x21, 0x96, 0xd8, 0xf1, 0x6f,
0xb4, 0x08, 0xe5, 0x2e, 0x8e, 0x3d, 0xe2, 0x47, 0x94, 0xc5, 0xa1, 0x80, 0x50, 0x5f, 0xb2, 0x7f,
0xb6, 0xa0, 0xba, 0x13, 0x8c, 0xc2, 0xc3, 0x34, 0xb6, 0xea, 0x90, 0xa7, 0xe1, 0xa1, 0xba, 0x02,
0x1a, 0x1e, 0x5e, 0x2c, 0x46, 0x9a, 0x30, 0xab, 0x1e, 0x1c, 0x07, 0xaa, 0xe4, 0xa4, 0xb4, 0xfe,
0x24, 0x0a, 0x9c, 0xa5, 0xc8, 0x2c, 0x94, 0xa7, 0xb3, 0x51, 0x1e, 0x41, 0x4d, 0xd9, 0x2b, 0x6f,
0x7c, 0x19, 0x8a, 0x04, 0xd3, 0x84, 0x88, 0x77, 0x76, 0x8a, 0x81, 0x52, 0x0c, 0xdd, 0x81, 0xd9,
0x9e, 0xeb, 0x0f, 0x12, 0x82, 0x99, 0x4f, 0x79, 0xbe, 0x45, 0xbb, 0x87, 0x03, 0xec, 0x1d, 0x6e,
0x09, 0xbe, 0x93, 0x0a, 0xda, 0x5f, 0x43, 0x85, 0x73, 0x34, 0x98, 0xd4, 0x91, 0x25, 0x87, 0x7d,
0x32, 0x98, 0xc2, 0x41, 0xf7, 0x6c, 0x98, 0x98, 0x10, 0x13, 0x0e, 0xf0, 0x2b, 0x11, 0x4b, 0xa7,
0x09, 0x33, 0x21, 0x3b, 0x81, 0xaa, 0x3c, 0xfb, 0xd8, 0x65, 0x3f, 0x88, 0x12, 0x19, 0xdd, 0xa7,
0xb9, 0x2c, 0xc4, 0x2e, 0xe7, 0xf2, 0x86, 0x74, 0x59, 0x72, 0xe4, 0xd5, 0x46, 0x98, 0x50, 0xf5,
0x42, 0x53, 0x9a, 0xa5, 0x2f, 0x82, 0xdd, 0x38, 0x0d, 0x32, 0x49, 0xd9, 0xbf, 0x58, 0x50, 0x6e,
0xfb, 0xbd, 0x9e, 0x82, 0xad, 0x06, 0x39, 0xbf, 0x2b, 0x77, 0xe7, 0xfc, 0xae, 0x82, 0x31, 0x37,
0x09, 0x63, 0xfe, 0x22, 0x30, 0x16, 0xce, 0x01, 0x23, 0x4b, 0x0d, 0x7e, 0x3f, 0x08, 0x09, 0xde,
0x3c, 0x70, 0x83, 0x3e, 0x0f, 0xb1, 0xfc, 0x52, 0xc9, 0x31, 0x17, 0xed, 0xdf, 0x2c, 0xa8, 0xec,
0x49, 0xb7, 0x98, 0xe5, 0x68, 0x05, 0x0a, 0x87, 0x7e, 0x20, 0x8c, 0xae, 0xad, 0x2e, 0x68, 0xb8,
0xe9, 0x62, 0xad, 0x87, 0x7e, 0xd0, 0x75, 0xb8, 0x24, 0x5a, 0x80, 0x12, 0xc7, 0x9d, 0xad, 0xcb,
0xbc, 0x72, 0xbc, 0x60, 0xbf, 0x80, 0x02, 0x93, 0x45, 0x33, 0x90, 0x5f, 0x6f, 0xb7, 0xeb, 0x53,
0xe8, 0x0a, 0x94, 0xd7, 0xdb, 0xed, 0xe7, 0x4e, 0x67, 0xef, 0xd1, 0xfa, 0x66, 0xa7, 0x6e, 0x21,
0x80, 0x62, 0xbb, 0xf3, 0xa8, 0xf3, 0xb4, 0x53, 0xcf, 0x21, 0x04, 0x35, 0xf1, 0x9d, 0xf2, 0xf3,
0x8c, 0xff, 0x6c, 0xaf, 0xbd, 0xfe, 0xb4, 0x53, 0x2f, 0x30, 0xbe, 0xf8, 0x4e, 0xf9, 0xd3, 0xf6,
0x1f, 0x79, 0xa8, 0x08, 0xd0, 0x65, 0xbc, 0x34, 0x61, 0x96, 0xe0, 0x68, 0xe0, 0x7a, 0xb2, 0x5c,
0x94, 0x9c, 0x94, 0x66, 0x8f, 0x32, 0xa6, 0xa2, 0x92, 0xe4, 0x38, 0x4b, 0x91, 0x68, 0x05, 0xde,
0xe8, 0xe2, 0x01, 0xa6, 0x78, 0x03, 0xf7, 0x42, 0x96, 0x62, 0xf9, 0x0e, 0x99, 0xfe, 0xb2, 0x58,
0xe8, 0x3e, 0xcc, 0x78, 0x12, 0xdb, 0x02, 0x47, 0xeb, 0x2d, 0x0d, 0x2d, 0xdd, 0x22, 0x4e, 0x48,
0xc4, 0x1d, 0xb5, 0x87, 0xe5, 0xfa, 0xae, 0xdf, 0xeb, 0xa9, 0x8b, 0x11, 0x04, 0x7a, 0x0c, 0x95,
0x2e, 0xa6, 0xae, 0x3f, 0xc0, 0x5d, 0x0e, 0x68, 0x91, 0xc7, 0xef, 0xbb, 0x27, 0x6a, 0xd6, 0x64,
0x45, 0xb9, 0x33, 0xb6, 0xb3, 0x54, 0x73, 0xe0, 0xc6, 0xba, 0x54, 0x63, 0x46, 0xa4, 0x9a, 0xb1,
0xe5, 0xe6, 0xe7, 0x30, 0x37, 0xa1, 0x2c, 0xa3, 0x42, 0xdd, 0xd6, 0x2b, 0x94, 0xf9, 0xb0, 0xf4,
0x00, 0xd1, 0x4b, 0xd7, 0x7d, 0xf1, 0x28, 0x24, 0x00, 0xa8, 0x0e, 0x95, 0xf6, 0xce, 0xd6, 0xd6,
0xf3, 0x67, 0xbb, 0x0f, 0x77, 0x9f, 0x7c, 0xb6, 0x5b, 0x9f, 0x42, 0x55, 0x28, 0xf1, 0x95, 0xdd,
0x27, 0xbb, 0x2c, 0x20, 0x14, 0xb9, 0xff, 0xe4, 0x71, 0xa7, 0x9e, 0xb3, 0xbf, 0xb7, 0xa0, 0xba,
0x49, 0xb0, 0x4b, 0xf1, 0xc9, 0xd9, 0xe8, 0x03, 0x00, 0xf9, 0x38, 0x7d, 0x7c, 0x66, 0x4e, 0xd2,
0x44, 0x59, 0x3c, 0x50, 0x7f, 0x88, 0xc3, 0x84, 0xf2, 0x9b, 0xb6, 0x1c, 0x45, 0x32, 0x4e, 0x24,
0x8b, 0xa5, 0x28, 0xe8, 0x8a, 0xb4, 0xbf, 0x80, 0x9a, 0xb2, 0x47, 0x46, 0xdc, 0xf8, 0x3b, 0xbf,
0xac, 0x39, 0xf6, 0x8f, 0x16, 0x94, 0x1d, 0xec, 0x76, 0xcf, 0x9f, 0x40, 0xcc, 0xa3, 0xf2, 0xe7,
0xf7, 0xfc, 0x38, 0xab, 0x16, 0xce, 0x95, 0x55, 0xed, 0x6f, 0x2d, 0xa8, 0x08, 0xdb, 0x5e, 0xb3,
0xd7, 0x9a, 0x29, 0xf9, 0xf3, 0x99, 0xf2, 0xa7, 0x05, 0xd5, 0x67, 0x51, 0x57, 0x0b, 0x89, 0xff,
0x33, 0xd3, 0x6a, 0x31, 0x34, 0x6d, 0xc6, 0xd0, 0x44, 0x0e, 0x2e, 0x66, 0xe4, 0x60, 0x3d, 0xd2,
0x66, 0xcc, 0x48, 0xdb, 0x81, 0x9a, 0x72, 0x53, 0x62, 0x6e, 0x62, 0x6c, 0x9d, 0x3f, 0xb2, 0xbe,
0xb1, 0xa0, 0xda, 0xe6, 0x49, 0xec, 0x3f, 0x88, 0x2d, 0x0d, 0x91, 0x82, 0x81, 0x88, 0xfd, 0x77,
0x91, 0x37, 0xf8, 0x62, 0x9e, 0xd0, 0x86, 0x87, 0x88, 0x84, 0x5f, 0x62, 0x8f, 0x4a, 0x73, 0x14,
0xc9, 0x72, 0x64, 0x4c, 0x5d, 0xef, 0x50, 0xf5, 0xc3, 0x9c, 0x40, 0x0f, 0xa0, 0xe8, 0xf1, 0xfe,
0xb1, 0x91, 0xe7, 0xd9, 0xf1, 0x1d, 0xb3, 0xb1, 0x34, 0x94, 0xcb, 0x4e, 0x53, 0xe4, 0x46, 0xb9,
0x8d, 0xd5, 0xef, 0x2e, 0x39, 0x72, 0x92, 0x40, 0x3e, 0x6d, 0x49, 0xf1, 0x9a, 0xef, 0x12, 0x77,
0x30, 0xc0, 0x03, 0x7e, 0x95, 0xd3, 0x4e, 0x4a, 0xb3, 0x4c, 0x3a, 0x0c, 0x03, 0x9f, 0x86, 0xa4,
0x13, 0x74, 0xa3, 0xd0, 0x0f, 0x68, 0xa3, 0xc8, 0x8d, 0x1a, 0x5f, 0x66, 0xbd, 0x29, 0x3d, 0x8a,
0x30, 0xbf, 0xcc, 0x92, 0xc3, 0xbf, 0xd3, 0x7e, 0x75, 0x56, 0xeb, 0x57, 0xe7, 0xa1, 0x18, 0xb9,
0x04, 0x07, 0xb4, 0x51, 0x12, 0x5d, 0x84, 0xa0, 0xb4, 0xe7, 0x00, 0xe7, 0xeb, 0x77, 0x5e, 0xc0,
0x9c, 0x28, 0xb8, 0x38, 0xc2, 0x41, 0x17, 0x07, 0x1e, 0xbb, 0xae, 0x32, 0x87, 0x66, 0xf5, 0x34,
0x68, 0x76, 0xc6, 0x37, 0x09, 0x94, 0x26, 0x95, 0xc9, 0x1b, 0xa2, 0xec, 0x86, 0x2a, 0x2a, 0x44,
0x39, 0xc9, 0x86, 0x33, 0xd5, 0xf1, 0xc6, 0x8d, 0x6a, 0xd6, 0x70, 0x66, 0x9e, 0xb9, 0xa7, 0x84,
0xe5, 0x70, 0x96, 0x6e, 0x66, 0x67, 0xb8, 0x03, 0xdf, 0x8d, 0x71, 0xdc, 0xa8, 0x89, 0xd2, 0x2c,
0x49, 0x64, 0xb3, 0x9a, 0xa8, 0xb9, 0x76, 0x85, 0xb3, 0x8d, 0xb5, 0xe6, 0x4d, 0xb8, 0x9a, 0xd6,
0x1f, 0xdd, 0x72, 0x04, 0x85, 0x84, 0x04, 0xaa, 0x11, 0xe0, 0xdf, 0xcd, 0xbb, 0x50, 0xd6, 0xa2,
0xe2, 0x22, 0x63, 0x58, 0x73, 0x04, 0xf3, 0xd9, 0xa8, 0x65, 0x68, 0xd9, 0x32, 0x4b, 0xe5, 0xca,
0x19, 0xb0, 0x4c, 0xd8, 0xae, 0x9f, 0xbb, 0x06, 0x35, 0x13, 0xb9, 0x0b, 0x0d, 0x8f, 0xbf, 0xe7,
0xf8, 0xf0, 0xa8, 0x8e, 0x94, 0xb9, 0x64, 0xb2, 0x8c, 0xde, 0xe6, 0xcf, 0x8d, 0xe2, 0xb3, 0x92,
0xb7, 0x90, 0x42, 0x2e, 0xcc, 0xf1, 0x0f, 0x23, 0xee, 0xc4, 0x93, 0xbc, 0x93, 0xed, 0xac, 0xec,
0x5a, 0xf6, 0xc7, 0x77, 0xc9, 0xc0, 0x9b, 0xd0, 0x76, 0xa1, 0x6b, 0x7d, 0x05, 0xf3, 0xd9, 0x8a,
0x33, 0xb0, 0xda, 0x36, 0xef, 0xe6, 0xfd, 0x53, 0xcd, 0x3d, 0xe3, 0x72, 0xec, 0x9f, 0x2c, 0xb8,
0xc6, 0xe7, 0x58, 0x35, 0xb8, 0xed, 0x04, 0x3e, 0xdd, 0xe2, 0xad, 0xd4, 0xeb, 0x2b, 0x92, 0x0d,
0x98, 0x11, 0x53, 0x86, 0x80, 0xb8, 0xe4, 0x28, 0xf2, 0xc2, 0x95, 0x7c, 0xf5, 0xaf, 0x19, 0xa8,
0x2b, 0x53, 0x55, 0x54, 0xb1, 0x87, 0x9c, 0xfe, 0xa7, 0x41, 0x37, 0x34, 0x3c, 0xc6, 0xff, 0xf5,
0x34, 0x17, 0xb2, 0x99, 0x02, 0x2c, 0x7b, 0x0a, 0x6d, 0x40, 0x99, 0x4f, 0x52, 0xe2, 0x8d, 0xa1,
0x89, 0xd9, 0x4b, 0xe9, 0x69, 0x4c, 0x32, 0x52, 0x1d, 0x0f, 0x00, 0x78, 0xcf, 0x28, 0xf3, 0xf5,
0x44, 0xfb, 0x2b, 0x34, 0x5c, 0x3b, 0xa1, 0x2d, 0xb6, 0xa7, 0x98, 0x3b, 0xe9, 0x3f, 0x06, 0xc3,
0x9d, 0xf1, 0xdf, 0x45, 0x86, 0x3b, 0x13, 0x7f, 0x58, 0xb8, 0x29, 0x45, 0x31, 0x83, 0x23, 0xdd,
0x60, 0xe3, 0x37, 0x42, 0xf3, 0x7a, 0x06, 0x27, 0x55, 0xb0, 0x0d, 0x95, 0x7d, 0x4a, 0xb0, 0x3b,
0xfc, 0x57, 0x6a, 0x56, 0x2c, 0xb4, 0x06, 0xd3, 0x1c, 0xa7, 0xcb, 0x41, 0x7a, 0x17, 0x0a, 0x7c,
0x24, 0xb8, 0x04, 0x98, 0x0f, 0xa0, 0x28, 0x3a, 0x5e, 0xc3, 0x76, 0xa3, 0x29, 0x37, 0x6c, 0x37,
0xdb, 0x63, 0x71, 0x36, 0x6b, 0x1d, 0x8d, 0xb3, 0xb5, 0x3e, 0xd7, 0x38, 0x5b, 0xef, 0x31, 0xc5,
0xd9, 0xa2, 0x07, 0x32, 0xce, 0x36, 0xba, 0x3f, 0xe3, 0x6c, 0xb3, 0x61, 0xb2, 0xa7, 0xd0, 0x1a,
0x14, 0x45, 0xe3, 0x63, 0x28, 0x30, 0x7a, 0xa1, 0xe6, 0xfc, 0xc4, 0x93, 0xe9, 0x0c, 0x23, 0x7a,
0x94, 0xc6, 0x91, 0x48, 0x08, 0xe3, 0x71, 0x64, 0xa4, 0xf0, 0xf1, 0x38, 0x32, 0x73, 0x88, 0x3d,
0x85, 0xee, 0x41, 0x71, 0xd3, 0x0d, 0x3c, 0x3c, 0x40, 0x27, 0x9c, 0x76, 0x8a, 0x15, 0x1f, 0x41,
0x75, 0x1b, 0xd3, 0x3d, 0xfe, 0x03, 0x77, 0x27, 0xe8, 0x85, 0x27, 0xaa, 0x78, 0x53, 0x9f, 0xc7,
0x52, 0x71, 0x7b, 0xea, 0x65, 0x91, 0x0b, 0xde, 0xf9, 0x27, 0x00, 0x00, 0xff, 0xff, 0xac, 0xa3,
0xd1, 0x1f, 0x21, 0x16, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View file

@ -119,6 +119,7 @@ type ReadResourceRequest struct {
AcceptSecrets bool `protobuf:"varint,9,opt,name=acceptSecrets,proto3" json:"acceptSecrets,omitempty"`
AdditionalSecretOutputs []string `protobuf:"bytes,10,rep,name=additionalSecretOutputs,proto3" json:"additionalSecretOutputs,omitempty"`
Aliases []string `protobuf:"bytes,11,rep,name=aliases,proto3" json:"aliases,omitempty"`
AcceptResources bool `protobuf:"varint,12,opt,name=acceptResources,proto3" json:"acceptResources,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -226,6 +227,13 @@ func (m *ReadResourceRequest) GetAliases() []string {
return nil
}
func (m *ReadResourceRequest) GetAcceptResources() bool {
if m != nil {
return m.AcceptResources
}
return false
}
// ReadResourceResponse contains the result of reading a resource's state.
type ReadResourceResponse struct {
Urn string `protobuf:"bytes,1,opt,name=urn,proto3" json:"urn,omitempty"`
@ -296,6 +304,7 @@ type RegisterResourceRequest struct {
DeleteBeforeReplaceDefined bool `protobuf:"varint,18,opt,name=deleteBeforeReplaceDefined,proto3" json:"deleteBeforeReplaceDefined,omitempty"`
SupportsPartialValues bool `protobuf:"varint,19,opt,name=supportsPartialValues,proto3" json:"supportsPartialValues,omitempty"`
Remote bool `protobuf:"varint,20,opt,name=remote,proto3" json:"remote,omitempty"`
AcceptResources bool `protobuf:"varint,21,opt,name=acceptResources,proto3" json:"acceptResources,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -466,6 +475,13 @@ func (m *RegisterResourceRequest) GetRemote() bool {
return false
}
func (m *RegisterResourceRequest) GetAcceptResources() bool {
if m != nil {
return m.AcceptResources
}
return false
}
// 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"`
@ -759,65 +775,66 @@ func init() {
func init() { proto.RegisterFile("resource.proto", fileDescriptor_d1b72f771c35e3b8) }
var fileDescriptor_d1b72f771c35e3b8 = []byte{
// 927 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x5f, 0x73, 0xdb, 0x44,
0x10, 0x8f, 0xed, 0x54, 0xb1, 0x37, 0xa9, 0x13, 0x2e, 0xc1, 0xb9, 0x0a, 0x26, 0x04, 0xc1, 0x83,
0xe1, 0xc1, 0x69, 0x03, 0x33, 0x0d, 0x0c, 0x7f, 0x66, 0x68, 0x0b, 0xd3, 0x87, 0x42, 0x51, 0x18,
0x06, 0x98, 0x81, 0x99, 0x8b, 0xb4, 0x71, 0x45, 0x64, 0xdd, 0xf5, 0xee, 0x94, 0x19, 0xbf, 0xc1,
0x23, 0x5f, 0x8b, 0x4f, 0xc3, 0x33, 0x9f, 0x80, 0xb9, 0x3b, 0xc9, 0x58, 0x96, 0x9c, 0xd8, 0xed,
0xdb, 0xed, 0xee, 0xdd, 0x4a, 0xfb, 0xfb, 0xfd, 0x76, 0xef, 0xa0, 0x2f, 0x51, 0xf1, 0x5c, 0x46,
0x38, 0x12, 0x92, 0x6b, 0x4e, 0x7a, 0x22, 0x4f, 0xf3, 0x49, 0x22, 0x45, 0xe4, 0xbf, 0x35, 0xe6,
0x7c, 0x9c, 0xe2, 0x89, 0x0d, 0x5c, 0xe4, 0x97, 0x27, 0x38, 0x11, 0x7a, 0xea, 0xf6, 0xf9, 0x6f,
0x2f, 0x06, 0x95, 0x96, 0x79, 0xa4, 0x8b, 0x68, 0x5f, 0x48, 0x7e, 0x9d, 0xc4, 0x28, 0x9d, 0x1d,
0x0c, 0x61, 0x70, 0x9e, 0x0b, 0xc1, 0xa5, 0x56, 0x5f, 0x23, 0xd3, 0xb9, 0xc4, 0x10, 0x5f, 0xe6,
0xa8, 0x34, 0xe9, 0x43, 0x3b, 0x89, 0x69, 0xeb, 0xb8, 0x35, 0xec, 0x85, 0xed, 0x24, 0x0e, 0x3e,
0x81, 0xc3, 0xda, 0x4e, 0x25, 0x78, 0xa6, 0x90, 0x1c, 0x01, 0xbc, 0x60, 0xaa, 0x88, 0xda, 0x23,
0xdd, 0x70, 0xce, 0x13, 0xfc, 0xdb, 0x86, 0xfd, 0x10, 0x59, 0x1c, 0x16, 0x15, 0x2d, 0xf9, 0x04,
0x21, 0xb0, 0xa9, 0xa7, 0x02, 0x69, 0xdb, 0x7a, 0xec, 0xda, 0xf8, 0x32, 0x36, 0x41, 0xda, 0x71,
0x3e, 0xb3, 0x26, 0x03, 0xf0, 0x04, 0x93, 0x98, 0x69, 0xba, 0x69, 0xbd, 0x85, 0x45, 0x1e, 0x02,
0x08, 0xc9, 0x05, 0x4a, 0x9d, 0xa0, 0xa2, 0x77, 0x8e, 0x5b, 0xc3, 0xed, 0xd3, 0xc3, 0x91, 0xc3,
0x63, 0x54, 0xe2, 0x31, 0x3a, 0xb7, 0x78, 0x84, 0x73, 0x5b, 0x49, 0x00, 0x3b, 0x31, 0x0a, 0xcc,
0x62, 0xcc, 0x22, 0x73, 0xd4, 0x3b, 0xee, 0x0c, 0x7b, 0x61, 0xc5, 0x47, 0x7c, 0xe8, 0x96, 0xd8,
0xd1, 0x2d, 0xfb, 0xd9, 0x99, 0x4d, 0x28, 0x6c, 0x5d, 0xa3, 0x54, 0x09, 0xcf, 0x68, 0xd7, 0x86,
0x4a, 0x93, 0xbc, 0x0f, 0x77, 0x59, 0x14, 0xa1, 0xd0, 0xe7, 0x18, 0x49, 0xd4, 0x8a, 0xf6, 0x2c,
0x3a, 0x55, 0x27, 0x39, 0x83, 0x43, 0x16, 0xc7, 0x89, 0x4e, 0x78, 0xc6, 0x52, 0xe7, 0xfc, 0x2e,
0xd7, 0x22, 0xd7, 0x8a, 0x82, 0xfd, 0x95, 0x65, 0x61, 0xf3, 0x65, 0x96, 0x26, 0x4c, 0xa1, 0xa2,
0xdb, 0x76, 0x67, 0x69, 0x06, 0x0c, 0x0e, 0xaa, 0x98, 0x17, 0x64, 0xed, 0x41, 0x27, 0x97, 0x59,
0x81, 0xba, 0x59, 0x2e, 0xc0, 0xd6, 0x5e, 0x19, 0xb6, 0xe0, 0x9f, 0x2e, 0x1c, 0x86, 0x38, 0x4e,
0x94, 0x46, 0xb9, 0xc8, 0x6d, 0xc9, 0x65, 0xab, 0x81, 0xcb, 0x76, 0x23, 0x97, 0x9d, 0x0a, 0x97,
0x03, 0xf0, 0xa2, 0x5c, 0x69, 0x3e, 0xb1, 0x1c, 0x77, 0xc3, 0xc2, 0x22, 0x27, 0xe0, 0xf1, 0x8b,
0xdf, 0x31, 0xd2, 0xb7, 0xf1, 0x5b, 0x6c, 0x33, 0x08, 0x99, 0x90, 0x39, 0xe1, 0xd9, 0x4c, 0xa5,
0x59, 0x63, 0x7d, 0xeb, 0x16, 0xd6, 0xbb, 0x0b, 0xac, 0x0b, 0x38, 0x28, 0xc0, 0x98, 0x3e, 0x9e,
0xcf, 0xd3, 0x3b, 0xee, 0x0c, 0xb7, 0x4f, 0x3f, 0x1b, 0xcd, 0x1a, 0x76, 0xb4, 0x04, 0xa4, 0xd1,
0xf3, 0x86, 0xe3, 0x4f, 0x32, 0x2d, 0xa7, 0x61, 0x63, 0x66, 0x72, 0x1f, 0xf6, 0x63, 0x4c, 0x51,
0xe3, 0x57, 0x78, 0xc9, 0x4d, 0x03, 0x8a, 0x94, 0x45, 0x48, 0xc1, 0xd6, 0xd5, 0x14, 0x9a, 0x57,
0xe6, 0x76, 0x4d, 0x99, 0xc9, 0x38, 0xe3, 0x12, 0x1f, 0xbd, 0x60, 0xd9, 0x18, 0x15, 0xdd, 0xb1,
0xe5, 0x57, 0x9d, 0x75, 0xfd, 0xde, 0x5d, 0x53, 0xbf, 0xfd, 0x95, 0xf5, 0xbb, 0x5b, 0xd1, 0xaf,
0x41, 0x3e, 0x99, 0x98, 0xf1, 0xf1, 0x34, 0xa6, 0x7b, 0x0e, 0xf9, 0xd2, 0x26, 0x3f, 0x43, 0xdf,
0xc9, 0xe1, 0x87, 0x64, 0x82, 0xdc, 0x7c, 0xe6, 0x0d, 0x2b, 0x86, 0x07, 0x2b, 0x60, 0xfe, 0xa8,
0x72, 0x30, 0x5c, 0x48, 0x44, 0xbe, 0x00, 0xbf, 0x01, 0xc7, 0xc7, 0x78, 0x99, 0x64, 0x18, 0x53,
0x62, 0xab, 0xbf, 0x61, 0x07, 0xf9, 0x18, 0xde, 0x54, 0xc5, 0x98, 0x7c, 0xce, 0xa4, 0x4e, 0x58,
0xfa, 0x23, 0x4b, 0x73, 0x54, 0x74, 0xdf, 0x1e, 0x6d, 0x0e, 0x1a, 0xb5, 0x4b, 0x9c, 0x70, 0x8d,
0xf4, 0xc0, 0xa9, 0xdd, 0x59, 0xfe, 0x87, 0x70, 0xd0, 0xa4, 0x11, 0xd3, 0x49, 0xb9, 0xcc, 0x14,
0x6d, 0x59, 0xcc, 0xec, 0xda, 0xff, 0x09, 0xfa, 0xd5, 0xda, 0x6c, 0x0f, 0x49, 0x64, 0xba, 0xec,
0xc2, 0xc2, 0x32, 0xfe, 0x5c, 0xc4, 0xc6, 0xef, 0x3a, 0xb1, 0xb0, 0x8c, 0xdf, 0x55, 0x56, 0xf6,
0xa2, 0xb3, 0xfc, 0x3f, 0x5a, 0x70, 0x6f, 0xa9, 0x54, 0xcd, 0x40, 0xb9, 0xc2, 0x69, 0x39, 0x50,
0xae, 0x70, 0x4a, 0x9e, 0xc1, 0x9d, 0x6b, 0x53, 0x57, 0x31, 0x4b, 0x1e, 0xbe, 0x62, 0x27, 0x84,
0x2e, 0xcb, 0xa7, 0xed, 0xb3, 0x56, 0xf0, 0x77, 0x07, 0x68, 0xfd, 0xec, 0xd2, 0x91, 0xe6, 0x6e,
0x96, 0xf6, 0xec, 0x66, 0xf9, 0x7f, 0x6a, 0x74, 0x56, 0x9b, 0x1a, 0x03, 0xf0, 0x94, 0x66, 0x17,
0x29, 0x96, 0xe3, 0xc7, 0x59, 0x46, 0xaf, 0x6e, 0x65, 0xee, 0x17, 0xab, 0xd7, 0xc2, 0x24, 0x2f,
0x97, 0x4c, 0x03, 0xcf, 0x4e, 0x83, 0xcf, 0x6f, 0xc4, 0xc0, 0xd5, 0xb1, 0xee, 0x38, 0x58, 0x4b,
0x1d, 0x7f, 0xae, 0xc9, 0xe1, 0xb7, 0x55, 0x0e, 0xcf, 0x5e, 0xf5, 0xff, 0xe7, 0x49, 0x44, 0x38,
0x5a, 0x3c, 0x5b, 0xcc, 0x81, 0xf2, 0xd6, 0xa8, 0x33, 0xf9, 0x00, 0xb6, 0x78, 0x31, 0x4a, 0x6e,
0xb9, 0x99, 0xca, 0x7d, 0xa7, 0x7f, 0x6d, 0xc2, 0x6e, 0x99, 0xff, 0x19, 0xcf, 0x12, 0xcd, 0x25,
0xf9, 0x05, 0x76, 0x17, 0x5e, 0x2f, 0xe4, 0xdd, 0xb9, 0x92, 0x9a, 0xdf, 0x40, 0x7e, 0x70, 0xd3,
0x16, 0x57, 0x74, 0xb0, 0x41, 0xbe, 0x04, 0xef, 0x69, 0x76, 0xcd, 0xaf, 0x90, 0xd0, 0xb9, 0xfd,
0xce, 0x55, 0x66, 0xba, 0xd7, 0x10, 0x99, 0x25, 0xf8, 0x06, 0x76, 0xce, 0xb5, 0x44, 0x36, 0x79,
0xad, 0x34, 0xf7, 0x5b, 0xe4, 0x7b, 0xd8, 0x99, 0xbf, 0xf3, 0xc9, 0x51, 0x85, 0xb5, 0xda, 0x03,
0xcc, 0x7f, 0x67, 0x69, 0x7c, 0xf6, 0x6f, 0xbf, 0xc2, 0xde, 0x22, 0x67, 0x24, 0xb8, 0xbd, 0xa1,
0xfd, 0xf7, 0x56, 0x10, 0x4c, 0xb0, 0x41, 0x7e, 0xab, 0xbf, 0x20, 0xca, 0xab, 0xe1, 0x83, 0x1b,
0x32, 0x54, 0x65, 0xe3, 0x0f, 0x6a, 0x9a, 0x78, 0x62, 0x5e, 0xc4, 0xc1, 0xc6, 0x85, 0x67, 0x3d,
0x1f, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xbf, 0x6d, 0x72, 0x4e, 0x0b, 0x00, 0x00,
// 943 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcd, 0x6f, 0x1c, 0x35,
0x14, 0xcf, 0xee, 0xa6, 0x93, 0xdd, 0x97, 0x74, 0x13, 0x9c, 0x34, 0x71, 0x07, 0x14, 0xc2, 0xc0,
0x61, 0xe1, 0xb0, 0x69, 0x03, 0x52, 0x03, 0xe2, 0x43, 0xa2, 0x2d, 0xa8, 0x87, 0x42, 0x99, 0x20,
0x04, 0x48, 0x20, 0x39, 0x33, 0x2f, 0xdb, 0x21, 0xb3, 0x63, 0xd7, 0xf6, 0x44, 0xda, 0x1b, 0x1c,
0xb9, 0x72, 0xe6, 0xaf, 0xe1, 0x2f, 0x43, 0xb6, 0x67, 0x96, 0x9d, 0x8f, 0x4d, 0x36, 0xe5, 0xe6,
0xf7, 0x69, 0xfb, 0xf7, 0x7e, 0xef, 0xd9, 0x30, 0x94, 0xa8, 0x78, 0x2e, 0x23, 0x1c, 0x0b, 0xc9,
0x35, 0x27, 0x03, 0x91, 0xa7, 0xf9, 0x34, 0x91, 0x22, 0xf2, 0xdf, 0x9c, 0x70, 0x3e, 0x49, 0xf1,
0xd8, 0x1a, 0xce, 0xf3, 0x8b, 0x63, 0x9c, 0x0a, 0x3d, 0x73, 0x7e, 0xfe, 0x5b, 0x75, 0xa3, 0xd2,
0x32, 0x8f, 0x74, 0x61, 0x1d, 0x0a, 0xc9, 0xaf, 0x92, 0x18, 0xa5, 0x93, 0x83, 0x11, 0xec, 0x9f,
0xe5, 0x42, 0x70, 0xa9, 0xd5, 0x57, 0xc8, 0x74, 0x2e, 0x31, 0xc4, 0x57, 0x39, 0x2a, 0x4d, 0x86,
0xd0, 0x4d, 0x62, 0xda, 0x39, 0xea, 0x8c, 0x06, 0x61, 0x37, 0x89, 0x83, 0x8f, 0xe1, 0xa0, 0xe1,
0xa9, 0x04, 0xcf, 0x14, 0x92, 0x43, 0x80, 0x97, 0x4c, 0x15, 0x56, 0x1b, 0xd2, 0x0f, 0x17, 0x34,
0xc1, 0xdf, 0x3d, 0xd8, 0x0d, 0x91, 0xc5, 0x61, 0x71, 0xa3, 0x25, 0x5b, 0x10, 0x02, 0xeb, 0x7a,
0x26, 0x90, 0x76, 0xad, 0xc6, 0xae, 0x8d, 0x2e, 0x63, 0x53, 0xa4, 0x3d, 0xa7, 0x33, 0x6b, 0xb2,
0x0f, 0x9e, 0x60, 0x12, 0x33, 0x4d, 0xd7, 0xad, 0xb6, 0x90, 0xc8, 0x23, 0x00, 0x21, 0xb9, 0x40,
0xa9, 0x13, 0x54, 0xf4, 0xce, 0x51, 0x67, 0xb4, 0x79, 0x72, 0x30, 0x76, 0x78, 0x8c, 0x4b, 0x3c,
0xc6, 0x67, 0x16, 0x8f, 0x70, 0xc1, 0x95, 0x04, 0xb0, 0x15, 0xa3, 0xc0, 0x2c, 0xc6, 0x2c, 0x32,
0xa1, 0xde, 0x51, 0x6f, 0x34, 0x08, 0x2b, 0x3a, 0xe2, 0x43, 0xbf, 0xc4, 0x8e, 0x6e, 0xd8, 0x6d,
0xe7, 0x32, 0xa1, 0xb0, 0x71, 0x85, 0x52, 0x25, 0x3c, 0xa3, 0x7d, 0x6b, 0x2a, 0x45, 0xf2, 0x1e,
0xdc, 0x65, 0x51, 0x84, 0x42, 0x9f, 0x61, 0x24, 0x51, 0x2b, 0x3a, 0xb0, 0xe8, 0x54, 0x95, 0xe4,
0x14, 0x0e, 0x58, 0x1c, 0x27, 0x3a, 0xe1, 0x19, 0x4b, 0x9d, 0xf2, 0xdb, 0x5c, 0x8b, 0x5c, 0x2b,
0x0a, 0xf6, 0x28, 0xcb, 0xcc, 0x66, 0x67, 0x96, 0x26, 0x4c, 0xa1, 0xa2, 0x9b, 0xd6, 0xb3, 0x14,
0xc9, 0x08, 0xb6, 0xdd, 0x26, 0x25, 0xea, 0x8a, 0x6e, 0xd9, 0xbd, 0xeb, 0xea, 0x80, 0xc1, 0x5e,
0xb5, 0x3a, 0x45, 0x59, 0x77, 0xa0, 0x97, 0xcb, 0xac, 0xa8, 0x8f, 0x59, 0xd6, 0x00, 0xee, 0xae,
0x0c, 0x70, 0xf0, 0xd7, 0x00, 0x0e, 0x42, 0x9c, 0x24, 0x4a, 0xa3, 0xac, 0xb3, 0xa0, 0xac, 0x7a,
0xa7, 0xa5, 0xea, 0xdd, 0xd6, 0xaa, 0xf7, 0x2a, 0x55, 0xdf, 0x07, 0x2f, 0xca, 0x95, 0xe6, 0x53,
0xcb, 0x86, 0x7e, 0x58, 0x48, 0xe4, 0x18, 0x3c, 0x7e, 0xfe, 0x1b, 0x46, 0xfa, 0x26, 0x26, 0x14,
0x6e, 0x06, 0x4b, 0x63, 0x32, 0x11, 0x9e, 0xcd, 0x54, 0x8a, 0x0d, 0x7e, 0x6c, 0xdc, 0xc0, 0x8f,
0x7e, 0x8d, 0x1f, 0x02, 0xf6, 0x0a, 0x30, 0x66, 0x4f, 0x16, 0xf3, 0x0c, 0x8e, 0x7a, 0xa3, 0xcd,
0x93, 0x4f, 0xc7, 0xf3, 0xd6, 0x1e, 0x2f, 0x01, 0x69, 0xfc, 0xa2, 0x25, 0xfc, 0x69, 0xa6, 0xe5,
0x2c, 0x6c, 0xcd, 0x4c, 0x1e, 0xc0, 0x6e, 0x8c, 0x29, 0x6a, 0xfc, 0x12, 0x2f, 0xb8, 0x69, 0x55,
0x91, 0xb2, 0x08, 0x29, 0xd8, 0x7b, 0xb5, 0x99, 0x16, 0x39, 0xbc, 0xd9, 0xe0, 0x70, 0x32, 0xc9,
0xb8, 0xc4, 0xc7, 0x2f, 0x59, 0x36, 0xb1, 0x3c, 0x32, 0xd7, 0xaf, 0x2a, 0x9b, 0x4c, 0xbf, 0x7b,
0x4b, 0xa6, 0x0f, 0x57, 0x66, 0xfa, 0x76, 0x95, 0xe9, 0x3e, 0xf4, 0x93, 0xa9, 0x19, 0x34, 0xcf,
0x62, 0xba, 0xe3, 0x90, 0x2f, 0x65, 0xf2, 0x13, 0x0c, 0x1d, 0x1d, 0xbe, 0x4f, 0xa6, 0xc8, 0xcd,
0x36, 0x6f, 0x58, 0x32, 0x3c, 0x5c, 0x01, 0xf3, 0xc7, 0x95, 0xc0, 0xb0, 0x96, 0x88, 0x7c, 0x0e,
0x7e, 0x0b, 0x8e, 0x4f, 0xf0, 0x22, 0xc9, 0x30, 0xa6, 0xc4, 0xde, 0xfe, 0x1a, 0x0f, 0xf2, 0x11,
0xdc, 0x53, 0xc5, 0x40, 0x7d, 0xc1, 0xa4, 0x4e, 0x58, 0xfa, 0x03, 0x4b, 0x73, 0x54, 0x74, 0xd7,
0x86, 0xb6, 0x1b, 0x0d, 0xdb, 0x25, 0x4e, 0xb9, 0x46, 0xba, 0xe7, 0xd8, 0xee, 0xa4, 0xb6, 0x76,
0xbf, 0xd7, 0xda, 0xee, 0xfe, 0x07, 0xb0, 0xd7, 0xc6, 0x26, 0xd3, 0x73, 0xb9, 0xcc, 0x14, 0xed,
0x58, 0x74, 0xed, 0xda, 0xff, 0x11, 0x86, 0x55, 0x14, 0x6c, 0xb7, 0x49, 0x64, 0xba, 0xec, 0xd7,
0x42, 0x32, 0xfa, 0x5c, 0xc4, 0x46, 0xef, 0x7a, 0xb6, 0x90, 0x8c, 0xde, 0x61, 0x50, 0x76, 0xad,
0x93, 0xfc, 0xdf, 0x3b, 0x70, 0x7f, 0x29, 0xa9, 0xcd, 0xe8, 0xb9, 0xc4, 0x59, 0x39, 0x7a, 0x2e,
0x71, 0x46, 0x9e, 0xc3, 0x9d, 0x2b, 0x83, 0x40, 0x31, 0x75, 0x1e, 0xbd, 0x66, 0xcf, 0x84, 0x2e,
0xcb, 0x27, 0xdd, 0xd3, 0x4e, 0xf0, 0x4f, 0x0f, 0x68, 0x33, 0x76, 0xe9, 0xf0, 0x73, 0xaf, 0x55,
0x77, 0xfe, 0x5a, 0xfd, 0x37, 0x5f, 0x7a, 0xab, 0xcd, 0x97, 0x7d, 0xf0, 0x94, 0x66, 0xe7, 0x29,
0x96, 0x83, 0xca, 0x49, 0x86, 0xd9, 0x6e, 0x65, 0xde, 0x2c, 0xcb, 0xec, 0x42, 0x24, 0xaf, 0x96,
0xcc, 0x0d, 0xcf, 0xce, 0x8d, 0xcf, 0xae, 0xc5, 0xc0, 0xdd, 0xe3, 0xb6, 0x83, 0xe3, 0x56, 0xec,
0xf8, 0xe3, 0x96, 0x35, 0xfc, 0xa6, 0x5a, 0xc3, 0xd3, 0xd7, 0x3d, 0xff, 0x62, 0x11, 0x11, 0x0e,
0xeb, 0xb1, 0xc5, 0xc4, 0x28, 0xdf, 0x97, 0x66, 0x25, 0x1f, 0xc2, 0x06, 0x2f, 0x86, 0xce, 0x0d,
0x6f, 0x58, 0xe9, 0x77, 0xf2, 0xe7, 0x3a, 0x6c, 0x97, 0xf9, 0x9f, 0xf3, 0x2c, 0xd1, 0x5c, 0x92,
0x9f, 0x61, 0xbb, 0xf6, 0x23, 0x22, 0xef, 0x2c, 0x5c, 0xa9, 0xfd, 0x5f, 0xe5, 0x07, 0xd7, 0xb9,
0xb8, 0x4b, 0x07, 0x6b, 0xe4, 0x0b, 0xf0, 0x9e, 0x65, 0x57, 0xfc, 0x12, 0x09, 0x5d, 0xf0, 0x77,
0xaa, 0x32, 0xd3, 0xfd, 0x16, 0xcb, 0x3c, 0xc1, 0xd7, 0xb0, 0x75, 0xa6, 0x25, 0xb2, 0xe9, 0xff,
0x4a, 0xf3, 0xa0, 0x43, 0xbe, 0x83, 0xad, 0xc5, 0xdf, 0x01, 0x39, 0xac, 0x54, 0xad, 0xf1, 0xa9,
0xf3, 0xdf, 0x5e, 0x6a, 0x9f, 0x9f, 0xed, 0x17, 0xd8, 0xa9, 0xd7, 0x8c, 0x04, 0x37, 0x37, 0xb4,
0xff, 0xee, 0x0a, 0x84, 0x09, 0xd6, 0xc8, 0xaf, 0xcd, 0xbf, 0x46, 0xf9, 0x88, 0xbc, 0x7f, 0x4d,
0x86, 0x2a, 0x6d, 0xfc, 0xfd, 0x06, 0x27, 0x9e, 0x9a, 0x5f, 0x76, 0xb0, 0x76, 0xee, 0x59, 0xcd,
0x87, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x70, 0x3e, 0x80, 0x35, 0xa2, 0x0b, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View file

@ -80,11 +80,13 @@ message ConfigureRequest {
map<string, string> variables = 1; // a map of configuration keys to values.
google.protobuf.Struct args = 2; // the input properties for the provider. Only filled in for newer providers.
bool acceptSecrets = 3; // when true, operations should return secrets as strongly typed.
bool acceptResources = 4; // when true, operations should return resources as strongly typed values to the provider.
}
message ConfigureResponse {
bool acceptSecrets = 1; // when true, the engine should pass secrets as strongly typed values to the provider.
bool supportsPreview = 2; // when true, the engine should invoke create and update with preview=true during previews.
bool acceptResources = 3; // when true, the engine should pass resources as strongly typed values to the provider.
}
// ConfigureErrorMissingKeys is sent as a Detail on an error returned from `ResourceProvider.Configure`.
@ -102,6 +104,7 @@ message InvokeRequest {
google.protobuf.Struct args = 2; // the arguments for the function invocation.
string provider = 3; // an optional reference to the provider to use for this invoke.
string version = 4; // the version of the provider to use when servicing this request.
bool acceptResources = 5; // when true operations should return resource references as strongly typed.
}
message InvokeResponse {

View file

@ -59,6 +59,7 @@ message ReadResourceRequest {
bool acceptSecrets = 9; // when true operations should return secrets as strongly typed.
repeated string additionalSecretOutputs = 10; // a list of output properties that should also be treated as secret, in addition to ones we detect.
repeated string aliases = 11; // a list of additional URNs that shoud be considered the same.
bool acceptResources = 12; // when true operations should return resource references as strongly typed.
}
// ReadResourceResponse contains the result of reading a resource's state.
@ -100,6 +101,7 @@ message RegisterResourceRequest {
bool deleteBeforeReplaceDefined = 18; // true if the deleteBeforeReplace property should be treated as defined even if it is false.
bool supportsPartialValues = 19; // true if the request is from an SDK that supports partially-known properties during preview.
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.
}
// RegisterResourceResponse is returned by the engine after a resource has finished being initialized. It includes the

View file

@ -48,3 +48,7 @@ from .invoke import (
from ._json import (
to_json,
)
from .rpc import (
register_resource_package,
)

View file

@ -27,12 +27,6 @@ within the functions themselves.
from typing import Any, Optional
# We override this global in test/test_next_serialize.py to stub the CustomResource type.
# TODO: Rework the test to remove the need for this global. https://github.com/pulumi/pulumi/issues/5000
_custom_resource_type: Optional[type] = None
"""The type of CustomResource."""
def is_asset(obj: Any) -> bool:
"""
Returns true if the given type is an Asset, false otherwise.
@ -49,12 +43,20 @@ def is_archive(obj: Any) -> bool:
return isinstance(obj, Archive)
def is_resource(obj: Any) -> bool:
"""
Returns true if the given type is a Resource, false otherwise.
"""
from .. import Resource # pylint: disable=import-outside-toplevel
return isinstance(obj, Resource)
def is_custom_resource(obj: Any) -> bool:
"""
Returns true if the given type is a CustomResource, false otherwise.
"""
from .. import CustomResource # pylint: disable=import-outside-toplevel
return isinstance(obj, _custom_resource_type or CustomResource)
return isinstance(obj, CustomResource)
def is_custom_timeouts(obj: Any) -> bool:

File diff suppressed because one or more lines are too long

View file

@ -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\"\xfc\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\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\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xaf\x06\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\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\"\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\x89\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\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\"\xc8\x06\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\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\"\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\x89\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\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,])
@ -174,6 +174,13 @@ _READRESOURCEREQUEST = _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='acceptResources', full_name='pulumirpc.ReadResourceRequest.acceptResources', index=11,
number=12, 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=[
],
@ -187,7 +194,7 @@ _READRESOURCEREQUEST = _descriptor.Descriptor(
oneofs=[
],
serialized_start=190,
serialized_end=442,
serialized_end=467,
)
@ -224,8 +231,8 @@ _READRESOURCERESPONSE = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=444,
serialized_end=524,
serialized_start=469,
serialized_end=549,
)
@ -255,8 +262,8 @@ _REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIES = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1122,
serialized_end=1158,
serialized_start=1172,
serialized_end=1208,
)
_REGISTERRESOURCEREQUEST_CUSTOMTIMEOUTS = _descriptor.Descriptor(
@ -299,8 +306,8 @@ _REGISTERRESOURCEREQUEST_CUSTOMTIMEOUTS = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1160,
serialized_end=1224,
serialized_start=1210,
serialized_end=1274,
)
_REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
@ -336,8 +343,8 @@ _REGISTERRESOURCEREQUEST_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1226,
serialized_end=1342,
serialized_start=1276,
serialized_end=1392,
)
_REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
@ -487,6 +494,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='acceptResources', full_name='pulumirpc.RegisterResourceRequest.acceptResources', index=20,
number=21, 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=[
],
@ -499,8 +513,8 @@ _REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=527,
serialized_end=1342,
serialized_start=552,
serialized_end=1392,
)
@ -530,8 +544,8 @@ _REGISTERRESOURCERESPONSE_PROPERTYDEPENDENCIES = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1122,
serialized_end=1158,
serialized_start=1172,
serialized_end=1208,
)
_REGISTERRESOURCERESPONSE_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
@ -567,8 +581,8 @@ _REGISTERRESOURCERESPONSE_PROPERTYDEPENDENCIESENTRY = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1603,
serialized_end=1720,
serialized_start=1653,
serialized_end=1770,
)
_REGISTERRESOURCERESPONSE = _descriptor.Descriptor(
@ -632,8 +646,8 @@ _REGISTERRESOURCERESPONSE = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1345,
serialized_end=1720,
serialized_start=1395,
serialized_end=1770,
)
@ -670,8 +684,8 @@ _REGISTERRESOURCEOUTPUTSREQUEST = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=1722,
serialized_end=1809,
serialized_start=1772,
serialized_end=1859,
)
_READRESOURCEREQUEST.fields_by_name['properties'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT
@ -797,8 +811,8 @@ _RESOURCEMONITOR = _descriptor.ServiceDescriptor(
file=DESCRIPTOR,
index=0,
serialized_options=None,
serialized_start=1812,
serialized_end=2333,
serialized_start=1862,
serialized_end=2383,
methods=[
_descriptor.MethodDescriptor(
name='SupportsFeature',

View file

@ -48,6 +48,9 @@ _special_archive_sig = "0def7320c3a5731c473e5ecbe6d01bc7"
_special_secret_sig = "1b47061264138c4ac30d75fd1eb44270"
"""special_secret_sig is a randomly assigned hash used to identify secrets in maps. See pkg/resource/properties.go"""
_special_resource_sig = "5cf8f73096256a8f31e491e813e4eb8e"
"""special_resource_sig is a randomly assigned hash used to identify resources in maps. See pkg/resource/properties.go"""
_INT_OR_FLOAT = six.integer_types + (float,)
def isLegalProtobufValue(value: Any) -> bool:
@ -104,10 +107,25 @@ async def serialize_property(value: 'Input[Any]',
if known_types.is_unknown(value):
return UNKNOWN
if known_types.is_custom_resource(value):
resource = cast('CustomResource', value)
if known_types.is_resource(value):
resource = cast('Resource', value)
deps.append(resource)
return await serialize_property(resource.id, deps, input_transformer)
is_custom = known_types.is_custom_resource(value)
resource_id = cast('CustomResource', value).id if is_custom else None
# If we're retaining resources, serialize the resource as a reference.
if await settings.monitor_supports_resource_references():
res = {
_special_sig_key: _special_resource_sig,
"urn": await serialize_property(resource.urn, deps, input_transformer)
}
if is_custom:
res["id"] = await serialize_property(resource_id, deps, input_transformer)
return res
# Otherwise, serialize the resource as either its ID (for custom resources) or its URN (for component resources)
return await serialize_property(resource_id if is_custom else resource.urn, deps, input_transformer)
if known_types.is_asset(value):
# Serializing an asset requires the use of a magical signature key, since otherwise it would
@ -246,6 +264,28 @@ def deserialize_properties(props_struct: struct_pb2.Struct, keep_unknowns: Optio
raise AssertionError("Invalid archive encountered when unmarshalling resource property")
if props_struct[_special_sig_key] == _special_secret_sig:
return wrap_rpc_secret(deserialize_property(props_struct["value"]))
if props_struct[_special_sig_key] == _special_resource_sig:
urn = props_struct["urn"]
version = props_struct["version"]
urn_parts = urn.split("::")
qualified_type = urn_parts[2]
typ = qualified_type.split("$")[-1]
typ_parts = typ.split(":")
pkg_name = typ_parts[0]
mod_name = typ_parts[1] if len(typ_parts) > 1 else ""
typ_name = typ_parts[2] if len(typ_parts) > 2 else ""
is_provider = pkg_name == "pulumi" and mod_name == "providers"
if is_provider:
pkg_name = typ_name
resource_package = RESOURCE_PACKAGES.get(package_key(pkg_name, version))
if resource_package is None:
raise Exception(f"Unable to deserialize resource URN {urn}, no resource package is registered for type {typ}.")
urn_name = urn_parts[3]
resource = resource_package.construct(urn_name, typ, {}, {"urn": urn}) if not is_provider \
else resource_package.construct_provider(urn_name, typ, {}, {"urn": urn})
return cast('Resource', resource)
raise AssertionError("Unrecognized signature when unmarshalling resource property")
@ -538,6 +578,10 @@ async def resolve_outputs(res: 'Resource',
# the user.
all_properties[translated_key] = translate_output_properties(deserialize_property(value), res.translate_output_property, types.get(key))
await resolve_properties(resolvers, all_properties, deps)
async def resolve_properties(resolvers: Dict[str, Resolver], all_properties: Dict[str, Any], deps: Mapping[str, Set['Resource']]):
for key, value in all_properties.items():
# Skip "id" and "urn", since we handle those specially.
if key in ["id", "urn"]:
@ -598,3 +642,15 @@ def resolve_outputs_due_to_exception(resolvers: Dict[str, Resolver], exn: Except
for key, resolve in resolvers.items():
log.debug(f"sending exception to resolver for {key}")
resolve(None, False, False, None, exn)
RESOURCE_PACKAGES: Dict[str, Any] = dict()
def package_key(typ: str, version: str) -> str:
return f"{typ}@{version}"
def register_resource_package(typ: str, version: str, package):
key = package_key(typ, version)
existing = RESOURCE_PACKAGES.get(key, None)
if existing is not None:
raise ValueError(f"Cannot re-register package {key}. Previous registration was {existing}, new registration was {package}.")
RESOURCE_PACKAGES[key] = package

View file

@ -40,6 +40,7 @@ class Settings:
dry_run: Optional[bool]
test_mode_enabled: Optional[bool]
legacy_apply_enabled: Optional[bool]
feature_support: dict
"""
A bag of properties for configuring the Pulumi Python language runtime.
@ -60,6 +61,7 @@ class Settings:
self.dry_run = dry_run
self.test_mode_enabled = test_mode_enabled
self.legacy_apply_enabled = legacy_apply_enabled
self.feature_support = {}
if self.test_mode_enabled is None:
self.test_mode_enabled = os.getenv("PULUMI_TEST_MODE", "false") == "true"
@ -203,25 +205,35 @@ def set_root_resource(root: 'Resource'):
ROOT = root
async def monitor_supports_feature(feature: str) -> bool:
if feature not in SETTINGS.feature_support:
monitor = SETTINGS.monitor
if not monitor:
return False
req = resource_pb2.SupportsFeatureRequest(id="secrets")
def do_rpc_call():
try:
resp = monitor.SupportsFeature(req)
return resp.hasSupport
except grpc.RpcError as exn:
# See the comment on invoke for the justification for disabling
# this warning
# pylint: disable=no-member
if exn.code() == grpc.StatusCode.UNAVAILABLE:
sys.exit(0)
if exn.code() == grpc.StatusCode.UNIMPLEMENTED:
return False
details = exn.details()
raise Exception(details)
result = await asyncio.get_event_loop().run_in_executor(None, do_rpc_call)
SETTINGS.feature_support[feature] = result
return SETTINGS.feature_support[feature]
async def monitor_supports_secrets() -> bool:
monitor = SETTINGS.monitor
if not monitor:
return False
return await monitor_supports_feature("secrets")
req = resource_pb2.SupportsFeatureRequest(id="secrets")
def do_rpc_call():
try:
resp = monitor.SupportsFeature(req)
return resp.hasSupport
except grpc.RpcError as exn:
# See the comment on invoke for the justification for disabling
# this warning
# pylint: disable=no-member
if exn.code() == grpc.StatusCode.UNAVAILABLE:
sys.exit(0)
if exn.code() == grpc.StatusCode.UNIMPLEMENTED:
return False
details = exn.details()
raise Exception(details)
return await asyncio.get_event_loop().run_in_executor(None, do_rpc_call)
async def monitor_supports_resource_references() -> bool:
return await monitor_supports_feature("resourceReferences")

View file

@ -16,7 +16,7 @@ import unittest
from typing import Any, Dict, List, Mapping, Optional, Sequence
from google.protobuf import struct_pb2
from pulumi.resource import CustomResource
from pulumi.resource import ComponentResource, CustomResource
from pulumi.runtime import rpc, known_types, settings
from pulumi import Input, Output, UNKNOWN, input_type
from pulumi.asset import (
@ -30,14 +30,14 @@ from pulumi.asset import (
import pulumi
class FakeCustomResource:
"""
Fake CustomResource class that duck-types to the real CustomResource.
This class is substituted for the real CustomResource for the below test.
"""
def __init__(self, id):
self.id = id
class TestCustomResource(CustomResource):
def __init__(self, urn):
self.__dict__["urn"] = Output.from_input(urn)
self.__dict__["id"] = Output.from_input("id")
class TestComponentResource(ComponentResource):
def __init__(self, urn):
self.__dict__["urn"] = Output.from_input(urn)
def async_test(coro):
def wrapper(*args, **kwargs):
@ -48,12 +48,6 @@ def async_test(coro):
class NextSerializationTests(unittest.TestCase):
def setUp(self):
known_types._custom_resource_type = FakeCustomResource
def tearDown(self):
known_types._custom_resource_type = CustomResource
@async_test
async def test_list(self):
test_list = [1, 2, 3]
@ -86,11 +80,40 @@ class NextSerializationTests(unittest.TestCase):
@async_test
async def test_custom_resource(self):
res = FakeCustomResource("some-id")
fake_urn = "urn:pulumi:mystack::myproject::my:mod:Fake::fake"
res = TestCustomResource(fake_urn)
settings.SETTINGS.feature_support["resourceReferences"] = False
deps = []
prop = await rpc.serialize_property(res, deps)
self.assertListEqual([res], deps)
self.assertEqual("some-id", prop)
self.assertEqual("id", prop)
settings.SETTINGS.feature_support["resourceReferences"] = True
deps = []
prop = await rpc.serialize_property(res, deps)
self.assertListEqual([res], deps)
self.assertEqual(rpc._special_resource_sig, prop[rpc._special_sig_key])
self.assertEqual(fake_urn, prop["urn"])
self.assertEqual("id", prop["id"])
@async_test
async def test_component_resource(self):
fake_urn = "urn:pulumi:mystack::myproject::my:mod:Fake::fake"
res = TestComponentResource(fake_urn)
settings.SETTINGS.feature_support["resourceReferences"] = False
deps = []
prop = await rpc.serialize_property(res, deps)
self.assertListEqual([res], deps)
self.assertEqual(fake_urn, prop)
settings.SETTINGS.feature_support["resourceReferences"] = True
deps = []
prop = await rpc.serialize_property(res, deps)
self.assertListEqual([res], deps)
self.assertEqual(rpc._special_resource_sig, prop[rpc._special_sig_key])
self.assertEqual(fake_urn, prop["urn"])
@async_test
async def test_string_asset(self):
@ -115,8 +138,8 @@ class NextSerializationTests(unittest.TestCase):
@async_test
async def test_output(self):
existing = FakeCustomResource("existing-dependency")
res = FakeCustomResource("some-dependency")
existing = TestCustomResource("existing-dependency")
res = TestCustomResource("some-dependency")
fut = asyncio.Future()
fut.set_result(42)
known_fut = asyncio.Future()
@ -152,7 +175,7 @@ class NextSerializationTests(unittest.TestCase):
@async_test
async def test_output_all(self):
res = FakeCustomResource("some-resource")
res = TestCustomResource("some-resource")
fut = asyncio.Future()
fut.set_result(42)
known_fut = asyncio.Future()
@ -168,14 +191,14 @@ class NextSerializationTests(unittest.TestCase):
@async_test
async def test_output_all_composes_dependencies(self):
res = FakeCustomResource("some-resource")
res = TestCustomResource("some-resource")
fut = asyncio.Future()
fut.set_result(42)
known_fut = asyncio.Future()
known_fut.set_result(True)
out = Output({res}, fut, known_fut)
other = FakeCustomResource("some-other-resource")
other = TestCustomResource("some-other-resource")
other_fut = asyncio.Future()
other_fut.set_result(99)
other_known_fut = asyncio.Future()
@ -190,14 +213,14 @@ class NextSerializationTests(unittest.TestCase):
@async_test
async def test_output_all_known_if_all_are_known(self):
res = FakeCustomResource("some-resource")
res = TestCustomResource("some-resource")
fut = asyncio.Future()
fut.set_result(42)
known_fut = asyncio.Future()
known_fut.set_result(True)
out = Output({res}, fut, known_fut)
other = FakeCustomResource("some-other-resource")
other = TestCustomResource("some-other-resource")
other_fut = asyncio.Future()
other_fut.set_result(UNKNOWN) # <- not known
other_known_fut = asyncio.Future()
@ -216,7 +239,7 @@ class NextSerializationTests(unittest.TestCase):
@async_test
async def test_unknown_output(self):
res = FakeCustomResource("some-dependency")
res = TestCustomResource("some-dependency")
fut = asyncio.Future()
fut.set_result(None)
known_fut = asyncio.Future()

View file

@ -337,6 +337,14 @@ func getBaseOptions() integration.ProgramTestOptions {
}
}
func getPythonBaseOptions() integration.ProgramTestOptions {
return integration.ProgramTestOptions{
Dependencies: []string{
filepath.Join("..", "sdk", "python", "env", "src"),
},
}
}
func skipIfNotNode610(t *testing.T) {
nodeVer, err := getNodeVersion()
if err != nil && nodeVer.Major == 6 && nodeVer.Minor == 10 {

View file

@ -3,7 +3,6 @@
"align": [
true,
"parameters",
"arguments",
"statements"
],
"ban": false,