Skip to content

Commit

Permalink
Merge #11564
Browse files Browse the repository at this point in the history
11564: [sdk/dotnet/nodejs] Add InvokeSingle variants to dotnet and nodejs SDKs r=Zaid-Ajaj a=Zaid-Ajaj

<!--- 
Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation.
-->

# Description

Needed for #11418 where we have invoke calls that return a simple type (such as `number`) but the runtime and engine _require_ the outputs to be a struct (as per the RPC definition) so here we are adding variants of `invoke` that unwraps the returned object and gets the first value from that object.

For example, a provider with a schema `outputs: { type: "number" }` will have an invoke implementation that returns `{ __result: 42.0 }`, in these case (non-object return types) we use `InvokeSingle` instead of `Invoke`

> It doesn't matter what the name of the key is, we always get the first value by first key.

## Checklist

<!--- Please provide details if the checkbox below is to be left unchecked. -->
- [ ] 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
bors[bot] and Zaid-Ajaj committed Dec 7, 2022
2 parents 68308f5 + 5022d9d commit b400c8d
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 1 deletion.
@@ -0,0 +1,4 @@
changes:
- type: feat
scope: sdk/dotnet,nodejs
description: Add InvokeSingle variants to dotnet and nodejs SDKs
29 changes: 29 additions & 0 deletions sdk/dotnet/Pulumi/Deployment/DeploymentInstance.cs
Expand Up @@ -50,6 +50,22 @@ internal DeploymentInstance(IDeployment deployment)
public Output<T> Invoke<T>(string token, InvokeArgs args, InvokeOptions? options = null)
=> _deployment.Invoke<T>(token, args, options);

/// <summary>
/// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
/// provider plugin.
/// <para/>
/// The result of <see cref="InvokeSingle"/> will be a <see cref="Output"/> resolved to the
/// result value of the provider plugin.
/// <para/>
/// Similar to the earlier <see cref="InvokeSingleAsync"/>, but supports passing input values
/// and returns an Output value.
/// <para/>
/// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
/// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
/// </summary>
public Output<T> InvokeSingle<T>(string token, InvokeArgs args, InvokeOptions? options = null)
=> _deployment.InvokeSingle<T>(token, args, options);

