use of io.strimzi.operator.cluster.model.InvalidResourceException in project strimzi by strimzi.
the class KafkaUserModelTest method testFromCrdAclsWithAclsAdminApiSupportMissing.
@Test
public void testFromCrdAclsWithAclsAdminApiSupportMissing() {
InvalidResourceException e = assertThrows(InvalidResourceException.class, () -> KafkaUserModel.fromCrd(scramShaUser, UserOperatorConfig.DEFAULT_SECRET_PREFIX, false));
assertThat(e.getMessage(), is("Simple authorization ACL rules are configured but not supported in the Kafka cluster configuration."));
}
use of io.strimzi.operator.cluster.model.InvalidResourceException in project strimzi by strimzi.
the class KafkaUserModel method maybeGeneratePassword.
/**
* Prepares password for further use. It either takes the password specified by the user, re-uses the existing
* password or generates a new one.
*
* @param reconciliation The reconciliation.
* @param generator The password generator.
* @param userSecret The Secret containing any existing password.
* @param desiredPasswordSecret The Secret with the desired password specified by the user
*/
public void maybeGeneratePassword(Reconciliation reconciliation, PasswordGenerator generator, Secret userSecret, Secret desiredPasswordSecret) {
if (isUserWithDesiredPassword()) {
// User requested custom secret
if (desiredPasswordSecret == null) {
throw new InvalidResourceException("Secret " + desiredPasswordSecretName() + " with requested user password does not exist.");
}
String password = desiredPasswordSecret.getData().get(desiredPasswordSecretKey());
if (password == null) {
throw new InvalidResourceException("Secret " + desiredPasswordSecretName() + " does not contain the key " + desiredPasswordSecretKey() + " with requested user password.");
} else if (password.isEmpty()) {
throw new InvalidResourceException("The requested user password is empty.");
}
LOGGER.debugCr(reconciliation, "Loading request password from Kubernetes Secret {}", desiredPasswordSecretName());
this.scramSha512Password = new String(Base64.getDecoder().decode(password), StandardCharsets.US_ASCII);
return;
} else if (userSecret != null) {
// Secret already exists -> lets verify if it has a password
String password = userSecret.getData().get(KEY_PASSWORD);
if (password != null && !password.isEmpty()) {
LOGGER.debugCr(reconciliation, "Re-using password which already exists");
this.scramSha512Password = new String(Base64.getDecoder().decode(password), StandardCharsets.US_ASCII);
return;
}
}
LOGGER.debugCr(reconciliation, "Generating user password");
this.scramSha512Password = generator.generate();
}
use of io.strimzi.operator.cluster.model.InvalidResourceException in project strimzi by strimzi.
the class AbstractConnectOperator method reconcileConnector.
private Future<Void> reconcileConnector(Reconciliation reconciliation, String host, KafkaConnectApi apiClient, boolean useResources, String connectorName, KafkaConnector connector) {
if (connector == null) {
if (useResources) {
LOGGER.infoCr(reconciliation, "deleting connector: {}", connectorName);
return apiClient.delete(reconciliation, host, port, connectorName);
} else {
return Future.succeededFuture();
}
} else {
LOGGER.infoCr(reconciliation, "creating/updating connector: {}", connectorName);
if (connector.getSpec() == null) {
return maybeUpdateConnectorStatus(reconciliation, connector, null, new InvalidResourceException("spec property is required"));
}
if (!useResources) {
return maybeUpdateConnectorStatus(reconciliation, connector, null, new NoSuchResourceException(reconciliation.kind() + " " + reconciliation.name() + " is not configured with annotation " + Annotations.STRIMZI_IO_USE_CONNECTOR_RESOURCES));
} else {
Promise<Void> promise = Promise.promise();
maybeCreateOrUpdateConnector(reconciliation, host, apiClient, connectorName, connector.getSpec(), connector).onComplete(result -> {
if (result.succeeded()) {
maybeUpdateConnectorStatus(reconciliation, connector, result.result(), null).onComplete(promise);
} else {
maybeUpdateConnectorStatus(reconciliation, connector, result.result(), result.cause()).onComplete(promise);
}
});
return promise.future();
}
}
}
use of io.strimzi.operator.cluster.model.InvalidResourceException in project strimzi by strimzi.
the class KafkaMirrorMaker2AssemblyOperator method reconcileConnectors.
/**
* Reconcile all the MirrorMaker 2.0 connectors selected by the given MirrorMaker 2.0 instance.
* @param reconciliation The reconciliation
* @param kafkaMirrorMaker2 The MirrorMaker 2.0
* @return A future, failed if any of the connectors could not be reconciled.
*/
protected Future<Void> reconcileConnectors(Reconciliation reconciliation, KafkaMirrorMaker2 kafkaMirrorMaker2, KafkaMirrorMaker2Cluster mirrorMaker2Cluster, KafkaMirrorMaker2Status mirrorMaker2Status, String desiredLogging) {
String mirrorMaker2Name = kafkaMirrorMaker2.getMetadata().getName();
if (kafkaMirrorMaker2.getSpec() == null) {
return maybeUpdateMirrorMaker2Status(reconciliation, kafkaMirrorMaker2, new InvalidResourceException("spec property is required"));
}
List<KafkaMirrorMaker2MirrorSpec> mirrors = ModelUtils.asListOrEmptyList(kafkaMirrorMaker2.getSpec().getMirrors());
String host = KafkaMirrorMaker2Resources.qualifiedServiceName(mirrorMaker2Name, reconciliation.namespace());
KafkaConnectApi apiClient = getKafkaConnectApi();
return apiClient.list(host, KafkaConnectCluster.REST_API_PORT).compose(deleteMirrorMaker2ConnectorNames -> {
for (Map.Entry<String, Function<KafkaMirrorMaker2MirrorSpec, KafkaMirrorMaker2ConnectorSpec>> connectorEntry : MIRRORMAKER2_CONNECTORS.entrySet()) {
deleteMirrorMaker2ConnectorNames.removeAll(mirrors.stream().filter(// filter out non-existent connectors
mirror -> connectorEntry.getValue().apply(mirror) != null).map(mirror -> mirror.getSourceCluster() + "->" + mirror.getTargetCluster() + connectorEntry.getKey()).collect(Collectors.toSet()));
}
LOGGER.debugCr(reconciliation, "delete MirrorMaker 2.0 connectors: {}", deleteMirrorMaker2ConnectorNames);
Stream<Future<Void>> deletionFutures = deleteMirrorMaker2ConnectorNames.stream().map(connectorName -> apiClient.delete(reconciliation, host, KafkaConnectCluster.REST_API_PORT, connectorName));
Stream<Future<Void>> createUpdateFutures = mirrors.stream().map(mirror -> reconcileMirrorMaker2Connectors(reconciliation, host, apiClient, kafkaMirrorMaker2, mirror, mirrorMaker2Cluster, mirrorMaker2Status, desiredLogging));
return CompositeFuture.join(Stream.concat(deletionFutures, createUpdateFutures).collect(Collectors.toList())).map((Void) null);
});
}
use of io.strimzi.operator.cluster.model.InvalidResourceException in project strimzi by strimzi.
the class KafkaRebalanceAssemblyOperator method reconcileRebalance.
/**
* Reconcile loop for the KafkaRebalance
*/
/* test */
Future<Void> reconcileRebalance(Reconciliation reconciliation, KafkaRebalance kafkaRebalance) {
if (kafkaRebalance == null) {
LOGGER.infoCr(reconciliation, "Rebalance resource deleted");
return Future.succeededFuture();
}
String clusterName = kafkaRebalance.getMetadata().getLabels() == null ? null : kafkaRebalance.getMetadata().getLabels().get(Labels.STRIMZI_CLUSTER_LABEL);
String clusterNamespace = kafkaRebalance.getMetadata().getNamespace();
if (clusterName == null) {
LOGGER.warnCr(reconciliation, "Resource lacks label '{}': No cluster related to a possible rebalance.", Labels.STRIMZI_CLUSTER_LABEL);
return updateStatus(reconciliation, kafkaRebalance, new KafkaRebalanceStatus(), new InvalidResourceException("Resource lacks label '" + Labels.STRIMZI_CLUSTER_LABEL + "': No cluster related to a possible rebalance.")).mapEmpty();
}
// Get associated Kafka cluster state
return kafkaOperator.getAsync(clusterNamespace, clusterName).compose(kafka -> {
if (kafka == null) {
LOGGER.warnCr(reconciliation, "Kafka resource '{}' identified by label '{}' does not exist in namespace {}.", clusterName, Labels.STRIMZI_CLUSTER_LABEL, clusterNamespace);
return updateStatus(reconciliation, kafkaRebalance, new KafkaRebalanceStatus(), new NoSuchResourceException("Kafka resource '" + clusterName + "' identified by label '" + Labels.STRIMZI_CLUSTER_LABEL + "' does not exist in namespace " + clusterNamespace + ".")).mapEmpty();
} else if (!Util.matchesSelector(kafkaSelector, kafka)) {
LOGGER.debugCr(reconciliation, "{} {} in namespace {} belongs to a Kafka cluster {} which does not match label selector {} and will be ignored", kind(), kafkaRebalance.getMetadata().getName(), clusterNamespace, clusterName, kafkaSelector.get().getMatchLabels());
return Future.succeededFuture();
} else if (kafka.getSpec().getCruiseControl() == null) {
LOGGER.warnCr(reconciliation, "Kafka resource lacks 'cruiseControl' declaration : No deployed Cruise Control for doing a rebalance.");
return updateStatus(reconciliation, kafkaRebalance, new KafkaRebalanceStatus(), new InvalidResourceException("Kafka resource lacks 'cruiseControl' declaration " + ": No deployed Cruise Control for doing a rebalance.")).mapEmpty();
}
if (kafka.getSpec().getKafka().getStorage() instanceof JbodStorage) {
usingJbodStorage = true;
}
String ccSecretName = CruiseControlResources.secretName(clusterName);
String ccApiSecretName = CruiseControlResources.apiSecretName(clusterName);
Future<Secret> ccSecretFuture = secretOperations.getAsync(clusterNamespace, ccSecretName);
Future<Secret> ccApiSecretFuture = secretOperations.getAsync(clusterNamespace, ccApiSecretName);
return CompositeFuture.join(ccSecretFuture, ccApiSecretFuture).compose(compositeFuture -> {
Secret ccSecret = compositeFuture.resultAt(0);
if (ccSecret == null) {
return Future.failedFuture(Util.missingSecretException(clusterNamespace, ccSecretName));
}
Secret ccApiSecret = compositeFuture.resultAt(1);
if (ccApiSecret == null) {
return Future.failedFuture(Util.missingSecretException(clusterNamespace, ccApiSecretName));
}
CruiseControlConfiguration c = new CruiseControlConfiguration(reconciliation, kafka.getSpec().getCruiseControl().getConfig().entrySet());
boolean apiAuthEnabled = CruiseControl.isApiAuthEnabled(c);
boolean apiSslEnabled = CruiseControl.isApiSslEnabled(c);
CruiseControlApi apiClient = cruiseControlClientProvider(ccSecret, ccApiSecret, apiAuthEnabled, apiSslEnabled);
// get latest KafkaRebalance state as it may have changed
return kafkaRebalanceOperator.getAsync(kafkaRebalance.getMetadata().getNamespace(), kafkaRebalance.getMetadata().getName()).compose(currentKafkaRebalance -> {
KafkaRebalanceStatus kafkaRebalanceStatus = currentKafkaRebalance.getStatus();
KafkaRebalanceState currentState;
// cluster rebalance is new or it is in one of the others states
if (kafkaRebalanceStatus == null || kafkaRebalanceStatus.getConditions().stream().filter(cond -> "ReconciliationPaused".equals(cond.getType())).findAny().isPresent()) {
currentState = KafkaRebalanceState.New;
} else {
String rebalanceStateType = rebalanceStateConditionType(kafkaRebalanceStatus);
if (rebalanceStateType == null) {
throw new RuntimeException("Unable to find KafkaRebalance State in current KafkaRebalance status");
}
currentState = KafkaRebalanceState.valueOf(rebalanceStateType);
}
// Check annotation
KafkaRebalanceAnnotation rebalanceAnnotation = rebalanceAnnotation(reconciliation, currentKafkaRebalance);
return reconcile(reconciliation, cruiseControlHost(clusterName, clusterNamespace), apiClient, currentKafkaRebalance, currentState, rebalanceAnnotation).mapEmpty();
}, exception -> Future.failedFuture(exception).mapEmpty());
});
}, exception -> updateStatus(reconciliation, kafkaRebalance, new KafkaRebalanceStatus(), exception).mapEmpty());
}
Aggregations