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

90 lines
2.7 KiB
Python
Executable File

#!/usr/bin/env python3
import asyncio
import ecs_logging
import logging
import os
import sys
from kubernetes_asyncio.client.api_client import ApiClient
from kubernetes_asyncio import client, config, watch
from time import time
# 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)
ZONEFILE_TEMPLATE = """
@ IN SOA ns1.%(zone)s. hostmaster.%(zone)s. (2022060820 300 300 300 300)
NS ns1.%(zone)s.
ns1 A %(ip)s
"""
_, ip = sys.argv
PATH_CONFIG = "/var/bind/bind.conf"
PATH_ZONEFILE = "/var/bind/db.%s"
active_zones = set()
def update_config():
with open(PATH_CONFIG + ".part", "w") as fh:
for zone in active_zones:
path = PATH_ZONEFILE % zone
fh.write("zone \"%s\" { type master; file \"%s\"; };\n" % (zone, path))
os.rename(PATH_CONFIG + ".part", PATH_CONFIG)
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)
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(ZONEFILE_TEMPLATE % {
"ip": ip,
"zone": zone
})
os.rename(path + ".part", path)
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()