From 5022d9d29e41d6533bd858f52a1a70d70c6c934c Mon Sep 17 00:00:00 2001 From: Zaid Ajaj Date: Tue, 6 Dec 2022 22:15:40 +0100 Subject: [PATCH 1/2] Add InvokeSingle variants to dotnet and nodejs SDKs --- ...le-variants-to-dotnet-and-nodejs-sdks.yaml | 4 +++ .../Pulumi/Deployment/DeploymentInstance.cs | 29 +++++++++++++++++++ .../Pulumi/Deployment/Deployment_Invoke.cs | 13 +++++++++ sdk/dotnet/Pulumi/Deployment/IDeployment.cs | 24 +++++++++++++++ sdk/dotnet/Pulumi/PublicAPI.Shipped.txt | 4 ++- sdk/nodejs/runtime/invoke.ts | 13 +++++++++ 6 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 changelog/pending/20221206--sdk-dotnet-nodejs--add-inokesingle-variants-to-dotnet-and-nodejs-sdks.yaml diff --git a/changelog/pending/20221206--sdk-dotnet-nodejs--add-inokesingle-variants-to-dotnet-and-nodejs-sdks.yaml b/changelog/pending/20221206--sdk-dotnet-nodejs--add-inokesingle-variants-to-dotnet-and-nodejs-sdks.yaml new file mode 100644 index 000000000000..cb47bcc7621f --- /dev/null +++ b/changelog/pending/20221206--sdk-dotnet-nodejs--add-inokesingle-variants-to-dotnet-and-nodejs-sdks.yaml @@ -0,0 +1,4 @@ +changes: +- type: feat + scope: sdk/dotnet,nodejs + description: Add InvokeSingle variants to dotnet and nodejs SDKs diff --git a/sdk/dotnet/Pulumi/Deployment/DeploymentInstance.cs b/sdk/dotnet/Pulumi/Deployment/DeploymentInstance.cs index 9bfa46b379fe..4577595ed216 100644 --- a/sdk/dotnet/Pulumi/Deployment/DeploymentInstance.cs +++ b/sdk/dotnet/Pulumi/Deployment/DeploymentInstance.cs @@ -50,6 +50,22 @@ internal DeploymentInstance(IDeployment deployment) public Output Invoke(string token, InvokeArgs args, InvokeOptions? options = null) => _deployment.Invoke(token, args, options); + /// + /// Dynamically invokes the function '', which is offered by a + /// provider plugin. + /// + /// The result of will be a resolved to the + /// result value of the provider plugin. + /// + /// Similar to the earlier , but supports passing input values + /// and returns an Output value. + /// + /// The inputs can be a bag of computed values(including, `T`s, + /// s, s etc.). + /// + public Output InvokeSingle(string token, InvokeArgs args, InvokeOptions? options = null) + => _deployment.InvokeSingle(token, args, options); + /// /// Dynamically invokes the function '', which is offered by a /// provider plugin. @@ -63,6 +79,19 @@ public Output Invoke(string token, InvokeArgs args, InvokeOptions? options public Task InvokeAsync(string token, InvokeArgs args, InvokeOptions? options = null) => _deployment.InvokeAsync(token, args, options); + /// + /// Dynamically invokes the function '', which is offered by a + /// provider plugin. + /// + /// The result of will be a resolved to the + /// result value of the provider plugin which is expected to be a dictionary with single value. + /// + /// The inputs can be a bag of computed values(including, `T`s, + /// s, s etc.). + /// + public Task InvokeSingleAsync(string token, InvokeArgs args, InvokeOptions? options = null) + => _deployment.InvokeSingleAsync(token, args, options); + /// /// Same as , however the /// return value is ignored. diff --git a/sdk/dotnet/Pulumi/Deployment/Deployment_Invoke.cs b/sdk/dotnet/Pulumi/Deployment/Deployment_Invoke.cs index 6e806391040c..b1303275a6e0 100644 --- a/sdk/dotnet/Pulumi/Deployment/Deployment_Invoke.cs +++ b/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; @@ -18,9 +19,21 @@ Task IDeployment.InvokeAsync(string token, InvokeArgs args, InvokeOptions? optio Task IDeployment.InvokeAsync(string token, InvokeArgs args, InvokeOptions? options) => InvokeAsync(token, args, options, convertResult: true); + async Task IDeployment.InvokeSingleAsync(string token, InvokeArgs args, InvokeOptions? options) + { + var outputs = await InvokeAsync>(token, args, options, convertResult: true); + return outputs.Values.First(); + } + Output IDeployment.Invoke(string token, InvokeArgs args, InvokeOptions? options) => new Output(RawInvoke(token, args, options)); + Output IDeployment.InvokeSingle(string token, InvokeArgs args, InvokeOptions? options) + { + var outputResult = new Output>(RawInvoke>(token, args, options)); + return outputResult.Apply(outputs => outputs.Values.First()); + } + private async Task> RawInvoke(string token, InvokeArgs args, InvokeOptions? options) { // This method backs all `Fn.Invoke()` calls that generate diff --git a/sdk/dotnet/Pulumi/Deployment/IDeployment.cs b/sdk/dotnet/Pulumi/Deployment/IDeployment.cs index 20e07ab9cf72..282af655a3ac 100644 --- a/sdk/dotnet/Pulumi/Deployment/IDeployment.cs +++ b/sdk/dotnet/Pulumi/Deployment/IDeployment.cs @@ -38,6 +38,18 @@ internal interface IDeployment /// Task InvokeAsync(string token, InvokeArgs args, InvokeOptions? options = null); + /// + /// Dynamically invokes the function '', which is offered by a + /// provider plugin. + /// + /// The result of will be a resolved to the + /// result value of the provider plugin that returns a bag of properties with a single value that is returned. + /// + /// The inputs can be a bag of computed values(including, `T`s, + /// s, s etc.). + /// + Task InvokeSingleAsync(string token, InvokeArgs args, InvokeOptions? options = null); + /// /// Dynamically invokes the function '', which is offered by a /// provider plugin. @@ -50,6 +62,18 @@ internal interface IDeployment /// Output Invoke(string token, InvokeArgs args, InvokeOptions? options = null); + /// + /// Dynamically invokes the function '', which is offered by a + /// provider plugin. + /// + /// The result of will be a resolved to the + /// result value of the provider plugin that returns a bag of properties with a single value that is returned. + /// + /// The inputs can be a bag of computed values(including, `T`s, + /// s, s etc.). + /// + Output InvokeSingle(string token, InvokeArgs args, InvokeOptions? options = null); + /// /// Same as , however the /// return value is ignored. diff --git a/sdk/dotnet/Pulumi/PublicAPI.Shipped.txt b/sdk/dotnet/Pulumi/PublicAPI.Shipped.txt index 9355ea57b3df..9d5dd36bb174 100644 --- a/sdk/dotnet/Pulumi/PublicAPI.Shipped.txt +++ b/sdk/dotnet/Pulumi/PublicAPI.Shipped.txt @@ -91,6 +91,7 @@ Pulumi.DeploymentInstance.Call(string token, Pulumi.CallArgs args, Pulumi.Resour Pulumi.DeploymentInstance.Call(string token, Pulumi.CallArgs args, Pulumi.Resource self = null, Pulumi.CallOptions options = null) -> Pulumi.Output Pulumi.DeploymentInstance.InvokeAsync(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task Pulumi.DeploymentInstance.InvokeAsync(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task +Pulumi.DeploymentInstance.InvokeSingleAsync(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> System.Threading.Tasks.Task Pulumi.DeploymentInstance.IsDryRun.get -> bool Pulumi.DeploymentInstance.ProjectName.get -> string Pulumi.DeploymentInstance.StackName.get -> string @@ -395,4 +396,5 @@ static Pulumi.Urn.Create(Pulumi.Input name, Pulumi.Input 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(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> Pulumi.Output \ No newline at end of file +Pulumi.DeploymentInstance.Invoke(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> Pulumi.Output +Pulumi.DeploymentInstance.InvokeSingle(string token, Pulumi.InvokeArgs args, Pulumi.InvokeOptions options = null) -> Pulumi.Output \ No newline at end of file diff --git a/sdk/nodejs/runtime/invoke.ts b/sdk/nodejs/runtime/invoke.ts index 3b278ed01b30..e60f31d190cc 100644 --- a/sdk/nodejs/runtime/invoke.ts +++ b/sdk/nodejs/runtime/invoke.ts @@ -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 { + 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, From f93977c3f626d8250448beadb2b4b08e1689b3fd Mon Sep 17 00:00:00 2001 From: Fraser Waters Date: Wed, 7 Dec 2022 15:24:02 +0000 Subject: [PATCH 2/2] Fix PCL binding of options.range = number --- pkg/codegen/pcl/binder_resource.go | 2 ++ pkg/codegen/testing/test/program_driver.go | 1 - .../simple-range-pp/dotnet/simple-range.cs | 20 +++++++++++-------- .../simple-range-pp/go/simple-range.go | 18 +++++++++-------- .../simple-range-pp/nodejs/simple-range.ts | 16 +++++++++------ .../simple-range-pp/python/simple-range.py | 15 ++++++++------ .../testdata/simple-range-pp/simple-range.pp | 16 +++++++++------ 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/pkg/codegen/pcl/binder_resource.go b/pkg/codegen/pcl/binder_resource.go index 2dd78ee48f79..8aaa4e214b70 100644 --- a/pkg/codegen/pcl/binder_resource.go +++ b/pkg/codegen/pcl/binder_resource.go @@ -305,6 +305,8 @@ func (b *binder) bindResourceBody(node *Resource) hcl.Diagnostics { diags := rangeExpr.Typecheck(false) contract.Assert(len(diags) == 0) + rangeValue = model.NumberType + node.VariableType = rangeExpr.Type() default: rk, rv, diags := model.GetCollectionTypes(typ, rng.Range()) diff --git a/pkg/codegen/testing/test/program_driver.go b/pkg/codegen/testing/test/program_driver.go index d4619af8ffc7..28356c74114c 100644 --- a/pkg/codegen/testing/test/program_driver.go +++ b/pkg/codegen/testing/test/program_driver.go @@ -110,7 +110,6 @@ var PulumiPulumiProgramTests = []ProgramTest{ { Directory: "simple-range", Description: "Simple range as int expression translation", - BindOptions: []pcl.BindOption{pcl.AllowMissingVariables}, }, { Directory: "azure-native", diff --git a/pkg/codegen/testing/test/testdata/simple-range-pp/dotnet/simple-range.cs b/pkg/codegen/testing/test/testdata/simple-range-pp/dotnet/simple-range.cs index dd1c3d1d08d6..5b7601e9e6dc 100644 --- a/pkg/codegen/testing/test/testdata/simple-range-pp/dotnet/simple-range.cs +++ b/pkg/codegen/testing/test/testdata/simple-range-pp/dotnet/simple-range.cs @@ -1,20 +1,24 @@ using System.Collections.Generic; using Pulumi; -using Aws = Pulumi.Aws; +using Random = Pulumi.Random; return await Deployment.RunAsync(() => { - var bucket = new List(); - for (var rangeIndex = 0; rangeIndex < 10; rangeIndex++) + var numbers = new List(); + for (var rangeIndex = 0; rangeIndex < 2; rangeIndex++) { var range = new { Value = rangeIndex }; - bucket.Add(new Aws.S3.Bucket($"bucket-{range.Value}", new() + numbers.Add(new Random.RandomInteger($"numbers-{range.Value}", new() { - Website = new Aws.S3.Inputs.BucketWebsiteArgs - { - IndexDocument = $"index-{range.Value}.html", - }, + Min = 1, + Max = range.Value, + Seed = $"seed{range.Value}", })); } + return new Dictionary + { + ["first"] = numbers[0].Id, + ["second"] = numbers[1].Id, + }; }); diff --git a/pkg/codegen/testing/test/testdata/simple-range-pp/go/simple-range.go b/pkg/codegen/testing/test/testdata/simple-range-pp/go/simple-range.go index 9988c12ae598..bb3316af9821 100644 --- a/pkg/codegen/testing/test/testdata/simple-range-pp/go/simple-range.go +++ b/pkg/codegen/testing/test/testdata/simple-range-pp/go/simple-range.go @@ -3,26 +3,28 @@ package main import ( "fmt" - "github.com/pulumi/pulumi-aws/sdk/v5/go/aws/s3" + "github.com/pulumi/pulumi-random/sdk/v4/go/random" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) func main() { pulumi.Run(func(ctx *pulumi.Context) error { - var bucket []*s3.Bucket - for index := 0; index < 10; index++ { + var numbers []*random.RandomInteger + for index := 0; index < 2; index++ { key0 := index val0 := index - __res, err := s3.NewBucket(ctx, fmt.Sprintf("bucket-%v", key0), &s3.BucketArgs{ - Website: &s3.BucketWebsiteArgs{ - IndexDocument: pulumi.String(fmt.Sprintf("index-%v.html", val0)), - }, + __res, err := random.NewRandomInteger(ctx, fmt.Sprintf("numbers-%v", key0), &random.RandomIntegerArgs{ + Min: pulumi.Int(1), + Max: pulumi.Float64(val0), + Seed: pulumi.String(fmt.Sprintf("seed%v", val0)), }) if err != nil { return err } - bucket = append(bucket, __res) + numbers = append(numbers, __res) } + ctx.Export("first", numbers[0].ID()) + ctx.Export("second", numbers[1].ID()) return nil }) } diff --git a/pkg/codegen/testing/test/testdata/simple-range-pp/nodejs/simple-range.ts b/pkg/codegen/testing/test/testdata/simple-range-pp/nodejs/simple-range.ts index a5324217c9a7..23cf1d57fa31 100644 --- a/pkg/codegen/testing/test/testdata/simple-range-pp/nodejs/simple-range.ts +++ b/pkg/codegen/testing/test/testdata/simple-range-pp/nodejs/simple-range.ts @@ -1,9 +1,13 @@ import * as pulumi from "@pulumi/pulumi"; -import * as aws from "@pulumi/aws"; +import * as random from "@pulumi/random"; -const bucket: aws.s3.Bucket[] = []; -for (const range = {value: 0}; range.value < 10; range.value++) { - bucket.push(new aws.s3.Bucket(`bucket-${range.value}`, {website: { - indexDocument: `index-${range.value}.html`, - }})); +const numbers: random.RandomInteger[] = []; +for (const range = {value: 0}; range.value < 2; range.value++) { + numbers.push(new random.RandomInteger(`numbers-${range.value}`, { + min: 1, + max: range.value, + seed: `seed${range.value}`, + })); } +export const first = numbers[0].id; +export const second = numbers[1].id; diff --git a/pkg/codegen/testing/test/testdata/simple-range-pp/python/simple-range.py b/pkg/codegen/testing/test/testdata/simple-range-pp/python/simple-range.py index 396e63ba2607..605e493e1df7 100644 --- a/pkg/codegen/testing/test/testdata/simple-range-pp/python/simple-range.py +++ b/pkg/codegen/testing/test/testdata/simple-range-pp/python/simple-range.py @@ -1,8 +1,11 @@ import pulumi -import pulumi_aws as aws +import pulumi_random as random -bucket = [] -for range in [{"value": i} for i in range(0, 10)]: - bucket.append(aws.s3.Bucket(f"bucket-{range['value']}", website=aws.s3.BucketWebsiteArgs( - index_document=f"index-{range['value']}.html", - ))) +numbers = [] +for range in [{"value": i} for i in range(0, 2)]: + numbers.append(random.RandomInteger(f"numbers-{range['value']}", + min=1, + max=range["value"], + seed=f"seed{range['value']}")) +pulumi.export("first", numbers[0].id) +pulumi.export("second", numbers[1].id) diff --git a/pkg/codegen/testing/test/testdata/simple-range-pp/simple-range.pp b/pkg/codegen/testing/test/testdata/simple-range-pp/simple-range.pp index b28985d21bdd..cb88b96ca555 100644 --- a/pkg/codegen/testing/test/testdata/simple-range-pp/simple-range.pp +++ b/pkg/codegen/testing/test/testdata/simple-range-pp/simple-range.pp @@ -1,8 +1,12 @@ -resource bucket "aws:s3:Bucket" { +resource numbers "random:index/randomInteger:RandomInteger" { options { - range = 10 + range = 2 } - website = { - indexDocument = "index-${range.value}.html" - } -} \ No newline at end of file + + min = 1 + max = range.value + seed = "seed${range.value}" +} + +output first { value = numbers[0].id } +output second { value = numbers[1].id }