diff --git a/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/lib/domain/DropletInfoFactory.java b/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/lib/domain/DropletInfoFactory.java index bba3f61b15..af168d2ed7 100644 --- a/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/lib/domain/DropletInfoFactory.java +++ b/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/lib/domain/DropletInfoFactory.java @@ -1,13 +1,13 @@ package org.cloudfoundry.multiapps.controller.client.lib.domain; +import java.util.List; + import com.sap.cloudfoundry.client.facade.CloudControllerClient; import com.sap.cloudfoundry.client.facade.domain.CloudApplication; import com.sap.cloudfoundry.client.facade.domain.DockerData; import com.sap.cloudfoundry.client.facade.domain.LifecycleType; import com.sap.cloudfoundry.client.facade.domain.Staging; -import java.util.List; - public class DropletInfoFactory { public DropletInfo createDropletInfo(Staging staging) { @@ -20,7 +20,7 @@ public DropletInfo createDropletInfo(Staging staging) { public DropletInfo createDropletInfo(CloudApplication app, CloudControllerClient client) { var lifecycle = app.getLifecycle(); - if (lifecycle.getType() == LifecycleType.BUILDPACK) { + if (lifecycle.getType() == LifecycleType.BUILDPACK || lifecycle.getType() == LifecycleType.CNB) { var buildpacks = (List) lifecycle.getData() .get("buildpacks"); var stack = (String) lifecycle.getData() 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 74eb64d9d1..feeca5e1bb 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 @@ -86,6 +86,11 @@ public final class Messages { public static final String OBJECT_STORE_FILE_STORAGE_HEALTH_DATABASE_HEALTH = "Object store file storage health: \"{0}\", Database health: \"{1}\""; public static final String ERROR_OCCURRED_DURING_OBJECT_STORE_HEALTH_CHECKING_FOR_INSTANCE = "Error occurred during object store health checking for instance: \"{0}\""; public static final String ERROR_OCCURRED_WHILE_CHECKING_DATABASE_INSTANCE_0 = "Error occurred while checking database instance: \"{0}\""; + public static final String DOCKER_INFO_NOT_ALLOWED_WITH_LIFECYCLE = "Docker information must not be provided when lifecycle is set to \"{0}\""; + public static final String UNSUPPORTED_LIFECYCLE_VALUE = "Unsupported lifecycle value: \"{0}\""; + public static final String BUILDPACKS_REQUIRED_FOR_CNB = "Buildpacks must be provided when lifecycle is set to 'cnb'."; + public static final String DOCKER_INFO_REQUIRED = "Docker information must be provided when lifecycle is set to 'docker'."; + public static final String BUILDPACKS_NOT_ALLOWED_WITH_DOCKER = "Buildpacks must not be provided when lifecycle is set to 'docker'."; // Warning messages public static final String ENVIRONMENT_VARIABLE_IS_NOT_SET_USING_DEFAULT = "Environment variable \"{0}\" is not set. Using default \"{1}\"..."; diff --git a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/model/SupportedParameters.java b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/model/SupportedParameters.java index a9b173c3ce..dd49ce935e 100644 --- a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/model/SupportedParameters.java +++ b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/model/SupportedParameters.java @@ -58,6 +58,7 @@ public class SupportedParameters { public static final String BUILDPACK = "buildpack"; public static final String BUILDPACKS = "buildpacks"; public static final String STACK = "stack"; + public static final String LIFECYCLE = "lifecycle"; public static final String HEALTH_CHECK_INVOCATION_TIMEOUT = "health-check-invocation-timeout"; public static final String HEALTH_CHECK_TIMEOUT = "health-check-timeout"; public static final String HEALTH_CHECK_TYPE = "health-check-type"; @@ -179,7 +180,7 @@ public class SupportedParameters { @Deprecated public static final String DEPRECATED_CONFIG_MTA_PROVIDES_DEPENDENCY = "mta-provides-dependency"; - public static final Set MODULE_PARAMETERS = Set.of(APP_NAME, APPLY_NAMESPACE, BUILDPACK, BUILDPACKS, COMMAND, + public static final Set MODULE_PARAMETERS = Set.of(APP_NAME, APPLY_NAMESPACE, BUILDPACK, BUILDPACKS, LIFECYCLE, 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, diff --git a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParser.java b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParser.java index 141f91d20e..b882a48fce 100644 --- a/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParser.java +++ b/multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParser.java @@ -1,17 +1,25 @@ package org.cloudfoundry.multiapps.controller.core.parser; +import java.text.MessageFormat; import java.util.List; import java.util.Map; -import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters; -import org.cloudfoundry.multiapps.mta.util.PropertiesUtil; - import com.sap.cloudfoundry.client.facade.domain.DockerInfo; import com.sap.cloudfoundry.client.facade.domain.ImmutableStaging; +import com.sap.cloudfoundry.client.facade.domain.LifecycleType; import com.sap.cloudfoundry.client.facade.domain.Staging; +import org.cloudfoundry.multiapps.common.ContentException; +import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters; +import org.cloudfoundry.multiapps.mta.util.PropertiesUtil; +import org.springframework.util.CollectionUtils; -public class StagingParametersParser implements ParametersParser { +import static org.cloudfoundry.multiapps.controller.core.Messages.BUILDPACKS_NOT_ALLOWED_WITH_DOCKER; +import static org.cloudfoundry.multiapps.controller.core.Messages.BUILDPACKS_REQUIRED_FOR_CNB; +import static org.cloudfoundry.multiapps.controller.core.Messages.DOCKER_INFO_NOT_ALLOWED_WITH_LIFECYCLE; +import static org.cloudfoundry.multiapps.controller.core.Messages.DOCKER_INFO_REQUIRED; +import static org.cloudfoundry.multiapps.controller.core.Messages.UNSUPPORTED_LIFECYCLE_VALUE; +public class StagingParametersParser implements ParametersParser { private static final String DEFAULT_HEALTH_CHECK_HTTP_ENDPOINT = "/"; private static final String HTTP_HEALTH_CHECK_TYPE = "http"; @@ -32,6 +40,10 @@ public Staging parse(List> parametersList) { getDefaultHealthCheckHttpEndpoint(healthCheckType)); Boolean isSshEnabled = (Boolean) PropertiesUtil.getPropertyValue(parametersList, SupportedParameters.ENABLE_SSH, null); DockerInfo dockerInfo = new DockerInfoParser().parse(parametersList); + LifecycleType lifecycleType = parseLifecycleType(parametersList); + + validateLifecycleType(lifecycleType, buildpacks, dockerInfo); + return ImmutableStaging.builder() .command(command) .buildpacks(buildpacks) @@ -42,9 +54,56 @@ public Staging parse(List> parametersList) { .healthCheckHttpEndpoint(healthCheckHttpEndpoint) .isSshEnabled(isSshEnabled) .dockerInfo(dockerInfo) + .lifecycleType(lifecycleType) .build(); } + private LifecycleType parseLifecycleType(List> parametersList) { + String lifecycleValue = (String) PropertiesUtil.getPropertyValue(parametersList, SupportedParameters.LIFECYCLE, null); + if (lifecycleValue == null) { + return null; + } + try { + return LifecycleType.valueOf(lifecycleValue.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new ContentException(MessageFormat.format(UNSUPPORTED_LIFECYCLE_VALUE, lifecycleValue)); + } + } + + private void validateLifecycleType(LifecycleType lifecycleType, List buildpacks, DockerInfo dockerInfo) { + validateBuildpacksWithCNB(lifecycleType, buildpacks); + + // Validate Docker-specific conditions + validateDockerInfoWithDocker(lifecycleType, dockerInfo); + validateBuildpacksWithDocker(lifecycleType, buildpacks); + validateDockerInfoWithNonDocker(lifecycleType, dockerInfo); + } + + private void validateBuildpacksWithCNB(LifecycleType lifecycleType, List buildpacks) { + if (lifecycleType == LifecycleType.CNB && CollectionUtils.isEmpty(buildpacks)) { + throw new ContentException(BUILDPACKS_REQUIRED_FOR_CNB); + } + } + + private void validateDockerInfoWithDocker(LifecycleType lifecycleType, DockerInfo dockerInfo) { + if (lifecycleType == LifecycleType.DOCKER && dockerInfo == null) { + throw new ContentException(DOCKER_INFO_REQUIRED); + } + } + + private void validateBuildpacksWithDocker(LifecycleType lifecycleType, List buildpacks) { + if (lifecycleType == LifecycleType.DOCKER && !CollectionUtils.isEmpty(buildpacks)) { + throw new ContentException(BUILDPACKS_NOT_ALLOWED_WITH_DOCKER); + } + } + + private void validateDockerInfoWithNonDocker(LifecycleType lifecycleType, DockerInfo dockerInfo) { + if (lifecycleType != LifecycleType.DOCKER && lifecycleType != null && dockerInfo != null) { + throw new ContentException( + MessageFormat.format(DOCKER_INFO_NOT_ALLOWED_WITH_LIFECYCLE, lifecycleType)); + } + } + private String getDefaultHealthCheckHttpEndpoint(String healthCheckType) { return HTTP_HEALTH_CHECK_TYPE.equals(healthCheckType) ? DEFAULT_HEALTH_CHECK_HTTP_ENDPOINT : null; } diff --git a/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParserTest.java b/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParserTest.java new file mode 100644 index 0000000000..aef7f3495e --- /dev/null +++ b/multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/parser/StagingParametersParserTest.java @@ -0,0 +1,149 @@ +package org.cloudfoundry.multiapps.controller.core.parser; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import com.sap.cloudfoundry.client.facade.domain.LifecycleType; +import com.sap.cloudfoundry.client.facade.domain.Staging; +import org.cloudfoundry.multiapps.common.ContentException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.util.CollectionUtils; + +import static org.cloudfoundry.multiapps.controller.core.Messages.BUILDPACKS_NOT_ALLOWED_WITH_DOCKER; +import static org.cloudfoundry.multiapps.controller.core.Messages.BUILDPACKS_REQUIRED_FOR_CNB; +import static org.cloudfoundry.multiapps.controller.core.Messages.DOCKER_INFO_NOT_ALLOWED_WITH_LIFECYCLE; +import static org.cloudfoundry.multiapps.controller.core.Messages.DOCKER_INFO_REQUIRED; +import static org.cloudfoundry.multiapps.controller.core.Messages.UNSUPPORTED_LIFECYCLE_VALUE; +import static org.cloudfoundry.multiapps.controller.core.model.SupportedParameters.BUILDPACK; +import static org.cloudfoundry.multiapps.controller.core.model.SupportedParameters.BUILDPACKS; +import static org.cloudfoundry.multiapps.controller.core.model.SupportedParameters.DOCKER; +import static org.cloudfoundry.multiapps.controller.core.model.SupportedParameters.LIFECYCLE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class StagingParametersParserTest { + + public static final String INVALID_VALUE = "invalid_value"; + public static final String CNB = "cnb"; + public static final String CUSTOM_BUILDPACK_URL = "custom-buildpack-url"; + public static final String IMAGE = "image"; + public static final String CLOUDFOUNDRY_TEST_APP = "cloudfoundry/test-app"; + public static final String SOME_BUILDPACK = "some-buildpack"; + private StagingParametersParser parser; + private List> parametersList; + + @BeforeEach + void setup() { + parser = new StagingParametersParser(); + parametersList = new ArrayList<>(); + } + + @Test + void testValidateLifecycleWithCnbAndValidBuildpacks() { + parametersList.add(mapOf(LIFECYCLE, CNB)); + parametersList.add(mapOf(BUILDPACKS, List.of(CUSTOM_BUILDPACK_URL))); + + Staging staging = parser.parse(parametersList); + + assertNotNull(staging); + assertEquals(LifecycleType.CNB, staging.getLifecycleType()); + assertNotNull(staging.getBuildpacks()); + assertEquals(1, staging.getBuildpacks() + .size()); + assertEquals(CUSTOM_BUILDPACK_URL, staging.getBuildpacks() + .get(0)); + } + + @Test + void testValidateLifecycleWithCnbAndNoBuildpacks() { + parametersList.add(mapOf(LIFECYCLE, CNB)); + + ContentException exception = assertThrows(ContentException.class, () -> parser.parse(parametersList)); + assertEquals(BUILDPACKS_REQUIRED_FOR_CNB, exception.getMessage()); + } + + @Test + void testValidateLifecycleWithDockerAndValidDockerInfo() { + parametersList.add(getDockerParams()); + + Staging staging = parser.parse(parametersList); + + assertNotNull(staging); + assertEquals(LifecycleType.DOCKER, staging.getLifecycleType()); + assertNotNull(staging.getDockerInfo()); + } + + @Test + void testValidateLifecycleWithDockerAndBuildpacksProvided() { + parametersList.add(getDockerParams()); + parametersList.add(mapOf(BUILDPACKS, List.of(SOME_BUILDPACK))); + + ContentException exception = assertThrows(ContentException.class, () -> parser.parse(parametersList)); + assertEquals(BUILDPACKS_NOT_ALLOWED_WITH_DOCKER, exception.getMessage()); + } + + @Test + void testValidateLifecycleWithBuildpackAndNoBuildpacks() { + parametersList.add(mapOf(LIFECYCLE, BUILDPACK)); + + Staging staging = parser.parse(parametersList); + + assertNotNull(staging); + assertEquals(LifecycleType.BUILDPACK, staging.getLifecycleType()); + + List buildpacks = staging.getBuildpacks(); + assertTrue(CollectionUtils.isEmpty(buildpacks)); + } + + @Test + void testValidateLifecycleWithInvalidLifecycleValue() { + parametersList.add(mapOf(LIFECYCLE, INVALID_VALUE)); + + ContentException exception = assertThrows(ContentException.class, () -> parser.parse(parametersList)); + assertEquals(MessageFormat.format(UNSUPPORTED_LIFECYCLE_VALUE, INVALID_VALUE), exception.getMessage()); + } + + @Test + void testValidateLifecycleWithDockerAndNoDockerInfo() { + parametersList.add(mapOf(LIFECYCLE, DOCKER)); + + ContentException exception = assertThrows(ContentException.class, () -> parser.parse(parametersList)); + assertEquals(DOCKER_INFO_REQUIRED, exception.getMessage()); + } + + @Test + void testValidateDockerInfoWithNonDockerLifecycle() { + parametersList.add(mapOf(LIFECYCLE, CNB)); + parametersList.add(mapOf(BUILDPACKS, List.of(SOME_BUILDPACK))); + parametersList.add(getDockerParams()); + + ContentException exception = assertThrows(ContentException.class, () -> parser.parse(parametersList)); + assertEquals(MessageFormat.format(DOCKER_INFO_NOT_ALLOWED_WITH_LIFECYCLE, LifecycleType.CNB), exception.getMessage()); + } + + @Test + void testValidateWithAllParametersMissing() { + Staging staging = parser.parse(parametersList); + + assertNotNull(staging); + assertNull(staging.getLifecycleType()); + assertTrue(CollectionUtils.isEmpty(staging.getBuildpacks())); + assertNull(staging.getDockerInfo()); + } + + private static Map mapOf(String key, Object value) { + return Collections.singletonMap(key, value); + } + + private static Map getDockerParams() { + return Map.of(LIFECYCLE, DOCKER, DOCKER, Map.of(IMAGE, CLOUDFOUNDRY_TEST_APP)); + } + +} diff --git a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/CreateOrUpdateStepWithExistingAppTest.java b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/CreateOrUpdateStepWithExistingAppTest.java index 652c316304..4d3060127c 100644 --- a/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/CreateOrUpdateStepWithExistingAppTest.java +++ b/multiapps-controller-process/src/test/java/org/cloudfoundry/multiapps/controller/process/steps/CreateOrUpdateStepWithExistingAppTest.java @@ -1,16 +1,5 @@ package org.cloudfoundry.multiapps.controller.process.steps; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.anySet; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -20,18 +9,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudApplicationExtended; -import org.cloudfoundry.multiapps.controller.client.lib.domain.ImmutableCloudApplicationExtended; -import org.cloudfoundry.multiapps.controller.core.Constants; -import org.cloudfoundry.multiapps.controller.core.cf.clients.AppBoundServiceInstanceNamesGetter; -import org.cloudfoundry.multiapps.controller.core.util.ApplicationURI; -import org.cloudfoundry.multiapps.controller.process.variables.Variables; -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 org.mockito.Mock; - import com.sap.cloudfoundry.client.facade.domain.CloudApplication; import com.sap.cloudfoundry.client.facade.domain.CloudRoute; import com.sap.cloudfoundry.client.facade.domain.HealthCheckType; @@ -47,6 +24,28 @@ import com.sap.cloudfoundry.client.facade.domain.LifecycleType; import com.sap.cloudfoundry.client.facade.domain.Staging; import com.sap.cloudfoundry.client.facade.util.JsonUtil; +import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudApplicationExtended; +import org.cloudfoundry.multiapps.controller.client.lib.domain.ImmutableCloudApplicationExtended; +import org.cloudfoundry.multiapps.controller.core.Constants; +import org.cloudfoundry.multiapps.controller.core.cf.clients.AppBoundServiceInstanceNamesGetter; +import org.cloudfoundry.multiapps.controller.core.util.ApplicationURI; +import org.cloudfoundry.multiapps.controller.process.variables.Variables; +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 org.mockito.Mock; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anySet; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; class CreateOrUpdateStepWithExistingAppTest extends SyncFlowableStepTest { @@ -63,18 +62,18 @@ class CreateOrUpdateStepWithExistingAppTest extends SyncFlowableStepTest testHandleStagingApplicationAttributes() { return Stream.of( -//@formatter:off + //@formatter:off Arguments.of(ImmutableStaging.builder().addBuildpack("buildpack-1").command("command1").build(), - ImmutableStaging.builder().addBuildpack("buildpack-1").command("command2").build(), true), + ImmutableStaging.builder().addBuildpack("buildpack-1").command("command2").build(), true, LifecycleType.BUILDPACK), Arguments.of(ImmutableStaging.builder().addBuildpack("buildpack-1").build(), - ImmutableStaging.builder().addBuildpack("buildpack-1").build(), false), + ImmutableStaging.builder().addBuildpack("buildpack-1").build(), false, LifecycleType.BUILDPACK), Arguments.of( ImmutableStaging.builder().addBuildpack("buildpack-1").command("command1").stackName("stack1") .healthCheckTimeout(5).healthCheckType("process").isSshEnabled(false).build(), ImmutableStaging.builder().addBuildpack("buildpack-2").command("command2").stackName("stack2") .healthCheckTimeout(10).healthCheckType("port").healthCheckHttpEndpoint("/test") .isSshEnabled(true).build(), - true), + true, LifecycleType.BUILDPACK), Arguments.of( ImmutableStaging.builder().addBuildpack("buildpack-2").command("command2").stackName("stack2") .healthCheckTimeout(10).healthCheckType("process").healthCheckHttpEndpoint("/test") @@ -82,50 +81,56 @@ static Stream testHandleStagingApplicationAttributes() { ImmutableStaging.builder().addBuildpack("buildpack-2").command("command2").stackName("stack2") .healthCheckTimeout(10).healthCheckType("process").healthCheckHttpEndpoint("/test") .isSshEnabled(true).build(), - false), + false, LifecycleType.BUILDPACK), Arguments.of(ImmutableStaging.builder() .dockerInfo(ImmutableDockerInfo.builder().image("cloudfoundry/test-app").build()).build(), ImmutableStaging.builder() .dockerInfo(ImmutableDockerInfo.builder().image("cloudfoundry/test-app2").build()) .build(), - true), + true, LifecycleType.DOCKER), Arguments.of(ImmutableStaging.builder() .dockerInfo(ImmutableDockerInfo.builder().image("cloudfoundry/test-app").build()).build(), ImmutableStaging.builder() .dockerInfo(ImmutableDockerInfo.builder().image("cloudfoundry/test-app").build()) .build(), - false)); + false, LifecycleType.DOCKER), + Arguments.of(ImmutableStaging.builder().build(), + ImmutableStaging.builder().lifecycleType(LifecycleType.CNB).build(), + false, LifecycleType.CNB), + Arguments.of(ImmutableStaging.builder().addBuildpack("buildpack-1").command("command1").build(), + ImmutableStaging.builder().addBuildpack("buildpack-1").command("command2").lifecycleType(LifecycleType.CNB).build(), + true, LifecycleType.CNB), + Arguments.of(ImmutableStaging.builder().addBuildpack("buildpack-333").build(), + ImmutableStaging.builder().addBuildpacks("buildpack-4", "buildpack-8").lifecycleType(LifecycleType.CNB).build(), + true, LifecycleType.CNB)); //@formatter:on } @ParameterizedTest @MethodSource - void testHandleStagingApplicationAttributes(Staging existingStaging, Staging staging, boolean expectedPropertiesChanged) { + void testHandleStagingApplicationAttributes(Staging existingStaging, Staging staging, boolean expectedPropertiesChanged, + LifecycleType expectedLifecycleType) { CloudApplication existingApplication = getApplicationBuilder(false).staging(existingStaging) .build(); - if (staging.getCommand() == null) { - staging = ImmutableStaging.copyOf(staging) - .withCommand(DEFAULT_COMMAND); - } - if (staging.getStackName() == null) { - staging = ImmutableStaging.copyOf(staging) - .withStackName(DEFAULT_STACK); - } + staging = ImmutableStaging.copyOf(applyDefaultsToStaging(staging)); CloudApplicationExtended application = getApplicationBuilder(false).staging(staging) .build(); - if (staging.getDockerInfo() != null) { - application = ImmutableCloudApplicationExtended.copyOf(application) - .withLifecycle(ImmutableLifecycle.builder() - .type(LifecycleType.DOCKER) - .build()); - } + LifecycleType lifecycleTypeToApply = determineLifecycleType(staging); + application = ImmutableCloudApplicationExtended.copyOf(application) + .withLifecycle(ImmutableLifecycle.builder() + .type(lifecycleTypeToApply) + .build()); + prepareContext(application, false); prepareClientWithStaging(existingApplication, existingStaging); step.execute(execution); assertStepFinishedSuccessfully(); + assertEquals(expectedLifecycleType, application.getLifecycle() + .getType()); assertEquals(expectedPropertiesChanged, context.getVariable(Variables.VCAP_APP_PROPERTIES_CHANGED)); + if (expectedPropertiesChanged) { verify(client).updateApplicationStaging(APP_NAME, staging); return; @@ -133,6 +138,27 @@ void testHandleStagingApplicationAttributes(Staging existingStaging, Staging sta verify(client, never()).updateApplicationStaging(eq(APP_NAME), any()); } + private LifecycleType determineLifecycleType(Staging staging) { + if (staging.getLifecycleType() != null) { + return staging.getLifecycleType(); + } else if (staging.getDockerInfo() != null) { + return LifecycleType.DOCKER; + } + return LifecycleType.BUILDPACK; + } + + private Staging applyDefaultsToStaging(Staging staging) { + if (staging.getCommand() == null) { + staging = ImmutableStaging.copyOf(staging) + .withCommand(DEFAULT_COMMAND); + } + if (staging.getStackName() == null) { + staging = ImmutableStaging.copyOf(staging) + .withStackName(DEFAULT_STACK); + } + return staging; + } + private ImmutableCloudApplicationExtended.Builder getApplicationBuilder(boolean shouldKeepExistingEnv) { return ImmutableCloudApplicationExtended.builder() .metadata(ImmutableCloudMetadata.of(UUID.randomUUID())) @@ -150,9 +176,11 @@ private ImmutableCloudApplicationExtended.Builder getApplicationBuilder(boolean .healthCheckType("port") .isSshEnabled(false) .build()) - .attributesUpdateStrategy(ImmutableCloudApplicationExtended.AttributeUpdateStrategy.builder() - .shouldKeepExistingEnv(shouldKeepExistingEnv) - .build()); + .attributesUpdateStrategy( + ImmutableCloudApplicationExtended.AttributeUpdateStrategy.builder() + .shouldKeepExistingEnv( + shouldKeepExistingEnv) + .build()); } private void prepareContext(CloudApplicationExtended application, boolean shouldSkipServiceRebinding) { @@ -200,10 +228,11 @@ private void prepareClient(CloudApplication application, Set routes, .command(command) .diskInMb(disk == null ? 1024 : disk) .memoryInMb(memory == null ? 1024 - : memory) + : memory) .healthCheckType(hcType == null - ? HealthCheckType.PORT - : HealthCheckType.valueOf(hcType.toUpperCase())) + ? HealthCheckType.PORT + : HealthCheckType.valueOf( + hcType.toUpperCase())) .healthCheckTimeout(hcTimeout) .healthCheckHttpEndpoint(hcEndpoint) .instances(1) diff --git a/pom.xml b/pom.xml index a8cde12d3e..f41a5235db 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ 2.19.0 4.32.0 5.1.0 - 2.56.0 + 2.57.0 1.6.16 2.7.0 33.4.8-jre