From 13dd5cffa8951bbfa732d2fdb9c29887f161d4a8 Mon Sep 17 00:00:00 2001
From: Martin van Es <martin@mrvanes.com>
Date: Thu, 10 Mar 2022 14:59:29 +0100
Subject: [PATCH] Add GeoDNS config parser and timer service

---
 files/srv.mdx.incubator.geant.org.yaml        |  5 +-
 roles/geodns/files/geoconfig.py               | 37 +++++++++
 .../files/srv.mdx.incubator.geant.org.yaml    | 78 +++++++++++++++++++
 roles/geodns/handlers/main.yml                |  8 +-
 roles/geodns/tasks/main.yml                   | 25 +++++-
 .../geodns/templates/geodns-config.service.j2 | 11 +++
 roles/geodns/templates/geodns-config.timer.j2 |  9 +++
 roles/geodns/templates/geodns.service.j2      |  4 +-
 8 files changed, 167 insertions(+), 10 deletions(-)
 create mode 100755 roles/geodns/files/geoconfig.py
 create mode 100644 roles/geodns/files/srv.mdx.incubator.geant.org.yaml
 create mode 100644 roles/geodns/templates/geodns-config.service.j2
 create mode 100644 roles/geodns/templates/geodns-config.timer.j2

diff --git a/files/srv.mdx.incubator.geant.org.yaml b/files/srv.mdx.incubator.geant.org.yaml
index 4b666fe..5748321 100644
--- a/files/srv.mdx.incubator.geant.org.yaml
+++ b/files/srv.mdx.incubator.geant.org.yaml
@@ -5,10 +5,11 @@ max_hosts: 1
 data:
   "":
     "a":
+      - [ "193.224.22.77" ]
       - [ "193.224.22.78" ]
-      - [ "145.100.180.185" ]
+      - [ "145.100.180.185", 10 ]
       - [ "62.217.72.109" ]
-      - [ "145.100.181.134" ]
+      - [ "145.100.181.134", 20 ]
   "srv1":
     "a":
       - [ "193.224.22.78" ]
diff --git a/roles/geodns/files/geoconfig.py b/roles/geodns/files/geoconfig.py
new file mode 100755
index 0000000..8c4c600
--- /dev/null
+++ b/roles/geodns/files/geoconfig.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import copy
+import yaml
+import json
+
+if len(sys.argv) < 2:
+    print(f"Usage:\n  {os.path.basename(sys.argv[0])} <file>")
+    sys.exit(1)
+
+
+def is_valid(address):
+    return not os.system(f"timeout 0.1 nc -z {address} 80")
+
+
+with open(f"{sys.argv[1]}.yaml", "r") as yaml_doc:
+    config = yaml.load(yaml_doc, Loader=yaml.FullLoader)
+
+    new_config = copy.deepcopy(config)
+    new_config['data'] = {}
+
+    for host, values in config.get('data', {}).items():
+        for record, addresslist in values.items():
+            if record != "a":
+                new_config['data'][host] = {record: addresslist}
+            else:
+                for address_config in addresslist:
+                    if is_valid(address_config[0]):
+                        try:
+                            new_config['data'][host][record].append(address_config)
+                        except KeyError:
+                            new_config['data'][host] = {record: [address_config]}
+
+with open(f"{sys.argv[1]}.json", "w") as geodns_config:
+    json.dump(new_config, geodns_config, indent=2)
diff --git a/roles/geodns/files/srv.mdx.incubator.geant.org.yaml b/roles/geodns/files/srv.mdx.incubator.geant.org.yaml
new file mode 100644
index 0000000..5748321
--- /dev/null
+++ b/roles/geodns/files/srv.mdx.incubator.geant.org.yaml
@@ -0,0 +1,78 @@
+---
+
+ttl: 60
+max_hosts: 1
+data:
+  "":
+    "a":
+      - [ "193.224.22.77" ]
+      - [ "193.224.22.78" ]
+      - [ "145.100.180.185", 10 ]
+      - [ "62.217.72.109" ]
+      - [ "145.100.181.134", 20 ]
+  "srv1":
+    "a":
+      - [ "193.224.22.78" ]
+  "srv1-signer":
+    "a":
+      - [ "193.224.22.78" ]
+  "srv1-proxy":
+    "a":
+      - [ "193.224.22.78" ]
+  "srv2":
+    "a":
+      - [ "145.100.180.185" ]
+  "srv2-signer":
+    "a":
+      - [ "145.100.180.185" ]
+  "srv2-proxy":
+    "a":
+      - [ "145.100.180.185" ]
+  "srv3":
+    "a":
+      - [ "62.217.72.109" ]
+  "srv3-signer":
+    "a":
+      - [ "62.217.72.109" ]
+  "srv3-proxy":
+    "a":
+      - [ "62.217.72.109" ]
+  "srv4":
+    "a":
+      - [ "145.100.181.134" ]
+  "srv4-signer":
+    "a":
+      - [ "145.100.181.134" ]
+  "srv4-proxy":
+    "a":
+      - [ "145.100.181.134" ]
+  "signer":
+    "a":
+      - [ "193.224.22.78" ]
+      - [ "62.217.72.109" ]
+  "signer.nl":
+    "a":
+      - [ "145.100.180.185" ]
+  "proxy":
+    "a":
+      - [ "193.224.22.78" ]
+      - [ "145.100.180.185" ]
+  "proxy.nl":
+    "a":
+      - [ "62.217.72.109" ]
+  "proxy-edugain":
+    "a":
+      - [ "193.224.22.78" ]
+      - [ "145.100.180.185" ]
+      - [ "62.217.72.109" ]
+  "proxy-test":
+    "a":
+      - [ "193.224.22.78" ]
+      - [ "145.100.180.185" ]
+      - [ "62.217.72.109" ]
+  "proxy-edugain.nl":
+    "a":
+      - [ "62.217.72.109" ]
+  "proxy-test.nl":
+    "a":
+      - [ "62.217.72.109" ]
diff --git a/roles/geodns/handlers/main.yml b/roles/geodns/handlers/main.yml
index a5ec62e..0b00ab4 100644
--- a/roles/geodns/handlers/main.yml
+++ b/roles/geodns/handlers/main.yml
@@ -1,7 +1,11 @@
 ---
 - name: enable geodns job
   systemd:
