File: manager.py

package info (click to toggle)
python-podman 5.4.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,140 kB
  • sloc: python: 7,532; makefile: 82; sh: 75
file content (134 lines) | stat: -rw-r--r-- 4,499 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""Base classes for PodmanResources and Manager's."""

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

from podman.api.client import APIClient

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


class PodmanResource(ABC):  # noqa: B024
    """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,
        podman_client: Optional["PodmanClient"] = 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
            podman_client: PodmanClient() configured to connect to Podman object.
        """
        super().__init__()
        self.client = client
        self.manager = collection
        self.podman_client = podman_client

        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]

    def reload(self) -> None:
        """Refresh this object's data from the service."""
        latest = self.manager.get(self.id)
        self.attrs = latest.attrs


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: Optional[APIClient] = None, podman_client: Optional["PodmanClient"] = None
    ) -> None:
        """Initialize Manager() object.

        Args:
            client: APIClient() configured to connect to Podman service.
            podman_client: PodmanClient() configured to connect to Podman object.
        """
        super().__init__()
        self.client = client
        self.podman_client = podman_client

    @abstractmethod
    def exists(self, key: str) -> bool:
        """Returns True if resource exists.

        Podman only.

        Notes:
            This method does _not_ provide any mutex mechanism.
        """

    @abstractmethod
    def get(self, key: str) -> PodmanResourceType:
        """Returns representation of resource."""

    @abstractmethod
    def list(self, **kwargs) -> list[PodmanResourceType]:
        """Returns list of resources."""

    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.podman_client = self.podman_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, podman_client=self.podman_client, collection=self
            )

        # pylint: disable=broad-exception-raised
        raise Exception(f"Can't create {self.resource.__name__} from {attrs}")