diff --git a/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/adapters/RawCloudProcess.java b/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/adapters/RawCloudProcess.java index 4bd4b83775..931f528b75 100644 --- a/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/adapters/RawCloudProcess.java +++ b/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/adapters/RawCloudProcess.java @@ -23,11 +23,13 @@ public CloudProcess derive() { Integer healthCheckTimeout = null; String healthCheckHttpEndpoint = null; Integer healthCheckInvocationTimeout = null; + Integer healthCheckInterval = null; if (healthCheck.getData() != null) { Data healthCheckData = healthCheck.getData(); healthCheckTimeout = healthCheckData.getTimeout(); healthCheckInvocationTimeout = healthCheckData.getInvocationTimeout(); healthCheckHttpEndpoint = healthCheckData.getEndpoint(); + healthCheckInterval = healthCheckData.getInterval(); } Integer readinessHealthCheckInvocationTimeout = null; String readinessHealthCheckHttpEndpoint = null; @@ -49,6 +51,7 @@ public CloudProcess derive() { .healthCheckHttpEndpoint(healthCheckHttpEndpoint) .healthCheckTimeout(healthCheckTimeout) .healthCheckInvocationTimeout(healthCheckInvocationTimeout) + .healthCheckInterval(healthCheckInterval) .readinessHealthCheckType(readinessHealthCheckType.getType() .getValue()) .readinessHealthCheckHttpEndpoint(readinessHealthCheckHttpEndpoint) diff --git a/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/domain/CloudProcess.java b/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/domain/CloudProcess.java index 86df6003a7..ef141ae3fe 100644 --- a/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/domain/CloudProcess.java +++ b/multiapps-controller-client/src/main/java/org/cloudfoundry/multiapps/controller/client/facade/domain/CloudProcess.java @@ -29,6 +29,9 @@ public abstract class CloudProcess extends CloudEntity implements Derivable all four health-check Integer/String fields stay null + RawCloudProcess raw = ImmutableRawCloudProcess.of(buildProcessResource(HealthCheckType.PORT, null, + ReadinessHealthCheckType.PORT, null)); + + CloudProcess derived = raw.derive(); + + assertEquals(org.cloudfoundry.multiapps.controller.client.facade.domain.HealthCheckType.PORT, derived.getHealthCheckType()); + assertNull(derived.getHealthCheckTimeout()); + assertNull(derived.getHealthCheckInvocationTimeout()); + assertNull(derived.getHealthCheckHttpEndpoint()); + assertNull(derived.getHealthCheckInterval()); + assertNull(derived.getReadinessHealthCheckInvocationTimeout()); + assertNull(derived.getReadinessHealthCheckHttpEndpoint()); + assertNull(derived.getReadinessHealthCheckInterval()); + } + + @Test + void testDeriveWithHealthCheckDataPresentButIntervalNull() { + Data dataWithoutInterval = Data.builder() + .endpoint(HTTP_ENDPOINT) + .timeout(TIMEOUT) + .invocationTimeout(INVOCATION_TIMEOUT) + .build(); + RawCloudProcess raw = ImmutableRawCloudProcess.of(buildProcessResource(HealthCheckType.HTTP, dataWithoutInterval, + ReadinessHealthCheckType.PORT, null)); + + CloudProcess derived = raw.derive(); + + assertEquals(TIMEOUT, derived.getHealthCheckTimeout()); + assertEquals(INVOCATION_TIMEOUT, derived.getHealthCheckInvocationTimeout()); + assertEquals(HTTP_ENDPOINT, derived.getHealthCheckHttpEndpoint()); + assertNull(derived.getHealthCheckInterval()); + } + + private static ProcessResource buildProcessResource(HealthCheckType healthCheckType, Data healthCheckData, + ReadinessHealthCheckType readinessHealthCheckType, Data readinessHealthCheckData) { + HealthCheck.Builder healthCheckBuilder = HealthCheck.builder() + .type(healthCheckType); + if (healthCheckData != null) { + healthCheckBuilder.data(healthCheckData); + } + ReadinessHealthCheck.Builder readinessBuilder = ReadinessHealthCheck.builder() + .type(readinessHealthCheckType); + if (readinessHealthCheckData != null) { + readinessBuilder.data(readinessHealthCheckData); + } + return ProcessResource.builder() + .id(RawCloudEntityTest.GUID_STRING) + .createdAt(RawCloudEntityTest.CREATED_AT_STRING) + .updatedAt(RawCloudEntityTest.UPDATED_AT_STRING) + .command(COMMAND) + .diskInMb(DISK_IN_MB) + .instances(INSTANCES) + .memoryInMb(MEMORY_IN_MB) + .type("web") + .metadata(Metadata.builder() + .build()) + .relationships(ProcessRelationships.builder() + .build()) + .healthCheck(healthCheckBuilder.build()) + .readinessHealthCheck(readinessBuilder.build()) + .build(); + } + + private static Data buildHealthCheckData() { + return Data.builder() + .endpoint(HTTP_ENDPOINT) + .timeout(TIMEOUT) + .invocationTimeout(INVOCATION_TIMEOUT) + .interval(INTERVAL) + .build(); + } + + private static Data buildReadinessHealthCheckData() { + return Data.builder() + .endpoint(READINESS_HTTP_ENDPOINT) + .invocationTimeout(READINESS_INVOCATION_TIMEOUT) + .interval(READINESS_INTERVAL) + .build(); + } + + private static CloudProcess buildExpected(org.cloudfoundry.multiapps.controller.client.facade.domain.HealthCheckType type, + Integer interval, String readinessHealthCheckType) { + return ImmutableCloudProcess.builder() + .command(COMMAND) + .instances(INSTANCES) + .memoryInMb(MEMORY_IN_MB) + .diskInMb(DISK_IN_MB) + .healthCheckType(type) + .healthCheckHttpEndpoint(HTTP_ENDPOINT) + .healthCheckTimeout(TIMEOUT) + .healthCheckInvocationTimeout(INVOCATION_TIMEOUT) + .healthCheckInterval(interval) + .readinessHealthCheckType(readinessHealthCheckType) + .readinessHealthCheckHttpEndpoint(READINESS_HTTP_ENDPOINT) + .readinessHealthCheckInvocationTimeout(READINESS_INVOCATION_TIMEOUT) + .readinessHealthCheckInterval(READINESS_INTERVAL) + .build(); + } +} diff --git a/multiapps-controller-client/src/test/java/org/cloudfoundry/multiapps/controller/client/lib/domain/HealthCheckInfoTest.java b/multiapps-controller-client/src/test/java/org/cloudfoundry/multiapps/controller/client/lib/domain/HealthCheckInfoTest.java new file mode 100644 index 0000000000..f58f490335 --- /dev/null +++ b/multiapps-controller-client/src/test/java/org/cloudfoundry/multiapps/controller/client/lib/domain/HealthCheckInfoTest.java @@ -0,0 +1,165 @@ +package org.cloudfoundry.multiapps.controller.client.lib.domain; + +import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudProcess; +import org.cloudfoundry.multiapps.controller.client.facade.domain.HealthCheckType; +import org.cloudfoundry.multiapps.controller.client.facade.domain.ImmutableCloudProcess; +import org.cloudfoundry.multiapps.controller.client.facade.domain.ImmutableStaging; +import org.cloudfoundry.multiapps.controller.client.facade.domain.Staging; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class HealthCheckInfoTest { + + private static final String HTTP_TYPE = "http"; + private static final Integer TIMEOUT = 30; + private static final Integer INVOCATION_TIMEOUT = 5; + private static final Integer INTERVAL = 10; + private static final String HTTP_ENDPOINT = "/health"; + + @Test + void testFromStagingPropagatesAllFieldsIncludingInterval() { + Staging staging = ImmutableStaging.builder() + .healthCheckType(HTTP_TYPE) + .healthCheckTimeout(TIMEOUT) + .invocationTimeout(INVOCATION_TIMEOUT) + .healthCheckInterval(INTERVAL) + .healthCheckHttpEndpoint(HTTP_ENDPOINT) + .build(); + + HealthCheckInfo info = HealthCheckInfo.fromStaging(staging); + + assertEquals(HTTP_TYPE, info.getType()); + assertEquals(TIMEOUT, info.getTimeout()); + assertEquals(INVOCATION_TIMEOUT, info.getInvocationTimeout()); + assertEquals(INTERVAL, info.getInterval()); + assertEquals(HTTP_ENDPOINT, info.getHttpEndpoint()); + } + + @Test + void testFromStagingDefaultsTypeToPortWhenNullAndCarriesNullInterval() { + Staging staging = ImmutableStaging.builder() + .build(); + + HealthCheckInfo info = HealthCheckInfo.fromStaging(staging); + + assertEquals("port", info.getType()); + assertNull(info.getTimeout()); + assertNull(info.getInvocationTimeout()); + assertNull(info.getInterval()); + assertNull(info.getHttpEndpoint()); + } + + @Test + void testFromProcessPropagatesAllFieldsIncludingInterval() { + CloudProcess process = ImmutableCloudProcess.builder() + .command("cmd") + .diskInMb(512) + .instances(1) + .memoryInMb(1024) + .healthCheckType(HealthCheckType.HTTP) + .healthCheckHttpEndpoint(HTTP_ENDPOINT) + .healthCheckTimeout(TIMEOUT) + .healthCheckInvocationTimeout(INVOCATION_TIMEOUT) + .healthCheckInterval(INTERVAL) + .build(); + + HealthCheckInfo info = HealthCheckInfo.fromProcess(process); + + assertEquals(HealthCheckType.HTTP.toString(), info.getType()); + assertEquals(TIMEOUT, info.getTimeout()); + assertEquals(INVOCATION_TIMEOUT, info.getInvocationTimeout()); + assertEquals(INTERVAL, info.getInterval()); + assertEquals(HTTP_ENDPOINT, info.getHttpEndpoint()); + } + + @Test + void testFromProcessWithNullIntervalCarriesNull() { + CloudProcess process = ImmutableCloudProcess.builder() + .command("cmd") + .diskInMb(512) + .instances(1) + .memoryInMb(1024) + .healthCheckType(HealthCheckType.PORT) + .build(); + + HealthCheckInfo info = HealthCheckInfo.fromProcess(process); + + assertEquals(HealthCheckType.PORT.toString(), info.getType()); + assertNull(info.getInterval()); + } + + @Test + void testEqualsReturnsTrueForIdenticalContent() { + Staging staging = ImmutableStaging.builder() + .healthCheckType(HTTP_TYPE) + .healthCheckTimeout(TIMEOUT) + .invocationTimeout(INVOCATION_TIMEOUT) + .healthCheckInterval(INTERVAL) + .healthCheckHttpEndpoint(HTTP_ENDPOINT) + .build(); + + HealthCheckInfo a = HealthCheckInfo.fromStaging(staging); + HealthCheckInfo b = HealthCheckInfo.fromStaging(staging); + + assertEquals(a, b); + } + + @Test + void testEqualsReturnsFalseWhenIntervalDiffers() { + Staging stagingWith10 = ImmutableStaging.builder() + .healthCheckType(HTTP_TYPE) + .healthCheckTimeout(TIMEOUT) + .invocationTimeout(INVOCATION_TIMEOUT) + .healthCheckInterval(10) + .healthCheckHttpEndpoint(HTTP_ENDPOINT) + .build(); + Staging stagingWith20 = ImmutableStaging.builder() + .healthCheckType(HTTP_TYPE) + .healthCheckTimeout(TIMEOUT) + .invocationTimeout(INVOCATION_TIMEOUT) + .healthCheckInterval(20) + .healthCheckHttpEndpoint(HTTP_ENDPOINT) + .build(); + + HealthCheckInfo a = HealthCheckInfo.fromStaging(stagingWith10); + HealthCheckInfo b = HealthCheckInfo.fromStaging(stagingWith20); + + assertNotEquals(a, b); + } + + @Test + void testEqualsReturnsFalseWhenOneIntervalIsNull() { + Staging stagingWithInterval = ImmutableStaging.builder() + .healthCheckType(HTTP_TYPE) + .healthCheckInterval(INTERVAL) + .build(); + Staging stagingWithoutInterval = ImmutableStaging.builder() + .healthCheckType(HTTP_TYPE) + .build(); + + HealthCheckInfo a = HealthCheckInfo.fromStaging(stagingWithInterval); + HealthCheckInfo b = HealthCheckInfo.fromStaging(stagingWithoutInterval); + + assertNotEquals(a, b); + } + + @Test + void testEqualsReturnsFalseForNonHealthCheckInfo() { + HealthCheckInfo info = HealthCheckInfo.fromStaging(ImmutableStaging.builder() + .build()); + + assertNotEquals(info, "not-a-health-check-info"); + } + + @Test + void testEqualsReturnsTrueForSelf() { + HealthCheckInfo info = HealthCheckInfo.fromStaging(ImmutableStaging.builder() + .healthCheckInterval(INTERVAL) + .build()); + + assertEquals(info, info); + } +} 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 1e84c0acd4..6f63f55c24 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 @@ -63,6 +63,7 @@ public class SupportedParameters { public static final String HEALTH_CHECK_TIMEOUT = "health-check-timeout"; public static final String HEALTH_CHECK_TYPE = "health-check-type"; public static final String HEALTH_CHECK_HTTP_ENDPOINT = "health-check-http-endpoint"; + public static final String HEALTH_CHECK_INTERVAL = "health-check-interval"; public static final String READINESS_HEALTH_CHECK_TYPE = "readiness-health-check-type"; public static final String READINESS_HEALTH_CHECK_HTTP_ENDPOINT = "readiness-health-check-http-endpoint"; public static final String READINESS_HEALTH_CHECK_INVOCATION_TIMEOUT = "readiness-health-check-invocation-timeout"; @@ -190,6 +191,7 @@ public class SupportedParameters { 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, + HEALTH_CHECK_INTERVAL, 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, 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 14d6021864..4d3cc9ca51 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 @@ -37,6 +37,8 @@ public Staging parse(List> parametersList) { Integer healthCheckInvocationTimeout = (Integer) PropertiesUtil.getPropertyValue(parametersList, SupportedParameters.HEALTH_CHECK_INVOCATION_TIMEOUT, null); + Integer healthCheckInterval = (Integer) PropertiesUtil.getPropertyValue(parametersList, + SupportedParameters.HEALTH_CHECK_INTERVAL, null); String healthCheckType = (String) PropertiesUtil.getPropertyValue(parametersList, SupportedParameters.HEALTH_CHECK_TYPE, null); String healthCheckHttpEndpoint = (String) PropertiesUtil.getPropertyValue(parametersList, SupportedParameters.HEALTH_CHECK_HTTP_ENDPOINT, @@ -69,6 +71,7 @@ public Staging parse(List> parametersList) { .invocationTimeout(healthCheckInvocationTimeout) .healthCheckType(healthCheckType) .healthCheckHttpEndpoint(healthCheckHttpEndpoint) + .healthCheckInterval(healthCheckInterval) .readinessHealthCheckType(readinessHealthCheckType) .readinessHealthCheckHttpEndpoint(readinessHealthCheckHttpEndpoint) .readinessHealthCheckInvocationTimeout(readinessHealthCheckInvocationTimeout) 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 index 98677fc307..b2a9edf5da 100644 --- 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 @@ -21,6 +21,7 @@ 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.HEALTH_CHECK_INTERVAL; 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; @@ -138,6 +139,24 @@ void testValidateWithAllParametersMissing() { assertNull(staging.getDockerInfo()); } + @Test + void testHealthCheckIntervalIsParsedWhenPresent() { + parametersList.add(mapOf(HEALTH_CHECK_INTERVAL, 15)); + + Staging staging = parser.parse(parametersList); + + assertNotNull(staging); + assertEquals(Integer.valueOf(15), staging.getHealthCheckInterval()); + } + + @Test + void testHealthCheckIntervalIsNullWhenAbsent() { + Staging staging = parser.parse(parametersList); + + assertNotNull(staging); + assertNull(staging.getHealthCheckInterval()); + } + private static Map mapOf(String key, Object value) { return Collections.singletonMap(key, value); }