Ejemplo n.º 1
0
    def load_config_watt(self, rqueue: queue.Queue, url: str):
        snapshot = url.split('/')[-1]
        ss_path = os.path.join(app.snapshot_path, "snapshot-tmp.yaml")

        self.logger.info("copying configuration: watt, %s to %s" % (url, ss_path))

        # Grab the serialization, and save it to disk too.
        serialization = load_url_contents(self.logger, url, stream2=open(ss_path, "w"))

        if not serialization:
            self.logger.debug("no data loaded from snapshot %s" % snapshot)
            # We never used to return here. I'm not sure if that's really correct?
            # self._respond(rqueue, 204, 'ignoring: no data loaded from snapshot %s' % snapshot)
            # return

        # Weirdly, we don't need a special WattSecretHandler: parse_watt knows how to handle
        # the secrets that watt sends.
        scc = SecretHandler(app.logger, url, app.snapshot_path, snapshot)

        aconf = Config()
        fetcher = ResourceFetcher(app.logger, aconf)

        if serialization:
            fetcher.parse_watt(serialization)

        if not fetcher.elements:
            self.logger.debug("no configuration found in snapshot %s" % snapshot)

            # Don't actually bail here. If they send over a valid config that happens
            # to have nothing for us, it's still a legit config.
            # self._respond(rqueue, 204, 'ignoring: no configuration found in snapshot %s' % snapshot)
            # return

        self._load_ir(rqueue, aconf, fetcher, scc, snapshot)
Ejemplo n.º 2
0
                                                 '-crt-',
                                                 '-key-',
                                                 decode_b64=False)

        return self.needed[secret_key]

    # Never cache anything.
    def cache_secret(self, context: 'IRTLSContext', secret_info: SecretInfo):
        return SavedSecret(secret_info.name, secret_info.namespace,
                           '-crt-path-', '-key-path-', {
                               'tls_crt': '-crt-',
                               'tls_key': '-key-'
                           })


scc = SecretHandler(logger, "test-dump", "ss")

yamlpath = sys.argv[1] if len(sys.argv) > 1 else "consul-3.yaml"

aconf = Config()
fetcher = ResourceFetcher(logger, aconf)
fetcher.parse_watt(open(yamlpath, "r").read())

aconf.load_all(fetcher.sorted())

open("test-aconf.json", "w").write(aconf.as_json())

# sys.exit(0)

