Search in sources :

Example 86 with KafkaTopic

use of io.strimzi.api.kafka.model.KafkaTopic in project strimzi-kafka-operator by strimzi.

the class TopicOperator method reconcileOnTopicChange.

/**
 * Called when one of the ZK watches notifies of a change to the topic
 */
private Future<Void> reconcileOnTopicChange(LogContext logContext, TopicName topicName, Topic kafkaTopic, Reconciliation reconciliation) {
    // Look up the private topic to discover the name of kube KafkaTopic
    return topicStore.read(topicName).compose(storeTopic -> {
        ResourceName resourceName = storeTopic != null ? storeTopic.getResourceName() : topicName.asKubeName();
        return k8s.getFromName(resourceName).compose(topic -> {
            reconciliation.observedTopicFuture(kafkaTopic != null ? topic : null);
            Topic k8sTopic = TopicSerialization.fromTopicResource(topic);
            return reconcile(reconciliation, logContext.withKubeTopic(topic), topic, k8sTopic, kafkaTopic, storeTopic);
        });
    });
}
Also used : KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic)

Example 87 with KafkaTopic

use of io.strimzi.api.kafka.model.KafkaTopic in project strimzi-kafka-operator by strimzi.

the class TopicOperator method reconcileAllTopics.

Future<?> reconcileAllTopics(String reconciliationType) {
    LOGGER.infoOp("Starting {} reconciliation", reconciliationType);
    return kafka.listTopics().recover(ex -> Future.failedFuture(new OperatorException("Error listing existing topics during " + reconciliationType + " reconciliation", ex))).compose(topicNamesFromKafka -> reconcileFromKafka(reconciliationType, topicNamesFromKafka.stream().map(TopicName::new).collect(Collectors.toList()))).compose(reconcileState -> {
        Future<List<KafkaTopic>> ktFut = k8s.listResources();
        return ktFut.recover(ex -> Future.failedFuture(new OperatorException("Error listing existing KafkaTopics during " + reconciliationType + " reconciliation", ex))).map(ktList -> {
            reconcileState.setKafkaTopics(ktList);
            return reconcileState;
        });
    }).compose(reconcileState -> {
        List<Future> futs = new ArrayList<>();
        pausedTopicCounter.set(0);
        topicCounter.set(reconcileState.ktList.size());
        for (KafkaTopic kt : reconcileState.ktList) {
            if (Annotations.isReconciliationPausedWithAnnotation(kt)) {
                pausedTopicCounter.getAndIncrement();
            }
            LogContext logContext = LogContext.periodic(reconciliationType + "kube " + kt.getMetadata().getName(), kt.getMetadata().getNamespace(), kt.getMetadata().getName()).withKubeTopic(kt);
            Topic topic = TopicSerialization.fromTopicResource(kt);
            TopicName topicName = topic.getTopicName();
            if (reconcileState.failed.containsKey(topicName)) {
                // we already failed to reconcile this topic in reconcileFromKafka(), /
                // don't bother trying again
                LOGGER.traceCr(logContext.toReconciliation(), "Already failed to reconcile {}", topicName);
                reconciliationsCounter.increment();
                failedReconciliationsCounter.increment();
            } else if (reconcileState.succeeded.contains(topicName)) {
                // we already succeeded in reconciling this topic in reconcileFromKafka()
                LOGGER.traceCr(logContext.toReconciliation(), "Already successfully reconciled {}", topicName);
                reconciliationsCounter.increment();
                successfulReconciliationsCounter.increment();
            } else if (reconcileState.undetermined.contains(topicName)) {
                // The topic didn't exist in topicStore, but now we know which KT it corresponds to
                futs.add(reconcileWithKubeTopic(logContext, kt, reconciliationType, new ResourceName(kt), topic.getTopicName()).compose(r -> {
                    // if success then remove from undetermined add to success
                    reconcileState.undetermined.remove(topicName);
                    reconcileState.succeeded.add(topicName);
                    return Future.succeededFuture(Boolean.TRUE);
                }));
            } else {
                // Topic exists in kube, but not in Kafka
                LOGGER.debugCr(logContext.toReconciliation(), "Topic {} exists in Kubernetes, but not Kafka", topicName, logTopic(kt));
                futs.add(reconcileWithKubeTopic(logContext, kt, reconciliationType, new ResourceName(kt), topic.getTopicName()).compose(r -> {
                    // if success then add to success
                    reconcileState.succeeded.add(topicName);
                    return Future.succeededFuture(Boolean.TRUE);
                }));
            }
        }
        return CompositeFuture.join(futs).compose(joined -> {
            List<Future> futs2 = new ArrayList<>();
            for (Throwable exception : reconcileState.failed.values()) {
                futs2.add(Future.failedFuture(exception));
            }
            // anything left in undetermined doesn't exist in topic store nor kube
            for (TopicName tn : reconcileState.undetermined) {
                LogContext logContext = LogContext.periodic(reconciliationType + "-" + tn, namespace, tn.asKubeName().toString());
                futs2.add(executeWithTopicLockHeld(logContext, tn, new Reconciliation(logContext, "delete-remaining", true) {

                    @Override
                    public Future<Void> execute() {
                        observedTopicFuture(null);
                        return getKafkaAndReconcile(this, logContext, tn, null, null);
                    }
                }));
            }
            return CompositeFuture.join(futs2);
        });
    });
}
Also used : BackOff(io.strimzi.operator.common.BackOff) ZonedDateTime(java.time.ZonedDateTime) BiFunction(java.util.function.BiFunction) Collections.disjoint(java.util.Collections.disjoint) Watcher(io.fabric8.kubernetes.client.Watcher) Annotations(io.strimzi.operator.common.Annotations) InvalidReplicationFactorException(org.apache.kafka.common.errors.InvalidReplicationFactorException) HashMap(java.util.HashMap) MaxAttemptsExceededException(io.strimzi.operator.common.MaxAttemptsExceededException) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) Collections.singletonList(java.util.Collections.singletonList) HashSet(java.util.HashSet) CompositeFuture(io.vertx.core.CompositeFuture) Timer(io.micrometer.core.instrument.Timer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) AsyncResult(io.vertx.core.AsyncResult) Counter(io.micrometer.core.instrument.Counter) StatusUtils(io.strimzi.operator.common.operator.resource.StatusUtils) Tag(io.micrometer.core.instrument.Tag) Tags(io.micrometer.core.instrument.Tags) KafkaTopicStatus(io.strimzi.api.kafka.model.status.KafkaTopicStatus) ReconciliationLogger(io.strimzi.operator.common.ReconciliationLogger) Collections.emptyList(java.util.Collections.emptyList) Promise(io.vertx.core.Promise) MetricsProvider(io.strimzi.operator.common.MetricsProvider) Vertx(io.vertx.core.Vertx) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) Meter(io.micrometer.core.instrument.Meter) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Future(io.vertx.core.Future) Collectors(java.util.stream.Collectors) EventBuilder(io.fabric8.kubernetes.api.model.EventBuilder) TopicExistsException(org.apache.kafka.common.errors.TopicExistsException) List(java.util.List) KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic) StatusDiff(io.strimzi.operator.cluster.model.StatusDiff) Util(io.strimzi.operator.common.Util) Logger(org.apache.logging.log4j.Logger) ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) KafkaTopicBuilder(io.strimzi.api.kafka.model.KafkaTopicBuilder) DateTimeFormatter(java.time.format.DateTimeFormatter) Optional(java.util.Optional) Handler(io.vertx.core.Handler) LogManager(org.apache.logging.log4j.LogManager) ArrayList(java.util.ArrayList) KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic) CompositeFuture(io.vertx.core.CompositeFuture) Future(io.vertx.core.Future) KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic)

