This commit is contained in:
@@ -176,6 +176,42 @@ def find_container_hostname(name):
|
||||
return extract_hostname(labels)
|
||||
|
||||
|
||||
def cert_issuer(hostname, timeout=5):
|
||||
"""Traefik'in o hostname icin su an sundugu sertifikanin issuer'ini
|
||||
dondurur (bos string = baglanti kurulamadi)."""
|
||||
try:
|
||||
p1 = subprocess.run(
|
||||
["openssl", "s_client", "-connect", "traefik:443", "-servername", hostname],
|
||||
input="", capture_output=True, text=True, timeout=timeout,
|
||||
)
|
||||
p2 = subprocess.run(
|
||||
["openssl", "x509", "-noout", "-issuer"],
|
||||
input=p1.stdout, capture_output=True, text=True, timeout=timeout,
|
||||
)
|
||||
return p2.stdout.strip()
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def wait_for_real_cert(hostname, max_wait=50):
|
||||
"""Traefik yeni bir hostname icin ilk ACME denemesini DNS/Cloudflare
|
||||
tam hazir olmadan yapabiliyor ve kendiliginden hizli tekrar
|
||||
denemiyor. Bu yuzden: gercek (Let's Encrypt) sertifika gelene kadar
|
||||
bekle; birkac saniye icinde gelmezse Traefik'i bir kez yeniden
|
||||
baslatarak ACME denemesini zorla tetikle."""
|
||||
deadline = time.time() + max_wait
|
||||
nudged = False
|
||||
while time.time() < deadline:
|
||||
if "Let's Encrypt" in cert_issuer(hostname):
|
||||
return True
|
||||
if not nudged and time.time() > deadline - max_wait + 8:
|
||||
subprocess.run(["docker", "restart", "traefik"])
|
||||
nudged = True
|
||||
time.sleep(3)
|
||||
time.sleep(2)
|
||||
return "Let's Encrypt" in cert_issuer(hostname)
|
||||
|
||||
|
||||
def ensure_dns(hostname):
|
||||
existing = requests.get(
|
||||
f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE_ID}/dns_records",
|
||||
@@ -486,7 +522,23 @@ def api_deploy():
|
||||
f"{name}:latest",
|
||||
], check=True)
|
||||
|
||||
return jsonify({"status": "deployed", "url": f"https://{hostname}"}), 200
|
||||
cert_ready = wait_for_real_cert(hostname)
|
||||
|
||||
return jsonify({
|
||||
"status": "deployed", "url": f"https://{hostname}", "cert_ready": cert_ready,
|
||||
}), 200
|
||||
|
||||
|
||||
@app.route("/api/wait-for-cert", methods=["POST"])
|
||||
def api_wait_for_cert():
|
||||
if not check_auth():
|
||||
return jsonify({"error": "unauthorized"}), 401
|
||||
body = request.get_json(force=True)
|
||||
hostname = body.get("hostname")
|
||||
if not hostname:
|
||||
return jsonify({"error": "hostname required"}), 400
|
||||
cert_ready = wait_for_real_cert(hostname)
|
||||
return jsonify({"cert_ready": cert_ready}), 200
|
||||
|
||||
|
||||
@app.route("/api/deploy/<name>", methods=["DELETE"])
|
||||
|
||||
Reference in New Issue
Block a user