Source code for smarter.lib.annotation.contract

"""Pydantic models of annotation changes and selectors."""

from typing import Literal, Optional

from pydantic import BaseModel, ConfigDict, Field

from .validation import split_annotation_key

AnnotationAction = Literal["added", "changed", "removed"]
"""What happened to an annotation."""

AnnotationOperator = Literal["exists", "not_exists", "equals", "not_equals"]
"""How an :class:`AnnotationRequirement` tests a resource's annotation."""


[docs] class AnnotationChange(BaseModel): """One annotation of a resource that was added, changed or removed.""" model_config = ConfigDict(frozen=True, extra="forbid") key: str = Field(..., description="The annotation key, e.g. 'acme.com/crm-account-id'.") old_value: Optional[str] = Field(default=None, description="The value before the change, or None if it was added.") new_value: Optional[str] = Field(default=None, description="The value after the change, or None if it was removed.") @property def action(self) -> AnnotationAction: """Return ``added``, ``changed`` or ``removed``.""" if self.old_value is None: return "added" if self.new_value is None: return "removed" return "changed" @property def prefix(self) -> Optional[str]: """Return the key's prefix, e.g. ``acme.com``, or ``None``.""" return split_annotation_key(self.key)[0]
[docs] class AnnotationRequirement(BaseModel): """ One requirement of an annotation selector, in the syntax of Kubernetes label selectors. ============================ ==================================================== Selector Matches resources whose annotation ============================ ==================================================== ``acme.com/crm-id`` ``acme.com/crm-id`` exists, with any value ``!acme.com/crm-id`` ``acme.com/crm-id`` doesn't exist ``acme.com/crm-id=A-10042`` ``acme.com/crm-id`` is ``A-10042`` ``acme.com/crm-id!=A-10042`` ``acme.com/crm-id`` is missing, or isn't ``A-10042`` ============================ ==================================================== """ model_config = ConfigDict(frozen=True, extra="forbid") key: str = Field(..., description="The annotation key.") operator: AnnotationOperator = Field(..., description="How the annotation is tested.") value: Optional[str] = Field(default=None, description="The value, for 'equals' and 'not_equals'.") def __str__(self) -> str: if self.operator == "exists": return self.key if self.operator == "not_exists": return "!" + self.key if self.operator == "equals": return f"{self.key}={self.value}" return f"{self.key}!={self.value}"
__all__ = ["AnnotationAction", "AnnotationChange", "AnnotationOperator", "AnnotationRequirement"]