Skip to content
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

feat: add support for REST API #812

Merged
merged 5 commits into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ public class MyFeatureTest {
// given
final ZeebeClient client =
ZeebeClient.newClientBuilder()
.gatewayAddress(zeebeContainer.getExternalGatewayAddress())
.grpcAddress(zeebeContainer.getGrpcAddress())
.restAddress(zeebeContainer.getRestAddress())
.usePlaintext()
.build();
final BpmnModelInstance process =
Expand Down Expand Up @@ -249,7 +250,8 @@ public class MyFeatureTest {
// given
final ZeebeClient client =
ZeebeClient.newClientBuilder()
.gatewayAddress(zeebeContainer.getExternalGatewayAddress())
.grpcAddress(zeebeContainer.getGrpcAddress())
.restAddress(zeebeContainer.getRestAddress())
.usePlaintext()
.build();
final BpmnModelInstance process =
Expand Down Expand Up @@ -309,7 +311,7 @@ The container is considered started if and only if:
> A topology is considered complete if there is a leader for all partitions.
Once started, the container is ready to accept commands, and a client can connect to it by setting
its `gatewayAddress` to `ZeebeContainer#getExternalGatewayAddress()`.
its `grpcAddress` to `ZeebeContainer#getGrpcAddress()`, and its `restAddress` to `ZeebeContainer#getRestAddress()`.

## Standalone broker without gateway

Expand Down Expand Up @@ -348,7 +350,7 @@ The container is considered started if and only if:
> A topology is considered complete if there is a leader for all partitions.
Once started, the container is ready to accept commands, and a client can connect to it by setting
its `gatewayAddress` to `ZeebeContainer#getExternalGatewayAddress()`.
its `grpcAddress` to `ZeebeContainer#getGrpcAddress()`, and its `restAddress` to `ZeebeContainer#getRestAddress()`.

## Configuring your container

Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/io/zeebe/containers/ZeebeContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ private void applyDefaultConfiguration() {
.withEnv("ZEEBE_BROKER_NETWORK_HOST", "0.0.0.0")
.withEnv("ZEEBE_BROKER_NETWORK_ADVERTISEDHOST", getInternalHost())
.addExposedPorts(
ZeebePort.GATEWAY.getPort(),
ZeebePort.GATEWAY_REST.getPort(),
ZeebePort.GATEWAY_GRPC.getPort(),
ZeebePort.COMMAND.getPort(),
ZeebePort.INTERNAL.getPort(),
ZeebePort.MONITORING.getPort());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@
*
* <pre>{@code
* ZeebeClient.newClientBuilder()
* .brokerContainerPoint(container.getExternalGatewayAddress())
* .grpcAddress(container.getGrpcAddress())
* .restAddress(container.getRestAddress())
* .usePlaintext()
* .build();
* }</pre>
*
* <p>Note that if your client is also a container within the same network, you can and should use
* the {@link #getInternalGatewayAddress()}.
* the {@link #getInternalGrpcAddress()} and {@link #getInternalRestAddress()} variants.
*/
@API(status = Status.STABLE)
@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
Expand Down Expand Up @@ -115,7 +116,8 @@ private void applyDefaultConfiguration() {
.withEnv("ZEEBE_STANDALONE_GATEWAY", "true")
.withStartupTimeout(DEFAULT_STARTUP_TIMEOUT)
.addExposedPorts(
ZeebePort.GATEWAY.getPort(),
ZeebePort.GATEWAY_REST.getPort(),
ZeebePort.GATEWAY_GRPC.getPort(),
ZeebePort.INTERNAL.getPort(),
ZeebePort.MONITORING.getPort());
}
Expand Down
188 changes: 181 additions & 7 deletions core/src/main/java/io/zeebe/containers/ZeebeGatewayNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.zeebe.containers;

import java.net.URI;
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
import org.testcontainers.containers.GenericContainer;
Expand All @@ -23,11 +24,10 @@
* Represents common properties of nodes which can act as a gateway for a Zeebe cluster, e.g. {@link
* ZeebeContainer} or {@link ZeebeGatewayContainer}.
*
* <p>You can use {@link #getExternalGatewayAddress()} for clients which are not part of the gateway
* container's network; this is most likely what you want to use, so when in doubt use this.
*
* <p>You can use {@link #getInternalGatewayAddress()} for clients which are within the gateway
* container's network.
* <p>You should typically use {@link #getGrpcAddress()} and {@link #getRestAddress()} to wire your
* clients with this gateway. If your client happens to be running in the same network as the Docker
* container, then you may want to use {@link #getInternalGrpcAddress()} or {@link
* #getInternalRestAddress()} instead.
*
* @param <T> the concrete type of the underlying container
*/
Expand Down Expand Up @@ -73,13 +73,16 @@ public interface ZeebeGatewayNode<T extends GenericContainer<T> & ZeebeGatewayNo
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .withBrokerContactPoint(container.getExternalGatewayAddress())
* .gatewayAddress(container.getExternalGatewayAddress())
* .usePlaintext()
* .build();
* }</pre>
*
* @return the gateway address visible from outside the docker network
* @deprecated Use the protocol specific variants from now on, {@link #getGrpcAddress()} or {@link
* #getRestAddress()}
*/
@Deprecated
default String getExternalGatewayAddress() {
return getExternalAddress(ZeebePort.GATEWAY.getPort());
}
Expand All @@ -91,14 +94,185 @@ default String getExternalGatewayAddress() {
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .withBrokerContactPoint(container.getInternalGatewayAddress())
* .gatewayAddress(container.getInternalGatewayAddress())
* .usePlaintext()
* .build();
* }</pre>
*
* @return the gateway address visible from within the docker network
* @deprecated Use the protocol specific variants from now on, {@link #getInternalGrpcAddress()}
* or {@link #getInternalRestAddress()}
*/
@Deprecated
default String getInternalGatewayAddress() {
return getInternalAddress(ZeebePort.GATEWAY.getPort());
}

/**
* Returns an address accessible from within the container's network for the REST API. Primarily
* meant to be used by clients.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .restAddress(container.getInternalRestUrl())
* .usePlaintext()
* .build();
* }</pre>
*
* @return internally accessible REST API address
*/
default URI getInternalRestAddress() {
return getInternalRestAddress("http");
}

/**
* Returns an address accessible from within the container's network for the REST API. Primarily
* meant to be used by clients.
*
* <p>Use this variant if you need to specify a different scheme, e.g. HTTPS.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .restAddress(container.getInternalRestUrl("https"))
* .build();
* }</pre>
*
* @param scheme the expected scheme (e.g. HTTP, HTTPS)
* @return internally accessible REST API address
*/
default URI getInternalRestAddress(final String scheme) {
final int port = ZeebePort.GATEWAY_REST.getPort();
return URI.create(String.format("%s://%s:%d", scheme, getInternalHost(), port));
}

/**
* Returns the address of the REST API a client which is not part of the container's network
* should use. If you want an address accessible from within the container's own network, use *
* {@link #getInternalRestAddress()}
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .restAddress(container.getRestAddress())
* .usePlaintext()
* .build();
* }</pre>
*
* @return externally accessible REST API address
*/
default URI getRestAddress() {
return getRestAddress("http");
}

/**
* Returns the address of the REST API a client which is not part of the container's network
* should use. If you want an address accessible from within the container's own network, use
* {@link #getInternalRestAddress(String)}.
*
* <p>Use this method if you need to specify a different connection scheme, e.g. HTTPS.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .restAddress(container.getExternalRestAddress("https"))
* .build();
* }</pre>
*
* @param scheme the expected scheme (e.g. HTTP, HTTPS)
* @return externally accessible REST API address
*/
default URI getRestAddress(final String scheme) {
final int port = getMappedPort(ZeebePort.GATEWAY_REST.getPort());
return URI.create(String.format("%s://%s:%d", scheme, getExternalHost(), port));
}

/**
* Returns an address accessible from within the container's network for the gRPC API. Primarily
* meant to be used by clients.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .grpcAddress(container.getInternalGrpcAddress())
* .usePlaintext()
* .build();
* }</pre>
*
* @return internally accessible REST API address
*/
default URI getInternalGrpcAddress() {
return getInternalGrpcAddress("http");
}

/**
* Returns an address accessible from within the container's network for the REST API. Primarily
* meant to be used by clients.
*
* <p>Use this variant if you need to specify a different scheme, e.g. HTTPS.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .grpcAddress(container.getInternalGrpcAddress("https"))
* .build();
* }</pre>
*
* @param scheme the expected scheme (e.g. HTTP, HTTPS)
* @return internally accessible REST API address
*/
default URI getInternalGrpcAddress(final String scheme) {
final int port = ZeebePort.GATEWAY_REST.getPort();
return URI.create(String.format("%s://%s:%d", scheme, getInternalHost(), port));
}

/**
* Returns the address of the gRPC API a client which is not part of the container's network
* should use. If you want an address accessible from within the container's own network, use
* {@link #getInternalGrpcAddress()}.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .grpcAddress(container.getGrpcAddress())
* .usePlaintext()
* .build();
* }</pre>
*
* @return externally accessible gRPC API address
*/
default URI getGrpcAddress() {
return getGrpcAddress("http");
}

/**
* Returns the address of the gRPC API a client which is not part of the container's network
* should use. If you want an address accessible from within the container's own network, use
* {@link #getInternalGrpcAddress(String)}.
*
* <p>Use this method if you need to specify a different connection scheme, e.g. HTTPS.
*
* <p>You can build your client like this:
*
* <pre>@{code
* ZeebeClient.newClientBuilder()
* .grpcAddress(container.getGrpcAddress("https"))
* .build();
* }</pre>
*
* @param scheme the expected scheme (e.g. HTTP, HTTPS)
* @return externally accessible gRPC API address
*/
default URI getGrpcAddress(final String scheme) {
final int port = getMappedPort(ZeebePort.GATEWAY_GRPC.getPort());
return URI.create(String.format("%s://%s:%d", scheme, getExternalHost(), port));
}
}
16 changes: 14 additions & 2 deletions core/src/main/java/io/zeebe/containers/ZeebePort.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,24 @@
public enum ZeebePort {
/** Port of the command API, i.e. the port used by the gateway to communicate with the broker */
COMMAND(26501),
/** Port of the gateway API, i.e. the port used by the client to communicate with any gateway */
/**
* Deprecated reference to the old GATEWAY port, which is the gRPC port; use {@link #GATEWAY_REST}
* or {@link #GATEWAY_GRPC} in the future
*/
@Deprecated
GATEWAY(26500),
/** Port for internal communication, i.e. what all nodes use to communicate for clustering */
INTERNAL(26502),
/** Port for the management server, i.e. actuators, metrics, etc. */
MONITORING(9600);
MONITORING(9600),
/**
* Port of the gateway REST API, i.e. the port used by the client to communicate with any gateway
*/
GATEWAY_REST(8080),
/**
* Port of the gateway gRPC API, i.e. the port used by the client to communicate with any gateway
*/
GATEWAY_GRPC(26500);

private final int port;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public ZeebeTopologyWaitStrategy(final int brokersCount, final int replicationFa
*/
public ZeebeTopologyWaitStrategy(
final int brokersCount, final int replicationFactor, final int partitionsCount) {
this(brokersCount, replicationFactor, partitionsCount, ZeebePort.GATEWAY.getPort());
this(brokersCount, replicationFactor, partitionsCount, ZeebePort.GATEWAY_GRPC.getPort());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ public ZeebeClientBuilder newClientBuilder() {
final ZeebeGatewayNode<?> gateway = getAvailableGateway();

return ZeebeClient.newClientBuilder()
.gatewayAddress(gateway.getExternalGatewayAddress())
.grpcAddress(gateway.getGrpcAddress())
.restAddress(gateway.getRestAddress())
.usePlaintext();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,12 @@ void shouldExposeAllPortsButGateway(
// given
final List<Integer> expectedPorts =
Arrays.stream(ZeebePort.values()).map(ZeebePort::getPort).collect(Collectors.toList());
final List<Integer> gatewayPorts =
Arrays.asList(ZeebePort.GATEWAY_GRPC.getPort(), ZeebePort.GATEWAY_REST.getPort());
expectedPorts.removeAll(gatewayPorts);

// when
final List<Integer> exposedPorts = node.getExposedPorts();
expectedPorts.remove((Integer) ZeebePort.GATEWAY.getPort());

// then
assertThat(exposedPorts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ void shouldStartClusterWithEmbeddedGateways() {
for (final ZeebeGatewayNode<?> gateway : cluster.getGateways().values()) {
final Topology topology;
try (final ZeebeClient client =
cluster.newClientBuilder().gatewayAddress(gateway.getExternalGatewayAddress()).build()) {
cluster
.newClientBuilder()
.grpcAddress(gateway.getGrpcAddress())
.restAddress(gateway.getRestAddress())
.build()) {
topology = client.newTopologyRequest().send().join();
}

Expand Down Expand Up @@ -154,7 +158,8 @@ void shouldStartClusterWithMixedGateways() {
try (final ZeebeClient client =
ZeebeClient.newClientBuilder()
.usePlaintext()
.gatewayAddress(gateway.getExternalGatewayAddress())
.grpcAddress(gateway.getGrpcAddress())
.restAddress(gateway.getRestAddress())
.build()) {
final Topology topology = client.newTopologyRequest().send().join();
assertThat(topology.getPartitionsCount())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ private ZeebeContainer getConfiguredClusterBroker(

private ZeebeClient newZeebeClient(final ZeebeContainer node) {
return ZeebeClient.newClientBuilder()
.gatewayAddress(node.getExternalGatewayAddress())
.grpcAddress(node.getGrpcAddress())
.restAddress(node.getRestAddress())
.usePlaintext()
.build();
}
Expand Down
Loading
Loading