Skip to content

Commit fbb21a1

Browse files
committed
Change AW fs loading to k8s and begin converting unit tests
1 parent ae70ffd commit fbb21a1

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
@@ -323,7 +323,7 @@ def list_all_queued(namespace: str, print_to_console: bool = True):
323323
return app_wrappers
324324

325325

326-
def get_current_namespace():
326+
def get_current_namespace(): # pragma: no cover
327327
try:
328328
config.load_kube_config()
329329
_, active_context = config.list_kube_config_contexts()
@@ -338,11 +338,12 @@ def get_current_namespace():
338338
# private methods
339339

340340

341-
def _kube_api_error_handling(e: Exception):
341+
def _kube_api_error_handling(e: Exception): # pragma: no cover
342342
perm_msg = (
343343
"Action not permitted, have you put in correct/up-to-date auth credentials?"
344344
)
345345
nf_msg = "No instances found, nothing to be done."
346+
exists_msg = "Resource with this name already exists."
346347
if type(e) == config.ConfigException:
347348
raise PermissionError(perm_msg)
348349
if type(e) == executing.executing.NotOneValueFound:
@@ -354,6 +355,8 @@ def _kube_api_error_handling(e: Exception):
354355
return
355356
elif e.reason == "Unauthorized" or e.reason == "Forbidden":
356357
raise PermissionError(perm_msg)
358+
elif e.reason == "Conflict":
359+
raise FileExistsError(exists_msg)
357360
raise e
358361

359362

Diff for: tests/unit_test.py

+23-11
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
from torchx.schedulers.ray_scheduler import RayJob
6464
from torchx.schedulers.kubernetes_mcad_scheduler import KubernetesMCADJob
6565
import pytest
66+
import yaml
6667

6768

6869
# For mocking openshift client results
@@ -242,7 +243,7 @@ def test_cluster_creation():
242243

243244
def test_default_cluster_creation(mocker):
244245
mocker.patch(
245-
"openshift.get_project_name",
246+
"codeflare_sdk.cluster.cluster.get_current_namespace",
246247
return_value="opendatahub",
247248
)
248249
default_config = ClusterConfiguration(
@@ -257,27 +258,38 @@ def test_default_cluster_creation(mocker):
257258
return cluster
258259

259260

260-
def arg_check_apply_effect(*args):
261-
assert args[0] == "apply"
262-
assert args[1] == ["-f", "unit-test-cluster.yaml"]
261+
def arg_check_apply_effect(group, version, namespace, plural, body, *args):
262+
assert group == "mcad.ibm.com"
263+
assert version == "v1beta1"
264+
assert namespace == "ns"
265+
assert plural == "appwrappers"
266+
with open("unit-test-cluster.yaml") as f:
267+
aw = yaml.load(f, Loader=yaml.FullLoader)
268+
assert body == aw
269+
assert args == tuple()
263270

264271

265-
def arg_check_del_effect(*args):
266-
assert args[0] == "delete"
267-
assert args[1] == ["AppWrapper", "unit-test-cluster"]
272+
def arg_check_del_effect(group, version, namespace, plural, name, *args):
273+
assert group == "mcad.ibm.com"
274+
assert version == "v1beta1"
275+
assert namespace == "ns"
276+
assert plural == "appwrappers"
277+
assert name == "unit-test-cluster"
278+
assert args == tuple()
268279

269280

270281
def test_cluster_up_down(mocker):
282+
mocker.patch("kubernetes.config.load_kube_config", return_value="ignore")
271283
mocker.patch(
272-
"codeflare_sdk.cluster.auth.TokenAuthentication.login", return_value="ignore"
284+
"kubernetes.client.CustomObjectsApi.create_namespaced_custom_object",
285+
side_effect=arg_check_apply_effect,
273286
)
274287
mocker.patch(
275-
"codeflare_sdk.cluster.auth.TokenAuthentication.logout", return_value="ignore"
288+
"kubernetes.client.CustomObjectsApi.delete_namespaced_custom_object",
289+
side_effect=arg_check_del_effect,
276290
)
277-
mocker.patch("openshift.invoke", side_effect=arg_check_apply_effect)
278291
cluster = test_cluster_creation()
279292
cluster.up()
280-
mocker.patch("openshift.invoke", side_effect=arg_check_del_effect)
281293
cluster.down()
282294

283295

0 commit comments

Comments
 (0)