def watch_loop(restarter): v1 = kube_v1() if v1: w = watch.Watch() if "AMBASSADOR_SINGLE_NAMESPACE" in os.environ: watched = w.stream(v1.list_namespaced_service, namespace=restarter.namespace) else: watched = w.stream(v1.list_service_for_all_namespaces) for evt in watched: logger.debug("Event: %s %s/%s" % (evt["type"], evt["object"].metadata.namespace, evt["object"].metadata.name)) sys.stdout.flush() if evt["type"] == "DELETED": restarter.delete(evt["object"]) else: restarter.update_from_service(evt["object"]) logger.info("watch loop exited?") else: logger.info("No K8s, idling")
def watch_loop(restarter): v1 = kube_v1() if v1: while True: try: w = watch.Watch() if "AMBASSADOR_SINGLE_NAMESPACE" in os.environ: watched = w.stream(v1.list_namespaced_service, namespace=restarter.namespace) else: watched = w.stream(v1.list_service_for_all_namespaces) for evt in watched: logger.debug( "Event: %s %s/%s" % (evt["type"], evt["object"].metadata.namespace, evt["object"].metadata.name)) sys.stdout.flush() if evt["type"] == "DELETED": restarter.delete(evt["object"]) else: restarter.update_from_service(evt["object"]) logger.info("watch loop exited?") except ProtocolError: logger.debug( "watch connection has been broken. retry automatically.") continue else: logger.info("No K8s, idling")
def run(self, id_only=False, sync_only=False): self.logger.debug("starting run") while True: need_wait = True # Catch exceptions... just in case. try: # Try for a Kube connection. v1 = kube_v1() if v1: self.logger.debug("connected to Kubernetes!") # Manage cluster_id if needed... if not self.cluster_id: # Nope. Try to figure it out. self.get_cluster_id(v1) # ...then do sync if needed. if self.need_sync and not id_only: self.sync(v1) # Whether or not we got a Kube connection, generate the initial Envoy config if needed # (including setting the restarter's cluster ID). if self.need_sync: logger.debug("Generating initial Envoy config") self.restarter.set_cluster_id(self.cluster_id) if not id_only: self.restarter.restart() self.need_sync = False # If we're just doing the sync, dump the cluster_id to stdout and then bail. if sync_only or id_only: print(self.cluster_id) need_wait = False break # We're not just doing a resync. Start the restarter loop if we need to. if not self.restarter_started: self.restarter.start() self.restarter_started = True # Finally, start watching, if we need to. if v1: self.watch(v1) except KeyboardInterrupt: # If the user hit ^C, this is an interactive session and we should bail. self.logger.warning("Exiting on ^C") need_wait = False raise except (ProtocolError, ApiException) as e: # If any Kubernetes thing failed, cycle (unless told otherwise) self.logger.warning("Kubernetes access failure! %s" % e) if 'AMBASSADOR_NO_KUBEWATCH_RETRY' in os.environ: logger.info( "not restarting! AMBASSADOR_NO_KUBEWATCH_RETRY is set") raise except Exception: # WTFO. self.logger.warning("kubewatch failed!") raise finally: # If we're cycling, wait 10 seconds, unless that was turned off. if need_wait: logger.debug("10-second watch loop delay") time.sleep(10)
def sync(restarter): v1 = kube_v1() if v1: # We have a Kube API! Do we have an ambassador-config ConfigMap? cm_names = [ x.metadata.name for x in v1.list_namespaced_config_map(restarter.namespace).items ] if 'ambassador-config' in cm_names: config_data = v1.read_namespaced_config_map( "ambassador-config", restarter.namespace) if config_data: for key, config_yaml in config_data.data.items(): logger.info("ambassador-config: found %s" % key) restarter.update( key, restarter.read_yaml(config_yaml, "ambassador-config %s" % key)) # If we don't already see a TLS server key in its usual spot... if not check_cert_file(TLSPaths.mount_tls_crt.value): # ...then try pulling keys directly from the configmaps. (server_cert, server_key, server_data) = read_cert_secret(v1, "ambassador-certs", restarter.namespace) (client_cert, _, client_data) = read_cert_secret(v1, "ambassador-cacert", restarter.namespace) if server_cert and server_key: tls_mod = { "apiVersion": "ambassador/v0", "kind": "Module", "name": "tls-from-ambassador-certs", "ambassador_id": ambassador_id, "config": { "server": { "enabled": True, "cert_chain_file": TLSPaths.tls_crt.value, "private_key_file": TLSPaths.tls_key.value } } } save_cert(server_cert, server_key, TLSPaths.cert_dir.value) if client_cert: tls_mod['config']['client'] = { "enabled": True, "cacert_chain_file": TLSPaths.client_tls_crt.value } if client_data.get('cert_required', None): tls_mod['config']['client']["cert_required"] = True save_cert(client_cert, None, TLSPaths.client_cert_dir.value) tls_yaml = yaml.safe_dump(tls_mod) logger.debug("generated TLS config %s" % tls_yaml) restarter.update("tls.yaml", tls_yaml) # Next, check for annotations and such. svc_list = None if "AMBASSADOR_SINGLE_NAMESPACE" in os.environ: svc_list = v1.list_namespaced_service(restarter.namespace) else: svc_list = v1.list_service_for_all_namespaces() if svc_list: logger.debug("sync: found %d service%s" % (len(svc_list.items), ("" if (len(svc_list.items) == 1) else "s"))) for svc in svc_list.items: restarter.update_from_service(svc) else: logger.debug("sync: no services found") # Always generate an initial envoy config. logger.debug("Generating initial Envoy config") restarter.restart()
def sync(restarter): v1 = kube_v1() if v1: # We have a Kube API! Do we have an ambassador-config ConfigMap? cm_names = [ x.metadata.name for x in v1.list_namespaced_config_map(restarter.namespace).items ] if 'ambassador-config' in cm_names: config_data = v1.read_namespaced_config_map("ambassador-config", restarter.namespace) if config_data: for key, config_yaml in config_data.data.items(): logger.info("ambassador-config: found %s" % key) restarter.update(key, restarter.read_yaml(config_yaml, "ambassador-config %s" % key)) # If we don't already see a TLS server key in its usual spot... if not check_cert_file(TLSPaths.mount_tls_crt.value): # ...then try pulling keys directly from the configmaps. (server_cert, server_key, server_data) = read_cert_secret(v1, "ambassador-certs", restarter.namespace) (client_cert, _, client_data) = read_cert_secret(v1, "ambassador-cacert", restarter.namespace) if server_cert and server_key: tls_mod = { "apiVersion": "ambassador/v0", "kind": "Module", "name": "tls-from-ambassador-certs", "ambassador_id": ambassador_id, "config": { "server": { "enabled": True, "cert_chain_file": TLSPaths.tls_crt.value, "private_key_file": TLSPaths.tls_key.value } } } save_cert(server_cert, server_key, TLSPaths.cert_dir.value) if client_cert: tls_mod['config']['client'] = { "enabled": True, "cacert_chain_file": TLSPaths.client_tls_crt.value } if client_data.get('cert_required', None): tls_mod['config']['client']["cert_required"] = True save_cert(client_cert, None, TLSPaths.client_cert_dir.value) tls_yaml = yaml.safe_dump(tls_mod) logger.debug("generated TLS config %s" % tls_yaml) restarter.update("tls.yaml", tls_yaml) # Next, check for annotations and such. svc_list = None if "AMBASSADOR_SINGLE_NAMESPACE" in os.environ: svc_list = v1.list_namespaced_service(restarter.namespace) else: svc_list = v1.list_service_for_all_namespaces() if svc_list: logger.debug("sync: found %d service%s" % (len(svc_list.items), ("" if (len(svc_list.items) == 1) else "s"))) for svc in svc_list.items: restarter.update_from_service(svc) else: logger.debug("sync: no services found") # Always generate an initial envoy config. logger.debug("Generating initial Envoy config") restarter.restart()