Skip to content

Commit

Permalink
Change AW fs loading to k8s and begin converting unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxusmusti committed Jun 8, 2023
1 parent ae70ffd commit fbb21a1
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 49 deletions.
65 changes: 29 additions & 36 deletions src/codeflare_sdk/cluster/awload.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import openshift as oc
import yaml

from kubernetes import client, config
from .cluster import _kube_api_error_handling


class AWManager:
"""
Expand All @@ -40,10 +43,10 @@ def __init__(self, filename: str) -> None:
self.filename = filename
try:
with open(self.filename) as f:
awyaml = yaml.load(f, Loader=yaml.FullLoader)
assert awyaml["kind"] == "AppWrapper"
self.name = awyaml["metadata"]["name"]
self.namespace = awyaml["metadata"]["namespace"]
self.awyaml = yaml.load(f, Loader=yaml.FullLoader)
assert self.awyaml["kind"] == "AppWrapper"
self.name = self.awyaml["metadata"]["name"]
self.namespace = self.awyaml["metadata"]["namespace"]
except:
raise ValueError(
f"{filename } is not a correctly formatted AppWrapper yaml"
Expand All @@ -55,19 +58,17 @@ def submit(self) -> None:
Attempts to create the AppWrapper custom resource using the yaml file
"""
try:
with oc.project(self.namespace):
oc.invoke("create", ["-f", self.filename])
except oc.OpenShiftPythonException as osp: # pragma: no cover
error_msg = osp.result.err()
if "Unauthorized" in error_msg or "Forbidden" in error_msg:
raise PermissionError(
"Action not permitted, have you put in correct/up-to-date auth credentials?"
)
elif "AlreadyExists" in error_msg:
raise FileExistsError(
f"An AppWrapper of the name {self.name} already exists in namespace {self.namespace}"
)
raise osp
config.load_kube_config()
api_instance = client.CustomObjectsApi()
api_instance.create_namespaced_custom_object(
group="mcad.ibm.com",
version="v1beta1",
namespace=self.namespace,
plural="appwrappers",
body=self.awyaml,
)
except Exception as e:
return _kube_api_error_handling(e)

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

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

self.submitted = False
print(f"AppWrapper {self.name} removed!")
7 changes: 5 additions & 2 deletions src/codeflare_sdk/cluster/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def list_all_queued(namespace: str, print_to_console: bool = True):
return app_wrappers


def get_current_namespace():
def get_current_namespace(): # pragma: no cover
try:
config.load_kube_config()
_, active_context = config.list_kube_config_contexts()
Expand All @@ -338,11 +338,12 @@ def get_current_namespace():
# private methods


def _kube_api_error_handling(e: Exception):
def _kube_api_error_handling(e: Exception): # pragma: no cover
perm_msg = (
"Action not permitted, have you put in correct/up-to-date auth credentials?"
)
nf_msg = "No instances found, nothing to be done."
exists_msg = "Resource with this name already exists."
if type(e) == config.ConfigException:
raise PermissionError(perm_msg)
if type(e) == executing.executing.NotOneValueFound:
Expand All @@ -354,6 +355,8 @@ def _kube_api_error_handling(e: Exception):
return
elif e.reason == "Unauthorized" or e.reason == "Forbidden":
raise PermissionError(perm_msg)
elif e.reason == "Conflict":
raise FileExistsError(exists_msg)
raise e


Expand Down
34 changes: 23 additions & 11 deletions tests/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
from torchx.schedulers.ray_scheduler import RayJob
from torchx.schedulers.kubernetes_mcad_scheduler import KubernetesMCADJob
import pytest
import yaml


# For mocking openshift client results
Expand Down Expand Up @@ -242,7 +243,7 @@ def test_cluster_creation():

def test_default_cluster_creation(mocker):
mocker.patch(
"openshift.get_project_name",
"codeflare_sdk.cluster.cluster.get_current_namespace",
return_value="opendatahub",
)
default_config = ClusterConfiguration(
Expand All @@ -257,27 +258,38 @@ def test_default_cluster_creation(mocker):
return cluster


def arg_check_apply_effect(*args):
assert args[0] == "apply"
assert args[1] == ["-f", "unit-test-cluster.yaml"]
def arg_check_apply_effect(group, version, namespace, plural, body, *args):
assert group == "mcad.ibm.com"
assert version == "v1beta1"
assert namespace == "ns"
assert plural == "appwrappers"
with open("unit-test-cluster.yaml") as f:
aw = yaml.load(f, Loader=yaml.FullLoader)
assert body == aw
assert args == tuple()


def arg_check_del_effect(*args):
assert args[0] == "delete"
assert args[1] == ["AppWrapper", "unit-test-cluster"]
def arg_check_del_effect(group, version, namespace, plural, name, *args):
assert group == "mcad.ibm.com"
assert version == "v1beta1"
assert namespace == "ns"
assert plural == "appwrappers"
assert name == "unit-test-cluster"
assert args == tuple()


def test_cluster_up_down(mocker):
mocker.patch("kubernetes.config.load_kube_config", return_value="ignore")
mocker.patch(
"codeflare_sdk.cluster.auth.TokenAuthentication.login", return_value="ignore"
"kubernetes.client.CustomObjectsApi.create_namespaced_custom_object",
side_effect=arg_check_apply_effect,
)
mocker.patch(
"codeflare_sdk.cluster.auth.TokenAuthentication.logout", return_value="ignore"
"kubernetes.client.CustomObjectsApi.delete_namespaced_custom_object",
side_effect=arg_check_del_effect,
)
mocker.patch("openshift.invoke", side_effect=arg_check_apply_effect)
cluster = test_cluster_creation()
cluster.up()
mocker.patch("openshift.invoke", side_effect=arg_check_del_effect)
cluster.down()


Expand Down

0 comments on commit fbb21a1

Please sign in to comment.