package io.pivotal.services.plugin.tasks.helper; import io.pivotal.services.plugin.CfProperties; import io.pivotal.services.plugin.CfRouteUtil; import io.pivotal.services.plugin.ImmutableCfProperties; import org.cloudfoundry.operations.CloudFoundryOperations; import org.cloudfoundry.operations.applications.ApplicationDetail; import org.gradle.api.Project; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import reactor.core.publisher.Mono; import java.util.Collections; import java.util.Optional; import static org.cloudfoundry.util.tuple.TupleUtils.function; /** * route -> app * <p> * Stage 1: * Step 1: * route-green -> app-green * ...testing after stage 1.. * Stage 2: * Step 2: * route -> app-green, app * route-green -> app-green * <p> * Step 3: * route -> app-green * route-green -> app-green * -> app * Step 4: * route -> app-green * -> app * <p> * Step 5: * route -> app-green * -> app-blue * <p> * Step 6: * route -> app * -> app-blue * * @author Biju Kunjummen * @author Gabriel Couto */ public class CfBlueGreenStage2Delegate { private static final Logger LOGGER = Logging .getLogger(CfBlueGreenStage2Delegate.class); private CfMapRouteDelegate mapRouteDelegate = new CfMapRouteDelegate(); private CfUnMapRouteDelegate unMapRouteDelegate = new CfUnMapRouteDelegate(); private CfAppDetailsDelegate appDetailsDelegate = new CfAppDetailsDelegate(); private CfRenameAppDelegate renameAppDelegate = new CfRenameAppDelegate(); private CfDeleteAppDelegate deleteAppDelegate = new CfDeleteAppDelegate(); private CfAppStopDelegate appStopDelegate = new CfAppStopDelegate(); public Mono<Void> runStage2(Project project, CloudFoundryOperations cfOperations, CfProperties cfProperties) { String greenNameString = cfProperties.name() + "-green"; Mono<String> greenRouteMono = CfRouteUtil.getTempRoute(cfOperations, cfProperties, "green"); CfProperties greenName = ImmutableCfProperties.copyOf(cfProperties) .withName(greenNameString); Mono<CfProperties> greenNameAndRouteMono = greenRouteMono.map(greenRoute -> ImmutableCfProperties.copyOf(cfProperties) .withName(greenNameString) .withHost(null) .withDomain(null) .withRoutes(Collections.singletonList(greenRoute))); CfProperties blueName = ImmutableCfProperties.copyOf(cfProperties) .withName(cfProperties.name() + "-blue"); Mono<Optional<ApplicationDetail>> backupAppMono = appDetailsDelegate .getAppDetails(cfOperations, blueName); Mono<Optional<ApplicationDetail>> existingAppMono = appDetailsDelegate .getAppDetails(cfOperations, cfProperties); Mono<Void> bgResult = Mono.zip(backupAppMono, existingAppMono, greenNameAndRouteMono, greenRouteMono) .flatMap(function((backupApp, existingApp, greenNameAndRoute, greenRouteString) -> { LOGGER.lifecycle( "Running Blue Green Deploy - after deploying a 'green' app. App '{}' with route '{}'", cfProperties.name(), greenRouteString); return (backupApp.isPresent() ? deleteAppDelegate.deleteApp(cfOperations, blueName) : Mono.empty()) .thenMany(mapRouteDelegate.mapRoute(cfOperations, greenName)) .thenMany(existingApp.isPresent() ? unMapRouteDelegate.unmapRoute(cfOperations, cfProperties) : Mono.empty()) .thenMany(unMapRouteDelegate.unmapRoute(cfOperations, greenNameAndRoute)) .then(existingApp.isPresent() ? renameAppDelegate .renameApp(cfOperations, cfProperties, blueName) : Mono.empty()) .then(renameAppDelegate .renameApp(cfOperations, greenName, cfProperties)) .then( existingApp.isPresent() ? appStopDelegate.stopApp(cfOperations, blueName) : Mono.empty()); })); return bgResult; } }