def test_property_proxy(subject_no_cache): from krules_core.providers import subject_factory, subject_storage_factory global _test_events _test_events = [] subject_no_cache.flush() with pytest.raises(AttributeError): _ = subject_no_cache.foo subject_no_cache.foo = 1 assert subject_no_cache.foo == 1 assert len(_test_events) == 1 if subject_storage_factory(subject_no_cache.name).is_persistent(): assert subject_factory(subject_no_cache.name).get("foo") == 1 assert subject_no_cache.m_foo == 1 assert subject_no_cache.foo == 1 subject_no_cache.m_foo = 2 assert len(_test_events) == 1 subject_no_cache.ext_foo = 3 assert subject_no_cache.ext_foo == 3 assert subject_no_cache.foo == 2 assert len(_test_events) == 1 if subject_storage_factory(subject_no_cache.name).is_persistent(): assert subject_factory(subject_no_cache.name).get_ext("foo") == 3 subject_no_cache.foo = lambda foo: foo * foo assert len(_test_events) == 2 assert subject_no_cache.foo == 4 subject_no_cache.foo.incr() assert len(_test_events) == 3 assert subject_no_cache.foo == 5 subject_no_cache.m_foo.incr(2) assert len(_test_events) == 3 assert subject_no_cache.foo == 7 subject_no_cache.foo.decr() assert subject_no_cache.foo == 6 with pytest.raises(TypeError): subject_no_cache.ext_foo.incr() with pytest.raises(TypeError): subject_no_cache.ext_foo.decr() del subject_no_cache.foo assert len(_test_events) == 5 with pytest.raises(AttributeError): _ = subject_no_cache.foo subject_no_cache.foo = 1 del subject_no_cache.m_foo assert len(_test_events) == 6 with pytest.raises(AttributeError): _ = subject_no_cache.foo del subject_no_cache.ext_foo with pytest.raises(AttributeError): _ = subject_no_cache.ext_foo
def test_memorydatabase(): subject_storage_factory.override( providers.Factory(lambda x: SQLLiteSubjectStorage(x, ":memory:")) ) assert not subject_storage_factory("test-subject").is_persistent() assert not subject_storage_factory("test-subject").is_concurrency_safe()
def test_memorydatabase(): if os.path.exists(TEST_FNAME): os.unlink(TEST_FNAME) subject_storage_factory.override( providers.Factory( lambda x, **kwargs: SQLLiteSubjectStorage(x, TEST_FNAME))) assert subject_storage_factory("test-subject").is_persistent() assert subject_storage_factory("test-subject").is_concurrency_safe()
def test_load_store_and_flush(): storage = subject_storage_factory("empty") storage.store(inserts=(SubjectProperty("p1", 1), SubjectProperty("p2", "2'3"), SubjectExtProperty("px1", 3), SubjectExtProperty("p1", "s1"))) props, ext_props = storage.load() assert len(props) == 0 assert len(ext_props) == 0 storage.store(updates=( SubjectProperty("p2", 3), SubjectExtProperty("p1", "s2"), ), deletes=( SubjectProperty("p1"), SubjectExtProperty("px1"), )) props, ext_props = storage.load() assert len(props) == 0 assert len(ext_props) == 0 storage.flush() assert len(props) == 0 assert len(ext_props) == 0
def test_set_and_get(): global NAMESPACE, POD_NAME spod = subject_storage_factory(f"/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}") with pytest.raises(AttributeError): spod.get(SubjectProperty("pset")) # simple value new_value, old_value = spod.set(SubjectProperty("pset", 1)) assert old_value is None assert new_value == 1 assert spod.get(SubjectProperty("pset")) == 1 spod.delete(SubjectProperty("pset")) new_value, old_value = spod.set(SubjectProperty("pset", 1), 0) assert old_value == 0 assert new_value == 1 new_value, old_value = spod.set(SubjectProperty("pset", "1'2")) assert new_value == "1'2" assert old_value == 1 assert spod.get(SubjectProperty("pset")) == "1'2" # computed value spod.set(SubjectProperty("pset", lambda: "1'2")) # no args spod.set(SubjectProperty("pset", lambda x: x.replace("'", "$"))) assert spod.get(SubjectProperty("pset")) == "1$2"
def __init__(self, name, event_info={}, use_cache_dafault=True): from krules_core.providers import subject_storage_factory self.name = name self._use_cache = use_cache_dafault self._storage = subject_storage_factory(name) self._event_info = event_info self._cached = None
def test_load_store_and_flush(): global NAMESPACE, POD_NAME spod = subject_storage_factory(f"/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}") props, ext_props = spod.load() initial_len_props = len(props) initial_len_ext_props = len(ext_props) spod.store( inserts=( SubjectProperty("p1", 1), SubjectProperty("p2", "2'3"), SubjectExtProperty("px1", 3), SubjectExtProperty("p1", "s1") ) ) spod._resource_body = None props, ext_props = spod.load() assert len(props) == 2+initial_len_props assert len(ext_props) == 2+initial_len_ext_props assert props["p1"] == 1 assert props["p2"] == "2'3" assert ext_props["px1"] == 3 assert ext_props["p1"] == "s1" spod.store( updates=( SubjectProperty("p2", 3), SubjectExtProperty("p1", "s2"), ), deletes=( SubjectProperty("p1"), SubjectExtProperty("px1"), ) ) spod._resource_body = None props, ext_props = spod.load() assert len(props) == 1+initial_len_props assert len(ext_props) == 1+initial_len_ext_props assert props["p2"] == 3 assert ext_props["p1"] == "s2" spod.flush() props, ext_props = spod.load() assert len(props) == initial_len_props and len(ext_props) == initial_len_ext_props
def test_ext_props(): storage = subject_storage_factory("test") storage.flush() storage.set(SubjectProperty("p1", 1)) storage.set(SubjectProperty("p2", 2)) storage.set(SubjectExtProperty("p3", 3)) storage.set(SubjectExtProperty("p4", 4)) props = storage.get_ext_props() assert len(props) == 0
def test_ext_props(): global NAMESPACE, POD_NAME spod = subject_storage_factory(f"/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}") spod.flush() initial_len = len(spod.get_ext_props()) spod.set(SubjectProperty("p1", 1)) spod.set(SubjectProperty("p2", 2)) spod.set(SubjectExtProperty("p3", 3)) spod.set(SubjectExtProperty("p4", 4)) props = spod.get_ext_props() assert len(props) == 2+initial_len assert "p3" in props and props["p3"] == 3 assert "p4" in props and props["p4"] == 4
def test_set_and_get(): storage = subject_storage_factory("empty") storage.flush() assert storage.get("my_prop") is None new_value, old_value = storage.set(SubjectProperty("my_prop", 1)) assert old_value is None assert new_value is None assert storage.get(SubjectProperty("my_prop")) is None storage.delete(SubjectProperty("my_prop")) new_value, old_value = storage.set(SubjectProperty("pset", 1), 0) assert old_value is None assert new_value is None new_value, old_value = storage.set(SubjectProperty("pset", "1'2")) assert new_value is None assert old_value is None assert storage.get(SubjectProperty("pset")) is None
def test_cache_policy(subject): from krules_core.providers import subject_factory, subject_storage_factory # default policy: use cache subject.flush() subject.set("p1", None) subject.set_ext("p2", None) subject_fresh = subject_factory(subject.name) with pytest.raises(AttributeError): subject_fresh.get("p1") with pytest.raises(AttributeError): subject_fresh.get_ext("p2") subject = subject_factory(subject.name, use_cache_default=False) subject.flush() subject.set("p1", None) subject.set_ext("p2", None) if subject_storage_factory(subject.name).is_persistent(): subject_fresh = subject_factory(subject.name) subject_fresh.get("p1") subject_fresh.get_ext("p2")
def test_factories(storage_subject1, storage_subject2): assert str(storage_subject1) != str(storage_subject2) assert str(subject_storage_factory("subject1")) == str(storage_subject1)
def storage_subject2(): return subject_storage_factory("subject2")
def storage_subject1(): return subject_storage_factory("subject1")
def test_factory_base_properties(): endpoints = [ ("/apis/apps/v1beta2/namespaces/my-namespace/deployments/my-deployment", { #"group": "apps", "apiversion": "apps/v1beta2", "namespace": "my-namespace", "resourcetype": "deployments", "name": "my-deployment", }), ("/apis/apps/v1beta2/namespaces/my-namespace/deployments/my-deployment/status", { #"group": "apps", "apiversion": "apps/v1beta2", "namespace": "my-namespace", "resourcetype": "deployments", "name": "my-deployment", "subresource": "status" }), ("/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations/my-webhook", { #"group": "admissionregistration.k8s.io", "apiversion": "admissionregistration.k8s.io/v1", "resourcetype": "mutatingwebhookconfigurations", "name": "my-webhook" }), ("/apis/airspot.krules.dev/v1/mycrd/my-resource/status", { #"group": "airspot.krules.dev", "apiversion": "airspot.krules.dev/v1", "resourcetype": "mycrd", "name": "my-resource", "subresource": "status" }), ("/api/v1/namespaces/my-namespace/pods/my-pod", { "apiversion": "v1", "namespace": "my-namespace", "resourcetype": "pods", "name": "my-pod" }), ("/api/v1/namespaces/my-namespace/pods/my-pod/status", { #"group": "core", "apiversion": "v1", "namespace": "my-namespace", "resourcetype": "pods", "name": "my-pod", "subresource": "status" }), ("/api/v1/nodes/my-node-1234", { #"group": "core", "apiversion": "v1", "resourcetype": "nodes", "name": "my-node-1234" }), ("/api/v1/nodes/my-node-1234/status", { #"group": "core", "apiversion": "v1", "resourcetype": "nodes", "name": "my-node-1234", "subresource": "status" }), ("/api/v1/namespaces/my-namespace", { #"group": "core", "apiversion": "v1", "resourcetype": "namespaces", "name": "my-namespace", }), ("/api/v1/namespaces/my-namespace/status", { #"group": "core", "apiversion": "v1", "resourcetype": "namespaces", "name": "my-namespace", "subresource": "status" }) ] for ep, values in endpoints: props, ext_props = subject_storage_factory(ep, {}).load() #if "group" in values: # assert ext_props["group"] == values["group"] assert ext_props["apiversion"] == values["apiversion"] if "namespace" in values: assert ext_props["namespace"] == values["namespace"] assert ext_props["resourcetype"] == values["resourcetype"] if "subresource" in values: assert ext_props["subresource"] == values["subresource"] assert ext_props["name"] == values["name"]
def test_set_get_del(subject): from krules_core.providers import subject_factory, subject_storage_factory subject.flush() # store nothing subject.store() global _test_events _test_events = [] # USE CACHE (default) subject.set("my-prop", 1) assert subject.get("my-prop") == 1 # not yet stored subject_copy = subject_factory(subject.name) with pytest.raises(AttributeError): subject_copy.get("my-prop") subject.store() subject_copy = subject_factory(subject.name) if subject_storage_factory(subject_copy.name).is_persistent(): assert subject_copy.get("my-prop") == 1 # callables new_value, old_value = subject.set("my-prop", lambda x: x + 2) assert new_value == 3 and old_value == 1 new_value, old_value = subject.set("my-prop-2", lambda x: x is None and 1 or x + 2) assert new_value == 1 and old_value is None # events assert len(_test_events) == 3 from krules_core import event_types # type assert _test_events[0][0] == _test_events[1][0] == _test_events[2][ 0] == event_types.SUBJECT_PROPERTY_CHANGED # subject assert _test_events[0][1].name == _test_events[1][1].name == _test_events[ 2][1].name == subject.name # payload payload = _test_events[0][2] assert payload[PayloadConst.PROPERTY_NAME] == "my-prop" and payload[PayloadConst.OLD_VALUE] is None \ and payload[PayloadConst.VALUE] == 1 payload = _test_events[1][2] assert payload[PayloadConst.PROPERTY_NAME] == "my-prop" and payload[PayloadConst.OLD_VALUE] == 1 \ and payload[PayloadConst.VALUE] == 3 payload = _test_events[2][2] assert payload[PayloadConst.PROPERTY_NAME] == "my-prop-2" and payload[PayloadConst.OLD_VALUE] is None \ and payload[PayloadConst.VALUE] == 1 # old the same with extended properties except that they are mute _test_events = [] subject.set_ext("my-prop", 1) assert subject.get_ext("my-prop") == 1 # not yet stored subject_copy = subject_factory(subject.name) with pytest.raises(AttributeError): subject_copy.get_ext("my-prop") subject.store() if subject_storage_factory(subject.name).is_persistent(): subject_copy = subject_factory(subject.name) assert subject_copy.get_ext("my-prop") == 1 # callables new_value, old_value = subject.set_ext("my-prop", lambda x: x + 2) assert new_value == 3 and old_value == 1 new_value, old_value = subject.set_ext("my-prop-2", lambda x: x is None and 1 or x + 2) assert new_value == 1 and old_value is None # events assert len(_test_events) == 0 # muted val, _ = subject.set("my-prop", "silent", muted=True) assert val == "silent" and len(_test_events) == 0 # NO CACHE subject.set("my-prop", 0, use_cache=False) # not calling store if subject_storage_factory(subject.name).is_persistent(): subject = subject_factory(subject.name) val = subject.get("my-prop", use_cache=False) assert val == 0 # with callables val, old_val = subject.set("my-prop", lambda x: x + 5, use_cache=False) assert old_val == 0 and val == 5 # events produced assert len(_test_events) == 2 # same with exts _test_events = [] subject.set_ext("my-prop", 0, use_cache=False) # not calling store if subject_storage_factory(subject.name).is_persistent(): subject = subject_factory(subject.name) val = subject.get_ext("my-prop", use_cache=False) assert val == 0 # with callables val, old_val = subject.set_ext("my-prop", lambda x: x + 5, use_cache=False) assert old_val == 0 and val == 5 # events NOT produced assert len(_test_events) == 0 # with cached if subject_storage_factory(subject.name).is_persistent(): subject = subject_factory(subject.name) val = subject.get("my-prop") assert val == 5 # prop cached subject.set("my-prop", 1, use_cache=False) val = subject.get("my-prop") # from cache assert val == 1 subject.store() # update cache subject = subject_factory(subject.name) val = subject.get("my-prop") assert val == 1 # prop cached subject.set("my-prop", 8, use_cache=True) val = subject.get("my-prop", use_cache=False) # update cache assert val == 1 val = subject.get("my-prop", use_cache=True) assert val == 1 subject.store() # deletes _test_events = [] # cache not loaded yet subject.delete("my-prop", use_cache=False) assert len(_test_events) == 1 and \ _test_events[0][0] == event_types.SUBJECT_PROPERTY_DELETED and \ _test_events[0][1].name == subject.name and \ _test_events[0][2][PayloadConst.PROPERTY_NAME] == "my-prop" with pytest.raises(AttributeError): subject.get("my-prop") with pytest.raises(AttributeError): subject.delete("my-prop") # add prop bypassing cache subject.set("my-prop", 0, use_cache=False) subject.delete("my-prop", use_cache=True) subject.store() with pytest.raises(AttributeError): subject.get("my-prop") # add prop in cache remove directly subject.set("my-prop", 0, use_cache=True) subject.delete("my-prop", use_cache=False) subject.store() with pytest.raises(AttributeError): subject.get("my-prop") # all in cache subject.set("my-prop", 0, use_cache=True) subject.delete("my-prop", use_cache=True) subject.store() with pytest.raises(AttributeError): subject.get("my-prop") # no cache subject.set("my-prop", 0, use_cache=False) subject.delete("my-prop", use_cache=False) subject.store() with pytest.raises(AttributeError): subject.get("my-prop")
def execute(self, prop, expected_value): if not subject_storage_factory( self.subject.name).is_concurrency_safe(): return True # skip test subject = subject_factory(self.subject.name) return subject.get(prop, cached=False) == expected_value