Search in sources :

Example 1 with ReconcileResult

use of io.strimzi.operator.common.operator.resource.ReconcileResult in project strimzi by strimzi.

the class AbstractOperator method reconcile.

/**
 * Reconcile assembly resources in the given namespace having the given {@code name}.
 * Reconciliation works by getting the assembly resource (e.g. {@code KafkaUser})
 * in the given namespace with the given name and
 * comparing with the corresponding resource.
 * @param reconciliation The reconciliation.
 * @return A Future which is completed with the result of the reconciliation.
 */
@Override
@SuppressWarnings("unchecked")
public final Future<Void> reconcile(Reconciliation reconciliation) {
    String namespace = reconciliation.namespace();
    String name = reconciliation.name();
    reconciliationsCounter(reconciliation.namespace()).increment();
    Timer.Sample reconciliationTimerSample = Timer.start(metrics.meterRegistry());
    Future<Void> handler = withLock(reconciliation, LOCK_TIMEOUT_MS, () -> {
        T cr = resourceOperator.get(namespace, name);
        if (cr != null) {
            if (!Util.matchesSelector(selector(), cr)) {
                // When the labels matching the selector are removed from the custom resource, a DELETE event is
                // triggered by the watch even through the custom resource might not match the watch labels anymore
                // and might not be really deleted. We have to filter these situations out and ignore the
                // reconciliation because such resource might be already operated by another instance (where the
                // same change triggered ADDED event).
                LOGGER.debugCr(reconciliation, "{} {} in namespace {} does not match label selector {} and will be ignored", kind(), name, namespace, selector().get().getMatchLabels());
                return Future.succeededFuture();
            }
            Promise<Void> createOrUpdate = Promise.promise();
            if (Annotations.isReconciliationPausedWithAnnotation(cr)) {
                S status = createStatus();
                Set<Condition> conditions = validate(reconciliation, cr);
                conditions.add(StatusUtils.getPausedCondition());
                status.setConditions(new ArrayList<>(conditions));
                status.setObservedGeneration(cr.getStatus() != null ? cr.getStatus().getObservedGeneration() : 0);
                updateStatus(reconciliation, status).onComplete(statusResult -> {
                    if (statusResult.succeeded()) {
                        createOrUpdate.complete();
                    } else {
                        createOrUpdate.fail(statusResult.cause());
                    }
                });
                pausedResourceCounter(namespace).getAndIncrement();
                LOGGER.debugCr(reconciliation, "Reconciliation of {} {} is paused", kind, name);
                return createOrUpdate.future();
            } else if (cr.getSpec() == null) {
                InvalidResourceException exception = new InvalidResourceException("Spec cannot be null");
                S status = createStatus();
                Condition errorCondition = new ConditionBuilder().withLastTransitionTime(StatusUtils.iso8601Now()).withType("NotReady").withStatus("True").withReason(exception.getClass().getSimpleName()).withMessage(exception.getMessage()).build();
                status.setObservedGeneration(cr.getMetadata().getGeneration());
                status.addCondition(errorCondition);
                LOGGER.errorCr(reconciliation, "{} spec cannot be null", cr.getMetadata().getName());
                updateStatus(reconciliation, status).onComplete(notUsed -> {
                    createOrUpdate.fail(exception);
                });
                return createOrUpdate.future();
            }
            Set<Condition> unknownAndDeprecatedConditions = validate(reconciliation, cr);
            LOGGER.infoCr(reconciliation, "{} {} will be checked for creation or modification", kind, name);
            createOrUpdate(reconciliation, cr).onComplete(res -> {
                if (res.succeeded()) {
                    S status = res.result();
                    addWarningsToStatus(status, unknownAndDeprecatedConditions);
                    updateStatus(reconciliation, status).onComplete(statusResult -> {
                        if (statusResult.succeeded()) {
                            createOrUpdate.complete();
                        } else {
                            createOrUpdate.fail(statusResult.cause());
                        }
                    });
                } else {
                    if (res.cause() instanceof ReconciliationException) {
                        ReconciliationException e = (ReconciliationException) res.cause();
                        Status status = e.getStatus();
                        addWarningsToStatus(status, unknownAndDeprecatedConditions);
                        LOGGER.errorCr(reconciliation, "createOrUpdate failed", e.getCause());
                        updateStatus(reconciliation, (S) status).onComplete(statusResult -> {
                            createOrUpdate.fail(e.getCause());
                        });
                    } else {
                        LOGGER.errorCr(reconciliation, "createOrUpdate failed", res.cause());
                        createOrUpdate.fail(res.cause());
                    }
                }
            });
            return createOrUpdate.future();
        } else {
            LOGGER.infoCr(reconciliation, "{} {} should be deleted", kind, name);
            return delete(reconciliation).map(deleteResult -> {
                if (deleteResult) {
                    LOGGER.infoCr(reconciliation, "{} {} deleted", kind, name);
                } else {
                    LOGGER.infoCr(reconciliation, "Assembly {} or some parts of it will be deleted by garbage collection", name);
                }
                return (Void) null;
            }).recover(deleteResult -> {
                LOGGER.errorCr(reconciliation, "Deletion of {} {} failed", kind, name, deleteResult);
                return Future.failedFuture(deleteResult);
            });
        }
    });
    Promise<Void> result = Promise.promise();
    handler.onComplete(reconcileResult -> {
        try {
            handleResult(reconciliation, reconcileResult, reconciliationTimerSample);
        } finally {
            result.handle(reconcileResult);
        }
    });
    return result.future();
}
Also used : Condition(io.strimzi.api.kafka.model.status.Condition) ClusterRoleBinding(io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding) LabelSelector(io.fabric8.kubernetes.api.model.LabelSelector) Watch(io.fabric8.kubernetes.client.Watch) Callable(java.util.concurrent.Callable) ResourceVisitor(io.strimzi.operator.common.model.ResourceVisitor) ArrayList(java.util.ArrayList) WatcherException(io.fabric8.kubernetes.client.WatcherException) Timer(io.micrometer.core.instrument.Timer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) Status(io.strimzi.api.kafka.model.status.Status) ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) AsyncResult(io.vertx.core.AsyncResult) LinkedHashSet(java.util.LinkedHashSet) 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) InvalidResourceException(io.strimzi.operator.cluster.model.InvalidResourceException) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ValidationVisitor(io.strimzi.operator.common.model.ValidationVisitor) Set(java.util.Set) Meter(io.micrometer.core.instrument.Meter) Spec(io.strimzi.api.kafka.model.Spec) Future(io.vertx.core.Future) Collectors(java.util.stream.Collectors) Util.async(io.strimzi.operator.common.Util.async) Consumer(java.util.function.Consumer) NamespaceAndName(io.strimzi.operator.common.model.NamespaceAndName) StatusDiff(io.strimzi.operator.cluster.model.StatusDiff) Labels(io.strimzi.operator.common.model.Labels) Lock(io.vertx.core.shareddata.Lock) ConditionBuilder(io.strimzi.api.kafka.model.status.ConditionBuilder) AbstractWatchableStatusedResourceOperator(io.strimzi.operator.common.operator.resource.AbstractWatchableStatusedResourceOperator) Optional(java.util.Optional) Condition(io.strimzi.api.kafka.model.status.Condition) Handler(io.vertx.core.Handler) Collections(java.util.Collections) CustomResource(io.fabric8.kubernetes.client.CustomResource) TimeoutException(io.strimzi.operator.common.operator.resource.TimeoutException) Status(io.strimzi.api.kafka.model.status.Status) InvalidResourceException(io.strimzi.operator.cluster.model.InvalidResourceException) ConditionBuilder(io.strimzi.api.kafka.model.status.ConditionBuilder) Timer(io.micrometer.core.instrument.Timer)

