use of com.spotify.helios.common.descriptors.Job in project helios by spotify.
the class DeploymentGroupTest method testRollingUpdateWithToken.
@Test
public void testRollingUpdateWithToken() throws Exception {
final String host = testHost();
startDefaultAgent(host, "--labels", TEST_LABEL);
// Wait for agent to come up
final HeliosClient client = defaultClient();
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
// Manually deploy a job with a token on the host (i.e. a job not part of the deployment group)
final Job job = Job.newBuilder().setName(testJobName).setVersion(testJobVersion).setImage(BUSYBOX).setCommand(IDLE_COMMAND).setToken(TOKEN).build();
final JobId jobId = createJob(job);
// Create a deployment-group and trigger a migration rolling-update
cli("create-deployment-group", "--json", TEST_GROUP, TEST_LABEL);
cli("rolling-update", "--async", "--token", TOKEN, testJobNameAndVersion, TEST_GROUP);
// rolling-update should succeed & job should be running
awaitDeploymentGroupStatus(defaultClient(), TEST_GROUP, DeploymentGroupStatus.State.DONE);
awaitTaskState(jobId, host, TaskStatus.State.RUNNING);
// Check that we cannot manually undeploy the job with a token
final String output = cli("undeploy", jobId.toString(), host);
assertThat(output, containsString("FORBIDDEN"));
awaitDeploymentGroupStatus(defaultClient(), TEST_GROUP, DeploymentGroupStatus.State.DONE);
awaitTaskState(jobId, host, TaskStatus.State.RUNNING);
}
use of com.spotify.helios.common.descriptors.Job in project helios by spotify.
the class DeploymentGroupTest method testRollingUpdateMigrateWithToken.
@Test
public void testRollingUpdateMigrateWithToken() throws Exception {
final String host = testHost();
startDefaultAgent(host, "--labels", TEST_LABEL);
// Wait for agent to come up
final HeliosClient client = defaultClient();
awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
// Manually deploy a job with a token on the host (i.e. a job not part of the deployment group)
final Job job = Job.newBuilder().setName(testJobName).setVersion(testJobVersion).setImage(BUSYBOX).setCommand(IDLE_COMMAND).setToken(TOKEN).build();
final JobId jobId = createJob(job);
deployJob(jobId, host, TOKEN);
awaitTaskState(jobId, host, TaskStatus.State.RUNNING);
// Create a deployment-group and trigger a migration rolling-update
cli("create-deployment-group", "--json", TEST_GROUP, TEST_LABEL);
cli("rolling-update", "--async", "--migrate", "--token", TOKEN, testJobNameAndVersion, TEST_GROUP);
// Check that the deployment's deployment-group name eventually changes to TEST_GROUP
// (should be null or empty before)
final String jobDeploymentGroup = Polling.await(LONG_WAIT_SECONDS, SECONDS, new Callable<String>() {
@Override
public String call() throws Exception {
final Deployment deployment = defaultClient().hostStatus(host).get().getJobs().get(jobId);
if (deployment != null && !isNullOrEmpty(deployment.getDeploymentGroupName())) {
return deployment.getDeploymentGroupName();
} else {
return null;
}
}
});
assertEquals(TEST_GROUP, jobDeploymentGroup);
// rolling-update should succeed & job should be running
awaitDeploymentGroupStatus(defaultClient(), TEST_GROUP, DeploymentGroupStatus.State.DONE);
awaitTaskState(jobId, host, TaskStatus.State.RUNNING);
}
use of com.spotify.helios.common.descriptors.Job in project helios by spotify.
the class DeploymentGroupTest method testUpdateFailedManualDeploymentGroupHosts.
// A test that ensures deployment groups that failed during a manual rolling update will not
// perform a new rolling update if the hosts change.
@Test
public void testUpdateFailedManualDeploymentGroupHosts() throws Exception {
final ZooKeeperClient client = spy(this.client);
final ZooKeeperMasterModel masterModel = spy(newMasterModel(client));
// Return a job so we can add a real deployment group.
final Job job = Job.newBuilder().setCommand(ImmutableList.of("COMMAND")).setImage("IMAGE").setName("JOB_NAME").setVersion("VERSION").build();
doReturn(job).when(masterModel).getJob(job.getId());
// Add a real deployment group.
final DeploymentGroup dg = DeploymentGroup.newBuilder().setName(GROUP_NAME).setHostSelectors(ImmutableList.of(HostSelector.parse("role=melmac"))).setJobId(job.getId()).setRolloutOptions(RolloutOptions.newBuilder().build()).setRollingUpdateReason(MANUAL).build();
masterModel.addDeploymentGroup(dg);
// Give the deployment group a host.
client.setData(Paths.statusDeploymentGroupHosts(dg.getName()), Json.asBytes(ImmutableList.of("host1")));
// And a status...
client.setData(Paths.statusDeploymentGroup(dg.getName()), DeploymentGroupStatus.newBuilder().setState(FAILED).build().toJsonBytes());
// Pretend our new host is UP.
final HostStatus statusUp = mock(HostStatus.class);
doReturn(HostStatus.Status.UP).when(statusUp).getStatus();
doReturn(statusUp).when(masterModel).getHostStatus("host2");
// Switch out our host!
masterModel.updateDeploymentGroupHosts(dg.getName(), ImmutableList.of("host2"));
// Ensure we do not set the DG status to HOSTS_CHANGED.
// We don't want to trigger a rolling update because the last one was manual, and failed.
final ZooKeeperOperation setDeploymentGroupHostChanged = set(Paths.configDeploymentGroup(dg.getName()), dg.toBuilder().setRollingUpdateReason(HOSTS_CHANGED).build());
verify(client, times(2)).transaction(opCaptor.capture());
assertThat(opCaptor.getValue(), not(hasItem(setDeploymentGroupHostChanged)));
}
use of com.spotify.helios.common.descriptors.Job in project helios by spotify.
the class DeploymentGroupTest method testUpdateFailedHostsChangedDeploymentGroupHosts.
// A test that ensures deployment groups that failed during a rolling update triggered by
// changing hosts will perform a new rolling update if the hosts change again.
@Test
public void testUpdateFailedHostsChangedDeploymentGroupHosts() throws Exception {
final ZooKeeperClient client = spy(this.client);
final ZooKeeperMasterModel masterModel = spy(newMasterModel(client));
// Return a job so we can add a real deployment group.
final Job job = Job.newBuilder().setCommand(ImmutableList.of("COMMAND")).setImage("IMAGE").setName("JOB_NAME").setVersion("VERSION").build();
doReturn(job).when(masterModel).getJob(job.getId());
// Add a real deployment group.
final DeploymentGroup dg = DeploymentGroup.newBuilder().setName(GROUP_NAME).setHostSelectors(ImmutableList.of(HostSelector.parse("role=melmac"))).setJobId(job.getId()).setRolloutOptions(RolloutOptions.newBuilder().build()).setRollingUpdateReason(HOSTS_CHANGED).build();
masterModel.addDeploymentGroup(dg);
// Give the deployment group a host.
client.setData(Paths.statusDeploymentGroupHosts(dg.getName()), Json.asBytes(ImmutableList.of("host1")));
// And a status...
client.setData(Paths.statusDeploymentGroup(dg.getName()), DeploymentGroupStatus.newBuilder().setState(FAILED).build().toJsonBytes());
// Pretend our new host is UP.
final HostStatus statusUp = mock(HostStatus.class);
doReturn(HostStatus.Status.UP).when(statusUp).getStatus();
doReturn(statusUp).when(masterModel).getHostStatus("host2");
// Switch out our host!
masterModel.updateDeploymentGroupHosts(dg.getName(), ImmutableList.of("host2"));
// Ensure we write the same DG status again.
// This is a no-op, but it means we triggered a rolling update.
final ZooKeeperOperation setDeploymentGroup = set(Paths.configDeploymentGroup(dg.getName()), dg);
verify(client, times(2)).transaction(opCaptor.capture());
assertThat(opCaptor.getValue(), hasItem(setDeploymentGroup));
}
use of com.spotify.helios.common.descriptors.Job in project helios by spotify.
the class CliJobCreationTest method testMergeFileAndCliArgs.
@Test
public void testMergeFileAndCliArgs() throws Exception {
final Map<String, PortMapping> ports = ImmutableMap.of("foo", PortMapping.of(4711), "bar", PortMapping.of(5000, externalPort));
final Map<ServiceEndpoint, ServicePorts> registration = ImmutableMap.of(ServiceEndpoint.of("foo-service", "tcp"), ServicePorts.of("foo"), ServiceEndpoint.of("bar-service", "http"), ServicePorts.of("bar"));
final String registrationDomain = "my-domain";
final Map<String, String> env = ImmutableMap.of("BAD", "f00d");
final Map<String, String> volumes = Maps.newHashMap();
volumes.put("/etc/spotify/secret-keys.yaml:ro", "/etc/spotify/secret-keys.yaml");
// Create a new job, serialize it to JSON
final Job.Builder builder = Job.newBuilder().setCommand(Lists.newArrayList("server", "foo-service.yaml")).setEnv(env).setPorts(ports).setRegistration(registration).setRegistrationDomain(registrationDomain).setVolumes(volumes).setCreatingUser(TEST_USER).setToken("foo-token").setNetworkMode("host").setSecurityOpt(ImmutableList.of("label:user:dxia", "apparmor:foo"));
final Job job = builder.build();
final String jobConfigJsonString = job.toJsonString();
// Create temporary job config file
final File file = temporaryFolder.newFile();
final String absolutePath = file.getAbsolutePath();
// Write JSON config to temp file
try (final FileOutputStream outFile = new FileOutputStream(file)) {
outFile.write(Charsets.UTF_8.encode(jobConfigJsonString).array());
// Create job and specify the temp file.
cli("create", "--file", absolutePath, testJobNameAndVersion, BUSYBOX);
// Inspect the job.
final String actualJobConfigJson = cli("inspect", testJobNameAndVersion, "--json");
// Compare to make sure the created job has the expected configuration,
// i.e. the configuration resulting from a merge of the JSON file and CLI args.
final Job actualJob = Json.read(actualJobConfigJson, Job.class);
final Job.Builder actualJobBuilder = actualJob.toBuilder();
builder.setName(testJobName).setVersion(testJobVersion).setImage(BUSYBOX);
assertJobEquals(builder.build(), actualJobBuilder.build());
}
}
Aggregations