Skip to content

Commit 4796650

Browse files
committed
Change AW fs loading to k8s and begin converting unit tests
1 parent 10e1f9d commit 4796650

File tree

3 files changed

+57
-49
lines changed

3 files changed

+57
-49
lines changed

src/codeflare_sdk/cluster/awload.py

Lines changed: 29 additions & 36 deletions
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!")

src/codeflare_sdk/cluster/cluster.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ def list_all_queued(namespace: str, print_to_console: bool = True):
327327
return app_wrappers
328328

329329

330-
def get_current_namespace():
330+
def get_current_namespace(): # pragma: no cover
331331
try:
332332
config.load_kube_config()
333333
_, active_context = config.list_kube_config_contexts()
@@ -342,11 +342,12 @@ def get_current_namespace():
342342
# private methods
343343

344344

345-
def _kube_api_error_handling(e: Exception):
345+
def _kube_api_error_handling(e: Exception): # pragma: no cover
346346
perm_msg = (
347347
"Action not permitted, have you put in correct/up-to-date auth credentials?"
348348
)
349349
nf_msg = "No instances found, nothing to be done."
350+
exists_msg = "Resource with this name already exists."
350351
if type(e) == config.ConfigException:
351352
raise PermissionError(perm_msg)
352353
if type(e) == executing.executing.NotOneValueFound:
@@ -358,6 +359,8 @@ def _kube_api_error_handling(e: Exception):
358359
return
359360
elif e.reason == "Unauthorized" or e.reason == "Forbidden":
360361
raise PermissionError(perm_msg)
362+
elif e.reason == "Conflict":
363+
raise FileExistsError(exists_msg)
361364
raise e
362365

363366

tests/unit_test.py

Lines changed: 23 additions & 11 deletions
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
@@ -248,7 +249,7 @@ def test_cluster_creation():
248249

249250
def test_default_cluster_creation(mocker):
250251
mocker.patch(
251-
"openshift.get_project_name",
252+
"codeflare_sdk.cluster.cluster.get_current_namespace",
252253
return_value="opendatahub",
253254
)
254255
default_config = ClusterConfiguration(
@@ -263,27 +264,38 @@ def test_default_cluster_creation(mocker):
263264
return cluster
264265

265266

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

270277

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

275286

276287
def test_cluster_up_down(mocker):
288+
mocker.patch("kubernetes.config.load_kube_config", return_value="ignore")
277289
mocker.patch(
278-
"codeflare_sdk.cluster.auth.TokenAuthentication.login", return_value="ignore"
290+
"kubernetes.client.CustomObjectsApi.create_namespaced_custom_object",
291+
side_effect=arg_check_apply_effect,
279292
)
280293
mocker.patch(
281-
"codeflare_sdk.cluster.auth.TokenAuthentication.logout", return_value="ignore"
294+
"kubernetes.client.CustomObjectsApi.delete_namespaced_custom_object",
295+
side_effect=arg_check_del_effect,
282296
)
283-
mocker.patch("openshift.invoke", side_effect=arg_check_apply_effect)
284297
cluster = test_cluster_creation()
285298
cluster.up()
286-
mocker.patch("openshift.invoke", side_effect=arg_check_del_effect)
287299
cluster.down()
288300

289301

0 commit comments

Comments
 (0)