Skip to content

Commit

Permalink
Merge pull request #425 from jsmolar/jsmolar
Browse files Browse the repository at this point in the history
Add support methods for CR objects
  • Loading branch information
jsmolar authored Jun 14, 2024
2 parents 42c2524 + 4314bec commit 7e93506
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 35 deletions.
24 changes: 24 additions & 0 deletions testsuite/openshift/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""OpenShift common objects"""

import dataclasses
import functools
from dataclasses import dataclass, field
from typing import Optional, Literal

from openshift_client import APIObject, timeout, OpenShiftPythonException

from testsuite.lifecycle import LifecycleObject
from testsuite.utils import asdict


class OpenShiftObject(APIObject, LifecycleObject):
Expand Down Expand Up @@ -44,6 +46,28 @@ def wait_until(self, test_function, timelimit=90):
return False


class CustomResource(OpenShiftObject):
"""Custom APIObjects that implements methods that improves manipulation with CR objects"""

def safe_apply(self):
"""
Modifies the model of the apiobj and asserts if a change was applied to a resource.
Uses modify_and_apply method from OpenshiftObject.
"""
result, status = self.modify_and_apply(lambda _: True, retries=2)
assert status, f"Unable to apply changes for APIObject with result: {result}"
return result

def __getitem__(self, name):
return self.model.spec[name]

def __setitem__(self, name, value):
if dataclasses.is_dataclass(value):
self.model.spec[name] = asdict(value)
else:
self.model.spec[name] = value


def modify(func):
"""Wraps method of a subclass of OpenShiftObject to use modify_and_apply when the object
is already committed to the server, or run it normally if it isn't.
Expand Down
8 changes: 4 additions & 4 deletions testsuite/openshift/authorino.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""Authorino CR object"""

import abc
from typing import Any, Optional, Dict, List
from dataclasses import dataclass
from typing import Any, Optional, Dict, List

from openshift_client import selector, timeout

from testsuite.openshift.client import OpenShiftClient
from testsuite.openshift import OpenShiftObject
from testsuite.lifecycle import LifecycleObject
from testsuite.openshift import CustomResource
from testsuite.openshift.client import OpenShiftClient
from testsuite.utils import asdict


Expand Down Expand Up @@ -44,7 +44,7 @@ def oidc_url(self):
"""Authorino oidc url"""


class AuthorinoCR(OpenShiftObject, Authorino):
class AuthorinoCR(CustomResource, Authorino):
"""Represents Authorino CR objects from Authorino-operator"""

@classmethod
Expand Down
62 changes: 51 additions & 11 deletions testsuite/openshift/kuadrant.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,69 @@
"""Kuadrant CR object"""

from openshift_client import selector
import dataclasses

from testsuite.openshift import OpenShiftObject, modify
from openshift_client import selector, timeout

from testsuite.openshift import CustomResource
from testsuite.openshift.deployment import Deployment
from testsuite.utils import asdict


class KuadrantSection:
"""
Base class for Kuadrant sub components:
Authorino - spec.authorino
Limitador - spec.limitador
"""

def __init__(self, kuadrant_cr, spec_name):
super().__init__()
self.kuadrant_cr = kuadrant_cr
self.spec_name = spec_name

def __getitem__(self, name):
return self.kuadrant_cr.model.spec[self.spec_name][name]

def __setitem__(self, name, value):
if dataclasses.is_dataclass(value):
self.kuadrant_cr.model.spec[self.spec_name][name] = asdict(value)
else:
self.kuadrant_cr.model.spec[self.spec_name][name] = value

def __getattr__(self, item):
try:
return getattr(self.kuadrant_cr, item)
except AttributeError as exc:
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{item}'") from exc

class KuadrantCR(OpenShiftObject):

class KuadrantCR(CustomResource):
"""Represents Kuadrant CR objects"""

LIMITADOR = "limitador-limitador"

@property
def limitador(self) -> dict:
"""Returns spec.limitador from Kuadrant object"""
return self.model.spec.setdefault("limitador", {})
def authorino(self) -> KuadrantSection:
"""Returns spec.authorino from Kuadrant object"""
return KuadrantSection(self, "authorino")

@limitador.setter
@modify
def limitador(self, value: dict):
"""Sets the value of spec.limitador"""
self.model.spec["limitador"] = value
@property
def limitador(self) -> KuadrantSection:
"""Returns spec.limitador from Kuadrant object"""
return KuadrantSection(self, "limitador")

@property
def limitador_deployment(self):
"""Returns Deployment object for this Authorino"""
with self.context:
return selector(f"deployment/{self.LIMITADOR}").object(cls=Deployment)

def wait_for_ready(self):
"""Waits until Kuadrant CR reports ready status"""
with timeout(90):
success, _, _ = self.self_selector().until_all(
success_func=lambda obj: len(obj.model.status.conditions) > 0
and all(x.status == "True" for x in obj.model.status.conditions)
)
assert success, "Kuadrant did got get ready in time"
self.refresh()
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import pytest

from testsuite.openshift.deployment import ContainerResources
from testsuite.utils import asdict

pytestmark = [pytest.mark.kuadrant_only]


Expand All @@ -18,31 +21,43 @@ def kuadrant_clean_up(request, kuadrant):
"""

