def showid(): """ Show Ambassador's installation ID """ scout = Scout() print("Ambassador Scout installation ID %s" % scout.install_id) result = scout.report(action="showid", mode="cli") show_notices(result, printer=stdout_printer)
def handle_exception(what, e, **kwargs): tb = "\n".join(traceback.format_exception(*sys.exc_info())) scout = Scout() result = scout.report(action=what, mode="cli", exception=str(e), traceback=tb, **kwargs) logger.debug("Scout %s, result: %s" % ("enabled" if scout._scout else "disabled", result)) logger.error("%s: %s\n%s" % (what, e, tb)) show_notices(result)
def version(): """ Show Ambassador's version """ print("Ambassador %s" % __version__) scout = Scout() print("Ambassador Scout version %s" % scout.version) print("Ambassador Scout semver %s" % scout.get_semver(scout.version)) result = scout.report(action="version", mode="cli") show_notices(result, printer=stdout_printer)
def generate_config(self, changes, output): if os.path.exists(output): shutil.rmtree(output) os.makedirs(output) for filename, config in self.configs.items(): path = os.path.join(output, filename) with open(path, "w") as fd: fd.write(config) logger.debug("Wrote %s to %s" % (filename, path)) plural = "" if (changes == 1) else "s" logger.info("generating config with gencount %d (%d change%s)" % (self.restart_count, changes, plural)) aconf = Config() aconf.load_from_directory(output) ir = IR(aconf, secret_reader=KubeSecretReader(secret_root)) envoy_config = V2Config(ir) bootstrap_config, ads_config = envoy_config.split_config() scout = Scout(install_id=self.cluster_id) scout_args = {"gencount": self.restart_count} if not os.environ.get("AMBASSADOR_DISABLE_FEATURES", None): scout_args["features"] = ir.features() result = scout.report(mode="kubewatch", action="reconfigure", **scout_args) notices = result.pop("notices", []) logger.debug("scout result %s" % json.dumps(result, sort_keys=True, indent=4)) for notice in notices: logger.log(logging.getLevelName(notice.get('level', 'WARNING')), notice.get('message', '?????')) return bootstrap_config, ads_config
def config(config_dir_path: Parameter.REQUIRED, output_json_path: Parameter.REQUIRED, *, debug=False, debug_scout=False, check=False, k8s=False, ir=None, aconf=None, exit_on_error=False): """ Generate an Envoy configuration :param config_dir_path: Configuration directory to scan for Ambassador YAML files :param output_json_path: Path to output envoy.json :param debug: If set, generate debugging output :param debug_scout: If set, generate debugging output when talking to Scout :param check: If set, generate configuration only if it doesn't already exist :param k8s: If set, assume configuration files are annotated K8s manifests :param exit_on_error: If set, will exit with status 1 on any configuration error :param ir: Pathname to which to dump the IR (not dumped if not present) :param aconf: Pathname to which to dump the aconf (not dumped if not present) """ if debug: logger.setLevel(logging.DEBUG) if debug_scout: logging.getLogger('ambassador.scout').setLevel(logging.DEBUG) try: logger.debug("CHECK MODE %s" % check) logger.debug("CONFIG DIR %s" % config_dir_path) logger.debug("OUTPUT PATH %s" % output_json_path) dump_aconf: Optional[str] = aconf dump_ir: Optional[str] = ir # Bypass the existence check... output_exists = False if check: # ...oh no wait, they explicitly asked for the existence check! # Assume that the file exists (ie, we'll do nothing) unless we # determine otherwise. output_exists = True try: parse_json(open(output_json_path, "r").read()) except FileNotFoundError: logger.debug("output file does not exist") output_exists = False except OSError: logger.warning("output file is not sane?") output_exists = False except json.decoder.JSONDecodeError: logger.warning("output file is not valid JSON") output_exists = False logger.info("Output file %s" % ("exists" if output_exists else "does not exist")) rc = RichStatus.fromError("impossible error") if not output_exists: # Either we didn't need to check, or the check didn't turn up # a valid config. Regenerate. logger.info("Generating new Envoy configuration...") aconf = Config() fetcher = ResourceFetcher(logger, aconf) fetcher.load_from_filesystem(config_dir_path, k8s=k8s) aconf.load_all(fetcher.sorted()) if dump_aconf: with open(dump_aconf, "w") as output: output.write(aconf.as_json()) output.write("\n") # If exit_on_error is set, log _errors and exit with status 1 if exit_on_error and aconf.errors: raise Exception("errors in: {0}".format(', '.join( aconf.errors.keys()))) secret_handler = NullSecretHandler(logger, config_dir_path, config_dir_path, "0") ir = IR(aconf, file_checker=file_checker, secret_handler=secret_handler) if dump_ir: with open(dump_ir, "w") as output: output.write(ir.as_json()) output.write("\n") # clize considers kwargs with False for default value as flags, # resulting in the logic below. # https://clize.readthedocs.io/en/stable/basics.html#accepting-flags logger.info("Writing envoy V2 configuration") v2config = V2Config(ir) rc = RichStatus.OK(msg="huh_v2") if rc: with open(output_json_path, "w") as output: output.write(v2config.as_json()) output.write("\n") else: logger.error("Could not generate new Envoy configuration: %s" % rc.error) scout = Scout() result = scout.report(action="config", mode="cli") show_notices(result) except Exception as e: handle_exception("EXCEPTION from config", e, config_dir_path=config_dir_path, output_json_path=output_json_path) # This is fatal. sys.exit(1)