/// <summary>
/// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
/// provider plugin.
Expand All @@ -63,6 +79,19 @@ public Output<T> Invoke<T>(string token, InvokeArgs args, InvokeOptions? options
public Task<T> InvokeAsync<T>(string token, InvokeArgs args, InvokeOptions? options = null)
=> _deployment.InvokeAsync<T>(token, args, options);

/// <summary>
/// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
/// provider plugin.
/// <para/>
/// The result of <see cref="InvokeSingleAsync"/> will be a <see cref="Task"/> resolved to the
/// result value of the provider plugin which is expected to be a dictionary with single value.
/// <para/>
/// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
/// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
/// </summary>
public Task<T> InvokeSingleAsync<T>(string token, InvokeArgs args, InvokeOptions? options = null)
=> _deployment.InvokeSingleAsync<T>(token, args, options);

/// <summary>
/// Same as <see cref="InvokeAsync{T}(string, InvokeArgs, InvokeOptions)"/>, however the
/// return value is ignored.
Expand Down
13 changes: 13 additions & 0 deletions sdk/dotnet/Pulumi/Deployment/Deployment_Invoke.cs
@@ -1,6 +1,7 @@
// Copyright 2016-2021, Pulumi Corporation

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -18,9 +19,21 @@ Task IDeployment.InvokeAsync(string token, InvokeArgs args, InvokeOptions? optio
Task<T> IDeployment.InvokeAsync<T>(string token, InvokeArgs args, InvokeOptions? options)
=> InvokeAsync<T>(token, args, options, convertResult: true);

async Task<T> IDeployment.InvokeSingleAsync<T>(string token, InvokeArgs args, InvokeOptions? options)
{
var outputs = await InvokeAsync<Dictionary<string, T>>(token, args, options, convertResult: true);
return outputs.Values.First();
}

Output<T> IDeployment.Invoke<T>(string token, InvokeArgs args, InvokeOptions? options)
=> new Output<T>(RawInvoke<T>(token, args, options));

Output<T> IDeployment.InvokeSingle<T>(string token, InvokeArgs args, InvokeOptions? options)
{
var outputResult = new Output<Dictionary<string, T>>(RawInvoke<Dictionary<string, T>>(token, args, options));
return outputResult.Apply(outputs => outputs.Values.First());
}

private async Task<OutputData<T>> RawInvoke<T>(string token, InvokeArgs args, InvokeOptions? options)
{
// This method backs all `Fn.Invoke()` calls that generate
Expand Down
24 changes: 24 additions & 0 deletions sdk/dotnet/Pulumi/Deployment/IDeployment.cs
Expand Up @@ -38,6 +38,18 @@ internal interface IDeployment
/// </summary>
Task<T> InvokeAsync<T>(string token, InvokeArgs args, InvokeOptions? options = null);

/// <summary>
/// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
/// provider plugin.
/// <para/>
/// The result of <see cref="InvokeSingleAsync"/> will be a <see cref="Task"/> resolved to the
/// result value of the provider plugin that returns a bag of properties with a single value that is returned.
/// <para/>
/// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
/// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
/// </summary>
Task<T> InvokeSingleAsync<T>(string token, InvokeArgs args, InvokeOptions? options = null);

/// <summary>
/// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
/// provider plugin.
Expand All @@ -50,6 +62,18 @@ internal interface IDeployment
/// </summary>
Output<T> Invoke<T>(string token, InvokeArgs args, InvokeOptions? options = null);

/// <summary>
/// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
/// provider plugin.
/// <para/>
/// The result of <see cref="InvokeSingle"/> will be a <see cref="Output"/> resolved to the
/// result value of the provider plugin that returns a bag of properties with a single value that is returned.
/// <para/>
/// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
/// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
/// </summary>
Output<T> InvokeSingle<T>(string token, InvokeArgs args, InvokeOptions? options = null);

/// <summary>
/// Same as <see cref="InvokeAsync{T}(string, InvokeArgs, InvokeOptions)"/>, however the
/// return value is ignored.
Expand Down
4 changes: 3 additions & 1 deletion sdk/dotnet/Pulumi/PublicAPI.Shipped.txt
Expand Up @@ -91,6 +91,7 @@ Pulumi.DeploymentInstance.Call(string token, Pulumi.CallArgs args, Pulumi.Resour
Pulumi.DeploymentInstance.Call<T>(string token, Pulumi.CallArgs args, Pulumi.Resource self = null, Pulumi.CallOptions options = null) -> Pulumi.Output<T>
Pulumi.DeploymentInstance.InvokeAsync(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task
Pulumi.DeploymentInstance.InvokeAsync<T>(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task<T>
Pulumi.DeploymentInstance.InvokeSingleAsync<T>(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task<T>
Pulumi.DeploymentInstance.IsDryRun.get -> bool
Pulumi.DeploymentInstance.ProjectName.get -> string
Pulumi.DeploymentInstance.StackName.get -> string
Expand Down Expand Up @@ -395,4 +396,5 @@ static Pulumi.Urn.Create(Pulumi.Input<string> name, Pulumi.Input<string> type, P
static readonly Pulumi.CallArgs.Empty -> Pulumi.CallArgs
static readonly Pulumi.InvokeArgs.Empty -> Pulumi.InvokeArgs
static readonly Pulumi.ResourceArgs.Empty -> Pulumi.ResourceArgs
Pulumi.DeploymentInstance.Invoke<T>(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> Pulumi.Output<T>
Pulumi.DeploymentInstance.Invoke<T>(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> Pulumi.Output<T>
Pulumi.DeploymentInstance.InvokeSingle<T>(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> Pulumi.Output<T>
13 changes: 13 additions & 0 deletions sdk/nodejs/runtime/invoke.ts
Expand Up @@ -74,6 +74,19 @@ export function invoke(tok: string, props: Inputs, opts: InvokeOptions = {}): Pr
return invokeAsync(tok, props, opts);
}

/*
* `invokeSingle` dynamically invokes the function, `tok`, which is offered by a provider plugin.
* Similar to `invoke`, but returns a single value instead of an object with a single key.
*/
export function invokeSingle(tok: string, props: Inputs, opts: InvokeOptions = {}): Promise<any> {
return invokeAsync(tok, props, opts).then(outputs => {
// assume outputs have a single key
const keys = Object.keys(outputs);
// return the first key's value from the outputs
return outputs[keys[0]];
});
}

export async function streamInvoke(
tok: string,
props: Inputs,
Expand Down

0 comments on commit b400c8d

Please sign in to comment.