Skip to content

Commit

Permalink
Merge pull request #439 from zZHorizonZz/devservices
Browse files Browse the repository at this point in the history
feature(devservices): added pubsub dev service
  • Loading branch information
loicmathieu authored Jun 8, 2023
2 parents caa389e + f98e2a2 commit 4e230e9
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 26 deletions.
69 changes: 69 additions & 0 deletions docs/modules/ROOT/pages/pubsub.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,72 @@ public class PubSubResource {
}
}
----

== Dev Service

=== Configuring the Dev Service

The extension provides a Dev Service that can be used to run a local PubSub emulator. This is useful for testing purposes, so you don't have to rely on a real PubSub instance. By default, the Dev Service is disabled, but you can enable it by setting the

* `quarkus.google.cloud.pubsub.devservice.enabled` property to `true`

You can also set the

* `quarkus.google.cloud.pubsub.devservice.port` property to change the port on which the emulator will be started (by default there is no port set, so the emulator will use a random port)

=== Using the Dev Service

If we want to connect to the Dev Service, we need to specify `TransportChannelProvider` when creating subscriptions and publishers.

We can just reuse the code from the previous example and add the `TransportChannelProvider` to the `Subscriber` and `Publisher`. So what do we need to change?

As a first thing, we should declare a variable which we can then reuse and also inject the `quarkus.google.cloud.pubsub.emulator-host` property:

[source,java]
----
@ConfigProperty(name = "quarkus.google.cloud.pubsub.emulator-host")
String emulatorHost;
private TransportChannelProvider channelProvider;
----

Then, we can create a `TransportChannelProvider` that provides connection to devservice within the `init` method:

[source,java]
----
// Create a ChannelProvider that connects to the Dev Service
ManagedChannel channel = ManagedChannelBuilder.forTarget(emulatorHost).usePlaintext().build();
channelProvider = FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel));
----

Also in the same method when creating the `Subscriber` we set the `TransportChannelProvider`:

[source,java]
----
// Create a subscriber and set the ChannelProvider
subscriber = Subscriber.newBuilder(subscriptionName, receiver).setChannelProvider(channelProvider).build();
subscriber.startAsync().awaitRunning();
----

The same is done when creating the `Publisher` in the `pubsub` method:

[source,java]
----
// Init a publisher to the topic
Publisher publisher = Publisher.newBuilder(topicName)
.setCredentialsProvider(credentialsProvider)
// Set the ChannelProvider
.setChannelProvider(channelProvider)
.build();
----

And finally we also set the `TransportChannelProvider` when creating the `SubscriptionAdminClient` in the `initSubscription` method:

[source,java]
----
SubscriptionAdminSettings subscriptionAdminSettings = SubscriptionAdminSettings.newBuilder()
.setCredentialsProvider(credentialsProvider)
// Set the ChannelProvider
.setTransportChannelProvider(channelProvider)
.build();
----
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public class TopicManager {
@ConfigProperty(name = "pubsub.use-emulator", defaultValue = "false")
boolean useEmulator;

@ConfigProperty(name = "quarkus.google.cloud.pubsub.emulator-host")
String emulatorHost;

private TopicName topicName;
private Optional<TransportChannelProvider> channelProvider;

Expand All @@ -39,7 +42,7 @@ void init() {
this.topicName = TopicName.of(projectId, "test-topic");

if (useEmulator) {
ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:8085").usePlaintext().build();
ManagedChannel channel = ManagedChannelBuilder.forTarget(emulatorHost).usePlaintext().build();
channelProvider = Optional.of(FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)));
} else {
channelProvider = Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# Use pubsub emulator
%test.pubsub.use-emulator=true
%test.quarkus.google.cloud.pubsub.devservice.enabled=true

# Secret Manager Demo
# You can load secrets from Google Cloud Secret Manager with the ${sm//<SECRET_ID>} syntax.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,17 @@
import static org.awaitility.Awaitility.await;
import static org.hamcrest.core.IsEqual.equalTo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PubSubEmulatorContainer;
import org.testcontainers.utility.DockerImageName;

import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;

@QuarkusTest
public class PubSubResourceTest {
private static final PubSubEmulatorContainer EMULATOR = new PubSubEmulatorContainer(
DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk"));

@BeforeAll
public static void startGcloudContainer() {
List<String> portBindings = new ArrayList<>();
portBindings.add("8085:8085");
EMULATOR.setPortBindings(portBindings);
EMULATOR.start();
}

@AfterAll
public static void stopGcloudContainer() {
EMULATOR.stop();
}

@Test
public void testPubSub() throws ExecutionException, InterruptedException, TimeoutException {
Expand Down
6 changes: 5 additions & 1 deletion pubsub/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
<groupId>io.quarkiverse.googlecloudservices</groupId>
<artifactId>quarkus-google-cloud-pubsub</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>gcloud</artifactId>
</dependency>
</dependencies>

<build>
Expand All @@ -48,4 +52,4 @@
</build>


</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import io.quarkus.deployment.builditem.FeatureBuildItem;

public class PubSubBuildSteps {
private static final String FEATURE = "google-cloud-pubsub";
public static final String FEATURE = "google-cloud-pubsub";

@BuildStep
public FeatureBuildItem feature() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkiverse.googlecloudservices.pubsub.deployement;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;

/**
* Root configuration class for Google Cloud Pub/Sub that operates at build time.
* This class provides a nested structure for configuration, including
* a separate group for the development service configuration.
*/
@ConfigRoot(name = "google.cloud.pubsub", phase = ConfigPhase.BUILD_TIME)
public class PubSubBuildTimeConfig {

/**
* Configuration for the Pub/Sub development service.
* These settings will be used when Pub/Sub service is being configured
* for development purposes.
*/
@ConfigItem
public PubSubDevServiceConfig devservice;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkiverse.googlecloudservices.pubsub.deployement;

import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;

/**
* Configuration group for the PubSubDevService. This class holds all the configuration properties
* related to the Google Cloud Pub/Sub service for development environments.
* <p>
* Here is an example of how to configure these properties:
* <p>
*
* <pre>
* quarkus.pub-sub-dev-service.enabled = true
* quarkus.pub-sub-dev-service.image-name = gcr.io/google.com/cloudsdktool/google-cloud-cli # optional
* quarkus.pub-sub-dev-service.emulatorPort = 8085 # optional
* </pre>
*/
@ConfigGroup
public class PubSubDevServiceConfig {

/**
* Indicates whether the Pub/Sub service should be enabled or not.
* The default value is 'false'.
*/
@ConfigItem(defaultValue = "false")
public boolean enabled;

/**
* Sets the Docker image name for the Google Cloud SDK.
* This image is used to emulate the Pub/Sub service in the development environment.
* The default value is 'gcr.io/google.com/cloudsdktool/google-cloud-cli'.
*/
@ConfigItem(name = "image-name", defaultValue = "gcr.io/google.com/cloudsdktool/google-cloud-cli")
public String imageName;

/**
* Specifies the emulatorPort on which the Pub/Sub service should run in the development environment.
*/
@ConfigItem(name = "emulatorPort")
public Optional<Integer> port = Optional.empty();
}
Loading

0 comments on commit 4e230e9

Please sign in to comment.