Skip to content

Commit 41454fa

Browse files
authored
flakiness - fix cert rotation tests (#19)
# Summary - cherry-pick of 10gen/ops-manager-kubernetes#4298 and linked pr will be closed and cherry-picked from here instead
1 parent a00f9ba commit 41454fa

File tree

5 files changed

+84
-71
lines changed

5 files changed

+84
-71
lines changed

docker/mongodb-enterprise-tests/kubetester/certs.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,27 @@
1313
from kubeobject import CustomObject
1414
from kubernetes import client
1515
from kubernetes.client.rest import ApiException
16-
from kubetester import create_secret, delete_secret, random_k8s_name, read_secret
16+
from kubetester import (
17+
create_secret,
18+
delete_secret,
19+
kubetester,
20+
random_k8s_name,
21+
read_secret,
22+
)
1723
from kubetester.kubetester import KubernetesTester
24+
from kubetester.mongodb import Phase
1825
from kubetester.mongodb_multi import MongoDBMulti, MultiClusterClient
26+
from opentelemetry import trace
27+
from tests import test_logger
1928
from tests.vaultintegration import (
2029
store_secret_in_vault,
2130
vault_namespace_name,
2231
vault_sts_name,
2332
)
2433

34+
TRACER = trace.get_tracer("evergreen-agent")
35+
logger = test_logger.get_test_logger(__name__)
36+
2537
ISSUER_CA_NAME = "ca-issuer"
2638

2739
SUBJECT = {
@@ -161,11 +173,13 @@ def generate_cert(
161173
return secret_name
162174

163175

164-
def rotate_cert(namespace, certificate_name):
176+
def rotate_cert(namespace, certificate_name, should_block_until_ready=False):
165177
cert = Certificate(name=certificate_name, namespace=namespace)
166178
cert.load()
167179
cert["spec"]["dnsNames"].append("foo") # Append DNS to cert to rotate the certificate
168180
cert.update()
181+
if should_block_until_ready:
182+
cert.block_until_ready()
169183

170184

171185
def create_tls_certs(
@@ -879,3 +893,36 @@ def yield_existing_csrs(csr_names: List[str], timeout: int = 300) -> Generator[s
879893
raise AssertionError(
880894
f"Expected to find {total_csrs} csrs, but only found {seen_csrs} after {timeout} seconds. Expected csrs {csr_names}"
881895
)
896+
897+
898+
@TRACER.start_as_current_span("assert_certificate_rotation")
899+
def rotate_and_assert_certificates(mdb, namespace, certificate_name):
900+
"""
901+
Verifies certificate rotation completes successfully.
902+
903+
Rotates the specified certificate and validates that:
904+
1. Automation config version increases, as cert changes causes a new ac version
905+
2. All MongoDB processes reach the new goal version
906+
3. MongoDB instance returns/stays to Running state
907+
908+
"""
909+
910+
old_ac_version = KubernetesTester.get_automation_config()["version"]
911+
rotate_cert(namespace, certificate_name, should_block_until_ready=True)
912+
913+
# Create named function to check version and process status
914+
def check_version_increased():
915+
916+
current_version = KubernetesTester.get_automation_config()["version"]
917+
version_increased = current_version > old_ac_version
918+
919+
return version_increased
920+
921+
timeout = 600
922+
KubernetesTester.wait_until(
923+
check_version_increased,
924+
timeout=timeout,
925+
)
926+
kubetester.wait_processes_ready()
927+
928+
mdb.assert_reaches_phase(Phase.Running, timeout=1200)

docker/mongodb-enterprise-tests/kubetester/kubetester.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@
2626
from kubernetes.client.rest import ApiException
2727
from kubernetes.stream import stream
2828
from kubetester.crypto import wait_for_certs_to_be_issued
29+
from opentelemetry import trace
2930
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
3031
from tests import test_logger
3132

33+
TRACER = trace.get_tracer("evergreen-agent")
34+
logger = test_logger.get_test_logger(__name__)
35+
3236
SSL_CA_CERT = "/var/run/secrets/kubernetes.io/serviceaccount/..data/ca.crt"
3337
EXTERNALLY_MANAGED_TAG = "EXTERNALLY_MANAGED_BY_KUBERNETES"
3438
MAX_TAG_LEN = 32
@@ -188,12 +192,17 @@ def decode_secret(cls, data: Dict[str, str]) -> Dict[str, str]:
188192
return {k: b64decode(v).decode("utf-8") for (k, v) in data.items()}
189193

190194
@classmethod
191-
def read_configmap(cls, namespace: str, name: str, api_client: Optional[client.ApiClient] = None) -> Dict[str, str]:
195+
def read_configmap(
196+
cls, namespace: str, name: str, api_client: Optional[client.ApiClient] = None, with_metadata=False
197+
) -> Dict[str, str]:
192198
corev1 = cls.clients("corev1")
193199
if api_client is not None:
194200
corev1 = client.CoreV1Api(api_client=api_client)
195201

196-
return corev1.read_namespaced_config_map(name, namespace).data
202+
cm = corev1.read_namespaced_config_map(name, namespace)
203+
if with_metadata:
204+
return cm
205+
return cm.data
197206

198207
@classmethod
199208
def read_pod(cls, namespace: str, name: str) -> Dict[str, str]:
@@ -962,6 +971,16 @@ def get_automation_status(group_id=None, group_name=None):
962971

963972
return response.json()
964973

974+
@staticmethod
975+
def get_automation_status(group_id=None, group_name=None):
976+
if group_id is None:
977+
group_id = KubernetesTester.get_om_group_id(group_name=group_name)
978+
979+
url = build_automation_status_endpoint(KubernetesTester.get_om_base_url(), group_id)
980+
response = KubernetesTester.om_request("get", url)
981+
982+
return response.json()
983+
965984
@staticmethod
966985
def get_monitoring_config(group_id=None):
967986
if group_id is None:

docker/mongodb-enterprise-tests/tests/authentication/sharded_cluster_x509_to_scram_transition.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414
from kubetester.mongodb import MongoDB, Phase
1515
from kubetester.mongotester import ShardedClusterTester
1616
from kubetester.omtester import get_sc_cert_names
17+
from opentelemetry import trace
1718
from pytest import fixture
1819
from tests import test_logger
1920

21+
TRACER = trace.get_tracer("evergreen-agent")
22+
2023
MDB_RESOURCE = "sharded-cluster-x509-to-scram-256"
2124
USER_NAME = "mms-user-1"
2225
PASSWORD_SECRET_NAME = "mms-user-1-password"
@@ -97,11 +100,6 @@ def test_ops_manager_state_updated_correctly(self):
97100
tester.assert_authentication_disabled()
98101

99102

100-
from opentelemetry import trace
101-
102-
TRACER = trace.get_tracer("evergreen-agent")
103-
104-
105103
@pytest.mark.e2e_sharded_cluster_x509_to_scram_transition
106104
class TestCanEnableScramSha256:
107105
@TRACER.start_as_current_span("test_can_enable_scram_sha_256")

docker/mongodb-enterprise-tests/tests/tls/tls_x509_configure_all_options_rs.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
ISSUER_CA_NAME,
55
create_x509_agent_tls_certs,
66
create_x509_mongodb_tls_certs,
7-
rotate_cert,
7+
rotate_and_assert_certificates,
88
)
99
from kubetester.kubetester import KubernetesTester
1010
from kubetester.kubetester import fixture as load_fixture
@@ -47,20 +47,10 @@ def test_ops_manager_state_correctly_updated(self):
4747
ac_tester.assert_internal_cluster_authentication_enabled()
4848
ac_tester.assert_authentication_enabled()
4949

50-
def test_rotate_certificate(self, mdb: MongoDB, namespace: str):
51-
rotate_cert(namespace, "{}-cert".format(MDB_RESOURCE))
52-
mdb.assert_abandons_phase(Phase.Running, timeout=900)
53-
mdb.assert_reaches_phase(Phase.Running, timeout=900)
54-
5550
def test_rotate_certificate_with_sts_restarting(self, mdb: MongoDB, namespace: str):
5651
mdb.trigger_sts_restart()
57-
assert_certificate_rotation(mdb, namespace, "{}-cert".format(MDB_RESOURCE))
52+
rotate_and_assert_certificates(mdb, namespace, "{}-cert".format(MDB_RESOURCE))
5853

5954
def test_rotate_clusterfile_with_sts_restarting(self, mdb: MongoDB, namespace: str):
6055
mdb.trigger_sts_restart()
61-
assert_certificate_rotation(mdb, namespace, "{}-clusterfile".format(MDB_RESOURCE))
62-
63-
64-
def assert_certificate_rotation(mdb, namespace, certificate_name):
65-
rotate_cert(namespace, certificate_name)
66-
mdb.assert_reaches_phase(Phase.Running, timeout=900)
56+
rotate_and_assert_certificates(mdb, namespace, "{}-clusterfile".format(MDB_RESOURCE))

docker/mongodb-enterprise-tests/tests/tls/tls_x509_configure_all_options_sc.py

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44
from kubetester.certs import (
55
create_sharded_cluster_certs,
66
create_x509_agent_tls_certs,
7-
rotate_cert,
7+
rotate_and_assert_certificates,
88
)
9-
from kubetester.kubetester import KubernetesTester, ensure_ent_version, is_multi_cluster
9+
from kubetester.kubetester import KubernetesTester, is_multi_cluster
1010
from kubetester.mongodb import MongoDB, Phase
1111
from kubetester.operator import Operator
1212
from pytest import fixture
13+
from tests import test_logger
1314
from tests.shardedcluster.conftest import enable_multi_cluster_deployment
1415

1516
MDB_RESOURCE_NAME = "test-x509-all-options-sc"
1617

18+
logger = test_logger.get_test_logger(__name__)
19+
1720

1821
@fixture(scope="module")
1922
def agent_certs(issuer: str, namespace: str) -> str:
@@ -86,58 +89,14 @@ def test_ops_manager_state_correctly_updated(self):
8689
ac_tester.assert_authentication_enabled()
8790
ac_tester.assert_expected_users(0)
8891

89-
def test_rotate_shard_cert(self, sc: MongoDB, namespace: str):
90-
rotate_cert(namespace, f"{MDB_RESOURCE_NAME}-0-cert")
91-
sc.assert_abandons_phase(Phase.Running, timeout=900)
92-
sc.assert_reaches_phase(Phase.Running, timeout=1200)
93-
94-
def test_rotate_config_cert(self, sc: MongoDB, namespace: str):
95-
rotate_cert(namespace, f"{MDB_RESOURCE_NAME}-config-cert")
96-
sc.assert_abandons_phase(Phase.Running, timeout=900)
97-
sc.assert_reaches_phase(Phase.Running, timeout=1200)
98-
99-
def test_rotate_mongos_cert(self, sc: MongoDB, namespace: str):
100-
rotate_cert(namespace, f"{MDB_RESOURCE_NAME}-mongos-cert")
101-
sc.assert_abandons_phase(Phase.Running, timeout=900)
102-
sc.assert_reaches_phase(Phase.Running, timeout=1200)
103-
10492
def test_rotate_shard_cert_with_sts_restarting(self, sc: MongoDB, namespace: str):
10593
sc.trigger_sts_restart("shard")
106-
assert_certificate_rotation(sc, namespace, f"{MDB_RESOURCE_NAME}-0-cert")
94+
rotate_and_assert_certificates(sc, namespace, f"{MDB_RESOURCE_NAME}-0-cert")
10795

10896
def test_rotate_config_cert_with_sts_restarting(self, sc: MongoDB, namespace: str):
10997
sc.trigger_sts_restart("config")
110-
assert_certificate_rotation(sc, namespace, f"{MDB_RESOURCE_NAME}-config-cert")
98+
rotate_and_assert_certificates(sc, namespace, f"{MDB_RESOURCE_NAME}-config-cert")
11199

112100
def test_rotate_mongos_cert_with_sts_restarting(self, sc: MongoDB, namespace: str):
113101
sc.trigger_sts_restart("mongos")
114-
assert_certificate_rotation(sc, namespace, f"{MDB_RESOURCE_NAME}-mongos-cert")
115-
116-
def test_rotate_shard_certfile_with_sts_restarting(self, sc: MongoDB, namespace: str):
117-
sc.trigger_sts_restart("shard")
118-
assert_certificate_rotation(
119-
sc,
120-
namespace,
121-
f"{MDB_RESOURCE_NAME}-0-clusterfile",
122-
)
123-
124-
def test_rotate_config_certfile_with_sts_restarting(self, sc: MongoDB, namespace: str):
125-
sc.trigger_sts_restart("config")
126-
assert_certificate_rotation(
127-
sc,
128-
namespace,
129-
f"{MDB_RESOURCE_NAME}-config-clusterfile",
130-
)
131-
132-
def test_rotate_mongos_certfile_with_sts_restarting(self, sc: MongoDB, namespace: str):
133-
sc.trigger_sts_restart("mongos")
134-
assert_certificate_rotation(
135-
sc,
136-
namespace,
137-
f"{MDB_RESOURCE_NAME}-mongos-clusterfile",
138-
)
139-
140-
141-
def assert_certificate_rotation(sharded_cluster, namespace, certificate_name):
142-
rotate_cert(namespace, certificate_name)
143-
sharded_cluster.assert_reaches_phase(Phase.Running, timeout=1200)
102+
rotate_and_assert_certificates(sc, namespace, f"{MDB_RESOURCE_NAME}-mongos-cert")

0 commit comments

Comments
 (0)