Example 2 with ReconcileResult

use of io.strimzi.operator.common.operator.resource.ReconcileResult in project strimzi by strimzi.

the class KafkaUserOperator method reconcileCredentialsQuotasAndAcls.

/**
 * Reconciles the credentials, quotas and ACLs
 *
 * @param reconciliation    Unique identification for the reconciliation
 * @param user              Model describing the KafkaUser
 * @param userStatus        Status subresource of the KafkaUser custom resource
 *
 * @return                  Future describing the result
 */
private CompositeFuture reconcileCredentialsQuotasAndAcls(Reconciliation reconciliation, KafkaUserModel user, KafkaUserStatus userStatus) {
    Set<SimpleAclRule> tlsAcls = null;
    Set<SimpleAclRule> scramOrNoneAcls = null;
    KafkaUserQuotas tlsQuotas = null;
    KafkaUserQuotas scramOrNoneQuotas = null;
    if (user.isTlsUser() || user.isTlsExternalUser()) {
        tlsAcls = user.getSimpleAclRules();
        tlsQuotas = user.getQuotas();
    } else if (user.isScramUser() || user.isNoneUser()) {
        scramOrNoneAcls = user.getSimpleAclRules();
        scramOrNoneQuotas = user.getQuotas();
    }
    // Reconcile the user SCRAM-SHA-512 credentials
    Future<ReconcileResult<String>> scramCredentialsFuture = scramCredentialsOperator.reconcile(reconciliation, user.getName(), user.getScramSha512Password());
    // Quotas need to reconciled for both regular and TLS username. It will be (possibly) set for one user and deleted for the other
    Future<ReconcileResult<KafkaUserQuotas>> tlsQuotasFuture = quotasOperator.reconcile(reconciliation, KafkaUserModel.getTlsUserName(reconciliation.name()), tlsQuotas);
    Future<ReconcileResult<KafkaUserQuotas>> quotasFuture = quotasOperator.reconcile(reconciliation, KafkaUserModel.getScramUserName(reconciliation.name()), scramOrNoneQuotas);
    // Reconcile the user secret generated by the user operator with the credentials
    Future<ReconcileResult<Secret>> userSecretFuture = reconcileUserSecret(reconciliation, user, userStatus);
    // ACLs need to reconciled for both regular and TLS username. It will be (possibly) set for one user and deleted for the other
    Future<ReconcileResult<Set<SimpleAclRule>>> aclsTlsUserFuture;
    Future<ReconcileResult<Set<SimpleAclRule>>> aclsScramUserFuture;
    if (config.isAclsAdminApiSupported()) {
        aclsTlsUserFuture = aclOperations.reconcile(reconciliation, KafkaUserModel.getTlsUserName(reconciliation.name()), tlsAcls);
        aclsScramUserFuture = aclOperations.reconcile(reconciliation, KafkaUserModel.getScramUserName(reconciliation.name()), scramOrNoneAcls);
    } else {
        aclsTlsUserFuture = Future.succeededFuture(ReconcileResult.noop(null));
        aclsScramUserFuture = Future.succeededFuture(ReconcileResult.noop(null));
    }
    return CompositeFuture.join(scramCredentialsFuture, tlsQuotasFuture, quotasFuture, aclsTlsUserFuture, aclsScramUserFuture, userSecretFuture);
}
Also used : KafkaUserQuotas(io.strimzi.api.kafka.model.KafkaUserQuotas) ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) SimpleAclRule(io.strimzi.operator.user.model.acl.SimpleAclRule)

