Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -49,6 +51,7 @@ public CloudProcess derive() {
.healthCheckHttpEndpoint(healthCheckHttpEndpoint)
.healthCheckTimeout(healthCheckTimeout)
.healthCheckInvocationTimeout(healthCheckInvocationTimeout)
.healthCheckInterval(healthCheckInterval)
.readinessHealthCheckType(readinessHealthCheckType.getType()
.getValue())
.readinessHealthCheckHttpEndpoint(readinessHealthCheckHttpEndpoint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public abstract class CloudProcess extends CloudEntity implements Derivable<Clou
@Nullable
public abstract Integer getReadinessHealthCheckInterval();

@Nullable
public abstract Integer getHealthCheckInterval();

@Nullable
public abstract Integer getReadinessHealthCheckInvocationTimeout();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public interface Staging {
@Nullable
Integer getReadinessHealthCheckInterval();

/**
* @return liveness health check interval in seconds, or null to use the CF platform default
*/
@Nullable
Integer getHealthCheckInterval();

/**
* @return readiness health check timeout
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ private void updateApplicationProcess(UUID applicationGuid, Staging staging) {
UpdateProcessRequest.Builder updateProcessRequestBuilder = UpdateProcessRequest.builder()
.processId(getApplicationProcessResponse.getId())
.command(staging.getCommand());
if (staging.getHealthCheckType() != null) {
if (staging.getHealthCheckType() != null || staging.getHealthCheckInterval() != null) {
updateProcessRequestBuilder.healthCheck(buildHealthCheck(staging));
}
if (staging.getReadinessHealthCheckType() != null) {
Expand Down Expand Up @@ -438,15 +438,17 @@ private GetApplicationProcessResponse getApplicationProcessResource(UUID applica
}

private HealthCheck buildHealthCheck(Staging staging) {
HealthCheckType healthCheckType = HealthCheckType.from(staging.getHealthCheckType());
return HealthCheck.builder()
.type(healthCheckType)
.data(Data.builder()
.endpoint(staging.getHealthCheckHttpEndpoint())
.timeout(staging.getHealthCheckTimeout())
.invocationTimeout(staging.getInvocationTimeout())
.build())
.build();
HealthCheck.Builder healthCheckBuilder = HealthCheck.builder()
.data(Data.builder()
.endpoint(staging.getHealthCheckHttpEndpoint())
.timeout(staging.getHealthCheckTimeout())
.invocationTimeout(staging.getInvocationTimeout())
.interval(staging.getHealthCheckInterval())
.build());
if (staging.getHealthCheckType() != null) {
healthCheckBuilder.type(HealthCheckType.from(staging.getHealthCheckType()));
}
return healthCheckBuilder.build();
}

private void addRoutes(Set<CloudRoute> routes, UUID applicationGuid) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ public class HealthCheckInfo {
private final Integer timeout;
private final Integer invocationTimeout;
private final String httpEndpoint;
private final Integer interval;

private HealthCheckInfo(String type, Integer timeout, Integer invocationTimeout, String httpEndpoint) {
private HealthCheckInfo(String type, Integer timeout, Integer invocationTimeout, String httpEndpoint, Integer interval) {
this.type = type;
this.timeout = timeout;
this.invocationTimeout = invocationTimeout;
this.httpEndpoint = httpEndpoint;
this.interval = interval;
}

public static HealthCheckInfo fromStaging(Staging staging) {
Expand All @@ -27,15 +29,17 @@ public static HealthCheckInfo fromStaging(Staging staging) {
var timeout = staging.getHealthCheckTimeout();
var invocationTimeout = staging.getInvocationTimeout();
var httpEndpoint = staging.getHealthCheckHttpEndpoint();
return new HealthCheckInfo(type, timeout, invocationTimeout, httpEndpoint);
var interval = staging.getHealthCheckInterval();
return new HealthCheckInfo(type, timeout, invocationTimeout, httpEndpoint, interval);
}

public static HealthCheckInfo fromProcess(CloudProcess process) {
var type = process.getHealthCheckType();
var timeout = process.getHealthCheckTimeout();
var invocationTimeout = process.getHealthCheckInvocationTimeout();
var httpEndpoint = process.getHealthCheckHttpEndpoint();
return new HealthCheckInfo(type.toString(), timeout, invocationTimeout, httpEndpoint);
var interval = process.getHealthCheckInterval();
return new HealthCheckInfo(type.toString(), timeout, invocationTimeout, httpEndpoint, interval);
}

public String getType() {
Expand All @@ -54,6 +58,10 @@ public String getHttpEndpoint() {
return httpEndpoint;
}

public Integer getInterval() {
return interval;
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
Expand All @@ -66,6 +74,7 @@ public boolean equals(Object obj) {
return Objects.equals(getType(), other.getType())
&& Objects.equals(getTimeout(), other.getTimeout())
&& Objects.equals(getInvocationTimeout(), other.getInvocationTimeout())
&& Objects.equals(getHttpEndpoint(), other.getHttpEndpoint());
&& Objects.equals(getHttpEndpoint(), other.getHttpEndpoint())
&& Objects.equals(getInterval(), other.getInterval());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.cloudfoundry.multiapps.controller.client.facade.adapters;

import org.cloudfoundry.client.v3.Metadata;
import org.cloudfoundry.client.v3.Relationship;
import org.cloudfoundry.client.v3.ToOneRelationship;
import org.cloudfoundry.client.v3.processes.Data;
import org.cloudfoundry.client.v3.processes.HealthCheck;
import org.cloudfoundry.client.v3.processes.HealthCheckType;
import org.cloudfoundry.client.v3.processes.ProcessRelationships;
import org.cloudfoundry.client.v3.processes.ProcessResource;
import org.cloudfoundry.client.v3.processes.ReadinessHealthCheck;
import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType;
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudProcess;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

class RawCloudProcessTest {

private static final String PROCESS_ID = "0d6b6f94-2e9b-4f62-9c3a-bdf9a7e4d1d0";
private static final String CREATED_AT = "2024-01-26T10:00:00Z";
private static final String COMMAND = "start";
private static final Integer INSTANCES = 2;
private static final Integer MEMORY_IN_MB = 256;
private static final Integer DISK_IN_MB = 1024;
private static final Integer HEALTH_CHECK_TIMEOUT = 60;
private static final Integer HEALTH_CHECK_INVOCATION_TIMEOUT = 5;
private static final String HEALTH_CHECK_HTTP_ENDPOINT = "/health";
private static final Integer HEALTH_CHECK_INTERVAL = 15;

@Test
void testDeriveMapsHealthCheckIntervalFromData() {
RawCloudProcess raw = buildRawProcess(buildHealthCheck(HEALTH_CHECK_INTERVAL), buildReadinessHealthCheck());

CloudProcess derived = raw.derive();

assertEquals(HEALTH_CHECK_INTERVAL, derived.getHealthCheckInterval());
assertEquals(HEALTH_CHECK_TIMEOUT, derived.getHealthCheckTimeout());
assertEquals(HEALTH_CHECK_INVOCATION_TIMEOUT, derived.getHealthCheckInvocationTimeout());
assertEquals(HEALTH_CHECK_HTTP_ENDPOINT, derived.getHealthCheckHttpEndpoint());
}

@Test
void testDeriveLeavesHealthCheckIntervalNullWhenAbsentFromData() {
HealthCheck healthCheck = HealthCheck.builder()
.type(HealthCheckType.HTTP)
.data(Data.builder()
.timeout(HEALTH_CHECK_TIMEOUT)
.invocationTimeout(HEALTH_CHECK_INVOCATION_TIMEOUT)
.endpoint(HEALTH_CHECK_HTTP_ENDPOINT)
.build())
.build();
RawCloudProcess raw = buildRawProcess(healthCheck, buildReadinessHealthCheck());

CloudProcess derived = raw.derive();

assertNull(derived.getHealthCheckInterval());
assertEquals(HEALTH_CHECK_TIMEOUT, derived.getHealthCheckTimeout());
}

@Test
void testDeriveLeavesHealthCheckIntervalNullWhenDataIsNull() {
HealthCheck healthCheck = HealthCheck.builder()
.type(HealthCheckType.PORT)
.build();
RawCloudProcess raw = buildRawProcess(healthCheck, buildReadinessHealthCheck());

CloudProcess derived = raw.derive();

assertNull(derived.getHealthCheckInterval());
assertNull(derived.getHealthCheckTimeout());
assertNull(derived.getHealthCheckInvocationTimeout());
assertNull(derived.getHealthCheckHttpEndpoint());
}

private static HealthCheck buildHealthCheck(Integer interval) {
return HealthCheck.builder()
.type(HealthCheckType.HTTP)
.data(Data.builder()
.timeout(HEALTH_CHECK_TIMEOUT)
.invocationTimeout(HEALTH_CHECK_INVOCATION_TIMEOUT)
.endpoint(HEALTH_CHECK_HTTP_ENDPOINT)
.interval(interval)
.build())
.build();
}

private static ReadinessHealthCheck buildReadinessHealthCheck() {
return ReadinessHealthCheck.builder()
.type(ReadinessHealthCheckType.PROCESS)
.build();
}

private static RawCloudProcess buildRawProcess(HealthCheck healthCheck, ReadinessHealthCheck readinessHealthCheck) {
ProcessResource processResource = ProcessResource.builder()
.id(PROCESS_ID)
.createdAt(CREATED_AT)
.type("web")
.command(COMMAND)
.instances(INSTANCES)
.memoryInMb(MEMORY_IN_MB)
.diskInMb(DISK_IN_MB)
.healthCheck(healthCheck)
.readinessHealthCheck(readinessHealthCheck)
.metadata(Metadata.builder()
.build())
.relationships(ProcessRelationships.builder()
.app(ToOneRelationship.builder()
.data(Relationship.builder()
.id("app-guid")
.build())
.build())
.build())
.build();
return ImmutableRawCloudProcess.of(processResource);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.cloudfoundry.multiapps.controller.client.lib.domain;

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.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

class HealthCheckInfoTest {

@Test
void testEqualHealthCheckInfoObjectsAreEqual() {
ImmutableStaging staging = ImmutableStaging.builder()
.healthCheckType("http")
.healthCheckInterval(15)
.build();
HealthCheckInfo first = HealthCheckInfo.fromStaging(staging);
HealthCheckInfo second = HealthCheckInfo.fromStaging(staging);

assertEquals(first, second);
}

@Test
void testHealthCheckInfoWithDifferentIntervalsAreNotEqual() {
ImmutableStaging stagingWithInterval15 = ImmutableStaging.builder()
.healthCheckType("http")
.healthCheckInterval(15)
.build();
ImmutableStaging stagingWithInterval30 = ImmutableStaging.builder()
.healthCheckType("http")
.healthCheckInterval(30)
.build();

HealthCheckInfo first = HealthCheckInfo.fromStaging(stagingWithInterval15);
HealthCheckInfo second = HealthCheckInfo.fromStaging(stagingWithInterval30);

assertNotEquals(first, second);
}

@Test
void testHealthCheckInfoIntervalNullVsNonNullAreNotEqual() {
ImmutableStaging stagingWithInterval = ImmutableStaging.builder()
.healthCheckType("http")
.healthCheckInterval(15)
.build();
ImmutableStaging stagingWithoutInterval = ImmutableStaging.builder()
.healthCheckType("http")
.build();

HealthCheckInfo withInterval = HealthCheckInfo.fromStaging(stagingWithInterval);
HealthCheckInfo withoutInterval = HealthCheckInfo.fromStaging(stagingWithoutInterval);

assertNotEquals(withInterval, withoutInterval);
}

@Test
void testHealthCheckInfoFromProcessWithInterval() {
ImmutableCloudProcess process = ImmutableCloudProcess.builder()
.command("start")
.diskInMb(256)
.instances(1)
.memoryInMb(512)
.healthCheckType(HealthCheckType.HTTP)
.healthCheckInterval(15)
.build();

HealthCheckInfo fromProcess = HealthCheckInfo.fromProcess(process);

ImmutableStaging staging = ImmutableStaging.builder()
.healthCheckType("http")
.healthCheckInterval(15)
.build();
HealthCheckInfo fromStaging = HealthCheckInfo.fromStaging(staging);

assertEquals(fromProcess, fromStaging);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public final class Messages {
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 INVALID_HEALTH_CHECK_INTERVAL = "Parameter \"health-check-interval\" must be a positive integer greater than 0, but was: {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'.";
Expand Down
Loading
Loading