Example 88 with KafkaTopic

use of io.strimzi.api.kafka.model.KafkaTopic in project strimzi-kafka-operator by strimzi.

the class TopicOperator method onTopicCreated.

/**
 * Called when a topic znode is created in ZK
 */
Future<Void> onTopicCreated(LogContext logContext, TopicName topicName) {
    // XXX currently runs on the ZK thread, requiring a synchronized inFlight
    // is it better to put this check in the topic deleted event?
    Reconciliation action = new Reconciliation(logContext, "onTopicCreated", true) {

        @Override
        public Future<Void> execute() {
            Reconciliation self = this;
            Promise<Void> promise = Promise.promise();
            TopicMetadataHandler handler = new TopicMetadataHandler(vertx, kafka, topicName, topicMetadataBackOff()) {

                @Override
                public void handle(AsyncResult<TopicMetadata> metadataResult) {
                    if (metadataResult.succeeded()) {
                        if (metadataResult.result() == null) {
                            // In this case it is most likely that we've been notified by ZK
                            // before Kafka has finished creating the topic, so we retry
                            // with exponential backoff.
                            retry(logContext.toReconciliation());
                        } else {
                            // We now have the metadata we need to create the
                            // resource...
                            Topic kafkaTopic = TopicSerialization.fromTopicMetadata(metadataResult.result());
                            reconcileOnTopicChange(logContext, topicName, kafkaTopic, self).onComplete(promise);
                        }
                    } else {
                        promise.fail(metadataResult.cause());
                    }
                }

                @Override
                public void onMaxAttemptsExceeded(MaxAttemptsExceededException e) {
                    promise.fail(e);
                }
            };
            return awaitExistential(logContext, topicName, true).compose(exists -> {
                kafka.topicMetadata(logContext.toReconciliation(), topicName).onComplete(handler);
                return promise.future();
            });
        }
    };
    return executeWithTopicLockHeld(logContext, topicName, action);
}
Also used : MaxAttemptsExceededException(io.strimzi.operator.common.MaxAttemptsExceededException) KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic) AsyncResult(io.vertx.core.AsyncResult)

