Skip to content

Commit e2a016a

Browse files
committed
Support excluding resource references from deps
Exclude resource references from "property dependencies" for remote components (i.e. MLCs) and for Calls. This way, component providers creating outputs for component inputs based on property dependencies won't create outputs for properties that only contain resource references.
1 parent 654f993 commit e2a016a

File tree

5 files changed

+123
-35
lines changed

5 files changed

+123
-35
lines changed

sdk/Pulumi.Tests/Serialization/ResourceRefPropertyTests.cs

+36
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,42 @@ public async Task SerializeCustomResourceDownlevel(bool isPreview)
151151
Assert.Equal(id, v);
152152
}
153153

154+
[Theory]
155+
[InlineData(true, true)]
156+
[InlineData(true, false)]
157+
[InlineData(false, true)]
158+
[InlineData(false, false)]
159+
public async Task SerializeCustomResourceDependencies(bool isPreview, bool excludeFromDependencies)
160+
{
161+
var resources = await RunAsync<MyStack>(isPreview);
162+
var res = resources.OfType<MyCustomResource>().Single();
163+
164+
async Task Test<T>(T value)
165+
{
166+
var serializer = new Serializer(excessiveDebugOutput: false);
167+
Serializer.CreateValue(await serializer.SerializeAsync("", value, true,
168+
excludeResourceReferencesFromDependencies: excludeFromDependencies));
169+
170+
if (excludeFromDependencies)
171+
{
172+
Assert.Empty(serializer.DependentResources);
173+
}
174+
else
175+
{
176+
Assert.Equal(new HashSet<Resource> { res }, serializer.DependentResources);
177+
}
178+
}
179+
180+
// Single resource.
181+
await Test(res);
182+
183+
// Resource in list.
184+
await Test(new List<Resource> { res });
185+
186+
// Resource in dictionary.
187+
await Test(new Dictionary<string, Resource> { { "resource", res } });
188+
}
189+
154190
public class DeserializeCustomResourceStack : Stack
155191
{
156192
[Output("values")]

sdk/Pulumi/Deployment/Deployment_Call.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ private async Task<OutputData<T>> CallAsync<T>(
8888
$"call:{token}",
8989
argsDict, _ => true,
9090
keepResources: true,
91-
keepOutputValues: await MonitorSupportsOutputValues().ConfigureAwait(false)).ConfigureAwait(false);
91+
keepOutputValues: await MonitorSupportsOutputValues().ConfigureAwait(false),
92+
excludeResourceReferencesFromDependencies: true).ConfigureAwait(false);
9293
Log.Debug($"Call RPC prepared: token={token}" +
9394
(_excessiveDebugOutput ? $", obj={serialized}" : ""));
9495

sdk/Pulumi/Deployment/Deployment_Prepare.cs

+10-2
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,20 @@ private async Task<PrepareResult> PrepareResourceAsync(
3737
// the Resources pointed to by any Dependency objects we encounter, adding them to 'propertyDependencies'.
3838
LogExcessive($"Serializing properties: t={type}, name={name}, custom={custom}, remote={remote}");
3939
var dictionary = await args.ToDictionaryAsync().ConfigureAwait(false);
40+
var keepResources = await MonitorSupportsResourceReferences().ConfigureAwait(false);
41+
var keepOutputValues = remote && await MonitorSupportsOutputValues().ConfigureAwait(false);
42+
// When remote is true (and the monitor supports resource references), exclude resource references
43+
// from `propertyToDirectDependencies`. This way, component providers creating outputs for component
44+
// inputs based on "propertyDependencies" won't create outputs for properties that only contain
45+
// resource references.
46+
var excludeResourceReferencesFromDependencies = remote && keepResources;
4047
var (serializedProps, propertyToDirectDependencies) =
4148
await SerializeResourcePropertiesAsync(
4249
label,
4350
dictionary,
44-
await this.MonitorSupportsResourceReferences().ConfigureAwait(false),
45-
keepOutputValues: remote && await MonitorSupportsOutputValues().ConfigureAwait(false)).ConfigureAwait(false);
51+
keepResources,
52+
keepOutputValues,
53+
excludeResourceReferencesFromDependencies).ConfigureAwait(false);
4654
LogExcessive($"Serialized properties: t={type}, name={name}, custom={custom}, remote={remote}");
4755

4856
// Wait for the parent to complete.

