-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[sdk/dotnet] Input<T>
eagerly converts values to Output<T>
leading to undesirable preview diffs
#22
Comments
Shouldn't preview diffs print Output's that are known? |
The problem is the way Internally
So when adding an One relatively simple solution is to change
Then, for the most part, we can keep the added values as-is by storing them in |
👍 from the consistency across SDK POV, the other SDKs have the capability to discriminate Input into either T, Promise or Output, so .NET SDK should also have that in the programming model. Fraser raised that perhaps .NET SDK can discriminate Output to find out if it's prompt known T, potentially eventually removing T. It sounds like something that should not block this work, but if we go that way I'd like to figure out how that works with other SDKs, how does imaginary "meta-SDK" code translate into .NET SDK under that API. |
So still 👍 on the main idea listed. Now the subtle implementation point on Lists (I think map follows similarly) - to follow up on the design discussion today. I made a point earlier about Tuple/Map2 interface on Input as a potential implementation path to updated InputList, but it was not very clear. I went ahead and wrote some code that clarified the issue for me at least: https://gist.github.com/t0yv0/84e4f976e190aabbd1ccd666b89d73bd In a world where Input discriminates between The code above works as expected, however there is a problem if
So in addition to changing internals of InputList, to carry this through previews, we either need to change the base type of InputList which is breaking or else we change the way reflective machinery considers InputList values when it encounters them; either way it seems potentially a lot more invasive change than a simple change to InputList internals. If I am wrong in this prediction you Justin can work out a solution that is a purely internal change to InputList I would be very curious to see how that works. This may have been exactly the point @Frassle was making. They are reasoning about this much faster than I am. But I do not want to assume. |
@t0yv0 Yeh these types are a bit confusing and hard to reason about, my first thinking was that either this is really just A) Also all of this is still fine in an SDK where |
I'm still struggling to understand how the PR will solve this example at the top, and I'm running out of time to try it out, guess need to wait for the tests: var bucket = new Bucket("bucket", new BucketArgs {
Tags = {
{ "hello", "world" },
{ "hi", "there" },
{ "foo", randString.Id },
}
}); What's the type of Tags? Looking at def of BucketArgs.Tags I see: /// <summary>
/// A mapping of tags to assign to the bucket.
/// </summary>
public InputMap<string> Tags
{
get => _tags ?? (_tags = new InputMap<string>());
set => _tags = value;
} And this header remains: public sealed class InputMap<V> : Input<ImmutableDictionary<string, V>>, IEnumerable, IAsyncEnumerable<Input<KeyValuePair<string, V>>> So then, if our framework casts it to If our framework however casts it to
|
Love the discussion above and agree with the point on it trying to be
I definitely intend to add a bunch more tests, but the draft does include an output value serialization test that indirectly demonstrates the fix (using a secret rather than unknown). new object[]
{
new InputMap<string> { { "foo", Output.CreateSecret("hello") } },
ImmutableDictionary<string, object>.Empty.Add("foo", CreateOutputValue("hello", isSecret: true))
}, Without the changes in the PR, the serialized value is: {
"4dabf18193072939515e22adb298388d": "d0e6a833031e9bbcd3f4e8bde6ca49a4",
"value": { "foo": "hello" },
"secret": true
} The expected serialized value (with the changes in the PR): {
"foo": {
"4dabf18193072939515e22adb298388d": "d0e6a833031e9bbcd3f4e8bde6ca49a4",
"value": "hello",
"secret": true
}
} The serializer isn't casting to The serializer currently does this: The implementation of The change in the PR changes the serializer to not use So the value that ends up being serialized will either be For the former, it'll then hit the non-generic For the latter, it'll hit the non-generic |
Hitting this issue while developing Pulumi Service Provider - really confusing behavior, forced to rewrite a map into an array of custom objects. Would be great to fix and avoid this. |
### Summary - Fixes: #447 (kinda) - The reason secret was failing to create is due to this c# specific bug - pulumi/pulumi-dotnet#22 - A secret among env vars made the whole object secret and it was skipped - Recent change #467 actually made the issue worse - it is creating the env vars, but NOT secret (Thankfully I never released after that PR! 😅 ) - This PR adds cascading logic to envVars and username values - they are the only ones that are optionally secret ### Testing - Manual test
In the .NET SDK,
Input<T>
(andInputList<T>
,InputMap<V>
,InputUnion<T0, T1>
, andInputJson
) eagerly stores the value ofT
as anOutput<T>
, which leads to undesirable preview diffs.https://github.com/pulumi/pulumi/blob/0a38bc295cfc5ae3c325dcece169da5a5e80fffc/sdk/dotnet/Pulumi/Core/Input.cs#L22-L31
For example, consider this program:
Expected preview diff:
Actual:
This also means that we have the same issue with programs that create multi-lang components, even with output values added in pulumi/pulumi#8316.
To address this, we need to fix
Input<T>
et. al. to not eagerly convert values toOutput<T>
. Instead, internally, it can keep a discriminated union of the plainT
andOutput<T>
and only convert toOutput<T>
when needed.The text was updated successfully, but these errors were encountered: