final AgentMain agent1 = startDefaultAgent(testHost(), "--port-range=" +
portRange.lowerEndpoint() + ":" +
portRange.upperEndpoint());
try (final DockerClient dockerClient = getNewDockerClient()) {
final HeliosClient client = defaultClient();
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
final Map<String, PortMapping> ports1 =
ImmutableMap.of("foo", PortMapping.of(4711),
"bar", PortMapping.of(4712, externalPort1));
final ImmutableMap<String, PortMapping> expectedMapping1 =
ImmutableMap.of("foo", PortMapping.of(4711, portRange.lowerEndpoint()),
"bar", PortMapping.of(4712, externalPort1));
final Map<String, PortMapping> ports2 =
ImmutableMap.of("foo", PortMapping.of(4711),
"bar", PortMapping.of(4712, externalPort2));
final ImmutableMap<String, PortMapping> expectedMapping2 =
ImmutableMap.of("foo", PortMapping.of(4711, portRange.lowerEndpoint() + 1),
"bar", PortMapping.of(4712, externalPort2));
final JobId jobId1 = createJob(testJobName + 1, testJobVersion, BUSYBOX, IDLE_COMMAND,
EMPTY_ENV, ports1);
assertNotNull(jobId1);
deployJob(jobId1, testHost());
final TaskStatus firstTaskStatus1 = awaitJobState(client, testHost(), jobId1, RUNNING,
LONG_WAIT_SECONDS, SECONDS);
final JobId jobId2 = createJob(testJobName + 2, testJobVersion, BUSYBOX, IDLE_COMMAND,
EMPTY_ENV, ports2);
assertNotNull(jobId2);
deployJob(jobId2, testHost());
final TaskStatus firstTaskStatus2 = awaitJobState(client, testHost(), jobId2, RUNNING,
LONG_WAIT_SECONDS, SECONDS);
assertEquals(expectedMapping1, firstTaskStatus1.getPorts());
assertEquals(expectedMapping2, firstTaskStatus2.getPorts());
// TODO (dano): the supervisor should report the allocated ports at all times
// Verify that port allocation is kept across container restarts
dockerClient.killContainer(firstTaskStatus1.getContainerId());
final TaskStatus restartedTaskStatus1 = Polling.await(
LONG_WAIT_SECONDS, SECONDS, new Callable<TaskStatus>() {
@Override
public TaskStatus call() throws Exception {
final HostStatus hostStatus = client.hostStatus(testHost()).get();
final TaskStatus taskStatus = hostStatus.getStatuses().get(jobId1);
return (taskStatus != null && taskStatus.getState() == RUNNING &&
!Objects.equals(taskStatus.getContainerId(), firstTaskStatus1.getContainerId()))
? taskStatus : null;
}
});
assertEquals(expectedMapping1, restartedTaskStatus1.getPorts());
// Verify that port allocation is kept across agent restarts
agent1.stopAsync().awaitTerminated();
dockerClient.killContainer(firstTaskStatus2.getContainerId());
startDefaultAgent(testHost());
final TaskStatus restartedTaskStatus2 = Polling.await(
LONG_WAIT_SECONDS, SECONDS, new Callable<TaskStatus>() {
@Override
public TaskStatus call() throws Exception {
final HostStatus hostStatus = client.hostStatus(testHost()).get();
final TaskStatus taskStatus = hostStatus.getStatuses().get(jobId2);
return (taskStatus != null && taskStatus.getState() == RUNNING &&
!Objects.equals(taskStatus.getContainerId(), firstTaskStatus2.getContainerId()))
? taskStatus : null;
}