use of com.netflix.titus.api.loadbalancer.model.LoadBalancerTarget in project titus-control-plane by Netflix.
the class CassandraLoadBalancerStoreTest method testOnlyDeregisteredTargetsAreRemoved.
@Test
public void testOnlyDeregisteredTargetsAreRemoved() throws Exception {
Map<LoadBalancerTarget, LoadBalancerTarget.State> targets = ImmutableMap.of(new LoadBalancerTarget("lb-1", "task1", "1.1.1.1"), LoadBalancerTarget.State.REGISTERED, new LoadBalancerTarget("lb-1", "task2", "2.2.2.2"), LoadBalancerTarget.State.DEREGISTERED, new LoadBalancerTarget("lb-2", "task1", "1.1.1.1"), LoadBalancerTarget.State.DEREGISTERED, new LoadBalancerTarget("lb-2", "task3", "3.3.3.3"), LoadBalancerTarget.State.DEREGISTERED);
loadTestData(new TestData(Collections.emptyMap(), targets));
CassandraLoadBalancerStore store = getInitdStore();
store.removeDeregisteredTargets(targets.keySet()).block(Duration.ofSeconds(10));
List<LoadBalancerTargetState> targets1 = store.getLoadBalancerTargets("lb-1").collectList().block(Duration.ofSeconds(5));
assertThat(targets1).hasSize(1);
assertThat(targets1.get(0).getIpAddress()).isEqualTo("1.1.1.1");
List<LoadBalancerTargetState> targets2 = store.getLoadBalancerTargets("lb-2").collectList().block(Duration.ofSeconds(5));
assertThat(targets2).isEmpty();
}
use of com.netflix.titus.api.loadbalancer.model.LoadBalancerTarget in project titus-control-plane by Netflix.
the class CassandraLoadBalancerStoreTest method generateTestData.
/**
* Returns a map of data to be inserted that can be used for later verification.
*/
private TestData generateTestData(int numJobs, int numLoadBalancersPerJob, int numTasksPerJob) {
Map<JobLoadBalancer, JobLoadBalancer.State> associations = new HashMap<>();
Map<LoadBalancerTarget, LoadBalancerTarget.State> targets = new HashMap<>();
for (int i = 0; i < numJobs; i++) {
String jobId = UUID.randomUUID().toString();
for (int j = 0; j < numLoadBalancersPerJob; j++) {
String loadBalancerId = UUID.randomUUID().toString();
JobLoadBalancer jobLoadBalancer = new JobLoadBalancer(jobId, jobId + "-" + loadBalancerId);
associations.put(jobLoadBalancer, ASSOCIATED);
for (int t = 0; t < numTasksPerJob; t++) {
targets.put(new LoadBalancerTarget(loadBalancerId, "task-" + t, String.format("%s.%s.%s.%s", i, t, t, t)), LoadBalancerTarget.State.REGISTERED);
}
}
}
assertThat(associations.size()).isEqualTo(numJobs * numLoadBalancersPerJob);
assertThat(targets.size()).isEqualTo(numJobs * numLoadBalancersPerJob * numTasksPerJob);
return new TestData(associations, targets);
}
use of com.netflix.titus.api.loadbalancer.model.LoadBalancerTarget in project titus-control-plane by Netflix.
the class DefaultLoadBalancerServiceTest method multipleLoadBalancersPerJob.
@Test
public void multipleLoadBalancersPerJob() {
PublishSubject<JobManagerEvent<?>> taskEvents = PublishSubject.create();
String jobId = UUID.randomUUID().toString();
String firstLoadBalancerId = "lb-" + UUID.randomUUID().toString();
String secondLoadBalancerId = "lb-" + UUID.randomUUID().toString();
int numberOfStartedTasks = 5;
when(client.registerAll(any(), any())).thenReturn(Completable.complete());
when(client.deregisterAll(any(), any())).thenReturn(Completable.complete());
when(v3JobOperations.observeJobs()).thenReturn(taskEvents);
LoadBalancerTests.applyValidGetJobMock(v3JobOperations, jobId);
List<Task> tasks = LoadBalancerTests.buildTasksStarted(numberOfStartedTasks, jobId);
Collection<LoadBalancerTargetState> firstExpectedTargets = tasks.stream().map(task -> new LoadBalancerTargetState(new LoadBalancerTarget(firstLoadBalancerId, task.getId(), task.getTaskContext().get(TaskAttributes.TASK_ATTRIBUTES_CONTAINER_IP)), REGISTERED)).collect(Collectors.toList());
Collection<LoadBalancerTargetState> secondExpectedTargets = tasks.stream().map(task -> new LoadBalancerTargetState(new LoadBalancerTarget(secondLoadBalancerId, task.getId(), task.getTaskContext().get(TaskAttributes.TASK_ATTRIBUTES_CONTAINER_IP)), REGISTERED)).collect(Collectors.toList());
when(v3JobOperations.getTasks(jobId)).thenReturn(CollectionsExt.merge(tasks, LoadBalancerTests.buildTasks(2, jobId, TaskState.StartInitiated), LoadBalancerTests.buildTasks(2, jobId, TaskState.KillInitiated), LoadBalancerTests.buildTasks(3, jobId, TaskState.Finished), LoadBalancerTests.buildTasks(1, jobId, TaskState.Disconnected)));
LoadBalancerConfiguration configuration = LoadBalancerTests.mockConfiguration(MIN_TIME_IN_QUEUE_MS);
DefaultLoadBalancerService service = new DefaultLoadBalancerService(runtime, configuration, client, loadBalancerStore, loadBalancerJobOperations, reconciler, validator, testScheduler);
AssertableSubscriber<Batch<TargetStateBatchable, String>> testSubscriber = service.events().test();
// associate two load balancers to the same job
assertTrue(service.addLoadBalancer(jobId, firstLoadBalancerId).await(100, TimeUnit.MILLISECONDS));
assertTrue(service.addLoadBalancer(jobId, secondLoadBalancerId).await(100, TimeUnit.MILLISECONDS));
assertThat(service.getJobLoadBalancers(jobId).toList().toBlocking().single()).containsOnly(firstLoadBalancerId, secondLoadBalancerId);
verify(v3JobOperations, times(2)).getTasks(jobId);
testScheduler.advanceTimeBy(FLUSH_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
// 1 batch per loadbalancer
testSubscriber.assertNoErrors().assertValueCount(2);
assertThat(loadBalancerStore.getLoadBalancerTargets(firstLoadBalancerId).collectList().block()).containsExactlyInAnyOrderElementsOf(firstExpectedTargets);
assertThat(loadBalancerStore.getLoadBalancerTargets(secondLoadBalancerId).collectList().block()).containsExactlyInAnyOrderElementsOf(secondExpectedTargets);
verify(client).registerAll(eq(firstLoadBalancerId), argThat(targets -> targets != null && targets.size() == numberOfStartedTasks));
verify(client).registerAll(eq(secondLoadBalancerId), argThat(targets -> targets != null && targets.size() == numberOfStartedTasks));
verify(client, never()).deregisterAll(eq(firstLoadBalancerId), any());
verify(client, never()).deregisterAll(eq(secondLoadBalancerId), any());
verifyReconcilerIgnore(firstLoadBalancerId, LoadBalancerTests.ipAddresses(tasks));
verifyReconcilerIgnore(secondLoadBalancerId, LoadBalancerTests.ipAddresses(tasks));
// now some more tasks are added to the job, check if both load balancers get updated
List<Task> newTasks = new ArrayList<>();
for (int i = 1; i <= numberOfStartedTasks; i++) {
String taskId = UUID.randomUUID().toString();
Task startingWithIp = ServiceJobTask.newBuilder().withJobId(jobId).withId(taskId).withStatus(TaskStatus.newBuilder().withState(TaskState.StartInitiated).build()).withTaskContext(CollectionsExt.asMap(TaskAttributes.TASK_ATTRIBUTES_CONTAINER_IP, String.format("%1$d.%1$d.%1$d.%1$d", i + numberOfStartedTasks))).build();
Task started = startingWithIp.toBuilder().withStatus(TaskStatus.newBuilder().withState(TaskState.Started).build()).build();
newTasks.add(started);
taskEvents.onNext(TaskUpdateEvent.taskChange(null, started, startingWithIp, callMetadata));
}
testScheduler.advanceTimeBy(FLUSH_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
// 2 more batches (one per load balancer)
testSubscriber.assertNoErrors().assertValueCount(4);
verify(client, times(2)).registerAll(eq(firstLoadBalancerId), argThat(targets -> targets != null && targets.size() == numberOfStartedTasks));
verify(client, times(2)).registerAll(eq(secondLoadBalancerId), argThat(targets -> targets != null && targets.size() == numberOfStartedTasks));
verify(client, never()).deregisterAll(eq(firstLoadBalancerId), any());
verify(client, never()).deregisterAll(eq(secondLoadBalancerId), any());
verifyReconcilerIgnore(firstLoadBalancerId, LoadBalancerTests.ipAddresses(newTasks));
verifyReconcilerIgnore(secondLoadBalancerId, LoadBalancerTests.ipAddresses(newTasks));
assertThat(loadBalancerStore.getLoadBalancerTargets(firstLoadBalancerId).collectList().block()).hasSize(firstExpectedTargets.size() + numberOfStartedTasks);
assertThat(loadBalancerStore.getLoadBalancerTargets(secondLoadBalancerId).collectList().block()).hasSize(secondExpectedTargets.size() + numberOfStartedTasks);
}
use of com.netflix.titus.api.loadbalancer.model.LoadBalancerTarget in project titus-control-plane by Netflix.
the class DefaultLoadBalancerReconcilerTest method orphanLoadBalancerAssociationsAreSetAsDissociatedAndRemoved.
@Test
public void orphanLoadBalancerAssociationsAreSetAsDissociatedAndRemoved() {
List<Task> tasks = LoadBalancerTests.buildTasksStarted(5, jobId);
JobLoadBalancer jobLoadBalancer = new JobLoadBalancer(jobId, loadBalancerId);
when(v3JobOperations.getTasks(jobId)).thenReturn(tasks);
reset(connector);
OngoingStubbing<Single<LoadBalancer>> ongoingStubbing = when(connector.getLoadBalancer(loadBalancerId)).thenReturn(Single.just(new LoadBalancer(loadBalancerId, LoadBalancer.State.ACTIVE, CollectionsExt.asSet("1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4", "5.5.5.5"))));
assertThat(store.addOrUpdateLoadBalancer(jobLoadBalancer, State.ASSOCIATED).await(5, TimeUnit.SECONDS)).isTrue();
// all targets were previously registered by us
store.addOrUpdateTargets(tasks.stream().map(task -> new LoadBalancerTargetState(new LoadBalancerTarget(loadBalancerId, task.getId(), task.getTaskContext().get(TaskAttributes.TASK_ATTRIBUTES_CONTAINER_IP)), LoadBalancerTarget.State.REGISTERED)).collect(Collectors.toList())).block();
testScheduler.triggerActions();
subscriber.assertNotCompleted().assertNoValues();
// load balancer was removed outside of Titus
ongoingStubbing.thenReturn(Single.just(new LoadBalancer(loadBalancerId, LoadBalancer.State.REMOVED, Collections.emptySet())));
// Let a few iterations run so all phases can be executed:
// 1. mark as orphan
// 2. update targets as DEREGISTERED
awaitReconciliationRuns(2);
subscriber.awaitValueCount(5, TEST_TIMEOUT_MS / 2, TimeUnit.MILLISECONDS).assertNoErrors();
assertThat(subscriber.getOnNextEvents()).allMatch(update -> update.getState().equals(LoadBalancerTarget.State.DEREGISTERED));
// simulate all targets got DEREGISTERED
List<LoadBalancerTargetState> currentTargets = store.getLoadBalancerTargets(loadBalancerId).collectList().block();
assertThat(currentTargets).isNotNull();
store.addOrUpdateTargets(currentTargets.stream().map(targetState -> targetState.getLoadBalancerTarget().withState(LoadBalancerTarget.State.DEREGISTERED)).collect(Collectors.toList())).block();
// 3. update orphan as Dissociated
awaitReconciliationRuns(1);
assertThat(store.getAssociations()).containsOnly(new JobLoadBalancerState(jobLoadBalancer, State.DISSOCIATED));
// 4. sweep all targets
// 5. sweep all Dissociated
awaitReconciliationRuns(2);
assertThat(store.getLoadBalancerTargets(loadBalancerId).collectList().block()).isEmpty();
assertThat(store.getAssociations()).isEmpty();
assertThat(store.getAssociatedLoadBalancersSetForJob(jobId)).isEmpty();
}
use of com.netflix.titus.api.loadbalancer.model.LoadBalancerTarget in project titus-control-plane by Netflix.
the class DefaultLoadBalancerReconcilerTest method dissociatedJobsAreNotRemovedUntilAllTargetsAreDeregisteredAndRemoved.
@Test
public void dissociatedJobsAreNotRemovedUntilAllTargetsAreDeregisteredAndRemoved() throws InterruptedException {
JobLoadBalancer jobLoadBalancer = new JobLoadBalancer(jobId, loadBalancerId);
when(v3JobOperations.getTasks(jobId)).thenThrow(JobManagerException.jobNotFound(jobId));
when(v3JobOperations.getJob(jobId)).thenReturn(Optional.empty());
reset(connector);
when(connector.getLoadBalancer(loadBalancerId)).thenReturn(Single.just(new LoadBalancer(loadBalancerId, LoadBalancer.State.ACTIVE, Collections.singleton("1.2.3.4"))));
store.addOrUpdateTargets(new LoadBalancerTargetState(new LoadBalancerTarget(loadBalancerId, "some-task", "1.2.3.4"), LoadBalancerTarget.State.DEREGISTERED)).block();
assertThat(store.addOrUpdateLoadBalancer(jobLoadBalancer, State.DISSOCIATED).await(5, TimeUnit.SECONDS)).isTrue();
testScheduler.triggerActions();
subscriber.assertNotCompleted().assertNoValues();
// 1. deregister
awaitReconciliationRuns(1);
subscriber.assertNoTerminalEvent().assertValueCount(1);
assertThat(store.getAssociations()).isNotEmpty().hasSize(1);
when(connector.getLoadBalancer(loadBalancerId)).thenReturn(Single.just(new LoadBalancer(loadBalancerId, LoadBalancer.State.ACTIVE, Collections.emptySet())));
// Let a few iterations run so the remaining phases have a chance to complete:
// 2. clean up target state
// 3. clean up association
awaitReconciliationRuns(3);
assertThat(store.getAssociations()).isEmpty();
assertThat(store.getLoadBalancerTargets(loadBalancerId).collectList().block()).isEmpty();
}
Aggregations