use of io.stackgres.operatorframework.reconciliation.ReconciliationResult in project stackgres by ongres.
the class ClusterControllerReconciliator method reconcile.
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "False positives")
@Override
protected ReconciliationResult<?> reconcile(KubernetesClient client, StackGresClusterContext context) throws Exception {
ReconciliationResult<Boolean> extensionReconciliationResult = extensionReconciliator.reconcile(client, context);
if (extensionReconciliationResult.result().orElse(false)) {
final String podName = propertyContext.getString(ClusterControllerProperty.CLUSTER_CONTROLLER_POD_NAME);
final StackGresCluster cluster = context.getCluster();
final StackGresClusterStatus status = cluster.getStatus();
String clusterName = cluster.getMetadata().getName();
String namespace = cluster.getMetadata().getNamespace();
clusterFinder.findByNameAndNamespace(clusterName, namespace).ifPresent(savedCluster -> {
var newPodStatus = findPodStatus(status.getPodStatuses(), podName).orElseThrow();
Optional.ofNullable(savedCluster.getStatus()).ifPresentOrElse(savedStatus -> Optional.ofNullable(savedStatus.getPodStatuses()).ifPresentOrElse(savedPodStatuses -> findPodStatus(savedPodStatuses, podName).ifPresentOrElse(savedPodStatus -> applyPodStatusChanges(newPodStatus, savedPodStatus), () -> savedPodStatuses.add(newPodStatus)), () -> savedStatus.setPodStatuses(status.getPodStatuses())), () -> savedCluster.setStatus(status));
clusterScheduler.updateStatus(savedCluster);
});
}
return extensionReconciliationResult;
}
use of io.stackgres.operatorframework.reconciliation.ReconciliationResult in project stackgres by ongres.
the class DistributedLogsClusterReconciliator method reconcile.
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "False positives")
protected ReconciliationResult<Boolean> reconcile(KubernetesClient client, StackGresDistributedLogsContext context) throws Exception {
StackGresDistributedLogs distributedLogs = context.getDistributedLogs();
if (distributedLogs.getStatus() == null || !isPatroniReady(context)) {
LOGGER.warn("Waiting for distributedlogs cluster to become ready...");
return new ReconciliationResult<>(false);
}
final ImmutableList.Builder<Exception> exceptions = ImmutableList.builder();
boolean statusUpdated = false;
for (StackGresDistributedLogsStatusCluster cluster : distributedLogs.getStatus().getConnectedClusters()) {
String database = FluentdUtil.databaseName(cluster.getNamespace(), cluster.getName());
try {
if (!databaseManager.existsDatabase(context, database)) {
LOGGER.info("Creating database {}", database);
databaseManager.createDatabase(context, database);
}
} catch (Exception ex) {
exceptions.add(ex);
handleException(client, distributedLogs, cluster, ex);
continue;
}
String retention = cluster.getConfig().getRetention();
if (!Optional.of(distributedLogs.getStatus().getDatabases()).flatMap(databases -> databases.stream().filter(databaseStatus -> databaseStatus.getName().equals(database)).findAny()).map(StackGresDistributedLogsStatusDatabase::getRetention).map(currentRetention -> Objects.equals(retention, currentRetention)).orElse(false)) {
for (String table : Seq.of(Tables.values()).map(Tables::getTableName)) {
LOGGER.info("Updating retention window for database {} and table to {}", database, retention);
try {
databaseManager.updateRetention(context, database, retention, table);
} catch (Exception ex) {
exceptions.add(ex);
handleException(client, distributedLogs, cluster, ex);
continue;
}
}
}
if (retention != null) {
for (String table : Seq.of(Tables.values()).map(Tables::getTableName)) {
try {
databaseManager.reconcileRetention(context, database, retention, table).stream().forEach(output -> LOGGER.info("Reconcile retention for database {} and table {}: {}", database, table, output));
} catch (Exception ex) {
exceptions.add(ex);
handleException(client, distributedLogs, cluster, ex);
continue;
}
}
}
statusUpdated = statusUpdated || updateStatus(distributedLogs, database, retention);
}
String fluentdConfigHash = configManager.getFluentdConfigHash();
if (!Objects.equals(distributedLogs.getStatus().getFluentdConfigHash(), fluentdConfigHash)) {
LOGGER.info("Reloading fluentd configuration");
configManager.reloadFluentdConfiguration();
distributedLogs.getStatus().setFluentdConfigHash(fluentdConfigHash);
}
return new ReconciliationResult<>(statusUpdated, exceptions.build());
}
use of io.stackgres.operatorframework.reconciliation.ReconciliationResult in project stackgres by ongres.
the class ExtensionReconciliator method reconcile.
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "False positives")
public ReconciliationResult<Boolean> reconcile(KubernetesClient client, T context) throws Exception {
final ImmutableList.Builder<Exception> exceptions = ImmutableList.builder();
final StackGresCluster cluster = context.getCluster();
final ImmutableList<StackGresClusterInstalledExtension> extensions = context.getExtensions();
if (cluster.getStatus() == null) {
cluster.setStatus(new StackGresClusterStatus());
}
if (cluster.getStatus().getPodStatuses() == null) {
cluster.getStatus().setPodStatuses(new ArrayList<>());
}
if (cluster.getStatus().getPodStatuses().stream().noneMatch(podStatus -> podStatus.getName().equals(podName))) {
StackGresClusterPodStatus podStatus = new StackGresClusterPodStatus();
podStatus.setName(podName);
podStatus.setInstalledPostgresExtensions(new ArrayList<>());
cluster.getStatus().getPodStatuses().add(podStatus);
}
final StackGresClusterPodStatus podStatus = cluster.getStatus().getPodStatuses().stream().filter(status -> status.getName().equals(podName)).findAny().get();
if (podStatus.getInstalledPostgresExtensions() == null) {
podStatus.setInstalledPostgresExtensions(new ArrayList<>());
}
final List<StackGresClusterInstalledExtension> installedExtensions = podStatus.getInstalledPostgresExtensions();
LOGGER.info("Reconcile postgres extensions...");
boolean clusterUpdated = false;
final List<StackGresClusterInstalledExtension> extensionToUninstall = installedExtensions.stream().filter(installedExtension -> extensions.stream().noneMatch(installedExtension::same)).collect(Collectors.toList());
for (StackGresClusterInstalledExtension installedExtension : extensionToUninstall) {
ExtensionUninstaller extensionUninstaller = extensionManager.getExtensionUninstaller(context, installedExtension);
try {
if (!skipSharedLibrariesOverwrites) {
if (extensionUninstaller.isExtensionInstalled()) {
LOGGER.info("Removing extension {}", ExtensionUtil.getDescription(installedExtension));
extensionEventEmitter.emitExtensionRemoved(installedExtension);
extensionUninstaller.uninstallExtension();
}
installedExtensions.remove(installedExtension);
clusterUpdated = true;
} else {
LOGGER.info("Skip uninstallation of extension {}", ExtensionUtil.getDescription(installedExtension));
if (!Optional.ofNullable(podStatus.getPendingRestart()).orElse(false)) {
podStatus.setPendingRestart(true);
clusterUpdated = true;
}
}
} catch (Exception ex) {
exceptions.add(ex);
onUninstallException(client, cluster, ExtensionUtil.getDescription(installedExtension), podName, ex);
}
}
for (StackGresClusterInstalledExtension extension : extensions) {
try {
final ExtensionInstaller extensionInstaller = Optional.ofNullable(extensionManager.getExtensionInstaller(context, extension)).orElseThrow(() -> new IllegalStateException("Can not find extension " + ExtensionUtil.getDescription(extension)));
if (!extensionInstaller.isExtensionInstalled() && (!skipSharedLibrariesOverwrites || !extensionInstaller.isExtensionPendingOverwrite())) {
LOGGER.info("Download extension {}", ExtensionUtil.getDescription(extension));
extensionEventEmitter.emitExtensionDownloading(extension);
extensionInstaller.downloadAndExtract();
LOGGER.info("Verify extension {}", ExtensionUtil.getDescription(extension));
extensionInstaller.verify();
if (skipSharedLibrariesOverwrites && extensionInstaller.doesInstallOverwriteAnySharedLibrary()) {
LOGGER.info("Skip installation of extension {}", ExtensionUtil.getDescription(extension));
if (!extensionInstaller.isExtensionPendingOverwrite()) {
extensionInstaller.setExtensionAsPending();
}
if (!Optional.ofNullable(podStatus.getPendingRestart()).orElse(false)) {
extensionEventEmitter.emitExtensionDeployedRestart(extension);
podStatus.setPendingRestart(true);
clusterUpdated = true;
}
} else {
LOGGER.info("Install extension {}", ExtensionUtil.getDescription(extension));
extensionInstaller.installExtension();
extensionEventEmitter.emitExtensionDeployed(extension);
}
} else {
if (!extensionInstaller.isLinksCreated()) {
LOGGER.info("Create links for extension {}", ExtensionUtil.getDescription(extension));
extensionInstaller.createExtensionLinks();
}
}
if (installedExtensions.stream().noneMatch(anInstalledExtension -> anInstalledExtension.equals(extension))) {
installedExtensions.stream().filter(anInstalledExtension -> anInstalledExtension.same(extension)).peek(previousInstalledExtension -> LOGGER.info("Extension upgraded from {} to {}", ExtensionUtil.getDescription(previousInstalledExtension), ExtensionUtil.getDescription(extension))).peek(previousInstalledExtension -> extensionEventEmitter.emitExtensionChanged(previousInstalledExtension, extension)).findAny().ifPresent(installedExtensions::remove);
installedExtensions.add(extension);
clusterUpdated = true;
}
} catch (Exception ex) {
exceptions.add(ex);
onInstallException(client, cluster, ExtensionUtil.getDescription(extension), podName, ex);
}
}
if (!skipSharedLibrariesOverwrites && Optional.ofNullable(podStatus.getPendingRestart()).orElse(false)) {
podStatus.setPendingRestart(false);
clusterUpdated = true;
}
LOGGER.info("Reconciliation of postgres extensions completed");
return new ReconciliationResult<>(clusterUpdated, exceptions.build());
}
Aggregations