9
0
Fork 0
bind-sidecar/bind-sidecar.py

98 lines
3.3 KiB
Python
Raw Normal View History

2022-09-21 09:35:12 +00:00
#!/usr/bin/env python3
2022-09-24 05:43:25 +00:00
import argparse
2022-09-21 09:35:12 +00:00
import asyncio
import ecs_logging
import logging
import os
2022-09-24 05:43:25 +00:00
import signal
import socket
2022-09-21 09:35:12 +00:00
from kubernetes_asyncio.client.api_client import ApiClient
from kubernetes_asyncio import client, config, watch
from time import time
2022-09-24 05:43:25 +00:00
parser = argparse.ArgumentParser()
parser.add_argument("--replica", action="store_true")
args = parser.parse_args()
2022-09-21 09:35:12 +00:00
# Get the Logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Add an ECS formatter to the Handler
handler = logging.StreamHandler()
handler.setFormatter(ecs_logging.StdlibFormatter())
logger.addHandler(handler)
PATH_CONFIG = "/var/bind/bind.conf"
PATH_ZONEFILE = "/var/bind/db.%s"
active_zones = set()
def update_config():
2022-09-24 05:43:25 +00:00
master = socket.gethostbyname("bind-primary")
2022-09-21 09:35:12 +00:00
with open(PATH_CONFIG + ".part", "w") as fh:
for zone in active_zones:
path = PATH_ZONEFILE % zone
2022-09-24 05:43:25 +00:00
if args.replica:
fh.write("zone \"%s\" { type slave; masters { %s key zone-transfer; }; };\n" % (zone, master))
else:
fh.write("zone \"%s\" { type master; file \"%s\"; };\n" % (zone, path))
2022-09-21 09:35:12 +00:00
os.rename(PATH_CONFIG + ".part", PATH_CONFIG)
2022-09-24 05:43:25 +00:00
logger.debug("File %s updated", PATH_CONFIG)
try:
with open("/var/bind/named.pid") as fh:
os.kill(int(fh.read()), signal.SIGHUP)
except FileNotFoundError:
logger.warn("File /var/bind/named.pid not found, assuming Bind not running yet")
2022-09-21 09:35:12 +00:00
async def update_loop(v1, apps_api, api_instance, revision):
flt = "codemowers.io", "v1alpha1", "bindzones"
method = api_instance.list_cluster_custom_object
w = watch.Watch()
latest_version = None
logger.info("Subscribing to updates")
async for event in w.stream(method, *flt, resource_version=latest_version):
latest_version = event["object"]["metadata"]["resourceVersion"]
if event["type"] == "ADDED":
zone = event["object"]["metadata"]["name"]
active_zones.add(zone)
2022-09-24 05:43:25 +00:00
if not args.replica:
path = PATH_ZONEFILE % zone
logger.info("Adding zone: %s", zone)
if not os.path.exists(path):
with open(path + ".part", "w") as fh:
fh.write("@ IN SOA ns1.%(zone)s. hostmaster.%(zone)s. (1 300 300 300 300)\n" % locals())
fh.write(" NS ns1.%(zone)s.\n" % locals())
fh.write("ns1 A 127.0.0.1\n")
os.rename(path + ".part", path)
2022-09-21 09:35:12 +00:00
update_config()
elif event["type"] == "DELETED":
logger.info("Removing zone: %s", zone)
active_zones.remove(zone)
os.unlink(PATH_ZONEFILE % event["object"]["metadata"]["name"])
async def main():
if os.getenv("KUBECONFIG"):
await config.load_kube_config()
else:
config.load_incluster_config()
async with ApiClient() as api:
v1 = client.CoreV1Api(api)
apps_api = client.AppsV1Api()
api_instance = client.CustomObjectsApi(api)
revision = str(time())
while True:
try:
await update_loop(v1, apps_api, api_instance, revision)
except asyncio.exceptions.TimeoutError:
pass
if __name__ == "__main__":
loop = asyncio.new_event_loop()
loop.run_until_complete(main())
loop.close()