Skip to content

Commit c552fbe

Browse files
committed
Add upgrade tests
1 parent c2b887e commit c552fbe

5 files changed

Lines changed: 325 additions & 114 deletions

File tree

tests/model_registry/conftest.py

Lines changed: 173 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -63,133 +63,181 @@ def model_registry_namespace(updated_dsc_component_state_scope_class: DataScienc
6363

6464
@pytest.fixture(scope="class")
6565
def model_registry_db_service(
66-
admin_client: DynamicClient, model_registry_namespace: str, is_model_registry_oauth: bool
66+
pytestconfig: Config,
67+
admin_client: DynamicClient,
68+
model_registry_namespace: str,
69+
is_model_registry_oauth: bool,
70+
teardown_resources: bool,
6771
) -> Generator[Service, Any, Any]:
68-
with Service(
69-
client=admin_client,
70-
name=DB_RESOURCES_NAME,
71-
namespace=model_registry_namespace,
72-
ports=[
73-
{
74-
"name": "mysql",
75-
"nodePort": 0,
76-
"port": 3306,
77-
"protocol": "TCP",
78-
"appProtocol": "tcp",
79-
"targetPort": 3306,
80-
}
81-
],
82-
selector={
83-
"name": DB_RESOURCES_NAME,
84-
},
85-
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
86-
annotations={
87-
"template.openshift.io/expose-uri": r"mysql://{.spec.clusterIP}:{.spec.ports[?(.name==\mysql\)].port}",
88-
},
89-
) as mr_db_service:
72+
if pytestconfig.option.post_upgrade:
73+
mr_db_service = Service(name=DB_RESOURCES_NAME, namespace=model_registry_namespace, ensure_exists=True)
9074
yield mr_db_service
75+
mr_db_service.delete(wait=True)
76+
else:
77+
with Service(
78+
client=admin_client,
79+
name=DB_RESOURCES_NAME,
80+
namespace=model_registry_namespace,
81+
ports=[
82+
{
83+
"name": "mysql",
84+
"nodePort": 0,
85+
"port": 3306,
86+
"protocol": "TCP",
87+
"appProtocol": "tcp",
88+
"targetPort": 3306,
89+
}
90+
],
91+
selector={
92+
"name": DB_RESOURCES_NAME,
93+
},
94+
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
95+
annotations={
96+
"template.openshift.io/expose-uri": r"mysql://{.spec.clusterIP}:{.spec.ports[?(.name==\mysql\)].port}",
97+
},
98+
teardown=teardown_resources,
99+
) as mr_db_service:
100+
yield mr_db_service
91101

92102

93103
@pytest.fixture(scope="class")
94104
def model_registry_db_pvc(
95-
admin_client: DynamicClient, model_registry_namespace: str, is_model_registry_oauth: bool
105+
pytestconfig: Config,
106+
admin_client: DynamicClient,
107+
model_registry_namespace: str,
108+
is_model_registry_oauth: bool,
109+
teardown_resources: bool,
96110
) -> Generator[PersistentVolumeClaim, Any, Any]:
97-
with PersistentVolumeClaim(
98-
accessmodes="ReadWriteOnce",
99-
name=DB_RESOURCES_NAME,
100-
namespace=model_registry_namespace,
101-
client=admin_client,
102-
size="5Gi",
103-
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
104-
) as pvc:
105-
yield pvc
111+
if pytestconfig.option.post_upgrade:
112+
mr_db_pvc = PersistentVolumeClaim(
113+
name=DB_RESOURCES_NAME, namespace=model_registry_namespace, ensure_exists=True
114+
)
115+
yield mr_db_pvc
116+
mr_db_pvc.delete(wait=True)
117+
else:
118+
with PersistentVolumeClaim(
119+
accessmodes="ReadWriteOnce",
120+
name=DB_RESOURCES_NAME,
121+
namespace=model_registry_namespace,
122+
client=admin_client,
123+
size="5Gi",
124+
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
125+
teardown=teardown_resources,
126+
) as pvc:
127+
yield pvc
106128

107129

108130
@pytest.fixture(scope="class")
109131
def model_registry_db_secret(
132+
pytestconfig: Config,
110133
admin_client: DynamicClient,
111134
model_registry_namespace: str,
112135
is_model_registry_oauth: bool,
136+
teardown_resources: bool,
113137
) -> Generator[Secret, Any, Any]:
114-
with Secret(
115-
client=admin_client,
116-
name=DB_RESOURCES_NAME,
117-
namespace=model_registry_namespace,
118-
string_data=MODEL_REGISTRY_DB_SECRET_STR_DATA,
119-
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
120-
annotations=MODEL_REGISTRY_DB_SECRET_ANNOTATIONS,
121-
) as mr_db_secret:
138+
if pytestconfig.option.post_upgrade:
139+
mr_db_secret = Secret(name=DB_RESOURCES_NAME, namespace=model_registry_namespace, ensure_exists=True)
122140
yield mr_db_secret
141+
mr_db_secret.delete(wait=True)
142+
else:
143+
with Secret(
144+
client=admin_client,
145+
name=DB_RESOURCES_NAME,
146+
namespace=model_registry_namespace,
147+
string_data=MODEL_REGISTRY_DB_SECRET_STR_DATA,
148+
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
149+
annotations=MODEL_REGISTRY_DB_SECRET_ANNOTATIONS,
150+
teardown=teardown_resources,
151+
) as mr_db_secret:
152+
yield mr_db_secret
123153

124154

125155
@pytest.fixture(scope="class")
126156
def model_registry_db_deployment(
157+
pytestconfig: Config,
127158
admin_client: DynamicClient,
128159
model_registry_namespace: str,
129160
model_registry_db_secret: Secret,
130161
model_registry_db_pvc: PersistentVolumeClaim,
131162
model_registry_db_service: Service,
132163
is_model_registry_oauth: bool,
164+
teardown_resources: bool,
133165
) -> Generator[Deployment, Any, Any]:
134-
with Deployment(
135-
name=DB_RESOURCES_NAME,
136-
namespace=model_registry_namespace,
137-
annotations={
138-
"template.alpha.openshift.io/wait-for-ready": "true",
139-
},
140-
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
141-
replicas=1,
142-
revision_history_limit=0,
143-
selector={"matchLabels": {"name": DB_RESOURCES_NAME}},
144-
strategy={"type": "Recreate"},
145-
template=get_model_registry_deployment_template_dict(
146-
secret_name=model_registry_db_secret.name, resource_name=DB_RESOURCES_NAME
147-
),
148-
wait_for_resource=True,
149-
) as mr_db_deployment:
150-
mr_db_deployment.wait_for_replicas(deployed=True)
151-
yield mr_db_deployment
166+
if pytestconfig.option.post_upgrade:
167+
db_deployment = Deployment(name=DB_RESOURCES_NAME, namespace=model_registry_namespace, ensure_exists=True)
168+
yield db_deployment
169+
db_deployment.delete(wait=True)
170+
else:
171+
with Deployment(
172+
name=DB_RESOURCES_NAME,
173+
namespace=model_registry_namespace,
174+
annotations={
175+
"template.alpha.openshift.io/wait-for-ready": "true",
176+
},
177+
label=get_model_registry_db_label_dict(db_resource_name=DB_RESOURCES_NAME),
178+
replicas=1,
179+
revision_history_limit=0,
180+
selector={"matchLabels": {"name": DB_RESOURCES_NAME}},
181+
strategy={"type": "Recreate"},
182+
template=get_model_registry_deployment_template_dict(
183+
secret_name=model_registry_db_secret.name, resource_name=DB_RESOURCES_NAME
184+
),
185+
wait_for_resource=True,
186+
teardown=teardown_resources,
187+
) as mr_db_deployment:
188+
mr_db_deployment.wait_for_replicas(deployed=True)
189+
yield mr_db_deployment
152190

153191

154192
@pytest.fixture(scope="class")
155193
def model_registry_instance(
156-
model_registry_namespace: str, model_registry_mysql_config: dict[str, Any], is_model_registry_oauth: bool
194+
pytestconfig: Config,
195+
model_registry_namespace: str,
196+
model_registry_mysql_config: dict[str, Any],
197+
is_model_registry_oauth: bool,
198+
teardown_resources: bool,
157199
) -> Generator[ModelRegistry, Any, Any]:
158-
istio_config = None
159-
oauth_config = None
160-
if is_model_registry_oauth:
161-
LOGGER.warning("Requested Ouath Proxy configuration:")
162-
oauth_config = OAUTH_PROXY_CONFIG_DICT
200+
if pytestconfig.option.post_upgrade:
201+
mr_instance = ModelRegistry(name=MR_INSTANCE_NAME, namespace=model_registry_namespace, ensure_exists=True)
202+
yield mr_instance
203+
mr_instance.delete(wait=True)
163204
else:
164-
LOGGER.warning("Requested OSSM configuration:")
165-
istio_config = ISTIO_CONFIG_DICT
166-
"""Creates a model registry instance with oauth proxy/service mesh configuration."""
167-
with ModelRegistry(
168-
name=MR_INSTANCE_NAME,
169-
namespace=model_registry_namespace,
170-
label=MODEL_REGISTRY_STANDARD_LABELS,
171-
grpc={},
172-
rest={},
173-
istio=istio_config,
174-
oauth_proxy=oauth_config,
175-
mysql=model_registry_mysql_config,
176-
wait_for_resource=True,
177-
) as mr:
178-
mr.wait_for_condition(condition="Available", status="True")
179-
yield mr
205+
istio_config = None
206+
oauth_config = None
207+
if is_model_registry_oauth:
208+
LOGGER.warning("Requested Ouath Proxy configuration:")
209+
oauth_config = OAUTH_PROXY_CONFIG_DICT
210+
else:
211+
LOGGER.warning("Requested OSSM configuration:")
212+
istio_config = ISTIO_CONFIG_DICT
213+
"""Creates a model registry instance with oauth proxy/service mesh configuration."""
214+
with ModelRegistry(
215+
name=MR_INSTANCE_NAME,
216+
namespace=model_registry_namespace,
217+
label=MODEL_REGISTRY_STANDARD_LABELS,
218+
grpc={},
219+
rest={},
220+
istio=istio_config,
221+
oauth_proxy=oauth_config,
222+
mysql=model_registry_mysql_config,
223+
wait_for_resource=True,
224+
teardown=teardown_resources,
225+
) as mr:
226+
mr.wait_for_condition(condition="Available", status="True")
227+
yield mr
180228

181229

182230
@pytest.fixture(scope="class")
183231
def model_registry_mysql_config(
184-
model_registry_db_deployment: Deployment, model_registry_db_secret: Secret
232+
model_registry_db_deployment: Deployment,
185233
) -> dict[str, Any]:
186234
return {
187235
"host": f"{model_registry_db_deployment.name}.{model_registry_db_deployment.namespace}.svc.cluster.local",
188-
"database": model_registry_db_secret.string_data["database-name"],
236+
"database": MODEL_REGISTRY_DB_SECRET_STR_DATA["database-name"],
189237
"passwordSecret": {"key": "database-password", "name": model_registry_db_deployment.name},
190238
"port": 3306,
191239
"skipDBCreation": False,
192-
"username": model_registry_db_secret.string_data["database-user"],
240+
"username": MODEL_REGISTRY_DB_SECRET_STR_DATA["database-user"],
193241
}
194242

195243

@@ -267,41 +315,52 @@ def after_call(self, response: Response, case: Case) -> None:
267315
@pytest.fixture(scope="class")
268316
def updated_dsc_component_state_scope_class(
269317
request: FixtureRequest,
318+
pytestconfig: Config,
270319
dsc_resource: DataScienceCluster,
271320
admin_client: DynamicClient,
272321
is_model_registry_oauth: bool,
322+
teardown_resources: bool,
273323
) -> Generator[DataScienceCluster, Any, Any]:
274-
original_components = dsc_resource.instance.spec.components
275-
component_patch = request.param["component_patch"]
276-
277-
with ResourceEditor(patches={dsc_resource: {"spec": {"components": component_patch}}}):
278-
for component_name in component_patch:
279-
dsc_resource.wait_for_condition(condition=DscComponents.COMPONENT_MAPPING[component_name], status="True")
280-
if component_patch.get(DscComponents.MODELREGISTRY):
281-
namespace = Namespace(
282-
name=dsc_resource.instance.spec.components.modelregistry.registriesNamespace, ensure_exists=True
283-
)
284-
namespace.wait_for_status(status=Namespace.Status.ACTIVE)
285-
wait_for_pods_running(
286-
admin_client=admin_client,
287-
namespace_name=py_config["applications_namespace"],
288-
number_of_consecutive_checks=6,
289-
)
324+
if not teardown_resources or pytestconfig.option.post_upgrade:
325+
# if we are not tearing down resources or we are in post upgrade, we don't need to do anything
326+
# the pre_upgrade/post_upgrade fixtures will handle the rest
290327
yield dsc_resource
291-
292-
for component_name, value in component_patch.items():
293-
LOGGER.info(f"Waiting for component {component_name} to be updated.")
294-
if original_components[component_name]["managementState"] == DscComponents.ManagementState.MANAGED:
295-
dsc_resource.wait_for_condition(condition=DscComponents.COMPONENT_MAPPING[component_name], status="True")
296-
if (
297-
component_name == DscComponents.MODELREGISTRY
298-
and value.get("managementState") == DscComponents.ManagementState.MANAGED
299-
):
300-
# Since namespace specified in registriesNamespace is automatically created after setting
301-
# managementStateto Managed. We need to explicitly delete it on clean up.
302-
namespace = Namespace(name=value["registriesNamespace"], ensure_exists=True)
303-
if namespace:
304-
namespace.delete(wait=True)
328+
else:
329+
original_components = dsc_resource.instance.spec.components
330+
component_patch = request.param["component_patch"]
331+
332+
with ResourceEditor(patches={dsc_resource: {"spec": {"components": component_patch}}}):
333+
for component_name in component_patch:
334+
dsc_resource.wait_for_condition(
335+
condition=DscComponents.COMPONENT_MAPPING[component_name], status="True"
336+
)
337+
if component_patch.get(DscComponents.MODELREGISTRY):
338+
namespace = Namespace(
339+
name=dsc_resource.instance.spec.components.modelregistry.registriesNamespace, ensure_exists=True
340+
)
341+
namespace.wait_for_status(status=Namespace.Status.ACTIVE)
342+
wait_for_pods_running(
343+
admin_client=admin_client,
344+
namespace_name=py_config["applications_namespace"],
345+
number_of_consecutive_checks=6,
346+
)
347+
yield dsc_resource
348+
349+
for component_name, value in component_patch.items():
350+
LOGGER.info(f"Waiting for component {component_name} to be updated.")
351+
if original_components[component_name]["managementState"] == DscComponents.ManagementState.MANAGED:
352+
dsc_resource.wait_for_condition(
353+
condition=DscComponents.COMPONENT_MAPPING[component_name], status="True"
354+
)
355+
if (
356+
component_name == DscComponents.MODELREGISTRY
357+
and value.get("managementState") == DscComponents.ManagementState.MANAGED
358+
):
359+
# Since namespace specified in registriesNamespace is automatically created after setting
360+
# managementStateto Managed. We need to explicitly delete it on clean up.
361+
namespace = Namespace(name=value["registriesNamespace"], ensure_exists=True)
362+
if namespace:
363+
namespace.delete(wait=True)
305364

306365

307366
@pytest.fixture(scope="class")

tests/model_registry/upgrade/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)