Skip to content

Commit 9b39910

Browse files
committed
Change AW fs loading to k8s and begin converting unit tests
1 parent 8d40bf8 commit 9b39910

File tree

3 files changed

+57
-49
lines changed

3 files changed

+57
-49
lines changed

Diff for: src/codeflare_sdk/cluster/awload.py

+29-36
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import openshift as oc
2424
import yaml
2525

26+
from kubernetes import client, config
27+
from .cluster import _kube_api_error_handling
28+
2629

2730
class AWManager:
2831
"""
@@ -40,10 +43,10 @@ def __init__(self, filename: str) -> None:
4043
self.filename = filename
4144
try:
4245
with open(self.filename) as f:
43-
awyaml = yaml.load(f, Loader=yaml.FullLoader)
44-
assert awyaml["kind"] == "AppWrapper"
45-
self.name = awyaml["metadata"]["name"]
46-
self.namespace = awyaml["metadata"]["namespace"]
46+
self.awyaml = yaml.load(f, Loader=yaml.FullLoader)
47+
assert self.awyaml["kind"] == "AppWrapper"
48+
self.name = self.awyaml["metadata"]["name"]
49+
self.namespace = self.awyaml["metadata"]["namespace"]
4750
except:
4851
raise ValueError(
4952
f"{filename } is not a correctly formatted AppWrapper yaml"
@@ -55,19 +58,17 @@ def submit(self) -> None:
5558
Attempts to create the AppWrapper custom resource using the yaml file
5659
"""
5760
try:
58-
with oc.project(self.namespace):
59-
oc.invoke("create", ["-f", self.filename])
60-
except oc.OpenShiftPythonException as osp: # pragma: no cover
61-
error_msg = osp.result.err()
62-
if "Unauthorized" in error_msg or "Forbidden" in error_msg:
63-
raise PermissionError(
64-
"Action not permitted, have you put in correct/up-to-date auth credentials?"
65-
)
66-
elif "AlreadyExists" in error_msg:
67-
raise FileExistsError(
68-
f"An AppWrapper of the name {self.name} already exists in namespace {self.namespace}"
69-
)
70-
raise osp
61+
config.load_kube_config()
62+
api_instance = client.CustomObjectsApi()
63+
api_instance.create_namespaced_custom_object(
64+
group="mcad.ibm.com",
65+
version="v1beta1",
66+
namespace=self.namespace,
67+
plural="appwrappers",
68+
body=self.awyaml,
69+
)
70+
except Exception as e:
71+
return _kube_api_error_handling(e)
7172

7273
self.submitted = True
7374
print(f"AppWrapper {self.filename} submitted!")
@@ -82,25 +83,17 @@ def remove(self) -> None:
8283
return
8384

8485
try:
85-
with oc.project(self.namespace):
86-
oc.invoke("delete", ["AppWrapper", self.name])
87-
except oc.OpenShiftPythonException as osp: # pragma: no cover
88-
error_msg = osp.result.err()
89-
if (
90-
'the server doesn\'t have a resource type "AppWrapper"' in error_msg
91-
or "forbidden" in error_msg
92-
or "Unauthorized" in error_msg
93-
or "Missing or incomplete configuration" in error_msg
94-
):
95-
raise PermissionError(
96-
"Action not permitted, have you put in correct/up-to-date auth credentials?"
97-
)
98-
elif "not found" in error_msg:
99-
self.submitted = False
100-
print("AppWrapper not found, was deleted in another manner")
101-
return
102-
else:
103-
raise osp
86+
config.load_kube_config()
87+
api_instance = client.CustomObjectsApi()
88+
api_instance.delete_namespaced_custom_object(
89+
group="mcad.ibm.com",
90+
version="v1beta1",
91+
namespace=self.namespace,
92+
plural="appwrappers",
93+
name=self.name,
94+
)
95+
except Exception as e:
96+
return _kube_api_error_handling(e)
10497

10598
self.submitted = False
10699
print(f"AppWrapper {self.name} removed!")

Diff for: src/codeflare_sdk/cluster/cluster.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ def list_all_queued(namespace: str, print_to_console: bool = True):
325325
return app_wrappers
326326

