Search in sources :

Example 6 with Condition

use of io.fabric8.kubernetes.api.model.Condition in project strimzi by strimzi.

the class KafkaRebalanceAssemblyOperatorTest method testNewWithMissingHardGoalsAndRefresh.

/**
 * Tests the transition from 'New' to 'NotReady' due to "missing hard goals" error
 * The KafkaRebalance resource is updated with "skip hard goals check" and refreshed; it then moves to the 'ProposalReady' state
 *
 * 1. A new KafkaRebalance resource is created with some specified not hard goals; it is in the New state
 * 2. The operator requests a rebalance proposal through the Cruise Control REST API
 * 3. The operator receives a "missing hard goals" error instead of a proposal
 * 4. The KafkaRebalance resource moves to the 'NotReady' state
 * 5. The rebalance is updated with the 'skip hard goals check' field to "true" and annotated with 'strimzi.io/rebalance=refresh'
 * 6. The operator requests a rebalance proposal through the Cruise Control REST API
 * 7. The rebalance proposal is ready on the first call
 * 8. The KafkaRebalance resource moves to the 'ProposalReady' state
 */
@Test
public void testNewWithMissingHardGoalsAndRefresh(VertxTestContext context) throws IOException, URISyntaxException {
    // Setup the rebalance endpoint to get error about hard goals
    MockCruiseControl.setupCCRebalanceBadGoalsError(ccServer);
    KafkaRebalanceSpec kafkaRebalanceSpec = new KafkaRebalanceSpecBuilder().withGoals("DiskCapacityGoal", "CpuCapacityGoal").build();
    KafkaRebalance kr = createKafkaRebalance(CLUSTER_NAMESPACE, CLUSTER_NAME, RESOURCE_NAME, kafkaRebalanceSpec);
    Crds.kafkaRebalanceOperation(kubernetesClient).inNamespace(CLUSTER_NAMESPACE).create(kr);
    // the Kafka cluster isn't deployed in the namespace
    when(mockKafkaOps.getAsync(CLUSTER_NAMESPACE, CLUSTER_NAME)).thenReturn(Future.succeededFuture(kafka));
    mockSecretResources();
    mockRebalanceOperator(mockRebalanceOps, mockCmOps, CLUSTER_NAMESPACE, RESOURCE_NAME, kubernetesClient);
    Checkpoint checkpoint = context.checkpoint();
    kcrao.reconcileRebalance(new Reconciliation("test-trigger", KafkaRebalance.RESOURCE_KIND, CLUSTER_NAMESPACE, RESOURCE_NAME), kr).onComplete(context.succeeding(v -> context.verify(() -> {
        // the resource moved from New to NotReady due to the error
        KafkaRebalance kr1 = Crds.kafkaRebalanceOperation(kubernetesClient).inNamespace(CLUSTER_NAMESPACE).withName(RESOURCE_NAME).get();
        assertThat(kr1, StateMatchers.hasState());
        Condition condition = kcrao.rebalanceStateCondition(kr1.getStatus());
        assertThat(condition, StateMatchers.hasStateInCondition(KafkaRebalanceState.NotReady, CruiseControlRestException.class, "Error processing POST request '/rebalance' due to: " + "'java.lang.IllegalArgumentException: Missing hard goals [NetworkInboundCapacityGoal, DiskCapacityGoal, RackAwareGoal, NetworkOutboundCapacityGoal, CpuCapacityGoal, ReplicaCapacityGoal] " + "in the provided goals: [RackAwareGoal, ReplicaCapacityGoal]. " + "Add skip_hard_goal_check=true parameter to ignore this sanity check.'."));
    }))).compose(v -> {
        ccServer.reset();
        try {
            // Setup the rebalance endpoint with the number of pending calls before a response is received.
            MockCruiseControl.setupCCRebalanceResponse(ccServer, 0);
        } catch (IOException | URISyntaxException e) {
            context.failNow(e);
        }
        // set the skip hard goals check flag
        KafkaRebalance kr2 = Crds.kafkaRebalanceOperation(kubernetesClient).inNamespace(CLUSTER_NAMESPACE).withName(RESOURCE_NAME).get();
        KafkaRebalance patchedKr = new KafkaRebalanceBuilder(kr2).editSpec().withSkipHardGoalCheck(true).endSpec().build();
        Crds.kafkaRebalanceOperation(kubernetesClient).inNamespace(CLUSTER_NAMESPACE).withName(RESOURCE_NAME).patch(patchedKr);
        // apply the "refresh" annotation to the resource in the NotReady state
        patchedKr = annotate(kubernetesClient, CLUSTER_NAMESPACE, RESOURCE_NAME, KafkaRebalanceAnnotation.refresh);
        // trigger another reconcile to process the NotReady state
        return kcrao.reconcileRebalance(new Reconciliation("test-trigger", KafkaRebalance.RESOURCE_KIND, CLUSTER_NAMESPACE, RESOURCE_NAME), patchedKr);
    }).onComplete(context.succeeding(v -> {
        // the resource transitioned from 'NotReady' to 'ProposalReady'
        assertState(context, kubernetesClient, CLUSTER_NAMESPACE, RESOURCE_NAME, KafkaRebalanceState.ProposalReady);
        checkpoint.flag();
    }));
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) URISyntaxException(java.net.URISyntaxException) Annotations(io.strimzi.operator.common.Annotations) KafkaRebalanceSpecBuilder(io.strimzi.api.kafka.model.KafkaRebalanceSpecBuilder) MockKube(io.strimzi.test.mockkube.MockKube) AfterAll(org.junit.jupiter.api.AfterAll) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Collections.singleton(java.util.Collections.singleton) BeforeAll(org.junit.jupiter.api.BeforeAll) Map(java.util.Map) Matchers.nullValue(org.hamcrest.Matchers.nullValue) ResourceOperatorSupplier(io.strimzi.operator.cluster.operator.resource.ResourceOperatorSupplier) ResourceUtils(io.strimzi.operator.cluster.ResourceUtils) KafkaRebalance(io.strimzi.api.kafka.model.KafkaRebalance) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) SecretOperator(io.strimzi.operator.common.operator.resource.SecretOperator) VertxExtension(io.vertx.junit5.VertxExtension) KafkaRebalanceList(io.strimzi.api.kafka.KafkaRebalanceList) KafkaRebalanceAnnotation(io.strimzi.api.kafka.model.balancing.KafkaRebalanceAnnotation) Future(io.vertx.core.Future) NoSuchResourceException(io.strimzi.operator.cluster.model.NoSuchResourceException) ClientAndServer(org.mockserver.integration.ClientAndServer) CruiseControlResources(io.strimzi.api.kafka.model.CruiseControlResources) Test(org.junit.jupiter.api.Test) Labels(io.strimzi.operator.common.model.Labels) CruiseControlApi(io.strimzi.operator.cluster.operator.resource.cruisecontrol.CruiseControlApi) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Secret(io.fabric8.kubernetes.api.model.Secret) Optional(java.util.Optional) Checkpoint(io.vertx.junit5.Checkpoint) Matchers.is(org.hamcrest.Matchers.is) Condition(io.strimzi.api.kafka.model.status.Condition) PlatformFeaturesAvailability(io.strimzi.operator.PlatformFeaturesAvailability) ClusterOperatorConfig(io.strimzi.operator.cluster.ClusterOperatorConfig) VertxTestContext(io.vertx.junit5.VertxTestContext) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) KafkaList(io.strimzi.api.kafka.KafkaList) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) KafkaRebalanceState(io.strimzi.api.kafka.model.balancing.KafkaRebalanceState) KafkaRebalanceBuilder(io.strimzi.api.kafka.model.KafkaRebalanceBuilder) CruiseControlApiImpl(io.strimzi.operator.cluster.operator.resource.cruisecontrol.CruiseControlApiImpl) Crds(io.strimzi.api.kafka.Crds) KafkaRebalanceSpec(io.strimzi.api.kafka.model.KafkaRebalanceSpec) KafkaBuilder(io.strimzi.api.kafka.model.KafkaBuilder) Mockito.verifyZeroInteractions(org.mockito.Mockito.verifyZeroInteractions) KafkaVersionTestUtils(io.strimzi.operator.cluster.KafkaVersionTestUtils) ConfigMapOperator(io.strimzi.operator.common.operator.resource.ConfigMapOperator) CrdOperator(io.strimzi.operator.common.operator.resource.CrdOperator) TestUtils(io.strimzi.test.TestUtils) ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) ConnectException(java.net.ConnectException) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) NoStackTraceTimeoutException(io.strimzi.operator.common.operator.resource.NoStackTraceTimeoutException) CruiseControl(io.strimzi.operator.cluster.model.CruiseControl) InvalidResourceException(io.strimzi.operator.cluster.model.InvalidResourceException) KubernetesVersion(io.strimzi.operator.KubernetesVersion) Vertx(io.vertx.core.Vertx) IOException(java.io.IOException) Mockito.when(org.mockito.Mockito.when) ConfigMap(io.fabric8.kubernetes.api.model.ConfigMap) KafkaRebalanceStatus(io.strimzi.api.kafka.model.status.KafkaRebalanceStatus) Reconciliation(io.strimzi.operator.common.Reconciliation) AfterEach(org.junit.jupiter.api.AfterEach) KubernetesClient(io.fabric8.kubernetes.client.KubernetesClient) Kafka(io.strimzi.api.kafka.model.Kafka) CruiseControlRestException(io.strimzi.operator.cluster.operator.resource.cruisecontrol.CruiseControlRestException) MockCruiseControl(io.strimzi.operator.cluster.operator.resource.cruisecontrol.MockCruiseControl) Collections(java.util.Collections) Condition(io.strimzi.api.kafka.model.status.Condition) Checkpoint(io.vertx.junit5.Checkpoint) KafkaRebalanceSpec(io.strimzi.api.kafka.model.KafkaRebalanceSpec) Reconciliation(io.strimzi.operator.common.Reconciliation) KafkaRebalanceBuilder(io.strimzi.api.kafka.model.KafkaRebalanceBuilder) KafkaRebalanceSpecBuilder(io.strimzi.api.kafka.model.KafkaRebalanceSpecBuilder) KafkaRebalance(io.strimzi.api.kafka.model.KafkaRebalance) CruiseControlRestException(io.strimzi.operator.cluster.operator.resource.cruisecontrol.CruiseControlRestException) Test(org.junit.jupiter.api.Test)

