text: import datetime
  import logging
  from abc import ABC, abstractmethod
  from collections.abc import AsyncIterator
  from dataclasses import dataclass, fields
  from typing import Any, Optional, TypeVar
  
  logger = logging.getLogger(__name__)
  
  
  class StorageError(Exception):
      pass
  
  
  class TransactionError(StorageError):
      pass
  
  
  class NotExistsError(StorageError):
      pass
  
  
  class ExistsError(StorageError):
      pass
  
  
  class UniquenessError(StorageError):
      pass
  
  
  _C = TypeVar("_C", bound="HasId")
  
  
  @dataclass(frozen=True)
  class HasId:
      id: str  # Unique, generated by storage
  
      @classmethod
      def from_data_obj(cls: type[_C], id: str, data_obj: Any) -> _C:
          assert issubclass(cls, type(data_obj))
  
          return cls(
              id=id,
              **{field.name: getattr(data_obj, field.name) for field in fields(data_obj)},
          )
  
  
  @dataclass(frozen=True)
  class ServiceAccountData:
      name: Optional[str]
      default_cluster: str
      role: str
      owner: str
      created_at: datetime.datetime
  
  
  @dataclass(frozen=True)
  class ServiceAccount(HasId, ServiceAccountData):
      pass
  
  
  class Storage(ABC):
      @abstractmethod
      async def create(self, data: ServiceAccountData) -> ServiceAccount:
          pass
  
      @abstractmethod
      async def get(self, id: str) -> ServiceAccount:
          pass
  
      @abstractmethod
      async def delete(self, id: str) -> None:
          pass
  
      @abstractmethod
      async def get_by_name(self, name: str, owner: str) -> ServiceAccount:
          pass
  
      @abstractmethod
      def list(
          self,
          owner: Optional[str] = None,
      ) -> AsyncIterator[ServiceAccount]:
          pass
  