[dotnet/sdk] Add create unknown to output utilities (#7173)

* Add create unknown to output utilities

* Update changelog

* Tweaks based on review

Co-authored-by: Anton Tayanovskyy <anton@pulumi.com>
This commit is contained in:
Sean Fausett 2021-06-11 02:54:16 +12:00 committed by GitHub
parent 3530ba3205
commit c4e55a7107
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 15 deletions

View file

@ -1,5 +1,8 @@
### Improvements
- [dotnet/sdk] Add create unknown to output utilities.
[#7173](https://github.com/pulumi/pulumi/pull/7173)
- [dotnet] Fix Resharper code issues.
[#7178](https://github.com/pulumi/pulumi/pull/7178)

View file

@ -4,6 +4,7 @@ using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Pulumi.Serialization;
using Pulumi.Utilities;
using Xunit;
namespace Pulumi.Tests.Core
@ -350,6 +351,16 @@ namespace Pulumi.Tests.Core
Assert.False(notSecretData.IsSecret);
Assert.Equal(2, notSecretData.Value);
});
[Fact]
public Task CreateUnknownSkipsValueFactory()
=> RunInPreview(async () =>
{
var output = OutputUtilities.CreateUnknown(() => Task.FromResult("value"));
var data = await output.DataTask.ConfigureAwait(false);
Assert.False(data.IsKnown);
Assert.Null(data.Value);
});
}
public class NormalTests
@ -585,6 +596,16 @@ namespace Pulumi.Tests.Core
Assert.True(data.IsSecret);
Assert.Equal("inner", data.Value);
});
[Fact]
public Task CreateUnknownRunsValueFactory()
=> RunInNormal(async () =>
{
var output = OutputUtilities.CreateUnknown(() => Task.FromResult("value"));
var data = await output.DataTask.ConfigureAwait(false);
Assert.False(data.IsKnown);
Assert.Equal("value", data.Value);
});
}
}
}

View file

@ -1,6 +1,5 @@
// Copyright 2016-2019, Pulumi Corporation
using System.Collections.Immutable;
using System.Threading.Tasks;
using Google.Protobuf.WellKnownTypes;
using Pulumi.Serialization;
@ -24,10 +23,6 @@ namespace Pulumi.Tests.Serialization
}
};
protected Output<T> CreateUnknownOutput<T>(T value)
=> new Output<T>(Task.FromResult(new OutputData<T>(
ImmutableHashSet<Resource>.Empty, value, isKnown: false, isSecret: false)));
protected async Task<Value> SerializeToValueAsync(object? value, bool keepResources = true)
{
var serializer = new Serializer(excessiveDebugOutput: false);

View file

@ -51,7 +51,7 @@ namespace Pulumi.Tests.Serialization
[Fact]
public async Task ListWithUnknownElement()
{
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(new List<object> { CreateUnknownOutput(true) }));
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(new List<object> { Output<bool>.CreateUnknown(true) }));
AssertEx.SequenceEqual(ImmutableArray<bool>.Empty.Add(false), data.Value);
Assert.False(data.IsKnown);

View file

@ -191,6 +191,12 @@ namespace Pulumi
return new Output<T>(tcs.Task);
}
internal static Output<T> CreateUnknown(T value)
=> Unknown(value);
internal static Output<T> CreateUnknown(Func<Task<T>> valueFactory)
=> Unknown(default!).Apply(_ => valueFactory());
/// <summary>
/// <see cref="Output{T}.Apply{U}(Func{T, Output{U}})"/> for more details.
/// </summary>
@ -329,5 +335,10 @@ namespace Pulumi
(isKnown, isSecret) = OutputData.Combine(data, isKnown, isSecret);
}
}
internal static Output<T> Unknown(T value) => new Output<T>(UnknownHelperAsync(value));
private static Task<OutputData<T>> UnknownHelperAsync(T value)
=> Task.FromResult(new OutputData<T>(ImmutableHashSet<Resource>.Empty, value, isKnown: false, isSecret: false));
}
}

View file