Example 7 with Condition

use of io.fabric8.kubernetes.api.model.Condition 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 8 with Condition

use of io.fabric8.kubernetes.api.model.Condition in project strimzi by strimzi.

the class OperatorMetricsTest method testDeleteCountsReconcile.

@Test
public void testDeleteCountsReconcile(VertxTestContext context) {
    MetricsProvider metrics = createCleanMetricsProvider();
    AbstractWatchableStatusedResourceOperator resourceOperator = new AbstractWatchableStatusedResourceOperator(vertx, null, "TestResource") {

        @Override
        protected MixedOperation operation() {
            return null;
        }

        @Override
        public HasMetadata get(String namespace, String name) {
            return null;
        }

        @Override
        public Future updateStatusAsync(Reconciliation reconciliation, HasMetadata resource) {
            return null;
        }
    };
    AbstractOperator operator = new AbstractOperator(vertx, "TestResource", resourceOperator, metrics, null) {

        @Override
        protected Future createOrUpdate(Reconciliation reconciliation, CustomResource resource) {
            return null;
        }

        @Override
        public Set<Condition> validate(Reconciliation reconciliation, CustomResource resource) {
            // Do nothing
            return emptySet();
        }

        @Override
        protected Future<Boolean> delete(Reconciliation reconciliation) {
            return Future.succeededFuture(Boolean.TRUE);
        }

        @Override
        protected Status createStatus() {
            return new Status() {
            };
        }
    };
    Checkpoint async = context.checkpoint();
    operator.reconcile(new Reconciliation("test", "TestResource", "my-namespace", "my-resource")).onComplete(context.succeeding(v -> context.verify(() -> {
        MeterRegistry registry = metrics.meterRegistry();
        Tag selectorTag = Tag.of("selector", "");
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations").tag("kind", "TestResource").counter().count(), is(1.0));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.successful").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.successful").tag("kind", "TestResource").counter().count(), is(1.0));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.duration").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.duration").tag("kind", "TestResource").timer().count(), is(1L));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.duration").tag("kind", "TestResource").timer().totalTime(TimeUnit.MILLISECONDS), greaterThan(0.0));
        assertThrows(MeterNotFoundException.class, () -> {
            registry.get(AbstractOperator.METRICS_PREFIX + "resource.state").tag("kind", "TestResource").tag("name", "my-resource").tag("resource-namespace", "my-namespace").gauge();
        });
        async.flag();
    })));
}
Also used : Condition(io.strimzi.api.kafka.model.status.Condition) Status(io.strimzi.api.kafka.model.status.Status) VertxTestContext(io.vertx.junit5.VertxTestContext) CoreMatchers.is(org.hamcrest.CoreMatchers.is) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) MixedOperation(io.fabric8.kubernetes.client.dsl.MixedOperation) AfterAll(org.junit.jupiter.api.AfterAll) HashSet(java.util.HashSet) MicrometerMetricsOptions(io.vertx.micrometer.MicrometerMetricsOptions) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) BeforeAll(org.junit.jupiter.api.BeforeAll) Status(io.strimzi.api.kafka.model.status.Status) Collections.singletonMap(java.util.Collections.singletonMap) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Version(io.fabric8.kubernetes.model.annotation.Version) Tag(io.micrometer.core.instrument.Tag) Collections.emptyMap(java.util.Collections.emptyMap) MeterNotFoundException(io.micrometer.core.instrument.search.MeterNotFoundException) Collections.emptySet(java.util.Collections.emptySet) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) VertxOptions(io.vertx.core.VertxOptions) Set(java.util.Set) VertxPrometheusOptions(io.vertx.micrometer.VertxPrometheusOptions) VertxExtension(io.vertx.junit5.VertxExtension) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Spec(io.strimzi.api.kafka.model.Spec) Future(io.vertx.core.Future) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) NamespaceAndName(io.strimzi.operator.common.model.NamespaceAndName) Labels(io.strimzi.operator.common.model.Labels) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) AbstractWatchableStatusedResourceOperator(io.strimzi.operator.common.operator.resource.AbstractWatchableStatusedResourceOperator) Group(io.fabric8.kubernetes.model.annotation.Group) Checkpoint(io.vertx.junit5.Checkpoint) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Condition(io.strimzi.api.kafka.model.status.Condition) Collections(java.util.Collections) CustomResource(io.fabric8.kubernetes.client.CustomResource) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) CustomResource(io.fabric8.kubernetes.client.CustomResource) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) Checkpoint(io.vertx.junit5.Checkpoint) AbstractWatchableStatusedResourceOperator(io.strimzi.operator.common.operator.resource.AbstractWatchableStatusedResourceOperator) Tag(io.micrometer.core.instrument.Tag) Test(org.junit.jupiter.api.Test)