Example 3 with ReconcileResult

use of io.strimzi.operator.common.operator.resource.ReconcileResult in project strimzi by strimzi.

the class StatefulSetOperator method internalReplace.

/**
 * Sometimes, patching the resource is not enough. For example when the persistent volume claim templates are modified.
 * In such case we need to delete the STS with cascading=false and recreate it.
 * A rolling update should done finished after the STS is recreated.
 *
 * @param namespace Namespace of the resource which should be deleted
 * @param name Name of the resource which should be deleted
 * @param current Current StatefulSet
 * @param desired Desired StatefulSet
 * @param cascading Defines whether the delete should be cascading or not (e.g. whether a STS deletion should delete pods etc.)
 *
 * @return Future with result of the reconciliation
 */
protected Future<ReconcileResult<StatefulSet>> internalReplace(Reconciliation reconciliation, String namespace, String name, StatefulSet current, StatefulSet desired, boolean cascading) {
    try {
        Promise<ReconcileResult<StatefulSet>> promise = Promise.promise();
        long pollingIntervalMs = 1_000;
        long timeoutMs = operationTimeoutMs;
        operation().inNamespace(namespace).withName(name).withPropagationPolicy(cascading ? DeletionPropagation.FOREGROUND : DeletionPropagation.ORPHAN).withGracePeriod(-1L).delete();
        Future<Void> deletedFut = waitFor(reconciliation, namespace, name, "deleted", pollingIntervalMs, timeoutMs, (ignore1, ignore2) -> {
            StatefulSet sts = get(namespace, name);
            LOGGER.traceCr(reconciliation, "Checking if {} {} in namespace {} has been deleted", resourceKind, name, namespace);
            return sts == null;
        });
        deletedFut.onComplete(res -> {
            if (res.succeeded()) {
                StatefulSet result = operation().inNamespace(namespace).withName(name).create(desired);
                LOGGER.debugCr(reconciliation, "{} {} in namespace {} has been replaced", resourceKind, name, namespace);
                promise.complete(wasChanged(current, result) ? ReconcileResult.patched(result) : ReconcileResult.noop(result));
            } else {
                promise.fail(res.cause());
            }
        });
        return promise.future();
    } catch (Exception e) {
        LOGGER.debugCr(reconciliation, "Caught exception while replacing {} {} in namespace {}", resourceKind, name, namespace, e);
        return Future.failedFuture(e);
    }
}
Also used : ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) StatefulSet(io.fabric8.kubernetes.api.model.apps.StatefulSet)

