diff --git a/multiapps-controller-persistence-test/src/main/java/org/cloudfoundry/multiapps/controller/persistence/test/TestDataSourceProvider.java b/multiapps-controller-persistence-test/src/main/java/org/cloudfoundry/multiapps/controller/persistence/test/TestDataSourceProvider.java index 65e4b37eef..ab9fe0a9b8 100644 --- a/multiapps-controller-persistence-test/src/main/java/org/cloudfoundry/multiapps/controller/persistence/test/TestDataSourceProvider.java +++ b/multiapps-controller-persistence-test/src/main/java/org/cloudfoundry/multiapps/controller/persistence/test/TestDataSourceProvider.java @@ -3,16 +3,14 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; - import javax.sql.DataSource; -import org.springframework.jdbc.datasource.SingleConnectionDataSource; - import liquibase.Liquibase; import liquibase.database.Database; import liquibase.database.DatabaseFactory; import liquibase.database.jvm.JdbcConnection; import liquibase.resource.ClassLoaderResourceAccessor; +import org.springframework.jdbc.datasource.SingleConnectionDataSource; public final class TestDataSourceProvider { @@ -20,6 +18,11 @@ private TestDataSourceProvider() { } + public static DataSource getDataSource() throws Exception { + Connection connection = createH2InMemoryConnection(); + return new SingleConnectionDataSource(connection, true); + } + public static DataSource getDataSource(String liquibaseChangelogLocation) throws Exception { // Liquibase closes the connection after it's done, so we need a separate one for it. Connection connectionForLiquibase = createH2InMemoryConnection(); diff --git a/multiapps-controller-process/pom.xml b/multiapps-controller-process/pom.xml index 06d5c2d465..9066ec03b5 100644 --- a/multiapps-controller-process/pom.xml +++ b/multiapps-controller-process/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 multiapps-controller-process @@ -96,5 +96,15 @@ jakarta.xml.bind jakarta.xml.bind-api + + org.cloudfoundry.multiapps + multiapps-controller-persistence-test + test + + + com.h2database + h2 + test + \ No newline at end of file diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableEngineTest.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableEngineTest.java new file mode 100644 index 0000000000..6dd2381b84 --- /dev/null +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableEngineTest.java @@ -0,0 +1,217 @@ +package org.cloudfoundry.multiapps.controller.process.flowable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; + +import org.cloudfoundry.multiapps.common.util.JsonSerializationStrategy; +import org.cloudfoundry.multiapps.common.util.JsonUtil; +import org.cloudfoundry.multiapps.controller.persistence.test.TestDataSourceProvider; +import org.cloudfoundry.multiapps.controller.process.variables.Serializer; +import org.cloudfoundry.multiapps.controller.process.variables.Variable; +import org.cloudfoundry.multiapps.controller.process.variables.Variables; +import org.flowable.engine.ProcessEngine; +import org.flowable.engine.ProcessEngineConfiguration; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.mail.common.api.client.FlowableMailClient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +/** + * Integration test for Flowable engine with in-memory H2 database. Tests real BPMN process creation, variable setting and retrieval using + * the multiapps-controller variable handling system. + */ +class FlowableEngineTest { + + private static final String TEST_PROCESS_KEY = "mtaDeploymentTest"; + private static final String MTA_DEPLOYMENT_TEST_PROCESS = "MTA Deployment Test Process"; + private static final String FLOWABLE_DB_SCHEMA_STRATEGY_CREATE_DROP = "create-drop"; + private static final String TEST_VARIABLE_TASK_BEAN_NAME = "testVariableTask"; + private static final String DEPLOYMENT_NAME_OF_DIAGRAM = "MTA Deployment Test"; + private static final String TEST_BPMN_DIAGRAM_RESOURCE = + "org/cloudfoundry/multiapps/controller/process/flowable/test-bpmn-diagram.bpmn"; + + @Mock + private FlowableMailClient flowableMailClient; + + private ProcessEngine processEngine; + private RepositoryService repositoryService; + private RuntimeService runtimeService; + private String deploymentId; + private TestVariableTask testVariableTask; + + @BeforeEach + void setUp() throws Exception { + MockitoAnnotations.openMocks(this); + testVariableTask = new TestVariableTask(); + DataSource dataSource = TestDataSourceProvider.getDataSource(); + ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration(); + configuration.setDataSource(dataSource); + configuration.setDefaultMailClient(flowableMailClient); + configuration.setDatabaseSchemaUpdate(FLOWABLE_DB_SCHEMA_STRATEGY_CREATE_DROP); + configuration.setBeans(Map.of(TEST_VARIABLE_TASK_BEAN_NAME, testVariableTask)); + processEngine = configuration.buildProcessEngine(); + repositoryService = processEngine.getRepositoryService(); + runtimeService = processEngine.getRuntimeService(); + deploymentId = repositoryService.createDeployment() + .name(DEPLOYMENT_NAME_OF_DIAGRAM) + .addClasspathResource( + TEST_BPMN_DIAGRAM_RESOURCE) + .deploy() + .getId(); + } + + @AfterEach + void tearDown() { + if (deploymentId != null) { + repositoryService.deleteDeployment(deploymentId, true); + } + if (processEngine != null) { + processEngine.close(); + } + } + + @Test + void testProcessDeployment() { + List processDefinitions = repositoryService.createProcessDefinitionQuery() + .processDefinitionKey(TEST_PROCESS_KEY) + .list(); + + assertEquals(1, processDefinitions.size()); + assertEquals(TEST_PROCESS_KEY, processDefinitions.get(0) + .getKey()); + assertEquals(MTA_DEPLOYMENT_TEST_PROCESS, processDefinitions.get(0) + .getName()); + } + + @Test + void testProcessWithPredefinedVariables() { + FlowableProcessTestData data = FlowableProcessTestDataUtils.predefinedScenario(); + runtimeService.startProcessInstanceByKey(TEST_PROCESS_KEY, buildVariablesMap(data)); + assertCapturedVariables(data, true); + } + + @Test + void testVariableUpdateAndRetrieval() { + FlowableProcessTestDataUtils.UpdateScenario updateScenario = FlowableProcessTestDataUtils.updateScenario(); + testVariableTask.variablesToSetInContext = buildVariablesMap(updateScenario.updated()); + runtimeService.startProcessInstanceByKey(TEST_PROCESS_KEY, buildVariablesMap(updateScenario.initial())); + // This assertion intentionally checks that the modified deployment descriptor is different from the initially set one because of flowable caching regression + // https://github.com/flowable/flowable-engine/issues/4130 + // The original behaviour must be to have same deployment descriptor as it was set in the task. Modify the test to assert for matching values when the issue is fixed. + assertCapturedVariables(updateScenario.updated(), false); + } + + @Test + void testSetVariablesInsideStep() { + FlowableProcessTestData data = FlowableProcessTestDataUtils.insideStepScenario(); + testVariableTask.variablesToSetInContext = buildVariablesMap(data); + runtimeService.startProcessInstanceByKey(TEST_PROCESS_KEY); + assertCapturedVariables(data, true); + } + + private Map buildVariablesMap(FlowableProcessTestData flowableProcessTestData) { + Map vars = new HashMap<>(); + setSerializedValueInMap(vars, Variables.CORRELATION_ID, flowableProcessTestData.getCorrelationId()); + setSerializedValueInMap(vars, Variables.SPACE_GUID, flowableProcessTestData.getSpaceGuid()); + setSerializedValueInMap(vars, Variables.ORGANIZATION_GUID, flowableProcessTestData.getOrgGuid()); + setSerializedValueInMap(vars, Variables.USER, flowableProcessTestData.getUsername()); + setSerializedValueInMap(vars, Variables.USER_GUID, flowableProcessTestData.getUserGuid()); + setSerializedValueInMap(vars, Variables.MTA_ID, flowableProcessTestData.getMtaId()); + setSerializedValueInMap(vars, Variables.KEEP_FILES, flowableProcessTestData.keepFiles()); + setSerializedValueInMap(vars, Variables.DELETE_SERVICES, flowableProcessTestData.deleteServices()); + setSerializedValueInMap(vars, Variables.APPS_STAGE_TIMEOUT_PROCESS_VARIABLE, flowableProcessTestData.getAppsStageTimeout()); + setSerializedValueInMap(vars, Variables.MODULES_COUNT, flowableProcessTestData.getModulesCount()); + setSerializedValueInMap(vars, Variables.DEPLOYMENT_DESCRIPTOR_WITH_SYSTEM_PARAMETERS, flowableProcessTestData.getSmallDescriptor()); + setSerializedValueInMap(vars, Variables.DEPLOYMENT_DESCRIPTOR, flowableProcessTestData.getBigDescriptor()); + setSerializedValueInMap(vars, Variables.DEPLOYED_MTA, flowableProcessTestData.getDeployedMta()); + setSerializedValueInMap(vars, Variables.CURRENT_ROUTES, flowableProcessTestData.getRoutes()); + setSerializedValueInMap(vars, Variables.STEP_PHASE, flowableProcessTestData.getStepPhase()); + setSerializedValueInMap(vars, Variables.APP_STATE_ACTIONS_TO_EXECUTE, flowableProcessTestData.getAppActions()); + setSerializedValueInMap(vars, Variables.CLOUD_SERVICE_KEYS_TO_CREATE, flowableProcessTestData.getServiceKeys()); + setSerializedValueInMap(vars, Variables.MODULES_FOR_DEPLOYMENT, flowableProcessTestData.getModulesForDeployment()); + setSerializedValueInMap(vars, Variables.MTA_EXTENSION_DESCRIPTOR_CHAIN, flowableProcessTestData.getExtensionDescriptors()); + return vars; + } + + private void setSerializedValueInMap(Map variables, Variable variable, T value) { + if (value == null) { + variables.put(variable.getName(), null); + return; + } + Serializer serializer = variable.getSerializer(); + variables.put(variable.getName(), serializer.serialize(value)); + } + + private T getDeserializedValue(Map variables, Variable variable) { + Object serializedValue = variables.get(variable.getName()); + if (serializedValue == null) { + return variable.getDefaultValue(); + } + Serializer serializer = variable.getSerializer(); + return serializer.deserialize(serializedValue); + } + + private void assertCapturedVariables(FlowableProcessTestData expected, boolean expectBigDescriptorMatch) { + Map actual = testVariableTask.capturedVariables; + assertEquals(expected.getCorrelationId(), getDeserializedValue(actual, Variables.CORRELATION_ID)); + assertEquals(expected.getSpaceGuid(), getDeserializedValue(actual, Variables.SPACE_GUID)); + assertEquals(expected.getOrgGuid(), getDeserializedValue(actual, Variables.ORGANIZATION_GUID)); + assertEquals(expected.getUsername(), getDeserializedValue(actual, Variables.USER)); + assertEquals(expected.getUserGuid(), getDeserializedValue(actual, Variables.USER_GUID)); + assertEquals(expected.getMtaId(), getDeserializedValue(actual, Variables.MTA_ID)); + assertEquals(expected.keepFiles(), getDeserializedValue(actual, Variables.KEEP_FILES)); + assertEquals(expected.deleteServices(), getDeserializedValue(actual, Variables.DELETE_SERVICES)); + assertEquals(expected.getAppsStageTimeout(), getDeserializedValue(actual, Variables.APPS_STAGE_TIMEOUT_PROCESS_VARIABLE)); + assertEquals(expected.getModulesCount(), getDeserializedValue(actual, Variables.MODULES_COUNT)); + assertEquals(JsonUtil.toJson(expected.getSmallDescriptor()), + JsonUtil.toJson(getDeserializedValue(actual, Variables.DEPLOYMENT_DESCRIPTOR_WITH_SYSTEM_PARAMETERS))); + + String expectedBigDescriptor = JsonUtil.toJson(expected.getBigDescriptor()); + String actualBigDescriptor = JsonUtil.toJson(getDeserializedValue(actual, Variables.DEPLOYMENT_DESCRIPTOR)); + assertBigDescriptor(expectBigDescriptorMatch, expectedBigDescriptor, actualBigDescriptor); + + assertEquals(expected.getDeployedMta(), getDeserializedValue(actual, Variables.DEPLOYED_MTA)); + assertEquals(expected.getRoutes(), getDeserializedValue(actual, Variables.CURRENT_ROUTES)); + assertEquals(expected.getStepPhase(), getDeserializedValue(actual, Variables.STEP_PHASE)); + assertEquals(expected.getAppActions(), getDeserializedValue(actual, Variables.APP_STATE_ACTIONS_TO_EXECUTE)); + assertEquals(expected.getServiceKeys(), getDeserializedValue(actual, Variables.CLOUD_SERVICE_KEYS_TO_CREATE)); + assertEquals(expected.getModulesForDeployment(), getDeserializedValue(actual, Variables.MODULES_FOR_DEPLOYMENT)); + assertEquals(JsonUtil.toJson(expected.getExtensionDescriptors(), JsonSerializationStrategy.ALLOW_NULLS), + JsonUtil.toJson(getDeserializedValue(actual, Variables.MTA_EXTENSION_DESCRIPTOR_CHAIN), + JsonSerializationStrategy.ALLOW_NULLS)); + } + + private static void assertBigDescriptor(boolean expectBigDescriptorMatch, String expectedBigDescriptor, String actualBigDescriptor) { + if (expectBigDescriptorMatch) { + assertEquals(expectedBigDescriptor, actualBigDescriptor); + return; + } + assertNotEquals(expectedBigDescriptor, actualBigDescriptor); + + } + + private class TestVariableTask implements JavaDelegate { + + Map variablesToSetInContext = new HashMap<>(); + Map capturedVariables = new HashMap<>(); + + @Override + public void execute(DelegateExecution execution) { + execution.setVariables(variablesToSetInContext); + capturedVariables = execution.getVariables(); + } + } + +} diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableProcessTestData.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableProcessTestData.java new file mode 100644 index 0000000000..dc1db91811 --- /dev/null +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableProcessTestData.java @@ -0,0 +1,67 @@ +package org.cloudfoundry.multiapps.controller.process.flowable; + +import java.time.Duration; +import java.util.List; + +import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudRoute; +import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudServiceKey; +import org.cloudfoundry.multiapps.controller.core.cf.apps.ApplicationStateAction; +import org.cloudfoundry.multiapps.controller.core.model.DeployedMta; +import org.cloudfoundry.multiapps.controller.process.steps.StepPhase; +import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor; +import org.cloudfoundry.multiapps.mta.model.ExtensionDescriptor; +import org.immutables.value.Value; + +@Value.Immutable +public interface FlowableProcessTestData { + + String getCorrelationId(); + + String getSpaceGuid(); + + String getOrgGuid(); + + String getUsername(); + + String getUserGuid(); + + String getMtaId(); + + String getMtaVersion(); + + @Value.Default + default boolean keepFiles() { + return false; + } + + @Value.Default + default boolean deleteServices() { + return false; + } + + Duration getAppsStageTimeout(); + + @Value.Default + default int getModulesCount() { + return 0; + } + + DeploymentDescriptor getSmallDescriptor(); + + DeploymentDescriptor getBigDescriptor(); + + DeployedMta getDeployedMta(); + + List getRoutes(); + + StepPhase getStepPhase(); + + List getAppActions(); + + List getServiceKeys(); + + List getModulesForDeployment(); + + List getExtensionDescriptors(); + +} diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableProcessTestDataUtils.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableProcessTestDataUtils.java new file mode 100644 index 0000000000..82909fdd58 --- /dev/null +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/flowable/FlowableProcessTestDataUtils.java @@ -0,0 +1,380 @@ +package org.cloudfoundry.multiapps.controller.process.flowable; + +import java.time.Duration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudRoute; +import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudServiceKey; +import org.cloudfoundry.multiapps.controller.client.facade.domain.ImmutableCloudServiceKey; +import org.cloudfoundry.multiapps.controller.core.cf.apps.ApplicationStateAction; +import org.cloudfoundry.multiapps.controller.core.cf.metadata.ImmutableMtaMetadata; +import org.cloudfoundry.multiapps.controller.core.model.DeployedMta; +import org.cloudfoundry.multiapps.controller.core.model.DeployedMtaApplication; +import org.cloudfoundry.multiapps.controller.core.model.DeployedMtaService; +import org.cloudfoundry.multiapps.controller.core.model.ImmutableDeployedMta; +import org.cloudfoundry.multiapps.controller.core.model.ImmutableDeployedMtaApplication; +import org.cloudfoundry.multiapps.controller.core.model.ImmutableDeployedMtaService; +import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters; +import org.cloudfoundry.multiapps.controller.core.util.ApplicationURI; +import org.cloudfoundry.multiapps.controller.process.steps.StepPhase; +import org.cloudfoundry.multiapps.mta.model.DeploymentDescriptor; +import org.cloudfoundry.multiapps.mta.model.ExtensionDescriptor; +import org.cloudfoundry.multiapps.mta.model.ExtensionModule; +import org.cloudfoundry.multiapps.mta.model.ExtensionResource; +import org.cloudfoundry.multiapps.mta.model.Module; +import org.cloudfoundry.multiapps.mta.model.ProvidedDependency; +import org.cloudfoundry.multiapps.mta.model.RequiredDependency; +import org.cloudfoundry.multiapps.mta.model.Resource; +import org.cloudfoundry.multiapps.mta.model.Version; + +public class FlowableProcessTestDataUtils { + + // MTA and test identifiers + private static final String DEFAULT_MTA_ID = "test-mta"; + private static final String DEFAULT_MTA_VERSION = "1.0.0"; + private static final String UPDATE_SCENARIO_MTA_ID = "test-mta-2"; + private static final String UPDATE_SCENARIO_VERSION_V2 = "2.0.0"; + private static final String TEST_USER_EMAIL = "test-user@example.com"; + + // Module names and types + private static final String MODULE_1_NAME = "module-1"; + private static final String MODULE_2_NAME = "module-2"; + private static final String MODULE_3_NAME = "module-3"; + private static final String MEMORY_1G = "1G"; + private static final String MODULE_TYPE_JAVASCRIPT = "javascript"; + private static final String MODULE_TYPE_JAVA = "java"; + private static final int MODULES_COUNT = 5; + + // Memory and disk quota values + private static final String MEMORY_512M = "512M"; + private static final String DISK_QUOTA_256M = "256M"; + private static final String DISK_QUOTA_4096M = "4096M"; + private static final int INSTANCES_COUNT_2 = 2; + + // Route configurations + private static final String ROUTE_1_EXAMPLE_COM = "route-1.example.com/foo-bar"; + private static final String ROUTE_2_EXAMPLE_COM = "route-2.example.com"; + private static final String ROUTE_3_EXAMPLE_COM = "route-3.example.com"; + private static final String ROUTE_1_IDLE_EXAMPLE_COM = "route-1-idle.example.com/bar-foo"; + private static final String ROUTE_2_IDLE_EXAMPLE_COM = "route-2-idle.example.com"; + private static final String MODULE_1_ROUTE_EXAMPLE_COM = "module-1-route.example.com"; + private static final String MODULE_2_ROUTE_EXAMPLE_COM = "module-2-route.example.com"; + private static final String MODULE_3_ROUTE_EXAMPLE_COM = "module-3-route.example.com"; + + // Resource names + private static final String RESOURCE_DB_NAME = "db"; + private static final String RESOURCE_CACHE_NAME = "cache"; + private static final String RESOURCE_AUTOSCALER_NAME = "autoscaler"; + private static final String RESOURCE_APPLICATION_LOGS_NAME = "application-logs"; + + // Service configurations + private static final String SERVICE_TYPE_MANAGED = "org.cloudfoundry.managed-service"; + private static final String SERVICE_TYPE_USER_PROVIDED = "org.cloudfoundry.user-provided-service"; + private static final String TEST_DB_SERVICE = "test-db-service"; + private static final String TEST_CACHE_SERVICE = "test-cache-service"; + private static final String APP_AUTOSCALER_SERVICE = "app-autoscaler"; + private static final String SERVICE_PLAN_FREE = "free"; + private static final String SERVICE_PLAN_DEFAULT = "default"; + + // Task configurations + private static final String TASK_1_NAME = "task-1"; + private static final String TASK_1_COMMAND = "migrate-db.sh"; + private static final String TASK_NAME_KEY = "name"; + private static final String TASK_COMMAND_KEY = "command"; + + // Application and service names + private static final String APP_1_NAME = "app-1"; + private static final String APP_2_NAME = "app-2"; + private static final String APP_3_NAME = "app-3"; + private static final String SERVICE_1_NAME = "service-1"; + private static final String SERVICE_2_NAME = "service-2"; + private static final String SERVICE_3_NAME = "service-3"; + + // Service key names + private static final String SERVICE_KEY_1_NAME = "service-key-1"; + private static final String SERVICE_KEY_2_NAME = "service-key-2"; + + // Extension descriptor configurations + private static final String TEST_EXTENSION_ID = "test-extension"; + private static final String TEST_PARAMETER_KEY = "test-parameter"; + + // API configurations + private static final String PROVIDED_DEPENDENCY_MY_API = "my-api"; + private static final String API_URL_KEY = "url"; + private static final String API_URL_VALUE = "https://api.example.com"; + + // Parameter values + private static final String NEW_PARAM_KEY = "new-param"; + private static final String NEW_PARAM_VALUE = "new-value"; + private static final String SYSLOG_DRAIN_URL_VALUE = "syslog://logs.example.com:514"; + + private FlowableProcessTestDataUtils() { + } + + public record UpdateScenario(FlowableProcessTestData initial, FlowableProcessTestData updated) { + } + + public static FlowableProcessTestData predefinedScenario() { + return baseBuilder(DEFAULT_MTA_ID, DEFAULT_MTA_VERSION).keepFiles(true) + .modulesCount(MODULES_COUNT) + .bigDescriptor(createBigDescriptor(DEFAULT_MTA_ID, DEFAULT_MTA_VERSION)) + .routes(createRoutes(ROUTE_1_EXAMPLE_COM, ROUTE_2_EXAMPLE_COM, + ROUTE_3_EXAMPLE_COM)) + .stepPhase(StepPhase.DONE) + .appActions( + List.of(ApplicationStateAction.STAGE, ApplicationStateAction.START)) + .build(); + } + + public static UpdateScenario updateScenario() { + DeploymentDescriptor bigDescriptorV1 = createBigDescriptor(UPDATE_SCENARIO_MTA_ID, DEFAULT_MTA_VERSION); + DeploymentDescriptor bigDescriptorV2 = DeploymentDescriptor.copyOf( + createBigDescriptor(UPDATE_SCENARIO_MTA_ID, UPDATE_SCENARIO_VERSION_V2)) + .setParameters(Map.of(NEW_PARAM_KEY, NEW_PARAM_VALUE)); + FlowableProcessTestData initial = baseBuilder(UPDATE_SCENARIO_MTA_ID, DEFAULT_MTA_VERSION).deleteServices(true) + .bigDescriptor(bigDescriptorV1) + .deployedMta( + createDeployed(UPDATE_SCENARIO_MTA_ID, + DEFAULT_MTA_VERSION)) + .routes( + createRoutes(ROUTE_1_IDLE_EXAMPLE_COM, + ROUTE_2_IDLE_EXAMPLE_COM)) + .stepPhase( + org.cloudfoundry.multiapps.controller.process.steps.StepPhase.POLL) + .appActions( + List.of(ApplicationStateAction.STAGE, + ApplicationStateAction.START)) + .build(); + FlowableProcessTestData updated = baseBuilder(UPDATE_SCENARIO_MTA_ID, UPDATE_SCENARIO_VERSION_V2).deleteServices(true) + .smallDescriptor( + createSmallDescriptor( + UPDATE_SCENARIO_MTA_ID, + UPDATE_SCENARIO_VERSION_V2)) + .bigDescriptor(bigDescriptorV2) + .deployedMta(createDeployed( + UPDATE_SCENARIO_MTA_ID, + UPDATE_SCENARIO_VERSION_V2)) + .routes(createRoutes( + ROUTE_1_EXAMPLE_COM, + ROUTE_2_EXAMPLE_COM, + ROUTE_3_EXAMPLE_COM)) + .stepPhase( + org.cloudfoundry.multiapps.controller.process.steps.StepPhase.DONE) + .appActions(List.of( + ApplicationStateAction.EXECUTE, + ApplicationStateAction.STOP)) + .build(); + return new UpdateScenario(initial, updated); + } + + public static FlowableProcessTestData insideStepScenario() { + return baseBuilder(UPDATE_SCENARIO_MTA_ID, UPDATE_SCENARIO_VERSION_V2).deleteServices(true) + .smallDescriptor(createSmallDescriptor(UPDATE_SCENARIO_MTA_ID, + UPDATE_SCENARIO_VERSION_V2)) + .bigDescriptor(createBigDescriptor(UPDATE_SCENARIO_MTA_ID, + UPDATE_SCENARIO_VERSION_V2)) + .deployedMta(createDeployed(UPDATE_SCENARIO_MTA_ID, + UPDATE_SCENARIO_VERSION_V2)) + .routes(createRoutes(ROUTE_1_EXAMPLE_COM, ROUTE_2_EXAMPLE_COM, + ROUTE_3_EXAMPLE_COM)) + .stepPhase(StepPhase.DONE) + .appActions(List.of(ApplicationStateAction.STAGE, + ApplicationStateAction.START)) + .build(); + } + + private static ImmutableFlowableProcessTestData.Builder baseBuilder(String mtaId, String mtaVersion) { + return ImmutableFlowableProcessTestData.builder() + .correlationId(UUID.randomUUID() + .toString()) + .spaceGuid(UUID.randomUUID() + .toString()) + .orgGuid(UUID.randomUUID() + .toString()) + .username(TEST_USER_EMAIL) + .userGuid(UUID.randomUUID() + .toString()) + .mtaId(mtaId) + .mtaVersion(mtaVersion) + .appsStageTimeout(Duration.ofMinutes(15)) + .smallDescriptor(createSmallDescriptor(mtaId, mtaVersion)) + .deployedMta(createDeployed(mtaId, mtaVersion)) + .stepPhase(StepPhase.DONE) + .serviceKeys(createServiceKeys()) + .modulesForDeployment(List.of(MODULE_1_NAME, MODULE_2_NAME, MODULE_3_NAME)) + .extensionDescriptors(createExtensionDescriptorsWithNullValues(mtaId)); + } + + private static DeploymentDescriptor createSmallDescriptor(String id, String mtaVersion) { + return DeploymentDescriptor.createV3() + .setId(id) + .setVersion(mtaVersion) + .setModules(List.of(Module.createV3() + .setName(MODULE_1_NAME) + .setType(MODULE_TYPE_JAVASCRIPT) + .setParameters(Map.of(SupportedParameters.MEMORY, MEMORY_512M, + SupportedParameters.DISK_QUOTA, DISK_QUOTA_256M, + SupportedParameters.ROUTES, + List.of(SupportedParameters.ROUTE, + MODULE_1_ROUTE_EXAMPLE_COM))) + .setRequiredDependencies(List.of(RequiredDependency.createV3() + .setName( + RESOURCE_DB_NAME))))) + .setResources(List.of(Resource.createV3() + .setName(RESOURCE_DB_NAME) + .setType(SERVICE_TYPE_MANAGED) + .setParameters(Map.of(SupportedParameters.SERVICE, TEST_DB_SERVICE, + SupportedParameters.SERVICE_PLAN, + SERVICE_PLAN_FREE)))); + } + + private static DeploymentDescriptor createBigDescriptor(String id, String mtaVersion) { + return DeploymentDescriptor.createV3() + .setId(id) + .setVersion(mtaVersion) + .setParameters(Map.of(SupportedParameters.ENABLE_PARALLEL_DEPLOYMENTS, true)) + .setModules(List.of(Module.createV3() + .setName(MODULE_1_NAME) + .setType(MODULE_TYPE_JAVASCRIPT) + .setParameters(Map.of(SupportedParameters.MEMORY, MEMORY_512M, + SupportedParameters.DISK_QUOTA, DISK_QUOTA_256M, + SupportedParameters.ROUTES, + List.of(SupportedParameters.ROUTE, + MODULE_1_ROUTE_EXAMPLE_COM), + SupportedParameters.TASKS, List.of( + Map.of(TASK_NAME_KEY, TASK_1_NAME, TASK_COMMAND_KEY, TASK_1_COMMAND)))) + .setRequiredDependencies(List.of(RequiredDependency.createV3() + .setName(RESOURCE_DB_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_APPLICATION_LOGS_NAME))), + Module.createV3() + .setName(MODULE_2_NAME) + .setType(MODULE_TYPE_JAVA) + .setParameters(Map.of(SupportedParameters.MEMORY, MEMORY_1G, + SupportedParameters.DISK_QUOTA, DISK_QUOTA_4096M, + SupportedParameters.INSTANCES, INSTANCES_COUNT_2, + SupportedParameters.ROUTES, + List.of(SupportedParameters.ROUTE, + MODULE_2_ROUTE_EXAMPLE_COM))) + .setRequiredDependencies(List.of(RequiredDependency.createV3() + .setName(RESOURCE_DB_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_CACHE_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_AUTOSCALER_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_APPLICATION_LOGS_NAME))), + Module.createV3() + .setName(MODULE_3_NAME) + .setType(MODULE_TYPE_JAVASCRIPT) + .setParameters( + Map.of(SupportedParameters.MEMORY, MEMORY_512M, + SupportedParameters.DISK_QUOTA, + DISK_QUOTA_256M, SupportedParameters.ROUTES, + List.of(SupportedParameters.ROUTE, MODULE_3_ROUTE_EXAMPLE_COM))) + .setRequiredDependencies(List.of(RequiredDependency.createV3() + .setName(RESOURCE_DB_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_CACHE_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_AUTOSCALER_NAME), + RequiredDependency.createV3() + .setName( + RESOURCE_APPLICATION_LOGS_NAME))) + .setProvidedDependencies(List.of(ProvidedDependency.createV3() + .setName( + PROVIDED_DEPENDENCY_MY_API) + .setProperties( + Map.of(API_URL_KEY, + API_URL_VALUE)))))) + .setResources(List.of(Resource.createV3() + .setName(RESOURCE_DB_NAME) + .setType(SERVICE_TYPE_MANAGED) + .setParameters(Map.of(SupportedParameters.SERVICE, TEST_DB_SERVICE, + SupportedParameters.SERVICE_PLAN, + SERVICE_PLAN_FREE)), + Resource.createV3() + .setName(RESOURCE_CACHE_NAME) + .setType(SERVICE_TYPE_MANAGED) + .setParameters(Map.of(SupportedParameters.SERVICE, TEST_CACHE_SERVICE, + SupportedParameters.SERVICE_PLAN, + SERVICE_PLAN_FREE)), + Resource.createV3() + .setName(RESOURCE_AUTOSCALER_NAME) + .setType(SERVICE_TYPE_MANAGED) + .setParameters(Map.of(SupportedParameters.SERVICE, APP_AUTOSCALER_SERVICE, + SupportedParameters.SERVICE_PLAN, + SERVICE_PLAN_DEFAULT)), + Resource.createV3() + .setName(RESOURCE_APPLICATION_LOGS_NAME) + .setType(SERVICE_TYPE_USER_PROVIDED) + .setParameters(Map.of(SupportedParameters.SYSLOG_DRAIN_URL, + SYSLOG_DRAIN_URL_VALUE)))); + } + + private static DeployedMta createDeployed(String id, String mtaVersion) { + List apps = Stream.of(APP_1_NAME, APP_2_NAME, APP_3_NAME) + .map(app -> ImmutableDeployedMtaApplication.builder() + .name(app) + .moduleName(app) + .build()) + .collect(Collectors.toList()); + List services = Stream.of(SERVICE_1_NAME, SERVICE_2_NAME, SERVICE_3_NAME) + .map(service -> ImmutableDeployedMtaService.builder() + .name(service) + .build()) + .collect(Collectors.toList()); + return ImmutableDeployedMta.builder() + .metadata(ImmutableMtaMetadata.builder() + .id(id) + .version(Version.parseVersion(mtaVersion)) + .build()) + .applications(apps) + .services(services) + .build(); + } + + private static List createRoutes(String... routes) { + return Stream.of(routes) + .map(route -> new ApplicationURI(route, false, null).toCloudRoute()) + .collect(Collectors.toList()); + } + + private static List createServiceKeys() { + return List.of(ImmutableCloudServiceKey.builder() + .name(SERVICE_KEY_1_NAME) + .build(), ImmutableCloudServiceKey.builder() + .name(SERVICE_KEY_2_NAME) + .build()); + } + + private static List createExtensionDescriptorsWithNullValues(String mtaId) { + Map moduleParams = new HashMap<>(); + moduleParams.put(SupportedParameters.MEMORY, null); + moduleParams.put(SupportedParameters.DISK_QUOTA, DISK_QUOTA_256M); + moduleParams.put(SupportedParameters.ROUTES, List.of(SupportedParameters.ROUTE, MODULE_1_ROUTE_EXAMPLE_COM)); + Map resourceParams = new HashMap<>(); + resourceParams.put(TEST_PARAMETER_KEY, null); + return List.of(ExtensionDescriptor.createV3() + .setId(TEST_EXTENSION_ID) + .setParentId(mtaId) + .setModules(List.of(ExtensionModule.createV3() + .setName(MODULE_1_NAME) + .setParameters(moduleParams))) + .setResources(List.of(ExtensionResource.createV3() + .setName(RESOURCE_DB_NAME) + .setParameters(resourceParams)))); + } + +} diff --git a/multiapps-controller-process/src/test/resources/META-INF/persistence.xml b/multiapps-controller-process/src/test/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..cda667cd28 --- /dev/null +++ b/multiapps-controller-process/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,18 @@ + + + + org.eclipse.persistence.jpa.PersistenceProvider + + + + + + + + + + + \ No newline at end of file diff --git a/multiapps-controller-process/src/test/resources/org/cloudfoundry/multiapps/controller/process/flowable/test-bpmn-diagram.bpmn b/multiapps-controller-process/src/test/resources/org/cloudfoundry/multiapps/controller/process/flowable/test-bpmn-diagram.bpmn new file mode 100644 index 0000000000..736d665177 --- /dev/null +++ b/multiapps-controller-process/src/test/resources/org/cloudfoundry/multiapps/controller/process/flowable/test-bpmn-diagram.bpmn @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file