Skip to content

Commit

Permalink
Adapted acct-mgt unit tests for Openshift API Wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
QuanMPhm committed Mar 26, 2024
1 parent 23ca13b commit 0549611
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 124 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test-py39-unit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ jobs:
- name: Run functional tests
run: |
./ci/run_unit_tests.sh
pytest ./src/coldfront_plugin_cloud/tests/unit/moc_openshift/ -v --cov=acct_mgt --cov-report=term
26 changes: 0 additions & 26 deletions ci/devstack-test-oidc.py

This file was deleted.

4 changes: 0 additions & 4 deletions ci/run_functional_tests_openstack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ fi
export DJANGO_SETTINGS_MODULE="local_settings"
export FUNCTIONAL_TESTS="True"
export OS_AUTH_URL="http://$HOST_IP/identity"
export KEYCLOAK_URL="http://$HOST_IP:8080"
export KEYCLOAK_USER="admin"
export KEYCLOAK_PASS="nomoresecret"
export KEYCLOAK_REALM="master"

coverage run --source="." -m django test coldfront_plugin_cloud.tests.functional.openstack
coverage report
Expand Down
4 changes: 3 additions & 1 deletion ci/run_unit_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ fi

export DJANGO_SETTINGS_MODULE="local_settings"

coverage run --source="." -m django test coldfront_plugin_cloud.tests.unit
coverage run --source="." -a -m django test coldfront_plugin_cloud.tests.unit.test_attribute_migration
coverage run --source="." -a -m django test coldfront_plugin_cloud.tests.unit.test_calculate_quota_unit_hours
coverage run --source="." -a -m django test coldfront_plugin_cloud.tests.unit.test_utils
coverage report
4 changes: 4 additions & 0 deletions src/coldfront_plugin_cloud/acct_mgt/moc_openshift.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def __init__(self, client, logger, identity_name, quotas, limits):
self.limits = limits
self.apis = {}

if not self.limits:
self.logger.error("No default limit file provided.")
sys.exit(1)

def get_resource_api(self, api_version: str, kind: str):
"""Either return the cached resource api from self.apis, or fetch a
new one, store it in self.apis, and return it."""
Expand Down
17 changes: 11 additions & 6 deletions src/coldfront_plugin_cloud/tests/unit/moc_openshift/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,25 @@
import logging
import pytest

from acct_mgt.moc_openshift import MocOpenShift4x

from coldfront_plugin_cloud.acct_mgt.moc_openshift import MocOpenShift4x

@pytest.fixture
def config():
return {
"IDENTITY_PROVIDER": "fake-id-provider",
"QUOTA_DEF_FILE": "fake-quota-file",
"LIMIT_DEF_FILE": "fake-limit-file",
"identity_name": "fake-id-provider",
"quotas": {
":requests.fake1": {"base": 2, "coefficient": 0},
":requests.fake2": {"base": 2, "coefficient": 0}
},
"limits": {
"type": "FakeContainer",
"default": {"cpu": "2", "memory": "1024Mi", "nvidia.com/gpu": "0"}
},
}


@pytest.fixture()
def moc(config):
fake_client = mock.Mock(spec=["resources"])
fake_logger = mock.Mock(spec=logging.Logger)
return MocOpenShift4x(fake_client, fake_logger, config)
return MocOpenShift4x(fake_client, fake_logger, **config)
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@

import pytest

from acct_mgt.moc_openshift import MocOpenShift4x
from coldfront_plugin_cloud.acct_mgt.moc_openshift import MocOpenShift4x


def test_moc_openshift(moc):
assert moc.id_provider == "fake-id-provider"
assert moc.quotafile == "fake-quota-file"
assert moc.limitfile == "fake-limit-file"
assert moc.quotas == {
":requests.fake1": {"base": 2, "coefficient": 0},
":requests.fake2": {"base": 2, "coefficient": 0}
}
assert moc.limits == {
"type": "FakeContainer",
"default": {"cpu": "2", "memory": "1024Mi", "nvidia.com/gpu": "0"}
}


def test_moc_openshift_no_limit():
with pytest.raises(SystemExit):
MocOpenShift4x(
mock.Mock(),
mock.Mock(),
{
"IDENTITY_PROVIDER": "fake",
"QUOTA_DEF_FILE": "fake",
"LIMIT_DEF_FILE": None,
},
**{
"identity_name": "fake-id-provider",
"quotas": "fake-quota-file",
"limits": None,
}
)


