Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ cryptography = "43.0.3"
executing = "1.2.0"
pydantic = "< 2"
ipywidgets = "8.1.2"
odh-kuberay-client = {version = "0.0.0.dev40", source = "testpypi"}
python-client = { git = "https://github.com/ray-project/kuberay.git", subdirectory = "clients/python-client", rev = "d1e750d9beac612ad455b951c1a789f971409ab3" }

[[tool.poetry.source]]
name = "pypi"
Expand Down Expand Up @@ -67,4 +67,3 @@ markers = [
]
addopts = "--timeout=900"
testpaths = ["src/codeflare_sdk"]
collect_ignore = ["src/codeflare_sdk/common/utils/unit_test_support.py"]
1 change: 1 addition & 0 deletions src/codeflare_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
AppWrapperStatus,
RayJobClient,
RayJob,
RayJobClusterConfig,
)

from .common.widgets import view_clusters
Expand Down
3 changes: 2 additions & 1 deletion src/codeflare_sdk/common/kueue/kueue.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from kubernetes import client
from kubernetes.client.exceptions import ApiException

from ...common.utils import get_current_namespace


def get_default_kueue_name(namespace: str) -> Optional[str]:
"""
Expand Down Expand Up @@ -81,7 +83,6 @@ def list_local_queues(
List[dict]:
A list of dictionaries containing the name of the local queue and the available flavors
"""
from ...ray.cluster.cluster import get_current_namespace

if namespace is None: # pragma: no cover
namespace = get_current_namespace()
Expand Down
7 changes: 7 additions & 0 deletions src/codeflare_sdk/common/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Common utilities for the CodeFlare SDK.
"""

from .k8s_utils import get_current_namespace

__all__ = ["get_current_namespace"]
37 changes: 37 additions & 0 deletions src/codeflare_sdk/common/utils/k8s_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Kubernetes utility functions for the CodeFlare SDK.
"""

import os
from kubernetes import config
from ..kubernetes_cluster import config_check, _kube_api_error_handling


def get_current_namespace():
"""
Retrieves the current Kubernetes namespace.

This function attempts to detect the current namespace by:
1. First checking if running inside a pod (reading from service account namespace file)
2. Falling back to reading from the current kubeconfig context

Returns:
str:
The current namespace or None if not found.
"""
if os.path.isfile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"):
try:
file = open("/var/run/secrets/kubernetes.io/serviceaccount/namespace", "r")
active_context = file.readline().strip("\n")
return active_context
except Exception as e:
print("Unable to find current namespace")
print("trying to gather from current context")
try:
_, active_context = config.list_kube_config_contexts(config_check())
except Exception as e:
return _kube_api_error_handling(e)
try:
return active_context["context"]["namespace"]
except KeyError:
return None
57 changes: 57 additions & 0 deletions src/codeflare_sdk/common/utils/test_demos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2025 IBM, Red Hat
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Tests for demos module.
"""

import pytest
import tempfile
from pathlib import Path
from unittest.mock import patch, MagicMock
from codeflare_sdk.common.utils.demos import copy_demo_nbs


class TestCopyDemoNbs:
"""Test cases for copy_demo_nbs function."""

def test_copy_demo_nbs_directory_exists_error(self):
"""Test that FileExistsError is raised when directory exists and overwrite=False."""
with tempfile.TemporaryDirectory() as temp_dir:
# Create a subdirectory that will conflict
conflict_dir = Path(temp_dir) / "demo-notebooks"
conflict_dir.mkdir()

with pytest.raises(FileExistsError, match="Directory.*already exists"):
copy_demo_nbs(dir=str(conflict_dir), overwrite=False)

def test_copy_demo_nbs_overwrite_true(self):
"""Test that overwrite=True allows copying to existing directory."""
with tempfile.TemporaryDirectory() as temp_dir:
# Create a subdirectory that will conflict
conflict_dir = Path(temp_dir) / "demo-notebooks"
conflict_dir.mkdir()

# Mock the demo_dir to point to a real directory
with patch("codeflare_sdk.common.utils.demos.demo_dir", temp_dir):
# Should not raise an error with overwrite=True
copy_demo_nbs(dir=str(conflict_dir), overwrite=True)

def test_copy_demo_nbs_default_parameters(self):
"""Test copy_demo_nbs with default parameters."""
with tempfile.TemporaryDirectory() as temp_dir:
# Mock the demo_dir to point to a real directory
with patch("codeflare_sdk.common.utils.demos.demo_dir", temp_dir):
# Should work with default parameters
copy_demo_nbs(dir=temp_dir, overwrite=True)
Loading
Loading