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
Expand Up @@ -38,6 +38,10 @@ public class SupportedParameters {
public static final String APPLY_NAMESPACE_SERVICES = "service-names";
public static final String APPLY_NAMESPACE_ROUTES = "app-routes";

public static final String DEPLOY_MODE = "deploy_mode";

public static final String PATH = "path";

// Module / module type parameters:
public static final String APP_NAME = "app-name";
public static final String DEFAULT_APP_NAME = "default-app-name";
Expand Down Expand Up @@ -99,7 +103,8 @@ public class SupportedParameters {
public static final String DOCKER = "docker";
public static final String TIMESTAMP = "timestamp";
public static final String ENABLE_PARALLEL_SERVICE_BINDINGS = "enable-parallel-service-bindings";

public static final String TCP_ROUTES = "tcp";
public static final String TCPS_ROUTES = "tcps";
public static final String EXECUTE_APP = "execute-app";
public static final String SUCCESS_MARKER = "success-marker";
public static final String FAILURE_MARKER = "failure-marker";
Expand All @@ -117,6 +122,8 @@ public class SupportedParameters {
public static final String SERVICE_BROKER_PASSWORD = "service-broker-password";
public static final String SERVICE_BROKER_URL = "service-broker-url";
public static final String SERVICE_BROKER_SPACE_SCOPED = "service-broker-space-scoped";
public static final String MODULE_CONFIG = "config";
public static final String HOOK_REQUIRES = "requires";

// Required dependency parameters:
public static final String SERVICE_BINDING_CONFIG = "config";
Expand Down Expand Up @@ -172,6 +179,40 @@ public class SupportedParameters {
@Deprecated
public static final String DEPRECATED_CONFIG_MTA_PROVIDES_DEPENDENCY = "mta-provides-dependency";

public static final Set<String> MODULE_PARAMETERS = Set.of(APP_NAME, APPLY_NAMESPACE, BUILDPACK, BUILDPACKS, COMMAND,
CREATE_SERVICE_BROKER, DEFAULT_APP_NAME, DEFAULT_HOST, DEFAULT_INSTANCES,
DEFAULT_LIVE_APP_NAME, DEFAULT_LIVE_DOMAIN, DEFAULT_LIVE_HOST,
DEFAULT_LIVE_URI, DEFAULT_LIVE_URL, DEFAULT_URI, DEFAULT_URL,
DEPENDENCY_TYPE, DISK_QUOTA, DOCKER, DOMAIN, DOMAINS, DEFAULT_DOMAIN,
ENABLE_SSH, ENABLE_PARALLEL_SERVICE_BINDINGS, HEALTH_CHECK_HTTP_ENDPOINT,
HEALTH_CHECK_TIMEOUT, HEALTH_CHECK_INVOCATION_TIMEOUT, HEALTH_CHECK_TYPE,
HOST, HOSTS, IDLE_DOMAIN, IDLE_DOMAINS, IDLE_HOST, IDLE_HOSTS, IDLE_ROUTES,
INSTANCES, KEEP_EXISTING_APPLICATION_ATTRIBUTES_UPDATE_STRATEGY,
KEEP_EXISTING_ROUTES, MEMORY, NO_ROUTE, NO_START, RESTART_ON_ENV_CHANGE,
ROUTES, ROUTE_PATH, SERVICE_BROKER_NAME, SERVICE_BROKER_PASSWORD,
SERVICE_BROKER_SPACE_SCOPED, SERVICE_BROKER_URL, SERVICE_BROKER_USERNAME,
STACK, STAGE_TIMEOUT, START_TIMEOUT, TASK_EXECUTION_TIMEOUT, TASKS,
TCP_ROUTES, TCPS_ROUTES, TIMESTAMP, UPLOAD_TIMEOUT, ROUTE, EXECUTE_APP,
SUCCESS_MARKER, FAILURE_MARKER, STOP_APP, CHECK_DEPLOY_ID,
REGISTER_SERVICE_URL, REGISTER_SERVICE_URL_SERVICE_NAME,
REGISTER_SERVICE_URL_SERVICE_URL, MODULE_CONFIG, MANAGED, PATH,
APPS_UPLOAD_TIMEOUT, APPS_TASK_EXECUTION_TIMEOUT,
APPS_START_TIMEOUT, APPS_STAGE_TIMEOUT);

public static final Set<String> RESOURCE_PARAMETERS = Set.of(APPLY_NAMESPACE, SERVICE_CONFIG, SYSLOG_DRAIN_URL, DEFAULT_CONTAINER_NAME,
DEFAULT_SERVICE_NAME, DEFAULT_XS_APP_NAME, SERVICE, SERVICE_KEYS,
SERVICE_KEY_NAME, SERVICE_NAME, SERVICE_PLAN, SERVICE_TAGS, SERVICE_BROKER,
SKIP_SERVICE_UPDATES, TYPE, PROVIDER_ID, PROVIDER_NID, TARGET,
SERVICE_CONFIG_PATH, FILTER, MANAGED, VERSION, PATH, MEMORY);
public static final Set<String> GLOBAL_PARAMETERS = Set.of(KEEP_EXISTING_ROUTES, APPS_UPLOAD_TIMEOUT, APPS_TASK_EXECUTION_TIMEOUT,
APPS_START_TIMEOUT, APPS_STAGE_TIMEOUT, APPLY_NAMESPACE,
ENABLE_PARALLEL_DEPLOYMENTS, DEPLOY_MODE);

public static final Set<String> DEPENDENCY_PARAMETERS = Set.of(BINDING_NAME, ENV_VAR_NAME, VISIBILITY, USE_LIVE_ROUTES,
SERVICE_BINDING_CONFIG);

public static final Set<String> MODULE_HOOK_PARAMETERS = Set.of(NAME, COMMAND, MEMORY, DISK_QUOTA, HOOK_REQUIRES);

public static final Set<String> CONFIGURATION_REFERENCE_PARAMETERS = Set.of(PROVIDER_NID, PROVIDER_ID, TARGET, VERSION,
DEPRECATED_CONFIG_MTA_ID, DEPRECATED_CONFIG_MTA_VERSION,
DEPRECATED_CONFIG_MTA_PROVIDES_DEPENDENCY, NAMESPACE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ public class Messages {
public static final String SERVICE_KEY_0_IS_ALREADY_DELETED = "Service key \"{0}\" is already deleted";
public static final String FILE_WITH_ID_0_OPERATION_OWNERSHIP_CHANGED_FROM_0_TO_1 = "File with id \"{0}\" operation ownership was changed from \"{1}\" to \"{2}\" and won't be deleted";

public static final String PARAMETERS_0_ARE_NOT_SUPPORTED_OR_REFERENCED_BY_ANY_OTHER_ENTITIES = "Parameter(s) \"{0}\" are not supported in the specified scope, or referenced by any other entities. These parameters will not be processed and can be lost after the operation completes.";

// INFO log messages
public static final String ACQUIRING_LOCK = "Process \"{0}\" attempting to acquire lock for operation on MTA \"{1}\"";
public static final String ACQUIRED_LOCK = "Process \"{0}\" acquired lock for operation on MTA \"{1}\"";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
package org.cloudfoundry.multiapps.controller.process.steps;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.cloudfoundry.multiapps.controller.core.cf.CloudHandlerFactory;
import org.cloudfoundry.multiapps.controller.core.helpers.MtaDescriptorMerger;
import org.cloudfoundry.multiapps.controller.persistence.dto.BackupDescriptor;
import org.cloudfoundry.multiapps.controller.persistence.dto.ImmutableBackupDescriptor;
import org.cloudfoundry.multiapps.controller.persistence.services.DescriptorBackupService;
import org.cloudfoundry.multiapps.controller.process.Messages;
import org.cloudfoundry.multiapps.controller.process.util.NamespaceGlobalParameters;
import org.cloudfoundry.multiapps.controller.process.util.UnsupportedParameterFinder;
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor;
import org.cloudfoundry.multiapps.mta.model.ExtensionDescriptor;
import org.cloudfoundry.multiapps.mta.model.Platform;
import org.cloudfoundry.multiapps.mta.resolvers.ReferenceContainer;
import org.cloudfoundry.multiapps.mta.resolvers.ReferencesFinder;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;

import jakarta.inject.Inject;
import jakarta.inject.Named;

@Named("mergeDescriptorsStep")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class MergeDescriptorsStep extends SyncFlowableStep {

@Inject
private DescriptorBackupService descriptorBackupService;

@Inject
private UnsupportedParameterFinder unsupportedParameterFinder;

protected MtaDescriptorMerger getMtaDescriptorMerger(CloudHandlerFactory factory, Platform platform) {
return new MtaDescriptorMerger(factory, platform, getStepLogger());
}
Expand All @@ -42,11 +49,23 @@ protected StepPhase executeStep(ProcessContext context) {
extensionDescriptors);
context.setVariable(Variables.DEPLOYMENT_DESCRIPTOR, descriptor);

warnForUnsupportedParameters(descriptor);

backupDeploymentDescriptor(context, descriptor);
getStepLogger().debug(Messages.DESCRIPTORS_MERGED);
return StepPhase.DONE;
}

private void warnForUnsupportedParameters(DeploymentDescriptor descriptor) {
List<ReferenceContainer> references = new ReferencesFinder().getAllReferences(descriptor);
Map<String, List<String>> unsupportedParameters = unsupportedParameterFinder.findUnsupportedParameters(descriptor,
references);
if (!unsupportedParameters.isEmpty()) {
getStepLogger().warn(MessageFormat.format(Messages.PARAMETERS_0_ARE_NOT_SUPPORTED_OR_REFERENCED_BY_ANY_OTHER_ENTITIES,
unsupportedParameters));
}
}

private void backupDeploymentDescriptor(ProcessContext context, DeploymentDescriptor descriptor) {
boolean shouldBackupPreviousVersion = context.getVariable(Variables.SHOULD_BACKUP_PREVIOUS_VERSION);
if (!shouldBackupPreviousVersion) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.cloudfoundry.multiapps.controller.process.util;

import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.cloudfoundry.multiapps.mta.resolvers.CustomParameterContainer;
import org.cloudfoundry.multiapps.mta.resolvers.ReferenceContainer;
import org.springframework.stereotype.Component;

@Component
public class CustomParameterContainerProcessor {
private static final String GLOBAL_PARAMETER = "global-parameter";

public Map.Entry<String, List<String>> processCustomParameterContainer(CustomParameterContainer container,
List<ReferenceContainer> references,
ReferenceContainerMatcher referenceMatcher) {
List<String> unreferenced = filterUnreferencedParameters(container, references, referenceMatcher);
String prefixedName = getPrefixedName(container);
return new AbstractMap.SimpleEntry<>(prefixedName, unreferenced);
}

private List<String> filterUnreferencedParameters(CustomParameterContainer container, List<ReferenceContainer> references,
ReferenceContainerMatcher referenceMatcher) {
return container.getParameters()
.stream()
.filter(parameter -> !isParameterReferenced(references, container, parameter, referenceMatcher))
.collect(Collectors.toList());
}

private boolean isParameterReferenced(List<ReferenceContainer> references, CustomParameterContainer container, String customParameter,
ReferenceContainerMatcher referenceMatcher) {
return references.stream()
.anyMatch(referenceContainer -> referenceMatcher.isReferenceContainerMatching(referenceContainer, container,
customParameter));
}

private String getPrefixedName(CustomParameterContainer container) {
return container.getPrefixedName() != null ? container.getPrefixedName() : GLOBAL_PARAMETER;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

package org.cloudfoundry.multiapps.controller.process.util;

import java.util.Collections;
Expand All @@ -13,9 +12,7 @@
import org.flowable.engine.delegate.DelegateExecution;

public class ModuleHooksAggregator {

private static final int MAJOR_SCHEMA_VERSION_THREE = 3;

private final DelegateExecution execution;
private final Module moduleToDeploy;

Expand All @@ -31,17 +28,17 @@ public List<Hook> aggregateHooks(List<HookPhase> currentHookPhasesForExecution)

private List<Hook> determineHooksForExecution(Map<String, List<String>> alreadyExecutedHooks,
List<HookPhase> hookPhasesForCurrentStepPhase) {
List<Hook> moduleHooksToExecuteOnCurrentStepPhase = collectHooksWithPhase(moduleToDeploy, hookPhasesForCurrentStepPhase);
List<Hook> moduleHooksToExecuteOnCurrentStepPhase = collectHooksWithPhase(hookPhasesForCurrentStepPhase);
return getHooksForExecution(alreadyExecutedHooks, moduleHooksToExecuteOnCurrentStepPhase, hookPhasesForCurrentStepPhase);
}

private List<Hook> collectHooksWithPhase(Module moduleToDeploy, List<HookPhase> hookPhasesForCurrentStepPhase) {
return getModuleHooks(moduleToDeploy).stream()
.filter(hook -> shouldCollectHook(hook.getPhases(), hookPhasesForCurrentStepPhase))
.collect(Collectors.toList());
private List<Hook> collectHooksWithPhase(List<HookPhase> hookPhasesForCurrentStepPhase) {
return getModuleHooks().stream()
.filter(hook -> shouldCollectHook(hook.getPhases(), hookPhasesForCurrentStepPhase))
.collect(Collectors.toList());
}

private List<Hook> getModuleHooks(Module moduleToDeploy) {
private List<Hook> getModuleHooks() {
return moduleToDeploy.getMajorSchemaVersion() < MAJOR_SCHEMA_VERSION_THREE ? Collections.emptyList() : moduleToDeploy.getHooks();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.cloudfoundry.multiapps.controller.process.util;

import org.cloudfoundry.multiapps.mta.resolvers.CustomParameterContainer;
import org.cloudfoundry.multiapps.mta.resolvers.Reference;
import org.cloudfoundry.multiapps.mta.resolvers.ReferenceContainer;
import org.springframework.stereotype.Component;

@Component
public class ReferenceContainerMatcher {
public boolean isReferenceContainerMatching(ReferenceContainer referenceContainer,
CustomParameterContainer container,
String customParameter) {
return isReferenceMatchingParameter(referenceContainer, customParameter, container)
&& isReferenceOwnerMatched(referenceContainer.getReferenceOwner(), container.getParameterOwner());
}

private boolean isReferenceMatchingParameter(ReferenceContainer referenceContainer,
String customParameter, CustomParameterContainer container) {
return referenceContainer.getReferences()
.stream()
.anyMatch(reference -> isReferenceNameMatched(reference, customParameter)
&& isReferenceDependencyMatched(reference, container));
}

private boolean isReferenceNameMatched(Reference reference, String customParameter) {
return reference.getKey()
.equals(customParameter);
}

private boolean isReferenceDependencyMatched(Reference reference, CustomParameterContainer container) {
String dependencyName = reference.getDependencyName();
String parameterOwner = container.getParameterOwner();

return dependencyName == null || parameterOwner == null || dependencyName.equals(parameterOwner);
}

private boolean isReferenceOwnerMatched(String referenceOwner, String parameterOwner) {
return parameterOwner == null || parameterOwner.equals(referenceOwner);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.cloudfoundry.multiapps.controller.process.util;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;

public class SchemaVersionUtils {

private static final int MAJOR_SCHEMA_VERSION_THREE = 3;

public static <T, R> List<R> getEntityData(T entity, Function<T, Integer> versionGetter, Function<T, List<R>> dataGetter) {
return versionGetter.apply(entity) < MAJOR_SCHEMA_VERSION_THREE ? Collections.emptyList() : dataGetter.apply(entity);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.cloudfoundry.multiapps.controller.process.util;

import java.util.HashSet;
import java.util.Set;

import jakarta.inject.Named;
import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters;
import org.cloudfoundry.multiapps.mta.resolvers.ParameterChecker;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;

@Named("supportedParameterChecker")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SupportedParameterChecker extends ParameterChecker {

private static final Set<String> REQUIRED_AND_PROVIDED_DEPENDENCY_PARAMETERS = initializeDependencyParameters();

@Override
protected Set<String> getModuleParametersToMatch() {
return SupportedParameters.MODULE_PARAMETERS;
}

@Override
protected Set<String> getModuleHookParametersToMatch() {
return SupportedParameters.MODULE_HOOK_PARAMETERS;
}

@Override
protected Set<String> getResourceParametersToMatch() {
return SupportedParameters.RESOURCE_PARAMETERS;
}

@Override
protected Set<String> getGlobalParametersToMatch() {
return SupportedParameters.GLOBAL_PARAMETERS;
}

@Override
protected Set<String> getDependencyParametersToMatch() {
return REQUIRED_AND_PROVIDED_DEPENDENCY_PARAMETERS;
}

private static Set<String> initializeDependencyParameters() {
Set<String> dependencyParameters = new HashSet<>();
dependencyParameters.addAll(SupportedParameters.DEPENDENCY_PARAMETERS);
dependencyParameters.addAll(SupportedParameters.MODULE_PARAMETERS);
dependencyParameters.addAll(SupportedParameters.RESOURCE_PARAMETERS);
return dependencyParameters;
}

}
Loading