diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/Provider.java b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/Provider.java new file mode 100644 index 00000000000..e4dc7857632 --- /dev/null +++ b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/Provider.java @@ -0,0 +1,11 @@ +package com.pulumi.provider.internal; + +import java.util.concurrent.CompletableFuture; + +import com.pulumi.provider.internal.models.*; + +public abstract class Provider { + public CompletableFuture getSchema(GetSchemaRequest request) { + throw new UnsupportedOperationException("Method 'getSchema' is not implemented"); + } +} diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/ResourceProviderService.java b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/ResourceProviderService.java new file mode 100644 index 00000000000..3f78e00fda8 --- /dev/null +++ b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/ResourceProviderService.java @@ -0,0 +1,105 @@ +package com.pulumi.provider.internal; + +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.stub.StreamObserver; +import com.google.protobuf.Empty; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; +import java.util.function.Function; + +public class ResourceProviderService { + + private static final Logger logger = Logger.getLogger(ResourceProviderService.class.getName()); + + private Server server; + private final Provider implementation; + + public ResourceProviderService(Provider implementation) { + this.implementation = implementation; + } + + public void startAndBlockUntilShutdown() throws IOException, InterruptedException { + start(); + blockUntilShutdown(); + } + + private void start() throws IOException { + server = ServerBuilder.forPort(0) // Use port 0 to let system assign a free port + .addService(new ResourceProviderImpl(this.implementation)) + .build() + .start(); + + // Print the actual bound port for the parent process to read + System.out.println(server.getPort()); + + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + try { + ResourceProviderService.this.stop(); + } catch (InterruptedException e) { + logger.severe(e.toString()); + } + } + }); + } + + private void stop() throws InterruptedException { + if (server != null) { + server.shutdown().awaitTermination(30, TimeUnit.SECONDS); + } + } + + private void blockUntilShutdown() throws InterruptedException { + if (server != null) { + server.awaitTermination(); + } + } + + static class ResourceProviderImpl extends pulumirpc.ResourceProviderGrpc.ResourceProviderImplBase { + private final Provider implementation; + + public ResourceProviderImpl(Provider implementation) { + this.implementation = implementation; + } + + @Override + public void getPluginInfo(Empty request, StreamObserver responseObserver) { + // Return basic plugin information + pulumirpc.Plugin.PluginInfo info = pulumirpc.Plugin.PluginInfo.newBuilder() + .setVersion("1.0.0") + .build(); + + responseObserver.onNext(info); + responseObserver.onCompleted(); + } + + @Override + public void getSchema(pulumirpc.Provider.GetSchemaRequest request, StreamObserver responseObserver) { + // protobuf sends an empty string for subpackageName/subpackageVersion, but really + // that means null in the domain model. + Function nullIfEmpty = s -> { + if (s == null || s.equals("")) { + return null; + } + return s; + }; + + var domRequest = new com.pulumi.provider.internal.models.GetSchemaRequest( + request.getVersion(), + nullIfEmpty.apply(request.getSubpackageName()), + nullIfEmpty.apply(request.getSubpackageVersion()) + ); + + this.implementation.getSchema(domRequest).thenAccept(domResponse -> { + var grpcResponse = pulumirpc.Provider.GetSchemaResponse.newBuilder() + .setSchema(domResponse.getSchema()) + .build(); + responseObserver.onNext(grpcResponse); + responseObserver.onCompleted(); + }); + } + } +} diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/models/GetSchemaRequest.java b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/models/GetSchemaRequest.java new file mode 100644 index 00000000000..7ed601e3523 --- /dev/null +++ b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/models/GetSchemaRequest.java @@ -0,0 +1,25 @@ +package com.pulumi.provider.internal.models; + +public class GetSchemaRequest { + private final int version; + private final String subpackageName; + private final String subpackageVersion; + + public GetSchemaRequest(int version, String subpackageName, String subpackageVersion) { + this.version = version; + this.subpackageName = subpackageName; + this.subpackageVersion = subpackageVersion; + } + + public int getVersion() { + return version; + } + + public String getSubpackageName() { + return subpackageName; + } + + public String getSubpackageVersion() { + return subpackageVersion; + } +} \ No newline at end of file diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/models/GetSchemaResponse.java b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/models/GetSchemaResponse.java new file mode 100644 index 00000000000..b713ab3cf64 --- /dev/null +++ b/sdk/java/pulumi/src/main/java/com/pulumi/provider/internal/models/GetSchemaResponse.java @@ -0,0 +1,13 @@ +package com.pulumi.provider.internal.models; + +public class GetSchemaResponse { + private final String schema; + + public GetSchemaResponse(String schema) { + this.schema = schema; + } + + public String getSchema() { + return schema; + } +} \ No newline at end of file