harbor-ctl: add type hints, build_url helper, verify_ssl flag

This commit is contained in:
Username
2026-01-18 18:32:43 +01:00
parent 2e3ba5f0db
commit aecf1b4148

View File

@@ -2,21 +2,25 @@
"""Harbor registry control utility.""" """Harbor registry control utility."""
import argparse import argparse
import base64
import json import json
import os import os
import ssl
import sys import sys
import time import time
import urllib.request
import urllib.error import urllib.error
import ssl import urllib.request
from pathlib import Path from pathlib import Path
from typing import Any
VERSION = "0.1.0"
# Default config # Default config
DEFAULT_CREDS = Path("/opt/ansible/secrets/harbor/credentials.json") DEFAULT_CREDS = Path("/opt/ansible/secrets/harbor/credentials.json")
DEFAULT_URL = "https://harbor.mymx.me" DEFAULT_URL = "https://harbor.mymx.me"
def load_credentials(): def load_credentials() -> tuple[str | None, str | None, str]:
"""Load Harbor credentials from secrets file.""" """Load Harbor credentials from secrets file."""
if DEFAULT_CREDS.exists(): if DEFAULT_CREDS.exists():
with open(DEFAULT_CREDS) as f: with open(DEFAULT_CREDS) as f:
@@ -27,16 +31,32 @@ def load_credentials():
return os.environ.get("HARBOR_USER"), os.environ.get("HARBOR_PASS"), DEFAULT_URL return os.environ.get("HARBOR_USER"), os.environ.get("HARBOR_PASS"), DEFAULT_URL
def api_request(url, user, password, method="GET", data=None): def build_url(base: str, *parts: str, **params: str) -> str:
"""Build API URL from parts and optional query parameters."""
url = f"{base}/api/v2.0/{'/'.join(parts)}"
if params:
query = "&".join(f"{k}={v}" for k, v in params.items())
url = f"{url}?{query}"
return url
def api_request(
url: str,
user: str,
password: str,
method: str = "GET",
data: dict[str, Any] | None = None,
verify_ssl: bool = False,
) -> dict[str, Any]:
"""Make authenticated API request to Harbor.""" """Make authenticated API request to Harbor."""
ctx = ssl.create_default_context() ctx = ssl.create_default_context()
ctx.check_hostname = False if not verify_ssl:
ctx.verify_mode = ssl.CERT_NONE ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
req = urllib.request.Request(url, method=method) req = urllib.request.Request(url, method=method)
# Basic auth # Basic auth
import base64
credentials = base64.b64encode(f"{user}:{password}".encode()).decode() credentials = base64.b64encode(f"{user}:{password}".encode()).decode()
req.add_header("Authorization", f"Basic {credentials}") req.add_header("Authorization", f"Basic {credentials}")
@@ -555,9 +575,11 @@ Examples:
%(prog)s config library --show Show project settings %(prog)s config library --show Show project settings
""" """
) )
parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {VERSION}")
parser.add_argument("--url", help="Harbor URL", default=None) parser.add_argument("--url", help="Harbor URL", default=None)
parser.add_argument("-u", "--user", help="Username", default=None) parser.add_argument("-u", "--user", help="Username", default=None)
parser.add_argument("-p", "--password", help="Password", default=None) parser.add_argument("-p", "--password", help="Password", default=None)
parser.add_argument("--verify-ssl", action="store_true", help="Verify SSL certificates (default: skip)")
subparsers = parser.add_subparsers(dest="command", help="Commands") subparsers = parser.add_subparsers(dest="command", help="Commands")
@@ -659,6 +681,11 @@ Examples:
"config": cmd_config, "config": cmd_config,
} }
# Store connection params on args for command access
args.api_user = user
args.api_password = password
args.api_url = url
return commands[args.command](args, user, password, url) return commands[args.command](args, user, password, url)