Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package org.cloudfoundry.multiapps.controller.process.steps;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -11,9 +8,10 @@
import java.util.TreeSet;
import java.util.stream.Collectors;

import com.sap.cloudfoundry.client.facade.CloudControllerClient;
import com.sap.cloudfoundry.client.facade.domain.CloudServiceKey;
import jakarta.inject.Inject;
import jakarta.inject.Named;

import org.cloudfoundry.multiapps.common.SLException;
import org.cloudfoundry.multiapps.controller.api.model.ProcessType;
import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudServiceInstanceExtended;
Expand All @@ -35,6 +33,7 @@
import org.cloudfoundry.multiapps.controller.core.util.CloudModelBuilderUtil;
import org.cloudfoundry.multiapps.controller.core.util.NameUtil;
import org.cloudfoundry.multiapps.controller.process.Messages;
import org.cloudfoundry.multiapps.controller.process.util.DeprecatedBuildpackChecker;
import org.cloudfoundry.multiapps.controller.process.util.ProcessTypeParser;
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
import org.cloudfoundry.multiapps.mta.builders.v2.ParametersChainBuilder;
Expand All @@ -51,8 +50,8 @@
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;

import com.sap.cloudfoundry.client.facade.CloudControllerClient;
import com.sap.cloudfoundry.client.facade.domain.CloudServiceKey;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

