-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[codegen] Output-versioned function invokes #612
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, looks promising.
btw. IMHO this change shows architectural issues already in code that should be addressed as a separate issue.
this is a very good question, I second this |
public static CompletableFuture<GetCertificateResult> getCertificate(GetCertificateArgs args, InvokeOptions options) { | ||
return Deployment.getInstance().invokeAsync("aws:acm/getCertificate:getCertificate", TypeShape.of(GetCertificateResult.class), args, Utilities.withVersion(options)); | ||
public static Output<GetCertificateResult> getCertificate(GetCertificateArgs args, InvokeOptions options) { | ||
return Deployment.getInstance().invoke("aws:acm/getCertificate:getCertificate", TypeShape.of(GetCertificateResult.class), args, Utilities.withVersion(options)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, good find! I've added this method for this purpose
A kind reminder, to clear the codegen test errors we currently need to manually commit the changes to the generated test code. Running Sorry for the inconvenience, we probably should automate this somehow in the future. |
Hi @pawelprazak, been trying to debug what is going on here to no avail 😓 I ran the command you sent but the tests keep failing. It is showing code diffs telling that the generated code has changed ... well, that's what the PR is supposed to do 😅 any leads? |
@Zaid-Ajaj I'm sorry you're having troubles with this, if you'd like we could pair on this over zoom. |
@pawelprazak thank you! Tomorrow I will have another look and reach out if I am still stuck 🙏 |
NOTE to self:
|
Alright so this is really frustrating to work with, after having changed how function invokes are implemented, regenerated code from providers and installed them locally, the test examples failed in the CI. For example
would fail in the CI but if I run it locally it tells me that everything is good while using a older version of the provider (gcp in this case) This means I was in the unfortunate state of ✅ locally and 🔴 on CI and had to rewrite the function invokes in the test examples by hand to make them work in CI but locally it was red squiggles all over the place. Somehow even when I install a provider after regenerating it, the test examples were still using a cached build somewhere on my machine. I would expect that The test examples are now all green which is good but still need to update private static Output<String> getStorageAccountPrimaryKey(Output<String> resourceGroupName,
Output<String> accountName) {
return Output.tuple(resourceGroupName, accountName).apply(tuple -> {
var actualResourceGroupName = tuple.t1;
var actualAccountName = tuple.t2;
var invokeResult = StorageFunctions.listStorageAccountKeys(ListStorageAccountKeysArgs.builder()
.resourceGroupName(actualResourceGroupName)
.accountName(actualAccountName)
.build());
return Output.of(invokeResult)
.applyValue(r -> r.keys().get(0).value())
.asSecret();
});
} should change into: private static Output<String> getStorageAccountPrimaryKey(Output<String> resourceGroupName,
Output<String> accountName) {
return Output.tuple(resourceGroupName, accountName).apply(tuple -> {
var actualResourceGroupName = tuple.t1;
var actualAccountName = tuple.t2;
var invokeResult = StorageFunctions.listStorageAccountKeys(ListStorageAccountKeysArgs.builder()
.resourceGroupName(actualResourceGroupName)
.accountName(actualAccountName)
.build());
return invokeResult
.applyValue(result -> result.keys().get(0).value())
.asSecret();
});
} I guess I should update that in the templates repo and then update the templates submodule from here |
NOTE: function invokes here also suffer from pulumi/pulumi#9593 which is why wrapping with |
TODOs
|
Both must coexist, unless we opt to expose |
There's some leeway here, I think in most of the SDKs we went with syntactic sugar implementation, but there was some blocker making it too difficult/impossible in the C# SDK case. Ah I remember what it was exactly. FPlainArgs and FInputArgs types differ in deeply nested Outputs. There was no way in the C# SDK to convert Java implementation started the port from C# so some of the same considerations can apply here. |
Yes, we need an update in templates repo unfortunately. Yes, the Makefile does not understand dependencies correctly which is quite frustrating. We could try working this out that'd help everyone. Providers team is experimenting and adopting with Task util instead of make also if that helps https://github.com/go-task/task One wrench here is that the provider team is taking over the provider code trees and moving them out of the repo, so the capability to "test my changes on provider X" will have to be able to work around the source being somewhere else. I'm open to input how to make this all better, it clearly is a time sink right now. |
MOre review comments in #636 - since this current PR breaks GH UI |
@@ -1604,31 +1596,29 @@ func (mod *modContext) genFunctions(ctx *classFileContext, addClass addClassMeth | |||
// Emit the args and result types, if any. | |||
if fun.Inputs != nil { | |||
// Generate "{Function}Args" class for invokes that return Output<T> | |||
// Notice here using fun.Inputs.InputShape.Properties which use the shape which accepting Outputs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There's a bit of misnomer here. In other languages there is an Input<T>
type, canonically (in TypeScript) it's an untagged union T | Output<T>
. In Java we made the controversial decision to not model that type at all, so we only have Output<T>
- but the cross-language Go framework is still calling that InputShape
- which is fine. at the meta-level InputShape
will inject InputType
wrappers, that will be translated to Output<T>
during the Java specific codegen pass.
@@ -35,6 +35,10 @@ var javaSpecificTests = []*test.SDKTest{ | |||
Directory: "mini-awsx", | |||
Description: "Regression tests extracted from trying to codegen awsx", | |||
}, | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, this one is a bit surprising to me. My mental model was that we borrow tests from the common test suite and then add Java-specific regression tests here. Like mini-awsnative
is Java specific test. But it would seem that output-funcs-edgeorder
should be coming from pulumi/pulumi? It's not there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is I was expecting it to be in test.PulumiPulumiSDKTests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take care of sorting this out later, not blocking.
This is a lot better! The changes looks good with the following caveats:
|
Actually @Zaid-Ajaj I have tried testing the azure-template with modifications, and it's not working. Unfortunately that's blocking. We have a bug in here somewhere. Here is the modification I've made to take advantage of the new features: private static Output<String> getStorageAccountPrimaryKey(Output<String> resourceGroupName,
Output<String> accountName) {
return StorageFunctions.listStorageAccountKeys(ListStorageAccountKeysArgs.builder()
.resourceGroupName(resourceGroupName)
.accountName(accountName)
.build())
.applyValue(r -> r.keys().get(0).value())
.asSecret();
}
Here's how I tested the change:
|
Here's a reason we can't do that - updating the templates repo would BREAK the templates for all Pulumi users since these changes are not released yet. Hence my suggestion of having a branch in that repo tracking |
@t0yv0 I've actually seen this error before, it is a manifestation of pulumi/pulumi-dotnet#33 where function invokes fail when populating their parameters with instances pulumi/pulumi#9593 Also demontrates the same behaviour The suggested workaround during a Another workaround in the template code is to guard the function invoke with an private static Output<String> getStorageAccountPrimaryKey(Output<String> resourceGroupName,
Output<String> accountName) {
if (Deployment.getInstance().isDryRun())
{
return Output.secret("*** StorageAccountPrimaryKey ***");
}
return StorageFunctions.listStorageAccountKeys(ListStorageAccountKeysArgs.builder()
.resourceGroupName(resourceGroupName)
.accountName(accountName)
.build())
.applyValue(r -> r.keys().get(0).value())
.asSecret();
} The final workaround at runtime is to make function invokes smarter and expanding their logic as follows: public static Output<ArbitFuncResult> arbitFunc(ArbitFuncArgs args)
{
if (Deployment.getInstance().isDryRun())
{
// return Output<ArbitFuncResult> but it is unknown?
}
// execute invoke as usual...
} I think making the generated function invokes smarter is the way to go so that users don't have to worry changing their code to adapt to preview/update runs. What do you think? |
I don't believe this is the issue.
How did this happen? There is a bug somewhere in Java. |
My preferred fix for this issue pulumi/pulumi#671 which is also what we have in C#, Python, etc. The suggestion to not invoke in preview is interesting but I can see some downsides, well, namely that invokes don't work in preview. Bookmarking it for further discussion. This would be a change across all SDKs not just Java. I also would like to step through the ref'd issues myself to get a better understanding: |
Confirming that I can pass the test with pulumi/pulumi#671 merged here.
|
Description
Fixes pulumi/pulumi#163
This PR is my initial attempt at getting function invokes to return
Output<ResultType>
instead ofCompletableFuture<ResultType>
My thought at first was to generate syntax sugar around existing function invokes that return
CompletableFuture<ResultType>
and wrap them usingOutput.all
,Output.apply
andOutput.of(CompletableFuture)
but then I saw that the SDK itself has the function that can be used immediately:Questions are
Output<T>
is there any need forCompletableFuture
alternative?TODO
Output.of(....)
Checklist