ir = IR(aconf, secret_handler=scc)
Ejemplo n.º 3
0
def main(k8s_yaml_path: str, debug: bool, force_pod_labels: bool, update: bool,
         source: List[str], labels: List[str], namespace: Optional[str], watch: str,
         include_ir: bool, include_aconf: bool,
         diff_path: Optional[str]=None, kat_name: Optional[str]=None) -> None:
    loglevel = logging.DEBUG if debug else logging.INFO

    logging.basicConfig(
        level=loglevel,
        format="%(asctime)s mockery %(levelname)s: %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )

    logger = logging.getLogger('mockery')

    logger.debug(f"reading from {k8s_yaml_path}")

    if not source:
        source = [
            "Host", "service", "ingresses",
            "AuthService", "LogService", "Mapping", "Module", "RateLimitService",
            "TCPMapping", "TLSContext", "TracingService",
            "ConsulResolver", "KubernetesEndpointResolver", "KubernetesServiceResolver"
        ]

    if namespace:
        os.environ['AMBASSADOR_NAMESPACE'] = namespace

    # Make labels a list, instead of a tuple.
    labels = list(labels)
    labels_to_force = { l: True for l in labels or [] }

    if kat_name:
        logger.debug(f"KAT name {kat_name}")

        # First set up some labels to force.

        labels_to_force["scope=AmbassadorTest"] = True
        labels_to_force[f"service={kat_name}"] = True

        kat_amb_id_label = f"kat-ambassador-id={kat_name}"

        if kat_amb_id_label not in labels_to_force:
            labels_to_force[kat_amb_id_label] = True
            labels.append(kat_amb_id_label)

        os.environ['AMBASSADOR_ID'] = kat_name

        # Forcibly override the cached ambassador_id.
        Config.ambassador_id = kat_name

    logger.debug(f"namespace {namespace or '*'}")
    logger.debug(f"labels to watch {', '.join(labels)}")
    logger.debug(f"labels to force {', '.join(sorted(labels_to_force.keys()))}")
    logger.debug(f"watch hook {watch}")
    logger.debug(f"sources {', '.join(source)}")

    for key in sorted(os.environ.keys()):
        if key.startswith('AMBASSADOR'):
            logger.debug(f"${key}={os.environ[key]}")

    if force_pod_labels:
        try:
            os.makedirs("/tmp/ambassador-pod-info")
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise

        with open("/tmp/ambassador-pod-info/labels", "w", encoding="utf-8") as outfile:
            for l in labels_to_force:
                outfile.write(l)
                outfile.write("\n")

    # Pull in the YAML.
    manifest = parse_yaml(open(k8s_yaml_path, "r").read())

    w = Mockery(logger, debug, source, ",".join(labels), namespace, watch)

    iteration = 0

    while True:
        iteration += 1

        if iteration > 10:
            print(f"!!!! Not stable after 10 iterations, failing")
            logger.error("Not stable after 10 iterations, failing")
            sys.exit(1)

        print(f"==== ITERATION {iteration}")

        watt_k8s = w.load(manifest)

        logger.info(f"WATT_K8S: {json.dumps(watt_k8s, sort_keys=True, indent=4)}")

        hook_ok, any_changes = w.run_hook(watt_k8s)
        
        if not hook_ok:
            raise Exception("hook failed")
            
        if any_changes:
            logger.info("WATT_K8S: some changes from the hook!")
            print("====== watches changed!")
        else:
            print("====== stable!")
            break

    # Once here, we should be good to go.
    try:
        os.makedirs("/tmp/ambassador/snapshots")
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    scc = SecretHandler(logger, "mockery", "/tmp/ambassador/snapshots", f"v{iteration}")

    aconf = Config()

    logger.debug(f"Config.ambassador_id {Config.ambassador_id}")
    logger.debug(f"Config.ambassador_namespace {Config.ambassador_namespace}")

    fetcher = ResourceFetcher(logger, aconf)
    fetcher.parse_watt(open("/tmp/mockery.json", "r", encoding="utf-8").read())
    aconf.load_all(fetcher.sorted())

    open("/tmp/ambassador/snapshots/aconf.json", "w", encoding="utf-8").write(aconf.as_json())

    ir = IR(aconf, secret_handler=scc)

    open("/tmp/ambassador/snapshots/ir.json", "w", encoding="utf-8").write(ir.as_json())

    econf = EnvoyConfig.generate(ir, "V2")
    bootstrap_config, ads_config = econf.split_config()

    ads_config.pop('@type', None)
    with open("/tmp/ambassador/snapshots/econf.json", "w", encoding="utf-8") as outfile:
        outfile.write(json.dumps(ads_config, sort_keys=True, indent=4))

    with open("/tmp/ambassador/snapshots/bootstrap.json", "w", encoding="utf-8") as outfile:
        outfile.write(json.dumps(bootstrap_config, sort_keys=True, indent=4))

    diag = Diagnostics(ir, econf)

    with open("/tmp/ambassador/snapshots/diag.json", "w", encoding="utf-8") as outfile:
        outfile.write(json.dumps(diag.as_dict(), sort_keys=True, indent=4))

    if diff_path:
        diffs = False

        pairs_to_check = [
            (os.path.join(diff_path, 'snapshots', 'econf.json'), '/tmp/ambassador/snapshots/econf.json'),
            (os.path.join(diff_path, 'bootstrap-ads.json'), '/tmp/ambassador/snapshots/bootstrap.json')
        ]

        if include_ir:
            pairs_to_check.append(
                ( os.path.join(diff_path, 'snapshots', 'ir.json'), '/tmp/ambassador/snapshots/ir.json' )
            )

        if include_aconf:
            pairs_to_check.append(
                ( os.path.join(diff_path, 'snapshots', 'aconf.json'), '/tmp/ambassador/snapshots/aconf.json' )
            )

        for gold_path, check_path in pairs_to_check:
            if update:
                logger.info(f"mv {check_path} {gold_path}")
                shutil.move(check_path, gold_path)
            elif not filecmp.cmp(gold_path, check_path):
                diffs = True

                gold_lines = open(gold_path, "r", encoding="utf-8").readlines()
                check_lines = open(check_path, "r", encoding="utf-8").readlines()

                for line in difflib.unified_diff(gold_lines, check_lines, fromfile=gold_path, tofile=check_path):
                    sys.stdout.write(line)

        if diffs:
            sys.exit(1)