@Named("buildCloudDeployModelStep")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
Expand All @@ -62,6 +61,8 @@ public class BuildCloudDeployModelStep extends SyncFlowableStep {
private ModuleToDeployHelper moduleToDeployHelper;
@Inject
private ProcessTypeParser processTypeParser;
@Inject
private DeprecatedBuildpackChecker buildpackChecker;

@Override
protected StepPhase executeStep(ProcessContext context) {
Expand Down Expand Up @@ -89,6 +90,10 @@ protected StepPhase executeStep(ProcessContext context) {
List<Module> modulesCalculatedForDeployment = calculateModulesForDeployment(context, deploymentDescriptor, mtaDescriptorModules,
mtaManifestModulesNames, deployedModuleNames,
mtaModulesForDeployment);

buildpackChecker.warnForDeprecatedBuildpacks(modulesCalculatedForDeployment, deploymentDescriptor, getStepLogger(),
moduleToDeployHelper);

List<String> moduleJsons = modulesCalculatedForDeployment.stream()
.map(SecureSerialization::toJson)
.collect(toList());
Expand Down Expand Up @@ -179,7 +184,7 @@ private List<String> getAppNames(List<Module> modulesCalculatedForDeployment) {
.map(NameUtil::getApplicationName)
.collect(toList());
}

private List<CloudServiceInstanceExtended> buildServicesForBindings(ServicesCloudModelBuilder servicesCloudModelBuilder,
DeploymentDescriptor deploymentDescriptor,
List<Module> modulesCalculatedForDeployment) {
Expand All @@ -191,11 +196,13 @@ private List<CloudServiceInstanceExtended> buildServicesForBindings(ServicesClou
private List<CloudServiceInstanceExtended> buildFilteredServices(DeploymentDescriptor deploymentDescriptor,
List<String> filteredResourceNames,
ServicesCloudModelBuilder servicesCloudModelBuilder) {
CloudModelBuilderContentCalculator<Resource> resourcesCloudModelBuilderContentCalculator = new ResourcesCloudModelBuilderContentCalculator(filteredResourceNames,
getStepLogger(),
false);
CloudModelBuilderContentCalculator<Resource> resourcesCloudModelBuilderContentCalculator = new ResourcesCloudModelBuilderContentCalculator(
filteredResourceNames,
getStepLogger(),
false);
// this always filters the 'isActive', 'isResourceSpecifiedForDeployment' and 'isService' resources
List<Resource> calculatedFilteredResources = resourcesCloudModelBuilderContentCalculator.calculateContentForBuilding(deploymentDescriptor.getResources());
List<Resource> calculatedFilteredResources = resourcesCloudModelBuilderContentCalculator.calculateContentForBuilding(
deploymentDescriptor.getResources());

return servicesCloudModelBuilder.build(calculatedFilteredResources);
}
Expand Down Expand Up @@ -235,9 +242,10 @@ private List<Module> calculateModulesForDeployment(ProcessContext context, Deplo

private List<Resource> calculateResourcesForDeployment(ProcessContext context, DeploymentDescriptor deploymentDescriptor) {
List<String> resourcesSpecifiedForDeployment = context.getVariable(Variables.RESOURCES_FOR_DEPLOYMENT);
CloudModelBuilderContentCalculator<Resource> resourcesCloudModelBuilderContentCalculator = new ResourcesCloudModelBuilderContentCalculator(resourcesSpecifiedForDeployment,
getStepLogger(),
shouldProcessOnlyUserProvidedServices(context));
CloudModelBuilderContentCalculator<Resource> resourcesCloudModelBuilderContentCalculator = new ResourcesCloudModelBuilderContentCalculator(
resourcesSpecifiedForDeployment,
getStepLogger(),
shouldProcessOnlyUserProvidedServices(context));
return resourcesCloudModelBuilderContentCalculator.calculateContentForBuilding(deploymentDescriptor.getResources());
}

Expand All @@ -247,8 +255,8 @@ private boolean shouldProcessOnlyUserProvidedServices(ProcessContext context) {
}

protected ModulesCloudModelBuilderContentCalculator
getModulesContentCalculator(ProcessContext context, List<Module> mtaDescriptorModules, Set<String> mtaManifestModuleNames,
Set<String> deployedModuleNames, Set<String> mtaModuleNamesForDeployment) {
getModulesContentCalculator(ProcessContext context, List<Module> mtaDescriptorModules, Set<String> mtaManifestModuleNames,
Set<String> deployedModuleNames, Set<String> mtaModuleNamesForDeployment) {
List<ModulesContentValidator> modulesValidators = getModuleContentValidators(context.getControllerClient(), mtaDescriptorModules,
mtaModuleNamesForDeployment, deployedModuleNames);
return new ModulesCloudModelBuilderContentCalculator(mtaManifestModuleNames,
Expand Down Expand Up @@ -306,7 +314,8 @@ private List<String> getDomainsFromApps(ProcessContext context, DeploymentDescri
if (!moduleToDeployHelper.isApplication(module)) {
continue;
}
ParametersChainBuilder parametersChainBuilder = new ParametersChainBuilder(context.getVariable(Variables.COMPLETE_DEPLOYMENT_DESCRIPTOR));
ParametersChainBuilder parametersChainBuilder = new ParametersChainBuilder(
context.getVariable(Variables.COMPLETE_DEPLOYMENT_DESCRIPTOR));
List<Map<String, Object>> parametersList = parametersChainBuilder.buildModuleChain(module.getName());

boolean noRoute = (Boolean) PropertiesUtil.getPropertyValue(parametersList, SupportedParameters.NO_ROUTE, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.cloudfoundry.multiapps.controller.process.util;

import java.util.List;
import java.util.Map;

import jakarta.inject.Named;
import org.cloudfoundry.multiapps.controller.core.helpers.ModuleToDeployHelper;
import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters;
import org.cloudfoundry.multiapps.mta.builders.v2.ParametersChainBuilder;
import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor;
import org.cloudfoundry.multiapps.mta.model.Module;
import org.cloudfoundry.multiapps.mta.util.PropertiesUtil;

@Named
public class DeprecatedBuildpackChecker {

private static final String DEPRECATION_MESSAGE = "SAP Java Buildpack 1 has been deprecated and is going to be removed from SAP BTP, Cloud Foundry environment after June, 2025!";
private static final String DEFAULT_BUILDPACK_MESSAGE_1 = "If no buildpack is specified, sap_java_buildpack is currently applied by default for certain module types (java.tomee, java.tomcat, java).";
private static final String DEFAULT_BUILDPACK_MESSAGE_2 = "This default will change after June - we strongly recommend that you manually migrate to the supported buildpack in advance to avoid deployment issues.";
private static final String DEPRECATION_LINK = "https://help.sap.com/whats-new/cf0cb2cb149647329b5d02aa96303f56?Component=SAP+Java+Buildpack&Valid_as_Of=2025-04-01:2025-04-10&locale=en-US";

private static final String DEPRECATED_BUILDPACK = "sap_java_buildpack";

public void warnForDeprecatedBuildpacks(List<Module> modulesCalculatedForDeployment,
DeploymentDescriptor deploymentDescriptor, StepLogger stepLogger,
ModuleToDeployHelper moduleToDeployHelper) {
List<String> appsWithDeprecatedBuildpacks = modulesCalculatedForDeployment.stream()
.filter(moduleToDeployHelper::isApplication)
.filter(module -> hasDeprecatedBuildpack(module,
deploymentDescriptor
))
.map(Module::getName)
.toList();

if (!appsWithDeprecatedBuildpacks.isEmpty()) {
logDeprecationNotice(stepLogger, appsWithDeprecatedBuildpacks);
}
}

private boolean hasDeprecatedBuildpack(Module module, DeploymentDescriptor deploymentDescriptor) {
List<Map<String, Object>> parametersList = new ParametersChainBuilder(deploymentDescriptor)
.buildModuleChain(module.getName());

List<String> buildpacks = PropertiesUtil.getPluralOrSingular(
parametersList, SupportedParameters.BUILDPACKS, SupportedParameters.BUILDPACK);

return buildpacks.contains(DEPRECATED_BUILDPACK);
}

private void logDeprecationNotice(StepLogger stepLogger, List<String> appsWithDeprecatedBuildpacks) {
String separator = "=".repeat(80);

stepLogger.warn("== ATTENTION: ==");
stepLogger.warn(separator);
stepLogger.warn(DEPRECATION_MESSAGE);
stepLogger.warn(DEFAULT_BUILDPACK_MESSAGE_1);
stepLogger.warn(DEFAULT_BUILDPACK_MESSAGE_2);
stepLogger.warn("Affected modules: " + appsWithDeprecatedBuildpacks);
stepLogger.warn("For more information, see: " + DEPRECATION_LINK);
stepLogger.warn(separator);
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package org.cloudfoundry.multiapps.controller.process.steps;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.type.TypeReference;
import com.sap.cloudfoundry.client.facade.domain.CloudServiceKey;
import org.cloudfoundry.multiapps.common.test.TestUtil;
import org.cloudfoundry.multiapps.common.test.Tester.Expectation;
import org.cloudfoundry.multiapps.common.util.JsonUtil;
Expand All @@ -20,6 +17,7 @@
import org.cloudfoundry.multiapps.controller.core.helpers.ModuleToDeployHelper;
import org.cloudfoundry.multiapps.controller.core.model.DeployedMta;
import org.cloudfoundry.multiapps.controller.core.test.DescriptorTestUtil;
import org.cloudfoundry.multiapps.controller.process.util.DeprecatedBuildpackChecker;
import org.cloudfoundry.multiapps.controller.process.util.ProcessTypeParser;
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor;
Expand All @@ -29,8 +27,10 @@
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;

import com.fasterxml.jackson.core.type.TypeReference;
import com.sap.cloudfoundry.client.facade.domain.CloudServiceKey;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

class BuildCloudDeployModelStepTest extends SyncFlowableStepTest<BuildCloudDeployModelStep> {

Expand All @@ -54,9 +54,12 @@ class BuildCloudDeployModelStepTest extends SyncFlowableStepTest<BuildCloudDeplo
@Mock
private ProcessTypeParser processTypeParser;

@Mock
private DeprecatedBuildpackChecker deprecatedBuildpackChecker;

public static Stream<Arguments> testExecute() {
return Stream.of(
// @formatter:off
// @formatter:off
Arguments.of(new StepInput("modules-to-deploy-01.json", "services-to-create-01.json", "service-keys-01.json", List.of("api.cf.neo.ondemand.com"), "deployed-mta-12.json")),
Arguments.of(new StepInput("modules-to-deploy-01.json", "services-to-create-01.json", "service-keys-01.json", List.of("api.cf.neo.ondemand.com"), null))
// @formatter:on
Expand Down Expand Up @@ -141,8 +144,8 @@ protected ApplicationCloudModelBuilder getApplicationCloudModelBuilder(ProcessCo

@Override
protected ModulesCloudModelBuilderContentCalculator
getModulesContentCalculator(ProcessContext context, List<Module> mtaDescriptorModules, Set<String> mtaManifestModuleNames,
Set<String> deployedModuleNames, Set<String> allMtaModuleNames) {
getModulesContentCalculator(ProcessContext context, List<Module> mtaDescriptorModules, Set<String> mtaManifestModuleNames,
Set<String> deployedModuleNames, Set<String> allMtaModuleNames) {
return modulesCloudModelBuilderContentCalculator;
}

Expand Down