Example 4 with ReconcileResult

use of io.strimzi.operator.common.operator.resource.ReconcileResult in project strimzi-kafka-operator by strimzi.

the class AbstractConnectOperator method createConnectorWatch.

/**
 * Create a watch on {@code KafkaConnector} in the given {@code namespace}.
 * The watcher will:
 * <ul>
 * <li>{@linkplain #reconcileConnectors(Reconciliation, CustomResource, KafkaConnectStatus, boolean, String, OrderedProperties)} on the KafkaConnect
 * identified by {@code KafkaConnector.metadata.labels[strimzi.io/cluster]}.</li>
 * <li>The {@code KafkaConnector} status is updated with the result.</li>
 * </ul>
 * @param connectOperator The operator for {@code KafkaConnect}.
 * @param watchNamespaceOrWildcard The namespace to watch.
 * @param selectorLabels Selector labels for filtering the custom resources
 *
 * @return A future which completes when the watch has been set up.
 */
public static Future<Void> createConnectorWatch(AbstractConnectOperator<KubernetesClient, KafkaConnect, KafkaConnectList, Resource<KafkaConnect>, KafkaConnectSpec, KafkaConnectStatus> connectOperator, String watchNamespaceOrWildcard, Labels selectorLabels) {
    Optional<LabelSelector> selector = (selectorLabels == null || selectorLabels.toMap().isEmpty()) ? Optional.empty() : Optional.of(new LabelSelector(null, selectorLabels.toMap()));
    return Util.async(connectOperator.vertx, () -> {
        connectOperator.connectorOperator.watch(watchNamespaceOrWildcard, new Watcher<KafkaConnector>() {

            @Override
            public void eventReceived(Action action, KafkaConnector kafkaConnector) {
                String connectorName = kafkaConnector.getMetadata().getName();
                String connectorNamespace = kafkaConnector.getMetadata().getNamespace();
                String connectorKind = kafkaConnector.getKind();
                String connectName = kafkaConnector.getMetadata().getLabels() == null ? null : kafkaConnector.getMetadata().getLabels().get(Labels.STRIMZI_CLUSTER_LABEL);
                String connectNamespace = connectorNamespace;
                switch(action) {
                    case ADDED:
                    case DELETED:
                    case MODIFIED:
                        if (connectName != null) {
                            // Check whether a KafkaConnect exists
                            connectOperator.resourceOperator.getAsync(connectNamespace, connectName).compose(connect -> {
                                KafkaConnectApi apiClient = connectOperator.connectClientProvider.apply(connectOperator.vertx);
                                if (connect == null) {
                                    Reconciliation r = new Reconciliation("connector-watch", connectOperator.kind(), kafkaConnector.getMetadata().getNamespace(), connectName);
                                    updateStatus(r, noConnectCluster(connectNamespace, connectName), kafkaConnector, connectOperator.connectorOperator);
                                    LOGGER.infoCr(r, "{} {} in namespace {} was {}, but Connect cluster {} does not exist", connectorKind, connectorName, connectorNamespace, action, connectName);
                                    return Future.succeededFuture();
                                } else {
                                    // grab the lock and call reconcileConnectors()
                                    // (i.e. short circuit doing a whole KafkaConnect reconciliation).
                                    Reconciliation reconciliation = new Reconciliation("connector-watch", connectOperator.kind(), kafkaConnector.getMetadata().getNamespace(), connectName);
                                    if (!Util.matchesSelector(selector, connect)) {
                                        LOGGER.debugCr(reconciliation, "{} {} in namespace {} was {}, but Connect cluster {} does not match label selector {} and will be ignored", connectorKind, connectorName, connectorNamespace, action, connectName, selectorLabels);
                                        return Future.succeededFuture();
                                    } else if (connect.getSpec() != null && connect.getSpec().getReplicas() == 0) {
                                        LOGGER.infoCr(reconciliation, "{} {} in namespace {} was {}, but Connect cluster {} has 0 replicas", connectorKind, connectorName, connectorNamespace, action, connectName);
                                        updateStatus(reconciliation, zeroReplicas(connectNamespace, connectName), kafkaConnector, connectOperator.connectorOperator);
                                        return Future.succeededFuture();
                                    } else {
                                        LOGGER.infoCr(reconciliation, "{} {} in namespace {} was {}", connectorKind, connectorName, connectorNamespace, action);
                                        return connectOperator.withLock(reconciliation, LOCK_TIMEOUT_MS, () -> connectOperator.reconcileConnectorAndHandleResult(reconciliation, KafkaConnectResources.qualifiedServiceName(connectName, connectNamespace), apiClient, isUseResources(connect), kafkaConnector.getMetadata().getName(), action == Action.DELETED ? null : kafkaConnector).compose(reconcileResult -> {
                                            LOGGER.infoCr(reconciliation, "reconciled");
                                            return Future.succeededFuture(reconcileResult);
                                        }));
                                    }
                                }
                            });
                        } else {
                            updateStatus(new Reconciliation("connector-watch", connectOperator.kind(), kafkaConnector.getMetadata().getNamespace(), null), new InvalidResourceException("Resource lacks label '" + Labels.STRIMZI_CLUSTER_LABEL + "': No connect cluster in which to create this connector."), kafkaConnector, connectOperator.connectorOperator);
                        }
                        break;
                    case ERROR:
                        LOGGER.errorCr(new Reconciliation("connector-watch", connectorKind, connectName, connectorNamespace), "Failed {} {} in namespace {} ", connectorKind, connectorName, connectorNamespace);
                        break;
                    default:
                        LOGGER.errorCr(new Reconciliation("connector-watch", connectorKind, connectName, connectorNamespace), "Unknown action: {} {} in namespace {}", connectorKind, connectorName, connectorNamespace);
                }
            }

            @Override
            public void onClose(WatcherException e) {
                if (e != null) {
                    throw new KubernetesClientException(e.getMessage());
                }
            }
        });
        return null;
    });
}
Also used : KafkaConnectorList(io.strimzi.api.kafka.KafkaConnectorList) OrderedProperties(io.strimzi.operator.common.model.OrderedProperties) LabelSelector(io.fabric8.kubernetes.api.model.LabelSelector) CustomResourceList(io.fabric8.kubernetes.client.CustomResourceList) BiFunction(java.util.function.BiFunction) Watcher(io.fabric8.kubernetes.client.Watcher) Annotations(io.strimzi.operator.common.Annotations) KafkaConnector(io.strimzi.api.kafka.model.KafkaConnector) ClusterRoleBindingOperator(io.strimzi.operator.common.operator.resource.ClusterRoleBindingOperator) ResourceVisitor(io.strimzi.operator.common.model.ResourceVisitor) Resource(io.fabric8.kubernetes.client.dsl.Resource) PodDisruptionBudgetV1Beta1Operator(io.strimzi.operator.common.operator.resource.PodDisruptionBudgetV1Beta1Operator) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) KafkaConnectStatus(io.strimzi.api.kafka.model.status.KafkaConnectStatus) Map(java.util.Map) KafkaConnectorSpec(io.strimzi.api.kafka.model.KafkaConnectorSpec) ANNO_STRIMZI_IO_RESTART_TASK(io.strimzi.operator.common.Annotations.ANNO_STRIMZI_IO_RESTART_TASK) ResourceOperatorSupplier(io.strimzi.operator.cluster.operator.resource.ResourceOperatorSupplier) JsonObject(io.vertx.core.json.JsonObject) Operator(io.strimzi.operator.common.Operator) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException) Counter(io.micrometer.core.instrument.Counter) AbstractOperator(io.strimzi.operator.common.AbstractOperator) StatusUtils(io.strimzi.operator.common.operator.resource.StatusUtils) KafkaConnect(io.strimzi.api.kafka.model.KafkaConnect) LabelSelectorBuilder(io.fabric8.kubernetes.api.model.LabelSelectorBuilder) ConnectTimeoutException(io.netty.channel.ConnectTimeoutException) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ValidationVisitor(io.strimzi.operator.common.model.ValidationVisitor) SecretOperator(io.strimzi.operator.common.operator.resource.SecretOperator) Set(java.util.Set) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Future(io.vertx.core.Future) Collectors(java.util.stream.Collectors) NoSuchResourceException(io.strimzi.operator.cluster.model.NoSuchResourceException) KafkaMirrorMaker2(io.strimzi.api.kafka.model.KafkaMirrorMaker2) KafkaConnectCluster(io.strimzi.operator.cluster.model.KafkaConnectCluster) List(java.util.List) ANNO_STRIMZI_IO_RESTART(io.strimzi.operator.common.Annotations.ANNO_STRIMZI_IO_RESTART) Labels(io.strimzi.operator.common.model.Labels) Stream(java.util.stream.Stream) KafkaConnectorStatus(io.strimzi.api.kafka.model.status.KafkaConnectorStatus) Secret(io.fabric8.kubernetes.api.model.Secret) Optional(java.util.Optional) Condition(io.strimzi.api.kafka.model.status.Condition) KafkaConnectList(io.strimzi.api.kafka.KafkaConnectList) PodDisruptionBudgetOperator(io.strimzi.operator.common.operator.resource.PodDisruptionBudgetOperator) PlatformFeaturesAvailability(io.strimzi.operator.PlatformFeaturesAvailability) ClusterOperatorConfig(io.strimzi.operator.cluster.ClusterOperatorConfig) CustomResource(io.fabric8.kubernetes.client.CustomResource) BackOff(io.strimzi.operator.common.BackOff) NetworkPolicyOperator(io.strimzi.operator.common.operator.resource.NetworkPolicyOperator) LocalObjectReference(io.fabric8.kubernetes.api.model.LocalObjectReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) WatcherException(io.fabric8.kubernetes.client.WatcherException) ServiceOperator(io.strimzi.operator.common.operator.resource.ServiceOperator) CompositeFuture(io.vertx.core.CompositeFuture) Timer(io.micrometer.core.instrument.Timer) ServiceAccountOperator(io.strimzi.operator.common.operator.resource.ServiceAccountOperator) ConfigMapOperator(io.strimzi.operator.common.operator.resource.ConfigMapOperator) CrdOperator(io.strimzi.operator.common.operator.resource.CrdOperator) Status(io.strimzi.api.kafka.model.status.Status) ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) LinkedHashSet(java.util.LinkedHashSet) KafkaConnectorBuilder(io.strimzi.api.kafka.model.KafkaConnectorBuilder) KafkaConnectorConfiguration(io.strimzi.operator.cluster.model.KafkaConnectorConfiguration) ReconciliationLogger(io.strimzi.operator.common.ReconciliationLogger) Collections.emptyMap(java.util.Collections.emptyMap) InvalidResourceException(io.strimzi.operator.cluster.model.InvalidResourceException) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) AbstractKafkaConnectSpec(io.strimzi.api.kafka.model.AbstractKafkaConnectSpec) ConnectorPlugin(io.strimzi.api.kafka.model.connect.ConnectorPlugin) ConfigMap(io.fabric8.kubernetes.api.model.ConfigMap) Reconciliation(io.strimzi.operator.common.Reconciliation) ImagePullPolicy(io.strimzi.operator.cluster.model.ImagePullPolicy) StatusDiff(io.strimzi.operator.cluster.model.StatusDiff) Util(io.strimzi.operator.common.Util) TreeMap(java.util.TreeMap) KubernetesClient(io.fabric8.kubernetes.client.KubernetesClient) NetworkPolicy(io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy) ServiceAccount(io.fabric8.kubernetes.api.model.ServiceAccount) KafkaConnectSpec(io.strimzi.api.kafka.model.KafkaConnectSpec) Collections(java.util.Collections) KafkaConnectResources(io.strimzi.api.kafka.model.KafkaConnectResources) LabelSelector(io.fabric8.kubernetes.api.model.LabelSelector) WatcherException(io.fabric8.kubernetes.client.WatcherException) InvalidResourceException(io.strimzi.operator.cluster.model.InvalidResourceException) Reconciliation(io.strimzi.operator.common.Reconciliation) KafkaConnector(io.strimzi.api.kafka.model.KafkaConnector) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Example 5 with ReconcileResult

