use of io.stackgres.common.crd.sgcluster.StackGresClusterStatus in project stackgres by ongres.
the class ExtensionReconciliationTest method testReconciliationWithExtensionThatOverwrite_installIsSkipped.
@Test
void testReconciliationWithExtensionThatOverwrite_installIsSkipped() throws Exception {
StackGresClusterInstalledExtension installedExtension = getInstalledExtension();
when(extensionManager.getExtensionInstaller(any(), any(StackGresClusterInstalledExtension.class))).thenReturn(extensionInstaller);
when(extensionInstaller.isExtensionInstalled()).thenReturn(false);
when(extensionInstaller.isExtensionPendingOverwrite()).thenReturn(false);
when(extensionInstaller.doesInstallOverwriteAnySharedLibrary()).thenReturn(true);
ExtensionReconciliatorContext context = getContext(cluster -> {
cluster.getSpec().getPostgres().setExtensions(null);
cluster.getSpec().setToInstallPostgresExtensions(new ArrayList<>());
cluster.getSpec().getToInstallPostgresExtensions().add(installedExtension);
});
doNothing().when(eventEmitter).emitExtensionDeployedRestart(installedExtension);
Assertions.assertTrue(reconciliator.reconcile(null, context).result().get());
Assertions.assertTrue(Optional.of(context.getCluster()).map(StackGresCluster::getStatus).map(StackGresClusterStatus::getPodStatuses).stream().flatMap(List::stream).anyMatch(podStatus -> podStatus.getName().equals("test-0")));
Assertions.assertTrue(context.getCluster().getStatus().getPodStatuses().stream().filter(podStatus -> podStatus.getName().equals("test-0")).findAny().map(StackGresClusterPodStatus::getPendingRestart).orElse(false));
Assertions.assertIterableEquals(ImmutableList.of(installedExtension), context.getCluster().getStatus().getPodStatuses().stream().filter(podStatus -> podStatus.getName().equals("test-0")).findAny().map(StackGresClusterPodStatus::getInstalledPostgresExtensions).stream().flatMap(List::stream).collect(ImmutableList.toImmutableList()));
verify(extensionInstaller, times(1)).isExtensionInstalled();
verify(extensionInstaller, times(0)).isLinksCreated();
verify(extensionInstaller, times(2)).isExtensionPendingOverwrite();
verify(extensionUninstaller, times(0)).isExtensionInstalled();
verify(extensionInstaller, times(1)).downloadAndExtract();
verify(extensionInstaller, times(1)).verify();
verify(extensionInstaller, times(0)).installExtension();
verify(extensionInstaller, times(0)).createExtensionLinks();
verify(extensionInstaller, times(1)).doesInstallOverwriteAnySharedLibrary();
verify(extensionInstaller, times(1)).setExtensionAsPending();
verify(extensionUninstaller, times(0)).uninstallExtension();
verify(eventEmitter).emitExtensionDeployedRestart(installedExtension);
}
use of io.stackgres.common.crd.sgcluster.StackGresClusterStatus in project stackgres by ongres.
the class ExtensionReconciliationTest method testReconciliationWithPreviousExtensionAlreadyInstalled_upgradeIsPerformed.
@Test
void testReconciliationWithPreviousExtensionAlreadyInstalled_upgradeIsPerformed() throws Exception {
StackGresClusterInstalledExtension previousInstalledExtension = getInstalledExtension();
previousInstalledExtension.setVersion("1.7.0");
StackGresClusterInstalledExtension installedExtension = getInstalledExtension();
ExtensionReconciliatorContext context = getContext(cluster -> {
cluster.getSpec().getPostgres().setExtensions(null);
cluster.getSpec().setToInstallPostgresExtensions(new ArrayList<>());
cluster.getSpec().getToInstallPostgresExtensions().add(installedExtension);
cluster.setStatus(new StackGresClusterStatus());
cluster.getStatus().setPodStatuses(new ArrayList<>());
StackGresClusterPodStatus podStatus = new StackGresClusterPodStatus();
podStatus.setName("test-0");
podStatus.setInstalledPostgresExtensions(new ArrayList<>());
podStatus.getInstalledPostgresExtensions().add(previousInstalledExtension);
cluster.getStatus().getPodStatuses().add(podStatus);
});
when(extensionManager.getExtensionInstaller(any(), any(StackGresClusterInstalledExtension.class))).thenReturn(extensionInstaller);
when(extensionInstaller.isExtensionPendingOverwrite()).thenReturn(false);
when(extensionInstaller.isExtensionInstalled()).thenReturn(false);
doNothing().when(eventEmitter).emitExtensionChanged(previousInstalledExtension, installedExtension);
Assertions.assertTrue(reconciliator.reconcile(null, context).result().get());
Assertions.assertTrue(Optional.of(context.getCluster()).map(StackGresCluster::getStatus).map(StackGresClusterStatus::getPodStatuses).stream().flatMap(List::stream).anyMatch(podStatus -> podStatus.getName().equals("test-0")));
Assertions.assertFalse(context.getCluster().getStatus().getPodStatuses().stream().filter(podStatus -> podStatus.getName().equals("test-0")).findAny().map(StackGresClusterPodStatus::getPendingRestart).orElse(false));
Assertions.assertIterableEquals(ImmutableList.of(installedExtension), context.getCluster().getStatus().getPodStatuses().stream().filter(podStatus -> podStatus.getName().equals("test-0")).findAny().map(StackGresClusterPodStatus::getInstalledPostgresExtensions).stream().flatMap(List::stream).collect(ImmutableList.toImmutableList()));
verify(extensionInstaller, times(1)).isExtensionInstalled();
verify(extensionInstaller, times(0)).isLinksCreated();
verify(extensionUninstaller, times(0)).isExtensionInstalled();
verify(extensionInstaller, times(1)).downloadAndExtract();
verify(extensionInstaller, times(1)).verify();
verify(extensionInstaller, times(1)).installExtension();
verify(extensionInstaller, times(0)).createExtensionLinks();
verify(extensionInstaller, times(1)).doesInstallOverwriteAnySharedLibrary();
verify(extensionInstaller, times(0)).setExtensionAsPending();
verify(extensionUninstaller, times(0)).uninstallExtension();
verify(eventEmitter).emitExtensionChanged(previousInstalledExtension, installedExtension);
}
use of io.stackgres.common.crd.sgcluster.StackGresClusterStatus in project stackgres by ongres.
the class ExtensionReconciliationTest method testReconciliationWithExtensionAlreadyPresent_installIsSkippedButStatusUpdated.
@Test
void testReconciliationWithExtensionAlreadyPresent_installIsSkippedButStatusUpdated() throws Exception {
StackGresClusterInstalledExtension installedExtension = getInstalledExtension();
ExtensionReconciliatorContext context = getContext(cluster -> {
cluster.getSpec().getPostgres().setExtensions(null);
cluster.getSpec().setToInstallPostgresExtensions(new ArrayList<>());
cluster.getSpec().getToInstallPostgresExtensions().add(installedExtension);
});
when(extensionManager.getExtensionInstaller(any(), any(StackGresClusterInstalledExtension.class))).thenReturn(extensionInstaller);
when(extensionInstaller.isExtensionInstalled()).thenReturn(true);
when(extensionInstaller.isLinksCreated()).thenReturn(true);
Assertions.assertTrue(reconciliator.reconcile(null, context).result().get());
Assertions.assertTrue(Optional.of(context.getCluster()).map(StackGresCluster::getStatus).map(StackGresClusterStatus::getPodStatuses).stream().flatMap(List::stream).anyMatch(podStatus -> podStatus.getName().equals("test-0")));
Assertions.assertFalse(context.getCluster().getStatus().getPodStatuses().stream().filter(podStatus -> podStatus.getName().equals("test-0")).findAny().map(StackGresClusterPodStatus::getPendingRestart).orElse(false));
Assertions.assertIterableEquals(ImmutableList.of(installedExtension), context.getCluster().getStatus().getPodStatuses().stream().filter(podStatus -> podStatus.getName().equals("test-0")).findAny().map(StackGresClusterPodStatus::getInstalledPostgresExtensions).stream().flatMap(List::stream).collect(ImmutableList.toImmutableList()));
verify(extensionInstaller, times(1)).isExtensionInstalled();
verify(extensionInstaller, times(1)).isLinksCreated();
verify(extensionUninstaller, times(0)).isExtensionInstalled();
verify(extensionInstaller, times(0)).downloadAndExtract();
verify(extensionInstaller, times(0)).verify();
verify(extensionInstaller, times(0)).installExtension();
verify(extensionInstaller, times(0)).createExtensionLinks();
verify(extensionInstaller, times(0)).doesInstallOverwriteAnySharedLibrary();
verify(extensionInstaller, times(0)).setExtensionAsPending();
verify(extensionUninstaller, times(0)).uninstallExtension();
}
use of io.stackgres.common.crd.sgcluster.StackGresClusterStatus 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());
}
use of io.stackgres.common.crd.sgcluster.StackGresClusterStatus in project stackgres by ongres.
the class ClusterStatusManager method isPendingRestart.
/**
* Check pending restart status condition.
*/
public boolean isPendingRestart(StackGresCluster cluster) {
List<StackGresClusterPodStatus> clusterPodStatuses = Optional.ofNullable(cluster.getStatus()).map(StackGresClusterStatus::getPodStatuses).orElse(ImmutableList.of());
Optional<StatefulSet> clusterStatefulSet = getClusterStatefulSet(cluster);
List<Pod> clusterPods = clusterStatefulSet.map(sts -> getStsPods(sts, cluster)).orElse(ImmutableList.of());
RestartReasons reasons = ClusterPendingRestartUtil.getRestartReasons(clusterPodStatuses, clusterStatefulSet, clusterPods);
for (RestartReason reason : reasons.getReasons()) {
switch(reason) {
case OPERATOR_VERSION:
LOGGER.debug("Cluster {} requires restart due to operator version change", getClusterId(cluster));
break;
case PATRONI:
LOGGER.debug("Cluster {} requires restart due to patroni's indication", getClusterId(cluster));
break;
case POD_STATUS:
LOGGER.debug("Cluster {} requires restart due to pod status indication", getClusterId(cluster));
break;
case STATEFULSET:
LOGGER.debug("Cluster {} requires restart due to pod template changes", getClusterId(cluster));
break;
default:
break;
}
}
return reasons.requiresRestart();
}
Aggregations