예제 #1
0
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")
예제 #2
0
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")
예제 #3
0
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")
예제 #4
0
    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)
예제 #5
0
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()
예제 #6
0
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()