fix(deploy): rejoue la synchronisation dynv6 quand l'API ne répond pas
L'API dynv6 laisse par intermittence une écriture sans réponse, parfois appliquée malgré tout. La synchronisation est rejouée jusqu'à trois fois et relit l'état avant chaque écriture : une création aboutie malgré le délai n'est jamais dupliquée. Délai par appel porté à 60 s. Validé contre le vrai dynv6 depuis la VM : zone, rec et dev visent 10.101.200.37, et un certificat de test Let's Encrypt a été émis par DNS-01 pour dev.enervision-g3.dynv6.net.
This commit is contained in:
+25
-13
@@ -143,7 +143,7 @@ publier_dns() {
|
|||||||
[[ -r "$JETON_DNS" ]] || { echo "pas de jeton $JETON_DNS : ni DNS ni Let's Encrypt"; return 0; }
|
[[ -r "$JETON_DNS" ]] || { echo "pas de jeton $JETON_DNS : ni DNS ni Let's Encrypt"; return 0; }
|
||||||
DNS_TOKEN="$(tr -d '[:space:]' < "$JETON_DNS")" python3 - "$DOMAINE" "$ADRESSE" rec dev <<'PY' \
|
DNS_TOKEN="$(tr -d '[:space:]' < "$JETON_DNS")" python3 - "$DOMAINE" "$ADRESSE" rec dev <<'PY' \
|
||||||
|| echo "DNS : dynv6 refuse la mise à jour de $DOMAINE, enregistrements inchangés" >&2
|
|| echo "DNS : dynv6 refuse la mise à jour de $DOMAINE, enregistrements inchangés" >&2
|
||||||
import json, os, sys, urllib.request
|
import json, os, sys, time, urllib.request
|
||||||
|
|
||||||
domaine, adresse, *sous_noms = sys.argv[1:]
|
domaine, adresse, *sous_noms = sys.argv[1:]
|
||||||
|
|
||||||
@@ -151,22 +151,34 @@ def appel(methode, chemin, corps=None):
|
|||||||
requete = urllib.request.Request(
|
requete = urllib.request.Request(
|
||||||
f"https://dynv6.com/api/v2/{chemin}", method=methode,
|
f"https://dynv6.com/api/v2/{chemin}", method=methode,
|
||||||
data=None if corps is None else json.dumps(corps).encode(),
|
data=None if corps is None else json.dumps(corps).encode(),
|
||||||
headers={"Authorization": f"Bearer {os.environ['DNS_TOKEN']}",
|
headers={"Authorization": f"Bearer {os.environ['DNS_TOKEN']}", "User-Agent": "enervision-provision",
|
||||||
"Content-Type": "application/json", "Accept": "application/json"})
|
"Content-Type": "application/json", "Accept": "application/json"})
|
||||||
with urllib.request.urlopen(requete, timeout=20) as reponse:
|
with urllib.request.urlopen(requete, timeout=60) as reponse:
|
||||||
contenu = reponse.read()
|
contenu = reponse.read()
|
||||||
return json.loads(contenu) if contenu else None
|
return json.loads(contenu) if contenu else None
|
||||||
|
|
||||||
zone = appel("GET", f"zones/by-name/{domaine}")
|
def synchroniser():
|
||||||
if zone.get("ipv4address") != adresse:
|
zone = appel("GET", f"zones/by-name/{domaine}")
|
||||||
appel("PATCH", f"zones/{zone['id']}", {"ipv4address": adresse})
|
if zone.get("ipv4address") != adresse:
|
||||||
existants = {(r["type"], r["name"]): r for r in appel("GET", f"zones/{zone['id']}/records")}
|
appel("PATCH", f"zones/{zone['id']}", {"ipv4address": adresse})
|
||||||
for nom in sous_noms:
|
existants = {(r["type"], r["name"]): r for r in appel("GET", f"zones/{zone['id']}/records")}
|
||||||
actuel = existants.get(("A", nom))
|
for nom in sous_noms:
|
||||||
if actuel is None:
|
actuel = existants.get(("A", nom))
|
||||||
appel("POST", f"zones/{zone['id']}/records", {"type": "A", "name": nom, "data": adresse})
|
if actuel is None:
|
||||||
elif actuel["data"] != adresse:
|
appel("POST", f"zones/{zone['id']}/records", {"type": "A", "name": nom, "data": adresse})
|
||||||
appel("PATCH", f"zones/{zone['id']}/records/{actuel['id']}", {"data": adresse})
|
elif actuel["data"] != adresse:
|
||||||
|
appel("PATCH", f"zones/{zone['id']}/records/{actuel['id']}", {"data": adresse})
|
||||||
|
|
||||||
|
# dynv6 laisse parfois une écriture sans réponse, appliquée ou non : chaque essai relit l'état
|
||||||
|
# avant d'écrire, si bien qu'une création aboutie malgré le délai n'est jamais dupliquée.
|
||||||
|
for essai in range(3):
|
||||||
|
try:
|
||||||
|
synchroniser()
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
if essai == 2:
|
||||||
|
raise
|
||||||
|
time.sleep(5)
|
||||||
print(f"DNS : {domaine}, {', '.join(sous_noms)} visent {adresse}")
|
print(f"DNS : {domaine}, {', '.join(sous_noms)} visent {adresse}")
|
||||||
PY
|
PY
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user