use of io.strimzi.operator.common.operator.resource.ReconcileResult in project strimzi-kafka-operator by strimzi.

the class KafkaUserOperator method reconcileCredentialsQuotasAndAcls.

/**
 * Reconciles the credentials, quotas and ACLs
 *
 * @param reconciliation    Unique identification for the reconciliation
 * @param user              Model describing the KafkaUser
 * @param userStatus        Status subresource of the KafkaUser custom resource
 *
 * @return                  Future describing the result
 */
private CompositeFuture reconcileCredentialsQuotasAndAcls(Reconciliation reconciliation, KafkaUserModel user, KafkaUserStatus userStatus) {
    Set<SimpleAclRule> tlsAcls = null;
    Set<SimpleAclRule> scramOrNoneAcls = null;
    KafkaUserQuotas tlsQuotas = null;
    KafkaUserQuotas scramOrNoneQuotas = null;
    if (user.isTlsUser() || user.isTlsExternalUser()) {
        tlsAcls = user.getSimpleAclRules();
        tlsQuotas = user.getQuotas();
    } else if (user.isScramUser() || user.isNoneUser()) {
        scramOrNoneAcls = user.getSimpleAclRules();
        scramOrNoneQuotas = user.getQuotas();
    }
    // Reconcile the user SCRAM-SHA-512 credentials
    Future<ReconcileResult<String>> scramCredentialsFuture = scramCredentialsOperator.reconcile(reconciliation, user.getName(), user.getScramSha512Password());
    // Quotas need to reconciled for both regular and TLS username. It will be (possibly) set for one user and deleted for the other
    Future<ReconcileResult<KafkaUserQuotas>> tlsQuotasFuture = quotasOperator.reconcile(reconciliation, KafkaUserModel.getTlsUserName(reconciliation.name()), tlsQuotas);
    Future<ReconcileResult<KafkaUserQuotas>> quotasFuture = quotasOperator.reconcile(reconciliation, KafkaUserModel.getScramUserName(reconciliation.name()), scramOrNoneQuotas);
    // Reconcile the user secret generated by the user operator with the credentials
    Future<ReconcileResult<Secret>> userSecretFuture = reconcileUserSecret(reconciliation, user, userStatus);
    // ACLs need to reconciled for both regular and TLS username. It will be (possibly) set for one user and deleted for the other
    Future<ReconcileResult<Set<SimpleAclRule>>> aclsTlsUserFuture;
    Future<ReconcileResult<Set<SimpleAclRule>>> aclsScramUserFuture;
    if (config.isAclsAdminApiSupported()) {
        aclsTlsUserFuture = aclOperations.reconcile(reconciliation, KafkaUserModel.getTlsUserName(reconciliation.name()), tlsAcls);
        aclsScramUserFuture = aclOperations.reconcile(reconciliation, KafkaUserModel.getScramUserName(reconciliation.name()), scramOrNoneAcls);
    } else {
        aclsTlsUserFuture = Future.succeededFuture(ReconcileResult.noop(null));
        aclsScramUserFuture = Future.succeededFuture(ReconcileResult.noop(null));
    }
    return CompositeFuture.join(scramCredentialsFuture, tlsQuotasFuture, quotasFuture, aclsTlsUserFuture, aclsScramUserFuture, userSecretFuture);
}
Also used : KafkaUserQuotas(io.strimzi.api.kafka.model.KafkaUserQuotas) ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) SimpleAclRule(io.strimzi.operator.user.model.acl.SimpleAclRule)

