Source code for podman.domain.manager

"""Base classes for PodmanResources and Manager's."""

from abc import ABC, abstractmethod
from collections import abc
from typing import Any, List, Mapping, Optional, TypeVar, Union

from podman.api.client import APIClient

# Methods use this Type when a subclass of PodmanResource is expected.
PodmanResourceType: TypeVar = TypeVar("PodmanResourceType", bound="PodmanResource")


[docs] class PodmanResource(ABC): """Base class for representing resource of a Podman service. Attributes: attrs: Mapping of attributes for resource from Podman service """ def __init__( self, attrs: Optional[Mapping[str, Any]] = None, client: Optional[APIClient] = None, collection: Optional["Manager"] = None, ): """Initialize base class for PodmanResource's. Args: attrs: Mapping of attributes for resource from Podman service. client: Configured connection to a Podman service. collection: Manager of this category of resource, named `collection` for compatibility """ super().__init__() self.client = client self.manager = collection self.attrs = {} if attrs is not None: self.attrs.update(attrs) def __repr__(self): return f"<{self.__class__.__name__}: {self.short_id}>" def __eq__(self, other): return isinstance(other, self.__class__) and self.id == other.id def __hash__(self): return hash(f"{self.__class__.__name__}:{self.id}") @property def id(self): # pylint: disable=invalid-name """str: Returns the identifier for the object.""" return self.attrs.get("Id") @property def short_id(self): """str: Returns truncated identifier. 'sha256' preserved when included in the id. No attempt is made to ensure the returned value is semantically meaningful for all resources. """ if self.id.startswith("sha256:"): return self.id[:17] return self.id[:10]
[docs] def reload(self) -> None: """Refresh this object's data from the service.""" latest = self.manager.get(self.id) self.attrs = latest.attrs
[docs] class Manager(ABC): """Base class for representing a Manager of resources for a Podman service.""" @property @abstractmethod def resource(self): """Type[PodmanResource]: Class which the factory method prepare_model() will use.""" def __init__(self, client: APIClient = None) -> None: """Initialize Manager() object. Args: client: APIClient() configured to connect to Podman service. """ super().__init__() self.client = client
[docs] @abstractmethod def exists(self, key: str) -> bool: """Returns True if resource exists. Podman only. Notes: This method does _not_ provide any mutex mechanism. """
[docs] @abstractmethod def get(self, key: str) -> PodmanResourceType: """Returns representation of resource."""
[docs] @abstractmethod def list(self, **kwargs) -> List[PodmanResourceType]: """Returns list of resources."""
[docs] def prepare_model(self, attrs: Union[PodmanResource, Mapping[str, Any]]) -> PodmanResourceType: """Create a model from a set of attributes.""" # Refresh existing PodmanResource. if isinstance(attrs, PodmanResource): attrs.client = self.client attrs.collection = self return attrs # Instantiate new PodmanResource from Mapping[str, Any] if isinstance(attrs, abc.Mapping): # TODO Determine why pylint is reporting typing.Type not callable # pylint: disable=not-callable return self.resource(attrs=attrs, client=self.client, collection=self) # pylint: disable=broad-exception-raised raise Exception(f"Can't create {self.resource.__name__} from {attrs}")