Skip to content

Commit e357ab1

Browse files
committed
fix: can not change Postgres version in SGShardedCluster
1 parent c0b8849 commit e357ab1

4 files changed

Lines changed: 128 additions & 188 deletions

File tree

stackgres-k8s/src/operator/src/main/java/io/stackgres/operator/conciliation/shardedcluster/context/ShardedClusterPostgresVersionContextAppender.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.stackgres.common.crd.sgshardedcluster.StackGresShardedClusterStatus;
2222
import io.stackgres.common.event.EventEmitter;
2323
import io.stackgres.operator.conciliation.ContextAppender;
24+
import io.stackgres.operator.conciliation.cluster.context.ClusterPostgresVersionContextAppender;
2425
import io.stackgres.operator.conciliation.shardedcluster.StackGresShardedClusterContext.Builder;
2526
import io.stackgres.operator.validation.ValidationUtil;
2627
import jakarta.enterprise.context.ApplicationScoped;
@@ -32,17 +33,8 @@
3233
public class ShardedClusterPostgresVersionContextAppender
3334
extends ContextAppender<StackGresShardedCluster, Builder> {
3435

35-
private static final String PG_14_CREATE_CONCURRENT_INDEX_BUG =
36-
"Please, use PostgreSQL 14.4 since it fixes an issue"
37-
+ " with CREATE INDEX CONCURRENTLY and REINDEX CONCURRENTLY that"
38-
+ " could cause silent data corruption of indexes. For more info"
39-
+ " see https://www.postgresql.org/about/news/postgresql-144-released-2470/.";
40-
public static final Map<String, String> BUGGY_PG_VERSIONS = Map.ofEntries(
41-
Map.entry("14.0", PG_14_CREATE_CONCURRENT_INDEX_BUG),
42-
Map.entry("14.1", PG_14_CREATE_CONCURRENT_INDEX_BUG),
43-
Map.entry("14.2", PG_14_CREATE_CONCURRENT_INDEX_BUG),
44-
Map.entry("14.3", PG_14_CREATE_CONCURRENT_INDEX_BUG)
45-
);
36+
public static final Map<String, String> BUGGY_PG_VERSIONS =
37+
ClusterPostgresVersionContextAppender.BUGGY_PG_VERSIONS;
4638

4739
private final Map<StackGresComponent, Map<StackGresVersion, List<String>>>
4840
supportedPostgresVersions;

stackgres-k8s/src/operator/src/main/java/io/stackgres/operator/validation/shardedcluster/PostgresConfigValidator.java

Lines changed: 0 additions & 177 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.operator.validation.shardedcluster;
7+
8+
import static io.stackgres.common.StackGresUtil.getPostgresFlavorComponent;
9+
10+
import java.util.Objects;
11+
12+
import io.stackgres.common.ErrorType;
13+
import io.stackgres.common.crd.sgshardedcluster.StackGresShardedCluster;
14+
import io.stackgres.operator.common.StackGresShardedClusterReview;
15+
import io.stackgres.operator.validation.ValidationType;
16+
import io.stackgres.operatorframework.admissionwebhook.validating.ValidationFailed;
17+
import jakarta.inject.Singleton;
18+
19+
@Singleton
20+
@ValidationType(ErrorType.FORBIDDEN_CR_UPDATE)
21+
public class PostgresFlavorValidator
22+
implements ShardedClusterValidator {
23+
24+
@Override
25+
public void validate(StackGresShardedClusterReview review) throws ValidationFailed {
26+
StackGresShardedCluster cluster = review.getRequest().getObject();
27+
28+
switch (review.getRequest().getOperation()) {
29+
case UPDATE:
30+
StackGresShardedCluster oldCluster = review.getRequest().getOldObject();
31+
if (!Objects.equals(
32+
getPostgresFlavorComponent(cluster),
33+
getPostgresFlavorComponent(oldCluster))) {
34+
fail("postgres flavor can not be changed");
35+
}
36+
break;
37+
default:
38+
}
39+
}
40+
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.operator.validation.shardedcluster;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertThrows;
10+
11+
import java.util.List;
12+
import java.util.Random;
13+
import java.util.function.Predicate;
14+
15+
import io.stackgres.common.StackGresComponent;
16+
import io.stackgres.common.crd.sgcluster.StackGresPostgresFlavor;
17+
import io.stackgres.common.crd.sgshardedcluster.StackGresShardedClusterSpec;
18+
import io.stackgres.operator.common.StackGresShardedClusterReview;
19+
import io.stackgres.operator.common.fixture.AdmissionReviewFixtures;
20+
import io.stackgres.operator.conciliation.shardedcluster.context.ShardedClusterPostgresVersionContextAppender;
21+
import io.stackgres.operatorframework.admissionwebhook.validating.ValidationFailed;
22+
import org.junit.jupiter.api.BeforeEach;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
import org.mockito.junit.jupiter.MockitoExtension;
26+
27+
@ExtendWith(MockitoExtension.class)
28+
class PostgresFlavorValidatorTest {
29+
30+
private static final List<String> SUPPORTED_POSTGRES_VERSIONS =
31+
StackGresComponent.POSTGRESQL.getLatest().streamOrderedVersions()
32+
.toList();
33+
private static final String FIRST_BF_MINOR_VERSION =
34+
StackGresComponent.BABELFISH.getLatest().streamOrderedVersions()
35+
.get(0).get();
36+
37+
private static String getRandomPostgresVersion() {
38+
Random random = new Random();
39+
List<String> validPostgresVersions = SUPPORTED_POSTGRES_VERSIONS.stream()
40+
.filter(Predicate.not(ShardedClusterPostgresVersionContextAppender.BUGGY_PG_VERSIONS.keySet()::contains))
41+
.toList();
42+
43+
int versionIndex = random.nextInt(validPostgresVersions.size());
44+
return validPostgresVersions.get(versionIndex);
45+
}
46+
47+
private PostgresFlavorValidator validator;
48+
49+
@BeforeEach
50+
void setUp() {
51+
validator = new PostgresFlavorValidator();
52+
}
53+
54+
@Test
55+
void givenValidPostgresFlavor_shouldNotFail() throws ValidationFailed {
56+
final StackGresShardedClusterReview review = AdmissionReviewFixtures.shardedCluster().loadCreate().get();
57+
58+
StackGresShardedClusterSpec spec = review.getRequest().getObject().getSpec();
59+
60+
final String randomVersion = getRandomPostgresVersion();
61+
spec.getPostgres().setVersion(randomVersion);
62+
63+
validator.validate(review);
64+
}
65+
66+
@Test
67+
void givenChangedPostgresFlavorUpdate_shouldFail() throws ValidationFailed {
68+
final StackGresShardedClusterReview review = AdmissionReviewFixtures.shardedCluster().loadUpdate().get();
69+
70+
StackGresShardedClusterSpec spec = review.getRequest().getObject().getSpec();
71+
spec.getPostgres().setVersion(FIRST_BF_MINOR_VERSION);
72+
spec.getPostgres().setFlavor(StackGresPostgresFlavor.BABELFISH.toString());
73+
74+
ValidationFailed exception = assertThrows(ValidationFailed.class, () -> {
75+
validator.validate(review);
76+
});
77+
78+
String resultMessage = exception.getResult().getMessage();
79+
80+
assertEquals("postgres flavor can not be changed",
81+
resultMessage);
82+
}
83+
84+
}

0 commit comments

Comments
 (0)