Aggregations

ReconcileResult (io.strimzi.operator.common.operator.resource.ReconcileResult)10 LabelSelector (io.fabric8.kubernetes.api.model.LabelSelector)4 CustomResource (io.fabric8.kubernetes.client.CustomResource)4 WatcherException (io.fabric8.kubernetes.client.WatcherException)4 Counter (io.micrometer.core.instrument.Counter)4 Timer (io.micrometer.core.instrument.Timer)4 Condition (io.strimzi.api.kafka.model.status.Condition)4 Status (io.strimzi.api.kafka.model.status.Status)4 InvalidResourceException (io.strimzi.operator.cluster.model.InvalidResourceException)4 StatusDiff (io.strimzi.operator.cluster.model.StatusDiff)4 Labels (io.strimzi.operator.common.model.Labels)4 ResourceVisitor (io.strimzi.operator.common.model.ResourceVisitor)4 ValidationVisitor (io.strimzi.operator.common.model.ValidationVisitor)4 StatusUtils (io.strimzi.operator.common.operator.resource.StatusUtils)4 Future (io.vertx.core.Future)4 Promise (io.vertx.core.Promise)4 Vertx (io.vertx.core.Vertx)4 ArrayList (java.util.ArrayList)4 Collections (java.util.Collections)4 LinkedHashSet (java.util.LinkedHashSet)4