From ec37d0fd4c539e097d4142507ce10b027687cdd7 Mon Sep 17 00:00:00 2001 From: Julien Poissonnier Date: Wed, 27 Nov 2024 16:34:12 +0100 Subject: [PATCH] Track dependencies --- .../com/pulumi/core/internal/OutputData.java | 9 ++++ .../deployment/internal/DeploymentImpl.java | 14 ++++--- .../DeploymentInvokeDependsOnTest.java | 42 +++++++------------ 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/core/internal/OutputData.java b/sdk/java/pulumi/src/main/java/com/pulumi/core/internal/OutputData.java index 79c327d09bb..f9af874e89d 100644 --- a/sdk/java/pulumi/src/main/java/com/pulumi/core/internal/OutputData.java +++ b/sdk/java/pulumi/src/main/java/com/pulumi/core/internal/OutputData.java @@ -20,6 +20,7 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.Collection; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -156,6 +157,14 @@ public OutputData withDependency(Resource resource) { return ofNullable(newDependencies, this.value, this.known, this.secret); } + public OutputData withDependencies(List resources) { + var newDependencies = Sets.union( + this.resources, + ImmutableSet.copyOf(resources) + ).immutableCopy(); + return ofNullable(newDependencies, this.value, this.known, this.secret); + } + public OutputData apply(Function function) { if (known) { return ofNullable(resources, function.apply(value), true, secret); diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/deployment/internal/DeploymentImpl.java b/sdk/java/pulumi/src/main/java/com/pulumi/deployment/internal/DeploymentImpl.java index 0aae57357c1..765c124ed78 100644 --- a/sdk/java/pulumi/src/main/java/com/pulumi/deployment/internal/DeploymentImpl.java +++ b/sdk/java/pulumi/src/main/java/com/pulumi/deployment/internal/DeploymentImpl.java @@ -535,14 +535,19 @@ public Output invoke(String token, TypeShape targetType, InvokeArgs ar ? CompletableFuture.completedFuture(null) : packageRef; + // Find all the resource dependencies from dependsOn, we need to wait for this task to complete + // before calling the invoke. + var depsFuture = this.prepare.getAllTransitivelyReferencedResourceUrnsAsync(ImmutableSet.copyOf(options.getDependsOn())); + // Wait for all values from args to be available, and then perform the RPC. return new OutputInternal<>(this.featureSupport.monitorSupportsResourceReferences() .thenCompose(keepResources -> this.serializeInvokeArgs(token, args, keepResources)) .thenCompose(serializedArgs -> { if (!serializedArgs.containsUnknowns) { - return packageRefFuture - .thenCompose(packageRefString -> this.invokeRawAsync(token, serializedArgs, options, packageRefString)) - .thenApply(result -> parseInvokeResponse(token, targetType, result)); + return CompletableFuture.allOf(depsFuture, packageRefFuture) + .thenCompose(v -> this.invokeRawAsync(token, serializedArgs, options, packageRefFuture.join())) + .thenApply(result -> parseInvokeResponse(token, targetType, result)) + .thenApply(output -> output.withDependencies(options.getDependsOn())); } else { return CompletableFuture.completedFuture(OutputData.unknown()); } @@ -701,9 +706,6 @@ private CompletableFuture invokeRawAsync( } ); - // Wait for all the resource dependencies from dependsOn to be available before we call the invoke - this.prepare.getAllTransitivelyReferencedResourceUrnsAsync(ImmutableSet.copyOf(options.getDependsOn())).join(); - return providerFuture.thenCompose(provider -> { var version = options.getVersion(); log.debugOrExcessive( diff --git a/sdk/java/pulumi/src/test/java/com/pulumi/deployment/DeploymentInvokeDependsOnTest.java b/sdk/java/pulumi/src/test/java/com/pulumi/deployment/DeploymentInvokeDependsOnTest.java index d5e3b9286d6..673cbc781ef 100644 --- a/sdk/java/pulumi/src/test/java/com/pulumi/deployment/DeploymentInvokeDependsOnTest.java +++ b/sdk/java/pulumi/src/test/java/com/pulumi/deployment/DeploymentInvokeDependsOnTest.java @@ -57,18 +57,18 @@ public CompletableFuture newResourceAsync(ResourceArgs args) { Thread.currentThread().interrupt(); throw new RuntimeException(e); } - return ResourceResult.of(Optional.of(args.id + "_id"), ImmutableMap.of("prop", "some value")); + return ResourceResult.of(Optional.of(args.id + "_id"), + ImmutableMap.of("prop", "some value")); }); return result; } @Override public CompletableFuture> callAsync(CallArgs args) { + assertThat(marker.resolved).isTrue(); // The resource should have been resolved return CompletableFuture.completedFuture( - ImmutableMap.of( - "result", - ImmutableList.of(ImmutableMap.of("root", - ImmutableMap.of("test1", ImmutableList.of("1", "2", "3")))))); + ImmutableMap.of("result", ImmutableList.of(ImmutableMap.of("root", + ImmutableMap.of("test1", ImmutableList.of("1", "2", "3")))))); } }) .build(); @@ -80,16 +80,12 @@ public CompletableFuture> callAsync(CallArgs args) { deps.add(res); var opts = new InvokeOutputOptions(null, null, null, deps); - var out = CustomInvokes.doStuff(CustomArgs.Empty, opts).applyValue(r -> { + CustomInvokes.doStuff(CustomArgs.Empty, opts).applyValue(r -> { assertThat(r).hasSize(1); - assertThat(r).contains(ImmutableMap.of("root", ImmutableMap.of("test1", ImmutableList.of("1", "2", "3")))); - return (Void) null; + assertThat(r) + .contains(ImmutableMap.of("root", ImmutableMap.of("test1", ImmutableList.of("1", "2", "3")))); + return r; }); - - // Check that the resource was resolved when we called the invoke - assertThat(marker.resolved).isTrue(); - - Internal.of(out).getDataAsync().join(); }); assertThat(result.exceptions()).hasSize(0); @@ -97,7 +93,6 @@ public CompletableFuture> callAsync(CallArgs args) { } public static final class MyArgs extends ResourceArgs { - // Empty } public static final class ResolveMarker { @@ -118,32 +113,23 @@ public MyCustomResource(String name, @Nullable MyArgs args, @Nullable CustomReso static class CustomInvokes { static Output>> doStuff( - @SuppressWarnings("SameParameterValue") CustomArgs args, - @Nullable InvokeOutputOptions options) { - return Deployment.getInstance().invoke( - "tests:custom:stuff", - TypeShape.of(CustomResult.class), - args, - options).applyValue(r -> { + @SuppressWarnings("SameParameterValue") CustomArgs args, @Nullable InvokeOutputOptions options) { + return Deployment.getInstance() + .invoke("tests:custom:stuff", TypeShape.of(CustomResult.class), args, options).applyValue(r -> { return r.result; }); } } static class CustomArgs extends InvokeArgs { - public static final CustomArgs Empty = new CustomArgs(null, null); + public static final CustomArgs Empty = new CustomArgs(null); @Import(name = "text") @Nullable public final String text; - @Import(name = "defaultNamespace") - @Nullable - public final String defaultNamespace; - - CustomArgs(@Nullable String text, @Nullable String defaultNamespace) { + CustomArgs(@Nullable String text) { this.text = text; - this.defaultNamespace = defaultNamespace; } }