Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
11335: [sdk/dotnet] Add DictionaryInvokeArgs for dynamically constructing invoke inputs r=Zaid-Ajaj a=Zaid-Ajaj <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Service, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Service API version <!-- `@Pulumi` employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Zaid Ajaj <zaid.naom@gmail.com>
- Loading branch information
Showing
4 changed files
with
121 additions
and
0 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
...add-dictionaryinvokeargs-for-dynamically-constructing-invoke-input-bag-of-properties.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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
47
sdk/dotnet/Pulumi.Tests/Resources/DictionaryInvokeArgsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |