Beispiel #1
0
def dump(config_dir_path: Parameter.REQUIRED,
         *,
         secret_dir_path=None,
         watt=False,
         debug=False,
         debug_scout=False,
         k8s=False,
         recurse=False,
         stats=False,
         nopretty=False,
         everything=False,
         aconf=False,
         ir=False,
         v2=False,
         v3=False,
         diag=False,
         features=False,
         profile=False):
    """
    Dump various forms of an Ambassador configuration for debugging

    Use --aconf, --ir, and --envoy to control what gets dumped. If none are requested, the IR
    will be dumped.

    :param config_dir_path: Configuration directory to scan for Ambassador YAML files
    :param secret_dir_path: Directory into which to save secrets
    :param watt: If set, input must be a WATT snapshot
    :param debug: If set, generate debugging output
    :param debug_scout: If set, generate debugging output
    :param k8s: If set, assume configuration files are annotated K8s manifests
    :param recurse: If set, recurse into directories below config_dir_path
    :param stats: If set, dump statistics to stderr
    :param nopretty: If set, do not pretty print the dumped JSON
    :param aconf: If set, dump the Ambassador config
    :param ir: If set, dump the IR
    :param v2: If set, dump the Envoy V2 config
    :param v3: If set, dump the Envoy V3 config
    :param diag: If set, dump the Diagnostics overview
    :param everything: If set, dump everything
    :param features: If set, dump the feature set
    :param profile: If set, profile with the cProfile module
    """

    if not secret_dir_path:
        secret_dir_path = "/tmp/cli-secrets"

        if not os.path.isdir(secret_dir_path):
            secret_dir_path = os.path.dirname(secret_dir_path)

    if debug:
        logger.setLevel(logging.DEBUG)

    if debug_scout:
        logging.getLogger('ambassador.scout').setLevel(logging.DEBUG)

    if everything:
        aconf = True
        ir = True
        v2 = True
        v3 = True
        diag = True
        features = True
    elif not (aconf or ir or v2 or v3 or diag or features):
        aconf = True
        ir = True
        v2 = True
        v3 = False
        diag = False
        features = False

    dump_aconf = aconf
    dump_ir = ir
    dump_v2 = v2
    dump_v3 = v3
    dump_diag = diag
    dump_features = features

    od = {}
    diagconfig: Optional[EnvoyConfig] = None

    _profile: Optional[cProfile.Profile] = None
    _rc = 0

    if profile:
        _profile = cProfile.Profile()
        _profile.enable()

    try:
        total_timer = Timer("total")
        total_timer.start()

        fetch_timer = Timer("fetch resources")
        with fetch_timer:
            aconf = Config()

            fetcher = ResourceFetcher(logger, aconf)

            if watt:
                fetcher.parse_watt(open(config_dir_path, "r").read())
            else:
                fetcher.load_from_filesystem(config_dir_path,
                                             k8s=k8s,
                                             recurse=True)

        load_timer = Timer("load fetched resources")
        with load_timer:
            aconf.load_all(fetcher.sorted())

        # aconf.post_error("Error from string, boo yah")
        # aconf.post_error(RichStatus.fromError("Error from RichStatus"))

        irgen_timer = Timer("ir generation")
        with irgen_timer:
            secret_handler = NullSecretHandler(logger, config_dir_path,
                                               secret_dir_path, "0")

            ir = IR(aconf,
                    file_checker=file_checker,
                    secret_handler=secret_handler)

        aconf_timer = Timer("aconf")
        with aconf_timer:
            if dump_aconf:
                od['aconf'] = aconf.as_dict()

        ir_timer = Timer("ir")
        with ir_timer:
            if dump_ir:
                od['ir'] = ir.as_dict()

        v2_timer = Timer("v2")
        with v2_timer:
            if dump_v2:
                v2config = V2Config(ir)
                diagconfig = v2config
                od['v2'] = v2config.as_dict()
        v3_timer = Timer("v3")
        with v3_timer:
            if dump_v3:
                v3config = V3Config(ir)
                diagconfig = v3config
                od['v3'] = v3config.as_dict()
        diag_timer = Timer("diag")
        with diag_timer:
            if dump_diag:
                if not diagconfig:
                    diagconfig = V2Config(ir)
                    diagconfigv3 = V3Config(ir)
                econf = typecast(EnvoyConfig, diagconfig)
                econfv3 = typecast(EnvoyConfig, diagconfigv3)
                diag = Diagnostics(ir, econf)
                diagv3 = Diagnostics(ir, econfv3)
                od['diag'] = diag.as_dict()
                od['elements'] = econf.elements
                od['diagv3'] = diagv3.as_dict()
                od['elementsv3'] = econfv3.elements

        features_timer = Timer("features")
        with features_timer:
            if dump_features:
                od['features'] = ir.features()

        # scout = Scout()
        # scout_args = {}
        #
        # if ir and not os.environ.get("AMBASSADOR_DISABLE_FEATURES", None):
        #     scout_args["features"] = ir.features()
        #
        # result = scout.report(action="dump", mode="cli", **scout_args)
        # show_notices(result)

        dump_timer = Timer("dump JSON")

        with dump_timer:
            js = dump_json(od, pretty=not nopretty)
            jslen = len(js)

        write_timer = Timer("write JSON")
        with write_timer:
            sys.stdout.write(js)
            sys.stdout.write("\n")

        total_timer.stop()

        route_count = 0
        vhost_count = 0
        filter_chain_count = 0
        filter_count = 0
        apiversion = 'v2' if v2 else 'v3'
        if apiversion in od:
            for listener in od[apiversion]['static_resources']['listeners']:
                for fc in listener['filter_chains']:
                    filter_chain_count += 1
                    for f in fc['filters']:
                        filter_count += 1
                        for vh in f['typed_config']['route_config'][
                                'virtual_hosts']:
                            vhost_count += 1
                            route_count += len(vh['routes'])

        if stats:
            sys.stderr.write("STATS:\n")
            sys.stderr.write("  config bytes:  %d\n" % jslen)
            sys.stderr.write("  vhosts:        %d\n" % vhost_count)
            sys.stderr.write("  filter chains: %d\n" % filter_chain_count)
            sys.stderr.write("  filters:       %d\n" % filter_count)
            sys.stderr.write("  routes:        %d\n" % route_count)
            sys.stderr.write("  routes/vhosts: %.3f\n" %
                             float(float(route_count) / float(vhost_count)))
            sys.stderr.write("TIMERS:\n")
            sys.stderr.write("  fetch resources:  %.3fs\n" %
                             fetch_timer.average)
            sys.stderr.write("  load resources:   %.3fs\n" %
                             load_timer.average)
            sys.stderr.write("  ir generation:    %.3fs\n" %
                             irgen_timer.average)
            sys.stderr.write("  aconf:            %.3fs\n" %
                             aconf_timer.average)
            sys.stderr.write("  envoy v2:         %.3fs\n" % v2_timer.average)
            sys.stderr.write("  diag:             %.3fs\n" %
                             diag_timer.average)
            sys.stderr.write("  features:         %.3fs\n" %
                             features_timer.average)
            sys.stderr.write("  dump json:        %.3fs\n" %
                             dump_timer.average)
            sys.stderr.write("  write json:       %.3fs\n" %
                             write_timer.average)
            sys.stderr.write("  ----------------------\n")
            sys.stderr.write("  total: %.3fs\n" % total_timer.average)
    except Exception as e:
        handle_exception("EXCEPTION from dump",
                         e,
                         config_dir_path=config_dir_path)
        _rc = 1

    if _profile:
        _profile.disable()
        _profile.dump_stats("ambassador.profile")

    sys.exit(_rc)
