From 061916c1d5576526b2c45509986e22a325087bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Wed, 21 Sep 2022 12:35:12 +0300 Subject: [PATCH] Initial commit --- .drone.yml | 2 ++ Dockerfile | 3 ++ README.md | 3 ++ bind-sidecar.py | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 .drone.yml create mode 100644 Dockerfile create mode 100644 README.md create mode 100755 bind-sidecar.py diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..e7b5dfa --- /dev/null +++ b/.drone.yml @@ -0,0 +1,2 @@ +kind: template +load: docker.yaml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..973f069 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM harbor.k-space.ee/k-space/microservice-base +ADD bind-sidecar.py / +ENTRYPOINT /bind-sidecar.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..a93426c --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Meta operator + +Meta operator allows creating operators without building any binaries diff --git a/bind-sidecar.py b/bind-sidecar.py new file mode 100755 index 0000000..f23204b --- /dev/null +++ b/bind-sidecar.py @@ -0,0 +1,89 @@ +#!/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()