Example 9 with Condition

use of io.fabric8.kubernetes.api.model.Condition in project strimzi by strimzi.

the class OperatorMetricsTest method testPauseReconcile.

@Test
public void testPauseReconcile(VertxTestContext context) {
    MetricsProvider metrics = createCleanMetricsProvider();
    AbstractWatchableStatusedResourceOperator resourceOperator = resourceOperatorWithExistingPausedResource();
    AbstractOperator operator = new AbstractOperator(vertx, "TestResource", resourceOperator, metrics, null) {

        @Override
        protected Future createOrUpdate(Reconciliation reconciliation, CustomResource resource) {
            return Future.succeededFuture();
        }

        @Override
        public Set<Condition> validate(Reconciliation reconciliation, CustomResource resource) {
            return new HashSet<>();
        }

        @Override
        protected Future<Boolean> delete(Reconciliation reconciliation) {
            return null;
        }

        @Override
        protected Status createStatus() {
            return new Status() {
            };
        }
    };
    Checkpoint async = context.checkpoint();
    operator.reconcile(new Reconciliation("test", "TestResource", "my-namespace", "my-resource")).onComplete(context.succeeding(v -> context.verify(() -> {
        MeterRegistry registry = metrics.meterRegistry();
        Tag selectorTag = Tag.of("selector", "");
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations").tag("kind", "TestResource").counter().count(), is(1.0));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.successful").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.successful").tag("kind", "TestResource").counter().count(), is(1.0));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "resources.paused").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "resources.paused").tag("kind", "TestResource").gauge().value(), is(1.0));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.duration").meter().getId().getTags().get(2), is(selectorTag));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.duration").tag("kind", "TestResource").timer().count(), is(1L));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "reconciliations.duration").tag("kind", "TestResource").timer().totalTime(TimeUnit.MILLISECONDS), greaterThan(0.0));
        assertThat(registry.get(AbstractOperator.METRICS_PREFIX + "resource.state").tag("kind", "TestResource").tag("name", "my-resource").tag("resource-namespace", "my-namespace").gauge().value(), is(1.0));
        async.flag();
    })));
}
Also used : Condition(io.strimzi.api.kafka.model.status.Condition) Status(io.strimzi.api.kafka.model.status.Status) VertxTestContext(io.vertx.junit5.VertxTestContext) CoreMatchers.is(org.hamcrest.CoreMatchers.is) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) MixedOperation(io.fabric8.kubernetes.client.dsl.MixedOperation) AfterAll(org.junit.jupiter.api.AfterAll) HashSet(java.util.HashSet) MicrometerMetricsOptions(io.vertx.micrometer.MicrometerMetricsOptions) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) BeforeAll(org.junit.jupiter.api.BeforeAll) Status(io.strimzi.api.kafka.model.status.Status) Collections.singletonMap(java.util.Collections.singletonMap) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Version(io.fabric8.kubernetes.model.annotation.Version) Tag(io.micrometer.core.instrument.Tag) Collections.emptyMap(java.util.Collections.emptyMap) MeterNotFoundException(io.micrometer.core.instrument.search.MeterNotFoundException) Collections.emptySet(java.util.Collections.emptySet) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) VertxOptions(io.vertx.core.VertxOptions) Set(java.util.Set) VertxPrometheusOptions(io.vertx.micrometer.VertxPrometheusOptions) VertxExtension(io.vertx.junit5.VertxExtension) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Spec(io.strimzi.api.kafka.model.Spec) Future(io.vertx.core.Future) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) NamespaceAndName(io.strimzi.operator.common.model.NamespaceAndName) Labels(io.strimzi.operator.common.model.Labels) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) AbstractWatchableStatusedResourceOperator(io.strimzi.operator.common.operator.resource.AbstractWatchableStatusedResourceOperator) Group(io.fabric8.kubernetes.model.annotation.Group) Checkpoint(io.vertx.junit5.Checkpoint) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Condition(io.strimzi.api.kafka.model.status.Condition) Collections(java.util.Collections) CustomResource(io.fabric8.kubernetes.client.CustomResource) CustomResource(io.fabric8.kubernetes.client.CustomResource) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) Checkpoint(io.vertx.junit5.Checkpoint) AbstractWatchableStatusedResourceOperator(io.strimzi.operator.common.operator.resource.AbstractWatchableStatusedResourceOperator) Tag(io.micrometer.core.instrument.Tag) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test)

