fix: 修复 Host Docker GC 合并回归
This commit is contained in:
@@ -1,6 +1,50 @@
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def parse_docker_human_size(raw):
|
||||
raw = str(raw).split("(")[0].strip()
|
||||
match = re.match(r"^([0-9.]+)\s*([KMGT]?B)$", raw, re.I)
|
||||
if not match:
|
||||
return None
|
||||
multiplier = {"B": 1, "KB": 1000, "MB": 1000**2, "GB": 1000**3, "TB": 1000**4}.get(match.group(2).upper(), 1)
|
||||
return int(float(match.group(1)) * multiplier)
|
||||
|
||||
|
||||
def parse_docker_build_cache(text):
|
||||
for line in text.splitlines():
|
||||
if not line.startswith("Build Cache"):
|
||||
continue
|
||||
match = re.match(r"^Build Cache\s+\S+\s+\S+\s+(\S+)\s+(\S+)", line.strip())
|
||||
if not match:
|
||||
continue
|
||||
size = parse_docker_human_size(match.group(1))
|
||||
reclaim = parse_docker_human_size(match.group(2))
|
||||
if size is None or reclaim is None:
|
||||
return None
|
||||
return {"sizeBytes": size, "reclaimableBytes": reclaim}
|
||||
return None
|
||||
|
||||
|
||||
def build_cache_only_payload(observed_at):
|
||||
disk_before = df_snapshot()
|
||||
section = host_docker_gc_section("buildCachePrune")
|
||||
until = str(OPTIONS.get("buildCacheUntil") or section.get("until") or "24h")
|
||||
if not host_docker_gc_enabled("buildCachePrune"):
|
||||
return {"ok": False, "action": "gc remote %s" % ACTION, "providerId": PROVIDER_ID, "scope": "build-cache-only", "dryRun": ACTION == "plan", "mutation": False, "diagnosis": host_docker_gc_reason("buildCachePrune", "BuildKit cache GC is disabled by YAML")}
|
||||
system_df = command(["docker", "system", "df"], 8)
|
||||
if system_df["exitCode"] != 0:
|
||||
return {"ok": False, "action": "gc remote %s" % ACTION, "providerId": PROVIDER_ID, "scope": "build-cache-only", "dryRun": ACTION == "plan", "mutation": False, "diagnosis": bounded(system_df)}
|
||||
cache = parse_docker_build_cache(system_df["stdout"])
|
||||
candidate = None
|
||||
if cache is not None and cache["reclaimableBytes"] > 0:
|
||||
candidate = {"id": "docker-builder:prune", "kind": "docker-build-cache-prune", "risk": "low", "sizeBytes": cache["sizeBytes"], "estimatedReclaimBytes": cache["reclaimableBytes"], "action": {"command": ["docker", "builder", "prune", "--all", "--force", "--filter", "until=%s" % until]}}
|
||||
payload = {"ok": True, "action": "gc remote %s" % ACTION, "providerId": PROVIDER_ID, "scope": "build-cache-only", "configSource": "config/unidesk-cli.yaml#gc.remote.targets.%s.hostDockerGc.buildCachePrune" % PROVIDER_ID, "dryRun": ACTION == "plan", "mutation": ACTION == "run" and candidate is not None, "observedAt": observed_at, "diskBefore": disk_before, "until": until, "candidates": [candidate] if candidate else []}
|
||||
if ACTION == "run" and candidate is not None:
|
||||
payload["result"] = execute(candidate)
|
||||
payload["diskAfter"] = df_snapshot()
|
||||
return payload
|
||||
|
||||
|
||||
def docker_containers():
|
||||
ps = command(["docker", "ps", "-qa", "--no-trunc"], 5)
|
||||
if ps["exitCode"] != 0 or not ps["stdout"].strip():
|
||||
|
||||
@@ -120,6 +120,10 @@ def run_json(args, timeout=45):
|
||||
}
|
||||
if process.returncode != 0:
|
||||
return None, result
|
||||
try:
|
||||
return json.loads(process.stdout or "{}"), result
|
||||
except Exception:
|
||||
return None, result
|
||||
|
||||
|
||||
def command_lines(args, timeout=30, limit=10000):
|
||||
@@ -150,10 +154,6 @@ def root_available_bytes():
|
||||
return int(result["stdoutTail"].splitlines()[-1].strip())
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return json.loads(process.stdout or "{}"), result
|
||||
except Exception:
|
||||
return None, result
|
||||
|
||||
|
||||
def write_state(config, payload):
|
||||
|
||||
@@ -1053,47 +1053,6 @@ def parse_journal_usage(text):
|
||||
mult = {"": 1, "K": 1024, "M": 1024**2, "G": 1024**3, "T": 1024**4}.get(m.group(2).upper(), 1)
|
||||
return int(float(m.group(1)) * mult)
|
||||
|
||||
def parse_docker_human_size(raw):
|
||||
raw = str(raw).split("(")[0].strip()
|
||||
m = re.match(r"^([0-9.]+)\s*([KMGT]?B)$", raw, re.I)
|
||||
if not m:
|
||||
return None
|
||||
mult = {"B": 1, "KB": 1000, "MB": 1000**2, "GB": 1000**3, "TB": 1000**4}.get(m.group(2).upper(), 1)
|
||||
return int(float(m.group(1)) * mult)
|
||||
|
||||
def parse_docker_build_cache(text):
|
||||
for line in text.splitlines():
|
||||
if not line.startswith("Build Cache"):
|
||||
continue
|
||||
match = re.match(r"^Build Cache\s+\S+\s+\S+\s+(\S+)\s+(\S+)", line.strip())
|
||||
if not match:
|
||||
continue
|
||||
size = parse_docker_human_size(match.group(1))
|
||||
reclaim = parse_docker_human_size(match.group(2))
|
||||
if size is None or reclaim is None:
|
||||
return None
|
||||
return {"sizeBytes": size, "reclaimableBytes": reclaim}
|
||||
return None
|
||||
|
||||
def build_cache_only_payload(observed_at):
|
||||
disk_before = df_snapshot()
|
||||
section = host_docker_gc_section("buildCachePrune")
|
||||
until = str(OPTIONS.get("buildCacheUntil") or section.get("until") or "24h")
|
||||
if not host_docker_gc_enabled("buildCachePrune"):
|
||||
return {"ok": False, "action": "gc remote %s" % ACTION, "providerId": PROVIDER_ID, "scope": "build-cache-only", "dryRun": ACTION == "plan", "mutation": False, "diagnosis": host_docker_gc_reason("buildCachePrune", "BuildKit cache GC is disabled by YAML")}
|
||||
system_df = command(["docker", "system", "df"], 8)
|
||||
if system_df["exitCode"] != 0:
|
||||
return {"ok": False, "action": "gc remote %s" % ACTION, "providerId": PROVIDER_ID, "scope": "build-cache-only", "dryRun": ACTION == "plan", "mutation": False, "diagnosis": bounded(system_df)}
|
||||
cache = parse_docker_build_cache(system_df["stdout"])
|
||||
candidate = None
|
||||
if cache is not None and cache["reclaimableBytes"] > 0:
|
||||
candidate = {"id": "docker-builder:prune", "kind": "docker-build-cache-prune", "risk": "low", "sizeBytes": cache["sizeBytes"], "estimatedReclaimBytes": cache["reclaimableBytes"], "action": {"command": ["docker", "builder", "prune", "--all", "--force", "--filter", "until=%s" % until]}}
|
||||
payload = {"ok": True, "action": "gc remote %s" % ACTION, "providerId": PROVIDER_ID, "scope": "build-cache-only", "configSource": "config/unidesk-cli.yaml#gc.remote.targets.%s.hostDockerGc.buildCachePrune" % PROVIDER_ID, "dryRun": ACTION == "plan", "mutation": ACTION == "run" and candidate is not None, "observedAt": observed_at, "diskBefore": disk_before, "until": until, "candidates": [candidate] if candidate else []}
|
||||
if ACTION == "run" and candidate is not None:
|
||||
payload["result"] = execute(candidate)
|
||||
payload["diskAfter"] = df_snapshot()
|
||||
return payload
|
||||
|
||||
# __UNIDESK_GC_REMOTE_HOST_DOCKER_HELPERS__
|
||||
|
||||
def cluster_preflight():
|
||||
|
||||
Reference in New Issue
Block a user