This commit is contained in:
@@ -176,6 +176,42 @@ def find_container_hostname(name):
|
|||||||
return extract_hostname(labels)
|
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):
|
def ensure_dns(hostname):
|
||||||
existing = requests.get(
|
existing = requests.get(
|
||||||
f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE_ID}/dns_records",
|
f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE_ID}/dns_records",
|
||||||
@@ -486,7 +522,23 @@ def api_deploy():
|
|||||||
f"{name}:latest",
|
f"{name}:latest",
|
||||||
], check=True)
|
], 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"])
|
@app.route("/api/deploy/<name>", methods=["DELETE"])
|
||||||
|
|||||||
Reference in New Issue
Block a user