Beispiel #2
0
def dump(config_dir_path: Parameter.REQUIRED,
         *,
         secret_dir_path=None,
         watt=False,
         debug=False,
         debug_scout=False,
         k8s=False,
         recurse=False,
         aconf=False,
         ir=False,
         v2=False,
         diag=False,
         features=False):
    """
    Dump various forms of an Ambassador configuration for debugging

    Use --aconf, --ir, and --envoy to control what gets dumped. If none are requested, the IR
    will be dumped.

    :param config_dir_path: Configuration directory to scan for Ambassador YAML files
    :param secret_dir_path: Directory into which to save secrets
    :param watt: If set, input must be a WATT snapshot
    :param debug: If set, generate debugging output
    :param debug_scout: If set, generate debugging output
    :param k8s: If set, assume configuration files are annotated K8s manifests
    :param recurse: If set, recurse into directories below config_dir_path
    :param aconf: If set, dump the Ambassador config
    :param ir: If set, dump the IR
    :param v2: If set, dump the Envoy V2 config
    :param diag: If set, dump the Diagnostics overview
    :param features: If set, dump the feature set
    """

    if not secret_dir_path:
        secret_dir_path = config_dir_path

        if not os.path.isdir(secret_dir_path):
            secret_dir_path = os.path.dirname(secret_dir_path)

    if debug:
        logger.setLevel(logging.DEBUG)

    if debug_scout:
        logging.getLogger('ambassador.scout').setLevel(logging.DEBUG)

    if not (aconf or ir or v2 or diag or features):
        aconf = True
        ir = True
        v2 = True
        diag = False
        features = False

    dump_aconf = aconf
    dump_ir = ir
    dump_v2 = v2
    dump_diag = diag
    dump_features = features

    od = {}
    diagconfig: Optional[EnvoyConfig] = None

    try:
        aconf = Config()
        fetcher = ResourceFetcher(logger, aconf)

        if watt:
            fetcher.parse_watt(open(config_dir_path, "r").read())
        else:
            fetcher.load_from_filesystem(config_dir_path,
                                         k8s=k8s,
                                         recurse=True)

        aconf.load_all(fetcher.sorted())

        # aconf.post_error("Error from string, boo yah")
        # aconf.post_error(RichStatus.fromError("Error from RichStatus"))

        if dump_aconf:
            od['aconf'] = aconf.as_dict()

        secret_handler = NullSecretHandler(logger, config_dir_path,
                                           secret_dir_path, "0")

        ir = IR(aconf,
                file_checker=file_checker,
                secret_handler=secret_handler)

        if dump_ir:
            od['ir'] = ir.as_dict()

        if dump_v2:
            v2config = V2Config(ir)
            diagconfig = v2config
            od['v2'] = v2config.as_dict()

        if dump_diag:
            if not diagconfig:
                diagconfig = V2Config(ir)

            econf = typecast(EnvoyConfig, diagconfig)
            diag = Diagnostics(ir, econf)
            od['diag'] = diag.as_dict()
            od['elements'] = econf.elements

        if dump_features:
            od['features'] = ir.features()

        # scout = Scout()
        # scout_args = {}
        #
        # if ir and not os.environ.get("AMBASSADOR_DISABLE_FEATURES", None):
        #     scout_args["features"] = ir.features()
        #
        # result = scout.report(action="dump", mode="cli", **scout_args)
        # show_notices(result)

        json.dump(od, sys.stdout, sort_keys=True, indent=4)
        sys.stdout.write("\n")
    except Exception as e:
        handle_exception("EXCEPTION from dump",
                         e,
                         config_dir_path=config_dir_path)

        # This is fatal.
        sys.exit(1)