io.pivotal.services.plugin.CfRouteUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ya-cf-app-gradle-plugin Show documentation
Show all versions of ya-cf-app-gradle-plugin Show documentation
Gradle Plugin to push an application to Cloud Foundry
package io.pivotal.services.plugin;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
import org.cloudfoundry.operations.applications.DecomposedRoute;
import org.cloudfoundry.operations.applications.DomainSummary;
import reactor.core.publisher.Mono;
/**
* @author Gabriel Couto
*/
public class CfRouteUtil {
private static Map> domainCache = new HashMap<>();
/**
* Returns a list of decomposed routes
*
* @param cfOperations the operations to check the domain names against
* @param routes all aplication's routes
* @param routePath the application path to be included in the routes
* @return the decomposed routes
*/
public static List decomposedRoutes(CloudFoundryOperations cfOperations, List routes, String routePath) {
final List finalDomainSummaries = getCachedDomainSummaries(cfOperations);
return routes.stream().map(route ->
decomposeRoute(finalDomainSummaries, route, routePath)
).collect(Collectors.toList());
}
/**
* Get the first route and generate a temp route from it, adding the suffix
* after the hostname.
*
* @param cfOperations the operations to check the domain names against
* @param cfProperties the properties of the app
* @param suffix the suffix to add in the host
* @return the calculated route
*/
public static String getTempRoute(CloudFoundryOperations cfOperations, CfProperties cfProperties, String suffix) {
if (cfProperties.routes() == null || cfProperties.routes().isEmpty())
return getTempRoute(cfProperties.host(), cfProperties.domain(), null, cfProperties.path(), suffix);
DecomposedRoute route = decomposeRoute(getCachedDomainSummaries(cfOperations), cfProperties.routes().get(0), cfProperties.path());
return getTempRoute(route.getHost(), route.getDomain(), route.getPort(), route.getPath(), suffix);
}
private static String getTempRoute(String host, String domain, Integer port, String path, String suffix) {
return (host != null ? host + suffix + "." : suffix + ".")
+ domain
+ (port != null ? ":" + port : "")
+ (path != null ? "/" + path : "");
}
public static List getCachedDomainSummaries(CloudFoundryOperations cfOperations) {
if(cfOperations instanceof DefaultCloudFoundryOperations) {
return domainCache.get(cfOperations);
}
throw new IllegalArgumentException(cfOperations.getClass().getName() + " does not support caching yet.");
}
public static void cacheDomainSummaries(DefaultCloudFoundryOperations cfOperations) {
if (!domainCache.containsKey(cfOperations)) {
domainCache.put(cfOperations, fetchDomainSummaries(cfOperations).block());
}
}
public static Mono> fetchDomainSummaries(CloudFoundryOperations cfOperations) {
return cfOperations.domains().list()
.map(domain -> DomainSummary.builder()
.id(domain.getId())
.name(domain.getName())
.type(domain.getType())
.build())
.collectList();
}
/**
* Copy of org.cloudfoundry.operations.applications.RouteUtil.decomposeRoute
*/
private static DecomposedRoute decomposeRoute(List availableDomains, String route, String routePath) {
String domain = null;
String host = null;
String path = null;
Integer port = null;
String routeWithoutSuffix = route;
if (availableDomains.size() == 0) {
throw new IllegalArgumentException(String.format("The route %s did not match any existing domains", route));
}
List sortedDomains = availableDomains.stream()
.sorted(Comparator.comparingInt(domainSummary -> domainSummary.getName().length()).reversed())
.collect(Collectors.toList());
if (route.contains("/")) {
int index = route.indexOf("/");
path = routePath != null ? routePath : route.substring(index);
routeWithoutSuffix = route.substring(0, index);
} else if (hasPort(route)) {
port = getPort(route);
routeWithoutSuffix = route.substring(0, route.indexOf(":"));
}
for (DomainSummary item : sortedDomains) {
if (isDomainMatch(routeWithoutSuffix, item.getName())) {
domain = item.getName();
if (domain.length() < routeWithoutSuffix.length()) {
host = routeWithoutSuffix.substring(0, routeWithoutSuffix.lastIndexOf(domain) - 1);
}
break;
}
}
if (domain == null) {
throw new IllegalArgumentException(String.format("The route %s did not match any existing domains", route));
}
if ((host != null || path != null) && port != null) {
throw new IllegalArgumentException(String.format("The route %s is invalid: Host/path cannot be set with port", route));
}
return DecomposedRoute.builder()
.domain(domain)
.host(host)
.path(path)
.port(port)
.build();
}
private static Integer getPort(String route) {
Pattern pattern = Pattern.compile(":\\d+$");
Matcher matcher = pattern.matcher(route);
matcher.find();
return Integer.valueOf(route.substring(matcher.start() + 1, matcher.end()));
}
private static Boolean hasPort(String route) {
Pattern pattern = Pattern.compile("^.+?:\\d+$");
Matcher matcher = pattern.matcher(route);
return matcher.matches();
}
private static boolean isDomainMatch(String route, String domain) {
return route.equals(domain) || route.endsWith(domain) && route.charAt(route.length() - domain.length() - 1) == '.';
}
}