use of com.spotify.helios.common.descriptors.HealthCheck in project helios by spotify.
the class JobValidator method validateJobHealthCheck.
/**
* Validate the Job's health check.
*
* @param job The Job to check.
*
* @return A set of error Strings
*/
private Set<String> validateJobHealthCheck(final Job job) {
final HealthCheck healthCheck = job.getHealthCheck();
if (healthCheck == null) {
return emptySet();
}
final Set<String> errors = Sets.newHashSet();
if (healthCheck instanceof ExecHealthCheck) {
final List<String> command = ((ExecHealthCheck) healthCheck).getCommand();
if (command == null || command.isEmpty()) {
errors.add("A command must be defined for `docker exec`-based health checks.");
}
} else if (healthCheck instanceof HttpHealthCheck || healthCheck instanceof TcpHealthCheck) {
final String port;
if (healthCheck instanceof HttpHealthCheck) {
port = ((HttpHealthCheck) healthCheck).getPort();
} else {
port = ((TcpHealthCheck) healthCheck).getPort();
}
final Map<String, PortMapping> ports = job.getPorts();
if (isNullOrEmpty(port)) {
errors.add("A port must be defined for HTTP and TCP health checks.");
} else if (!ports.containsKey(port)) {
errors.add(format("Health check port '%s' not defined in the job. Known ports are '%s'", port, Joiner.on(", ").join(ports.keySet())));
}
}
return errors;
}
use of com.spotify.helios.common.descriptors.HealthCheck in project helios by spotify.
the class HealthCheckTest method testTcp.
@Test
public void testTcp() throws Exception {
startDefaultMaster();
final HeliosClient client = defaultClient();
startDefaultAgent(testHost(), "--service-registry=" + registryAddress);
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
final HealthCheck healthCheck = TcpHealthCheck.of("health");
final Job job = pokeJob(healthCheck);
assertContainerRegistersAfterPoke(client, job);
}
use of com.spotify.helios.common.descriptors.HealthCheck in project helios by spotify.
the class HealthCheckTest method testHttp.
@Test
public void testHttp() throws Exception {
startDefaultMaster();
final HeliosClient client = defaultClient();
startDefaultAgent(testHost(), "--service-registry=" + registryAddress);
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
final HealthCheck healthCheck = HttpHealthCheck.of("http", "/");
// start a container that listens on a poke port, and once poked runs a web server
final Job job = Job.newBuilder().setName(testJobName).setVersion(testJobVersion).setImage(NGINX).setCommand(asList("sh", "-c", "nc -l -p 4711 && nginx -g 'daemon off;'")).addPort("poke", PortMapping.of(4711)).addPort("http", PortMapping.of(80)).addRegistration(ServiceEndpoint.of("foo_service", "foo_proto"), ServicePorts.of("http")).setHealthCheck(healthCheck).build();
assertContainerRegistersAfterPoke(client, job);
}
use of com.spotify.helios.common.descriptors.HealthCheck in project helios by spotify.
the class HealthCheckTest method testContainerDiesDuringHealthcheck.
@Test
public void testContainerDiesDuringHealthcheck() throws Exception {
startDefaultMaster();
final HeliosClient client = defaultClient();
startDefaultAgent(testHost(), "--service-registry=" + registryAddress);
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
final HealthCheck healthCheck = TcpHealthCheck.of("health");
final Job job = pokeJob(healthCheck);
final JobId jobId = createJob(job);
deployJob(jobId, testHost());
awaitTaskState(jobId, testHost(), HEALTHCHECKING);
// kill the underlying container
final JobStatus jobStatus = getOrNull(client.jobStatus(jobId));
final TaskStatus taskStatus = jobStatus.getTaskStatuses().get(testHost());
getNewDockerClient().killContainer(taskStatus.getContainerId());
// ensure the job is marked as failed
final int timeout = WAIT_TIMEOUT_SECONDS;
Polling.await(timeout, SECONDS, new Callable<Object>() {
@Override
public Object call() throws Exception {
final TaskStatusEvents jobHistory = getOrNull(client.jobHistory(jobId));
for (final TaskStatusEvent event : jobHistory.getEvents()) {
if (event.getStatus().getState() == FAILED) {
return true;
}
}
return null;
}
});
// wait for the job to come back up and start healthchecking again
awaitTaskState(jobId, testHost(), HEALTHCHECKING);
pokeAndVerifyRegistration(client, jobId, timeout);
}
use of com.spotify.helios.common.descriptors.HealthCheck in project helios by spotify.
the class HealthCheckTest method testExec.
@Test
public void testExec() throws Exception {
// CircleCI uses lxc which doesn't support exec - https://circleci.com/docs/docker/#docker-exec
assumeFalse(isCircleCi());
final DockerClient dockerClient = getNewDockerClient();
assumeThat(dockerClient.version(), is(execCompatibleDockerVersion()));
startDefaultMaster();
final HeliosClient client = defaultClient();
startDefaultAgent(testHost(), "--service-registry=" + registryAddress);
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
// check if "file" exists in the root directory as a healthcheck
final HealthCheck healthCheck = ExecHealthCheck.of("test", "-e", "file");
// start a container that listens on the service port
final String portName = "service";
final String serviceName = "foo_service";
final String serviceProtocol = "foo_proto";
final Job job = Job.newBuilder().setName(testJobName).setVersion(testJobVersion).setImage(BUSYBOX).setCommand(asList("sh", "-c", "nc -l -p 4711")).addPort(portName, PortMapping.of(4711)).addRegistration(ServiceEndpoint.of(serviceName, serviceProtocol), ServicePorts.of(portName)).setHealthCheck(healthCheck).build();
final JobId jobId = createJob(job);
deployJob(jobId, testHost());
final TaskStatus jobState = awaitTaskState(jobId, testHost(), HEALTHCHECKING);
// wait a few seconds to see if the service gets registered
Thread.sleep(3000);
// shouldn't be registered, since we haven't created the file yet
verify(registrar, never()).register(any(ServiceRegistration.class));
// create the file in the container to make the healthcheck succeed
final String[] makeFileCmd = new String[] { "touch", "file" };
final ExecCreation execCreation = dockerClient.execCreate(jobState.getContainerId(), makeFileCmd);
final String execId = execCreation.id();
dockerClient.execStart(execId);
awaitTaskState(jobId, testHost(), RUNNING);
dockerClient.close();
verify(registrar, timeout((int) SECONDS.toMillis(LONG_WAIT_SECONDS))).register(registrationCaptor.capture());
final ServiceRegistration serviceRegistration = registrationCaptor.getValue();
assertEquals(1, serviceRegistration.getEndpoints().size());
final Endpoint registeredEndpoint = serviceRegistration.getEndpoints().get(0);
assertEquals("wrong service", serviceName, registeredEndpoint.getName());
assertEquals("wrong protocol", serviceProtocol, registeredEndpoint.getProtocol());
}
Aggregations