@ -1,5 +1,6 @@
// Copyright 2016-2020, Pulumi Corporation
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
@ -8,9 +9,39 @@ namespace Pulumi.Utilities
/// <summary>
/// Allows extracting some internal insights about an instance of
/// <see cref="Output{T}"/>.
///
/// Danger: these utilities are intended for use in test and
/// debugging scenarios. In normal Pulumi programs, please
/// consider using `.Apply` instead to chain `Output{T}`
/// transformations without unpacking the underlying T. Doing
/// so preserves metadata such as resource dependencies that
/// is used by Pulumi engine to operate correctly. Using
/// `await output.GetValueAsync()` directly opens up a possibility
/// to introduce issues with lost metadata.
/// </summary>
public static class OutputUtilities
{
/// <summary>
/// Create an unknown with the given value.
/// Note: generally, this should never be used since an unknown never resolves during preview.
/// Bearing that in mind, this can be used in combination with await for
/// a program control flow to avoid deadlock situations.
/// </summary>
/// <param name="value">The value.</param>
public static Output<T> CreateUnknown<T>(T value)
=> Output<T>.CreateUnknown(value);
/// <summary>
/// Create an unknown with the given value factory.
/// Note: generally, this should never be used since an unknown never resolves during preview.
/// Bearing that in mind, this can be used in combination with await for
/// a program control flow to avoid deadlock situations.
/// In particular, the value factory will never be called during preview.
/// </summary>
/// <param name="valueFactory">The value factory.</param>
public static Output<T> CreateUnknown<T>(Func<Task<T>> valueFactory)
=> Output<T>.CreateUnknown(valueFactory);
/// <summary>
/// Retrieve the known status of the given output.
/// Note: generally, this should never be used in combination with await for
@ -25,15 +56,8 @@ namespace Pulumi.Utilities
/// <summary>
/// Retrieve the value of the given output.
///
/// Danger: this facility is intended for use in test and
/// debugging scenarios. In normal Pulumi programs, please
/// consider using `.Apply` instead to chain `Output[T]`
/// transformations without unpacking the underlying T. Doing
/// so preserves metadata such as resource dependencies that
/// is used by Pulumi engine to operate correctly. Using
/// `await o.GetValueAsync()` directly opens up a possibility
/// to introduce issues with lost metadata.
/// Note: generally, this should never be used in combination with await for
/// a program control flow to avoid deadlock situations.
/// </summary>
/// <param name="output">The <see cref="Output{T}"/> to evaluate.</param>
public static Task<T> GetValueAsync<T>(Output<T> output)

View file

@ -347,6 +347,8 @@ static Pulumi.OutputExtensions.IsT0<T0, T1>(this Pulumi.Output<Pulumi.Union<T0,
static Pulumi.OutputExtensions.IsT1<T0, T1>(this Pulumi.Output<Pulumi.Union<T0, T1>> output) -> Pulumi.Output<bool>
static Pulumi.OutputExtensions.Length<T>(this Pulumi.Output<System.Collections.Immutable.ImmutableArray<T>> array) -> Pulumi.Output<int>
static Pulumi.OutputExtensions.Value<T0, T1>(this Pulumi.Output<Pulumi.Union<T0, T1>> output) -> Pulumi.Output<object>
static Pulumi.Utilities.OutputUtilities.CreateUnknown<T>(System.Func<System.Threading.Tasks.Task<T>> valueFactory) -> Pulumi.Output<T>
static Pulumi.Utilities.OutputUtilities.CreateUnknown<T>(T value) -> Pulumi.Output<T>
static Pulumi.Utilities.OutputUtilities.GetDependenciesAsync<T>(Pulumi.Output<T> output) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableHashSet<Pulumi.Resource>>
static Pulumi.Utilities.OutputUtilities.GetIsKnownAsync<T>(Pulumi.Output<T> output) -> System.Threading.Tasks.Task<bool>
static Pulumi.Utilities.OutputUtilities.GetValueAsync<T>(Pulumi.Output<T> output) -> System.Threading.Tasks.Task<T>