327327

328-
def get_current_namespace():
328+
def get_current_namespace(): # pragma: no cover
329329
try:
330330
config.load_kube_config()
331331
_, active_context = config.list_kube_config_contexts()
@@ -340,11 +340,12 @@ def get_current_namespace():
340340
# private methods
341341

342342

343-
def _kube_api_error_handling(e: Exception):
343+
def _kube_api_error_handling(e: Exception): # pragma: no cover
344344
perm_msg = (
345345
"Action not permitted, have you put in correct/up-to-date auth credentials?"
346346
)
347347
nf_msg = "No instances found, nothing to be done."
348+
exists_msg = "Resource with this name already exists."
348349
if type(e) == config.ConfigException:
349350
raise PermissionError(perm_msg)
350351
if type(e) == executing.executing.NotOneValueFound:
@@ -356,6 +357,8 @@ def _kube_api_error_handling(e: Exception):
356357
return
357358
elif e.reason == "Unauthorized" or e.reason == "Forbidden":
358359
raise PermissionError(perm_msg)
360+
elif e.reason == "Conflict":
361+
raise FileExistsError(exists_msg)
359362
raise e
360363

361364

Diff for: tests/unit_test.py

+23-11
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
from torchx.schedulers.ray_scheduler import RayJob
7171
from torchx.schedulers.kubernetes_mcad_scheduler import KubernetesMCADJob
7272
import pytest
73+
import yaml
7374

7475

7576
# For mocking openshift client results
@@ -249,7 +250,7 @@ def test_cluster_creation():
249250

250251
def test_default_cluster_creation(mocker):
251252
mocker.patch(
252-
"openshift.get_project_name",
253+
"codeflare_sdk.cluster.cluster.get_current_namespace",
253254
return_value="opendatahub",
254255
)
255256
default_config = ClusterConfiguration(
@@ -264,27 +265,38 @@ def test_default_cluster_creation(mocker):
264265
return cluster
265266

266267

267-
def arg_check_apply_effect(*args):
268-
assert args[0] == "apply"
269-
assert args[1] == ["-f", "unit-test-cluster.yaml"]
268+
def arg_check_apply_effect(group, version, namespace, plural, body, *args):
269+
assert group == "mcad.ibm.com"
270+
assert version == "v1beta1"
271+
assert namespace == "ns"
272+
assert plural == "appwrappers"
273+
with open("unit-test-cluster.yaml") as f:
274+
aw = yaml.load(f, Loader=yaml.FullLoader)
275+
assert body == aw
276+
assert args == tuple()
270277

271278

272-
def arg_check_del_effect(*args):
273-
assert args[0] == "delete"
274-
assert args[1] == ["AppWrapper", "unit-test-cluster"]
279+
def arg_check_del_effect(group, version, namespace, plural, name, *args):
280+
assert group == "mcad.ibm.com"
281+
assert version == "v1beta1"
282+
assert namespace == "ns"
283+
assert plural == "appwrappers"
284+
assert name == "unit-test-cluster"
285+
assert args == tuple()
275286

276287

277288
def test_cluster_up_down(mocker):
289+
mocker.patch("kubernetes.config.load_kube_config", return_value="ignore")
278290
mocker.patch(
279-
"codeflare_sdk.cluster.auth.TokenAuthentication.login", return_value="ignore"
291+
"kubernetes.client.CustomObjectsApi.create_namespaced_custom_object",
292+
side_effect=arg_check_apply_effect,
280293
)
281294
mocker.patch(
282-
"codeflare_sdk.cluster.auth.TokenAuthentication.logout", return_value="ignore"
295+
"kubernetes.client.CustomObjectsApi.delete_namespaced_custom_object",
296+
side_effect=arg_check_del_effect,
283297
)
284-
mocker.patch("openshift.invoke", side_effect=arg_check_apply_effect)
285298
cluster = test_cluster_creation()
286299
cluster.up()
287-
mocker.patch("openshift.invoke", side_effect=arg_check_del_effect)
288300
cluster.down()
289301

290302

0 commit comments

Comments
 (0)