From b8c25b2529321cb41e2b6ba022a7d398ffff95b7 Mon Sep 17 00:00:00 2001 From: chest Date: Fri, 2 Jan 2026 00:31:05 +0300 Subject: [PATCH] feat: source find --- main.py | 119 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 28 deletions(-) diff --git a/main.py b/main.py index d23e308..2840e30 100644 --- a/main.py +++ b/main.py @@ -2,51 +2,99 @@ import docker client = docker.from_env() running_containers = [] -# sleeping_containers = [] -for c in client.containers.list(all=True): + +for c in client.containers.list(): # только запущенные контейнеры 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 # статус контейнера (вкл-выкл) - if tags := c.image.tags: - ver = c.image.tags[0].split(':')[-1] # версия - else: ver = None - workdir = info["Config"].get("WorkingDir") or '/' # рабочая директория + image = info["Config"]["Image"] # образ + created = info["Created"] # время создания + ports = info["NetworkSettings"]["Ports"] # проброшенные порты + mounts = info.get("Mounts", []) # маунты + status = c.status # статус контейнера (д.б. "running") + labels_container = info["Config"].get("Labels", {}) or {} + image_cfg = c.image.attrs.get("Config", {}) or {} + image_labels = image_cfg.get("Labels", {}) or {} + all_labels = {**image_labels, **labels_container} + source_url = ( + all_labels.get("org.opencontainers.image.source") + or all_labels.get("org.opencontainers.image.url") + or all_labels.get("org.opencontainers.image.documentation") + or all_labels.get("org.label-schema.vcs-url") + or all_labels.get("org.label-schema.url") + ) + source_revision = ( + all_labels.get("org.opencontainers.image.revision") + or all_labels.get("org.label-schema.vcs-ref") + ) + image_version_label = ( + all_labels.get("org.opencontainers.image.version") + or all_labels.get("org.label-schema.version") + ) + + # Версия из тега образа + tags = c.image.tags + if tags: + ver = tags[0].split(":", 1)[-1] + else: + ver = None + + # Рабочая директория + workdir = info["Config"].get("WorkingDir") or "/" + + # Поиск файлов зависимостей + req_paths = [] + language = None + req_find_cmd = ( - f"sh -c \"cd {workdir} 2>/dev/null && " + f"cd {workdir} 2>/dev/null || cd /; " "find . -maxdepth 3 \\( " "-name 'requirements*.txt' -o " "-name 'Pipfile' -o " "-name 'pyproject.toml' -o " - "-name 'package.json' " - "\\) 2>/dev/null | head -n 5\"" + "-name 'package.json' -о " + "-name 'go.mod' " + "\\) 2>/dev/null | head -n 5" ) - req = c.exec_run(req_find_cmd)[1].decode() # путь до файла с зависимостями - req_paths = [line.strip() for line in req.splitlines() if line.strip()] - language = None + req_res = c.exec_run(["sh", "-lc", req_find_cmd]) + if req_res.exit_code == 0: + req_out = req_res.output.decode(errors="ignore") + req_paths = [line.strip() for line in req_out.splitlines() if line.strip()] + else: + req_paths = [] + + # Определяем язык по файлам зависимостей for p in req_paths: - if "requirements" in p.lower() or p.endswith("Pipfile") or p.endswith("pyproject.toml"): + lower = p.lower() + if "requirements" in lower or p.endswith("Pipfile") or p.endswith("pyproject.toml"): language = "python" break if p.endswith("package.json"): language = "nodejs" break + if p.endswith("go.mod"): + language = "go" + break + + # Поиск "главных" файлов кода + code_paths = [] code_find_cmd = ( f"cd {workdir} 2>/dev/null || cd /; " "find . -maxdepth 4 -type f \\( " - "-name 'main.*' -o " + "-name 'main.*' -о " "-name 'app.*' -o " "-name 'index.*' " "\\) 2>/dev/null | head -n 10" ) - code = c.exec_run(code_find_cmd) - code_paths = [line.strip() for line in code[1].decode(errors='ignore').splitlines() if line.strip()] + code_res = c.exec_run(["sh", "-lc", code_find_cmd]) + if code_res.exit_code == 0: + code_out = code_res.output.decode(errors="ignore") + code_paths = [line.strip() for line in code_out.splitlines() if line.strip()] + else: + code_paths = [] + + # Если по зависимостям язык не определился — пробуем по расширениям файлов кода if language is None: for p in code_paths: p_lower = p.lower() @@ -72,16 +120,31 @@ for c in client.containers.list(all=True): language = "java" break - container = { + container_data = { "name": c.name, "version": ver, "image": image, "id": c.id[:12], "create_time": created, "mounted_data": mounts, - "labels": labels + "labels": labels_container, + "all_labels": all_labels, + "source_url": source_url, + "source_revision": source_revision, + "image_version_label": image_version_label, + "language": language, + "dep_files": req_paths, + "code_files": code_paths, } - if status == "running": - running_containers.append(container) - # else: - # sleeping_containers.append(container) + running_containers.append(container_data) + +# Проверочный вывод +for c in running_containers: + print(f"{c['name']} ({c['image']})") + print(f" id: {c['id']}, created: {c['create_time']}") + print(f" tag_version: {c['version']}, label_version: {c['image_version_label']}") + print(f" language: {c['language']}") + print(f" source: {c['source_url']} rev: {c['source_revision']}") + print(f" dep_files: {c['dep_files']}") + print(f" code_files: {c['code_files']}") + print()