Skip to content

Commit 39a7d7c

Browse files
committed
Merge branch '850-route-service-bindings' into 2.x
2 parents c76a353 + 4e977ad commit 39a7d7c

File tree

4 files changed

+176
-15
lines changed

4 files changed

+176
-15
lines changed

cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@
3232
import org.cloudfoundry.client.v2.routes.RouteEntity;
3333
import org.cloudfoundry.client.v2.routes.RouteExistsRequest;
3434
import org.cloudfoundry.client.v2.routes.RouteResource;
35+
import org.cloudfoundry.client.v2.serviceinstances.UnionServiceInstanceResource;
3536
import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsRequest;
3637
import org.cloudfoundry.client.v2.shareddomains.SharedDomainResource;
3738
import org.cloudfoundry.client.v2.spaces.ListSpaceApplicationsRequest;
3839
import org.cloudfoundry.client.v2.spaces.ListSpaceRoutesRequest;
40+
import org.cloudfoundry.client.v2.spaces.ListSpaceServiceInstancesRequest;
3941
import org.cloudfoundry.client.v2.spaces.SpaceResource;
4042
import org.cloudfoundry.operations.util.OperationsLogging;
4143
import org.cloudfoundry.util.ExceptionUtils;
@@ -154,13 +156,14 @@ public Flux<Route> list(ListRoutesRequest request) {
154156
getAllSpaces(cloudFoundryClient, organizationId)
155157
)))
156158
.flatMapMany(function((cloudFoundryClient, domains, spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, this.spaceId)
157-
.map(resource -> Tuples.of(cloudFoundryClient, domains, resource, spaces))))
158-
.flatMap(function((cloudFoundryClient, domains, resource, spaces) -> Mono
159+
.map(route -> Tuples.of(cloudFoundryClient, domains, route, spaces))))
160+
.flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono
159161
.when(
160-
getApplicationNames(cloudFoundryClient, ResourceUtils.getId(resource)),
161-
getDomainName(domains, ResourceUtils.getEntity(resource).getDomainId()),
162-
Mono.just(resource),
163-
getSpaceName(spaces, ResourceUtils.getEntity(resource).getSpaceId())
162+
getApplicationNames(cloudFoundryClient, ResourceUtils.getId(route)),
163+
getDomainName(domains, ResourceUtils.getEntity(route).getDomainId()),
164+
Mono.just(route),
165+
getServiceName(cloudFoundryClient, ResourceUtils.getEntity(route)),
166+
getSpaceName(spaces, ResourceUtils.getEntity(route).getSpaceId())
164167
)))
165168
.map(function(DefaultRoutes::toRoute))
166169
.transform(OperationsLogging.log("List Routes"))
@@ -312,6 +315,19 @@ private static Flux<RouteResource> getRoutes(CloudFoundryClient cloudFoundryClie
312315
}
313316
}
314317

318+
private static Mono<Optional<String>> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, String serviceInstanceId, String spaceId) {
319+
return requestListSpaceServiceInstances(cloudFoundryClient, spaceId)
320+
.filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource)))
321+
.single()
322+
.map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName()));
323+
}
324+
325+
private static Mono<Optional<String>> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) {
326+
return Mono.justOrEmpty(route.getServiceInstanceId())
327+
.then(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, serviceInstanceId, route.getSpaceId()))
328+
.defaultIfEmpty(Optional.empty());
329+
}
330+
315331
private static Mono<SpaceResource> getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, String space) {
316332
return requestSpaces(cloudFoundryClient, organizationId, space)
317333
.single()
@@ -420,6 +436,16 @@ private static Mono<DeleteRouteResponse> requestDeleteRoute(CloudFoundryClient c
420436
.build());
421437
}
422438

439+
private static Flux<UnionServiceInstanceResource> requestListSpaceServiceInstances(CloudFoundryClient cloudFoundryClient, String spaceId) {
440+
return PaginationUtils
441+
.requestClientV2Resources(page -> cloudFoundryClient.spaces()
442+
.listServiceInstances(ListSpaceServiceInstancesRequest.builder()
443+
.page(page)
444+
.returnUserProvidedServiceInstances(true)
445+
.spaceId(spaceId)
446+
.build()));
447+
}
448+
423449
private static Flux<PrivateDomainResource> requestPrivateDomains(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) {
424450
return PaginationUtils
425451
.requestClientV2Resources(page -> cloudFoundryClient.organizations()
@@ -495,17 +521,19 @@ private static Flux<SpaceResource> requestSpaces(CloudFoundryClient cloudFoundry
495521
.build()));
496522
}
497523

