def remove(self, digest: str) -> None: """Remove Image digest from manifest list. Args: digest: Image digest to be removed. Should a full Image reference be provided the digest will be parsed out. Raises: ImageNotFound: When the Image could not be found APIError: When service reports an error """ if "@" in digest: digest = digest.split("@", maxsplit=2)[1] response = self.client.delete(f"/manifests/{self.quoted_name}", params={"digest": digest}) if response.status_code == requests.codes.okay: return self.reload() body = response.json() if response.status_code == requests.codes.not_found: raise ImageNotFound(body["cause"], response=response, explanation=body["message"]) raise APIError(body["cause"], response=response, explanation=body["message"])
def add(self, images: List[Union[Image, str]], **kwargs) -> None: """Add Image to manifest list. Args: images: List of Images to be added to manifest. Keyword Args: all (bool): annotation (Dict[str, str]): arch (str): features (List[str]): os (str): os_version (str): variant (str): Raises: ImageNotFound: When Image(s) could not be found APIError: When service reports an error """ params = { "all": kwargs.get("all"), "annotation": kwargs.get("annotation"), "arch": kwargs.get("arch"), "features": kwargs.get("features"), "images": list(), "os": kwargs.get("os"), "os_version": kwargs.get("os_version"), "variant": kwargs.get("variant"), } for item in images: if isinstance(item, Image): item = item.attrs["RepoTags"][0] params["images"].append(item) data = api.prepare_body(params) response = self.client.post(f"/manifests/{self.quoted_name}/add", data=data) if response.status_code == requests.codes.okay: return self.reload() body = response.json() if response.status_code == requests.codes.not_found: raise ImageNotFound(body["cause"], response=response, explanation=body["message"]) raise APIError(body["cause"], response=response, explanation=body["message"])
def create( self, names: List[str], images: Optional[List[Union[Image, str]]] = None, all: Optional[bool] = None, # pylint: disable=redefined-builtin ) -> Manifest: """Create a Manifest. Args: names: Identifiers to be added to the manifest. There must be at least one. images: Images or Image identifiers to be included in the manifest. all: When True, add all contents from images given. Raises: ValueError: When no names are provided. NotFoundImage: When a given image does not exist. """ if names is None or len(names) == 0: raise ValueError("At least one manifest name is required.") params = {"name": names} if images is not None: params["image"] = list() for item in images: if isinstance(item, Image): item = item.attrs["RepoTags"][0] params["image"].append(item) if all is not None: params["all"] = all response = self.client.post("/manifests/create", params=params) body = response.json() if response.status_code == requests.codes.okay: manifest = self.get(body["Id"]) manifest.attrs["names"] = names return manifest if response.status_code == requests.codes.not_found: raise ImageNotFound(body["cause"], response=response, explanation=body["message"]) raise APIError(body["cause"], response=response, explanation=body["message"])
def get(self, name: str) -> Image: # pylint: disable=arguments-differ """Returns an image by name or id. Args: name: Image id or name for which to search Raises: ImageNotFound: when image does not exist. APIError: when service returns an error. """ name = urllib.parse.quote_plus(name) response = self.client.get(f"/images/{name}/json") body = response.json() if response.status_code == requests.codes.ok: return self.prepare_model(body) if response.status_code == requests.codes.not_found: raise ImageNotFound(body["cause"], response=response, explanation=body["message"]) raise APIError(body["cause"], response=response, explanation=body["message"])
def history(self) -> List[Dict[str, Any]]: """Returns history of the Image. Raises: APIError: when service returns an error. """ response = self.client.get(f"/images/{self.id}/history") body = response.json() if response.status_code == requests.codes.ok: return body if response.status_code == requests.codes.not_found: raise ImageNotFound(body["cause"], response=response, explanation=body["message"]) raise APIError(body["cause"], response=response, explanation=body["message"])
def remove( self, image: Union[Image, str], force: Optional[bool] = None, noprune: bool = False ) -> List[Dict[str, Union[str, int]]]: """Delete image from Podman service. Args: image: Name or Id of Image to remove force: Delete Image even if in use noprune: Do not delete untagged parents. Ignored. Returns: List[Dict[Literal["Deleted", "Untagged", "Errors", "ExitCode"], Union[str, int]]] Raises: APIError: when service returns an error. Notes: The dictionaries with keys Errors and ExitCode are added. """ _ = noprune if isinstance(image, Image): image = image.id response = self.client.delete(f"/images/{image}", params={"force": force}) body = response.json() if response.status_code != requests.codes.ok: if response.status_code == requests.codes.not_found: raise ImageNotFound(body["cause"], response=response, explanation=body["message"]) raise APIError(body["cause"], response=response, explanation=body["message"]) # Dict[Literal["Deleted", "Untagged", "Errors", "ExitCode"], Union[int, List[str]]] results: List[Dict[str, Union[int, str]]] = [] for key in ("Deleted", "Untagged", "Errors"): if key in body: for element in body[key]: results.append({key: element}) results.append({"ExitCode": body["ExitCode"]}) return results
def tag(self, repository: str, tag: Optional[str], force: bool = False) -> bool: """Tag Image into repository. Args: repository: The repository for tagging Image. tag: optional tag name. force: force tagging. Always ignored. Returns: True, when operational succeeds. Raises: ImageNotFound: when service cannot find image. APIError: when service returns an error. """ _ = force params = {"repo": repository} if tag is not None: params["tag"] = tag response = self.client.post(f"/images/{self.id}/tag", params=params) if response.status_code == requests.codes.created: return True error = response.json() if response.status_code == requests.codes.not_found: raise ImageNotFound(error["cause"], response=response, explanation=error["message"]) raise APIError(error["cause"], response=response, explanation=error["message"])