From 107156170854d1be3b09b56f5b2cab4b4280d8b8 Mon Sep 17 00:00:00 2001 From: chest Date: Mon, 1 Dec 2025 18:00:23 +0300 Subject: [PATCH] test: tags print --- main.py | 28 +++++++++ main_script.py | 162 ------------------------------------------------- 2 files changed, 28 insertions(+), 162 deletions(-) create mode 100644 main.py delete mode 100644 main_script.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..8e4244d --- /dev/null +++ b/main.py @@ -0,0 +1,28 @@ +import docker +from ctypes.wintypes import tagSIZE + +client = docker.from_env() +running_containers = [] +sleeping_containers = [] +for c in client.containers.list(all=True): + info = c.attrs # словарь со всеми данными + image = info["Config"]["Image"] # образ + created = info["Created"] # время создания + labels = info["Config"].get("Labels", {}) # лейблы + ports = info["NetworkSettings"]["Ports"] # проброшенные порты ЪЪЪ + mounts = info.get("Mounts", []) # маунты + status = c.status # статус контейнера (вкл-выкл) + tags = c.image.tags + container = { + "name": c.name, + "image": image, + "id": c.id[:12], + "create_time": created, + "mounted_data": mounts, + "labels": labels + } + if status == "running": + running_containers.append(container) + else: + sleeping_containers.append(container) +print(tags) \ No newline at end of file diff --git a/main_script.py b/main_script.py deleted file mode 100644 index 44ca63b..0000000 --- a/main_script.py +++ /dev/null @@ -1,162 +0,0 @@ -import docker -import re -from typing import List, Tuple, Optional, Dict - -SAFE_VERSIONS: Dict[str, str] = { #Потом тут будет взятие версий и CVE из базы CVE - "nginx": "1.25.4", - "redis": "7.2.4", - "postgres": "16.2", - "mysql": "8.0.36", -} - - -def parse_image_ref(image_ref: str) -> Tuple[str, str]: - if ":" in image_ref: - repo, tag = image_ref.rsplit(":", 1) - else: - repo, tag = image_ref, "latest" - name = repo.split("/")[-1] - return name, tag - - -def extract_version_from_tag(tag: str) -> Optional[str]: - tag = tag.strip() - if tag in ("latest", "", ""): - return None - base = re.split(r"[^0-9.]", tag)[0] - if not base or not re.search(r"\d", base): - return None - return base - - -def version_tuple(v: str) -> Tuple[int, ...]: - parts = v.split(".") - nums: List[int] = [] - for p in parts: - if p.isdigit(): - nums.append(int(p)) - else: - # На всякий случай вытащим ведущие цифры - m = re.match(r"(\d+)", p) - if m: - nums.append(int(m.group(1))) - return tuple(nums) - - -def compare_versions(v1: str, v2: str) -> int: - - t1 = version_tuple(v1) - t2 = version_tuple(v2) - max_len = max(len(t1), len(t2)) - t1 += (0,) * (max_len - len(t1)) - t2 += (0,) * (max_len - len(t2)) - if t1 < t2: - return -1 - if t1 > t2: - return 1 - return 0 - - -def detect_service(name: str) -> Optional[str]: - lname = name.lower() - for service in SAFE_VERSIONS.keys(): - if service in lname: - return service - return None - - -def main() -> None: - client = docker.from_env() - containers = client.containers.list(all=True) - - rows = [] - for c in containers: - image_tags = c.image.tags - if image_tags: - image_ref = image_tags[0] - else: - image_ref = c.attrs["Config"]["Image"] - - service_name_raw, tag = parse_image_ref(image_ref) - service = detect_service(service_name_raw) - version = extract_version_from_tag(tag) - - status = "UNKNOWN" - note = "" - - if service is None: - status = "SKIP" - note = "Неизвестный сервис (не в списке SAFE_VERSIONS)" - elif version is None: - status = "UNKNOWN" - note = "Не удалось определить версию из тега" - else: - safe_ver = SAFE_VERSIONS.get(service) - if safe_ver is None: - status = "UNKNOWN" - note = "Нет эталонной версии для сравнения" - else: - cmp_res = compare_versions(version, safe_ver) - if cmp_res < 0: - status = "OUTDATED" - note = f"Версия ниже безопасной ({safe_ver})" - elif cmp_res == 0: - status = "SAFE" - note = "Соответствует безопасной версии" - else: - status = "NEWER" - note = f"Версия выше эталонной ({safe_ver})" - - rows.append( - { - "container": c.name, - "image": image_ref, - "service": service or "-", - "version": version or "-", - "status": status, - "note": note, - } - ) - - headers = ["CONTAINER", "IMAGE", "SERVICE", "VERSION", "STATUS", "NOTE"] - col_widths = {h: len(h) for h in headers} - - for r in rows: - col_widths["CONTAINER"] = max(col_widths["CONTAINER"], len(r["container"])) - col_widths["IMAGE"] = max(col_widths["IMAGE"], len(r["image"])) - col_widths["SERVICE"] = max(col_widths["SERVICE"], len(str(r["service"]))) - col_widths["VERSION"] = max(col_widths["VERSION"], len(str(r["version"]))) - col_widths["STATUS"] = max(col_widths["STATUS"], len(r["status"])) - col_widths["NOTE"] = max(col_widths["NOTE"], len(r["note"])) - - header_line = " ".join(h.ljust(col_widths[h]) for h in headers) - sep_line = " ".join("-" * col_widths[h] for h in headers) - print(header_line) - print(sep_line) - - for r in rows: - line = " ".join( - [ - r["container"].ljust(col_widths["CONTAINER"]), - r["image"].ljust(col_widths["IMAGE"]), - str(r["service"]).ljust(col_widths["SERVICE"]), - str(r["version"]).ljust(col_widths["VERSION"]), - r["status"].ljust(col_widths["STATUS"]), - r["note"].ljust(col_widths["NOTE"]), - ] - ) - print(line) - - total = len(rows) - outdated = sum(1 for r in rows if r["status"] == "OUTDATED") - safe = sum(1 for r in rows if r["status"] == "SAFE") - unknown = sum(1 for r in rows if r["status"] == "UNKNOWN") - print() - print(f"Всего контейнеров: {total}") - print(f"Безопасных: {safe}") - print(f"Устаревших: {outdated}") - print(f"Неопределённых: {unknown}") - - -if __name__ == "__main__": - main()