-    name: "geodns.service"
+    name: "{{ item }}"
     enabled: true
-    state: "restarted"
+    state: "started"
     daemon_reload: true
+  with_items:
+    - geodns.service
+    - geodns-config.service
+    - geodns-config.timer
diff --git a/roles/geodns/tasks/main.yml b/roles/geodns/tasks/main.yml
index 9833c63..ce0ec6e 100644
--- a/roles/geodns/tasks/main.yml
+++ b/roles/geodns/tasks/main.yml
@@ -43,12 +43,20 @@
 
 - name: Copy geoDNS config
   ansible.builtin.copy:
-    content: "{{ lookup('file', tld + '.yaml') | from_yaml | to_nice_json }}"
-    dest: "{{ geo_dns_config }}/{{ tld }}.json"
+    src: "{{ tld }}.yaml"
+    dest: "{{ geo_dns_config }}/{{ tld }}.yaml"
     mode: '0644'
   notify:
     - "enable geodns job"
 
+- name: Copy geoDNS config parser
+  ansible.builtin.copy:
+    src: "geoconfig.py"
+    dest: "{{ geo_dns_config }}/geoconfig.py"
+    mode: '0755'
+  notify:
+    - "enable geodns job"
+
 - name: Copy GeoLite2DB's
   ansible.builtin.copy:
     src: "{{ item }}"
@@ -66,9 +74,18 @@
   notify:
     - "enable geodns job"
 
+- name: Run GeoDns config job once
+  ansible.builtin.command:
+    cmd: "/opt/geodns/config/geoconfig.py {{ tld }}"
+    chdir: "{{ geo_dns_config }}"
+
 - name: Copy geoDNS service files
   ansible.builtin.template:
-    src: "geodns.service.j2"
-    dest: "/etc/systemd/system/geodns.service"
+    src: "{{ item }}.j2"
+    dest: "/etc/systemd/system/{{ item }}"
+  with_items:
+    - geodns.service
+    - geodns-config.service
+    - geodns-config.timer
   notify:
     - "enable geodns job"
diff --git a/roles/geodns/templates/geodns-config.service.j2 b/roles/geodns/templates/geodns-config.service.j2
new file mode 100644
index 0000000..dd98870
--- /dev/null
+++ b/roles/geodns/templates/geodns-config.service.j2
@@ -0,0 +1,11 @@
+[Unit]
+Description=GeoDNS config
+
+[Service]
+Type=oneshot
+WorkingDirectory={{ geo_dns_config }}
+ExecStart={{ geo_dns_config }}/geoconfig.py {{ tld }}
+ExecStartPost=/bin/systemctl restart geodns
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/geodns/templates/geodns-config.timer.j2 b/roles/geodns/templates/geodns-config.timer.j2
new file mode 100644
index 0000000..9016e1d
--- /dev/null
+++ b/roles/geodns/templates/geodns-config.timer.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description=Run GeoDNS config
+
+[Timer]
+OnCalendar=*-*-* *:0/5:00
+Unit=geodns-config.service
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/geodns/templates/geodns.service.j2 b/roles/geodns/templates/geodns.service.j2
index c900f56..cc60802 100644
--- a/roles/geodns/templates/geodns.service.j2
+++ b/roles/geodns/templates/geodns.service.j2
@@ -5,8 +5,8 @@ After=syslog.target network.target
 [Service]
 Type=simple
 WorkingDirectory={{ geodns_dir }}
-ExecStart=/opt/geodns/geodns -config={{ geo_dns_config }} -log -interface {{ ansible_facts.default_ipv4.address }} -port 53
-ExecReload=/bin/kill -HUP $MAINPID
+ExecStart={{ geodns_dir }}/geodns -config={{ geo_dns_config }} -log -interface {{ ansible_facts.default_ipv4.address }} -port 53
+# ExecReload=/bin/kill -HUP $MAINPID
 Restart=on-failure
 RestartSec=10
 SyslogIdentifier=geodns
-- 
GitLab