import logging
from abc import ABC, abstractmethod
from typing import List, Optional
from olc.bean.match_wrapper import MatchWrapper
from olc.bean.olc_config_rule import BasePolicy
from olc.bean.olc_control_request import OlcControlRequest
from olc.bean.tag_group import TagGroup, SubGroup
from olc.cache.safe__ttl_cache import SafeTTLCache, key_of_list
from olc.event.sny_event import Event
from olc.rule.olc_rule_manager import OlcRuleManager
logger = logging.getLogger(__name__)
class PolicyMatcher(ABC):
@abstractmethod
def match(
self, req: OlcControlRequest, group: List[TagGroup]
) -> List[MatchWrapper]:
pass
class AbstractPolicyMatcher(PolicyMatcher):
def __init__(self):
self._cache: SafeTTLCache[List[MatchWrapper[BasePolicy]]] = SafeTTLCache(
maxsize=100000, ttl=60
)
@abstractmethod
def get_policy(self, name: str) -> Optional[BasePolicy]:
pass
def match(
self, req: OlcControlRequest, groups: List[TagGroup]
) -> List[MatchWrapper]:
if not groups:
return []
result = self._cache.get(key_of_list(groups))
if (result is not None) and (len(result) == 0):
return result
result: List[MatchWrapper[BasePolicy]] = []
for group in groups:
if group.create_sub_group():
continue
group_name = group.name
if isinstance(group, SubGroup):
group_name = group.parent.name
policy: BasePolicy = self.get_policy(group_name)
if policy is None:
continue
result.append(MatchWrapper(group, policy))
if result:
min_priority = min(wrapper.tag_group.priority for wrapper in result)
result = [
wrapper
for wrapper in result
if wrapper.tag_group.priority == min_priority
]
self._cache.put(key_of_list(groups), result)
return result
class FlowMatcher(AbstractPolicyMatcher):
def __init__(self):
super().__init__()
Event.get_instance().olc_clean_rule.connect(self.subscribe_clean)
def get_policy(self, name: str) -> Optional[BasePolicy]:
return OlcRuleManager.get_instance().get_flow_policy_by_group_name(name)
def clean_cache(self):
self._cache.clear()
def subscribe_clean(self, sender, **kwargs):
logger.info("clean flow matcher cache")
self.clean_cache()
class AdmissionMatcher(AbstractPolicyMatcher):
def __init__(self):
super().__init__()
Event.get_instance().olc_clean_rule.connect(self.subscribe_clean)
def get_policy(self, name: str) -> Optional[BasePolicy]:
return OlcRuleManager.get_instance().get_admission_policy_by_group_name(name)
def clean_cache(self):
self._cache.clear()
def subscribe_clean(self, sender, **kwargs):
logger.info("clean admission matcher cache")
self.clean_cache()