Expand All @@ -31,11 +37,11 @@ def test_moc_openshift_no_quota():
MocOpenShift4x(
mock.Mock(),
mock.Mock(),
{
"IDENTITY_PROVIDER": "fake",
"QUOTA_DEF_FILE": None,
"LIMIT_DEF_FILE": "fake",
},
**{
"identity_name": "fake-id-provider",
"quotas": None,
"limits": {"fake-limits": 1},
}
)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# pylint: disable=missing-module-docstring
import pytest

import acct_mgt.moc_openshift
import coldfront_plugin_cloud.acct_mgt.moc_openshift as moc_openshift


@pytest.mark.parametrize(
Expand Down Expand Up @@ -29,4 +29,4 @@
],
)
def test_clean_openshift_metadata(data, expected):
assert acct_mgt.moc_openshift.clean_openshift_metadata(data) == expected
assert moc_openshift.clean_openshift_metadata(data) == expected
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ def test_delete_identity(moc):
)


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_user")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_user")
def test_useridentitymapping_exists(fake_get_user, moc):
fake_get_user.return_value = {"identities": ["fake-id-provider:fake-id"]}
assert moc.useridentitymapping_exists("fake-user", "fake-id")


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_user")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_user")
def test_useridentitymapping_exists_not(fake_get_user, moc):
fake_get_user.side_effect = kexc.NotFoundError(mock.Mock())
assert not moc.useridentitymapping_exists("fake-user", "fake-id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_project_exists_not(moc):
assert not moc.project_exists("fake-project")


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.create_limits", mock.Mock())
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.create_limits", mock.Mock())
def test_create_project(moc):
moc.create_project("fake-project", "Fake Project", "fake-user")
moc.client.resources.get.return_value.create.assert_called_with(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,39 @@
import pytest


@pytest.mark.xfail(reason="raises FileNotFoundError")
def test_get_quota_definitions_missing(moc):
"""What happens if the quota file is missing?"""
with mock.patch("builtins.open", mock.mock_open()) as fake_open:
fake_open.side_effect = FileNotFoundError()
res = moc.get_quota_definitions()
assert res == {}


@pytest.mark.xfail(reason="raises JSONDecodeError")
def test_get_quota_definitions_empty(moc):
"""What happens if the quota file exists but is empty?"""
with mock.patch("builtins.open", mock.mock_open(read_data="")):
res = moc.get_quota_definitions()
assert res == {}
"""What happens if the quota is None?"""
moc.quotas = None
res = moc.get_quota_definitions()
assert res == {}


@pytest.mark.xfail(reason="raises TypeError")
def test_get_quota_definitions_invalid(moc):
"""What happens if the quota file exists but contains invalid data?"""
with mock.patch("builtins.open", mock.mock_open(read_data='{"foo": "bar"}')):
res = moc.get_quota_definitions()
assert res == {}
"""What happens if the quota exists but contains invalid data?"""
moc.quotas = {"foo": "bar"}
res = moc.get_quota_definitions()
assert res == {}


def test_get_quota_definitions_valid(moc):
"""What happens if a valid quota file exists?"""
"""What happens if a valid quota exists?"""
quotadefs = {
":configmaps": {"base": 2, "coefficient": 0},
}
with mock.patch("builtins.open", mock.mock_open(read_data=json.dumps(quotadefs))):
res = moc.get_quota_definitions()
quotadefs[":configmaps"]["value"] = None
assert res == quotadefs
moc.quotas = quotadefs
res = moc.get_quota_definitions()
quotadefs[":configmaps"]["value"] = None
assert res == quotadefs


def test_split_quota_name(moc):
assert moc.split_quota_name(":foo") == ("Project", "foo")
assert moc.split_quota_name("scope:foo") == ("scope", "foo")


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_project", mock.Mock())
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_project", mock.Mock())
def test_get_resourcequotas(moc):
fake_quota = mock.Mock(spec=["to_dict"])
fake_quota.to_dict.return_value = {"items": []}
Expand All @@ -65,7 +56,7 @@ def test_delete_quota(moc):
assert res == {}


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_resourcequotas")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_resourcequotas")
def test_delete_moc_quota(fake_get_resourcequotas, moc):
fake_get_resourcequotas.return_value = [{"metadata": {"name": "fake-quota"}}]
moc.delete_moc_quota("test-project")
Expand All @@ -74,7 +65,7 @@ def test_delete_moc_quota(fake_get_resourcequotas, moc):
)


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_resourcequotas")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_resourcequotas")
def test_get_moc_quota_from_resourcequotas(fake_get_resourcequotas, moc):
fake_get_resourcequotas.return_value = [
{
Expand All @@ -91,7 +82,7 @@ def test_get_moc_quota_from_resourcequotas(fake_get_resourcequotas, moc):
assert res == {":cpu": "1", "BestEffort:memory": "1"}


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.wait_for_quota_to_settle")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.wait_for_quota_to_settle")
def test_create_shift_quotas(fake_wait_quota, moc):
quotadefs = {
":configmaps": {"value": "1"},
Expand Down Expand Up @@ -132,11 +123,11 @@ def test_wait_for_quota_to_settle(moc):


@mock.patch(
"acct_mgt.moc_openshift.MocOpenShift4x.get_moc_quota_from_resourcequotas",
"coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_moc_quota_from_resourcequotas",
mock.Mock(),
)
@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.delete_moc_quota", mock.Mock())
@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.create_shift_quotas")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.delete_moc_quota", mock.Mock())
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.create_shift_quotas")
def test_update_moc_quota(
fake_create_quotas,
moc,
Expand All @@ -152,17 +143,17 @@ def test_update_moc_quota(
}
}

with mock.patch("builtins.open", mock.mock_open(read_data=json.dumps(quotadefs))):
moc.update_moc_quota("fake-project", new_quota)
fake_create_quotas.assert_called_with(
"fake-project",
{":configmaps": {"value": None}, ":cpu": {"value": "1000"}},
)
moc.quotas = quotadefs
moc.update_moc_quota("fake-project", new_quota)
fake_create_quotas.assert_called_with(
"fake-project",
{":configmaps": {"value": None}, ":cpu": {"value": "1000"}},
)


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.delete_moc_quota", mock.Mock())
@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_resourcequotas")
@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.create_shift_quotas")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.delete_moc_quota", mock.Mock())
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_resourcequotas")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.create_shift_quotas")
def test_update_moc_quota_patch(
fake_create_quotas,
fake_get_resourcequotas,
Expand All @@ -188,19 +179,19 @@ def test_update_moc_quota_patch(

fake_get_resourcequotas.return_value = [fake_quota]

with mock.patch("builtins.open", mock.mock_open(read_data=json.dumps(quotadefs))):
moc.update_moc_quota("fake-project", new_quota, patch=True)
fake_create_quotas.assert_called_with(
"fake-project",
{
":services": {"value": "2"},
":configmaps": {"value": None},
":cpu": {"value": "1000"},
},
)
moc.quotas = quotadefs
moc.update_moc_quota("fake-project", new_quota, patch=True)
fake_create_quotas.assert_called_with(
"fake-project",
{
":services": {"value": "2"},
":configmaps": {"value": None},
":cpu": {"value": "1000"},
},
)


@mock.patch("acct_mgt.moc_openshift.MocOpenShift4x.get_moc_quota_from_resourcequotas")
@mock.patch("coldfront_plugin_cloud.acct_mgt.moc_openshift.MocOpenShift4x.get_moc_quota_from_resourcequotas")
def test_get_moc_quota(fake_get_quota, moc):
fake_get_quota.return_value = {
":services": {"value": "2"},
Expand All @@ -221,26 +212,26 @@ def test_get_moc_quota(fake_get_quota, moc):


def test_get_limit_definitions_valid(moc):
with mock.patch("builtins.open", mock.mock_open(read_data="{}")):
res = moc.get_limit_definitions()
assert res == {}
moc.limits = {}
res = moc.get_limit_definitions()
assert res == {}


def test_create_limits(moc):
limitdefs = '[{"type": "Container", "default": {"cpu": "200m", "memory": "512Mi"}}]'
fake_limit = mock.Mock(spec=["to_dict"])
fake_limit.to_dict.return_value = "fake-limit"
moc.client.resources.get.return_value.create.return_value = fake_limit
with mock.patch("builtins.open", mock.mock_open(read_data=limitdefs)):
res = moc.create_limits("fake-project")
assert res == "fake-limit"
moc.client.resources.get.return_value.create.assert_called_with(
namespace="fake-project",
body={
"metadata": {"name": "fake-project-limits"},
"spec": {"limits": json.loads(limitdefs)},
},
)
moc.limits = json.loads(limitdefs)
res = moc.create_limits("fake-project")
assert res == "fake-limit"
moc.client.resources.get.return_value.create.assert_called_with(
namespace="fake-project",
body={
"metadata": {"name": "fake-project-limits"},
"spec": {"limits": json.loads(limitdefs)},
},
)


def test_create_limits_custom(moc):
Expand Down
Loading

0 comments on commit 0549611

Please sign in to comment.