sdk/Pulumi/Deployment/Deployment_Serialization.cs

+20-8
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,22 @@ public partial class Deployment
2020
/// to registerResource.
2121
/// </summary>
2222
private static Task<SerializationResult> SerializeResourcePropertiesAsync(
23-
string label, IDictionary<string, object?> args, bool keepResources, bool keepOutputValues)
23+
string label, IDictionary<string, object?> args, bool keepResources, bool keepOutputValues,
24+
bool excludeResourceReferencesFromDependencies = false)
2425
{
2526
return SerializeFilteredPropertiesAsync(
2627
label, args,
2728
key => key != Constants.IdPropertyName && key != Constants.UrnPropertyName,
28-
keepResources, keepOutputValues: keepOutputValues);
29+
keepResources, keepOutputValues, excludeResourceReferencesFromDependencies);
2930
}
3031

3132
private static async Task<Struct> SerializeAllPropertiesAsync(
32-
string label, IDictionary<string, object?> args, bool keepResources, bool keepOutputValues = false)
33+
string label, IDictionary<string, object?> args, bool keepResources, bool keepOutputValues = false,
34+
bool excludeResourceReferencesFromDependencies = false)
3335
{
3436
var result = await SerializeFilteredPropertiesAsync(
3537
label, args, _ => true,
36-
keepResources, keepOutputValues).ConfigureAwait(false);
38+
keepResources, keepOutputValues, excludeResourceReferencesFromDependencies).ConfigureAwait(false);
3739
return result.Serialized;
3840
}
3941

@@ -52,10 +54,18 @@ private static async Task<Struct> SerializeAllPropertiesAsync(
5254
/// responsibility to ensure that the monitor supports the OutputValues
5355
/// feature.
5456
/// </param>
57+
/// <param name="excludeResourceReferencesFromDependencies">
58+
/// Specifies if we should exclude resource references from the resulting
59+
/// <see cref="SerializationResult.PropertyToDependentResources"/>. This is useful for remote
60+
/// components (i.e. multi-lang components, or MLCs) where we want property dependencies to be
61+
/// empty for a property that only contains resource references.
62+
/// </param>
5563
private static async Task<SerializationResult> SerializeFilteredPropertiesAsync(
56-
string label, IDictionary<string, object?> args, Predicate<string> acceptKey, bool keepResources, bool keepOutputValues)
64+
string label, IDictionary<string, object?> args, Predicate<string> acceptKey, bool keepResources, bool keepOutputValues,
65+
bool excludeResourceReferencesFromDependencies = false)
5766
{
58-
var result = await SerializeFilteredPropertiesRawAsync(label, args, acceptKey, keepResources, keepOutputValues);
67+
var result = await SerializeFilteredPropertiesRawAsync(label, args, acceptKey, keepResources, keepOutputValues,
68+
excludeResourceReferencesFromDependencies);
5969
return result.ToSerializationResult();
6070
}
6171

@@ -64,7 +74,8 @@ private static async Task<SerializationResult> SerializeFilteredPropertiesAsync(
6474
/// last step of encoding the value into a Protobuf form.
6575
/// </summary>
6676
private static async Task<RawSerializationResult> SerializeFilteredPropertiesRawAsync(
67-
string label, IDictionary<string, object?> args, Predicate<string> acceptKey, bool keepResources, bool keepOutputValues)
77+
string label, IDictionary<string, object?> args, Predicate<string> acceptKey, bool keepResources, bool keepOutputValues,
78+
bool excludeResourceReferencesFromDependencies = false)
6879
{
6980
var propertyToDependentResources = ImmutableDictionary.CreateBuilder<string, HashSet<Resource>>();
7081
var result = ImmutableDictionary.CreateBuilder<string, object>();
@@ -75,7 +86,8 @@ private static async Task<RawSerializationResult> SerializeFilteredPropertiesRaw
7586
{
7687
// We treat properties with null values as if they do not exist.
7788
var serializer = new Serializer(_excessiveDebugOutput);
78-
var v = await serializer.SerializeAsync($"{label}.{key}", val, keepResources, keepOutputValues).ConfigureAwait(false);
89+
var v = await serializer.SerializeAsync($"{label}.{key}", val, keepResources, keepOutputValues,
90+
excludeResourceReferencesFromDependencies).ConfigureAwait(false);
7991
if (v != null)
8092
{
8193
result[key] = v;

0 commit comments

Comments
 (0)