Example 89 with KafkaTopic

use of io.strimzi.api.kafka.model.KafkaTopic in project strimzi-kafka-operator by strimzi.

the class TopicSerialization method toTopicResource.

/**
 * Create a resource to reflect the given Topic.
 */
public static KafkaTopic toTopicResource(Topic topic, Labels labels) {
    ResourceName resourceName = topic.getOrAsKubeName();
    ObjectMeta om = topic.getMetadata();
    Map<String, String> lbls = new HashMap<>(labels.labels());
    if (om != null) {
        om.setName(resourceName.toString());
        if (topic.getMetadata().getLabels() != null)
            lbls.putAll(topic.getMetadata().getLabels());
        om.setLabels(lbls);
        om.setOwnerReferences(topic.getMetadata().getOwnerReferences());
        om.setAnnotations(topic.getMetadata().getAnnotations());
    } else {
        om = new ObjectMetaBuilder().withName(resourceName.toString()).withLabels(lbls).build();
    }
    KafkaTopic kt = new KafkaTopicBuilder().withMetadata(om).withNewSpec().withTopicName(topic.getTopicName().toString()).withPartitions(topic.getNumPartitions()).withReplicas((int) topic.getNumReplicas()).withConfig(new LinkedHashMap<>(topic.getConfig())).endSpec().build();
    // topic is created with annotations={} (empty map but should be null as well)
    if (topic.getMetadata() != null)
        kt.getMetadata().setAnnotations(topic.getMetadata().getAnnotations());
    return kt;
}
Also used : ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic) KafkaTopicBuilder(io.strimzi.api.kafka.model.KafkaTopicBuilder) ObjectMetaBuilder(io.fabric8.kubernetes.api.model.ObjectMetaBuilder)

Example 90 with KafkaTopic

use of io.strimzi.api.kafka.model.KafkaTopic in project strimzi-kafka-operator by strimzi.

the class K8sImpl method createResource.

@Override
public Future<KafkaTopic> createResource(KafkaTopic topicResource) {
    Promise<KafkaTopic> handler = Promise.promise();
    vertx.executeBlocking(future -> {
        try {
            KafkaTopic kafkaTopic = operation().inNamespace(namespace).create(topicResource);
            LOGGER.debug("KafkaTopic {} created with version {}->{}", kafkaTopic.getMetadata().getName(), topicResource.getMetadata() != null ? topicResource.getMetadata().getResourceVersion() : null, kafkaTopic.getMetadata().getResourceVersion());
            future.complete(kafkaTopic);
        } catch (Exception e) {
            future.fail(e);
        }
    }, handler);
    return handler.future();
}
Also used : KafkaTopic(io.strimzi.api.kafka.model.KafkaTopic) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Aggregations

KafkaTopic (io.strimzi.api.kafka.model.KafkaTopic)187 Test (org.junit.jupiter.api.Test)92 KafkaTopicBuilder (io.strimzi.api.kafka.model.KafkaTopicBuilder)80 Checkpoint (io.vertx.junit5.Checkpoint)46 ObjectMetaBuilder (io.fabric8.kubernetes.api.model.ObjectMetaBuilder)38 HashMap (java.util.HashMap)32 ObjectMeta (io.fabric8.kubernetes.api.model.ObjectMeta)30 CountDownLatch (java.util.concurrent.CountDownLatch)28 NewTopic (org.apache.kafka.clients.admin.NewTopic)28 List (java.util.List)26 Map (java.util.Map)26 MeterRegistry (io.micrometer.core.instrument.MeterRegistry)22 KafkaTopicStatus (io.strimzi.api.kafka.model.status.KafkaTopicStatus)22 AsyncResult (io.vertx.core.AsyncResult)22 MaxAttemptsExceededException (io.strimzi.operator.common.MaxAttemptsExceededException)20 Vertx (io.vertx.core.Vertx)20 Matchers.containsString (org.hamcrest.Matchers.containsString)20 Watcher (io.fabric8.kubernetes.client.Watcher)18 KafkaClients (io.strimzi.systemtest.kafkaclients.internalClients.KafkaClients)18 KafkaClientsBuilder (io.strimzi.systemtest.kafkaclients.internalClients.KafkaClientsBuilder)18