Example 10 with Condition

use of io.fabric8.kubernetes.api.model.Condition in project strimzi by strimzi.

the class ValidationVisitorTest method testValidationErrorsAreLogged.

@Test
public void testValidationErrorsAreLogged() {
    Kafka k = TestUtils.fromYaml("/example.yaml", Kafka.class, true);
    assertThat(k, is(notNullValue()));
    TestLogger logger = TestLogger.create(ValidationVisitorTest.class);
    HasMetadata resource = new KafkaBuilder().withNewMetadata().withName("testname").withNamespace("testnamespace").endMetadata().withApiVersion("v1beta2").build();
    Set<Condition> warningConditions = new HashSet<>();
    ResourceVisitor.visit(Reconciliation.DUMMY_RECONCILIATION, k, new ValidationVisitor(resource, logger, warningConditions));
    List<String> warningMessages = warningConditions.stream().map(Condition::getMessage).collect(Collectors.toList());
    assertThat(warningMessages, hasItem("Contains object at path spec.kafka with an unknown property: foo"));
    assertThat(warningMessages, hasItem("In API version v1beta2 the enableECDSA property at path spec.kafka.listeners.auth.enableECDSA has been deprecated."));
    assertThat(warningMessages, hasItem("In API version v1beta2 the service property at path spec.kafkaExporter.template.service has been deprecated. " + "The Kafka Exporter service has been removed."));
    logger.assertLoggedAtLeastOnce(lm -> lm.level() == Level.WARN && lm.formattedMessage().matches("Reconciliation #[0-9]*\\(test\\) kind\\(namespace\\/name\\): " + "Contains object at path spec.kafka with an unknown property: foo"));
    logger.assertLoggedAtLeastOnce(lm -> lm.level() == Level.WARN && lm.formattedMessage().matches("Reconciliation #[0-9]*\\(test\\) kind\\(namespace\\/name\\): " + "In API version v1beta2 the enableECDSA property at path spec.kafka.listeners.auth.enableECDSA has been deprecated."));
    logger.assertLoggedAtLeastOnce(lm -> lm.level() == Level.WARN && lm.formattedMessage().matches("Reconciliation #[0-9]*\\(test\\) kind\\(namespace\\/name\\): " + "In API version v1beta2 the service property at path spec.kafkaExporter.template.service has been deprecated. " + "The Kafka Exporter service has been removed."));
}
Also used : Condition(io.strimzi.api.kafka.model.status.Condition) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Kafka(io.strimzi.api.kafka.model.Kafka) KafkaBuilder(io.strimzi.api.kafka.model.KafkaBuilder) TestLogger(io.strimzi.test.logging.TestLogger) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test)

Aggregations

Condition (io.strimzi.api.kafka.model.status.Condition)46 Collections (java.util.Collections)36 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)32 Vertx (io.vertx.core.Vertx)30 Labels (io.strimzi.operator.common.model.Labels)28 Future (io.vertx.core.Future)28 BeforeAll (org.junit.jupiter.api.BeforeAll)28 Map (java.util.Map)27 Test (org.junit.jupiter.api.Test)25 Promise (io.vertx.core.Promise)22 List (java.util.List)21 Checkpoint (io.vertx.junit5.Checkpoint)20 VertxExtension (io.vertx.junit5.VertxExtension)20 VertxTestContext (io.vertx.junit5.VertxTestContext)20 CoreMatchers.is (org.hamcrest.CoreMatchers.is)20 AfterAll (org.junit.jupiter.api.AfterAll)20 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)20 Annotations (io.strimzi.operator.common.Annotations)18 HasMetadata (io.fabric8.kubernetes.api.model.HasMetadata)16 KubernetesClient (io.fabric8.kubernetes.client.KubernetesClient)16