Skip to content

Commit

Permalink
Merge pull request #812 from camunda-community-hub/np-support-rest-api
Browse files Browse the repository at this point in the history
feat: add support for REST API
  • Loading branch information
npepinpe authored Dec 29, 2024
2 parents 5234978 + e8e850f commit 72579c8
Show file tree
Hide file tree
Showing 22 changed files with 255 additions and 75 deletions.
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

0 comments on commit 72579c8

Please sign in to comment.