use of io.strimzi.api.kafka.model.KafkaTopicBuilder in project strimzi by strimzi.
the class TopicOperatorMockTest method testCreatedWithoutTopicNameInKube.
@Test
public void testCreatedWithoutTopicNameInKube(VertxTestContext context) throws InterruptedException, ExecutionException {
LOGGER.info("Test started");
int retention = 100_000_000;
KafkaTopic kt = new KafkaTopicBuilder().withNewMetadata().withName("my-topic").withNamespace(NAMESPACE).addToLabels(Labels.STRIMZI_KIND_LABEL, "topic").addToLabels(Labels.KUBERNETES_NAME_LABEL, "topic-operator").endMetadata().withNewSpec().withPartitions(1).withReplicas(1).addToConfig("retention.bytes", retention).endSpec().build();
testCreatedInKube(context, kt);
}
use of io.strimzi.api.kafka.model.KafkaTopicBuilder in project strimzi by strimzi.
the class TopicOperatorReplicationIT method testKafkaTopicModifiedChangedReplication.
@Test
public void testKafkaTopicModifiedChangedReplication() throws Exception {
// create the topicResource
String topicName = "test-kafkatopic-modified-with-changed-replication";
String resourceName = createTopic(topicName, asList(1));
// now change the topicResource
KafkaTopic changedTopic = new KafkaTopicBuilder(operation().inNamespace(NAMESPACE).withName(resourceName).get()).editOrNewSpec().withReplicas(2).endSpec().build();
operation().inNamespace(NAMESPACE).withName(resourceName).patch(changedTopic);
assertStatusNotReady(topicName, "Changing 'spec.replicas' is not supported. " + "This KafkaTopic's 'spec.replicas' should be reverted to 1 and then " + "the replication should be changed directly in Kafka.");
// Now do the revert
changedTopic = new KafkaTopicBuilder(operation().inNamespace(NAMESPACE).withName(resourceName).get()).editOrNewSpec().withReplicas(1).endSpec().build();
operation().inNamespace(NAMESPACE).withName(resourceName).patch(changedTopic);
assertStatusReady(topicName);
File file = File.createTempFile(getClass().getSimpleName(), ".json");
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = new ObjectNode(mapper.getNodeFactory());
root.put("version", 1).putArray("partitions").addObject().put("topic", topicName).put("partition", 0).putArray("replicas").add(0).add(1);
mapper.writeValue(file, root);
LOGGER.info("Creating 2nd replica: {}", mapper.writeValueAsString(root));
// Now change it in Kafka
String reassignmentOutput = doReassignmentCommand("--bootstrap-server", kafkaCluster.getBootstrapServers(), "--reassignment-json-file", file.getAbsolutePath(), "--execute");
LOGGER.info(reassignmentOutput);
LOGGER.info("Waiting for reassignment completion");
waitFor(() -> {
String output = doReassignmentCommand("--bootstrap-server", kafkaCluster.getBootstrapServers(), "--reassignment-json-file", file.getAbsolutePath(), "--verify");
LOGGER.info(output);
if (output.contains("Reassignment of partition test-kafkatopic-modified-with-changed-replication-0 is still in progress")) {
return false;
} else {
assertThat("Reassignment is no longer in progress, but wasn't successful: " + output, output.contains("Reassignment of partition test-kafkatopic-modified-with-changed-replication-0 is complete"), is(true));
return true;
}
}, "reassignment completion");
// wait for reconciliation and that now replicas=2.
waitFor(() -> {
KafkaTopic kafkaTopic = Crds.topicOperation(kubeClient).inNamespace(NAMESPACE).withName(resourceName).get();
LOGGER.info(kafkaTopic == null ? "Null topic" : kafkaTopic.toString());
return kafkaTopic.getSpec().getReplicas() == 2;
}, "KafkaTopic.spec.replicas=2");
// And check that the status is ready
assertStatusReady(topicName);
}
use of io.strimzi.api.kafka.model.KafkaTopicBuilder in project strimzi by strimzi.
the class TopicOperatorTest method testOnKafkaTopicAdded_invalidResource.
/**
* Test what happens when a non-topic KafkaTopic gets created in kubernetes
*/
@Test
public void testOnKafkaTopicAdded_invalidResource(VertxTestContext context) {
KafkaTopic kafkaTopic = new KafkaTopicBuilder().withMetadata(new ObjectMetaBuilder().withName("invalid").withLabels(labels.labels()).build()).withNewSpec().withReplicas(1).withPartitions(1).withConfig(singletonMap(null, null)).endSpec().build();
String errorMessage = "KafkaTopic's spec.config has invalid entry: The key 'null' of the topic config is invalid: The value corresponding to the key must have a string, number or boolean value but the value was null";
mockK8s.setGetFromNameResponse(new ResourceName(kafkaTopic), Future.succeededFuture(kafkaTopic));
LogContext logContext = LogContext.kubeWatch(Watcher.Action.ADDED, kafkaTopic);
Checkpoint async = context.checkpoint();
topicOperator.onResourceEvent(logContext, kafkaTopic, ADDED).onComplete(ar -> {
assertFailed(context, ar);
context.verify(() -> assertThat(ar.cause(), instanceOf(InvalidTopicException.class)));
context.verify(() -> assertThat(ar.cause().getMessage(), is(errorMessage)));
mockKafka.assertEmpty(context);
mockTopicStore.assertEmpty(context);
assertNotReadyStatus(context, new InvalidTopicException(null, ar.cause().getMessage()));
context.verify(() -> {
MeterRegistry registry = metrics.meterRegistry();
assertThat(registry.get(TopicOperator.METRICS_PREFIX + "reconciliations").tag("kind", "KafkaTopic").counter().count(), is(0.0));
assertThat(registry.get(TopicOperator.METRICS_PREFIX + "reconciliations.successful").tag("kind", "KafkaTopic").counter().count(), is(0.0));
assertThat(registry.get(TopicOperator.METRICS_PREFIX + "reconciliations.failed").tag("kind", "KafkaTopic").counter().count(), is(0.0));
assertThat(registry.get(TopicOperator.METRICS_PREFIX + "reconciliations.duration").tag("kind", "KafkaTopic").timer().count(), is(0L));
assertThat(registry.get(TopicOperator.METRICS_PREFIX + "reconciliations.duration").tag("kind", "KafkaTopic").timer().totalTime(TimeUnit.MILLISECONDS), is(0.0));
assertThat(registry.get(TopicOperator.METRICS_PREFIX + "resource.state").tag("kind", "KafkaTopic").tag("name", "invalid").tag("resource-namespace", "default-namespace").tag("reason", errorMessage).gauge().value(), is(0.0));
});
async.flag();
});
}
use of io.strimzi.api.kafka.model.KafkaTopicBuilder in project strimzi by strimzi.
the class TopicOperatorTest method resourceAdded.
/**
* Trigger {@link TopicOperator#onResourceEvent(LogContext, KafkaTopic, io.fabric8.kubernetes.client.Watcher.Action)}
* and have the Kafka and TopicStore respond with the given exceptions.
*/
private TopicOperator resourceAdded(VertxTestContext context, CountDownLatch latch, Exception createException, Exception storeException) throws InterruptedException {
mockKafka.setCreateTopicResponse(topicName.toString(), createException);
mockKafka.setTopicExistsResult(t -> Future.succeededFuture(false));
mockTopicStore.setCreateTopicResponse(topicName, storeException);
KafkaTopic kafkaTopic = new KafkaTopicBuilder().withMetadata(metadata).withNewSpec().withReplicas(2).withPartitions(10).endSpec().build();
mockKafka.setTopicMetadataResponses(topicName -> Future.succeededFuture(), topicName -> Future.succeededFuture(Utils.getTopicMetadata(TopicSerialization.fromTopicResource(kafkaTopic))));
LogContext logContext = LogContext.kubeWatch(Watcher.Action.ADDED, kafkaTopic);
Checkpoint async = context.checkpoint();
mockK8s.setGetFromNameResponse(new ResourceName(kafkaTopic), Future.succeededFuture(kafkaTopic));
topicOperator.onResourceEvent(logContext, kafkaTopic, ADDED).onComplete(ar -> {
if (createException != null || storeException != null) {
assertFailed(context, ar);
Class<? extends Exception> expectedExceptionType;
if (createException != null) {
expectedExceptionType = createException.getClass();
} else {
expectedExceptionType = storeException.getClass();
}
if (!expectedExceptionType.equals(ar.cause().getClass())) {
ar.cause().printStackTrace();
}
context.verify(() -> assertThat(ar.cause().getMessage(), ar.cause().getClass().getName(), is(expectedExceptionType.getName())));
TopicName topicName = TopicSerialization.fromTopicResource(kafkaTopic).getTopicName();
if (createException != null) {
mockKafka.assertNotExists(context, topicName);
} else {
mockKafka.assertExists(context, topicName);
}
mockTopicStore.assertNotExists(context, topicName);
// TODO mockK8s.assertContainsEvent(context, e -> "Error".equals(e.getKind()));
} else {
assertSucceeded(context, ar);
Topic expectedTopic = TopicSerialization.fromTopicResource(kafkaTopic);
mockKafka.assertContains(context, expectedTopic);
mockTopicStore.assertContains(context, expectedTopic);
mockK8s.assertNoEvents(context);
}
if (latch != null) {
latch.countDown();
}
async.flag();
});
if (!context.awaitCompletion(60, TimeUnit.SECONDS)) {
context.failNow(new Throwable("Test timeout"));
}
return topicOperator;
}
use of io.strimzi.api.kafka.model.KafkaTopicBuilder in project strimzi by strimzi.
the class TopicSerializationTest method testErrorInConfigInvalidValueWrongType.
@Test
public void testErrorInConfigInvalidValueWrongType() {
KafkaTopic kafkaTopic = new KafkaTopicBuilder().withMetadata(new ObjectMetaBuilder().withName("my-topic").build()).withNewSpec().withReplicas(1).withPartitions(1).withConfig(singletonMap("foo", new Object())).endSpec().build();
try {
TopicSerialization.fromTopicResource(kafkaTopic);
fail("Should throw");
} catch (InvalidTopicException e) {
assertThat(e.getMessage(), is("KafkaTopic's spec.config has invalid entry: The key 'foo' of the topic config is invalid: The value corresponding to the key must have a string, number or boolean value but was of type java.lang.Object"));
}
}
Aggregations