기능 추가

This commit is contained in:
2026-01-02 16:31:41 +09:00
parent c7266d7fad
commit a1ecf4c634
2 changed files with 101 additions and 65 deletions

View File

@@ -20,10 +20,17 @@ yaml.width = 4096
# -----------------------------
# kubectl ingress 조회
# -----------------------------
def kubectl_ingress():
out = subprocess.check_output(
["kubectl", "get", "ingress", "--all-namespaces", "-o", "yaml"]
)
def kubectl_ingress(namespace=None):
cmd = ["kubectl", "get", "ingress"]
if namespace:
cmd += ["-n", namespace]
else:
cmd.append("--all-namespaces")
cmd += ["-o", "yaml"]
out = subprocess.check_output(cmd)
return yaml.load(out)
@@ -37,7 +44,6 @@ def load_mapping(path):
# -----------------------------
# annotation 렌더링
# (모든 value를 문자열로 강제)
# -----------------------------
def render_annotations_block(unsupported, partial, converted):
lines = []
@@ -53,7 +59,7 @@ def render_annotations_block(unsupported, partial, converted):
for p in partial:
lines.append(f" # PARTIAL SUPPORT: {p['note']}")
lines.append(f" {p['haproxy']}: \"{str(p['value'])}\"")
lines.append("")
lines.append("")
for c in converted:
lines.append(f" {c['haproxy']}: \"{str(c['value'])}\"")
@@ -62,7 +68,7 @@ def render_annotations_block(unsupported, partial, converted):
# -----------------------------
# 불필요한 metadata 제거
# metadata 정리
# -----------------------------
def cleanup_metadata(meta):
for k in [
@@ -75,10 +81,46 @@ def cleanup_metadata(meta):
meta.pop(k, None)
# -----------------------------
# ingressClassName 기준 필터링
# -----------------------------
def filter_by_ingress_class(data, from_ingress_class):
filtered = deepcopy(data)
filtered["items"] = []
for item in data.get("items", []):
spec = item.get("spec", {})
current_class = spec.get("ingressClassName", "nginx")
if current_class == from_ingress_class:
filtered["items"].append(item)
return filtered
# -----------------------------
# 변환 전 원본 백업 (backup/ns/ingress.yaml)
# -----------------------------
def backup_original_ingress(data, backup_dir="./backup"):
base = Path(backup_dir)
base.mkdir(parents=True, exist_ok=True)
for item in data.get("items", []):
meta = item.get("metadata", {})
name = meta.get("name")
namespace = meta.get("namespace", "default")
ns_dir = base / namespace
ns_dir.mkdir(parents=True, exist_ok=True)
with (ns_dir / f"{name}.yaml").open("w") as f:
yaml.dump(item, f)
# -----------------------------
# ingress 변환 로직
# -----------------------------
def migrate_ingress(data, mapping, ingress_class=None):
def migrate_ingress(data, mapping, to_ingress_class=None):
report = {
"converted": [],
"partial": [],
@@ -98,8 +140,8 @@ def migrate_ingress(data, mapping, ingress_class=None):
namespace = meta.get("namespace", "default")
ingress_id = f"{namespace}/{name}"
if ingress_class:
spec["ingressClassName"] = ingress_class
if to_ingress_class:
spec["ingressClassName"] = to_ingress_class
anns = meta.get("annotations", {}) or {}
@@ -123,18 +165,13 @@ def migrate_ingress(data, mapping, ingress_class=None):
report["converted"].append(k)
elif support == "partial" and haproxy_key:
partial.append(
{"haproxy": haproxy_key, "value": v, "note": note}
)
partial.append({"haproxy": haproxy_key, "value": v, "note": note})
report["partial"].append(k)
report["detail"][ingress_id]["partial"].append(
{"nginx": k, "haproxy": haproxy_key, "note": note}
)
else:
unsupported.append(
{"key": k, "value": v, "note": note}
)
unsupported.append({"key": k, "value": v, "note": note})
report["unsupported"].append(k)
report["detail"][ingress_id]["unsupported"].append(
{"nginx": k, "value": v, "note": note}
@@ -182,18 +219,24 @@ def write_report(report, path):
# -----------------------------
# 파일 저장 (split)
# 파일 저장 (yaml/ns/ingress.yaml)
# -----------------------------
def save_split(data, out_dir):
Path(out_dir).mkdir(parents=True, exist_ok=True)
def save_split(data, out_dir="./yaml"):
base = Path(out_dir)
base.mkdir(parents=True, exist_ok=True)
for item in data.get("items", []):
rendered = item.pop("_rendered_annotations", "")
name = item["metadata"]["name"]
namespace = item["metadata"].get("namespace", "default")
path = Path(out_dir) / f"{namespace}__{name}.yaml"
meta = item["metadata"]
name = meta["name"]
namespace = meta.get("namespace", "default")
with open(path, "w") as f:
ns_dir = base / namespace
ns_dir.mkdir(parents=True, exist_ok=True)
path = ns_dir / f"{name}.yaml"
with path.open("w") as f:
yaml.dump(item, f)
if rendered:
@@ -206,33 +249,6 @@ def save_split(data, out_dir):
path.write_text(content)
# -----------------------------
# 파일 저장 (single)
# -----------------------------
def save_single(data, out_path):
rendered_map = {}
for item in data.get("items", []):
rendered_map[id(item)] = item.pop("_rendered_annotations", "")
path = Path(out_path)
with path.open("w") as f:
yaml.dump(data, f)
content = path.read_text()
for item in data.get("items", []):
rendered = rendered_map.get(id(item))
if rendered:
content = content.replace(
"metadata:\n",
"metadata:\n annotations:\n" + rendered + "\n",
1,
)
path.write_text(content)
# -----------------------------
# main
# -----------------------------
@@ -241,37 +257,55 @@ def main():
description="nginx ingress → HAProxy ingress migration utility"
)
parser.add_argument("--mapping", default="mapping.yaml")
parser.add_argument("--single", action="store_true")
parser.add_argument("--split", action="store_true")
parser.add_argument("--out", default="output")
parser.add_argument("--ingress-class")
parser.add_argument("--out", default="./yaml")
parser.add_argument("--ingress-class", help="target ingressClassName")
parser.add_argument(
"--from-ingress-class",
default="nginx",
help="source ingressClassName (default: nginx)",
)
parser.add_argument(
"--namespace",
help="target namespace (default: all namespaces)",
)
parser.add_argument("--report", default="migration-report.md")
args = parser.parse_args()
if not args.single and not args.split:
parser.error("one of --single or --split must be specified")
if not args.split:
parser.error("--split must be specified")
# 🔹 기본 디렉토리 보장
Path("./backup").mkdir(parents=True, exist_ok=True)
Path(args.out).mkdir(parents=True, exist_ok=True)
ingress = kubectl_ingress(args.namespace)
ingress = filter_by_ingress_class(
ingress,
args.from_ingress_class,
)
backup_original_ingress(ingress)
ingress = kubectl_ingress()
mapping = load_mapping(args.mapping)
converted, report = migrate_ingress(
ingress, mapping, ingress_class=args.ingress_class
ingress,
mapping,
to_ingress_class=args.ingress_class,
)
if args.single:
out_file = args.out if args.out.endswith(".yaml") else f"{args.out}.yaml"
save_single(converted, out_file)
if args.split:
save_split(converted, args.out)
save_split(converted, args.out)
write_report(report, args.report)
print("\n=== Migration Summary ===")
print(f"Converted : {len(report['converted'])}")
print(f"Partial : {len(report['partial'])}")
print(f"Unsupported: {len(report['unsupported'])}")
print(f"Backup : ./backup/<namespace>/<ingress>.yaml")
print(f"Output : {args.out}/<namespace>/<ingress>.yaml")
print(f"Report : {args.report}")