diff --git a/README.md b/README.md index 837f93e..c694918 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,14 @@ To run the tests behind proxy using Notebook: * kfp_v2 * training (except TFJob due to https://github.com/canonical/training-operator/issues/182) +#### Running using `driver` + +After modifying the `PodDefault` from the pre-requisites section, you can pass the `--proxy` flag to the tox command and this should automatically apply the required changes to run behind proxy. + +```bash +tox -e kubeflow- -- --proxy +``` + #### Developer Notes Any environment that can be used to access and configure the Charmed Kubeflow deployment is diff --git a/assets/test-job.yaml.j2 b/assets/test-job.yaml.j2 index 89d254f..2dd22ca 100644 --- a/assets/test-job.yaml.j2 +++ b/assets/test-job.yaml.j2 @@ -7,6 +7,9 @@ spec: template: metadata: labels: + {% if proxy %} + notebook-proxy: "true" + {% endif %} access-minio: "true" access-ml-pipeline: "true" mlflow-server-minio: "true" diff --git a/driver/conftest.py b/driver/conftest.py index aabb9fc..111ae91 100644 --- a/driver/conftest.py +++ b/driver/conftest.py @@ -10,6 +10,12 @@ def pytest_addoption(parser: Parser): * Add a `--filter` option to (de)select test cases based on their name (see also https://docs.pytest.org/en/7.4.x/reference/reference.html#command-line-flags) """ + parser.addoption( + "--proxy", + help="If passed, a PodDefault with proxy environment variables will be applied to the Kubernetes deployment." + " Defaults to False.", + action="store_true", + ) parser.addoption( "--filter", help="Provide a filter to (de)select tests cases based on their name. The filter follows" diff --git a/driver/test_kubeflow_workloads.py b/driver/test_kubeflow_workloads.py index 203a995..11709d8 100644 --- a/driver/test_kubeflow_workloads.py +++ b/driver/test_kubeflow_workloads.py @@ -8,7 +8,11 @@ import pytest from lightkube import ApiError, Client, codecs -from lightkube.generic_resource import create_global_resource, load_in_cluster_generic_resources +from lightkube.generic_resource import ( + create_global_resource, + create_namespaced_resource, + load_in_cluster_generic_resources, +) from utils import assert_namespace_active, delete_job, fetch_job_logs, wait_for_job log = logging.getLogger(__name__) @@ -34,6 +38,15 @@ PYTEST_CMD_BASE = "pytest" +PODDEFAULT_RESOURCE = create_namespaced_resource( + group="kubeflow.org", + version="v1alpha1", + kind="poddefault", + plural="poddefaults", +) +PODDEFAULT_WITH_PROXY_PATH = Path("tests") / "proxy-poddefault.yaml" +PODDEFAULT_WITH_PROXY_NAME = "notebook-proxy" + @pytest.fixture(scope="session") def pytest_filter(request): @@ -83,6 +96,27 @@ def create_profile(lightkube_client): lightkube_client.delete(PROFILE_RESOURCE, name=NAMESPACE) +@pytest.fixture(scope="function") +def create_poddefaults_on_proxy(request, lightkube_client): + """Create PodDefault with proxy env variables for the Notebook inside the Job.""" + # Simply yield None if the proxy flag is not set + if not request.config.getoption("proxy"): + yield None + else: + log.info("Adding PodDefault with proxy settings.") + poddefault_resource = codecs.load_all_yaml(PODDEFAULT_WITH_PROXY_PATH.read_text()) + # Using the first item of the list of poddefault_resource. It is a one item list. + lightkube_client.create(poddefault_resource[0], namespace=NAMESPACE) + + yield + + # delete the PodDefault at the end of the module tests + log.info(f"Deleting PodDefault {PODDEFAULT_WITH_PROXY_NAME}...") + lightkube_client.delete( + PODDEFAULT_RESOURCE, name=PODDEFAULT_WITH_PROXY_NAME, namespace=NAMESPACE + ) + + @pytest.mark.abort_on_fail async def test_create_profile(lightkube_client, create_profile): """Test Profile creation. @@ -105,7 +139,9 @@ async def test_create_profile(lightkube_client, create_profile): assert_namespace_active(lightkube_client, NAMESPACE) -def test_kubeflow_workloads(lightkube_client, pytest_cmd, tests_checked_out_commit): +def test_kubeflow_workloads( + lightkube_client, pytest_cmd, tests_checked_out_commit, request, create_poddefaults_on_proxy +): """Run a K8s Job to execute the notebook tests.""" log.info(f"Starting Kubernetes Job {NAMESPACE}/{JOB_NAME} to run notebook tests...") resources = list( @@ -118,9 +154,11 @@ def test_kubeflow_workloads(lightkube_client, pytest_cmd, tests_checked_out_comm "tests_image": TESTS_IMAGE, "tests_remote_commit": tests_checked_out_commit, "pytest_cmd": pytest_cmd, + "proxy": True if request.config.getoption("proxy") else False, }, ) ) + assert len(resources) == 1, f"Expected 1 Job, got {len(resources)}!" lightkube_client.create(resources[0], namespace=NAMESPACE)