diff --git a/blueos_repository/consolidate.py b/blueos_repository/consolidate.py index d6709c3..7ff7664 100755 --- a/blueos_repository/consolidate.py +++ b/blueos_repository/consolidate.py @@ -43,6 +43,17 @@ class Author: def from_json(json_dict: Dict[str, str]) -> "Author": return Author(name=json_dict["name"], email=json_dict["email"]) +@dataclasses.dataclass +class Platform: + architecture: str + variant: Optional[str] = None + os: Optional[str] = None + +@dataclasses.dataclass +class Image: + digest: str + size: int + platform: Platform @dataclasses.dataclass class Company: @@ -78,6 +89,7 @@ class Version: type: ExtensionType filter_tags: List[str] extra_links: Dict[str, str] + images: List[Image] @staticmethod def validate_filter_tags(tags: List[str]) -> List[str]: @@ -161,15 +173,37 @@ def valid_semver(string: str) -> Optional[semver.VersionInfo]: except ValueError: return None # not valid + def extract_images_from_tag(self, tag: Any) -> List[Image]: + active_images = [ + image + for image in tag["images"] + if (image["status"] == "active" and image["architecture"] != "unknown" and image["os"] != "unknown") + ] + + images = [ + Image( + digest=image["digest"], + size=image["size"], + platform=Platform( + architecture=image["architecture"], + variant=image.get("variant", None), + os=image.get("os", None), + ), + ) + for image in active_images + ] + return images + # pylint: disable=too-many-locals async def run(self) -> None: async for repository in self.all_repositories(): for tag in await self.registry.fetch_remote_tags(repository.docker): + tag_name = tag["name"] try: - if not self.valid_semver(tag): - print(f"{tag} is not valid SemVer, ignoring it...") + if not self.valid_semver(tag_name): + print(f"{tag_name} is not valid SemVer, ignoring it...") continue - raw_labels = await self.registry.fetch_labels(f"{repository.docker}:{tag}") + raw_labels = await self.registry.fetch_labels(f"{repository.docker}:{tag_name}") permissions = raw_labels.get("permissions", None) links = json5.loads(raw_labels.get("links", "{}")) website = links.pop("website", raw_labels.get("website", None)) @@ -178,7 +212,7 @@ async def run(self) -> None: docs = links.pop("docs", links.pop("documentation", raw_labels.get("docs", None))) readme = raw_labels.get("readme", None) if readme is not None: - readme = readme.replace(r"{tag}", tag) + readme = readme.replace(r"{tag_name}", tag_name) try: readme = await self.fetch_readme(readme) except Exception as error: # pylint: disable=broad-except @@ -201,9 +235,10 @@ async def run(self) -> None: type=type_, filter_tags=Version.validate_filter_tags(filter_tags), requirements=raw_labels.get("requirements", None), - tag=tag, + tag=tag_name, + images=self.extract_images_from_tag(tag), ) - repository.versions[tag] = new_version + repository.versions[tag_name] = new_version except KeyError as error: raise Exception(f"unable to parse repository {repository}: {error}") from error # sort the versions, with the highest version first diff --git a/blueos_repository/registry.py b/blueos_repository/registry.py index a7ea716..cfad120 100644 --- a/blueos_repository/registry.py +++ b/blueos_repository/registry.py @@ -41,7 +41,7 @@ async def _get_token(self, repo: str) -> str: raise Exception("Could not get auth token") return str((await resp.json(content_type=None))["token"]) - async def fetch_remote_tags(self, repository: str) -> List[str]: + async def fetch_remote_tags(self, repository: str) -> List[Any]: """Fetches the tags available for an image in DockerHub""" print(f"fetching tags in {repository}") self.token = await self._get_token(repository) @@ -55,9 +55,7 @@ async def fetch_remote_tags(self, repository: str) -> List[str]: data = await resp.json(content_type=None) tags = data["results"] - valid_images = [tag["name"] for tag in tags] - print(valid_images) - return valid_images + return tags def is_compatible(self, entry: Any) -> bool: if entry["os"] != "linux":