def _finalize():
kuadrant.limitador = {"replicas": 1, "resourceRequirements": {"requests": {"cpu": "250m", "memory": "32Mi"}}}
kuadrant.limitador["replicas"] = 1
kuadrant.limitador["resourceRequirements"] = ContainerResources(requests_cpu="250m", requests_memory="32Mi")
kuadrant.safe_apply()
kuadrant.wait_for_ready()

request.addfinalizer(_finalize)


@pytest.mark.parametrize(
"field, value",
[
pytest.param("replicas", 2, id="replicas"),
pytest.param(
"resourceRequirements", {"requests": {"cpu": "300m", "memory": "40Mi"}}, id="resourceRequirements"
),
],
)
def test_fields_to_reconcile(kuadrant, field, value):
def test_replicas_field_to_reconcile(kuadrant):
"""
Test:
- change replicas field to 2 in Kuadrant CR
- assert that replicas field in Kuadrant CR spec.limitador and Limitador deployment is equal to 2
"""
kuadrant.limitador["replicas"] = 2
kuadrant.safe_apply()
kuadrant.wait_for_ready()

assert kuadrant.limitador["replicas"] == 2
assert kuadrant.limitador_deployment.model.spec["replicas"] == 2


def test_resource_requirements_field_to_reconcile(kuadrant):
"""
Test:
- change specific `field` to `value` in Kuadrant CR
- assert that `field` in Kuadrant CR Limitador is equal to `value`
- assert that `field` in Limitador deployment is equal to `value`
- change resourceRequirements field to `value` in Kuadrant CR
- assert that resourceRequirements field in Kuadrant CR spec.limitador and Limitador deployment
is equal to `value`
"""
kuadrant.limitador = {field: value}
value = ContainerResources(requests_cpu="300m", requests_memory="40Mi")

kuadrant.limitador["resourceRequirements"] = value
kuadrant.safe_apply()
kuadrant.wait_for_ready()

assert value == kuadrant.limitador[field]
assert str(value) in str(kuadrant.limitador_deployment.model.spec)
assert kuadrant.limitador["resourceRequirements"] == asdict(value)
assert kuadrant.limitador_deployment.model.spec.template.spec.containers[0]["resources"] == asdict(value)


@pytest.mark.xfail
Expand All @@ -55,9 +70,16 @@ def test_blank_fields_wont_reconcile(kuadrant):
- assert replicas field is 3 for limitador deployment
- assert blank field resourceRequirements is returned to default for limitador deployment
"""
kuadrant.limitador = {"replicas": 2, "resourceRequirements": {"requests": {"cpu": "300m", "memory": "40Mi"}}}
kuadrant.limitador["replicas"] = 2
kuadrant.limitador["resourceRequirements"] = ContainerResources(requests_cpu="300m", requests_memory="40Mi")
kuadrant.safe_apply()
kuadrant.wait_for_ready()

kuadrant.limitador = {"replicas": 3}
kuadrant.limitador["replicas"] = 3
kuadrant.safe_apply()
kuadrant.wait_for_ready()

assert kuadrant.limitador_deployment.model.spec.replicas == 3
assert "'cpu': '250m', 'memory': '32Mi'" in str(kuadrant.limitador_deployment.model.spec)
assert kuadrant.limitador_deployment.model.spec.template.spec.containers[0]["resources"] == asdict(
ContainerResources(requests_cpu="250m", requests_memory="32Mi")
)

0 comments on commit 7e93506

Please sign in to comment.