use of io.strimzi.operator.cluster.model.KafkaConnectCluster in project strimzi-kafka-operator by strimzi.
the class KafkaConnectAssemblyOperatorTest method testUpdateClusterWithFailedScaleDownSetsStatusNotReady.
@Test
public void testUpdateClusterWithFailedScaleDownSetsStatusNotReady(VertxTestContext context) {
ResourceOperatorSupplier supplier = ResourceUtils.supplierWithMocks(true);
var mockConnectOps = supplier.connectOperator;
DeploymentOperator mockDcOps = supplier.deploymentOperations;
PodDisruptionBudgetOperator mockPdbOps = supplier.podDisruptionBudgetOperator;
ConfigMapOperator mockCmOps = supplier.configMapOperations;
ServiceOperator mockServiceOps = supplier.serviceOperations;
NetworkPolicyOperator mockNetPolOps = supplier.networkPolicyOperator;
PodOperator mockPodOps = supplier.podOperations;
BuildConfigOperator mockBcOps = supplier.buildConfigOperations;
SecretOperator mockSecretOps = supplier.secretOperations;
String kcName = "foo";
String kcNamespace = "test";
String failureMsg = "failure";
KafkaConnect kc = ResourceUtils.createEmptyKafkaConnect(kcNamespace, kcName);
KafkaConnectCluster connect = KafkaConnectCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, kc, VERSIONS);
when(mockConnectOps.get(kcNamespace, kcName)).thenReturn(kc);
when(mockConnectOps.getAsync(anyString(), anyString())).thenReturn(Future.succeededFuture(kc));
when(mockServiceOps.reconcile(any(), anyString(), anyString(), any())).thenReturn(Future.succeededFuture());
when(mockDcOps.reconcile(any(), anyString(), anyString(), any())).thenReturn(Future.succeededFuture());
when(mockDcOps.getAsync(kcNamespace, connect.getName())).thenReturn(Future.succeededFuture(connect.generateDeployment(Map.of(), true, null, null)));
when(mockDcOps.scaleUp(any(), anyString(), anyString(), anyInt())).thenReturn(Future.succeededFuture(42));
when(mockDcOps.scaleDown(any(), anyString(), anyString(), anyInt())).thenReturn(Future.failedFuture(failureMsg));
when(mockDcOps.readiness(any(), anyString(), anyString(), anyLong(), anyLong())).thenReturn(Future.succeededFuture());
when(mockDcOps.waitForObserved(any(), anyString(), anyString(), anyLong(), anyLong())).thenReturn(Future.succeededFuture());
when(mockCmOps.reconcile(any(), anyString(), any(), any())).thenReturn(Future.succeededFuture(ReconcileResult.created(new ConfigMap())));
when(mockNetPolOps.reconcile(any(), eq(kc.getMetadata().getNamespace()), eq(KafkaConnectResources.deploymentName(kc.getMetadata().getName())), any())).thenReturn(Future.succeededFuture(ReconcileResult.created(new NetworkPolicy())));
when(mockPodOps.reconcile(any(), eq(kc.getMetadata().getNamespace()), eq(KafkaConnectResources.buildPodName(kc.getMetadata().getName())), eq(null))).thenReturn(Future.succeededFuture(ReconcileResult.noop(null)));
when(mockBcOps.reconcile(any(), eq(kc.getMetadata().getNamespace()), eq(KafkaConnectResources.buildConfigName(kc.getMetadata().getName())), eq(null))).thenReturn(Future.succeededFuture(ReconcileResult.noop(null)));
when(mockPdbOps.reconcile(any(), anyString(), any(), any())).thenReturn(Future.succeededFuture());
when(mockSecretOps.reconcile(any(), anyString(), anyString(), any())).thenReturn(Future.succeededFuture());
ArgumentCaptor<KafkaConnect> connectCaptor = ArgumentCaptor.forClass(KafkaConnect.class);
when(mockConnectOps.updateStatusAsync(any(), connectCaptor.capture())).thenReturn(Future.succeededFuture());
KafkaConnectAssemblyOperator ops = new KafkaConnectAssemblyOperator(vertx, new PlatformFeaturesAvailability(true, kubernetesVersion), supplier, ResourceUtils.dummyClusterOperatorConfig(VERSIONS));
Checkpoint async = context.checkpoint();
ops.reconcile(new Reconciliation("test-trigger", KafkaConnect.RESOURCE_KIND, kcNamespace, kcName)).onComplete(context.failing(v -> context.verify(() -> {
// Verify status
List<KafkaConnect> capturedConnects = connectCaptor.getAllValues();
assertThat(capturedConnects, hasSize(1));
KafkaConnectStatus connectStatus = capturedConnects.get(0).getStatus();
assertThat(connectStatus.getUrl(), is("http://foo-connect-api.test.svc:8083"));
assertThat(connectStatus.getConditions().get(0).getStatus(), is("True"));
assertThat(connectStatus.getConditions().get(0).getType(), is("NotReady"));
assertThat(connectStatus.getConditions().get(0).getMessage(), is(failureMsg));
async.flag();
})));
}
use of io.strimzi.operator.cluster.model.KafkaConnectCluster in project strimzi-kafka-operator by strimzi.
the class KafkaConnectAssemblyOperator method createOrUpdate.
@Override
protected Future<KafkaConnectStatus> createOrUpdate(Reconciliation reconciliation, KafkaConnect kafkaConnect) {
KafkaConnectCluster connect;
KafkaConnectBuild build;
KafkaConnectStatus kafkaConnectStatus = new KafkaConnectStatus();
try {
connect = KafkaConnectCluster.fromCrd(reconciliation, kafkaConnect, versions);
build = KafkaConnectBuild.fromCrd(reconciliation, kafkaConnect, versions);
} catch (Exception e) {
LOGGER.warnCr(reconciliation, e);
StatusUtils.setStatusConditionAndObservedGeneration(kafkaConnect, kafkaConnectStatus, Future.failedFuture(e));
return Future.failedFuture(new ReconciliationException(kafkaConnectStatus, e));
}
Promise<KafkaConnectStatus> createOrUpdatePromise = Promise.promise();
String namespace = reconciliation.namespace();
Map<String, String> annotations = new HashMap<>(2);
boolean connectHasZeroReplicas = connect.getReplicas() == 0;
final AtomicReference<String> image = new AtomicReference<>();
final AtomicReference<String> desiredLogging = new AtomicReference<>();
String initCrbName = KafkaConnectResources.initContainerClusterRoleBindingName(kafkaConnect.getMetadata().getName(), namespace);
ClusterRoleBinding initCrb = connect.generateClusterRoleBinding();
LOGGER.debugCr(reconciliation, "Updating Kafka Connect cluster");
connectServiceAccount(reconciliation, namespace, KafkaConnectResources.serviceAccountName(connect.getCluster()), connect).compose(i -> connectInitClusterRoleBinding(reconciliation, initCrbName, initCrb)).compose(i -> connectNetworkPolicy(reconciliation, namespace, connect, isUseResources(kafkaConnect))).compose(i -> connectBuildOperator.reconcile(reconciliation, namespace, connect.getName(), build)).compose(buildInfo -> {
if (buildInfo != null) {
annotations.put(Annotations.STRIMZI_IO_CONNECT_BUILD_REVISION, buildInfo.getBuildRevision());
image.set(buildInfo.getImage());
}
return Future.succeededFuture();
}).compose(i -> deploymentOperations.scaleDown(reconciliation, namespace, connect.getName(), connect.getReplicas())).compose(i -> serviceOperations.reconcile(reconciliation, namespace, connect.getServiceName(), connect.generateService())).compose(i -> generateMetricsAndLoggingConfigMap(reconciliation, namespace, connect)).compose(logAndMetricsConfigMap -> {
String logging = logAndMetricsConfigMap.getData().get(AbstractModel.ANCILLARY_CM_KEY_LOG_CONFIG);
annotations.put(Annotations.ANNO_STRIMZI_LOGGING_DYNAMICALLY_UNCHANGEABLE_HASH, Util.hashStub(Util.getLoggingDynamicallyUnmodifiableEntries(logging)));
desiredLogging.set(logging);
return configMapOperations.reconcile(reconciliation, namespace, connect.getAncillaryConfigMapName(), logAndMetricsConfigMap);
}).compose(i -> kafkaConnectJmxSecret(reconciliation, namespace, kafkaConnect.getMetadata().getName(), connect)).compose(i -> pfa.hasPodDisruptionBudgetV1() ? podDisruptionBudgetOperator.reconcile(reconciliation, namespace, connect.getName(), connect.generatePodDisruptionBudget()) : Future.succeededFuture()).compose(i -> !pfa.hasPodDisruptionBudgetV1() ? podDisruptionBudgetV1Beta1Operator.reconcile(reconciliation, namespace, connect.getName(), connect.generatePodDisruptionBudgetV1Beta1()) : Future.succeededFuture()).compose(i -> generateAuthHash(namespace, kafkaConnect.getSpec())).compose(hash -> {
annotations.put(Annotations.ANNO_STRIMZI_AUTH_HASH, Integer.toString(hash));
Deployment deployment = generateDeployment(connect, image.get(), annotations);
return deploymentOperations.reconcile(reconciliation, namespace, connect.getName(), deployment);
}).compose(i -> deploymentOperations.scaleUp(reconciliation, namespace, connect.getName(), connect.getReplicas())).compose(i -> deploymentOperations.waitForObserved(reconciliation, namespace, connect.getName(), 1_000, operationTimeoutMs)).compose(i -> connectHasZeroReplicas ? Future.succeededFuture() : deploymentOperations.readiness(reconciliation, namespace, connect.getName(), 1_000, operationTimeoutMs)).compose(i -> reconcileConnectors(reconciliation, kafkaConnect, kafkaConnectStatus, connectHasZeroReplicas, desiredLogging.get(), connect.getDefaultLogConfig())).onComplete(reconciliationResult -> {
StatusUtils.setStatusConditionAndObservedGeneration(kafkaConnect, kafkaConnectStatus, reconciliationResult);
if (!connectHasZeroReplicas) {
kafkaConnectStatus.setUrl(KafkaConnectResources.url(connect.getCluster(), namespace, KafkaConnectCluster.REST_API_PORT));
}
kafkaConnectStatus.setReplicas(connect.getReplicas());
kafkaConnectStatus.setLabelSelector(connect.getSelectorLabels().toSelectorString());
if (reconciliationResult.succeeded()) {
createOrUpdatePromise.complete(kafkaConnectStatus);
} else {
createOrUpdatePromise.fail(new ReconciliationException(kafkaConnectStatus, reconciliationResult.cause()));
}
});
return createOrUpdatePromise.future();
}
Aggregations