diff --git a/README.md b/README.md index dcb52026..e230a67e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # What? -This is a docker container intended to run inside a kubernetes cluster to collect config maps with a specified label and store the included files in an local folder. The main target is to be run as a sidecar container to supply an application with information from the cluster. The contained python script is working with the Kubernetes API 1.10 +This is a docker container intended to run inside a kubernetes cluster to collect config maps with a specified label and store the included files in an local folder. It can also send a html request to a specified URL after a configmap change. The main target is to be run as a sidecar container to supply an application with information from the cluster. The contained python script is working with the Kubernetes API 1.10 # Why? @@ -13,6 +13,7 @@ Currently (April 2018) there is no simple way to hand files in configmaps to a s # How? Run the container created by this repo together you application in an single pod with a shared volume. Specify which label should be monitored and where the files should be stored. +By adding additional env variables the container can send a html request to specified URL. # Features @@ -35,3 +36,20 @@ Example for a simple deployment can be found in `example.yaml`. Depending on the - description: Folder where the files should be placed - required: true - type: string + +- `REQ_URL` + - description: URL to which send a request after a configmap got reloaded + - required: false + - type: URI + +- `REQ_METHOD` + - description: Request method GET(default) or POST + - required: false + - type: string + +- `REQ_PAYLOAD` + - description: If you use POST you can also provide json payload + - required: false + - type: json + + diff --git a/sidecar/sidecar.py b/sidecar/sidecar.py index 76dab18c..2f17158e 100644 --- a/sidecar/sidecar.py +++ b/sidecar/sidecar.py @@ -1,6 +1,9 @@ from kubernetes import client, config, watch import os import sys +import requests +from requests.packages.urllib3.util.retry import Retry +from requests.adapters import HTTPAdapter def writeTextToFile(folder, filename, data): @@ -9,6 +12,25 @@ def writeTextToFile(folder, filename, data): f.close() +def request(url, method, payload): + r = requests.Session() + retries = Retry(total = 5, + connect = 5, + backoff_factor = 0.2, + status_forcelist = [ 500, 502, 503, 504 ]) + r.mount('http://', HTTPAdapter(max_retries=retries)) + r.mount('https://', HTTPAdapter(max_retries=retries)) + if url is None: + print("No url provided. Doing nothing.") + # If method is not provided use GET as default + elif method == "GET" or method is None: + res = r.get("%s" % url, timeout=10) + print ("%s request sent to %s. Response: %d %s" % (method, url, res.status_code, res.reason)) + elif method == "POST": + res = r.post("%s" % url, json=payload, timeout=10) + print ("%s request sent to %s. Response: %d %s" % (method, url, res.status_code, res.reason)) + + def removeFile(folder, filename): completeFile = folder +"/"+filename if os.path.isfile(completeFile): @@ -17,7 +39,7 @@ def removeFile(folder, filename): print("Error: %s file not found" % completeFile) -def watchForChanges(label, targetFolder): +def watchForChanges(label, targetFolder, url, method, payload): v1 = client.CoreV1Api() w = watch.Watch() for event in w.stream(v1.list_config_map_for_all_namespaces): @@ -36,8 +58,12 @@ def watchForChanges(label, targetFolder): print("File in configmap %s %s" % (filename, eventType)) if (eventType == "ADDED") or (eventType == "MODIFIED"): writeTextToFile(targetFolder, filename, dataMap[filename]) + if url is not None: + request(url, method, payload) else: removeFile(targetFolder, filename) + if url is not None: + request(url, method, payload) def main(): @@ -50,9 +76,14 @@ def main(): if targetFolder is None: print("Should have added FOLDER as environment variable! Exit") return -1 + + method = os.getenv('REQ_METHOD') + url = os.getenv('REQ_URL') + payload = os.getenv('REQ_PAYLOAD') + config.load_incluster_config() print("Config for cluster api loaded...") - watchForChanges(label, targetFolder) + watchForChanges(label, targetFolder, url, method, payload) if __name__ == '__main__':