From e12c73cf21bba77231396e1935c99cb321984522 Mon Sep 17 00:00:00 2001 From: radoslav-tomov Date: Thu, 7 Sep 2023 11:26:56 +0300 Subject: [PATCH 1/7] porting check route to v3 api --- .../operations/routes/DefaultRoutes.java | 578 +++++++------ .../operations/v3/mapper/MapperUtils.java | 167 ++++ .../operations/AbstractOperationsTest.java | 30 +- .../operations/routes/DefaultRoutesTest.java | 797 +++++++++--------- 4 files changed, 923 insertions(+), 649 deletions(-) create mode 100644 cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java index bd02a06ff4..e671857886 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java @@ -30,7 +30,7 @@ import org.cloudfoundry.client.v2.routes.DeleteRouteResponse; import org.cloudfoundry.client.v2.routes.ListRouteApplicationsRequest; import org.cloudfoundry.client.v2.routes.RouteEntity; -import org.cloudfoundry.client.v2.routes.RouteExistsRequest; + import org.cloudfoundry.client.v2.routes.RouteResource; import org.cloudfoundry.client.v2.serviceinstances.UnionServiceInstanceResource; import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsRequest; @@ -39,7 +39,11 @@ import org.cloudfoundry.client.v2.spaces.ListSpaceRoutesRequest; import org.cloudfoundry.client.v2.spaces.ListSpaceServiceInstancesRequest; import org.cloudfoundry.client.v2.spaces.SpaceResource; +import org.cloudfoundry.client.v3.domains.CheckReservedRoutesRequest; +import org.cloudfoundry.client.v3.organizations.ListOrganizationDomainsRequest; +import org.cloudfoundry.client.v3.domains.DomainResource; import org.cloudfoundry.operations.util.OperationsLogging; +import org.cloudfoundry.operations.v3.mapper.MapperUtils; import org.cloudfoundry.util.ExceptionUtils; import org.cloudfoundry.util.JobUtils; import org.cloudfoundry.util.PaginationUtils; @@ -68,7 +72,8 @@ public final class DefaultRoutes implements Routes { private final Mono spaceId; - public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, Mono spaceId) { + public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, + Mono spaceId) { this.cloudFoundryClient = cloudFoundryClient; this.organizationId = organizationId; this.spaceId = spaceId; @@ -76,260 +81,308 @@ public DefaultRoutes(Mono cloudFoundryClient, Mono o @Override public Mono check(CheckRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getOptionalDomainId(cloudFoundryClient, organizationId, request.getDomain()) - ))) - .flatMap(function((cloudFoundryClient, domainId) -> requestRouteExists(cloudFoundryClient, domainId, request.getHost(), request.getPath()))) - .defaultIfEmpty(false) - .transform(OperationsLogging.log("Check Route Exists")) - .checkpoint(); + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((client, organizationId) -> Mono.zip(this.cloudFoundryClient, + getOptionalDomainIdByName( + client, organizationId, + request.getDomain())))) + .flatMap(function((client, domainId) -> routeExists(client, domainId, request.getHost(), + request.getPath()))) + .defaultIfEmpty(false) + .transform(OperationsLogging.log("Check Route Exists")) + .checkpoint(); + } + + private static Mono routeExists(CloudFoundryClient cloudFoundryClient, String domainId, + String host, + String path) { + return cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() + .domainId(domainId) + .host(host) + .path(path) + .build()) + .flatMap(response -> Mono.just(response.getMatchingRoute())); + } + + private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, + String organizationId, + String domain) { + return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) + .singleOrEmpty() + .map(resource -> resource.getId()); + } + + private static Flux listDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String[] domainNamesFilter) { + return PaginationUtils + .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( + ListOrganizationDomainsRequest.builder() + .names(domainNamesFilter) + .page(page) + .organizationId(organizationId).build())); } @Override public Mono create(CreateRouteRequest request) { return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), - getDomainId(cloudFoundryClient, organizationId, request.getDomain()) - ))) - .flatMap(function((cloudFoundryClient, spaceId, domainId) -> - requestCreateRoute(cloudFoundryClient, domainId, request.getHost(), request.getPath(), request.getPort(), request.getRandomPort(), spaceId) - .map(ResourceUtils::getEntity) - .flatMap(routeEntity -> Mono.justOrEmpty(routeEntity.getPort())) - )) - .transform(OperationsLogging.log("Create Route")) - .checkpoint(); + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), + getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) + .flatMap(function((cloudFoundryClient, spaceId, + domainId) -> requestCreateRoute(cloudFoundryClient, domainId, request.getHost(), + request.getPath(), request.getPort(), request.getRandomPort(), spaceId) + .map(ResourceUtils::getEntity) + .flatMap(routeEntity -> Mono.justOrEmpty(routeEntity.getPort())))) + .transform(OperationsLogging.log("Create Route")) + .checkpoint(); } @Override public Mono delete(DeleteRouteRequest request) { return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getDomainId(cloudFoundryClient, organizationId, request.getDomain()) - ))) - .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( - Mono.just(cloudFoundryClient), - Mono.just(request.getCompletionTimeout()), - getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), domainId, request.getPath(), request.getPort()) - ))) - .flatMap(function(DefaultRoutes::deleteRoute)) - .transform(OperationsLogging.log("Delete Route")) - .checkpoint(); + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) + .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( + Mono.just(cloudFoundryClient), + Mono.just(request.getCompletionTimeout()), + getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), domainId, + request.getPath(), request.getPort())))) + .flatMap(function(DefaultRoutes::deleteRoute)) + .transform(OperationsLogging.log("Delete Route")) + .checkpoint(); } @Override public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { return Mono - .zip(this.cloudFoundryClient, this.spaceId) - .flatMapMany(function((cloudFoundryClient, spaceId) -> requestSpaceRoutes(cloudFoundryClient, spaceId) - .filter(route -> isRouteOrphan(ResourceUtils.getEntity(route))) - .map(ResourceUtils::getId) - .map(routeId -> Tuples.of(cloudFoundryClient, routeId)))) - .flatMap(function((cloudFoundryClient, routeId) -> getApplications(cloudFoundryClient, routeId) - .map(applicationResources -> Tuples.of(cloudFoundryClient, applicationResources, routeId)))) - .filter(predicate((cloudFoundryClient, applicationResources, routeId) -> isApplicationOrphan(applicationResources))) - .flatMap(function((cloudFoundryClient, applicationResources, routeId) -> deleteRoute(cloudFoundryClient, request.getCompletionTimeout(), routeId))) - .then() - .transform(OperationsLogging.log("Delete Orphaned Routes")) - .checkpoint(); + .zip(this.cloudFoundryClient, this.spaceId) + .flatMapMany(function((cloudFoundryClient, spaceId) -> requestSpaceRoutes(cloudFoundryClient, spaceId) + .filter(route -> isRouteOrphan(ResourceUtils.getEntity(route))) + .map(ResourceUtils::getId) + .map(routeId -> Tuples.of(cloudFoundryClient, routeId)))) + .flatMap(function((cloudFoundryClient, routeId) -> getApplications(cloudFoundryClient, routeId) + .map(applicationResources -> Tuples.of(cloudFoundryClient, applicationResources, routeId)))) + .filter(predicate((cloudFoundryClient, applicationResources, + routeId) -> isApplicationOrphan(applicationResources))) + .flatMap(function((cloudFoundryClient, applicationResources, routeId) -> deleteRoute(cloudFoundryClient, + request.getCompletionTimeout(), routeId))) + .then() + .transform(OperationsLogging.log("Delete Orphaned Routes")) + .checkpoint(); } @Override public Flux list(ListRoutesRequest request) { return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getAllDomains(cloudFoundryClient, organizationId), - getAllSpaces(cloudFoundryClient, organizationId) - ))) - .flatMapMany(function((cloudFoundryClient, domains, spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, this.spaceId) - .map(route -> Tuples.of(cloudFoundryClient, domains, route, spaces)))) - .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono - .zip( - getApplicationNames(cloudFoundryClient, ResourceUtils.getId(route)), - getDomainName(domains, ResourceUtils.getEntity(route).getDomainId()), - Mono.just(route), - getServiceName(cloudFoundryClient, ResourceUtils.getEntity(route)), - getSpaceName(spaces, ResourceUtils.getEntity(route).getSpaceId()) - ))) - .map(function(DefaultRoutes::toRoute)) - .transform(OperationsLogging.log("List Routes")) - .checkpoint(); + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getAllDomains(cloudFoundryClient, organizationId), + getAllSpaces(cloudFoundryClient, organizationId)))) + .flatMapMany(function((cloudFoundryClient, domains, + spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, this.spaceId) + .map(route -> Tuples.of(cloudFoundryClient, domains, route, spaces)))) + .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono + .zip( + getApplicationNames(cloudFoundryClient, ResourceUtils.getId(route)), + getDomainName(domains, ResourceUtils.getEntity(route).getDomainId()), + Mono.just(route), + getServiceName(cloudFoundryClient, ResourceUtils.getEntity(route)), + getSpaceName(spaces, ResourceUtils.getEntity(route).getSpaceId())))) + .map(function(DefaultRoutes::toRoute)) + .transform(OperationsLogging.log("List Routes")) + .checkpoint(); } @Override public Mono map(MapRouteRequest request) { return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, request.getDomain(), request.getHost(), request.getPath(), request.getPort(), request.getRandomPort()), - getApplicationId(cloudFoundryClient, request.getApplicationName(), spaceId) - ))) - .flatMap(function((cloudFoundryClient, routeResource, applicationId) -> requestAssociateRoute(cloudFoundryClient, applicationId, ResourceUtils.getId(routeResource)))) - .then(Mono.justOrEmpty(request.getPort())) - .transform(OperationsLogging.log("Map Route")) - .checkpoint(); + .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) + .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, request.getDomain(), + request.getHost(), request.getPath(), request.getPort(), request.getRandomPort()), + getApplicationId(cloudFoundryClient, request.getApplicationName(), spaceId)))) + .flatMap(function((cloudFoundryClient, routeResource, applicationId) -> requestAssociateRoute( + cloudFoundryClient, applicationId, ResourceUtils.getId(routeResource)))) + .then(Mono.justOrEmpty(request.getPort())) + .transform(OperationsLogging.log("Map Route")) + .checkpoint(); } @Override public Mono unmap(UnmapRouteRequest request) { return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getApplicationId(cloudFoundryClient, request.getApplicationName(), spaceId), - getDomainId(cloudFoundryClient, organizationId, request.getDomain()) - .flatMap(domainId -> getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), domainId, request.getPath(), request.getPort())) - ))) - .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) - .transform(OperationsLogging.log("Unmap Route")) - .checkpoint(); - } - - private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, Duration completionTimeout, String routeId) { + .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) + .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getApplicationId(cloudFoundryClient, request.getApplicationName(), spaceId), + getDomainId(cloudFoundryClient, organizationId, request.getDomain()) + .flatMap(domainId -> getRouteId(cloudFoundryClient, request.getHost(), + request.getDomain(), domainId, request.getPath(), request.getPort()))))) + .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) + .transform(OperationsLogging.log("Unmap Route")) + .checkpoint(); + } + + private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, Duration completionTimeout, + String routeId) { return requestDeleteRoute(cloudFoundryClient, routeId) - .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, completionTimeout, job)); + .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, completionTimeout, job)); } - private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, String organizationId) { + private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, + String organizationId) { return requestAllPrivateDomains(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName())) - .mergeWith(requestAllSharedDomains(cloudFoundryClient) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName()))) - .collectMap(function((id, name) -> id), function((id, name) -> name)); + .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName())) + .mergeWith(requestAllSharedDomains(cloudFoundryClient) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName()))) + .collectMap(function((id, name) -> id), function((id, name) -> name)); } - private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, String organizationId) { + private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { return requestAllSpaces(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName())) - .collectMap(function((id, name) -> id), function((id, name) -> name)); + .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName())) + .collectMap(function((id, name) -> id), function((id, name) -> name)); } - private static Mono getApplication(CloudFoundryClient cloudFoundryClient, String application, String spaceId) { + private static Mono getApplication(CloudFoundryClient cloudFoundryClient, String application, + String spaceId) { return requestApplications(cloudFoundryClient, application, spaceId) - .single() - .onErrorResume(NoSuchElementException.class, t -> ExceptionUtils.illegalArgument("Application %s does not exist", application)); + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Application %s does not exist", application)); } - private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, String spaceId) { + private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, + String spaceId) { return getApplication(cloudFoundryClient, application, spaceId) - .map(ResourceUtils::getId); + .map(ResourceUtils::getId); } private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, String routeId) { return requestApplications(cloudFoundryClient, routeId) - .map(resource -> ResourceUtils.getEntity(resource).getName()) - .collectList(); + .map(resource -> ResourceUtils.getEntity(resource).getName()) + .collectList(); } - private static Mono> getApplications(CloudFoundryClient cloudFoundryClient, String routeId) { + private static Mono> getApplications(CloudFoundryClient cloudFoundryClient, + String routeId) { return requestApplications(cloudFoundryClient, routeId) - .collectList(); + .collectList(); } - private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) { + private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { return getDomains(cloudFoundryClient, organizationId, domain) - .single() - .onErrorResume(NoSuchElementException.class, t -> ExceptionUtils.illegalArgument("Domain %s does not exist", domain)); + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Domain %s does not exist", domain)); } - private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) { + private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { return getDomain(cloudFoundryClient, organizationId, domain) - .map(ResourceUtils::getId); + .map(ResourceUtils::getId); } private static Mono getDomainName(Map domains, String domainId) { return Mono.just(domains.get(domainId)); } - private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) { + private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { return requestPrivateDomains(cloudFoundryClient, organizationId, domain) - .map((Function>) in -> in) - .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); + .map((Function>) in -> in) + .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); } - private static Mono getOptionalDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) { - return getDomains(cloudFoundryClient, organizationId, domain) - .singleOrEmpty() - .map(ResourceUtils::getId); - } - - private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, String organizationId, String spaceId, String domain, String host, String path, Integer port, - Boolean randomPort) { + private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, + String organizationId, String spaceId, String domain, String host, String path, Integer port, + Boolean randomPort) { if (randomPort != null) { return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, path, port, randomPort, spaceId)); + .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, path, port, randomPort, + spaceId)); } return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) - .cast(AbstractRouteResource.class) - .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, path, port, randomPort, spaceId))); + .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) + .cast(AbstractRouteResource.class) + .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, path, port, randomPort, + spaceId))); } - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String domain, String host, String path, Integer port) { + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String domain, + String host, String path, Integer port) { return getRoute(cloudFoundryClient, domainId, host, path, port) - .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); + .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); } - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path, Integer port) { + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, + String path, Integer port) { if (port != null) { return requestRoutes(cloudFoundryClient, domainId, null, null, port) - .singleOrEmpty(); + .singleOrEmpty(); } else { return requestRoutes(cloudFoundryClient, domainId, host, path, port) - .filter(resource -> isIdentical(nullSafe(host), ResourceUtils.getEntity(resource).getHost())) - .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), ResourceUtils.getEntity(resource).getPath())) - .singleOrEmpty(); + .filter(resource -> isIdentical(nullSafe(host), ResourceUtils.getEntity(resource).getHost())) + .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), + ResourceUtils.getEntity(resource).getPath())) + .singleOrEmpty(); } } - private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, String domainId, String path, Integer port) { + private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, + String domainId, String path, Integer port) { return getRoute(cloudFoundryClient, domainId, domain, host, path, port) - .map(ResourceUtils::getId); + .map(ResourceUtils::getId); } - private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, Mono organizationId, Mono spaceId) { + private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, + Mono organizationId, Mono spaceId) { if (Level.ORGANIZATION == request.getLevel()) { return organizationId - .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, builder -> builder.organizationId(organizationId1))); + .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, + builder -> builder.organizationId(organizationId1))); } else { return spaceId - .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); + .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); } } - private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, String serviceInstanceId, String spaceId) { + private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, + String serviceInstanceId, String spaceId) { return requestListSpaceServiceInstances(cloudFoundryClient, spaceId) - .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) - .single() - .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); + .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) + .single() + .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); } private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) { return Mono.justOrEmpty(route.getServiceInstanceId()) - .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, serviceInstanceId, route.getSpaceId())) - .defaultIfEmpty(Optional.empty()); + .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, serviceInstanceId, + route.getSpaceId())) + .defaultIfEmpty(Optional.empty()); } - private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, String space) { + private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { return requestSpaces(cloudFoundryClient, organizationId, space) - .single() - .onErrorResume(NoSuchElementException.class, t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); } private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, String organizationId, String space) { return getSpace(cloudFoundryClient, organizationId, space) - .map(ResourceUtils::getId); + .map(ResourceUtils::getId); } private static Mono getSpaceName(Map spaces, String spaceId) { @@ -348,62 +401,68 @@ private static String nullSafe(String host) { return host == null ? "" : host; } - private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, String organizationId) { + private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, + String organizationId) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId) + .page(page) + .build())); } private static Flux requestAllSharedDomains(CloudFoundryClient cloudFoundryClient) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() + .list(ListSharedDomainsRequest.builder() + .page(page) + .build())); } private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, String organizationId) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .page(page) + .build())); } - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, String routeId) { + private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, + String routeId) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .listApplications(ListRouteApplicationsRequest.builder() - .routeId(routeId) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.routes() + .listApplications(ListRouteApplicationsRequest.builder() + .routeId(routeId) + .page(page) + .build())); } - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, String application, String spaceId) { + private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, + String application, String spaceId) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listApplications(ListSpaceApplicationsRequest.builder() - .name(application) - .page(page) - .spaceId(spaceId) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listApplications(ListSpaceApplicationsRequest.builder() + .name(application) + .page(page) + .spaceId(spaceId) + .build())); } - private static Mono requestAssociateRoute(CloudFoundryClient cloudFoundryClient, String applicationId, String routeId) { + private static Mono requestAssociateRoute(CloudFoundryClient cloudFoundryClient, + String applicationId, String routeId) { return cloudFoundryClient.applicationsV2() - .associateRoute(AssociateApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); + .associateRoute(AssociateApplicationRouteRequest.builder() + .applicationId(applicationId) + .routeId(routeId) + .build()); } - private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path, Integer port, Boolean randomPort, String spaceId) { + private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, String domainId, + String host, String path, Integer port, Boolean randomPort, String spaceId) { - org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest.builder(); + org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest + .builder(); if (randomPort != null && randomPort) { builder.generatePort(true); @@ -415,114 +474,113 @@ private static Mono requestCreateRoute(CloudFoundryClient c } return cloudFoundryClient.routes() - .create(builder - .domainId(domainId) - .spaceId(spaceId) - .build()); + .create(builder + .domainId(domainId) + .spaceId(spaceId) + .build()); } private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, String routeId) { return cloudFoundryClient.routes() - .delete(org.cloudfoundry.client.v2.routes.DeleteRouteRequest.builder() - .async(true) - .routeId(routeId) - .build()); + .delete(org.cloudfoundry.client.v2.routes.DeleteRouteRequest.builder() + .async(true) + .routeId(routeId) + .build()); } - private static Flux requestListSpaceServiceInstances(CloudFoundryClient cloudFoundryClient, String spaceId) { + private static Flux requestListSpaceServiceInstances( + CloudFoundryClient cloudFoundryClient, String spaceId) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listServiceInstances(ListSpaceServiceInstancesRequest.builder() - .page(page) - .returnUserProvidedServiceInstances(true) - .spaceId(spaceId) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listServiceInstances(ListSpaceServiceInstancesRequest.builder() + .page(page) + .returnUserProvidedServiceInstances(true) + .spaceId(spaceId) + .build())); } - private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) { + private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .name(domain) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId) + .name(domain) + .page(page) + .build())); } - private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, String applicationId, String routeId) { + private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, + String applicationId, String routeId) { return cloudFoundryClient.applicationsV2() - .removeRoute(RemoveApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Mono requestRouteExists(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path) { - return cloudFoundryClient.routes() - .exists(RouteExistsRequest.builder() - .domainId(domainId) - .host(host) - .path(path) - .build()); + .removeRoute(RemoveApplicationRouteRequest.builder() + .applicationId(applicationId) + .routeId(routeId) + .build()); } - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, UnaryOperator modifier) { + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, + UnaryOperator modifier) { - org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier.apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); + org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier + .apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .list(listBuilder - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.routes() + .list(listBuilder + .page(page) + .build())); } - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path, Integer port) { + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, + String host, String path, Integer port) { return requestRoutes(cloudFoundryClient, builder -> builder - .domainId(domainId) - .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) - .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) - .port(Optional.ofNullable(port).orElse(null)) - ); + .domainId(domainId) + .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) + .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) + .port(Optional.ofNullable(port).orElse(null))); } - private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, String domain) { + private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, + String domain) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .name(domain) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() + .list(ListSharedDomainsRequest.builder() + .name(domain) + .page(page) + .build())); } private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, String spaceId) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listRoutes(ListSpaceRoutesRequest.builder() - .spaceId(spaceId) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listRoutes(ListSpaceRoutesRequest.builder() + .spaceId(spaceId) + .page(page) + .build())); } - private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, String space) { + private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .name(space) - .page(page) - .build())); + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .name(space) + .page(page) + .build())); } - private static Route toRoute(List applications, String domain, RouteResource resource, Optional service, String space) { + private static Route toRoute(List applications, String domain, RouteResource resource, + Optional service, String space) { RouteEntity entity = ResourceUtils.getEntity(resource); Route.Builder builder = Route.builder() - .applications(applications) - .domain(domain) - .host(entity.getHost()) - .id(ResourceUtils.getId(resource)) - .path(entity.getPath()) - .space(space); + .applications(applications) + .domain(domain) + .host(entity.getHost()) + .id(ResourceUtils.getId(resource)) + .path(entity.getPath()) + .space(space); service.ifPresent(builder::service); diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java new file mode 100644 index 0000000000..2baaea011d --- /dev/null +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java @@ -0,0 +1,167 @@ +/* + * Copyright 2013-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cloudfoundry.operations.v3.mapper; + +import org.cloudfoundry.Nullable; +import org.cloudfoundry.client.CloudFoundryClient; +import org.immutables.value.Value; +import org.cloudfoundry.client.v3.applications.ListApplicationsRequest; +import org.cloudfoundry.client.v3.applications.ApplicationResource; +import org.cloudfoundry.client.v3.spaces.ListSpacesRequest; +import org.cloudfoundry.client.v3.spaces.SpaceResource; +import org.cloudfoundry.client.v3.routes.RouteRelationships; +import org.cloudfoundry.client.v3.routes.RouteResource; +import org.cloudfoundry.client.v3.ToOneRelationship; +import org.cloudfoundry.client.v3.organizations.ListOrganizationDomainsRequest; +import org.cloudfoundry.client.v3.domains.DomainResource; +import org.cloudfoundry.client.v3.Relationship; +import org.cloudfoundry.util.PaginationUtils; +import org.cloudfoundry.util.ExceptionUtils; + +import reactor.core.publisher.Mono; +import reactor.core.publisher.Flux; +import java.util.NoSuchElementException; + +public final class MapperUtils { + + public static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain, + String host, Integer port, String path) { + + return getRoute(cloudFoundryClient, organizationId, domain, host, port, path, null) + .flatMap(route -> Mono.just(route.getId())); + } + + public static Mono getRoute(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain, + String host, Integer port, String path, String applicationId) { + + return Mono.just(domain) + .flatMap(name -> getDomainIdByName(cloudFoundryClient, organizationId, name)) + .flatMap(domainId -> listRoutes(cloudFoundryClient, + new String[] { organizationId }, null, new String[] { path }, + new String[] { host }, new int[] { port }, + new String[] { domainId }, + (applicationId != null) ? new String[] { applicationId } + : new String[] {}) + .single() + .switchIfEmpty(ExceptionUtils.illegalArgument( + "Route for %s does not exist", + domain))); + } + + public static Mono getSpaceIdByName(CloudFoundryClient cloudFoundryClient, String organizationId, + String spaceName) { + return listSpaces(cloudFoundryClient, organizationId, new String[] { spaceName }) + .flatMap(space -> Mono.just(space.getId())); + } + + public static Mono getDomainIdByName(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return getDomain(cloudFoundryClient, organizationId, domain) + .map(resource -> resource.getId()); + } + + public static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, + String organizationId, + String domain) { + return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) + .singleOrEmpty() + .map(resource -> resource.getId()); + } + + public static Mono listSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, + String[] spacesNameFilter) { + return PaginationUtils.requestClientV3Resources(page -> cloudFoundryClient.spacesV3() + .list(ListSpacesRequest.builder() + .organizationId(organizationId) + .names(spacesNameFilter) + .page(page) + .build())) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument( + "Space %s does not exist", + String.join(",", spacesNameFilter))); + + } + + private static Mono getDomain(CloudFoundryClient cloudFoundryClient, + String organizationId, String domainName) { + return listDomains(cloudFoundryClient, organizationId, new String[] { domainName }) + .single() + .onErrorResume(NoSuchElementException.class, t -> ExceptionUtils + .illegalArgument("Domain %s does not exist", domainName)); + + } + + public static Flux listDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String[] domainNamesFilter) { + return PaginationUtils + .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( + ListOrganizationDomainsRequest.builder() + .names(domainNamesFilter) + .page(page) + .organizationId(organizationId).build())); + } + + public static Flux listRoutes(CloudFoundryClient cloudFoundryClient, + String[] organizationIdsFilter, String[] spaceIdFilter, String[] pathsFilter, + String[] hostsFilter, + int[] portsFilter, String[] domainIdFilter, String[] applicationIds) { + + return PaginationUtils + .requestClientV3Resources(page -> cloudFoundryClient.routesV3() + .list(org.cloudfoundry.client.v3.routes.ListRoutesRequest.builder() + .page(page) + .applicationIds(applicationIds) + .spaceIds(spaceIdFilter) + .organizationIds(organizationIdsFilter) + .ports(portsFilter) + .hosts(hostsFilter) + .paths(pathsFilter) + .domainIds(domainIdFilter) + .build())); + } + + private static Flux listApplications(CloudFoundryClient cloudFoundryClient, + String[] nameFilter, String[] organizationIdsFilter, String[] spaceIdsFilter) { + return PaginationUtils + .requestClientV3Resources(page -> cloudFoundryClient.applicationsV3() + .list(ListApplicationsRequest.builder() + .names(nameFilter) + .page(page) + .spaceIds(spaceIdsFilter) + .organizationIds(organizationIdsFilter) + .build())); + } + + public static Mono getApplicationIdByName(CloudFoundryClient cloudFoundryClient, + String name, String spaceId, String organizationId) { + + return listApplications(cloudFoundryClient, + new String[] { name }, + new String[] { organizationId }, + new String[] { spaceId }) + .single() + .map(app -> app.getId()) + .switchIfEmpty(ExceptionUtils.illegalArgument( + "Application with name %s does not exist", + name)); + } + +} diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java index 4efb6e4b9d..e2f2a3e428 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java @@ -20,11 +20,13 @@ import org.cloudfoundry.client.v2.applications.ApplicationsV2; import org.cloudfoundry.client.v2.buildpacks.Buildpacks; import org.cloudfoundry.client.v2.domains.Domains; +import org.cloudfoundry.client.v3.domains.DomainsV3; import org.cloudfoundry.client.v2.events.Events; import org.cloudfoundry.client.v2.featureflags.FeatureFlags; import org.cloudfoundry.client.v2.jobs.Jobs; import org.cloudfoundry.client.v2.organizationquotadefinitions.OrganizationQuotaDefinitions; import org.cloudfoundry.client.v2.organizations.Organizations; +import org.cloudfoundry.client.v3.organizations.OrganizationsV3; import org.cloudfoundry.client.v2.privatedomains.PrivateDomains; import org.cloudfoundry.client.v2.resourcematch.ResourceMatch; import org.cloudfoundry.client.v2.routes.Routes; @@ -60,11 +62,14 @@ public abstract class AbstractOperationsTest { protected static final Mono MISSING_ID = Mono.error(new java.lang.IllegalStateException("MISSING_ID")); - protected static final Mono MISSING_ORGANIZATION_ID = Mono.error(new java.lang.IllegalStateException("MISSING_ORGANIZATION_ID")); + protected static final Mono MISSING_ORGANIZATION_ID = Mono + .error(new java.lang.IllegalStateException("MISSING_ORGANIZATION_ID")); - protected static final Mono MISSING_SPACE_ID = Mono.error(new java.lang.IllegalStateException("MISSING_SPACE_ID")); + protected static final Mono MISSING_SPACE_ID = Mono + .error(new java.lang.IllegalStateException("MISSING_SPACE_ID")); - protected static final Mono MISSING_USERNAME = Mono.error(new java.lang.IllegalStateException("MISSING_USERNAME")); + protected static final Mono MISSING_USERNAME = Mono + .error(new java.lang.IllegalStateException("MISSING_USERNAME")); protected static final String TEST_ORGANIZATION_ID = "test-organization-id"; @@ -87,6 +92,7 @@ public abstract class AbstractOperationsTest { protected final CloudFoundryClient cloudFoundryClient = mock(CloudFoundryClient.class, RETURNS_SMART_NULLS); protected final Domains domains = mock(Domains.class, RETURNS_SMART_NULLS); + protected final DomainsV3 domainsV3 = mock(DomainsV3.class, RETURNS_SMART_NULLS); protected final DopplerClient dopplerClient = mock(DopplerClient.class, RETURNS_SMART_NULLS); @@ -96,9 +102,11 @@ public abstract class AbstractOperationsTest { protected final Jobs jobs = mock(Jobs.class, RETURNS_SMART_NULLS); - protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = mock(OrganizationQuotaDefinitions.class, RETURNS_SMART_NULLS); + protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = mock(OrganizationQuotaDefinitions.class, + RETURNS_SMART_NULLS); protected final Organizations organizations = mock(Organizations.class, RETURNS_SMART_NULLS); + protected final OrganizationsV3 organizationsV3 = mock(OrganizationsV3.class, RETURNS_SMART_NULLS); protected final PrivateDomains privateDomains = mock(PrivateDomains.class, RETURNS_SMART_NULLS); @@ -118,7 +126,8 @@ public abstract class AbstractOperationsTest { protected final ServiceKeys serviceKeys = mock(ServiceKeys.class, RETURNS_SMART_NULLS); - protected final ServicePlanVisibilities servicePlanVisibilities = mock(ServicePlanVisibilities.class, RETURNS_SMART_NULLS); + protected final ServicePlanVisibilities servicePlanVisibilities = mock(ServicePlanVisibilities.class, + RETURNS_SMART_NULLS); protected final ServicePlans servicePlans = mock(ServicePlans.class, RETURNS_SMART_NULLS); @@ -126,7 +135,8 @@ public abstract class AbstractOperationsTest { protected final SharedDomains sharedDomains = mock(SharedDomains.class, RETURNS_SMART_NULLS); - protected final SpaceQuotaDefinitions spaceQuotaDefinitions = mock(SpaceQuotaDefinitions.class, RETURNS_SMART_NULLS); + protected final SpaceQuotaDefinitions spaceQuotaDefinitions = mock(SpaceQuotaDefinitions.class, + RETURNS_SMART_NULLS); protected final Spaces spaces = mock(Spaces.class, RETURNS_SMART_NULLS); @@ -138,9 +148,11 @@ public abstract class AbstractOperationsTest { protected final UaaClient uaaClient = mock(UaaClient.class, RETURNS_SMART_NULLS); - protected final org.cloudfoundry.uaa.users.Users uaaUsers = mock(org.cloudfoundry.uaa.users.Users.class, RETURNS_SMART_NULLS); + protected final org.cloudfoundry.uaa.users.Users uaaUsers = mock(org.cloudfoundry.uaa.users.Users.class, + RETURNS_SMART_NULLS); - protected final UserProvidedServiceInstances userProvidedServiceInstances = mock(UserProvidedServiceInstances.class, RETURNS_SMART_NULLS); + protected final UserProvidedServiceInstances userProvidedServiceInstances = mock(UserProvidedServiceInstances.class, + RETURNS_SMART_NULLS); protected final Users users = mock(Users.class, RETURNS_SMART_NULLS); @@ -150,10 +162,12 @@ public final void mockClient() { when(this.cloudFoundryClient.applicationsV3()).thenReturn(this.applicationsV3); when(this.cloudFoundryClient.buildpacks()).thenReturn(this.buildpacks); when(this.cloudFoundryClient.domains()).thenReturn(this.domains); + when(this.cloudFoundryClient.domainsV3()).thenReturn(this.domainsV3); when(this.cloudFoundryClient.events()).thenReturn(this.events); when(this.cloudFoundryClient.featureFlags()).thenReturn(this.featureFlags); when(this.cloudFoundryClient.jobs()).thenReturn(this.jobs); when(this.cloudFoundryClient.organizations()).thenReturn(this.organizations); + when(this.cloudFoundryClient.organizationsV3()).thenReturn(this.organizationsV3); when(this.cloudFoundryClient.organizationQuotaDefinitions()).thenReturn(this.organizationQuotaDefinitions); when(this.cloudFoundryClient.privateDomains()).thenReturn(this.privateDomains); when(this.cloudFoundryClient.resourceMatch()).thenReturn(this.resourceMatch); diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java index 31e015f1ec..c0ad2667aa 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java @@ -56,8 +56,26 @@ import org.cloudfoundry.client.v2.spaces.ListSpaceServiceInstancesResponse; import org.cloudfoundry.client.v2.spaces.SpaceEntity; import org.cloudfoundry.client.v2.spaces.SpaceResource; +import org.cloudfoundry.client.v3.domains.CheckReservedRoutesRequest; +import org.cloudfoundry.client.v3.domains.CheckReservedRoutesResponse; +import org.cloudfoundry.client.v3.organizations.ListOrganizationDomainsRequest; +import org.cloudfoundry.client.v3.organizations.ListOrganizationDomainsResponse; +import org.cloudfoundry.client.v3.Pagination; +import org.cloudfoundry.client.v3.Relationship; +import org.cloudfoundry.client.v3.ToManyRelationship; +import org.cloudfoundry.client.v3.ToOneRelationship; +import org.cloudfoundry.client.v3.domains.CheckReservedRoutesRequest; +import org.cloudfoundry.client.v3.domains.CheckReservedRoutesResponse; +import org.cloudfoundry.client.v3.domains.DomainRelationships; +import org.cloudfoundry.client.v3.domains.DomainResource; import org.cloudfoundry.operations.AbstractOperationsTest; +import org.cloudfoundry.operations.v3.mapper.MapperUtils; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import reactor.test.scheduler.VirtualTimeScheduler; @@ -73,77 +91,72 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.cloudfoundry.operations.TestObjects.fill; import static org.mockito.Mockito.when; +import org.mockito.MockedStatic; public final class DefaultRoutesTest extends AbstractOperationsTest { - private final DefaultRoutes routes = new DefaultRoutes(Mono.just(this.cloudFoundryClient), Mono.just(TEST_ORGANIZATION_ID), Mono.just(TEST_SPACE_ID)); - - @Test - public void checkRouteInvalidDomain() { - requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); - - this.routes - .check(CheckRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .build()) - .as(StepVerifier::create) - .expectNext(false) - .expectComplete() - .verify(Duration.ofSeconds(5)); - } - - @Test - public void checkRouteInvalidHost() { - requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRouteExistsFalse(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path"); - - this.routes - .check(CheckRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectNext(false) - .expectComplete() - .verify(Duration.ofSeconds(5)); - } + private final DefaultRoutes routes = new DefaultRoutes(Mono.just(this.cloudFoundryClient), + Mono.just(TEST_ORGANIZATION_ID), Mono.just(TEST_SPACE_ID)); + private static final String TEST_DOMAIN_ID = "3a5d3d89-3f89-4f05-8188-8a2b298c79d5"; + private static final String TEST_DOMAIN_NAME = "domain-name"; + private static final String TEST_PATH = "test-path"; + private static final String TEST_HOST = "192.168.0,.1"; + private static final Integer TEST_PORT = 8080; @Test - public void checkRoutePrivateDomain() { - requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRouteExistsTrue(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path"); - - this.routes - .check(CheckRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") + public void checkRoute() { + mockListDomains(this.cloudFoundryClient); + mockCheckReservedRoutes(this.cloudFoundryClient); + + this.routes.check(CheckRouteRequest.builder() + .host(TEST_HOST) + .path(TEST_PATH) + .domain(TEST_DOMAIN_NAME) .build()) - .as(StepVerifier::create) - .expectNext(true) - .expectComplete() - .verify(Duration.ofSeconds(5)); - } - - @Test - public void checkRouteSharedDomain() { - requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestRouteExistsTrue(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", "test-path"); - - this.routes - .check(CheckRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectNext(true) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .as(StepVerifier::create) + .expectNext(true) + .expectComplete() + .verify(Duration.ofSeconds(5)); + + } + + private static void mockCheckReservedRoutes(CloudFoundryClient cloudFoundryClient){ + when(cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() + .domainId(TEST_DOMAIN_ID) + .host(TEST_HOST) + .path(TEST_PATH) + .build())) + .thenReturn(Mono.just( + CheckReservedRoutesResponse.builder().matchingRoute(true).build())); + } + + private static void mockListDomains(CloudFoundryClient cloudFoundryClient){ + when(cloudFoundryClient.organizationsV3().listDomains( + ListOrganizationDomainsRequest.builder() + .name(TEST_DOMAIN_NAME) + .page(1) + .organizationId(TEST_ORGANIZATION_ID).build())) + .thenReturn(Mono.just( ListOrganizationDomainsResponse.builder() + .pagination(Pagination.builder() + .totalResults(1) + .totalPages(1) + .build()) + .resource(DomainResource.builder() + .id(TEST_DOMAIN_ID) + .createdAt("2019-03-08T01:06:19Z") + .updatedAt("2019-03-08T01:06:19Z") + .name(TEST_DOMAIN_NAME) + .isInternal(false) + .relationships(DomainRelationships.builder() + .organization(ToOneRelationship.builder() + .data(Relationship.builder() + .id(TEST_ORGANIZATION_ID) + .build()) + .build()) + .sharedOrganizations(ToManyRelationship.builder().build()) + .build()) + .build()) + .build())); } @Test @@ -151,18 +164,19 @@ public void createRouteAssignedPort() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, null, 9999, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, null, 9999, + "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .port(9999) - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .port(9999) + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .expectNext(1) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -172,14 +186,15 @@ public void createRouteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Domain test-domain does not exist")) - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Domain test-domain does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -188,70 +203,74 @@ public void createRouteInvalidSpace() { requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Space test-space-name does not exist")) - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Space test-space-name does not exist")) + .verify(Duration.ofSeconds(5)); } @Test public void createRouteNoHost() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, "test-path", null, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, "test-path", null, + "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .path("test-path") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .path("test-path") + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .expectNext(1) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test public void createRouteNoPath() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, null, null, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, null, null, + "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .expectNext(1) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test public void createRoutePrivateDomain() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", null, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", + null, "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .expectNext(1) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -259,18 +278,19 @@ public void createRouteRandomPort() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, true, null, null, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, true, null, null, + "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .randomPort(true) - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .create(CreateRouteRequest.builder() + .domain("test-domain") + .randomPort(true) + .space(TEST_SPACE_NAME) + .build()) + .as(StepVerifier::create) + .expectNext(1) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -282,13 +302,13 @@ public void deleteAssignedPort() { requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .port(9999) - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .delete(DeleteRouteRequest.builder() + .domain("test-domain") + .port(9999) + .build())) + .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -299,14 +319,15 @@ public void deleteFailure() { requestJobFailure(this.cloudFoundryClient, "test-job-entity-id"); StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(ClientV2Exception.class).hasMessage("test-error-details-errorCode(1): test-error-details-description")) - .verify(Duration.ofSeconds(5)); + .delete(DeleteRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .build())) + .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(ClientV2Exception.class) + .hasMessage("test-error-details-errorCode(1): test-error-details-description")) + .verify(Duration.ofSeconds(5)); } @Test @@ -315,14 +336,15 @@ public void deleteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Domain test-domain does not exist")) - .verify(Duration.ofSeconds(5)); + .delete(DeleteRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Domain test-domain does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -331,14 +353,15 @@ public void deleteInvalidRoute() { requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Route for test-domain does not exist")) - .verify(Duration.ofSeconds(5)); + .delete(DeleteRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Route for test-domain does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -347,11 +370,11 @@ public void deleteOrphanedRoutesAssociatedApplication() { requestApplications(this.cloudFoundryClient, "test-route-id"); this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -359,11 +382,11 @@ public void deleteOrphanedRoutesAssociatedService() { requestSpaceRoutesService(this.cloudFoundryClient, TEST_SPACE_ID); this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -374,11 +397,11 @@ public void deleteOrphanedRoutesNoAssociations() { requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); StepVerifier.withVirtualTime(() -> this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() + .build())) + .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -389,11 +412,12 @@ public void deleteOrphanedRoutesNoAssociationsFailure() { requestJobFailure(this.cloudFoundryClient, "test-job-entity-id"); StepVerifier.withVirtualTime(() -> this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(ClientV2Exception.class).hasMessage("test-error-details-errorCode(1): test-error-details-description")) - .verify(Duration.ofSeconds(5)); + .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() + .build())) + .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(ClientV2Exception.class) + .hasMessage("test-error-details-errorCode(1): test-error-details-description")) + .verify(Duration.ofSeconds(5)); } @Test @@ -401,11 +425,11 @@ public void deleteOrphanedRoutesNoRoutes() { requestSpaceRoutesEmpty(this.cloudFoundryClient, TEST_SPACE_ID); this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -416,14 +440,14 @@ public void deletePrivateDomain() { requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .delete(DeleteRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .build())) + .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -435,14 +459,14 @@ public void deleteSharedDomain() { requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .delete(DeleteRouteRequest.builder() + .domain("test-domain") + .host("test-host") + .path("test-path") + .build())) + .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -451,25 +475,26 @@ public void listCurrentOrganizationNoSpace() { requestPrivateDomainsAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID); requestSharedDomainsAll(this.cloudFoundryClient); requestSpacesAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID); - requestSpaceServiceInstances(this.cloudFoundryClient, "test-route-entity-serviceInstanceId", "test-route-entity-spaceId"); + requestSpaceServiceInstances(this.cloudFoundryClient, "test-route-entity-serviceInstanceId", + "test-route-entity-spaceId"); requestApplications(this.cloudFoundryClient, "test-id"); this.routes - .list(ListRoutesRequest.builder() - .level(Level.ORGANIZATION) - .build()) - .as(StepVerifier::create) - .expectNext(Route.builder() - .application("test-application-name") - .domain("test-shared-domain-name") - .host("test-route-entity-host") - .id("test-id") - .path("test-route-entity-path") - .service("test-service-instance-entityname") - .space("test-space-entity-name") - .build()) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .list(ListRoutesRequest.builder() + .level(Level.ORGANIZATION) + .build()) + .as(StepVerifier::create) + .expectNext(Route.builder() + .application("test-application-name") + .domain("test-shared-domain-name") + .host("test-route-entity-host") + .id("test-id") + .path("test-route-entity-path") + .service("test-service-instance-entityname") + .space("test-space-entity-name") + .build()) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -481,12 +506,12 @@ public void listCurrentOrganizationNoSpaceNoRoutes() { requestApplications(this.cloudFoundryClient, "test-id"); this.routes - .list(ListRoutesRequest.builder() - .level(Level.ORGANIZATION) - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .list(ListRoutesRequest.builder() + .level(Level.ORGANIZATION) + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -498,20 +523,20 @@ public void listCurrentSpace() { requestApplications(this.cloudFoundryClient, "test-route-id"); this.routes - .list(ListRoutesRequest.builder() - .level(Level.SPACE) - .build()) - .as(StepVerifier::create) - .expectNext(Route.builder() - .application("test-application-name") - .domain("test-shared-domain-name") - .host("test-route-entity-host") - .id("test-route-id") - .path("test-route-entity-path") - .space("test-space-entity-name") - .build()) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .list(ListRoutesRequest.builder() + .level(Level.SPACE) + .build()) + .as(StepVerifier::create) + .expectNext(Route.builder() + .application("test-application-name") + .domain("test-shared-domain-name") + .host("test-route-entity-host") + .id("test-route-id") + .path("test-route-entity-path") + .space("test-space-entity-name") + .build()) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -523,19 +548,19 @@ public void listCurrentSpaceNoPath() { requestApplications(this.cloudFoundryClient, "test-route-id"); this.routes - .list(ListRoutesRequest.builder() - .level(Level.SPACE) - .build()) - .as(StepVerifier::create) - .expectNext(Route.builder() - .application("test-application-name") - .domain("test-shared-domain-name") - .host("test-route-entity-host") - .id("test-route-id") - .space("test-space-entity-name") - .build()) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .list(ListRoutesRequest.builder() + .level(Level.SPACE) + .build()) + .as(StepVerifier::create) + .expectNext(Route.builder() + .application("test-application-name") + .domain("test-shared-domain-name") + .host("test-route-entity-host") + .id("test-route-id") + .space("test-space-entity-name") + .build()) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -544,19 +569,20 @@ public void mapRouteAssignedPort() { requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); requestRoutesEmpty(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, 9999); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, null, 9999, TEST_SPACE_ID); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, null, 9999, + TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .port(9999) - .build()) - .as(StepVerifier::create) - .expectNext(9999) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .port(9999) + .build()) + .as(StepVerifier::create) + .expectNext(9999) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -567,15 +593,15 @@ public void mapRouteExists() { requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -583,18 +609,20 @@ public void mapRouteInvalidApplicationName() { requestApplicationsEmpty(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", null, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", + null, "test-space-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Application test-application-name does not exist")) - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Application test-application-name does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -604,15 +632,16 @@ public void mapRouteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Domain test-domain does not exist")) - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Domain test-domain does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -620,18 +649,19 @@ public void mapRouteNoHost() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", null, "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, "test-path", null, TEST_SPACE_ID); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, "test-path", null, + TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -642,15 +672,15 @@ public void mapRoutePath() { requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -658,19 +688,20 @@ public void mapRoutePrivateDomain() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", null, TEST_SPACE_ID); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", + null, TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -679,19 +710,20 @@ public void mapRouteSharedDomain() { requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); requestRoutesEmpty(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", null, "test-path", null, TEST_SPACE_ID); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", null, "test-path", + null, TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -703,14 +735,14 @@ public void unmapRouteAssignedPort() { requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .port(9999) - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .port(9999) + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -719,14 +751,15 @@ public void unmapRouteInvalidApplicationName() { requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Application test-application-name does not exist")) - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Application test-application-name does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -736,14 +769,15 @@ public void unmapRouteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Domain test-domain does not exist")) - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Domain test-domain does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -753,15 +787,16 @@ public void unmapRouteInvalidRoute() { requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("Route for test-domain does not exist")) - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Route for test-domain does not exist")) + .verify(Duration.ofSeconds(5)); } @Test @@ -772,15 +807,15 @@ public void unmapRoutePrivateDomain() { requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } @Test @@ -792,15 +827,15 @@ public void unmapRouteSharedDomain() { requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder() + .applicationName("test-application-name") + .domain("test-domain") + .host("test-host") + .path("test-path") + .build()) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); } private static void requestApplications(CloudFoundryClient cloudFoundryClient, String routeId) { From e6fae74da723fde0900c9e80509548baf1abe8b0 Mon Sep 17 00:00:00 2001 From: radoslav-tomov Date: Thu, 7 Sep 2023 11:43:19 +0300 Subject: [PATCH 2/7] porting delete orphaned routes --- .../operations/routes/DefaultRoutes.java | 44 +++++++---- .../operations/AbstractOperationsTest.java | 6 ++ .../operations/routes/DefaultRoutesTest.java | 75 ++++--------------- 3 files changed, 53 insertions(+), 72 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java index e671857886..990cd7a40c 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java @@ -42,6 +42,7 @@ import org.cloudfoundry.client.v3.domains.CheckReservedRoutesRequest; import org.cloudfoundry.client.v3.organizations.ListOrganizationDomainsRequest; import org.cloudfoundry.client.v3.domains.DomainResource; +import org.cloudfoundry.client.v3.spaces.DeleteUnmappedRoutesRequest; import org.cloudfoundry.operations.util.OperationsLogging; import org.cloudfoundry.operations.v3.mapper.MapperUtils; import org.cloudfoundry.util.ExceptionUtils; @@ -158,22 +159,39 @@ public Mono delete(DeleteRouteRequest request) { @Override public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.spaceId) - .flatMapMany(function((cloudFoundryClient, spaceId) -> requestSpaceRoutes(cloudFoundryClient, spaceId) - .filter(route -> isRouteOrphan(ResourceUtils.getEntity(route))) - .map(ResourceUtils::getId) - .map(routeId -> Tuples.of(cloudFoundryClient, routeId)))) - .flatMap(function((cloudFoundryClient, routeId) -> getApplications(cloudFoundryClient, routeId) - .map(applicationResources -> Tuples.of(cloudFoundryClient, applicationResources, routeId)))) - .filter(predicate((cloudFoundryClient, applicationResources, - routeId) -> isApplicationOrphan(applicationResources))) - .flatMap(function((cloudFoundryClient, applicationResources, routeId) -> deleteRoute(cloudFoundryClient, - request.getCompletionTimeout(), routeId))) - .then() + return Mono.zip(this.cloudFoundryClient, this.spaceId) + .flatMap(function((client, spaceId) -> Mono.zip(this.cloudFoundryClient, + client.spacesV3().deleteUnmappedRoutes( + DeleteUnmappedRoutesRequest.builder().spaceId(spaceId) + .build())))) + .flatMap(function((client, job) -> JobUtils.waitForCompletion(client, + request.getCompletionTimeout(), job))) .transform(OperationsLogging.log("Delete Orphaned Routes")) .checkpoint(); + } + // @Override + // public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { + // return Mono + // .zip(this.cloudFoundryClient, this.spaceId) + // .flatMapMany(function((cloudFoundryClient, spaceId) -> + // requestSpaceRoutes(cloudFoundryClient, spaceId) + // .filter(route -> isRouteOrphan(ResourceUtils.getEntity(route))) + // .map(ResourceUtils::getId) + // .map(routeId -> Tuples.of(cloudFoundryClient, routeId)))) + // .flatMap(function((cloudFoundryClient, routeId) -> + // getApplications(cloudFoundryClient, routeId) + // .map(applicationResources -> Tuples.of(cloudFoundryClient, + // applicationResources, routeId)))) + // .filter(predicate((cloudFoundryClient, applicationResources, + // routeId) -> isApplicationOrphan(applicationResources))) + // .flatMap(function((cloudFoundryClient, applicationResources, routeId) -> + // deleteRoute(cloudFoundryClient, + // request.getCompletionTimeout(), routeId))) + // .then() + // .transform(OperationsLogging.log("Delete Orphaned Routes")) + // .checkpoint(); + // } @Override public Flux list(ListRoutesRequest request) { diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java index e2f2a3e428..ca6979a1f8 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java @@ -24,6 +24,7 @@ import org.cloudfoundry.client.v2.events.Events; import org.cloudfoundry.client.v2.featureflags.FeatureFlags; import org.cloudfoundry.client.v2.jobs.Jobs; +import org.cloudfoundry.client.v3.jobs.JobsV3; import org.cloudfoundry.client.v2.organizationquotadefinitions.OrganizationQuotaDefinitions; import org.cloudfoundry.client.v2.organizations.Organizations; import org.cloudfoundry.client.v3.organizations.OrganizationsV3; @@ -40,6 +41,7 @@ import org.cloudfoundry.client.v2.shareddomains.SharedDomains; import org.cloudfoundry.client.v2.spacequotadefinitions.SpaceQuotaDefinitions; import org.cloudfoundry.client.v2.spaces.Spaces; +import org.cloudfoundry.client.v3.spaces.SpacesV3; import org.cloudfoundry.client.v2.stacks.Stacks; import org.cloudfoundry.client.v2.userprovidedserviceinstances.UserProvidedServiceInstances; import org.cloudfoundry.client.v2.users.Users; @@ -101,6 +103,7 @@ public abstract class AbstractOperationsTest { protected final FeatureFlags featureFlags = mock(FeatureFlags.class, RETURNS_SMART_NULLS); protected final Jobs jobs = mock(Jobs.class, RETURNS_SMART_NULLS); + protected final JobsV3 jobsV3 = mock(JobsV3.class, RETURNS_SMART_NULLS); protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = mock(OrganizationQuotaDefinitions.class, RETURNS_SMART_NULLS); @@ -139,6 +142,7 @@ public abstract class AbstractOperationsTest { RETURNS_SMART_NULLS); protected final Spaces spaces = mock(Spaces.class, RETURNS_SMART_NULLS); + protected final SpacesV3 spacesV3 = mock(SpacesV3.class, RETURNS_SMART_NULLS); protected final Stacks stacks = mock(Stacks.class, RETURNS_SMART_NULLS); @@ -166,6 +170,7 @@ public final void mockClient() { when(this.cloudFoundryClient.events()).thenReturn(this.events); when(this.cloudFoundryClient.featureFlags()).thenReturn(this.featureFlags); when(this.cloudFoundryClient.jobs()).thenReturn(this.jobs); + when(this.cloudFoundryClient.jobsV3()).thenReturn(this.jobsV3); when(this.cloudFoundryClient.organizations()).thenReturn(this.organizations); when(this.cloudFoundryClient.organizationsV3()).thenReturn(this.organizationsV3); when(this.cloudFoundryClient.organizationQuotaDefinitions()).thenReturn(this.organizationQuotaDefinitions); @@ -182,6 +187,7 @@ public final void mockClient() { when(this.cloudFoundryClient.sharedDomains()).thenReturn(this.sharedDomains); when(this.cloudFoundryClient.spaceQuotaDefinitions()).thenReturn(this.spaceQuotaDefinitions); when(this.cloudFoundryClient.spaces()).thenReturn(this.spaces); + when(this.cloudFoundryClient.spacesV3()).thenReturn(this.spacesV3); when(this.cloudFoundryClient.stacks()).thenReturn(this.stacks); when(this.cloudFoundryClient.tasks()).thenReturn(this.tasks); when(this.cloudFoundryClient.userProvidedServiceInstances()).thenReturn(this.userProvidedServiceInstances); diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java index c0ad2667aa..c28ccf479d 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java @@ -68,6 +68,8 @@ import org.cloudfoundry.client.v3.domains.CheckReservedRoutesResponse; import org.cloudfoundry.client.v3.domains.DomainRelationships; import org.cloudfoundry.client.v3.domains.DomainResource; +import org.cloudfoundry.client.v3.spaces.DeleteUnmappedRoutesRequest; + import org.cloudfoundry.operations.AbstractOperationsTest; import org.cloudfoundry.operations.v3.mapper.MapperUtils; import org.junit.After; @@ -88,6 +90,8 @@ import java.util.Queue; import java.util.function.Supplier; +import javax.print.attribute.standard.JobState; + import static org.assertj.core.api.Assertions.assertThat; import static org.cloudfoundry.operations.TestObjects.fill; import static org.mockito.Mockito.when; @@ -102,6 +106,7 @@ public final class DefaultRoutesTest extends AbstractOperationsTest { private static final String TEST_PATH = "test-path"; private static final String TEST_HOST = "192.168.0,.1"; private static final Integer TEST_PORT = 8080; + private static final String TEST_JOB_ID = "test-job-id"; @Test public void checkRoute() { @@ -365,71 +370,23 @@ public void deleteInvalidRoute() { } @Test - public void deleteOrphanedRoutesAssociatedApplication() { - requestSpaceRoutes(this.cloudFoundryClient, TEST_SPACE_ID); - requestApplications(this.cloudFoundryClient, "test-route-id"); - - this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); - } - - @Test - public void deleteOrphanedRoutesAssociatedService() { - requestSpaceRoutesService(this.cloudFoundryClient, TEST_SPACE_ID); + public void deleteOrphanedRoutes() { + mockDeleteOrphanedRoutes(this.cloudFoundryClient); - this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build()) + this.routes.deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder().build()) .as(StepVerifier::create) .expectComplete() .verify(Duration.ofSeconds(5)); } - @Test - public void deleteOrphanedRoutesNoAssociations() { - requestSpaceRoutes(this.cloudFoundryClient, TEST_SPACE_ID); - requestApplicationsEmpty(this.cloudFoundryClient, "test-route-id"); - requestDeleteRoute(this.cloudFoundryClient, "test-route-id"); - requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); - - StepVerifier.withVirtualTime(() -> this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); - } - - @Test - public void deleteOrphanedRoutesNoAssociationsFailure() { - requestSpaceRoutes(this.cloudFoundryClient, TEST_SPACE_ID); - requestApplicationsEmpty(this.cloudFoundryClient, "test-route-id"); - requestDeleteRoute(this.cloudFoundryClient, "test-route-id"); - requestJobFailure(this.cloudFoundryClient, "test-job-entity-id"); - - StepVerifier.withVirtualTime(() -> this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(ClientV2Exception.class) - .hasMessage("test-error-details-errorCode(1): test-error-details-description")) - .verify(Duration.ofSeconds(5)); - } - - @Test - public void deleteOrphanedRoutesNoRoutes() { - requestSpaceRoutesEmpty(this.cloudFoundryClient, TEST_SPACE_ID); - - this.routes - .deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder() - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + private static void mockDeleteOrphanedRoutes(CloudFoundryClient cloudFoundryClient){ + when(cloudFoundryClient.spacesV3() + .deleteUnmappedRoutes(DeleteUnmappedRoutesRequest.builder() + .spaceId(TEST_SPACE_ID) + .build())) + .thenReturn(Mono.just(TEST_JOB_ID)); + when(cloudFoundryClient.jobsV3().get(org.cloudfoundry.client.v3.jobs.GetJobRequest.builder().jobId(TEST_JOB_ID).build())).thenReturn( + Mono.just(fill(org.cloudfoundry.client.v3.jobs.GetJobResponse.builder()).state(org.cloudfoundry.client.v3.jobs.JobState.COMPLETE).build())); } @Test From e04b9b943709b9f72d0c59285c397b236896c2df Mon Sep 17 00:00:00 2001 From: radoslav-tomov Date: Thu, 7 Sep 2023 13:04:12 +0300 Subject: [PATCH 3/7] cleanup --- .../operations/routes/DefaultRoutes.java | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java index 990cd7a40c..f85e103ff9 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java @@ -170,28 +170,6 @@ public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { .checkpoint(); } - // @Override - // public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { - // return Mono - // .zip(this.cloudFoundryClient, this.spaceId) - // .flatMapMany(function((cloudFoundryClient, spaceId) -> - // requestSpaceRoutes(cloudFoundryClient, spaceId) - // .filter(route -> isRouteOrphan(ResourceUtils.getEntity(route))) - // .map(ResourceUtils::getId) - // .map(routeId -> Tuples.of(cloudFoundryClient, routeId)))) - // .flatMap(function((cloudFoundryClient, routeId) -> - // getApplications(cloudFoundryClient, routeId) - // .map(applicationResources -> Tuples.of(cloudFoundryClient, - // applicationResources, routeId)))) - // .filter(predicate((cloudFoundryClient, applicationResources, - // routeId) -> isApplicationOrphan(applicationResources))) - // .flatMap(function((cloudFoundryClient, applicationResources, routeId) -> - // deleteRoute(cloudFoundryClient, - // request.getCompletionTimeout(), routeId))) - // .then() - // .transform(OperationsLogging.log("Delete Orphaned Routes")) - // .checkpoint(); - // } @Override public Flux list(ListRoutesRequest request) { @@ -290,12 +268,6 @@ private static Mono> getApplicationNames(CloudFoundryClient cloudFo .collectList(); } - private static Mono> getApplications(CloudFoundryClient cloudFoundryClient, - String routeId) { - return requestApplications(cloudFoundryClient, routeId) - .collectList(); - } - private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, String domain) { return getDomains(cloudFoundryClient, organizationId, domain) @@ -407,10 +379,6 @@ private static Mono getSpaceName(Map spaces, String spac return Mono.just(spaces.get(spaceId)); } - private static boolean isApplicationOrphan(List applications) { - return applications.isEmpty(); - } - private static boolean isIdentical(String s, String t) { return s == null ? t == null : s.equals(t); } @@ -605,8 +573,4 @@ private static Route toRoute(List applications, String domain, RouteReso return builder.build(); } - private boolean isRouteOrphan(RouteEntity entity) { - return entity.getServiceInstanceId() == null || entity.getServiceInstanceId().isEmpty(); - } - } From 29ee08e4dff3a279f0ac7b23a702e5ca2b111823 Mon Sep 17 00:00:00 2001 From: radoslav-tomov Date: Thu, 7 Sep 2023 15:35:08 +0300 Subject: [PATCH 4/7] cleaning up --- .../operations/routes/DefaultRoutes.java | 1047 +++++++++-------- .../operations/v3/mapper/MapperUtils.java | 167 --- .../operations/routes/DefaultRoutesTest.java | 2 +- 3 files changed, 542 insertions(+), 674 deletions(-) delete mode 100644 cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java index f85e103ff9..b0831ec834 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java @@ -44,7 +44,6 @@ import org.cloudfoundry.client.v3.domains.DomainResource; import org.cloudfoundry.client.v3.spaces.DeleteUnmappedRoutesRequest; import org.cloudfoundry.operations.util.OperationsLogging; -import org.cloudfoundry.operations.v3.mapper.MapperUtils; import org.cloudfoundry.util.ExceptionUtils; import org.cloudfoundry.util.JobUtils; import org.cloudfoundry.util.PaginationUtils; @@ -67,510 +66,546 @@ public final class DefaultRoutes implements Routes { - private final Mono cloudFoundryClient; - - private final Mono organizationId; - - private final Mono spaceId; - - public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, - Mono spaceId) { - this.cloudFoundryClient = cloudFoundryClient; - this.organizationId = organizationId; - this.spaceId = spaceId; - } - - @Override - public Mono check(CheckRouteRequest request) { - return Mono.zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((client, organizationId) -> Mono.zip(this.cloudFoundryClient, - getOptionalDomainIdByName( - client, organizationId, - request.getDomain())))) - .flatMap(function((client, domainId) -> routeExists(client, domainId, request.getHost(), - request.getPath()))) - .defaultIfEmpty(false) - .transform(OperationsLogging.log("Check Route Exists")) - .checkpoint(); - } - - private static Mono routeExists(CloudFoundryClient cloudFoundryClient, String domainId, - String host, - String path) { - return cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() - .domainId(domainId) - .host(host) - .path(path) - .build()) - .flatMap(response -> Mono.just(response.getMatchingRoute())); - } - - private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, - String organizationId, - String domain) { - return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) - .singleOrEmpty() - .map(resource -> resource.getId()); - } - - private static Flux listDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String[] domainNamesFilter) { - return PaginationUtils - .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( - ListOrganizationDomainsRequest.builder() - .names(domainNamesFilter) - .page(page) - .organizationId(organizationId).build())); - } - - @Override - public Mono create(CreateRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), - getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) - .flatMap(function((cloudFoundryClient, spaceId, - domainId) -> requestCreateRoute(cloudFoundryClient, domainId, request.getHost(), - request.getPath(), request.getPort(), request.getRandomPort(), spaceId) - .map(ResourceUtils::getEntity) - .flatMap(routeEntity -> Mono.justOrEmpty(routeEntity.getPort())))) - .transform(OperationsLogging.log("Create Route")) - .checkpoint(); - } - - @Override - public Mono delete(DeleteRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) - .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( - Mono.just(cloudFoundryClient), - Mono.just(request.getCompletionTimeout()), - getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), domainId, - request.getPath(), request.getPort())))) - .flatMap(function(DefaultRoutes::deleteRoute)) - .transform(OperationsLogging.log("Delete Route")) - .checkpoint(); - } - - @Override - public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { - return Mono.zip(this.cloudFoundryClient, this.spaceId) - .flatMap(function((client, spaceId) -> Mono.zip(this.cloudFoundryClient, - client.spacesV3().deleteUnmappedRoutes( - DeleteUnmappedRoutesRequest.builder().spaceId(spaceId) - .build())))) - .flatMap(function((client, job) -> JobUtils.waitForCompletion(client, - request.getCompletionTimeout(), job))) - .transform(OperationsLogging.log("Delete Orphaned Routes")) - .checkpoint(); - - } - - @Override - public Flux list(ListRoutesRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getAllDomains(cloudFoundryClient, organizationId), - getAllSpaces(cloudFoundryClient, organizationId)))) - .flatMapMany(function((cloudFoundryClient, domains, - spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, this.spaceId) - .map(route -> Tuples.of(cloudFoundryClient, domains, route, spaces)))) - .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono - .zip( - getApplicationNames(cloudFoundryClient, ResourceUtils.getId(route)), - getDomainName(domains, ResourceUtils.getEntity(route).getDomainId()), - Mono.just(route), - getServiceName(cloudFoundryClient, ResourceUtils.getEntity(route)), - getSpaceName(spaces, ResourceUtils.getEntity(route).getSpaceId())))) - .map(function(DefaultRoutes::toRoute)) - .transform(OperationsLogging.log("List Routes")) - .checkpoint(); - } - - @Override - public Mono map(MapRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, request.getDomain(), - request.getHost(), request.getPath(), request.getPort(), request.getRandomPort()), - getApplicationId(cloudFoundryClient, request.getApplicationName(), spaceId)))) - .flatMap(function((cloudFoundryClient, routeResource, applicationId) -> requestAssociateRoute( - cloudFoundryClient, applicationId, ResourceUtils.getId(routeResource)))) - .then(Mono.justOrEmpty(request.getPort())) - .transform(OperationsLogging.log("Map Route")) - .checkpoint(); - } - - @Override - public Mono unmap(UnmapRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getApplicationId(cloudFoundryClient, request.getApplicationName(), spaceId), - getDomainId(cloudFoundryClient, organizationId, request.getDomain()) - .flatMap(domainId -> getRouteId(cloudFoundryClient, request.getHost(), - request.getDomain(), domainId, request.getPath(), request.getPort()))))) - .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) - .transform(OperationsLogging.log("Unmap Route")) - .checkpoint(); - } - - private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, Duration completionTimeout, - String routeId) { - return requestDeleteRoute(cloudFoundryClient, routeId) - .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, completionTimeout, job)); - } - - private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return requestAllPrivateDomains(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName())) - .mergeWith(requestAllSharedDomains(cloudFoundryClient) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName()))) - .collectMap(function((id, name) -> id), function((id, name) -> name)); - } - - private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return requestAllSpaces(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), ResourceUtils.getEntity(resource).getName())) - .collectMap(function((id, name) -> id), function((id, name) -> name)); - } - - private static Mono getApplication(CloudFoundryClient cloudFoundryClient, String application, - String spaceId) { - return requestApplications(cloudFoundryClient, application, spaceId) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Application %s does not exist", application)); - } - - private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, - String spaceId) { - return getApplication(cloudFoundryClient, application, spaceId) - .map(ResourceUtils::getId); - } - - private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, String routeId) { - return requestApplications(cloudFoundryClient, routeId) - .map(resource -> ResourceUtils.getEntity(resource).getName()) - .collectList(); - } - - private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomains(cloudFoundryClient, organizationId, domain) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Domain %s does not exist", domain)); - } - - private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomain(cloudFoundryClient, organizationId, domain) - .map(ResourceUtils::getId); - } - - private static Mono getDomainName(Map domains, String domainId) { - return Mono.just(domains.get(domainId)); - } - - private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return requestPrivateDomains(cloudFoundryClient, organizationId, domain) - .map((Function>) in -> in) - .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); - } - - private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, - String organizationId, String spaceId, String domain, String host, String path, Integer port, - Boolean randomPort) { - if (randomPort != null) { - return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, path, port, randomPort, - spaceId)); - } - - return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) - .cast(AbstractRouteResource.class) - .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, path, port, randomPort, - spaceId))); - } - - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String domain, - String host, String path, Integer port) { - return getRoute(cloudFoundryClient, domainId, host, path, port) - .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); - } - - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, - String path, Integer port) { - if (port != null) { - return requestRoutes(cloudFoundryClient, domainId, null, null, port) - .singleOrEmpty(); - } else { - return requestRoutes(cloudFoundryClient, domainId, host, path, port) - .filter(resource -> isIdentical(nullSafe(host), ResourceUtils.getEntity(resource).getHost())) - .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), - ResourceUtils.getEntity(resource).getPath())) - .singleOrEmpty(); - } - } - - private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, - String domainId, String path, Integer port) { - return getRoute(cloudFoundryClient, domainId, domain, host, path, port) - .map(ResourceUtils::getId); - } - - private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, - Mono organizationId, Mono spaceId) { - if (Level.ORGANIZATION == request.getLevel()) { - return organizationId - .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, - builder -> builder.organizationId(organizationId1))); - } else { - return spaceId - .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); - } - } - - private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, - String serviceInstanceId, String spaceId) { - return requestListSpaceServiceInstances(cloudFoundryClient, spaceId) - .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) - .single() - .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); - } - - private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) { - return Mono.justOrEmpty(route.getServiceInstanceId()) - .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, serviceInstanceId, - route.getSpaceId())) - .defaultIfEmpty(Optional.empty()); - } - - private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return requestSpaces(cloudFoundryClient, organizationId, space) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); - } - - private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, String organizationId, String space) { - return getSpace(cloudFoundryClient, organizationId, space) - .map(ResourceUtils::getId); - } - - private static Mono getSpaceName(Map spaces, String spaceId) { - return Mono.just(spaces.get(spaceId)); - } - - private static boolean isIdentical(String s, String t) { - return s == null ? t == null : s.equals(t); - } - - private static String nullSafe(String host) { - return host == null ? "" : host; - } - - private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); - } - - private static Flux requestAllSharedDomains(CloudFoundryClient cloudFoundryClient) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .page(page) - .build())); - } - - private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, String organizationId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); - } - - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, - String routeId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .listApplications(ListRouteApplicationsRequest.builder() - .routeId(routeId) - .page(page) - .build())); - } - - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, - String application, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listApplications(ListSpaceApplicationsRequest.builder() - .name(application) - .page(page) - .spaceId(spaceId) - .build())); - } - - private static Mono requestAssociateRoute(CloudFoundryClient cloudFoundryClient, - String applicationId, String routeId) { - return cloudFoundryClient.applicationsV2() - .associateRoute(AssociateApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, String domainId, - String host, String path, Integer port, Boolean randomPort, String spaceId) { - - org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest - .builder(); - - if (randomPort != null && randomPort) { - builder.generatePort(true); - } else if (port != null) { - builder.port(port); - } else { - builder.host(host); - builder.path(path); - } - - return cloudFoundryClient.routes() - .create(builder - .domainId(domainId) - .spaceId(spaceId) - .build()); - } - - private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, String routeId) { - return cloudFoundryClient.routes() - .delete(org.cloudfoundry.client.v2.routes.DeleteRouteRequest.builder() - .async(true) - .routeId(routeId) - .build()); - } - - private static Flux requestListSpaceServiceInstances( - CloudFoundryClient cloudFoundryClient, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listServiceInstances(ListSpaceServiceInstancesRequest.builder() - .page(page) - .returnUserProvidedServiceInstances(true) - .spaceId(spaceId) - .build())); - } - - private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String domain) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .name(domain) - .page(page) - .build())); - } - - private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, - String applicationId, String routeId) { - return cloudFoundryClient.applicationsV2() - .removeRoute(RemoveApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, - UnaryOperator modifier) { - - org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier - .apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); - - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .list(listBuilder - .page(page) - .build())); - } - - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, - String host, String path, Integer port) { - return requestRoutes(cloudFoundryClient, builder -> builder - .domainId(domainId) - .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) - .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) - .port(Optional.ofNullable(port).orElse(null))); - } - - private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, - String domain) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .name(domain) - .page(page) - .build())); - } - - private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listRoutes(ListSpaceRoutesRequest.builder() - .spaceId(spaceId) - .page(page) - .build())); - } - - private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .name(space) - .page(page) - .build())); - } - - private static Route toRoute(List applications, String domain, RouteResource resource, - Optional service, String space) { - RouteEntity entity = ResourceUtils.getEntity(resource); - Route.Builder builder = Route.builder() - .applications(applications) - .domain(domain) - .host(entity.getHost()) - .id(ResourceUtils.getId(resource)) - .path(entity.getPath()) - .space(space); - - service.ifPresent(builder::service); - - return builder.build(); - } + private final Mono cloudFoundryClient; + + private final Mono organizationId; + + private final Mono spaceId; + + public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, + Mono spaceId) { + this.cloudFoundryClient = cloudFoundryClient; + this.organizationId = organizationId; + this.spaceId = spaceId; + } + + @Override + public Mono check(CheckRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((client, organizationId) -> Mono.zip(this.cloudFoundryClient, + getOptionalDomainIdByName( + client, organizationId, + request.getDomain())))) + .flatMap(function((client, domainId) -> routeExists(client, domainId, request.getHost(), + request.getPath()))) + .defaultIfEmpty(false) + .transform(OperationsLogging.log("Check Route Exists")) + .checkpoint(); + } + + private static Mono routeExists(CloudFoundryClient cloudFoundryClient, String domainId, + String host, + String path) { + return cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() + .domainId(domainId) + .host(host) + .path(path) + .build()) + .flatMap(response -> Mono.just(response.getMatchingRoute())); + } + + private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, + String organizationId, + String domain) { + return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) + .singleOrEmpty() + .map(resource -> resource.getId()); + } + + private static Flux listDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String[] domainNamesFilter) { + return PaginationUtils + .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( + ListOrganizationDomainsRequest.builder() + .names(domainNamesFilter) + .page(page) + .organizationId(organizationId).build())); + } + + @Override + public Mono create(CreateRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), + getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) + .flatMap(function((cloudFoundryClient, spaceId, + domainId) -> requestCreateRoute(cloudFoundryClient, domainId, + request.getHost(), + request.getPath(), request.getPort(), + request.getRandomPort(), spaceId) + .map(ResourceUtils::getEntity) + .flatMap(routeEntity -> Mono + .justOrEmpty(routeEntity.getPort())))) + .transform(OperationsLogging.log("Create Route")) + .checkpoint(); + } + + @Override + public Mono delete(DeleteRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) + .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( + Mono.just(cloudFoundryClient), + Mono.just(request.getCompletionTimeout()), + getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), + domainId, + request.getPath(), request.getPort())))) + .flatMap(function(DefaultRoutes::deleteRoute)) + .transform(OperationsLogging.log("Delete Route")) + .checkpoint(); + } + + @Override + public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { + return Mono.zip(this.cloudFoundryClient, this.spaceId) + .flatMap(function((client, spaceId) -> Mono.zip(this.cloudFoundryClient, + client.spacesV3().deleteUnmappedRoutes( + DeleteUnmappedRoutesRequest.builder().spaceId(spaceId) + .build())))) + .flatMap(function((client, job) -> JobUtils.waitForCompletion(client, + request.getCompletionTimeout(), job))) + .transform(OperationsLogging.log("Delete Orphaned Routes")) + .checkpoint(); + + } + + @Override + public Flux list(ListRoutesRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getAllDomains(cloudFoundryClient, organizationId), + getAllSpaces(cloudFoundryClient, organizationId)))) + .flatMapMany(function((cloudFoundryClient, domains, + spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, + this.spaceId) + .map(route -> Tuples.of(cloudFoundryClient, domains, + route, spaces)))) + .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono + .zip( + getApplicationNames(cloudFoundryClient, + ResourceUtils.getId(route)), + getDomainName(domains, + ResourceUtils.getEntity(route) + .getDomainId()), + Mono.just(route), + getServiceName(cloudFoundryClient, + ResourceUtils.getEntity(route)), + getSpaceName(spaces, + ResourceUtils.getEntity(route) + .getSpaceId())))) + .map(function(DefaultRoutes::toRoute)) + .transform(OperationsLogging.log("List Routes")) + .checkpoint(); + } + + @Override + public Mono map(MapRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) + .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, + request.getDomain(), + request.getHost(), request.getPath(), request.getPort(), + request.getRandomPort()), + getApplicationId(cloudFoundryClient, request.getApplicationName(), + spaceId)))) + .flatMap(function((cloudFoundryClient, routeResource, + applicationId) -> requestAssociateRoute( + cloudFoundryClient, applicationId, + ResourceUtils.getId(routeResource)))) + .then(Mono.justOrEmpty(request.getPort())) + .transform(OperationsLogging.log("Map Route")) + .checkpoint(); + } + + @Override + public Mono unmap(UnmapRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) + .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getApplicationId(cloudFoundryClient, request.getApplicationName(), + spaceId), + getDomainId(cloudFoundryClient, organizationId, request.getDomain()) + .flatMap(domainId -> getRouteId(cloudFoundryClient, + request.getHost(), + request.getDomain(), domainId, + request.getPath(), + request.getPort()))))) + .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) + .transform(OperationsLogging.log("Unmap Route")) + .checkpoint(); + } + + private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, Duration completionTimeout, + String routeId) { + return requestDeleteRoute(cloudFoundryClient, routeId) + .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, completionTimeout, job)); + } + + private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return requestAllPrivateDomains(cloudFoundryClient, organizationId) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName())) + .mergeWith(requestAllSharedDomains(cloudFoundryClient) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName()))) + .collectMap(function((id, name) -> id), function((id, name) -> name)); + } + + private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return requestAllSpaces(cloudFoundryClient, organizationId) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName())) + .collectMap(function((id, name) -> id), function((id, name) -> name)); + } + + private static Mono getApplication(CloudFoundryClient cloudFoundryClient, + String application, + String spaceId) { + return requestApplications(cloudFoundryClient, application, spaceId) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Application %s does not exist", + application)); + } + + private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, + String spaceId) { + return getApplication(cloudFoundryClient, application, spaceId) + .map(ResourceUtils::getId); + } + + private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, String routeId) { + return requestApplications(cloudFoundryClient, routeId) + .map(resource -> ResourceUtils.getEntity(resource).getName()) + .collectList(); + } + + private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return getDomains(cloudFoundryClient, organizationId, domain) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Domain %s does not exist", + domain)); + } + + private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return getDomain(cloudFoundryClient, organizationId, domain) + .map(ResourceUtils::getId); + } + + private static Mono getDomainName(Map domains, String domainId) { + return Mono.just(domains.get(domainId)); + } + + private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return requestPrivateDomains(cloudFoundryClient, organizationId, domain) + .map((Function>) in -> in) + .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); + } + + private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, + String organizationId, String spaceId, String domain, String host, String path, Integer port, + Boolean randomPort) { + if (randomPort != null) { + return getDomainId(cloudFoundryClient, organizationId, domain) + .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, + path, port, randomPort, + spaceId)); + } + + return getDomainId(cloudFoundryClient, organizationId, domain) + .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) + .cast(AbstractRouteResource.class) + .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, + path, port, randomPort, + spaceId))); + } + + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, + String domain, + String host, String path, Integer port) { + return getRoute(cloudFoundryClient, domainId, host, path, port) + .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); + } + + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, + String path, Integer port) { + if (port != null) { + return requestRoutes(cloudFoundryClient, domainId, null, null, port) + .singleOrEmpty(); + } else { + return requestRoutes(cloudFoundryClient, domainId, host, path, port) + .filter(resource -> isIdentical(nullSafe(host), + ResourceUtils.getEntity(resource).getHost())) + .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), + ResourceUtils.getEntity(resource).getPath())) + .singleOrEmpty(); + } + } + + private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, + String domainId, String path, Integer port) { + return getRoute(cloudFoundryClient, domainId, domain, host, path, port) + .map(ResourceUtils::getId); + } + + private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, + Mono organizationId, Mono spaceId) { + if (Level.ORGANIZATION == request.getLevel()) { + return organizationId + .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, + builder -> builder.organizationId(organizationId1))); + } else { + return spaceId + .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); + } + } + + private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, + String serviceInstanceId, String spaceId) { + return requestListSpaceServiceInstances(cloudFoundryClient, spaceId) + .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) + .single() + .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); + } + + private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) { + return Mono.justOrEmpty(route.getServiceInstanceId()) + .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, + serviceInstanceId, + route.getSpaceId())) + .defaultIfEmpty(Optional.empty()); + } + + private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { + return requestSpaces(cloudFoundryClient, organizationId, space) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); + } + + private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { + return getSpace(cloudFoundryClient, organizationId, space) + .map(ResourceUtils::getId); + } + + private static Mono getSpaceName(Map spaces, String spaceId) { + return Mono.just(spaces.get(spaceId)); + } + + private static boolean isIdentical(String s, String t) { + return s == null ? t == null : s.equals(t); + } + + private static String nullSafe(String host) { + return host == null ? "" : host; + } + + private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId) + .page(page) + .build())); + } + + private static Flux requestAllSharedDomains(CloudFoundryClient cloudFoundryClient) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() + .list(ListSharedDomainsRequest.builder() + .page(page) + .build())); + } + + private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .page(page) + .build())); + } + + private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, + String routeId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.routes() + .listApplications(ListRouteApplicationsRequest.builder() + .routeId(routeId) + .page(page) + .build())); + } + + private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, + String application, String spaceId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listApplications(ListSpaceApplicationsRequest.builder() + .name(application) + .page(page) + .spaceId(spaceId) + .build())); + } + + private static Mono requestAssociateRoute( + CloudFoundryClient cloudFoundryClient, + String applicationId, String routeId) { + return cloudFoundryClient.applicationsV2() + .associateRoute(AssociateApplicationRouteRequest.builder() + .applicationId(applicationId) + .routeId(routeId) + .build()); + } + + private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, + String domainId, + String host, String path, Integer port, Boolean randomPort, String spaceId) { + + org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest + .builder(); + + if (randomPort != null && randomPort) { + builder.generatePort(true); + } else if (port != null) { + builder.port(port); + } else { + builder.host(host); + builder.path(path); + } + + return cloudFoundryClient.routes() + .create(builder + .domainId(domainId) + .spaceId(spaceId) + .build()); + } + + private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, + String routeId) { + return cloudFoundryClient.routes() + .delete(org.cloudfoundry.client.v2.routes.DeleteRouteRequest.builder() + .async(true) + .routeId(routeId) + .build()); + } + + private static Flux requestListSpaceServiceInstances( + CloudFoundryClient cloudFoundryClient, String spaceId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listServiceInstances(ListSpaceServiceInstancesRequest.builder() + .page(page) + .returnUserProvidedServiceInstances(true) + .spaceId(spaceId) + .build())); + } + + private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId) + .name(domain) + .page(page) + .build())); + } + + private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, + String applicationId, String routeId) { + return cloudFoundryClient.applicationsV2() + .removeRoute(RemoveApplicationRouteRequest.builder() + .applicationId(applicationId) + .routeId(routeId) + .build()); + } + + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, + UnaryOperator modifier) { + + org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier + .apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); + + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.routes() + .list(listBuilder + .page(page) + .build())); + } + + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, + String host, String path, Integer port) { + return requestRoutes(cloudFoundryClient, builder -> builder + .domainId(domainId) + .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) + .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) + .port(Optional.ofNullable(port).orElse(null))); + } + + private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, + String domain) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() + .list(ListSharedDomainsRequest.builder() + .name(domain) + .page(page) + .build())); + } + + private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, String spaceId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listRoutes(ListSpaceRoutesRequest.builder() + .spaceId(spaceId) + .page(page) + .build())); + } + + private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .name(space) + .page(page) + .build())); + } + + private static Route toRoute(List applications, String domain, RouteResource resource, + Optional service, String space) { + RouteEntity entity = ResourceUtils.getEntity(resource); + Route.Builder builder = Route.builder() + .applications(applications) + .domain(domain) + .host(entity.getHost()) + .id(ResourceUtils.getId(resource)) + .path(entity.getPath()) + .space(space); + + service.ifPresent(builder::service); + + return builder.build(); + } } diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java deleted file mode 100644 index 2baaea011d..0000000000 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/v3/mapper/MapperUtils.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2013-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.cloudfoundry.operations.v3.mapper; - -import org.cloudfoundry.Nullable; -import org.cloudfoundry.client.CloudFoundryClient; -import org.immutables.value.Value; -import org.cloudfoundry.client.v3.applications.ListApplicationsRequest; -import org.cloudfoundry.client.v3.applications.ApplicationResource; -import org.cloudfoundry.client.v3.spaces.ListSpacesRequest; -import org.cloudfoundry.client.v3.spaces.SpaceResource; -import org.cloudfoundry.client.v3.routes.RouteRelationships; -import org.cloudfoundry.client.v3.routes.RouteResource; -import org.cloudfoundry.client.v3.ToOneRelationship; -import org.cloudfoundry.client.v3.organizations.ListOrganizationDomainsRequest; -import org.cloudfoundry.client.v3.domains.DomainResource; -import org.cloudfoundry.client.v3.Relationship; -import org.cloudfoundry.util.PaginationUtils; -import org.cloudfoundry.util.ExceptionUtils; - -import reactor.core.publisher.Mono; -import reactor.core.publisher.Flux; -import java.util.NoSuchElementException; - -public final class MapperUtils { - - public static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain, - String host, Integer port, String path) { - - return getRoute(cloudFoundryClient, organizationId, domain, host, port, path, null) - .flatMap(route -> Mono.just(route.getId())); - } - - public static Mono getRoute(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain, - String host, Integer port, String path, String applicationId) { - - return Mono.just(domain) - .flatMap(name -> getDomainIdByName(cloudFoundryClient, organizationId, name)) - .flatMap(domainId -> listRoutes(cloudFoundryClient, - new String[] { organizationId }, null, new String[] { path }, - new String[] { host }, new int[] { port }, - new String[] { domainId }, - (applicationId != null) ? new String[] { applicationId } - : new String[] {}) - .single() - .switchIfEmpty(ExceptionUtils.illegalArgument( - "Route for %s does not exist", - domain))); - } - - public static Mono getSpaceIdByName(CloudFoundryClient cloudFoundryClient, String organizationId, - String spaceName) { - return listSpaces(cloudFoundryClient, organizationId, new String[] { spaceName }) - .flatMap(space -> Mono.just(space.getId())); - } - - public static Mono getDomainIdByName(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomain(cloudFoundryClient, organizationId, domain) - .map(resource -> resource.getId()); - } - - public static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, - String organizationId, - String domain) { - return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) - .singleOrEmpty() - .map(resource -> resource.getId()); - } - - public static Mono listSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, - String[] spacesNameFilter) { - return PaginationUtils.requestClientV3Resources(page -> cloudFoundryClient.spacesV3() - .list(ListSpacesRequest.builder() - .organizationId(organizationId) - .names(spacesNameFilter) - .page(page) - .build())) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument( - "Space %s does not exist", - String.join(",", spacesNameFilter))); - - } - - private static Mono getDomain(CloudFoundryClient cloudFoundryClient, - String organizationId, String domainName) { - return listDomains(cloudFoundryClient, organizationId, new String[] { domainName }) - .single() - .onErrorResume(NoSuchElementException.class, t -> ExceptionUtils - .illegalArgument("Domain %s does not exist", domainName)); - - } - - public static Flux listDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String[] domainNamesFilter) { - return PaginationUtils - .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( - ListOrganizationDomainsRequest.builder() - .names(domainNamesFilter) - .page(page) - .organizationId(organizationId).build())); - } - - public static Flux listRoutes(CloudFoundryClient cloudFoundryClient, - String[] organizationIdsFilter, String[] spaceIdFilter, String[] pathsFilter, - String[] hostsFilter, - int[] portsFilter, String[] domainIdFilter, String[] applicationIds) { - - return PaginationUtils - .requestClientV3Resources(page -> cloudFoundryClient.routesV3() - .list(org.cloudfoundry.client.v3.routes.ListRoutesRequest.builder() - .page(page) - .applicationIds(applicationIds) - .spaceIds(spaceIdFilter) - .organizationIds(organizationIdsFilter) - .ports(portsFilter) - .hosts(hostsFilter) - .paths(pathsFilter) - .domainIds(domainIdFilter) - .build())); - } - - private static Flux listApplications(CloudFoundryClient cloudFoundryClient, - String[] nameFilter, String[] organizationIdsFilter, String[] spaceIdsFilter) { - return PaginationUtils - .requestClientV3Resources(page -> cloudFoundryClient.applicationsV3() - .list(ListApplicationsRequest.builder() - .names(nameFilter) - .page(page) - .spaceIds(spaceIdsFilter) - .organizationIds(organizationIdsFilter) - .build())); - } - - public static Mono getApplicationIdByName(CloudFoundryClient cloudFoundryClient, - String name, String spaceId, String organizationId) { - - return listApplications(cloudFoundryClient, - new String[] { name }, - new String[] { organizationId }, - new String[] { spaceId }) - .single() - .map(app -> app.getId()) - .switchIfEmpty(ExceptionUtils.illegalArgument( - "Application with name %s does not exist", - name)); - } - -} diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java index c28ccf479d..c8bce7f945 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java @@ -71,7 +71,7 @@ import org.cloudfoundry.client.v3.spaces.DeleteUnmappedRoutesRequest; import org.cloudfoundry.operations.AbstractOperationsTest; -import org.cloudfoundry.operations.v3.mapper.MapperUtils; + import org.junit.After; import org.junit.Before; import org.junit.Test; From 666e3fefb5064bc7050d2d754fc858a99a791500 Mon Sep 17 00:00:00 2001 From: radoslav-tomov Date: Thu, 7 Sep 2023 16:09:13 +0300 Subject: [PATCH 5/7] pushing delete route --- .../operations/routes/DefaultRoutes.java | 1083 +++++++++-------- .../operations/AbstractOperationsTest.java | 115 +- .../operations/routes/DefaultRoutesTest.java | 124 +- 3 files changed, 616 insertions(+), 706 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java index b0831ec834..110369293e 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java @@ -66,546 +66,547 @@ public final class DefaultRoutes implements Routes { - private final Mono cloudFoundryClient; - - private final Mono organizationId; - - private final Mono spaceId; - - public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, - Mono spaceId) { - this.cloudFoundryClient = cloudFoundryClient; - this.organizationId = organizationId; - this.spaceId = spaceId; - } - - @Override - public Mono check(CheckRouteRequest request) { - return Mono.zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((client, organizationId) -> Mono.zip(this.cloudFoundryClient, - getOptionalDomainIdByName( - client, organizationId, - request.getDomain())))) - .flatMap(function((client, domainId) -> routeExists(client, domainId, request.getHost(), - request.getPath()))) - .defaultIfEmpty(false) - .transform(OperationsLogging.log("Check Route Exists")) - .checkpoint(); - } - - private static Mono routeExists(CloudFoundryClient cloudFoundryClient, String domainId, - String host, - String path) { - return cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() - .domainId(domainId) - .host(host) - .path(path) - .build()) - .flatMap(response -> Mono.just(response.getMatchingRoute())); - } - - private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, - String organizationId, - String domain) { - return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) - .singleOrEmpty() - .map(resource -> resource.getId()); - } - - private static Flux listDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String[] domainNamesFilter) { - return PaginationUtils - .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( - ListOrganizationDomainsRequest.builder() - .names(domainNamesFilter) - .page(page) - .organizationId(organizationId).build())); - } - - @Override - public Mono create(CreateRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), - getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) - .flatMap(function((cloudFoundryClient, spaceId, - domainId) -> requestCreateRoute(cloudFoundryClient, domainId, - request.getHost(), - request.getPath(), request.getPort(), - request.getRandomPort(), spaceId) - .map(ResourceUtils::getEntity) - .flatMap(routeEntity -> Mono - .justOrEmpty(routeEntity.getPort())))) - .transform(OperationsLogging.log("Create Route")) - .checkpoint(); - } - - @Override - public Mono delete(DeleteRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) - .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( - Mono.just(cloudFoundryClient), - Mono.just(request.getCompletionTimeout()), - getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), - domainId, - request.getPath(), request.getPort())))) - .flatMap(function(DefaultRoutes::deleteRoute)) - .transform(OperationsLogging.log("Delete Route")) - .checkpoint(); - } - - @Override - public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { - return Mono.zip(this.cloudFoundryClient, this.spaceId) - .flatMap(function((client, spaceId) -> Mono.zip(this.cloudFoundryClient, - client.spacesV3().deleteUnmappedRoutes( - DeleteUnmappedRoutesRequest.builder().spaceId(spaceId) - .build())))) - .flatMap(function((client, job) -> JobUtils.waitForCompletion(client, - request.getCompletionTimeout(), job))) - .transform(OperationsLogging.log("Delete Orphaned Routes")) - .checkpoint(); - - } - - @Override - public Flux list(ListRoutesRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getAllDomains(cloudFoundryClient, organizationId), - getAllSpaces(cloudFoundryClient, organizationId)))) - .flatMapMany(function((cloudFoundryClient, domains, - spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, - this.spaceId) - .map(route -> Tuples.of(cloudFoundryClient, domains, - route, spaces)))) - .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono - .zip( - getApplicationNames(cloudFoundryClient, - ResourceUtils.getId(route)), - getDomainName(domains, - ResourceUtils.getEntity(route) - .getDomainId()), - Mono.just(route), - getServiceName(cloudFoundryClient, - ResourceUtils.getEntity(route)), - getSpaceName(spaces, - ResourceUtils.getEntity(route) - .getSpaceId())))) - .map(function(DefaultRoutes::toRoute)) - .transform(OperationsLogging.log("List Routes")) - .checkpoint(); - } - - @Override - public Mono map(MapRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, - request.getDomain(), - request.getHost(), request.getPath(), request.getPort(), - request.getRandomPort()), - getApplicationId(cloudFoundryClient, request.getApplicationName(), - spaceId)))) - .flatMap(function((cloudFoundryClient, routeResource, - applicationId) -> requestAssociateRoute( - cloudFoundryClient, applicationId, - ResourceUtils.getId(routeResource)))) - .then(Mono.justOrEmpty(request.getPort())) - .transform(OperationsLogging.log("Map Route")) - .checkpoint(); - } - - @Override - public Mono unmap(UnmapRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getApplicationId(cloudFoundryClient, request.getApplicationName(), - spaceId), - getDomainId(cloudFoundryClient, organizationId, request.getDomain()) - .flatMap(domainId -> getRouteId(cloudFoundryClient, - request.getHost(), - request.getDomain(), domainId, - request.getPath(), - request.getPort()))))) - .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) - .transform(OperationsLogging.log("Unmap Route")) - .checkpoint(); - } - - private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, Duration completionTimeout, - String routeId) { - return requestDeleteRoute(cloudFoundryClient, routeId) - .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, completionTimeout, job)); - } - - private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return requestAllPrivateDomains(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName())) - .mergeWith(requestAllSharedDomains(cloudFoundryClient) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName()))) - .collectMap(function((id, name) -> id), function((id, name) -> name)); - } - - private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return requestAllSpaces(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName())) - .collectMap(function((id, name) -> id), function((id, name) -> name)); - } - - private static Mono getApplication(CloudFoundryClient cloudFoundryClient, - String application, - String spaceId) { - return requestApplications(cloudFoundryClient, application, spaceId) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Application %s does not exist", - application)); - } - - private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, - String spaceId) { - return getApplication(cloudFoundryClient, application, spaceId) - .map(ResourceUtils::getId); - } - - private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, String routeId) { - return requestApplications(cloudFoundryClient, routeId) - .map(resource -> ResourceUtils.getEntity(resource).getName()) - .collectList(); - } - - private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomains(cloudFoundryClient, organizationId, domain) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Domain %s does not exist", - domain)); - } - - private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomain(cloudFoundryClient, organizationId, domain) - .map(ResourceUtils::getId); - } - - private static Mono getDomainName(Map domains, String domainId) { - return Mono.just(domains.get(domainId)); - } - - private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return requestPrivateDomains(cloudFoundryClient, organizationId, domain) - .map((Function>) in -> in) - .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); - } - - private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, - String organizationId, String spaceId, String domain, String host, String path, Integer port, - Boolean randomPort) { - if (randomPort != null) { - return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, - path, port, randomPort, - spaceId)); - } - - return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) - .cast(AbstractRouteResource.class) - .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, - path, port, randomPort, - spaceId))); - } - - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, - String domain, - String host, String path, Integer port) { - return getRoute(cloudFoundryClient, domainId, host, path, port) - .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); - } - - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, - String path, Integer port) { - if (port != null) { - return requestRoutes(cloudFoundryClient, domainId, null, null, port) - .singleOrEmpty(); - } else { - return requestRoutes(cloudFoundryClient, domainId, host, path, port) - .filter(resource -> isIdentical(nullSafe(host), - ResourceUtils.getEntity(resource).getHost())) - .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), - ResourceUtils.getEntity(resource).getPath())) - .singleOrEmpty(); - } - } - - private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, - String domainId, String path, Integer port) { - return getRoute(cloudFoundryClient, domainId, domain, host, path, port) - .map(ResourceUtils::getId); - } - - private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, - Mono organizationId, Mono spaceId) { - if (Level.ORGANIZATION == request.getLevel()) { - return organizationId - .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, - builder -> builder.organizationId(organizationId1))); - } else { - return spaceId - .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); - } - } - - private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, - String serviceInstanceId, String spaceId) { - return requestListSpaceServiceInstances(cloudFoundryClient, spaceId) - .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) - .single() - .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); - } - - private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) { - return Mono.justOrEmpty(route.getServiceInstanceId()) - .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, - serviceInstanceId, - route.getSpaceId())) - .defaultIfEmpty(Optional.empty()); - } - - private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return requestSpaces(cloudFoundryClient, organizationId, space) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); - } - - private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return getSpace(cloudFoundryClient, organizationId, space) - .map(ResourceUtils::getId); - } - - private static Mono getSpaceName(Map spaces, String spaceId) { - return Mono.just(spaces.get(spaceId)); - } - - private static boolean isIdentical(String s, String t) { - return s == null ? t == null : s.equals(t); - } - - private static String nullSafe(String host) { - return host == null ? "" : host; - } - - private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); - } - - private static Flux requestAllSharedDomains(CloudFoundryClient cloudFoundryClient) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .page(page) - .build())); - } - - private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); - } - - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, - String routeId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .listApplications(ListRouteApplicationsRequest.builder() - .routeId(routeId) - .page(page) - .build())); - } - - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, - String application, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listApplications(ListSpaceApplicationsRequest.builder() - .name(application) - .page(page) - .spaceId(spaceId) - .build())); - } - - private static Mono requestAssociateRoute( - CloudFoundryClient cloudFoundryClient, - String applicationId, String routeId) { - return cloudFoundryClient.applicationsV2() - .associateRoute(AssociateApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, - String domainId, - String host, String path, Integer port, Boolean randomPort, String spaceId) { - - org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest - .builder(); - - if (randomPort != null && randomPort) { - builder.generatePort(true); - } else if (port != null) { - builder.port(port); - } else { - builder.host(host); - builder.path(path); - } - - return cloudFoundryClient.routes() - .create(builder - .domainId(domainId) - .spaceId(spaceId) - .build()); - } - - private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, - String routeId) { - return cloudFoundryClient.routes() - .delete(org.cloudfoundry.client.v2.routes.DeleteRouteRequest.builder() - .async(true) - .routeId(routeId) - .build()); - } - - private static Flux requestListSpaceServiceInstances( - CloudFoundryClient cloudFoundryClient, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listServiceInstances(ListSpaceServiceInstancesRequest.builder() - .page(page) - .returnUserProvidedServiceInstances(true) - .spaceId(spaceId) - .build())); - } - - private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String domain) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .name(domain) - .page(page) - .build())); - } - - private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, - String applicationId, String routeId) { - return cloudFoundryClient.applicationsV2() - .removeRoute(RemoveApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, - UnaryOperator modifier) { - - org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier - .apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); - - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .list(listBuilder - .page(page) - .build())); - } - - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, - String host, String path, Integer port) { - return requestRoutes(cloudFoundryClient, builder -> builder - .domainId(domainId) - .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) - .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) - .port(Optional.ofNullable(port).orElse(null))); - } - - private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, - String domain) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .name(domain) - .page(page) - .build())); - } - - private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listRoutes(ListSpaceRoutesRequest.builder() - .spaceId(spaceId) - .page(page) - .build())); - } - - private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .name(space) - .page(page) - .build())); - } - - private static Route toRoute(List applications, String domain, RouteResource resource, - Optional service, String space) { - RouteEntity entity = ResourceUtils.getEntity(resource); - Route.Builder builder = Route.builder() - .applications(applications) - .domain(domain) - .host(entity.getHost()) - .id(ResourceUtils.getId(resource)) - .path(entity.getPath()) - .space(space); - - service.ifPresent(builder::service); - - return builder.build(); - } + private final Mono cloudFoundryClient; + + private final Mono organizationId; + + private final Mono spaceId; + + public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, + Mono spaceId) { + this.cloudFoundryClient = cloudFoundryClient; + this.organizationId = organizationId; + this.spaceId = spaceId; + } + + @Override + public Mono check(CheckRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((client, organizationId) -> Mono.zip(this.cloudFoundryClient, + getOptionalDomainIdByName( + client, organizationId, + request.getDomain())))) + .flatMap(function((client, domainId) -> routeExists(client, domainId, request.getHost(), + request.getPath()))) + .defaultIfEmpty(false) + .transform(OperationsLogging.log("Check Route Exists")) + .checkpoint(); + } + + private static Mono routeExists(CloudFoundryClient cloudFoundryClient, String domainId, + String host, + String path) { + return cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() + .domainId(domainId) + .host(host) + .path(path) + .build()) + .flatMap(response -> Mono.just(response.getMatchingRoute())); + } + + private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, + String organizationId, + String domain) { + return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) + .singleOrEmpty() + .map(resource -> resource.getId()); + } + + private static Flux listDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String[] domainNamesFilter) { + return PaginationUtils + .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( + ListOrganizationDomainsRequest.builder() + .names(domainNamesFilter) + .page(page) + .organizationId(organizationId).build())); + } + + @Override + public Mono create(CreateRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), + getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) + .flatMap(function((cloudFoundryClient, spaceId, + domainId) -> requestCreateRoute(cloudFoundryClient, domainId, + request.getHost(), + request.getPath(), request.getPort(), + request.getRandomPort(), spaceId) + .map(ResourceUtils::getEntity) + .flatMap(routeEntity -> Mono + .justOrEmpty(routeEntity.getPort())))) + .transform(OperationsLogging.log("Create Route")) + .checkpoint(); + } + + @Override + public Mono delete(DeleteRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) + .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( + Mono.just(cloudFoundryClient), + Mono.just(request.getCompletionTimeout()), + getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), + domainId, + request.getPath(), request.getPort())))) + .flatMap(function(DefaultRoutes::deleteRoute)) + .transform(OperationsLogging.log("Delete Route")) + .checkpoint(); + } + + @Override + public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { + return Mono.zip(this.cloudFoundryClient, this.spaceId) + .flatMap(function((client, spaceId) -> Mono.zip(this.cloudFoundryClient, + client.spacesV3().deleteUnmappedRoutes( + DeleteUnmappedRoutesRequest.builder().spaceId(spaceId) + .build())))) + .flatMap(function((client, job) -> JobUtils.waitForCompletion(client, + request.getCompletionTimeout(), job))) + .transform(OperationsLogging.log("Delete Orphaned Routes")) + .checkpoint(); + + } + + @Override + public Flux list(ListRoutesRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getAllDomains(cloudFoundryClient, organizationId), + getAllSpaces(cloudFoundryClient, organizationId)))) + .flatMapMany(function((cloudFoundryClient, domains, + spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, + this.spaceId) + .map(route -> Tuples.of(cloudFoundryClient, domains, + route, spaces)))) + .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono + .zip( + getApplicationNames(cloudFoundryClient, + ResourceUtils.getId(route)), + getDomainName(domains, + ResourceUtils.getEntity(route) + .getDomainId()), + Mono.just(route), + getServiceName(cloudFoundryClient, + ResourceUtils.getEntity(route)), + getSpaceName(spaces, + ResourceUtils.getEntity(route) + .getSpaceId())))) + .map(function(DefaultRoutes::toRoute)) + .transform(OperationsLogging.log("List Routes")) + .checkpoint(); + } + + @Override + public Mono map(MapRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) + .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, + request.getDomain(), + request.getHost(), request.getPath(), request.getPort(), + request.getRandomPort()), + getApplicationId(cloudFoundryClient, request.getApplicationName(), + spaceId)))) + .flatMap(function((cloudFoundryClient, routeResource, + applicationId) -> requestAssociateRoute( + cloudFoundryClient, applicationId, + ResourceUtils.getId(routeResource)))) + .then(Mono.justOrEmpty(request.getPort())) + .transform(OperationsLogging.log("Map Route")) + .checkpoint(); + } + + @Override + public Mono unmap(UnmapRouteRequest request) { + return Mono + .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) + .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getApplicationId(cloudFoundryClient, request.getApplicationName(), + spaceId), + getDomainId(cloudFoundryClient, organizationId, request.getDomain()) + .flatMap(domainId -> getRouteId(cloudFoundryClient, + request.getHost(), + request.getDomain(), domainId, + request.getPath(), + request.getPort()))))) + .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) + .transform(OperationsLogging.log("Unmap Route")) + .checkpoint(); + } + + private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return requestAllPrivateDomains(cloudFoundryClient, organizationId) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName())) + .mergeWith(requestAllSharedDomains(cloudFoundryClient) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName()))) + .collectMap(function((id, name) -> id), function((id, name) -> name)); + } + + private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return requestAllSpaces(cloudFoundryClient, organizationId) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName())) + .collectMap(function((id, name) -> id), function((id, name) -> name)); + } + + private static Mono getApplication(CloudFoundryClient cloudFoundryClient, + String application, + String spaceId) { + return requestApplications(cloudFoundryClient, application, spaceId) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Application %s does not exist", + application)); + } + + private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, + String spaceId) { + return getApplication(cloudFoundryClient, application, spaceId) + .map(ResourceUtils::getId); + } + + private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, String routeId) { + return requestApplications(cloudFoundryClient, routeId) + .map(resource -> ResourceUtils.getEntity(resource).getName()) + .collectList(); + } + + private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return getDomains(cloudFoundryClient, organizationId, domain) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Domain %s does not exist", + domain)); + } + + private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return getDomain(cloudFoundryClient, organizationId, domain) + .map(ResourceUtils::getId); + } + + private static Mono getDomainName(Map domains, String domainId) { + return Mono.just(domains.get(domainId)); + } + + private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return requestPrivateDomains(cloudFoundryClient, organizationId, domain) + .map((Function>) in -> in) + .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); + } + + private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, + String organizationId, String spaceId, String domain, String host, String path, Integer port, + Boolean randomPort) { + if (randomPort != null) { + return getDomainId(cloudFoundryClient, organizationId, domain) + .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, + path, port, randomPort, + spaceId)); + } + + return getDomainId(cloudFoundryClient, organizationId, domain) + .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) + .cast(AbstractRouteResource.class) + .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, + path, port, randomPort, + spaceId))); + } + + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, + String domain, + String host, String path, Integer port) { + return getRoute(cloudFoundryClient, domainId, host, path, port) + .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); + } + + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, + String path, Integer port) { + if (port != null) { + return requestRoutes(cloudFoundryClient, domainId, null, null, port) + .singleOrEmpty(); + } else { + return requestRoutes(cloudFoundryClient, domainId, host, path, port) + .filter(resource -> isIdentical(nullSafe(host), + ResourceUtils.getEntity(resource).getHost())) + .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), + ResourceUtils.getEntity(resource).getPath())) + .singleOrEmpty(); + } + } + + private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, + String domainId, String path, Integer port) { + return getRoute(cloudFoundryClient, domainId, domain, host, path, port) + .map(ResourceUtils::getId); + } + + private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, + Mono organizationId, Mono spaceId) { + if (Level.ORGANIZATION == request.getLevel()) { + return organizationId + .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, + builder -> builder.organizationId(organizationId1))); + } else { + return spaceId + .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); + } + } + + private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, + String serviceInstanceId, String spaceId) { + return requestListSpaceServiceInstances(cloudFoundryClient, spaceId) + .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) + .single() + .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); + } + + private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) { + return Mono.justOrEmpty(route.getServiceInstanceId()) + .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, + serviceInstanceId, + route.getSpaceId())) + .defaultIfEmpty(Optional.empty()); + } + + private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { + return requestSpaces(cloudFoundryClient, organizationId, space) + .single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); + } + + private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { + return getSpace(cloudFoundryClient, organizationId, space) + .map(ResourceUtils::getId); + } + + private static Mono getSpaceName(Map spaces, String spaceId) { + return Mono.just(spaces.get(spaceId)); + } + + private static boolean isIdentical(String s, String t) { + return s == null ? t == null : s.equals(t); + } + + private static String nullSafe(String host) { + return host == null ? "" : host; + } + + private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId) + .page(page) + .build())); + } + + private static Flux requestAllSharedDomains(CloudFoundryClient cloudFoundryClient) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() + .list(ListSharedDomainsRequest.builder() + .page(page) + .build())); + } + + private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .page(page) + .build())); + } + + private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, + String routeId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.routes() + .listApplications(ListRouteApplicationsRequest.builder() + .routeId(routeId) + .page(page) + .build())); + } + + private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, + String application, String spaceId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listApplications(ListSpaceApplicationsRequest.builder() + .name(application) + .page(page) + .spaceId(spaceId) + .build())); + } + + private static Mono requestAssociateRoute( + CloudFoundryClient cloudFoundryClient, + String applicationId, String routeId) { + return cloudFoundryClient.applicationsV2() + .associateRoute(AssociateApplicationRouteRequest.builder() + .applicationId(applicationId) + .routeId(routeId) + .build()); + } + + private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, + String domainId, + String host, String path, Integer port, Boolean randomPort, String spaceId) { + + org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest + .builder(); + + if (randomPort != null && randomPort) { + builder.generatePort(true); + } else if (port != null) { + builder.port(port); + } else { + builder.host(host); + builder.path(path); + } + + return cloudFoundryClient.routes() + .create(builder + .domainId(domainId) + .spaceId(spaceId) + .build()); + } + + private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, + Duration completionTimeout, + String routeId) { + return requestDeleteRoute(cloudFoundryClient, routeId) + .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, + completionTimeout, job)); + } + + private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, + String routeId) { + return cloudFoundryClient.routesV3() + .delete(org.cloudfoundry.client.v3.routes.DeleteRouteRequest.builder() + .routeId(routeId) + .build()); + } + + private static Flux requestListSpaceServiceInstances( + CloudFoundryClient cloudFoundryClient, String spaceId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listServiceInstances(ListSpaceServiceInstancesRequest.builder() + .page(page) + .returnUserProvidedServiceInstances(true) + .spaceId(spaceId) + .build())); + } + + private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId) + .name(domain) + .page(page) + .build())); + } + + private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, + String applicationId, String routeId) { + return cloudFoundryClient.applicationsV2() + .removeRoute(RemoveApplicationRouteRequest.builder() + .applicationId(applicationId) + .routeId(routeId) + .build()); + } + + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, + UnaryOperator modifier) { + + org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier + .apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); + + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.routes() + .list(listBuilder + .page(page) + .build())); + } + + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, + String host, String path, Integer port) { + return requestRoutes(cloudFoundryClient, builder -> builder + .domainId(domainId) + .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) + .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) + .port(Optional.ofNullable(port).orElse(null))); + } + + private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, + String domain) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() + .list(ListSharedDomainsRequest.builder() + .name(domain) + .page(page) + .build())); + } + + private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, String spaceId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listRoutes(ListSpaceRoutesRequest.builder() + .spaceId(spaceId) + .page(page) + .build())); + } + + private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, + String space) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .name(space) + .page(page) + .build())); + } + + private static Route toRoute(List applications, String domain, RouteResource resource, + Optional service, String space) { + RouteEntity entity = ResourceUtils.getEntity(resource); + Route.Builder builder = Route.builder() + .applications(applications) + .domain(domain) + .host(entity.getHost()) + .id(ResourceUtils.getId(resource)) + .path(entity.getPath()) + .space(space); + + service.ifPresent(builder::service); + + return builder.build(); + } } diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java index ca6979a1f8..abf89ad2b0 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java @@ -31,6 +31,7 @@ import org.cloudfoundry.client.v2.privatedomains.PrivateDomains; import org.cloudfoundry.client.v2.resourcematch.ResourceMatch; import org.cloudfoundry.client.v2.routes.Routes; +import org.cloudfoundry.client.v3.routes.RoutesV3; import org.cloudfoundry.client.v2.servicebindings.ServiceBindingsV2; import org.cloudfoundry.client.v2.servicebrokers.ServiceBrokers; import org.cloudfoundry.client.v2.serviceinstances.ServiceInstances; @@ -62,103 +63,106 @@ public abstract class AbstractOperationsTest { - protected static final Mono MISSING_ID = Mono.error(new java.lang.IllegalStateException("MISSING_ID")); + protected static final Mono MISSING_ID = Mono.error(new java.lang.IllegalStateException("MISSING_ID")); - protected static final Mono MISSING_ORGANIZATION_ID = Mono - .error(new java.lang.IllegalStateException("MISSING_ORGANIZATION_ID")); + protected static final Mono MISSING_ORGANIZATION_ID = Mono + .error(new java.lang.IllegalStateException("MISSING_ORGANIZATION_ID")); - protected static final Mono MISSING_SPACE_ID = Mono - .error(new java.lang.IllegalStateException("MISSING_SPACE_ID")); + protected static final Mono MISSING_SPACE_ID = Mono + .error(new java.lang.IllegalStateException("MISSING_SPACE_ID")); - protected static final Mono MISSING_USERNAME = Mono - .error(new java.lang.IllegalStateException("MISSING_USERNAME")); + protected static final Mono MISSING_USERNAME = Mono + .error(new java.lang.IllegalStateException("MISSING_USERNAME")); - protected static final String TEST_ORGANIZATION_ID = "test-organization-id"; + protected static final String TEST_ORGANIZATION_ID = "test-organization-id"; - protected static final String TEST_ORGANIZATION_NAME = "test-organization-name"; + protected static final String TEST_ORGANIZATION_NAME = "test-organization-name"; - protected static final String TEST_SPACE_ID = "test-space-id"; + protected static final String TEST_SPACE_ID = "test-space-id"; - protected static final String TEST_SPACE_NAME = "test-space-name"; + protected static final String TEST_SPACE_NAME = "test-space-name"; - protected static final String TEST_USERNAME = "test-username"; + protected static final String TEST_USERNAME = "test-username"; - protected final ApplicationsV2 applications = mock(ApplicationsV2.class, RETURNS_SMART_NULLS); + protected final ApplicationsV2 applications = mock(ApplicationsV2.class, RETURNS_SMART_NULLS); - protected final ApplicationsV3 applicationsV3 = mock(ApplicationsV3.class, RETURNS_SMART_NULLS); + protected final ApplicationsV3 applicationsV3 = mock(ApplicationsV3.class, RETURNS_SMART_NULLS); - protected final Authorizations authorizations = mock(Authorizations.class, RETURNS_SMART_NULLS); + protected final Authorizations authorizations = mock(Authorizations.class, RETURNS_SMART_NULLS); - protected final Buildpacks buildpacks = mock(Buildpacks.class, RETURNS_SMART_NULLS); + protected final Buildpacks buildpacks = mock(Buildpacks.class, RETURNS_SMART_NULLS); - protected final CloudFoundryClient cloudFoundryClient = mock(CloudFoundryClient.class, RETURNS_SMART_NULLS); + protected final CloudFoundryClient cloudFoundryClient = mock(CloudFoundryClient.class, RETURNS_SMART_NULLS); - protected final Domains domains = mock(Domains.class, RETURNS_SMART_NULLS); - protected final DomainsV3 domainsV3 = mock(DomainsV3.class, RETURNS_SMART_NULLS); + protected final Domains domains = mock(Domains.class, RETURNS_SMART_NULLS); + protected final DomainsV3 domainsV3 = mock(DomainsV3.class, RETURNS_SMART_NULLS); - protected final DopplerClient dopplerClient = mock(DopplerClient.class, RETURNS_SMART_NULLS); + protected final DopplerClient dopplerClient = mock(DopplerClient.class, RETURNS_SMART_NULLS); - protected final Events events = mock(Events.class, RETURNS_SMART_NULLS); + protected final Events events = mock(Events.class, RETURNS_SMART_NULLS); - protected final FeatureFlags featureFlags = mock(FeatureFlags.class, RETURNS_SMART_NULLS); + protected final FeatureFlags featureFlags = mock(FeatureFlags.class, RETURNS_SMART_NULLS); - protected final Jobs jobs = mock(Jobs.class, RETURNS_SMART_NULLS); - protected final JobsV3 jobsV3 = mock(JobsV3.class, RETURNS_SMART_NULLS); + protected final Jobs jobs = mock(Jobs.class, RETURNS_SMART_NULLS); + protected final JobsV3 jobsV3 = mock(JobsV3.class, RETURNS_SMART_NULLS); - protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = mock(OrganizationQuotaDefinitions.class, - RETURNS_SMART_NULLS); + protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = mock( + OrganizationQuotaDefinitions.class, + RETURNS_SMART_NULLS); - protected final Organizations organizations = mock(Organizations.class, RETURNS_SMART_NULLS); - protected final OrganizationsV3 organizationsV3 = mock(OrganizationsV3.class, RETURNS_SMART_NULLS); + protected final Organizations organizations = mock(Organizations.class, RETURNS_SMART_NULLS); + protected final OrganizationsV3 organizationsV3 = mock(OrganizationsV3.class, RETURNS_SMART_NULLS); - protected final PrivateDomains privateDomains = mock(PrivateDomains.class, RETURNS_SMART_NULLS); + protected final PrivateDomains privateDomains = mock(PrivateDomains.class, RETURNS_SMART_NULLS); - protected final ResourceMatch resourceMatch = mock(ResourceMatch.class, RETURNS_SMART_NULLS); + protected final ResourceMatch resourceMatch = mock(ResourceMatch.class, RETURNS_SMART_NULLS); - protected final RouterGroups routerGroups = mock(RouterGroups.class, RETURNS_SMART_NULLS); + protected final RouterGroups routerGroups = mock(RouterGroups.class, RETURNS_SMART_NULLS); - protected final Routes routes = mock(Routes.class, RETURNS_SMART_NULLS); + protected final Routes routes = mock(Routes.class, RETURNS_SMART_NULLS); + protected final RoutesV3 routesV3 = mock(RoutesV3.class, RETURNS_SMART_NULLS); - protected final RoutingClient routingClient = mock(RoutingClient.class, RETURNS_SMART_NULLS); + protected final RoutingClient routingClient = mock(RoutingClient.class, RETURNS_SMART_NULLS); - protected final ServiceBindingsV2 serviceBindingsV2 = mock(ServiceBindingsV2.class, RETURNS_SMART_NULLS); + protected final ServiceBindingsV2 serviceBindingsV2 = mock(ServiceBindingsV2.class, RETURNS_SMART_NULLS); - protected final ServiceBrokers serviceBrokers = mock(ServiceBrokers.class, RETURNS_SMART_NULLS); + protected final ServiceBrokers serviceBrokers = mock(ServiceBrokers.class, RETURNS_SMART_NULLS); - protected final ServiceInstances serviceInstances = mock(ServiceInstances.class, RETURNS_SMART_NULLS); + protected final ServiceInstances serviceInstances = mock(ServiceInstances.class, RETURNS_SMART_NULLS); - protected final ServiceKeys serviceKeys = mock(ServiceKeys.class, RETURNS_SMART_NULLS); + protected final ServiceKeys serviceKeys = mock(ServiceKeys.class, RETURNS_SMART_NULLS); - protected final ServicePlanVisibilities servicePlanVisibilities = mock(ServicePlanVisibilities.class, - RETURNS_SMART_NULLS); + protected final ServicePlanVisibilities servicePlanVisibilities = mock(ServicePlanVisibilities.class, + RETURNS_SMART_NULLS); - protected final ServicePlans servicePlans = mock(ServicePlans.class, RETURNS_SMART_NULLS); + protected final ServicePlans servicePlans = mock(ServicePlans.class, RETURNS_SMART_NULLS); - protected final Services services = mock(Services.class, RETURNS_SMART_NULLS); + protected final Services services = mock(Services.class, RETURNS_SMART_NULLS); - protected final SharedDomains sharedDomains = mock(SharedDomains.class, RETURNS_SMART_NULLS); + protected final SharedDomains sharedDomains = mock(SharedDomains.class, RETURNS_SMART_NULLS); - protected final SpaceQuotaDefinitions spaceQuotaDefinitions = mock(SpaceQuotaDefinitions.class, - RETURNS_SMART_NULLS); + protected final SpaceQuotaDefinitions spaceQuotaDefinitions = mock(SpaceQuotaDefinitions.class, + RETURNS_SMART_NULLS); - protected final Spaces spaces = mock(Spaces.class, RETURNS_SMART_NULLS); - protected final SpacesV3 spacesV3 = mock(SpacesV3.class, RETURNS_SMART_NULLS); + protected final Spaces spaces = mock(Spaces.class, RETURNS_SMART_NULLS); + protected final SpacesV3 spacesV3 = mock(SpacesV3.class, RETURNS_SMART_NULLS); - protected final Stacks stacks = mock(Stacks.class, RETURNS_SMART_NULLS); + protected final Stacks stacks = mock(Stacks.class, RETURNS_SMART_NULLS); - protected final Tasks tasks = mock(Tasks.class, RETURNS_SMART_NULLS); + protected final Tasks tasks = mock(Tasks.class, RETURNS_SMART_NULLS); - protected final Tokens tokens = mock(Tokens.class, RETURNS_SMART_NULLS); + protected final Tokens tokens = mock(Tokens.class, RETURNS_SMART_NULLS); - protected final UaaClient uaaClient = mock(UaaClient.class, RETURNS_SMART_NULLS); + protected final UaaClient uaaClient = mock(UaaClient.class, RETURNS_SMART_NULLS); - protected final org.cloudfoundry.uaa.users.Users uaaUsers = mock(org.cloudfoundry.uaa.users.Users.class, - RETURNS_SMART_NULLS); + protected final org.cloudfoundry.uaa.users.Users uaaUsers = mock(org.cloudfoundry.uaa.users.Users.class, + RETURNS_SMART_NULLS); - protected final UserProvidedServiceInstances userProvidedServiceInstances = mock(UserProvidedServiceInstances.class, - RETURNS_SMART_NULLS); + protected final UserProvidedServiceInstances userProvidedServiceInstances = mock( + UserProvidedServiceInstances.class, + RETURNS_SMART_NULLS); - protected final Users users = mock(Users.class, RETURNS_SMART_NULLS); + protected final Users users = mock(Users.class, RETURNS_SMART_NULLS); @Before public final void mockClient() { @@ -177,6 +181,7 @@ public final void mockClient() { when(this.cloudFoundryClient.privateDomains()).thenReturn(this.privateDomains); when(this.cloudFoundryClient.resourceMatch()).thenReturn(this.resourceMatch); when(this.cloudFoundryClient.routes()).thenReturn(this.routes); + when(this.cloudFoundryClient.routesV3()).thenReturn(this.routesV3); when(this.cloudFoundryClient.serviceBindingsV2()).thenReturn(this.serviceBindingsV2); when(this.cloudFoundryClient.serviceBrokers()).thenReturn(this.serviceBrokers); when(this.cloudFoundryClient.serviceInstances()).thenReturn(this.serviceInstances); diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java index c8bce7f945..a96fcfa924 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java @@ -298,77 +298,6 @@ public void createRouteRandomPort() { .verify(Duration.ofSeconds(5)); } - @Test - public void deleteAssignedPort() { - requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, 9999); - requestDeleteRoute(this.cloudFoundryClient, "test-route-id"); - requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); - - StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .port(9999) - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); - } - - @Test - public void deleteFailure() { - requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestDeleteRoute(this.cloudFoundryClient, "test-route-id"); - requestJobFailure(this.cloudFoundryClient, "test-job-entity-id"); - - StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(ClientV2Exception.class) - .hasMessage("test-error-details-errorCode(1): test-error-details-description")) - .verify(Duration.ofSeconds(5)); - } - - @Test - public void deleteInvalidDomain() { - requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); - - this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) - .hasMessage("Domain test-domain does not exist")) - .verify(Duration.ofSeconds(5)); - } - - @Test - public void deleteInvalidRoute() { - requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - - this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) - .hasMessage("Route for test-domain does not exist")) - .verify(Duration.ofSeconds(5)); - } - @Test public void deleteOrphanedRoutes() { mockDeleteOrphanedRoutes(this.cloudFoundryClient); @@ -390,40 +319,28 @@ private static void mockDeleteOrphanedRoutes(CloudFoundryClient cloudFoundryClie } @Test - public void deletePrivateDomain() { + public void deleteRoute() { requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestDeleteRoute(this.cloudFoundryClient, "test-route-id"); - requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); + mockDeleteRequest(this.cloudFoundryClient, "test-route-id"); - StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) + this.routes.delete(DeleteRouteRequest.builder() + .host("test-host") + .path("test-path") + .domain("test-domain") + .build()) + .as(StepVerifier::create) .expectComplete() .verify(Duration.ofSeconds(5)); } - @Test - public void deleteSharedDomain() { - requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", "test-path", null); - requestDeleteRoute(this.cloudFoundryClient, "test-route-id"); - requestJobSuccess(this.cloudFoundryClient, "test-job-entity-id"); - - StepVerifier.withVirtualTime(() -> this.routes - .delete(DeleteRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") + private static void mockDeleteRequest(CloudFoundryClient cloudFoundryClient,String routeId){ + when(cloudFoundryClient.routesV3().delete(org.cloudfoundry.client.v3.routes.DeleteRouteRequest.builder() + .routeId(routeId) .build())) - .then(() -> VirtualTimeScheduler.get().advanceTimeBy(Duration.ofSeconds(3))) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .thenReturn(Mono.just("test-delete-job")); + when(cloudFoundryClient.jobsV3().get(org.cloudfoundry.client.v3.jobs.GetJobRequest.builder().jobId("test-delete-job").build())).thenReturn( + Mono.just(fill(org.cloudfoundry.client.v3.jobs.GetJobResponse.builder()).state(org.cloudfoundry.client.v3.jobs.JobState.COMPLETE).build())); } @Test @@ -871,19 +788,6 @@ private static void requestCreateRoute(CloudFoundryClient cloudFoundryClient, St .build())); } - private static void requestDeleteRoute(CloudFoundryClient cloudFoundryClient, String routeId) { - when(cloudFoundryClient.routes() - .delete(org.cloudfoundry.client.v2.routes.DeleteRouteRequest.builder() - .async(true) - .routeId(routeId) - .build())) - .thenReturn(Mono - .just(fill(DeleteRouteResponse.builder()) - .entity(fill(JobEntity.builder(), "job-entity-") - .build()) - .build())); - } - private static void requestJobFailure(CloudFoundryClient cloudFoundryClient, String jobId) { when(cloudFoundryClient.jobs() .get(GetJobRequest.builder() From ea1ade133fcc9aa7dba256f11a2ce34c92ff985f Mon Sep 17 00:00:00 2001 From: radoslav-tomov Date: Thu, 7 Sep 2023 16:18:14 +0300 Subject: [PATCH 6/7] cleaning up leftovers in tests --- .../operations/routes/DefaultRoutesTest.java | 96 ++----------------- 1 file changed, 6 insertions(+), 90 deletions(-) diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java index a96fcfa924..1408a79e4f 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java @@ -23,10 +23,10 @@ import org.cloudfoundry.client.v2.applications.AssociateApplicationRouteRequest; import org.cloudfoundry.client.v2.applications.AssociateApplicationRouteResponse; import org.cloudfoundry.client.v2.applications.RemoveApplicationRouteRequest; -import org.cloudfoundry.client.v2.jobs.ErrorDetails; -import org.cloudfoundry.client.v2.jobs.GetJobRequest; -import org.cloudfoundry.client.v2.jobs.GetJobResponse; -import org.cloudfoundry.client.v2.jobs.JobEntity; + +import org.cloudfoundry.client.v3.jobs.GetJobRequest; +import org.cloudfoundry.client.v3.jobs.GetJobResponse; +import org.cloudfoundry.client.v3.jobs.JobState; import org.cloudfoundry.client.v2.organizations.ListOrganizationPrivateDomainsRequest; import org.cloudfoundry.client.v2.organizations.ListOrganizationPrivateDomainsResponse; import org.cloudfoundry.client.v2.organizations.ListOrganizationSpacesRequest; @@ -90,8 +90,6 @@ import java.util.Queue; import java.util.function.Supplier; -import javax.print.attribute.standard.JobState; - import static org.assertj.core.api.Assertions.assertThat; import static org.cloudfoundry.operations.TestObjects.fill; import static org.mockito.Mockito.when; @@ -314,8 +312,8 @@ private static void mockDeleteOrphanedRoutes(CloudFoundryClient cloudFoundryClie .spaceId(TEST_SPACE_ID) .build())) .thenReturn(Mono.just(TEST_JOB_ID)); - when(cloudFoundryClient.jobsV3().get(org.cloudfoundry.client.v3.jobs.GetJobRequest.builder().jobId(TEST_JOB_ID).build())).thenReturn( - Mono.just(fill(org.cloudfoundry.client.v3.jobs.GetJobResponse.builder()).state(org.cloudfoundry.client.v3.jobs.JobState.COMPLETE).build())); + when(cloudFoundryClient.jobsV3().get( GetJobRequest.builder().jobId(TEST_JOB_ID).build())).thenReturn( + Mono.just(fill( GetJobResponse.builder()).state( JobState.COMPLETE).build())); } @Test @@ -788,66 +786,6 @@ private static void requestCreateRoute(CloudFoundryClient cloudFoundryClient, St .build())); } - private static void requestJobFailure(CloudFoundryClient cloudFoundryClient, String jobId) { - when(cloudFoundryClient.jobs() - .get(GetJobRequest.builder() - .jobId(jobId) - .build())) - .thenReturn(Mono - .defer(new Supplier>() { - - private final Queue responses = new LinkedList<>(Arrays.asList( - fill(GetJobResponse.builder(), "job-") - .entity(fill(JobEntity.builder()) - .status("running") - .build()) - .build(), - fill(GetJobResponse.builder(), "job-") - .entity(fill(JobEntity.builder()) - .errorDetails(fill(ErrorDetails.builder(), "error-details-") - .build()) - .status("failed") - .build()) - .build() - )); - - @Override - public Mono get() { - return Mono.just(this.responses.poll()); - } - - })); - } - - private static void requestJobSuccess(CloudFoundryClient cloudFoundryClient, String jobId) { - when(cloudFoundryClient.jobs() - .get(GetJobRequest.builder() - .jobId(jobId) - .build())) - .thenReturn(Mono - .defer(new Supplier>() { - - private final Queue responses = new LinkedList<>(Arrays.asList( - fill(GetJobResponse.builder(), "job-") - .entity(fill(JobEntity.builder()) - .status("running") - .build()) - .build(), - fill(GetJobResponse.builder(), "job-") - .entity(fill(JobEntity.builder()) - .status("finished") - .build()) - .build() - )); - - @Override - public Mono get() { - return Mono.just(this.responses.poll()); - } - - })); - } - private static void requestOrganizationsRoutes(CloudFoundryClient cloudFoundryClient, String organizationId) { when(cloudFoundryClient.routes() .list(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder() @@ -927,28 +865,6 @@ private static void requestRemoveRouteFromApplication(CloudFoundryClient cloudFo .thenReturn(Mono.empty()); } - private static void requestRouteExistsFalse(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path) { - when(cloudFoundryClient.routes() - .exists(RouteExistsRequest.builder() - .domainId(domainId) - .host(host) - .path(path) - .build())) - .thenReturn(Mono - .just(false)); - } - - private static void requestRouteExistsTrue(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path) { - when(cloudFoundryClient.routes() - .exists(RouteExistsRequest.builder() - .domainId(domainId) - .host(host) - .path(path) - .build())) - .thenReturn(Mono - .just(true)); - } - private static void requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, String host, String path, Integer port) { when(cloudFoundryClient.routes() .list(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder() From f616d2007d9236d8b0103abf3462dc4a24b96529 Mon Sep 17 00:00:00 2001 From: Radoslav Tomov Date: Mon, 16 Oct 2023 13:28:39 +0000 Subject: [PATCH 7/7] applying default style and fixing missing imports --- .../operations/routes/DefaultRoutes.java | 1078 ++++++++--------- .../operations/AbstractOperationsTest.java | 135 ++- .../operations/routes/DefaultRoutesTest.java | 432 +++---- 3 files changed, 734 insertions(+), 911 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java index 110369293e..d718a3fd88 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/routes/DefaultRoutes.java @@ -1,17 +1,15 @@ /* * Copyright 2013-2021 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. */ package org.cloudfoundry.operations.routes; @@ -27,7 +25,6 @@ import org.cloudfoundry.client.v2.privatedomains.PrivateDomainResource; import org.cloudfoundry.client.v2.routes.AbstractRouteResource; import org.cloudfoundry.client.v2.routes.CreateRouteResponse; -import org.cloudfoundry.client.v2.routes.DeleteRouteResponse; import org.cloudfoundry.client.v2.routes.ListRouteApplicationsRequest; import org.cloudfoundry.client.v2.routes.RouteEntity; @@ -62,551 +59,526 @@ import java.util.function.UnaryOperator; import static org.cloudfoundry.util.tuple.TupleUtils.function; -import static org.cloudfoundry.util.tuple.TupleUtils.predicate; public final class DefaultRoutes implements Routes { - private final Mono cloudFoundryClient; - - private final Mono organizationId; - - private final Mono spaceId; - - public DefaultRoutes(Mono cloudFoundryClient, Mono organizationId, - Mono spaceId) { - this.cloudFoundryClient = cloudFoundryClient; - this.organizationId = organizationId; - this.spaceId = spaceId; - } - - @Override - public Mono check(CheckRouteRequest request) { - return Mono.zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((client, organizationId) -> Mono.zip(this.cloudFoundryClient, - getOptionalDomainIdByName( - client, organizationId, - request.getDomain())))) - .flatMap(function((client, domainId) -> routeExists(client, domainId, request.getHost(), - request.getPath()))) - .defaultIfEmpty(false) - .transform(OperationsLogging.log("Check Route Exists")) - .checkpoint(); - } - - private static Mono routeExists(CloudFoundryClient cloudFoundryClient, String domainId, - String host, - String path) { - return cloudFoundryClient.domainsV3().checkReservedRoutes(CheckReservedRoutesRequest.builder() - .domainId(domainId) - .host(host) - .path(path) - .build()) - .flatMap(response -> Mono.just(response.getMatchingRoute())); - } - - private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, - String organizationId, - String domain) { - return listDomains(cloudFoundryClient, organizationId, new String[] { domain }) - .singleOrEmpty() - .map(resource -> resource.getId()); - } - - private static Flux listDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String[] domainNamesFilter) { - return PaginationUtils - .requestClientV3Resources(page -> cloudFoundryClient.organizationsV3().listDomains( - ListOrganizationDomainsRequest.builder() - .names(domainNamesFilter) - .page(page) - .organizationId(organizationId).build())); - } - - @Override - public Mono create(CreateRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getSpaceId(cloudFoundryClient, organizationId, request.getSpace()), - getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) - .flatMap(function((cloudFoundryClient, spaceId, - domainId) -> requestCreateRoute(cloudFoundryClient, domainId, - request.getHost(), - request.getPath(), request.getPort(), - request.getRandomPort(), spaceId) - .map(ResourceUtils::getEntity) - .flatMap(routeEntity -> Mono - .justOrEmpty(routeEntity.getPort())))) - .transform(OperationsLogging.log("Create Route")) - .checkpoint(); - } - - @Override - public Mono delete(DeleteRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getDomainId(cloudFoundryClient, organizationId, request.getDomain())))) - .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( - Mono.just(cloudFoundryClient), - Mono.just(request.getCompletionTimeout()), - getRouteId(cloudFoundryClient, request.getHost(), request.getDomain(), - domainId, - request.getPath(), request.getPort())))) - .flatMap(function(DefaultRoutes::deleteRoute)) - .transform(OperationsLogging.log("Delete Route")) - .checkpoint(); - } - - @Override - public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { - return Mono.zip(this.cloudFoundryClient, this.spaceId) - .flatMap(function((client, spaceId) -> Mono.zip(this.cloudFoundryClient, - client.spacesV3().deleteUnmappedRoutes( - DeleteUnmappedRoutesRequest.builder().spaceId(spaceId) - .build())))) - .flatMap(function((client, job) -> JobUtils.waitForCompletion(client, - request.getCompletionTimeout(), job))) - .transform(OperationsLogging.log("Delete Orphaned Routes")) - .checkpoint(); - - } - - @Override - public Flux list(ListRoutesRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId) - .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getAllDomains(cloudFoundryClient, organizationId), - getAllSpaces(cloudFoundryClient, organizationId)))) - .flatMapMany(function((cloudFoundryClient, domains, - spaces) -> getRoutes(cloudFoundryClient, request, this.organizationId, - this.spaceId) - .map(route -> Tuples.of(cloudFoundryClient, domains, - route, spaces)))) - .flatMap(function((cloudFoundryClient, domains, route, spaces) -> Mono - .zip( - getApplicationNames(cloudFoundryClient, - ResourceUtils.getId(route)), - getDomainName(domains, - ResourceUtils.getEntity(route) - .getDomainId()), - Mono.just(route), - getServiceName(cloudFoundryClient, - ResourceUtils.getEntity(route)), - getSpaceName(spaces, - ResourceUtils.getEntity(route) - .getSpaceId())))) - .map(function(DefaultRoutes::toRoute)) - .transform(OperationsLogging.log("List Routes")) - .checkpoint(); - } - - @Override - public Mono map(MapRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getOrCreateRoute(cloudFoundryClient, organizationId, spaceId, - request.getDomain(), - request.getHost(), request.getPath(), request.getPort(), - request.getRandomPort()), - getApplicationId(cloudFoundryClient, request.getApplicationName(), - spaceId)))) - .flatMap(function((cloudFoundryClient, routeResource, - applicationId) -> requestAssociateRoute( - cloudFoundryClient, applicationId, - ResourceUtils.getId(routeResource)))) - .then(Mono.justOrEmpty(request.getPort())) - .transform(OperationsLogging.log("Map Route")) - .checkpoint(); - } - - @Override - public Mono unmap(UnmapRouteRequest request) { - return Mono - .zip(this.cloudFoundryClient, this.organizationId, this.spaceId) - .flatMap(function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( - Mono.just(cloudFoundryClient), - getApplicationId(cloudFoundryClient, request.getApplicationName(), - spaceId), - getDomainId(cloudFoundryClient, organizationId, request.getDomain()) - .flatMap(domainId -> getRouteId(cloudFoundryClient, - request.getHost(), - request.getDomain(), domainId, - request.getPath(), - request.getPort()))))) - .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) - .transform(OperationsLogging.log("Unmap Route")) - .checkpoint(); - } - - private static Mono> getAllDomains(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return requestAllPrivateDomains(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName())) - .mergeWith(requestAllSharedDomains(cloudFoundryClient) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName()))) - .collectMap(function((id, name) -> id), function((id, name) -> name)); - } - - private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return requestAllSpaces(cloudFoundryClient, organizationId) - .map(resource -> Tuples.of(ResourceUtils.getId(resource), - ResourceUtils.getEntity(resource).getName())) - .collectMap(function((id, name) -> id), function((id, name) -> name)); - } - - private static Mono getApplication(CloudFoundryClient cloudFoundryClient, - String application, - String spaceId) { - return requestApplications(cloudFoundryClient, application, spaceId) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Application %s does not exist", - application)); - } - - private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, String application, - String spaceId) { - return getApplication(cloudFoundryClient, application, spaceId) - .map(ResourceUtils::getId); - } - - private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, String routeId) { - return requestApplications(cloudFoundryClient, routeId) - .map(resource -> ResourceUtils.getEntity(resource).getName()) - .collectList(); - } - - private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomains(cloudFoundryClient, organizationId, domain) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Domain %s does not exist", - domain)); - } - - private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return getDomain(cloudFoundryClient, organizationId, domain) - .map(ResourceUtils::getId); - } - - private static Mono getDomainName(Map domains, String domainId) { - return Mono.just(domains.get(domainId)); - } - - private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, String organizationId, - String domain) { - return requestPrivateDomains(cloudFoundryClient, organizationId, domain) - .map((Function>) in -> in) - .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); - } - - private static Mono getOrCreateRoute(CloudFoundryClient cloudFoundryClient, - String organizationId, String spaceId, String domain, String host, String path, Integer port, - Boolean randomPort) { - if (randomPort != null) { - return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> requestCreateRoute(cloudFoundryClient, domainId, host, - path, port, randomPort, - spaceId)); - } - - return getDomainId(cloudFoundryClient, organizationId, domain) - .flatMap(domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) - .cast(AbstractRouteResource.class) - .switchIfEmpty(requestCreateRoute(cloudFoundryClient, domainId, host, - path, port, randomPort, - spaceId))); - } - - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, - String domain, - String host, String path, Integer port) { - return getRoute(cloudFoundryClient, domainId, host, path, port) - .switchIfEmpty(ExceptionUtils.illegalArgument("Route for %s does not exist", domain)); - } - - private static Mono getRoute(CloudFoundryClient cloudFoundryClient, String domainId, String host, - String path, Integer port) { - if (port != null) { - return requestRoutes(cloudFoundryClient, domainId, null, null, port) - .singleOrEmpty(); - } else { - return requestRoutes(cloudFoundryClient, domainId, host, path, port) - .filter(resource -> isIdentical(nullSafe(host), - ResourceUtils.getEntity(resource).getHost())) - .filter(resource -> isIdentical(Optional.ofNullable(path).orElse(""), - ResourceUtils.getEntity(resource).getPath())) - .singleOrEmpty(); - } - } - - private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, String domain, - String domainId, String path, Integer port) { - return getRoute(cloudFoundryClient, domainId, domain, host, path, port) - .map(ResourceUtils::getId); - } - - private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, ListRoutesRequest request, - Mono organizationId, Mono spaceId) { - if (Level.ORGANIZATION == request.getLevel()) { - return organizationId - .flatMapMany(organizationId1 -> requestRoutes(cloudFoundryClient, - builder -> builder.organizationId(organizationId1))); - } else { - return spaceId - .flatMapMany(spaceId1 -> requestSpaceRoutes(cloudFoundryClient, spaceId1)); - } - } - - private static Mono> getServiceInstanceName(CloudFoundryClient cloudFoundryClient, - String serviceInstanceId, String spaceId) { - return requestListSpaceServiceInstances(cloudFoundryClient, spaceId) - .filter(resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) - .single() - .map(resource -> Optional.of(ResourceUtils.getEntity(resource).getName())); - } - - private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, RouteEntity route) { - return Mono.justOrEmpty(route.getServiceInstanceId()) - .flatMap(serviceInstanceId -> getServiceInstanceName(cloudFoundryClient, - serviceInstanceId, - route.getSpaceId())) - .defaultIfEmpty(Optional.empty()); - } - - private static Mono getSpace(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return requestSpaces(cloudFoundryClient, organizationId, space) - .single() - .onErrorResume(NoSuchElementException.class, - t -> ExceptionUtils.illegalArgument("Space %s does not exist", space)); - } - - private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return getSpace(cloudFoundryClient, organizationId, space) - .map(ResourceUtils::getId); - } - - private static Mono getSpaceName(Map spaces, String spaceId) { - return Mono.just(spaces.get(spaceId)); - } - - private static boolean isIdentical(String s, String t) { - return s == null ? t == null : s.equals(t); - } - - private static String nullSafe(String host) { - return host == null ? "" : host; - } - - private static Flux requestAllPrivateDomains(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); - } - - private static Flux requestAllSharedDomains(CloudFoundryClient cloudFoundryClient) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .page(page) - .build())); - } - - private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, - String organizationId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .page(page) - .build())); - } - - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, - String routeId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .listApplications(ListRouteApplicationsRequest.builder() - .routeId(routeId) - .page(page) - .build())); - } - - private static Flux requestApplications(CloudFoundryClient cloudFoundryClient, - String application, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listApplications(ListSpaceApplicationsRequest.builder() - .name(application) - .page(page) - .spaceId(spaceId) - .build())); - } - - private static Mono requestAssociateRoute( - CloudFoundryClient cloudFoundryClient, - String applicationId, String routeId) { - return cloudFoundryClient.applicationsV2() - .associateRoute(AssociateApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Mono requestCreateRoute(CloudFoundryClient cloudFoundryClient, - String domainId, - String host, String path, Integer port, Boolean randomPort, String spaceId) { - - org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = org.cloudfoundry.client.v2.routes.CreateRouteRequest - .builder(); - - if (randomPort != null && randomPort) { - builder.generatePort(true); - } else if (port != null) { - builder.port(port); - } else { - builder.host(host); - builder.path(path); - } - - return cloudFoundryClient.routes() - .create(builder - .domainId(domainId) - .spaceId(spaceId) - .build()); - } - - private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, - Duration completionTimeout, - String routeId) { - return requestDeleteRoute(cloudFoundryClient, routeId) - .flatMap(job -> JobUtils.waitForCompletion(cloudFoundryClient, - completionTimeout, job)); - } - - private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, - String routeId) { - return cloudFoundryClient.routesV3() - .delete(org.cloudfoundry.client.v3.routes.DeleteRouteRequest.builder() - .routeId(routeId) - .build()); - } - - private static Flux requestListSpaceServiceInstances( - CloudFoundryClient cloudFoundryClient, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listServiceInstances(ListSpaceServiceInstancesRequest.builder() - .page(page) - .returnUserProvidedServiceInstances(true) - .spaceId(spaceId) - .build())); - } - - private static Flux requestPrivateDomains(CloudFoundryClient cloudFoundryClient, - String organizationId, String domain) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() - .organizationId(organizationId) - .name(domain) - .page(page) - .build())); - } - - private static Mono requestRemoveRouteFromApplication(CloudFoundryClient cloudFoundryClient, - String applicationId, String routeId) { - return cloudFoundryClient.applicationsV2() - .removeRoute(RemoveApplicationRouteRequest.builder() - .applicationId(applicationId) - .routeId(routeId) - .build()); - } - - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, - UnaryOperator modifier) { - - org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = modifier - .apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest.builder()); - - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.routes() - .list(listBuilder - .page(page) - .build())); - } - - private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, String domainId, - String host, String path, Integer port) { - return requestRoutes(cloudFoundryClient, builder -> builder - .domainId(domainId) - .hosts(Optional.ofNullable(host).map(Collections::singletonList).orElse(null)) - .paths(Optional.ofNullable(path).map(Collections::singletonList).orElse(null)) - .port(Optional.ofNullable(port).orElse(null))); - } - - private static Flux requestSharedDomains(CloudFoundryClient cloudFoundryClient, - String domain) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.sharedDomains() - .list(ListSharedDomainsRequest.builder() - .name(domain) - .page(page) - .build())); - } - - private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, String spaceId) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.spaces() - .listRoutes(ListSpaceRoutesRequest.builder() - .spaceId(spaceId) - .page(page) - .build())); - } - - private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, String organizationId, - String space) { - return PaginationUtils - .requestClientV2Resources(page -> cloudFoundryClient.organizations() - .listSpaces(ListOrganizationSpacesRequest.builder() - .organizationId(organizationId) - .name(space) - .page(page) - .build())); - } - - private static Route toRoute(List applications, String domain, RouteResource resource, - Optional service, String space) { - RouteEntity entity = ResourceUtils.getEntity(resource); - Route.Builder builder = Route.builder() - .applications(applications) - .domain(domain) - .host(entity.getHost()) - .id(ResourceUtils.getId(resource)) - .path(entity.getPath()) - .space(space); - - service.ifPresent(builder::service); - - return builder.build(); - } + private final Mono cloudFoundryClient; + + private final Mono organizationId; + + private final Mono spaceId; + + public DefaultRoutes(Mono cloudFoundryClient, + Mono organizationId, Mono spaceId) { + this.cloudFoundryClient = cloudFoundryClient; + this.organizationId = organizationId; + this.spaceId = spaceId; + } + + @Override + public Mono check(CheckRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((client, organizationId) -> Mono.zip( + this.cloudFoundryClient, + getOptionalDomainIdByName(client, organizationId, + request.getDomain())))) + .flatMap(function((client, domainId) -> routeExists(client, + domainId, request.getHost(), request.getPath()))) + .defaultIfEmpty(false) + .transform(OperationsLogging.log("Check Route Exists")) + .checkpoint(); + } + + private static Mono routeExists(CloudFoundryClient cloudFoundryClient, + String domainId, String host, String path) { + return cloudFoundryClient.domainsV3() + .checkReservedRoutes(CheckReservedRoutesRequest.builder() + .domainId(domainId).host(host).path(path).build()) + .flatMap(response -> Mono.just(response.getMatchingRoute())); + } + + private static Mono getOptionalDomainIdByName(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { + return listDomains(cloudFoundryClient, organizationId, new String[] {domain}) + .singleOrEmpty().map(resource -> resource.getId()); + } + + private static Flux listDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String[] domainNamesFilter) { + return PaginationUtils.requestClientV3Resources(page -> cloudFoundryClient + .organizationsV3() + .listDomains(ListOrganizationDomainsRequest.builder() + .names(domainNamesFilter).page(page) + .organizationId(organizationId).build())); + } + + @Override + public Mono create(CreateRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getSpaceId(cloudFoundryClient, organizationId, + request.getSpace()), + getDomainId(cloudFoundryClient, organizationId, + request.getDomain())))) + .flatMap(function((cloudFoundryClient, spaceId, + domainId) -> requestCreateRoute(cloudFoundryClient, + domainId, request.getHost(), + request.getPath(), + request.getPort(), request + .getRandomPort(), + spaceId).map(ResourceUtils::getEntity) + .flatMap(routeEntity -> Mono + .justOrEmpty(routeEntity + .getPort())))) + .transform(OperationsLogging.log("Create Route")).checkpoint(); + } + + @Override + public Mono delete(DeleteRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getDomainId(cloudFoundryClient, organizationId, + request.getDomain())))) + .flatMap(function((cloudFoundryClient, domainId) -> Mono.zip( + Mono.just(cloudFoundryClient), + Mono.just(request.getCompletionTimeout()), + getRouteId(cloudFoundryClient, request.getHost(), + request.getDomain(), domainId, + request.getPath(), + request.getPort())))) + .flatMap(function(DefaultRoutes::deleteRoute)) + .transform(OperationsLogging.log("Delete Route")).checkpoint(); + } + + @Override + public Mono deleteOrphanedRoutes(DeleteOrphanedRoutesRequest request) { + return Mono.zip(this.cloudFoundryClient, this.spaceId).flatMap(function((client, + spaceId) -> Mono.zip(this.cloudFoundryClient, client.spacesV3() + .deleteUnmappedRoutes(DeleteUnmappedRoutesRequest + .builder().spaceId(spaceId) + .build())))) + .flatMap(function((client, job) -> JobUtils.waitForCompletion( + client, request.getCompletionTimeout(), job))) + .transform(OperationsLogging.log("Delete Orphaned Routes")) + .checkpoint(); + + } + + @Override + public Flux list(ListRoutesRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId) + .flatMap(function((cloudFoundryClient, organizationId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getAllDomains(cloudFoundryClient, organizationId), + getAllSpaces(cloudFoundryClient, organizationId)))) + .flatMapMany(function((cloudFoundryClient, domains, + spaces) -> getRoutes(cloudFoundryClient, request, + this.organizationId, this.spaceId) + .map(route -> Tuples + .of(cloudFoundryClient, + domains, + route, + spaces)))) + .flatMap(function((cloudFoundryClient, domains, route, + spaces) -> Mono.zip(getApplicationNames( + cloudFoundryClient, + ResourceUtils.getId(route)), + getDomainName(domains, ResourceUtils + .getEntity(route) + .getDomainId()), + Mono.just(route), + getServiceName(cloudFoundryClient, + ResourceUtils.getEntity( + route)), + getSpaceName(spaces, ResourceUtils + .getEntity(route) + .getSpaceId())))) + .map(function(DefaultRoutes::toRoute)) + .transform(OperationsLogging.log("List Routes")).checkpoint(); + } + + @Override + public Mono map(MapRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId, this.spaceId).flatMap( + function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getOrCreateRoute(cloudFoundryClient, organizationId, + spaceId, request.getDomain(), + request.getHost(), + request.getPath(), + request.getPort(), + request.getRandomPort()), + getApplicationId(cloudFoundryClient, + request.getApplicationName(), + spaceId)))) + .flatMap(function((cloudFoundryClient, routeResource, + applicationId) -> requestAssociateRoute( + cloudFoundryClient, applicationId, + ResourceUtils.getId( + routeResource)))) + .then(Mono.justOrEmpty(request.getPort())) + .transform(OperationsLogging.log("Map Route")).checkpoint(); + } + + @Override + public Mono unmap(UnmapRouteRequest request) { + return Mono.zip(this.cloudFoundryClient, this.organizationId, this.spaceId).flatMap( + function((cloudFoundryClient, organizationId, spaceId) -> Mono.zip( + Mono.just(cloudFoundryClient), + getApplicationId(cloudFoundryClient, + request.getApplicationName(), + spaceId), + getDomainId(cloudFoundryClient, organizationId, + request.getDomain()).flatMap( + domainId -> getRouteId( + cloudFoundryClient, + request.getHost(), + request.getDomain(), + domainId, + request.getPath(), + request.getPort()))))) + .flatMap(function(DefaultRoutes::requestRemoveRouteFromApplication)) + .transform(OperationsLogging.log("Unmap Route")).checkpoint(); + } + + private static Mono> getAllDomains( + CloudFoundryClient cloudFoundryClient, String organizationId) { + return requestAllPrivateDomains(cloudFoundryClient, organizationId) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName())) + .mergeWith(requestAllSharedDomains(cloudFoundryClient).map( + resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource) + .getName()))) + .collectMap(function((id, name) -> id), + function((id, name) -> name)); + } + + private static Mono> getAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return requestAllSpaces(cloudFoundryClient, organizationId) + .map(resource -> Tuples.of(ResourceUtils.getId(resource), + ResourceUtils.getEntity(resource).getName())) + .collectMap(function((id, name) -> id), + function((id, name) -> name)); + } + + private static Mono getApplication( + CloudFoundryClient cloudFoundryClient, String application, String spaceId) { + return requestApplications(cloudFoundryClient, application, spaceId).single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument( + "Application %s does not exist", + application)); + } + + private static Mono getApplicationId(CloudFoundryClient cloudFoundryClient, + String application, String spaceId) { + return getApplication(cloudFoundryClient, application, spaceId) + .map(ResourceUtils::getId); + } + + private static Mono> getApplicationNames(CloudFoundryClient cloudFoundryClient, + String routeId) { + return requestApplications(cloudFoundryClient, routeId) + .map(resource -> ResourceUtils.getEntity(resource).getName()) + .collectList(); + } + + private static Mono> getDomain(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { + return getDomains(cloudFoundryClient, organizationId, domain).single() + .onErrorResume(NoSuchElementException.class, + t -> ExceptionUtils.illegalArgument( + "Domain %s does not exist", + domain)); + } + + private static Mono getDomainId(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { + return getDomain(cloudFoundryClient, organizationId, domain) + .map(ResourceUtils::getId); + } + + private static Mono getDomainName(Map domains, String domainId) { + return Mono.just(domains.get(domainId)); + } + + private static Flux> getDomains(CloudFoundryClient cloudFoundryClient, + String organizationId, String domain) { + return requestPrivateDomains(cloudFoundryClient, organizationId, domain) + .map((Function>) in -> in) + .switchIfEmpty(requestSharedDomains(cloudFoundryClient, domain)); + } + + private static Mono getOrCreateRoute( + CloudFoundryClient cloudFoundryClient, String organizationId, + String spaceId, String domain, String host, String path, Integer port, + Boolean randomPort) { + if (randomPort != null) { + return getDomainId(cloudFoundryClient, organizationId, domain).flatMap( + domainId -> requestCreateRoute(cloudFoundryClient, domainId, + host, path, port, randomPort, spaceId)); + } + + return getDomainId(cloudFoundryClient, organizationId, domain).flatMap( + domainId -> getRoute(cloudFoundryClient, domainId, host, path, port) + .cast(AbstractRouteResource.class) + .switchIfEmpty(requestCreateRoute( + cloudFoundryClient, domainId, host, + path, port, randomPort, spaceId))); + } + + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, + String domainId, String domain, String host, String path, Integer port) { + return getRoute(cloudFoundryClient, domainId, host, path, port).switchIfEmpty( + ExceptionUtils.illegalArgument("Route for %s does not exist", + domain)); + } + + private static Mono getRoute(CloudFoundryClient cloudFoundryClient, + String domainId, String host, String path, Integer port) { + if (port != null) { + return requestRoutes(cloudFoundryClient, domainId, null, null, port) + .singleOrEmpty(); + } else { + return requestRoutes(cloudFoundryClient, domainId, host, path, port) + .filter(resource -> isIdentical(nullSafe(host), + ResourceUtils.getEntity(resource) + .getHost())) + .filter(resource -> isIdentical( + Optional.ofNullable(path).orElse(""), + ResourceUtils.getEntity(resource) + .getPath())) + .singleOrEmpty(); + } + } + + private static Mono getRouteId(CloudFoundryClient cloudFoundryClient, String host, + String domain, String domainId, String path, Integer port) { + return getRoute(cloudFoundryClient, domainId, domain, host, path, port) + .map(ResourceUtils::getId); + } + + private static Flux getRoutes(CloudFoundryClient cloudFoundryClient, + ListRoutesRequest request, Mono organizationId, + Mono spaceId) { + if (Level.ORGANIZATION == request.getLevel()) { + return organizationId.flatMapMany(organizationId1 -> requestRoutes( + cloudFoundryClient, + builder -> builder.organizationId(organizationId1))); + } else { + return spaceId.flatMapMany(spaceId1 -> requestSpaceRoutes( + cloudFoundryClient, spaceId1)); + } + } + + private static Mono> getServiceInstanceName( + CloudFoundryClient cloudFoundryClient, String serviceInstanceId, + String spaceId) { + return requestListSpaceServiceInstances(cloudFoundryClient, spaceId).filter( + resource -> serviceInstanceId.equals(ResourceUtils.getId(resource))) + .single().map(resource -> Optional + .of(ResourceUtils.getEntity(resource).getName())); + } + + private static Mono> getServiceName(CloudFoundryClient cloudFoundryClient, + RouteEntity route) { + return Mono.justOrEmpty(route.getServiceInstanceId()) + .flatMap(serviceInstanceId -> getServiceInstanceName( + cloudFoundryClient, serviceInstanceId, + route.getSpaceId())) + .defaultIfEmpty(Optional.empty()); + } + + private static Mono getSpace(CloudFoundryClient cloudFoundryClient, + String organizationId, String space) { + return requestSpaces(cloudFoundryClient, organizationId, space).single() + .onErrorResume(NoSuchElementException.class, t -> ExceptionUtils + .illegalArgument("Space %s does not exist", space)); + } + + private static Mono getSpaceId(CloudFoundryClient cloudFoundryClient, + String organizationId, String space) { + return getSpace(cloudFoundryClient, organizationId, space) + .map(ResourceUtils::getId); + } + + private static Mono getSpaceName(Map spaces, String spaceId) { + return Mono.just(spaces.get(spaceId)); + } + + private static boolean isIdentical(String s, String t) { + return s == null ? t == null : s.equals(t); + } + + private static String nullSafe(String host) { + return host == null ? "" : host; + } + + private static Flux requestAllPrivateDomains( + CloudFoundryClient cloudFoundryClient, String organizationId) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient + .organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId).page(page) + .build())); + } + + private static Flux requestAllSharedDomains( + CloudFoundryClient cloudFoundryClient) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient + .sharedDomains() + .list(ListSharedDomainsRequest.builder().page(page).build())); + } + + private static Flux requestAllSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .page(page).build())); + } + + private static Flux requestApplications( + CloudFoundryClient cloudFoundryClient, String routeId) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient.routes() + .listApplications(ListRouteApplicationsRequest.builder() + .routeId(routeId).page(page).build())); + } + + private static Flux requestApplications( + CloudFoundryClient cloudFoundryClient, String application, String spaceId) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listApplications(ListSpaceApplicationsRequest.builder() + .name(application).page(page).spaceId(spaceId) + .build())); + } + + private static Mono requestAssociateRoute( + CloudFoundryClient cloudFoundryClient, String applicationId, + String routeId) { + return cloudFoundryClient.applicationsV2() + .associateRoute(AssociateApplicationRouteRequest.builder() + .applicationId(applicationId).routeId(routeId) + .build()); + } + + private static Mono requestCreateRoute( + CloudFoundryClient cloudFoundryClient, String domainId, String host, + String path, Integer port, Boolean randomPort, String spaceId) { + + org.cloudfoundry.client.v2.routes.CreateRouteRequest.Builder builder = + org.cloudfoundry.client.v2.routes.CreateRouteRequest.builder(); + + if (randomPort != null && randomPort) { + builder.generatePort(true); + } else if (port != null) { + builder.port(port); + } else { + builder.host(host); + builder.path(path); + } + + return cloudFoundryClient.routes() + .create(builder.domainId(domainId).spaceId(spaceId).build()); + } + + private static Mono deleteRoute(CloudFoundryClient cloudFoundryClient, + Duration completionTimeout, String routeId) { + return requestDeleteRoute(cloudFoundryClient, routeId).flatMap(job -> JobUtils + .waitForCompletion(cloudFoundryClient, completionTimeout, job)); + } + + private static Mono requestDeleteRoute(CloudFoundryClient cloudFoundryClient, + String routeId) { + return cloudFoundryClient.routesV3() + .delete(org.cloudfoundry.client.v3.routes.DeleteRouteRequest + .builder().routeId(routeId).build()); + } + + private static Flux requestListSpaceServiceInstances( + CloudFoundryClient cloudFoundryClient, String spaceId) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listServiceInstances(ListSpaceServiceInstancesRequest.builder() + .page(page).returnUserProvidedServiceInstances(true) + .spaceId(spaceId).build())); + } + + private static Flux requestPrivateDomains( + CloudFoundryClient cloudFoundryClient, String organizationId, + String domain) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient + .organizations() + .listPrivateDomains(ListOrganizationPrivateDomainsRequest.builder() + .organizationId(organizationId).name(domain) + .page(page).build())); + } + + private static Mono requestRemoveRouteFromApplication( + CloudFoundryClient cloudFoundryClient, String applicationId, + String routeId) { + return cloudFoundryClient.applicationsV2().removeRoute(RemoveApplicationRouteRequest + .builder().applicationId(applicationId).routeId(routeId).build()); + } + + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, + UnaryOperator modifier) { + + org.cloudfoundry.client.v2.routes.ListRoutesRequest.Builder listBuilder = + modifier.apply(org.cloudfoundry.client.v2.routes.ListRoutesRequest + .builder()); + + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient.routes() + .list(listBuilder.page(page).build())); + } + + private static Flux requestRoutes(CloudFoundryClient cloudFoundryClient, + String domainId, String host, String path, Integer port) { + return requestRoutes(cloudFoundryClient, builder -> builder.domainId(domainId) + .hosts(Optional.ofNullable(host).map(Collections::singletonList) + .orElse(null)) + .paths(Optional.ofNullable(path).map(Collections::singletonList) + .orElse(null)) + .port(Optional.ofNullable(port).orElse(null))); + } + + private static Flux requestSharedDomains( + CloudFoundryClient cloudFoundryClient, String domain) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient + .sharedDomains().list(ListSharedDomainsRequest.builder() + .name(domain).page(page).build())); + } + + private static Flux requestSpaceRoutes(CloudFoundryClient cloudFoundryClient, + String spaceId) { + return PaginationUtils.requestClientV2Resources(page -> cloudFoundryClient.spaces() + .listRoutes(ListSpaceRoutesRequest.builder().spaceId(spaceId) + .page(page).build())); + } + + private static Flux requestSpaces(CloudFoundryClient cloudFoundryClient, + String organizationId, String space) { + return PaginationUtils + .requestClientV2Resources(page -> cloudFoundryClient.organizations() + .listSpaces(ListOrganizationSpacesRequest.builder() + .organizationId(organizationId) + .name(space).page(page).build())); + } + + private static Route toRoute(List applications, String domain, + RouteResource resource, Optional service, String space) { + RouteEntity entity = ResourceUtils.getEntity(resource); + Route.Builder builder = Route.builder().applications(applications).domain(domain) + .host(entity.getHost()).id(ResourceUtils.getId(resource)) + .path(entity.getPath()).space(space); + + service.ifPresent(builder::service); + + return builder.build(); + } } diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java index abf89ad2b0..d2ddf8b47e 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/AbstractOperationsTest.java @@ -1,17 +1,15 @@ /* * Copyright 2013-2021 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. */ package org.cloudfoundry.operations; @@ -63,106 +61,109 @@ public abstract class AbstractOperationsTest { - protected static final Mono MISSING_ID = Mono.error(new java.lang.IllegalStateException("MISSING_ID")); + protected static final Mono MISSING_ID = + Mono.error(new java.lang.IllegalStateException("MISSING_ID")); - protected static final Mono MISSING_ORGANIZATION_ID = Mono - .error(new java.lang.IllegalStateException("MISSING_ORGANIZATION_ID")); + protected static final Mono MISSING_ORGANIZATION_ID = + Mono.error(new java.lang.IllegalStateException("MISSING_ORGANIZATION_ID")); - protected static final Mono MISSING_SPACE_ID = Mono - .error(new java.lang.IllegalStateException("MISSING_SPACE_ID")); + protected static final Mono MISSING_SPACE_ID = + Mono.error(new java.lang.IllegalStateException("MISSING_SPACE_ID")); - protected static final Mono MISSING_USERNAME = Mono - .error(new java.lang.IllegalStateException("MISSING_USERNAME")); + protected static final Mono MISSING_USERNAME = + Mono.error(new java.lang.IllegalStateException("MISSING_USERNAME")); - protected static final String TEST_ORGANIZATION_ID = "test-organization-id"; + protected static final String TEST_ORGANIZATION_ID = "test-organization-id"; - protected static final String TEST_ORGANIZATION_NAME = "test-organization-name"; + protected static final String TEST_ORGANIZATION_NAME = "test-organization-name"; - protected static final String TEST_SPACE_ID = "test-space-id"; + protected static final String TEST_SPACE_ID = "test-space-id"; - protected static final String TEST_SPACE_NAME = "test-space-name"; + protected static final String TEST_SPACE_NAME = "test-space-name"; - protected static final String TEST_USERNAME = "test-username"; + protected static final String TEST_USERNAME = "test-username"; - protected final ApplicationsV2 applications = mock(ApplicationsV2.class, RETURNS_SMART_NULLS); + protected final ApplicationsV2 applications = mock(ApplicationsV2.class, RETURNS_SMART_NULLS); - protected final ApplicationsV3 applicationsV3 = mock(ApplicationsV3.class, RETURNS_SMART_NULLS); + protected final ApplicationsV3 applicationsV3 = mock(ApplicationsV3.class, RETURNS_SMART_NULLS); - protected final Authorizations authorizations = mock(Authorizations.class, RETURNS_SMART_NULLS); + protected final Authorizations authorizations = mock(Authorizations.class, RETURNS_SMART_NULLS); - protected final Buildpacks buildpacks = mock(Buildpacks.class, RETURNS_SMART_NULLS); + protected final Buildpacks buildpacks = mock(Buildpacks.class, RETURNS_SMART_NULLS); - protected final CloudFoundryClient cloudFoundryClient = mock(CloudFoundryClient.class, RETURNS_SMART_NULLS); + protected final CloudFoundryClient cloudFoundryClient = + mock(CloudFoundryClient.class, RETURNS_SMART_NULLS); - protected final Domains domains = mock(Domains.class, RETURNS_SMART_NULLS); - protected final DomainsV3 domainsV3 = mock(DomainsV3.class, RETURNS_SMART_NULLS); + protected final Domains domains = mock(Domains.class, RETURNS_SMART_NULLS); + protected final DomainsV3 domainsV3 = mock(DomainsV3.class, RETURNS_SMART_NULLS); - protected final DopplerClient dopplerClient = mock(DopplerClient.class, RETURNS_SMART_NULLS); + protected final DopplerClient dopplerClient = mock(DopplerClient.class, RETURNS_SMART_NULLS); - protected final Events events = mock(Events.class, RETURNS_SMART_NULLS); + protected final Events events = mock(Events.class, RETURNS_SMART_NULLS); - protected final FeatureFlags featureFlags = mock(FeatureFlags.class, RETURNS_SMART_NULLS); + protected final FeatureFlags featureFlags = mock(FeatureFlags.class, RETURNS_SMART_NULLS); - protected final Jobs jobs = mock(Jobs.class, RETURNS_SMART_NULLS); - protected final JobsV3 jobsV3 = mock(JobsV3.class, RETURNS_SMART_NULLS); + protected final Jobs jobs = mock(Jobs.class, RETURNS_SMART_NULLS); + protected final JobsV3 jobsV3 = mock(JobsV3.class, RETURNS_SMART_NULLS); - protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = mock( - OrganizationQuotaDefinitions.class, - RETURNS_SMART_NULLS); + protected final OrganizationQuotaDefinitions organizationQuotaDefinitions = + mock(OrganizationQuotaDefinitions.class, RETURNS_SMART_NULLS); - protected final Organizations organizations = mock(Organizations.class, RETURNS_SMART_NULLS); - protected final OrganizationsV3 organizationsV3 = mock(OrganizationsV3.class, RETURNS_SMART_NULLS); + protected final Organizations organizations = mock(Organizations.class, RETURNS_SMART_NULLS); + protected final OrganizationsV3 organizationsV3 = + mock(OrganizationsV3.class, RETURNS_SMART_NULLS); - protected final PrivateDomains privateDomains = mock(PrivateDomains.class, RETURNS_SMART_NULLS); + protected final PrivateDomains privateDomains = mock(PrivateDomains.class, RETURNS_SMART_NULLS); - protected final ResourceMatch resourceMatch = mock(ResourceMatch.class, RETURNS_SMART_NULLS); + protected final ResourceMatch resourceMatch = mock(ResourceMatch.class, RETURNS_SMART_NULLS); - protected final RouterGroups routerGroups = mock(RouterGroups.class, RETURNS_SMART_NULLS); + protected final RouterGroups routerGroups = mock(RouterGroups.class, RETURNS_SMART_NULLS); - protected final Routes routes = mock(Routes.class, RETURNS_SMART_NULLS); - protected final RoutesV3 routesV3 = mock(RoutesV3.class, RETURNS_SMART_NULLS); + protected final Routes routes = mock(Routes.class, RETURNS_SMART_NULLS); + protected final RoutesV3 routesV3 = mock(RoutesV3.class, RETURNS_SMART_NULLS); - protected final RoutingClient routingClient = mock(RoutingClient.class, RETURNS_SMART_NULLS); + protected final RoutingClient routingClient = mock(RoutingClient.class, RETURNS_SMART_NULLS); - protected final ServiceBindingsV2 serviceBindingsV2 = mock(ServiceBindingsV2.class, RETURNS_SMART_NULLS); + protected final ServiceBindingsV2 serviceBindingsV2 = + mock(ServiceBindingsV2.class, RETURNS_SMART_NULLS); - protected final ServiceBrokers serviceBrokers = mock(ServiceBrokers.class, RETURNS_SMART_NULLS); + protected final ServiceBrokers serviceBrokers = mock(ServiceBrokers.class, RETURNS_SMART_NULLS); - protected final ServiceInstances serviceInstances = mock(ServiceInstances.class, RETURNS_SMART_NULLS); + protected final ServiceInstances serviceInstances = + mock(ServiceInstances.class, RETURNS_SMART_NULLS); - protected final ServiceKeys serviceKeys = mock(ServiceKeys.class, RETURNS_SMART_NULLS); + protected final ServiceKeys serviceKeys = mock(ServiceKeys.class, RETURNS_SMART_NULLS); - protected final ServicePlanVisibilities servicePlanVisibilities = mock(ServicePlanVisibilities.class, - RETURNS_SMART_NULLS); + protected final ServicePlanVisibilities servicePlanVisibilities = + mock(ServicePlanVisibilities.class, RETURNS_SMART_NULLS); - protected final ServicePlans servicePlans = mock(ServicePlans.class, RETURNS_SMART_NULLS); + protected final ServicePlans servicePlans = mock(ServicePlans.class, RETURNS_SMART_NULLS); - protected final Services services = mock(Services.class, RETURNS_SMART_NULLS); + protected final Services services = mock(Services.class, RETURNS_SMART_NULLS); - protected final SharedDomains sharedDomains = mock(SharedDomains.class, RETURNS_SMART_NULLS); + protected final SharedDomains sharedDomains = mock(SharedDomains.class, RETURNS_SMART_NULLS); - protected final SpaceQuotaDefinitions spaceQuotaDefinitions = mock(SpaceQuotaDefinitions.class, - RETURNS_SMART_NULLS); + protected final SpaceQuotaDefinitions spaceQuotaDefinitions = + mock(SpaceQuotaDefinitions.class, RETURNS_SMART_NULLS); - protected final Spaces spaces = mock(Spaces.class, RETURNS_SMART_NULLS); - protected final SpacesV3 spacesV3 = mock(SpacesV3.class, RETURNS_SMART_NULLS); + protected final Spaces spaces = mock(Spaces.class, RETURNS_SMART_NULLS); + protected final SpacesV3 spacesV3 = mock(SpacesV3.class, RETURNS_SMART_NULLS); - protected final Stacks stacks = mock(Stacks.class, RETURNS_SMART_NULLS); + protected final Stacks stacks = mock(Stacks.class, RETURNS_SMART_NULLS); - protected final Tasks tasks = mock(Tasks.class, RETURNS_SMART_NULLS); + protected final Tasks tasks = mock(Tasks.class, RETURNS_SMART_NULLS); - protected final Tokens tokens = mock(Tokens.class, RETURNS_SMART_NULLS); + protected final Tokens tokens = mock(Tokens.class, RETURNS_SMART_NULLS); - protected final UaaClient uaaClient = mock(UaaClient.class, RETURNS_SMART_NULLS); + protected final UaaClient uaaClient = mock(UaaClient.class, RETURNS_SMART_NULLS); - protected final org.cloudfoundry.uaa.users.Users uaaUsers = mock(org.cloudfoundry.uaa.users.Users.class, - RETURNS_SMART_NULLS); + protected final org.cloudfoundry.uaa.users.Users uaaUsers = + mock(org.cloudfoundry.uaa.users.Users.class, RETURNS_SMART_NULLS); - protected final UserProvidedServiceInstances userProvidedServiceInstances = mock( - UserProvidedServiceInstances.class, - RETURNS_SMART_NULLS); + protected final UserProvidedServiceInstances userProvidedServiceInstances = + mock(UserProvidedServiceInstances.class, RETURNS_SMART_NULLS); - protected final Users users = mock(Users.class, RETURNS_SMART_NULLS); + protected final Users users = mock(Users.class, RETURNS_SMART_NULLS); @Before public final void mockClient() { diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java index 1408a79e4f..c86ce38a62 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/routes/DefaultRoutesTest.java @@ -1,29 +1,25 @@ /* * Copyright 2013-2021 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. */ package org.cloudfoundry.operations.routes; import org.cloudfoundry.client.CloudFoundryClient; -import org.cloudfoundry.client.v2.ClientV2Exception; import org.cloudfoundry.client.v2.Metadata; import org.cloudfoundry.client.v2.applications.ApplicationResource; import org.cloudfoundry.client.v2.applications.AssociateApplicationRouteRequest; import org.cloudfoundry.client.v2.applications.AssociateApplicationRouteResponse; import org.cloudfoundry.client.v2.applications.RemoveApplicationRouteRequest; - import org.cloudfoundry.client.v3.jobs.GetJobRequest; import org.cloudfoundry.client.v3.jobs.GetJobResponse; import org.cloudfoundry.client.v3.jobs.JobState; @@ -33,16 +29,11 @@ import org.cloudfoundry.client.v2.organizations.ListOrganizationSpacesResponse; import org.cloudfoundry.client.v2.privatedomains.PrivateDomainResource; import org.cloudfoundry.client.v2.routes.CreateRouteResponse; -import org.cloudfoundry.client.v2.routes.DeleteRouteResponse; import org.cloudfoundry.client.v2.routes.ListRouteApplicationsRequest; import org.cloudfoundry.client.v2.routes.ListRouteApplicationsResponse; import org.cloudfoundry.client.v2.routes.ListRoutesResponse; import org.cloudfoundry.client.v2.routes.RouteEntity; -import org.cloudfoundry.client.v2.routes.RouteExistsRequest; import org.cloudfoundry.client.v2.routes.RouteResource; -import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceRequest; -import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceResponse; -import org.cloudfoundry.client.v2.serviceinstances.ServiceInstanceResource; import org.cloudfoundry.client.v2.serviceinstances.UnionServiceInstanceEntity; import org.cloudfoundry.client.v2.serviceinstances.UnionServiceInstanceResource; import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsRequest; @@ -64,36 +55,22 @@ import org.cloudfoundry.client.v3.Relationship; import org.cloudfoundry.client.v3.ToManyRelationship; import org.cloudfoundry.client.v3.ToOneRelationship; -import org.cloudfoundry.client.v3.domains.CheckReservedRoutesRequest; -import org.cloudfoundry.client.v3.domains.CheckReservedRoutesResponse; import org.cloudfoundry.client.v3.domains.DomainRelationships; import org.cloudfoundry.client.v3.domains.DomainResource; import org.cloudfoundry.client.v3.spaces.DeleteUnmappedRoutesRequest; import org.cloudfoundry.operations.AbstractOperationsTest; - -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import reactor.test.scheduler.VirtualTimeScheduler; - import java.time.Duration; -import java.util.Arrays; import java.util.Collections; -import java.util.LinkedList; import java.util.Optional; -import java.util.Queue; -import java.util.function.Supplier; import static org.assertj.core.api.Assertions.assertThat; import static org.cloudfoundry.operations.TestObjects.fill; import static org.mockito.Mockito.when; -import org.mockito.MockedStatic; + public final class DefaultRoutesTest extends AbstractOperationsTest { @@ -103,7 +80,7 @@ public final class DefaultRoutesTest extends AbstractOperationsTest { private static final String TEST_DOMAIN_NAME = "domain-name"; private static final String TEST_PATH = "test-path"; private static final String TEST_HOST = "192.168.0,.1"; - private static final Integer TEST_PORT = 8080; + private static final String TEST_JOB_ID = "test-job-id"; @Test @@ -111,14 +88,10 @@ public void checkRoute() { mockListDomains(this.cloudFoundryClient); mockCheckReservedRoutes(this.cloudFoundryClient); - this.routes.check(CheckRouteRequest.builder() - .host(TEST_HOST) - .path(TEST_PATH) - .domain(TEST_DOMAIN_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(true) - .expectComplete() + this.routes + .check(CheckRouteRequest.builder().host(TEST_HOST).path(TEST_PATH) + .domain(TEST_DOMAIN_NAME).build()) + .as(StepVerifier::create).expectNext(true).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -167,18 +140,13 @@ public void createRouteAssignedPort() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, null, 9999, - "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, + null, 9999, "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .port(9999) - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() + .create(CreateRouteRequest.builder().domain("test-domain").port(9999) + .space(TEST_SPACE_NAME).build()) + .as(StepVerifier::create).expectNext(1).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -189,11 +157,8 @@ public void createRouteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .space(TEST_SPACE_NAME) - .build()) + .create(CreateRouteRequest.builder().domain("test-domain").host("test-host") + .space(TEST_SPACE_NAME).build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Domain test-domain does not exist")) @@ -206,12 +171,8 @@ public void createRouteInvalidSpace() { requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .space(TEST_SPACE_NAME) - .build()) + .create(CreateRouteRequest.builder().domain("test-domain").host("test-host") + .path("test-path").space(TEST_SPACE_NAME).build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Space test-space-name does not exist")) @@ -222,18 +183,13 @@ public void createRouteInvalidSpace() { public void createRouteNoHost() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, "test-path", null, - "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, + "test-path", null, "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .path("test-path") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() + .create(CreateRouteRequest.builder().domain("test-domain").path("test-path") + .space(TEST_SPACE_NAME).build()) + .as(StepVerifier::create).expectNext(1).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -241,18 +197,13 @@ public void createRouteNoHost() { public void createRouteNoPath() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, null, null, - "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + null, null, null, "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() + .create(CreateRouteRequest.builder().domain("test-domain").host("test-host") + .space(TEST_SPACE_NAME).build()) + .as(StepVerifier::create).expectNext(1).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -260,19 +211,13 @@ public void createRouteNoPath() { public void createRoutePrivateDomain() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", - null, "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + null, "test-path", null, "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .host("test-host") - .path("test-path") - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() + .create(CreateRouteRequest.builder().domain("test-domain").host("test-host") + .path("test-path").space(TEST_SPACE_NAME).build()) + .as(StepVerifier::create).expectNext(1).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -281,18 +226,13 @@ public void createRouteRandomPort() { requestSpaces(this.cloudFoundryClient, TEST_ORGANIZATION_ID, TEST_SPACE_NAME); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, true, null, null, - "test-space-id"); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, true, + null, null, "test-space-id"); this.routes - .create(CreateRouteRequest.builder() - .domain("test-domain") - .randomPort(true) - .space(TEST_SPACE_NAME) - .build()) - .as(StepVerifier::create) - .expectNext(1) - .expectComplete() + .create(CreateRouteRequest.builder().domain("test-domain").randomPort(true) + .space(TEST_SPACE_NAME).build()) + .as(StepVerifier::create).expectNext(1).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -301,9 +241,7 @@ public void deleteOrphanedRoutes() { mockDeleteOrphanedRoutes(this.cloudFoundryClient); this.routes.deleteOrphanedRoutes(DeleteOrphanedRoutesRequest.builder().build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } private static void mockDeleteOrphanedRoutes(CloudFoundryClient cloudFoundryClient){ @@ -319,17 +257,14 @@ private static void mockDeleteOrphanedRoutes(CloudFoundryClient cloudFoundryClie @Test public void deleteRoute() { requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); + requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path", null); mockDeleteRequest(this.cloudFoundryClient, "test-route-id"); - this.routes.delete(DeleteRouteRequest.builder() - .host("test-host") - .path("test-path") - .domain("test-domain") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + this.routes + .delete(DeleteRouteRequest.builder().host("test-host").path("test-path") + .domain("test-domain").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } private static void mockDeleteRequest(CloudFoundryClient cloudFoundryClient,String routeId){ @@ -351,22 +286,14 @@ public void listCurrentOrganizationNoSpace() { "test-route-entity-spaceId"); requestApplications(this.cloudFoundryClient, "test-id"); - this.routes - .list(ListRoutesRequest.builder() - .level(Level.ORGANIZATION) - .build()) + this.routes.list(ListRoutesRequest.builder().level(Level.ORGANIZATION).build()) .as(StepVerifier::create) - .expectNext(Route.builder() - .application("test-application-name") - .domain("test-shared-domain-name") - .host("test-route-entity-host") - .id("test-id") - .path("test-route-entity-path") - .service("test-service-instance-entityname") - .space("test-space-entity-name") + .expectNext(Route.builder().application("test-application-name") + .domain("test-shared-domain-name").host("test-route-entity-host") + .id("test-id").path("test-route-entity-path") + .service("test-service-instance-entityname").space("test-space-entity-name") .build()) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -377,13 +304,8 @@ public void listCurrentOrganizationNoSpaceNoRoutes() { requestSpacesAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID); requestApplications(this.cloudFoundryClient, "test-id"); - this.routes - .list(ListRoutesRequest.builder() - .level(Level.ORGANIZATION) - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + this.routes.list(ListRoutesRequest.builder().level(Level.ORGANIZATION).build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -394,21 +316,13 @@ public void listCurrentSpace() { requestSpacesAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID); requestApplications(this.cloudFoundryClient, "test-route-id"); - this.routes - .list(ListRoutesRequest.builder() - .level(Level.SPACE) - .build()) + this.routes.list(ListRoutesRequest.builder().level(Level.SPACE).build()) .as(StepVerifier::create) - .expectNext(Route.builder() - .application("test-application-name") - .domain("test-shared-domain-name") - .host("test-route-entity-host") - .id("test-route-id") - .path("test-route-entity-path") - .space("test-space-entity-name") - .build()) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .expectNext(Route.builder().application("test-application-name") + .domain("test-shared-domain-name").host("test-route-entity-host") + .id("test-route-id").path("test-route-entity-path") + .space("test-space-entity-name").build()) + .expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -419,20 +333,12 @@ public void listCurrentSpaceNoPath() { requestSpacesAll(this.cloudFoundryClient, TEST_ORGANIZATION_ID); requestApplications(this.cloudFoundryClient, "test-route-id"); - this.routes - .list(ListRoutesRequest.builder() - .level(Level.SPACE) - .build()) + this.routes.list(ListRoutesRequest.builder().level(Level.SPACE).build()) .as(StepVerifier::create) - .expectNext(Route.builder() - .application("test-application-name") - .domain("test-shared-domain-name") - .host("test-route-entity-host") - .id("test-route-id") - .space("test-space-entity-name") - .build()) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .expectNext(Route.builder().application("test-application-name") + .domain("test-shared-domain-name").host("test-route-entity-host") + .id("test-route-id").space("test-space-entity-name").build()) + .expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -440,20 +346,16 @@ public void mapRouteAssignedPort() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, 9999); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, null, 9999, - TEST_SPACE_ID); + requestRoutesEmpty(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, + 9999); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, + null, 9999, TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .port(9999) - .build()) - .as(StepVerifier::create) - .expectNext(9999) - .expectComplete() + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").port(9999).build()) + .as(StepVerifier::create).expectNext(9999).expectComplete() .verify(Duration.ofSeconds(5)); } @@ -461,36 +363,28 @@ public void mapRouteAssignedPort() { public void mapRouteExists() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); + requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path", null); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test public void mapRouteInvalidApplicationName() { requestApplicationsEmpty(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", - null, "test-space-id"); + requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path", null); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + null, "test-path", null, "test-space-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Application test-application-name does not exist")) @@ -504,12 +398,8 @@ public void mapRouteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Domain test-domain does not exist")) @@ -520,60 +410,46 @@ public void mapRouteInvalidDomain() { public void mapRouteNoHost() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", null, "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, "test-path", null, - TEST_SPACE_ID); + requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", null, + "test-path", null); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", null, null, + "test-path", null, TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test public void mapRoutePath() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutesTwo(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path"); + requestRoutesTwo(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path"); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test public void mapRoutePrivateDomain() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", null, "test-path", - null, TEST_SPACE_ID); + requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path", null); + requestCreateRoute(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + null, "test-path", null, TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -581,21 +457,16 @@ public void mapRouteSharedDomain() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", "test-path", null); - requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", null, "test-path", - null, TEST_SPACE_ID); + requestRoutesEmpty(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", + "test-path", null); + requestCreateRoute(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", + null, "test-path", null, TEST_SPACE_ID); requestAssociateRoute(this.cloudFoundryClient, "test-application-id", "test-route-id"); this.routes - .map(MapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .map(MapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -604,17 +475,13 @@ public void unmapRouteAssignedPort() { requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); requestRoutes(this.cloudFoundryClient, "test-shared-domain-metadata-id", null, null, 9999); - requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", "test-route-id"); + requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", + "test-route-id"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .port(9999) - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").port(9999).build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -623,11 +490,8 @@ public void unmapRouteInvalidApplicationName() { requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .build()) + .unmap(UnmapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Application test-application-name does not exist")) @@ -641,11 +505,8 @@ public void unmapRouteInvalidDomain() { requestSharedDomainsEmpty(this.cloudFoundryClient, "test-domain"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .build()) + .unmap(UnmapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Domain test-domain does not exist")) @@ -656,15 +517,12 @@ public void unmapRouteInvalidDomain() { public void unmapRouteInvalidRoute() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); + requestRoutesEmpty(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path", null); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) + .unmap(UnmapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) .as(StepVerifier::create) .consumeErrorWith(t -> assertThat(t).isInstanceOf(IllegalArgumentException.class) .hasMessage("Route for test-domain does not exist")) @@ -675,19 +533,15 @@ public void unmapRouteInvalidRoute() { public void unmapRoutePrivateDomain() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomains(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", "test-path", null); - requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", "test-route-id"); + requestRoutes(this.cloudFoundryClient, "test-private-domain-metadata-id", "test-host", + "test-path", null); + requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", + "test-route-id"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } @Test @@ -695,19 +549,15 @@ public void unmapRouteSharedDomain() { requestApplications(this.cloudFoundryClient, "test-application-name", TEST_SPACE_ID); requestPrivateDomainsEmpty(this.cloudFoundryClient, TEST_ORGANIZATION_ID, "test-domain"); requestSharedDomains(this.cloudFoundryClient, "test-domain"); - requestRoutes(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", "test-path", null); - requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", "test-route-id"); + requestRoutes(this.cloudFoundryClient, "test-shared-domain-metadata-id", "test-host", + "test-path", null); + requestRemoveRouteFromApplication(this.cloudFoundryClient, "test-application-id", + "test-route-id"); this.routes - .unmap(UnmapRouteRequest.builder() - .applicationName("test-application-name") - .domain("test-domain") - .host("test-host") - .path("test-path") - .build()) - .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .unmap(UnmapRouteRequest.builder().applicationName("test-application-name") + .domain("test-domain").host("test-host").path("test-path").build()) + .as(StepVerifier::create).expectComplete().verify(Duration.ofSeconds(5)); } private static void requestApplications(CloudFoundryClient cloudFoundryClient, String routeId) {