Skip to content

Commit

Permalink
Add DictionaryInvokeArgs for dynamically constructing invoke input bag
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaid-Ajaj committed Nov 11, 2022
1 parent 51efd16 commit 134d821
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
@@ -0,0 +1,4 @@
changes:
- type: feat
scope: sdk/dotnet
description: Add DictionaryInvokeArgs for dynamically constructing invoke input bag of properties.
47 changes: 47 additions & 0 deletions sdk/dotnet/Pulumi.Tests/Resources/DictionaryInvokeArgsTests.cs
@@ -0,0 +1,47 @@
// Copyright 2016-2021, Pulumi Corporation

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Xunit;

namespace Pulumi.Tests.Resources
{
public class DictionaryInvokeArgsTests
{
[Fact]
public void ConstructorValidValues()
{
try
{
var dict = new Dictionary<string, object?>
{
{ "null", null },
{ "string", "foo" },
{ "int", 123 },
{ "dictionary", new Dictionary<string, object?> { {"foo", "bar"} }.ToImmutableDictionary() },
{ "output", Output.CreateSecret("secret") },
};
var dictionary = new DictionaryInvokeArgs(dict.ToImmutableDictionary());
}
catch
{
Assert.True(false, "DictionaryInvokeArgs constructor should not throw an exception");
}
}

[Fact]
public void ConstructorInvalidValue()
{
var dict = new Dictionary<string, object?>
{
{ "arbitrary", new { Foo = "bar" } },
};

Assert.Throws<InvalidOperationException>(() =>
{
new DictionaryInvokeArgs(dict.ToImmutableDictionary());
});
}
}
}
2 changes: 2 additions & 0 deletions sdk/dotnet/Pulumi/PublicAPI.Shipped.txt
Expand Up @@ -83,6 +83,8 @@ Pulumi.CustomTimeouts.Update.get -> System.TimeSpan?
Pulumi.CustomTimeouts.Update.set -> void
Pulumi.DictionaryResourceArgs
Pulumi.DictionaryResourceArgs.DictionaryResourceArgs(System.Collections.Immutable.ImmutableDictionary<string, object> dictionary) -> void
Pulumi.DictionaryInvokeArgs
Pulumi.DictionaryInvokeArgs.DictionaryInvokeArgs(System.Collections.Immutable.ImmutableDictionary<string, object> dictionary) -> void
Pulumi.Deployment
Pulumi.DeploymentInstance
Pulumi.DeploymentInstance.Call(string token, Pulumi.CallArgs args, Pulumi.Resource self = null, Pulumi.CallOptions options = null) -> void
Expand Down
68 changes: 68 additions & 0 deletions sdk/dotnet/Pulumi/Resources/DictionaryInvokeArgs.cs
@@ -0,0 +1,68 @@
// Copyright 2016-2022, Pulumi Corporation

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi.Serialization;

namespace Pulumi
{
/// <summary>
/// A special type of <see cref="InvokeArgs"/> with resource inputs represented
/// as a loosely-typed dictionary of objects. Normally,
/// <see cref="DictionaryInvokeArgs "/> should not be used by resource providers
/// since it's too low-level and provides low safety. Its target scenario are
/// resources with a very dynamic shape of inputs.
/// The input dictionary may only contain objects that are serializable by
/// Pulumi, i.e only the following types (or pulumi.Output of those types) are allowed:
/// <list type="bullet">
/// <item><description>Primitive types: <see cref="string"/>, <see cref="double"/>,
/// <see cref="int"/>, <see cref="bool"/></description></item>
/// <item><description><see cref="Asset"/>, <see cref="Archive"/>, or
/// <see cref="AssetArchive"/></description></item>
/// <item><description><see cref="System.Text.Json.JsonElement"/>
/// </description></item>
/// <item><description>Generic collections of the above:
/// <see cref="ImmutableArray{T}"/>, <see cref="ImmutableDictionary{TKey,TValue}"/>
/// with <see cref="string"/> keys, <see cref="Union{T0,T1}"/></description></item>
/// </list>
/// </summary>
public sealed class DictionaryInvokeArgs : InvokeArgs
{
private readonly ImmutableDictionary<string, object?> _dictionary;

/// <summary>
/// Constructs an instance of <see cref="DictionaryInvokeArgs"/> from
/// a dictionary of input objects.
/// </summary>
/// <param name="dictionary">The input dictionary. It may only contain objects
/// that are serializable by Pulumi.</param>
public DictionaryInvokeArgs(ImmutableDictionary<string, object?> dictionary)
{
// Run a basic validation of types of values in the dictionary
var seenTypes = new HashSet<Type>();
foreach (var value in dictionary.Values)
{
if (value == null) continue;

var targetType = value.GetType();
if (value is IOutput)
{
var type = value.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Output<>))
{
targetType = type.GenericTypeArguments[0];
}
}

Converter.CheckTargetType(nameof(dictionary), targetType, seenTypes);
}

_dictionary = dictionary;
}

internal override Task<ImmutableDictionary<string, object?>> ToDictionaryAsync()
=> Task.FromResult(_dictionary);
}
}

0 comments on commit 134d821

Please sign in to comment.