diff --git a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/cf/clients/CustomServiceKeysClient.java b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/cf/clients/CustomServiceKeysClient.java index 733843fd25..0b9915b93f 100644 --- a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/cf/clients/CustomServiceKeysClient.java +++ b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/cf/clients/CustomServiceKeysClient.java @@ -3,7 +3,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.function.Function; +import java.util.Objects; +import java.util.UUID; import java.util.stream.Collectors; import org.cloudfoundry.client.v3.serviceinstances.ServiceInstanceType; @@ -29,8 +30,12 @@ public CustomServiceKeysClient(ApplicationConfiguration configuration, WebClient super(configuration, webClientFactory, credentials, correlationId); } - public List getServiceKeysByMetadataAndGuids(String spaceGuid, String mtaId, String mtaNamespace, - List services) { + public List getServiceKeysByMetadataAndExistingGuids( + String spaceGuid, + String mtaId, + String mtaNamespace, + List existingServiceGuids) { + String labelSelector = MtaMetadataCriteriaBuilder.builder() .label(MtaMetadataLabels.SPACE_GUID) .hasValue(spaceGuid) @@ -43,31 +48,73 @@ public List getServiceKeysByMetadataAndGuids(String space .build() .get(); - return new CustomControllerClientErrorHandler().handleErrorsOrReturnResult( - () -> getServiceKeysByMetadataInternal(labelSelector, services)); + List allServiceGuids = existingServiceGuids.stream() + .filter(Objects::nonNull) + .toList(); + + if (allServiceGuids.isEmpty()) { + return List.of(); + } + + return new CustomControllerClientErrorHandler() + .handleErrorsOrReturnResult( + () -> getServiceKeysByMetadataInternal(labelSelector, allServiceGuids) + ); } - private List getServiceKeysByMetadataInternal(String labelSelector, List services) { - String uriSuffix = INCLUDE_SERVICE_INSTANCE_RESOURCES_PARAM; - List managedServices = getManagedServices(services); - if (managedServices != null) { - uriSuffix += "&service_instance_guids=" + managedServices.stream() - .map(service -> service.getGuid() - .toString()) - .collect(Collectors.joining(",")); + public List getServiceKeysByMetadataAndManagedServices( + String spaceGuid, + String mtaId, + String mtaNamespace, + List services) { + + String labelSelector = MtaMetadataCriteriaBuilder.builder() + .label(MtaMetadataLabels.SPACE_GUID) + .hasValue(spaceGuid) + .and() + .label(MtaMetadataLabels.MTA_NAMESPACE) + .hasValueOrIsntPresent(MtaMetadataUtil.getHashedLabel(mtaNamespace)) + .and() + .label(MtaMetadataLabels.MTA_ID) + .hasValue(MtaMetadataUtil.getHashedLabel(mtaId)) + .build() + .get(); + + List managedGuids = extractManagedServiceGuids(services).stream() + .filter(Objects::nonNull) + .toList(); + + if (managedGuids.isEmpty()) { + return List.of(); } - return getListOfResources(new ServiceKeysResponseMapper(managedServices), SERVICE_KEYS_BY_METADATA_SELECTOR_URI + uriSuffix, + + return new CustomControllerClientErrorHandler() + .handleErrorsOrReturnResult( + () -> getServiceKeysByMetadataInternal(labelSelector, managedGuids) + ); + } + + private List extractManagedServiceGuids(List services) { + return getManagedServices(services).stream() + .map(DeployedMtaService::getGuid) + .map(UUID::toString) + .toList(); + } + + private List getServiceKeysByMetadataInternal(String labelSelector, List guids) { + + String uriSuffix = INCLUDE_SERVICE_INSTANCE_RESOURCES_PARAM + + "&service_instance_guids=" + String.join(",", guids); + + return getListOfResources(new ServiceKeysResponseMapper(), + SERVICE_KEYS_BY_METADATA_SELECTOR_URI + uriSuffix, labelSelector); } private List getManagedServices(List services) { - if (services == null) { - return null; - } - List managedServices = services.stream() - .filter(this::serviceIsNotUserProvided) - .collect(Collectors.toList()); - return managedServices.isEmpty() ? null : managedServices; + return services.stream() + .filter(this::serviceIsNotUserProvided) + .toList(); } private boolean serviceIsNotUserProvided(DeployedMtaService service) { @@ -76,23 +123,12 @@ private boolean serviceIsNotUserProvided(DeployedMtaService service) { } protected class ServiceKeysResponseMapper extends ResourcesResponseMapper { - - List mtaServices; - - public ServiceKeysResponseMapper(List mtaServices) { - this.mtaServices = mtaServices; + public ServiceKeysResponseMapper() { } @Override public List getMappedResources() { - Map serviceMapping; - if (mtaServices != null) { - serviceMapping = mtaServices.stream() - .collect(Collectors.toMap(service -> service.getGuid() - .toString(), Function.identity())); - } else { - serviceMapping = getIncludedServiceInstancesMapping(); - } + Map serviceMapping = getIncludedServiceInstancesMapping(); return getQueriedResources().stream() .map(resource -> resourceMapper.mapServiceKeyResource(resource, serviceMapping)) .collect(Collectors.toList()); @@ -108,4 +144,4 @@ public Map getIncludedServiceInstancesMapping() { } } -} +} \ No newline at end of file diff --git a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/NameUtil.java b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/NameUtil.java index 675f4603e9..2441ef044d 100644 --- a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/NameUtil.java +++ b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/NameUtil.java @@ -73,7 +73,8 @@ public static String computeNamespacedNameWithLength(String name, String namespa private static String getNameWithNamespaceSuffix(String name, String namespace, int maxLength) { String namespaceSuffix = getNamespaceSuffix(namespace); - String shortenedName = getNameWithProperLength(name, calculateNameLengthWithoutNamespaceAndBlueGreenSuffix(namespaceSuffix, maxLength)); + String shortenedName = getNameWithProperLength(name, + calculateNameLengthWithoutNamespaceAndBlueGreenSuffix(namespaceSuffix, maxLength)); return correctNameSuffix(shortenedName, name, namespaceSuffix); } @@ -120,6 +121,7 @@ public static String computeUserNamespaceWithSystemNamespace(String systemNamesp } return systemNamespace; } + private static String getShortenedName(String name, int maxLength) { String nameHashCode = getHashCodeAsHexString(name); if (maxLength < nameHashCode.length()) { @@ -157,6 +159,14 @@ public static String getServiceName(Resource resource) { .get(SupportedParameters.SERVICE_NAME); } + public static String getServiceInstanceNameOrDefault(Resource resource) { + String serviceInstanceName = getServiceName(resource); + if (serviceInstanceName == null || serviceInstanceName.isBlank()) { + return resource.getName(); + } + return serviceInstanceName; + } + public static class NameRequirements { public static final String XS_APP_NAME_PATTERN = "(?!sap_system)[a-zA-Z0-9\\._\\-\\\\/]{1,240}"; diff --git a/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/util/NameUtilTest.java b/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/util/NameUtilTest.java index db4c1f3731..264f2c56a8 100644 --- a/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/util/NameUtilTest.java +++ b/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/util/NameUtilTest.java @@ -1,16 +1,20 @@ package org.cloudfoundry.multiapps.controller.core.util; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - +import java.util.HashMap; +import java.util.Map; import java.util.stream.Stream; +import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters; import org.cloudfoundry.multiapps.controller.core.util.NameUtil.NameRequirements; +import org.cloudfoundry.multiapps.mta.model.Resource; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + class NameUtilTest { static Stream testGetNameWithProperLength() { @@ -94,4 +98,43 @@ void testComputeNamespacedNameWithLength(String name, String namespace, boolean NameUtil.computeNamespacedNameWithLength(name, namespace, applyNamespace, applyNamespaceAsSuffix, maxLength)); } + @Test + void testGetServiceInstanceNameOrDefault_UsesServiceNameParameter() { + Resource resource = createResource("resource-name", "service-name-from-param"); + + String serviceInstanceName = NameUtil.getServiceInstanceNameOrDefault(resource); + + assertEquals("service-name-from-param", serviceInstanceName); + } + + @Test + void testGetServiceInstanceNameOrDefault_FallsBackToResourceNameWhenServiceNameMissing() { + Resource resource = createResource("resource-name-1", null); + + String serviceInstanceName = NameUtil.getServiceInstanceNameOrDefault(resource); + + assertEquals("resource-name-1", serviceInstanceName); + } + + @Test + void testGetServiceInstanceNameOrDefault_FallsBackToResourceNameWhenServiceNameBlank() { + Resource resource = createResource("resource-name-2", " "); + + String serviceInstanceName = NameUtil.getServiceInstanceNameOrDefault(resource); + + assertEquals("resource-name-2", serviceInstanceName); + } + + private Resource createResource(String resourceName, String serviceInstanceName) { + Resource resource = Resource.createV3(); + resource.setName(resourceName); + + Map params = new HashMap<>(); + if (serviceInstanceName != null) { + params.put(SupportedParameters.SERVICE_NAME, serviceInstanceName); + } + resource.setParameters(params); + + return resource; + } } diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/Messages.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/Messages.java index a345de783c..ac66ccaa68 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/Messages.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/Messages.java @@ -790,6 +790,9 @@ public class Messages { public static final String TOTAL_SIZE_OF_ALL_RESOLVED_CONTENT_0 = "Total size for all resolved content {0}"; + public static final String IGNORING_NOT_FOUND_OPTIONAL_SERVICE = "Service {0} not found but is optional"; + public static final String IGNORING_NOT_FOUND_INACTIVE_SERVICE = "Service {0} not found but is inactive"; + // Not log messages public static final String SERVICE_TYPE = "{0}/{1}"; public static final String PARSE_NULL_STRING_ERROR = "Cannot parse null string"; diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStep.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStep.java index 8057ba4423..6ac553db39 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStep.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStep.java @@ -1,9 +1,11 @@ package org.cloudfoundry.multiapps.controller.process.steps; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; @@ -13,9 +15,14 @@ import org.cloudfoundry.multiapps.common.SLException; import org.cloudfoundry.multiapps.controller.api.model.ProcessType; import org.cloudfoundry.multiapps.controller.client.facade.CloudControllerClient; +import org.cloudfoundry.multiapps.controller.client.facade.CloudCredentials; +import org.cloudfoundry.multiapps.controller.client.facade.CloudOperationException; +import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudServiceInstance; import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudServiceKey; import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudServiceInstanceExtended; import org.cloudfoundry.multiapps.controller.core.cf.CloudHandlerFactory; +import org.cloudfoundry.multiapps.controller.core.cf.clients.CustomServiceKeysClient; +import org.cloudfoundry.multiapps.controller.core.cf.clients.WebClientFactory; import org.cloudfoundry.multiapps.controller.core.cf.util.CloudModelBuilderContentCalculator; import org.cloudfoundry.multiapps.controller.core.cf.util.DeployedAfterModulesContentValidator; import org.cloudfoundry.multiapps.controller.core.cf.util.ModulesCloudModelBuilderContentCalculator; @@ -23,13 +30,16 @@ import org.cloudfoundry.multiapps.controller.core.cf.util.ResourcesCloudModelBuilderContentCalculator; import org.cloudfoundry.multiapps.controller.core.cf.util.UnresolvedModulesContentValidator; import org.cloudfoundry.multiapps.controller.core.cf.v2.ApplicationCloudModelBuilder; +import org.cloudfoundry.multiapps.controller.core.cf.v2.ResourceType; import org.cloudfoundry.multiapps.controller.core.cf.v2.ServiceKeysCloudModelBuilder; import org.cloudfoundry.multiapps.controller.core.cf.v2.ServicesCloudModelBuilder; import org.cloudfoundry.multiapps.controller.core.helpers.ModuleToDeployHelper; import org.cloudfoundry.multiapps.controller.core.model.DeployedMta; import org.cloudfoundry.multiapps.controller.core.model.DeployedMtaApplication; +import org.cloudfoundry.multiapps.controller.core.model.DeployedMtaServiceKey; import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters; import org.cloudfoundry.multiapps.controller.core.security.serialization.SecureSerialization; +import org.cloudfoundry.multiapps.controller.core.security.token.TokenService; import org.cloudfoundry.multiapps.controller.core.util.CloudModelBuilderUtil; import org.cloudfoundry.multiapps.controller.core.util.NameUtil; import org.cloudfoundry.multiapps.controller.process.Messages; @@ -47,6 +57,8 @@ import org.cloudfoundry.multiapps.mta.model.Resource; import org.cloudfoundry.multiapps.mta.util.PropertiesUtil; import org.flowable.engine.delegate.DelegateExecution; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; @@ -64,11 +76,25 @@ public class BuildCloudDeployModelStep extends SyncFlowableStep { @Inject private DeprecatedBuildpackChecker buildpackChecker; + @Inject + private TokenService tokenService; + @Inject + private WebClientFactory webClientFactory; + + private static final Logger LOGGER = LoggerFactory.getLogger(BuildCloudDeployModelStep.class); + @Override protected StepPhase executeStep(ProcessContext context) { getStepLogger().debug(Messages.BUILDING_CLOUD_MODEL); DeploymentDescriptor deploymentDescriptor = context.getVariable(Variables.COMPLETE_DEPLOYMENT_DESCRIPTOR); + String mtaId = context.getVariable(Variables.MTA_ID); + String mtaNamespace = context.getVariable(Variables.MTA_NAMESPACE); + + var deployedServiceKeys = detectDeployedServiceKeys(mtaId, mtaNamespace, context); + context.setVariable(Variables.DEPLOYED_MTA_SERVICE_KEYS, deployedServiceKeys); + getStepLogger().debug(Messages.DEPLOYED_MTA_SERVICE_KEYS, SecureSerialization.toJson(deployedServiceKeys)); + // Get module sets: DeployedMta deployedMta = context.getVariable(Variables.DEPLOYED_MTA); List deployedApplications = (deployedMta != null) ? deployedMta.getApplications() : Collections.emptyList(); @@ -331,4 +357,72 @@ private List getDomainsFromApps(ProcessContext context, DeploymentDescri return new ArrayList<>(domains); } + private List detectDeployedServiceKeys(String mtaId, String mtaNamespace, + ProcessContext context) { + String spaceGuid = context.getVariable(Variables.SPACE_GUID); + String userGuid = context.getVariable(Variables.USER_GUID); + var token = tokenService.getToken(userGuid); + var creds = new CloudCredentials(token, true); + + CustomServiceKeysClient serviceKeysClient = getCustomServiceKeysClient(creds, context.getVariable(Variables.CORRELATION_ID)); + + List existingInstanceGuids = getExistingServiceGuids(context); + + return serviceKeysClient.getServiceKeysByMetadataAndExistingGuids( + spaceGuid, mtaId, mtaNamespace, existingInstanceGuids + ); + } + + private List getExistingServiceGuids(ProcessContext context) { + CloudControllerClient client = context.getControllerClient(); + List resources = getExistingServiceResourcesFromDescriptor(context); + + return resources.stream() + .map(resource -> resolveServiceGuid(client, resource)) + .flatMap(Optional::stream) + .toList(); + } + + private Optional resolveServiceGuid(CloudControllerClient client, Resource resource) { + String serviceInstanceName = NameUtil.getServiceInstanceNameOrDefault(resource); + + try { + CloudServiceInstance instance = client.getServiceInstance(serviceInstanceName); + return Optional.of(instance.getGuid() + .toString()); + } catch (CloudOperationException e) { + if (resource.isOptional()) { + logIgnoredService(Messages.IGNORING_NOT_FOUND_OPTIONAL_SERVICE, resource.getName(), e); + return Optional.empty(); + } + if (!resource.isActive()) { + logIgnoredService(Messages.IGNORING_NOT_FOUND_INACTIVE_SERVICE, resource.getName(), e); + return Optional.empty(); + } + throw e; + } + } + + private void logIgnoredService(String message, String serviceName, Exception e) { + String formattedMessage = MessageFormat.format(message, serviceName); + getStepLogger().debug(formattedMessage); + LOGGER.error(formattedMessage, e); + } + + private List getExistingServiceResourcesFromDescriptor(ProcessContext context) { + DeploymentDescriptor descriptor = context.getVariable(Variables.COMPLETE_DEPLOYMENT_DESCRIPTOR); + + if (descriptor == null) { + return List.of(); + } + return descriptor.getResources() + .stream() + .filter(resource -> CloudModelBuilderUtil.getResourceType(resource) == ResourceType.EXISTING_SERVICE) + .toList(); + } + + protected CustomServiceKeysClient getCustomServiceKeysClient(CloudCredentials credentials, String correlationId) { + return new CustomServiceKeysClient(configuration, webClientFactory, credentials, correlationId); + } + } diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudUndeployModelStep.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudUndeployModelStep.java index 75c29b4619..56256bfcd2 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudUndeployModelStep.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudUndeployModelStep.java @@ -65,9 +65,16 @@ protected StepPhase executeStep(ProcessContext context) { getStepLogger().debug(Messages.BUILDING_CLOUD_UNDEPLOY_MODEL); DeployedMta deployedMta = context.getVariable(Variables.DEPLOYED_MTA); + List serviceKeysToDelete = computeServiceKeysToDelete(context); + getStepLogger().debug(Messages.SERVICE_KEYS_FOR_DELETION, serviceKeysToDelete); + if (deployedMta == null) { setComponentsToUndeploy(context, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + if (!serviceKeysToDelete.isEmpty()) { + context.setVariable(Variables.SERVICE_KEYS_TO_DELETE, + getServiceKeysToDelete(context, serviceKeysToDelete)); + } return StepPhase.DONE; } @@ -98,9 +105,6 @@ protected StepPhase executeStep(ProcessContext context) { servicesForApplications, serviceNames); getStepLogger().debug(Messages.SERVICES_TO_DELETE, servicesToDelete); - List serviceKeysToDelete = computeServiceKeysToDelete(context); - getStepLogger().debug(Messages.SERVICE_KEYS_FOR_DELETION, serviceKeysToDelete); - List appsToUndeploy = computeAppsToUndeploy(deployedAppsToUndeploy, context.getControllerClient()); DeployedMta backupMta = context.getVariable(Variables.BACKUP_MTA); diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/DetectDeployedMtaStep.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/DetectDeployedMtaStep.java index eb25617a37..dc39aba61f 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/DetectDeployedMtaStep.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/DetectDeployedMtaStep.java @@ -94,14 +94,19 @@ private void detectBackupMta(String mtaId, String mtaNamespace, CloudControllerC private List detectDeployedServiceKeys(String mtaId, String mtaNamespace, DeployedMta deployedMta, ProcessContext context) { - List deployedMtaServices = deployedMta == null ? null : deployedMta.getServices(); + List deployedManagedMtaServices = Optional.ofNullable(deployedMta) + .map(DeployedMta::getServices) + .orElse(List.of()); String spaceGuid = context.getVariable(Variables.SPACE_GUID); String userGuid = context.getVariable(Variables.USER_GUID); var token = tokenService.getToken(userGuid); var creds = new CloudCredentials(token, true); CustomServiceKeysClient serviceKeysClient = getCustomServiceKeysClient(creds, context.getVariable(Variables.CORRELATION_ID)); - return serviceKeysClient.getServiceKeysByMetadataAndGuids(spaceGuid, mtaId, mtaNamespace, deployedMtaServices); + + return serviceKeysClient.getServiceKeysByMetadataAndManagedServices( + spaceGuid, mtaId, mtaNamespace, deployedManagedMtaServices + ); } private void logNoMtaDeployedDetected(String mtaId, String mtaNamespace) { diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStepTest.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStepTest.java index ddf288592c..331a51601f 100644 --- a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStepTest.java +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/BuildCloudDeployModelStepTest.java @@ -11,11 +11,13 @@ import org.cloudfoundry.multiapps.common.test.Tester.Expectation; import org.cloudfoundry.multiapps.common.util.JsonUtil; import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudServiceKey; +import org.cloudfoundry.multiapps.controller.core.cf.clients.WebClientFactory; import org.cloudfoundry.multiapps.controller.core.cf.util.ModulesCloudModelBuilderContentCalculator; import org.cloudfoundry.multiapps.controller.core.cf.v2.ApplicationCloudModelBuilder; import org.cloudfoundry.multiapps.controller.core.cf.v2.ServiceKeysCloudModelBuilder; import org.cloudfoundry.multiapps.controller.core.helpers.ModuleToDeployHelper; import org.cloudfoundry.multiapps.controller.core.model.DeployedMta; +import org.cloudfoundry.multiapps.controller.core.security.token.TokenService; import org.cloudfoundry.multiapps.controller.core.test.DescriptorTestUtil; import org.cloudfoundry.multiapps.controller.process.util.DeprecatedBuildpackChecker; import org.cloudfoundry.multiapps.controller.process.util.ProcessTypeParser; @@ -53,6 +55,10 @@ class BuildCloudDeployModelStepTest extends SyncFlowableStepTest