diff --git a/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/OperationsApiService.java b/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/OperationsApiService.java index 6c11ab0074..331b586940 100644 --- a/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/OperationsApiService.java +++ b/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/OperationsApiService.java @@ -2,6 +2,7 @@ import java.util.List; +import jakarta.servlet.http.HttpServletRequest; import org.cloudfoundry.multiapps.controller.api.model.Log; import org.cloudfoundry.multiapps.controller.api.model.Operation; import org.springframework.http.ResponseEntity; @@ -20,6 +21,6 @@ public interface OperationsApiService { ResponseEntity getOperationLogContent(String spaceGuid, String operationId, String logId); - ResponseEntity startOperation(String spaceGuid, Operation operation); + ResponseEntity startOperation(String spaceGuid, Operation operation, HttpServletRequest httpServletRequest); } diff --git a/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/v1/OperationsApi.java b/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/v1/OperationsApi.java index 5b807d3abd..f94e5e130f 100644 --- a/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/v1/OperationsApi.java +++ b/multiapps-controller-api/src/main/java/org/cloudfoundry/multiapps/controller/api/v1/OperationsApi.java @@ -9,6 +9,7 @@ import io.swagger.annotations.ApiResponses; import io.swagger.annotations.Authorization; import jakarta.inject.Inject; +import jakarta.servlet.http.HttpServletRequest; import org.cloudfoundry.multiapps.controller.api.Constants.Endpoints; import org.cloudfoundry.multiapps.controller.api.Constants.PathVariables; import org.cloudfoundry.multiapps.controller.api.Constants.QueryVariables; @@ -114,8 +115,8 @@ public ResponseEntity> getOperationActions(@PathVariable(PathVariab }) }, tags = {}) @ApiResponses(value = { @ApiResponse(code = 202, message = "Accepted") }) public ResponseEntity startOperation(@PathVariable(PathVariables.SPACE_GUID) String spaceGuid, - @RequestBody Operation operation) { - return delegate.startOperation(spaceGuid, operation); + @RequestBody Operation operation, HttpServletRequest httpServletRequest) { + return delegate.startOperation(spaceGuid, operation, httpServletRequest); } } diff --git a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/Messages.java b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/Messages.java index 0e7a987734..60617f9397 100644 --- a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/Messages.java +++ b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/Messages.java @@ -149,6 +149,7 @@ public final class Messages { public static final String GLOBAL_CONFIG_SPACE = "Global config space: {0}"; public static final String OBJECT_STORE_CLIENT_TYPE = "Object store client type: {0}"; public static final String APPLICATION_GUID = "Application GUID: {0}"; + public static final String USE_LEGACY_ROUTE_WARNING = "Legacy route warning enablement: {0}"; public static final String APPLICATION_INSTANCE_INDEX = "Application instance index: {0}"; public static final String AUDIT_LOG_CLIENT_CORE_THREADS = "Audit log client core threads: {0}"; public static final String AUDIT_LOG_CLIENT_MAX_THREADS = "Audit log client max threads: {0}"; diff --git a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/ApplicationConfiguration.java b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/ApplicationConfiguration.java index 4d856b479f..a11fba78b5 100644 --- a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/ApplicationConfiguration.java +++ b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/util/ApplicationConfiguration.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; + import jakarta.inject.Inject; import jakarta.inject.Named; import org.apache.commons.collections4.CollectionUtils; @@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.support.CronExpression; + import static java.text.MessageFormat.format; @Named @@ -99,6 +101,7 @@ public class ApplicationConfiguration { static final String CFG_THREADS_FOR_FILE_UPLOAD_TO_CONTROLLER = "THREADS_FOR_FILE_UPLOAD_TO_CONTROLLER"; static final String CFG_THREADS_FOR_FILE_STORAGE_UPLOAD = "THREADS_FOR_FILE_STORAGE_UPLOAD"; static final String CFG_IS_HEALTH_CHECK_ENABLED = "IS_HEALTH_CHECK_ENABLED"; + static final String USE_LEGACY_ROUTE_WARNING = "USE_LEGACY_ROUTE_WARNING"; private static final List VCAP_APPLICATION_URIS_KEYS = List.of("full_application_uris", "application_uris", "uris"); @@ -158,6 +161,7 @@ public class ApplicationConfiguration { public static final int DEFAULT_THREADS_FOR_FILE_STORAGE_UPLOAD = 7; public static final boolean DEFAULT_IS_HEALTH_CHECK_ENABLED = false; public static final Boolean DEFAULT_IS_READINESS_HEALTH_CHECK_ENABLED = Boolean.FALSE; + public static final Boolean DEFAULT_USE_LEGACY_ROUTE_WARNING = false; protected final Environment environment; @@ -218,6 +222,7 @@ public class ApplicationConfiguration { private Boolean isHealthCheckEnabled; private Set objectStoreRegions; private Boolean isReadinessHealthCheckEnabled; + private Boolean useLegacyRouteWarning; public ApplicationConfiguration() { this(new Environment()); @@ -500,6 +505,13 @@ public String getObjectStoreClientType() { return objectStoreClientType; } + public Boolean getLegacyRouteWarningEnablement() { + if (useLegacyRouteWarning == null) { + useLegacyRouteWarning = getLegacyRouteWarningEnablementFromEnvironment(); + } + return useLegacyRouteWarning; + } + public HealthCheckConfiguration getHealthCheckConfiguration() { if (healthCheckConfiguration == null) { healthCheckConfiguration = getHealthCheckConfigurationFromEnvironment(); @@ -916,6 +928,12 @@ private String getObjectStoreClientTypeFromEnvironment() { return value; } + private Boolean getLegacyRouteWarningEnablementFromEnvironment() { + Boolean value = environment.getBoolean(USE_LEGACY_ROUTE_WARNING, DEFAULT_USE_LEGACY_ROUTE_WARNING); + logEnvironmentVariable(USE_LEGACY_ROUTE_WARNING, Messages.USE_LEGACY_ROUTE_WARNING, value); + return value; + } + private HealthCheckConfiguration getHealthCheckConfigurationFromEnvironment() { HealthCheckConfiguration healthCheckConfigurationFromEnvironment = ImmutableHealthCheckConfiguration.builder() .spaceId( diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadata.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadata.java index 2b6f3d7266..b996d7c06a 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadata.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadata.java @@ -144,6 +144,10 @@ public static OperationMetadata getMetadata() { .type(ParameterType.BOOLEAN) .defaultValue(false) .build()) + .addParameter(ImmutableParameterMetadata.builder() + .id(Variables.API_REQUEST_PATH.getName()) + .type(ParameterType.STRING) + .build()) // Special blue green deploy parameters: .addParameter(ImmutableParameterMetadata.builder() diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadata.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadata.java index f09fce1565..ff2131283c 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadata.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadata.java @@ -155,6 +155,10 @@ public static OperationMetadata getMetadata() { .type(ParameterType.BOOLEAN) .defaultValue(false) .build()) + .addParameter(ImmutableParameterMetadata.builder() + .id(Variables.API_REQUEST_PATH.getName()) + .type(ParameterType.STRING) + .build()) // Special CTS+ parameters: .addParameter(ImmutableParameterMetadata.builder() diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadata.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadata.java index cb14f45f11..9e51a153ec 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadata.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadata.java @@ -149,6 +149,10 @@ public static OperationMetadata getMetadata() { .type(ParameterType.BOOLEAN) .defaultValue(false) .build()) + .addParameter(ImmutableParameterMetadata.builder() + .id(Variables.API_REQUEST_PATH.getName()) + .type(ParameterType.STRING) + .build()) .build(); } diff --git a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/variables/Variables.java b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/variables/Variables.java index 666c776225..8c35932c48 100644 --- a/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/variables/Variables.java +++ b/multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/variables/Variables.java @@ -118,6 +118,9 @@ public interface Variables { Variable DEPLOY_URI = ImmutableSimpleVariable. builder() .name("deployUri") .build(); + Variable API_REQUEST_PATH = ImmutableSimpleVariable. builder() + .name("apiRequestPath") + .build(); Variable CTS_USERNAME = ImmutableSimpleVariable. builder() .name("userId") .build(); diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadataTest.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadataTest.java index 14fa9118ad..c2d88499d2 100644 --- a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadataTest.java +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/BlueGreenDeployMetadataTest.java @@ -57,7 +57,8 @@ protected String[] getParametersIds() { Variables.STOP_ORDER_IS_DEPENDENCY_AWARE.getName(), Variables.IS_SECURITY_ENABLED.getName(), Variables.DISPOSABLE_USER_PROVIDED_SERVICE_NAME.getName(), - Variables.IS_DISPOSABLE_USER_PROVIDED_SERVICE_ENABLED.getName() + Variables.IS_DISPOSABLE_USER_PROVIDED_SERVICE_ENABLED.getName(), + Variables.API_REQUEST_PATH.getName() // @formatter:on }; } diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadataTest.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadataTest.java index 001bddc927..7109b0b423 100644 --- a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadataTest.java +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/CtsDeployMetadataTest.java @@ -60,7 +60,8 @@ protected String[] getParametersIds() { Variables.SKIP_APP_DIGEST_CALCULATION.getName(), Variables.IS_SECURITY_ENABLED.getName(), Variables.DISPOSABLE_USER_PROVIDED_SERVICE_NAME.getName(), - Variables.IS_DISPOSABLE_USER_PROVIDED_SERVICE_ENABLED.getName() + Variables.IS_DISPOSABLE_USER_PROVIDED_SERVICE_ENABLED.getName(), + Variables.API_REQUEST_PATH.getName() // @formatter:on }; } diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadataTest.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadataTest.java index a196260473..1e35d8dfff 100644 --- a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadataTest.java +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/metadata/DeployMetadataTest.java @@ -51,7 +51,8 @@ protected String[] getParametersIds() { Variables.SKIP_APP_DIGEST_CALCULATION.getName(), Variables.IS_SECURITY_ENABLED.getName(), Variables.DISPOSABLE_USER_PROVIDED_SERVICE_NAME.getName(), - Variables.IS_DISPOSABLE_USER_PROVIDED_SERVICE_ENABLED.getName() + Variables.IS_DISPOSABLE_USER_PROVIDED_SERVICE_ENABLED.getName(), + Variables.API_REQUEST_PATH.getName() // @formatter:on }; } diff --git a/multiapps-controller-web/src/main/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImpl.java b/multiapps-controller-web/src/main/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImpl.java index 3bd31cee34..0cc3ef0e5a 100644 --- a/multiapps-controller-web/src/main/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImpl.java +++ b/multiapps-controller-web/src/main/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImpl.java @@ -17,6 +17,7 @@ import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.persistence.NoResultException; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections4.ListUtils; import org.cloudfoundry.multiapps.common.ContentException; import org.cloudfoundry.multiapps.common.NotFoundException; @@ -148,13 +149,13 @@ public ResponseEntity getOperationLogContent(String spaceGuid, String op } @Override - public ResponseEntity startOperation(String spaceGuid, Operation operation) { + public ResponseEntity startOperation(String spaceGuid, Operation operation, HttpServletRequest httpServletRequest) { operationsApiServiceAuditLog.logStartOperation(SecurityContextUtil.getUsername(), spaceGuid, operation); UserInfo authenticatedUser = getAuthenticatedUser(); String processDefinitionKey = operationsHelper.getProcessDefinitionKey(operation); Set predefinedParameters = operationMetadataMapper.getOperationMetadata(operation.getProcessType()) .getParameters(); - operation = addServiceParameters(operation, spaceGuid, authenticatedUser.getName(), authenticatedUser.getId()); + operation = addServiceParameters(operation, spaceGuid, authenticatedUser.getName(), authenticatedUser.getId(), httpServletRequest); operation = addParameterValues(operation, predefinedParameters); ensureRequiredParametersSet(operation, predefinedParameters); ProcessInstance processInstance = flowableFacade.startProcess(processDefinitionKey, operation.getParameters()); @@ -246,7 +247,8 @@ private List getAvailableActions(Operation operation) { throw new IllegalStateException(MessageFormat.format("State \"{0}\" not recognized!", operation.getState())); } - private Operation addServiceParameters(Operation operation, String spaceGuid, String user, String userGuid) { + private Operation addServiceParameters(Operation operation, String spaceGuid, String user, String userGuid, + HttpServletRequest httpServletRequest) { Map parameters = new HashMap<>(operation.getParameters()); CloudSpaceClient client = getSpaceClient(); @@ -265,6 +267,8 @@ private Operation addServiceParameters(Operation operation, String spaceGuid, St .toString()); parameters.put(Variables.TIMESTAMP.getName(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss") .format(ZonedDateTime.now())); + parameters.put(Variables.API_REQUEST_PATH.getName(), httpServletRequest.getRequestURL() + .toString()); String namespace = operation.getNamespace(); if (namespace != null) { parameters.put(Variables.MTA_NAMESPACE.getName(), namespace); diff --git a/multiapps-controller-web/src/test/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImplTest.java b/multiapps-controller-web/src/test/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImplTest.java index 055b21a337..724d388fb8 100644 --- a/multiapps-controller-web/src/test/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImplTest.java +++ b/multiapps-controller-web/src/test/java/org/cloudfoundry/multiapps/controller/web/api/impl/OperationsApiServiceImplTest.java @@ -196,7 +196,10 @@ void testStartOperation() { Operation operation = createOperation(null, null, parameters); Mockito.when(operationsHelper.getProcessDefinitionKey(operation)) .thenReturn("deploy"); - operationsApiService.startOperation(SPACE_GUID, operation); + HttpServletRequest httpServletRequestMock = Mockito.mock(HttpServletRequest.class); + Mockito.when(httpServletRequestMock.getRequestURL()) + .thenReturn(new StringBuffer("test/api/path")); + operationsApiService.startOperation(SPACE_GUID, operation, httpServletRequestMock); Mockito.verify(flowableFacade) .startProcess(Mockito.any(), Mockito.anyMap()); } @@ -210,12 +213,15 @@ void testStartOperationWithInvalidParametersForTheProcess() { Mockito.when(operationsHelper.getProcessDefinitionKey(operation)) .thenReturn("deploy"); - operationsApiService.startOperation(SPACE_GUID, operation); + HttpServletRequest httpServletRequestMock = Mockito.mock(HttpServletRequest.class); + Mockito.when(httpServletRequestMock.getRequestURL()) + .thenReturn(new StringBuffer("test/api/path")); + operationsApiService.startOperation(SPACE_GUID, operation, httpServletRequestMock); Mockito.verify(flowableFacade) .startProcess(ArgumentMatchers.eq("deploy"), ArgumentMatchers.argThat( map -> map.containsKey(Variables.MTA_ID.getName()) && map.containsKey(Variables.EXT_DESCRIPTOR_FILE_ID.getName()) - && !map.containsKey(Variables.CTS_PROCESS_ID.getName()) && !map.containsKey(Variables.DEPLOY_URI.getName()))); + && !map.containsKey(Variables.CTS_PROCESS_ID.getName()) && !map.containsKey(Variables.CTS_PASSWORD.getName()))); } @Test @@ -225,8 +231,10 @@ void testStartOperationWithValidParametersForTheProcess() { Operation operation = createOperation(null, null, parameters); Mockito.when(operationsHelper.getProcessDefinitionKey(operation)) .thenReturn("deploy"); - - operationsApiService.startOperation(SPACE_GUID, operation); + HttpServletRequest httpServletRequestMock = Mockito.mock(HttpServletRequest.class); + Mockito.when(httpServletRequestMock.getRequestURL()) + .thenReturn(new StringBuffer("test/api/path")); + operationsApiService.startOperation(SPACE_GUID, operation, httpServletRequestMock); Mockito.verify(flowableFacade) .startProcess(ArgumentMatchers.eq("deploy"), ArgumentMatchers.argThat(