diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_CreateRouteRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_CreateRouteRequest.java index 7f66e5d9cf..a0848dba77 100644 --- a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_CreateRouteRequest.java +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_CreateRouteRequest.java @@ -27,6 +27,13 @@ abstract class _CreateRouteRequest { @JsonProperty("metadata") abstract Metadata getMetadata(); + /** + * Route options + */ + @Nullable + @JsonProperty("options") + abstract RouteOptions getOptions(); + /** * The path */ diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_RouteOptions.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_RouteOptions.java index 0c8bc8b15c..ceeedc2a51 100644 --- a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_RouteOptions.java +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_RouteOptions.java @@ -1,5 +1,6 @@ package org.cloudfoundry.client.v3.routes; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.cloudfoundry.Nullable; @@ -13,10 +14,26 @@ abstract class _RouteOptions { /** - * The loadbalancing + * The loadbalancing algorithm */ + @JsonInclude @JsonProperty("loadbalancing") @Nullable public abstract String getLoadbalancing(); + /** + * The hash header + */ + @JsonInclude + @JsonProperty("hash_header") + @Nullable + public abstract String getHashHeader(); + + /** + * The hash balance + */ + @JsonInclude + @JsonProperty("hash_balance") + @Nullable + public abstract String getHashBalance(); } diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_UpdateRouteRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_UpdateRouteRequest.java index e375cdeac1..42a9f97e95 100644 --- a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_UpdateRouteRequest.java +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/routes/_UpdateRouteRequest.java @@ -21,6 +21,13 @@ abstract class _UpdateRouteRequest { @Nullable abstract Metadata getMetadata(); + /** + * Route options + */ + @JsonProperty("options") + @Nullable + abstract RouteOptions getOptions(); + /** * The route id */ diff --git a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/CreateRouteRequestTest.java b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/CreateRouteRequestTest.java index 602ec57f84..9c925b2adc 100644 --- a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/CreateRouteRequestTest.java +++ b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/CreateRouteRequestTest.java @@ -16,6 +16,7 @@ package org.cloudfoundry.client.v3.routes; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.cloudfoundry.client.v3.Relationship; @@ -94,4 +95,38 @@ void valid() { .build()) .build()); } + + @Test + void validWithRouteOptions() { + CreateRouteRequest request = + CreateRouteRequest.builder() + .relationships( + RouteRelationships.builder() + .domain( + ToOneRelationship.builder() + .data( + Relationship.builder() + .id("test-domain-id") + .build()) + .build()) + .space( + ToOneRelationship.builder() + .data( + Relationship.builder() + .id("test-space-id") + .build()) + .build()) + .build()) + .options( + RouteOptions.builder() + .loadbalancing("hash") + .hashHeader("X-Hash") + .hashBalance("90") + .build()) + .build(); + + assertEquals("hash", request.getOptions().getLoadbalancing()); + assertEquals("X-Hash", request.getOptions().getHashHeader()); + assertEquals("90", request.getOptions().getHashBalance()); + } } diff --git a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/UpdateRouteRequestTest.java b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/UpdateRouteRequestTest.java index 10e0f1eb0a..0ca13db01e 100644 --- a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/UpdateRouteRequestTest.java +++ b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/routes/UpdateRouteRequestTest.java @@ -16,6 +16,7 @@ package org.cloudfoundry.client.v3.routes; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.cloudfoundry.client.v3.Metadata; @@ -39,4 +40,23 @@ void valid() { .routeId("test-route-id") .build(); } + + @Test + void validWithRouteOptions() { + UpdateRouteRequest request = + UpdateRouteRequest.builder() + .metadata(Metadata.builder().label("test-key", "test-value").build()) + .options( + RouteOptions.builder() + .loadbalancing("hash") + .hashHeader("X-Hash") + .hashBalance("90") + .build()) + .routeId("test-route-id") + .build(); + + assertEquals("hash", request.getOptions().getLoadbalancing()); + assertEquals("X-Hash", request.getOptions().getHashHeader()); + assertEquals("90", request.getOptions().getHashBalance()); + } } diff --git a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryVersion.java b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryVersion.java index 65d7a8e38c..dffe0465f6 100644 --- a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryVersion.java +++ b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryVersion.java @@ -55,6 +55,8 @@ public enum CloudFoundryVersion { PCF_2_13(Version.forIntegers(2, 186, 0)), + PCF_2_14(Version.forIntegers(2, 248, 0)), + PCF_4_v2(Version.forIntegers(2, 209, 0)), PCF_4_v3(Version.forIntegers(3, 138, 0)), diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/RoutesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/RoutesTest.java index d3f5bf4ff6..74a2b2a2e0 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/RoutesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/RoutesTest.java @@ -46,6 +46,7 @@ import org.cloudfoundry.client.v3.routes.RemoveRouteDestinationsRequest; import org.cloudfoundry.client.v3.routes.ReplaceRouteDestinationsRequest; import org.cloudfoundry.client.v3.routes.ReplaceRouteDestinationsResponse; +import org.cloudfoundry.client.v3.routes.RouteOptions; import org.cloudfoundry.client.v3.routes.RouteRelationships; import org.cloudfoundry.client.v3.routes.RouteResource; import org.cloudfoundry.client.v3.routes.UpdateRouteRequest; @@ -128,6 +129,72 @@ public void create() { .verify(Duration.ofMinutes(5)); } + @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_14) + @Test + public void createWithOptions() { + String domainName = this.nameFactory.getDomainName(); + + this.organizationId + .flatMap( + organizationId -> + Mono.zip( + createDomainId( + this.cloudFoundryClient, + domainName, + organizationId), + this.spaceId)) + .flatMap( + function( + (domainId, spaceId) -> + this.cloudFoundryClient + .routesV3() + .create( + CreateRouteRequest.builder() + .metadata( + Metadata.builder() + .label( + "test-createWithOptions-key", + "test-createWithOptions-value") + .build()) + .options( + RouteOptions.builder() + .loadbalancing( + "round-robin") + .build()) + .relationships( + RouteRelationships.builder() + .domain( + ToOneRelationship + .builder() + .data( + Relationship + .builder() + .id( + domainId) + .build()) + .build()) + .space( + ToOneRelationship + .builder() + .data( + Relationship + .builder() + .id( + spaceId) + .build()) + .build()) + .build()) + .build()) + .thenReturn(domainId))) + .flatMapMany(domainId -> requestListRoutes(this.cloudFoundryClient, domainId)) + .map(RouteResource::getOptions) + .map(RouteOptions::getLoadbalancing) + .as(StepVerifier::create) + .expectNext("round-robin") + .expectComplete() + .verify(Duration.ofMinutes(5)); + } + @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_9) @Test public void get() { @@ -966,6 +1033,56 @@ public void update() { .verify(Duration.ofMinutes(5)); } + @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_14) + @Test + public void updateOptions() { + String domainName = this.nameFactory.getDomainName(); + + this.organizationId + .flatMap( + organizationId -> + Mono.zip( + createDomainId( + this.cloudFoundryClient, + domainName, + organizationId), + this.spaceId)) + .flatMap( + function( + (domainId, spaceId) -> + Mono.zip( + Mono.just(domainId), + createRouteId( + this.cloudFoundryClient, + domainId, + "updateOptions", + spaceId)))) + .delayUntil( + function( + (domainId, routeId) -> + this.cloudFoundryClient + .routesV3() + .update( + UpdateRouteRequest.builder() + .routeId(routeId) + .options( + RouteOptions.builder() + .loadbalancing( + "least-connection") + .build()) + .build()))) + .flatMapMany( + function( + (domainId, ignore) -> + requestListRoutes(this.cloudFoundryClient, domainId))) + .map(RouteResource::getOptions) + .map(RouteOptions::getLoadbalancing) + .as(StepVerifier::create) + .expectNext("least-connection") + .expectComplete() + .verify(Duration.ofMinutes(5)); + } + private static Mono createApplicationId( CloudFoundryClient cloudFoundryClient, String applicationName, String spaceId) { return requestCreateApplication(cloudFoundryClient, applicationName, spaceId)