498-
private static Route toRoute(List<String> applications, String domain, RouteResource resource, String space) {
524+
private static Route toRoute(List<String> applications, String domain, RouteResource resource, Optional<String> service, String space) {
499525
RouteEntity entity = ResourceUtils.getEntity(resource);
500-
501-
return Route.builder()
526+
Route.Builder builder = Route.builder()
502527
.applications(applications)
503528
.domain(domain)
504529
.host(entity.getHost())
505530
.id(ResourceUtils.getId(resource))
506531
.path(entity.getPath())
507-
.space(space)
508-
.build();
532+
.space(space);
533+
534+
service.ifPresent(builder::service);
535+
536+
return builder.build();
509537
}
510538

511539
private boolean isRouteOrphan(RouteEntity entity) {

cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/_Route.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616

1717
package org.cloudfoundry.operations.routes;
1818

19+
import org.cloudfoundry.Nullable;
1920
import org.immutables.value.Value;
2021

2122
import java.util.List;
2223

2324
/**
24-
* A route and the applications which are bound to the route.
25+
* A route and the applications that are bound to the route.
2526
*/
2627
@Value.Immutable
2728
abstract class _Route {
@@ -49,10 +50,30 @@ abstract class _Route {
4950
/**
5051
* The path of this route
5152
*/
53+
@Nullable
5254
abstract String getPath();
5355

56+
/**
57+
* The port of this route
58+
*/
59+
@Nullable
60+
abstract String getPort();
61+
62+
/**
63+
* The service of this route
64+
*/
65+
@Nullable
66+
abstract String getService();
67+
5468
/**
5569
* The name of the space of this route
5670
*/
5771
abstract String getSpace();
72+
73+
/**
74+
* The type of this route
75+
*/
76+
@Nullable
77+
abstract String getType();
78+
5879
}

cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,20 @@
4040
import org.cloudfoundry.client.v2.routes.RouteEntity;
4141
import org.cloudfoundry.client.v2.routes.RouteExistsRequest;
4242
import org.cloudfoundry.client.v2.routes.RouteResource;
43+
import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceRequest;
44+
import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceResponse;
45+
import org.cloudfoundry.client.v2.serviceinstances.ServiceInstanceResource;
46+
import org.cloudfoundry.client.v2.serviceinstances.UnionServiceInstanceEntity;
47+
import org.cloudfoundry.client.v2.serviceinstances.UnionServiceInstanceResource;
4348
import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsRequest;
4449
import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsResponse;
4550
import org.cloudfoundry.client.v2.shareddomains.SharedDomainResource;
4651
import org.cloudfoundry.client.v2.spaces.ListSpaceApplicationsRequest;
4752
import org.cloudfoundry.client.v2.spaces.ListSpaceApplicationsResponse;
4853
import org.cloudfoundry.client.v2.spaces.ListSpaceRoutesRequest;
4954
import org.cloudfoundry.client.v2.spaces.ListSpaceRoutesResponse;
55+
import org.cloudfoundry.client.v2.spaces.ListSpaceServiceInstancesRequest;
56+
import org.cloudfoundry.client.v2.spaces.ListSpaceServiceInstancesResponse;
5057
import org.cloudfoundry.client.v2.spaces.SpaceEntity;
5158
import org.cloudfoundry.client.v2.spaces.SpaceResource;
5259
import org.cloudfoundry.operations.AbstractOperationsTest;
@@ -444,19 +451,21 @@ public void listCurrentOrganizationNoSpace() {
444451
requestPrivateDomainsAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID);
445452
requestSharedDomainsAll(this.cloudFoundryClient);
446453
requestSpacesAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID);
454+
requestSpaceServiceInstances(this.cloudFoundryClient, "test-route-entity-serviceInstanceId", "test-route-entity-spaceId");
447455
requestApplications(this.cloudFoundryClient, "test-id");
448456

449457
this.routes
450458
.list(ListRoutesRequest.builder()
451459
.level(Level.ORGANIZATION)
452460
.build())
453461
.as(StepVerifier::create)
454-
.expectNext(fill(Route.builder())
462+
.expectNext(Route.builder()
455463
.application("test-application-name")
456464
.domain("test-shared-domain-name")
457465
.host("test-route-entity-host")
458466
.id("test-id")
459467
.path("test-route-entity-path")
468+
.service("test-service-instance-entityname")
460469
.space("test-space-entity-name")
461470
.build())
462471
.expectComplete()
@@ -493,7 +502,7 @@ public void listCurrentSpace() {
493502
.level(Level.SPACE)
494503
.build())
495504
.as(StepVerifier::create)
496-
.expectNext(fill(Route.builder())
505+
.expectNext(Route.builder()
497506
.application("test-application-name")
498507
.domain("test-shared-domain-name")
499508
.host("test-route-entity-host")
@@ -505,6 +514,30 @@ public void listCurrentSpace() {
505514
.verify(Duration.ofSeconds(5));
506515
}
507516

517+
@Test
518+
public void listCurrentSpaceNoPath() {
519+
requestSpaceRoutesNoPath(this.cloudFoundryClient, TEST_SPACE_ID);
520+
requestPrivateDomainsAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID);
521+
requestSharedDomainsAll(this.cloudFoundryClient);
522+
requestSpacesAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID);
523+
requestApplications(this.cloudFoundryClient, "test-route-id");
524+
525+
this.routes
526+
.list(ListRoutesRequest.builder()
527+
.level(Level.SPACE)
528+
.build())
529+
.as(StepVerifier::create)
530+
.expectNext(Route.builder()
531+
.application("test-application-name")
532+
.domain("test-shared-domain-name")
533+
.host("test-route-entity-host")
534+
.id("test-route-id")
535+
.space("test-space-entity-name")
536+
.build())
537+
.expectComplete()
538+
.verify(Duration.ofSeconds(5));
539+
}
540+
508541
@Test
509542
public void mapRouteAssignedPort() {
510543
requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID);
@@ -1152,6 +1185,24 @@ private static void requestSpaceRoutesEmpty(CloudFoundryClient cloudFoundryClien
11521185
.build()));
11531186
}
11541187

1188+
private static void requestSpaceRoutesNoPath(CloudFoundryClient cloudFoundryClient, String spaceId) {
1189+
when(cloudFoundryClient.spaces()
1190+
.listRoutes(ListSpaceRoutesRequest.builder()
1191+
.page(1)
1192+
.spaceId(spaceId)
1193+
.build()))
1194+
.thenReturn(Mono
1195+
.just(fill(ListSpaceRoutesResponse.builder())
1196+
.resource(fill(RouteResource.builder(), "route-")
1197+
.entity(fill(RouteEntity.builder(), "route-entity-")
1198+
.domainId("test-domain-id")
1199+
.path(null)
1200+
.serviceInstanceId(null)
1201+
.build())
1202+
.build())
1203+
.build()));
1204+
}
1205+
11551206
private static void requestSpaceRoutesService(CloudFoundryClient cloudFoundryClient, String spaceId) {
11561207
when(cloudFoundryClient.spaces()
11571208
.listRoutes(ListSpaceRoutesRequest.builder()
@@ -1169,6 +1220,26 @@ private static void requestSpaceRoutesService(CloudFoundryClient cloudFoundryCli
11691220
.build()));
11701221
}
11711222

1223+
private static void requestSpaceServiceInstances(CloudFoundryClient cloudFoundryClient, String serviceInstanceId, String spaceId) {
1224+
when(cloudFoundryClient.spaces()
1225+
.listServiceInstances(ListSpaceServiceInstancesRequest.builder()
1226+
.page(1)
1227+
.returnUserProvidedServiceInstances(true)
1228+
.spaceId(spaceId)
1229+
.build()))
1230+
.thenReturn(Mono
1231+
.just(fill(ListSpaceServiceInstancesResponse.builder())
1232+
.resource(fill(UnionServiceInstanceResource.builder(), "service-instance-")
1233+
.metadata(fill(Metadata.builder(), "service-instance-metadata-")
1234+
.id(serviceInstanceId)
1235+
.build())
1236+
.entity(fill(UnionServiceInstanceEntity.builder(), "service-instance-entity")
1237+
.spaceId(spaceId)
1238+
.build())
1239+
.build())
1240+
.build()));
1241+
}
1242+
11721243
private static void requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, String space) {
11731244
when(cloudFoundryClient.organizations()
11741245
.listSpaces(ListOrganizationSpacesRequest.builder()

integration-test/src/test/java/org/cloudfoundry/operations/RoutesTest.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.cloudfoundry.operations.routes.MapRouteRequest;
3030
import org.cloudfoundry.operations.routes.Route;
3131
import org.cloudfoundry.operations.routes.UnmapRouteRequest;
32+
import org.cloudfoundry.operations.services.BindRouteServiceInstanceRequest;
33+
import org.cloudfoundry.operations.services.CreateUserProvidedServiceInstanceRequest;
3234
import org.junit.Test;
3335
import org.springframework.beans.factory.annotation.Autowired;
3436
import org.springframework.core.io.ClassPathResource;
@@ -41,7 +43,6 @@
4143
import java.time.Duration;
4244
import java.util.Collections;
4345
import java.util.Optional;
44-
import java.util.concurrent.TimeoutException;
4546
import java.util.function.Predicate;
4647

4748
import static org.assertj.core.api.Assertions.assertThat;
@@ -283,6 +284,28 @@ public void listWithOrganizationLevel() {
283284
.verify(Duration.ofMinutes(5));
284285
}
285286

287+
@Test
288+
public void listWithService() {
289+
String domainName = this.nameFactory.getDomainName();
290+
String hostName = this.nameFactory.getHostName();
291+
String path = this.nameFactory.getPath();
292+
String serviceInstanceName = this.nameFactory.getServiceInstanceName();
293+
294+
createSharedDomainAndRoute(this.cloudFoundryOperations, this.spaceName, domainName, hostName, path)
295+
.then(requestCreateUserProvidedServiceInstance(this.cloudFoundryOperations, serviceInstanceName))
296+
.then(requestBindRouteServiceInstance(this.cloudFoundryOperations, domainName, hostName, path, serviceInstanceName))
297+
.thenMany(this.cloudFoundryOperations.routes()
298+
.list(ListRoutesRequest.builder()
299+
.level(SPACE)
300+
.build()))
301+
.filter(filterRoutes(domainName, hostName, path, null))
302+
.map(Route::getService)
303+
.as(StepVerifier::create)
304+
.expectNext(serviceInstanceName)
305+
.expectComplete()
306+
.verify(Duration.ofMinutes(5));
307+
}
308+
286309
@Test
287310
public void listWithSpaceLevel() {
288311
String domainName = this.nameFactory.getDomainName();
@@ -539,6 +562,16 @@ private static Predicate<Route> filterRoutes(String domainName, String host, Str
539562
&& Optional.ofNullable(path).map(route.getPath()::equals).orElse(true);
540563
}
541564

565+
private static Mono<Void> requestBindRouteServiceInstance(CloudFoundryOperations cloudFoundryOperations, String domainName, String hostName, String path, String serviceInstanceName) {
566+
return cloudFoundryOperations.services()
567+
.bindRoute(BindRouteServiceInstanceRequest.builder()
568+
.domainName(domainName)
569+
.hostname(hostName)
570+
.path(path)
571+
.serviceInstanceName(serviceInstanceName)
572+
.build());
573+
}
574+
542575
private static Mono<Void> requestCreateApplication(CloudFoundryOperations cloudFoundryOperations, Path application, String name, Boolean noStart) {
543576
return cloudFoundryOperations.applications()
544577
.push(PushApplicationRequest.builder()
@@ -596,6 +629,14 @@ private static Mono<Void> requestCreateSharedDomain(CloudFoundryOperations cloud
596629
.build());
597630
}
598631

632+
private static Mono<Void> requestCreateUserProvidedServiceInstance(CloudFoundryOperations cloudFoundryOperations, String name) {
633+
return cloudFoundryOperations.services()
634+
.createUserProvidedInstance(CreateUserProvidedServiceInstanceRequest.builder()
635+
.name(name)
636+
.routeServiceUrl("https://test.route.service")
637+
.build());
638+
}
639+
599640
private static Flux<Route> requestListRoutes(CloudFoundryOperations cloudFoundryOperations) {
600641
return cloudFoundryOperations.routes()
601642
.list(ListRoutesRequest.builder()

0 commit comments

Comments
 (0)