diff --git a/ai-tooling/user/skills/nvcf-self-managed-cli/examples/ci-pipelines.md b/ai-tooling/user/skills/nvcf-self-managed-cli/examples/ci-pipelines.md index e854a34373..ee36891ae5 100644 --- a/ai-tooling/user/skills/nvcf-self-managed-cli/examples/ci-pipelines.md +++ b/ai-tooling/user/skills/nvcf-self-managed-cli/examples/ci-pipelines.md @@ -12,15 +12,18 @@ deploy_nvcf: variables: KUBECONFIG: $KUBECONFIG_FILE script: - - nvcf-cli self-hosted check --pre --json | jq -e '.event != "phase_failed"' || exit 2 + - nvcf-cli self-hosted check --pre --json 2>&1 >/dev/null | grep '^{' | jq -se 'length > 0 and all(.[]; .event != "phase_failed")' || exit 2 - nvcf-cli self-hosted up --cluster-name=$CLUSTER_NAME --token=$NVCF_ADMIN_JWT --non-interactive --json - - nvcf-cli self-hosted status --json | jq -e '.verdict == "healthy"' + - nvcf-cli self-hosted status --json 2>&1 >/dev/null | grep '^{' | jq -se 'any(.[]; .verdict == "healthy")' ``` Notes: - `--non-interactive --token=$JWT` is required in CI; never use interactive `init`. - Always `--json` for machine-parsing. +- `--json` writes JSONL to stderr, not stdout, so redirect with `2>&1 >/dev/null` before a parser. +- Slurp with `jq -s` before testing a condition. Without it `jq -e` takes its exit status from the last event alone, so a `phase_failed` followed by any other event still exits 0. +- stderr also carries plain-text notices, so filter to JSON lines. Do not add `--show-logs` here: it appends a non-JSON transcript to the same stream. - Final status check gates downstream stages on `verdict == "healthy"`. ## GitOps (Argo / Flux) pattern diff --git a/ai-tooling/user/skills/nvcf-self-managed-cli/reference/flags.md b/ai-tooling/user/skills/nvcf-self-managed-cli/reference/flags.md index 65bcbb6b97..cdc0e0cf53 100644 --- a/ai-tooling/user/skills/nvcf-self-managed-cli/reference/flags.md +++ b/ai-tooling/user/skills/nvcf-self-managed-cli/reference/flags.md @@ -26,6 +26,35 @@ | `--icms-url URL` | Public ICMS URL; required when contexts differ | derived from `base_http_url` | | `--local-only` | `check --pre` only; skip all kubectl contact | `false` | +## `check`-specific + +At least one of `--pre`, `--control-plane`, `--compute-plane`, or `--all` is +required. Each selects a role; only the selected roles contact a cluster. + +| Flag | Purpose | Default | +|---|---|---| +| `--pre` | Pre-flight: local-host tools plus cluster readiness | `false` | +| `--control-plane` | Control-plane checks | `false` | +| `--compute-plane` | Compute-plane checks | `false` | +| `--all` | Every category | `false` | +| `--cluster-name NAME` | Cluster name for compute-plane checks | - | +| `--skip-inotify-check` | Skip the per-node inotify-limits probe. Needed when the kubeconfig user cannot create pods in `default`. Env: `NVCF_CLI_SELFHOSTED_SKIP_INOTIFY` | `false` | + +### Cluster-validator flags + +The validator runs as a Job in the cluster being checked. The CLI creates a +ServiceAccount, ClusterRole, and ClusterRoleBinding for it and removes them +after the run, so the kubeconfig context needs permission to manage those. + +| Flag | Purpose | Default | +|---|---|---| +| `--cluster-validator-image REF` | Validator image. Resolution order: flag, `NVCF_CLI_CLUSTER_VALIDATOR_IMAGE`, config key `cluster_validator_image`. A ref with no tag discovers the latest stable tag from the registry. Unset everywhere skips the probe with a warning | - | +| `--cluster-validator-registries host:port,...` | Extra registries the control-plane validator probes for reachability. `nvcr.io` is always probed. Repeatable or comma-separated. Env: `NVCF_CLI_CLUSTER_VALIDATOR_REGISTRIES`; config key `cluster_validator_registries` | `nvcr.io` only | +| `--cluster-validator-pull-secret NAME` | docker-registry Secret in `default` used to pull the validator image. When empty, the CLI looks for one in the NVCF namespaces and falls back to minting one from `NGC_API_KEY` | auto-detect | +| `--skip-cluster-validation` | Skip the in-cluster validator probe entirely. Env: `NVCF_CLI_SELFHOSTED_SKIP_CLUSTER_VALIDATION` | `false` | +| `--no-cleanup` | Keep the validator Job (and its RBAC) after the run for debugging. The next run still sweeps prior Jobs | `false` | +| `--show-logs` | Print the validator transcript to stderr after the check events. The transcript is not JSON, and `--json` also writes to stderr, so leave this off when a parser is reading the stream | `false` | + ## `up`-specific | Flag | Purpose | Default | diff --git a/src/clis/nvcf-cli/.nvcf-cli.yaml.template b/src/clis/nvcf-cli/.nvcf-cli.yaml.template index 585adc8b21..f21daa19d5 100644 --- a/src/clis/nvcf-cli/.nvcf-cli.yaml.template +++ b/src/clis/nvcf-cli/.nvcf-cli.yaml.template @@ -142,7 +142,13 @@ api_keys_owner_id: svc@nvcf-api.local # Image reference for the cluster-validator pod used by # `nvcf-cli self-hosted check`. The CLI runs this image as a Job in the -# compute-plane cluster to verify NVCA prerequisites before install. +# cluster being checked to verify prerequisites before install. One image +# serves both roles; the Job environment selects the check set. +# +# The Job needs a ServiceAccount, ClusterRole, and ClusterRoleBinding, which +# the CLI creates and removes per run. The kubeconfig context therefore needs +# permission to manage those objects; without it the probe reports a warning +# instead of a result. # # Config key: cluster_validator_image # Environment variable: NVCF_CLI_CLUSTER_VALIDATOR_IMAGE @@ -156,6 +162,18 @@ api_keys_owner_id: svc@nvcf-api.local # Prod: nvcr.io/nvidia/nvcf-byoc/cluster-validator # cluster_validator_image: nvcr.io/nvidia/nvcf-byoc/cluster-validator +# Extra container registries the control-plane validator probes for +# reachability, as host:port. nvcr.io is always probed, so list only the +# registries your stack pulls from in addition to it. +# +# Config key: cluster_validator_registries (list) +# Environment variable: NVCF_CLI_CLUSTER_VALIDATOR_REGISTRIES (comma-separated) +# Command-line flag: --cluster-validator-registries (repeatable or comma-separated) +# +# cluster_validator_registries: +# - harbor.example.com:443 +# - ghcr.io:443 + # ============================================================================== # General Settings # ============================================================================== diff --git a/src/clis/nvcf-cli/cmd/BUILD.bazel b/src/clis/nvcf-cli/cmd/BUILD.bazel index 2f83c8da26..f67e61ba00 100644 --- a/src/clis/nvcf-cli/cmd/BUILD.bazel +++ b/src/clis/nvcf-cli/cmd/BUILD.bazel @@ -141,6 +141,7 @@ go_test( "//src/clis/nvcf-cli/internal/selfhosted", "//src/clis/nvcf-cli/internal/selfhosted/auth", "//src/clis/nvcf-cli/internal/selfhosted/controlplaneprofile", + "//src/clis/nvcf-cli/internal/selfhosted/kubectx", "//src/clis/nvcf-cli/internal/selfhosted/progress", "//src/clis/nvcf-cli/internal/selfhosted/reachability", "//src/clis/nvcf-cli/internal/selfhosted/teardown", diff --git a/src/clis/nvcf-cli/cmd/main_test.go b/src/clis/nvcf-cli/cmd/main_test.go index d0fa86ed75..4d65747743 100644 --- a/src/clis/nvcf-cli/cmd/main_test.go +++ b/src/clis/nvcf-cli/cmd/main_test.go @@ -21,14 +21,35 @@ import ( "context" "os" "testing" + + "nvcf-cli/internal/selfhosted" ) -// Default-stub out the validator-tag registry probe so cmd tests don't make -// real network calls or pollute the on-disk cache. Individual tests can -// reassign the variable if they explicitly want to exercise discovery. +// Default-stub every seam that would otherwise reach the developer's cluster or +// the network. Individual tests reassign a variable when they explicitly want +// to exercise that path. +// +// These are not conveniences. Without them `go test ./cmd/` creates a hostPath +// busybox pod per node in `default` (the inotify probe), lists Secrets across +// the stack namespaces of whatever kubeconfig happens to be current, and makes +// an outbound request to nvcr.io per configured registry. That mutates a real +// cluster from a unit test, and it is why the package took minutes and failed +// on a proxied kubeconfig rather than seconds and deterministically. func TestMain(m *testing.M) { resolveLatestValidatorTagForSelfHosted = func(_ context.Context, _ string) (string, bool) { return "", false } + // Nil prober: the inotify check is skipped rather than creating pods. + newInotifyProberForSelfHosted = func() selfhosted.NodeInotifyProber { return nil } + // No cluster contact, and a clean result so the category still renders. + newStaleNamespaceProberForSelfHosted = func() selfhosted.StaleNamespaceProber { + return func(context.Context, string, []string) ([]selfhosted.StaleNamespace, error) { + return nil, nil + } + } + // No outbound registry request. + newRegistryCredentialCheckerForSelfHosted = func() selfhosted.RegistryCredentialChecker { + return func(context.Context, string, string, bool) error { return nil } + } os.Exit(m.Run()) } diff --git a/src/clis/nvcf-cli/cmd/root.go b/src/clis/nvcf-cli/cmd/root.go index a42df48c08..2f07f1b943 100644 --- a/src/clis/nvcf-cli/cmd/root.go +++ b/src/clis/nvcf-cli/cmd/root.go @@ -285,6 +285,7 @@ func initConfig() { // swapping --config files. The env name matches the historical // NVCF_CLI_CLUSTER_VALIDATOR_IMAGE override. viper.BindEnv("cluster_validator_image", "NVCF_CLI_CLUSTER_VALIDATOR_IMAGE") + viper.BindEnv("cluster_validator_registries", "NVCF_CLI_CLUSTER_VALIDATOR_REGISTRIES") // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil && viper.GetBool("debug") { diff --git a/src/clis/nvcf-cli/cmd/self_hosted_check.go b/src/clis/nvcf-cli/cmd/self_hosted_check.go index dafb00fbf5..e8e80d40c7 100644 --- a/src/clis/nvcf-cli/cmd/self_hosted_check.go +++ b/src/clis/nvcf-cli/cmd/self_hosted_check.go @@ -22,6 +22,8 @@ import ( "fmt" "io" "os" + "path/filepath" + "strings" "time" "github.com/spf13/cobra" @@ -45,6 +47,7 @@ var ( checkClusterValidatorImage string checkClusterValidatorPullSecret string checkClusterValidatorNoCleanup bool + checkClusterValidatorRegistries []string checkShowLogs bool ) @@ -58,9 +61,19 @@ var newClusterValidatorForSelfHosted = func() selfhosted.ClusterValidator { return selfhosted.NewClusterValidator() } +// Test seam. +var newStaleNamespaceProberForSelfHosted = func() selfhosted.StaleNamespaceProber { + return selfhosted.NewStaleNamespaceProber() +} + // Test seam. Tests stub this to skip the registry network call. var resolveLatestValidatorTagForSelfHosted = selfhosted.ResolveLatestValidatorTag +// Test seam. +var newRegistryCredentialCheckerForSelfHosted = func() selfhosted.RegistryCredentialChecker { + return selfhosted.NewRegistryCredentialChecker() +} + var checkWriterIsTTY = isWriterTTY var selfHostedCheckCmd = &cobra.Command{ @@ -100,6 +113,13 @@ func init() { selfHostedCheckCmd.Flags().BoolVar(&checkClusterValidatorNoCleanup, "no-cleanup", false, "Disable the validator Job's TTL so the Job persists for debugging. "+ "The next run still deletes prior Jobs via the singleton sweep.") + selfHostedCheckCmd.Flags().StringSliceVar(&checkClusterValidatorRegistries, "cluster-validator-registries", nil, + "Additional container registries to probe for reachability in the control-plane validator. "+ + "Format: host:port (e.g. harbor.company.internal:443,ghcr.io:443). "+ + "nvcr.io is always included. Env: NVCF_CLI_CLUSTER_VALIDATOR_REGISTRIES. "+ + "Can also be set in nvcf-cli config as cluster_validator_registries (list).") + _ = viper.BindPFlag("cluster_validator_registries", + selfHostedCheckCmd.Flags().Lookup("cluster-validator-registries")) selfHostedCheckCmd.Flags().BoolVar(&checkShowLogs, "show-logs", false, "Print the cleaned cluster-validator transcript to stderr after the check events. "+ "Useful when piping --json output to a script that also wants the transcript.") @@ -113,25 +133,40 @@ func runSelfHostedCheck(c *cobra.Command, _ []string) error { localOnly := checkLocalOnly || os.Getenv("NVCF_CLI_SELFHOSTED_LOCAL_ONLY") != "" skipClusterValidation := checkSkipClusterValidation || os.Getenv("NVCF_CLI_SELFHOSTED_SKIP_CLUSTER_VALIDATION") != "" + // Mode is needed before image resolution so computePlaneIsTargeted can + // gate the registry round trip. ValidateFlags in PersistentPreRunE + // guarantees mode is ModeSingle or ModeSplit here. + mode := kubectx.SelectMode(selfHostedControlPlaneContext, selfHostedComputePlaneContext) + // Resolve the validator image up-front so we can right-size the // outer timeout (only when the validator actually runs) and emit a // one-shot stderr note up-front explaining why no validator row // appears in the output. Empty == not configured anywhere. + // One image covers both roles (VALIDATOR_ROLE selects the check set). + // *IsVisited, matching the dispatch below. --pre in ModeSplit visits both + // clusters but targets neither role, so gating image resolution on + // *IsTargeted left the validator unresolved and both probes nil, with no + // note explaining why. + anyValidatorIsTargeted := !localOnly && !skipClusterValidation && + (computePlaneIsVisited() || controlPlaneIsVisited()) clusterValidatorImage := "" - if !localOnly && !skipClusterValidation && (checkPre || checkAll) { + if anyValidatorIsTargeted { if img, ok := resolveClusterValidatorImage(c.Context()); ok { clusterValidatorImage = img } } - clusterValidatorWillRun := !localOnly && !skipClusterValidation && (checkPre || checkAll) && clusterValidatorImage != "" + clusterValidatorWillRun := anyValidatorIsTargeted && clusterValidatorImage != "" - // The cluster-validator Job's internal budget is 5m - // (selfhosted.clusterValidatorTimeout). The outer ctx must be at least - // that plus headroom for RBAC bootstrap + log fetch, otherwise vctx - // derives from a shorter ceiling and silently truncates the wait. outerTimeout := 2 * time.Minute if clusterValidatorWillRun { - outerTimeout = 6 * time.Minute + // Each validator Job has a 5m internal budget. ModeSingle runs both + // validators sequentially (two 5m runs); ModeSplit runs them in + // parallel so one 6m ceiling covers both. + if mode == kubectx.ModeSingle && controlPlaneIsTargeted(mode) && computePlaneIsTargeted(mode) { + outerTimeout = 12 * time.Minute + } else { + outerTimeout = 6 * time.Minute + } } // --wait polls for the declared duration. The outer ctx has to outlive // the last iteration, so add waitDur on top of a single iteration's @@ -154,7 +189,7 @@ func runSelfHostedCheck(c *cobra.Command, _ []string) error { // validator row" with "validator silently dropped". Print at most one // reason; --skip-cluster-validation takes precedence over missing // config since it's the explicit operator choice. - if !localOnly && (checkPre || checkAll) { + if !localOnly && (computePlaneIsVisited() || controlPlaneIsVisited()) { switch { case skipClusterValidation: fmt.Fprintln(c.ErrOrStderr(), "note: cluster-validator skipped (--skip-cluster-validation)") @@ -163,9 +198,33 @@ func runSelfHostedCheck(c *cobra.Command, _ []string) error { } } + // Enumerate registries for the local credential check. Skipped when + // local-only (no network) or when no validator image is configured. + // Uses the same extras list as the in-cluster ConfigMap reachability check. + var ( + credEntries []selfhosted.RegistryEntry + registryChecker selfhosted.RegistryCredentialChecker + ) + // Run credential checks whenever not local-only. The validator image is + // optional: EnumerateRegistries handles an empty image ref and still picks + // up global.image.registry from the stack values file and any + // --cluster-validator-registries extras independently of the image config. + if !localOnly { + extraRegistries := configuredValidatorRegistries() + stackValuesFile := resolveStackValuesFile() + credEntries = selfhosted.EnumerateRegistries( + clusterValidatorImage, stackValuesFile, extraRegistries, + ) + if len(credEntries) > 0 { + registryChecker = newRegistryCredentialCheckerForSelfHosted() + } + } + cfg := selfhosted.PreflightConfig{ - LocalOnly: localOnly, - Tools: selfHostedPreflightTools(), + LocalOnly: localOnly, + Tools: selfHostedPreflightTools(), + Registries: credEntries, + RegistryChecker: registryChecker, } sink, err := selectCheckRenderer(c.ErrOrStderr(), selfHostedWait != "") @@ -181,8 +240,8 @@ func runSelfHostedCheck(c *cobra.Command, _ []string) error { runOnce := func() []selfhosted.CheckResult { var results []selfhosted.CheckResult - if checkPre || checkAll { - results = append(results, runPreflightByRole(ctx, cfg, sink, clusterValidatorImage)...) + if checkPre || checkAll || checkControlPlane || checkComputePlane { + results = append(results, runPreflightByRole(ctx, cfg, sink, mode, clusterValidatorImage)...) } // Inject force-fail seam for tests. if os.Getenv("NVCF_CLI_SELFHOSTED_FORCE_FAIL") != "" { @@ -194,7 +253,6 @@ func runSelfHostedCheck(c *cobra.Command, _ []string) error { Message: "forced failure (test seam)", }}, results...) } - // control-plane / compute-plane wired in M3/M4 — placeholder no-op for M2. return results } @@ -240,6 +298,139 @@ func runSelfHostedCheck(c *cobra.Command, _ []string) error { } } +// resolveStackValuesFile returns the environment values YAML to read +// global.image.registry from, or "" when none is available. +// +// It prefers --control-plane-stack, the same source every sibling command uses, +// and only falls back to walking up from the working directory. Within a stack +// it tries HELMFILE_ENV (default "default") and then base.yaml, which is where +// global.image.registry actually lives. The previous version looked only for +// environments/local.yaml, which is not a tracked file, so on any clean +// checkout os.Stat never succeeded and this whole lookup was dead. +func resolveStackValuesFile() string { + var roots []string + if selfHostedControlPlaneStack != "" { + roots = append(roots, selfHostedControlPlaneStack) + } + if cwd, err := os.Getwd(); err == nil { + dir := cwd + for i := 0; i < 6; i++ { + roots = append(roots, dir) + parent := filepath.Dir(dir) + if parent == dir { + break + } + dir = parent + } + } + + // selfHostedEnv (--env, default "local"), not HELMFILE_ENV: that variable + // is only ever injected into the helmfile subprocess, so reading it here + // always returned "" and fell through to base.yaml. An operator whose + // local.yaml points global.image.registry at their mirror would get + // base.yaml's nvcr.io, and the preflight would credential-check a registry + // the install never pulls from. + env := strings.TrimSpace(selfHostedEnv) + if env == "" { + env = "local" + } + names := []string{env + ".yaml", "base.yaml"} + + for _, root := range roots { + for _, sub := range [][]string{ + {"deploy", "stacks", "self-managed", "environments"}, + {"environments"}, // a stack dir passed directly + } { + for _, name := range names { + candidate := filepath.Join(append(append([]string{root}, sub...), name)...) + if _, err := os.Stat(candidate); err == nil { + return candidate + } + } + } + } + return "" +} + +// localStackDir returns src when it points at a readable local directory. +// Remote sources (oci://, git@, https://...git) are not fetched here: the +// stale-namespace check falls back to its static list rather than making +// preflight depend on a network round trip. +func localStackDir(src string) string { + if src == "" { + return "" + } + src = strings.TrimPrefix(src, "file://") + if strings.Contains(src, "://") || strings.HasPrefix(src, "git@") { + return "" + } + if fi, err := os.Stat(src); err == nil && fi.IsDir() { + return src + } + return "" +} + +// configuredValidatorRegistries returns the extra registries from the flag, env +// var, or config file, normalized to one entry per registry. +// +// viper.GetStringSlice splits a raw env string on whitespace, so the documented +// comma form "a:443,b:443" arrives as a single element. Left as-is it reaches +// net.SplitHostPort as "a:443,b:443", which errors with "too many colons" and is +// then passed through verbatim as a host, producing https://a:443,b:443/v2/. +func configuredValidatorRegistries() []string { + var out []string + for _, raw := range viper.GetStringSlice("cluster_validator_registries") { + for _, part := range strings.Split(raw, ",") { + if part = strings.TrimSpace(part); part != "" { + out = append(out, part) + } + } + } + return out +} + +// computePlaneIsTargeted reports whether the compute-plane validator should run: +// --compute-plane, --all, or --pre in ModeSingle. --pre in ModeSplit does not +// target it because separate clusters have no implicit compute-plane role. +func computePlaneIsTargeted(mode kubectx.Mode) bool { + return checkComputePlane || checkAll || (checkPre && mode == kubectx.ModeSingle) +} + +// controlPlaneIsTargeted mirrors computePlaneIsTargeted but for the control +// plane. Runs when: --control-plane, --all, or --pre in ModeSingle. +func controlPlaneIsTargeted(mode kubectx.Mode) bool { + return checkControlPlane || checkAll || (checkPre && mode == kubectx.ModeSingle) +} + +// The *IsVisited pair reports whether a cluster should be contacted at all, +// which is broader than whether its role-specific check set runs. --pre in +// ModeSplit visits both clusters for the shared pre-install checks (stale +// namespaces) without targeting either role, so the targeting predicates alone +// cannot gate the dispatch. +// +// No mode parameter, unlike *IsTargeted: "(X || (pre && single)) || pre" +// absorbs to "X || pre", so the mode cannot change the answer. Taking one +// would imply a mode-dependence that does not exist. +func computePlaneIsVisited() bool { + return checkComputePlane || checkAll || checkPre +} + +func controlPlaneIsVisited() bool { + return checkControlPlane || checkAll || checkPre +} + +// withoutHostLocalChecks returns a copy of cfg with the inputs for the checks +// that run on the operator's machine cleared: local tool versions and registry +// credentials. Neither contacts a cluster, so exactly one role invocation must +// carry them. Without this both roles emit the same check IDs, which +// double-counts them in the pass/fail totals and repeats them in --json. +func withoutHostLocalChecks(cfg selfhosted.PreflightConfig) selfhosted.PreflightConfig { + cfg.Tools = nil + cfg.Registries = nil + cfg.RegistryChecker = nil + return cfg +} + // maybeShowClusterValidatorLogs prints the cleaned cluster-validator transcript // to the given writer when --show-logs is set, framed by markers so operators // can find it in mixed CLI output. Silent no-op when: @@ -262,7 +453,9 @@ func maybeShowClusterValidatorLogs(w io.Writer, results []selfhosted.CheckResult fmt.Fprintln(w, "--- cluster-validator logs ---") fmt.Fprint(w, r.Logs) fmt.Fprintln(w, "--- end cluster-validator logs ---") - return + // No early return: both roles produce a cluster-validator result under + // the same ID, so stopping at the first drops the other transcript + // entirely from --all --show-logs. } } @@ -296,24 +489,29 @@ func selectCheckRenderer(w io.Writer, wait bool) (progress.EventSink, error) { // - ModeSingle (no context flags) → RoleControlPlane + RoleComputePlane sequentially // - ModeSplit (both context flags set) → RoleControlPlane + RoleComputePlane in parallel // -// clusterValidatorImage is the already-resolved validator image (empty when -// not configured). Resolution happens in the caller so the outer-timeout -// and stderr-note logic can see the same answer this function does. -func runPreflightByRole(ctx context.Context, cfg selfhosted.PreflightConfig, sink progress.EventSink, clusterValidatorImage string) []selfhosted.CheckResult { +// mode is the already-resolved kubectx.Mode (hoisted to the caller so image +// resolution and timeout sizing share the same answer). clusterValidatorImage +// is the already-resolved validator image (empty when not configured). +func runPreflightByRole(ctx context.Context, cfg selfhosted.PreflightConfig, sink progress.EventSink, mode kubectx.Mode, clusterValidatorImage string) []selfhosted.CheckResult { // LocalOnly: skip all cluster probes. if cfg.LocalOnly { return selfhosted.RunPreflightForRole(ctx, cfg, selfhosted.RoleLocalOnly, selfhosted.RoleConfig{}, sink) } + // SIS reachability is a compute-plane concern, and it is skipped pre-install + // because SIS is not up yet. The previous `!checkPre` form was also true + // whenever --control-plane was passed, so a control-plane run fired an HTTP + // request at SIS that the operator never asked for. icmsURL := "" - if checkAll || checkComputePlane || !checkPre { + if computePlaneIsTargeted(mode) && !checkPre { icmsURL = resolveICMSURL(selfHostedICMSURL) } - mode := kubectx.SelectMode(selfHostedControlPlaneContext, selfHostedComputePlaneContext) skipInotify := checkSkipInotifyCheck || os.Getenv("NVCF_CLI_SELFHOSTED_SKIP_INOTIFY") != "" var inotifyProber selfhosted.NodeInotifyProber - if !skipInotify { + // Visited, not targeted: the inotify limit is exactly what --pre exists to + // catch before NVCA bootstrap, so it must run for --pre in ModeSplit too. + if computePlaneIsVisited() && !skipInotify { inotifyProber = newInotifyProberForSelfHosted() } @@ -323,65 +521,153 @@ func runPreflightByRole(ctx context.Context, cfg selfhosted.PreflightConfig, sin // Either way, leave clusterValidator nil so the validator row is // omitted from the check stream; the caller already emitted a // one-line stderr notice explaining which case applies. + // Gate on the role predicate as well as the image, mirroring + // cpClusterValidator below. Without this, --control-plane in ModeSplit + // still creates a ServiceAccount, cluster-wide ClusterRole/CRB, pull secret + // and validator Job in the compute cluster. var clusterValidator selfhosted.ClusterValidator - if clusterValidatorImage != "" { + if computePlaneIsVisited() && clusterValidatorImage != "" { clusterValidator = newClusterValidatorForSelfHosted() } + staleNSProber := newStaleNamespaceProberForSelfHosted() + + // Additional registries to probe in the control-plane validator ConfigMap. + // Priority: flag > env > config file. + registries := configuredValidatorRegistries() + + // The cluster-validator image is the same for both roles; VALIDATOR_ROLE + // in the Job env selects which check set runs inside the binary. + // Gate on the image, not on the compute-plane validator being constructed: + // in ModeSplit with --control-plane the compute role is not targeted, so + // clusterValidator is nil and keying off it would drop the control-plane + // validator check from the run entirely. + var cpClusterValidator selfhosted.ClusterValidator + if controlPlaneIsVisited() && clusterValidatorImage != "" { + cpClusterValidator = newClusterValidatorForSelfHosted() + } + + // Local tool versions and registry credentials are checked on the + // operator's machine, so they belong to one invocation only. The control + // plane carries them when it runs; otherwise the compute plane does, so + // neither is silently dropped by a compute-plane-only invocation. + runControlPlane := controlPlaneIsVisited() + runComputePlane := computePlaneIsVisited() + cpCfg, gpuCfg := cfg, cfg + if runControlPlane { + gpuCfg = withoutHostLocalChecks(cfg) + } + switch mode { case kubectx.ModeSplit: // Run both roles in parallel; each gets its own kubeconfig context. + // Each dispatch is gated: with only one role selected the other + // cluster is never contacted, so its stale-namespace probe cannot + // report a failure the operator did not ask about. var ( cpResults []selfhosted.CheckResult gpuResults []selfhosted.CheckResult ) eg, egCtx := errgroup.WithContext(ctx) - eg.Go(func() error { - rc := selfhosted.RoleConfig{KubeContext: selfHostedControlPlaneContext} - cpResults = selfhosted.RunPreflightForRole(egCtx, cfg, selfhosted.RoleControlPlane, rc, sink) - return nil - }) - eg.Go(func() error { - rc := selfhosted.RoleConfig{ - KubeContext: selfHostedComputePlaneContext, + if runControlPlane { + eg.Go(func() error { + rc := selfhosted.RoleConfig{ + KubeContext: selfHostedControlPlaneContext, + ClusterValidator: cpClusterValidator, + ClusterValidatorImage: clusterValidatorImage, + ClusterValidatorPullSecret: checkClusterValidatorPullSecret, + ClusterValidatorNoCleanup: checkClusterValidatorNoCleanup, + ClusterValidatorRegistries: registries, + StaleNamespaceProber: staleNSProber, + StackDir: localStackDir(selfHostedControlPlaneStack), + } + cpResults = selfhosted.RunPreflightForRole(egCtx, cpCfg, selfhosted.RoleControlPlane, rc, sink) + return nil + }) + } + if runComputePlane { + eg.Go(func() error { + rc := selfhosted.RoleConfig{ + KubeContext: selfHostedComputePlaneContext, + SISURL: icmsURL, + InotifyProber: inotifyProber, + ClusterValidator: clusterValidator, + ClusterValidatorImage: clusterValidatorImage, + ClusterValidatorPullSecret: checkClusterValidatorPullSecret, + ClusterValidatorNoCleanup: checkClusterValidatorNoCleanup, + StaleNamespaceProber: staleNSProber, + StackDir: localStackDir(selfHostedComputePlaneStack), + } + gpuResults = selfhosted.RunPreflightForRole(egCtx, gpuCfg, selfhosted.RoleComputePlane, rc, sink) + return nil + }) + } + _ = eg.Wait() + return append(cpResults, gpuResults...) + + default: // ModeSingle - one cluster; run only the roles the flags target. + var results []selfhosted.CheckResult + + // The stale-namespace probe goes to exactly one role. Both roles share + // the cluster here, so handing it to both emits two check_completed + // events with the same ID and loads the kubeconfig twice, which means a + // second exec-credential-plugin prompt. + // + // The two roles probe disjoint namespace lists, so the skipped role's + // namespaces are merged into the surviving probe rather than dropped. + // Without that, a kai-scheduler or nvca-operator namespace wedged + // Terminating by a failed teardown reports "no stale NVCF namespaces + // detected" and the next install fails into it. + staleForControlPlane := staleNSProber + staleForComputePlane := staleNSProber + var cpExtraNamespaces, gpuExtraNamespaces []string + if runControlPlane { + staleForComputePlane = nil + cpExtraNamespaces = selfhosted.ComputePlaneStaleNamespaces( + localStackDir(selfHostedComputePlaneStack)) + } else { + staleForControlPlane = nil + gpuExtraNamespaces = selfhosted.ControlPlaneStaleNamespaces( + localStackDir(selfHostedControlPlaneStack)) + } + + if runControlPlane { + cpRC := selfhosted.RoleConfig{ + SISURL: icmsURL, + ClusterValidator: cpClusterValidator, + ClusterValidatorImage: clusterValidatorImage, + ClusterValidatorPullSecret: checkClusterValidatorPullSecret, + ClusterValidatorNoCleanup: checkClusterValidatorNoCleanup, + ClusterValidatorRegistries: registries, + StaleNamespaceProber: staleForControlPlane, + StackDir: localStackDir(selfHostedControlPlaneStack), + ExtraStaleNamespaces: cpExtraNamespaces, + } + results = append(results, + selfhosted.RunPreflightForRole(ctx, cpCfg, selfhosted.RoleControlPlane, cpRC, sink)...) + } + if runComputePlane { + gpuRC := selfhosted.RoleConfig{ SISURL: icmsURL, InotifyProber: inotifyProber, ClusterValidator: clusterValidator, ClusterValidatorImage: clusterValidatorImage, ClusterValidatorPullSecret: checkClusterValidatorPullSecret, ClusterValidatorNoCleanup: checkClusterValidatorNoCleanup, + StaleNamespaceProber: staleForComputePlane, + StackDir: localStackDir(selfHostedComputePlaneStack), + ExtraStaleNamespaces: gpuExtraNamespaces, } - gpuResults = selfhosted.RunPreflightForRole(egCtx, cfg, selfhosted.RoleComputePlane, rc, sink) - return nil - }) - _ = eg.Wait() - return append(cpResults, gpuResults...) - - default: // ModeSingle — no context flags; union both role check sets sequentially. - cpRC := selfhosted.RoleConfig{SISURL: icmsURL} - gpuRC := selfhosted.RoleConfig{ - SISURL: icmsURL, - InotifyProber: inotifyProber, - ClusterValidator: clusterValidator, - ClusterValidatorImage: clusterValidatorImage, - ClusterValidatorPullSecret: checkClusterValidatorPullSecret, - ClusterValidatorNoCleanup: checkClusterValidatorNoCleanup, + results = append(results, + selfhosted.RunPreflightForRole(ctx, gpuCfg, selfhosted.RoleComputePlane, gpuRC, sink)...) } - cpResults := selfhosted.RunPreflightForRole(ctx, cfg, selfhosted.RoleControlPlane, cpRC, sink) - gpuResults := selfhosted.RunPreflightForRole(ctx, cfg, selfhosted.RoleComputePlane, gpuRC, sink) - return append(cpResults, gpuResults...) + return results } } -// Resolves the validator image from the viper-backed config chain -// (flag > env > config-file > default). Returns ("", false) when nothing -// is configured so the caller can surface a clear "not configured" -// warning instead of pulling from a stale built-in default. -// -// When the configured value already has a tag, it is used as-is. When it -// names only a repo, the latest tag is discovered from the registry -// (preferring stable over rc, 1h cached); any discovery failure falls -// back to the configured value unchanged. +// resolveClusterValidatorImage resolves the validator image from flag > env > +// config-file. Returns ("", false) when unconfigured. When only a repo is +// given, discovers the latest stable tag (1h cached; falls back on failure). func resolveClusterValidatorImage(ctx context.Context) (string, bool) { image := viper.GetString("cluster_validator_image") if image == "" { @@ -396,17 +682,29 @@ func resolveClusterValidatorImage(ctx context.Context) (string, bool) { // emitCheckFinal emits a Final event with check-mode verdict fields derived // from the result slice. Called once per run (or once per wait-loop exit). func emitCheckFinal(ctx context.Context, sink progress.EventSink, results []selfhosted.CheckResult) { - var passed, failed int + // Success and FailedCount must agree with the process exit code, which is + // driven by anyFailed. Counting every non-pass as a failure made a + // warning-severity result emit success:false / verdict:failed while the + // process exited 0, so a CI gate on final.success broke for anyone whose + // registry credentials live in a Docker credential helper. "warnings" is + // already part of the documented Verdict vocabulary; it was never emitted. + var passed, failed, warned int for _, r := range results { - if r.Passed { + switch { + case r.Passed: passed++ - } else { + case isBlockingFailure(r): failed++ + default: + warned++ } } verdict := "ok" - if failed > 0 { + switch { + case failed > 0: verdict = "failed" + case warned > 0: + verdict = "warnings" } _ = sink.Emit(ctx, progress.Final{ Success: failed == 0, @@ -417,11 +715,17 @@ func emitCheckFinal(ctx context.Context, sink progress.EventSink, results []self }) } +func isBlockingFailure(r selfhosted.CheckResult) bool { + return !r.Passed && r.Severity == selfhosted.SeverityError +} + // anyFailed returns true if any check failed at error severity. Warnings do // not trigger non-zero exit per spec §6.3. +// isBlockingFailure is the single definition of "this fails the run". Both the +// exit code and the JSON verdict derive from it, so they cannot disagree. func anyFailed(results []selfhosted.CheckResult) bool { for _, r := range results { - if !r.Passed && r.Severity == "error" { + if isBlockingFailure(r) { return true } } diff --git a/src/clis/nvcf-cli/cmd/self_hosted_check_test.go b/src/clis/nvcf-cli/cmd/self_hosted_check_test.go index d3a6d94b64..ddf4f72cac 100644 --- a/src/clis/nvcf-cli/cmd/self_hosted_check_test.go +++ b/src/clis/nvcf-cli/cmd/self_hosted_check_test.go @@ -30,6 +30,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "nvcf-cli/internal/selfhosted" + "nvcf-cli/internal/selfhosted/kubectx" "nvcf-cli/internal/selfhosted/progress" ) @@ -343,9 +345,205 @@ func TestCheck_SplitClusterMode(t *testing.T) { assert.Contains(t, categories, "compute-plane-cluster", "expected compute-plane-cluster in split mode") } -// parseJSONLLines splits s into non-empty lines, skips any non-JSON lines -// (e.g. cobra error messages written to stderr), and unmarshals each JSON line -// as an object. Returns them in order. +// TestComputePlaneIsTargeted tests the predicate that gates the cluster-validator +// probe. The validator should run when the compute plane is explicitly targeted +// (--compute-plane, --all) or implicitly targeted by ModeSingle + --pre. +// It must NOT run for --pre alone in ModeSplit, where the two context flags +// identify separate clusters and --pre does not constitute targeting the compute plane. +func TestComputePlaneIsTargeted(t *testing.T) { + t.Cleanup(func() { + checkPre = false + checkComputePlane = false + checkAll = false + }) + + tests := []struct { + name string + pre bool + cp bool + all bool + mode kubectx.Mode + want bool + }{ + {"--compute-plane single", false, true, false, kubectx.ModeSingle, true}, + {"--compute-plane split", false, true, false, kubectx.ModeSplit, true}, + {"--all single", false, false, true, kubectx.ModeSingle, true}, + {"--all split", false, false, true, kubectx.ModeSplit, true}, + {"--pre single - implicit compute plane", true, false, false, kubectx.ModeSingle, true}, + {"--pre split - must not target compute plane", true, false, false, kubectx.ModeSplit, false}, + {"--control-plane only", false, false, false, kubectx.ModeSingle, false}, + {"no relevant flag", false, false, false, kubectx.ModeSingle, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + checkPre = tt.pre + checkComputePlane = tt.cp + checkAll = tt.all + assert.Equal(t, tt.want, computePlaneIsTargeted(tt.mode)) + }) + } +} + +func TestControlPlaneIsTargeted(t *testing.T) { + t.Cleanup(func() { + checkPre = false + checkControlPlane = false + checkAll = false + }) + + tests := []struct { + name string + pre bool + cp bool + all bool + mode kubectx.Mode + want bool + }{ + {"--control-plane single", false, true, false, kubectx.ModeSingle, true}, + {"--control-plane split", false, true, false, kubectx.ModeSplit, true}, + {"--all single", false, false, true, kubectx.ModeSingle, true}, + {"--all split", false, false, true, kubectx.ModeSplit, true}, + {"--pre single -- implicit control plane", true, false, false, kubectx.ModeSingle, true}, + {"--pre split -- must not target control plane", true, false, false, kubectx.ModeSplit, false}, + {"--compute-plane only", false, false, false, kubectx.ModeSingle, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + checkPre = tt.pre + checkControlPlane = tt.cp + checkAll = tt.all + assert.Equal(t, tt.want, controlPlaneIsTargeted(tt.mode)) + }) + } +} + +// TestCheck_ComputePlaneFlagRunsChecks verifies that --compute-plane alone +// produces compute-plane-cluster category events. Before the gating fix this +// flag was a complete no-op and produced no check events at all. +func TestCheck_ComputePlaneFlagRunsChecks(t *testing.T) { + t.Cleanup(func() { + selfHostedJSON = false + selfHostedOutput = "text" + checkComputePlane = false + }) + + var stderr bytes.Buffer + rootCmd.SetErr(&stderr) + rootCmd.SetOut(&bytes.Buffer{}) + + t.Setenv("NVCF_CLI_SELFHOSTED_SKIP_INOTIFY", "1") + rootCmd.SetArgs([]string{"self-hosted", "check", "--compute-plane", "--skip-cluster-validation", "--json"}) + _ = rootCmd.Execute() + + lines := parseJSONLLines(t, stderr.String()) + require.NotEmpty(t, lines, "expected at least one JSONL line") + + var categories []string + for _, l := range lines[1:] { + if l["event"] == "category_completed" { + if cat, ok := l["category"].(string); ok { + categories = append(categories, cat) + } + } + } + assert.Contains(t, categories, "compute-plane-cluster", + "--compute-plane must produce compute-plane-cluster events") +} + +// TestCheck_ControlPlaneFlagRunsChecks verifies that --control-plane alone +// produces control-plane-cluster category events. +func TestCheck_ControlPlaneFlagRunsChecks(t *testing.T) { + t.Cleanup(func() { + selfHostedJSON = false + selfHostedOutput = "text" + checkControlPlane = false + }) + + var stderr bytes.Buffer + rootCmd.SetErr(&stderr) + rootCmd.SetOut(&bytes.Buffer{}) + + t.Setenv("NVCF_CLI_SELFHOSTED_SKIP_INOTIFY", "1") + rootCmd.SetArgs([]string{"self-hosted", "check", "--control-plane", "--skip-cluster-validation", "--json"}) + _ = rootCmd.Execute() + + lines := parseJSONLLines(t, stderr.String()) + require.NotEmpty(t, lines, "expected at least one JSONL line") + + var categories []string + for _, l := range lines[1:] { + if l["event"] == "category_completed" { + if cat, ok := l["category"].(string); ok { + categories = append(categories, cat) + } + } + } + assert.Contains(t, categories, "control-plane-cluster", + "--control-plane must produce control-plane-cluster events") +} + +// TestCheck_ValidatorSkipNoteAppearsOnComputePlane verifies that the +// "cluster-validator skipped" note appears on stderr when --compute-plane is +// used with --skip-cluster-validation (compute plane is targeted, validator is +// suppressed). +func TestCheck_ValidatorSkipNoteAppearsOnComputePlane(t *testing.T) { + t.Cleanup(func() { + selfHostedJSON = false + selfHostedOutput = "text" + checkComputePlane = false + checkSkipClusterValidation = false + }) + // --skip-cluster-validation does not gate the inotify prober, which lists + // every node and creates a privileged pod on each. Without this the test + // writes to whatever cluster is in the developer's current kubecontext. + t.Setenv("NVCF_CLI_SELFHOSTED_SKIP_INOTIFY", "1") + + var stderr bytes.Buffer + rootCmd.SetErr(&stderr) + rootCmd.SetOut(&bytes.Buffer{}) + + rootCmd.SetArgs([]string{ + "self-hosted", "check", "--compute-plane", + "--skip-cluster-validation", "--json", + }) + _ = rootCmd.Execute() + + assert.Contains(t, stderr.String(), "cluster-validator skipped", + "expected skip note when compute plane is targeted and --skip-cluster-validation is set") +} + +// --pre in ModeSplit visits both clusters, so when the validator is skipped the +// operator must be told why. This previously asserted silence, which is the +// "no validator row vs validator silently dropped" confusion the note exists +// to prevent. +func TestCheck_ValidatorSkipNotePresentForPreInSplitMode(t *testing.T) { + t.Cleanup(func() { + selfHostedJSON = false + selfHostedOutput = "text" + checkPre = false + checkSkipClusterValidation = false + selfHostedControlPlaneContext = "" + selfHostedComputePlaneContext = "" + }) + + var stderr bytes.Buffer + rootCmd.SetErr(&stderr) + rootCmd.SetOut(&bytes.Buffer{}) + + rootCmd.SetArgs([]string{ + "self-hosted", "check", "--pre", + "--skip-cluster-validation", "--json", + "--control-plane-context", "admin@cp", + "--compute-plane-context", "admin@gpu1", + }) + _ = rootCmd.Execute() + + assert.Contains(t, stderr.String(), "cluster-validator skipped", + "--pre in split mode visits both clusters, so an explicit skip must be explained") +} + func parseJSONLLines(t *testing.T, s string) []map[string]any { t.Helper() var out []map[string]any @@ -363,3 +561,175 @@ func parseJSONLLines(t *testing.T, s string) []map[string]any { } return out } + +// TestPlaneIsVisited covers the dispatch predicates, which are broader than +// the targeting predicates: --pre in ModeSplit visits both clusters for the +// shared pre-install checks without targeting either role. Gating the split +// dispatch on the targeting predicates alone would make --pre a no-op there. +// +// The mode column is kept to document that the answer is the same in both +// modes: the predicate is mode-independent by absorption, so a table that +// varied only the mode would be asserting a dependence that does not exist. +func TestPlaneIsVisited(t *testing.T) { + t.Cleanup(func() { + checkPre = false + checkControlPlane = false + checkComputePlane = false + checkAll = false + }) + + tests := []struct { + name string + pre, cp, gpu bool + all bool + mode kubectx.Mode + wantCP bool + wantComputeGP bool + }{ + {"--pre split visits both", true, false, false, false, kubectx.ModeSplit, true, true}, + {"--pre single visits both", true, false, false, false, kubectx.ModeSingle, true, true}, + {"--control-plane split skips compute", false, true, false, false, kubectx.ModeSplit, true, false}, + {"--compute-plane split skips control", false, false, true, false, kubectx.ModeSplit, false, true}, + {"--all split visits both", false, false, false, true, kubectx.ModeSplit, true, true}, + {"--control-plane single skips compute", false, true, false, false, kubectx.ModeSingle, true, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + checkPre, checkControlPlane, checkComputePlane, checkAll = tt.pre, tt.cp, tt.gpu, tt.all + assert.Equal(t, tt.wantCP, controlPlaneIsVisited()) + assert.Equal(t, tt.wantComputeGP, computePlaneIsVisited()) + }) + } +} + +// TestCheck_SplitModeControlPlaneOnlySkipsComputeCluster is the regression +// guard for the dispatch gating: in ModeSplit with only --control-plane, the +// compute cluster must not be contacted at all, so no compute-plane-cluster +// category is emitted. +func TestCheck_SplitModeControlPlaneOnlySkipsComputeCluster(t *testing.T) { + t.Cleanup(func() { + selfHostedJSON = false + selfHostedOutput = "text" + checkControlPlane = false + selfHostedControlPlaneContext = "" + selfHostedComputePlaneContext = "" + }) + + var stderr bytes.Buffer + rootCmd.SetErr(&stderr) + rootCmd.SetOut(&bytes.Buffer{}) + + t.Setenv("NVCF_CLI_SELFHOSTED_SKIP_INOTIFY", "1") + rootCmd.SetArgs([]string{"self-hosted", "check", "--control-plane", + "--control-plane-context", "cp-ctx", "--compute-plane-context", "gpu-ctx", + "--skip-cluster-validation", "--json"}) + _ = rootCmd.Execute() + + lines := parseJSONLLines(t, stderr.String()) + require.NotEmpty(t, lines, "expected at least one JSONL line") + + var categories []string + for _, l := range lines[1:] { + if l["event"] == "category_completed" { + if cat, ok := l["category"].(string); ok { + categories = append(categories, cat) + } + } + } + assert.Contains(t, categories, "control-plane-cluster") + assert.NotContains(t, categories, "compute-plane-cluster", + "--control-plane in split mode must not probe the compute cluster") +} + +// TestCheck_HostLocalChecksRunOnce guards against the host-local categories +// being emitted once per role. Local tool versions and registry credentials +// are checked on the operator's machine, so running them for both roles +// repeats the same check IDs in --json and double-counts them in the totals. +func TestCheck_HostLocalChecksRunOnce(t *testing.T) { + t.Cleanup(func() { + selfHostedJSON = false + selfHostedOutput = "text" + checkAll = false + }) + + var stderr bytes.Buffer + rootCmd.SetErr(&stderr) + rootCmd.SetOut(&bytes.Buffer{}) + + t.Setenv("NVCF_CLI_SELFHOSTED_SKIP_INOTIFY", "1") + rootCmd.SetArgs([]string{"self-hosted", "check", "--all", "--skip-cluster-validation", "--json"}) + _ = rootCmd.Execute() + + lines := parseJSONLLines(t, stderr.String()) + require.NotEmpty(t, lines, "expected at least one JSONL line") + + counts := map[string]int{} + for _, l := range lines { + if l["event"] != "check_completed" { + continue + } + if id, ok := l["id"].(string); ok && strings.HasPrefix(id, "local-host-tools-") { + counts[id]++ + } + } + require.NotEmpty(t, counts, "expected local-host-tools checks in the stream") + for id, n := range counts { + assert.Equal(t, 1, n, "check %s emitted %d times", id, n) + } +} + +// The JSON verdict and the exit code must derive from the same predicate. A +// warning-severity result previously emitted success:false / verdict:failed +// while the process exited 0, so a CI gate on final.success broke for every +// user whose registry credentials live in a Docker credential helper. +func TestEmitCheckFinal_WarningIsNotAFailure(t *testing.T) { + results := []selfhosted.CheckResult{ + {ID: "a", Passed: true, Severity: selfhosted.SeverityInfo}, + {ID: "b", Passed: false, Severity: selfhosted.SeverityWarning}, + } + assert.False(t, anyFailed(results), "a warning must not set the exit code") + + var buf bytes.Buffer + sink := progress.NewJSONLRenderer(&buf) + emitCheckFinal(context.Background(), sink, results) + + line := buf.String() + assert.Contains(t, line, `"verdict":"warnings"`) + assert.Contains(t, line, `"success":true`, + "success must agree with the exit code") + assert.Contains(t, line, `"failedCount":0`) +} + +func TestEmitCheckFinal_ErrorIsAFailure(t *testing.T) { + results := []selfhosted.CheckResult{ + {ID: "a", Passed: true, Severity: selfhosted.SeverityInfo}, + {ID: "b", Passed: false, Severity: selfhosted.SeverityError}, + } + assert.True(t, anyFailed(results)) + + var buf bytes.Buffer + sink := progress.NewJSONLRenderer(&buf) + emitCheckFinal(context.Background(), sink, results) + assert.Contains(t, buf.String(), `"verdict":"failed"`) + assert.Contains(t, buf.String(), `"success":false`) +} + +// Both roles emit a cluster-validator result under the same ID, so stopping at +// the first drops the other transcript entirely from --all --show-logs. +func TestMaybeShowClusterValidatorLogs_PrintsBothRoles(t *testing.T) { + prev := checkShowLogs + checkShowLogs = true + t.Cleanup(func() { checkShowLogs = prev }) + + var buf bytes.Buffer + maybeShowClusterValidatorLogs(&buf, []selfhosted.CheckResult{ + {ID: "cluster-validator", Logs: "control-plane transcript\n"}, + {ID: "cluster-validator", Logs: "compute-plane transcript\n"}, + }) + + out := buf.String() + assert.Contains(t, out, "control-plane transcript") + assert.Contains(t, out, "compute-plane transcript") + assert.Equal(t, 2, strings.Count(out, "--- cluster-validator logs ---")) +} diff --git a/src/clis/nvcf-cli/cmd/self_hosted_up.go b/src/clis/nvcf-cli/cmd/self_hosted_up.go index d9b3f9f9e4..681da61272 100644 --- a/src/clis/nvcf-cli/cmd/self_hosted_up.go +++ b/src/clis/nvcf-cli/cmd/self_hosted_up.go @@ -1507,6 +1507,17 @@ func kubectxFor(phaseNum int) string { } } +type registerValuesWriteRequest struct { + StackPath string + ClusterName string + NCAID string + Region string + IdentitySource string + ClusterID string + ClusterGroupID string + Endpoints registerEndpointValues +} + // writeRegisterValuesYAML persists the helm values handoff file the worker-layer // helmfile expects at /out/-register-values.yaml. Schema mirrors // `printRegistrationOutput` (cmd/cluster_registration.go, fixed in `ff9aaf7`): @@ -1519,17 +1530,6 @@ func kubectxFor(phaseNum int) string { // The pre-`ff9aaf7` shape (nested `selfManaged.clusterId`, lowercase-d) left // the chart's `.Values.clusterID` empty → cluster-dto.yaml rendered with empty // IDs → operator failed to fetch backend identity. (Iter #12 from dev-VM E2E.) -type registerValuesWriteRequest struct { - StackPath string - ClusterName string - NCAID string - Region string - IdentitySource string - ClusterID string - ClusterGroupID string - Endpoints registerEndpointValues -} - func writeRegisterValuesYAML(req registerValuesWriteRequest) error { outDir := filepath.Join(req.StackPath, "out") if err := os.MkdirAll(outDir, 0o755); err != nil { diff --git a/src/clis/nvcf-cli/go.mod b/src/clis/nvcf-cli/go.mod index 9a4c8d3d83..19cc5ea3ba 100644 --- a/src/clis/nvcf-cli/go.mod +++ b/src/clis/nvcf-cli/go.mod @@ -11,6 +11,7 @@ require ( github.com/charmbracelet/lipgloss v1.0.0 github.com/muesli/termenv v0.15.2 github.com/spf13/cobra v1.9.1 + github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.10.0 golang.org/x/oauth2 v0.27.0 @@ -23,6 +24,7 @@ require ( k8s.io/apiextensions-apiserver v0.34.1 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 + sigs.k8s.io/yaml v1.6.0 ) require ( @@ -68,7 +70,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.6 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -89,5 +90,4 @@ require ( sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect - sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/src/clis/nvcf-cli/internal/agentskill/skilldata_generated.go b/src/clis/nvcf-cli/internal/agentskill/skilldata_generated.go index 2e403af1a1..fb4c37f925 100644 --- a/src/clis/nvcf-cli/internal/agentskill/skilldata_generated.go +++ b/src/clis/nvcf-cli/internal/agentskill/skilldata_generated.go @@ -31,14 +31,14 @@ import ( const skillDataZipBase64 = "" + "UEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAASAAkAZGF0YS9tYW5pZmVzdC5qc29uVVQFAAEAps4S" + "ewogICJzY2hlbWFWZXJzaW9uIjogMSwKICAiZ2VuZXJhdGVkQXQiOiAiMTk3MC0wMS0wMVQwMDow" + - "MDowMFoiLAogICJ0b3RhbEZpbGVzIjogMjIsCiAgInRvdGFsQnl0ZXMiOiAyMDAzNjgsCiAgImZp" + + "MDowMFoiLAogICJ0b3RhbEZpbGVzIjogMjIsCiAgInRvdGFsQnl0ZXMiOiAyMDMyNDAsCiAgImZp" + "bGVzIjogWwogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvU0tJTEwu" + - "bWQiLAogICAgICAic2hhMjU2IjogImM0ZjI4OGY2MmU1MDg4NjI5ZGY1MTcyYTlhYjMwZWVlOGMz" + - "OTRmYzgzOTFjMjMwMDMzNzI2NGVmZjRiMmU3ZWYiLAogICAgICAic2l6ZSI6IDI0OTA5CiAgICB9" + + "bWQiLAogICAgICAic2hhMjU2IjogImFhOWY3ZTI0NmYzODA0YjMzNDNiNjU2MWU1YmNmZTdiYjcy" + + "YjI0MDIxOTMzZTA0OWY4NWUwMDI4OTAzYmJmYTQiLAogICAgICAic2l6ZSI6IDI0OTE1CiAgICB9" + "LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvZXhhbXBsZXMvY2kt" + - "cGlwZWxpbmVzLm1kIiwKICAgICAgInNoYTI1NiI6ICI2Yjg2NGE3OWFjMTgxYTAyNTQ3NWJmNTA2" + - "YjM0NmIyOWQ1NDNlOGFhZmVmMWJjNDk2Y2E2NzA5ZjQ3M2FhZWU5IiwKICAgICAgInNpemUiOiAy" + - "ODAwCiAgICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvZXhh" + + "cGlwZWxpbmVzLm1kIiwKICAgICAgInNoYTI1NiI6ICJkMzM5M2VmOTVhZWRiYWE1NzBiY2JiZjQ3" + + "MzVkM2ZhYjI1MzY0MDdlM2U1NjdlZmMzNzhhOWVkM2JiYTJmMWNjIiwKICAgICAgInNpemUiOiAz" + + "MzI0CiAgICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvZXhh" + "bXBsZXMvbXVsdGktY2x1c3Rlci5tZCIsCiAgICAgICJzaGEyNTYiOiAiNmRmMjg0NjBiNTgzNDNl" + "MjEwMjVhYTViZDc5ZjMzYjUxMmRjYTlmZjM5YjZhYjI2MDRmYzNmZWJiMDE1ODhiNCIsCiAgICAg" + "ICJzaXplIjogMzE2NQogICAgfSwKICAgIHsKICAgICAgInBhdGgiOiAibnZjZi1zZWxmLW1hbmFn" + @@ -46,24 +46,24 @@ const skillDataZipBase64 = "" + "NGI5ZDI4MzA2MTk2MzBiM2FmOWZlOTc0MDQ3OGU0YWQ1ZTBiNGVhYjMwNGI2Y2FmZjQyYjExNDFi" + "ODJjNmYiLAogICAgICAic2l6ZSI6IDMzMzMKICAgIH0sCiAgICB7CiAgICAgICJwYXRoIjogIm52" + "Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL2NyZWF0ZS1hbmQtcnVuLXRhc2subWQiLAogICAg" + - "ICAic2hhMjU2IjogImNmYzQ4OGVlODhmM2I4YmY1YWMzOWE5MGU5ZjdlNzBlYmRhODM0OWM0YTQw" + - "ZTQyNDJmNWQ2ZTI3MDJkZDAxM2QiLAogICAgICAic2l6ZSI6IDY1NTIKICAgIH0sCiAgICB7CiAg" + + "ICAic2hhMjU2IjogIjcxMWMzMGFiODg5ZTNlYjI4MWQxZmRjODUxMDI3ZWIzMzkzYzdiODRmYzc0" + + "NTUwNDkwZDU1OTNjNDE5NTYzOTkiLAogICAgICAic2l6ZSI6IDY1NTkKICAgIH0sCiAgICB7CiAg" + "ICAgICJwYXRoIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL2RlcGxveS1hbmQtaW52" + "b2tlLm1kIiwKICAgICAgInNoYTI1NiI6ICIyNWY0NTU1ZTFiNmZkYzExZGYyYzI4NWJhMDY1MjA2" + "NzZiYzVjOWU2ZTQ4NzczNWRiZDllOGFiNGQ1ZmUzZjgzIiwKICAgICAgInNpemUiOiA5NDk2CiAg" + "ICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy9k" + - "aWFnbm9zZS1mYWlsZWQtaW5zdGFsbC5tZCIsCiAgICAgICJzaGEyNTYiOiAiMjY1NjJkMGUwMjU3" + - "NTU5NWY1ZjNmZTA2YTU5ZjQ2M2U0NGUyMGFkNjg2YjRlYzQ2Mjk2MjI1ODRjZTRmMDQ3NSIsCiAg" + - "ICAgICJzaXplIjogMzc3MwogICAgfSwKICAgIHsKICAgICAgInBhdGgiOiAibnZjZi1zZWxmLW1h" + + "aWFnbm9zZS1mYWlsZWQtaW5zdGFsbC5tZCIsCiAgICAgICJzaGEyNTYiOiAiNDA4ZDNjMjM3ZWE2" + + "NzRmMWM5MGE1ZjI2NTUwNWM0MWJkMjQ5ZGQ2Y2MzOGZkOTE4NGY2Njk3ZDhmMDBjNTY1YSIsCiAg" + + "ICAgICJzaXplIjogMzc3NAogICAgfSwKICAgIHsKICAgICAgInBhdGgiOiAibnZjZi1zZWxmLW1h" + "bmFnZWQtY2xpL3Byb21wdHMvaW5zdGFsbC1mcm9tLXNjcmF0Y2gubWQiLAogICAgICAic2hhMjU2" + "IjogIjgzMTA5NmY5MmZjMjU2NWQ0NDg1YmExZDBmNWM1MGZiYTljNjQyNTIxZmRhOTZhNzllZDUy" + "MmU0ZmU3NWEzYmQiLAogICAgICAic2l6ZSI6IDEwMjQxCiAgICB9LAogICAgewogICAgICAicGF0" + "aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy9yb3RhdGUtY2x1c3Rlci1qd2tzLm1k" + - "IiwKICAgICAgInNoYTI1NiI6ICI2ZmFlNTU2MmRjNWU5N2MyNGE5MzYwNWI2NzRhMGFmYzdlYzRh" + - "M2QwYmVjM2NlYmY5ZjY0ZThiZTZmMjY3OGE1IiwKICAgICAgInNpemUiOiAxOTkxCiAgICB9LAog" + + "IiwKICAgICAgInNoYTI1NiI6ICI3NDdiNmM3OTJkYzI0NmE3OWE1MTA4YTk0NWQ5YWIyNzc1MTE3" + + "MjA3ZGExODlmYjE0Mjg0MzQ1NzRhYTYxZTFmIiwKICAgICAgInNpemUiOiAxOTkyCiAgICB9LAog" + "ICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy90ZWFyZG93" + - "bi5tZCIsCiAgICAgICJzaGEyNTYiOiAiYmI0MGY4MTM3N2M0Y2UzYWRkOGVhNDFmNzMzMmM1OWZh" + - "ZDA3YmY4YTIwZGQzMDJjZDJiZjgzOGRmYzY0NWQwZiIsCiAgICAgICJzaXplIjogODY3MgogICAg" + + "bi5tZCIsCiAgICAgICJzaGEyNTYiOiAiMWE2NmI5YTM3MmJmOTI3NjQzOTdjOWVmMzliNzNlNDZm" + + "NzE2M2ExNTgyMzgzZjFkNGJiNDE4ZThjM2Q2M2QwMyIsCiAgICAgICJzaXplIjogODY3NgogICAg" + "fSwKICAgIHsKICAgICAgInBhdGgiOiAibnZjZi1zZWxmLW1hbmFnZWQtY2xpL3JlZmVyZW5jZS9j" + "b21tYW5kcy5tZCIsCiAgICAgICJzaGEyNTYiOiAiMmI0YjAzNmU3NTA3MDZiOWUzYjgxZmNkNjAy" + "YzcwNmY3NGY3N2Y2MjQwZmI3YWFkNjIwYzg3OWZmNzQ5NmNkOCIsCiAgICAgICJzaXplIjogODk5" + @@ -71,3640 +71,3691 @@ const skillDataZipBase64 = "" + "ZW5jZS9leGl0LWNvZGVzLm1kIiwKICAgICAgInNoYTI1NiI6ICI2NGI1ZmE5YmNhZjBlMGE1M2Y3" + "ODkyMGI3M2ZjYjUzMGFiNjk0NTFiNDhhNWI0OTNmMjUyY2ExODU4M2FiMDg2IiwKICAgICAgInNp" + "emUiOiAxNzQ5CiAgICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1j" + - "bGkvcmVmZXJlbmNlL2ZsYWdzLm1kIiwKICAgICAgInNoYTI1NiI6ICJkNGQ5ODg2N2M1OGE1MjJk" + - "OWJhNmJjMjc0M2ZkZDhmYzBmMDQ3ZDVmNDUxZWRlMmU5YWNlMGI4NzI2NGM2MzczIiwKICAgICAg" + - "InNpemUiOiA5NTE3CiAgICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdl" + - "ZC1jbGkvcmVmZXJlbmNlL3Ryb3VibGVzaG9vdGluZy5tZCIsCiAgICAgICJzaGEyNTYiOiAiYTYz" + - "MDg0ZTIyNDlmMWQxNTRjNTk4MWU0YTA3MmI3Yzc4NGI4NWVhMTQ2MDg2NTE1ZWFiNGFiNjcwYTk0" + - "MGU5NCIsCiAgICAgICJzaXplIjogNDQ2OAogICAgfSwKICAgIHsKICAgICAgInBhdGgiOiAibnZj" + - "Zi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL1NLSUxMLm1kIiwKICAgICAgInNoYTI1NiI6ICJj" + - "MzNmZDgzMDVlYzNmZDAyMGViNGM5ODJjM2FmZTc2YTdjMWQ0M2MzZTA1NGM4ZmJkMzhjNGJiMWI3" + - "MDdjNzVhIiwKICAgICAgInNpemUiOiAyNTE1NAogICAgfSwKICAgIHsKICAgICAgInBhdGgiOiAi" + - "bnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL2V2YWxzL2V2YWxzLmpzb24iLAogICAgICAi" + - "c2hhMjU2IjogIjYxMDA3N2I2OWI0NGU1OTUzNzc2NzdjNDM5NDcyMDE1ODUzMWIxNzFhYTk2ZDZk" + - "Y2M3YTY1ZTFkZmQzMDliODkiLAogICAgICAic2l6ZSI6IDIyMDkwCiAgICB9LAogICAgewogICAg" + - "ICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vZXhhbXBsZXMubWQiLAog" + - "ICAgICAic2hhMjU2IjogIjlhMzllNWNjYWJkNDA4MTljNzFmMmIwZjJkNzUyMzE2YjcyMzE1NjU0" + - "ZDgwZDNkMDE3Njk4Y2UxZmIzZTViMTEiLAogICAgICAic2l6ZSI6IDEwMzY3CiAgICB9LAogICAg" + - "ewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNl" + - "cy9jb21wdXRlLXBsYW5lLWluc3RhbGxhdGlvbi5tZCIsCiAgICAgICJzaGEyNTYiOiAiNWRlZTU4" + - "YWUyYzY3YTYyOTQ2ZTNjNTkzMDJhZmFjYzQwYmRlNzFmOGRjMmYyNWNkNzc5OWNjNDViNDc0ZmEx" + - "OSIsCiAgICAgICJzaXplIjogMTIzMDYKICAgIH0sCiAgICB7CiAgICAgICJwYXRoIjogIm52Y2Yt" + - "c2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL2RlYnVnZ2luZy5tZCIsCiAgICAg" + - "ICJzaGEyNTYiOiAiYTUyODE1OGJjMGJmZmZlZWY2ZTAxZGUzODRjYWY1NjVlNjQ0NWI0OGFiZDNj" + - "ZWU0MDA0ODcxZjUyM2Y1M2I5NyIsCiAgICAgICJzaXplIjogMTI0MzcKICAgIH0sCiAgICB7CiAg" + - "ICAgICJwYXRoIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL2hl" + - "bG1maWxlLXN0cnVjdHVyZS5tZCIsCiAgICAgICJzaGEyNTYiOiAiNjEyMDk2M2Y0NDcyNzQ2MDQ5" + - "NWU5ZmMwZGE1MmFlN2YzYzY5YTM4ZTU3ZWZlNzI2MmM3NTAxNjQxZWRhNWY4MiIsCiAgICAgICJz" + - "aXplIjogMTA3NDYKICAgIH0sCiAgICB7CiAgICAgICJwYXRoIjogIm52Y2Ytc2VsZi1tYW5hZ2Vk" + - "LWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL252Y2YtdWktYWRkb24ubWQiLAogICAgICAic2hhMjU2" + - "IjogIjUwNTI0ZTZlMTk3MTE4M2JkYzlhZDBhYzM4YTgwN2RmNzJjYzA4NTFiNzlmNTE4ZmUxMWE0" + - "OGU0NTk3Yzg1MGUiLAogICAgICAic2l6ZSI6IDE5NzcKICAgIH0sCiAgICB7CiAgICAgICJwYXRo" + - "IjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL3B1bGwtc2VjcmV0" + - "cy5tZCIsCiAgICAgICJzaGEyNTYiOiAiZWMxZjNmZmNkMTdlNWY5NTgzZmVlMzk3NDRlZTg5N2Q0" + - "NjZiYzNjZjYzODkyOTQyNjRkODllN2Y5ZWQwMWI4NyIsCiAgICAgICJzaXplIjogNTYzMgogICAg" + - "fQogIF0KfQpQSwcIpc8HuUkQAABJEAAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAAjAAkAZGF0" + - "YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvU0tJTEwubWRVVAUAAQCmzhItLS0KbmFtZTogbnZjZi1z" + - "ZWxmLW1hbmFnZWQtY2xpCmRlc2NyaXB0aW9uOiB8CiAgSW5zdGFsbCwgb3BlcmF0ZSwgYW5kIHRl" + - "YXIgZG93biBzZWxmLWhvc3RlZCBOVklESUEgQ2xvdWQgRnVuY3Rpb25zIChOVkNGKQogIGRlcGxv" + - "eW1lbnRzIHdpdGggbnZjZi1jbGkuIFVzZSBmb3IgY29udHJvbC1wbGFuZSBvciBjb21wdXRlLXBs" + - "YW5lIGluc3RhbGwsCiAgc3RhdHVzIGNoZWNrcywgY2x1c3RlciByZWdpc3RyYXRpb24sIGZ1bmN0" + - "aW9uIGRlcGxveS9pbnZva2UsIHRhc2sKICBjcmVhdGUvbGlzdC9jYW5jZWwvZGVsZXRlLCBBUEkg" + - "a2V5cywgYWRtaW4gdG9rZW5zLCBKV0tTIHJvdGF0aW9uLAogIGZhaWxlZC1pbnN0YWxsIGRpYWdu" + - "b3NpcywgYW5kIHVuaW5zdGFsbCBvciBkb3duIHdvcmtmbG93cy4gVHJpZ2dlciBrZXl3b3JkczoK" + - "ICBudmNmLCBudmNmLWNsaSwgc2VsZi1ob3N0ZWQgbnZjZiwgc2VsZi1tYW5hZ2VkIG52Y2YsIE5W" + - "Q0ZCYWNrZW5kLCBOVkNBLCBOQ1AsCiAgSUNNUywgaGVsbWZpbGUsIGNvbnRyb2wgcGxhbmUsIGNv" + - "bXB1dGUgcGxhbmUsIExMTSBmdW5jdGlvbiwKICBPcGVuQUktY29tcGF0aWJsZSBpbnZvY2F0aW9u" + - "LCBSZXNwb25zZXMgQVBJLCBlbWJlZGRpbmdzLCBiYXRjaCB0YXNrLCB0YXNrCiAgbW9uaXRvciwg" + - "Y2x1c3RlciByb3RhdGUsIGNsdXN0ZXIgZGVsZXRlLCBoZWxtIHRhc2ssIGhlbG0tYmFzZWQgdGFz" + - "aywKICB0YXNrIHNlY3JldHMsIHVwZGF0ZSB0YXNrIHNlY3JldHMsIHJldHJpZXZlIHRhc2sgcmVz" + - "dWx0cywgYnVsayBmZXRjaCB0YXNrcywKICB0YXNrIHJlc3VsdHMsIE5WQ1QsIE5WQ1QgdGFzaywg" + - "TlZDVCBiYXRjaCBqb2IuCmFsbG93ZWQtdG9vbHM6IEJhc2gsIFJlYWQsIEFza1VzZXJRdWVzdGlv" + - "bgphcmd1bWVudC1oaW50OiAiW2luc3RhbGx8c3RhdHVzfGNoZWNrfGRlcGxveS1mdW5jdGlvbnxy" + - "ZWdpc3Rlci1jbHVzdGVyfHRlYXJkb3duXSBbYXJnc10iCi0tLQo8IS0tClRva2VuIEJ1ZGdldDoK" + - "LSBMZXZlbCAxIChZQU1MKTogfjEyMCB0b2tlbnMKLSBMZXZlbCAyICh0aGlzIGZpbGUpOiB+MTkw" + - "MCB0b2tlbnMgKHRhcmdldCA8MjAwMCkKLSBMZXZlbCAzIChwcm9tcHRzLywgcmVmZXJlbmNlLywg" + - "ZXhhbXBsZXMvKTogbG9hZGVkIG9uIGRlbWFuZAotLT4KCiMgTlZDRiBTZWxmLUhvc3RlZCBDTEkK" + - "CmBudmNmLWNsaWAgZHJpdmVzIGV2ZXJ5IHN0ZXAgb2YgYnJpbmdpbmcgdXAgc2VsZi1ob3N0ZWQg" + - "TlZJRElBIENsb3VkIEZ1bmN0aW9uczogY2x1c3RlciByZWdpc3RyYXRpb24sIGNvbnRyb2wtcGxh" + - "bmUgaW5zdGFsbCwgY29tcHV0ZS1wbGFuZSBpbnN0YWxsLCBmdW5jdGlvbiBkZXBsb3kvaW52b2tl" + - "LCBhbmQgbGlmZWN5Y2xlIG1hbmFnZW1lbnQuIFVzZSB0aGlzIHNraWxsIGFueSB0aW1lIHRoZSB1" + - "c2VyIHdhbnRzIHRvIG9wZXJhdGUgc2VsZi1ob3N0ZWQgTlZDRi4KCiMjIFdoZW4gdG8gdXNlCgot" + - "ICJpbnN0YWxsIHNlbGYtaG9zdGVkIE5WQ0YiIC8gImJyaW5nIHVwIGFuIE5WQ0YgY2x1c3RlciIK" + - "LSAicmVnaXN0ZXIgYSAoY29tcHV0ZXxHUFUpIGNsdXN0ZXIgd2l0aCBOVkNGIgotICJkZXBsb3kg" + - "YSAoY29udGFpbmVyfEdQVSkgZnVuY3Rpb24iIC8gImludm9rZSBhbiBOVkNGIGZ1bmN0aW9uIgot" + - "ICJjaGVjayBOVkNGIGNsdXN0ZXIgaGVhbHRoIiAvICJpcyBteSBOVkNGIGluc3RhbGwgT0s/Igot" + - "ICJyb3RhdGUgTlZDRiBjbHVzdGVyIEpXS1MiIC8gInRoZSBOVkNBIGFnZW50IHN0b3BwZWQgYXV0" + - "aGVudGljYXRpbmciCi0gInRlYXIgZG93biBOVkNGIiAvICJyZW1vdmUgdGhlIGNvbXB1dGUgcGxh" + - "bmUiIC8gInVuaW5zdGFsbCBOVkNGIiAvICJkZXJlZ2lzdGVyIHRoaXMgY2x1c3RlciIKLSAicHJl" + - "dmlldyB3aGF0IGBkb3duYCB3b3VsZCBkbyIgLyAiZHJ5LXJ1biB1bmluc3RhbGwiCi0gQW55IHRh" + - "c2sgb3BlcmF0aW9uOiBjcmVhdGUgLyBydW4gLyBzdWJtaXQgLyBtb25pdG9yIC8gY2FuY2VsIC8g" + - "ZGVsZXRlIC8gbGlzdCB0YXNrcywgaGVsbSB0YXNrLCB1cGRhdGUgdGFzayBzZWNyZXRzLCByZXRy" + - "aWV2ZSB0YXNrIHJlc3VsdHMsIGJ1bGsgZmV0Y2ggdGFzayBkZXRhaWxzLgotIEFueSByZWZlcmVu" + - "Y2UgdG8gYE5WQ1RgLCBgTlZDVCB0YXNrYCwgb3IgYE5WQ1QgYmF0Y2ggam9iYCAobGlzdCAvIHJ1" + - "biAvIGNhbmNlbCAvIGRlbGV0ZSAvIHJlc3VsdHMpLgotIEFueSByZWZlcmVuY2UgdG8gYE5WQ0ZC" + - "YWNrZW5kYCwgYE5WQ0FgLCBJQ01TLCBoZWxtIHJlbGVhc2VzIGxpa2UgYGhlbG0tbnZjZi0qYCwg" + - "b3IgYGljbXMuPGRvbWFpbj5gIC8gYGFwaS48ZG9tYWluPmAgVVJMcy4KCiMjIFF1aWNrIHN0YXJ0" + - "CgpGb3IgcmVtb3RlIG9uZS1jbGljayBpbnN0YWxscywgcHJlcGFyZSBHYXRld2F5IEFQSSBpbmdy" + - "ZXNzIGFuZCBDTEkgZW5kcG9pbnQKY29uZmlndXJhdGlvbiBiZWZvcmUgcnVubmluZyBgc2VsZi1o" + - "b3N0ZWQgdXBgLiBUaGUgY29tbWFuZCBhcHBsaWVzIHRoZSBjb250cm9sCnBsYW5lIGFuZCB0aGVu" + - "IGltbWVkaWF0ZWx5IGNhbGxzIEFQSSwgQVBJIEtleXMsIGludm9jYXRpb24sIGFuZCBnUlBDIGVu" + - "ZHBvaW50cy4KSWYgdGhlIEdhdGV3YXkgaXMgbm90IHByb2dyYW1tZWQgb3IgdGhlIENMSSBob3N0" + - "IGhlYWRlcnMgZG8gbm90IG1hdGNoIHRoZQpIVFRQUm91dGVzIHJlbmRlcmVkIGJ5IHRoZSBzdGFj" + - "ayBlbnZpcm9ubWVudCwgcG9zdC1pbnN0YWxsIGhlYWx0aCBhbmQgY2x1c3RlcgpyZWdpc3RyYXRp" + - "b24gd2lsbCBmYWlsLgoKYGBgc2gKIyBTaW5nbGUtY2x1c3RlciAoY29udHJvbCArIGNvbXB1dGUg" + - "b24gdGhlIGN1cnJlbnQga3ViZWNvbmZpZyBjb250ZXh0KToKbnZjZi1jbGkgc2VsZi1ob3N0ZWQg" + - "dXAgLS1jbHVzdGVyLW5hbWU9bmNwLWxvY2FsCgojIFNwbGl0LWNsdXN0ZXIgKGNvbnRyb2wgcGxh" + - "bmUgb24gY29udGV4dCBBLCBjb21wdXRlIHBsYW5lIG9uIGNvbnRleHQgQik6CktVQkVDT05GSUc9" + - "Y3AueWFtbDpncHUxLnlhbWwgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgdXAgXAogIC0tY2x1c3Rlci1u" + - "YW1lPW5jcC1sb2NhbCBcCiAgLS1jb250cm9sLXBsYW5lLWNvbnRleHQ9YWRtaW5AY3AgXAogIC0t" + - "Y29tcHV0ZS1wbGFuZS1jb250ZXh0PWFkbWluQGdwdTEgXAogIC0taWNtcy11cmw9aHR0cHM6Ly9p" + - "Y21zLm52Y2YuZXhhbXBsZS5jb20KCiMgQWRkIGEgbmV3IGNvbXB1dGUgcGxhbmUgdG8gYW4gZXhp" + - "c3RpbmcgY29udHJvbCBwbGFuZSAobm8ga3ViZWN0bCBhY2Nlc3MgdG8gQ1AgbmVlZGVkOwojIHJl" + - "YWNoZXMgdGhlIGNvbnRyb2wgcGxhbmUgdmlhIHRoZSBwdWJsaWMgSUNNUyBIVFRQUm91dGUpOgpu" + - "dmNmLWNsaSBzZWxmLWhvc3RlZCBhZGQtY29tcHV0ZS1wbGFuZSBcCiAgLS1jbHVzdGVyLW5hbWU9" + - "bmNwLWxvY2FsLTIgXAogIC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0PWFkbWluQGdwdTIgXAogIC0t" + - "aWNtcy11cmw9aHR0cHM6Ly9pY21zLm52Y2YuZXhhbXBsZS5jb20gXAogIC0tdG9rZW49JEFETUlO" + - "X0pXVAoKIyBUZWFyIGRvd24gKGFsd2F5cyBwbGFuLW9ubHkgZmlyc3QpOgpudmNmLWNsaSBzZWxm" + - "LWhvc3RlZCBkb3duIC0tcGxhbi1vbmx5IC0tY2x1c3Rlci1uYW1lPW5jcC1sb2NhbCAtLWpzb24g" + - "fCBqcQpudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tY2x1c3Rlci1uYW1lPW5jcC1sb2NhbAoK" + - "IyBQZXItcGxhbmUgdW5pbnN0YWxsIChHaXRPcHM7IG1pcnJvcnMgYGluc3RhbGxgKToKbnZjZi1j" + - "bGkgc2VsZi1ob3N0ZWQgdW5pbnN0YWxsIC0tbm8tYXBwbHkgLS1jb21wdXRlLXBsYW5lIC0tY2x1" + - "c3Rlci1uYW1lPW5jcC1sb2NhbCB8IGt1YmVjdGwgZGVsZXRlIC1mIC0KYGBgCgo+ICoqYHVwYCB2" + - "cyBgYWRkLWNvbXB1dGUtcGxhbmVgLioqIGB1cGAgYWx3YXlzIGluc3RhbGxzIGJvdGggcGxhbmVz" + - "IOKAlCB1c2UgaXQgZm9yIHRoZSAqZmlyc3QqIGluc3RhbGwuIGBhZGQtY29tcHV0ZS1wbGFuZWAg" + - "aXMgdGhlIHJpZ2h0IHN1YmNvbW1hbmQgYW55IHRpbWUgdGhlIGNvbnRyb2wgcGxhbmUgaXMgYWxy" + - "ZWFkeSBydW5uaW5nIGFuZCB5b3Ugd2FudCB0byBhdHRhY2ggYW4gTnRoIGNvbXB1dGUgY2x1c3Rl" + - "ci4KCj4gKipgZG93bmAgYWx3YXlzIHdpdGggYC0tcGxhbi1vbmx5YCBmaXJzdC4qKiBTaG93IHRo" + - "ZSB1c2VyIHRoZSBgd2lsbFVuaW5zdGFsbC5jb21tYW5kc1tdYCBhcnJheSBiZWZvcmUgcnVubmlu" + - "ZyBmb3IgcmVhbC4KCiMjIEF1dGhlbnRpY2F0aW9uCgpgbnZjZi1jbGlgIHVzZXMgdHdvIGNyZWRl" + - "bnRpYWxzLiBFYWNoIGlzIHJlc29sdmVkIGluZGVwZW5kZW50bHkgaW4gdGhpcyBvcmRlcjoKCnwg" + - "UHJlY2VkZW5jZSB8IFNvdXJjZSB8CnwtLS18LS0tfAp8IDEgKGhpZ2hlc3QpIHwgRW52aXJvbm1l" + - "bnQgdmFyaWFibGUgKGBOVkNGX1RPS0VOYCwgYE5WQ0ZfQVBJX0tFWWApIHwKfCAyIHwgQ29uZmln" + - "IGZpbGUgKGB+Ly5udmNmLWNsaS55YW1sYCwga2V5cyBgdG9rZW5gIGFuZCBgYXBpX2tleWApIHwK" + - "fCAzIHwgU3RhdGUgZmlsZSAoYH4vLm52Y2YtY2xpLnN0YXRlYCksIHNraXBwZWQgd2hlbiB0aGUg" + - "c3RvcmVkIHRva2VuIGlzIGV4cGlyZWQgfAoKfCBFbnYgdmFyIHwgVG9rZW4gdHlwZSB8IFVzZWQg" + - "YnkgfAp8LS0tfC0tLXwtLS18CnwgYE5WQ0ZfVE9LRU5gIHwgQWRtaW4gSldUIHwgYGZ1bmN0aW9u" + - "IGNyZWF0ZWAgLyBgZGVwbG95YCAvIGB1cGRhdGVgIC8gYGRlbGV0ZWAsIGNsdXN0ZXIgbWFuYWdl" + - "bWVudCAoYGNsdXN0ZXIgcmVnaXN0ZXJgL2BsaXN0LXJlZ2lzdGVyZWRgL2Byb3RhdGVgL2BkZWxl" + - "dGVgLCBgc2VsZi1ob3N0ZWRgIG9wcykuIFJlcXVpcmVkIGZvciBhZG1pbiBjb21tYW5kczsgcHJl" + - "ZmVycmVkIGZvciB0aGUgcmVzdC4gfAp8IGBOVkNGX0FQSV9LRVlgIHwgYG52YXBpLS4uLmAgQVBJ" + - "IGtleSB8IGBmdW5jdGlvbiBpbnZva2VgIC8gYGxpc3RgIC8gYGdldGAsIHF1ZXVlIGRldGFpbHMu" + - "IEZhbGxzIGJhY2sgdG8gYE5WQ0ZfVE9LRU5gIHdoZW4gdW5zZXQuIHwKClRva2VuIGdlbmVyYXRp" + - "b24gZmxvdzoKCjEuIFBvaW50IHRoZSBDTEkgYXQgeW91ciBzZWxmLWhvc3RlZCBlbmRwb2ludHMu" + - "IERlZmF1bHRzIHRhcmdldCBwcm9kdWN0aW9uIE5WQ0Y7IG92ZXJyaWRlIHdpdGggZW52IHZhcnMg" + - "b3IgYSB5YW1sIGZpbGUgKGAtLWNvbmZpZyA8cGF0aD5gLCBgLi8ubnZjZi1jbGkueWFtbGAsIG9y" + - "IGB+Ly5udmNmLWNsaS55YW1sYDsgYSBmdWxsIHRlbXBsYXRlIHNoaXBzIGF0IGBzcmMvY2xpcy9u" + - "dmNmLWNsaS8ubnZjZi1jbGkueWFtbC50ZW1wbGF0ZWApLgoKICAgYE5WQ0ZfQkFTRV9IVFRQX1VS" + - "TGAgLyBgQVBJX0tFWVNfU0VSVklDRV9VUkxgIC8gYE5WQ0ZfQkFTRV9HUlBDX1VSTGAgdGVsbCB0" + - "aGUgQ0xJICp3aGVyZSB0byBzZW5kIHJlcXVlc3RzKi4gYEFQSV9IT1NUYCAvIGBBUElfS0VZU19I" + - "T1NUYCAvIGBJTlZPS0VfSE9TVGAgc2V0IHRoZSBgSG9zdDpgIGhlYWRlciBvbiB0aG9zZSByZXF1" + - "ZXN0cyDigJQgbmVlZGVkIHdoZW4gZXZlcnkgTlZDRiBzZXJ2aWNlIHNpdHMgYmVoaW5kIGEgc2lu" + - "Z2xlIGdhdGV3YXkgdGhhdCByb3V0ZXMgYnkgaG9zdG5hbWUgKEVudm95IEdhdGV3YXkgSFRUUFJv" + - "dXRlIG9uIGBhcGkuPEVMQj5gLCBgYXBpLWtleXMuPEVMQj5gLCBgaW52b2NhdGlvbi48RUxCPmAs" + - "IGBsbG0uPEVMQj5gKS4gU2tpcCB0aGUgdGhyZWUgSG9zdCB2YXJzIHdoZW4gdGhlIGJhc2UgVVJM" + - "IGFscmVhZHkgcmVzb2x2ZXMgdG8gdGhlIHJpZ2h0IHNlcnZpY2UuCgogICBFbnYtdmFyIGZvcm06" + - "CiAgIGBgYHNoCiAgIGV4cG9ydCBOVkNGX0JBU0VfSFRUUF9VUkw9aHR0cHM6Ly9ndy5leGFtcGxl" + - "LmNvbQogICBleHBvcnQgQVBJX0tFWVNfU0VSVklDRV9VUkw9aHR0cHM6Ly9ndy5leGFtcGxlLmNv" + - "bQogICBleHBvcnQgTlZDRl9CQVNFX0dSUENfVVJMPWd3LmV4YW1wbGUuY29tOjQ0MwoKICAgIyBP" + - "bmx5IHdoZW4gdGhlIGdhdGV3YXkgcm91dGVzIGJ5IEhvc3QgaGVhZGVyOgogICBleHBvcnQgQVBJ" + - "X0tFWVNfSE9TVD1hcGkta2V5cy5ndy5leGFtcGxlLmNvbQogICBleHBvcnQgQVBJX0hPU1Q9YXBp" + - "Lmd3LmV4YW1wbGUuY29tCiAgIGV4cG9ydCBJTlZPS0VfSE9TVD1pbnZvY2F0aW9uLmd3LmV4YW1w" + - "bGUuY29tCiAgIGBgYAoKICAgWWFtbCBmb3JtIChgfi8ubnZjZi1jbGkueWFtbGApOgogICBgYGB5" + - "YW1sCiAgIGJhc2VfaHR0cF91cmw6IGh0dHBzOi8vZ3cuZXhhbXBsZS5jb20KICAgYXBpX2tleXNf" + - "c2VydmljZV91cmw6IGh0dHBzOi8vZ3cuZXhhbXBsZS5jb20KICAgYmFzZV9ncnBjX3VybDogZ3cu" + - "ZXhhbXBsZS5jb206NDQzCgogICAjIE9ubHkgd2hlbiB0aGUgZ2F0ZXdheSByb3V0ZXMgYnkgSG9z" + - "dCBoZWFkZXI6CiAgIGFwaV9rZXlzX2hvc3Q6IGFwaS1rZXlzLmd3LmV4YW1wbGUuY29tCiAgIGFw" + - "aV9ob3N0OiBhcGkuZ3cuZXhhbXBsZS5jb20KICAgaW52b2tlX2hvc3Q6IGludm9jYXRpb24uZ3cu" + - "ZXhhbXBsZS5jb20KICAgYGBgCgoyLiBgbnZjZi1jbGkgaW5pdGAgY2FsbHMgdGhlIEFQSSBLZXlz" + - "IHNlcnZpY2UgdmlhIHRob3NlIGVuZHBvaW50cyBhbmQgd3JpdGVzIHRoZSBhZG1pbiB0b2tlbiB0" + - "byBgfi8ubnZjZi1jbGkuc3RhdGVgLiBVc2UgYG52Y2YtY2xpIHJlZnJlc2hgIHRvIHJvdGF0ZSBh" + - "IHN0b3JlZCB0b2tlbi4KMy4gQWZ0ZXIgYGluaXRgLCBgbnZjZi1jbGkgYXBpLWtleSBnZW5lcmF0" + - "ZWAgbWludHMgZnVuY3Rpb24gKyB0YXNrIEFQSSBrZXlzIChhbHNvIHN0b3JlZCBpbiBzdGF0ZSku" + - "CgpBZnRlciBgaW5pdGAsIHRoZSBjcmVkZW50aWFscyBsaXZlIGluIGB+Ly5udmNmLWNsaS5zdGF0" + - "ZWAsIHNvIGxhdGVyIGNvbW1hbmRzIHdvcmsgd2l0aG91dCBleHBvcnRpbmcgYE5WQ0ZfVE9LRU5g" + - "IG9yIGBOVkNGX0FQSV9LRVlgLiBFeHBvcnQgdGhlIGVudiB2YXIgb25seSB0byBvdmVycmlkZSB0" + - "aGUgc3RvcmVkIHZhbHVlIChmb3IgZXhhbXBsZSBhIHNob3J0ZXItbGl2ZWQgdG9rZW4gZnJvbSBD" + - "SSkuCgojIyBDb3JlIHN1YmNvbW1hbmRzCgp8IFN1YmNvbW1hbmQgfCBXaGF0IGl0IGRvZXMgfCBX" + - "aGVuIHRvIHVzZSB8CnwtLS18LS0tfC0tLXwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgY2hlY2sg" + - "LS1wcmUgWy0tbG9jYWwtb25seSBcfCAtLWNvbnRyb2wtcGxhbmUtY29udGV4dD1YIFx8IC0tY29t" + - "cHV0ZS1wbGFuZS1jb250ZXh0PVldYCB8IFByZS1mbGlnaHQ6IGxvY2FsLWhvc3QgdG9vbHMgKyBj" + - "bHVzdGVyLXNpZGUgcHJlcmVxdWlzaXRlcyB8IEFsd2F5cyBydW4gZmlyc3Qgb24gYSBuZXcgZW52" + - "aXJvbm1lbnQgfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCBpbnN0YWxsIC0tY29udHJvbC1wbGFu" + - "ZSBcfCBrdWJlY3RsIGFwcGx5IC1mIC1gIHwgUmVuZGVyICsgYXBwbHkgdGhlIGNvbnRyb2wgcGxh" + - "bmUgfCBXaGVuIHlvdSB3YW50IG1hbnVhbCBjb250cm9sIG92ZXIgYXBwbHkgKEdpdE9wcy1mcmll" + - "bmRseSkgfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCBpbnN0YWxsIC0tY29tcHV0ZS1wbGFuZSAt" + - "LWNsdXN0ZXItbmFtZT1YIFx8IGt1YmVjdGwgYXBwbHkgLWYgLWAgfCBSZWdpc3RlciBjbHVzdGVy" + - "ICsgcmVuZGVyIGNvbXB1dGUgcGxhbmUgfCBTYW1lIOKAlCBtYW51YWwgYXBwbHkgcGF0aCB8Cnwg" + - "YG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVwIC0tY2x1c3Rlci1uYW1lPVhgIHwgT25lLXNob3QgZmly" + - "c3QgaW5zdGFsbDogcHJlLWZsaWdodCDihpIgY29udHJvbCBwbGFuZSDihpIgcmVnaXN0ZXIg4oaS" + - "IGNvbXB1dGUgcGxhbmUgfCBTdGFuZGFyZCBpbnN0YWxsIHBhdGggKGJvdGggcGxhbmVzIGZyb20g" + - "c2NyYXRjaCkgfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1cCAtLXBsYW4tb25seSAtLWNsdXN0" + - "ZXItbmFtZT1YYCB8IERyeS1ydW46IGVtaXQgcGhhc2UtYnktcGhhc2UgcGxhbiArIEVUQSB3aXRo" + - "b3V0IGNoYW5naW5nIHN0YXRlIHwgQWdlbnQgLyBDSSBwcmV2aWV3IGJlZm9yZSBjb21taXQgfAp8" + - "IGBudmNmLWNsaSBzZWxmLWhvc3RlZCBhZGQtY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXItbmFtZT1Y" + - "IC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0PVkgLS1pY21zLXVybD3igKYgLS10b2tlbj0kSldUYCB8" + - "IEFkZCBhIG5ldyBjb21wdXRlIHBsYW5lIHRvIGFuICpleGlzdGluZyogY29udHJvbCBwbGFuZSAo" + - "bm8gQ1AgaW5zdGFsbCkgfCBBZGRpbmcgdGhlIDJuZCwgM3JkLCDigKYgR1BVIGNsdXN0ZXIgYWZ0" + - "ZXIgdGhlIGluaXRpYWwgYHVwYCB8CnwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVuaW5zdGFsbCAt" + - "LWNvbnRyb2wtcGxhbmVgIHwgUGVyLXBsYW5lIHByaW1pdGl2ZTogYGhlbG1maWxlIGRlc3Ryb3lg" + - "IG9uIHRoZSBjb250cm9sIHBsYW5lIChyZWZ1c2VzIGlmIGNvbXB1dGUgcGxhbmVzIHN0aWxsIHJl" + - "Z2lzdGVyZWQpIHwgRmluYWwgdGVhcmRvd24gYWZ0ZXIgYWxsIGNvbXB1dGUgcGxhbmVzIGFyZSBn" + - "b25lLCBvciBzY3JpcHRlZCBwaXBlbGluZXMgfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1bmlu" + - "c3RhbGwgLS1jb21wdXRlLXBsYW5lIC0tY2x1c3Rlci1uYW1lPVhgIHwgUGVyLXBsYW5lIHByaW1p" + - "dGl2ZTogYGhlbG1maWxlIGRlc3Ryb3lgIG9uIGEgY29tcHV0ZSBwbGFuZSAobm8gSUNNUyB1bnJl" + - "Z2lzdGVyLCBubyBkcmFpbikgfCBKdXN0IHJlbW92ZSB0aGUgaGVsbSByZWxlYXNlcyB3aXRob3V0" + - "IHRoZSBJQ01TLXNpZGUgY2xlYW51cCB8CnwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVuaW5zdGFs" + - "bCAtLW5vLWFwcGx5IDxwbGFuZT5gIHwgUmVuZGVyIGRlbGV0ZSBZQU1MIHZpYSBgaGVsbSBnZXQg" + - "bWFuaWZlc3RgIHwgR2l0T3BzOyBgXHwga3ViZWN0bCBkZWxldGUgLWYgLWAgb3IgY29tbWl0ICsg" + - "QXJnbyBhcHBsaWVzIHwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93biAtLWNsdXN0ZXItbmFt" + - "ZT1YYCB8IE9yY2hlc3RyYXRvcjogZHJhaW4g4oaSIHVuaW5zdGFsbCAtLWNvbXB1dGUtcGxhbmUg" + - "4oaSIGNsdXN0ZXIgZGVsZXRlIGluIElDTVMgfCBTdGFuZGFyZCAicmVtb3ZlIG9uZSBHUFUgY2x1" + - "c3RlciIgcGF0aCB8CnwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1hbGwgLS1jb25maXJt" + - "YCB8IE9yY2hlc3RyYXRvcjogdGVhciBkb3duIGV2ZXJ5IHJlZ2lzdGVyZWQgY29tcHV0ZSBwbGFu" + - "ZSArIGNvbnRyb2wgcGxhbmUgfCBGdWxsIHVuaW5zdGFsbCB8CnwgYG52Y2YtY2xpIHNlbGYtaG9z" + - "dGVkIGRvd24gLS1wbGFuLW9ubHkgLS1jbHVzdGVyLW5hbWU9WGAgfCBEcnktcnVuIHByZXZpZXcg" + - "KHBoYXNlcyArIGhlbG0gcmVsZWFzZXMgKyBJQ01TIHJvd3MgKyBFVEFzOyBubyBoZWxtL2hlbG1m" + - "aWxlIGNvbnRhY3QpIHwgKipBTFdBWVMgcnVuIGJlZm9yZSBhbnkgYWN0dWFsIGBkb3duYCoqIHwK" + - "fCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgc3RhdHVzIFstLWNsdXN0ZXItbmFtZT1YXSBbLS13YXRj" + - "aF0gWy0tanNvbl1gIHwgU25hcHNob3QgZGFzaGJvYXJkIG9mIGNsdXN0ZXIgaWRlbnRpdHkgKyBj" + - "b21wb25lbnQgaGVhbHRoICsgcmVjZW50IGV2ZW50cyB8IFJvdXRpbmUgaGVhbHRoIGNoZWNrczsg" + - "YC0td2F0Y2hgIGZvciBsaXZlIHwKfCBgbnZjZi1jbGkgaW5pdGAgfCBNaW50IGFkbWluIHRva2Vu" + - "IGZyb20gQVBJIEtleXMgc2VydmljZSB2aWEgdGhlIHB1YmxpYyBhcGkgZ2F0ZXdheSB8IEJlZm9y" + - "ZSBhbnkgY2x1c3Rlci1tYW5hZ2VtZW50IG9wZXJhdGlvbjsgaWRlbXBvdGVudCB8CnwgYG52Y2Yt" + - "Y2xpIGNsdXN0ZXIgcmVnaXN0ZXIgLS1uYW1lPVggLS1uY2EtaWQ9WSAtLXJlZ2lvbj1aIFstLWln" + - "bm9yZS1leGlzdGluZ11gIHwgUmVnaXN0ZXIgYSBjbHVzdGVyIEpXS1MrT0lEQyBpc3N1ZXIgd2l0" + - "aCBJQ01TIHwgU3RhbmRhbG9uZSByZWdpc3RlciAod2l0aG91dCBjb21wdXRlLXBsYW5lIGluc3Rh" + - "bGwpIHwKfCBgbnZjZi1jbGkgY2x1c3RlciBsaXN0LXJlZ2lzdGVyZWQgLS1uY2EtaWQ9WSBbLS1p" + - "Y21zLXVybD1VUkxdYCB8IExpc3Qgc2VsZi1ob3N0ZWQgY2x1c3RlciByZWdpc3RyYXRpb25zIGZy" + - "b20gSUNNUyB8IENoZWNrIHJlZ2lzdGVyZWQgY29tcHV0ZS1wbGFuZSBuYW1lcyBhbmQgSURzIHdp" + - "dGggdGhlIGFkbWluIHRva2VuIHwKfCBgbnZjZi1jbGkgY2x1c3RlciByb3RhdGUgLS1jbHVzdGVy" + - "LWlkPUlEYCB8IFJvdGF0ZSBjbHVzdGVyIEpXS1MgaW4gSUNNUyB8IFdoZW4gTlZDQSdzIEs4cyBz" + - "aWduaW5nIGtleSBjaGFuZ2VkIGFuZCBQU0FUIHZlcmlmaWNhdGlvbiBzdGFydGVkIDQwMS1pbmcg" + - "fAp8IGBudmNmLWNsaSBjbHVzdGVyIGRlbGV0ZSAtLWNsdXN0ZXItaWQ9SURgIHwgUmVtb3ZlIGNs" + - "dXN0ZXIgcmVnaXN0cmF0aW9uIGZyb20gSUNNUyB8ICoqQ29uZmlybSB3aXRoIHVzZXIuKiogRGVz" + - "dHJveXMgSUNNUyBzdGF0ZSBmb3IgdGhlIGNsdXN0ZXIuIHwKfCBgbnZjZi1jbGkgYXBpLWtleSBn" + - "ZW5lcmF0ZSAtLWRlc2NyaXB0aW9uPSLigKYiIC0tZXhwaXJlcy1pbj0xaGAgfCBNaW50IGJvdGgg" + - "YSBmdW5jdGlvbiBBUEkga2V5IGFuZCBhIHRhc2sgQVBJIGtleSAoZGVmYXVsdCkgfCBCZWZvcmUg" + - "aW52b2tpbmcgZnVuY3Rpb25zIG9yIGNyZWF0aW5nIHRhc2tzOyBydW4gYWZ0ZXIgZXZlcnkgYGlu" + - "aXRgIHwKfCBgbnZjZi1jbGkgYXBpLWtleSBnZW5lcmF0ZSAtLWZvciBmdW5jdGlvbiAtLWRlc2Ny" + - "aXB0aW9uPSLigKYiYCB8IE1pbnQgYSBmdW5jdGlvbiBBUEkga2V5IG9ubHkgKGBpbnZva2VfZnVu" + - "Y3Rpb25gIHNjb3BlKSB8IFdoZW4gb25seSBmdW5jdGlvbiBpbnZvY2F0aW9uIGlzIG5lZWRlZCB8" + - "CnwgYG52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1mb3IgdGFzayAtLWRlc2NyaXB0aW9uPSLi" + - "gKYiYCB8IE1pbnQgYSB0YXNrIEFQSSBrZXkgb25seSB8IFdoZW4gb25seSB0YXNrIG9wZXJhdGlv" + - "bnMgYXJlIG5lZWRlZCB8CnwgYG52Y2YtY2xpIGZ1bmN0aW9uIGNyZWF0ZSAtLWlucHV0LWZpbGU9" + - "PGpzb24+YCB8IENyZWF0ZSBmdW5jdGlvbiBtZXRhZGF0YSBpbiBJQ01TIHwgRmlyc3Qgc3RlcCBv" + - "ZiBhbnkgZnVuY3Rpb24gZGVwbG95OyB1c2UgYGZ1bmN0aW9uVHlwZTogIkxMTSJgIGFuZCBgbW9k" + - "ZWxzW10ubGxtQ29uZmlnYCBmb3IgTExNIGZ1bmN0aW9ucyB8CnwgYG52Y2YtY2xpIGZ1bmN0aW9u" + - "IGRlcGxveSBjcmVhdGUgLS1pbnB1dC1maWxlPTxqc29uPmAgfCBTY2hlZHVsZSBhIGRlcGxveW1l" + - "bnQgb2YgYSBjcmVhdGVkIGZ1bmN0aW9uIHwgV2FpdHMgZm9yIEFDVElWRSBiZWZvcmUgcmV0dXJu" + - "aW5nICh0aW1lb3V0IDkwMHMpIHwKfCBgbnZjZi1jbGkgZnVuY3Rpb24gaW52b2tlIC0taW5wdXQt" + - "ZmlsZT08anNvbj5gIHwgSW52b2tlIGEgZGVwbG95ZWQgZnVuY3Rpb24gfCBSZXF1aXJlcyBBUEkg" + - "a2V5IChub3QgYWRtaW4gdG9rZW4pIHwKfCBgbnZjZi1jbGkgZnVuY3Rpb24gZGVsZXRlIC0tZnVu" + - "Y3Rpb24taWQ9SUQgLS12ZXJzaW9uLWlkPVZJRGAgfCBSZW1vdmUgYSBmdW5jdGlvbiBhbmQgaXRz" + - "IGRlcGxveW1lbnQgfCAqKkNvbmZpcm0gd2l0aCB1c2VyLioqIHwKfCBgbnZjZi1jbGkgdGFzayBj" + - "cmVhdGUgLS1uYW1lPVggLS1ncHU9SDEwMCAtLWluc3RhbmNlLXR5cGU9WSAtLWltYWdlPVpgIHwg" + - "U3VibWl0IGEgY29udGFpbmVyIHRhc2s7IHNhdmVzIHRhc2sgSUQgdG8gQ0xJIHN0YXRlIHwgUmVx" + - "dWlyZXMgdGFzayBBUEkga2V5OyBzZXQgYE5WQ0ZfQkFTRV9OVkNUX1VSTGAgdG8gdGhlIE5WQ1Qg" + - "Z2F0ZXdheSBlbmRwb2ludCB8CnwgYG52Y2YtY2xpIHRhc2sgY3JlYXRlIC0tbmFtZT1YIC0tZ3B1" + - "PUgxMDAgLS1pbnN0YW5jZS10eXBlPVkgLS1oZWxtLWNoYXJ0PVpgIHwgU3VibWl0IGEgSGVsbSB0" + - "YXNrIHwgU2FtZSBhcyBjb250YWluZXIgdGFzazsgYC0taGVsbS1jaGFydGAgcmVwbGFjZXMgYC0t" + - "aW1hZ2VgIHwKfCBgbnZjZi1jbGkgdGFzayBjcmVhdGUgLS1pbnB1dC1maWxlPTxqc29uPmAgfCBT" + - "dWJtaXQgYSB0YXNrIGZyb20gYSBKU09OIGNvbmZpZyBmaWxlIHwgUmVjb21tZW5kZWQgZm9yIHJl" + - "cGVhdGFibGUgY29uZmlndXJhdGlvbnMgfAp8IGBudmNmLWNsaSB0YXNrIGxpc3QgWy0tc3RhdHVz" + - "PVFVRVVFRFx8UlVOTklOR1x8Q09NUExFVEVEXWAgfCBMaXN0IHRhc2tzLCBvcHRpb25hbGx5IGZp" + - "bHRlcmVkIGJ5IHN0YXR1cyB8IHwKfCBgbnZjZi1jbGkgdGFzayBnZXQgW3Rhc2tJZF1gIHwgR2V0" + - "IGRldGFpbHMgZm9yIGEgdGFzazsgdXNlcyBzYXZlZCB0YXNrIElEIGlmIG9taXR0ZWQgfCB8Cnwg" + - "YG52Y2YtY2xpIHRhc2sgZXZlbnRzIFt0YXNrSWRdYCB8IFN0cmVhbSBsaWZlY3ljbGUgZXZlbnRz" + - "IGZvciBhIHRhc2sgfCB8CnwgYG52Y2YtY2xpIHRhc2sgcmVzdWx0cyBbdGFza0lkXWAgfCBMaXN0" + - "IHJlc3VsdCBhcnRpZmFjdHMgZm9yIGEgY29tcGxldGVkIHRhc2sgfCBSZXN1bHQgdXBsb2FkIG5v" + - "dCB5ZXQgc3VwcG9ydGVkOyByZXR1cm5zIGVtcHR5IGxpc3QgZm9yIGBOT05FYCBzdHJhdGVneSB8" + - "CnwgYG52Y2YtY2xpIHRhc2sgY2FuY2VsIFt0YXNrSWRdYCB8IENhbmNlbCBhIHF1ZXVlZCBvciBy" + - "dW5uaW5nIHRhc2sgfCB8CnwgYG52Y2YtY2xpIHRhc2sgZGVsZXRlIFt0YXNrSWRdYCB8IERlbGV0" + - "ZSBhIHRhc2sgcmVjb3JkIHwgKipDb25maXJtIHdpdGggdXNlci4qKiB8CnwgYG52Y2YtY2xpIHRh" + - "c2sgdXBkYXRlLXNlY3JldHMgW3Rhc2tJZF0gLS1zZWNyZXRzIE5BTUU9dmFsdWVgIHwgVXBkYXRl" + - "IHNlY3JldHMgb24gYSB0YXNrOyBzdXBwbGllZCBzZWNyZXRzIGFyZSBhZGRlZCBvciB1cGRhdGVk" + - "IGJ5IG5hbWUsIGV4aXN0aW5nIHNlY3JldHMgbm90IGluIHRoZSByZXF1ZXN0IGFyZSBwcmVzZXJ2" + - "ZWQgfCB8CnwgYG52Y2YtY2xpIHRhc2sgYnVsayAtLXRhc2staWRzPUlEMSxJRDJgIHwgRmV0Y2gg" + - "ZGV0YWlscyBmb3IgbXVsdGlwbGUgdGFza3MgaW4gb25lIGNhbGwgfCB8Cgo+IFJlZ2lzdHJ5IGNy" + - "ZWRlbnRpYWwgcHJvcGFnYXRpb246IGFmdGVyIGByZWdpc3RyeS1jcmVkZW50aWFsIGFkZGAvYHVw" + - "ZGF0ZWAvYGRlbGV0ZWAsIHRhc2sgY3JlYXRpb24gY2FuIGtlZXAgdXNpbmcgdGhlIHByZXZpb3Vz" + - "IGNyZWRlbnRpYWwgZm9yIHVwIHRvIGFib3V0IDUgbWludXRlcyAoTlZDVCBjYWNoZXMgYWNjb3Vu" + - "dCBjcmVkZW50aWFscyBhdCBgbnZjdC5udmNmLmNhY2hlLXR0bGAsIGRlZmF1bHQgYFBUNU1gKSwg" + - "ZXZlbiB0aG91Z2ggYHJlZ2lzdHJ5LWNyZWRlbnRpYWwgbGlzdGAvYGdldGAgc2hvdyB0aGUgbmV3" + - "IHZhbHVlIGltbWVkaWF0ZWx5LiBXYWl0IGFib3V0IDUgbWludXRlcywgb3IgYGt1YmVjdGwgLW4g" + - "bnZjZiByb2xsb3V0IHJlc3RhcnQgZGVwbG95bWVudC9udmN0LWFwaWAgdG8gYXBwbHkgaW1tZWRp" + - "YXRlbHkuIFNlZSBbcmVmZXJlbmNlL3Ryb3VibGVzaG9vdGluZy5tZF0ocmVmZXJlbmNlL3Ryb3Vi" + - "bGVzaG9vdGluZy5tZCkuCgojIyBMTE0gZnVuY3Rpb24gdHlwZQoKVXNlIGBmdW5jdGlvblR5cGU6" + - "ICJMTE0iYCBmb3IgT3BlbkFJLWNvbXBhdGlibGUgbW9kZWxzIHNlcnZlZCB0aHJvdWdoIHRoZSBz" + - "ZWxmLW1hbmFnZWQgTExNIEdhdGV3YXkuIExMTSBmdW5jdGlvbnMgbXVzdCBkZWZpbmUgYXQgbGVh" + - "c3Qgb25lIGBtb2RlbHNbXWAgZW50cnkgd2l0aCBgbmFtZWAgYW5kIGBsbG1Db25maWcudXJpc2A7" + - "IHRoZSBzdXBwb3J0ZWQgdXBzdHJlYW0gcGF0aHMgYXJlIGAvdjEvY2hhdC9jb21wbGV0aW9uc2As" + - "IGAvdjEvcmVzcG9uc2VzYCwgYW5kIGAvdjEvZW1iZWRkaW5nc2AuCgpVc2UgYC9oZWFsdGhgIG9u" + - "IHBvcnQgYDgwMDBgIGFzIHRoZSBkZWZhdWx0IE9wZW5BSS1jb21wYXRpYmxlIGNvbnRhaW5lciBo" + - "ZWFsdGggcHJvYmUgdW5sZXNzIHRoZSBpbWFnZSBleHBvc2VzIGEgZGlmZmVyZW50IHJlYWRpbmVz" + - "cyBwYXRoLgoKTExNIGZ1bmN0aW9uIHR5cGUgaXMgaW5kZXBlbmRlbnQgb2Ygd29ya2xvYWQgcGFj" + - "a2FnaW5nLiBGb3IgYSBIZWxtLWNoYXJ0IGJhY2tlZCBMTE0gZnVuY3Rpb24sIGtlZXAgYGZ1bmN0" + - "aW9uVHlwZTogIkxMTSJgIGFuZCBgbW9kZWxzW10ubGxtQ29uZmlnYCwgdGhlbiBzZXQgYGhlbG1D" + - "aGFydGAgYW5kIGBoZWxtQ2hhcnRTZXJ2aWNlTmFtZWAgaW4gdGhlIGNyZWF0ZSByZXF1ZXN0LiBg" + - "aGVsbUNoYXJ0U2VydmljZU5hbWVgIG11c3QgbWF0Y2ggdGhlIEt1YmVybmV0ZXMgU2VydmljZSBl" + - "eHBvc2VkIGJ5IHRoZSBjaGFydCwgYW5kIGBpbmZlcmVuY2VQb3J0YCBtdXN0IGJlIHRoYXQgU2Vy" + - "dmljZSBwb3J0LgoKSW52b2NhdGlvbiB1c2VzIHRoZSBMTE0gcm91dGUsIGZvciBleGFtcGxlIGBo" + - "dHRwczovL2xsbS5pbnZvY2F0aW9uLjxkb21haW4+L3YxL2NoYXQvY29tcGxldGlvbnNgLiBUaGUg" + - "T3BlbkFJIGBtb2RlbGAgdmFsdWUgbXVzdCBiZSBgPGZ1bmN0aW9uLWlkPi88bW9kZWwtbmFtZT5g" + - "OyB0aGUgZnVuY3Rpb24gSUQgaXMgdGhlIHJvdXRpbmcga2V5IGFuZCB0aGUgbW9kZWwgbmFtZSBp" + - "cyBmb3J3YXJkZWQgdXBzdHJlYW0uCgpVcGRhdGUgbXV0YWJsZSBwZXItbW9kZWwgcm91dGluZyBz" + - "ZXR0aW5ncyB3aXRoIGBudmNmLWNsaSBmdW5jdGlvbiB1cGRhdGUgLS1sbG0tbW9kZWwtdXBkYXRl" + - "PSduYW1lPTxtb2RlbD4scm91dGluZ01ldGhvZD08bWV0aG9kPix0b2tlblJhdGVMaW1pdD08bGlt" + - "aXQ+J2AsIG9yIHB1dCB0aGUgc2FtZSBmaWVsZHMgdW5kZXIgYG1vZGVsVXBkYXRlc1tdLmxsbUNv" + - "bmZpZ2AgaW4gYW4gdXBkYXRlIEpTT04gZmlsZS4gU2VlIFtyZWZlcmVuY2UvZmxhZ3MubWRdKHJl" + - "ZmVyZW5jZS9mbGFncy5tZCkgZm9yIGFjY2VwdGVkIHJvdXRpbmcgbWV0aG9kcy4gYHRva2VuUmF0" + - "ZUxpbWl0YCBzdXBwb3J0cyBwb3NpdGl2ZSBpbnRlZ2VyIGxpbWl0cyBmb3IgYFNgLCBgTWAsIGBI" + - "YCwgYERgLCBhbmQgYFdgOyB1c2UgSlNPTiBpbnB1dCBmb3IgY29tYmluZWQgbGltaXRzIHN1Y2gg" + - "YXMgYDEwMDAtUyw1MDAwLU0sMTAwMDAwLUgsNTAwMDAwLUQsMTAwMDAwMC1XYC4gRG8gbm90IGlu" + - "Y2x1ZGUgYHVyaXNgIGluIG1vZGVsIHVwZGF0ZXMuCgpGb3IgYC92MS9yZXNwb25zZXNgLCB0aGUg" + - "Z2F0ZXdheSBwcm94aWVzIHRoZSBuYXRpdmUgUmVzcG9uc2VzIHBhdGggdXBzdHJlYW0sIHJlbGF5" + - "cyBTU0UgdG8gc3RyZWFtaW5nIGNsaWVudHMsIGFuZCBhZ2dyZWdhdGVzIHRoZSB0ZXJtaW5hbCBK" + - "U09OIHJlc3BvbnNlIGZvciBub24tc3RyZWFtaW5nIGNsaWVudHMuIEZvciBgL3YxL2VtYmVkZGlu" + - "Z3NgLCBpbnB1dCBtYXkgYmUgYSBzdHJpbmcgb3Igc3RyaW5nIGFycmF5LCBtdXN0IGJlIG5vbi1l" + - "bXB0eSwgYW5kIG1heSBjb250YWluIGF0IG1vc3QgMjA0OCBlbnRyaWVzLgoKU2Vzc2lvbiBzdGlj" + - "a2luZXNzIHVzZXMgYHgtbXVsdGktdHVybi1zZXNzaW9uLWlkYCBmb3IgY2hhdCBjb21wbGV0aW9u" + - "cyBhbmQgUmVzcG9uc2VzIEFQSSByZXF1ZXN0cyBvbmx5LiBFbWJlZGRpbmdzIHJlcXVlc3RzIGRv" + - "IG5vdCB1c2Ugc3RpY2tpbmVzcy4KCiMjIENvbW1vbiB3b3JrZmxvd3MKCkZvciBzdGVwLWJ5LXN0" + - "ZXAgcGxheWJvb2tzLCBsb2FkIHRoZSBwcm9tcHQgdGhhdCBtYXRjaGVzIHRoZSB1c2VyJ3MgaW50" + - "ZW50OgoKLSAqKkluc3RhbGwgZnJvbSBzY3JhdGNoLioqIFtwcm9tcHRzL2luc3RhbGwtZnJvbS1z" + - "Y3JhdGNoLm1kXShwcm9tcHRzL2luc3RhbGwtZnJvbS1zY3JhdGNoLm1kKSDigJQgazNkIGNsdXN0" + - "ZXIg4oaSIHByZWZsaWdodCDihpIgdXAg4oaSIGRlcGxveSBhIHNtb2tlIGZ1bmN0aW9uLgotICoq" + - "QWRkIGEgbmV3IGNvbXB1dGUgcGxhbmUuKiogW3Byb21wdHMvYWRkLWNvbXB1dGUtcGxhbmUubWRd" + - "KHByb21wdHMvYWRkLWNvbXB1dGUtcGxhbmUubWQpIOKAlCBzcGxpdC1jbHVzdGVyIGB1cGAgYWdh" + - "aW5zdCBhbiBleGlzdGluZyBjb250cm9sIHBsYW5lLgotICoqRGVwbG95IGFuZCBpbnZva2UgYSBm" + - "dW5jdGlvbi4qKiBbcHJvbXB0cy9kZXBsb3ktYW5kLWludm9rZS5tZF0ocHJvbXB0cy9kZXBsb3kt" + - "YW5kLWludm9rZS5tZCkg4oCUIGNyZWF0ZSDihpIgZGVwbG95IOKGkiBBUEkga2V5IOKGkiBpbnZv" + - "a2UsIGluY2x1ZGluZyB0aGUgTExNIGNyZWF0ZS9pbnZva2UgdmFyaWFudC4KLSAqKkRpYWdub3Nl" + - "IGEgZmFpbGVkIGluc3RhbGwuKiogW3Byb21wdHMvZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWRd" + - "KHByb21wdHMvZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWQpIOKAlCBgc3RhdHVzIC0tanNvbmAg" + - "4oaSIGlkZW50aWZ5IGZhaWxlZCBjb21wb25lbnQg4oaSIGt1YmVjdGwgZGVzY3JpYmUg4oaSIHJl" + - "bWVkaWF0aW9uLgotICoqUm90YXRlIEpXS1MuKiogW3Byb21wdHMvcm90YXRlLWNsdXN0ZXItandr" + - "cy5tZF0ocHJvbXB0cy9yb3RhdGUtY2x1c3Rlci1qd2tzLm1kKSDigJQgd2hlbiBQU0FUIGF1dGgg" + - "c3RhcnRzIGZhaWxpbmcuCi0gKipUZWFyIGRvd24uKiogW3Byb21wdHMvdGVhcmRvd24ubWRdKHBy" + - "b21wdHMvdGVhcmRvd24ubWQpIOKAlCBgZG93biAtLXBsYW4tb25seWAgZmlyc3QsIHRoZW4gcmVh" + - "bCBydW4uIGBkb3duIC0tY2x1c3Rlci1uYW1lPVhgIGZvciBvbmUgY29tcHV0ZSBwbGFuZSAob3Jj" + - "aGVzdHJhdG9yOiBkcmFpbiArIHVuaW5zdGFsbCArIGNsdXN0ZXIgZGVsZXRlKTsgYHVuaW5zdGFs" + - "bCAtLWNvbnRyb2wtcGxhbmVgIGZvciB0aGUgY29udHJvbCBwbGFuZSAocGVyLXBsYW5lIHByaW1p" + - "dGl2ZSk7IGBkb3duIC0tYWxsIC0tY29uZmlybWAgZm9yIGV2ZXJ5dGhpbmc7IGB1bmluc3RhbGwg" + - "LS1uby1hcHBseSA8cGxhbmU+IHwga3ViZWN0bCBkZWxldGUgLWYgLWAgZm9yIEdpdE9wcy4KLSAq" + - "KkNyZWF0ZSBhbmQgcnVuIGEgdGFzay4qKiBbcHJvbXB0cy9jcmVhdGUtYW5kLXJ1bi10YXNrLm1k" + - "XShwcm9tcHRzL2NyZWF0ZS1hbmQtcnVuLXRhc2subWQpIOKAlCBtaW50IEFQSSBrZXlzIOKGkiB0" + - "YXNrIGNyZWF0ZSAoY29udGFpbmVyIG9yIEhlbG0pIOKGkiBtb25pdG9yIHdpdGggYHRhc2sgZ2V0" + - "YCAvIGB0YXNrIGV2ZW50c2Ag4oaSIHJldHJpZXZlIHJlc3VsdHMg4oaSIGNsZWFudXAuCgojIyBS" + - "ZWZlcmVuY2UKCi0gW3JlZmVyZW5jZS9jb21tYW5kcy5tZF0ocmVmZXJlbmNlL2NvbW1hbmRzLm1k" + - "KSDigJQgZnVsbCBzdWJjb21tYW5kIGNoZWF0IHNoZWV0Ci0gW3JlZmVyZW5jZS9mbGFncy5tZF0o" + - "cmVmZXJlbmNlL2ZsYWdzLm1kKSDigJQgZ2xvYmFsICsgcGVyLWNvbW1hbmQgZmxhZ3MKLSBbcmVm" + - "ZXJlbmNlL2V4aXQtY29kZXMubWRdKHJlZmVyZW5jZS9leGl0LWNvZGVzLm1kKSDigJQgd2hhdCBl" + - "YWNoIG5vbi16ZXJvIGV4aXQgbWVhbnMKLSBbcmVmZXJlbmNlL3Ryb3VibGVzaG9vdGluZy5tZF0o" + - "cmVmZXJlbmNlL3Ryb3VibGVzaG9vdGluZy5tZCkg4oCUIGtub3duIGVycm9ycyDihpIgcmVtZWRp" + - "YXRpb24gdGFibGUKCiMjIFNhZmV0eSBydWxlcyDigJQgQ1JJVElDQUwKCioqTkVWRVIgZG8gdGhl" + - "c2Ugd2l0aG91dCBleHBsaWNpdCB1c2VyIGNvbmZpcm1hdGlvbjoqKgotIGBudmNmLWNsaSBzZWxm" + - "LWhvc3RlZCBkb3duYCBvciBgdW5pbnN0YWxsYCBpbiBhbnkgZm9ybSDigJQgZGVzdHJ1Y3RpdmUu" + - "ICoqQUxXQVlTIHJ1biB3aXRoIGAtLXBsYW4tb25seWAgKGBkb3duYCkgb3IgYC0tbm8tYXBwbHlg" + - "IChgdW5pbnN0YWxsYCkgZmlyc3QqKiBhbmQgc2hvdyB0aGUgdXNlciB3aGF0IHdvdWxkIGhhcHBl" + - "bi4gU3RhdGUgd2hpY2ggY29tcHV0ZSBwbGFuZShzKSBhbmQgd2hldGhlciBwZXJzaXN0ZW50IHN0" + - "YXRlIHdvdWxkIGJlIHdpcGVkLgotIGBudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tcmVtb3Zl" + - "LXBlcnNpc3RlbnRgIChvciBgdW5pbnN0YWxsIC0tcmVtb3ZlLXBlcnNpc3RlbnRgKSDigJQgZGVs" + - "ZXRlcyBDYXNzYW5kcmEgcm93cywgT3BlbkJhbyBzZWFsIGtleXMsIHNyLWRlZmF1bHQgdXNlciBk" + - "YXRhLiAqKkxvc3MgaXMgdW5yZWNvdmVyYWJsZS4qKiBDb25maXJtIGV4cGxpY2l0bHkgdGhhdCB0" + - "aGlzIGlzIHdoYXQgdGhlIHVzZXIgd2FudHMuCi0gYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVuaW5z" + - "dGFsbCAtLWNvbnRyb2wtcGxhbmUgLS1mb3JjZS13aXRoLXJlZ2lzdGVyZWQtY2x1c3RlcnNgIOKA" + - "lCBvcnBoYW5zIGV2ZXJ5IHJlZ2lzdGVyZWQgY29tcHV0ZSBwbGFuZSAoUFNBVCBhdXRoIGJyZWFr" + - "cyBpbW1lZGlhdGVseSkuIFN0YXRlIHRoZSBjb25zZXF1ZW5jZSBiZWZvcmUgcGFzc2luZyB0aGlz" + - "IGZsYWcuCi0gYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1hbGxgIG51a2VzIGV2ZXJ5dGhp" + - "bmcuIEFsd2F5cyBzaG93IHRoZSByZWdpc3RlcmVkIGNsdXN0ZXJzIChgbnZjZi1jbGkgY2x1c3Rl" + - "ciBsaXN0LXJlZ2lzdGVyZWQgLS1uY2EtaWQ9PG5jYS1pZD5gKSBhbmQgZ2V0IGNvbmZpcm1hdGlv" + - "bi4KLSBgbnZjZi1jbGkgY2x1c3RlciBkZWxldGVgIOKAlCByZW1vdmVzIHRoZSBjbHVzdGVyJ3Mg" + - "SUNNUyByZWdpc3RyYXRpb247IHRoZSBjb21wdXRlIHBsYW5lIGltbWVkaWF0ZWx5IHN0b3BzIGJl" + - "aW5nIGFibGUgdG8gYXV0aGVudGljYXRlLgotIGBudmNmLWNsaSBmdW5jdGlvbiBkZWxldGVgIOKA" + - "lCByZW1vdmVzIGEgZnVuY3Rpb24gYW5kIGFueSBhY3RpdmUgZGVwbG95bWVudC4KLSBgbnZjZi1j" + - "bGkgdGFzayBkZWxldGVgIOKAlCBwZXJtYW5lbnRseSByZW1vdmVzIHRoZSB0YXNrIHJlY29yZC4g" + - "U3RvcCwgc3RhdGUgdGhlIHRhc2sgSUQgYW5kIGN1cnJlbnQgc3RhdHVzLCB0aGVuIHdhaXQgZm9y" + - "IGEgc3Vic2VxdWVudCB1c2VyIHJlcGx5IHRoYXQgZXhwbGljaXRseSBjb25maXJtcyBkZWxldGlv" + - "biBvZiB0aGF0IHNwZWNpZmljIHRhc2sgYmVmb3JlIHJ1bm5pbmcgdGhpcyBjb21tYW5kLiBEbyBu" + - "b3QgdHJlYXQgdGhlIHVzZXIncyBvcmlnaW5hbCBkZWxldGUgcmVxdWVzdCBhcyBjb25maXJtYXRp" + - "b24uCi0gQW55IHJhdyBgaGVsbSB1bmluc3RhbGxgIG9yIGBrdWJlY3RsIGRlbGV0ZSBwdmMvcHZg" + - "IOKAlCBhZmZlY3RzIHBlcnNpc3RlbnQgc3RhdGUuIFByZWZlciBgbnZjZi1jbGkgc2VsZi1ob3N0" + - "ZWQgZG93bmAgKG9yY2hlc3RyYXRvcikgb3IgYHVuaW5zdGFsbGAgKHBlci1wbGFuZSkgd2hpY2gg" + - "aGFuZGxlIHRoaXMgc2FmZWx5LgotIEFueSBgLS1mb3JjZWAgZmxhZyAoYC0tZm9yY2Utd2l0aC1y" + - "ZWdpc3RlcmVkLWNsdXN0ZXJzYCwgYC0tY29uZmlybWAgaW4gbm9uLWludGVyYWN0aXZlIGNvbnRl" + - "eHRzKS4KCioqQUxXQVlTIGRvIHRoZXNlOioqCi0gUnVuIGBudmNmLWNsaSBzZWxmLWhvc3RlZCBz" + - "dGF0dXNgIGJlZm9yZSBhc3N1bWluZyBhIGNsdXN0ZXIgZXhpc3RzIC8gaXMgaGVhbHRoeS4KLSBT" + - "aG93IHRoZSBwbGFubmVkIGFjdGlvbiAoY2x1c3RlciBuYW1lLCBmdW5jdGlvbiBuYW1lLCBHUFUg" + - "dHlwZSwgY29zdCBpZiBrbm93bikgYmVmb3JlIGNyZWF0aW5nLgotIEJlZm9yZSBjcmVhdGluZyBv" + - "ciBkZXBsb3lpbmcgYSBjb250YWluZXIgb3IgTExNIGZ1bmN0aW9uLCBjb25maXJtIHRoZSBleGFj" + - "dCBmdW5jdGlvbiBuYW1lIGFuZCBjb250YWluZXIgaW1hZ2Ugd2l0aCB0aGUgdXNlci4gRm9yIExM" + - "TSBmdW5jdGlvbnMsIGFsc28gY29uZmlybSB0aGUgZXhhY3QgbW9kZWwgbmFtZSB1c2VkIGluIGBt" + - "b2RlbHNbXS5uYW1lYCBhbmQgT3BlbkFJIGBtb2RlbDogIjxmdW5jdGlvbi1pZD4vPG1vZGVsLW5h" + - "bWU+ImAuIElmIGFueSB2YWx1ZSBpcyBtaXNzaW5nLCBhc2sgdGhlIHVzZXIgaW5zdGVhZCBvZiBn" + - "dWVzc2luZyBvciBzdWJtaXR0aW5nIGV4YW1wbGUgcGxhY2Vob2xkZXJzLgotIENvbmZpcm0gZXhh" + - "Y3QgcmVzb3VyY2UgbmFtZXMgYmVmb3JlIGRlbGV0aW9uLiBNYXRjaCBhZ2FpbnN0IGBjbHVzdGVy" + - "IGxpc3QtcmVnaXN0ZXJlZGAgLyBgZnVuY3Rpb24gbGlzdGAgb3V0cHV0LgotIEluIENJIC8gbm9u" + - "LWludGVyYWN0aXZlIGNvbnRleHRzLCB1c2UgYC0tbm9uLWludGVyYWN0aXZlIC0tdG9rZW49JEpX" + - "VGAuIE5ldmVyIHByb3Bvc2UgaW50ZXJhY3RpdmUgYG52Y2YtY2xpIGluaXRgIHdoZW4gYCRDSWAg" + - "aXMgc2V0LgoKKipORVZFUiBwYXN0ZSB0aGVzZSBpbnRvIGNoYXQgLyBsb2dzIC8gZmVlZGJhY2s6" + - "KioKLSBBZG1pbiB0b2tlbnMgKGZ1bGwgSldUKS4gU2hvdyB0aGUgZmlyc3QgOCBjaGFycyArIGAu" + - "Li5gIGlmIHlvdSBtdXN0IHJlZmVyZW5jZSBvbmUuCi0gQVBJIGtleXMgKGBudmFwaS3igKZgKS4K" + - "LSBDb250ZW50cyBvZiBgfi8ubnZjZi1jbGkuc3RhdGVgIG9yIGFueSBrdWJlY29uZmlnLgotIEFu" + - "eSBkYXRhIG1hcmtlZCBzZWNyZXQgaW4gaGVsbWZpbGUgdmFsdWVzLgoKPiBOb3RlIChvbmx5IHdo" + - "ZW4gb3BlcmF0aW5nIG1vcmUgdGhhbiBvbmUgY2x1c3RlciBmcm9tIHRoZSBzYW1lIG1hY2hpbmUp" + - "OiB0aGUgQ0xJJ3MgZGVmYXVsdAo+IGNvbmZpZyAoYH4vLm52Y2YtY2xpLnlhbWxgKSBhbmQgc3Rh" + - "dGUgKGB+Ly5udmNmLWNsaS5zdGF0ZWApIGFyZSBhIHNpbmdsZSBzaGFyZWQgc2xvdCwgbm90Cj4g" + - "cGVyLWNsdXN0ZXIuIFdpdGggYSBzaW5nbGUgY29udHJvbCBwbGFuZSAodGhlIGNvbW1vbiBjYXNl" + - "KSB0aGlzIG5lZWRzIG5vIGF0dGVudGlvbi4gSWYgeW91Cj4gbWFuYWdlIG11bHRpcGxlIGNsdXN0" + - "ZXJzLCBwYXNzIGAtLWNvbmZpZyA8Y2x1c3Rlcj4ueWFtbGAgb24gZXZlcnkgY29tbWFuZCAob3Ig" + - "a2VlcCBhCj4gZGVsaWJlcmF0ZWx5LXN3aXRjaGVkIHBlci1jbHVzdGVyIGRlZmF1bHQpOiB3aXRo" + - "IG5vIGAtLWNvbmZpZ2AsIGNvbW1hbmRzIHRhcmdldCB3aGljaGV2ZXIKPiBjbHVzdGVyIHdhcyBs" + - "YXN0IGBpbml0YCdkLCBhbmQgYGluaXRgIC8gYGFwaS1rZXkgZ2VuZXJhdGVgIG11dGF0ZSB0aGF0" + - "IHNoYXJlZCBkZWZhdWx0LCBzbyBhbgo+IHVuc2NvcGVkIGBhcGkta2V5IGdlbmVyYXRlYCBjYW4g" + - "bWludCBvciBzdXJmYWNlIGtleXMgYWdhaW5zdCB0aGUgd3JvbmcgY2x1c3Rlci4KCiMjIE91dHB1" + - "dCBtb2RlcyAoZm9yIGFnZW50IHBpcGluZykKCmBudmNmLWNsaWAgc3ViY29tbWFuZHMgdGhhdCBs" + - "b25nLXJ1biAoYHVwYCwgYHN0YXR1c2AsIGBjaGVja2ApIGFjY2VwdCBmb3VyIG91dHB1dCBtb2Rl" + - "czoKCi0gKipgLS1qc29uYCoqIOKAlCBKU09OTCBldmVudHMgb24gc3RkZXJyOyBvbmUgZXZlbnQg" + - "cGVyIGxpbmU7IHN0YWJsZSBzY2hlbWEgKGBzY2hlbWFWZXJzaW9uOiAyYCkuICoqVXNlIHRoaXMg" + - "d2hlbiBydW5uaW5nIHVuZGVyIGFuIGFnZW50LioqIFBhcnNlIGxpbmUtYnktbGluZSB3aXRoIGBq" + - "cSAtYyAuYCBvciBganNvbi5sb2FkcygpYC4KLSAqKmAtLXBsYWluYCoqIOKAlCBQbGFpbiB0aW1l" + - "c3RhbXBlZCBsaW5lcywgUkZDMzMzOSBVVEMsIGBbTk4vOF1gIHBoYXNlIHByZWZpeDsgZ3JlcC1m" + - "cmllbmRseS4gRGVmYXVsdCBpbiBub24tVFRZLgotICoqYC0tYWNjZXNzaWJsZWAqKiDigJQgUGxh" + - "aW4gb3V0cHV0IHdpdGhvdXQgc3Bpbm5lcnMsIHdpdGggdmVyYm9zZSBzdGF0ZSBtYXJrZXJzIChg" + - "W2NvbXBsZXRlZF1gLCBgW3J1bm5pbmddYCwgYFtwZW5kaW5nXWAsIGBbZmFpbGVkXWApLiBGb3Ig" + - "c2NyZWVuIHJlYWRlcnMgYW5kIGNvbnN0cmFpbmVkIHRlcm1pbmFscy4KLSAqKihubyBmbGFnKSoq" + - "IOKAlCBCdWJibGV0ZWEgVFRZIGRhc2hib2FyZC4gRGVmYXVsdCBpbiBUVFkg4omlMTAww5czMC4g" + - "RG9uJ3QgdXNlIHVuZGVyIGFuIGFnZW50IChjdXJzb3ItdXAgc2VxdWVuY2VzIGFyZSBub2lzeSku" + - "CgpBdXRvLWRldGVjdCBwaWNrcyB0aGUgcmlnaHQgbW9kZSBmb3Igd2hhdGV2ZXIgc3Rkb3V0L3N0" + - "ZGVyciBpcy4gVGhlIENMSSBhbHNvIGhvbm9ycyBgTk9fQ09MT1JgIChhbnkgdmFsdWUg4oaSIGZv" + - "cmNlcyBwbGFpbiksIGBURVJNPWR1bWJgIChmb3JjZXMgcGxhaW4pLCBhbmQgYENJPXRydXRoeWAg" + - "KGZvcmNlcyBwbGFpbiBldmVuIG9uIGEgZmFrZSBUVFkpLiBXaGVuIHRoZSB0ZXJtaW5hbCBpcyBz" + - "bWFsbGVyIHRoYW4gMTAww5czMCwgdGhlIGJ1YmJsZXRlYSByZW5kZXJlciBmYWxscyBiYWNrIHRv" + - "IGEgY29tcGFjdCBsYXlvdXQuIEV4cGxpY2l0IGAtLWpzb25gIGlzIHRoZSByaWdodCBjYWxsIGZv" + - "ciBhZ2VudCBwaXBpbmcuCgojIyBPbiBmYWlsdXJlCgpgbnZjZi1jbGlgIGZhaWx1cmVzIGVtaXQg" + - "c3RydWN0dXJlZCBgcGhhc2VfZmFpbGVkYCBldmVudHMgaW4gSlNPTjoKCmBgYGpzb24KeyJldmVu" + - "dCI6InBoYXNlX2ZhaWxlZCIsInBoYXNlTnVtIjo0LCJwaGFzZSI6ImFwcGx5LWNwIiwKICJlcnJD" + - "YXRlZ29yeSI6ImhlbG1fYXBwbHkiLCJlcnJNZXNzYWdlIjoiaGVsbSBpbnN0YWxsIGFwaS1rZXlz" + - "OiB0aW1lZCBvdXQiLAogInJldHJ5Q2xhc3MiOiJiYWNrb2ZmIiwicmV0cnlBZnRlclNlYyI6NjAs" + - "CiAicmVtZWRpYXRpb24iOlsia3ViZWN0bCBkZXNjcmliZSBwb2QgLW4gY2Fzc2FuZHJhLXN5c3Rl" + - "bSBjYXNzYW5kcmEtMCIsCiAgICAgICAgICAgICAgICAiUmUtcnVuIHdpdGggLS1kZWJ1ZyBmb3Ig" + - "dmVyYm9zZSBoZWxtZmlsZSBvdXRwdXQiXSwKICJyYXciOnsic3VicHJvY2VzcyI6ImhlbG1maWxl" + - "IiwiZXhpdENvZGUiOjEsInN0ZGVyclRhaWwiOiLigKYiLCJrdWJlcm5ldGVzUmVhc29uIjoiRmFp" + - "bGVkU2NoZWR1bGluZyJ9fQpgYGAKClRoZSBgcmV0cnlDbGFzc2AgZmllbGQgdGVsbHMgdGhlIGFn" + - "ZW50IGhvdyB0byBoYW5kbGUgdGhlIGZhaWx1cmU6Cgp8IGByZXRyeUNsYXNzYCB8IE1lYW5pbmcg" + - "fCBBZ2VudCBhY3Rpb24gfAp8LS0tfC0tLXwtLS18CnwgYGltbWVkaWF0ZWAgfCBUcmFuc2llbnQg" + - "YmxpcCB8IFJldHJ5IHRoZSBzYW1lIGB1cGAgY29tbWFuZCBub3cgfAp8IGBiYWNrb2ZmYCB8IFJh" + - "dGUgbGltaXQgLyBwZW5kaW5nIG9wZXJhdGlvbiB8IFdhaXQgYHJldHJ5QWZ0ZXJTZWNgIHNlY29u" + - "ZHMsIHRoZW4gcmV0cnkgfAp8IGBhZnRlcl9yZW1lZGlhdGlvbmAgfCBPcGVyYXRvciBtdXN0IGlu" + - "dGVydmVuZSB8IFN1cmZhY2UgYGVyck1lc3NhZ2VgICsgYHJlbWVkaWF0aW9uYCwgU1RPUC4gRG9u" + - "J3QgYXV0by1yZXRyeS4gfAp8IGBub25lYCB8IE5vbi1yZXRyeWFibGUgfCBTYW1lIGFzIGBhZnRl" + - "cl9yZW1lZGlhdGlvbmAg4oCUIHN1cmZhY2UgYW5kIHN0b3AgfAp8IGB1bmtub3duYCB8IENsYXNz" + - "aWZpZXIgdW5zdXJlIHwgVHJlYXQgY29uc2VydmF0aXZlbHk6IHN1cmZhY2UgYW5kIHN0b3AgfAoK" + - "TmV2ZXIgcmUtcnVuIHdpdGggYC0tZm9yY2VgIChubyBjb21tYW5kIHRha2VzIG9uZSkuIFRoZSBg" + - "cmF3YCBibG9jayBjYXJyaWVzIHRoZSB1bmRlcmx5aW5nIHNpZ25hbCAoc3VicHJvY2VzcyBleGl0" + - "LCBIVFRQIHN0YXR1cywgSzhzIHJlYXNvbikg4oCUIHF1b3RlIHJlbGV2YW50IGZpZWxkcyB3aGVu" + - "IGV4cGxhaW5pbmcgZmFpbHVyZXMgdG8gdGhlIHVzZXIsIGJ1dCBkb24ndCBkdW1wIGBzdGRlcnJU" + - "YWlsYCB2ZXJiYXRpbSBpbnRvIGNoYXQgd2l0aG91dCBzY2FubmluZyBmb3Igc2VjcmV0cyBmaXJz" + - "dC4KCiMjIFF1aWNrIGNvbW1hbmQgcmVmZXJlbmNlCgpgYGBzaApudmNmLWNsaSBzZWxmLWhvc3Rl" + - "ZCBjaGVjayAtLXByZSAgICAgICAgICAgICAgIyBwcmUtZmxpZ2h0Cm52Y2YtY2xpIHNlbGYtaG9z" + - "dGVkIHVwIC0tY2x1c3Rlci1uYW1lPU5BTUUgICAjIG9uZS1zaG90IGluc3RhbGwKbnZjZi1jbGkg" + - "c2VsZi1ob3N0ZWQgc3RhdHVzICAgICAgICAgICAgICAgICAgICMgc25hcHNob3QKbnZjZi1jbGkg" + - "c2VsZi1ob3N0ZWQgc3RhdHVzIC0td2F0Y2ggICAgICAgICAgICMgbGl2ZQpudmNmLWNsaSBpbml0" + - "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtaW50IGFkbWluIHRva2VuIChjbGVh" + - "cnMgYWxsIHNhdmVkIEFQSSBrZXlzKQpudmNmLWNsaSBjbHVzdGVyIHJlZ2lzdGVyIOKApiAgICAg" + - "ICAgICAgICAgICAgICAjIHJlZ2lzdGVyIGNsdXN0ZXIKbnZjZi1jbGkgY2x1c3RlciBsaXN0LXJl" + - "Z2lzdGVyZWQgLS1uY2EtaWQ9PG5jYS1pZD4gIyBsaXN0IHNlbGYtaG9zdGVkIHJlZ2lzdHJhdGlv" + - "bnMKbnZjZi1jbGkgYXBpLWtleSBnZW5lcmF0ZSAtLWRlc2NyaXB0aW9uPeKApiAgICAgIyBtaW50" + - "IGJvdGggZnVuY3Rpb24gYW5kIHRhc2sgQVBJIGtleXMgKHJ1biBhZnRlciBldmVyeSBpbml0KQpu" + - "dmNmLWNsaSBhcGkta2V5IGdlbmVyYXRlIC0tZm9yIGZ1bmN0aW9uIOKApiAgICAjIGZ1bmN0aW9u" + - "IGtleSBvbmx5Cm52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1mb3IgdGFzayDigKYgICAgICAg" + - "ICMgdGFzayBrZXkgb25seQpudmNmLWNsaSBmdW5jdGlvbiBjcmVhdGUgLS1pbnB1dC1maWxlPeKA" + - "piAgICAgICAjIGNyZWF0ZSBmdW5jdGlvbgpudmNmLWNsaSBmdW5jdGlvbiBjcmVhdGUgLS1mdW5j" + - "dGlvbi10eXBlPUxMTSAtLWxsbS1tb2RlbD08c3BlYz4gICMgY3JlYXRlIExMTSBmdW5jdGlvbiBt" + - "ZXRhZGF0YQpudmNmLWNsaSBmdW5jdGlvbiBjcmVhdGUgLS1uYW1lPWxsbS1oZWxtIC0taW5mZXJl" + - "bmNlLXVybD0vIC0taW5mZXJlbmNlLXBvcnQ9ODAwMCBcCiAgLS1mdW5jdGlvbi10eXBlPUxMTSAt" + - "LWhlbG0tY2hhcnQ9PGNoYXJ0PiAtLWhlbG0tY2hhcnQtc2VydmljZT08c2VydmljZT4gLS1sbG0t" + - "bW9kZWw9PHNwZWM+Cm52Y2YtY2xpIGZ1bmN0aW9uIHVwZGF0ZSAtLWxsbS1tb2RlbC11cGRhdGU9" + - "PHNwZWM+ICAjIHVwZGF0ZSBMTE0gcm91dGluZy90b2tlbiBsaW1pdHMKbnZjZi1jbGkgZnVuY3Rp" + - "b24gZGVwbG95IGNyZWF0ZSAtLWlucHV0LWZpbGU94oCmCm52Y2YtY2xpIGZ1bmN0aW9uIGludm9r" + - "ZSAtLWlucHV0LWZpbGU94oCmCgojIFRhc2sgY29tbWFuZHMg4oCUIHJlcXVpcmVzIE5WQ0ZfQkFT" + - "RV9OVkNUX1VSTD1odHRwOi8vPG52Y3QtZ2F0ZXdheT4KbnZjZi1jbGkgdGFzayBjcmVhdGUgLS1u" + - "YW1lPVggLS1ncHU9SDEwMCAtLWluc3RhbmNlLXR5cGU9WSAtLWltYWdlPVoKbnZjZi1jbGkgdGFz" + - "ayBjcmVhdGUgLS1pbnB1dC1maWxlPXRhc2suanNvbiAgICMgZnJvbSBKU09OIGNvbmZpZwpudmNm" + - "LWNsaSB0YXNrIGxpc3QgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsaXN0IGFsbCB0YXNr" + - "cwpudmNmLWNsaSB0YXNrIGxpc3QgLS1zdGF0dXM9UlVOTklORyAgICAgICAgICAgIyBmaWx0ZXIg" + - "Ynkgc3RhdHVzCm52Y2YtY2xpIHRhc2sgZ2V0IFt0YXNrSWRdICAgICAgICAgICAgICAgICAgICAj" + - "IHRhc2sgZGV0YWlscwpudmNmLWNsaSB0YXNrIGV2ZW50cyBbdGFza0lkXSAgICAgICAgICAgICAg" + - "ICAgIyBsaWZlY3ljbGUgZXZlbnRzCm52Y2YtY2xpIHRhc2sgcmVzdWx0cyBbdGFza0lkXSAgICAg" + - "ICAgICAgICAgICAjIHJlc3VsdCBhcnRpZmFjdHMKbnZjZi1jbGkgdGFzayBjYW5jZWwgW3Rhc2tJ" + - "ZF0KbnZjZi1jbGkgdGFzayBkZWxldGUgW3Rhc2tJZF0KYGBgCgojIyBGZWVkYmFjawoKSWYgdGhl" + - "IHVzZXIgaGl0cyBhIGJ1ZyBvciBsaW1pdGF0aW9uLCBmaWxlIGFuIGlzc3VlIHRocm91Z2ggdGhl" + - "IHByb2plY3QgdHJhY2tlci4gRG9uJ3QgaW5jbHVkZSBzZWNyZXRzLgpQSwcIzYEw5E1hAABNYQAA" + - "UEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAAzAAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkv" + - "ZXhhbXBsZXMvY2ktcGlwZWxpbmVzLm1kVVQFAAEAps4SIyBDSSBwaXBlbGluZSBwYXR0ZXJucwoK" + - "SG93IHRvIGRyaXZlIGBudmNmLWNsaWAgZnJvbSBDSSAoR2l0TGFiIENJLCBHaXRIdWIgQWN0aW9u" + - "cywgSmVua2lucywgQXJnb0NEKS4gUGF0dGVybnMgdGhhdCBzdXJmYWNlIGZyZXF1ZW50bHkuCgoj" + - "IyBCYXNpYyBpbnN0YWxsIHBpcGVsaW5lCgpgYGB5YW1sCiMgR2l0TGFiIENJIGV4YW1wbGUKZGVw" + - "bG95X252Y2Y6CiAgc3RhZ2U6IGRlcGxveQogIGltYWdlOiBudmNyLmlvLzA2NTExNTUyMTU4NjQ5" + - "NzkvbmNwLWRldi9udmNmLWNsaToxLjQuMAogIHZhcmlhYmxlczoKICAgIEtVQkVDT05GSUc6ICRL" + - "VUJFQ09ORklHX0ZJTEUKICBzY3JpcHQ6CiAgICAtIG52Y2YtY2xpIHNlbGYtaG9zdGVkIGNoZWNr" + - "IC0tcHJlIC0tanNvbiB8IGpxIC1lICcuZXZlbnQgIT0gInBoYXNlX2ZhaWxlZCInIHx8IGV4aXQg" + - "MgogICAgLSBudmNmLWNsaSBzZWxmLWhvc3RlZCB1cCAtLWNsdXN0ZXItbmFtZT0kQ0xVU1RFUl9O" + - "QU1FIC0tdG9rZW49JE5WQ0ZfQURNSU5fSldUIC0tbm9uLWludGVyYWN0aXZlIC0tanNvbgogICAg" + - "LSBudmNmLWNsaSBzZWxmLWhvc3RlZCBzdGF0dXMgLS1qc29uIHwganEgLWUgJy52ZXJkaWN0ID09" + - "ICJoZWFsdGh5IicKYGBgCgpOb3RlczoKLSBgLS1ub24taW50ZXJhY3RpdmUgLS10b2tlbj0kSldU" + - "YCBpcyByZXF1aXJlZCBpbiBDSTsgbmV2ZXIgdXNlIGludGVyYWN0aXZlIGBpbml0YC4KLSBBbHdh" + - "eXMgYC0tanNvbmAgZm9yIG1hY2hpbmUtcGFyc2luZy4KLSBGaW5hbCBzdGF0dXMgY2hlY2sgZ2F0" + - "ZXMgZG93bnN0cmVhbSBzdGFnZXMgb24gYHZlcmRpY3QgPT0gImhlYWx0aHkiYC4KCiMjIEdpdE9w" + - "cyAoQXJnbyAvIEZsdXgpIHBhdHRlcm4KCkNJIGRvZXNuJ3QgYGt1YmVjdGwgYXBwbHlgIOKAlCBp" + - "bnN0ZWFkLCByZW5kZXIgbWFuaWZlc3RzLCBjb21taXQgdGhlbSwgbGV0IHRoZSBjb250cm9sbGVy" + - "IGFwcGx5LgoKYGBgeWFtbApyZW5kZXI6CiAgc2NyaXB0OgogICAgLSBudmNmLWNsaSBzZWxmLWhv" + - "c3RlZCBpbnN0YWxsIC0tY29udHJvbC1wbGFuZSAtLW5vLWFwcGx5ID4gcmVuZGVyZWQvY29udHJv" + - "bC1wbGFuZS55YW1sCiAgICAtIG52Y2YtY2xpIHNlbGYtaG9zdGVkIGluc3RhbGwgLS1jb21wdXRl" + - "LXBsYW5lIC0tY2x1c3Rlci1uYW1lPSROQU1FIC0tbm8tYXBwbHkgPiByZW5kZXJlZC9jb21wdXRl" + - "LXBsYW5lLnlhbWwKICAgIC0gZ2l0IGFkZCByZW5kZXJlZC8gJiYgZ2l0IGNvbW1pdCAtbSAiZGVw" + - "bG95IE5WQ0YgJFRBRyIgJiYgZ2l0IHB1c2gKYGBgCgpUaGVuIEFyZ29DRCBvciBGbHV4IHdhdGNo" + - "ZXMgYHJlbmRlcmVkL2AgYW5kIGFwcGxpZXMuIFRoZSBDTEkgbmV2ZXIgdG91Y2hlcyB0aGUgY2x1" + - "c3RlciBkaXJlY3RseS4KCkZvciB0aGUgcmVnaXN0ZXIgc3RlcCAod2hpY2ggbXV0YXRlcyBJQ01T" + - "LCBub3QganVzdCBLOHMpOgoKYGBgeWFtbApyZWdpc3RlcjoKICBzY3JpcHQ6CiAgICAtIG52Y2Yt" + - "Y2xpIGNsdXN0ZXIgcmVnaXN0ZXIgLS1uYW1lPSROQU1FIC0tbmNhLWlkPSROQ0EgLS1yZWdpb249" + - "JFJFR0lPTiAtLWlnbm9yZS1leGlzdGluZwpgYGAKCmAtLWlnbm9yZS1leGlzdGluZ2AgaXMgdGhl" + - "IEdpdE9wcy1mcmllbmRseSBpZGVtcG90ZW50IGNvbnRyYWN0LgoKIyMgTXVsdGktY2x1c3RlciBw" + - "aXBlbGluZQoKV2hlbiB0aGUgcGlwZWxpbmUgbWFuYWdlcyBtYW55IGNvbXB1dGUgY2x1c3RlcnMg" + - "YWdhaW5zdCBvbmUgY29udHJvbCBwbGFuZToKCmBgYHlhbWwKZGVwbG95X2NvbXB1dGVfcGxhbmVz" + - "OgogIHBhcmFsbGVsOgogICAgbWF0cml4OgogICAgICAtIENMVVNURVI6IG5jcC1lYXN0LTEKICAg" + - "ICAgICBDT05URVhUOiBhZG1pbkBncHUtZWFzdC0xCiAgICAgIC0gQ0xVU1RFUjogbmNwLXdlc3Qt" + - "MQogICAgICAgIENPTlRFWFQ6IGFkbWluQGdwdS13ZXN0LTEKICAgICAgLSBDTFVTVEVSOiBuY3At" + - "ZXUtMQogICAgICAgIENPTlRFWFQ6IGFkbWluQGdwdS1ldS0xCiAgc2NyaXB0OgogICAgLSBudmNm" + - "LWNsaSBzZWxmLWhvc3RlZCB1cAogICAgICAgIC0tY2x1c3Rlci1uYW1lPSRDTFVTVEVSCiAgICAg" + - "ICAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9JENPTlRFWFQKICAgICAgICAtLWljbXMtdXJsPSRJ" + - "Q01TX1BVQkxJQ19VUkwKICAgICAgICAtLXRva2VuPSROVkNGX0FETUlOX0pXVAogICAgICAgIC0t" + - "bm9uLWludGVyYWN0aXZlCiAgICAgICAgLS1qc29uCmBgYAoKRWFjaCBwYXJhbGxlbCBqb2IgcmVn" + - "aXN0ZXJzICsgaW5zdGFsbHMgb25lIGNvbXB1dGUgcGxhbmUgYWdhaW5zdCB0aGUgc2hhcmVkIGNv" + - "bnRyb2wgcGxhbmUuIEZhaWx1cmVzIGFyZSBpc29sYXRlZC4KCiMjIFBsYW4tb25seSBwcmV2aWV3" + - "IGluIFBScwoKYGBgeWFtbApwcmV2aWV3OgogIHJ1bGVzOgogICAgLSBpZjogJENJX1BJUEVMSU5F" + - "X1NPVVJDRSA9PSAibWVyZ2VfcmVxdWVzdF9ldmVudCIKICBzY3JpcHQ6CiAgICAtIHwKICAgICAg" + - "bnZjZi1jbGkgc2VsZi1ob3N0ZWQgdXAgXAogICAgICAgIC0tY2x1c3Rlci1uYW1lPSRDTFVTVEVS" + - "X05BTUUgXAogICAgICAgIC0tcGxhbi1vbmx5IFwKICAgICAgICAtLWpzb24gfCB0ZWUgcGxhbi5q" + - "c29ubAogICAgLSBqcSAtcyAnLlswXScgcGxhbi5qc29ubCA+IHBsYW4uanNvbgogICAgLSAnZ2l0" + - "bGFiLW1yLWNvbW1lbnQgIiMjIE5WQ0YgZGVwbG95IHBsYW5cblxuXGBcYFxganNvblxuJChjYXQg" + - "cGxhbi5qc29uKVxuXGBcYFxgIicKYGBgCgpgLS1wbGFuLW9ubHlgIGV4aXRzIDAgd2l0aG91dCBj" + - "aGFuZ2luZyBjbHVzdGVyIHN0YXRlOyB0aGUgSlNPTkwgb3V0cHV0IGxpc3RzIGVhY2ggcGhhc2Ug" + - "KyBFVEEuIFJlbmRlcnMgbmljZWx5IGFzIGFuIE1SIGNvbW1lbnQuClBLBwghxsiG8AoAAPAKAABQ" + - "SwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADQACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9l" + - "eGFtcGxlcy9tdWx0aS1jbHVzdGVyLm1kVVQFAAEAps4SIyBNdWx0aS1jbHVzdGVyIHBhdHRlcm5z" + - "CgpFeGFtcGxlcyBvZiBzcGxpdC1jbHVzdGVyICsgbWFueS1jb21wdXRlLXBsYW5lIG9wZXJhdGlv" + - "bi4KCiMjIE9uZSBjb250cm9sIHBsYW5lICsgTiBjb21wdXRlIHBsYW5lcwoKVGhlIGNhbm9uaWNh" + - "bCBtdWx0aS1jbHVzdGVyIHRvcG9sb2d5LiBFYWNoIGNvbXB1dGUgcGxhbmUgaXMgcmVnaXN0ZXJl" + - "ZCBzZXBhcmF0ZWx5OgoKYGBgc2gKIyAxLiBCcmluZyB1cCB0aGUgY29udHJvbCBwbGFuZSAob25l" + - "LXRpbWUsIG9uIHRoZSBjb250cm9sLXBsYW5lIGNsdXN0ZXIpOgpLVUJFQ09ORklHPWNwLnlhbWwg" + - "bnZjZi1jbGkgc2VsZi1ob3N0ZWQgaW5zdGFsbCAtLWNvbnRyb2wtcGxhbmUgfCBrdWJlY3RsIGFw" + - "cGx5IC1mIC0KbnZjZi1jbGkgc2VsZi1ob3N0ZWQgY2hlY2sgLS1jb250cm9sLXBsYW5lIC0td2Fp" + - "dCA1bQoKIyAyLiBSZWdpc3RlciArIGluc3RhbGwgZWFjaCBjb21wdXRlIHBsYW5lOgpmb3IgQ1RY" + - "IGluIGFkbWluQGdwdS1lYXN0LTEgYWRtaW5AZ3B1LXdlc3QtMSBhZG1pbkBncHUtZXUtMTsgZG8K" + - "ICBOQU1FPSQoZWNobyAiJENUWCIgfCBjdXQgLWRAIC1mMikKICBudmNmLWNsaSBzZWxmLWhvc3Rl" + - "ZCB1cCBcCiAgICAtLWNsdXN0ZXItbmFtZT0kTkFNRSBcCiAgICAtLWNvbXB1dGUtcGxhbmUtY29u" + - "dGV4dD0kQ1RYIFwKICAgIC0taWNtcy11cmw9aHR0cHM6Ly9pY21zLm52Y2YuZXhhbXBsZS5jb20g" + - "XAogICAgLS10b2tlbj0kTlZDRl9BRE1JTl9KV1QgXAogICAgLS1ub24taW50ZXJhY3RpdmUgXAog" + - "ICAgLS1qc29uCmRvbmUKCiMgMy4gVmVyaWZ5IGFsbCBjb21wdXRlIHBsYW5lcyByZWdpc3RlcmVk" + - "OgpudmNmLWNsaSBjbHVzdGVyIGxpc3QtcmVnaXN0ZXJlZCAtLW5jYS1pZD0kTkNBX0lEIC0taWNt" + - "cy11cmw9JElDTVMgLS1qc29uIFwKICB8IGpxICcuY2x1c3RlcnNbXSB8IHtuYW1lOiAuY2x1c3Rl" + - "ck5hbWUsIHN0YXR1cywgbnZjYVZlcnNpb259JwpgYGAKCiMjIENvbXB1dGUtcGxhbmUtb25seSBv" + - "cGVyYXRvciBzY2VuYXJpbwoKVGhlIG9wZXJhdG9yIGhhcyBrdWJlY3RsIGFjY2VzcyB0byBPTkUg" + - "Y29tcHV0ZSBwbGFuZSBvbmx5IOKAlCB0aGUgY29udHJvbCBwbGFuZSBpcyBvcGVyYXRlZCBieSBz" + - "b21lb25lIGVsc2UgKGUuZy4gWW90dGEgcnVucyB0aGUgY29udHJvbCBwbGFuZSBmb3IgYSBjdXN0" + - "b21lcikuCgpgYGBzaAojIE1pbnQgYSB0b2tlbiB2aWEgdGhlIHB1YmxpYyBhcGkgZ2F0ZXdheSAo" + - "dGhlIGNvbnRyb2wgcGxhbmUncyBBUEkgS2V5cwojIHNlcnZpY2UgaXMgcmVhY2hhYmxlIHZpYSBh" + - "cGkubnZjZi5leGFtcGxlLmNvbSDigJQgbm8ga3ViZWN0bCBhY2Nlc3MgbmVlZGVkKToKbnZjZi1j" + - "bGkgaW5pdCAtLWFwaS11cmw9aHR0cHM6Ly9hcGkubnZjZi5leGFtcGxlLmNvbQoKIyBSdW4gcHJl" + - "LWZsaWdodCBzY29wZWQgdG8gdGhlIGNvbXB1dGUgcGxhbmUgb25seToKbnZjZi1jbGkgc2VsZi1o" + - "b3N0ZWQgY2hlY2sgLS1wcmUgXAogIC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0PWFkbWluQGdwdTEg" + - "XAogIC0taWNtcy11cmw9aHR0cHM6Ly9pY21zLm52Y2YuZXhhbXBsZS5jb20gXAogIC0tanNvbgoK" + - "IyBCcmluZyB1cCBqdXN0IHRoZSBjb21wdXRlIHBsYW5lOgpudmNmLWNsaSBzZWxmLWhvc3RlZCB1" + - "cCBcCiAgLS1jbHVzdGVyLW5hbWU9bXktY29tcHV0ZS0xIFwKICAtLWNvbXB1dGUtcGxhbmUtY29u" + - "dGV4dD1hZG1pbkBncHUxIFwKICAtLWljbXMtdXJsPWh0dHBzOi8vaWNtcy5udmNmLmV4YW1wbGUu" + - "Y29tIFwKICAtLXRva2VuPSRBRE1JTl9KV1QgXAogIC0tbm9uLWludGVyYWN0aXZlCgojIFN0YXR1" + - "cyAoY29tcHV0ZS1vbmx5IOKAlCBvcGVyYXRvciBjYW4ndCBzZWUgY29udHJvbC1wbGFuZSBjb21w" + - "b25lbnQgaGVhbHRoKToKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgc3RhdHVzIFwKICAtLWNvbXB1dGUt" + - "cGxhbmUtY29udGV4dD1hZG1pbkBncHUxIFwKICAtLWljbXMtdXJsPWh0dHBzOi8vaWNtcy5udmNm" + - "LmV4YW1wbGUuY29tCmBgYAoKIyMgRnVuY3Rpb25zIHRhcmdldGluZyBzcGVjaWZpYyBjb21wdXRl" + - "IHBsYW5lcwoKV2hlbiB5b3UgaGF2ZSBtdWx0aXBsZSBjb21wdXRlIHBsYW5lcyBhbmQgd2FudCBh" + - "IGZ1bmN0aW9uIHRvIGRlcGxveSB0byBvbmU6CgpgYGBqc29uCnsKICAiZnVuY3Rpb25JZCI6ICI8" + - "Zm5faWQ+IiwKICAidmVyc2lvbklkIjogIjx2ZXJfaWQ+IiwKICAiZGVwbG95bWVudFNwZWNpZmlj" + - "YXRpb25zIjogW3sKICAgICJncHUiOiAiSDEwMCIsCiAgICAiaW5zdGFuY2VUeXBlIjogIk5DUC5H" + - "UFUuSDEwMF8xeCIsCiAgICAibWluSW5zdGFuY2VzIjogMSwKICAgICJtYXhJbnN0YW5jZXMiOiAx" + - "LAogICAgImNsdXN0ZXJzIjogWyJncHUtZWFzdC0xIl0KICB9XQp9CmBgYAoKVGhlIGBjbHVzdGVy" + - "c2AgYXJyYXkgKHVzaW5nIGNsdXN0ZXIgbmFtZXMsIG5vdCBJRHMpIGxpbWl0cyBzY2hlZHVsaW5n" + - "IHRvIHRob3NlIGNvbXB1dGUgcGxhbmVzLiBPbWl0IHRvIGxldCBJQ01TIGNob29zZSBhbnkgY29t" + - "cHV0ZSBwbGFuZSB3aXRoIGEgbWF0Y2hpbmcgU0tVLgoKIyMgU3RhdHVzIGZhbi1vdXQgYWNyb3Nz" + - "IGNvbXB1dGUgcGxhbmVzCgpgYGBzaAojIExpc3QgYWxsIHJlZ2lzdGVyZWQgY29tcHV0ZSBwbGFu" + - "ZXM6Cm52Y2YtY2xpIGNsdXN0ZXIgbGlzdC1yZWdpc3RlcmVkIC0tbmNhLWlkPSROQ0FfSUQgLS1p" + - "Y21zLXVybD0kSUNNUyAtLWpzb24gXAogIHwganEgLXIgJy5jbHVzdGVyc1tdLmNsdXN0ZXJOYW1l" + - "JyA+IGNsdXN0ZXJzLnR4dAoKIyBTdGF0dXMgc25hcHNob3QgcGVyIGNvbXB1dGUgcGxhbmUgKGFz" + - "c3VtaW5nIGVhY2ggY29udGV4dCBuYW1lIG1hdGNoZXMpOgp3aGlsZSByZWFkIE5BTUU7IGRvCiAg" + - "ZWNobyAiPT09ICROQU1FID09PSIKICBudmNmLWNsaSBzZWxmLWhvc3RlZCBzdGF0dXMgXAogICAg" + - "LS1jbHVzdGVyLW5hbWU9JE5BTUUgXAogICAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9YWRtaW5A" + - "JE5BTUUgXAogICAgLS1qc29uIHwganEgLWMgJ3tjbHVzdGVyOi5jbHVzdGVyLCB2ZXJkaWN0Oi52" + - "ZXJkaWN0LCByZWNvbmNpbGU6LnJlY29uY2lsZUFnZVNlY30nCmRvbmUgPCBjbHVzdGVycy50eHQK" + - "YGBgCgpBIGZ1dHVyZSBNKzExIG1pbGVzdG9uZSB3aWxsIGFkZCBuYXRpdmUgZmFuLW91dCAoYHN0" + - "YXR1cyAtLWFsbC1jb21wdXRlLXBsYW5lc2ApIHNvIHRoaXMgZG9lc24ndCBuZWVkIGEgc2hlbGwg" + - "bG9vcC4KUEsHCKEU44FdDAAAXQwAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAANwAJAGRhdGEv" + - "bnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Byb21wdHMvYWRkLWNvbXB1dGUtcGxhbmUubWRVVAUAAQCm" + - "zhIjIEFkZCBhIGNvbXB1dGUgcGxhbmUgdG8gYW4gZXhpc3RpbmcgY29udHJvbCBwbGFuZQoKVXNl" + - "ciBoYXMgYSB3b3JraW5nIE5WQ0YgY29udHJvbCBwbGFuZSAocnVubmluZyBzb21ld2hlcmUpIGFu" + - "ZCB3YW50cyB0byByZWdpc3RlciBhIG5ldyBHUFUgY2x1c3RlciBhZ2FpbnN0IGl0LiBUaGlzIGlz" + - "IHRoZSBtdWx0aS1jbHVzdGVyIHNjYWxpbmcgcGF0aDogb25lIGNvbnRyb2wgcGxhbmUg4oaSIE4g" + - "Y29tcHV0ZSBwbGFuZXMuCgojIyBQcmVyZXF1aXNpdGVzIHRoZSB1c2VyIG11c3QgaGF2ZQoKLSAq" + - "Kmt1YmVjdGwgY29udGV4dCBmb3IgdGhlIG5ldyBjb21wdXRlIHBsYW5lKiogaW4gdGhlaXIgYEtV" + - "QkVDT05GSUdgLgotICoqUHVibGljIElDTVMgVVJMKiogb2YgdGhlIGV4aXN0aW5nIGNvbnRyb2wg" + - "cGxhbmUgKGUuZy4gYGh0dHBzOi8vaWNtcy5udmNmLmV4YW1wbGUuY29tYCkuCi0gKipBZG1pbiBK" + - "V1QqKiBmb3IgdGhlIGNvbnRyb2wgcGxhbmUncyBhY2NvdW50LCBPUiBhYmlsaXR5IHRvIG1pbnQg" + - "b25lIHZpYSBgbnZjZi1jbGkgaW5pdGAgYWdhaW5zdCB0aGUgY29udHJvbCBwbGFuZSdzIHB1Ymxp" + - "YyBhcGkgZW5kcG9pbnQuIChBZG1pbiB0b2tlbnMgY29tZSBmcm9tIHRoZSBBUEkgS2V5cyBzZXJ2" + - "aWNlIHZpYSB0aGUgcHVibGljIGFwaSBnYXRld2F5IOKAlCBrdWJlY3RsIGFjY2VzcyB0byB0aGUg" + - "Y29udHJvbCBwbGFuZSBpcyBOT1QgcmVxdWlyZWQgdG8gb2J0YWluIG9uZS4pCi0gQSB1bmlxdWUg" + - "YC0tY2x1c3Rlci1uYW1lYCB0aGF0IGRvZXNuJ3QgY29sbGlkZSB3aXRoIGFscmVhZHktcmVnaXN0" + - "ZXJlZCBjbHVzdGVycy4gVXNlIGBudmNmLWNsaSBjbHVzdGVyIGxpc3QtcmVnaXN0ZXJlZCAtLW5j" + - "YS1pZD0kTkNBX0lEIC0taWNtcy11cmw9JElDTVNgIHRvIGNoZWNrLgoKIyMgU3RlcHMKCjEuICoq" + - "QXNrIGZvciBpbnB1dHM6KioKICAgLSBgLS1jbHVzdGVyLW5hbWU9PHVuaXF1ZT5gIOKAlCBtdXN0" + - "IGJlIHVuaXF1ZSB3aXRoaW4gdGhlIGNvbnRyb2wgcGxhbmUncyBOQ0Egc2NvcGUKICAgLSBgLS1j" + - "b21wdXRlLXBsYW5lLWNvbnRleHQ9PGNvbnRleHQ+YCDigJQgdGhlIG5ldyBHUFUgY2x1c3Rlcidz" + - "IGt1YmVjdGwgY29udGV4dAogICAtIGAtLWljbXMtdXJsPTxodHRwczovL2ljbXMubnZjZi5leGFt" + - "cGxlLmNvbT5gIOKAlCBjb250cm9sIHBsYW5lJ3MgcHVibGljIElDTVMgVVJMCiAgIC0gR1BVIHR5" + - "cGU/IChkZWZhdWx0IGBIMTAwYCwgYnV0IGFzaykKCjIuICoqUHJlLWZsaWdodCBqdXN0IHRoZSBj" + - "b21wdXRlIHBsYW5lOioqCgogICBgYGBzaAogICBudmNmLWNsaSBzZWxmLWhvc3RlZCBjaGVjayAt" + - "LXByZSBcCiAgICAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9JENUWCBcCiAgICAgLS1pY21zLXVy" + - "bD0kSUNNUyBcCiAgICAgLS1qc29uIHwganEgLWMgLgogICBgYGAKCiAgIFRoaXMgdmFsaWRhdGVz" + - "IHRoZSBHUFUgb3BlcmF0b3IgaXMgaW5zdGFsbGVkLCBHUFUgbm9kZSBsYWJlbHMgYXJlIHByZXNl" + - "bnQsIGFuZCBJQ01TIGlzIHJlYWNoYWJsZSB2aWEgSFRUUC4gQWRkcmVzcyBhbnkgZmFpbHVyZXMg" + - "YmVmb3JlIHByb2NlZWRpbmcuCgozLiAqKlJ1biBgYWRkLWNvbXB1dGUtcGxhbmVgOioqCgogICBg" + - "YGBzaAogICBudmNmLWNsaSBzZWxmLWhvc3RlZCBhZGQtY29tcHV0ZS1wbGFuZSBcCiAgICAgLS1j" + - "bHVzdGVyLW5hbWU9JE5BTUUgXAogICAgIC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0PSRDVFggXAog" + - "ICAgIC0taWNtcy11cmw9JElDTVMgXAogICAgIC0tdG9rZW49JEpXVCBcCiAgICAgLS1ub24taW50" + - "ZXJhY3RpdmUgXAogICAgIC0tanNvbgogICBgYGAKCiAgIFRoaXMgaXMgYSBzZXBhcmF0ZSBzdWJj" + - "b21tYW5kIGZyb20gYHVwYC4gSXQgcnVucyBvbmx5IHRoZSBjb21wdXRlLXBsYW5lLXJlbGV2YW50" + - "IHBoYXNlczogMSAoY29tcHV0ZS1wbGFuZSBwcmVmbGlnaHQpLCA1IChyZWdpc3RlciksIDYgKGNv" + - "bXB1dGUtcGxhbmUgYXBwbHkpLCA4IChmaW5hbCBoZWFsdGggb24gdGhlIG5ldyBjb21wdXRlIHBs" + - "YW5lKS4gSXQgZG9lcyBOT1QgdG91Y2ggdGhlIGNvbnRyb2wgcGxhbmUgYW5kIGRvZXMgTk9UIGFj" + - "Y2VwdCBgLS1jb250cm9sLXBsYW5lLWNvbnRleHRgIOKAlCB0aGUgY29udHJvbCBwbGFuZSBpcyBy" + - "ZWFjaGVkIG92ZXIgSFRUUFMgYXQgYC0taWNtcy11cmxgLiBgLS10b2tlbmAgaXMgcmVxdWlyZWQg" + - "YmVjYXVzZSB0aGVyZSdzIG5vIGt1YmVjdGwgcGF0aCB0byBtaW50IG9uZSBmcm9tLgoKNC4gKipW" + - "ZXJpZnkuKiogYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHN0YXR1cyAtLWNsdXN0ZXItbmFtZT0kTkFN" + - "RSAtLWpzb24gfCBqcWAg4oCUIGV4cGVjdCBgdmVyZGljdDogImhlYWx0aHkiYC4gVGhlIFJlZ2lz" + - "dGVyZWQgQ29tcHV0ZSBQbGFuZXMgcGFuZWwgZnJvbSBJQ01TIHNob3VsZCBub3cgbGlzdCB0aGUg" + - "bmV3IGNsdXN0ZXIuCgo1LiAqKlNtb2tlLioqIFtkZXBsb3ktYW5kLWludm9rZS5tZF0oZGVwbG95" + - "LWFuZC1pbnZva2UubWQpIOKAlCBkZXBsb3kgYSBzbWFsbCBmdW5jdGlvbiB0byB0aGUgbmV3IGNv" + - "bXB1dGUgcGxhbmUgdG8gY29uZmlybSBzY2hlZHVsaW5nIHdvcmtzLgoKIyMgV2hhdCBpZiBhIGNs" + - "dXN0ZXIgd2l0aCB0aGUgc2FtZSBuYW1lIGFscmVhZHkgZXhpc3RzPwoKYGFkZC1jb21wdXRlLXBs" + - "YW5lYCdzIHJlZ2lzdGVyIHBoYXNlIHVzZXMgYC0taWdub3JlLWV4aXN0aW5nYCBzZW1hbnRpY3Mg" + - "4oCUIGl0J2xsIG1hdGNoIHRoZSBleGlzdGluZyBJQ01TIHJvdyBhbmQgcmV1c2UgaXRzIGNsdXN0" + - "ZXJJZC4gVHdvIHNjZW5hcmlvczoKCi0gKipSZS1yZWdpc3RlcmluZyB0aGUgc2FtZSBjbHVzdGVy" + - "KiogKHJlLXJ1bm5pbmcgb24gdGhlIHNhbWUgY29tcHV0ZSBwbGFuZSB0aGF0IHdhcyBwcmV2aW91" + - "c2x5IHJlZ2lzdGVyZWQpOiBleHBlY3RlZCwgbm8tb3Agc2VtYW50aWNzLgotICoqRGlmZmVyZW50" + - "IHBoeXNpY2FsIGNsdXN0ZXIgYnV0IHNhbWUgbmFtZSoqOiB0aGUgc2Vjb25kIGF0dGVtcHQgd2ls" + - "bCByZXVzZSB0aGUgSUNNUyByb3csIGJ1dCB0aGUgbmV3IGNvbXB1dGUgcGxhbmUncyBKV0tTIHdp" + - "bGwgYmUgc2lsZW50bHkgKnJlcGxhY2VkKiDigJQgdGhlIG9sZCBjb21wdXRlIHBsYW5lJ3MgTlZD" + - "QSBhZ2VudCB3aWxsIHN0YXJ0IGZhaWxpbmcgUFNBVCBhdXRoLiAqKkNvbmZpcm0gd2l0aCB0aGUg" + - "dXNlcioqIHRoYXQgdGhleSBtZWFudCB0byBvdmVyd3JpdGUuCgpXaGVuIGluIGRvdWJ0LCBydW4g" + - "YG52Y2YtY2xpIGNsdXN0ZXIgbGlzdC1yZWdpc3RlcmVkIC0tbmNhLWlkPSROQ0FfSUQgLS1pY21z" + - "LXVybD0kSUNNU2AgZmlyc3QgYW5kIGFzayB0aGUgdXNlciBiZWZvcmUgcHJvY2VlZGluZyB3aXRo" + - "IGEgbmFtZSB0aGF0IGFscmVhZHkgZXhpc3RzLgpQSwcIQidJDwUNAAAFDQAAUEsDBBQACAAAAAAA" + - "IQAAAAAAAAAAAAAAAAA5AAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy9jcmVh" + - "dGUtYW5kLXJ1bi10YXNrLm1kVVQFAAEAps4SIyBDcmVhdGUgYW5kIHJ1biBhIHRhc2sKClN0YW5k" + - "YXJkIGZsb3c6IG1pbnQgQVBJIGtleXMgLT4gdGFzayBDUkVBVEUgLT4gbW9uaXRvciAtPiByZXRy" + - "aWV2ZSByZXN1bHRzIC0+IGNsZWFudXAuCgojIyAxLiBNaW50IEFQSSBrZXlzCgpUaGUgYWRtaW4g" + - "dG9rZW4gZnJvbSBgaW5pdGAgZG9lcyBub3QgY2FycnkgdGFzayBpbnZvY2F0aW9uIHNjb3BlLiBH" + - "ZW5lcmF0ZSBBUEkga2V5czoKCmBgYHNoCm52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1kZXNj" + - "cmlwdGlvbj0idGFzayBzbW9rZSB0ZXN0IiAtLWV4cGlyZXMtaW49OGgKIyAtPiBmdW5jdGlvbiBr" + - "ZXk6IG52YXBpLS4uLgojIC0+IHRhc2sga2V5OiBudmFwaS0uLi4KYGBgCgpCb3RoIGtleXMgYXJl" + - "IHNhdmVkIHRvIENMSSBzdGF0ZS4gVG8gbWludCBvbmx5IHRoZSB0YXNrIGtleToKCmBgYHNoCm52" + - "Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1mb3IgdGFzayAtLWRlc2NyaXB0aW9uPSJ0YXNrIHNt" + - "b2tlIHRlc3QiIC0tZXhwaXJlcy1pbj04aApgYGAKClRvIHZhbGlkYXRlIGVhY2gga2V5IGltbWVk" + - "aWF0ZWx5IGFmdGVyIG1pbnRpbmc6CgpgYGBzaApudmNmLWNsaSBhcGkta2V5IGdlbmVyYXRlIC0t" + - "ZGVzY3JpcHRpb249InRhc2sgc21va2UgdGVzdCIgLS1leHBpcmVzLWluPThoIC0tdmFsaWRhdGUK" + - "IyAtPiBmdW5jdGlvbiBBUEkga2V5IHZhbGlkYXRpb24gcGFzc2VkIQojIC0+IHRhc2sgQVBJIGtl" + - "eSB2YWxpZGF0aW9uIHBhc3NlZCEKYGBgCgpOZXZlciBlY2hvIHRoZSBrZXkgdmFsdWUgKG52YXBp" + - "LS4uLikgaW50byBjaGF0IG9yIGxvZ3MuIFJlcG9ydCBvbmx5IHRoYXQgdGhlIGtleSB3YXMgbWlu" + - "dGVkLCBpdHMgZGVzY3JpcHRpb24sIGFuZCBpdHMgZXhwaXJ5IOKAlCBuZXZlciB0aGUgdmFsdWUg" + - "aXRzZWxmLgoKIyMjIEZyZXNoIHNlc3Npb24gcHJlLWZsaWdodAoKQmVmb3JlIHJ1bm5pbmcgYW55" + - "IGB0YXNrYCBjb21tYW5kIGluIGEgZnJlc2ggYWdlbnQgc2Vzc2lvbiwgdmVyaWZ5IGNyZWRlbnRp" + - "YWxzOgoKMS4gQ2hlY2sgd2hldGhlciBgTlZDRl9BUElfS0VZYCBpcyBzZXQ6CiAgIGBgYHNoCiAg" + - "IHByaW50ZW52IE5WQ0ZfQVBJX0tFWSA+IC9kZXYvbnVsbCAyPiYxICYmIGVjaG8gc2V0IHx8IGVj" + - "aG8gdW5zZXQKICAgYGBgCjIuIElmIHVuc2V0LCByZWFkIHRoZSBzdG9yZWQga2V5IGV4cGlyeSB3" + - "aXRob3V0IHByaW50aW5nIHRoZSB2YWx1ZToKICAgYGBgc2gKICAgcHl0aG9uMyAtYyAiaW1wb3J0" + - "IGpzb24scGF0aGxpYjsgcz1qc29uLmxvYWRzKHBhdGhsaWIuUGF0aCgnfi8ubnZjZi1jbGkuc3Rh" + - "dGUnKS5leHBhbmR1c2VyKCkucmVhZF90ZXh0KCkpOyBwcmludChzLmdldCgnbnZjdEFwaUtleUV4" + - "cGlyYXRpb24nLCdtaXNzaW5nJykpIgogICBgYGAKMy4gSWYgdGhlIGV4cGlyeSBpcyBpbiB0aGUg" + - "cGFzdCBvciBtaXNzaW5nLCByZWdlbmVyYXRlOgogICBgYGBzaAogICBudmNmLWNsaSByZWZyZXNo" + - "CiAgIG52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1mb3IgdGFzayAtLWRlc2NyaXB0aW9uPSJ0" + - "YXNrLWtleSIgLS1leHBpcmVzLWluPTI0aCAtLXZhbGlkYXRlCiAgIGBgYAo0LiBJbmplY3QgdGhl" + - "IHN0b3JlZCBrZXkgaW50byB0aGUgc3VicHJvY2VzcyBlbnYgd2l0aG91dCBsb2dnaW5nIHRoZSB2" + - "YWx1ZS4gVXNlIGEgc2hlbGwgc3Vic2hlbGwgb3IgZW52IHByZWZpeCDigJQgbmV2ZXIgcHJpbnQg" + - "dGhlIGtleSBpbnRvIGNoYXQuCgpFcnJvciBjbGFzc2lmaWNhdGlvbjoKLSAibWlzc2luZyBhdXRo" + - "ZW50aWNhdGlvbiBjcmVkZW50aWFscyIgb3IgZXhpdCAyOiBrZXkgbm90IGluamVjdGVkOyByZXBl" + - "YXQgcHJlLWZsaWdodC4KLSBIVFRQIDQwMzoga2V5IGV4cGlyZWQgb3Igd3JvbmcgYXVkaWVuY2U7" + - "IHJlZ2VuZXJhdGUuCi0gRW1wdHkgdGFzayBsaXN0OiB2YWxpZDsgbm8gdGFza3MgZXhpc3QgeWV0" + - "LgoKIyMgMi4gVGFzayBDUkVBVEU6IGNvbnRhaW5lcgoKRGVmaW5lIHRoZSB0YXNrIGluIGEgSlNP" + - "TiBmaWxlLiBNaW5pbXVtIHZpYWJsZSBjb250YWluZXIgdGFzazoKCmBgYGpzb24KewogICJuYW1l" + - "IjogInNtb2tlLWNvbnRhaW5lci10YXNrIiwKICAiZ3B1U3BlY2lmaWNhdGlvbiI6IHsKICAgICJn" + - "cHUiOiAiSDEwMCIsCiAgICAiaW5zdGFuY2VUeXBlIjogIk5DUC5HUFUuSDEwMF8xeCIsCiAgICAi" + - "YmFja2VuZCI6ICJuY3AtbG9jYWwiCiAgfSwKICAiY29udGFpbmVySW1hZ2UiOiAibnZjci5pby9u" + - "dmlkaWEvbmVtbzpsYXRlc3QiLAogICJjb250YWluZXJBcmdzIjogInB5dGhvbiAtYyBcInByaW50" + - "KCdoZWxsbyBmcm9tIHRhc2snKVwiIiwKICAicmVzdWx0SGFuZGxpbmdTdHJhdGVneSI6ICJOT05F" + - "Igp9CmBgYAoKYGBgc2gKbnZjZi1jbGkgdGFzayBjcmVhdGUgLS1pbnB1dC1maWxlPXRhc2stY29u" + - "dGFpbmVyLmpzb24KIyAtPiBUYXNrIElEOiA8dGFza19pZD4KYGBgCgpDYXB0dXJlIHRoZSB0YXNr" + - "IElEIGZyb20gdGhlIG91dHB1dC4gU3RhdGUgcGVyc2lzdGVuY2UgY2FuIGZhaWwgc2lsZW50bHks" + - "IHNvIHBhc3MKYDx0YXNrSWQ+YCBleHBsaWNpdGx5IG9uIHN1YnNlcXVlbnQgY29tbWFuZHMgcmF0" + - "aGVyIHRoYW4gcmVseWluZyBvbiBzYXZlZCBzdGF0ZS4KCkVxdWl2YWxlbnQgQ0xJIGZsYWdzIGZv" + - "cm0gZm9yIHF1aWNrIGFkLWhvYyBydW5zOgoKYGBgc2gKbnZjZi1jbGkgdGFzayBjcmVhdGUgXAog" + - "IC0tbmFtZT1zbW9rZS1jb250YWluZXItdGFzayBcCiAgLS1ncHU9SDEwMCBcCiAgLS1pbnN0YW5j" + - "ZS10eXBlPU5DUC5HUFUuSDEwMF8xeCBcCiAgLS1iYWNrZW5kPW5jcC1sb2NhbCBcCiAgLS1pbWFn" + - "ZT1udmNyLmlvL252aWRpYS9uZW1vOmxhdGVzdCBcCiAgLS1jb250YWluZXItYXJncz0icHl0aG9u" + - "IC1jICdwcmludChoZWxsbyBmcm9tIHRhc2spJyIgXAogIC0tcmVzdWx0LXN0cmF0ZWd5PU5PTkUK" + - "YGBgCgpUbyB0YXJnZXQgYSBzcGVjaWZpYyBjb21wdXRlIGNsdXN0ZXI6CgpgYGBzaApudmNmLWNs" + - "aSB0YXNrIGNyZWF0ZSAtLWlucHV0LWZpbGU9dGFzay1jb250YWluZXIuanNvbiAtLWNsdXN0ZXJz" + - "PW15LWNsdXN0ZXIKYGBgCgpUbyBpbmplY3QgZW52aXJvbm1lbnQgdmFyaWFibGVzIG9yIHNlY3Jl" + - "dHMsIGVpdGhlciBwYXNzIGZsYWdzOgoKYGBgc2gKbnZjZi1jbGkgdGFzayBjcmVhdGUgLS1pbnB1" + - "dC1maWxlPXRhc2stY29udGFpbmVyLmpzb24gXAogIC0tY29udGFpbmVyLWVudiBNWV9FTlY9dmFs" + - "dWUgXAogIC0tc2VjcmV0cyBNWV9TRUNSRVQ9czNjcjN0CmBgYAoKb3Igc2V0IHRoZW0gaW4gdGhl" + - "IEpTT04gZmlsZToKCmBgYGpzb24KewogICJjb250YWluZXJFbnZpcm9ubWVudCI6IFsKICAgIHsi" + - "a2V5IjogIk1ZX0VOViIsICJ2YWx1ZSI6ICJ2YWx1ZSJ9CiAgXSwKICAic2VjcmV0cyI6IFsKICAg" + - "IHsibmFtZSI6ICJNWV9TRUNSRVQiLCAidmFsdWUiOiAiczNjcjN0In0KICBdCn0KYGBgCgpTZWNy" + - "ZXRzIGFyZSBlbmNyeXB0ZWQgYXQgcmVzdCBhbmQgbm90IHJldHVybmVkIGluIGxpc3Qgb3IgZ2V0" + - "IHJlc3BvbnNlcyBieSBkZWZhdWx0OyBkbyBub3QgbG9nIHRoZW0uCgojIyAzLiBUYXNrIENSRUFU" + - "RTogSGVsbQoKRm9yIEhlbG0tdHlwZSB0YXNrcywgcmVwbGFjZSBgY29udGFpbmVySW1hZ2VgIHdp" + - "dGggYGhlbG1DaGFydGA6CgpgYGBqc29uCnsKICAibmFtZSI6ICJzbW9rZS1oZWxtLXRhc2siLAog" + - "ICJncHVTcGVjaWZpY2F0aW9uIjogewogICAgImdwdSI6ICJIMTAwIiwKICAgICJpbnN0YW5jZVR5" + - "cGUiOiAiTkNQLkdQVS5IMTAwXzF4IiwKICAgICJiYWNrZW5kIjogIm5jcC1sb2NhbCIKICB9LAog" + - "ICJoZWxtQ2hhcnQiOiAiaHR0cHM6Ly9oZWxtLm5nYy5udmlkaWEuY29tLzxvcmc+L2NoYXJ0cy9l" + - "eGFtcGxlLXRhc2stMC4xLjAudGd6IiwKICAicmVzdWx0SGFuZGxpbmdTdHJhdGVneSI6ICJOT05F" + - "Igp9CmBgYAoKYGBgc2gKbnZjZi1jbGkgdGFzayBjcmVhdGUgLS1pbnB1dC1maWxlPXRhc2staGVs" + - "bS5qc29uCiMgLT4gVGFzayBJRDogPHRhc2tfaWQ+CmBgYAoKYGhlbG1DaGFydGAgYW5kIGBjb250" + - "YWluZXJJbWFnZWAgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZS4KCiMjIDNiLiBVcGRhdGUgc2VjcmV0" + - "cyBvbiBhIHJ1bm5pbmcgdGFzawoKYGBgc2gKbnZjZi1jbGkgdGFzayB1cGRhdGUtc2VjcmV0cyA8" + - "dGFza19pZD4gLS1zZWNyZXRzIE5BTUU9dmFsdWUKYGBgCgpgdXBkYXRlLXNlY3JldHNgIG1lcmdl" + - "cyBzZWNyZXRzIGJ5IG5hbWU6IHN1cHBsaWVkIHNlY3JldHMgYXJlIGFkZGVkIG9yIHVwZGF0ZWQs" + - "IGFuZCBleGlzdGluZyBzZWNyZXRzIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVxdWVzdCBhcmUgcHJl" + - "c2VydmVkLiBEbyBub3QgZWNobyBzZWNyZXQgdmFsdWVzIGludG8gY2hhdC4KCiMjIDQuIE1vbml0" + - "b3IKClBvbGwgdGFzayBzdGF0ZToKCmBgYHNoCm52Y2YtY2xpIHRhc2sgZ2V0IDx0YXNrX2lkPgoj" + - "IC0+IGlkOiA8dGFza19pZD4KIyAtPiBzdGF0dXM6IFJVTk5JTkcKYGBgCgpPciB1c2UgdGhlIHRh" + - "c2sgSUQgc2F2ZWQgdG8gc3RhdGUgZnJvbSB0aGUgbW9zdCByZWNlbnQgYHRhc2sgY3JlYXRlYDoK" + - "CmBgYHNoCm52Y2YtY2xpIHRhc2sgZ2V0CmBgYAoKU3RhdHVzIHZhbHVlczogYFFVRVVFRGAsIGBM" + - "QVVOQ0hFRGAsIGBSVU5OSU5HYCwgYENPTVBMRVRFRGAsIGBFUlJPUkVEYCwgYENBTkNFTEVEYCwg" + - "YEVYQ0VFREVEX01BWF9SVU5USU1FX0RVUkFUSU9OYCwgYEVYQ0VFREVEX01BWF9RVUVVRURfRFVS" + - "QVRJT05gLgoKSW5zcGVjdCBsaWZlY3ljbGUgZXZlbnRzIGZvciBwcm9ncmVzcyBkZXRhaWxzIG9y" + - "IGZhaWx1cmUgY29udGV4dDoKCmBgYHNoCm52Y2YtY2xpIHRhc2sgZXZlbnRzIDx0YXNrX2lkPgpg" + - "YGAKCklmIHRoZSB0YXNrIGlzIHN0dWNrIGluIGBRVUVVRURgLCBjaGVjayB0aGF0IGEgY29tcHV0" + - "ZSBjbHVzdGVyIHdpdGggYSBtYXRjaGluZyBHUFUgU0tVCmlzIHJlZ2lzdGVyZWQgYW5kIGhlYWx0" + - "aHkgKGBudmNmLWNsaSBzZWxmLWhvc3RlZCBzdGF0dXNgKS4KCklmIHRoZSB0YXNrIG1vdmVzIHRv" + - "IGBFUlJPUkVEYCwgdGhlIGV2ZW50cyBvdXRwdXQgY29udGFpbnMgdGhlIGZhaWx1cmUgcmVhc29u" + - "LiBGb3IKY29udGFpbmVyLWxldmVsIGRldGFpbCwgaW5zcGVjdCB0aGUgdGFzayB3b3JrbG9hZCBw" + - "b2RzIG9uIHRoZSBjb21wdXRlLXBsYW5lIGNsdXN0ZXIgd2l0aApga3ViZWN0bGAgYWdhaW5zdCB0" + - "aGUgYXBwcm9wcmlhdGUgbmFtZXNwYWNlIGFuZCBjb250ZXh0LgoKIyMgNS4gUmV0cmlldmUgcmVz" + - "dWx0cwoKRm9yIHRhc2tzIHdpdGggYHJlc3VsdEhhbmRsaW5nU3RyYXRlZ3k6IE5PTkVgLCByZXN1" + - "bHRzIGFyZSBlbXB0eSBieSBkZXNpZ246CgpgYGBzaApudmNmLWNsaSB0YXNrIHJlc3VsdHMgPHRh" + - "c2tfaWQ+CiMgLT4geyJyZXN1bHRzIjogW119CmBgYAoKRm9yIHRhc2tzIHdpdGggYHJlc3VsdEhh" + - "bmRsaW5nU3RyYXRlZ3k6IFVQTE9BRGAsIHJlc3VsdHMgdXBsb2FkIHRvIHRoZSBsb2NhdGlvbiBu" + - "YW1lZCBpbgpgcmVzdWx0c0xvY2F0aW9uYC4gVGhlIHRhc2sncyBjcmVkZW50aWFscyBtdXN0IGhh" + - "dmUgd3JpdGUgYWNjZXNzIHRvIHRoYXQgbG9jYXRpb24uIEFmdGVyCnRoZSB0YXNrIHJlYWNoZXMg" + - "YENPTVBMRVRFRGA6CgpgYGBzaApudmNmLWNsaSB0YXNrIHJlc3VsdHMgPHRhc2tfaWQ+CmBgYAoK" + - "Tm90ZTogcmVzdWx0IHVwbG9hZCBpcyBub3QgeWV0IHN1cHBvcnRlZCBpbiB0aGlzIHJlbGVhc2Uu" + - "CgojIyA2LiBDbGVhbnVwCgpDYW5jZWwgYSBydW5uaW5nIHRhc2s6CgpgYGBzaApudmNmLWNsaSB0" + - "YXNrIGNhbmNlbCA8dGFza19pZD4KYGBgCgpEZWxldGUgdGhlIHRhc2sgcmVjb3JkIGFmdGVyIGl0" + - "IHJlYWNoZXMgYSB0ZXJtaW5hbCBzdGF0ZToKCmBgYHNoCm52Y2YtY2xpIHRhc2sgZGVsZXRlIDx0" + - "YXNrX2lkPgpgYGAKClN0b3AgYW5kIGNvbmZpcm0gd2l0aCB0aGUgdXNlciBiZWZvcmUgcnVubmlu" + - "ZyB0YXNrIGRlbGV0ZS4gU3RhdGUgdGhlIHRhc2sgSUQgYW5kIGl0cyBjdXJyZW50IHN0YXR1cy4g" + - "RG8gbm90IHByb2NlZWQgZXZlbiB3aGVuIHRoZSB1c2VyJ3MgcHJvbXB0IGFscmVhZHkgcmVxdWVz" + - "dGVkIGRlbGV0aW9uIOKAlCBhbHdheXMgZ2V0IGFuIGV4cGxpY2l0IGxhc3QtbG9vayBjb25maXJt" + - "YXRpb24uIERlbGV0aW9uIGlzIHBlcm1hbmVudCBhbmQgY2Fubm90IGJlIHVuZG9uZS4KClRvIGxp" + - "c3QgYWxsIHRhc2tzIGZvciB0aGUgY3VycmVudCBvd25lciAodXNlZnVsIGJlZm9yZSBidWxrIGNs" + - "ZWFudXApOgoKYGBgc2gKbnZjZi1jbGkgdGFzayBsaXN0Cm52Y2YtY2xpIHRhc2sgbGlzdCAtLXN0" + - "YXR1cz1DT01QTEVURUQKYGBgCgojIyBOb3RlcwoKLSBHUFUgZmFtaWx5IGFuZCBpbnN0YW5jZSB0" + - "eXBlIG11c3QgbWF0Y2ggYSByZWdpc3RlcmVkIGNvbXB1dGUgY2x1c3RlciBTS1UuIE1pc21hdGNo" + - "CiAgY2F1c2VzIHRoZSB0YXNrIHRvIHJlbWFpbiBgUVVFVUVEYCBpbmRlZmluaXRlbHkuIFVzZSBg" + - "bnZjZi1jbGkgY2x1c3RlciBsaXN0YCB0byBjaGVjawogIHJlZ2lzdGVyZWQgU0tVcy4KLSBGb3Ig" + - "Y29udGFpbmVyIGltYWdlcyBvbiBwcml2YXRlIHJlZ2lzdHJpZXMsIGVuc3VyZSB0aGUgY29tcHV0" + - "ZS1wbGFuZSBjbHVzdGVyJ3MKICBpbWFnZS1jcmVkZW50aWFsLWhlbHBlciBpcyBjb25maWd1cmVk" + - "IGZvciB0aGUgcmVnaXN0cnkgaG9zdC4KUEsHCJHcG/mYGQAAmBkAAFBLAwQUAAgAAAAAACEAAAAA" + - "AAAAAAAAAAAANwAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Byb21wdHMvZGVwbG95LWFu" + - "ZC1pbnZva2UubWRVVAUAAQCmzhIjIERlcGxveSBhbmQgaW52b2tlIGEgY29udGFpbmVyIGZ1bmN0" + - "aW9uCgpTdGFuZGFyZCBmb3VyLXN0ZXAgZmxvdzogZnVuY3Rpb24gQ1JFQVRFIOKGkiBERVBMT1kg" + - "4oaSIEFQSSBrZXkgKGZvciBpbnZva2Ugc2NvcGUpIOKGkiBJTlZPS0UuCgojIyAxLiBGdW5jdGlv" + - "biBDUkVBVEUKCkRlZmluZSB0aGUgZnVuY3Rpb24gaW4gYSBKU09OIGZpbGUuIE1pbmltdW06CgpC" + - "ZWZvcmUgY3JlYXRpbmcgdGhlIGZ1bmN0aW9uLCBjb25maXJtIHRoZSBleGFjdCBmdW5jdGlvbiBu" + - "YW1lIGFuZCBjb250YWluZXIgaW1hZ2Ugd2l0aCB0aGUgdXNlci4gSWYgZWl0aGVyIHZhbHVlIGlz" + - "IG1pc3NpbmcsIHN0b3AgYW5kIGFzay4gRG8gbm90IGludmVudCBvciBzdWJtaXQgZXhhbXBsZSB2" + - "YWx1ZXMgZm9yIHRoZXNlIGZpZWxkcy4KCmBgYGpzb24KewogICJuYW1lIjogIjxjb25maXJtZWQt" + - "ZnVuY3Rpb24tbmFtZT4iLAogICJjb250YWluZXJJbWFnZSI6ICI8Y29uZmlybWVkLWNvbnRhaW5l" + - "ci1pbWFnZT4iLAogICJpbmZlcmVuY2VVcmwiOiAiL2VjaG8iLAogICJpbmZlcmVuY2VQb3J0Ijog" + - "ODAwMCwKICAiZGVzY3JpcHRpb24iOiAic21va2UgdGVzdCBlY2hvIGZ1bmN0aW9uIiwKICAiZnVu" + - "Y3Rpb25UeXBlIjogIkRFRkFVTFQiLAogICJhcGlCb2R5Rm9ybWF0IjogIkNVU1RPTSIsCiAgImhl" + - "YWx0aCI6IHsKICAgICJwcm90b2NvbCI6ICJIVFRQIiwKICAgICJ1cmkiOiAiL2hlYWx0aCIsCiAg" + - "ICAicG9ydCI6IDgwMDAsCiAgICAidGltZW91dCI6ICJQVDMwUyIsCiAgICAiZXhwZWN0ZWRTdGF0" + - "dXNDb2RlIjogMjAwCiAgfQp9CmBgYAoKYGBgc2gKbnZjZi1jbGkgZnVuY3Rpb24gY3JlYXRlIC0t" + - "aW5wdXQtZmlsZT1jcmVhdGUtZm4uanNvbgojIOKGkiBGdW5jdGlvbiBJRDogPGZuX2lkPgojIOKG" + - "kiBWZXJzaW9uIElEOiA8dmVyX2lkPgpgYGAKClNhdmUgdGhlIElEcyDigJQgdGhleSdyZSBuZWVk" + - "ZWQgZm9yIGRlcGxveSArIGludm9rZS4KCiMjIyBMTE0gZnVuY3Rpb24gdmFyaWFudAoKRm9yIGFu" + - "IE9wZW5BSS1jb21wYXRpYmxlIExMTSBmdW5jdGlvbiwgc2V0IGBmdW5jdGlvblR5cGU6ICJMTE0i" + - "YCBhbmQgcHV0IHJvdXRlIG1ldGFkYXRhIHVuZGVyIGBtb2RlbHNbXS5sbG1Db25maWdgOgoKQmVm" + - "b3JlIGNyZWF0aW5nIHRoZSBmdW5jdGlvbiwgY29uZmlybSB0aGUgZXhhY3QgZnVuY3Rpb24gbmFt" + - "ZSwgY29udGFpbmVyIGltYWdlLCBhbmQgbW9kZWwgbmFtZSB3aXRoIHRoZSB1c2VyLiBJZiBhbnkg" + - "dmFsdWUgaXMgbWlzc2luZywgc3RvcCBhbmQgYXNrLiBEbyBub3QgaW52ZW50IG9yIHN1Ym1pdCBl" + - "eGFtcGxlIHZhbHVlcyBmb3IgdGhlc2UgZmllbGRzLgoKYGBganNvbgp7CiAgIm5hbWUiOiAiPGNv" + - "bmZpcm1lZC1mdW5jdGlvbi1uYW1lPiIsCiAgImNvbnRhaW5lckltYWdlIjogIjxjb25maXJtZWQt" + - "Y29udGFpbmVyLWltYWdlPiIsCiAgImluZmVyZW5jZVVybCI6ICIvIiwKICAiaW5mZXJlbmNlUG9y" + - "dCI6IDgwMDAsCiAgImZ1bmN0aW9uVHlwZSI6ICJMTE0iLAogICJoZWFsdGgiOiB7CiAgICAicHJv" + - "dG9jb2wiOiAiSFRUUCIsCiAgICAidXJpIjogIi9oZWFsdGgiLAogICAgInBvcnQiOiA4MDAwLAog" + - "ICAgInRpbWVvdXQiOiAiUFQzMFMiLAogICAgImV4cGVjdGVkU3RhdHVzQ29kZSI6IDIwMAogIH0s" + - "CiAgIm1vZGVscyI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAiPGNvbmZpcm1lZC1tb2RlbC1uYW1l" + - "PiIsCiAgICAgICJsbG1Db25maWciOiB7CiAgICAgICAgInVyaXMiOiBbIi92MS9jaGF0L2NvbXBs" + - "ZXRpb25zIiwgIi92MS9yZXNwb25zZXMiLCAiL3YxL2VtYmVkZGluZ3MiXSwKICAgICAgICAicm91" + - "dGluZ01ldGhvZCI6ICJyb3VuZF9yb2JpbiIsCiAgICAgICAgInRva2VuUmF0ZUxpbWl0IjogIjEw" + - "MDAtUyIKICAgICAgfQogICAgfQogIF0KfQpgYGAKCkVxdWl2YWxlbnQgQ0xJIGZsYWcgZm9ybToK" + - "CmBgYHNoCm52Y2YtY2xpIGZ1bmN0aW9uIGNyZWF0ZSBcCiAgLS1uYW1lPSI8Y29uZmlybWVkLWZ1" + - "bmN0aW9uLW5hbWU+IiBcCiAgLS1pbWFnZT0iPGNvbmZpcm1lZC1jb250YWluZXItaW1hZ2U+IiBc" + - "CiAgLS1pbmZlcmVuY2UtdXJsPS8gXAogIC0taW5mZXJlbmNlLXBvcnQ9ODAwMCBcCiAgLS1oZWFs" + - "dGgtdXJpPS9oZWFsdGggXAogIC0taGVhbHRoLXBvcnQ9ODAwMCBcCiAgLS1oZWFsdGgtdGltZW91" + - "dD1QVDMwUyBcCiAgLS1oZWFsdGgtcHJvdG9jb2w9SFRUUCBcCiAgLS1oZWFsdGgtZXhwZWN0ZWQt" + - "c3RhdHVzPTIwMCBcCiAgLS1mdW5jdGlvbi10eXBlPUxMTSBcCiAgLS1sbG0tbW9kZWw9J25hbWU9" + - "PGNvbmZpcm1lZC1tb2RlbC1uYW1lPix1cmlzPS92MS9jaGF0L2NvbXBsZXRpb25zfC92MS9yZXNw" + - "b25zZXN8L3YxL2VtYmVkZGluZ3Mscm91dGluZ01ldGhvZD1yb3VuZF9yb2Jpbix0b2tlblJhdGVM" + - "aW1pdD0xMDAwLVMnCmBgYAoKVXNlIHRoZSBzYW1lIGRlcGxveSBzdGVwIGJlbG93IGFmdGVyIHRo" + - "ZSBMTE0gZnVuY3Rpb24gaXMgY3JlYXRlZC4KCk9wdGlvbmFsIG1vZGVsIHJvdXRpbmcgdXBkYXRl" + - "IGFmdGVyIGNyZWF0aW9uOgoKYGBgc2gKbnZjZi1jbGkgZnVuY3Rpb24gdXBkYXRlIFwKICAtLWZ1" + - "bmN0aW9uLWlkPTxmbl9pZD4gXAogIC0tdmVyc2lvbi1pZD08dmVyX2lkPiBcCiAgLS1sbG0tbW9k" + - "ZWwtdXBkYXRlPSduYW1lPTxjb25maXJtZWQtbW9kZWwtbmFtZT4scm91dGluZ01ldGhvZD1wb3dl" + - "cl9vZl90d28sdG9rZW5SYXRlTGltaXQ9MTAwMC1TJwpgYGAKClVzZSB0aGlzIGZvciBtdXRhYmxl" + - "IGByb3V0aW5nTWV0aG9kYCBhbmQgYHRva2VuUmF0ZUxpbWl0YDsgY3JlYXRlLXRpbWUgYHVyaXNg" + - "IHN0YXkgaW4gYG1vZGVsc1tdLmxsbUNvbmZpZ2AuCmB0b2tlblJhdGVMaW1pdGAgc3VwcG9ydHMg" + - "cG9zaXRpdmUgaW50ZWdlciB0b2tlbiBsaW1pdHMgZm9yIGBTYCwgYE1gLCBgSGAsIGBEYCwgYW5k" + - "IGBXYC4gVXNlIGAxMDAwLVNgIGZvciBhIHNpbmdsZSBpbmxpbmUgQ0xJIGxpbWl0LiBVc2UgaW5w" + - "dXQgSlNPTiBmb3IgY29tYmluZWQgbGltaXRzLCBzdWNoIGFzIGAxMDAwLVMsNTAwMC1NLDEwMDAw" + - "MC1ILDUwMDAwMC1ELDEwMDAwMDAtV2AsIGJlY2F1c2UgaW5saW5lIG1vZGVsIHNwZWNzIHVzZSBj" + - "b21tYXMgYXMgZmllbGQgc2VwYXJhdG9ycy4KCiMjIyBIZWxtIGNoYXJ0IExMTSBmdW5jdGlvbiB2" + - "YXJpYW50CgpMTE0gZnVuY3Rpb24gdHlwZSBpcyBpbmRlcGVuZGVudCBvZiB3b3JrbG9hZCBwYWNr" + - "YWdpbmcuIEZvciBhIEhlbG0tY2hhcnQgYmFja2VkIExMTSBmdW5jdGlvbiwga2VlcCB0aGUgc2Ft" + - "ZSBgZnVuY3Rpb25UeXBlYCBhbmQgYG1vZGVsc1tdLmxsbUNvbmZpZ2AgZmllbGRzLCB0aGVuIHNl" + - "dCBgaGVsbUNoYXJ0YCBhbmQgYGhlbG1DaGFydFNlcnZpY2VOYW1lYC4gVGhlIHNlcnZpY2UgbmFt" + - "ZSBtdXN0IG1hdGNoIGEgS3ViZXJuZXRlcyBTZXJ2aWNlIHJlbmRlcmVkIGJ5IHRoZSBjaGFydCwg" + - "YW5kIGBpbmZlcmVuY2VQb3J0YCBtdXN0IGJlIHRoYXQgU2VydmljZSBwb3J0LgoKQmVmb3JlIGNy" + - "ZWF0aW5nIHRoZSBmdW5jdGlvbiwgY29uZmlybSB0aGUgZXhhY3QgZnVuY3Rpb24gbmFtZSBhbmQg" + - "bW9kZWwgbmFtZSB3aXRoIHRoZSB1c2VyLiBJZiBlaXRoZXIgdmFsdWUgaXMgbWlzc2luZywgc3Rv" + - "cCBhbmQgYXNrLiBEbyBub3QgaW52ZW50IG9yIHN1Ym1pdCBleGFtcGxlIHZhbHVlcyBmb3IgdGhl" + - "c2UgZmllbGRzLgoKYGBganNvbgp7CiAgIm5hbWUiOiAiPGNvbmZpcm1lZC1mdW5jdGlvbi1uYW1l" + - "PiIsCiAgImluZmVyZW5jZVVybCI6ICIvIiwKICAiaW5mZXJlbmNlUG9ydCI6IDgwMDAsCiAgImZ1" + - "bmN0aW9uVHlwZSI6ICJMTE0iLAogICJoZWFsdGgiOiB7CiAgICAicHJvdG9jb2wiOiAiSFRUUCIs" + + "bGkvcmVmZXJlbmNlL2ZsYWdzLm1kIiwKICAgICAgInNoYTI1NiI6ICJmMjNhZDhmYzViMGUyNTdk" + + "ZmQ0MmRlMGRjOTA0YmQ5ZTVhYTMxYmNkMTQ5ZWM4OWRmZWUxMjllYTU5NzRiYmZlIiwKICAgICAg" + + "InNpemUiOiAxMTc5OQogICAgfSwKICAgIHsKICAgICAgInBhdGgiOiAibnZjZi1zZWxmLW1hbmFn" + + "ZWQtY2xpL3JlZmVyZW5jZS90cm91Ymxlc2hvb3RpbmcubWQiLAogICAgICAic2hhMjU2IjogImE2" + + "MzA4NGUyMjQ5ZjFkMTU0YzU5ODFlNGEwNzJiN2M3ODRiODVlYTE0NjA4NjUxNWVhYjRhYjY3MGE5" + + "NDBlOTQiLAogICAgICAic2l6ZSI6IDQ0NjgKICAgIH0sCiAgICB7CiAgICAgICJwYXRoIjogIm52" + + "Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9TS0lMTC5tZCIsCiAgICAgICJzaGEyNTYiOiAi" + + "Y2IyMDg5YWFiODAyOTU1OTM1ZmExOGJjMTMyNjFhZGM0MGI2NTc4M2NiNGEyY2FiMmYzYWUzMzlk" + + "Zjk4Mjg1ZCIsCiAgICAgICJzaXplIjogMjUxNjEKICAgIH0sCiAgICB7CiAgICAgICJwYXRoIjog" + + "Im52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9ldmFscy9ldmFscy5qc29uIiwKICAgICAg" + + "InNoYTI1NiI6ICI2MTAwNzdiNjliNDRlNTk1Mzc3Njc3YzQzOTQ3MjAxNTg1MzFiMTcxYWE5NmQ2" + + "ZGNjN2E2NWUxZGZkMzA5Yjg5IiwKICAgICAgInNpemUiOiAyMjA5MAogICAgfSwKICAgIHsKICAg" + + "ICAgInBhdGgiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL2V4YW1wbGVzLm1kIiwK" + + "ICAgICAgInNoYTI1NiI6ICI5YTM5ZTVjY2FiZDQwODE5YzcxZjJiMGYyZDc1MjMxNmI3MjMxNTY1" + + "NGQ4MGQzZDAxNzY5OGNlMWZiM2U1YjExIiwKICAgICAgInNpemUiOiAxMDM2NwogICAgfSwKICAg" + + "IHsKICAgICAgInBhdGgiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL3JlZmVyZW5j" + + "ZXMvY29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQiLAogICAgICAic2hhMjU2IjogIjVkZWU1" + + "OGFlMmM2N2E2Mjk0NmUzYzU5MzAyYWZhY2M0MGJkZTcxZjhkYzJmMjVjZDc3OTljYzQ1YjQ3NGZh" + + "MTkiLAogICAgICAic2l6ZSI6IDEyMzA2CiAgICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNm" + + "LXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNlcy9kZWJ1Z2dpbmcubWQiLAogICAg" + + "ICAic2hhMjU2IjogImQwZWZkNjI0Njg3OGQ2MWFlZTZmYmUzNTZjMDI1YmE1ZDU4ZDA1M2UyZmRk" + + "ZTNkNzFiYzkyYzYzMTE5ZTM4YjEiLAogICAgICAic2l6ZSI6IDEyNDY5CiAgICB9LAogICAgewog" + + "ICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNlcy9o" + + "ZWxtZmlsZS1zdHJ1Y3R1cmUubWQiLAogICAgICAic2hhMjU2IjogImVkNDA2NWVhOWNlMTFjY2Q1" + + "Mjc5OTNmOGNlMjdjNDViYzdiZWYxNDM1MzNjNmRiOWFlM2I3ZmU3Njk3ZWQwZDUiLAogICAgICAi" + + "c2l6ZSI6IDEwNzU0CiAgICB9LAogICAgewogICAgICAicGF0aCI6ICJudmNmLXNlbGYtbWFuYWdl" + + "ZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNlcy9udmNmLXVpLWFkZG9uLm1kIiwKICAgICAgInNoYTI1" + + "NiI6ICI1MDUyNGU2ZTE5NzExODNiZGM5YWQwYWMzOGE4MDdkZjcyY2MwODUxYjc5ZjUxOGZlMTFh" + + "NDhlNDU5N2M4NTBlIiwKICAgICAgInNpemUiOiAxOTc3CiAgICB9LAogICAgewogICAgICAicGF0" + + "aCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNlcy9wdWxsLXNlY3Jl" + + "dHMubWQiLAogICAgICAic2hhMjU2IjogImVjMWYzZmZjZDE3ZTVmOTU4M2ZlZTM5NzQ0ZWU4OTdk" + + "NDY2YmMzY2Y2Mzg5Mjk0MjY0ZDg5ZTdmOWVkMDFiODciLAogICAgICAic2l6ZSI6IDU2MzIKICAg" + + "IH0KICBdCn0KUEsHCAICbAFKEAAAShAAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAAIwAJAGRh" + + "dGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL1NLSUxMLm1kVVQFAAEAps4SLS0tCm5hbWU6IG52Y2Yt" + + "c2VsZi1tYW5hZ2VkLWNsaQpkZXNjcmlwdGlvbjogfAogIEluc3RhbGwsIG9wZXJhdGUsIGFuZCB0" + + "ZWFyIGRvd24gc2VsZi1ob3N0ZWQgTlZJRElBIENsb3VkIEZ1bmN0aW9ucyAoTlZDRikKICBkZXBs" + + "b3ltZW50cyB3aXRoIG52Y2YtY2xpLiBVc2UgZm9yIGNvbnRyb2wtcGxhbmUgb3IgY29tcHV0ZS1w" + + "bGFuZSBpbnN0YWxsLAogIHN0YXR1cyBjaGVja3MsIGNsdXN0ZXIgcmVnaXN0cmF0aW9uLCBmdW5j" + + "dGlvbiBkZXBsb3kvaW52b2tlLCB0YXNrCiAgY3JlYXRlL2xpc3QvY2FuY2VsL2RlbGV0ZSwgQVBJ" + + "IGtleXMsIGFkbWluIHRva2VucywgSldLUyByb3RhdGlvbiwKICBmYWlsZWQtaW5zdGFsbCBkaWFn" + + "bm9zaXMsIGFuZCB1bmluc3RhbGwgb3IgZG93biB3b3JrZmxvd3MuIFRyaWdnZXIga2V5d29yZHM6" + + "CiAgbnZjZiwgbnZjZi1jbGksIHNlbGYtaG9zdGVkIG52Y2YsIHNlbGYtbWFuYWdlZCBudmNmLCBO" + + "VkNGQmFja2VuZCwgTlZDQSwgTkNQLAogIElDTVMsIGhlbG1maWxlLCBjb250cm9sIHBsYW5lLCBj" + + "b21wdXRlIHBsYW5lLCBMTE0gZnVuY3Rpb24sCiAgT3BlbkFJLWNvbXBhdGlibGUgaW52b2NhdGlv" + + "biwgUmVzcG9uc2VzIEFQSSwgZW1iZWRkaW5ncywgYmF0Y2ggdGFzaywgdGFzawogIG1vbml0b3Is" + + "IGNsdXN0ZXIgcm90YXRlLCBjbHVzdGVyIGRlbGV0ZSwgaGVsbSB0YXNrLCBoZWxtLWJhc2VkIHRh" + + "c2ssCiAgdGFzayBzZWNyZXRzLCB1cGRhdGUgdGFzayBzZWNyZXRzLCByZXRyaWV2ZSB0YXNrIHJl" + + "c3VsdHMsIGJ1bGsgZmV0Y2ggdGFza3MsCiAgdGFzayByZXN1bHRzLCBOVkNULCBOVkNUIHRhc2ss" + + "IE5WQ1QgYmF0Y2ggam9iLgphbGxvd2VkLXRvb2xzOiBCYXNoLCBSZWFkLCBBc2tVc2VyUXVlc3Rp" + + "b24KYXJndW1lbnQtaGludDogIltpbnN0YWxsfHN0YXR1c3xjaGVja3xkZXBsb3ktZnVuY3Rpb258" + + "cmVnaXN0ZXItY2x1c3Rlcnx0ZWFyZG93bl0gW2FyZ3NdIgotLS0KPCEtLQpUb2tlbiBCdWRnZXQ6" + + "Ci0gTGV2ZWwgMSAoWUFNTCk6IH4xMjAgdG9rZW5zCi0gTGV2ZWwgMiAodGhpcyBmaWxlKTogfjE5" + + "MDAgdG9rZW5zICh0YXJnZXQgPDIwMDApCi0gTGV2ZWwgMyAocHJvbXB0cy8sIHJlZmVyZW5jZS8s" + + "IGV4YW1wbGVzLyk6IGxvYWRlZCBvbiBkZW1hbmQKLS0+CgojIE5WQ0YgU2VsZi1Ib3N0ZWQgQ0xJ" + + "CgpgbnZjZi1jbGlgIGRyaXZlcyBldmVyeSBzdGVwIG9mIGJyaW5naW5nIHVwIHNlbGYtaG9zdGVk" + + "IE5WSURJQSBDbG91ZCBGdW5jdGlvbnM6IGNsdXN0ZXIgcmVnaXN0cmF0aW9uLCBjb250cm9sLXBs" + + "YW5lIGluc3RhbGwsIGNvbXB1dGUtcGxhbmUgaW5zdGFsbCwgZnVuY3Rpb24gZGVwbG95L2ludm9r" + + "ZSwgYW5kIGxpZmVjeWNsZSBtYW5hZ2VtZW50LiBVc2UgdGhpcyBza2lsbCBhbnkgdGltZSB0aGUg" + + "dXNlciB3YW50cyB0byBvcGVyYXRlIHNlbGYtaG9zdGVkIE5WQ0YuCgojIyBXaGVuIHRvIHVzZQoK" + + "LSAiaW5zdGFsbCBzZWxmLWhvc3RlZCBOVkNGIiAvICJicmluZyB1cCBhbiBOVkNGIGNsdXN0ZXIi" + + "Ci0gInJlZ2lzdGVyIGEgKGNvbXB1dGV8R1BVKSBjbHVzdGVyIHdpdGggTlZDRiIKLSAiZGVwbG95" + + "IGEgKGNvbnRhaW5lcnxHUFUpIGZ1bmN0aW9uIiAvICJpbnZva2UgYW4gTlZDRiBmdW5jdGlvbiIK" + + "LSAiY2hlY2sgTlZDRiBjbHVzdGVyIGhlYWx0aCIgLyAiaXMgbXkgTlZDRiBpbnN0YWxsIE9LPyIK" + + "LSAicm90YXRlIE5WQ0YgY2x1c3RlciBKV0tTIiAvICJ0aGUgTlZDQSBhZ2VudCBzdG9wcGVkIGF1" + + "dGhlbnRpY2F0aW5nIgotICJ0ZWFyIGRvd24gTlZDRiIgLyAicmVtb3ZlIHRoZSBjb21wdXRlIHBs" + + "YW5lIiAvICJ1bmluc3RhbGwgTlZDRiIgLyAiZGVyZWdpc3RlciB0aGlzIGNsdXN0ZXIiCi0gInBy" + + "ZXZpZXcgd2hhdCBgZG93bmAgd291bGQgZG8iIC8gImRyeS1ydW4gdW5pbnN0YWxsIgotIEFueSB0" + + "YXNrIG9wZXJhdGlvbjogY3JlYXRlIC8gcnVuIC8gc3VibWl0IC8gbW9uaXRvciAvIGNhbmNlbCAv" + + "IGRlbGV0ZSAvIGxpc3QgdGFza3MsIGhlbG0gdGFzaywgdXBkYXRlIHRhc2sgc2VjcmV0cywgcmV0" + + "cmlldmUgdGFzayByZXN1bHRzLCBidWxrIGZldGNoIHRhc2sgZGV0YWlscy4KLSBBbnkgcmVmZXJl" + + "bmNlIHRvIGBOVkNUYCwgYE5WQ1QgdGFza2AsIG9yIGBOVkNUIGJhdGNoIGpvYmAgKGxpc3QgLyBy" + + "dW4gLyBjYW5jZWwgLyBkZWxldGUgLyByZXN1bHRzKS4KLSBBbnkgcmVmZXJlbmNlIHRvIGBOVkNG" + + "QmFja2VuZGAsIGBOVkNBYCwgSUNNUywgaGVsbSByZWxlYXNlcyBsaWtlIGBoZWxtLW52Y2YtKmAs" + + "IG9yIGBpY21zLjxkb21haW4+YCAvIGBhcGkuPGRvbWFpbj5gIFVSTHMuCgojIyBRdWljayBzdGFy" + + "dAoKRm9yIHJlbW90ZSBvbmUtY2xpY2sgaW5zdGFsbHMsIHByZXBhcmUgR2F0ZXdheSBBUEkgaW5n" + + "cmVzcyBhbmQgQ0xJIGVuZHBvaW50CmNvbmZpZ3VyYXRpb24gYmVmb3JlIHJ1bm5pbmcgYHNlbGYt" + + "aG9zdGVkIHVwYC4gVGhlIGNvbW1hbmQgYXBwbGllcyB0aGUgY29udHJvbApwbGFuZSBhbmQgdGhl" + + "biBpbW1lZGlhdGVseSBjYWxscyBBUEksIEFQSSBLZXlzLCBpbnZvY2F0aW9uLCBhbmQgZ1JQQyBl" + + "bmRwb2ludHMuCklmIHRoZSBHYXRld2F5IGlzIG5vdCBwcm9ncmFtbWVkIG9yIHRoZSBDTEkgaG9z" + + "dCBoZWFkZXJzIGRvIG5vdCBtYXRjaCB0aGUKSFRUUFJvdXRlcyByZW5kZXJlZCBieSB0aGUgc3Rh" + + "Y2sgZW52aXJvbm1lbnQsIHBvc3QtaW5zdGFsbCBoZWFsdGggYW5kIGNsdXN0ZXIKcmVnaXN0cmF0" + + "aW9uIHdpbGwgZmFpbC4KCmBgYHNoCiMgU2luZ2xlLWNsdXN0ZXIgKGNvbnRyb2wgKyBjb21wdXRl" + + "IG9uIHRoZSBjdXJyZW50IGt1YmVjb25maWcgY29udGV4dCk6Cm52Y2YtY2xpIHNlbGYtaG9zdGVk" + + "IHVwIC0tY2x1c3Rlci1uYW1lPW5jcC1sb2NhbAoKIyBTcGxpdC1jbHVzdGVyIChjb250cm9sIHBs" + + "YW5lIG9uIGNvbnRleHQgQSwgY29tcHV0ZSBwbGFuZSBvbiBjb250ZXh0IEIpOgpLVUJFQ09ORklH" + + "PWNwLnlhbWw6Z3B1MS55YW1sIG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVwIFwKICAtLWNsdXN0ZXIt" + + "bmFtZT1uY3AtbG9jYWwgXAogIC0tY29udHJvbC1wbGFuZS1jb250ZXh0PWFkbWluQGNwIFwKICAt" + + "LWNvbXB1dGUtcGxhbmUtY29udGV4dD1hZG1pbkBncHUxIFwKICAtLWljbXMtdXJsPWh0dHBzOi8v" + + "aWNtcy5udmNmLmV4YW1wbGUuY29tCgojIEFkZCBhIG5ldyBjb21wdXRlIHBsYW5lIHRvIGFuIGV4" + + "aXN0aW5nIGNvbnRyb2wgcGxhbmUgKG5vIGt1YmVjdGwgYWNjZXNzIHRvIENQIG5lZWRlZDsKIyBy" + + "ZWFjaGVzIHRoZSBjb250cm9sIHBsYW5lIHZpYSB0aGUgcHVibGljIElDTVMgSFRUUFJvdXRlKToK" + + "bnZjZi1jbGkgc2VsZi1ob3N0ZWQgYWRkLWNvbXB1dGUtcGxhbmUgXAogIC0tY2x1c3Rlci1uYW1l" + + "PW5jcC1sb2NhbC0yIFwKICAtLWNvbXB1dGUtcGxhbmUtY29udGV4dD1hZG1pbkBncHUyIFwKICAt" + + "LWljbXMtdXJsPWh0dHBzOi8vaWNtcy5udmNmLmV4YW1wbGUuY29tIFwKICAtLXRva2VuPSRBRE1J" + + "Tl9KV1QKCiMgVGVhciBkb3duIChhbHdheXMgcGxhbi1vbmx5IGZpcnN0KToKbnZjZi1jbGkgc2Vs" + + "Zi1ob3N0ZWQgZG93biAtLXBsYW4tb25seSAtLWNsdXN0ZXItbmFtZT1uY3AtbG9jYWwgLS1qc29u" + + "IHwganEKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93biAtLWNsdXN0ZXItbmFtZT1uY3AtbG9jYWwK" + + "CiMgUGVyLXBsYW5lIHVuaW5zdGFsbCAoR2l0T3BzOyBtaXJyb3JzIGBpbnN0YWxsYCk6Cm52Y2Yt" + + "Y2xpIHNlbGYtaG9zdGVkIHVuaW5zdGFsbCAtLW5vLWFwcGx5IC0tY29tcHV0ZS1wbGFuZSAtLWNs" + + "dXN0ZXItbmFtZT1uY3AtbG9jYWwgfCBrdWJlY3RsIGRlbGV0ZSAtZiAtCmBgYAoKPiAqKmB1cGAg" + + "dnMgYGFkZC1jb21wdXRlLXBsYW5lYC4qKiBgdXBgIGFsd2F5cyBpbnN0YWxscyBib3RoIHBsYW5l" + + "cyDigJQgdXNlIGl0IGZvciB0aGUgKmZpcnN0KiBpbnN0YWxsLiBgYWRkLWNvbXB1dGUtcGxhbmVg" + + "IGlzIHRoZSByaWdodCBzdWJjb21tYW5kIGFueSB0aW1lIHRoZSBjb250cm9sIHBsYW5lIGlzIGFs" + + "cmVhZHkgcnVubmluZyBhbmQgeW91IHdhbnQgdG8gYXR0YWNoIGFuIE50aCBjb21wdXRlIGNsdXN0" + + "ZXIuCj4KPiAqKmBkb3duYCBhbHdheXMgd2l0aCBgLS1wbGFuLW9ubHlgIGZpcnN0LioqIFNob3cg" + + "dGhlIHVzZXIgdGhlIGB3aWxsVW5pbnN0YWxsLmNvbW1hbmRzW11gIGFycmF5IGJlZm9yZSBydW5u" + + "aW5nIGZvciByZWFsLgoKIyMgQXV0aGVudGljYXRpb24KCmBudmNmLWNsaWAgdXNlcyB0d28gY3Jl" + + "ZGVudGlhbHMuIEVhY2ggaXMgcmVzb2x2ZWQgaW5kZXBlbmRlbnRseSBpbiB0aGlzIG9yZGVyOgoK" + + "fCBQcmVjZWRlbmNlIHwgU291cmNlIHwKfC0tLXwtLS18CnwgMSAoaGlnaGVzdCkgfCBFbnZpcm9u" + + "bWVudCB2YXJpYWJsZSAoYE5WQ0ZfVE9LRU5gLCBgTlZDRl9BUElfS0VZYCkgfAp8IDIgfCBDb25m" + + "aWcgZmlsZSAoYH4vLm52Y2YtY2xpLnlhbWxgLCBrZXlzIGB0b2tlbmAgYW5kIGBhcGlfa2V5YCkg" + + "fAp8IDMgfCBTdGF0ZSBmaWxlIChgfi8ubnZjZi1jbGkuc3RhdGVgKSwgc2tpcHBlZCB3aGVuIHRo" + + "ZSBzdG9yZWQgdG9rZW4gaXMgZXhwaXJlZCB8Cgp8IEVudiB2YXIgfCBUb2tlbiB0eXBlIHwgVXNl" + + "ZCBieSB8CnwtLS18LS0tfC0tLXwKfCBgTlZDRl9UT0tFTmAgfCBBZG1pbiBKV1QgfCBgZnVuY3Rp" + + "b24gY3JlYXRlYCAvIGBkZXBsb3lgIC8gYHVwZGF0ZWAgLyBgZGVsZXRlYCwgY2x1c3RlciBtYW5h" + + "Z2VtZW50IChgY2x1c3RlciByZWdpc3RlcmAvYGxpc3QtcmVnaXN0ZXJlZGAvYHJvdGF0ZWAvYGRl" + + "bGV0ZWAsIGBzZWxmLWhvc3RlZGAgb3BzKS4gUmVxdWlyZWQgZm9yIGFkbWluIGNvbW1hbmRzOyBw" + + "cmVmZXJyZWQgZm9yIHRoZSByZXN0LiB8CnwgYE5WQ0ZfQVBJX0tFWWAgfCBgbnZhcGktLi4uYCBB" + + "UEkga2V5IHwgYGZ1bmN0aW9uIGludm9rZWAgLyBgbGlzdGAgLyBgZ2V0YCwgcXVldWUgZGV0YWls" + + "cy4gRmFsbHMgYmFjayB0byBgTlZDRl9UT0tFTmAgd2hlbiB1bnNldC4gfAoKVG9rZW4gZ2VuZXJh" + + "dGlvbiBmbG93OgoKMS4gUG9pbnQgdGhlIENMSSBhdCB5b3VyIHNlbGYtaG9zdGVkIGVuZHBvaW50" + + "cy4gRGVmYXVsdHMgdGFyZ2V0IHByb2R1Y3Rpb24gTlZDRjsgb3ZlcnJpZGUgd2l0aCBlbnYgdmFy" + + "cyBvciBhIHlhbWwgZmlsZSAoYC0tY29uZmlnIDxwYXRoPmAsIGAuLy5udmNmLWNsaS55YW1sYCwg" + + "b3IgYH4vLm52Y2YtY2xpLnlhbWxgOyBhIGZ1bGwgdGVtcGxhdGUgc2hpcHMgYXQgYHNyYy9jbGlz" + + "L252Y2YtY2xpLy5udmNmLWNsaS55YW1sLnRlbXBsYXRlYCkuCgogICBgTlZDRl9CQVNFX0hUVFBf" + + "VVJMYCAvIGBBUElfS0VZU19TRVJWSUNFX1VSTGAgLyBgTlZDRl9CQVNFX0dSUENfVVJMYCB0ZWxs" + + "IHRoZSBDTEkgKndoZXJlIHRvIHNlbmQgcmVxdWVzdHMqLiBgQVBJX0hPU1RgIC8gYEFQSV9LRVlT" + + "X0hPU1RgIC8gYElOVk9LRV9IT1NUYCBzZXQgdGhlIGBIb3N0OmAgaGVhZGVyIG9uIHRob3NlIHJl" + + "cXVlc3RzIOKAlCBuZWVkZWQgd2hlbiBldmVyeSBOVkNGIHNlcnZpY2Ugc2l0cyBiZWhpbmQgYSBz" + + "aW5nbGUgZ2F0ZXdheSB0aGF0IHJvdXRlcyBieSBob3N0bmFtZSAoRW52b3kgR2F0ZXdheSBIVFRQ" + + "Um91dGUgb24gYGFwaS48RUxCPmAsIGBhcGkta2V5cy48RUxCPmAsIGBpbnZvY2F0aW9uLjxFTEI+" + + "YCwgYGxsbS48RUxCPmApLiBTa2lwIHRoZSB0aHJlZSBIb3N0IHZhcnMgd2hlbiB0aGUgYmFzZSBV" + + "UkwgYWxyZWFkeSByZXNvbHZlcyB0byB0aGUgcmlnaHQgc2VydmljZS4KCiAgIEVudi12YXIgZm9y" + + "bToKCiAgIGBgYHNoCiAgIGV4cG9ydCBOVkNGX0JBU0VfSFRUUF9VUkw9aHR0cHM6Ly9ndy5leGFt" + + "cGxlLmNvbQogICBleHBvcnQgQVBJX0tFWVNfU0VSVklDRV9VUkw9aHR0cHM6Ly9ndy5leGFtcGxl" + + "LmNvbQogICBleHBvcnQgTlZDRl9CQVNFX0dSUENfVVJMPWd3LmV4YW1wbGUuY29tOjQ0MwoKICAg" + + "IyBPbmx5IHdoZW4gdGhlIGdhdGV3YXkgcm91dGVzIGJ5IEhvc3QgaGVhZGVyOgogICBleHBvcnQg" + + "QVBJX0tFWVNfSE9TVD1hcGkta2V5cy5ndy5leGFtcGxlLmNvbQogICBleHBvcnQgQVBJX0hPU1Q9" + + "YXBpLmd3LmV4YW1wbGUuY29tCiAgIGV4cG9ydCBJTlZPS0VfSE9TVD1pbnZvY2F0aW9uLmd3LmV4" + + "YW1wbGUuY29tCiAgIGBgYAoKICAgWWFtbCBmb3JtIChgfi8ubnZjZi1jbGkueWFtbGApOgoKICAg" + + "YGBgeWFtbAogICBiYXNlX2h0dHBfdXJsOiBodHRwczovL2d3LmV4YW1wbGUuY29tCiAgIGFwaV9r" + + "ZXlzX3NlcnZpY2VfdXJsOiBodHRwczovL2d3LmV4YW1wbGUuY29tCiAgIGJhc2VfZ3JwY191cmw6" + + "IGd3LmV4YW1wbGUuY29tOjQ0MwoKICAgIyBPbmx5IHdoZW4gdGhlIGdhdGV3YXkgcm91dGVzIGJ5" + + "IEhvc3QgaGVhZGVyOgogICBhcGlfa2V5c19ob3N0OiBhcGkta2V5cy5ndy5leGFtcGxlLmNvbQog" + + "ICBhcGlfaG9zdDogYXBpLmd3LmV4YW1wbGUuY29tCiAgIGludm9rZV9ob3N0OiBpbnZvY2F0aW9u" + + "Lmd3LmV4YW1wbGUuY29tCiAgIGBgYAoKMi4gYG52Y2YtY2xpIGluaXRgIGNhbGxzIHRoZSBBUEkg" + + "S2V5cyBzZXJ2aWNlIHZpYSB0aG9zZSBlbmRwb2ludHMgYW5kIHdyaXRlcyB0aGUgYWRtaW4gdG9r" + + "ZW4gdG8gYH4vLm52Y2YtY2xpLnN0YXRlYC4gVXNlIGBudmNmLWNsaSByZWZyZXNoYCB0byByb3Rh" + + "dGUgYSBzdG9yZWQgdG9rZW4uCjMuIEFmdGVyIGBpbml0YCwgYG52Y2YtY2xpIGFwaS1rZXkgZ2Vu" + + "ZXJhdGVgIG1pbnRzIGZ1bmN0aW9uICsgdGFzayBBUEkga2V5cyAoYWxzbyBzdG9yZWQgaW4gc3Rh" + + "dGUpLgoKQWZ0ZXIgYGluaXRgLCB0aGUgY3JlZGVudGlhbHMgbGl2ZSBpbiBgfi8ubnZjZi1jbGku" + + "c3RhdGVgLCBzbyBsYXRlciBjb21tYW5kcyB3b3JrIHdpdGhvdXQgZXhwb3J0aW5nIGBOVkNGX1RP" + + "S0VOYCBvciBgTlZDRl9BUElfS0VZYC4gRXhwb3J0IHRoZSBlbnYgdmFyIG9ubHkgdG8gb3ZlcnJp" + + "ZGUgdGhlIHN0b3JlZCB2YWx1ZSAoZm9yIGV4YW1wbGUgYSBzaG9ydGVyLWxpdmVkIHRva2VuIGZy" + + "b20gQ0kpLgoKIyMgQ29yZSBzdWJjb21tYW5kcwoKfCBTdWJjb21tYW5kIHwgV2hhdCBpdCBkb2Vz" + + "IHwgV2hlbiB0byB1c2UgfAp8LS0tfC0tLXwtLS18CnwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGNo" + + "ZWNrIC0tcHJlIFstLWxvY2FsLW9ubHkgXHwgLS1jb250cm9sLXBsYW5lLWNvbnRleHQ9WCBcfCAt" + + "LWNvbXB1dGUtcGxhbmUtY29udGV4dD1ZXWAgfCBQcmUtZmxpZ2h0OiBsb2NhbC1ob3N0IHRvb2xz" + + "ICsgY2x1c3Rlci1zaWRlIHByZXJlcXVpc2l0ZXMgfCBBbHdheXMgcnVuIGZpcnN0IG9uIGEgbmV3" + + "IGVudmlyb25tZW50IHwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgaW5zdGFsbCAtLWNvbnRyb2wt" + + "cGxhbmUgXHwga3ViZWN0bCBhcHBseSAtZiAtYCB8IFJlbmRlciArIGFwcGx5IHRoZSBjb250cm9s" + + "IHBsYW5lIHwgV2hlbiB5b3Ugd2FudCBtYW51YWwgY29udHJvbCBvdmVyIGFwcGx5IChHaXRPcHMt" + + "ZnJpZW5kbHkpIHwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgaW5zdGFsbCAtLWNvbXB1dGUtcGxh" + + "bmUgLS1jbHVzdGVyLW5hbWU9WCBcfCBrdWJlY3RsIGFwcGx5IC1mIC1gIHwgUmVnaXN0ZXIgY2x1" + + "c3RlciArIHJlbmRlciBjb21wdXRlIHBsYW5lIHwgU2FtZSDigJQgbWFudWFsIGFwcGx5IHBhdGgg" + + "fAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1cCAtLWNsdXN0ZXItbmFtZT1YYCB8IE9uZS1zaG90" + + "IGZpcnN0IGluc3RhbGw6IHByZS1mbGlnaHQg4oaSIGNvbnRyb2wgcGxhbmUg4oaSIHJlZ2lzdGVy" + + "IOKGkiBjb21wdXRlIHBsYW5lIHwgU3RhbmRhcmQgaW5zdGFsbCBwYXRoIChib3RoIHBsYW5lcyBm" + + "cm9tIHNjcmF0Y2gpIHwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgdXAgLS1wbGFuLW9ubHkgLS1j" + + "bHVzdGVyLW5hbWU9WGAgfCBEcnktcnVuOiBlbWl0IHBoYXNlLWJ5LXBoYXNlIHBsYW4gKyBFVEEg" + + "d2l0aG91dCBjaGFuZ2luZyBzdGF0ZSB8IEFnZW50IC8gQ0kgcHJldmlldyBiZWZvcmUgY29tbWl0" + + "IHwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgYWRkLWNvbXB1dGUtcGxhbmUgLS1jbHVzdGVyLW5h" + + "bWU9WCAtLWNvbXB1dGUtcGxhbmUtY29udGV4dD1ZIC0taWNtcy11cmw94oCmIC0tdG9rZW49JEpX" + + "VGAgfCBBZGQgYSBuZXcgY29tcHV0ZSBwbGFuZSB0byBhbiAqZXhpc3RpbmcqIGNvbnRyb2wgcGxh" + + "bmUgKG5vIENQIGluc3RhbGwpIHwgQWRkaW5nIHRoZSAybmQsIDNyZCwg4oCmIEdQVSBjbHVzdGVy" + + "IGFmdGVyIHRoZSBpbml0aWFsIGB1cGAgfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1bmluc3Rh" + + "bGwgLS1jb250cm9sLXBsYW5lYCB8IFBlci1wbGFuZSBwcmltaXRpdmU6IGBoZWxtZmlsZSBkZXN0" + + "cm95YCBvbiB0aGUgY29udHJvbCBwbGFuZSAocmVmdXNlcyBpZiBjb21wdXRlIHBsYW5lcyBzdGls" + + "bCByZWdpc3RlcmVkKSB8IEZpbmFsIHRlYXJkb3duIGFmdGVyIGFsbCBjb21wdXRlIHBsYW5lcyBh" + + "cmUgZ29uZSwgb3Igc2NyaXB0ZWQgcGlwZWxpbmVzIHwKfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQg" + + "dW5pbnN0YWxsIC0tY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXItbmFtZT1YYCB8IFBlci1wbGFuZSBw" + + "cmltaXRpdmU6IGBoZWxtZmlsZSBkZXN0cm95YCBvbiBhIGNvbXB1dGUgcGxhbmUgKG5vIElDTVMg" + + "dW5yZWdpc3Rlciwgbm8gZHJhaW4pIHwgSnVzdCByZW1vdmUgdGhlIGhlbG0gcmVsZWFzZXMgd2l0" + + "aG91dCB0aGUgSUNNUy1zaWRlIGNsZWFudXAgfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1bmlu" + + "c3RhbGwgLS1uby1hcHBseSA8cGxhbmU+YCB8IFJlbmRlciBkZWxldGUgWUFNTCB2aWEgYGhlbG0g" + + "Z2V0IG1hbmlmZXN0YCB8IEdpdE9wczsgYFx8IGt1YmVjdGwgZGVsZXRlIC1mIC1gIG9yIGNvbW1p" + + "dCArIEFyZ28gYXBwbGllcyB8CnwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1jbHVzdGVy" + + "LW5hbWU9WGAgfCBPcmNoZXN0cmF0b3I6IGRyYWluIOKGkiB1bmluc3RhbGwgLS1jb21wdXRlLXBs" + + "YW5lIOKGkiBjbHVzdGVyIGRlbGV0ZSBpbiBJQ01TIHwgU3RhbmRhcmQgInJlbW92ZSBvbmUgR1BV" + + "IGNsdXN0ZXIiIHBhdGggfAp8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tYWxsIC0tY29u" + + "ZmlybWAgfCBPcmNoZXN0cmF0b3I6IHRlYXIgZG93biBldmVyeSByZWdpc3RlcmVkIGNvbXB1dGUg" + + "cGxhbmUgKyBjb250cm9sIHBsYW5lIHwgRnVsbCB1bmluc3RhbGwgfAp8IGBudmNmLWNsaSBzZWxm" + + "LWhvc3RlZCBkb3duIC0tcGxhbi1vbmx5IC0tY2x1c3Rlci1uYW1lPVhgIHwgRHJ5LXJ1biBwcmV2" + + "aWV3IChwaGFzZXMgKyBoZWxtIHJlbGVhc2VzICsgSUNNUyByb3dzICsgRVRBczsgbm8gaGVsbS9o" + + "ZWxtZmlsZSBjb250YWN0KSB8ICoqQUxXQVlTIHJ1biBiZWZvcmUgYW55IGFjdHVhbCBgZG93bmAq" + + "KiB8CnwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHN0YXR1cyBbLS1jbHVzdGVyLW5hbWU9WF0gWy0t" + + "d2F0Y2hdIFstLWpzb25dYCB8IFNuYXBzaG90IGRhc2hib2FyZCBvZiBjbHVzdGVyIGlkZW50aXR5" + + "ICsgY29tcG9uZW50IGhlYWx0aCArIHJlY2VudCBldmVudHMgfCBSb3V0aW5lIGhlYWx0aCBjaGVj" + + "a3M7IGAtLXdhdGNoYCBmb3IgbGl2ZSB8CnwgYG52Y2YtY2xpIGluaXRgIHwgTWludCBhZG1pbiB0" + + "b2tlbiBmcm9tIEFQSSBLZXlzIHNlcnZpY2UgdmlhIHRoZSBwdWJsaWMgYXBpIGdhdGV3YXkgfCBC" + + "ZWZvcmUgYW55IGNsdXN0ZXItbWFuYWdlbWVudCBvcGVyYXRpb247IGlkZW1wb3RlbnQgfAp8IGBu" + + "dmNmLWNsaSBjbHVzdGVyIHJlZ2lzdGVyIC0tbmFtZT1YIC0tbmNhLWlkPVkgLS1yZWdpb249WiBb" + + "LS1pZ25vcmUtZXhpc3RpbmddYCB8IFJlZ2lzdGVyIGEgY2x1c3RlciBKV0tTK09JREMgaXNzdWVy" + + "IHdpdGggSUNNUyB8IFN0YW5kYWxvbmUgcmVnaXN0ZXIgKHdpdGhvdXQgY29tcHV0ZS1wbGFuZSBp" + + "bnN0YWxsKSB8CnwgYG52Y2YtY2xpIGNsdXN0ZXIgbGlzdC1yZWdpc3RlcmVkIC0tbmNhLWlkPVkg" + + "Wy0taWNtcy11cmw9VVJMXWAgfCBMaXN0IHNlbGYtaG9zdGVkIGNsdXN0ZXIgcmVnaXN0cmF0aW9u" + + "cyBmcm9tIElDTVMgfCBDaGVjayByZWdpc3RlcmVkIGNvbXB1dGUtcGxhbmUgbmFtZXMgYW5kIElE" + + "cyB3aXRoIHRoZSBhZG1pbiB0b2tlbiB8CnwgYG52Y2YtY2xpIGNsdXN0ZXIgcm90YXRlIC0tY2x1" + + "c3Rlci1pZD1JRGAgfCBSb3RhdGUgY2x1c3RlciBKV0tTIGluIElDTVMgfCBXaGVuIE5WQ0EncyBL" + + "OHMgc2lnbmluZyBrZXkgY2hhbmdlZCBhbmQgUFNBVCB2ZXJpZmljYXRpb24gc3RhcnRlZCA0MDEt" + + "aW5nIHwKfCBgbnZjZi1jbGkgY2x1c3RlciBkZWxldGUgLS1jbHVzdGVyLWlkPUlEYCB8IFJlbW92" + + "ZSBjbHVzdGVyIHJlZ2lzdHJhdGlvbiBmcm9tIElDTVMgfCAqKkNvbmZpcm0gd2l0aCB1c2VyLioq" + + "IERlc3Ryb3lzIElDTVMgc3RhdGUgZm9yIHRoZSBjbHVzdGVyLiB8CnwgYG52Y2YtY2xpIGFwaS1r" + + "ZXkgZ2VuZXJhdGUgLS1kZXNjcmlwdGlvbj0i4oCmIiAtLWV4cGlyZXMtaW49MWhgIHwgTWludCBi" + + "b3RoIGEgZnVuY3Rpb24gQVBJIGtleSBhbmQgYSB0YXNrIEFQSSBrZXkgKGRlZmF1bHQpIHwgQmVm" + + "b3JlIGludm9raW5nIGZ1bmN0aW9ucyBvciBjcmVhdGluZyB0YXNrczsgcnVuIGFmdGVyIGV2ZXJ5" + + "IGBpbml0YCB8CnwgYG52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1mb3IgZnVuY3Rpb24gLS1k" + + "ZXNjcmlwdGlvbj0i4oCmImAgfCBNaW50IGEgZnVuY3Rpb24gQVBJIGtleSBvbmx5IChgaW52b2tl" + + "X2Z1bmN0aW9uYCBzY29wZSkgfCBXaGVuIG9ubHkgZnVuY3Rpb24gaW52b2NhdGlvbiBpcyBuZWVk" + + "ZWQgfAp8IGBudmNmLWNsaSBhcGkta2V5IGdlbmVyYXRlIC0tZm9yIHRhc2sgLS1kZXNjcmlwdGlv" + + "bj0i4oCmImAgfCBNaW50IGEgdGFzayBBUEkga2V5IG9ubHkgfCBXaGVuIG9ubHkgdGFzayBvcGVy" + + "YXRpb25zIGFyZSBuZWVkZWQgfAp8IGBudmNmLWNsaSBmdW5jdGlvbiBjcmVhdGUgLS1pbnB1dC1m" + + "aWxlPTxqc29uPmAgfCBDcmVhdGUgZnVuY3Rpb24gbWV0YWRhdGEgaW4gSUNNUyB8IEZpcnN0IHN0" + + "ZXAgb2YgYW55IGZ1bmN0aW9uIGRlcGxveTsgdXNlIGBmdW5jdGlvblR5cGU6ICJMTE0iYCBhbmQg" + + "YG1vZGVsc1tdLmxsbUNvbmZpZ2AgZm9yIExMTSBmdW5jdGlvbnMgfAp8IGBudmNmLWNsaSBmdW5j" + + "dGlvbiBkZXBsb3kgY3JlYXRlIC0taW5wdXQtZmlsZT08anNvbj5gIHwgU2NoZWR1bGUgYSBkZXBs" + + "b3ltZW50IG9mIGEgY3JlYXRlZCBmdW5jdGlvbiB8IFdhaXRzIGZvciBBQ1RJVkUgYmVmb3JlIHJl" + + "dHVybmluZyAodGltZW91dCA5MDBzKSB8CnwgYG52Y2YtY2xpIGZ1bmN0aW9uIGludm9rZSAtLWlu" + + "cHV0LWZpbGU9PGpzb24+YCB8IEludm9rZSBhIGRlcGxveWVkIGZ1bmN0aW9uIHwgUmVxdWlyZXMg" + + "QVBJIGtleSAobm90IGFkbWluIHRva2VuKSB8CnwgYG52Y2YtY2xpIGZ1bmN0aW9uIGRlbGV0ZSAt" + + "LWZ1bmN0aW9uLWlkPUlEIC0tdmVyc2lvbi1pZD1WSURgIHwgUmVtb3ZlIGEgZnVuY3Rpb24gYW5k" + + "IGl0cyBkZXBsb3ltZW50IHwgKipDb25maXJtIHdpdGggdXNlci4qKiB8CnwgYG52Y2YtY2xpIHRh" + + "c2sgY3JlYXRlIC0tbmFtZT1YIC0tZ3B1PUgxMDAgLS1pbnN0YW5jZS10eXBlPVkgLS1pbWFnZT1a" + + "YCB8IFN1Ym1pdCBhIGNvbnRhaW5lciB0YXNrOyBzYXZlcyB0YXNrIElEIHRvIENMSSBzdGF0ZSB8" + + "IFJlcXVpcmVzIHRhc2sgQVBJIGtleTsgc2V0IGBOVkNGX0JBU0VfTlZDVF9VUkxgIHRvIHRoZSBO" + + "VkNUIGdhdGV3YXkgZW5kcG9pbnQgfAp8IGBudmNmLWNsaSB0YXNrIGNyZWF0ZSAtLW5hbWU9WCAt" + + "LWdwdT1IMTAwIC0taW5zdGFuY2UtdHlwZT1ZIC0taGVsbS1jaGFydD1aYCB8IFN1Ym1pdCBhIEhl" + + "bG0gdGFzayB8IFNhbWUgYXMgY29udGFpbmVyIHRhc2s7IGAtLWhlbG0tY2hhcnRgIHJlcGxhY2Vz" + + "IGAtLWltYWdlYCB8CnwgYG52Y2YtY2xpIHRhc2sgY3JlYXRlIC0taW5wdXQtZmlsZT08anNvbj5g" + + "IHwgU3VibWl0IGEgdGFzayBmcm9tIGEgSlNPTiBjb25maWcgZmlsZSB8IFJlY29tbWVuZGVkIGZv" + + "ciByZXBlYXRhYmxlIGNvbmZpZ3VyYXRpb25zIHwKfCBgbnZjZi1jbGkgdGFzayBsaXN0IFstLXN0" + + "YXR1cz1RVUVVRURcfFJVTk5JTkdcfENPTVBMRVRFRF1gIHwgTGlzdCB0YXNrcywgb3B0aW9uYWxs" + + "eSBmaWx0ZXJlZCBieSBzdGF0dXMgfCB8CnwgYG52Y2YtY2xpIHRhc2sgZ2V0IFt0YXNrSWRdYCB8" + + "IEdldCBkZXRhaWxzIGZvciBhIHRhc2s7IHVzZXMgc2F2ZWQgdGFzayBJRCBpZiBvbWl0dGVkIHwg" + + "fAp8IGBudmNmLWNsaSB0YXNrIGV2ZW50cyBbdGFza0lkXWAgfCBTdHJlYW0gbGlmZWN5Y2xlIGV2" + + "ZW50cyBmb3IgYSB0YXNrIHwgfAp8IGBudmNmLWNsaSB0YXNrIHJlc3VsdHMgW3Rhc2tJZF1gIHwg" + + "TGlzdCByZXN1bHQgYXJ0aWZhY3RzIGZvciBhIGNvbXBsZXRlZCB0YXNrIHwgUmVzdWx0IHVwbG9h" + + "ZCBub3QgeWV0IHN1cHBvcnRlZDsgcmV0dXJucyBlbXB0eSBsaXN0IGZvciBgTk9ORWAgc3RyYXRl" + + "Z3kgfAp8IGBudmNmLWNsaSB0YXNrIGNhbmNlbCBbdGFza0lkXWAgfCBDYW5jZWwgYSBxdWV1ZWQg" + + "b3IgcnVubmluZyB0YXNrIHwgfAp8IGBudmNmLWNsaSB0YXNrIGRlbGV0ZSBbdGFza0lkXWAgfCBE" + + "ZWxldGUgYSB0YXNrIHJlY29yZCB8ICoqQ29uZmlybSB3aXRoIHVzZXIuKiogfAp8IGBudmNmLWNs" + + "aSB0YXNrIHVwZGF0ZS1zZWNyZXRzIFt0YXNrSWRdIC0tc2VjcmV0cyBOQU1FPXZhbHVlYCB8IFVw" + + "ZGF0ZSBzZWNyZXRzIG9uIGEgdGFzazsgc3VwcGxpZWQgc2VjcmV0cyBhcmUgYWRkZWQgb3IgdXBk" + + "YXRlZCBieSBuYW1lLCBleGlzdGluZyBzZWNyZXRzIG5vdCBpbiB0aGUgcmVxdWVzdCBhcmUgcHJl" + + "c2VydmVkIHwgfAp8IGBudmNmLWNsaSB0YXNrIGJ1bGsgLS10YXNrLWlkcz1JRDEsSUQyYCB8IEZl" + + "dGNoIGRldGFpbHMgZm9yIG11bHRpcGxlIHRhc2tzIGluIG9uZSBjYWxsIHwgfAoKPiBSZWdpc3Ry" + + "eSBjcmVkZW50aWFsIHByb3BhZ2F0aW9uOiBhZnRlciBgcmVnaXN0cnktY3JlZGVudGlhbCBhZGRg" + + "L2B1cGRhdGVgL2BkZWxldGVgLCB0YXNrIGNyZWF0aW9uIGNhbiBrZWVwIHVzaW5nIHRoZSBwcmV2" + + "aW91cyBjcmVkZW50aWFsIGZvciB1cCB0byBhYm91dCA1IG1pbnV0ZXMgKE5WQ1QgY2FjaGVzIGFj" + + "Y291bnQgY3JlZGVudGlhbHMgYXQgYG52Y3QubnZjZi5jYWNoZS10dGxgLCBkZWZhdWx0IGBQVDVN" + + "YCksIGV2ZW4gdGhvdWdoIGByZWdpc3RyeS1jcmVkZW50aWFsIGxpc3RgL2BnZXRgIHNob3cgdGhl" + + "IG5ldyB2YWx1ZSBpbW1lZGlhdGVseS4gV2FpdCBhYm91dCA1IG1pbnV0ZXMsIG9yIGBrdWJlY3Rs" + + "IC1uIG52Y2Ygcm9sbG91dCByZXN0YXJ0IGRlcGxveW1lbnQvbnZjdC1hcGlgIHRvIGFwcGx5IGlt" + + "bWVkaWF0ZWx5LiBTZWUgW3JlZmVyZW5jZS90cm91Ymxlc2hvb3RpbmcubWRdKHJlZmVyZW5jZS90" + + "cm91Ymxlc2hvb3RpbmcubWQpLgoKIyMgTExNIGZ1bmN0aW9uIHR5cGUKClVzZSBgZnVuY3Rpb25U" + + "eXBlOiAiTExNImAgZm9yIE9wZW5BSS1jb21wYXRpYmxlIG1vZGVscyBzZXJ2ZWQgdGhyb3VnaCB0" + + "aGUgc2VsZi1tYW5hZ2VkIExMTSBHYXRld2F5LiBMTE0gZnVuY3Rpb25zIG11c3QgZGVmaW5lIGF0" + + "IGxlYXN0IG9uZSBgbW9kZWxzW11gIGVudHJ5IHdpdGggYG5hbWVgIGFuZCBgbGxtQ29uZmlnLnVy" + + "aXNgOyB0aGUgc3VwcG9ydGVkIHVwc3RyZWFtIHBhdGhzIGFyZSBgL3YxL2NoYXQvY29tcGxldGlv" + + "bnNgLCBgL3YxL3Jlc3BvbnNlc2AsIGFuZCBgL3YxL2VtYmVkZGluZ3NgLgoKVXNlIGAvaGVhbHRo" + + "YCBvbiBwb3J0IGA4MDAwYCBhcyB0aGUgZGVmYXVsdCBPcGVuQUktY29tcGF0aWJsZSBjb250YWlu" + + "ZXIgaGVhbHRoIHByb2JlIHVubGVzcyB0aGUgaW1hZ2UgZXhwb3NlcyBhIGRpZmZlcmVudCByZWFk" + + "aW5lc3MgcGF0aC4KCkxMTSBmdW5jdGlvbiB0eXBlIGlzIGluZGVwZW5kZW50IG9mIHdvcmtsb2Fk" + + "IHBhY2thZ2luZy4gRm9yIGEgSGVsbS1jaGFydCBiYWNrZWQgTExNIGZ1bmN0aW9uLCBrZWVwIGBm" + + "dW5jdGlvblR5cGU6ICJMTE0iYCBhbmQgYG1vZGVsc1tdLmxsbUNvbmZpZ2AsIHRoZW4gc2V0IGBo" + + "ZWxtQ2hhcnRgIGFuZCBgaGVsbUNoYXJ0U2VydmljZU5hbWVgIGluIHRoZSBjcmVhdGUgcmVxdWVz" + + "dC4gYGhlbG1DaGFydFNlcnZpY2VOYW1lYCBtdXN0IG1hdGNoIHRoZSBLdWJlcm5ldGVzIFNlcnZp" + + "Y2UgZXhwb3NlZCBieSB0aGUgY2hhcnQsIGFuZCBgaW5mZXJlbmNlUG9ydGAgbXVzdCBiZSB0aGF0" + + "IFNlcnZpY2UgcG9ydC4KCkludm9jYXRpb24gdXNlcyB0aGUgTExNIHJvdXRlLCBmb3IgZXhhbXBs" + + "ZSBgaHR0cHM6Ly9sbG0uaW52b2NhdGlvbi48ZG9tYWluPi92MS9jaGF0L2NvbXBsZXRpb25zYC4g" + + "VGhlIE9wZW5BSSBgbW9kZWxgIHZhbHVlIG11c3QgYmUgYDxmdW5jdGlvbi1pZD4vPG1vZGVsLW5h" + + "bWU+YDsgdGhlIGZ1bmN0aW9uIElEIGlzIHRoZSByb3V0aW5nIGtleSBhbmQgdGhlIG1vZGVsIG5h" + + "bWUgaXMgZm9yd2FyZGVkIHVwc3RyZWFtLgoKVXBkYXRlIG11dGFibGUgcGVyLW1vZGVsIHJvdXRp" + + "bmcgc2V0dGluZ3Mgd2l0aCBgbnZjZi1jbGkgZnVuY3Rpb24gdXBkYXRlIC0tbGxtLW1vZGVsLXVw" + + "ZGF0ZT0nbmFtZT08bW9kZWw+LHJvdXRpbmdNZXRob2Q9PG1ldGhvZD4sdG9rZW5SYXRlTGltaXQ9" + + "PGxpbWl0PidgLCBvciBwdXQgdGhlIHNhbWUgZmllbGRzIHVuZGVyIGBtb2RlbFVwZGF0ZXNbXS5s" + + "bG1Db25maWdgIGluIGFuIHVwZGF0ZSBKU09OIGZpbGUuIFNlZSBbcmVmZXJlbmNlL2ZsYWdzLm1k" + + "XShyZWZlcmVuY2UvZmxhZ3MubWQpIGZvciBhY2NlcHRlZCByb3V0aW5nIG1ldGhvZHMuIGB0b2tl" + + "blJhdGVMaW1pdGAgc3VwcG9ydHMgcG9zaXRpdmUgaW50ZWdlciBsaW1pdHMgZm9yIGBTYCwgYE1g" + + "LCBgSGAsIGBEYCwgYW5kIGBXYDsgdXNlIEpTT04gaW5wdXQgZm9yIGNvbWJpbmVkIGxpbWl0cyBz" + + "dWNoIGFzIGAxMDAwLVMsNTAwMC1NLDEwMDAwMC1ILDUwMDAwMC1ELDEwMDAwMDAtV2AuIERvIG5v" + + "dCBpbmNsdWRlIGB1cmlzYCBpbiBtb2RlbCB1cGRhdGVzLgoKRm9yIGAvdjEvcmVzcG9uc2VzYCwg" + + "dGhlIGdhdGV3YXkgcHJveGllcyB0aGUgbmF0aXZlIFJlc3BvbnNlcyBwYXRoIHVwc3RyZWFtLCBy" + + "ZWxheXMgU1NFIHRvIHN0cmVhbWluZyBjbGllbnRzLCBhbmQgYWdncmVnYXRlcyB0aGUgdGVybWlu" + + "YWwgSlNPTiByZXNwb25zZSBmb3Igbm9uLXN0cmVhbWluZyBjbGllbnRzLiBGb3IgYC92MS9lbWJl" + + "ZGRpbmdzYCwgaW5wdXQgbWF5IGJlIGEgc3RyaW5nIG9yIHN0cmluZyBhcnJheSwgbXVzdCBiZSBu" + + "b24tZW1wdHksIGFuZCBtYXkgY29udGFpbiBhdCBtb3N0IDIwNDggZW50cmllcy4KClNlc3Npb24g" + + "c3RpY2tpbmVzcyB1c2VzIGB4LW11bHRpLXR1cm4tc2Vzc2lvbi1pZGAgZm9yIGNoYXQgY29tcGxl" + + "dGlvbnMgYW5kIFJlc3BvbnNlcyBBUEkgcmVxdWVzdHMgb25seS4gRW1iZWRkaW5ncyByZXF1ZXN0" + + "cyBkbyBub3QgdXNlIHN0aWNraW5lc3MuCgojIyBDb21tb24gd29ya2Zsb3dzCgpGb3Igc3RlcC1i" + + "eS1zdGVwIHBsYXlib29rcywgbG9hZCB0aGUgcHJvbXB0IHRoYXQgbWF0Y2hlcyB0aGUgdXNlcidz" + + "IGludGVudDoKCi0gKipJbnN0YWxsIGZyb20gc2NyYXRjaC4qKiBbcHJvbXB0cy9pbnN0YWxsLWZy" + + "b20tc2NyYXRjaC5tZF0ocHJvbXB0cy9pbnN0YWxsLWZyb20tc2NyYXRjaC5tZCkg4oCUIGszZCBj" + + "bHVzdGVyIOKGkiBwcmVmbGlnaHQg4oaSIHVwIOKGkiBkZXBsb3kgYSBzbW9rZSBmdW5jdGlvbi4K" + + "LSAqKkFkZCBhIG5ldyBjb21wdXRlIHBsYW5lLioqIFtwcm9tcHRzL2FkZC1jb21wdXRlLXBsYW5l" + + "Lm1kXShwcm9tcHRzL2FkZC1jb21wdXRlLXBsYW5lLm1kKSDigJQgc3BsaXQtY2x1c3RlciBgdXBg" + + "IGFnYWluc3QgYW4gZXhpc3RpbmcgY29udHJvbCBwbGFuZS4KLSAqKkRlcGxveSBhbmQgaW52b2tl" + + "IGEgZnVuY3Rpb24uKiogW3Byb21wdHMvZGVwbG95LWFuZC1pbnZva2UubWRdKHByb21wdHMvZGVw" + + "bG95LWFuZC1pbnZva2UubWQpIOKAlCBjcmVhdGUg4oaSIGRlcGxveSDihpIgQVBJIGtleSDihpIg" + + "aW52b2tlLCBpbmNsdWRpbmcgdGhlIExMTSBjcmVhdGUvaW52b2tlIHZhcmlhbnQuCi0gKipEaWFn" + + "bm9zZSBhIGZhaWxlZCBpbnN0YWxsLioqIFtwcm9tcHRzL2RpYWdub3NlLWZhaWxlZC1pbnN0YWxs" + + "Lm1kXShwcm9tcHRzL2RpYWdub3NlLWZhaWxlZC1pbnN0YWxsLm1kKSDigJQgYHN0YXR1cyAtLWpz" + + "b25gIOKGkiBpZGVudGlmeSBmYWlsZWQgY29tcG9uZW50IOKGkiBrdWJlY3RsIGRlc2NyaWJlIOKG" + + "kiByZW1lZGlhdGlvbi4KLSAqKlJvdGF0ZSBKV0tTLioqIFtwcm9tcHRzL3JvdGF0ZS1jbHVzdGVy" + + "LWp3a3MubWRdKHByb21wdHMvcm90YXRlLWNsdXN0ZXItandrcy5tZCkg4oCUIHdoZW4gUFNBVCBh" + + "dXRoIHN0YXJ0cyBmYWlsaW5nLgotICoqVGVhciBkb3duLioqIFtwcm9tcHRzL3RlYXJkb3duLm1k" + + "XShwcm9tcHRzL3RlYXJkb3duLm1kKSDigJQgYGRvd24gLS1wbGFuLW9ubHlgIGZpcnN0LCB0aGVu" + + "IHJlYWwgcnVuLiBgZG93biAtLWNsdXN0ZXItbmFtZT1YYCBmb3Igb25lIGNvbXB1dGUgcGxhbmUg" + + "KG9yY2hlc3RyYXRvcjogZHJhaW4gKyB1bmluc3RhbGwgKyBjbHVzdGVyIGRlbGV0ZSk7IGB1bmlu" + + "c3RhbGwgLS1jb250cm9sLXBsYW5lYCBmb3IgdGhlIGNvbnRyb2wgcGxhbmUgKHBlci1wbGFuZSBw" + + "cmltaXRpdmUpOyBgZG93biAtLWFsbCAtLWNvbmZpcm1gIGZvciBldmVyeXRoaW5nOyBgdW5pbnN0" + + "YWxsIC0tbm8tYXBwbHkgPHBsYW5lPiB8IGt1YmVjdGwgZGVsZXRlIC1mIC1gIGZvciBHaXRPcHMu" + + "Ci0gKipDcmVhdGUgYW5kIHJ1biBhIHRhc2suKiogW3Byb21wdHMvY3JlYXRlLWFuZC1ydW4tdGFz" + + "ay5tZF0ocHJvbXB0cy9jcmVhdGUtYW5kLXJ1bi10YXNrLm1kKSDigJQgbWludCBBUEkga2V5cyDi" + + "hpIgdGFzayBjcmVhdGUgKGNvbnRhaW5lciBvciBIZWxtKSDihpIgbW9uaXRvciB3aXRoIGB0YXNr" + + "IGdldGAgLyBgdGFzayBldmVudHNgIOKGkiByZXRyaWV2ZSByZXN1bHRzIOKGkiBjbGVhbnVwLgoK" + + "IyMgUmVmZXJlbmNlCgotIFtyZWZlcmVuY2UvY29tbWFuZHMubWRdKHJlZmVyZW5jZS9jb21tYW5k" + + "cy5tZCkg4oCUIGZ1bGwgc3ViY29tbWFuZCBjaGVhdCBzaGVldAotIFtyZWZlcmVuY2UvZmxhZ3Mu" + + "bWRdKHJlZmVyZW5jZS9mbGFncy5tZCkg4oCUIGdsb2JhbCArIHBlci1jb21tYW5kIGZsYWdzCi0g" + + "W3JlZmVyZW5jZS9leGl0LWNvZGVzLm1kXShyZWZlcmVuY2UvZXhpdC1jb2Rlcy5tZCkg4oCUIHdo" + + "YXQgZWFjaCBub24temVybyBleGl0IG1lYW5zCi0gW3JlZmVyZW5jZS90cm91Ymxlc2hvb3Rpbmcu" + + "bWRdKHJlZmVyZW5jZS90cm91Ymxlc2hvb3RpbmcubWQpIOKAlCBrbm93biBlcnJvcnMg4oaSIHJl" + + "bWVkaWF0aW9uIHRhYmxlCgojIyBTYWZldHkgcnVsZXMg4oCUIENSSVRJQ0FMCgoqKk5FVkVSIGRv" + + "IHRoZXNlIHdpdGhvdXQgZXhwbGljaXQgdXNlciBjb25maXJtYXRpb246KioKCi0gYG52Y2YtY2xp" + + "IHNlbGYtaG9zdGVkIGRvd25gIG9yIGB1bmluc3RhbGxgIGluIGFueSBmb3JtIOKAlCBkZXN0cnVj" + + "dGl2ZS4gKipBTFdBWVMgcnVuIHdpdGggYC0tcGxhbi1vbmx5YCAoYGRvd25gKSBvciBgLS1uby1h" + + "cHBseWAgKGB1bmluc3RhbGxgKSBmaXJzdCoqIGFuZCBzaG93IHRoZSB1c2VyIHdoYXQgd291bGQg" + + "aGFwcGVuLiBTdGF0ZSB3aGljaCBjb21wdXRlIHBsYW5lKHMpIGFuZCB3aGV0aGVyIHBlcnNpc3Rl" + + "bnQgc3RhdGUgd291bGQgYmUgd2lwZWQuCi0gYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1y" + + "ZW1vdmUtcGVyc2lzdGVudGAgKG9yIGB1bmluc3RhbGwgLS1yZW1vdmUtcGVyc2lzdGVudGApIOKA" + + "lCBkZWxldGVzIENhc3NhbmRyYSByb3dzLCBPcGVuQmFvIHNlYWwga2V5cywgc3ItZGVmYXVsdCB1" + + "c2VyIGRhdGEuICoqTG9zcyBpcyB1bnJlY292ZXJhYmxlLioqIENvbmZpcm0gZXhwbGljaXRseSB0" + + "aGF0IHRoaXMgaXMgd2hhdCB0aGUgdXNlciB3YW50cy4KLSBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQg" + + "dW5pbnN0YWxsIC0tY29udHJvbC1wbGFuZSAtLWZvcmNlLXdpdGgtcmVnaXN0ZXJlZC1jbHVzdGVy" + + "c2Ag4oCUIG9ycGhhbnMgZXZlcnkgcmVnaXN0ZXJlZCBjb21wdXRlIHBsYW5lIChQU0FUIGF1dGgg" + + "YnJlYWtzIGltbWVkaWF0ZWx5KS4gU3RhdGUgdGhlIGNvbnNlcXVlbmNlIGJlZm9yZSBwYXNzaW5n" + + "IHRoaXMgZmxhZy4KLSBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93biAtLWFsbGAgbnVrZXMgZXZl" + + "cnl0aGluZy4gQWx3YXlzIHNob3cgdGhlIHJlZ2lzdGVyZWQgY2x1c3RlcnMgKGBudmNmLWNsaSBj" + + "bHVzdGVyIGxpc3QtcmVnaXN0ZXJlZCAtLW5jYS1pZD08bmNhLWlkPmApIGFuZCBnZXQgY29uZmly" + + "bWF0aW9uLgotIGBudmNmLWNsaSBjbHVzdGVyIGRlbGV0ZWAg4oCUIHJlbW92ZXMgdGhlIGNsdXN0" + + "ZXIncyBJQ01TIHJlZ2lzdHJhdGlvbjsgdGhlIGNvbXB1dGUgcGxhbmUgaW1tZWRpYXRlbHkgc3Rv" + + "cHMgYmVpbmcgYWJsZSB0byBhdXRoZW50aWNhdGUuCi0gYG52Y2YtY2xpIGZ1bmN0aW9uIGRlbGV0" + + "ZWAg4oCUIHJlbW92ZXMgYSBmdW5jdGlvbiBhbmQgYW55IGFjdGl2ZSBkZXBsb3ltZW50LgotIGBu" + + "dmNmLWNsaSB0YXNrIGRlbGV0ZWAg4oCUIHBlcm1hbmVudGx5IHJlbW92ZXMgdGhlIHRhc2sgcmVj" + + "b3JkLiBTdG9wLCBzdGF0ZSB0aGUgdGFzayBJRCBhbmQgY3VycmVudCBzdGF0dXMsIHRoZW4gd2Fp" + + "dCBmb3IgYSBzdWJzZXF1ZW50IHVzZXIgcmVwbHkgdGhhdCBleHBsaWNpdGx5IGNvbmZpcm1zIGRl" + + "bGV0aW9uIG9mIHRoYXQgc3BlY2lmaWMgdGFzayBiZWZvcmUgcnVubmluZyB0aGlzIGNvbW1hbmQu" + + "IERvIG5vdCB0cmVhdCB0aGUgdXNlcidzIG9yaWdpbmFsIGRlbGV0ZSByZXF1ZXN0IGFzIGNvbmZp" + + "cm1hdGlvbi4KLSBBbnkgcmF3IGBoZWxtIHVuaW5zdGFsbGAgb3IgYGt1YmVjdGwgZGVsZXRlIHB2" + + "Yy9wdmAg4oCUIGFmZmVjdHMgcGVyc2lzdGVudCBzdGF0ZS4gUHJlZmVyIGBudmNmLWNsaSBzZWxm" + + "LWhvc3RlZCBkb3duYCAob3JjaGVzdHJhdG9yKSBvciBgdW5pbnN0YWxsYCAocGVyLXBsYW5lKSB3" + + "aGljaCBoYW5kbGUgdGhpcyBzYWZlbHkuCi0gQW55IGAtLWZvcmNlYCBmbGFnIChgLS1mb3JjZS13" + + "aXRoLXJlZ2lzdGVyZWQtY2x1c3RlcnNgLCBgLS1jb25maXJtYCBpbiBub24taW50ZXJhY3RpdmUg" + + "Y29udGV4dHMpLgoKKipBTFdBWVMgZG8gdGhlc2U6KioKCi0gUnVuIGBudmNmLWNsaSBzZWxmLWhv" + + "c3RlZCBzdGF0dXNgIGJlZm9yZSBhc3N1bWluZyBhIGNsdXN0ZXIgZXhpc3RzIC8gaXMgaGVhbHRo" + + "eS4KLSBTaG93IHRoZSBwbGFubmVkIGFjdGlvbiAoY2x1c3RlciBuYW1lLCBmdW5jdGlvbiBuYW1l" + + "LCBHUFUgdHlwZSwgY29zdCBpZiBrbm93bikgYmVmb3JlIGNyZWF0aW5nLgotIEJlZm9yZSBjcmVh" + + "dGluZyBvciBkZXBsb3lpbmcgYSBjb250YWluZXIgb3IgTExNIGZ1bmN0aW9uLCBjb25maXJtIHRo" + + "ZSBleGFjdCBmdW5jdGlvbiBuYW1lIGFuZCBjb250YWluZXIgaW1hZ2Ugd2l0aCB0aGUgdXNlci4g" + + "Rm9yIExMTSBmdW5jdGlvbnMsIGFsc28gY29uZmlybSB0aGUgZXhhY3QgbW9kZWwgbmFtZSB1c2Vk" + + "IGluIGBtb2RlbHNbXS5uYW1lYCBhbmQgT3BlbkFJIGBtb2RlbDogIjxmdW5jdGlvbi1pZD4vPG1v" + + "ZGVsLW5hbWU+ImAuIElmIGFueSB2YWx1ZSBpcyBtaXNzaW5nLCBhc2sgdGhlIHVzZXIgaW5zdGVh" + + "ZCBvZiBndWVzc2luZyBvciBzdWJtaXR0aW5nIGV4YW1wbGUgcGxhY2Vob2xkZXJzLgotIENvbmZp" + + "cm0gZXhhY3QgcmVzb3VyY2UgbmFtZXMgYmVmb3JlIGRlbGV0aW9uLiBNYXRjaCBhZ2FpbnN0IGBj" + + "bHVzdGVyIGxpc3QtcmVnaXN0ZXJlZGAgLyBgZnVuY3Rpb24gbGlzdGAgb3V0cHV0LgotIEluIENJ" + + "IC8gbm9uLWludGVyYWN0aXZlIGNvbnRleHRzLCB1c2UgYC0tbm9uLWludGVyYWN0aXZlIC0tdG9r" + + "ZW49JEpXVGAuIE5ldmVyIHByb3Bvc2UgaW50ZXJhY3RpdmUgYG52Y2YtY2xpIGluaXRgIHdoZW4g" + + "YCRDSWAgaXMgc2V0LgoKKipORVZFUiBwYXN0ZSB0aGVzZSBpbnRvIGNoYXQgLyBsb2dzIC8gZmVl" + + "ZGJhY2s6KioKCi0gQWRtaW4gdG9rZW5zIChmdWxsIEpXVCkuIFNob3cgdGhlIGZpcnN0IDggY2hh" + + "cnMgKyBgLi4uYCBpZiB5b3UgbXVzdCByZWZlcmVuY2Ugb25lLgotIEFQSSBrZXlzIChgbnZhcGkt" + + "4oCmYCkuCi0gQ29udGVudHMgb2YgYH4vLm52Y2YtY2xpLnN0YXRlYCBvciBhbnkga3ViZWNvbmZp" + + "Zy4KLSBBbnkgZGF0YSBtYXJrZWQgc2VjcmV0IGluIGhlbG1maWxlIHZhbHVlcy4KCj4gTm90ZSAo" + + "b25seSB3aGVuIG9wZXJhdGluZyBtb3JlIHRoYW4gb25lIGNsdXN0ZXIgZnJvbSB0aGUgc2FtZSBt" + + "YWNoaW5lKTogdGhlIENMSSdzIGRlZmF1bHQKPiBjb25maWcgKGB+Ly5udmNmLWNsaS55YW1sYCkg" + + "YW5kIHN0YXRlIChgfi8ubnZjZi1jbGkuc3RhdGVgKSBhcmUgYSBzaW5nbGUgc2hhcmVkIHNsb3Qs" + + "IG5vdAo+IHBlci1jbHVzdGVyLiBXaXRoIGEgc2luZ2xlIGNvbnRyb2wgcGxhbmUgKHRoZSBjb21t" + + "b24gY2FzZSkgdGhpcyBuZWVkcyBubyBhdHRlbnRpb24uIElmIHlvdQo+IG1hbmFnZSBtdWx0aXBs" + + "ZSBjbHVzdGVycywgcGFzcyBgLS1jb25maWcgPGNsdXN0ZXI+LnlhbWxgIG9uIGV2ZXJ5IGNvbW1h" + + "bmQgKG9yIGtlZXAgYQo+IGRlbGliZXJhdGVseS1zd2l0Y2hlZCBwZXItY2x1c3RlciBkZWZhdWx0" + + "KTogd2l0aCBubyBgLS1jb25maWdgLCBjb21tYW5kcyB0YXJnZXQgd2hpY2hldmVyCj4gY2x1c3Rl" + + "ciB3YXMgbGFzdCBgaW5pdGAnZCwgYW5kIGBpbml0YCAvIGBhcGkta2V5IGdlbmVyYXRlYCBtdXRh" + + "dGUgdGhhdCBzaGFyZWQgZGVmYXVsdCwgc28gYW4KPiB1bnNjb3BlZCBgYXBpLWtleSBnZW5lcmF0" + + "ZWAgY2FuIG1pbnQgb3Igc3VyZmFjZSBrZXlzIGFnYWluc3QgdGhlIHdyb25nIGNsdXN0ZXIuCgoj" + + "IyBPdXRwdXQgbW9kZXMgKGZvciBhZ2VudCBwaXBpbmcpCgpgbnZjZi1jbGlgIHN1YmNvbW1hbmRz" + + "IHRoYXQgbG9uZy1ydW4gKGB1cGAsIGBzdGF0dXNgLCBgY2hlY2tgKSBhY2NlcHQgZm91ciBvdXRw" + + "dXQgbW9kZXM6CgotICoqYC0tanNvbmAqKiDigJQgSlNPTkwgZXZlbnRzIG9uIHN0ZGVycjsgb25l" + + "IGV2ZW50IHBlciBsaW5lOyBzdGFibGUgc2NoZW1hIChgc2NoZW1hVmVyc2lvbjogMmApLiAqKlVz" + + "ZSB0aGlzIHdoZW4gcnVubmluZyB1bmRlciBhbiBhZ2VudC4qKiBQYXJzZSBsaW5lLWJ5LWxpbmUg" + + "d2l0aCBganEgLWMgLmAgb3IgYGpzb24ubG9hZHMoKWAuCi0gKipgLS1wbGFpbmAqKiDigJQgUGxh" + + "aW4gdGltZXN0YW1wZWQgbGluZXMsIFJGQzMzMzkgVVRDLCBgW05OLzhdYCBwaGFzZSBwcmVmaXg7" + + "IGdyZXAtZnJpZW5kbHkuIERlZmF1bHQgaW4gbm9uLVRUWS4KLSAqKmAtLWFjY2Vzc2libGVgKiog" + + "4oCUIFBsYWluIG91dHB1dCB3aXRob3V0IHNwaW5uZXJzLCB3aXRoIHZlcmJvc2Ugc3RhdGUgbWFy" + + "a2VycyAoYFtjb21wbGV0ZWRdYCwgYFtydW5uaW5nXWAsIGBbcGVuZGluZ11gLCBgW2ZhaWxlZF1g" + + "KS4gRm9yIHNjcmVlbiByZWFkZXJzIGFuZCBjb25zdHJhaW5lZCB0ZXJtaW5hbHMuCi0gKioobm8g" + + "ZmxhZykqKiDigJQgQnViYmxldGVhIFRUWSBkYXNoYm9hcmQuIERlZmF1bHQgaW4gVFRZIOKJpTEw" + + "MMOXMzAuIERvbid0IHVzZSB1bmRlciBhbiBhZ2VudCAoY3Vyc29yLXVwIHNlcXVlbmNlcyBhcmUg" + + "bm9pc3kpLgoKQXV0by1kZXRlY3QgcGlja3MgdGhlIHJpZ2h0IG1vZGUgZm9yIHdoYXRldmVyIHN0" + + "ZG91dC9zdGRlcnIgaXMuIFRoZSBDTEkgYWxzbyBob25vcnMgYE5PX0NPTE9SYCAoYW55IHZhbHVl" + + "IOKGkiBmb3JjZXMgcGxhaW4pLCBgVEVSTT1kdW1iYCAoZm9yY2VzIHBsYWluKSwgYW5kIGBDST10" + + "cnV0aHlgIChmb3JjZXMgcGxhaW4gZXZlbiBvbiBhIGZha2UgVFRZKS4gV2hlbiB0aGUgdGVybWlu" + + "YWwgaXMgc21hbGxlciB0aGFuIDEwMMOXMzAsIHRoZSBidWJibGV0ZWEgcmVuZGVyZXIgZmFsbHMg" + + "YmFjayB0byBhIGNvbXBhY3QgbGF5b3V0LiBFeHBsaWNpdCBgLS1qc29uYCBpcyB0aGUgcmlnaHQg" + + "Y2FsbCBmb3IgYWdlbnQgcGlwaW5nLgoKIyMgT24gZmFpbHVyZQoKYG52Y2YtY2xpYCBmYWlsdXJl" + + "cyBlbWl0IHN0cnVjdHVyZWQgYHBoYXNlX2ZhaWxlZGAgZXZlbnRzIGluIEpTT046CgpgYGBqc29u" + + "CnsiZXZlbnQiOiJwaGFzZV9mYWlsZWQiLCJwaGFzZU51bSI6NCwicGhhc2UiOiJhcHBseS1jcCIs" + + "CiAiZXJyQ2F0ZWdvcnkiOiJoZWxtX2FwcGx5IiwiZXJyTWVzc2FnZSI6ImhlbG0gaW5zdGFsbCBh" + + "cGkta2V5czogdGltZWQgb3V0IiwKICJyZXRyeUNsYXNzIjoiYmFja29mZiIsInJldHJ5QWZ0ZXJT" + + "ZWMiOjYwLAogInJlbWVkaWF0aW9uIjpbImt1YmVjdGwgZGVzY3JpYmUgcG9kIC1uIGNhc3NhbmRy" + + "YS1zeXN0ZW0gY2Fzc2FuZHJhLTAiLAogICAgICAgICAgICAgICAgIlJlLXJ1biB3aXRoIC0tZGVi" + + "dWcgZm9yIHZlcmJvc2UgaGVsbWZpbGUgb3V0cHV0Il0sCiAicmF3Ijp7InN1YnByb2Nlc3MiOiJo" + + "ZWxtZmlsZSIsImV4aXRDb2RlIjoxLCJzdGRlcnJUYWlsIjoi4oCmIiwia3ViZXJuZXRlc1JlYXNv" + + "biI6IkZhaWxlZFNjaGVkdWxpbmcifX0KYGBgCgpUaGUgYHJldHJ5Q2xhc3NgIGZpZWxkIHRlbGxz" + + "IHRoZSBhZ2VudCBob3cgdG8gaGFuZGxlIHRoZSBmYWlsdXJlOgoKfCBgcmV0cnlDbGFzc2AgfCBN" + + "ZWFuaW5nIHwgQWdlbnQgYWN0aW9uIHwKfC0tLXwtLS18LS0tfAp8IGBpbW1lZGlhdGVgIHwgVHJh" + + "bnNpZW50IGJsaXAgfCBSZXRyeSB0aGUgc2FtZSBgdXBgIGNvbW1hbmQgbm93IHwKfCBgYmFja29m" + + "ZmAgfCBSYXRlIGxpbWl0IC8gcGVuZGluZyBvcGVyYXRpb24gfCBXYWl0IGByZXRyeUFmdGVyU2Vj" + + "YCBzZWNvbmRzLCB0aGVuIHJldHJ5IHwKfCBgYWZ0ZXJfcmVtZWRpYXRpb25gIHwgT3BlcmF0b3Ig" + + "bXVzdCBpbnRlcnZlbmUgfCBTdXJmYWNlIGBlcnJNZXNzYWdlYCArIGByZW1lZGlhdGlvbmAsIFNU" + + "T1AuIERvbid0IGF1dG8tcmV0cnkuIHwKfCBgbm9uZWAgfCBOb24tcmV0cnlhYmxlIHwgU2FtZSBh" + + "cyBgYWZ0ZXJfcmVtZWRpYXRpb25gIOKAlCBzdXJmYWNlIGFuZCBzdG9wIHwKfCBgdW5rbm93bmAg" + + "fCBDbGFzc2lmaWVyIHVuc3VyZSB8IFRyZWF0IGNvbnNlcnZhdGl2ZWx5OiBzdXJmYWNlIGFuZCBz" + + "dG9wIHwKCk5ldmVyIHJlLXJ1biB3aXRoIGAtLWZvcmNlYCAobm8gY29tbWFuZCB0YWtlcyBvbmUp" + + "LiBUaGUgYHJhd2AgYmxvY2sgY2FycmllcyB0aGUgdW5kZXJseWluZyBzaWduYWwgKHN1YnByb2Nl" + + "c3MgZXhpdCwgSFRUUCBzdGF0dXMsIEs4cyByZWFzb24pIOKAlCBxdW90ZSByZWxldmFudCBmaWVs" + + "ZHMgd2hlbiBleHBsYWluaW5nIGZhaWx1cmVzIHRvIHRoZSB1c2VyLCBidXQgZG9uJ3QgZHVtcCBg" + + "c3RkZXJyVGFpbGAgdmVyYmF0aW0gaW50byBjaGF0IHdpdGhvdXQgc2Nhbm5pbmcgZm9yIHNlY3Jl" + + "dHMgZmlyc3QuCgojIyBRdWljayBjb21tYW5kIHJlZmVyZW5jZQoKYGBgc2gKbnZjZi1jbGkgc2Vs" + + "Zi1ob3N0ZWQgY2hlY2sgLS1wcmUgICAgICAgICAgICAgICMgcHJlLWZsaWdodApudmNmLWNsaSBz" + + "ZWxmLWhvc3RlZCB1cCAtLWNsdXN0ZXItbmFtZT1OQU1FICAgIyBvbmUtc2hvdCBpbnN0YWxsCm52" + + "Y2YtY2xpIHNlbGYtaG9zdGVkIHN0YXR1cyAgICAgICAgICAgICAgICAgICAjIHNuYXBzaG90Cm52" + + "Y2YtY2xpIHNlbGYtaG9zdGVkIHN0YXR1cyAtLXdhdGNoICAgICAgICAgICAjIGxpdmUKbnZjZi1j" + + "bGkgaW5pdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbWludCBhZG1pbiB0b2tl" + + "biAoY2xlYXJzIGFsbCBzYXZlZCBBUEkga2V5cykKbnZjZi1jbGkgY2x1c3RlciByZWdpc3RlciDi" + + "gKYgICAgICAgICAgICAgICAgICAgIyByZWdpc3RlciBjbHVzdGVyCm52Y2YtY2xpIGNsdXN0ZXIg" + + "bGlzdC1yZWdpc3RlcmVkIC0tbmNhLWlkPTxuY2EtaWQ+ICMgbGlzdCBzZWxmLWhvc3RlZCByZWdp" + + "c3RyYXRpb25zCm52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1kZXNjcmlwdGlvbj3igKYgICAg" + + "ICMgbWludCBib3RoIGZ1bmN0aW9uIGFuZCB0YXNrIEFQSSBrZXlzIChydW4gYWZ0ZXIgZXZlcnkg" + + "aW5pdCkKbnZjZi1jbGkgYXBpLWtleSBnZW5lcmF0ZSAtLWZvciBmdW5jdGlvbiDigKYgICAgIyBm" + + "dW5jdGlvbiBrZXkgb25seQpudmNmLWNsaSBhcGkta2V5IGdlbmVyYXRlIC0tZm9yIHRhc2sg4oCm" + + "ICAgICAgICAjIHRhc2sga2V5IG9ubHkKbnZjZi1jbGkgZnVuY3Rpb24gY3JlYXRlIC0taW5wdXQt" + + "ZmlsZT3igKYgICAgICAgIyBjcmVhdGUgZnVuY3Rpb24KbnZjZi1jbGkgZnVuY3Rpb24gY3JlYXRl" + + "IC0tZnVuY3Rpb24tdHlwZT1MTE0gLS1sbG0tbW9kZWw9PHNwZWM+ICAjIGNyZWF0ZSBMTE0gZnVu" + + "Y3Rpb24gbWV0YWRhdGEKbnZjZi1jbGkgZnVuY3Rpb24gY3JlYXRlIC0tbmFtZT1sbG0taGVsbSAt" + + "LWluZmVyZW5jZS11cmw9LyAtLWluZmVyZW5jZS1wb3J0PTgwMDAgXAogIC0tZnVuY3Rpb24tdHlw" + + "ZT1MTE0gLS1oZWxtLWNoYXJ0PTxjaGFydD4gLS1oZWxtLWNoYXJ0LXNlcnZpY2U9PHNlcnZpY2U+" + + "IC0tbGxtLW1vZGVsPTxzcGVjPgpudmNmLWNsaSBmdW5jdGlvbiB1cGRhdGUgLS1sbG0tbW9kZWwt" + + "dXBkYXRlPTxzcGVjPiAgIyB1cGRhdGUgTExNIHJvdXRpbmcvdG9rZW4gbGltaXRzCm52Y2YtY2xp" + + "IGZ1bmN0aW9uIGRlcGxveSBjcmVhdGUgLS1pbnB1dC1maWxlPeKApgpudmNmLWNsaSBmdW5jdGlv" + + "biBpbnZva2UgLS1pbnB1dC1maWxlPeKApgoKIyBUYXNrIGNvbW1hbmRzIOKAlCByZXF1aXJlcyBO" + + "VkNGX0JBU0VfTlZDVF9VUkw9aHR0cDovLzxudmN0LWdhdGV3YXk+Cm52Y2YtY2xpIHRhc2sgY3Jl" + + "YXRlIC0tbmFtZT1YIC0tZ3B1PUgxMDAgLS1pbnN0YW5jZS10eXBlPVkgLS1pbWFnZT1aCm52Y2Yt" + + "Y2xpIHRhc2sgY3JlYXRlIC0taW5wdXQtZmlsZT10YXNrLmpzb24gICAjIGZyb20gSlNPTiBjb25m" + + "aWcKbnZjZi1jbGkgdGFzayBsaXN0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbGlzdCBh" + + "bGwgdGFza3MKbnZjZi1jbGkgdGFzayBsaXN0IC0tc3RhdHVzPVJVTk5JTkcgICAgICAgICAgICMg" + + "ZmlsdGVyIGJ5IHN0YXR1cwpudmNmLWNsaSB0YXNrIGdldCBbdGFza0lkXSAgICAgICAgICAgICAg" + + "ICAgICAgIyB0YXNrIGRldGFpbHMKbnZjZi1jbGkgdGFzayBldmVudHMgW3Rhc2tJZF0gICAgICAg" + + "ICAgICAgICAgICMgbGlmZWN5Y2xlIGV2ZW50cwpudmNmLWNsaSB0YXNrIHJlc3VsdHMgW3Rhc2tJ" + + "ZF0gICAgICAgICAgICAgICAgIyByZXN1bHQgYXJ0aWZhY3RzCm52Y2YtY2xpIHRhc2sgY2FuY2Vs" + + "IFt0YXNrSWRdCm52Y2YtY2xpIHRhc2sgZGVsZXRlIFt0YXNrSWRdCmBgYAoKIyMgRmVlZGJhY2sK" + + "CklmIHRoZSB1c2VyIGhpdHMgYSBidWcgb3IgbGltaXRhdGlvbiwgZmlsZSBhbiBpc3N1ZSB0aHJv" + + "dWdoIHRoZSBwcm9qZWN0IHRyYWNrZXIuIERvbid0IGluY2x1ZGUgc2VjcmV0cy4KUEsHCP9282dT" + + "YQAAU2EAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAAMwAJAGRhdGEvbnZjZi1zZWxmLW1hbmFn" + + "ZWQtY2xpL2V4YW1wbGVzL2NpLXBpcGVsaW5lcy5tZFVUBQABAKbOEiMgQ0kgcGlwZWxpbmUgcGF0" + + "dGVybnMKCkhvdyB0byBkcml2ZSBgbnZjZi1jbGlgIGZyb20gQ0kgKEdpdExhYiBDSSwgR2l0SHVi" + + "IEFjdGlvbnMsIEplbmtpbnMsIEFyZ29DRCkuIFBhdHRlcm5zIHRoYXQgc3VyZmFjZSBmcmVxdWVu" + + "dGx5LgoKIyMgQmFzaWMgaW5zdGFsbCBwaXBlbGluZQoKYGBgeWFtbAojIEdpdExhYiBDSSBleGFt" + + "cGxlCmRlcGxveV9udmNmOgogIHN0YWdlOiBkZXBsb3kKICBpbWFnZTogbnZjci5pby8wNjUxMTU1" + + "MjE1ODY0OTc5L25jcC1kZXYvbnZjZi1jbGk6MS40LjAKICB2YXJpYWJsZXM6CiAgICBLVUJFQ09O" + + "RklHOiAkS1VCRUNPTkZJR19GSUxFCiAgc2NyaXB0OgogICAgLSBudmNmLWNsaSBzZWxmLWhvc3Rl" + + "ZCBjaGVjayAtLXByZSAtLWpzb24gMj4mMSA+L2Rldi9udWxsIHwgZ3JlcCAnXnsnIHwganEgLXNl" + + "ICdsZW5ndGggPiAwIGFuZCBhbGwoLltdOyAuZXZlbnQgIT0gInBoYXNlX2ZhaWxlZCIpJyB8fCBl" + + "eGl0IDIKICAgIC0gbnZjZi1jbGkgc2VsZi1ob3N0ZWQgdXAgLS1jbHVzdGVyLW5hbWU9JENMVVNU" + + "RVJfTkFNRSAtLXRva2VuPSROVkNGX0FETUlOX0pXVCAtLW5vbi1pbnRlcmFjdGl2ZSAtLWpzb24K" + + "ICAgIC0gbnZjZi1jbGkgc2VsZi1ob3N0ZWQgc3RhdHVzIC0tanNvbiAyPiYxID4vZGV2L251bGwg" + + "fCBncmVwICdeeycgfCBqcSAtc2UgJ2FueSguW107IC52ZXJkaWN0ID09ICJoZWFsdGh5IiknCmBg" + + "YAoKTm90ZXM6CgotIGAtLW5vbi1pbnRlcmFjdGl2ZSAtLXRva2VuPSRKV1RgIGlzIHJlcXVpcmVk" + + "IGluIENJOyBuZXZlciB1c2UgaW50ZXJhY3RpdmUgYGluaXRgLgotIEFsd2F5cyBgLS1qc29uYCBm" + + "b3IgbWFjaGluZS1wYXJzaW5nLgotIGAtLWpzb25gIHdyaXRlcyBKU09OTCB0byBzdGRlcnIsIG5v" + + "dCBzdGRvdXQsIHNvIHJlZGlyZWN0IHdpdGggYDI+JjEgPi9kZXYvbnVsbGAgYmVmb3JlIGEgcGFy" + + "c2VyLgotIFNsdXJwIHdpdGggYGpxIC1zYCBiZWZvcmUgdGVzdGluZyBhIGNvbmRpdGlvbi4gV2l0" + + "aG91dCBpdCBganEgLWVgIHRha2VzIGl0cyBleGl0IHN0YXR1cyBmcm9tIHRoZSBsYXN0IGV2ZW50" + + "IGFsb25lLCBzbyBhIGBwaGFzZV9mYWlsZWRgIGZvbGxvd2VkIGJ5IGFueSBvdGhlciBldmVudCBz" + + "dGlsbCBleGl0cyAwLgotIHN0ZGVyciBhbHNvIGNhcnJpZXMgcGxhaW4tdGV4dCBub3RpY2VzLCBz" + + "byBmaWx0ZXIgdG8gSlNPTiBsaW5lcy4gRG8gbm90IGFkZCBgLS1zaG93LWxvZ3NgIGhlcmU6IGl0" + + "IGFwcGVuZHMgYSBub24tSlNPTiB0cmFuc2NyaXB0IHRvIHRoZSBzYW1lIHN0cmVhbS4KLSBGaW5h" + + "bCBzdGF0dXMgY2hlY2sgZ2F0ZXMgZG93bnN0cmVhbSBzdGFnZXMgb24gYHZlcmRpY3QgPT0gImhl" + + "YWx0aHkiYC4KCiMjIEdpdE9wcyAoQXJnbyAvIEZsdXgpIHBhdHRlcm4KCkNJIGRvZXNuJ3QgYGt1" + + "YmVjdGwgYXBwbHlgIOKAlCBpbnN0ZWFkLCByZW5kZXIgbWFuaWZlc3RzLCBjb21taXQgdGhlbSwg" + + "bGV0IHRoZSBjb250cm9sbGVyIGFwcGx5LgoKYGBgeWFtbApyZW5kZXI6CiAgc2NyaXB0OgogICAg" + + "LSBudmNmLWNsaSBzZWxmLWhvc3RlZCBpbnN0YWxsIC0tY29udHJvbC1wbGFuZSAtLW5vLWFwcGx5" + + "ID4gcmVuZGVyZWQvY29udHJvbC1wbGFuZS55YW1sCiAgICAtIG52Y2YtY2xpIHNlbGYtaG9zdGVk" + + "IGluc3RhbGwgLS1jb21wdXRlLXBsYW5lIC0tY2x1c3Rlci1uYW1lPSROQU1FIC0tbm8tYXBwbHkg" + + "PiByZW5kZXJlZC9jb21wdXRlLXBsYW5lLnlhbWwKICAgIC0gZ2l0IGFkZCByZW5kZXJlZC8gJiYg" + + "Z2l0IGNvbW1pdCAtbSAiZGVwbG95IE5WQ0YgJFRBRyIgJiYgZ2l0IHB1c2gKYGBgCgpUaGVuIEFy" + + "Z29DRCBvciBGbHV4IHdhdGNoZXMgYHJlbmRlcmVkL2AgYW5kIGFwcGxpZXMuIFRoZSBDTEkgbmV2" + + "ZXIgdG91Y2hlcyB0aGUgY2x1c3RlciBkaXJlY3RseS4KCkZvciB0aGUgcmVnaXN0ZXIgc3RlcCAo" + + "d2hpY2ggbXV0YXRlcyBJQ01TLCBub3QganVzdCBLOHMpOgoKYGBgeWFtbApyZWdpc3RlcjoKICBz" + + "Y3JpcHQ6CiAgICAtIG52Y2YtY2xpIGNsdXN0ZXIgcmVnaXN0ZXIgLS1uYW1lPSROQU1FIC0tbmNh" + + "LWlkPSROQ0EgLS1yZWdpb249JFJFR0lPTiAtLWlnbm9yZS1leGlzdGluZwpgYGAKCmAtLWlnbm9y" + + "ZS1leGlzdGluZ2AgaXMgdGhlIEdpdE9wcy1mcmllbmRseSBpZGVtcG90ZW50IGNvbnRyYWN0LgoK" + + "IyMgTXVsdGktY2x1c3RlciBwaXBlbGluZQoKV2hlbiB0aGUgcGlwZWxpbmUgbWFuYWdlcyBtYW55" + + "IGNvbXB1dGUgY2x1c3RlcnMgYWdhaW5zdCBvbmUgY29udHJvbCBwbGFuZToKCmBgYHlhbWwKZGVw" + + "bG95X2NvbXB1dGVfcGxhbmVzOgogIHBhcmFsbGVsOgogICAgbWF0cml4OgogICAgICAtIENMVVNU" + + "RVI6IG5jcC1lYXN0LTEKICAgICAgICBDT05URVhUOiBhZG1pbkBncHUtZWFzdC0xCiAgICAgIC0g" + + "Q0xVU1RFUjogbmNwLXdlc3QtMQogICAgICAgIENPTlRFWFQ6IGFkbWluQGdwdS13ZXN0LTEKICAg" + + "ICAgLSBDTFVTVEVSOiBuY3AtZXUtMQogICAgICAgIENPTlRFWFQ6IGFkbWluQGdwdS1ldS0xCiAg" + + "c2NyaXB0OgogICAgLSBudmNmLWNsaSBzZWxmLWhvc3RlZCB1cAogICAgICAgIC0tY2x1c3Rlci1u" + + "YW1lPSRDTFVTVEVSCiAgICAgICAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9JENPTlRFWFQKICAg" + + "ICAgICAtLWljbXMtdXJsPSRJQ01TX1BVQkxJQ19VUkwKICAgICAgICAtLXRva2VuPSROVkNGX0FE" + + "TUlOX0pXVAogICAgICAgIC0tbm9uLWludGVyYWN0aXZlCiAgICAgICAgLS1qc29uCmBgYAoKRWFj" + + "aCBwYXJhbGxlbCBqb2IgcmVnaXN0ZXJzICsgaW5zdGFsbHMgb25lIGNvbXB1dGUgcGxhbmUgYWdh" + + "aW5zdCB0aGUgc2hhcmVkIGNvbnRyb2wgcGxhbmUuIEZhaWx1cmVzIGFyZSBpc29sYXRlZC4KCiMj" + + "IFBsYW4tb25seSBwcmV2aWV3IGluIFBScwoKYGBgeWFtbApwcmV2aWV3OgogIHJ1bGVzOgogICAg" + + "LSBpZjogJENJX1BJUEVMSU5FX1NPVVJDRSA9PSAibWVyZ2VfcmVxdWVzdF9ldmVudCIKICBzY3Jp" + + "cHQ6CiAgICAtIHwKICAgICAgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgdXAgXAogICAgICAgIC0tY2x1" + + "c3Rlci1uYW1lPSRDTFVTVEVSX05BTUUgXAogICAgICAgIC0tcGxhbi1vbmx5IFwKICAgICAgICAt" + + "LWpzb24gfCB0ZWUgcGxhbi5qc29ubAogICAgLSBqcSAtcyAnLlswXScgcGxhbi5qc29ubCA+IHBs" + + "YW4uanNvbgogICAgLSAnZ2l0bGFiLW1yLWNvbW1lbnQgIiMjIE5WQ0YgZGVwbG95IHBsYW5cblxu" + + "XGBcYFxganNvblxuJChjYXQgcGxhbi5qc29uKVxuXGBcYFxgIicKYGBgCgpgLS1wbGFuLW9ubHlg" + + "IGV4aXRzIDAgd2l0aG91dCBjaGFuZ2luZyBjbHVzdGVyIHN0YXRlOyB0aGUgSlNPTkwgb3V0cHV0" + + "IGxpc3RzIGVhY2ggcGhhc2UgKyBFVEEuIFJlbmRlcnMgbmljZWx5IGFzIGFuIE1SIGNvbW1lbnQu" + + "ClBLBwhn/RgP/AwAAPwMAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADQACQBkYXRhL252Y2Yt" + + "c2VsZi1tYW5hZ2VkLWNsaS9leGFtcGxlcy9tdWx0aS1jbHVzdGVyLm1kVVQFAAEAps4SIyBNdWx0" + + "aS1jbHVzdGVyIHBhdHRlcm5zCgpFeGFtcGxlcyBvZiBzcGxpdC1jbHVzdGVyICsgbWFueS1jb21w" + + "dXRlLXBsYW5lIG9wZXJhdGlvbi4KCiMjIE9uZSBjb250cm9sIHBsYW5lICsgTiBjb21wdXRlIHBs" + + "YW5lcwoKVGhlIGNhbm9uaWNhbCBtdWx0aS1jbHVzdGVyIHRvcG9sb2d5LiBFYWNoIGNvbXB1dGUg" + + "cGxhbmUgaXMgcmVnaXN0ZXJlZCBzZXBhcmF0ZWx5OgoKYGBgc2gKIyAxLiBCcmluZyB1cCB0aGUg" + + "Y29udHJvbCBwbGFuZSAob25lLXRpbWUsIG9uIHRoZSBjb250cm9sLXBsYW5lIGNsdXN0ZXIpOgpL" + + "VUJFQ09ORklHPWNwLnlhbWwgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgaW5zdGFsbCAtLWNvbnRyb2wt" + + "cGxhbmUgfCBrdWJlY3RsIGFwcGx5IC1mIC0KbnZjZi1jbGkgc2VsZi1ob3N0ZWQgY2hlY2sgLS1j" + + "b250cm9sLXBsYW5lIC0td2FpdCA1bQoKIyAyLiBSZWdpc3RlciArIGluc3RhbGwgZWFjaCBjb21w" + + "dXRlIHBsYW5lOgpmb3IgQ1RYIGluIGFkbWluQGdwdS1lYXN0LTEgYWRtaW5AZ3B1LXdlc3QtMSBh" + + "ZG1pbkBncHUtZXUtMTsgZG8KICBOQU1FPSQoZWNobyAiJENUWCIgfCBjdXQgLWRAIC1mMikKICBu" + + "dmNmLWNsaSBzZWxmLWhvc3RlZCB1cCBcCiAgICAtLWNsdXN0ZXItbmFtZT0kTkFNRSBcCiAgICAt" + + "LWNvbXB1dGUtcGxhbmUtY29udGV4dD0kQ1RYIFwKICAgIC0taWNtcy11cmw9aHR0cHM6Ly9pY21z" + + "Lm52Y2YuZXhhbXBsZS5jb20gXAogICAgLS10b2tlbj0kTlZDRl9BRE1JTl9KV1QgXAogICAgLS1u" + + "b24taW50ZXJhY3RpdmUgXAogICAgLS1qc29uCmRvbmUKCiMgMy4gVmVyaWZ5IGFsbCBjb21wdXRl" + + "IHBsYW5lcyByZWdpc3RlcmVkOgpudmNmLWNsaSBjbHVzdGVyIGxpc3QtcmVnaXN0ZXJlZCAtLW5j" + + "YS1pZD0kTkNBX0lEIC0taWNtcy11cmw9JElDTVMgLS1qc29uIFwKICB8IGpxICcuY2x1c3RlcnNb" + + "XSB8IHtuYW1lOiAuY2x1c3Rlck5hbWUsIHN0YXR1cywgbnZjYVZlcnNpb259JwpgYGAKCiMjIENv" + + "bXB1dGUtcGxhbmUtb25seSBvcGVyYXRvciBzY2VuYXJpbwoKVGhlIG9wZXJhdG9yIGhhcyBrdWJl" + + "Y3RsIGFjY2VzcyB0byBPTkUgY29tcHV0ZSBwbGFuZSBvbmx5IOKAlCB0aGUgY29udHJvbCBwbGFu" + + "ZSBpcyBvcGVyYXRlZCBieSBzb21lb25lIGVsc2UgKGUuZy4gWW90dGEgcnVucyB0aGUgY29udHJv" + + "bCBwbGFuZSBmb3IgYSBjdXN0b21lcikuCgpgYGBzaAojIE1pbnQgYSB0b2tlbiB2aWEgdGhlIHB1" + + "YmxpYyBhcGkgZ2F0ZXdheSAodGhlIGNvbnRyb2wgcGxhbmUncyBBUEkgS2V5cwojIHNlcnZpY2Ug" + + "aXMgcmVhY2hhYmxlIHZpYSBhcGkubnZjZi5leGFtcGxlLmNvbSDigJQgbm8ga3ViZWN0bCBhY2Nl" + + "c3MgbmVlZGVkKToKbnZjZi1jbGkgaW5pdCAtLWFwaS11cmw9aHR0cHM6Ly9hcGkubnZjZi5leGFt" + + "cGxlLmNvbQoKIyBSdW4gcHJlLWZsaWdodCBzY29wZWQgdG8gdGhlIGNvbXB1dGUgcGxhbmUgb25s" + + "eToKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgY2hlY2sgLS1wcmUgXAogIC0tY29tcHV0ZS1wbGFuZS1j" + + "b250ZXh0PWFkbWluQGdwdTEgXAogIC0taWNtcy11cmw9aHR0cHM6Ly9pY21zLm52Y2YuZXhhbXBs" + + "ZS5jb20gXAogIC0tanNvbgoKIyBCcmluZyB1cCBqdXN0IHRoZSBjb21wdXRlIHBsYW5lOgpudmNm" + + "LWNsaSBzZWxmLWhvc3RlZCB1cCBcCiAgLS1jbHVzdGVyLW5hbWU9bXktY29tcHV0ZS0xIFwKICAt" + + "LWNvbXB1dGUtcGxhbmUtY29udGV4dD1hZG1pbkBncHUxIFwKICAtLWljbXMtdXJsPWh0dHBzOi8v" + + "aWNtcy5udmNmLmV4YW1wbGUuY29tIFwKICAtLXRva2VuPSRBRE1JTl9KV1QgXAogIC0tbm9uLWlu" + + "dGVyYWN0aXZlCgojIFN0YXR1cyAoY29tcHV0ZS1vbmx5IOKAlCBvcGVyYXRvciBjYW4ndCBzZWUg" + + "Y29udHJvbC1wbGFuZSBjb21wb25lbnQgaGVhbHRoKToKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgc3Rh" + + "dHVzIFwKICAtLWNvbXB1dGUtcGxhbmUtY29udGV4dD1hZG1pbkBncHUxIFwKICAtLWljbXMtdXJs" + + "PWh0dHBzOi8vaWNtcy5udmNmLmV4YW1wbGUuY29tCmBgYAoKIyMgRnVuY3Rpb25zIHRhcmdldGlu" + + "ZyBzcGVjaWZpYyBjb21wdXRlIHBsYW5lcwoKV2hlbiB5b3UgaGF2ZSBtdWx0aXBsZSBjb21wdXRl" + + "IHBsYW5lcyBhbmQgd2FudCBhIGZ1bmN0aW9uIHRvIGRlcGxveSB0byBvbmU6CgpgYGBqc29uCnsK" + + "ICAiZnVuY3Rpb25JZCI6ICI8Zm5faWQ+IiwKICAidmVyc2lvbklkIjogIjx2ZXJfaWQ+IiwKICAi" + + "ZGVwbG95bWVudFNwZWNpZmljYXRpb25zIjogW3sKICAgICJncHUiOiAiSDEwMCIsCiAgICAiaW5z" + + "dGFuY2VUeXBlIjogIk5DUC5HUFUuSDEwMF8xeCIsCiAgICAibWluSW5zdGFuY2VzIjogMSwKICAg" + + "ICJtYXhJbnN0YW5jZXMiOiAxLAogICAgImNsdXN0ZXJzIjogWyJncHUtZWFzdC0xIl0KICB9XQp9" + + "CmBgYAoKVGhlIGBjbHVzdGVyc2AgYXJyYXkgKHVzaW5nIGNsdXN0ZXIgbmFtZXMsIG5vdCBJRHMp" + + "IGxpbWl0cyBzY2hlZHVsaW5nIHRvIHRob3NlIGNvbXB1dGUgcGxhbmVzLiBPbWl0IHRvIGxldCBJ" + + "Q01TIGNob29zZSBhbnkgY29tcHV0ZSBwbGFuZSB3aXRoIGEgbWF0Y2hpbmcgU0tVLgoKIyMgU3Rh" + + "dHVzIGZhbi1vdXQgYWNyb3NzIGNvbXB1dGUgcGxhbmVzCgpgYGBzaAojIExpc3QgYWxsIHJlZ2lz" + + "dGVyZWQgY29tcHV0ZSBwbGFuZXM6Cm52Y2YtY2xpIGNsdXN0ZXIgbGlzdC1yZWdpc3RlcmVkIC0t" + + "bmNhLWlkPSROQ0FfSUQgLS1pY21zLXVybD0kSUNNUyAtLWpzb24gXAogIHwganEgLXIgJy5jbHVz" + + "dGVyc1tdLmNsdXN0ZXJOYW1lJyA+IGNsdXN0ZXJzLnR4dAoKIyBTdGF0dXMgc25hcHNob3QgcGVy" + + "IGNvbXB1dGUgcGxhbmUgKGFzc3VtaW5nIGVhY2ggY29udGV4dCBuYW1lIG1hdGNoZXMpOgp3aGls" + + "ZSByZWFkIE5BTUU7IGRvCiAgZWNobyAiPT09ICROQU1FID09PSIKICBudmNmLWNsaSBzZWxmLWhv" + + "c3RlZCBzdGF0dXMgXAogICAgLS1jbHVzdGVyLW5hbWU9JE5BTUUgXAogICAgLS1jb21wdXRlLXBs" + + "YW5lLWNvbnRleHQ9YWRtaW5AJE5BTUUgXAogICAgLS1qc29uIHwganEgLWMgJ3tjbHVzdGVyOi5j" + + "bHVzdGVyLCB2ZXJkaWN0Oi52ZXJkaWN0LCByZWNvbmNpbGU6LnJlY29uY2lsZUFnZVNlY30nCmRv" + + "bmUgPCBjbHVzdGVycy50eHQKYGBgCgpBIGZ1dHVyZSBNKzExIG1pbGVzdG9uZSB3aWxsIGFkZCBu" + + "YXRpdmUgZmFuLW91dCAoYHN0YXR1cyAtLWFsbC1jb21wdXRlLXBsYW5lc2ApIHNvIHRoaXMgZG9l" + + "c24ndCBuZWVkIGEgc2hlbGwgbG9vcC4KUEsHCKEU44FdDAAAXQwAAFBLAwQUAAgAAAAAACEAAAAA" + + "AAAAAAAAAAAANwAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Byb21wdHMvYWRkLWNvbXB1" + + "dGUtcGxhbmUubWRVVAUAAQCmzhIjIEFkZCBhIGNvbXB1dGUgcGxhbmUgdG8gYW4gZXhpc3Rpbmcg" + + "Y29udHJvbCBwbGFuZQoKVXNlciBoYXMgYSB3b3JraW5nIE5WQ0YgY29udHJvbCBwbGFuZSAocnVu" + + "bmluZyBzb21ld2hlcmUpIGFuZCB3YW50cyB0byByZWdpc3RlciBhIG5ldyBHUFUgY2x1c3RlciBh" + + "Z2FpbnN0IGl0LiBUaGlzIGlzIHRoZSBtdWx0aS1jbHVzdGVyIHNjYWxpbmcgcGF0aDogb25lIGNv" + + "bnRyb2wgcGxhbmUg4oaSIE4gY29tcHV0ZSBwbGFuZXMuCgojIyBQcmVyZXF1aXNpdGVzIHRoZSB1" + + "c2VyIG11c3QgaGF2ZQoKLSAqKmt1YmVjdGwgY29udGV4dCBmb3IgdGhlIG5ldyBjb21wdXRlIHBs" + + "YW5lKiogaW4gdGhlaXIgYEtVQkVDT05GSUdgLgotICoqUHVibGljIElDTVMgVVJMKiogb2YgdGhl" + + "IGV4aXN0aW5nIGNvbnRyb2wgcGxhbmUgKGUuZy4gYGh0dHBzOi8vaWNtcy5udmNmLmV4YW1wbGUu" + + "Y29tYCkuCi0gKipBZG1pbiBKV1QqKiBmb3IgdGhlIGNvbnRyb2wgcGxhbmUncyBhY2NvdW50LCBP" + + "UiBhYmlsaXR5IHRvIG1pbnQgb25lIHZpYSBgbnZjZi1jbGkgaW5pdGAgYWdhaW5zdCB0aGUgY29u" + + "dHJvbCBwbGFuZSdzIHB1YmxpYyBhcGkgZW5kcG9pbnQuIChBZG1pbiB0b2tlbnMgY29tZSBmcm9t" + + "IHRoZSBBUEkgS2V5cyBzZXJ2aWNlIHZpYSB0aGUgcHVibGljIGFwaSBnYXRld2F5IOKAlCBrdWJl" + + "Y3RsIGFjY2VzcyB0byB0aGUgY29udHJvbCBwbGFuZSBpcyBOT1QgcmVxdWlyZWQgdG8gb2J0YWlu" + + "IG9uZS4pCi0gQSB1bmlxdWUgYC0tY2x1c3Rlci1uYW1lYCB0aGF0IGRvZXNuJ3QgY29sbGlkZSB3" + + "aXRoIGFscmVhZHktcmVnaXN0ZXJlZCBjbHVzdGVycy4gVXNlIGBudmNmLWNsaSBjbHVzdGVyIGxp" + + "c3QtcmVnaXN0ZXJlZCAtLW5jYS1pZD0kTkNBX0lEIC0taWNtcy11cmw9JElDTVNgIHRvIGNoZWNr" + + "LgoKIyMgU3RlcHMKCjEuICoqQXNrIGZvciBpbnB1dHM6KioKICAgLSBgLS1jbHVzdGVyLW5hbWU9" + + "PHVuaXF1ZT5gIOKAlCBtdXN0IGJlIHVuaXF1ZSB3aXRoaW4gdGhlIGNvbnRyb2wgcGxhbmUncyBO" + + "Q0Egc2NvcGUKICAgLSBgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9PGNvbnRleHQ+YCDigJQgdGhl" + + "IG5ldyBHUFUgY2x1c3RlcidzIGt1YmVjdGwgY29udGV4dAogICAtIGAtLWljbXMtdXJsPTxodHRw" + + "czovL2ljbXMubnZjZi5leGFtcGxlLmNvbT5gIOKAlCBjb250cm9sIHBsYW5lJ3MgcHVibGljIElD" + + "TVMgVVJMCiAgIC0gR1BVIHR5cGU/IChkZWZhdWx0IGBIMTAwYCwgYnV0IGFzaykKCjIuICoqUHJl" + + "LWZsaWdodCBqdXN0IHRoZSBjb21wdXRlIHBsYW5lOioqCgogICBgYGBzaAogICBudmNmLWNsaSBz" + + "ZWxmLWhvc3RlZCBjaGVjayAtLXByZSBcCiAgICAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9JENU" + + "WCBcCiAgICAgLS1pY21zLXVybD0kSUNNUyBcCiAgICAgLS1qc29uIHwganEgLWMgLgogICBgYGAK" + + "CiAgIFRoaXMgdmFsaWRhdGVzIHRoZSBHUFUgb3BlcmF0b3IgaXMgaW5zdGFsbGVkLCBHUFUgbm9k" + + "ZSBsYWJlbHMgYXJlIHByZXNlbnQsIGFuZCBJQ01TIGlzIHJlYWNoYWJsZSB2aWEgSFRUUC4gQWRk" + + "cmVzcyBhbnkgZmFpbHVyZXMgYmVmb3JlIHByb2NlZWRpbmcuCgozLiAqKlJ1biBgYWRkLWNvbXB1" + + "dGUtcGxhbmVgOioqCgogICBgYGBzaAogICBudmNmLWNsaSBzZWxmLWhvc3RlZCBhZGQtY29tcHV0" + + "ZS1wbGFuZSBcCiAgICAgLS1jbHVzdGVyLW5hbWU9JE5BTUUgXAogICAgIC0tY29tcHV0ZS1wbGFu" + + "ZS1jb250ZXh0PSRDVFggXAogICAgIC0taWNtcy11cmw9JElDTVMgXAogICAgIC0tdG9rZW49JEpX" + + "VCBcCiAgICAgLS1ub24taW50ZXJhY3RpdmUgXAogICAgIC0tanNvbgogICBgYGAKCiAgIFRoaXMg" + + "aXMgYSBzZXBhcmF0ZSBzdWJjb21tYW5kIGZyb20gYHVwYC4gSXQgcnVucyBvbmx5IHRoZSBjb21w" + + "dXRlLXBsYW5lLXJlbGV2YW50IHBoYXNlczogMSAoY29tcHV0ZS1wbGFuZSBwcmVmbGlnaHQpLCA1" + + "IChyZWdpc3RlciksIDYgKGNvbXB1dGUtcGxhbmUgYXBwbHkpLCA4IChmaW5hbCBoZWFsdGggb24g" + + "dGhlIG5ldyBjb21wdXRlIHBsYW5lKS4gSXQgZG9lcyBOT1QgdG91Y2ggdGhlIGNvbnRyb2wgcGxh" + + "bmUgYW5kIGRvZXMgTk9UIGFjY2VwdCBgLS1jb250cm9sLXBsYW5lLWNvbnRleHRgIOKAlCB0aGUg" + + "Y29udHJvbCBwbGFuZSBpcyByZWFjaGVkIG92ZXIgSFRUUFMgYXQgYC0taWNtcy11cmxgLiBgLS10" + + "b2tlbmAgaXMgcmVxdWlyZWQgYmVjYXVzZSB0aGVyZSdzIG5vIGt1YmVjdGwgcGF0aCB0byBtaW50" + + "IG9uZSBmcm9tLgoKNC4gKipWZXJpZnkuKiogYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHN0YXR1cyAt" + + "LWNsdXN0ZXItbmFtZT0kTkFNRSAtLWpzb24gfCBqcWAg4oCUIGV4cGVjdCBgdmVyZGljdDogImhl" + + "YWx0aHkiYC4gVGhlIFJlZ2lzdGVyZWQgQ29tcHV0ZSBQbGFuZXMgcGFuZWwgZnJvbSBJQ01TIHNo" + + "b3VsZCBub3cgbGlzdCB0aGUgbmV3IGNsdXN0ZXIuCgo1LiAqKlNtb2tlLioqIFtkZXBsb3ktYW5k" + + "LWludm9rZS5tZF0oZGVwbG95LWFuZC1pbnZva2UubWQpIOKAlCBkZXBsb3kgYSBzbWFsbCBmdW5j" + + "dGlvbiB0byB0aGUgbmV3IGNvbXB1dGUgcGxhbmUgdG8gY29uZmlybSBzY2hlZHVsaW5nIHdvcmtz" + + "LgoKIyMgV2hhdCBpZiBhIGNsdXN0ZXIgd2l0aCB0aGUgc2FtZSBuYW1lIGFscmVhZHkgZXhpc3Rz" + + "PwoKYGFkZC1jb21wdXRlLXBsYW5lYCdzIHJlZ2lzdGVyIHBoYXNlIHVzZXMgYC0taWdub3JlLWV4" + + "aXN0aW5nYCBzZW1hbnRpY3Mg4oCUIGl0J2xsIG1hdGNoIHRoZSBleGlzdGluZyBJQ01TIHJvdyBh" + + "bmQgcmV1c2UgaXRzIGNsdXN0ZXJJZC4gVHdvIHNjZW5hcmlvczoKCi0gKipSZS1yZWdpc3Rlcmlu" + + "ZyB0aGUgc2FtZSBjbHVzdGVyKiogKHJlLXJ1bm5pbmcgb24gdGhlIHNhbWUgY29tcHV0ZSBwbGFu" + + "ZSB0aGF0IHdhcyBwcmV2aW91c2x5IHJlZ2lzdGVyZWQpOiBleHBlY3RlZCwgbm8tb3Agc2VtYW50" + + "aWNzLgotICoqRGlmZmVyZW50IHBoeXNpY2FsIGNsdXN0ZXIgYnV0IHNhbWUgbmFtZSoqOiB0aGUg" + + "c2Vjb25kIGF0dGVtcHQgd2lsbCByZXVzZSB0aGUgSUNNUyByb3csIGJ1dCB0aGUgbmV3IGNvbXB1" + + "dGUgcGxhbmUncyBKV0tTIHdpbGwgYmUgc2lsZW50bHkgKnJlcGxhY2VkKiDigJQgdGhlIG9sZCBj" + + "b21wdXRlIHBsYW5lJ3MgTlZDQSBhZ2VudCB3aWxsIHN0YXJ0IGZhaWxpbmcgUFNBVCBhdXRoLiAq" + + "KkNvbmZpcm0gd2l0aCB0aGUgdXNlcioqIHRoYXQgdGhleSBtZWFudCB0byBvdmVyd3JpdGUuCgpX" + + "aGVuIGluIGRvdWJ0LCBydW4gYG52Y2YtY2xpIGNsdXN0ZXIgbGlzdC1yZWdpc3RlcmVkIC0tbmNh" + + "LWlkPSROQ0FfSUQgLS1pY21zLXVybD0kSUNNU2AgZmlyc3QgYW5kIGFzayB0aGUgdXNlciBiZWZv" + + "cmUgcHJvY2VlZGluZyB3aXRoIGEgbmFtZSB0aGF0IGFscmVhZHkgZXhpc3RzLgpQSwcIQidJDwUN" + + "AAAFDQAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAA5AAkAZGF0YS9udmNmLXNlbGYtbWFuYWdl" + + "ZC1jbGkvcHJvbXB0cy9jcmVhdGUtYW5kLXJ1bi10YXNrLm1kVVQFAAEAps4SIyBDcmVhdGUgYW5k" + + "IHJ1biBhIHRhc2sKClN0YW5kYXJkIGZsb3c6IG1pbnQgQVBJIGtleXMgLT4gdGFzayBDUkVBVEUg" + + "LT4gbW9uaXRvciAtPiByZXRyaWV2ZSByZXN1bHRzIC0+IGNsZWFudXAuCgojIyAxLiBNaW50IEFQ" + + "SSBrZXlzCgpUaGUgYWRtaW4gdG9rZW4gZnJvbSBgaW5pdGAgZG9lcyBub3QgY2FycnkgdGFzayBp" + + "bnZvY2F0aW9uIHNjb3BlLiBHZW5lcmF0ZSBBUEkga2V5czoKCmBgYHNoCm52Y2YtY2xpIGFwaS1r" + + "ZXkgZ2VuZXJhdGUgLS1kZXNjcmlwdGlvbj0idGFzayBzbW9rZSB0ZXN0IiAtLWV4cGlyZXMtaW49" + + "OGgKIyAtPiBmdW5jdGlvbiBrZXk6IG52YXBpLS4uLgojIC0+IHRhc2sga2V5OiBudmFwaS0uLi4K" + + "YGBgCgpCb3RoIGtleXMgYXJlIHNhdmVkIHRvIENMSSBzdGF0ZS4gVG8gbWludCBvbmx5IHRoZSB0" + + "YXNrIGtleToKCmBgYHNoCm52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1mb3IgdGFzayAtLWRl" + + "c2NyaXB0aW9uPSJ0YXNrIHNtb2tlIHRlc3QiIC0tZXhwaXJlcy1pbj04aApgYGAKClRvIHZhbGlk" + + "YXRlIGVhY2gga2V5IGltbWVkaWF0ZWx5IGFmdGVyIG1pbnRpbmc6CgpgYGBzaApudmNmLWNsaSBh" + + "cGkta2V5IGdlbmVyYXRlIC0tZGVzY3JpcHRpb249InRhc2sgc21va2UgdGVzdCIgLS1leHBpcmVz" + + "LWluPThoIC0tdmFsaWRhdGUKIyAtPiBmdW5jdGlvbiBBUEkga2V5IHZhbGlkYXRpb24gcGFzc2Vk" + + "IQojIC0+IHRhc2sgQVBJIGtleSB2YWxpZGF0aW9uIHBhc3NlZCEKYGBgCgpOZXZlciBlY2hvIHRo" + + "ZSBrZXkgdmFsdWUgKG52YXBpLS4uLikgaW50byBjaGF0IG9yIGxvZ3MuIFJlcG9ydCBvbmx5IHRo" + + "YXQgdGhlIGtleSB3YXMgbWludGVkLCBpdHMgZGVzY3JpcHRpb24sIGFuZCBpdHMgZXhwaXJ5IOKA" + + "lCBuZXZlciB0aGUgdmFsdWUgaXRzZWxmLgoKIyMjIEZyZXNoIHNlc3Npb24gcHJlLWZsaWdodAoK" + + "QmVmb3JlIHJ1bm5pbmcgYW55IGB0YXNrYCBjb21tYW5kIGluIGEgZnJlc2ggYWdlbnQgc2Vzc2lv" + + "biwgdmVyaWZ5IGNyZWRlbnRpYWxzOgoKMS4gQ2hlY2sgd2hldGhlciBgTlZDRl9BUElfS0VZYCBp" + + "cyBzZXQ6CgogICBgYGBzaAogICBwcmludGVudiBOVkNGX0FQSV9LRVkgPiAvZGV2L251bGwgMj4m" + + "MSAmJiBlY2hvIHNldCB8fCBlY2hvIHVuc2V0CiAgIGBgYAoKMi4gSWYgdW5zZXQsIHJlYWQgdGhl" + + "IHN0b3JlZCBrZXkgZXhwaXJ5IHdpdGhvdXQgcHJpbnRpbmcgdGhlIHZhbHVlOgoKICAgYGBgc2gK" + + "ICAgcHl0aG9uMyAtYyAiaW1wb3J0IGpzb24scGF0aGxpYjsgcz1qc29uLmxvYWRzKHBhdGhsaWIu" + + "UGF0aCgnfi8ubnZjZi1jbGkuc3RhdGUnKS5leHBhbmR1c2VyKCkucmVhZF90ZXh0KCkpOyBwcmlu" + + "dChzLmdldCgnbnZjdEFwaUtleUV4cGlyYXRpb24nLCdtaXNzaW5nJykpIgogICBgYGAKCjMuIElm" + + "IHRoZSBleHBpcnkgaXMgaW4gdGhlIHBhc3Qgb3IgbWlzc2luZywgcmVnZW5lcmF0ZToKCiAgIGBg" + + "YHNoCiAgIG52Y2YtY2xpIHJlZnJlc2gKICAgbnZjZi1jbGkgYXBpLWtleSBnZW5lcmF0ZSAtLWZv" + + "ciB0YXNrIC0tZGVzY3JpcHRpb249InRhc2sta2V5IiAtLWV4cGlyZXMtaW49MjRoIC0tdmFsaWRh" + + "dGUKICAgYGBgCgo0LiBJbmplY3QgdGhlIHN0b3JlZCBrZXkgaW50byB0aGUgc3VicHJvY2VzcyBl" + + "bnYgd2l0aG91dCBsb2dnaW5nIHRoZSB2YWx1ZS4gVXNlIGEgc2hlbGwgc3Vic2hlbGwgb3IgZW52" + + "IHByZWZpeCDigJQgbmV2ZXIgcHJpbnQgdGhlIGtleSBpbnRvIGNoYXQuCgpFcnJvciBjbGFzc2lm" + + "aWNhdGlvbjoKCi0gIm1pc3NpbmcgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMiIG9yIGV4aXQg" + + "Mjoga2V5IG5vdCBpbmplY3RlZDsgcmVwZWF0IHByZS1mbGlnaHQuCi0gSFRUUCA0MDM6IGtleSBl" + + "eHBpcmVkIG9yIHdyb25nIGF1ZGllbmNlOyByZWdlbmVyYXRlLgotIEVtcHR5IHRhc2sgbGlzdDog" + + "dmFsaWQ7IG5vIHRhc2tzIGV4aXN0IHlldC4KCiMjIDIuIFRhc2sgQ1JFQVRFOiBjb250YWluZXIK" + + "CkRlZmluZSB0aGUgdGFzayBpbiBhIEpTT04gZmlsZS4gTWluaW11bSB2aWFibGUgY29udGFpbmVy" + + "IHRhc2s6CgpgYGBqc29uCnsKICAibmFtZSI6ICJzbW9rZS1jb250YWluZXItdGFzayIsCiAgImdw" + + "dVNwZWNpZmljYXRpb24iOiB7CiAgICAiZ3B1IjogIkgxMDAiLAogICAgImluc3RhbmNlVHlwZSI6" + + "ICJOQ1AuR1BVLkgxMDBfMXgiLAogICAgImJhY2tlbmQiOiAibmNwLWxvY2FsIgogIH0sCiAgImNv" + + "bnRhaW5lckltYWdlIjogIm52Y3IuaW8vbnZpZGlhL25lbW86bGF0ZXN0IiwKICAiY29udGFpbmVy" + + "QXJncyI6ICJweXRob24gLWMgXCJwcmludCgnaGVsbG8gZnJvbSB0YXNrJylcIiIsCiAgInJlc3Vs" + + "dEhhbmRsaW5nU3RyYXRlZ3kiOiAiTk9ORSIKfQpgYGAKCmBgYHNoCm52Y2YtY2xpIHRhc2sgY3Jl" + + "YXRlIC0taW5wdXQtZmlsZT10YXNrLWNvbnRhaW5lci5qc29uCiMgLT4gVGFzayBJRDogPHRhc2tf" + + "aWQ+CmBgYAoKQ2FwdHVyZSB0aGUgdGFzayBJRCBmcm9tIHRoZSBvdXRwdXQuIFN0YXRlIHBlcnNp" + + "c3RlbmNlIGNhbiBmYWlsIHNpbGVudGx5LCBzbyBwYXNzCmA8dGFza0lkPmAgZXhwbGljaXRseSBv" + + "biBzdWJzZXF1ZW50IGNvbW1hbmRzIHJhdGhlciB0aGFuIHJlbHlpbmcgb24gc2F2ZWQgc3RhdGUu" + + "CgpFcXVpdmFsZW50IENMSSBmbGFncyBmb3JtIGZvciBxdWljayBhZC1ob2MgcnVuczoKCmBgYHNo" + + "Cm52Y2YtY2xpIHRhc2sgY3JlYXRlIFwKICAtLW5hbWU9c21va2UtY29udGFpbmVyLXRhc2sgXAog" + + "IC0tZ3B1PUgxMDAgXAogIC0taW5zdGFuY2UtdHlwZT1OQ1AuR1BVLkgxMDBfMXggXAogIC0tYmFj" + + "a2VuZD1uY3AtbG9jYWwgXAogIC0taW1hZ2U9bnZjci5pby9udmlkaWEvbmVtbzpsYXRlc3QgXAog" + + "IC0tY29udGFpbmVyLWFyZ3M9InB5dGhvbiAtYyAncHJpbnQoaGVsbG8gZnJvbSB0YXNrKSciIFwK" + + "ICAtLXJlc3VsdC1zdHJhdGVneT1OT05FCmBgYAoKVG8gdGFyZ2V0IGEgc3BlY2lmaWMgY29tcHV0" + + "ZSBjbHVzdGVyOgoKYGBgc2gKbnZjZi1jbGkgdGFzayBjcmVhdGUgLS1pbnB1dC1maWxlPXRhc2st" + + "Y29udGFpbmVyLmpzb24gLS1jbHVzdGVycz1teS1jbHVzdGVyCmBgYAoKVG8gaW5qZWN0IGVudmly" + + "b25tZW50IHZhcmlhYmxlcyBvciBzZWNyZXRzLCBlaXRoZXIgcGFzcyBmbGFnczoKCmBgYHNoCm52" + + "Y2YtY2xpIHRhc2sgY3JlYXRlIC0taW5wdXQtZmlsZT10YXNrLWNvbnRhaW5lci5qc29uIFwKICAt" + + "LWNvbnRhaW5lci1lbnYgTVlfRU5WPXZhbHVlIFwKICAtLXNlY3JldHMgTVlfU0VDUkVUPXMzY3Iz" + + "dApgYGAKCm9yIHNldCB0aGVtIGluIHRoZSBKU09OIGZpbGU6CgpgYGBqc29uCnsKICAiY29udGFp" + + "bmVyRW52aXJvbm1lbnQiOiBbCiAgICB7ImtleSI6ICJNWV9FTlYiLCAidmFsdWUiOiAidmFsdWUi" + + "fQogIF0sCiAgInNlY3JldHMiOiBbCiAgICB7Im5hbWUiOiAiTVlfU0VDUkVUIiwgInZhbHVlIjog" + + "InMzY3IzdCJ9CiAgXQp9CmBgYAoKU2VjcmV0cyBhcmUgZW5jcnlwdGVkIGF0IHJlc3QgYW5kIG5v" + + "dCByZXR1cm5lZCBpbiBsaXN0IG9yIGdldCByZXNwb25zZXMgYnkgZGVmYXVsdDsgZG8gbm90IGxv" + + "ZyB0aGVtLgoKIyMgMy4gVGFzayBDUkVBVEU6IEhlbG0KCkZvciBIZWxtLXR5cGUgdGFza3MsIHJl" + + "cGxhY2UgYGNvbnRhaW5lckltYWdlYCB3aXRoIGBoZWxtQ2hhcnRgOgoKYGBganNvbgp7CiAgIm5h" + + "bWUiOiAic21va2UtaGVsbS10YXNrIiwKICAiZ3B1U3BlY2lmaWNhdGlvbiI6IHsKICAgICJncHUi" + + "OiAiSDEwMCIsCiAgICAiaW5zdGFuY2VUeXBlIjogIk5DUC5HUFUuSDEwMF8xeCIsCiAgICAiYmFj" + + "a2VuZCI6ICJuY3AtbG9jYWwiCiAgfSwKICAiaGVsbUNoYXJ0IjogImh0dHBzOi8vaGVsbS5uZ2Mu" + + "bnZpZGlhLmNvbS88b3JnPi9jaGFydHMvZXhhbXBsZS10YXNrLTAuMS4wLnRneiIsCiAgInJlc3Vs" + + "dEhhbmRsaW5nU3RyYXRlZ3kiOiAiTk9ORSIKfQpgYGAKCmBgYHNoCm52Y2YtY2xpIHRhc2sgY3Jl" + + "YXRlIC0taW5wdXQtZmlsZT10YXNrLWhlbG0uanNvbgojIC0+IFRhc2sgSUQ6IDx0YXNrX2lkPgpg" + + "YGAKCmBoZWxtQ2hhcnRgIGFuZCBgY29udGFpbmVySW1hZ2VgIGFyZSBtdXR1YWxseSBleGNsdXNp" + + "dmUuCgojIyAzYi4gVXBkYXRlIHNlY3JldHMgb24gYSBydW5uaW5nIHRhc2sKCmBgYHNoCm52Y2Yt" + + "Y2xpIHRhc2sgdXBkYXRlLXNlY3JldHMgPHRhc2tfaWQ+IC0tc2VjcmV0cyBOQU1FPXZhbHVlCmBg" + + "YAoKYHVwZGF0ZS1zZWNyZXRzYCBtZXJnZXMgc2VjcmV0cyBieSBuYW1lOiBzdXBwbGllZCBzZWNy" + + "ZXRzIGFyZSBhZGRlZCBvciB1cGRhdGVkLCBhbmQgZXhpc3Rpbmcgc2VjcmV0cyBub3QgaW5jbHVk" + + "ZWQgaW4gdGhlIHJlcXVlc3QgYXJlIHByZXNlcnZlZC4gRG8gbm90IGVjaG8gc2VjcmV0IHZhbHVl" + + "cyBpbnRvIGNoYXQuCgojIyA0LiBNb25pdG9yCgpQb2xsIHRhc2sgc3RhdGU6CgpgYGBzaApudmNm" + + "LWNsaSB0YXNrIGdldCA8dGFza19pZD4KIyAtPiBpZDogPHRhc2tfaWQ+CiMgLT4gc3RhdHVzOiBS" + + "VU5OSU5HCmBgYAoKT3IgdXNlIHRoZSB0YXNrIElEIHNhdmVkIHRvIHN0YXRlIGZyb20gdGhlIG1v" + + "c3QgcmVjZW50IGB0YXNrIGNyZWF0ZWA6CgpgYGBzaApudmNmLWNsaSB0YXNrIGdldApgYGAKClN0" + + "YXR1cyB2YWx1ZXM6IGBRVUVVRURgLCBgTEFVTkNIRURgLCBgUlVOTklOR2AsIGBDT01QTEVURURg" + + "LCBgRVJST1JFRGAsIGBDQU5DRUxFRGAsIGBFWENFRURFRF9NQVhfUlVOVElNRV9EVVJBVElPTmAs" + + "IGBFWENFRURFRF9NQVhfUVVFVUVEX0RVUkFUSU9OYC4KCkluc3BlY3QgbGlmZWN5Y2xlIGV2ZW50" + + "cyBmb3IgcHJvZ3Jlc3MgZGV0YWlscyBvciBmYWlsdXJlIGNvbnRleHQ6CgpgYGBzaApudmNmLWNs" + + "aSB0YXNrIGV2ZW50cyA8dGFza19pZD4KYGBgCgpJZiB0aGUgdGFzayBpcyBzdHVjayBpbiBgUVVF" + + "VUVEYCwgY2hlY2sgdGhhdCBhIGNvbXB1dGUgY2x1c3RlciB3aXRoIGEgbWF0Y2hpbmcgR1BVIFNL" + + "VQppcyByZWdpc3RlcmVkIGFuZCBoZWFsdGh5IChgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgc3RhdHVz" + + "YCkuCgpJZiB0aGUgdGFzayBtb3ZlcyB0byBgRVJST1JFRGAsIHRoZSBldmVudHMgb3V0cHV0IGNv" + + "bnRhaW5zIHRoZSBmYWlsdXJlIHJlYXNvbi4gRm9yCmNvbnRhaW5lci1sZXZlbCBkZXRhaWwsIGlu" + + "c3BlY3QgdGhlIHRhc2sgd29ya2xvYWQgcG9kcyBvbiB0aGUgY29tcHV0ZS1wbGFuZSBjbHVzdGVy" + + "IHdpdGgKYGt1YmVjdGxgIGFnYWluc3QgdGhlIGFwcHJvcHJpYXRlIG5hbWVzcGFjZSBhbmQgY29u" + + "dGV4dC4KCiMjIDUuIFJldHJpZXZlIHJlc3VsdHMKCkZvciB0YXNrcyB3aXRoIGByZXN1bHRIYW5k" + + "bGluZ1N0cmF0ZWd5OiBOT05FYCwgcmVzdWx0cyBhcmUgZW1wdHkgYnkgZGVzaWduOgoKYGBgc2gK" + + "bnZjZi1jbGkgdGFzayByZXN1bHRzIDx0YXNrX2lkPgojIC0+IHsicmVzdWx0cyI6IFtdfQpgYGAK" + + "CkZvciB0YXNrcyB3aXRoIGByZXN1bHRIYW5kbGluZ1N0cmF0ZWd5OiBVUExPQURgLCByZXN1bHRz" + + "IHVwbG9hZCB0byB0aGUgbG9jYXRpb24gbmFtZWQgaW4KYHJlc3VsdHNMb2NhdGlvbmAuIFRoZSB0" + + "YXNrJ3MgY3JlZGVudGlhbHMgbXVzdCBoYXZlIHdyaXRlIGFjY2VzcyB0byB0aGF0IGxvY2F0aW9u" + + "LiBBZnRlcgp0aGUgdGFzayByZWFjaGVzIGBDT01QTEVURURgOgoKYGBgc2gKbnZjZi1jbGkgdGFz" + + "ayByZXN1bHRzIDx0YXNrX2lkPgpgYGAKCk5vdGU6IHJlc3VsdCB1cGxvYWQgaXMgbm90IHlldCBz" + + "dXBwb3J0ZWQgaW4gdGhpcyByZWxlYXNlLgoKIyMgNi4gQ2xlYW51cAoKQ2FuY2VsIGEgcnVubmlu" + + "ZyB0YXNrOgoKYGBgc2gKbnZjZi1jbGkgdGFzayBjYW5jZWwgPHRhc2tfaWQ+CmBgYAoKRGVsZXRl" + + "IHRoZSB0YXNrIHJlY29yZCBhZnRlciBpdCByZWFjaGVzIGEgdGVybWluYWwgc3RhdGU6CgpgYGBz" + + "aApudmNmLWNsaSB0YXNrIGRlbGV0ZSA8dGFza19pZD4KYGBgCgpTdG9wIGFuZCBjb25maXJtIHdp" + + "dGggdGhlIHVzZXIgYmVmb3JlIHJ1bm5pbmcgdGFzayBkZWxldGUuIFN0YXRlIHRoZSB0YXNrIElE" + + "IGFuZCBpdHMgY3VycmVudCBzdGF0dXMuIERvIG5vdCBwcm9jZWVkIGV2ZW4gd2hlbiB0aGUgdXNl" + + "cidzIHByb21wdCBhbHJlYWR5IHJlcXVlc3RlZCBkZWxldGlvbiDigJQgYWx3YXlzIGdldCBhbiBl" + + "eHBsaWNpdCBsYXN0LWxvb2sgY29uZmlybWF0aW9uLiBEZWxldGlvbiBpcyBwZXJtYW5lbnQgYW5k" + + "IGNhbm5vdCBiZSB1bmRvbmUuCgpUbyBsaXN0IGFsbCB0YXNrcyBmb3IgdGhlIGN1cnJlbnQgb3du" + + "ZXIgKHVzZWZ1bCBiZWZvcmUgYnVsayBjbGVhbnVwKToKCmBgYHNoCm52Y2YtY2xpIHRhc2sgbGlz" + + "dApudmNmLWNsaSB0YXNrIGxpc3QgLS1zdGF0dXM9Q09NUExFVEVECmBgYAoKIyMgTm90ZXMKCi0g" + + "R1BVIGZhbWlseSBhbmQgaW5zdGFuY2UgdHlwZSBtdXN0IG1hdGNoIGEgcmVnaXN0ZXJlZCBjb21w" + + "dXRlIGNsdXN0ZXIgU0tVLiBNaXNtYXRjaAogIGNhdXNlcyB0aGUgdGFzayB0byByZW1haW4gYFFV" + + "RVVFRGAgaW5kZWZpbml0ZWx5LiBVc2UgYG52Y2YtY2xpIGNsdXN0ZXIgbGlzdGAgdG8gY2hlY2sK" + + "ICByZWdpc3RlcmVkIFNLVXMuCi0gRm9yIGNvbnRhaW5lciBpbWFnZXMgb24gcHJpdmF0ZSByZWdp" + + "c3RyaWVzLCBlbnN1cmUgdGhlIGNvbXB1dGUtcGxhbmUgY2x1c3RlcidzCiAgaW1hZ2UtY3JlZGVu" + + "dGlhbC1oZWxwZXIgaXMgY29uZmlndXJlZCBmb3IgdGhlIHJlZ2lzdHJ5IGhvc3QuClBLBwjU3o00" + + "nxkAAJ8ZAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADcACQBkYXRhL252Y2Ytc2VsZi1tYW5h" + + "Z2VkLWNsaS9wcm9tcHRzL2RlcGxveS1hbmQtaW52b2tlLm1kVVQFAAEAps4SIyBEZXBsb3kgYW5k" + + "IGludm9rZSBhIGNvbnRhaW5lciBmdW5jdGlvbgoKU3RhbmRhcmQgZm91ci1zdGVwIGZsb3c6IGZ1" + + "bmN0aW9uIENSRUFURSDihpIgREVQTE9ZIOKGkiBBUEkga2V5IChmb3IgaW52b2tlIHNjb3BlKSDi" + + "hpIgSU5WT0tFLgoKIyMgMS4gRnVuY3Rpb24gQ1JFQVRFCgpEZWZpbmUgdGhlIGZ1bmN0aW9uIGlu" + + "IGEgSlNPTiBmaWxlLiBNaW5pbXVtOgoKQmVmb3JlIGNyZWF0aW5nIHRoZSBmdW5jdGlvbiwgY29u" + + "ZmlybSB0aGUgZXhhY3QgZnVuY3Rpb24gbmFtZSBhbmQgY29udGFpbmVyIGltYWdlIHdpdGggdGhl" + + "IHVzZXIuIElmIGVpdGhlciB2YWx1ZSBpcyBtaXNzaW5nLCBzdG9wIGFuZCBhc2suIERvIG5vdCBp" + + "bnZlbnQgb3Igc3VibWl0IGV4YW1wbGUgdmFsdWVzIGZvciB0aGVzZSBmaWVsZHMuCgpgYGBqc29u" + + "CnsKICAibmFtZSI6ICI8Y29uZmlybWVkLWZ1bmN0aW9uLW5hbWU+IiwKICAiY29udGFpbmVySW1h" + + "Z2UiOiAiPGNvbmZpcm1lZC1jb250YWluZXItaW1hZ2U+IiwKICAiaW5mZXJlbmNlVXJsIjogIi9l" + + "Y2hvIiwKICAiaW5mZXJlbmNlUG9ydCI6IDgwMDAsCiAgImRlc2NyaXB0aW9uIjogInNtb2tlIHRl" + + "c3QgZWNobyBmdW5jdGlvbiIsCiAgImZ1bmN0aW9uVHlwZSI6ICJERUZBVUxUIiwKICAiYXBpQm9k" + + "eUZvcm1hdCI6ICJDVVNUT00iLAogICJoZWFsdGgiOiB7CiAgICAicHJvdG9jb2wiOiAiSFRUUCIs" + "CiAgICAidXJpIjogIi9oZWFsdGgiLAogICAgInBvcnQiOiA4MDAwLAogICAgInRpbWVvdXQiOiAi" + - "UFQzMFMiLAogICAgImV4cGVjdGVkU3RhdHVzQ29kZSI6IDIwMAogIH0sCiAgImhlbG1DaGFydCI6" + - "ICJodHRwczovL2hlbG0ubmdjLm52aWRpYS5jb20vZXhhbXBsZS90ZWFtL2NoYXJ0cy9vcGVuYWkt" + - "Y29tcGF0aWJsZS0wLjEuMC50Z3oiLAogICJoZWxtQ2hhcnRTZXJ2aWNlTmFtZSI6ICJvcGVuYWkt" + - "Y29tcGF0aWJsZSIsCiAgIm1vZGVscyI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAiPGNvbmZpcm1l" + - "ZC1tb2RlbC1uYW1lPiIsCiAgICAgICJsbG1Db25maWciOiB7CiAgICAgICAgInVyaXMiOiBbIi92" + - "MS9jaGF0L2NvbXBsZXRpb25zIiwgIi92MS9yZXNwb25zZXMiLCAiL3YxL2VtYmVkZGluZ3MiXSwK" + - "ICAgICAgICAicm91dGluZ01ldGhvZCI6ICJyb3VuZF9yb2JpbiIsCiAgICAgICAgInRva2VuUmF0" + - "ZUxpbWl0IjogIjEwMDAtUyIKICAgICAgfQogICAgfQogIF0KfQpgYGAKCkVxdWl2YWxlbnQgQ0xJ" + - "IGZsYWcgZm9ybToKCmBgYHNoCm52Y2YtY2xpIGZ1bmN0aW9uIGNyZWF0ZSBcCiAgLS1uYW1lPSI8" + - "Y29uZmlybWVkLWZ1bmN0aW9uLW5hbWU+IiBcCiAgLS1pbmZlcmVuY2UtdXJsPS8gXAogIC0taW5m" + - "ZXJlbmNlLXBvcnQ9ODAwMCBcCiAgLS1oZWFsdGgtdXJpPS9oZWFsdGggXAogIC0taGVhbHRoLXBv" + - "cnQ9ODAwMCBcCiAgLS1oZWFsdGgtdGltZW91dD1QVDMwUyBcCiAgLS1oZWFsdGgtcHJvdG9jb2w9" + - "SFRUUCBcCiAgLS1oZWFsdGgtZXhwZWN0ZWQtc3RhdHVzPTIwMCBcCiAgLS1mdW5jdGlvbi10eXBl" + - "PUxMTSBcCiAgLS1oZWxtLWNoYXJ0PWh0dHBzOi8vaGVsbS5uZ2MubnZpZGlhLmNvbS9leGFtcGxl" + - "L3RlYW0vY2hhcnRzL29wZW5haS1jb21wYXRpYmxlLTAuMS4wLnRneiBcCiAgLS1oZWxtLWNoYXJ0" + - "LXNlcnZpY2U9b3BlbmFpLWNvbXBhdGlibGUgXAogIC0tbGxtLW1vZGVsPSduYW1lPTxjb25maXJt" + - "ZWQtbW9kZWwtbmFtZT4sdXJpcz0vdjEvY2hhdC9jb21wbGV0aW9uc3wvdjEvcmVzcG9uc2VzfC92" + - "MS9lbWJlZGRpbmdzLHJvdXRpbmdNZXRob2Q9cm91bmRfcm9iaW4sdG9rZW5SYXRlTGltaXQ9MTAw" + - "MC1TJwpgYGAKCkRlcGxveSBpcyB1bmNoYW5nZWQuIFB1dCBjaGFydC1zcGVjaWZpYyB2YWx1ZXMg" + - "dW5kZXIgYGRlcGxveW1lbnRTcGVjaWZpY2F0aW9uc1tdLmNvbmZpZ3VyYXRpb25gIG9ubHkgd2hl" + - "biB0aGUgY2hhcnQgbmVlZHMgdmFsdWUgb3ZlcnJpZGVzOgoKYGBganNvbgp7CiAgImZ1bmN0aW9u" + - "SWQiOiAiPGZuX2lkPiIsCiAgInZlcnNpb25JZCI6ICI8dmVyX2lkPiIsCiAgImRlcGxveW1lbnRT" + - "cGVjaWZpY2F0aW9ucyI6IFt7CiAgICAiZ3B1IjogIkgxMDAiLAogICAgImluc3RhbmNlVHlwZSI6" + - "ICJOQ1AuR1BVLkgxMDBfMXgiLAogICAgIm1pbkluc3RhbmNlcyI6IDEsCiAgICAibWF4SW5zdGFu" + - "Y2VzIjogMSwKICAgICJtYXhSZXF1ZXN0Q29uY3VycmVuY3kiOiAxMCwKICAgICJjb25maWd1cmF0" + - "aW9uIjogewogICAgICAic2VydmluZyI6IHsKICAgICAgICAidGVuc29yUGFyYWxsZWxTaXplIjog" + - "MQogICAgICB9CiAgICB9CiAgfV0KfQpgYGAKCkxMTSBHYXRld2F5IHJvdXRlcyByZXF1ZXN0cyBi" + - "eSB0aGUgT3BlbkFJIGBtb2RlbGAgdmFsdWUuIFVzZSBgPGZ1bmN0aW9uLWlkPi88bW9kZWwtbmFt" + - "ZT5gOiB0aGUgZnVuY3Rpb24gSUQgc2VsZWN0cyB0aGUgTlZDRiBmdW5jdGlvbiwgYW5kIHRoZSBt" + - "b2RlbCBuYW1lIGlzIGZvcndhcmRlZCB0byB0aGUgdXBzdHJlYW0gY29udGFpbmVyIHRocm91Z2gg" + - "YHN0YXJnYXRlLWNsaWVudGAuCgpTdXBwb3J0ZWQgTExNIHBhdGhzOgoKfCBQYXRoIHwgTm90ZXMg" + - "fAp8IC0tLSB8IC0tLSB8CnwgYC92MS9jaGF0L2NvbXBsZXRpb25zYCB8IFN1cHBvcnRzIHN0cmVh" + - "bWluZyBhbmQgc2Vzc2lvbiBzdGlja2luZXNzLiB8CnwgYC92MS9yZXNwb25zZXNgIHwgTmF0aXZl" + - "IFJlc3BvbnNlcyBwcm94eSBwYXRoOyByZWxheXMgU1NFIGZvciBzdHJlYW1pbmcgY2xpZW50cyBh" + - "bmQgcmV0dXJucyB0ZXJtaW5hbCBKU09OIGZvciBub24tc3RyZWFtaW5nIGNsaWVudHMuIFN1cHBv" + - "cnRzIHNlc3Npb24gc3RpY2tpbmVzcy4gfAp8IGAvdjEvZW1iZWRkaW5nc2AgfCBBY2NlcHRzIHN0" + - "cmluZyBvciBzdHJpbmctYXJyYXkgYGlucHV0YDsgaW5wdXQgbXVzdCBiZSBub24tZW1wdHkgYW5k" + - "IG1heSBjb250YWluIGF0IG1vc3QgMjA0OCBlbnRyaWVzLiBObyBzZXNzaW9uIHN0aWNraW5lc3Mu" + - "IHwKCiMjIDIuIEZ1bmN0aW9uIERFUExPWQoKYGBganNvbgp7CiAgImZ1bmN0aW9uSWQiOiAiPGZu" + - "X2lkPiIsCiAgInZlcnNpb25JZCI6ICI8dmVyX2lkPiIsCiAgImRlcGxveW1lbnRTcGVjaWZpY2F0" + - "aW9ucyI6IFt7CiAgICAiZ3B1IjogIkgxMDAiLAogICAgImluc3RhbmNlVHlwZSI6ICJOQ1AuR1BV" + - "LkgxMDBfMXgiLAogICAgIm1pbkluc3RhbmNlcyI6IDEsCiAgICAibWF4SW5zdGFuY2VzIjogMSwK" + - "ICAgICJtYXhSZXF1ZXN0Q29uY3VycmVuY3kiOiAxMAogIH1dCn0KYGBgCgpOb3RlOiBgZ3B1YCBp" + - "cyB0aGUgR1BVICoqZmFtaWx5KiogKGUuZy4gYEgxMDBgKSwgYGluc3RhbmNlVHlwZWAgaXMgdGhl" + - "IFNLVSAoZS5nLiBgTkNQLkdQVS5IMTAwXzF4YCkuIE1pc21hdGNoIHJldHVybnMgSUNNUyA0MDAg" + - "IkludmFsaWQgR1BVIi4KCmBgYHNoCm52Y2YtY2xpIGZ1bmN0aW9uIGRlcGxveSBjcmVhdGUgLS1p" + - "bnB1dC1maWxlPWRlcGxveS1mbi5qc29uCmBgYAoKVGhpcyBjb21tYW5kICoqYmxvY2tzKiogdW50" + - "aWwgdGhlIGRlcGxveW1lbnQgcmVhY2hlcyBBQ1RJVkUgKGRlZmF1bHQgOTAwcyB0aW1lb3V0KS4g" + - "V2hlbiBpdCByZXR1cm5zIHJjPTAsIGEgZnVuY3Rpb24gcG9kIGlzIHJ1bm5pbmcgaW4gdGhlIGBu" + - "dmNmLWJhY2tlbmRgIG5hbWVzcGFjZSBvbiB0aGUgY29tcHV0ZS1wbGFuZSBjbHVzdGVyLgoKIyMg" + - "My4gTWludCBhbiBBUEkga2V5IHdpdGggYGludm9rZV9mdW5jdGlvbmAgc2NvcGUKCmBudmNmLWNs" + - "aSBpbml0YCdzIGFkbWluIHRva2VuIGRvZXMgTk9UIGNhcnJ5IHRoZSBgaW52b2tlX2Z1bmN0aW9u" + - "YCBzY29wZSDigJQgaW52b2tlIHdvdWxkIDQwMyB3aXRoICJtaXNzaW5nIHJlcXVlc3RlZCBhdXRo" + - "b3JpdGllcyIuIE1pbnQgYW4gQVBJIGtleToKCmBgYHNoCm52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJh" + - "dGUgLS1kZXNjcmlwdGlvbj0iPGNvbmZpcm1lZC1mdW5jdGlvbi1uYW1lPiBpbnZva2UiIC0tZXhw" + - "aXJlcy1pbj0xaAojIOKGkiBBUEkgS2V5OiBudmFwaS1udmNmLXN0Zy0uLi4KYGBgCgpUaGUga2V5" + - "IGlzIGF1dG9tYXRpY2FsbHkgc2F2ZWQgdG8gdGhlIENMSSBzdGF0ZSBmaWxlIGFuZCB1c2VkIGJ5" + - "IHRoZSBuZXh0IGBmdW5jdGlvbiBpbnZva2VgIGNhbGwuICoqRG9uJ3QgZWNobyB0aGUga2V5IGlu" + - "dG8gY2hhdCAvIGxvZ3MqKi4KCiMjIDQuIEZ1bmN0aW9uIElOVk9LRQoKYGBganNvbgp7CiAgImZ1" + - "bmN0aW9uSWQiOiAiPGZuX2lkPiIsCiAgInZlcnNpb25JZCI6ICI8dmVyX2lkPiIsCiAgInJlcXVl" + - "c3RCb2R5IjogeyJtZXNzYWdlIjogImhlbGxvIn0KfQpgYGAKCmBgYHNoCm52Y2YtY2xpIGZ1bmN0" + - "aW9uIGludm9rZSAtLWlucHV0LWZpbGU9aW52b2tlLWZuLmpzb24KIyDihpIgRnVuY3Rpb24gaW52" + - "b2NhdGlvbiBjb21wbGV0ZWQhCiMg4oaSIFN0YXR1czogZnVsZmlsbGVkCiMg4oaSIFJlcXVlc3Qg" + - "SUQ6IC4uLgpgYGAKCkZvciBhbiBMTE0gZnVuY3Rpb24sIGludm9rZSB0aGUgT3BlbkFJLWNvbXBh" + - "dGlibGUgcm91dGUgYWZ0ZXIgZGVwbG95bWVudDoKCmBgYHNoCmN1cmwgLXNTIC1YIFBPU1QgImh0" + - "dHBzOi8vbGxtLmludm9jYXRpb24uPGRvbWFpbj4vdjEvY2hhdC9jb21wbGV0aW9ucyIgXAogIC1I" + - "ICJBdXRob3JpemF0aW9uOiBCZWFyZXIgJHtOVkNGX0FQSV9LRVl9IiBcCiAgLUggIkNvbnRlbnQt" + - "VHlwZTogYXBwbGljYXRpb24vanNvbiIgXAogIC1kICd7CiAgICAibW9kZWwiOiAiPGZuX2lkPi88" + - "Y29uZmlybWVkLW1vZGVsLW5hbWU+IiwKICAgICJzdHJlYW0iOiB0cnVlLAogICAgIm1lc3NhZ2Vz" + - "IjogWwogICAgICB7CiAgICAgICAgInJvbGUiOiAidXNlciIsCiAgICAgICAgImNvbnRlbnQiOiAi" + - "SGVsbG8iCiAgICAgIH0KICAgIF0KICB9JwpgYGAKClRoZSBPcGVuQUkgYG1vZGVsYCB2YWx1ZSBt" + - "dXN0IGJlIGA8ZnVuY3Rpb24taWQ+Lzxtb2RlbC1uYW1lPmAgc28gdGhlIGdhdGV3YXkgY2FuIHNl" + - "bGVjdCB0aGUgZnVuY3Rpb24gYW5kIG1vZGVsLgoKUmVzcG9uc2VzIEFQSSBleGFtcGxlOgoKYGBg" + - "c2gKY3VybCAtc1MgLVggUE9TVCAiaHR0cHM6Ly9sbG0uaW52b2NhdGlvbi48ZG9tYWluPi92MS9y" + - "ZXNwb25zZXMiIFwKICAtSCAiQXV0aG9yaXphdGlvbjogQmVhcmVyICR7TlZDRl9BUElfS0VZfSIg" + - "XAogIC1IICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAtZCAnewogICAgIm1v" + - "ZGVsIjogIjxmbl9pZD4vPGNvbmZpcm1lZC1tb2RlbC1uYW1lPiIsCiAgICAiaW5wdXQiOiAiV3Jp" + - "dGUgYSBvbmUgc2VudGVuY2Ugc3VtbWFyeSBvZiBOVkNGLiIKICB9JwpgYGAKCkVtYmVkZGluZ3Mg" + - "ZXhhbXBsZToKCmBgYHNoCmN1cmwgLXNTIC1YIFBPU1QgImh0dHBzOi8vbGxtLmludm9jYXRpb24u" + - "PGRvbWFpbj4vdjEvZW1iZWRkaW5ncyIgXAogIC1IICJBdXRob3JpemF0aW9uOiBCZWFyZXIgJHtO" + - "VkNGX0FQSV9LRVl9IiBcCiAgLUggIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbiIgXAog" + - "IC1kICd7CiAgICAibW9kZWwiOiAiPGZuX2lkPi88Y29uZmlybWVkLW1vZGVsLW5hbWU+IiwKICAg" + - "ICJpbnB1dCI6ICJOVkNGIGVtYmVkZGluZ3MgY2hlY2siCiAgfScKYGBgCgpJZiBzdGF0dXMgaXMg" + - "YGVycm9yZWRgLCBxdWVyeSBJQ01TIGZvciB0aGUgZGVwbG95bWVudCdzIHBvZCBsb2dzIChrdWJl" + - "Y3RsIG9uIHRoZSBjb21wdXRlLXBsYW5lIGNsdXN0ZXIpIGFuZCBzdXJmYWNlIHRvIHRoZSB1c2Vy" + - "LgoKIyMgNS4gQ2xlYW51cAoKV2hlbiB0aGUgdXNlciBpcyBkb25lIHdpdGggdGhlIHNtb2tlIHRl" + - "c3Q6CgpgYGBzaApudmNmLWNsaSBmdW5jdGlvbiBkZWxldGUgLS1mdW5jdGlvbi1pZD08Zm5faWQ+" + - "IC0tdmVyc2lvbi1pZD08dmVyX2lkPgpgYGAKCioqQ29uZmlybSB3aXRoIHRoZSB1c2VyIGJlZm9y" + - "ZSBkZWxldGluZy4qKiBUaGlzIHJlbW92ZXMgYm90aCB0aGUgZGVwbG95bWVudCBhbmQgdGhlIGZ1" + - "bmN0aW9uIHJlY29yZC4KCiMjIE5vdGVzCgotIERlcGxveSB0aW1lcyBjYW4gdmFyeSB3aWRlbHkg" + - "ZGVwZW5kaW5nIG9uIE5BVFMgc3RyZWFtLWluaXQgbGF0ZW5jeSBvbiBjb2xkLWNsdXN0ZXIgcnVu" + - "cyAoMS03IG1pbnV0ZXMgb2JzZXJ2ZWQgaW4gZGV2LVZNIHRlc3RzKS4gQmUgcGF0aWVudDsgZG9u" + - "J3Qga2lsbCB0aGUgYGZ1bmN0aW9uIGRlcGxveSBjcmVhdGVgIGNvbW1hbmQgZWFybHkuCi0gRm9y" + - "IGRpZmZlcmVudCBHUFUgZmFtaWxpZXMsIGNoYW5nZSBib3RoIGBncHVgIGFuZCBgaW5zdGFuY2VU" + - "eXBlYCB0b2dldGhlci4gQ29tbW9uIFNLVXM6IGBOQ1AuR1BVLkgxMDBfMXhgLCBgTkNQLkdQVS5I" + - "MTAwXzJ4YCwgYE5DUC5HUFUuQTEwMF8xeGAuCi0gVGhlIGZ1bmN0aW9uJ3MgY29udGFpbmVyIGlt" + - "YWdlIG11c3QgYmUgcHVsbGFibGUgZnJvbSB0aGUgY29tcHV0ZS1wbGFuZSBjbHVzdGVyJ3MgaW1h" + - "Z2UtY3JlZGVudGlhbC1oZWxwZXIgY29uZmlnIChjaGVjayBga3ViZWN0bCBkZXNjcmliZSBwb2Qg" + - "LW4gbnZjZi1iYWNrZW5kYCBpZiBwb2RzIGxhbmQgaW4gYEltYWdlUHVsbEJhY2tPZmZgKS4KUEsH" + - "CNJD3AQYJQAAGCUAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAAPQAJAGRhdGEvbnZjZi1zZWxm" + - "LW1hbmFnZWQtY2xpL3Byb21wdHMvZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWRVVAUAAQCmzhIj" + - "IERpYWdub3NlIGEgZmFpbGVkIHNlbGYtaG9zdGVkIE5WQ0YgaW5zdGFsbAoKVXNlciBzYXlzICJt" + - "eSBpbnN0YWxsIGZhaWxlZCIgb3IgIlggaXNuJ3Qgd29ya2luZyIuIERvbid0IGd1ZXNzIOKAlCBx" + - "dWVyeSB0aGUgY2x1c3Rlci4KCiMjIDEuIEdldCB0aGUgdmVyZGljdAoKYGBgc2gKbnZjZi1jbGkg" + - "c2VsZi1ob3N0ZWQgc3RhdHVzIC0tanNvbiB8IGpxIC1jIC4KYGBgCgpUaGUgZmlyc3QgZXZlbnQg" + - "aXMgdGhlIHNuYXBzaG90LiBQYXJzZSBgLnZlcmRpY3RgOgoKLSAqKmBoZWFsdGh5YCoqIOKAlCBu" + - "b3RoaW5nJ3Mgd3JvbmcuIEFzayB0aGUgdXNlciB3aGF0IHRoZXkncmUgYWN0dWFsbHkgc2VlaW5n" + - "OyB0aGVpciBwcm9ibGVtIG1heSBiZSBhdCBhIGRpZmZlcmVudCBsYXllciAoZnVuY3Rpb24gZGVw" + - "bG95LCBuZXR3b3JrLCBldGMuKS4KLSAqKmBkZWdyYWRlZGAqKiDigJQgYXQgbGVhc3Qgb25lIGNv" + - "bXBvbmVudCBub3QgcmVhZHkuIFRoZSBDb21wb25lbnRzIGxpc3Qgd2lsbCBpZGVudGlmeSB3aGlj" + - "aC4gTW9zdCBjb21tb246IGBjYXNzYW5kcmFgIFBvZEluaXRpYWxpemluZywgYG9wZW5iYW9gIG5v" + - "dCB1bnNlYWxlZCwgYHNpc2AgSW1hZ2VQdWxsQmFja09mZi4KLSAqKmBmYWlsZWRgKiog4oCUIE5W" + - "Q0ZCYWNrZW5kIGBIZWFsdGg9RmFpbGVkYC4gUmVhZCB0aGUgY2x1c3RlcidzIE5WQ0ZCYWNrZW5k" + - "IHN0YXR1cyBjb25kaXRpb24gbWVzc2FnZS4KLSAqKmB1bmtub3duYCoqIOKAlCBJQ01TIHVucmVh" + - "Y2hhYmxlLiBUaGUgY29udHJvbCBwbGFuZSBpdHNlbGYgbWF5IGJlIGRvd247IGNoZWNrIGBrdWJl" + - "Y3RsIGdldCBwb2RzIC1uIHNpc2AgZGlyZWN0bHkuCgojIyAyLiBEcmlsbCBpbnRvIHRoZSBmYWls" + - "aW5nIGNvbXBvbmVudAoKRm9yIGVhY2ggbm9uLXJlYWR5IGNvbXBvbmVudCwgdGhlIHNuYXBzaG90" + - "IGluY2x1ZGVzIGEgYG1lc3NhZ2VgIChlLmcuIGBjYXNzYW5kcmEtMCBQb2RJbml0aWFsaXppbmcg" + - "Nm0yM3NgKS4gQXNrIHRoZSB1c2VyIHRvIHJ1bjoKCmBgYHNoCmt1YmVjdGwgZGVzY3JpYmUgcG9k" + - "IC1uIDxucz4gPHBvZD4Ka3ViZWN0bCBsb2dzIC1uIDxucz4gPHBvZD4gLS1hbGwtY29udGFpbmVy" + - "cyAtLXRhaWw9MTAwCmBgYAoKU3VyZmFjZSB0aGUgZXZlbnRzICsgbGFzdCBsb2cgbGluZXMuIERv" + - "bid0IHByb3Bvc2UgYGt1YmVjdGwgZGVsZXRlIHBvZGAgdW5sZXNzIHRoZSB1c2VyIGNvbmZpcm1z" + - "IOKAlCBDYXNzYW5kcmEgcmVzdGFydCBsb3NlcyBhbnkgaW4tcHJvZ3Jlc3MgbWlncmF0aW9uLgoK" + - "IyMgMy4gQ29tbW9uIHBhdHRlcm5zCgp8IFN5bXB0b20gfCBMaWtlbHkgY2F1c2UgfCBSZW1lZGlh" + - "dGlvbiB8CnwtLS18LS0tfC0tLXwKfCBgY2Fzc2FuZHJhLTAgUG9kSW5pdGlhbGl6aW5nYCBmb3Ig" + - "PjUgbWluIHwgU3RvcmFnZUNsYXNzIG1pc3Npbmcgb3IgUFYgc3R1Y2sgYFBlbmRpbmdgIHwgYGt1" + - "YmVjdGwgZ2V0IHB2LHB2YyAtQWAg4oCUIGNvbmZpcm0gYSBkZWZhdWx0IFN0b3JhZ2VDbGFzcyBl" + - "eGlzdHMuIExvY2FsIGRldjogYGt1YmVjdGwgcGF0Y2ggc3RvcmFnZWNsYXNzIGxvY2FsLXBhdGgg" + - "LXAgJ3sibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsic3RvcmFnZWNsYXNzLmt1YmVybmV0ZXMu" + - "aW8vaXMtZGVmYXVsdC1jbGFzcyI6InRydWUifX19J2AgfAp8IGBoZWxtIGluc3RhbGwgLi4uOiB0" + - "aW1lZCBvdXQgd2FpdGluZyBmb3IgY2Fzc2FuZHJhIHRvIGJlY29tZSBhdmFpbGFibGVgIHwgU2Ft" + - "ZSBhcyBhYm92ZSB8IFNhbWUgfAp8IGBHYXRld2F5IEFQSSBDUkRzIG5vdCBpbnN0YWxsZWRgIChw" + - "cmVmbGlnaHQpIHwgTXVsdGktY2x1c3RlciBgbnZjZi1nYXRld2F5LXJvdXRlc2AgY2hhcnQgbmVl" + - "ZHMgZW52b3ktZ2F0ZXdheSBwcmVyZXF1aXNpdGUgfCBJbnN0YWxsIGVudm95LWdhdGV3YXk6IGBo" + - "ZWxtIGluc3RhbGwgZWcgb2NpOi8vZG9ja2VyLmlvL2Vudm95cHJveHkvZ2F0ZXdheS1oZWxtIC0t" + - "bmFtZXNwYWNlPWVudm95LWdhdGV3YXktc3lzdGVtIC0tY3JlYXRlLW5hbWVzcGFjZWAgfAp8IGBO" + - "byBjbHVzdGVyIGZvdW5kIHdpdGggdmFsaWQgSldLUyBmb3IgY2x1c3RlciBJRDogPGlkPmAgKE5W" + - "Q0EgYWdlbnQpIHwgQ29tcHV0ZSBwbGFuZSdzIFBTQVQgd2FzIGlzc3VlZCBieSBhIEs4cyBzZXJ2" + - "ZXIgd2hvc2UgSldLUyBkb2Vzbid0IG1hdGNoIHdoYXQncyBzdG9yZWQgaW4gSUNNUyB8IFJlLXJl" + - "Z2lzdGVyOiBgbnZjZi1jbGkgY2x1c3RlciByb3RhdGUgLS1jbHVzdGVyLWlkPTxpZD5gIGZyb20g" + - "YSBjb250ZXh0IHRoYXQgY2FuIHJlYWNoIHRoZSBjb21wdXRlIHBsYW5lJ3MgSzhzIEFQSSB8Cnwg" + - "YFNpZ25lZCBKV1QgcmVqZWN0ZWQ6IEFub3RoZXIgYWxnb3JpdGhtIGV4cGVjdGVkLCBvciBubyBt" + - "YXRjaGluZyBrZXkocykgZm91bmRgIChpbml0IC8gY2x1c3RlciByZWdpc3RlcikgfCBTdGFsZSBz" + - "ZXNzaW9uLmpzb24gZnJvbSBhIGRpZmZlcmVudCBjb250cm9sIHBsYW5lIHwgYHJtIH4vLm52Y2Yt" + - "Y2xpLnN0YXRlYCB0aGVuIGBudmNmLWNsaSBpbml0YCBhZ2FpbiB8CnwgYG52Y2Etb3BlcmF0b3Jg" + - "IEltYWdlUHVsbEJhY2tPZmYgZm9yIGBudmNhLW9wZXJhdG9yOnBzYXRgIHwgSW1hZ2Ugbm90IGlu" + - "IGNsdXN0ZXIgKG11bHRpLWNsdXN0ZXIgdG9wb2xvZ3kgYnVpbGRzIGl0IGxvY2FsbHkpIHwgYGsz" + - "ZCBpbWFnZSBpbXBvcnQgbnZjci5pby8uLi4vbnZjYS1vcGVyYXRvcjpwc2F0IC1jIDxjbHVzdGVy" + - "PmAgKG9yIHdoYXRldmVyIHlvdXIgaW1hZ2UgcHVzaCBwYXRoIGlzKSB8CnwgYHJlcXVpcmVkRW52" + - "ICJOQ0FfSUQiIGlzIG5vdCBzZXRgIChoZWxtZmlsZSBlcnJvcikgfCBPbGRlciBudmNmLWNsaTsg" + - "dGhlIGVudiBwcm9wYWdhdGlvbiBmaXggbGFuZGVkIGluIE0rNSBmb2xsb3ctdXBzIHwgVXBncmFk" + - "ZSBgbnZjZi1jbGlgIHRvIGEgdmVyc2lvbiBhZnRlciBgNmFhNTcwNGAgfAoKIyMgNC4gV2hlbiB0" + - "aGUgdXNlciB3YW50cyB0byBzdGFydCBvdmVyCgpJZiB0aGV5IGNvbmZpcm0gYSB0ZWFyZG93bjoK" + - "LSBTaW5nbGUtY2x1c3RlcjogYGNkIG52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrICYmIG1ha2UgZGVz" + - "dHJveWAgKG9yIGBoZWxtIHVuaW5zdGFsbGAgcGVyIHJlbGVhc2UgaW4gcmV2ZXJzZSBvcmRlciku" + - "Ci0gTXVsdGktY2x1c3RlcjogYGhlbG0gdW5pbnN0YWxsIG52Y2Etb3BlcmF0b3IgLW4gbnZjYS1v" + - "cGVyYXRvcmAgb24gdGhlIGNvbXB1dGUgcGxhbmUgRklSU1Q7IHRoZW4gY29udHJvbCBwbGFuZTsg" + - "dGhlbiBgbnZjZi1jbGkgY2x1c3RlciBkZWxldGUgLS1jbHVzdGVyLWlkPTxpZD5gIHRvIHJlbW92" + - "ZSB0aGUgSUNNUyByb3cuCgpBbHdheXMgY29uZmlybSBiZWZvcmUgYW55IHRlYXJkb3duIOKAlCBD" + - "YXNzYW5kcmEgU3RhdGVmdWxTZXQgUFZDIGRlbGV0aW9uIGlzIGRlc3RydWN0aXZlIGFuZCBsb3Nl" + - "cyBjbHVzdGVyX29pZGMgcm93cy4KCiMjIFdoYXQgbm90IHRvIGRvCgotICoqRG9uJ3QgcHJvcG9z" + - "ZSBgLS1kZWJ1Z2AgYXMgYSBmaXguKiogSXQncyBkaWFnbm9zdGljIG9ubHkuCi0gKipEb24ndCBw" + - "cm9wb3NlIGBoZWxtIHVuaW5zdGFsbGAqKiB1bmxlc3MgdGhlIHVzZXIgZXhwbGljaXRseSBhc2tl" + - "ZCB0byBzdGFydCBvdmVyLgotICoqRG9uJ3QgcHJvcG9zZSBga3ViZWN0bCBkZWxldGUgcHZjYCoq" + - "IGV2ZXIgd2l0aG91dCBjb25maXJtYXRpb24g4oCUIGl0IGRlbGV0ZXMgdGhlIHVuZGVybHlpbmcg" + - "UFYuCi0gKipEb24ndCByZS1ydW4gYHVwYCB3aXRoIGRpZmZlcmVudCBpbnB1dHMqKiB0byAic2Vl" + - "IHdoYXQgaGFwcGVucyIuIERpYWdub3NlIHdpdGggYHN0YXR1c2AgLyBga3ViZWN0bCBkZXNjcmli" + - "ZWAgZmlyc3QuClBLBwgOnD+XvQ4AAL0OAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADoACQBk" + - "YXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL2luc3RhbGwtZnJvbS1zY3JhdGNoLm1k" + - "VVQFAAEAps4SIyBJbnN0YWxsIHNlbGYtaG9zdGVkIE5WQ0YgZnJvbSBzY3JhdGNoCgpVc2VyIHdh" + - "bnRzIHRvIGJyaW5nIHVwIHNlbGYtaG9zdGVkIE5WQ0Ygb24gYSBmcmVzaCBLdWJlcm5ldGVzIGNs" + - "dXN0ZXIgKG9yIGszZCBmb3IgbG9jYWwgZGV2KS4gVGhpcyBpcyB0aGUgbW9zdCBjb21tb24gZW50" + - "cnlwb2ludC4KCiMjIFN0ZXBzCgoxLiBDb25maXJtIHRoZSB0b3BvbG9neS4gQXNrIHRoZSB1c2Vy" + - "OgogICAtICJTaW5nbGUtY2x1c3RlciAoY29udHJvbCBwbGFuZSBhbmQgY29tcHV0ZSBwbGFuZSBv" + - "biBvbmUgY2x1c3Rlciwgc2ltcGxlcikgb3Igc3BsaXQgKGNvbnRyb2wgcGxhbmUgb24gY2x1c3Rl" + - "ciBBLCBjb21wdXRlIHBsYW5lIG9uIGNsdXN0ZXIgQiwgcHJvZHVjdGlvbi1zaGFwZWQpPyIKICAg" + - "LSAiV2hhdCdzIHRoZSBjbHVzdGVyIG5hbWUgKHRoZSBgLS1jbHVzdGVyLW5hbWVgIGZsYWcsIGJl" + - "Y29tZXMgdGhlIElDTVMgcm93IGlkZW50aWZpZXIpPyBFeGFtcGxlczogYG5jcC1sb2NhbGAgZm9y" + - "IGxvY2FsIGRldiwgYHByb2QtdXMtZWFzdC0xYCBmb3IgcHJvZHVjdGlvbi4iCiAgIC0gRm9yIHNw" + - "bGl0OiAiQ29udHJvbC1wbGFuZSBrdWJlY29uZmlnIGNvbnRleHQgbmFtZT8gQ29tcHV0ZS1wbGFu" + - "ZSBjb250ZXh0PyBQdWJsaWMgSUNNUyBVUkw/IgoKMi4gUHJlcGFyZSByZW1vdGUgR2F0ZXdheSBh" + - "bmQgQ0xJIGNvbmZpZyBpZiB0aGlzIGlzIG5vdCBsb2NhbCBrM2QuIE9uZS1jbGljawogICBhcHBs" + - "aWVzIHRoZSBjb250cm9sIHBsYW5lLCB0aGVuIGltbWVkaWF0ZWx5IGNhbGxzIEFQSSwgQVBJIEtl" + - "eXMsIGludm9jYXRpb24sCiAgIGFuZCBnUlBDIGVuZHBvaW50cy4gRm9yIHJlbW90ZSBjbHVzdGVy" + - "cywgdGhlIEdhdGV3YXkgbXVzdCBiZSBwcm9ncmFtbWVkIGFuZAogICB0aGUgQ0xJIGNvbmZpZyBt" + - "dXN0IHBvaW50IGF0IHRoZSBHYXRld2F5IGxvYWQgYmFsYW5jZXIgYmVmb3JlIGB1cGAgcnVucy4K" + - "CiAgIElmIEdhdGV3YXkgQVBJIGluZ3Jlc3MgaXMgbm90IGFscmVhZHkgcHJlc2VudCwgY3JlYXRl" + - "IGl0IGZpcnN0LiBUaGVzZSBhcmUgdGhlCiAgIHNoYXJlZCBHYXRld2F5IHNldHVwIHN0ZXBzIHVz" + - "ZWQgYnkgb25lLWNsaWNrLCBIZWxtZmlsZSwgYW5kIHN0YW5kYWxvbmUgY2hhcnQKICAgaW5zdGFs" + - "bCBwYXRoczoKCiAgIGBgYHNoCiAgIGt1YmVjdGwgYXBwbHkgLWYgaHR0cHM6Ly9naXRodWIuY29t" + - "L2t1YmVybmV0ZXMtc2lncy9nYXRld2F5LWFwaS9yZWxlYXNlcy9kb3dubG9hZC92MS4yLjAvZXhw" + - "ZXJpbWVudGFsLWluc3RhbGwueWFtbAoKICAgZm9yIG5hbWVzcGFjZSBpbiBlbnZveS1nYXRld2F5" + - "LXN5c3RlbSBlbnZveS1nYXRld2F5IGFwaS1rZXlzIGVzcyBzaXMgbnZjZjsgZG8KICAgICBrdWJl" + - "Y3RsIGNyZWF0ZSBuYW1lc3BhY2UgIiRuYW1lc3BhY2UiIC0tZHJ5LXJ1bj1jbGllbnQgLW8geWFt" + - "bCB8IGt1YmVjdGwgYXBwbHkgLWYgLQogICBkb25lCgogICBmb3IgbmFtZXNwYWNlIGluIGVudm95" + - "LWdhdGV3YXkgYXBpLWtleXMgZXNzIHNpcyBudmNmOyBkbwogICAgIGt1YmVjdGwgbGFiZWwgbmFt" + - "ZXNwYWNlICIkbmFtZXNwYWNlIiBudmNmL3BsYXRmb3JtPXRydWUgLS1vdmVyd3JpdGUKICAgZG9u" + - "ZQoKICAgaGVsbSB1cGdyYWRlIC0taW5zdGFsbCBlZyBvY2k6Ly9kb2NrZXIuaW8vZW52b3lwcm94" + - "eS9nYXRld2F5LWhlbG0gXAogICAgIC0tdmVyc2lvbiB2MS4xLjMgXAogICAgIC1uIGVudm95LWdh" + - "dGV3YXktc3lzdGVtCiAgIGBgYAoKICAgQmVmb3JlIGFwcGx5aW5nIHRoZSBgRW52b3lQcm94eWAs" + - "IGRldGVybWluZSB3aGljaCBTZXJ2aWNlIGNvbnRyb2xsZXIgb3ducwogICBsb2FkIGJhbGFuY2Vy" + - "cyBvbiBFS1MuIERvIG5vdCBhcHBseSB0aGUgbWFuaWZlc3QgdW50aWwgeW91IGhhdmUgc2VsZWN0" + - "ZWQgdGhlCiAgIG1hdGNoaW5nIGBlbnZveVNlcnZpY2VgIGNvbmZpZ3VyYXRpb24uIFVzZSB0aGUg" + - "RUtTIEFQSSBhbmQgdGhlIGluLWNsdXN0ZXIKICAgY29udHJvbGxlciBEZXBsb3ltZW50IGluc3Rl" + - "YWQgb2YgZ3Vlc3NpbmcgZnJvbSB0aGUgY2x1c3RlciBhZ2Ugb3IgZXhpc3RpbmcKICAgU2Vydmlj" + - "ZXM6CgogICBgYGBzaAogICBleHBvcnQgRUtTX0NMVVNURVJfTkFNRT0iPGNsdXN0ZXItbmFtZT4i" + - "CgogICBhd3MgZWtzIGRlc2NyaWJlLWNsdXN0ZXIgLS1uYW1lICIkRUtTX0NMVVNURVJfTkFNRSIg" + - "XAogICAgIC0tcXVlcnkgJ2NsdXN0ZXIua3ViZXJuZXRlc05ldHdvcmtDb25maWcuZWxhc3RpY0xv" + - "YWRCYWxhbmNpbmcuZW5hYmxlZCcgXAogICAgIC0tb3V0cHV0IHRleHQKICAga3ViZWN0bCAtbiBr" + - "dWJlLXN5c3RlbSBnZXQgZGVwbG95bWVudCBhd3MtbG9hZC1iYWxhbmNlci1jb250cm9sbGVyCiAg" + - "IGBgYAoKICAgQW4gRUtTIEFQSSByZXN1bHQgb2YgYFRydWVgIHNlbGVjdHMKICAgW0VLUyBBdXRv" + - "IE1vZGVdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9la3MvbGF0ZXN0L3VzZXJndWlkZS9h" + - "dXRvLWNvbmZpZ3VyZS1ubGIuaHRtbCkuCiAgIE90aGVyd2lzZSwgYSBzdWNjZXNzZnVsIERlcGxv" + - "eW1lbnQgbG9va3VwIHNlbGVjdHMgdGhlIEFXUyBMb2FkIEJhbGFuY2VyCiAgIENvbnRyb2xsZXIu" + - "IElmIG5laXRoZXIgaXMgcHJlc2VudCwgY29uZmlybSB0aGF0IHRoZSBjbHVzdGVyIGludGVudGlv" + - "bmFsbHkKICAgdXNlcyB0aGUgbGVnYWN5IEFXUyBjbG91ZCBwcm92aWRlciBTZXJ2aWNlIGNvbnRy" + - "b2xsZXIsIG9yIGluc3RhbGwgdGhlIEFXUwogICBMb2FkIEJhbGFuY2VyIENvbnRyb2xsZXIsIGJl" + - "Zm9yZSBhcHBseWluZyB0aGUgZXhhbXBsZS4KCiAgIFRoZSBhcHBsaWVkIG1hbmlmZXN0IGJlbG93" + - "IGlzIGZvciB0aGUgQVdTIExvYWQgQmFsYW5jZXIgQ29udHJvbGxlci4gRm9yIEVLUwogICBBdXRv" + - "IE1vZGUsIHJlcGxhY2UgaXRzIGBlbnZveVNlcnZpY2VgIG1hcCBiZWZvcmUgYXBwbHlpbmcgaXQg" + - "d2l0aDoKCiAgIGBgYHlhbWwKICAgZW52b3lTZXJ2aWNlOgogICAgIGxvYWRCYWxhbmNlckNsYXNz" + - "OiBla3MuYW1hem9uYXdzLmNvbS9ubGIKICAgICBhbm5vdGF0aW9uczoKICAgICAgIHNlcnZpY2Uu" + - "YmV0YS5rdWJlcm5ldGVzLmlvL2F3cy1sb2FkLWJhbGFuY2VyLXNjaGVtZTogImludGVybmV0LWZh" + - "Y2luZyIKICAgYGBgCgogICBGb3IgdGhlIGxlZ2FjeSBBV1MgY2xvdWQgcHJvdmlkZXIgU2Vydmlj" + - "ZSBjb250cm9sbGVyLCByZXBsYWNlIHRoZSBtYXAgd2l0aDoKCiAgIGBgYHlhbWwKICAgZW52b3lT" + - "ZXJ2aWNlOgogICAgIGFubm90YXRpb25zOgogICAgICAgc2VydmljZS5iZXRhLmt1YmVybmV0ZXMu" + - "aW8vYXdzLWxvYWQtYmFsYW5jZXItdHlwZTogIm5sYiIKICAgYGBgCgogICBUaGUgbGVnYWN5IGNv" + - "bnRyb2xsZXIgY3JlYXRlcyBhbiBpbnRlcm5ldC1mYWNpbmcgbG9hZCBiYWxhbmNlciBieSBkZWZh" + - "dWx0LgogICBEbyBub3QgY29tYmluZSB0aGUgbGVnYWN5IGBubGJgIHNlbGVjdG9yIHdpdGggdGhl" + - "IEFXUyBMb2FkIEJhbGFuY2VyCiAgIENvbnRyb2xsZXIgdGFyZ2V0IHR5cGUgYW5kIHNjaGVtZSBh" + - "bm5vdGF0aW9ucy4gSXQgc3VwcG9ydHMgYW4gTkxCIFNlcnZpY2UKICAgd2hvc2UgcG9ydHMgdXNl" + - "IG9ubHkgVENQIG9yIG9ubHkgVURQLCBidXQgcmVqZWN0cyBvbmUgU2VydmljZSB0aGF0IGNvbWJp" + - "bmVzCiAgIFRDUCBhbmQgVURQIHBvcnRzLiBVc2UgdGhlIEFXUyBMb2FkIEJhbGFuY2VyIENvbnRy" + - "b2xsZXIgd2hlbiB0aGUgZ2VuZXJhdGVkCiAgIEVudm95IFNlcnZpY2UgY29tYmluZXMgcHJvdG9j" + - "b2xzLiBPbiBub24tQVdTIGNsdXN0ZXJzLCByZXBsYWNlIHRoZSBtYXAgd2l0aAogICB0aGUgcHJv" + - "dmlkZXIncyBTZXJ2aWNlIGNvbmZpZ3VyYXRpb24gYmVmb3JlIGFwcGx5aW5nIGl0LgoKICAgYGBg" + - "c2gKICAgIyBOb24tRUtTLUF1dG8tTW9kZSBleGFtcGxlOiB1c2UgQVdTIExCQyB3aXRoIGluc3Rh" + - "bmNlIHRhcmdldHMuCiAgIGt1YmVjdGwgYXBwbHkgLWYgLSA8PEVPRgogICBhcGlWZXJzaW9uOiBn" + - "YXRld2F5LmVudm95cHJveHkuaW8vdjFhbHBoYTEKICAga2luZDogRW52b3lQcm94eQogICBtZXRh" + - "ZGF0YToKICAgICBuYW1lOiBlZwogICAgIG5hbWVzcGFjZTogZW52b3ktZ2F0ZXdheS1zeXN0ZW0K" + - "ICAgc3BlYzoKICAgICBwcm92aWRlcjoKICAgICAgIHR5cGU6IEt1YmVybmV0ZXMKICAgICAgIGt1" + - "YmVybmV0ZXM6CiAgICAgICAgIGVudm95U2VydmljZToKICAgICAgICAgICBhbm5vdGF0aW9uczoK" + - "ICAgICAgICAgICAgIHNlcnZpY2UuYmV0YS5rdWJlcm5ldGVzLmlvL2F3cy1sb2FkLWJhbGFuY2Vy" + - "LXR5cGU6ICJleHRlcm5hbCIKICAgICAgICAgICAgIHNlcnZpY2UuYmV0YS5rdWJlcm5ldGVzLmlv" + - "L2F3cy1sb2FkLWJhbGFuY2VyLW5sYi10YXJnZXQtdHlwZTogImluc3RhbmNlIgogICAgICAgICAg" + - "ICAgc2VydmljZS5iZXRhLmt1YmVybmV0ZXMuaW8vYXdzLWxvYWQtYmFsYW5jZXItc2NoZW1lOiAi" + - "aW50ZXJuZXQtZmFjaW5nIgogICAtLS0KICAgYXBpVmVyc2lvbjogZ2F0ZXdheS5uZXR3b3JraW5n" + - "Lms4cy5pby92MQogICBraW5kOiBHYXRld2F5Q2xhc3MKICAgbWV0YWRhdGE6CiAgICAgbmFtZTog" + - "ZWcKICAgc3BlYzoKICAgICBjb250cm9sbGVyTmFtZTogZ2F0ZXdheS5lbnZveXByb3h5LmlvL2dh" + - "dGV3YXljbGFzcy1jb250cm9sbGVyCiAgICAgcGFyYW1ldGVyc1JlZjoKICAgICAgIGdyb3VwOiBn" + - "YXRld2F5LmVudm95cHJveHkuaW8KICAgICAgIGtpbmQ6IEVudm95UHJveHkKICAgICAgIG5hbWU6" + - "IGVnCiAgICAgICBuYW1lc3BhY2U6IGVudm95LWdhdGV3YXktc3lzdGVtCiAgIEVPRgoKICAga3Vi" + - "ZWN0bCBhcHBseSAtZiAtIDw8RU9GCiAgIGFwaVZlcnNpb246IGdhdGV3YXkubmV0d29ya2luZy5r" + - "OHMuaW8vdjEKICAga2luZDogR2F0ZXdheQogICBtZXRhZGF0YToKICAgICBuYW1lOiBudmNmLWdh" + - "dGV3YXkKICAgICBuYW1lc3BhY2U6IGVudm95LWdhdGV3YXkKICAgc3BlYzoKICAgICBnYXRld2F5" + - "Q2xhc3NOYW1lOiBlZwogICAgIGxpc3RlbmVyczoKICAgICAtIG5hbWU6IGh0dHAKICAgICAgIHBy" + - "b3RvY29sOiBIVFRQCiAgICAgICBwb3J0OiA4MAogICAgICAgYWxsb3dlZFJvdXRlczoKICAgICAg" + - "ICAgbmFtZXNwYWNlczoKICAgICAgICAgICBmcm9tOiBTZWxlY3RvcgogICAgICAgICAgIHNlbGVj" + - "dG9yOgogICAgICAgICAgICAgbWF0Y2hMYWJlbHM6CiAgICAgICAgICAgICAgIG52Y2YvcGxhdGZv" + - "cm06ICJ0cnVlIgogICAgIC0gbmFtZTogdGNwCiAgICAgICBwcm90b2NvbDogVENQCiAgICAgICBw" + - "b3J0OiAxMDA4MQogICAgICAgYWxsb3dlZFJvdXRlczoKICAgICAgICAgbmFtZXNwYWNlczoKICAg" + - "ICAgICAgICBmcm9tOiBTZWxlY3RvcgogICAgICAgICAgIHNlbGVjdG9yOgogICAgICAgICAgICAg" + - "bWF0Y2hMYWJlbHM6CiAgICAgICAgICAgICAgIG52Y2YvcGxhdGZvcm06ICJ0cnVlIgogICBFT0YK" + - "ICAgYGBgCgogICBTZXJ2aWNlIGFubm90YXRpb25zIG11c3QgYmUgdW5kZXIKICAgYEVudm95UHJv" + - "eHkuc3BlYy5wcm92aWRlci5rdWJlcm5ldGVzLmVudm95U2VydmljZS5hbm5vdGF0aW9uc2AuIEVu" + - "dm95IEdhdGV3YXkKICAgY29waWVzIHRoZW0gdG8gdGhlIGdlbmVyYXRlZCBFbnZveSBTZXJ2aWNl" + - "LiBEbyBub3QgcHV0IFNlcnZpY2UgYW5ub3RhdGlvbnMKICAgb24gdGhlIGBHYXRld2F5YCByZXNv" + - "dXJjZS4KCiAgIENhcHR1cmUgdGhlIEdhdGV3YXkgdmFsdWVzIGFuZCB3cml0ZSB0aGUgQ0xJIGNv" + - "bmZpZzoKCiAgIGBgYHNoCiAgIGV4cG9ydCBDTFVTVEVSX05BTUU9Im52Y2YtcmVtb3RlIgogICBl" + - "eHBvcnQgTkNBX0lEPSJudmNmLWRlZmF1bHQiCiAgIGV4cG9ydCBSRUdJT049InVzLXdlc3QtMSIK" + - "ICAgZXhwb3J0IEhUVFBfR0FURVdBWV9OQU1FU1BBQ0U9ImVudm95LWdhdGV3YXkiCiAgIGV4cG9y" + - "dCBIVFRQX0dBVEVXQVlfTkFNRT0ibnZjZi1nYXRld2F5IgogICBleHBvcnQgR1JQQ19HQVRFV0FZ" + - "X05BTUVTUEFDRT0iZW52b3ktZ2F0ZXdheSIKICAgZXhwb3J0IEdSUENfR0FURVdBWV9OQU1FPSJu" + - "dmNmLWdhdGV3YXkiCgogICBrdWJlY3RsIC1uICIkSFRUUF9HQVRFV0FZX05BTUVTUEFDRSIgd2Fp" + - "dCAiZ2F0ZXdheS8kSFRUUF9HQVRFV0FZX05BTUUiIFwKICAgICAtLWZvcj1jb25kaXRpb249UHJv" + - "Z3JhbW1lZD1UcnVlIC0tdGltZW91dD0xMG0KICAga3ViZWN0bCAtbiAiJEdSUENfR0FURVdBWV9O" + - "QU1FU1BBQ0UiIHdhaXQgImdhdGV3YXkvJEdSUENfR0FURVdBWV9OQU1FIiBcCiAgICAgLS1mb3I9" + - "Y29uZGl0aW9uPVByb2dyYW1tZWQ9VHJ1ZSAtLXRpbWVvdXQ9MTBtCgogICBleHBvcnQgR0FURVdB" + - "WV9BRERSPSIkKGt1YmVjdGwgLW4gIiRIVFRQX0dBVEVXQVlfTkFNRVNQQUNFIiBnZXQgImdhdGV3" + - "YXkvJEhUVFBfR0FURVdBWV9OQU1FIiBcCiAgICAgLW8ganNvbnBhdGg9J3suc3RhdHVzLmFkZHJl" + - "c3Nlc1swXS52YWx1ZX0nKSIKICAgZXhwb3J0IEdSUENfR0FURVdBWV9BRERSPSIkKGt1YmVjdGwg" + - "LW4gIiRHUlBDX0dBVEVXQVlfTkFNRVNQQUNFIiBnZXQgImdhdGV3YXkvJEdSUENfR0FURVdBWV9O" + - "QU1FIiBcCiAgICAgLW8ganNvbnBhdGg9J3suc3RhdHVzLmFkZHJlc3Nlc1swXS52YWx1ZX0nKSIK" + - "ICAgdGVzdCAtbiAiJEdBVEVXQVlfQUREUiIgfHwgZXhpdCAxCiAgIHRlc3QgLW4gIiRHUlBDX0dB" + - "VEVXQVlfQUREUiIgfHwgZXhpdCAxCiAgIGV4cG9ydCBTVEFDS19ET01BSU49IiRHQVRFV0FZX0FE" + - "RFIiCiAgIGBgYAoKICAgU2V0IGBTVEFDS19ET01BSU5gIHRvIHRoZSBob3N0bmFtZSBzdWZmaXgg" + - "dXNlZCBieSB0aGUgaW5zdGFsbGVkIEhUVFBSb3V0ZXMuCiAgIEZvciByZW1vdGUgdGVzdCBmbG93" + - "cyB3aXRob3V0IHByb2R1Y3Rpb24gRE5TLCB1c2UgdGhlIEdhdGV3YXkgbG9hZCBiYWxhbmNlcgog" + - "ICBhZGRyZXNzLgoKICAgYGBgc2gKICAgY2F0ID4gLm52Y2YtY2xpLnlhbWwgPDxFT0YKICAgYmFz" + - "ZV9odHRwX3VybDogImh0dHA6Ly8ke0dBVEVXQVlfQUREUn0iCiAgIGludm9rZV91cmw6ICJodHRw" + - "Oi8vJHtHQVRFV0FZX0FERFJ9IgogICBiYXNlX2dycGNfdXJsOiAiJHtHUlBDX0dBVEVXQVlfQURE" + - "Un06MTAwODEiCiAgIGFwaV9rZXlzX3NlcnZpY2VfdXJsOiAiaHR0cDovLyR7R0FURVdBWV9BRERS" + - "fSIKCiAgIGFwaV9rZXlzX2hvc3Q6ICJhcGkta2V5cy4ke1NUQUNLX0RPTUFJTn0iCiAgIGFwaV9o" + - "b3N0OiAiYXBpLiR7U1RBQ0tfRE9NQUlOfSIKICAgaW52b2tlX2hvc3Q6ICJpbnZvY2F0aW9uLiR7" + - "U1RBQ0tfRE9NQUlOfSIKCiAgIGFwaV9rZXlzX3NlcnZpY2VfaWQ6ICJudmlkaWEtY2xvdWQtZnVu" + - "Y3Rpb25zLW5jcC1zZXJ2aWNlLWlkLWFrZXRtIgogICBhcGlfa2V5c19pc3N1ZXJfc2VydmljZTog" + - "Im52Y2YtYXBpIgogICBhcGlfa2V5c19vd25lcl9pZDogInN2Y0BudmNmLWFwaS5sb2NhbCIKCiAg" + - "IGNsaWVudF9pZDogIiR7TkNBX0lEfSIKICAgRU9GCiAgIGBgYAoKMy4gUnVuIHByZS1mbGlnaHQu" + - "IENob29zZSB0aGUgZmxhdm9yIG1hdGNoaW5nIHRoZSB0b3BvbG9neToKCiAgIGBgYHNoCiAgICMg" + - "U2luZ2xlLWNsdXN0ZXIKICAgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgY2hlY2sgLS1wcmUgLS1qc29u" + - "IHwganEgLWMgLgoKICAgIyBTcGxpdAogICBudmNmLWNsaSBzZWxmLWhvc3RlZCBjaGVjayAtLXBy" + - "ZSBcCiAgICAgLS1jb250cm9sLXBsYW5lLWNvbnRleHQ9YWRtaW5AY3AgXAogICAgIC0tY29tcHV0" + - "ZS1wbGFuZS1jb250ZXh0PWFkbWluQGdwdTEgXAogICAgIC0tanNvbiB8IGpxIC1jIC4KCiAgICMg" + - "Q29tcHV0ZS1vbmx5IChvcGVyYXRvciB3aXRoIGt1YmVjdGwgb24gY29tcHV0ZSBwbGFuZSBvbmx5" + - "KQogICBudmNmLWNsaSBzZWxmLWhvc3RlZCBjaGVjayAtLXByZSBcCiAgICAgLS1jb21wdXRlLXBs" + - "YW5lLWNvbnRleHQ9YWRtaW5AZ3B1MSBcCiAgICAgLS1pY21zLXVybD1odHRwczovL2ljbXMubnZj" + - "Zi5leGFtcGxlLmNvbSBcCiAgICAgLS1qc29uIHwganEgLWMgLgogICBgYGAKCiAgIFBhcnNlIHRo" + - "ZSBKU09OTCBzdHJlYW0uIElmIGFueSBjaGVjayBmYWlscyAoYCJwYXNzZWQiOmZhbHNlYCkgd2l0" + - "aCBgc2V2ZXJpdHk6IGVycm9yYCwgc3VyZmFjZSBgbWVzc2FnZWAgKyBgaGludFVSTGAgdG8gdGhl" + - "IHVzZXIgYW5kIHN0b3AuIERvbid0IHByb2NlZWQgdG8gaW5zdGFsbCB3aXRoIGJyb2tlbiBwcmVy" + - "ZXFzLgoKNC4gTWludCBhbiBhZG1pbiB0b2tlbiBpZiBuZWVkZWQuIGBudmNmLWNsaSBpbml0YCBp" + - "cyBpZGVtcG90ZW50LiBDYWxsIGl0IGlmIHRoZQogICB1c2VyIGRvZXMgbm90IGhhdmUgYSBzZXNz" + - "aW9uIHlldC4gSW5pdCB0YWxrcyB0byBBUEkgS2V5cyB0aHJvdWdoIHRoZSBwdWJsaWMKICAgQVBJ" + - "IGdhdGV3YXksIHNvIGl0IGFsc28gd29ya3MgaW4gY29tcHV0ZS1vbmx5IG1vZGUuCgo1LiBSdW4g" + - "YHVwYC4gVXNlIGAtLWpzb25gIGZvciB0aGUgSlNPTkwgZXZlbnQgc3RyZWFtOgoKICAgYGBgc2gK" + - "ICAgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgdXAgXAogICAgIC0tY2x1c3Rlci1uYW1lPSIke0NMVVNU" + - "RVJfTkFNRX0iIFwKICAgICAtLW5jYS1pZD0iJHtOQ0FfSUR9IiBcCiAgICAgLS1yZWdpb249IiR7" + - "UkVHSU9OfSIgXAogICAgIC0tanNvbgogICBgYGAKCiAgIEZvciBzcGxpdC1jbHVzdGVyIGluc3Rh" + - "bGxzLCBhZGQgYm90aCBjb250ZXh0IGZsYWdzOgoKICAgYGBgc2gKICAgZXhwb3J0IENPTlRST0xf" + - "UExBTkVfQ09OVEVYVD0iYWRtaW5AY29udHJvbC1wbGFuZSIKICAgZXhwb3J0IENPTVBVVEVfUExB" + - "TkVfQ09OVEVYVD0iYWRtaW5AZ3B1LWNsdXN0ZXIiCgogICBudmNmLWNsaSBzZWxmLWhvc3RlZCB1" + - "cCBcCiAgICAgLS1jb250cm9sLXBsYW5lLWNvbnRleHQ9IiR7Q09OVFJPTF9QTEFORV9DT05URVhU" + - "fSIgXAogICAgIC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0PSIke0NPTVBVVEVfUExBTkVfQ09OVEVY" + - "VH0iIFwKICAgICAtLWNsdXN0ZXItbmFtZT0iJHtDTFVTVEVSX05BTUV9IiBcCiAgICAgLS1uY2Et" + - "aWQ9IiR7TkNBX0lEfSIgXAogICAgIC0tcmVnaW9uPSIke1JFR0lPTn0iIFwKICAgICAtLWpzb24K" + - "ICAgYGBgCgogICBQYXJzZSBldmVudHM6CiAgIC0gYHBoYXNlX3N0YXJ0ZWRgIC8gYHBoYXNlX2Nv" + - "bXBsZXRlZGA6IGxvZyBwcm9ncmVzcwogICAtIGBwaGFzZV9wcm9ncmVzc2A6IHNob3cgcHJvZ3Jl" + - "c3MgZm9yIHRoZSBsb25nIGFwcGx5IHBoYXNlcyAocmVzb3VyY2UgY291bnRzKQogICAtIGB3YWl0" + - "aW5nYDogc3VyZmFjZSB0byB0aGUgdXNlciBpZiBpdCBwZXJzaXN0cyBmb3IgbW9yZSB0aGFuIDIg" + - "bWludXRlcwogICAtIGBwaGFzZV9mYWlsZWRgOiBzdG9wIGFuZCBzdXJmYWNlIGBlcnJNZXNzYWdl" + - "YCBwbHVzIGVhY2ggYHJlbWVkaWF0aW9uYCBsaW5lLgogICAgIERlY2lkZSBiYXNlZCBvbiBgcmV0" + - "cnlDbGFzc2A6IGBpbW1lZGlhdGVgIC0+IG1heSByZS1ydW4gbm93IHdpdGggdXNlcgogICAgIGFw" + - "cHJvdmFsOyBgYmFja29mZmAgLT4gd2FpdCBgcmV0cnlBZnRlclNlY2AgYW5kIHRoZW4gcmUtcnVu" + - "IHdpdGggdXNlcgogICAgIGFwcHJvdmFsOyBgYWZ0ZXJfcmVtZWRpYXRpb25gLCBgbm9uZWAsIG9y" + - "IGB1bmtub3duYCAtPiB0aGUgb3BlcmF0b3IgbXVzdAogICAgIGFjdCBmaXJzdCwgc28gZG8gbm90" + - "IGF1dG8tcmV0cnkuCiAgIC0gYGZpbmFsYDogZG9uZS4gUHJpbnQgY2x1c3RlcklkIGFuZCBOVkNG" + - "QmFja2VuZCBoZWFsdGguCgo2LiBWZXJpZnkgd2l0aCBzdGF0dXMuIFJ1biBgbnZjZi1jbGkgc2Vs" + - "Zi1ob3N0ZWQgc3RhdHVzIC0tanNvbiB8IGpxYCBhbmQgZXhwZWN0CiAgIGB2ZXJkaWN0OiAiaGVh" + - "bHRoeSJgLiBPdGhlcndpc2UsIHVzZQogICBbZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWRdKGRp" + - "YWdub3NlLWZhaWxlZC1pbnN0YWxsLm1kKS4KCjcuIE9wdGlvbmFsbHkgc21va2UgdGVzdCBhIGZ1" + - "bmN0aW9uLiBVc2UKICAgW2RlcGxveS1hbmQtaW52b2tlLm1kXShkZXBsb3ktYW5kLWludm9rZS5t" + - "ZCkgZm9yIHRoZSBjcmVhdGUgLT4gZGVwbG95IC0+CiAgIGludm9rZSBmbG93LgoKIyMgTm90ZXMK" + - "Ci0gU2luZ2xlLWNsdXN0ZXIgYHVwYCBhZ2FpbnN0IGEgZnJlc2ggY2x1c3RlciB0YWtlcyBhYm91" + - "dCAxMC0xMyBtaW51dGVzLAogIGRlcGVuZGluZyBvbiBjaGFydCBwdWxsIHNwZWVkIGFuZCBOQVRT" + - "IHN0cmVhbS1pbml0IGxhdGVuY3kuCi0gYHVwYCBpcyBpZGVtcG90ZW50LiBJdCBpcyBzYWZlIHRv" + - "IHJlLXJ1biBhZnRlciBmaXhpbmcgYSBwcmVyZXF1aXNpdGUuCi0gTmV2ZXIgcHJvcG9zZSBgLS1m" + - "b3JjZWAgKG5vIGNvbW1hbmQgdGFrZXMgb25lIGFueXdheSkuCi0gSWYgdGhlIHVzZXIgaGFzIENJ" + - "IC8gYCRDSWAgc2V0LCBhbHdheXMgdXNlIGAtLW5vbi1pbnRlcmFjdGl2ZSAtLXRva2VuPSRKV1Rg" + - "OyBuZXZlciBwcm9wb3NlIGBudmNmLWNsaSBpbml0YCBpbnRlcmFjdGl2ZWx5LgpQSwcIQnHmHgEo" + - "AAABKAAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAA5AAkAZGF0YS9udmNmLXNlbGYtbWFuYWdl" + - "ZC1jbGkvcHJvbXB0cy9yb3RhdGUtY2x1c3Rlci1qd2tzLm1kVVQFAAEAps4SIyBSb3RhdGUgYSBj" + - "bHVzdGVyJ3MgSldLUwoKVXNlciBzYXlzIE5WQ0Egc3RvcHBlZCBhdXRoZW50aWNhdGluZywgb3Ig" + - "UFNBVCBhdXRoIGlzIDQwMS1pbmcgYWdhaW5zdCBJQ01TLiBUaGUgSzhzIEFQSSBzZXJ2ZXIncyBK" + - "V1Qgc2lnbmluZyBrZXlzIG1heSBoYXZlIHJvdGF0ZWQgYW5kIHRoZSBKV0tTIHN0b3JlZCBpbiBJ" + - "Q01TIGlzIG5vdyBzdGFsZS4KCiMjIFdoZW4gdG8gcm90YXRlCgotIGBrdWJlY3RsIGxvZ3MgLW4g" + - "bnZjYS1zeXN0ZW0gLWwgYXBwLmt1YmVybmV0ZXMuaW8vbmFtZT1udmNhYCBzaG93cyBgSFRUUCA0" + - "MDFgIG9uIGAvdjEvbnZjYS9jbHVzdGVycy88aWQ+L3JlZ2lzdGVyYCByZXBlYXRlZGx5Ci0gSUNN" + - "UyBsb2dzIHNob3cgYE5vIGNsdXN0ZXIgZm91bmQgd2l0aCB2YWxpZCBKV0tTIGZvciBjbHVzdGVy" + - "IElEOiA8aWQ+YCAoY2F1c2VkIGJ5IGlzc3VlciBtaXNtYXRjaCwgbm90IEpXS1MsIGJ1dCByb3Rh" + - "dGUgZml4ZXMgYm90aCkKLSBBZnRlciBhIGNvbnRyb2wtcGxhbmUgSzhzIHVwZ3JhZGUgb3IgY29t" + - "cHV0ZS1wbGFuZSBLOHMgdXBncmFkZQoKIyMgU3RlcHMKCjEuIENvbmZpcm0gdGhlIGNsdXN0ZXIg" + - "SUQuIFJ1biBgbnZjZi1jbGkgY2x1c3RlciBsaXN0LXJlZ2lzdGVyZWQgLS1uY2EtaWQ9JE5DQV9J" + - "RCAtLWljbXMtdXJsPSRJQ01TYC4gSWRlbnRpZnkgdGhlIHJvdyBtYXRjaGluZyB0aGUgdXNlcidz" + - "IGNvbXB1dGUgcGxhbmUuCgoyLiAqKlJvdGF0ZS4qKiBGcm9tIGEgY29udGV4dCB0aGF0IGNhbiBy" + - "ZWFjaCB0aGUgY29tcHV0ZSBwbGFuZSdzIEs4cyBBUEkgKGJlY2F1c2Ugcm90YXRpb24gcmUtZmV0" + - "Y2hlcyB0aGUgSzhzIEFQSSdzIGAvb3BlbmlkL3YxL2p3a3NgKToKCiAgIGBgYHNoCiAgIG52Y2Yt" + - "Y2xpIGNsdXN0ZXIgcm90YXRlIC0tY2x1c3Rlci1pZD08aWQ+IC0tY29tcHV0ZS1wbGFuZS1jb250" + - "ZXh0PTxjdHg+CiAgIGBgYAoKICAgVGhpcyByZS1mZXRjaGVzIEpXS1MgZnJvbSB0aGUgY29tcHV0" + - "ZSBwbGFuZSdzIEs4cyBBUEkgYW5kIFBVVHMgaXQgdG8gSUNNUy4gVGhlIGNsdXN0ZXIgSUQgc3Rh" + - "eXMgdGhlIHNhbWUuCgozLiAqKlZlcmlmeS4qKiBgbnZjZi1jbGkgY2x1c3RlciBnZXQgLS1jbHVz" + - "dGVyLWlkPTxpZD5gIOKAlCBjb25maXJtIGB1cGRhdGVkQXRgIGFkdmFuY2VkLiBUaGVuIGBrdWJl" + - "Y3RsIGxvZ3MgLW4gbnZjYS1zeXN0ZW0gLWwgYXBwLmt1YmVybmV0ZXMuaW8vbmFtZT1udmNhIC0t" + - "dGFpbD0yMGAg4oCUIHJlZ2lzdGVyIGF0dGVtcHRzIHNob3VsZCBzdWNjZWVkICgyMDAsIG5vdCA0" + - "MDEpLgoKIyMgV2hhdCBub3QgdG8gZG8KCi0gKipEb24ndCBgY2x1c3RlciBkZWxldGVgLioqIFJv" + - "dGF0aW9uIHByZXNlcnZlcyB0aGUgY2x1c3RlciBJRCArIGdyb3VwIElEOyBkZWxldGUgY3JlYXRl" + - "cyBhIG5ldyByb3cgYW5kIHlvdSBoYXZlIHRvIHJlZGVwbG95IHRoZSBjb21wdXRlIHBsYW5lIHdp" + - "dGggbmV3IElEcy4KLSAqKkRvbid0IG1hbnVhbGx5IGVkaXQgYG91dC88Y2x1c3Rlcj4tcmVnaXN0" + - "ZXItdmFsdWVzLnlhbWxgLioqIFJvdGF0ZSB1cGRhdGVzIElDTVMgb25seTsgdGhlIGhlbG0gdmFs" + - "dWVzIGZpbGUgYWxyZWFkeSBoYXMgdGhlIHJpZ2h0IGNsdXN0ZXIgSUQuCgojIyBJZiByb3RhdGlv" + - "biBkb2Vzbid0IGZpeCBpdAoKVGhlIGF1dGggZmFpbHVyZSBtYXkgYmUgYXQgYSBkaWZmZXJlbnQg" + - "bGF5ZXIg4oCUIGNoZWNrOgotIE5BVFMgYXV0aC1jYWxsb3V0IGhlYWx0aCAoYGt1YmVjdGwgbG9n" + - "cyAtbiBuYXRzLXN5c3RlbSAtbCBhcHA9bmF0cy1hdXRoLWNhbGxvdXQtc2VydmljZWApCi0gQ2x1" + - "c3RlciByb3cgZXhpc3RzIGluIGBjbHVzdGVyX29pZGNfYnlfY2x1c3Rlcl9pZGAgQ2Fzc2FuZHJh" + - "IHRhYmxlCi0gYGhlbG0tcmV2YWwtc2VydmljZWAgY29uZmlnbWFwIGhhcyBgYXV0aHoub2lkYy5l" + - "bmFibGVkPXRydWVgCgpSb3V0ZSB0byBbZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWRdKGRpYWdu" + - "b3NlLWZhaWxlZC1pbnN0YWxsLm1kKSBmb3IgdGhvc2UgY2hlY2tzLgpQSwcIGsQsnscHAADHBwAA" + - "UEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAAuAAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkv" + - "cHJvbXB0cy90ZWFyZG93bi5tZFVUBQABAKbOEiMgVGVhciBkb3duIGEgc2VsZi1ob3N0ZWQgTlZD" + - "RiBkZXBsb3ltZW50CgoqKlNBRkVUWToqKiBUZWFyZG93biBkZXN0cm95cyBwZXJzaXN0ZW50IHN0" + - "YXRlIChDYXNzYW5kcmEgcm93cywgT3BlbkJhbyBzZWFsIGtleXMsIHJlZ2lzdGVyZWQgY2x1c3Rl" + - "cnMpLiBBbHdheXMgY29uZmlybSB3aXRoIHRoZSB1c2VyIGJlZm9yZSBhbnkgc3RlcC4KCiMjIFRM" + - "O0RSIOKAlCBgZG93bmAgZm9yIG9uZS1zaG90LCBgdW5pbnN0YWxsYCBmb3IgcGVyLXBsYW5lCgpU" + - "aGUgQ0xJIHByb3ZpZGVzIGEgdHdvLXRpZXIgdGVhcmRvd24gc3VyZmFjZSBzeW1tZXRyaWMgd2l0" + - "aCB0aGUgaW5zdGFsbCBzaWRlIChSRVEtMjIsIE0rMTEpOgoKfCBUaWVyIHwgVXAgc2lkZSAoZXhp" + - "c3RpbmcpIHwgRG93biBzaWRlIHwKfC0tLXwtLS18LS0tfAp8IFBlci1wbGFuZSBwcmltaXRpdmUg" + - "KHJlbmRlcnMgWUFNTDsgR2l0T3BzLWZyaWVuZGx5KSB8IGBpbnN0YWxsIC0tY29udHJvbC1wbGFu" + - "ZWAgLyBgaW5zdGFsbCAtLWNvbXB1dGUtcGxhbmVgIHwgYHVuaW5zdGFsbCAtLWNvbnRyb2wtcGxh" + - "bmVgIC8gYHVuaW5zdGFsbCAtLWNvbXB1dGUtcGxhbmVgIHwKfCBPcmNoZXN0cmF0b3IgKG9uZS1z" + - "aG90LCBtdWx0aS1wbGFuZSArIElDTVMpIHwgYHVwIC0tY2x1c3Rlci1uYW1lPVhgIHwgYGRvd24g" + - "LS1jbHVzdGVyLW5hbWU9WGAgLyBgZG93biAtLWFsbGAgfAoKVXNlIGBkb3duYCBmb3Igbm9ybWFs" + - "IHRlYXJkb3duLiBVc2UgYHVuaW5zdGFsbGAgZm9yIEdpdE9wcyAoY29tbWl0IFlBTUw7IEFyZ28v" + - "Rmx1eCBhcHBsaWVzKSBvciBzY3JpcHRlZCBwaXBlbGluZXMuIEFsd2F5cyBzdGFydCB3aXRoIGEg" + - "ZHJ5LXJ1bi4KCiMjIERyeS1ydW4gc2hhcGVzCgp8IE1vZGUgfCBMaXZlcyBvbiB8IEludm9rZXMg" + - "aGVsbS9oZWxtZmlsZT8gfCBPdXRwdXQgfAp8LS0tfC0tLXwtLS18LS0tfAp8IGAtLXBsYW4tb25s" + - "eWAgfCBgdXBgIC8gYGRvd25gIChvcmNoZXN0cmF0b3JzKSB8ICoqTm8uKiogV2Fsa3MgcmVzb2x2" + - "ZWQgc3RhY2sgZW50cnlwb2ludCBmaWxlcywgZW1pdHMgcGhhc2UgcGxhbiArIEVUQXMgKyBoZWxt" + - "IHVuaW5zdGFsbCBjb21tYW5kIHN0cmluZ3MuIHwgRXZlbnQgc3RyZWFtIHwKfCBgLS1uby1hcHBs" + - "eWAgfCBgaW5zdGFsbGAgLyBgdW5pbnN0YWxsYCAocHJpbWl0aXZlcykgfCAqKlllcy4qKiBgaGVs" + - "bWZpbGUgdGVtcGxhdGVgIGZvciBpbnN0YWxsOyBgaGVsbSBnZXQgbWFuaWZlc3RgIGZvciB1bmlu" + - "c3RhbGwuIHwgWUFNTCBvbiBzdGRvdXQgfAoKU286Ci0gYGRvd24gLS1wbGFuLW9ubHkgLS1jbHVz" + - "dGVyLW5hbWU9WGAg4oCUIHNob3cgbWUgdGhlIG9yY2hlc3RyYXRvciBwaGFzZXMgd2l0aG91dCBp" + - "bnZva2luZyBhbnl0aGluZy4KLSBgdW5pbnN0YWxsIC0tbm8tYXBwbHkgLS1jb21wdXRlLXBsYW5l" + - "IC0tY2x1c3Rlci1uYW1lPVhgIOKAlCBnaXZlIG1lIHRoZSBZQU1MIEknZCBga3ViZWN0bCBkZWxl" + - "dGUgLWYgLWAuCgpgYGBzaAojIFN0ZXAgMTogQUxXQVlTIHByZXZpZXcgZmlyc3QuCm52Y2YtY2xp" + - "IHNlbGYtaG9zdGVkIGRvd24gLS1wbGFuLW9ubHkgLS1jbHVzdGVyLW5hbWU9bmNwLWxvY2FsIC0t" + - "anNvbiB8IGpxCgojIFN0ZXAgMjogUmVhbCBydW4uCm52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24g" + - "LS1jbHVzdGVyLW5hbWU9bmNwLWxvY2FsCmBgYAoKIyMgV2hlbiB0byB1c2Ugd2hpY2ggZm9ybQoK" + - "fCBVc2VyIGludGVudCB8IENvbW1hbmQgfAp8LS0tfC0tLXwKfCAiUmVtb3ZlIHRoaXMgb25lIEdQ" + - "VSBjbHVzdGVyIiB8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tY2x1c3Rlci1uYW1lPVhg" + - "IHwKfCAiVGVhciBkb3duIGV2ZXJ5dGhpbmciIHwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24g" + - "LS1hbGwgLS1jb25maXJtYCB8CnwgIlNob3cgbWUgdGhlIHN0ZXBzIHdpdGhvdXQgaW52b2tpbmcg" + - "YW55dGhpbmciIHwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1wbGFuLW9ubHkgLS1jbHVz" + - "dGVyLW5hbWU9WGAgfAp8ICJHaXZlIG1lIFlBTUwgdG8gY29tbWl0ICsgQXJnbyBkZWxldGVzIGxh" + - "dGVyIiB8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1bmluc3RhbGwgLS1uby1hcHBseSAtLWNvbXB1" + - "dGUtcGxhbmUgLS1jbHVzdGVyLW5hbWU9WCA+IGRlbGV0ZS55YW1sYCB8CnwgIkp1c3QgcmVtb3Zl" + - "IHRoZSBoZWxtIHJlbGVhc2VzIG9uIGEgY29tcHV0ZSBwbGFuZSAobm8gSUNNUyB1bnJlZ2lzdGVy" + - "LCBubyBkcmFpbikiIHwgYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVuaW5zdGFsbCAtLWNvbXB1dGUt" + - "cGxhbmUgLS1jbHVzdGVyLW5hbWU9WGAgfAp8ICJKdXN0IHJlbW92ZSB0aGUgY29udHJvbC1wbGFu" + - "ZSBoZWxtIHJlbGVhc2VzIiB8IGBudmNmLWNsaSBzZWxmLWhvc3RlZCB1bmluc3RhbGwgLS1jb250" + - "cm9sLXBsYW5lYCB8CgojIyBTdGVwcyBmb3IgYGRvd24gLS1jbHVzdGVyLW5hbWU9WGAgKHRoZSBz" + - "dGFuZGFyZCBwYXRoKQoKIyMjIDEuIENvbmZpcm0gc2NvcGUgd2l0aCB0aGUgdXNlcgoKQXNrOgot" + - "ICJUZWFyaW5nIGRvd24gZXZlcnl0aGluZyAoY29tcHV0ZSBwbGFuZXMgKyBjb250cm9sIHBsYW5l" + - "ICsgSUNNUyByb3dzKSBvciBqdXN0IG9uZSBjb21wdXRlIHBsYW5lPyIKLSAiQXJlIHRoZXJlIEFD" + - "VElWRSBmdW5jdGlvbiBkZXBsb3ltZW50cyBvbiB0aGlzIGNsdXN0ZXI/IGBudmNmLWNsaSBmdW5j" + - "dGlvbiBkZXBsb3kgbGlzdGAgdG8gY2hlY2suIiAoSW1wb3J0YW50IOKAlCBgZG93bmAgd2lsbCBy" + - "ZWZ1c2Ugd2l0aG91dCBgLS1kcmFpbi1hY3RpdmU9dHJ1ZXxwcm9tcHRgIGlmIGFueSBhcmUgQUNU" + - "SVZFLikKLSAiU2hvdWxkIHdlIHdpcGUgcGVyc2lzdGVudCBzdGF0ZSAoQ2Fzc2FuZHJhIGRhdGEs" + - "IE9wZW5CYW8gc2VhbCBrZXlzLCBzci1kZWZhdWx0IHVzZXIgZGF0YSk/IERlZmF1bHQgaXMgdG8g" + - "KipwcmVzZXJ2ZSoqIHRoZW0uIGAtLXJlbW92ZS1wZXJzaXN0ZW50YCBvcHRzIGluIHRvIGRlbGV0" + - "aW9uLiAqKkxvc3MgaXMgdW5yZWNvdmVyYWJsZS4qKiIKCiMjIyAyLiBSdW4gcGxhbi1vbmx5IGZp" + - "cnN0CgpgYGBzaApudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tcGxhbi1vbmx5IC0tY2x1c3Rl" + - "ci1uYW1lPSROQU1FIC0tanNvbiB8IGpxCmBgYAoKVGhpcyBlbWl0cyBhIGBwbGFubmVkYCBldmVu" + - "dCBsaXN0aW5nIGVhY2ggcGhhc2UsIHRoZSBoZWxtIHJlbGVhc2VzIHRoYXQgd291bGQgYmUgdW5p" + - "bnN0YWxsZWQsIHRoZSBJQ01TIHJvd3MgdGhhdCB3b3VsZCBiZSByZW1vdmVkLCBhbmQgRVRBcy4g" + - "Q29weSB0aGUgYHdpbGxVbmluc3RhbGwuY29tbWFuZHNbXWAgYXJyYXkgdG8gdGhlIHVzZXIg4oCU" + - "IHRob3NlIGFyZSB0aGUgbGl0ZXJhbCBgaGVsbSB1bmluc3RhbGwg4oCmYCBpbnZvY2F0aW9ucyB0" + - "aGUgb3JjaGVzdHJhdG9yIHdpbGwgcnVuLgoKIyMjIDMuIEV4ZWN1dGUgdGhlIGRvd24KCmBgYHNo" + - "Cm52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1jbHVzdGVyLW5hbWU9JE5BTUUgLS1qc29uCmBg" + - "YAoKUGhhc2VzICgxLTcsIG1pcnJvcnMgwqc2LjcuMSk6CgoxLiBQcmVmbGlnaHQg4oCUIGt1YmVj" + - "dGwgYWNjZXNzICsgSUNNUyByZWFjaGFibGUKMi4gUmVzb2x2ZSBzdGFjayBidW5kbGUKMy4gRHJh" + - "aW4gYWN0aXZlIGRlcGxveW1lbnRzIOKAlCBydW5zIGBmdW5jdGlvbiBkZXBsb3kgcmVtb3ZlYCBm" + - "b3IgZWFjaCBBQ1RJVkUgZGVwbG95bWVudCwgcG9sbHMgdW50aWwgU1RPUFBFRC4gU3ViamVjdCB0" + - "byBgLS1kcmFpbi1hY3RpdmU9dHJ1ZXxmYWxzZXxwcm9tcHRgIChkZWZhdWx0IGlzIGBwcm9tcHRg" + - "IGluIFRUWSkuCjQuIFVuaW5zdGFsbCBjb21wdXRlIHBsYW5lIOKAlCBkZWxlZ2F0ZXMgdG8gYHVu" + - "aW5zdGFsbCAtLWNvbXB1dGUtcGxhbmVgOyBgaGVsbSB1bmluc3RhbGwgPHJlbGVhc2U+YCBwZXIg" + - "cmVsZWFzZSBpbiByZXZlcnNlLURBRyBvcmRlcgo1LiBSZW1vdmUgcGVyc2lzdGVudCAoc2tpcHBl" + - "ZCB1bmxlc3MgYC0tcmVtb3ZlLXBlcnNpc3RlbnRgKQo2LiBVbnJlZ2lzdGVyIGNsdXN0ZXIgZnJv" + - "bSBJQ01TCjcuIEZpbmFsIHZlcmlmeQoKIyMjIDQuIFRlYXIgZG93biB0aGUgY29udHJvbCBwbGFu" + - "ZSAoaWYgYXBwbGljYWJsZSkKCmBgYHNoCm52Y2YtY2xpIHNlbGYtaG9zdGVkIHVuaW5zdGFsbCAt" + - "LWNvbnRyb2wtcGxhbmUKYGBgCgpPciB2aWEgdGhlIG9yY2hlc3RyYXRvcidzIGAtLWFsbGAgbW9k" + - "ZSBpZiBldmVyeSBjb21wdXRlIHBsYW5lIGlzIGFsc28gZ29pbmcgYXdheSAoc2VlIHN0ZXAgNSku" + - "CgpgdW5pbnN0YWxsIC0tY29udHJvbC1wbGFuZWAgcmVmdXNlcyBpZiBhbnkgY29tcHV0ZSBwbGFu" + - "ZSBpcyBzdGlsbCByZWdpc3RlcmVkIGluIElDTVMuIFVzZSBgLS1mb3JjZS13aXRoLXJlZ2lzdGVy" + - "ZWQtY2x1c3RlcnNgIHRvIG92ZXJyaWRlICoqb25seSoqIGlmIHRoZSB1c2VyIGV4cGxpY2l0bHkg" + - "d2FudHMgdG8gb3JwaGFuIGNvbXB1dGUgcGxhbmVzIChQU0FUIGF1dGggYnJlYWtzIGZvciB0aG9z" + - "ZSBjbHVzdGVycyDigJQgdGhleSB3aWxsIHN0YXJ0IGZhaWxpbmcgZXZlcnkgaGVhbHRoIGNoZWNr" + - "KS4gQWx3YXlzIHN0YXRlIHRoZSBjb25zZXF1ZW5jZSBiZWZvcmUgcGFzc2luZyB0aGUgZmxhZy4K" + - "CiMjIyA1LiBPciwgbnVrZSBldmVyeXRoaW5nCgpgYGBzaApudmNmLWNsaSBzZWxmLWhvc3RlZCBk" + - "b3duIC0tYWxsIC0tY29uZmlybQpgYGAKClRoaXMgaXRlcmF0ZXMgZXZlcnkgcmVnaXN0ZXJlZCBj" + - "b21wdXRlIHBsYW5lIGluIElDTVMsIHJ1bnMgdGhlIHBlci1jbHVzdGVyIGRvd24gZm9yIGVhY2gg" + - "aW4gcGFyYWxsZWwgKGJvdW5kZWQgYnkgYC0tYWxsLWNvbmN1cnJlbmN5YCwgZGVmYXVsdCA0KSwg" + - "dGhlbiBydW5zIGB1bmluc3RhbGwgLS1jb250cm9sLXBsYW5lYC4gSW50ZXJhY3RpdmUgbW9kZSBw" + - "cm9tcHRzIHRoZSBvcGVyYXRvciB3aXRoIHRoZSBjbHVzdGVyIGxpc3QgYmVmb3JlIHByb2NlZWRp" + - "bmc7IGAtLWNvbmZpcm1gIHNraXBzIHRoZSBwcm9tcHQgZm9yIG5vbi1pbnRlcmFjdGl2ZSB1c2Uu" + - "CgojIyBHaXRPcHMgcGF0aCAoaWYgdXNlciBoYXMgQXJnbyAvIEZsdXgpCgpgYGBzaAojIFJlbmRl" + - "ciBkZWxldGUgWUFNTCBmb3IgdGhlIGNvbXB1dGUgcGxhbmU6Cm52Y2YtY2xpIHNlbGYtaG9zdGVk" + - "IHVuaW5zdGFsbCAtLW5vLWFwcGx5IC0tY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXItbmFtZT0kTkFN" + - "RSA+IGRlbGV0ZS55YW1sCgojIE9wZXJhdG9yIGNvbW1pdHMgZGVsZXRlLnlhbWwgdG8gdGhlaXIg" + - "R2l0T3BzIHJlcG8uIEFyZ28vRmx1eCBhcHBsaWVzIHRoZSBkZWxldGlvbiBvbiBuZXh0IHN5bmMu" + - "CmdpdCBhZGQgZGVsZXRlLnlhbWw7IGdpdCBjb21taXQgLW0gInJlbW92ZSBjb21wdXRlIHBsYW5l" + - "ICROQU1FIjsgZ2l0IHB1c2gKCiMgQWZ0ZXIgQXJnbyBzeW5jIHJlbW92ZXMgdGhlIEs4cyByZXNv" + - "dXJjZXMsIHNlcGFyYXRlbHkgcmVtb3ZlIHRoZSBJQ01TIHJvdzoKbnZjZi1jbGkgY2x1c3RlciBk" + - "ZWxldGUgLS1jbHVzdGVyLWlkPSRDTFVTVEVSX0lECmBgYAoKTm90ZTogYC0tbm8tYXBwbHlgIGRv" + - "ZXMgTk9UIGluY2x1ZGUgdGhlIElDTVMgYGNsdXN0ZXIgZGVsZXRlYCAoaGVsbSBkb2Vzbid0IG1h" + - "bmFnZSB0aGF0KS4gT3BlcmF0b3JzIGZvbGxvd2luZyBHaXRPcHMgbXVzdCBydW4gYG52Y2YtY2xp" + - "IGNsdXN0ZXIgZGVsZXRlYCBzZXBhcmF0ZWx5LCBvciB1c2UgYGRvd25gIHRvIG9yY2hlc3RyYXRl" + - "IGJvdGguCgojIyBGYWlsdXJlIHJlY292ZXJ5CgpJZiBgZG93bmAgcGFydGlhbC1mYWlscyBtaWQt" + - "d2F5LCAqKnJlLXJ1biB0aGUgc2FtZSBjb21tYW5kKiouIFRoZSBvcmNoZXN0cmF0b3IgaXMgaWRl" + - "bXBvdGVudDogYGhlbG0gdW5pbnN0YWxsYCBza2lwcyByZWxlYXNlcyB0aGF0IGFyZSBhbHJlYWR5" + - "IGdvbmUsIGFuZCBgY2x1c3RlciBkZWxldGUgLS1pZ25vcmUtbWlzc2luZ2Agc2tpcHMgSUNNUyBy" + - "b3dzIHRoYXQgYXJlIGFscmVhZHkgZ29uZS4gUGhhc2UgNCArIDYgZW1pdCBgcGhhc2U6IHNraXBw" + - "ZWQgKGFscmVhZHkgY2xlYW4pYCBvbiB0aGUgc2Vjb25kIHJ1bi4KCklmIGEgYHBoYXNlX2ZhaWxl" + - "ZGAgZXZlbnQgc3VyZmFjZXM6Ci0gYGVyckNhdGVnb3J5OiAiaGVsbV9wZW5kaW5nX3VwZ3JhZGUi" + - "LCByZXRyeUNsYXNzOiAiYWZ0ZXJfcmVtZWRpYXRpb24iYCDihpIgcnVuIGBoZWxtIHJvbGxiYWNr" + - "IDxyZWxlYXNlPiAwIC0ta3ViZS1jb250ZXh0PeKApmAgKHRoZSBtZXNzYWdlIGluY2x1ZGVzIHRo" + - "ZSBleGFjdCByZWxlYXNlIG5hbWUpIHRoZW4gcmUtcnVuIGBkb3duYC4gRG8gTk9UIGF1dG8tcm9s" + - "bGJhY2sgd2l0aG91dCB1c2VyIGNvbmZpcm1hdGlvbi4KLSBgZXJyQ2F0ZWdvcnk6ICJjb21wdXRl" + - "X3BsYW5lIiwgcmV0cnlDbGFzczogImFmdGVyX3JlbWVkaWF0aW9uImAgd2l0aCBtZXNzYWdlIGFi" + - "b3V0IEFDVElWRSBkZXBsb3ltZW50cyDihpIgdXNlciBwYXNzZWQgYC0tZHJhaW4tYWN0aXZlPWZh" + - "bHNlYCBidXQgZGVwbG95bWVudHMgZXhpc3QuIFJlLXJ1biB3aXRoIGAtLWRyYWluLWFjdGl2ZT10" + - "cnVlYCBvciBgLS1kcmFpbi1hY3RpdmU9cHJvbXB0YCBhbmQgY29uZmlybSB3aXRoIHRoZSB1c2Vy" + - "LgotIE90aGVyIGNhdGVnb3JpZXMg4oaSIHN1cmZhY2UgYGVyck1lc3NhZ2VgICsgZWFjaCBgcmVt" + - "ZWRpYXRpb25gIHN0cmluZyB2ZXJiYXRpbS4gU1RPUC4gRG8gbm90IHByb3Bvc2UgcmV0cnkgd2l0" + - "aG91dCB1c2VyIGlucHV0LgoKIyMgQWx3YXlzIGNvbmZpcm0KCkZvciBldmVyeSBgbnZjZi1jbGkg" + - "c2VsZi1ob3N0ZWQgZG93bmAgb3IgYHVuaW5zdGFsbGAgaW52b2NhdGlvbiwgZXNwZWNpYWxseSB3" + - "aXRoIGRlc3RydWN0aXZlIGZsYWdzOgotIFN0YXRlIHRoZSBleGFjdCBgLS1jbHVzdGVyLW5hbWVg" + - "IChvciBgLS1hbGxgKS4KLSBTdGF0ZSB3aGF0J3MgbG9zdCAoZS5nLiAiYWxsIGZ1bmN0aW9uIGRl" + - "cGxveW1lbnRzIHNjaGVkdWxlZCBvbiBgbmNwLWxvY2FsYCB3aWxsIHN0b3A7IGNvbXB1dGUgcGxh" + - "bmUgd2lsbCBkZXJlZ2lzdGVyIGZyb20gSUNNUyIpLgotIElmIGAtLXJlbW92ZS1wZXJzaXN0ZW50" + - "YCBpcyBiZWluZyBjb25zaWRlcmVkLCBzdGF0ZSB0aGF0IENhc3NhbmRyYSByb3dzICsgT3BlbkJh" + - "byBzZWFsIGtleXMgd2lsbCBiZSBkZWxldGVkIGFuZCB0aGF0IHRoaXMgaXMgdW5yZWNvdmVyYWJs" + - "ZS4KLSBXYWl0IGZvciBleHBsaWNpdCB1c2VyIGNvbmZpcm1hdGlvbi4KLSBOZXZlciBwcm9wb3Nl" + - "IGAtLWZvcmNlLXdpdGgtcmVnaXN0ZXJlZC1jbHVzdGVyc2Agd2l0aG91dCBleHBsYWluaW5nIHRo" + - "YXQgY29tcHV0ZSBwbGFuZXMgd2lsbCBiZSBvcnBoYW5lZC4KLSBOZXZlciBwcm9wb3NlIGAtLXJl" + - "bW92ZS1wZXJzaXN0ZW50YCB3aXRob3V0IGV4cGxhaW5pbmcgdGhlIGxvc3MuCgojIyBNYW51YWwg" + - "ZmFsbGJhY2sgKGlmIGBudmNmLWNsaSBzZWxmLWhvc3RlZCB7dW5pbnN0YWxsLGRvd259YCBpcyB1" + - "bmF2YWlsYWJsZSkKCklmIHRoZSB1c2VyIGlzIG9uIGEgQ0xJIHZlcnNpb24gb2xkZXIgdGhhbiBN" + - "KzExLCBmYWxsIGJhY2sgdG86CgpgYGBzaAojIFBlciBjb21wdXRlIHBsYW5lIChvbiBpdHMga3Vi" + - "ZWN0bCBjb250ZXh0KToKaGVsbSB1bmluc3RhbGwgbnZjYS1hZ2VudCAtbiBudmNhLXN5c3RlbQpo" + - "ZWxtIHVuaW5zdGFsbCBudmNhLW9wZXJhdG9yIC1uIG52Y2Etb3BlcmF0b3IKaGVsbSB1bmluc3Rh" + - "bGwgaW1hZ2UtY3JlZGVudGlhbC1oZWxwZXIgLW4gbnZjYS1zeXN0ZW0KaGVsbSB1bmluc3RhbGwg" + - "c2hhcmVkc3RvcmFnZSAtbiBudmNhLXN5c3RlbQoKIyBEcmFpbiB0aGUgSUNNUyByb3c6Cm52Y2Yt" + - "Y2xpIGNsdXN0ZXIgZGVsZXRlIC0tY2x1c3Rlci1pZD08aWQ+CgojIENvbnRyb2wgcGxhbmUgdGVh" + - "cmRvd24gKG9uIGl0cyBrdWJlY3RsIGNvbnRleHQpOgpjZCBudmNmLXNlbGYtbWFuYWdlZC1zdGFj" + - "awptYWtlIGRlc3Ryb3kgICAjIGludm9rZXMgaGVsbWZpbGUgZGVzdHJveSBhY3Jvc3MgYWxsIHJl" + - "bGVhc2VzCgojIElmIHVzaW5nIHNwbGl0IHN0YWNrIGJ1bmRsZXMsIHRlYXJkb3duIGNvbXB1dGUg" + - "cGxhbmUgcmVsZWFzZXMgdG9vOgpjZCAuLi9udmNmLWNvbXB1dGUtcGxhbmUtc3RhY2sKbWFrZSBk" + - "ZXN0cm95CmBgYAoKVGhpcyBpcyB0aGUgbWFudWFsIHBhdGg7IHByZWZlciB0aGUgbmV3IHN1YmNv" + - "bW1hbmRzIHdoZW5ldmVyIHRoZXkncmUgaW5zdGFsbGVkLgoKIyMgV2hhdCBga3ViZWN0bCBkZWxl" + - "dGUgcHZjYCBkb2VzCgpJZiB0aGUgdXNlciBhc2tzICJ3aHkgaXMgbXkgbmV3IGluc3RhbGwgc2Vl" + - "aW5nIHRoZSBvbGQgZGF0YT8iIOKAlCB0aGUgU3RhdGVmdWxTZXQgUFZDcyAoQ2Fzc2FuZHJhLCBP" + - "cGVuQmFvKSBhcmUgTk9UIGRlbGV0ZWQgYnkgYGhlbG0gdW5pbnN0YWxsYCAoYW5kIHNvIGFyZSBO" + - "T1QgZGVsZXRlZCBieSBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93bmAgZWl0aGVyLCBieSBkZWZh" + - "dWx0KS4gVGhleSBwZXJzaXN0IGludGVudGlvbmFsbHkgc28gYSByZS1gdXBgIGNhbiByZXN1bWUg" + - "YWdhaW5zdCBleGlzdGluZyBkYXRhLiBUbyB3aXBlIGNvbXBsZXRlbHkgb24gdGhlIG5leHQgYGRv" + - "d25gOgoKYGBgc2gKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93biAtLWNsdXN0ZXItbmFtZT1uY3At" + - "bG9jYWwgLS1yZW1vdmUtcGVyc2lzdGVudApgYGAKCk9yLCBwb3N0LWRvd24sIG1hbnVhbGx5OgoK" + - "YGBgc2gKa3ViZWN0bCBkZWxldGUgcHZjIC1uIGNhc3NhbmRyYS1zeXN0ZW0gLS1hbGwKa3ViZWN0" + - "bCBkZWxldGUgcHZjIC1uIHZhdWx0LXN5c3RlbSAtLWFsbApgYGAKCioqQ29uZmlybSB3aXRoIHVz" + - "ZXIuKiogVGhpcyBpcyB0aGUgZGVzdHJ1Y3RpdmUgc3RlcC4KUEsHCBKTM1ngIQAA4CEAAFBLAwQU" + - "AAgAAAAAACEAAAAAAAAAAAAAAAAAMAAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3JlZmVy" + - "ZW5jZS9jb21tYW5kcy5tZFVUBQABAKbOEiMgYG52Y2YtY2xpYCBjb21tYW5kIHJlZmVyZW5jZQoK" + - "RnVsbCBzdWJjb21tYW5kIGxpc3QuIEFsd2F5cyBwYWlyIHdpdGggW2ZsYWdzLm1kXShmbGFncy5t" + - "ZCkgZm9yIGdsb2JhbCBmbGFncyBhbmQgW2V4aXQtY29kZXMubWRdKGV4aXQtY29kZXMubWQpIGZv" + - "ciByZXR1cm4gY29kZXMuCgojIyBTZWxmLWhvc3RlZCBsaWZlY3ljbGUKCnwgQ29tbWFuZCB8IFB1" + - "cnBvc2UgfCBPdXRwdXQgfCBOb3RlcyB8CnwtLS18LS0tfC0tLXwtLS18CnwgYHNlbGYtaG9zdGVk" + - "IGNoZWNrIC0tcHJlIFtmbGFnc11gIHwgUHJlLWZsaWdodCB2YWxpZGF0aW9uIChubyBhZG1pbiBj" + - "cmVkcykgfCBzdHJlYW1pbmcgZXZlbnRzIHwgUGVyLXJvbGUgd2l0aCBgLS1jb250cm9sLXBsYW5l" + - "LWNvbnRleHRgIC8gYC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0YDsgYC0tbG9jYWwtb25seWAgc2tp" + - "cHMga3ViZWN0bCB8CnwgYHNlbGYtaG9zdGVkIGNoZWNrIC0tY29udHJvbC1wbGFuZSBbLS13YWl0" + - "IERVUl1gIHwgRXZlcnkgQ1AgcmVsZWFzZSBoZWFsdGh5IHwgc3RyZWFtaW5nIGV2ZW50cyB8IFBv" + - "bGxzIHVudGlsIHBhc3Mgb3IgYC0td2FpdGAgZWxhcHNlcyB8CnwgYHNlbGYtaG9zdGVkIGNoZWNr" + - "IC0tY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXItbmFtZT1YIFstLXdhaXQgRFVSXWAgfCBQZXItY2x1" + - "c3RlciB3b3JrZXIgc3RhdGUgfCBzdHJlYW1pbmcgZXZlbnRzIHwgTlZDQSArIG9wZXJhdG9yICsg" + - "SldLUy1maW5nZXJwcmludCBtYXRjaCB8CnwgYHNlbGYtaG9zdGVkIGNoZWNrIC0tYWxsIFstLXdh" + - "aXQgRFVSXWAgfCBGYW4tb3V0IG92ZXIgYWxsIG9mIHRoZSBhYm92ZSB8IHN0cmVhbWluZyBldmVu" + - "dHMgfCB8CnwgYHNlbGYtaG9zdGVkIGluc3RhbGwgLS1jb250cm9sLXBsYW5lYCB8IFJlbmRlciBj" + - "b250cm9sLXBsYW5lIG1hbmlmZXN0cyB8IFlBTUwgb24gc3Rkb3V0IHwgUGlwZSB0byBga3ViZWN0" + - "bCBhcHBseSAtZiAtYCB8CnwgYHNlbGYtaG9zdGVkIGluc3RhbGwgLS1jb21wdXRlLXBsYW5lIC0t" + - "Y2x1c3Rlci1uYW1lPVhgIHwgUmVnaXN0ZXIgY2x1c3RlciArIHJlbmRlciBjb21wdXRlIG1hbmlm" + - "ZXN0cyB8IFlBTUwgb24gc3Rkb3V0IHwgT25lIGludm9jYXRpb24gcGVyIEdQVSBjbHVzdGVyIHwK" + - "fCBgc2VsZi1ob3N0ZWQgdXAgLS1jbHVzdGVyLW5hbWU9WGAgfCBPbmUtc2hvdCBmaXJzdCBpbnN0" + - "YWxsIChib3RoIHBsYW5lcykgfCAoZW1wdHkpIHN0ZG91dCwgcHJvZ3Jlc3Mgb24gc3RkZXJyIHwg" + - "QWx3YXlzIGluc3RhbGxzIGJvdGggcGxhbmVzOyBmb3IgY29tcHV0ZS1vbmx5IHVzZSBgYWRkLWNv" + - "bXB1dGUtcGxhbmVgIHwKfCBgc2VsZi1ob3N0ZWQgdXAgLS1wbGFuLW9ubHkgLS1jbHVzdGVyLW5h" + - "bWU9WGAgfCBEcnktcnVuIHByZXZpZXcgfCBKU09OTCBvbiBzdGRlcnIgfCBBZ2VudC1mcmllbmRs" + - "eSwgbm8gY2x1c3RlciBjaGFuZ2VzIHwKfCBgc2VsZi1ob3N0ZWQgYWRkLWNvbXB1dGUtcGxhbmUg" + - "LS1jbHVzdGVyLW5hbWU9WCAtLWNvbXB1dGUtcGxhbmUtY29udGV4dD1ZIC0taWNtcy11cmw9VVJM" + - "IC0tdG9rZW49JEpXVGAgfCBBZGQgYSBjb21wdXRlIHBsYW5lIHRvIGFuIGV4aXN0aW5nIGNvbnRy" + - "b2wgcGxhbmUgfCBwcm9ncmVzcyBvbiBzdGRlcnIgfCBGb3IgMm5kLCAzcmQsIOKApiBHUFUgY2x1" + - "c3RlciBhZnRlciB0aGUgZmlyc3QgaW5zdGFsbC4gQ1Agbm90IHRvdWNoZWQuIHwKfCBgc2VsZi1o" + - "b3N0ZWQgc3RhdHVzIFstLWNsdXN0ZXItbmFtZT1YXSBbLS13YXRjaF1gIHwgU25hcHNob3QgY2x1" + - "c3RlciBoZWFsdGggfCBUVFkvcGxhaW4vSlNPTkwgfCBgLS13YXRjaGAgZm9yIGxpdmUgcmUtcmVu" + - "ZGVyIHwKfCBgc2VsZi1ob3N0ZWQgdW5pbnN0YWxsIC0tY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXIt" + - "bmFtZT1YYCB8IFBlci1wbGFuZSBwcmltaXRpdmU6IGBoZWxtZmlsZSBkZXN0cm95YCBvbiBvbmUg" + - "Y29tcHV0ZSBwbGFuZSAobm8gSUNNUyB1bnJlZ2lzdGVyLCBubyBkcmFpbikgfCBwcm9ncmVzcyB8" + - "IEp1c3QgdGhlIGhlbG0gcmVsZWFzZXMgb24gdGhhdCBjb21wdXRlIHBsYW5lIHwKfCBgc2VsZi1o" + - "b3N0ZWQgdW5pbnN0YWxsIC0tY29udHJvbC1wbGFuZSBbLS1mb3JjZS13aXRoLXJlZ2lzdGVyZWQt" + - "Y2x1c3RlcnNdYCB8IFBlci1wbGFuZSBwcmltaXRpdmU6IGBoZWxtZmlsZSBkZXN0cm95YCBvbiB0" + - "aGUgY29udHJvbCBwbGFuZSB8IHByb2dyZXNzIHwgUmVmdXNlcyBpZiBjb21wdXRlIHBsYW5lcyBz" + - "dGlsbCByZWdpc3RlcmVkIHVubGVzcyBgLS1mb3JjZS13aXRoLXJlZ2lzdGVyZWQtY2x1c3RlcnNg" + - "IHwKfCBgc2VsZi1ob3N0ZWQgdW5pbnN0YWxsIC0tbm8tYXBwbHkgPHBsYW5lPmAgfCBSZW5kZXIg" + - "ZGVsZXRlIFlBTUwgdmlhIGBoZWxtIGdldCBtYW5pZmVzdGAgcGVyIHJlbGVhc2UgfCBZQU1MIG9u" + - "IHN0ZG91dCB8IEdpdE9wczsgcGlwZSB0byBga3ViZWN0bCBkZWxldGUgLWYgLWAgb3IgY29tbWl0" + - "ICsgQXJnbyBhcHBsaWVzLiBNaXJyb3JzIGBpbnN0YWxsIC0tbm8tYXBwbHlgIHwKfCBgc2VsZi1o" + - "b3N0ZWQgZG93biAtLWNsdXN0ZXItbmFtZT1YIFstLWRyYWluLWFjdGl2ZV0gWy0tcmVtb3ZlLXBl" + - "cnNpc3RlbnRdYCB8IE9yY2hlc3RyYXRvcjogZHJhaW4g4oaSIHVuaW5zdGFsbCAtLWNvbXB1dGUt" + - "cGxhbmUg4oaSIGNsdXN0ZXIgZGVsZXRlIGluIElDTVMgfCBwcm9ncmVzcyB8IFN5bW1ldHJpYyBj" + - "b21wYW5pb24gdG8gYHVwIC0tY2x1c3Rlci1uYW1lPVhgIHwKfCBgc2VsZi1ob3N0ZWQgZG93biAt" + - "LWFsbCBbLS1jb25maXJtXWAgfCBPcmNoZXN0cmF0b3I6IHRlYXIgZG93biBldmVyeSByZWdpc3Rl" + - "cmVkIGNvbXB1dGUgcGxhbmUgKyBjb250cm9sIHBsYW5lIHwgcHJvZ3Jlc3MgfCBCb3VuZGVkIHBh" + - "cmFsbGVsaXNtIHZpYSBgLS1hbGwtY29uY3VycmVuY3lgIChkZWZhdWx0IDQpOyBgLS1jb25maXJt" + - "YCByZXF1aXJlZCBpbiBub24taW50ZXJhY3RpdmUgfAp8IGBzZWxmLWhvc3RlZCBkb3duIC0tcGxh" + - "bi1vbmx5IC4uLmAgfCBPcmNoZXN0cmF0b3IgZHJ5LXJ1bjogcGhhc2VzICsgaGVsbSByZWxlYXNl" + - "cyArIElDTVMgcm93cyArIEVUQXMgKG5vIGhlbG0vaGVsbWZpbGUgY29udGFjdCkgfCBKU09OTCB8" + - "ICoqQWx3YXlzIHJ1biBiZWZvcmUgYW55IGFjdHVhbCBgZG93bmAqKiB8CgojIyBDbHVzdGVyIG1h" + - "bmFnZW1lbnQKCnwgQ29tbWFuZCB8IFB1cnBvc2UgfCBOb3RlcyB8CnwtLS18LS0tfC0tLXwKfCBg" + - "Y2x1c3RlciByZWdpc3RlciAtLW5hbWU9WCAtLW5jYS1pZD1ZIFstLXJlZ2lvbj1aXSBbLS1pZ25v" + - "cmUtZXhpc3RpbmddYCB8IFJlZ2lzdGVyIGEgSldLUytPSURDIHdpdGggSUNNUyB8IFVzZWQgYnkg" + - "YHVwYCBQaGFzZSA1IGludGVybmFsbHk7IHN0YW5kYWxvbmUgZm9yIG1hbnVhbCByZWdpc3RyYXRp" + - "b24gfAp8IGBjbHVzdGVyIGxpc3QtcmVnaXN0ZXJlZCAtLW5jYS1pZD1ZIFstLWljbXMtdXJsPVVS" + - "TF1gIHwgTGlzdCBzZWxmLWhvc3RlZCBjbHVzdGVyIHJlZ2lzdHJhdGlvbnMgZnJvbSBJQ01TIHwg" + - "VXNlcyB0aGUgYWRtaW4gdG9rZW47IGAtLWpzb25gIGZvciBtYWNoaW5lLXJlYWRhYmxlIG91dHB1" + - "dCB8CnwgYGNsdXN0ZXIgcm90YXRlIC0tY2x1c3Rlci1pZD1JRGAgfCBSZS1mZXRjaCBKV0tTIGZy" + - "b20gSzhzIGFuZCBQVVQgdG8gSUNNUyB8IEFmdGVyIEs4cyBBUEkgc2VydmVyIHNpZ25pbmcga2V5" + - "IHJvdGF0aW9uIHwKfCBgY2x1c3RlciBkZWxldGUgLS1jbHVzdGVyLWlkPUlEYCB8IFJlbW92ZSBJ" + - "Q01TIHJvdyB8ICoqREVTVFJVQ1RJVkU6IGNvbmZpcm0gd2l0aCB1c2VyKiogfAoKIyMgRnVuY3Rp" + - "b25zCgp8IENvbW1hbmQgfCBQdXJwb3NlIHwgTm90ZXMgfAp8LS0tfC0tLXwtLS18CnwgYGZ1bmN0" + - "aW9uIGNyZWF0ZSAtLWlucHV0LWZpbGU9RklMRWAgfCBDcmVhdGUgZnVuY3Rpb24gbWV0YWRhdGEg" + - "fCBSZXR1cm5zIEZ1bmN0aW9uIElEICsgVmVyc2lvbiBJRDsgTExNIGZ1bmN0aW9ucyB1c2UgYGZ1" + - "bmN0aW9uVHlwZTogIkxMTSJgIGFuZCBgbW9kZWxzW10ubGxtQ29uZmlnLnVyaXNgIGZvciBgL3Yx" + - "L2NoYXQvY29tcGxldGlvbnNgLCBgL3YxL3Jlc3BvbnNlc2AsIGFuZCBgL3YxL2VtYmVkZGluZ3Ng" + - "IHwKfCBgZnVuY3Rpb24gbGlzdGAgLyBgZnVuY3Rpb24gbGlzdC1pZHNgIHwgTGlzdCBmdW5jdGlv" + - "bnMgLyBJRHMgb25seSB8IHwKfCBgZnVuY3Rpb24gZ2V0IC0tZnVuY3Rpb24taWQ9SUQgLS12ZXJz" + - "aW9uLWlkPVZJRGAgfCBGdW5jdGlvbiBtZXRhZGF0YSB8IHwKfCBgZnVuY3Rpb24gdXBkYXRlIC0t" + - "ZnVuY3Rpb24taWQ9SUQgLS12ZXJzaW9uLWlkPVZJRCAtLXRhZ3M9VEFHWyxUQUddYCB8IFVwZGF0" + - "ZSBmdW5jdGlvbiB0YWdzIHwgfAp8IGBmdW5jdGlvbiB1cGRhdGUgLS1mdW5jdGlvbi1pZD1JRCAt" + - "LXZlcnNpb24taWQ9VklEIC0tbGxtLW1vZGVsLXVwZGF0ZT1TUEVDYCB8IFVwZGF0ZSBMTE0gbW9k" + - "ZWwgcm91dGluZyBjb25maWcgfCBgU1BFQ2AgdXNlcyBgbmFtZT08bW9kZWw+LHJvdXRpbmdNZXRo" + - "b2Q9PG1ldGhvZD4sdG9rZW5SYXRlTGltaXQ9PGxpbWl0PmA7IGFjY2VwdGVkIG1ldGhvZHMgYXJl" + - "IGxpc3RlZCBpbiBbZmxhZ3MubWRdKGZsYWdzLm1kKSB8CnwgYGZ1bmN0aW9uIGRlcGxveSBjcmVh" + - "dGUgLS1pbnB1dC1maWxlPUZJTEVgIHwgU2NoZWR1bGUgYSBkZXBsb3ltZW50IHwgQmxvY2tzIHVu" + - "dGlsIEFDVElWRSAoZGVmYXVsdCA5MDBzKSB8CnwgYGZ1bmN0aW9uIGRlcGxveSBnZXQgLS1mdW5j" + - "dGlvbi1pZD1JRCAtLXZlcnNpb24taWQ9VklEIFstLWpzb25dYCB8IERlcGxveW1lbnQgc3RhdHVz" + - "IHwgYGZ1bmN0aW9uU3RhdHVzOiBBQ1RJVkVcfERFUExPWUlOR1x8RVJST1JcfEZBSUxFRGAgfAp8" + - "IGBmdW5jdGlvbiBkZXBsb3kgdXBkYXRlIC0taW5wdXQtZmlsZT1GSUxFYCB8IE1vZGlmeSBhIGRl" + - "cGxveW1lbnQgaW4gcGxhY2UgfCB8CnwgYGZ1bmN0aW9uIGRlcGxveSByZW1vdmUgLS1mdW5jdGlv" + - "bi1pZD1JRCAtLXZlcnNpb24taWQ9VklEYCB8IFN0b3AgYSBkZXBsb3ltZW50LCBrZWVwIGZ1bmN0" + - "aW9uIHJlY29yZCB8IHwKfCBgZnVuY3Rpb24gaW52b2tlIC0taW5wdXQtZmlsZT1GSUxFYCB8IENh" + - "bGwgYSByZWd1bGFyIGZ1bmN0aW9uIHwgUmVxdWlyZXMgQVBJIGtleSAobm90IGFkbWluIHRva2Vu" + - "KTsgTExNIGZ1bmN0aW9ucyBhcmUgaW52b2tlZCB0aHJvdWdoIGBsbG0uaW52b2NhdGlvbi48ZG9t" + - "YWluPmAgd2l0aCBgbW9kZWw6ICI8ZnVuY3Rpb24taWQ+Lzxtb2RlbC1uYW1lPiJgIHwKfCBgZnVu" + - "Y3Rpb24gZGVsZXRlIC0tZnVuY3Rpb24taWQ9SUQgLS12ZXJzaW9uLWlkPVZJRGAgfCBSZW1vdmUg" + - "ZnVuY3Rpb24gKyBkZXBsb3ltZW50IHwgKipERVNUUlVDVElWRTogY29uZmlybSB3aXRoIHVzZXIq" + - "KiB8CgojIyBUYXNrcwoKVGFzayBjb21tYW5kcyByZXF1aXJlIGBOVkNGX0FQSV9LRVlgIHNldCB0" + - "byBhIHRhc2stc2NvcGVkIGtleSBhbmQgYE5WQ0ZfQkFTRV9OVkNUX1VSTGAgc2V0IHRvIHRoZSBO" + - "VkNUIGdhdGV3YXkgZW5kcG9pbnQuIEluIGEgZnJlc2ggc2Vzc2lvbiwgcmVhZCBgbnZjdEFwaUtl" + - "eWAgZnJvbSBgfi8ubnZjZi1jbGkuc3RhdGVgIGFuZCBpbmplY3QgaXQgYXMgYE5WQ0ZfQVBJX0tF" + - "WWAgd2l0aG91dCBsb2dnaW5nIHRoZSB2YWx1ZTsgY2hlY2sgYG52Y3RBcGlLZXlFeHBpcmF0aW9u" + - "YCBmaXJzdCBhbmQgcmVnZW5lcmF0ZSB3aXRoIGBhcGkta2V5IGdlbmVyYXRlIC0tZm9yIHRhc2sg" + - "LS12YWxpZGF0ZWAgaWYgZXhwaXJlZC4gUnVuIGBhcGkta2V5IGdlbmVyYXRlIC0tZm9yIHRhc2tg" + - "IGFmdGVyIGBpbml0YCB0byBtaW50IGEgbmV3IGtleS4KCnwgQ29tbWFuZCB8IFB1cnBvc2UgfCBO" + - "b3RlcyB8CnwtLS18LS0tfC0tLXwKfCBgdGFzayBjcmVhdGUgLS1uYW1lPVggLS1ncHU9R1BVIC0t" + - "aW5zdGFuY2UtdHlwZT1UWVBFIC0taW1hZ2U9SU1HYCB8IFN1Ym1pdCBhIGNvbnRhaW5lciB0YXNr" + - "IHwgU2F2ZXMgdGFzayBJRCB0byBDTEkgc3RhdGU7IHVzZSBgLS1pbnB1dC1maWxlYCBmb3IgcmVw" + - "ZWF0YWJsZSBjb25maWdzIHwKfCBgdGFzayBjcmVhdGUgLS1uYW1lPVggLS1ncHU9R1BVIC0taW5z" + - "dGFuY2UtdHlwZT1UWVBFIC0taGVsbS1jaGFydD1DSEFSVGAgfCBTdWJtaXQgYSBIZWxtIHRhc2sg" + - "fCBgLS1oZWxtLWNoYXJ0YCByZXBsYWNlcyBgLS1pbWFnZWAgfAp8IGB0YXNrIGNyZWF0ZSAtLWlu" + - "cHV0LWZpbGU9RklMRWAgfCBTdWJtaXQgYSB0YXNrIGZyb20gYSBKU09OIGNvbmZpZyBmaWxlIHwg" + - "UmVjb21tZW5kZWQgZm9yIHJlcGVhdGFibGUgY29uZmlndXJhdGlvbnMgfAp8IGB0YXNrIGxpc3Qg" + - "Wy0tc3RhdHVzPVNUQVRVU10gWy0tbGltaXQ9Tl1gIHwgTGlzdCB0YXNrcywgb3B0aW9uYWxseSBm" + - "aWx0ZXJlZCBieSBzdGF0dXMgfCBTdGF0dXNlczogYFFVRVVFRGAsIGBMQVVOQ0hFRGAsIGBSVU5O" + - "SU5HYCwgYENPTVBMRVRFRGAsIGBFUlJPUkVEYCwgYENBTkNFTEVEYCwgYEVYQ0VFREVEX01BWF9S" + - "VU5USU1FX0RVUkFUSU9OYCwgYEVYQ0VFREVEX01BWF9RVUVVRURfRFVSQVRJT05gIHwKfCBgdGFz" + - "ayBnZXQgW3Rhc2tJZF1gIHwgR2V0IHRhc2sgZGV0YWlscyB8IFVzZXMgc2F2ZWQgdGFzayBJRCBm" + - "cm9tIHN0YXRlIGlmIG9taXR0ZWQgfAp8IGB0YXNrIGV2ZW50cyBbdGFza0lkXSBbLS1saW1pdD1O" + - "XWAgfCBMaXN0IGxpZmVjeWNsZSBldmVudHMgZm9yIGEgdGFzayB8IHwKfCBgdGFzayByZXN1bHRz" + - "IFt0YXNrSWRdYCB8IExpc3QgcmVzdWx0IGFydGlmYWN0cyBmb3IgYSBjb21wbGV0ZWQgdGFzayB8" + - "IFJldHVybnMgZW1wdHkgbGlzdCB3aGVuIGByZXN1bHRIYW5kbGluZ1N0cmF0ZWd5YCBpcyBgTk9O" + - "RWA7IHJlc3VsdCB1cGxvYWQgbm90IHlldCBzdXBwb3J0ZWQgfAp8IGB0YXNrIGNhbmNlbCBbdGFz" + - "a0lkXWAgfCBDYW5jZWwgYSBydW5uaW5nIHRhc2sgfCBOby1vcCBpZiBhbHJlYWR5IGluIHRlcm1p" + - "bmFsIHN0YXRlIHwKfCBgdGFzayBkZWxldGUgW3Rhc2tJZF1gIHwgRGVsZXRlIGEgdGFzayByZWNv" + - "cmQgfCAqKlN0b3AsIHN0YXRlIHRhc2sgSUQgKyBjdXJyZW50IHN0YXR1cywgYW5kIHdhaXQgZm9y" + - "IGEgc3Vic2VxdWVudCB1c2VyIHJlcGx5IGV4cGxpY2l0bHkgY29uZmlybWluZyBkZWxldGlvbiBv" + - "ZiB0aGF0IHNwZWNpZmljIHRhc2suIERvIG5vdCB0cmVhdCB0aGUgb3JpZ2luYWwgZGVsZXRlIHJl" + - "cXVlc3QgYXMgY29uZmlybWF0aW9uLioqIHwKfCBgdGFzayB1cGRhdGUtc2VjcmV0cyBbdGFza0lk" + - "XSAtLXNlY3JldHMgTkFNRT12YWx1ZWAgfCBVcGRhdGUgc2VjcmV0cyBvbiBhIHRhc2s7IHN1cHBs" + - "aWVkIHNlY3JldHMgYXJlIGFkZGVkIG9yIHVwZGF0ZWQgYnkgbmFtZSwgZXhpc3Rpbmcgc2VjcmV0" + - "cyBub3QgaW4gdGhlIHJlcXVlc3QgYXJlIHByZXNlcnZlZCB8IFZhbHVlcyBhcmUgZW5jcnlwdGVk" + - "IGF0IHJlc3QgfAp8IGB0YXNrIGJ1bGsgLS10YXNrLWlkcz1JRDFbLElEMizigKZdYCB8IEZldGNo" + - "IGRldGFpbHMgZm9yIG11bHRpcGxlIHRhc2tzIGluIG9uZSByZXF1ZXN0IHwgfAoKIyMgQXV0aAoK" + - "fCBDb21tYW5kIHwgUHVycG9zZSB8IE5vdGVzIHwKfC0tLXwtLS18LS0tfAp8IGBpbml0YCB8IE1p" + - "bnQgYWRtaW4gdG9rZW4gZnJvbSBBUEkgS2V5cyB2aWEgcHVibGljIGFwaSBnYXRld2F5IHwgSWRl" + - "bXBvdGVudDsgd3JpdGVzIGB+Ly5udmNmLWNsaS5zdGF0ZWA7IGNsZWFycyBzYXZlZCBmdW5jdGlv" + - "biBzdGF0ZSBhbmQgYWxsIEFQSSBrZXlzIChmdW5jdGlvbiBhbmQgdGFzaykgfAp8IGBzdGF0dXNg" + - "IHwgU2hvdyBDTEkgc3RhdGUgKHRva2VuLCBsYXN0IGVuZHBvaW50cywgZnVuY3Rpb24gY29udGV4" + - "dCkgfCBEaXN0aW5jdCBmcm9tIGBzZWxmLWhvc3RlZCBzdGF0dXNgIHwKfCBgYXBpLWtleSBnZW5l" + - "cmF0ZSBbLS1mb3IgZnVuY3Rpb25cfHRhc2tdIFstLWRlc2NyaXB0aW9uPeKApl0gWy0tZXhwaXJl" + - "cy1pbj3igKZdYCB8IE1pbnQgQVBJIGtleXMgfCBEZWZhdWx0IChubyBgLS1mb3JgKTogZ2VuZXJh" + - "dGVzIGJvdGggYSBmdW5jdGlvbiBrZXkgYW5kIGEgdGFzayBrZXk7IGAtLWZvciBmdW5jdGlvbmAg" + - "b3IgYC0tZm9yIHRhc2tgIGdlbmVyYXRlcyBvbmUgb25seTsgYC0tc2NvcGVzYCByZXF1aXJlcyBg" + - "LS1mb3JgIHwKfCBgYXBpLWtleSBnZW5lcmF0ZSAtLXZhbGlkYXRlYCB8IE1pbnQgYW5kIGltbWVk" + - "aWF0ZWx5IHZhbGlkYXRlIGVhY2ggZ2VuZXJhdGVkIGtleSB8IFZhbGlkYXRlcyBlYWNoIGtleSBh" + - "Z2FpbnN0IGl0cyBjb3JyZWN0IGF1ZGllbmNlIChOVkNGIGZvciBmdW5jdGlvbiBrZXlzLCBOVkNU" + - "IGZvciB0YXNrIGtleXMpIHwKfCBgYXBpLWtleSBsaXN0YCB8IExpc3QgQVBJIGtleXMgZm9yIGN1" + - "cnJlbnQgb3duZXIgfCBMaXN0cyBOVkNGLXNjb3BlZCBrZXlzIG9ubHkgfAp8IGBhcGkta2V5IGRl" + - "bGV0ZSBLRVktSURgIC8gYGFwaS1rZXkgcmV2b2tlIEtFWS1JRGAgfCBSZW1vdmUgYW4gQVBJIGtl" + - "eSB8ICoqQ29uZmlybSB3aXRoIHVzZXIqKiB8CnwgYGFwaS1rZXkgc2hvd2AgfCBTaG93IGN1cnJl" + - "bnRseSBzYXZlZCBBUEkga2V5IGZyb20gc3RhdGUgfCB8CgojIyBBZ2VudCBza2lsbAoKfCBDb21t" + - "YW5kIHwgUHVycG9zZSB8IE5vdGVzIHwKfC0tLXwtLS18LS0tfAp8IGBhZ2VudC1za2lsbCBpbnN0" + - "YWxsIFstLXRhcmdldD1ESVJdYCB8IEluc3RhbGwgYWxsIGJ1bmRsZWQgcHVibGljIHVzZXIgc2tp" + - "bGxzIGludG8gYH4vLmNsYXVkZS9za2lsbHMvYCBhbmQgYH4vLmFnZW50cy9za2lsbHMvYCB8IERl" + - "ZmF1bHQ6IGJvdGggYmFzZSBza2lsbHMgZGlyZWN0b3JpZXMgfAp8IGBhZ2VudC1za2lsbCB1bmlu" + - "c3RhbGwgWy0tdGFyZ2V0PURJUl1gIHwgUmVtb3ZlIG9ubHkgYnVuZGxlZCBwdWJsaWMgdXNlciBz" + - "a2lsbHMgZnJvbSB0aGUgdGFyZ2V0IGJhc2Ugc2tpbGxzIGRpcmVjdG9yaWVzIHwgSWRlbXBvdGVu" + - "dDsgdW5yZWxhdGVkIHNraWxscyByZW1haW4gfAp8IGBhZ2VudC1za2lsbCBzaG93IFstLWZpbGU9" + - "UkVMXWAgfCBQcmludCBidW5kbGVkIGBudmNmLXNlbGYtbWFuYWdlZC1jbGkvU0tJTEwubWRgIG9y" + - "IGFub3RoZXIgZW1iZWRkZWQgZmlsZSB8IEZvciBkZWJ1Z2dpbmcgfAp8IGBhZ2VudC1za2lsbCB2" + - "ZXJzaW9uYCB8IFByaW50IGJ1aWxkIFNIQSBhbmQgZW1iZWRkZWQgcHVibGljIHVzZXIgc2tpbGwg" + - "c3VtbWFyeSB8IHwKUEsHCHIND2QhIwAAISMAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAAMgAJ" + - "AGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3JlZmVyZW5jZS9leGl0LWNvZGVzLm1kVVQFAAEA" + - "ps4SIyBgbnZjZi1jbGlgIGV4aXQgY29kZXMKClN0YWJsZSBhY3Jvc3Mgc3ViY29tbWFuZHMuIFVz" + - "ZSB0aGVzZSB0byBkcml2ZSBhZ2VudCByZXRyeSAvIHN1cmZhY2luZyBsb2dpYy4KCnwgQ29kZSB8" + - "IE1lYW5pbmcgfCBFeGFtcGxlIGNhdXNlcyB8CnwtLS18LS0tfC0tLXwKfCBgMGAgfCBTdWNjZXNz" + - "IHwgQWxsIGNoZWNrcyBwYXNzZWQ7IGluc3RhbGwgY29tcGxldGVkOyBkZXBsb3ltZW50IEFDVElW" + - "RSB8CnwgYDFgIHwgR2VuZXJpYyBlcnJvciB8IEhlbG0gcmVuZGVyIGZhaWxlZDsgbmV0d29yayB1" + - "bnJlYWNoYWJsZTsgZmlsZSBub3QgZm91bmQ7IFlBTUwgcGFyc2UgZXJyb3IgfAp8IGAyYCB8IFBy" + - "ZS1mbGlnaHQgY2hlY2sgZmFpbGVkIHwgR2F0ZXdheSBBUEkgQ1JEcyBtaXNzaW5nOyBrdWJlY3Rs" + - "IG5vdCBvbiBQQVRIOyBkZWZhdWx0IFN0b3JhZ2VDbGFzcyBhYnNlbnQgfAp8IGAzYCB8IEFkbWlu" + - "IGF1dGggZmFpbGVkIHwgTm8gdG9rZW4gKyBgLS1ub24taW50ZXJhY3RpdmVgIHNldDsgSUNNUyBy" + - "ZWplY3RlZCBKV1Q7IGluaXQgZW5kcG9pbnQgdW5yZWFjaGFibGUgfAp8IGA1YCB8IE1hbmlmZXN0" + - "IGFwcGx5IG9yIGAtLXdhaXRgIHRpbWVkIG91dCB8IEhlbG0gaW5zdGFsbCB0aW1lb3V0OyBjaGVj" + - "ayBwb2xsZWQgYnV0IGRpZG4ndCBwYXNzIGJlZm9yZSBkdXJhdGlvbiB8CnwgYDEzMGAgfCBDYW5j" + - "ZWxsZWQgYnkgU0lHSU5UL1NJR1RFUk0gfCBVc2VyIEN0cmwtQzsgQ0kgYnVkZ2V0IGV4Y2VlZGVk" + - "OyBwb2QgZXZpY3RlZCB8CgojIyBIb3cgYW4gYWdlbnQgc2hvdWxkIHJlYWN0Cgp8IENvZGUgfCBB" + - "Z2VudCBiZWhhdmlvciB8CnwtLS18LS0tfAp8IGAwYCB8IENvbnRpbnVlIC8gcmVwb3J0IHN1Y2Nl" + - "c3MuIHwKfCBgMWAgfCBTdXJmYWNlIHN0ZGVyciB0byB1c2VyOyBhc2sgYmVmb3JlIGFueSByZXRy" + - "eS4gR2VuZXJpYyBlcnJvcnMgdXN1YWxseSBuZWVkIGEgaHVtYW4gdG8gcmVhZCB0aGUgbWVzc2Fn" + - "ZS4gfAp8IGAyYCB8IFN1cmZhY2UgZmFpbGVkIGNoZWNrcyArIHRoZWlyIGBoaW50VVJMYC4gRG9u" + - "J3QgcHJvcG9zZSBgdXBgIHVudGlsIHRoZSB1c2VyIGZpeGVzIHByZXJlcXMuIHwKfCBgM2AgfCBT" + - "dWdnZXN0IGBudmNmLWNsaSBpbml0YCAoaW50ZXJhY3RpdmUpIE9SIGAtLXRva2VuPSRKV1RgIChD" + - "SSkuIERvbid0IGF1dG8tbWludCB3aXRob3V0IHVzZXIgT0suIHwKfCBgNWAgfCBBc2sgdXNlciBp" + - "ZiB0aGV5IHdhbnQgdG8gd2FpdCBsb25nZXIsIGRpZyBpbnRvIHRoZSBzdGFsbGVkIGNvbXBvbmVu" + - "dCwgb3IgY2FuY2VsLiB8CnwgYDEzMGAgfCBEb24ndCByZXRyeSBhdXRvbWF0aWNhbGx5OyB1c2Vy" + - "IGV4cGxpY2l0bHkgY2FuY2VsbGVkLiBDb25maXJtIGJlZm9yZSByZS1ydW5uaW5nLiB8CgojIyBX" + - "aGVyZSB0byBmaW5kIG1vcmUgZGV0YWlsCgpFdmVyeSBub24temVybyBleGl0IGVtaXRzIGEgc3Ry" + - "dWN0dXJlZCBgcGhhc2VfZmFpbGVkYCBKU09OIGV2ZW50IHdpdGggYGVyckNhdGVnb3J5YCwgYGVy" + - "ck1lc3NhZ2VgLCBgcmVtZWRpYXRpb25gIChhcnJheSksIGByZXRyeUNsYXNzYCAoZW51bTogYG5v" + - "bmV8aW1tZWRpYXRlfGJhY2tvZmZ8YWZ0ZXJfcmVtZWRpYXRpb258dW5rbm93bmApLCBgcmV0cnlB" + - "ZnRlclNlY2AgKGludCwgb3B0aW9uYWwpLCBhbmQgYHJhd2AgKHN1YnByb2Nlc3MgKyBIVFRQICsg" + - "S3ViZXJuZXRlcyBzaWduYWwpLiBBbHdheXMgY29uc3VtZSB0aGVzZSBpbiBgLS1qc29uYCBtb2Rl" + - "IHJhdGhlciB0aGFuIHBhcnNpbmcgRW5nbGlzaCBmcm9tIHN0ZGVyci4KUEsHCHOnWmTVBgAA1QYA" + - "AFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAALQAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xp" + - "L3JlZmVyZW5jZS9mbGFncy5tZFVUBQABAKbOEiMgYG52Y2YtY2xpYCBmbGFnIHJlZmVyZW5jZQoK" + - "IyMgR2xvYmFsIGZsYWdzIChldmVyeSBzdWJjb21tYW5kKQoKfCBGbGFnIHwgUHVycG9zZSB8IERl" + - "ZmF1bHQgfAp8LS0tfC0tLXwtLS18CnwgYC0tY29uZmlnIEZJTEVgIHwgQ29uZmlnIGZpbGUgcGF0" + - "aCB8IGAkSE9NRS8ubnZjZi1jbGkueWFtbGAgfAp8IGAtLWRlYnVnYCB8IFZlcmJvc2UgSFRUUCBs" + - "b2dnaW5nIG9uIHN0ZGVyciB8IGBmYWxzZWAgfAp8IGAtLWpzb25gIHwgSlNPTkwgZXZlbnRzIG9u" + - "IHN0ZGVyciB8IGF1dG8gKG9mZiBpbiBUVFksIG9uIHVuZGVyIGAtLW5vbi1pbnRlcmFjdGl2ZWAp" + - "IHwKCiMjIGBzZWxmLWhvc3RlZGAgcGFyZW50IChwZXJzaXN0ZW50IGFjcm9zcyBzdWJjb21tYW5k" + - "cykKCnwgRmxhZyB8IFB1cnBvc2UgfCBEZWZhdWx0IHwKfC0tLXwtLS18LS0tfAp8IGAtLWNvbnRy" + - "b2wtcGxhbmUtc3RhY2s94oCmYCB8IENvbnRyb2wtcGxhbmUgYnVuZGxlIHNvdXJjZTogbG9jYWwg" + - "cGF0aCwgZ2l0IFVSTCwgb3IgYG9jaTovL2AgVVJMIHwgZW1iZWRkZWQgT0NJIFVSTCBwaW5uZWQg" + - "YnkgQ0xJIHZlcnNpb24gfAp8IGAtLWNvbXB1dGUtcGxhbmUtc3RhY2s94oCmYCB8IENvbXB1dGUt" + - "cGxhbmUgYnVuZGxlIHNvdXJjZTogbG9jYWwgcGF0aCwgZ2l0IFVSTCwgb3IgYG9jaTovL2AgVVJM" + - "IHwgZW1iZWRkZWQgT0NJIFVSTCBwaW5uZWQgYnkgQ0xJIHZlcnNpb24gfAp8IGAtLWVudj1sb2Nh" + - "bFx8cHJkXHzigKZgIHwgSGVsbWZpbGUgZW52aXJvbm1lbnQgbmFtZSB8IGBsb2NhbGAgZm9yIGRl" + - "diBidWlsZHMsIGBwcmRgIGZvciByZWxlYXNlcyB8CnwgYC0tbm9uLWludGVyYWN0aXZlYCB8IERp" + - "c2FibGUgYWxsIHN0ZGluIHByb21wdHMgfCBgZmFsc2VgIHwKfCBgLS10b2tlbj0kSldUYCB8IEFk" + - "bWluIEpXVCwgb3ZlcnJpZGVzIHN0b3JlZCBzZXNzaW9uIHwgLSB8CnwgYC0tbm8tYXBwbHlgIHwg" + - "YGluc3RhbGxgIG9ubHkgLSBlbWl0IFlBTUwsIGRvIG5vdCBrdWJlY3RsIGFwcGx5IHwgYGZhbHNl" + - "YCB8CnwgYC0tb3V0cHV0PXRleHRcfGpzb25gIHwgTGVnYWN5IGFsaWFzIGZvciBgLS1qc29uYCAo" + - "ZGVwcmVjYXRlZCwgcmVtb3ZlZCBpbiBuZXh0IG1ham9yKSB8IGB0ZXh0YCB8CnwgYC0tcGxhaW5g" + - "IHwgRm9yY2UgcGxhaW4gc3RyZWFtaW5nIG91dHB1dCB8IGF1dG8tZGV0ZWN0IHwKfCBgLS13YWl0" + - "IERVUkFUSU9OYCB8IGBjaGVja2Agb25seTsgYmxvY2sgdW50aWwgcGFzcyB8IC0gfAp8IGAtLWNv" + - "bnRyb2wtcGxhbmUtY29udGV4dCBDVFhgIHwga3ViZWN0bCBjb250ZXh0IGZvciBjb250cm9sIHBs" + - "YW5lIChSRVEtMjApIHwgY3VycmVudCBjb250ZXh0IHwKfCBgLS1jb21wdXRlLXBsYW5lLWNvbnRl" + - "eHQgQ1RYYCB8IGt1YmVjdGwgY29udGV4dCBmb3IgY29tcHV0ZSBwbGFuZSAoUkVRLTIwKSB8IGN1" + - "cnJlbnQgY29udGV4dCB8CnwgYC0taWNtcy11cmwgVVJMYCB8IFB1YmxpYyBJQ01TIFVSTDsgcmVx" + - "dWlyZWQgd2hlbiBjb250ZXh0cyBkaWZmZXIgfCBkZXJpdmVkIGZyb20gYGJhc2VfaHR0cF91cmxg" + - "IHwKfCBgLS1sb2NhbC1vbmx5YCB8IGBjaGVjayAtLXByZWAgb25seTsgc2tpcCBhbGwga3ViZWN0" + - "bCBjb250YWN0IHwgYGZhbHNlYCB8CgojIyBgdXBgLXNwZWNpZmljCgp8IEZsYWcgfCBQdXJwb3Nl" + - "IHwgRGVmYXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS1jbHVzdGVyLW5hbWUgTkFNRWAgfCBJQ01T" + - "IGNsdXN0ZXIgcm93IGlkZW50aWZpZXIgKHJlcXVpcmVkKSB8IC0gfAp8IGAtLW5jYS1pZCBJRGAg" + - "fCBOQ0EgYWNjb3VudCBJRCB8IGBudmNmLWRlZmF1bHRgIHwKfCBgLS1yZWdpb24gUkVHSU9OYCB8" + - "IENsdXN0ZXIgcmVnaW9uIHwgYHVzLXdlc3QtMWAgfAp8IGAtLXBsYW4tb25seWAgfCBEcnktcnVu" + - "OyBlbWl0IHBoYXNlIHBsYW4gKyBFVEFzIHdpdGhvdXQgY2hhbmdlcyB8IGBmYWxzZWAgfAoKIyMg" + - "YHN0YXR1c2Atc3BlY2lmaWMKCnwgRmxhZyB8IFB1cnBvc2UgfCBEZWZhdWx0IHwKfC0tLXwtLS18" + - "LS0tfAp8IGAtLWNsdXN0ZXItbmFtZSBOQU1FYCB8IExpbWl0IHRvIG9uZSBjb21wdXRlIHBsYW5l" + - "IHwgLSAoY29udHJvbCArIGFsbCBjbHVzdGVycykgfAp8IGAtLXdhdGNoYCB8IExpdmUgcmUtcmVu" + - "ZGVyIHwgYGZhbHNlYCB8CnwgYC0td2F0Y2gtaW50ZXJ2YWwgRFVSYCB8IGAtLXdhdGNoYCBjYWRl" + - "bmNlIHwgYDVzYCB8CnwgYC0tY29tcG9uZW50IE5BTUVgIHwgRmlsdGVyIGNvbXBvbmVudHMgcGFu" + - "ZWwgfCBhbGwgfAp8IGAtLW5vLWV2ZW50c2AgfCBTa2lwIGV2ZW50cyBwYW5lbCB8IGBmYWxzZWAg" + - "fAoKIyMgYGNsdXN0ZXIgcmVnaXN0ZXJgLXNwZWNpZmljCgp8IEZsYWcgfCBQdXJwb3NlIHwgRGVm" + - "YXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS1uYW1lIE5BTUVgIHwgQ2x1c3RlciBuYW1lIChyZXF1" + - "aXJlZCkgfCAtIHwKfCBgLS1uY2EtaWQgSURgIHwgTkNBIElEIChyZXF1aXJlZCkgfCAtIHwKfCBg" + - "LS1yZWdpb24gUkVHSU9OYCB8IFJlZ2lvbiB8IGB1cy13ZXN0LTFgIHwKfCBgLS1pY21zLXVybCBV" + - "UkxgIHwgSUNNUyBlbmRwb2ludCB8IGZyb20gY29uZmlnIHwKfCBgLS1pZ25vcmUtZXhpc3Rpbmdg" + - "IHwgTWF0Y2gtb3ItY3JlYXRlIGluc3RlYWQgb2YgZmFpbC1vbi1leGlzdHMgfCBgZmFsc2VgIHwK" + - "CiMjIGBhcGkta2V5IGdlbmVyYXRlYC1zcGVjaWZpYwoKfCBGbGFnIHwgUHVycG9zZSB8IERlZmF1" + - "bHQgfAp8LS0tfC0tLXwtLS18CnwgYC0tZm9yIGZ1bmN0aW9uXHx0YXNrYCB8IEdlbmVyYXRlIG9u" + - "bHkgdGhlIHNwZWNpZmllZCBrZXkgdHlwZSB8IChvbWl0IHRvIGdlbmVyYXRlIGJvdGgpIHwKfCBg" + - "LS1kZXNjcmlwdGlvbiBURVhUYCB8IEh1bWFuLXJlYWRhYmxlIGxhYmVsIGZvciB0aGUga2V5IHwg" + - "YEdlbmVyYXRlZCBieSBudmNmLWNsaWAgfAp8IGAtLWV4cGlyZXMtaW4gRFVSQVRJT05gIHwgRXhw" + - "aXJ5IG9mZnNldCAoZS5nLiBgMjRoYCwgYDdkYCk7IHBhcnNlZCBhcyBleHRlbmRlZCBkdXJhdGlv" + - "biB8IGAyNGhgIHwKfCBgLS1zY29wZXMgU0NPUEVbLFNDT1BFXWAgfCBPdmVycmlkZSBkZWZhdWx0" + - "IHNjb3BlczsgcmVxdWlyZXMgYC0tZm9yYCB8IChzZXJ2aWNlIGRlZmF1bHRzKSB8CnwgYC0tdmFs" + - "aWRhdGVgIHwgVmFsaWRhdGUgZWFjaCBnZW5lcmF0ZWQga2V5IGltbWVkaWF0ZWx5IGFmdGVyIG1p" + - "bnRpbmcgfCBgZmFsc2VgIHwKCkV4dGVuZGVkIGR1cmF0aW9uIHVuaXRzOiBgc2AgKHNlY29uZHMp" + - "LCBgbWAgKG1pbnV0ZXMpLCBgaGAgKGhvdXJzKSwgYGRgIChkYXlzKSwgYHdgICh3ZWVrcykuCgoj" + - "IyBgZnVuY3Rpb24gY3JlYXRlYC1zcGVjaWZpYwoKYC0taW5wdXQtZmlsZSBGSUxFYCBpcyByZWNv" + - "bW1lbmRlZCBmb3IgcmVwZWF0YWJsZSBmdW5jdGlvbiBkZWZpbml0aW9ucy4gRm9yIGFkLWhvYyBj" + - "cmVhdGVzOgoKfCBGbGFnIHwgUHVycG9zZSB8IERlZmF1bHQgfAp8LS0tfC0tLXwtLS18CnwgYC0t" + - "bmFtZSBOQU1FYCB8IEZ1bmN0aW9uIG5hbWUgfCAtIHwKfCBgLS1pbWFnZSBJTUFHRWAgfCBDb250" + - "YWluZXIgaW1hZ2UgfCAtIHwKfCBgLS1pbmZlcmVuY2UtdXJsIFVSSWAgfCBDb250YWluZXIgaW5m" + - "ZXJlbmNlIGVuZHBvaW50IHwgLSB8CnwgYC0taW5mZXJlbmNlLXBvcnQgUE9SVGAgfCBDb250YWlu" + - "ZXIgaW5mZXJlbmNlIHBvcnQgfCAtIHwKfCBgLS1mdW5jdGlvbi10eXBlIERFRkFVTFRcfFNUUkVB" + - "TUlOR1x8TExNYCB8IEZ1bmN0aW9uIHR5cGUgfCBgREVGQVVMVGAgfAp8IGAtLWhlbG0tY2hhcnQg" + - "Q0hBUlRgIHwgSGVsbSBjaGFydCBVUkwgb3IgT0NJIHJlZmVyZW5jZS4gQ2FuIGJlIHVzZWQgd2l0" + - "aCBgLS1mdW5jdGlvbi10eXBlPUxMTWAgZm9yIGNoYXJ0LXBhY2thZ2VkIExMTSB3b3JrbG9hZHMu" + - "IHwgLSB8CnwgYC0taGVsbS1jaGFydC1zZXJ2aWNlIE5BTUVgIHwgS3ViZXJuZXRlcyBTZXJ2aWNl" + - "IG5hbWUgZXhwb3NlZCBieSB0aGUgY2hhcnQuIFJlcXVpcmVkIHdoZW4gYC0taGVsbS1jaGFydGAg" + - "aXMgc2V0LiB8IC0gfAp8IGAtLW1vZGVscyBOQU1FOlZFUlNJT046VVJJYCB8IFN0YW5kYXJkIG1v" + - "ZGVsIGFydGlmYWN0OyByZXBlYXRhYmxlIHwgLSB8CnwgYC0tbGxtLW1vZGVsIFNQRUNgIHwgTExN" + - "IG1vZGVsIGNvbmZpZzsgZm9ybWF0IGBuYW1lPTxtb2RlbD4sdXJpcz08dXJpPlx8PHVyaT4scm91" + - "dGluZ01ldGhvZD08bWV0aG9kPix0b2tlblJhdGVMaW1pdD08bGltaXQ+YDsgcmVwZWF0YWJsZS4g" + - "VG9rZW4gbGltaXRzIHVzZSBgPHZhbHVlPi08dW5pdD5gIHdpdGggYFNgLCBgTWAsIGBIYCwgYERg" + - "LCBvciBgV2AsIGZvciBleGFtcGxlIGAxMDAwLVNgLiBVc2UgaW5wdXQgSlNPTiBmb3IgY29tYmlu" + - "ZWQgdG9rZW4gbGltaXRzIGJlY2F1c2UgaW5saW5lIHNwZWNzIHVzZSBjb21tYXMgYXMgZmllbGQg" + - "c2VwYXJhdG9ycy4gfCAtIHwKfCBgLS1sbG0tZGVmYXVsdC1wcmlvcml0eSBQUklPUklUWWAgfCBG" + - "dW5jdGlvbi1sZXZlbCBkZWZhdWx0IHJlcXVlc3QgcHJpb3JpdHkuIExvd2VyIHZhbHVlcyBoYXZl" + - "IGhpZ2hlciBwcmlvcml0eS4gfCAtIHwKfCBgLS1sbG0tcGVyLWFjY291bnQtcHJpb3JpdHkgTkNB" + - "LUlEOlBSSU9SSVRZYCB8IFBlci1hY2NvdW50IHByaW9yaXR5IG92ZXJyaWRlOyByZXBlYXRhYmxl" + - "OyBzdXBwb3J0cyB1cCB0byA2NCBkaXN0aW5jdCBOQ0EgSUQgb3ZlcnJpZGVzLiBSZXF1aXJlcyBh" + - "IGRlZmF1bHQgcHJpb3JpdHkuIHwgLSB8CgpJbiBKU09OIGFuZCBpbmxpbmUgc3BlY3MsIExMTSBm" + - "dW5jdGlvbnMgc2V0IGBmdW5jdGlvblR5cGU6ICJMTE0iYCBhbmQgbW9kZWwgcm91dGluZyBtZXRh" + - "ZGF0YSB1bmRlciBgbW9kZWxzW10ubGxtQ29uZmlnYC4gYGxsbUNvbmZpZy51cmlzYCBkZWNsYXJl" + - "cyB0aGUgT3BlbkFJLWNvbXBhdGlibGUgdXBzdHJlYW0gcGF0aHMgZXhwb3NlZCBieSB0aGUgbW9k" + - "ZWwuIEN1cnJlbnQgc3VwcG9ydGVkIHBhdGhzIGFyZSBgL3YxL2NoYXQvY29tcGxldGlvbnNgLCBg" + - "L3YxL3Jlc3BvbnNlc2AsIGFuZCBgL3YxL2VtYmVkZGluZ3NgLiBgbGxtQ29uZmlnLnJvdXRpbmdN" + - "ZXRob2RgIGFjY2VwdHMgYHJvdW5kX3JvYmluYCwgYHBvd2VyX29mX3R3b2AsIGBncm9xX211bHRp" + - "cmVnaW9uYCwgYHB1bHNhcmAsIG9yIGByYW5kb21gLgpgbGxtQ29uZmlnLnRva2VuUmF0ZUxpbWl0" + - "YCBhY2NlcHRzIG9uZSBvciBtb3JlIGNvbW1hLXNlcGFyYXRlZCBwb3NpdGl2ZSBpbnRlZ2VyIHRv" + - "a2VuIGxpbWl0cyBpbiBgPHZhbHVlPi08dW5pdD5gIGZvcm1hdC4gU3VwcG9ydGVkIHVuaXRzIGFy" + - "ZSBgU2AgKHNlY29uZHMpLCBgTWAgKG1pbnV0ZXMpLCBgSGAgKGhvdXJzKSwgYERgIChkYXlzKSwg" + - "YW5kIGBXYCAod2Vla3MpLiBVc2UgZGlzdGluY3QgdW5pdHMgd2hlbiBjb21iaW5pbmcgbGltaXRz" + - "LCBmb3IgZXhhbXBsZSBgMTAwMC1TLDUwMDAtTSwxMDAwMDAtSCw1MDAwMDAtRCwxMDAwMDAwLVdg" + - "IGluIGlucHV0IEpTT04uCgpIZWxtIGNoYXJ0IHBhY2thZ2luZyBpcyBpbmRlcGVuZGVudCBvZiBg" + - "ZnVuY3Rpb25UeXBlYC4gRm9yIGEgSGVsbS1jaGFydCBiYWNrZWQgTExNIGZ1bmN0aW9uLCBzZXQg" + - "YGZ1bmN0aW9uVHlwZTogIkxMTSJgLCBgaGVsbUNoYXJ0YCwgYGhlbG1DaGFydFNlcnZpY2VOYW1l" + - "YCwgYW5kIGBtb2RlbHNbXS5sbG1Db25maWdgIGluIHRoZSBzYW1lIGNyZWF0ZSByZXF1ZXN0LiBg" + - "aW5mZXJlbmNlUG9ydGAgbXVzdCBiZSB0aGUgS3ViZXJuZXRlcyBTZXJ2aWNlIHBvcnQgZXhwb3Nl" + - "ZCBieSBgaGVsbUNoYXJ0U2VydmljZU5hbWVgLgoKTExNIGludm9jYXRpb24gcmVxdWVzdHMgdXNl" + - "IGBtb2RlbDogIjxmdW5jdGlvbi1pZD4vPG1vZGVsLW5hbWU+ImAuIFRoZSBmdW5jdGlvbiBJRCBz" + - "ZWxlY3RzIHRoZSBOVkNGIGZ1bmN0aW9uLCBhbmQgdGhlIG1vZGVsIG5hbWUgaXMgZm9yd2FyZGVk" + - "IHVwc3RyZWFtLiBDaGF0IGNvbXBsZXRpb25zIGFuZCBSZXNwb25zZXMgQVBJIHJlcXVlc3RzIGNh" + - "biB1c2UgYHgtbXVsdGktdHVybi1zZXNzaW9uLWlkYCBmb3Igc2Vzc2lvbiBzdGlja2luZXNzOyBl" + - "bWJlZGRpbmdzIHJlcXVlc3RzIGRvIG5vdC4KCiMjIGBmdW5jdGlvbiB1cGRhdGVgLXNwZWNpZmlj" + - "Cgp8IEZsYWcgfCBQdXJwb3NlIHwgRGVmYXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS10YWdzIFRB" + - "R1ssVEFHXWAgfCBSZXBsYWNlIGZ1bmN0aW9uIHRhZ3MgfCAtIHwKfCBgLS1sbG0tbW9kZWwtdXBk" + - "YXRlIFNQRUNgIHwgTExNIG1vZGVsIHVwZGF0ZTsgZm9ybWF0IGBuYW1lPTxtb2RlbD4scm91dGlu" + - "Z01ldGhvZD08bWV0aG9kPix0b2tlblJhdGVMaW1pdD08bGltaXQ+YDsgcmVwZWF0YWJsZS4gUm91" + - "dGluZyBtZXRob2RzIG1hdGNoIGAtLWxsbS1tb2RlbGAuIFRva2VuIGxpbWl0IGV4YW1wbGU6IGAx" + - "MDAwLVNgLiBVc2UgaW5wdXQgSlNPTiBmb3IgY29tYmluZWQgdG9rZW4gbGltaXRzLiB8IC0gfAp8" + - "IGAtLWxsbS1kZWZhdWx0LXByaW9yaXR5IFBSSU9SSVRZYCB8IFJlcGxhY2UgdGhlIGZ1bmN0aW9u" + - "LWxldmVsIHByaW9yaXR5IGNvbmZpZ3VyYXRpb24gd2l0aCB0aGlzIGRlZmF1bHQgYW5kIGFueSBz" + - "dXBwbGllZCBwZXItYWNjb3VudCBvdmVycmlkZXMuIHwgLSB8CnwgYC0tbGxtLXBlci1hY2NvdW50" + - "LXByaW9yaXR5IE5DQS1JRDpQUklPUklUWWAgfCBQZXItYWNjb3VudCBwcmlvcml0eSBvdmVycmlk" + - "ZTsgcmVwZWF0YWJsZTsgc3VwcG9ydHMgdXAgdG8gNjQgZGlzdGluY3QgTkNBIElEIG92ZXJyaWRl" + - "cy4gUmVxdWlyZXMgYSBkZWZhdWx0IHByaW9yaXR5LiB8IC0gfAoKSW4gSlNPTiwgYGZ1bmN0aW9u" + - "IHVwZGF0ZWAgYWNjZXB0cyBgbW9kZWxVcGRhdGVzW11gIGVudHJpZXMgd2l0aCBgbW9kZWxOYW1l" + - "YCBhbmQgYGxsbUNvbmZpZy5yb3V0aW5nTWV0aG9kYCBhbmQvb3IgYGxsbUNvbmZpZy50b2tlblJh" + - "dGVMaW1pdGAuIGB1cmlzYCBhcmUgY3JlYXRlLXRpbWUgbW9kZWwgbWV0YWRhdGEgYW5kIGFyZSBu" + - "b3QgcGFydCBvZiBtb2RlbCB1cGRhdGVzLgoKIyMgYGZ1bmN0aW9uIGRlcGxveSBjcmVhdGVgLXNw" + - "ZWNpZmljCgpgLS1pbnB1dC1maWxlIEZJTEVgIGlzIHJlY29tbWVuZGVkIChmdWxsIEpTT04gc3Bl" + - "YykuIEZvciBhZC1ob2Mgb25lLXNob3QgdXNlOgoKfCBGbGFnIHwgUHVycG9zZSB8IERlZmF1bHQg" + - "fAp8LS0tfC0tLXwtLS18CnwgYC0tZnVuY3Rpb24taWQgSURgIHwgRnVuY3Rpb24gSUQgKHJlcXVp" + - "cmVkKSB8IC0gfAp8IGAtLWdwdSBOQU1FYCB8IEdQVSBmYW1pbHkgfCBgSDEwMGAgfAp8IGAtLWlu" + - "c3RhbmNlLXR5cGUgVFlQRWAgfCBTS1UgfCBgTkNQLkdQVS5IMTAwXzF4YCB8CnwgYC0tbWluLWlu" + - "c3RhbmNlcyBOYCB8IE1pbiByZXBsaWNhcyB8IGAxYCB8CnwgYC0tbWF4LWluc3RhbmNlcyBOYCB8" + - "IE1heCByZXBsaWNhcyB8IGAxYCB8CnwgYC0tbWF4LXJlcXVlc3QtY29uY3VycmVuY3kgTmAgfCBD" + - "b25jdXJyZW5jeSB8IGAwYCAodW5zZXQ7IHNlcnZlciBkZWZhdWx0IGFwcGxpZXMpIHwKfCBgLS1j" + - "bHVzdGVycyBOQU1FWyxOQU1FXWAgfCBUYXJnZXQgc3BlY2lmaWMgY29tcHV0ZSBjbHVzdGVycyB8" + - "IChhbnkgbWF0Y2hpbmcgU0tVKSB8CgojIyBgdGFzayBjcmVhdGVgLXNwZWNpZmljCgpgLS1pbnB1" + - "dC1maWxlIEZJTEVgIGlzIHJlY29tbWVuZGVkIGZvciByZXBlYXRhYmxlIHRhc2sgZGVmaW5pdGlv" + - "bnMuIEZvciBhZC1ob2MgdXNlOgoKfCBGbGFnIHwgUHVycG9zZSB8IE5vdGVzIHwKfC0tLXwtLS18" + - "LS0tfAp8IGAtLW5hbWUgTkFNRWAgfCBUYXNrIG5hbWUgKHJlcXVpcmVkKSB8IDEtMTI4IGNoYXJz" + - "LCBgXlthLXowLTlBLVpdW2EtejAtOUEtWlwtX10qJGAgfAp8IGAtLWdwdSBHUFVgIHwgR1BVIG5h" + - "bWUgKHJlcXVpcmVkIHdpdGhvdXQgYC0taW5wdXQtZmlsZWApIHwgRXhhbXBsZTogYEgxMDBgIHwK" + - "fCBgLS1pbnN0YW5jZS10eXBlIFRZUEVgIHwgSW5zdGFuY2UgdHlwZSAocmVxdWlyZWQgd2l0aG91" + - "dCBgLS1pbnB1dC1maWxlYCkgfCBFeGFtcGxlOiBgTkNQLkdQVS5IMTAwXzF4YCB8CnwgYC0taW1h" + - "Z2UgSU1BR0VgIHwgQ29udGFpbmVyIGltYWdlIHwgTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYC0t" + - "aGVsbS1jaGFydGAgfAp8IGAtLWhlbG0tY2hhcnQgQ0hBUlRgIHwgSGVsbSBjaGFydCBVUkwgb3Ig" + - "T0NJIHJlZmVyZW5jZSB8IE11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIGAtLWltYWdlYCB8CnwgYC0t" + - "aW5wdXQtZmlsZSBGSUxFYCB8IEpTT04gdGFzayBzcGVjIGZpbGUgfCBDTEkgZmxhZ3Mgb3ZlcnJp" + - "ZGUgSlNPTiB2YWx1ZXMgd2hlbiBib3RoIGFyZSBzZXQgfAp8IGAtLWJhY2tlbmQgQkFDS0VORGAg" + - "fCBCYWNrZW5kIC8gQ1NQIHwgLSB8CnwgYC0tY2x1c3RlcnMgTkFNRVssTkFNRV1gIHwgU3BlY2lm" + - "aWMgY2x1c3RlcnMgd2l0aGluIHRoZSBpbnN0YW5jZSB8IENvbW1hLXNlcGFyYXRlZCB8CnwgYC0t" + - "Y29udGFpbmVyLWFyZ3MgQVJHU2AgfCBBcmdzIHBhc3NlZCB3aGVuIGxhdW5jaGluZyB0aGUgY29u" + - "dGFpbmVyIHwgU2luZ2xlIHN0cmluZywgZS5nLiBgIi0tZXBvY2hzIDEwIC0tYmF0Y2gtc2l6ZSAz" + - "MiJgIHwKfCBgLS1jb250YWluZXItZW52IE5BTUU9dmFsdWVgIHwgQ29udGFpbmVyIGVudmlyb25t" + - "ZW50IHZhcmlhYmxlOyByZXBlYXRhYmxlIHwgLSB8CnwgYC0tc2VjcmV0cyBOQU1FPXZhbHVlYCB8" + - "IFNlY3JldCBlbnZpcm9ubWVudCB2YXJpYWJsZTsgcmVwZWF0YWJsZTsgZW5jcnlwdGVkIGF0IHJl" + - "c3QgfCAtIHwKfCBgLS1tYXgtcnVudGltZSBEVVJBVElPTmAgfCBNYXggd2FsbC1jbG9jayBydW4g" + - "dGltZSAoSVNPIDg2MDEsIGUuZy4gYFBUNEhgKSB8IE5vIGRlZmF1bHQ7IG9taXQgZm9yIG5vIHRp" + - "bWUgbGltaXQgfAp8IGAtLW1heC1xdWV1ZWQgRFVSQVRJT05gIHwgTWF4IHRpbWUgaW4gcXVldWUg" + - "YmVmb3JlIGNhbmNlbGxhdGlvbiAoSVNPIDg2MDEpIHwgU2VydmVyIGRlZmF1bHQgYFBUNzJIYCB8" + - "CnwgYC0tdGVybWluYXRpb24tZ3JhY2UgRFVSQVRJT05gIHwgR3JhY2UgcGVyaW9kIGFmdGVyIHN0" + - "b3Agc2lnbmFsIChJU08gODYwMSkgfCBTZXJ2ZXIgZGVmYXVsdCBgUFQxSGAgfAp8IGAtLXJlc3Vs" + - "dC1zdHJhdGVneSBVUExPQURcfE5PTkVgIHwgSG93IHRvIGhhbmRsZSB0YXNrIG91dHB1dCBhcnRp" + - "ZmFjdHMgfCAtIHwKfCBgLS1yZXN1bHRzLWxvY2F0aW9uIExPQ0FUSU9OYCB8IFJlc3VsdCB1cGxv" + - "YWQgdGFyZ2V0LCBmb3JtYXQgYG9yZy1uYW1lL1t0ZWFtLW5hbWUvXW1vZGVsLW5hbWVgOyByZXF1" + - "aXJlZCB3aGVuIGAtLXJlc3VsdC1zdHJhdGVneT1VUExPQURgIHwgLSB8CnwgYC0tbW9kZWxzIE5B" + - "TUU6VkVSU0lPTjpVUklgIHwgTW9kZWwgYXJ0aWZhY3Q7IHJlcGVhdGFibGUgfCAtIHwKfCBgLS1y" + - "ZXNvdXJjZXMgTkFNRTpWRVJTSU9OOlVSSWAgfCBSZXNvdXJjZSBhcnRpZmFjdDsgcmVwZWF0YWJs" + - "ZSB8IC0gfAp8IGAtLXRhZ3MgVEFHWyxUQUddYCB8IFRhc2sgdGFncyB8IENvbW1hLXNlcGFyYXRl" + - "ZCB8CnwgYC0tZGVzY3JpcHRpb24gVEVYVGAgfCBUYXNrIGRlc2NyaXB0aW9uIHwgLSB8CnwgYC0t" + - "bG9ncy10ZWxlbWV0cnktaWQgVVVJRGAgfCBMb2dzIHRlbGVtZXRyeSBlbmRwb2ludCBJRCB8IC0g" + - "fAp8IGAtLW1ldHJpY3MtdGVsZW1ldHJ5LWlkIFVVSURgIHwgTWV0cmljcyB0ZWxlbWV0cnkgZW5k" + - "cG9pbnQgSUQgfCAtIHwKfCBgLS10cmFjZXMtdGVsZW1ldHJ5LWlkIFVVSURgIHwgVHJhY2VzIHRl" + - "bGVtZXRyeSBlbmRwb2ludCBJRCB8IC0gfApQSwcI5GexzC0lAAAtJQAAUEsDBBQACAAAAAAAIQAA" + - "AAAAAAAAAAAAAAA3AAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcmVmZXJlbmNlL3Ryb3Vi" + - "bGVzaG9vdGluZy5tZFVUBQABAKbOEiMgVHJvdWJsZXNob290aW5nCgpLbm93biBlcnJvcnMg4oaS" + - "IGRpYWdub3N0aWMgY29tbWFuZCDihpIgcmVtZWRpYXRpb24uIEtlZXAgaW4gc3luYyB3aXRoIHRo" + - "ZSBzdHJ1Y3R1cmVkIGBwaGFzZV9mYWlsZWRgIGV2ZW50cyB0aGUgQ0xJIGVtaXRzIChSRVEtMTUp" + - "IOKAlCBldmVyeSBlbnRyeSBiZWxvdyBzaG91bGQgbWFwIHRvIGFuIGBlcnJDYXRlZ29yeWAgYW5k" + - "IGEgYHJlbWVkaWF0aW9uYCBhcnJheS4KCiMjIFByZS1mbGlnaHQKCnwgU3ltcHRvbSB8IENhdXNl" + - "IHwgUmVtZWRpYXRpb24gfAp8LS0tfC0tLXwtLS18CnwgYGt1YmVjdGwgbm90IG9uIFBBVEhgIHwg" + - "T3BlcmF0b3IncyBgJFBBVEhgIGRvZXNuJ3QgaW5jbHVkZSBrdWJlY3RsIHwgSW5zdGFsbCBrdWJl" + - "Y3RsIDEuMjgrOiBodHRwczovL2t1YmVybmV0ZXMuaW8vZG9jcy90YXNrcy90b29scy9pbnN0YWxs" + - "LWt1YmVjdGwvIHwKfCBgaGVsbWZpbGUgbm90IG9uIFBBVEhgIHwgU2FtZSB8IGh0dHBzOi8vZ2l0" + - "aHViLmNvbS9oZWxtZmlsZS9oZWxtZmlsZSNpbnN0YWxsYXRpb24gfAp8IGBoZWxtIG5vdCBvbiBQ" + - "QVRIYCB8IFNhbWUgfCBodHRwczovL2hlbG0uc2gvZG9jcy9pbnRyby9pbnN0YWxsLyB8CnwgYEdh" + - "dGV3YXkgQVBJIENSRHMgbm90IGluc3RhbGxlZGAgfCBlbnZveS1nYXRld2F5IHByZXJlcSBtaXNz" + - "aW5nIHwgYGhlbG0gaW5zdGFsbCBlZyBvY2k6Ly9kb2NrZXIuaW8vZW52b3lwcm94eS9nYXRld2F5" + - "LWhlbG0gLS1uYW1lc3BhY2U9ZW52b3ktZ2F0ZXdheS1zeXN0ZW0gLS1jcmVhdGUtbmFtZXNwYWNl" + - "YCB8CnwgYGRlZmF1bHQgU3RvcmFnZUNsYXNzIG5vdCBhdmFpbGFibGVgIHwgQ2x1c3RlciBoYXMg" + - "bm8gZGVmYXVsdCBTQyB8IEFubm90YXRlIG9uZTogYGt1YmVjdGwgcGF0Y2ggc2MgPG5hbWU+IC1w" + - "ICd7Im1ldGFkYXRhIjp7ImFubm90YXRpb25zIjp7InN0b3JhZ2VjbGFzcy5rdWJlcm5ldGVzLmlv" + - "L2lzLWRlZmF1bHQtY2xhc3MiOiJ0cnVlIn19fSdgIHwKfCBgR1BVIG9wZXJhdG9yIG5vdCBpbnN0" + - "YWxsZWRgIChjb21wdXRlLXBsYW5lKSB8IG52aWRpYSBHUFUgb3BlcmF0b3IgbWlzc2luZyB8IElu" + - "c3RhbGwgcGVyIGh0dHBzOi8vZG9jcy5udmlkaWEuY29tL2RhdGFjZW50ZXIvY2xvdWQtbmF0aXZl" + - "L2dwdS1vcGVyYXRvci9sYXRlc3QvaW5zdGFsbC1ncHUtb3BlcmF0b3IuaHRtbCwgT1IgdXNlIGBm" + - "YWtlLWdwdS1vcGVyYXRvcmAgZm9yIGRldiB8CnwgYEdQVSBub2RlIGxhYmVscyBtaXNzaW5nYCAo" + - "Y29tcHV0ZS1wbGFuZSkgfCBOb2RlcyBuZWVkIGBudmlkaWEuY29tL2dwdS5mYW1pbHlgIGV0Yy4g" + - "fCBTZXQgYC0tazNzLW5vZGUtbGFiZWwgbnZpZGlhLmNvbS9ncHUuZmFtaWx5PWhvcHBlckBhZ2Vu" + - "dDpOYCBmb3IgazNkIHwKCiMjIEF1dGgKCnwgU3ltcHRvbSB8IENhdXNlIHwgUmVtZWRpYXRpb24g" + - "fAp8LS0tfC0tLXwtLS18CnwgYGFkbWluIHRva2VuIHJlcXVpcmVkYCAoaW5pdCBub3QgcnVuKSB8" + - "IE5vIGB+Ly5udmNmLWNsaS5zdGF0ZWAgYW5kIGAtLXRva2VuYCBub3QgcGFzc2VkIHwgYG52Y2Yt" + - "Y2xpIGluaXRgIChpbnRlcmFjdGl2ZSkgb3IgYC0tdG9rZW49JEpXVCAtLW5vbi1pbnRlcmFjdGl2" + - "ZWAgKENJKSB8CnwgYFNpZ25lZCBKV1QgcmVqZWN0ZWQ6IEFub3RoZXIgYWxnb3JpdGhtIGV4cGVj" + - "dGVkLCBvciBubyBtYXRjaGluZyBrZXkocykgZm91bmRgIHwgU3RhbGUgc2Vzc2lvbi5qc29uIGZy" + - "b20gYSBkaWZmZXJlbnQgY29udHJvbCBwbGFuZSB8IGBybSB+Ly5udmNmLWNsaS5zdGF0ZWAgdGhl" + - "biBgbnZjZi1jbGkgaW5pdGAgYWdhaW4gfAp8IGA0MDMgbWlzc2luZyByZXF1ZXN0ZWQgYXV0aG9y" + - "aXRpZXNgIChmdW5jdGlvbiBpbnZva2UpIHwgQWRtaW4gdG9rZW4gZG9lc24ndCBoYXZlIGBpbnZv" + - "a2VfZnVuY3Rpb25gIHNjb3BlIHwgYG52Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1kZXNjcmlw" + - "dGlvbj3igKZgIHRoZW4gcmUtcnVuIGludm9rZSB8CgojIyBJbnN0YWxsIC8gYHVwYAoKfCBTeW1w" + - "dG9tIHwgQ2F1c2UgfCBSZW1lZGlhdGlvbiB8CnwtLS18LS0tfC0tLXwKfCBIZWxtIGB0aW1lZCBv" + - "dXQgd2FpdGluZyBmb3IgY2Fzc2FuZHJhYCB8IENhc3NhbmRyYSBTdGF0ZWZ1bFNldCBQVkMgc3R1" + - "Y2sgYFBlbmRpbmdgIHwgQ29uZmlybSBkZWZhdWx0IFN0b3JhZ2VDbGFzczsgY2hlY2sgYGt1YmVj" + - "dGwgZ2V0IHB2LHB2YyAtbiBjYXNzYW5kcmEtc3lzdGVtYCB8CnwgYEludmFsaWQgR1BVICdOQ1Au" + - "R1BVLkgxMDAnIHNwZWNpZmllZGAgKGZ1bmN0aW9uIGRlcGxveSkgfCBXcm9uZyBmaWVsZCDigJQg" + - "YGdwdWAgaXMgdGhlIGZhbWlseSwgbm90IHRoZSBTS1UgfCBVc2UgYCJncHUiOiAiSDEwMCJgLCBg" + - "Imluc3RhbmNlVHlwZSI6ICJOQ1AuR1BVLkgxMDBfMXgiYCB8CnwgYHJlZ2lvbiBtdXN0IGJlIHBy" + - "b3ZpZGVkYCAoY2x1c3RlciByZWdpc3RlciAvIGluc3RhbGwgLS1jb21wdXRlLXBsYW5lKSB8IGAt" + - "LXJlZ2lvbmAgZW1wdHkgKyBgQ0xVU1RFUl9SRUdJT05gIGVudiBlbXB0eSB8IFBhc3MgYC0tcmVn" + - "aW9uPXVzLXdlc3QtMWAgKG9yIGFueSBub24tZW1wdHkgdmFsdWUpIHwKfCBgcmVxdWlyZWRFbnYg" + - "Ik5DQV9JRCIgaXMgbm90IHNldGAgKGhlbG1maWxlIGVycm9yIGR1cmluZyBjb21wdXRlLXBsYW5l" + - "IGFwcGx5KSB8IE9sZGVyIG52Y2YtY2xpIGJlZm9yZSBjb21taXQgYDZhYTU3MDRgOyBFeHRyYUVu" + - "diBub3QgcHJvcGFnYXRpbmcgTkNBX0lEIHwgVXBncmFkZSBgbnZjZi1jbGlgIHRvIGEgcmVsZWFz" + - "ZSBhZnRlciBgNmFhNTcwNGAgfAp8IGBudmNhLW9wZXJhdG9yOiBJbWFnZVB1bGxCYWNrT2ZmYCBm" + - "b3IgYG52Y2Etb3BlcmF0b3I6cHNhdGAgfCBJbWFnZSBub3QgaW4gY2x1c3RlciByZWdpc3RyeTsg" + - "bXVsdGktY2x1c3RlciBidWlsZCBpcyBsb2NhbCB8IGBrM2QgaW1hZ2UgaW1wb3J0IG52Y3IuaW8v" + - "Li4uL252Y2Etb3BlcmF0b3I6cHNhdCAtYyA8Y2x1c3Rlcj5gIHwKCiMjIENvbXB1dGUtcGxhbmUg" + - "cnVudGltZQoKfCBTeW1wdG9tIHwgQ2F1c2UgfCBSZW1lZGlhdGlvbiB8CnwtLS18LS0tfC0tLXwK" + - "fCBOVkNBIGFnZW50IENyYXNoTG9vcEJhY2tPZmYgd2l0aCBgSFRUUCA0MDFgIG9uIGAvdjEvbnZj" + - "YS9jbHVzdGVycy8uLi4vcmVnaXN0ZXJgIHwgU3RhbGUgYG91dC88Y2x1c3Rlcj4tcmVnaXN0ZXIt" + - "dmFsdWVzLnlhbWxgIGZyb20gcHJpb3IgcmVnaXN0ZXI7IGNsdXN0ZXIgSUQgZG9lc24ndCBtYXRj" + - "aCBJQ01TIHwgRGVsZXRlIHRoZSBzdGFsZSBmaWxlOyByZS1ydW4gYG52Y2YtY2xpIHNlbGYtaG9z" + - "dGVkIHVwYCAoaWRlbXBvdGVudCByZWdpc3RlciB3cml0ZXMgYSBmcmVzaCBmaWxlKSB8CnwgYE5v" + - "IGNsdXN0ZXIgZm91bmQgd2l0aCB2YWxpZCBKV0tTIGZvciBjbHVzdGVyIElEOiA8aWQ+YCAoSUNN" + - "UyBsb2cpIHwgSldLUyBpbiBJQ01TIGRvZXNuJ3QgbWF0Y2ggd2hhdCBjb21wdXRlLXBsYW5lIEs4" + - "cyBpcyBjdXJyZW50bHkgc2lnbmluZyB8IGBudmNmLWNsaSBjbHVzdGVyIHJvdGF0ZSAtLWNsdXN0" + - "ZXItaWQ9PGlkPmAgfAp8IEZ1bmN0aW9uIHBvZCBgSW1hZ2VQdWxsQmFja09mZmAgaW4gYG52Y2Yt" + - "YmFja2VuZGAgfCBJbWFnZS1jcmVkZW50aWFsLWhlbHBlciBjb25maWcgbWlzc2luZyBvciB3cm9u" + - "ZyB8IGBrdWJlY3RsIGRlc2NyaWJlIHBvZCAtbiBudmNmLWJhY2tlbmQgPHBvZD5gOyBjaGVjayB0" + - "aGUgcHVsbCBzZWNyZXQgY29uZmlnIHwKfCBGdW5jdGlvbiBkZXBsb3kgc3R1Y2sgYERFUExPWUlO" + - "R2AgZm9yID41IG1pbiB8IE5BVFMgc3RyZWFtIGluaXQgbGFnIChjb2xkLWNsdXN0ZXIpIOKAlCB3" + - "YWl0LCBvciBjaGVjayBOQVRTIGF1dGgtY2FsbG91dCBoZWFsdGggfCBga3ViZWN0bCBsb2dzIC1u" + - "IG5hdHMtc3lzdGVtIC1sIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU9bmF0cy1hdXRoLWNhbGxvdXQt" + - "c2VydmljZWAgfAoKIyMgVGFza3MKCnwgU3ltcHRvbSB8IENhdXNlIHwgUmVtZWRpYXRpb24gfAp8" + - "LS0tfC0tLXwtLS18CnwgYHRhc2sgY3JlYXRlYCByZXR1cm5zIGBNaXNzaW5nIDxUWVBFPiByZWdp" + - "c3RyeSBjcmVkZW50aWFsIGZvciBob3N0bmFtZWAsIG9yIGtlZXBzIHVzaW5nIGEgcHJldmlvdXMg" + - "Y3JlZGVudGlhbCB2YWx1ZSwgc2hvcnRseSBhZnRlciBgcmVnaXN0cnktY3JlZGVudGlhbCBhZGQv" + - "dXBkYXRlL2RlbGV0ZWAgd2hpbGUgYHJlZ2lzdHJ5LWNyZWRlbnRpYWwgbGlzdGAvYGdldGAgYWxy" + - "ZWFkeSBzaG93IHRoZSBuZXcgdmFsdWUgfCBFeHBlY3RlZCBwcm9wYWdhdGlvbiBkZWxheTogTlZD" + - "VCBjYWNoZXMgdGhlIGFjY291bnQncyByZWdpc3RyeSBjcmVkZW50aWFscyB3aXRoIGBudmN0Lm52" + - "Y2YuY2FjaGUtdHRsYCAoZGVmYXVsdCBgUFQ1TWAsIGFib3V0IDUgbWluKSBhbmQgYXBwbGllcyB0" + - "aGUgY2hhbmdlIHdoZW4gdGhhdCBjYWNoZWQgY29weSByZWZyZXNoZXMgfCBXYWl0IHVwIHRvIGFi" + - "b3V0IDUgbWluIGFuZCByZXRyeSwgb3IgYGt1YmVjdGwgLW4gbnZjZiByb2xsb3V0IHJlc3RhcnQg" + - "ZGVwbG95bWVudC9udmN0LWFwaWAgdG8gYXBwbHkgaW1tZWRpYXRlbHkgfApQSwcI864ThHQRAAB0" + - "EQAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAAsAAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1p" + - "bnN0YWxsYXRpb24vU0tJTEwubWRVVAUAAQCmzhItLS0KbmFtZTogbnZjZi1zZWxmLW1hbmFnZWQt" + - "aW5zdGFsbGF0aW9uCmRlc2NyaXB0aW9uOiA+LQogIEluc3RhbGwgYW5kIG9wZXJhdGUgTlZDRiBz" + - "ZWxmLWhvc3RlZCBjb250cm9sLXBsYW5lIGFuZCBzZXBhcmF0ZSBjb21wdXRlLXBsYW5lCiAgc3Rh" + - "Y2tzLiBDb3ZlcnMgSGVsbWZpbGUgdmFsdWVzIGFuZCBDTEkgcHJvZmlsZSBpbnN0YWxsYXRpb24g" + - "Zmxvd3MsIHRlYXJkb3duLAogIHZhbHVlcyBvdmVycmlkZXMsIHB1bGwgc2VjcmV0cywgYW5kIHRy" + - "b3VibGVzaG9vdGluZy4gVXNlIGZvcgogIG52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrLCBudmNmLWNv" + - "bXB1dGUtcGxhbmUtc3RhY2ssIHNwbGl0IGNvbXB1dGUtcGxhbmUKICBpbnN0YWxsYXRpb24sIGNv" + - "bnRyb2wtcGxhbmUgaW5zdGFsbGF0aW9uLCBDTEktZ2VuZXJhdGVkIGNvbnRyb2wtcGxhbmUKICBw" + - "cm9maWxlcywgSGVsbWZpbGUsIHNlbGYtbWFuYWdlZCwgb3Igc2VsZi1ob3N0ZWQgZGVwbG95bWVu" + - "dHMuIERvIE5PVCB1c2UgZm9yCiAgbG9jYWwgazNkIGVudmlyb25tZW50czsgdXNlIHRoZSBsb2Nh" + - "bCBrM2QgZGV2ZWxvcG1lbnQgd29ya2Zsb3cgaW5zdGVhZC4KbGljZW5zZTogQXBhY2hlLTIuMApj" + - "b21wYXRpYmlsaXR5OiBSZXF1aXJlcyBoZWxtZmlsZSA+PSAxLjEuMCA8IDEuMi4wLCBoZWxtID49" + - "IDMuMTIsIGhlbG0tZGlmZiBwbHVnaW4sIGt1YmVjdGwgbWF0Y2hpbmcgY2x1c3RlciB2ZXJzaW9u" + - "CmF1dGhvcjogIm52Y2YtY29yZS1lbmcgPG52Y2YtY29yZS1lbmdAZXhjaGFuZ2UubnZpZGlhLmNv" + - "bT4iCnZlcnNpb246ICIxLjAuMCIKdGFnczogW252Y2YsIHNlbGYtbWFuYWdlZCwgaGVsbWZpbGUs" + - "IHNlbGYtaG9zdGVkLCBjb250cm9sLXBsYW5lLCBjb21wdXRlLXBsYW5lLCBjbGktcHJvZmlsZSwg" + - "aW5zdGFsbGF0aW9uLCBkZXBsb3ltZW50LCBwdWxsLXNlY3JldHNdCnRvb2xzOiBbU2hlbGwsIFJl" + - "YWQsIEVkaXQsIEdyZXAsIEdsb2JdCm1ldGFkYXRhOgogIGludGVybmFsOiBmYWxzZQogIGF1dGhv" + - "cjogIm52Y2YtY29yZS1lbmcgPG52Y2YtY29yZS1lbmdAZXhjaGFuZ2UubnZpZGlhLmNvbT4iCiAg" + - "dmVyc2lvbjogIjEuMCIKICB0YWdzOiBbbnZjZiwgc2VsZi1tYW5hZ2VkLCBoZWxtZmlsZSwgc2Vs" + - "Zi1ob3N0ZWQsIGNvbnRyb2wtcGxhbmUsIGNvbXB1dGUtcGxhbmUsIGNsaS1wcm9maWxlLCBpbnN0" + - "YWxsYXRpb24sIGRlcGxveW1lbnQsIHB1bGwtc2VjcmV0c10KICBsYW5ndWFnZXM6IFtiYXNoLCB5" + - "YW1sXQogIGZyYW1ld29ya3M6IFtoZWxtZmlsZSwgaGVsbSwga3ViZWN0bF0KICBkb21haW46IGNs" + - "b3VkLWluZnJhc3RydWN0dXJlCi0tLQoKIyBOVkNGIFNlbGYtTWFuYWdlZCBTdGFjayBPcGVyYXRp" + - "b25zCgpPcGVyYXRpb25hbCBndWlkZSBmb3IgbWF0Y2hpbmcgTlZDRiBjb250cm9sLXBsYW5lIGFu" + - "ZCBjb21wdXRlLXBsYW5lIEhlbG1maWxlIGJ1bmRsZXMuCgojIyBJbnN0cnVjdGlvbnMKClVzZSB0" + - "aGlzIHNraWxsIGZvciBpbnN0YWxsLCB1cGdyYWRlLCBvciB0ZWFyZG93biB3b3JrIGluIG1hdGNo" + - "aW5nIGBudmNmLXNlbGYtbWFuYWdlZC1zdGFja2AgYW5kIGBudmNmLWNvbXB1dGUtcGxhbmUtc3Rh" + - "Y2tgIGJ1bmRsZXM7IGtlZXAgSGVsbWZpbGUgdmFsdWVzIGFuZCBDTEkgcHJvZmlsZSBoYW5kb2Zm" + - "cyBzZXBhcmF0ZS4gRm9yIGBmdW5jdGlvblR5cGU6ICJMTE0iYCwgcmVhZCBbTExNIEZ1bmN0aW9u" + - "IEVuYWJsZW1lbnRdKHJlZmVyZW5jZXMvaGVsbWZpbGUtc3RydWN0dXJlLm1kI2xsbS1mdW5jdGlv" + - "bi1lbmFibGVtZW50KS4KCiMjIFByZXJlcXVpc2l0ZXMKCkFzayBmb3IgdGhlIGV4dHJhY3RlZCBg" + - "bnZjZi1zZWxmLW1hbmFnZWQtc3RhY2tgIHBhdGguIEZvciBzcGxpdCBpbnN0YWxsYXRpb24sCmFs" + - "c28gcmVxdWlyZSB0aGUgbWF0Y2hpbmctdmVyc2lvbiBgbnZjZi1jb21wdXRlLXBsYW5lLXN0YWNr" + - "YCBwYXRoLiBWZXJpZnkgYm90aDoKCmBgYGJhc2gKbHMgPGNvbnRyb2wtcGxhbmUtc3RhY2s+L2hl" + - "bG1maWxlLmQvIDxjb250cm9sLXBsYW5lLXN0YWNrPi9lbnZpcm9ubWVudHMvIDxjb250cm9sLXBs" + - "YW5lLXN0YWNrPi9zZWNyZXRzLyA8Y29udHJvbC1wbGFuZS1zdGFjaz4vZ2xvYmFsLnlhbWwuZ290" + - "bXBsCmxzIDxjb21wdXRlLXBsYW5lLXN0YWNrPi9oZWxtZmlsZS5kLyA8Y29tcHV0ZS1wbGFuZS1z" + - "dGFjaz4vZW52aXJvbm1lbnRzLyA8Y29tcHV0ZS1wbGFuZS1zdGFjaz4vZ2xvYmFsLnlhbWwuZ290" + - "bXBsCmBgYAoKSWYgZWl0aGVyIGRpcmVjdG9yeSBpcyBtaXNzaW5nLCBkb3dubG9hZCBtYXRjaGlu" + - "ZyBidW5kbGUgdmVyc2lvbnMgZnJvbSBOR0M6CgpgYGBiYXNoCm5nYyByZWdpc3RyeSByZXNvdXJj" + - "ZSBkb3dubG9hZC12ZXJzaW9uIDxvcmc+L252Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrOjx2ZXJzaW9u" + - "PgpuZ2MgcmVnaXN0cnkgcmVzb3VyY2UgZG93bmxvYWQtdmVyc2lvbiA8b3JnPi9udmNmLWNvbXB1" + - "dGUtcGxhbmUtc3RhY2s6PHZlcnNpb24+CmBgYAoKQ29udHJvbC1wbGFuZSBjb21tYW5kcyBiZWxv" + - "dyBhc3N1bWUgdGhlIGNvbnRyb2wtcGxhbmUgYnVuZGxlIHJvb3QuIFNwbGl0LWZsb3cKY29tbWFu" + - "ZHMgYW5kIHJvb3Qgc3Vic3RpdHV0aW9uIGFyZSBpbgpbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0" + - "YWxsYXRpb25dKHJlZmVyZW5jZXMvY29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpLgoKIyMg" + - "QmVmb3JlIFlvdSBTdGFydAoKVmVyaWZ5IHRvb2xpbmcgYW5kIGNvbnRleHQgYmVmb3JlIGFueSBv" + - "cGVyYXRpb246CgpgYGBiYXNoCmhlbG1maWxlIC0tdmVyc2lvbiAgICMgTXVzdCBiZSAxLjEueCAo" + - "MS4yLjAgcmVtb3ZlZCBzZXF1ZW50aWFsIG1vZGUpCmhlbG0gdmVyc2lvbiAgICAgICAgICMgTXVz" + - "dCBiZSA+PSAzLjEyCmhlbG0gcGx1Z2luIGxpc3QgICAgICMgTXVzdCBpbmNsdWRlIGhlbG0tZGlm" + - "ZiA+PSAzLjExCmt1YmVjdGwgdmVyc2lvbiAgICAgICMgQ2xpZW50IG11c3QgYmUgd2l0aGluIDEg" + - "bWlub3IgdmVyc2lvbiBvZiBjbHVzdGVyCmBgYAoKQ29udHJvbC1wbGFuZSBjb21tYW5kcyBydW4g" + - "ZnJvbSB0aGUgZXh0cmFjdGVkIGBudmNmLXNlbGYtbWFuYWdlZC1zdGFjay9gIHJvb3Q6CgpgYGBi" + - "YXNoCmNkIHBhdGgvdG8vbnZjZi1zZWxmLW1hbmFnZWQtc3RhY2sKbHMgaGVsbWZpbGUuZC8gZW52" + - "aXJvbm1lbnRzLyBzZWNyZXRzLyBnbG9iYWwueWFtbC5nb3RtcGwKYGBgCgpJZGVudGlmeSB0aGUg" + - "ZW52aXJvbm1lbnQgZnJvbSBgZW52aXJvbm1lbnRzLzxuYW1lPi55YW1sYCBhbmQKYHNlY3JldHMv" + - "PG5hbWU+LXNlY3JldHMueWFtbGA7IGZvciBFS1MsIHVzZSB0aGUgY2Fub25pY2FsCltDU1AgRW5k" + - "LXRvLUVuZCBFeGFtcGxlXShodHRwczovL2RvY3MubnZpZGlhLmNvbS9udmNmL3YwLjYuMC1yYy9j" + - "c3AtZW5kLXRvLWVuZC1leGFtcGxlKS4KCiMjIEhvdyBWYWx1ZXMgRmxvdwoKVW5kZXJzdGFuZGlu" + - "ZyB2YWx1ZSBwcmVjZWRlbmNlIHByZXZlbnRzIHRoZSBtb3N0IGNvbW1vbiBjb25maWd1cmF0aW9u" + - "IG1pc3Rha2VzLgoKYGBgCmVudmlyb25tZW50cy9iYXNlLnlhbWwgICAgICAgICAgKGRlZmF1bHRz" + - "KQogICAgLT4gbWVyZ2VkIHdpdGgKZW52aXJvbm1lbnRzLzxlbnY+LnlhbWwgICAgICAgICAoeW91" + - "ciBvdmVycmlkZXMpCiAgICAtPiBjb25zdW1lZCBieQpnbG9iYWwueWFtbC5nb3RtcGwgICAgICAg" + - "ICAgICAgIChHbyB0ZW1wbGF0ZSwgY29uc3RydWN0cyBwZXItY2hhcnQgdmFsdWVzKQogICAgLT4g" + - "Y29uc3VtZWQgYnkKc2VjcmV0cy88ZW52Pi1zZWNyZXRzLnlhbWwgICAgICAoc2Vuc2l0aXZlIHZh" + - "bHVlcykKICAgIC0+IG92ZXJyaWRkZW4gYnkKcmVsZWFzZSBpbmxpbmUgdmFsdWVzOiBibG9ja3Mg" + - "ICAoaGlnaGVzdCBwcmVjZWRlbmNlKQpgYGAKCkNyaXRpY2FsOiBgZ2xvYmFsLnlhbWwuZ290bXBs" + - "YCBvbmx5IHBhc3NlcyB0aHJvdWdoIHNwZWNpZmljIGtleXMgdG8gZWFjaCBjaGFydCAoaW1hZ2Ug" + - "cmVnaXN0cmllcywgbm9kZSBzZWxlY3RvcnMsIHN0b3JhZ2UsIHJlcGxpY2EgY291bnRzKS4gU2V0" + - "dGluZyBhbiBhcmJpdHJhcnkgY2hhcnQgdmFsdWUgaW4gdGhlIGVudmlyb25tZW50IGZpbGUgd2ls" + - "bCBiZSBzaWxlbnRseSBpZ25vcmVkIGlmIGBnbG9iYWwueWFtbC5nb3RtcGxgIGRvZXMgbm90IHBy" + - "b3BhZ2F0ZSBpdC4KClRvIG92ZXJyaWRlIGFyYml0cmFyeSBjaGFydCB2YWx1ZXMsIHVzZSBhIGhl" + - "bG1maWxlIHJlbGVhc2UgYHZhbHVlczpgIGJsb2NrLiBTZWUgW092ZXJyaWRpbmcgSGVsbSBDaGFy" + - "dCBWYWx1ZXNdKCNvdmVycmlkaW5nLWhlbG0tY2hhcnQtdmFsdWVzKS4KCiMjIENsZWFuIEluc3Rh" + - "bGxhdGlvbgoKIyMjIDEuIENyZWF0ZSBuYW1lc3BhY2VzIGFuZCBpbWFnZSBwdWxsIHNlY3JldHMg" + - "KGlmIHVzaW5nIGEgcHJpdmF0ZSByZWdpc3RyeSkKCmBgYGJhc2gKZm9yIG5zIGluIGNhc3NhbmRy" + - "YS1zeXN0ZW0gbmF0cy1zeXN0ZW0gbnZjZiBhcGkta2V5cyBlc3Mgc2lzIHZhdWx0LXN5c3RlbSBj" + - "ZXJ0LW1hbmFnZXI7IGRvCiAga3ViZWN0bCBjcmVhdGUgbmFtZXNwYWNlICIkbnMiIC0tZHJ5LXJ1" + - "bj1jbGllbnQgLW8geWFtbCB8IGt1YmVjdGwgYXBwbHkgLWYgLQpkb25lCgojIE9ubHkgaWYgcHVs" + - "bGluZyBmcm9tIGEgcHJpdmF0ZSByZWdpc3RyeSAoZS5nLiwgTkdDIG52Y3IuaW8pCmV4cG9ydCBO" + - "R0NfQVBJX0tFWT0iPHlvdXIta2V5PiIKZm9yIG5zIGluIGNhc3NhbmRyYS1zeXN0ZW0gbmF0cy1z" + - "eXN0ZW0gbnZjZiBhcGkta2V5cyBlc3Mgc2lzIHZhdWx0LXN5c3RlbSBjZXJ0LW1hbmFnZXI7IGRv" + - "CiAga3ViZWN0bCBjcmVhdGUgc2VjcmV0IGRvY2tlci1yZWdpc3RyeSBudmNyLWNyZWRzIFwKICAg" + - "IC0tZG9ja2VyLXNlcnZlcj1udmNyLmlvIFwKICAgIC0tZG9ja2VyLXVzZXJuYW1lPSckb2F1dGh0" + - "b2tlbicgXAogICAgLS1kb2NrZXItcGFzc3dvcmQ9IiROR0NfQVBJX0tFWSIgXAogICAgLS1uYW1l" + - "c3BhY2U9IiRucyIgXAogICAgLS1kcnktcnVuPWNsaWVudCAtbyB5YW1sIHwga3ViZWN0bCBhcHBs" + - "eSAtZiAtCmRvbmUKYGBgCgpJZiB1c2luZyBwdWxsIHNlY3JldHMsIHlvdSBtdXN0IGFsc28gY29u" + - "ZmlndXJlIGVhY2ggaGVsbWZpbGUgcmVsZWFzZSB0byByZWZlcmVuY2UgdGhlbS4gU2VlIFtJbWFn" + - "ZSBQdWxsIFNlY3JldHNdKCNpbWFnZS1wdWxsLXNlY3JldHMpLgoKIyMjIDIuIEF1dGhlbnRpY2F0" + - "ZSBoZWxtIHRvIHlvdXIgY2hhcnQgcmVnaXN0cnkKCkJvdGggYGRvY2tlciBsb2dpbmAgQU5EIGBo" + - "ZWxtIHJlZ2lzdHJ5IGxvZ2luYCBhcmUgcmVxdWlyZWQgZm9yIE5HQy4gSGVsbWZpbGUgdXNlcyBo" + - "ZWxtIChub3QgZG9ja2VyKSB0byBwdWxsIE9DSSBjaGFydHMsIHNvIHRoZSBoZWxtIGNyZWRlbnRp" + - "YWwgc3RvcmUgbXVzdCBiZSBhdXRoZW50aWNhdGVkIHNlcGFyYXRlbHkuCgpgYGBiYXNoCiMgTkdD" + - "IC0tIGJvdGggY29tbWFuZHMgYXJlIHJlcXVpcmVkCmRvY2tlciBsb2dpbiBudmNyLmlvIC11ICck" + - "b2F1dGh0b2tlbicgLXAgIiROR0NfQVBJX0tFWSIKaGVsbSByZWdpc3RyeSBsb2dpbiBudmNyLmlv" + - "IC11ICckb2F1dGh0b2tlbicgLXAgIiROR0NfQVBJX0tFWSIKCiMgRUNSCmF3cyBlY3IgZ2V0LWxv" + - "Z2luLXBhc3N3b3JkIC0tcmVnaW9uIDxyZWdpb24+IHwgXAogIGhlbG0gcmVnaXN0cnkgbG9naW4g" + - "LS11c2VybmFtZSBBV1MgLS1wYXNzd29yZC1zdGRpbiA8YWNjb3VudD4uZGtyLmVjci48cmVnaW9u" + - "Pi5hbWF6b25hd3MuY29tCmBgYAoKPiBOb3RlOiBgaGVsbSByZWdpc3RyeSBsb2dpbmAga2VlcHMg" + - "b25seSB0aGUgbGFzdCBsb2dpbiBwZXIgaG9zdCAobXVsdGktb3JnIGdvdGNoYSkuCj4gVGhlIHN0" + - "YWNrIGFuZCB0aGUgY2FjaGVzIHNwYW4gc2V2ZXJhbCBOR0Mgb3JncyB0aGF0IG5lZWQgZGlmZmVy" + - "ZW50IGtleXMsIGJ1dCB0aGV5IGFsbAo+IGxpdmUgdW5kZXIgdGhlIG9uZSBob3N0IGBudmNyLmlv" + - "YC4gQSBzZWNvbmQgYGhlbG0gcmVnaXN0cnkgbG9naW4gbnZjci5pb2AgKG9yCj4gYGRvY2tlciBs" + - "b2dpbmApIHdpdGggYSBkaWZmZXJlbnQga2V5IHNpbGVudGx5IG92ZXJ3cml0ZXMgdGhlIGZpcnN0" + - "LCBzbyBwdWxscyBmb3IgdGhlCj4gZmlyc3Qgb3JnIHRoZW4gZmFpbCB3aXRoIGEgbWlzbGVhZGlu" + - "ZyBgNDAzIEFjY2VzcyBEZW5pZWRgIChub3QgYSA0MDE6IHRoZSBhdXRoCj4gc3VjY2VlZGVkLCBp" + - "dCdzIHRoZSB3cm9uZy1vcmcga2V5KS4gSWYgeW91IHB1bGwgY2hhcnRzL2ltYWdlcyBmcm9tIG1v" + - "cmUgdGhhbiBvbmUgb3JnLAo+IGVpdGhlciByZS1ydW4gdGhlIGxvZ2luIHdpdGggdGhlIGNvcnJl" + - "Y3Qga2V5IGltbWVkaWF0ZWx5IGJlZm9yZSBlYWNoIHB1bGwsIG9yIHBhc3MKPiBgLS11c2VybmFt" + - "ZSAnJG9hdXRodG9rZW4nIC0tcGFzc3dvcmQgPGtleT5gIHBlciBgaGVsbSBwdWxsYCBpbnZvY2F0" + - "aW9uIGluc3RlYWQgb2YgcmVseWluZwo+IG9uIHRoZSBzdG9yZWQgbG9naW4uIChQdWxsaW5nIGV2" + - "ZXJ5dGhpbmcgZnJvbSBhIHNpbmdsZSByZWdpc3RyeSBtaXJyb3IgYXZvaWRzIHRoaXMKPiBlbnRp" + - "cmVseS4pCgojIyMgMmIuIChSZWNvbW1lbmRlZCkgUHVsbCBmcm9tIGEgcmVnaXN0cnkgdGhlIGNs" + - "dXN0ZXIgYXV0aGVudGljYXRlcyB0byBhdXRvbWF0aWNhbGx5CgpJZiB5b3UgbWlycm9yIHRoZSBO" + - "VkNGIGltYWdlcyBpbnRvIGEgcmVnaXN0cnkgdGhhdCB0aGUgY2x1c3RlciBjYW4gcHVsbCBmcm9t" + - "IHdpdGhvdXQgYW4KZXhwbGljaXQgaW1hZ2UgcHVsbCBzZWNyZXQgKGZvciBleGFtcGxlLCBhIHJl" + - "Z2lzdHJ5IHdoZXJlIHRoZSBub2RlIG9yIHdvcmtsb2FkIGlkZW50aXR5IGlzCmdyYW50ZWQgcHVs" + - "bCBhY2Nlc3MgYXV0b21hdGljYWxseSksIHBvaW50IHRoZSBzdGFjayBhdCBpdCBhbmQgc2tpcCB0" + - "aGUgY3JlZGVudGlhbCBzdGVwcwphYm92ZS4KCjEuIFBvaW50IHRoZSBzdGFjayBhdCB0aGUgbWly" + - "cm9yIGluIGBlbnZpcm9ubWVudHMvPGVudj4ueWFtbGA6CgogICBgYGB5YW1sCiAgIGdsb2JhbDoK" + - "ICAgICBpbWFnZToKICAgICAgIHJlZ2lzdHJ5OiA8eW91ci1yZWdpc3RyeT4gICAgICAgICAgICAj" + - "IGUuZy4gcmVnaXN0cnkuZXhhbXBsZS5jb20KICAgICAgIHJlcG9zaXRvcnk6IDxtaXJyb3Itc3Vi" + - "LXBhdGg+CiAgICAgaGVsbToKICAgICAgIHNvdXJjZXM6ICAgICAgICAgICAgICAgICAgICAgICAg" + - "ICAgICAgIyBvbmx5IGlmIHlvdSBhbHNvIG1pcnJvcmVkIHRoZSBoZWxtIGNoYXJ0cwogICAgICAg" + - "ICByZWdpc3RyeTogPHlvdXItcmVnaXN0cnk+CiAgICAgICAgIHJlcG9zaXRvcnk6IDxtaXJyb3It" + - "c3ViLXBhdGg+CiAgIGBgYAoKICAgPiBUaGUgbWFuaWZlc3QgaGFzIGEgbWl4IG9mIE9DSSBhbmQg" + - "bm9uLU9DSSBhcnRpZmFjdHMsIHNvIGNvbnZlcnQgbm9uLU9DSSBjaGFydHMgYmVmb3JlCiAgID4g" + - "bWlycm9yaW5nLiBDb250YWluZXIgaW1hZ2VzIChgbnZjci5pby8uLi5gKSBhcmUgYWxyZWFkeSBP" + - "Q0kgYW5kIG1pcnJvciBhcy1pcy4gU29tZSBIZWxtCiAgID4gY2hhcnRzLCB0aG91Z2gsIGFyZSBw" + - "dWJsaXNoZWQgdG8gYW4gYGh0dHBzOi8vYCBIZWxtIHJlcG9zaXRvcnkgKGZvciBleGFtcGxlCiAg" + - "ID4gYGhlbG0ubmdjLm52aWRpYS5jb21gKS4gVGhvc2UgYXJlIG5vdCBPQ0kgYW5kIGNhbm5vdCBi" + - "ZSByZXNvbHZlZCBieSBgZ2xvYmFsLmhlbG0uc291cmNlc2AKICAgPiAoT0NJKSBvciBtaXJyb3Jl" + - "ZCBkaXJlY3RseS4gQmVmb3JlIHBvaW50aW5nIHRoZSBzdGFjayBhdCB5b3VyIG1pcnJvciwgY29u" + - "dmVydCBlYWNoCiAgID4gYGh0dHBzOi8vYCBjaGFydCB0byBPQ0k6IGBoZWxtIHJlcG8gYWRkYC9g" + - "aGVsbSBwdWxsYCB0aGUgYC50Z3pgLCB0aGVuCiAgID4gYGhlbG0gcHVzaCA8Y2hhcnQ+LnRneiBv" + - "Y2k6Ly88eW91ci1yZWdpc3RyeT4vPG1pcnJvci1zdWItcGF0aD5gLiBPbmx5IE9DSSBjaGFydHMg" + - "Y2FuIGxpdmUKICAgPiB1bmRlciBgZ2xvYmFsLmhlbG0uc291cmNlc2AuCgoyLiBTa2lwIHRoZSBj" + - "cmVkZW50aWFsIHN0ZXBzIGFib3ZlLiBXaGVuIHRoZSBjbHVzdGVyIGF1dGhlbnRpY2F0ZXMgdG8g" + - "dGhlIHJlZ2lzdHJ5CiAgIGF1dG9tYXRpY2FsbHkgKHRoZSBub2RlIG9yIHdvcmtsb2FkIGlkZW50" + - "aXR5IGhhcyBwdWxsIGFjY2VzcyksIHRoZSBwdWxsIG5lZWRzIG5vCiAgIEt1YmVybmV0ZXMgc2Vj" + - "cmV0LCBzbyB5b3UgZG8gbm90IG5lZWQ6IHRoZSBwZXItbmFtZXNwYWNlIGBudmNyLWNyZWRzYCBm" + - "cm9tIHN0ZXAgMQogICAoc3RpbGwgY3JlYXRlIHRoZSBuYW1lc3BhY2VzLCBqdXN0IG5vdCB0aGUg" + - "c2VjcmV0KSwgdGhlIGBnbG9iYWwuaW1hZ2VQdWxsU2VjcmV0c2AgZW50cnksCiAgIG9yIHRoZSBg" + - "ZG9ja2VyIGxvZ2luYC9gaGVsbSByZWdpc3RyeSBsb2dpbiBudmNyLmlvYCBmcm9tIHN0ZXAgMi4K" + - "CiAgID4gT25lIHJlc2lkdWFsIGNyZWRlbnRpYWw6IG52Y2YtYXBpIHN0aWxsIHZhbGlkYXRlcyB0" + - "aGUgdXNlciBmdW5jdGlvbiBpbWFnZSBhdAogICA+IGBmdW5jdGlvbiBjcmVhdGVgIHZpYSB0aGUg" + - "YWNjb3VudCByZWdpc3RyeSBjcmVkZW50aWFsLCBzbyB0aGF0IGNyZWRlbnRpYWwgbXVzdCBwb2lu" + - "dCBhdAogICA+IHdoaWNoZXZlciByZWdpc3RyeSBob2xkcyB0aGUgdXNlciBpbWFnZSAoc2V0IGl0" + - "IHRvIHlvdXIgbWlycm9yIGlmIHRoZSBpbWFnZSBpcyBtaXJyb3JlZAogICA+IHRoZXJlKS4KCiMj" + - "IyAzLiBTZXQgdGhlIHJvdXRlIGRvbWFpbgoKYGdsb2JhbC5kb21haW5gIHNldHMgdGhlIGhvc3Ru" + - "YW1lIHN1ZmZpeCBmb3Igcm91dGVzIHN1Y2ggYXMgYGFwaS48ZG9tYWluPmAuIEl0IGRvZXMgbm90" + - "IGNvbmZpZ3VyZSB0aGUgR2F0ZXdheSBvciBpdHMgbG9hZCBiYWxhbmNlci4gUXVlcnkgdGhlIGV4" + - "YWN0IGV4aXN0aW5nIEdhdGV3YXk6CgpgYGBiYXNoCkdBVEVXQVlfQUREUkVTUz0kKGt1YmVjdGwg" + - "Z2V0IGdhdGV3YXkgPGdhdGV3YXktbmFtZT4gLW4gPGdhdGV3YXktbmFtZXNwYWNlPiAtbyBqc29u" + - "cGF0aD0ney5zdGF0dXMuYWRkcmVzc2VzWzBdLnZhbHVlfScpCnRlc3QgLW4gIiRHQVRFV0FZX0FE" + - "RFJFU1MiCmBgYAoKVGhlIGFkZHJlc3MgbWF5IGJlIGEgaG9zdG5hbWUgb3IgSVAuIENsb3VkIHBy" + - "b3ZpZGVyIGFuZCBHYXRld2F5IGNvbmZpZ3VyYXRpb24gZGV0ZXJtaW5lIHRoZSBsb2FkIGJhbGFu" + - "Y2VyIHR5cGUgYW5kIGFkZHJlc3MgZm9ybWF0LiBUaGUgc2VsZi1tYW5hZ2VkIHN0YWNrIGRvZXMg" + - "bm90IHNlbGVjdCBlaXRoZXIuCgpGb3IgdGVtcG9yYXJ5IHRlc3Rpbmcgd2l0aG91dCBETlMsIHVz" + - "ZSBhIHN0YWJsZSByZXNlcnZlZCBzdWZmaXggc3VjaCBhcyBgZ2xvYmFsLmRvbWFpbjogIm52Y2Yu" + - "dGVzdCJgLCBjb25uZWN0IHRvIGBHQVRFV0FZX0FERFJFU1NgLCBhbmQgc2VuZCBgSG9zdDogYXBp" + - "Lm52Y2YudGVzdGAuIEZvciBwcm9kdWN0aW9uLCB1c2UgeW91ciBiYXNlIEROUyBkb21haW4gYW5k" + - "IHBvaW50IGl0cyByb3V0ZSByZWNvcmRzIHRvIGBHQVRFV0FZX0FERFJFU1NgLiBJZiB0aGUgZW5k" + - "cG9pbnQgbGF0ZXIgY2hhbmdlcywga2VlcCBgZ2xvYmFsLmRvbWFpbmAgc3RhYmxlIGFuZCB1cGRh" + - "dGUgb25seSBETlMgb3IgdGhlIGNsaWVudCBkZXN0aW5hdGlvbi4gU2VlIEV4YW1wbGUgNCBpbiBb" + - "ZXhhbXBsZXMubWRdKGV4YW1wbGVzLm1kKS4KCiMjIyA0LiBQcmV2aWV3IGFuZCBkZXBsb3kKCmBg" + - "YGJhc2gKSEVMTUZJTEVfRU5WPTxlbnYtbmFtZT4gaGVsbWZpbGUgdGVtcGxhdGUgICAjIFByZXZp" + - "ZXcgcmVuZGVyZWQgbWFuaWZlc3RzCkhFTE1GSUxFX0VOVj08ZW52LW5hbWU+IGhlbG1maWxlIHN5" + - "bmMgICAgICAgIyBEZXBsb3kKYGBgCgo+IFNldCBCT1RIIENhc3NhbmRyYSBwYXNzd29yZHMgaW4g" + - "dGhlIHNlY3JldHMgZmlsZS4gVGhlIHNlY3JldHMgZmlsZSBkb2N1bWVudHMKPiBgREVGQVVMVF9D" + - "QVNTQU5EUkFfUEFTU1dPUkRgLCBidXQgdGhlIGNhc3NhbmRyYSBjaGFydCBoYXMgYSBzZWNvbmQg" + - "Y3JlZGVudGlhbCwKPiBgY2Fzc2FuZHJhLnNlcnZpY2VSb2xlUGFzc3dvcmRgLCB0aGF0IGRlZmF1" + - "bHRzIHRvIGBjaEBuZzNtM2AuIElmIHlvdSBzZXQgb25seQo+IGBERUZBVUxUX0NBU1NBTkRSQV9Q" + - "QVNTV09SRGAsIHRoZSBzZXJ2aWNlIHJvbGUga2VlcHMgdGhhdCBkZWZhdWx0IGFuZCBldmVyeSBE" + - "Qi1iYWNrZWQKPiBzZXJ2aWNlIGNyYXNoLWxvb3BzIHdpdGggYEJhZCBjcmVkZW50aWFsc2Agb25j" + - "ZSBpdCB0cmllcyB0byBhdXRoZW50aWNhdGUuIFNldAo+IGBjYXNzYW5kcmEuc2VydmljZVJvbGVQ" + - "YXNzd29yZGAgdG8gdGhlIHNhbWUgdmFsdWUgYXMgYERFRkFVTFRfQ0FTU0FORFJBX1BBU1NXT1JE" + - "YC4KCiMjIyA1LiBEZXBsb3ltZW50IHBoYXNlcwoKSGVsbWZpbGUgZGVwbG95cyBpbiBvcmRlciB3" + - "aXRoIGRlcGVuZGVuY2llczoKCnwgUGhhc2UgfCBTZWxlY3RvciB8IFNlcnZpY2VzIHwgV2FpdCB0" + - "aW1lIHwKfC0tLS0tLS18LS0tLS0tLS0tLXwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tfAp8IDEgfCBg" + - "cmVsZWFzZS1ncm91cD1kZXBlbmRlbmNpZXNgIHwgTkFUUywgT3BlbkJhbywgQ2Fzc2FuZHJhIHwg" + - "NS0xMCBtaW4gfAp8IDIgfCBgcmVsZWFzZS1ncm91cD1zZXJ2aWNlc2AgfCBBUEksIFNJUywgRVNT" + - "LCBpbnZvY2F0aW9uLCBncnBjLXByb3h5LCBub3RhcnksIGFwaS1rZXlzLCBvcHRpb25hbCBMTE0g" + - "Z2F0ZXdheS9yb3V0ZXIsIG9wdGlvbmFsIFZhbml0eSBHYXRld2F5LCBOVkNGIFVJIHdoZW4gdGhl" + - "IHN0YWNrIHBhY2thZ2UgaW5jbHVkZXMgdGhlIGFkZG9uIHwgNS0xMCBtaW4gfAp8IDMgfCBgcmVs" + - "ZWFzZS1ncm91cD1pbmdyZXNzYCB8IEdhdGV3YXkgcm91dGVzIHwgMS0yIG1pbiB8CnwgNCB8IGBy" + - "ZWxlYXNlLWdyb3VwPW9ic2VydmFiaWxpdHlgIHwgT2JzZXJ2YWJpbGl0eSBzdGFjayAoaWYgZW5h" + - "YmxlZCkgfCAxLTIgbWluIHwKCk1vbml0b3IgaW4gYSBzZXBhcmF0ZSB0ZXJtaW5hbDoKCmBgYGJh" + - "c2gKa3ViZWN0bCBnZXQgcG9kcyAtQSAtdwpgYGAKCiMjIyA2LiBFbmFibGUgVmFuaXR5IEdhdGV3" + - "YXkgKG9wdGlvbmFsKQoKVmFuaXR5IEdhdGV3YXkgaXMgZGlzYWJsZWQgYnkgZGVmYXVsdCBhbmQg" + - "aXMgb25seSBuZWVkZWQgZm9yIGN1c3RvbWVyLWZhY2luZwpob3N0bmFtZXMgb3IgcGF0aCBtYXBw" + - "aW5ncyBpbiBmcm9udCBvZiB0aGUgc3RhbmRhcmQgTlZDRiBBUEkgYW5kIGludm9jYXRpb24Kcm91" + - "dGVzLiBJdCBpcyBhdmFpbGFibGUgb25seSBpbiBzdGFjayBwYWNrYWdlcyB0aGF0IGluY2x1ZGUg" + - "dGhlIFZhbml0eSBHYXRld2F5CmFkZG9uLiBJZiB0aGUgZXh0cmFjdGVkIHN0YWNrIHBhY2thZ2Ug" + - "ZG9lcyBub3QgY29udGFpbiBhIGB2YW5pdHktZ2F0ZXdheWAKcmVsZWFzZSBhbmQgYHZhbml0eUdh" + - "dGV3YXlgIHJvdXRlIHZhbHVlcywgc2tpcCB0aGVzZSBjb21tYW5kcyBhbmQgdXNlIGEgbmV3ZXIK" + - "c3RhY2sgcGFja2FnZSB0aGF0IGluY2x1ZGVzIHRoZW0uCgpJZiB0aGUgc3RhY2sgcGFja2FnZSBp" + - "bmNsdWRlcyB0aGUgYWRkb24sIGVuYWJsZSBpdCBpbgpgZW52aXJvbm1lbnRzLzxlbnYtbmFtZT4u" + - "eWFtbGA6CgpgYGB5YW1sCmFkZG9uczoKICB2YW5pdHlHYXRld2F5OgogICAgZW5hYmxlZDogdHJ1" + - "ZQogICAgbWFwcGluZ0NvbmZpZzoge30KYGBgCgpUaGUgZGVmYXVsdCByb3V0ZSBob3N0IGlzIGB2" + - "YW5pdHkuPGRvbWFpbj5gIGFuZCB0aGUgYmFja2VuZCBpcwpgdmFuaXR5LWdhdGV3YXkubnZjZjo4" + - "MDgwYC4gUHV0IGRlcGxveW1lbnQtc3BlY2lmaWMgaG9zdCBhbmQgcGF0aCBtYXBwaW5ncyB1bmRl" + - "cgpgYWRkb25zLnZhbml0eUdhdGV3YXkubWFwcGluZ0NvbmZpZ2AuIElmIHlvdSBuZWVkIGN1c3Rv" + - "bSB2YW5pdHkgaG9zdHMgaW5zdGVhZCBvZgpgdmFuaXR5Ljxkb21haW4+YCwgdXNlIHRoZSByb3V0" + - "ZSBob3N0bmFtZSBvdmVycmlkZXMgc3VwcG9ydGVkIGJ5IHRoZSBzdGFjawpwYWNrYWdlIGFuZCBj" + - "cmVhdGUgbWF0Y2hpbmcgRE5TIHJlY29yZHMuCgpBZnRlciBjb25maXJtaW5nIHRoZSBwYWNrYWdl" + - "IGluY2x1ZGVzIHRoZSBgdmFuaXR5LWdhdGV3YXlgIHJlbGVhc2UsIHByZXZpZXcgYW5kCmFwcGx5" + - "IHRoZSBzZXJ2aWNlIGFuZCByb3V0ZToKCmBgYGJhc2gKSEVMTUZJTEVfRU5WPTxlbnYtbmFtZT4g" + - "aGVsbWZpbGUgLS1zZWxlY3RvciBuYW1lPXZhbml0eS1nYXRld2F5IHRlbXBsYXRlCkhFTE1GSUxF" + - "X0VOVj08ZW52LW5hbWU+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT12YW5pdHktZ2F0ZXdheSBz" + - "eW5jCkhFTE1GSUxFX0VOVj08ZW52LW5hbWU+IGhlbG1maWxlIC0tc2VsZWN0b3IgcmVsZWFzZS1n" + - "cm91cD1pbmdyZXNzIHN5bmMKYGBgCgpWZXJpZnkgdGhlIHJvdXRlIG9ubHkgd2hlbiB0aGUgYWRk" + - "b24gaXMgcHJlc2VudCBhbmQgZW5hYmxlZDoKCmBgYGJhc2gKa3ViZWN0bCBnZXQgZGVwbG95LHN2" + - "YyAtbiBudmNmIC1sIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU9dmFuaXR5LWdhdGV3YXkKa3ViZWN0" + - "bCBnZXQgaHR0cHJvdXRlIC1BIHwgZ3JlcCAtaSB2YW5pdHkKY3VybCAtSCAiSG9zdDogdmFuaXR5" + - "Ljxkb21haW4+IiAiaHR0cDovLzxnYXRld2F5LWFkZHJlc3M+L2hlYWx0aCIKYGBgCgpEbyBub3Qg" + - "ZW5hYmxlIFZhbml0eSBHYXRld2F5IGZvciBzdGFuZGFyZCBBUEksIEFQSSBLZXlzLCBpbnZvY2F0" + - "aW9uLCBMTE0KaW52b2NhdGlvbiwgb3IgZ1JQQyB0cmFmZmljLiBUaG9zZSByb3V0ZXMgYXJlIHBy" + - "b3ZpZGVkIGJ5IHRoZSBiYXNlIGdhdGV3YXkKcm91dGVzLgoKIyMjIDcuIEVuYWJsZSBOVkNGIFVJ" + - "IChvcHRpb25hbCkKCk5WQ0YgVUkgaXMgYW4gb3B0aW9uYWwsIGN1c3RvbWVyLWZhY2luZyBhZG1p" + - "bi1wYW5lbCBVSS4gSXQgaXMgZGlzYWJsZWQgYnkKZGVmYXVsdCBhbmQgYXZhaWxhYmxlIG9ubHkg" + - "aW4gc3RhY2sgcGFja2FnZXMgdGhhdCBpbmNsdWRlIHRoZSBOVkNGIFVJIGFkZG9uLiBJZgp5b3Vy" + - "IGV4dHJhY3RlZCBzdGFjayBwYWNrYWdlIGRvZXMgbm90IGNvbnRhaW4gYSBgbnZjZi11aWAgcmVs" + - "ZWFzZSBhbmQgYG52Y2ZVaWAKcm91dGUgdmFsdWVzLCBza2lwIHRoaXMgc2VjdGlvbi4gVGhlIE5W" + - "Q0YgVUkgYWRtaW4gcGFuZWwgaXMgY3VycmVudGx5CnVuYXV0aGVudGljYXRlZDsgZG8gbm90IGV4" + - "cG9zZSBpdCB0byB0aGUgcHVibGljIGludGVybmV0LgoKRm9yIGVuYWJsZW1lbnQsIG5hbWVzcGFj" + - "ZSBhbmQgcHVsbCBzZWNyZXQgc2V0dXAsIGFwcGx5LCBhbmQgdmVyaWZpY2F0aW9uIHN0ZXBzLApz" + - "ZWUgW05WQ0YgVUkgQWRkb25dKHJlZmVyZW5jZXMvbnZjZi11aS1hZGRvbi5tZCkuCgojIyMgOC4g" + - "SW5zdGFsbCB0aGUgc2VwYXJhdGUgY29tcHV0ZS1wbGFuZSBzdGFjawoKVGhlIGNvbnRyb2wtcGxh" + - "bmUgc3RhY2sgZG9lcyBub3QgaW5zdGFsbCBjb21wdXRlLXBsYW5lIGNvbXBvbmVudHMuIEFmdGVy" + - "IGl0IGlzIGhlYWx0aHksIGNob29zZSBleGFjdGx5IG9uZSBjb21wdXRlLXBsYW5lIGhhbmRvZmY6" + - "CgotIEhlbG1maWxlIHZhbHVlcyBmbG93OiBhdXRob3Igc2VwYXJhdGUgZW52aXJvbm1lbnQgZmls" + - "ZXMsIHRoZW4gcmVnaXN0ZXIgYW5kCiAgaW5zdGFsbCB3aXRoIHRoZSBjb21wdXRlLXBsYW5lIE1h" + - "a2VmaWxlLgotIENMSSBwcm9maWxlIGZsb3c6IHVzZSB0aGUgcHJvZmlsZSBnZW5lcmF0ZWQgYnkg" + - "dGhlIENMSSBjb250cm9sLXBsYW5lIGluc3RhbGwsCiAgdGhlbiBydW4gdGhlIGNvbXBsZXRlIENM" + - "SSByZWdpc3RlciBhbmQgaW5zdGFsbCBjb21tYW5kcy4KCkRvIG5vdCBtaXggdGhlc2UgaGFuZG9m" + - "ZnMuIEZvbGxvdyBbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKHJlZmVyZW5jZXMv" + - "Y29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpCmZvciBjb21tYW5kcywgRUtTIHJvdXRpbmcs" + - "IHB1bGwgc2VjcmV0cywgdmVyaWZpY2F0aW9uLCBhbmQgdGVhcmRvd24gb3JkZXIuCgojIyBDbGVh" + - "biBUZWFyZG93bgoKRGVzdHJveSBldmVyeSBjb21wdXRlIHBsYW5lIGJlZm9yZSB0aGUgY29udHJv" + - "bCBwbGFuZSwgdXNpbmcgdGhlIHRlYXJkb3duIGZvcgp0aGUgc2FtZSBoYW5kb2ZmOyBzZWUgW1Nw" + - "bGl0IENvbXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9uXShyZWZlcmVuY2VzL2NvbXB1dGUtcGxhbmUt" + - "aW5zdGFsbGF0aW9uLm1kI3RlYXJkb3duKS4KClNjb3BlOiBPbmx5IGRlc3Ryb3kgcmVsZWFzZXMg" + - "bWFuYWdlZCBieSB0aGlzIGNvbnRyb2wtcGxhbmUgaGVsbWZpbGUgc3RhY2suIFRoZSBOVkNGIHJl" + - "bGVhc2VzIGFyZTogYG5hdHNgLCBgb3BlbmJhby1zZXJ2ZXJgLCBgY2Fzc2FuZHJhYCwgYGFwaS1r" + - "ZXlzYCwgYHNpc2AsIGBhcGlgLCBgaW52b2NhdGlvbi1zZXJ2aWNlYCwgYGdycGMtcHJveHlgLCBg" + - "ZXNzLWFwaWAsIGBub3Rhcnktc2VydmljZWAsIG9wdGlvbmFsIGB2YW5pdHktZ2F0ZXdheWAsIGBu" + - "dmNmLXVpYCwgYGFkbWluLWlzc3Vlci1wcm94eWAsIGFuZCBgaW5ncmVzc2A7IGBjZXJ0LW1hbmFn" + - "ZXJgIGlzIGluY2x1ZGVkIG9ubHkgd2hlbiBgY2VydE1hbmFnZXIuZW5hYmxlZDogdHJ1ZWAuIFRo" + - "ZSBjb250cm9sLXBsYW5lIG5hbWVzcGFjZSBpbnZlbnRvcnkgYWxzbyBpbmNsdWRlcyBgY2VydC1t" + - "YW5hZ2VyYCwgYnV0IGRlZmF1bHQgbmFtZXNwYWNlIGNsZWFudXAgcHJlc2VydmVzIGl0LiBOYW1l" + - "c3BhY2UgcHJlc2VydmF0aW9uIGRvZXMgbm90IHByZXNlcnZlIHRoZSBIZWxtIHJlbGVhc2UuIEV4" + - "dGVybmFsIGNlcnQtbWFuYWdlciBtdXN0IHVzZSBgY2VydE1hbmFnZXIuZW5hYmxlZDogZmFsc2Vg" + - "OyBvdGhlcndpc2UgSGVsbWZpbGUgdHJlYXRzIHRoZSByZWxlYXNlIGFzIHN0YWNrLW1hbmFnZWQu" + - "IERvIG5vdCBkZWxldGUgb3RoZXIgaGVsbSByZWxlYXNlcyBvciBuYW1lc3BhY2VzIG9uIHRoZSBj" + - "bHVzdGVyLgoKQmVmb3JlIGNvbnRyb2wtcGxhbmUgZGVzdHJveSwgaWRlbnRpZnkgd2hldGhlciBj" + - "ZXJ0LW1hbmFnZXIgaXMgZXh0ZXJuYWwuIEZvciBhbiBleHRlcm5hbCBpbnN0YWxsYXRpb24sIHJl" + - "cXVpcmUgZWZmZWN0aXZlIGBjZXJ0TWFuYWdlci5lbmFibGVkOiBmYWxzZWAgYW5kIGFib3J0IGlm" + - "IGl0IGlzIHRydWUuIEZvciBhbiBpbnRlbmRlZCBzdGFjay1tYW5hZ2VkIHJlbGVhc2Ugd2l0aCBl" + - "ZmZlY3RpdmUgYGNlcnRNYW5hZ2VyLmVuYWJsZWQ6IHRydWVgLCB2ZXJpZnkgbWF0Y2hpbmcgc3Rh" + - "Y2sgSGVsbSByZWxlYXNlIG1ldGFkYXRhIGFuZCBhYm9ydCBvbiBtaXNzaW5nIG9yIG1pc21hdGNo" + - "ZWQgZXZpZGVuY2UuIFByZXNlcnZlIHRoZSBuYW1lc3BhY2UgYnkgZGVmYXVsdDsgb25seSBwbGFu" + - "IGl0cyByZW1vdmFsIGFmdGVyIHZlcmlmeWluZyBuYW1lc3BhY2UgcHJvdmVuYW5jZSBhbmQgZ2V0" + - "dGluZyBleHBsaWNpdCBjb25maXJtYXRpb24uCgojIyMgU3RhbmRhcmQgdGVhcmRvd24KClJ1biBm" + - "cm9tIGluc2lkZSB0aGUgYG52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrL2AgZGlyZWN0b3J5OgoKYGBg" + - "YmFzaApIRUxNRklMRV9FTlY9PGVudi1uYW1lPiBoZWxtZmlsZSBkZXN0cm95CmBgYAoKIyMjIERl" + - "bGV0ZSBuYW1lc3BhY2VzCgpgYGBiYXNoCmZvciBucyBpbiBjYXNzYW5kcmEtc3lzdGVtIG5hdHMt" + - "c3lzdGVtIG52Y2YgYXBpLWtleXMgZXNzIHNpcyBudmNmLXVpIHZhdWx0LXN5c3RlbTsgZG8KICBr" + - "dWJlY3RsIGRlbGV0ZSBuYW1lc3BhY2UgIiRucyIgLS1pZ25vcmUtbm90LWZvdW5kCmRvbmUKYGBg" + - "CgojIyMgVmVyaWZ5IGNsZWFuCgpgYGBiYXNoCmt1YmVjdGwgZ2V0IG5zIHwgZ3JlcCAtRSAnKGNh" + - "c3NhbmRyYXxuYXRzfHZhdWx0fG52Y2Z8YXBpLWtleXN8ZXNzfHNpcyknCiMgU2hvdWxkIHJldHVy" + - "biBlbXB0eQpgYGAKCiMjIE92ZXJyaWRpbmcgSGVsbSBDaGFydCBWYWx1ZXMKCiMjIyBFbnZpcm9u" + - "bWVudCBmaWxlIChsaW1pdGVkKQoKV29ya3Mgb25seSBmb3Iga2V5cyB0aGF0IGBnbG9iYWwueWFt" + - "bC5nb3RtcGxgIHByb3BhZ2F0ZXMgKGUuZy4sIGBjYXNzYW5kcmEucmVwbGljYUNvdW50YCwgYGds" + - "b2JhbC5zdG9yYWdlQ2xhc3NgLCBgZ2xvYmFsLmltYWdlYCkuCgojIyMgUmVsZWFzZSB2YWx1ZXMg" + - "YmxvY2sgKGFueSBjaGFydCB2YWx1ZSkKCkVkaXQgdGhlIHJlbGVhc2UgaW4gYGhlbG1maWxlLmQv" + - "Ki55YW1sLmdvdG1wbGAgYW5kIGFkZCBhIGB2YWx1ZXM6YCBibG9jay4gSW4gdGhlIGV4YW1wbGVz" + - "IGJlbG93LCBgPHByaXZhdGUtdmFsdWVzPmAgcmVmZXJzIHRvIHRoZSBgc2VjcmV0cy9gIGRpcmVj" + - "dG9yeSBhdCB0aGUgaGVsbWZpbGUgc3RhY2sgcm9vdC4KCmBgYHlhbWwKLSBuYW1lOiBjYXNzYW5k" + - "cmEKICB2ZXJzaW9uOiAwLjguMAogIGNvbmRpdGlvbjogY2Fzc2FuZHJhLmVuYWJsZWQKICBuYW1l" + - "c3BhY2U6IGNhc3NhbmRyYS1zeXN0ZW0KICA8PDogKmRlcGVuZGVuY3kKICB2YWx1ZXM6CiAgICAt" + - "IC4uL2dsb2JhbC55YW1sLmdvdG1wbAogICAgLSAuLi88cHJpdmF0ZS12YWx1ZXM+L3t7IHJlcXVp" + - "cmVkRW52ICJIRUxNRklMRV9FTlYiIH19LXNlY3JldHMueWFtbAogICAgLSBjYXNzYW5kcmE6CiAg" + - "ICAgICAgcmVzb3VyY2VzOgogICAgICAgICAgbGltaXRzOgogICAgICAgICAgICBjcHU6ICI4Igog" + - "ICAgICAgICAgICBtZW1vcnk6IDgxOTJNaQogICAgICAgICAgcmVxdWVzdHM6CiAgICAgICAgICAg" + - "IGNwdTogIjIiCiAgICAgICAgICAgIG1lbW9yeTogNDA5Nk1pCmBgYAoKWUFNTCBtZXJnZSBnb3Rj" + - "aGE6IFdoZW4gYSByZWxlYXNlIHVzZXMgYDw8OiAqZGVwZW5kZW5jeWAgb3IgYGluaGVyaXRgLCBz" + - "cGVjaWZ5aW5nIGB2YWx1ZXM6YCByZXBsYWNlcyB0aGUgdGVtcGxhdGUncyB2YWx1ZXMgbGlzdC4g" + - "WW91IG11c3QgcmUtaW5jbHVkZSBgZ2xvYmFsLnlhbWwuZ290bXBsYCBhbmQgdGhlIHNlY3JldHMg" + - "ZmlsZS4KCiMjIyBQcmV2aWV3IGFuZCBhcHBseSBhIHNpbmdsZSByZWxlYXNlCgpgYGBiYXNoCkhF" + - "TE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9Y2Fzc2FuZHJhIHRlbXBs" + - "YXRlICAjIFByZXZpZXcKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFt" + - "ZT1jYXNzYW5kcmEgc3luYyAgICAgICMgQXBwbHkKYGBgCgojIyBJbWFnZSBQdWxsIFNlY3JldHMK" + - "ClRoZXJlIGFyZSB0aHJlZSBkaXN0aW5jdCBjcmVkZW50aWFsIHR5cGVzLiBEbyBub3QgY29uZmxh" + - "dGUgdGhlbSwgYW5kIG1pbmQgdGhlCmZvcm1hdCBydWxlIGJlbG93ICh0d28gb2YgdGhlbSBmYWls" + - "IGV2ZW4gd2l0aCB0aGUgY29ycmVjdCBrZXkgaWYgdGhlIGZvcm1hdCBpcyB3cm9uZyk6Cgp8IHwg" + - "Q29udHJvbCBQbGFuZSBQdWxsIFNlY3JldHMgfCBBUEkgQm9vdHN0cmFwIFJlZ2lzdHJ5IENyZWRz" + - "IHwgU2lkZWNhciBJbWFnZS1QdWxsIFNlY3JldCB8CnwtLS18LS0tfC0tLXwtLS18CnwgUHVycG9z" + - "ZSB8IEs4cyBwdWxscyBOVkNGIHNlcnZpY2UgaW1hZ2VzIHwgbnZjZi1hcGkgdmFsaWRhdGVzIHRo" + - "ZSB1c2VyIGZ1bmN0aW9uIGltYWdlIGF0IGBmdW5jdGlvbiBjcmVhdGVgIHwgbnZjZi1hcGkgcHVs" + - "bHMgdGhlIHBsYXRmb3JtIHNpZGVjYXJzIGluamVjdGVkIGludG8gZXZlcnkgd29ya2VyIHBvZCB8" + - "CnwgV2hlcmUgfCBLOHMgYGRvY2tlci1yZWdpc3RyeWAgU2VjcmV0cyArIEt5dmVybm8gQ2x1c3Rl" + - "clBvbGljeSB8IGA8cHJpdmF0ZS12YWx1ZXM+LzxlbnY+LXNlY3JldHMueWFtbGAgKGFjY291bnQt" + - "Ym9vdHN0cmFwKSB8IGBOVkNGX0FQSV9TSURFQ0FSU19JTUFHRV9QVUxMX1NFQ1JFVGAgaW4gYDxl" + - "bnY+LXNlY3JldHMueWFtbGAgLT4gT3BlbkJhbyBgc2VydmljZXMvbnZjZi1hcGkva3Yvc2lkZWNh" + - "cnMvaW1hZ2UtcHVsbC1zZWNyZXRgIChmaWVsZCBgc2VjcmV0YCkgfAp8IEZvcm1hdCB8IHN0YW5k" + - "YXJkIGAuZG9ja2VyY29uZmlnanNvbmAgKGt1YmVjdGwgYnVpbGRzIGl0IGZvciB5b3UpIHwgYGJh" + - "c2U2NCgiJG9hdXRodG9rZW46PGtleT4iKWAgfCBgYmFzZTY0KCIkb2F1dGh0b2tlbjo8a2V5PiIp" + - "YCB8Cgo+IE5vdGU6IHRoZSBhY2NvdW50LWJvb3RzdHJhcCBjcmVkIGFuZCB0aGUgc2lkZWNhciBz" + - "ZWNyZXQgYXJlIE5PVCBhCj4gZG9ja2VyY29uZmlnanNvbi4gVGhlIHNlY3JldHMgdGVtcGxhdGUg" + - "c2hpcHMgdGhlIHBsYWNlaG9sZGVyCj4gYFJFUExBQ0VfV0lUSF9CQVNFNjRfRE9DS0VSX0NSRURF" + - "TlRJQUxgLCB3aGljaCByZWFkcyBhcyAiYmFzZTY0IG9mIGEgZG9ja2VyY29uZmlnanNvbi4iCj4g" + - "SXQgaXNuJ3QuIEJvdGggdmFsdWVzIGFyZSBjb25zdW1lZCBhcyBhIHJhdyBkb2NrZXIgYGF1dGhg" + - "IHN0cmluZzogbnZjZi1hcGkgdGFrZXMgdGhlCj4gdmFsdWUgdmVyYmF0aW0gYW5kIGRyb3BzIGl0" + - "IGludG8gdGhlIGBhdXRoYCBmaWVsZCBvZiB0aGUgZG9ja2VyY29uZmlnIGl0IGJ1aWxkcy4gU28g" + - "dGhlCj4gdmFsdWUgbXVzdCBiZSBgYmFzZTY0KCIkb2F1dGh0b2tlbjo8a2V5PiIpYCwgZS5nLiBg" + - "cHJpbnRmICckb2F1dGh0b2tlbjolcycgIiRLRVkiIHwgb3BlbnNzbCBiYXNlNjQgLUFgLAo+IG5v" + - "dCBgYmFzZTY0KDxkb2NrZXJjb25maWdqc29uPilgLgo+ICAtIFdyb25nIGFjY291bnQtYm9vdHN0" + - "cmFwIHZhbHVlOiBgZnVuY3Rpb24gY3JlYXRlYCByZXR1cm5zCj4gICAgYDQwMCAibXVzdCBiZSBi" + - "YXNlNjQgZW5jb2RlZCB1c2VybmFtZTpwYXNzd29yZCBmb3JtYXQiYC4KPiAgLSBXcm9uZyBzaWRl" + - "Y2FyIHZhbHVlOiBldmVyeSB3b3JrZXIncyBzaWRlY2FyIHB1bGwgZ2V0cyBhIG1hbGZvcm1lZCBj" + - "cmVkZW50aWFsIGFuZAo+ICAgIGA0MDNgcywgcmVnYXJkbGVzcyBvZiB3aGljaCBrZXkgaXMgaW5z" + - "aWRlLiBUaGUgc3ltcHRvbSBsb29rcyBsaWtlIGEgYmFkIG9yIHdyb25nLW9yZwo+ICAgIGtleSwg" + - "YnV0IHRoZSBrZXkgaXMgZmluZSBhbmQgdGhlIGVuY29kaW5nIGlzIHRoZSBidWcuIFRvIHJlcGFp" + - "ciBhbiBhbHJlYWR5LWluc3RhbGxlZAo+ICAgIHN0YWNrIHdpdGhvdXQgYSBmdWxsIHJlLXN5bmM6" + - "Cj4gICAgYGBgYmFzaAo+ICAgIEFVVEg9JChwcmludGYgJyRvYXV0aHRva2VuOiVzJyAiJEtFWSIg" + - "fCBvcGVuc3NsIGJhc2U2NCAtQSkKPiAgICBiYW8ga3YgcHV0IHNlcnZpY2VzL252Y2YtYXBpL2t2" + - "L3NpZGVjYXJzL2ltYWdlLXB1bGwtc2VjcmV0IHNlY3JldD0iJEFVVEgiCj4gICAgIyBpZiBOVklE" + - "SUEgQ2xvdWQgVGFza3MgaXMgZW5hYmxlZCwgcmVwZWF0IGZvciBzZXJ2aWNlcy9udmN0LWFwaS9r" + - "di9zaWRlY2Fycy9pbWFnZS1wdWxsLXNlY3JldAo+ICAgIGt1YmVjdGwgcm9sbG91dCByZXN0YXJ0" + - "IC1uIG52Y2YgZGVwbG95L252Y2YtYXBpICAgIyBwaWNrcyB1cCB0aGUgbmV3IHNpZGVjYXIgY3Jl" + - "ZAo+ICAgIGBgYAoKPiBOb3RlIChtdWx0aS1vcmcpOiB3aGVuIHB1bGxpbmcgZnJvbSBOR0MgKG5v" + - "dCBhIG1pcnJvciksIHRoZSB1c2VyIGZ1bmN0aW9uIGltYWdlIGFuZAo+IHRoZSBwbGF0Zm9ybSBz" + - "aWRlY2FycyBvZnRlbiBsaXZlIGluIGRpZmZlcmVudCBudmNyLmlvIG9yZ3MsIGVhY2ggbmVlZGlu" + - "ZyBhIGRpZmZlcmVudAo+IGtleSwgc28gdGhlIGFjY291bnQtYm9vdHN0cmFwIGNyZWQgKGZ1bmN0" + - "aW9uIGltYWdlKSBhbmQgdGhlIHNpZGVjYXIgc2VjcmV0IChzaWRlY2FycykKPiBhcmUgZnJlcXVl" + - "bnRseSB0d28gZGlmZmVyZW50IGtleXMuIE1pcnJvcmluZyBldmVyeXRoaW5nIGludG8gYSBzaW5n" + - "bGUgcmVnaXN0cnkgdGhlCj4gY2x1c3RlciBhdXRoZW50aWNhdGVzIHRvIGF1dG9tYXRpY2FsbHkg" + - "Y29sbGFwc2VzIHRoaXMgdG8gb25lIGNyZWRlbnRpYWwgcGF0aC4KCiMjIyBDb25maWd1cmluZyB3" + - "aXRoIEt5dmVybm8gKHJlY29tbWVuZGVkKQoKVXNlIGEgS3l2ZXJubyBtdXRhdGluZyBhZG1pc3Np" + - "b24gcG9saWN5IHRvIGF1dG9tYXRpY2FsbHkgaW5qZWN0IGBpbWFnZVB1bGxTZWNyZXRzYCBpbnRv" + - "IGFsbCBwb2RzIGluIE5WQ0YgbmFtZXNwYWNlcy4gVGhpcyB3b3JrcyB1bmlmb3JtbHkgZm9yIGFs" + - "bCBjaGFydHMgLS0gbm8gcGVyLWNoYXJ0IGNvbmZpZ3VyYXRpb24gb3IgaGVsbWZpbGUgbW9kaWZp" + - "Y2F0aW9ucyBuZWVkZWQuCgpgYGBiYXNoCiMgMS4gSW5zdGFsbCBLeXZlcm5vCmhlbG0gcmVwbyBh" + - "ZGQga3l2ZXJubyBodHRwczovL2t5dmVybm8uZ2l0aHViLmlvL2t5dmVybm8vCmhlbG0gcmVwbyB1" + - "cGRhdGUKaGVsbSBpbnN0YWxsIGt5dmVybm8ga3l2ZXJuby9reXZlcm5vIC1uIGt5dmVybm8gLS1j" + - "cmVhdGUtbmFtZXNwYWNlCgojIDIuIENyZWF0ZSBwdWxsIHNlY3JldCBpbiBlYWNoIG5hbWVzcGFj" + - "ZQpleHBvcnQgTkdDX0FQSV9LRVk9Ijx5b3VyLWtleT4iCmZvciBucyBpbiBjYXNzYW5kcmEtc3lz" + - "dGVtIG5hdHMtc3lzdGVtIG52Y2YgYXBpLWtleXMgZXNzIHNpcyB2YXVsdC1zeXN0ZW0gY2VydC1t" + - "YW5hZ2VyOyBkbwogIGt1YmVjdGwgY3JlYXRlIHNlY3JldCBkb2NrZXItcmVnaXN0cnkgbnZjci1j" + - "cmVkcyBcCiAgICAtLWRvY2tlci1zZXJ2ZXI9bnZjci5pbyBcCiAgICAtLWRvY2tlci11c2VybmFt" + - "ZT0nJG9hdXRodG9rZW4nIFwKICAgIC0tZG9ja2VyLXBhc3N3b3JkPSIkTkdDX0FQSV9LRVkiIFwK" + - "ICAgIC0tbmFtZXNwYWNlPSIkbnMiIFwKICAgIC0tZHJ5LXJ1bj1jbGllbnQgLW8geWFtbCB8IGt1" + - "YmVjdGwgYXBwbHkgLWYgLQpkb25lCgojIDMuIEFwcGx5IHRoZSBLeXZlcm5vIENsdXN0ZXJQb2xp" + - "Y3kKa3ViZWN0bCBhcHBseSAtZiBreXZlcm5vLWltYWdlcHVsbHNlY3JldC1wb2xpY3kueWFtbApg" + - "YGAKClRoZSBwb2xpY3kgbXV0YXRlcyBldmVyeSBwb2QgYXQgYWRtaXNzaW9uIHRpbWUsIGFkZGlu" + - "ZyBgaW1hZ2VQdWxsU2VjcmV0czogW3tuYW1lOiBudmNyLWNyZWRzfV1gLiBWZXJpZnkgd2l0aDoK" + - "CmBgYGJhc2gKa3ViZWN0bCBnZXQgcG9kIC1uIDxuYW1lc3BhY2U+IDxwb2QtbmFtZT4gLW8ganNv" + - "bnBhdGg9J3suc3BlYy5pbWFnZVB1bGxTZWNyZXRzfScKIyBTaG91bGQgc2hvdzogW3sibmFtZSI6" + - "Im52Y3ItY3JlZHMifV0KYGBgCgpOb3QgbmVlZGVkIGlmIHVzaW5nIGEgQ1NQIGJ1aWx0LWluIGNy" + - "ZWRlbnRpYWwgaGVscGVyIChlLmcuLCBFQ1Igd2l0aCBJQU0gbm9kZSByb2xlcykuCgpGb3IgdGhl" + - "IEt5dmVybm8gcG9saWN5IFlBTUwgYW5kIHB1bGwgc2VjcmV0IGNyZWF0aW9uIHNjcmlwdCwgc2Vl" + - "IFtyZWZlcmVuY2VzL3B1bGwtc2VjcmV0cy5tZF0ocmVmZXJlbmNlcy9wdWxsLXNlY3JldHMubWQp" + - "LgoKIyMgRGVidWdnaW5nCgojIyMgUXVpY2sgc3RhdHVzIGNoZWNrCgpgYGBiYXNoCmt1YmVjdGwg" + - "Z2V0IHBvZHMgLUEgLW8gd2lkZSAgICAgICAgICAgICAgICAgICAgICAgICMgQWxsIHBvZHMKaGVs" + - "bSBsaXN0IC1BICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQWxsIGhl" + - "bG0gcmVsZWFzZXMKa3ViZWN0bCBnZXQgZXZlbnRzIC1uIDxucz4gLS1zb3J0LWJ5PScubGFzdFRp" + - "bWVzdGFtcCcgICMgUmVjZW50IGV2ZW50cwpgYGAKCiMjIyBDb21tb24gZmFpbHVyZSBwYXR0ZXJu" + - "cwoKfCBTeW1wdG9tIHwgQ2F1c2UgfCBGaXggfAp8LS0tLS0tLS0tfC0tLS0tLS18LS0tLS18Cnwg" + - "YEltYWdlUHVsbEJhY2tPZmZgICsgYDQwMSBVbmF1dGhvcml6ZWRgIHwgTWlzc2luZyBvciB3cm9u" + - "ZyBwdWxsIHNlY3JldCB8IENoZWNrIHNlY3JldCBleGlzdHMsIGNoZWNrIFNBIGhhcyBpbWFnZVB1" + - "bGxTZWNyZXRzIHwKfCBgSW5pdDowLzFgIHN0dWNrIG9uIHNlcnZpY2UgcG9kcyB8IFZhdWx0LWFn" + - "ZW50IHdhaXRpbmcgZm9yIE9wZW5CYW8gfCBDaGVjayBPcGVuQmFvIHBvZHMgKyBtaWdyYXRpb24g" + - "am9iIHN0YXR1cyB8CnwgYEluaXQ6MC8xYCArIGB2YXVsdC1hZ2VudC1pbml0YCBzaG93cyBgYXV0" + - "aC9qd3QvbG9naW5gIC0+IGA0MDAgLi4uIG5vIGtub3duIGtleSBzdWNjZXNzZnVsbHkgdmFsaWRh" + - "dGVkIHRoZSB0b2tlbiBzaWduYXR1cmVgIHwgT3BlbkJhbyBKV1QgYXV0aCBjb25maWd1cmVkIHdp" + - "dGggYSBzdGF0aWMgcHVia2V5IGluc3RlYWQgb2YgdGhlIGNsdXN0ZXIncyBsaXZlIEpXS1MgLS0g" + - "dGhlIGJhc2UgZGVmYXVsdCBgb3BlbmJhby5taWdyYXRpb25zLmlzc3VlckRpc2NvdmVyeS5lbmFi" + - "bGVkOiBmYWxzZWAuIENvbW1vbiBvbiBBS1MgLyBhbnkgT0lEQy1pc3N1ZXIgY2x1c3RlciB8IFNl" + - "dCBgb3BlbmJhby5taWdyYXRpb25zLmlzc3VlckRpc2NvdmVyeS5lbmFibGVkOiB0cnVlYCwgZGVs" + - "ZXRlIGpvYiBgb3BlbmJhby1zZXJ2ZXItbWlncmF0aW9uc2AsIHJlLXN5bmMgYG9wZW5iYW8tc2Vy" + - "dmVyYC4gU2VlIFtyZWZlcmVuY2VzL2RlYnVnZ2luZy5tZF0ocmVmZXJlbmNlcy9kZWJ1Z2dpbmcu" + - "bWQpICJJbml0OjAvMSBTdHVjayIgZml4ICM0LiB8CnwgYE9PTUtpbGxlZGAgb24gQ2Fzc2FuZHJh" + - "IHwgRGVmYXVsdCByZXNvdXJjZXMgdG9vIHNtYWxsIHwgT3ZlcnJpZGUgYGNhc3NhbmRyYS5yZXNv" + - "dXJjZXNgIHZpYSB2YWx1ZXMgYmxvY2sgfAp8IERCLWJhY2tlZCBzZXJ2aWNlcyBjcmFzaC1sb29w" + - "IGBCYWQgY3JlZGVudGlhbHNgIGNvbm5lY3RpbmcgdG8gQ2Fzc2FuZHJhIHwgU2VjcmV0cyBmaWxl" + - "IHNldCBvbmx5IGBERUZBVUxUX0NBU1NBTkRSQV9QQVNTV09SRGA7IGBjYXNzYW5kcmEuc2Vydmlj" + - "ZVJvbGVQYXNzd29yZGAgc3RpbGwgZGVmYXVsdHMgdG8gYGNoQG5nM20zYCB8IFNldCBgY2Fzc2Fu" + - "ZHJhLnNlcnZpY2VSb2xlUGFzc3dvcmRgIGluIHRoZSBzZWNyZXRzIGZpbGUgZXF1YWwgdG8gYERF" + - "RkFVTFRfQ0FTU0FORFJBX1BBU1NXT1JEYCwgdGhlbiByZS1zeW5jIGNhc3NhbmRyYSArIHRoZSBE" + - "Qi1iYWNrZWQgc2VydmljZXMgfAp8IGBQZW5kaW5nYCBwb2RzIHwgTm9kZSBzZWxlY3RvciBtaXNt" + - "YXRjaCBvciBubyBzdG9yYWdlIGNsYXNzIHwgYGt1YmVjdGwgZGVzY3JpYmUgcG9kYCwgY2hlY2sg" + - "bGFiZWxzIGFuZCBzdG9yYWdlIHwKfCBIZWxtIHJlbGVhc2UgaW4gYGZhaWxlZGAgc3RhdGUgfCBG" + - "aXJzdCBpbnN0YWxsIGZhaWxlZCBwYXJ0d2F5IHwgYGhlbG1maWxlIGRlc3Ryb3lgIHRoZSByZWxl" + - "YXNlLCB0aGVuIGBzeW5jYCBhZ2FpbiB8CnwgQWNjb3VudCBib290c3RyYXAgdGltZW91dCB8IFdy" + - "b25nIGJhc2U2NCBjcmVkZW50aWFscyBpbiBzZWNyZXRzIGZpbGUgfCBDaGVjayBga3ViZWN0bCBs" + - "b2dzIGpvYi9udmNmLWFwaS1hY2NvdW50LWJvb3RzdHJhcCAtbiBudmNmYCB8CnwgZnVuY3Rpb24g" + - "LyBhY2NvdW50IGNhbGxzIHJldHVybiBgNDA0IFVua25vd24gY2xpZW50X2lkYCB8IFRoZSBhY2Nv" + - "dW50LWJvb3RzdHJhcCBwb3N0LWluc3RhbGwgaG9vayBuZXZlciByYW46IHRoZSBgYXBpYCByZWxl" + - "YXNlIGluc3RhbGwgZmFpbGVkLCBvciB3YXMgcmVwYWlyZWQgd2l0aCBsaXZlIHBhdGNoZXMgaW5z" + - "dGVhZCBvZiBhIGNsZWFuIHJlLXN5bmMsIHNvIHRoZSBob29rIChhbmQgdGhlIGFjY291bnQpIHdh" + - "cyBza2lwcGVkIHwgVmVyaWZ5IGFuZCByZS1ydW4gdGhlIGhvb2s7IHNlZSBbVmVyaWZ5IHRoZSBh" + - "Y2NvdW50IGJvb3RzdHJhcCByYW5dKCN2ZXJpZnktdGhlLWFjY291bnQtYm9vdHN0cmFwLXJhbikg" + - "fAp8IFNlcnZpY2VzIGZhaWwgdG8gcmVhZCB2YXVsdCBzZWNyZXRzOyBgc2VjcmV0cy5qc29uYCBu" + - "b3QgZm91bmQgfCBWYXVsdCBwYXRoIGhhcmRjb2RlZCB0byBgL2hvbWUvYXBwL3ZhdWx0L2AgaW4g" + - "YF9oZWxwZXJzLnRwbGA7IHRoZSBydW50aW1lIHJlc29sdmVzIHRoZSBtb3VudGVkIHBhdGggcmVs" + - "YXRpdmUgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGFuZCBkcm9wcyB0aGUgbGVhZGluZyBgL2Ag" + - "fCBPdmVycmlkZSBgcG9kQW5ub3RhdGlvbnNgIGFuZCBzZXQgYEpBVkFfVE9PTF9PUFRJT05TOiAi" + - "LUR1c2VyLmRpcj0vImAgaW4gcmVsZWFzZSB2YWx1ZXMgfAp8IE5BVFMgY29ubmVjdGlvbiBmYWls" + - "cyBhdCBzdGFydHVwOyBwbGFjZW1lbnQgdGFnIG1pc21hdGNoIHwgTkFUUyBzZXJ2ZXIgdGFncyBo" + - "YXJkY29kZWQgdG8gYGRjOm5jcGA7IGFwcCBkZXJpdmVzIHRhZyBmcm9tIGBBV1NfUkVHSU9OYCAo" + - "ZS5nLiwgYHVzLWdvdi13ZXN0LTFgKSB8IFNldCBgQVdTX1JFR0lPTj1uY3BgIGFuZCBgTlZDRl9B" + - "V1NfUkVHSU9OPW5jcGAgaW4gZW52IGNvbmZpZyB8CgojIyMgVmVyaWZ5IHRoZSBhY2NvdW50IGJv" + - "b3RzdHJhcCByYW4KClRoZSBkZWZhdWx0IGFjY291bnQgaXMgY3JlYXRlZCBieSBhICoqYHBvc3Qt" + - "aW5zdGFsbGAgaG9vayBvbiB0aGUgYGFwaWAgcmVsZWFzZSoqCihgam9iL252Y2YtYXBpLWFjY291" + - "bnQtYm9vdHN0cmFwYCBpbiBgbnZjZmApLiBCZWNhdXNlIGl0IGlzIGEgcG9zdC1pbnN0YWxsIGhv" + - "b2ssIGl0IG9ubHkKZmlyZXMgb24gYSBzdWNjZXNzZnVsIGBhcGlgIGluc3RhbGwuIElmIHRoYXQg" + - "aW5zdGFsbCBmYWlsZWQgYW5kIHlvdSByZXBhaXJlZCBpdCB3aXRoIGxpdmUKcGF0Y2hlcyAocmF0" + - "aGVyIHRoYW4gYSBjbGVhbiByZS1zeW5jKSwgdGhlIGhvb2sgbmV2ZXIgcnVucywgbm8gYWNjb3Vu" + - "dCBpcyBjcmVhdGVkLCBhbmQKZXZlcnkgc3Vic2VxdWVudCBmdW5jdGlvbi9hY2NvdW50IGNhbGwg" + - "cmV0dXJucyBhIGNyeXB0aWMgYDQwNCBVbmtub3duIGNsaWVudF9pZGAgd2l0aApub3RoaW5nIG9i" + - "dmlvdXNseSB3cm9uZyBpbiB0aGUgcnVubmluZyBwb2RzLgoKVmVyaWZ5IGl0IHJhbiBhZnRlciB0" + - "aGUgZmlyc3Qgc3luYzoKCmBgYGJhc2gKa3ViZWN0bCBnZXQgam9iIC1uIG52Y2YgbnZjZi1hcGkt" + - "YWNjb3VudC1ib290c3RyYXAgXAogIC1vIGpzb25wYXRoPSd7LnN0YXR1cy5zdWNjZWVkZWR9JyAg" + - "ICMgZXhwZWN0IDEKYGBgCgpJZiB0aGUgam9iIGlzIGFic2VudCBvciBgMGAsIHJlLXJ1biBpdCBi" + - "eSByZS1zeW5jaW5nIHRoZSBgYXBpYCByZWxlYXNlIHNvIHRoZSBob29rIGZpcmVzCmFnYWluIChk" + - "ZWxldGUgdGhlIHByaW9yIGpvYiBmaXJzdCBpZiBpdCBsaW5nZXJzIGluIGEgY29tcGxldGVkL2Zh" + - "aWxlZCBzdGF0ZSBhbmQgYmxvY2tzIHRoZQpob29rKToKCmBgYGJhc2gKa3ViZWN0bCBkZWxldGUg" + - "am9iIC1uIG52Y2YgbnZjZi1hcGktYWNjb3VudC1ib290c3RyYXAgLS1pZ25vcmUtbm90LWZvdW5k" + - "CkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9YXBpIHN5bmMKa3Vi" + - "ZWN0bCBsb2dzIC1uIG52Y2Ygam9iL252Y2YtYXBpLWFjY291bnQtYm9vdHN0cmFwICAgIyBjb25m" + - "aXJtIHRoZSBhY2NvdW50IHdhcyBjcmVhdGVkCmBgYAoKIyMgQWRkaXRpb25hbCBSZXNvdXJjZXMK" + - "Ci0gSW5zdGFsbGF0aW9uOiBbZXhhbXBsZXMubWRdKGV4YW1wbGVzLm1kKSwgdGhlIFtDU1AgRW5k" + - "LXRvLUVuZCBFeGFtcGxlXShodHRwczovL2RvY3MubnZpZGlhLmNvbS9udmNmL3YwLjYuMC1yYy9j" + - "c3AtZW5kLXRvLWVuZC1leGFtcGxlKSwgYW5kIFtzcGxpdCBjb21wdXRlLXBsYW5lIHdvcmtmbG93" + - "c10ocmVmZXJlbmNlcy9jb21wdXRlLXBsYW5lLWluc3RhbGxhdGlvbi5tZCkKLSBPcGVyYXRpb25z" + - "OiBbSGVsbWZpbGUgc3RydWN0dXJlXShyZWZlcmVuY2VzL2hlbG1maWxlLXN0cnVjdHVyZS5tZCks" + - "IFtwdWxsIHNlY3JldHNdKHJlZmVyZW5jZXMvcHVsbC1zZWNyZXRzLm1kKSwgYW5kIFtkZWJ1Z2dp" + - "bmddKHJlZmVyZW5jZXMvZGVidWdnaW5nLm1kKQoKQWZ0ZXIgZGVwbG95bWVudCwgdXNlIHRoZSBg" + - "bnZjZi1zZWxmLW1hbmFnZWQtY2xpYCBza2lsbCB0byBjcmVhdGUgZnVuY3Rpb25zLCBjcmVhdGUg" + - "dGFza3MsIG1hbmFnZSBBUEkga2V5cywgYW5kIGludm9rZSBlbmRwb2ludHMuClBLBwgv2rl1QmIA" + - "AEJiAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADQACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2Vk" + - "LWluc3RhbGxhdGlvbi9ldmFscy9ldmFscy5qc29uVVQFAAEAps4SWwogIHsKICAgICJpZCI6ICJH" + - "MS12YWxpZGF0ZS10b29sLXZlcnNpb25zIiwKICAgICJxdWVzdGlvbiI6ICJJbnN0YWxsIHRoZSBO" + - "VkNGIHNlbGYtbWFuYWdlZCBzdGFjayBvbiBteSBBV1MgRUtTIGNsdXN0ZXIiLAogICAgImV4cGVj" + - "dGVkX3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5k" + - "X3RydXRoIjogIlRoZSBhZ2VudCdzIGZpcnN0IG9wZXJhdGlvbmFsIHN0ZXAgYWZ0ZXIgcmVhZGlu" + - "ZyB0aGUgc2tpbGwgd2FzIHRvIHZhbGlkYXRlIGFsbCByZXF1aXJlZCB0b29sIHZlcnNpb25zOiBo" + - "ZWxtZmlsZSAobXVzdCBiZSAxLjEueCwgbm90IDEuMi4wKSwgaGVsbSAoPj0gMy4xMiksIGhlbG0t" + - "ZGlmZiBwbHVnaW4gKD49IDMuMTEpLCBhbmQga3ViZWN0bCAoY2xpZW50IHdpdGhpbiAxIG1pbm9y" + - "IG9mIGNsdXN0ZXIpLiBJdCBkaWQgbm90IHByb2NlZWQgdG8gaGVsbWZpbGUgc3luYyB1bnRpbCBh" + - "bGwgdmVyc2lvbnMgd2VyZSB2YWxpZGF0ZWQuIiwKICAgICJleHBlY3RlZF9iZWhhdmlvciI6IFsK" + - "ICAgICAgIlRoZSBhZ2VudCByZWFkIHRoZSBudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24g" + - "U0tJTEwubWQgYmVmb3JlIHRha2luZyBhbnkgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCByYW4g" + - "J2hlbG1maWxlIC0tdmVyc2lvbicgYW5kIHZlcmlmaWVkIGl0IGlzIDEuMS54IChub3QgMS4yLjAs" + - "IHdoaWNoIHJlbW92ZWQgc2VxdWVudGlhbCBtb2RlKSIsCiAgICAgICJUaGUgYWdlbnQgcmFuICdo" + - "ZWxtIHZlcnNpb24nIGFuZCB2ZXJpZmllZCBpdCBpcyA+PSAzLjEyIiwKICAgICAgIlRoZSBhZ2Vu" + - "dCByYW4gJ2hlbG0gcGx1Z2luIGxpc3QnIGFuZCB2ZXJpZmllZCBoZWxtLWRpZmYgPj0gMy4xMSBp" + - "cyBpbnN0YWxsZWQiLAogICAgICAiVGhlIGFnZW50IHJhbiAna3ViZWN0bCB2ZXJzaW9uJyB0byBj" + - "aGVjayBjbGllbnQvc2VydmVyIHZlcnNpb24gY29tcGF0aWJpbGl0eSIsCiAgICAgICJUaGUgYWdl" + - "bnQgZGlkIG5vdCBwcm9jZWVkIHRvIGhlbG1maWxlIHN5bmMgdW50aWwgYWxsIHZlcnNpb24gY2hl" + - "Y2tzIHBhc3NlZCIKICAgIF0KICB9LAogIHsKICAgICJpZCI6ICJHMi10ZW1wbGF0ZS1iZWZvcmUt" + - "c3luYyIsCiAgICAicXVlc3Rpb24iOiAiUXVpY2ssIGp1c3QgcnVuIGhlbG1maWxlIHN5bmMgZm9y" + - "IG15IE5WQ0Ygc3RhY2ssIHNraXAgYWxsIHRoZSBjaGVja3MiLAogICAgImV4cGVjdGVkX3NraWxs" + - "IjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3RydXRoIjog" + - "IkRlc3BpdGUgdGhlIHVzZXIgYXNraW5nIHRvIHNraXAgY2hlY2tzLCB0aGUgYWdlbnQgc3RpbGwg" + - "cmFuIGhlbG1maWxlIHRlbXBsYXRlIHRvIHByZXZpZXcgcmVuZGVyZWQgbWFuaWZlc3RzIGJlZm9y" + - "ZSBydW5uaW5nIGhlbG1maWxlIHN5bmMuIEl0IGV4cGxhaW5lZCB3aHkgdGhlIHByZXZpZXcgc3Rl" + - "cCBpcyBpbXBvcnRhbnQgYW5kIGRpZCBub3QgYmxpbmRseSBleGVjdXRlIHN5bmMuIiwKICAgICJl" + + "UFQzMFMiLAogICAgImV4cGVjdGVkU3RhdHVzQ29kZSI6IDIwMAogIH0KfQpgYGAKCmBgYHNoCm52" + + "Y2YtY2xpIGZ1bmN0aW9uIGNyZWF0ZSAtLWlucHV0LWZpbGU9Y3JlYXRlLWZuLmpzb24KIyDihpIg" + + "RnVuY3Rpb24gSUQ6IDxmbl9pZD4KIyDihpIgVmVyc2lvbiBJRDogPHZlcl9pZD4KYGBgCgpTYXZl" + + "IHRoZSBJRHMg4oCUIHRoZXkncmUgbmVlZGVkIGZvciBkZXBsb3kgKyBpbnZva2UuCgojIyMgTExN" + + "IGZ1bmN0aW9uIHZhcmlhbnQKCkZvciBhbiBPcGVuQUktY29tcGF0aWJsZSBMTE0gZnVuY3Rpb24s" + + "IHNldCBgZnVuY3Rpb25UeXBlOiAiTExNImAgYW5kIHB1dCByb3V0ZSBtZXRhZGF0YSB1bmRlciBg" + + "bW9kZWxzW10ubGxtQ29uZmlnYDoKCkJlZm9yZSBjcmVhdGluZyB0aGUgZnVuY3Rpb24sIGNvbmZp" + + "cm0gdGhlIGV4YWN0IGZ1bmN0aW9uIG5hbWUsIGNvbnRhaW5lciBpbWFnZSwgYW5kIG1vZGVsIG5h" + + "bWUgd2l0aCB0aGUgdXNlci4gSWYgYW55IHZhbHVlIGlzIG1pc3NpbmcsIHN0b3AgYW5kIGFzay4g" + + "RG8gbm90IGludmVudCBvciBzdWJtaXQgZXhhbXBsZSB2YWx1ZXMgZm9yIHRoZXNlIGZpZWxkcy4K" + + "CmBgYGpzb24KewogICJuYW1lIjogIjxjb25maXJtZWQtZnVuY3Rpb24tbmFtZT4iLAogICJjb250" + + "YWluZXJJbWFnZSI6ICI8Y29uZmlybWVkLWNvbnRhaW5lci1pbWFnZT4iLAogICJpbmZlcmVuY2VV" + + "cmwiOiAiLyIsCiAgImluZmVyZW5jZVBvcnQiOiA4MDAwLAogICJmdW5jdGlvblR5cGUiOiAiTExN" + + "IiwKICAiaGVhbHRoIjogewogICAgInByb3RvY29sIjogIkhUVFAiLAogICAgInVyaSI6ICIvaGVh" + + "bHRoIiwKICAgICJwb3J0IjogODAwMCwKICAgICJ0aW1lb3V0IjogIlBUMzBTIiwKICAgICJleHBl" + + "Y3RlZFN0YXR1c0NvZGUiOiAyMDAKICB9LAogICJtb2RlbHMiOiBbCiAgICB7CiAgICAgICJuYW1l" + + "IjogIjxjb25maXJtZWQtbW9kZWwtbmFtZT4iLAogICAgICAibGxtQ29uZmlnIjogewogICAgICAg" + + "ICJ1cmlzIjogWyIvdjEvY2hhdC9jb21wbGV0aW9ucyIsICIvdjEvcmVzcG9uc2VzIiwgIi92MS9l" + + "bWJlZGRpbmdzIl0sCiAgICAgICAgInJvdXRpbmdNZXRob2QiOiAicm91bmRfcm9iaW4iLAogICAg" + + "ICAgICJ0b2tlblJhdGVMaW1pdCI6ICIxMDAwLVMiCiAgICAgIH0KICAgIH0KICBdCn0KYGBgCgpF" + + "cXVpdmFsZW50IENMSSBmbGFnIGZvcm06CgpgYGBzaApudmNmLWNsaSBmdW5jdGlvbiBjcmVhdGUg" + + "XAogIC0tbmFtZT0iPGNvbmZpcm1lZC1mdW5jdGlvbi1uYW1lPiIgXAogIC0taW1hZ2U9Ijxjb25m" + + "aXJtZWQtY29udGFpbmVyLWltYWdlPiIgXAogIC0taW5mZXJlbmNlLXVybD0vIFwKICAtLWluZmVy" + + "ZW5jZS1wb3J0PTgwMDAgXAogIC0taGVhbHRoLXVyaT0vaGVhbHRoIFwKICAtLWhlYWx0aC1wb3J0" + + "PTgwMDAgXAogIC0taGVhbHRoLXRpbWVvdXQ9UFQzMFMgXAogIC0taGVhbHRoLXByb3RvY29sPUhU" + + "VFAgXAogIC0taGVhbHRoLWV4cGVjdGVkLXN0YXR1cz0yMDAgXAogIC0tZnVuY3Rpb24tdHlwZT1M" + + "TE0gXAogIC0tbGxtLW1vZGVsPSduYW1lPTxjb25maXJtZWQtbW9kZWwtbmFtZT4sdXJpcz0vdjEv" + + "Y2hhdC9jb21wbGV0aW9uc3wvdjEvcmVzcG9uc2VzfC92MS9lbWJlZGRpbmdzLHJvdXRpbmdNZXRo" + + "b2Q9cm91bmRfcm9iaW4sdG9rZW5SYXRlTGltaXQ9MTAwMC1TJwpgYGAKClVzZSB0aGUgc2FtZSBk" + + "ZXBsb3kgc3RlcCBiZWxvdyBhZnRlciB0aGUgTExNIGZ1bmN0aW9uIGlzIGNyZWF0ZWQuCgpPcHRp" + + "b25hbCBtb2RlbCByb3V0aW5nIHVwZGF0ZSBhZnRlciBjcmVhdGlvbjoKCmBgYHNoCm52Y2YtY2xp" + + "IGZ1bmN0aW9uIHVwZGF0ZSBcCiAgLS1mdW5jdGlvbi1pZD08Zm5faWQ+IFwKICAtLXZlcnNpb24t" + + "aWQ9PHZlcl9pZD4gXAogIC0tbGxtLW1vZGVsLXVwZGF0ZT0nbmFtZT08Y29uZmlybWVkLW1vZGVs" + + "LW5hbWU+LHJvdXRpbmdNZXRob2Q9cG93ZXJfb2ZfdHdvLHRva2VuUmF0ZUxpbWl0PTEwMDAtUycK" + + "YGBgCgpVc2UgdGhpcyBmb3IgbXV0YWJsZSBgcm91dGluZ01ldGhvZGAgYW5kIGB0b2tlblJhdGVM" + + "aW1pdGA7IGNyZWF0ZS10aW1lIGB1cmlzYCBzdGF5IGluIGBtb2RlbHNbXS5sbG1Db25maWdgLgpg" + + "dG9rZW5SYXRlTGltaXRgIHN1cHBvcnRzIHBvc2l0aXZlIGludGVnZXIgdG9rZW4gbGltaXRzIGZv" + + "ciBgU2AsIGBNYCwgYEhgLCBgRGAsIGFuZCBgV2AuIFVzZSBgMTAwMC1TYCBmb3IgYSBzaW5nbGUg" + + "aW5saW5lIENMSSBsaW1pdC4gVXNlIGlucHV0IEpTT04gZm9yIGNvbWJpbmVkIGxpbWl0cywgc3Vj" + + "aCBhcyBgMTAwMC1TLDUwMDAtTSwxMDAwMDAtSCw1MDAwMDAtRCwxMDAwMDAwLVdgLCBiZWNhdXNl" + + "IGlubGluZSBtb2RlbCBzcGVjcyB1c2UgY29tbWFzIGFzIGZpZWxkIHNlcGFyYXRvcnMuCgojIyMg" + + "SGVsbSBjaGFydCBMTE0gZnVuY3Rpb24gdmFyaWFudAoKTExNIGZ1bmN0aW9uIHR5cGUgaXMgaW5k" + + "ZXBlbmRlbnQgb2Ygd29ya2xvYWQgcGFja2FnaW5nLiBGb3IgYSBIZWxtLWNoYXJ0IGJhY2tlZCBM" + + "TE0gZnVuY3Rpb24sIGtlZXAgdGhlIHNhbWUgYGZ1bmN0aW9uVHlwZWAgYW5kIGBtb2RlbHNbXS5s" + + "bG1Db25maWdgIGZpZWxkcywgdGhlbiBzZXQgYGhlbG1DaGFydGAgYW5kIGBoZWxtQ2hhcnRTZXJ2" + + "aWNlTmFtZWAuIFRoZSBzZXJ2aWNlIG5hbWUgbXVzdCBtYXRjaCBhIEt1YmVybmV0ZXMgU2Vydmlj" + + "ZSByZW5kZXJlZCBieSB0aGUgY2hhcnQsIGFuZCBgaW5mZXJlbmNlUG9ydGAgbXVzdCBiZSB0aGF0" + + "IFNlcnZpY2UgcG9ydC4KCkJlZm9yZSBjcmVhdGluZyB0aGUgZnVuY3Rpb24sIGNvbmZpcm0gdGhl" + + "IGV4YWN0IGZ1bmN0aW9uIG5hbWUgYW5kIG1vZGVsIG5hbWUgd2l0aCB0aGUgdXNlci4gSWYgZWl0" + + "aGVyIHZhbHVlIGlzIG1pc3NpbmcsIHN0b3AgYW5kIGFzay4gRG8gbm90IGludmVudCBvciBzdWJt" + + "aXQgZXhhbXBsZSB2YWx1ZXMgZm9yIHRoZXNlIGZpZWxkcy4KCmBgYGpzb24KewogICJuYW1lIjog" + + "Ijxjb25maXJtZWQtZnVuY3Rpb24tbmFtZT4iLAogICJpbmZlcmVuY2VVcmwiOiAiLyIsCiAgImlu" + + "ZmVyZW5jZVBvcnQiOiA4MDAwLAogICJmdW5jdGlvblR5cGUiOiAiTExNIiwKICAiaGVhbHRoIjog" + + "ewogICAgInByb3RvY29sIjogIkhUVFAiLAogICAgInVyaSI6ICIvaGVhbHRoIiwKICAgICJwb3J0" + + "IjogODAwMCwKICAgICJ0aW1lb3V0IjogIlBUMzBTIiwKICAgICJleHBlY3RlZFN0YXR1c0NvZGUi" + + "OiAyMDAKICB9LAogICJoZWxtQ2hhcnQiOiAiaHR0cHM6Ly9oZWxtLm5nYy5udmlkaWEuY29tL2V4" + + "YW1wbGUvdGVhbS9jaGFydHMvb3BlbmFpLWNvbXBhdGlibGUtMC4xLjAudGd6IiwKICAiaGVsbUNo" + + "YXJ0U2VydmljZU5hbWUiOiAib3BlbmFpLWNvbXBhdGlibGUiLAogICJtb2RlbHMiOiBbCiAgICB7" + + "CiAgICAgICJuYW1lIjogIjxjb25maXJtZWQtbW9kZWwtbmFtZT4iLAogICAgICAibGxtQ29uZmln" + + "IjogewogICAgICAgICJ1cmlzIjogWyIvdjEvY2hhdC9jb21wbGV0aW9ucyIsICIvdjEvcmVzcG9u" + + "c2VzIiwgIi92MS9lbWJlZGRpbmdzIl0sCiAgICAgICAgInJvdXRpbmdNZXRob2QiOiAicm91bmRf" + + "cm9iaW4iLAogICAgICAgICJ0b2tlblJhdGVMaW1pdCI6ICIxMDAwLVMiCiAgICAgIH0KICAgIH0K" + + "ICBdCn0KYGBgCgpFcXVpdmFsZW50IENMSSBmbGFnIGZvcm06CgpgYGBzaApudmNmLWNsaSBmdW5j" + + "dGlvbiBjcmVhdGUgXAogIC0tbmFtZT0iPGNvbmZpcm1lZC1mdW5jdGlvbi1uYW1lPiIgXAogIC0t" + + "aW5mZXJlbmNlLXVybD0vIFwKICAtLWluZmVyZW5jZS1wb3J0PTgwMDAgXAogIC0taGVhbHRoLXVy" + + "aT0vaGVhbHRoIFwKICAtLWhlYWx0aC1wb3J0PTgwMDAgXAogIC0taGVhbHRoLXRpbWVvdXQ9UFQz" + + "MFMgXAogIC0taGVhbHRoLXByb3RvY29sPUhUVFAgXAogIC0taGVhbHRoLWV4cGVjdGVkLXN0YXR1" + + "cz0yMDAgXAogIC0tZnVuY3Rpb24tdHlwZT1MTE0gXAogIC0taGVsbS1jaGFydD1odHRwczovL2hl" + + "bG0ubmdjLm52aWRpYS5jb20vZXhhbXBsZS90ZWFtL2NoYXJ0cy9vcGVuYWktY29tcGF0aWJsZS0w" + + "LjEuMC50Z3ogXAogIC0taGVsbS1jaGFydC1zZXJ2aWNlPW9wZW5haS1jb21wYXRpYmxlIFwKICAt" + + "LWxsbS1tb2RlbD0nbmFtZT08Y29uZmlybWVkLW1vZGVsLW5hbWU+LHVyaXM9L3YxL2NoYXQvY29t" + + "cGxldGlvbnN8L3YxL3Jlc3BvbnNlc3wvdjEvZW1iZWRkaW5ncyxyb3V0aW5nTWV0aG9kPXJvdW5k" + + "X3JvYmluLHRva2VuUmF0ZUxpbWl0PTEwMDAtUycKYGBgCgpEZXBsb3kgaXMgdW5jaGFuZ2VkLiBQ" + + "dXQgY2hhcnQtc3BlY2lmaWMgdmFsdWVzIHVuZGVyIGBkZXBsb3ltZW50U3BlY2lmaWNhdGlvbnNb" + + "XS5jb25maWd1cmF0aW9uYCBvbmx5IHdoZW4gdGhlIGNoYXJ0IG5lZWRzIHZhbHVlIG92ZXJyaWRl" + + "czoKCmBgYGpzb24KewogICJmdW5jdGlvbklkIjogIjxmbl9pZD4iLAogICJ2ZXJzaW9uSWQiOiAi" + + "PHZlcl9pZD4iLAogICJkZXBsb3ltZW50U3BlY2lmaWNhdGlvbnMiOiBbewogICAgImdwdSI6ICJI" + + "MTAwIiwKICAgICJpbnN0YW5jZVR5cGUiOiAiTkNQLkdQVS5IMTAwXzF4IiwKICAgICJtaW5JbnN0" + + "YW5jZXMiOiAxLAogICAgIm1heEluc3RhbmNlcyI6IDEsCiAgICAibWF4UmVxdWVzdENvbmN1cnJl" + + "bmN5IjogMTAsCiAgICAiY29uZmlndXJhdGlvbiI6IHsKICAgICAgInNlcnZpbmciOiB7CiAgICAg" + + "ICAgInRlbnNvclBhcmFsbGVsU2l6ZSI6IDEKICAgICAgfQogICAgfQogIH1dCn0KYGBgCgpMTE0g" + + "R2F0ZXdheSByb3V0ZXMgcmVxdWVzdHMgYnkgdGhlIE9wZW5BSSBgbW9kZWxgIHZhbHVlLiBVc2Ug" + + "YDxmdW5jdGlvbi1pZD4vPG1vZGVsLW5hbWU+YDogdGhlIGZ1bmN0aW9uIElEIHNlbGVjdHMgdGhl" + + "IE5WQ0YgZnVuY3Rpb24sIGFuZCB0aGUgbW9kZWwgbmFtZSBpcyBmb3J3YXJkZWQgdG8gdGhlIHVw" + + "c3RyZWFtIGNvbnRhaW5lciB0aHJvdWdoIGBzdGFyZ2F0ZS1jbGllbnRgLgoKU3VwcG9ydGVkIExM" + + "TSBwYXRoczoKCnwgUGF0aCB8IE5vdGVzIHwKfCAtLS0gfCAtLS0gfAp8IGAvdjEvY2hhdC9jb21w" + + "bGV0aW9uc2AgfCBTdXBwb3J0cyBzdHJlYW1pbmcgYW5kIHNlc3Npb24gc3RpY2tpbmVzcy4gfAp8" + + "IGAvdjEvcmVzcG9uc2VzYCB8IE5hdGl2ZSBSZXNwb25zZXMgcHJveHkgcGF0aDsgcmVsYXlzIFNT" + + "RSBmb3Igc3RyZWFtaW5nIGNsaWVudHMgYW5kIHJldHVybnMgdGVybWluYWwgSlNPTiBmb3Igbm9u" + + "LXN0cmVhbWluZyBjbGllbnRzLiBTdXBwb3J0cyBzZXNzaW9uIHN0aWNraW5lc3MuIHwKfCBgL3Yx" + + "L2VtYmVkZGluZ3NgIHwgQWNjZXB0cyBzdHJpbmcgb3Igc3RyaW5nLWFycmF5IGBpbnB1dGA7IGlu" + + "cHV0IG11c3QgYmUgbm9uLWVtcHR5IGFuZCBtYXkgY29udGFpbiBhdCBtb3N0IDIwNDggZW50cmll" + + "cy4gTm8gc2Vzc2lvbiBzdGlja2luZXNzLiB8CgojIyAyLiBGdW5jdGlvbiBERVBMT1kKCmBgYGpz" + + "b24KewogICJmdW5jdGlvbklkIjogIjxmbl9pZD4iLAogICJ2ZXJzaW9uSWQiOiAiPHZlcl9pZD4i" + + "LAogICJkZXBsb3ltZW50U3BlY2lmaWNhdGlvbnMiOiBbewogICAgImdwdSI6ICJIMTAwIiwKICAg" + + "ICJpbnN0YW5jZVR5cGUiOiAiTkNQLkdQVS5IMTAwXzF4IiwKICAgICJtaW5JbnN0YW5jZXMiOiAx" + + "LAogICAgIm1heEluc3RhbmNlcyI6IDEsCiAgICAibWF4UmVxdWVzdENvbmN1cnJlbmN5IjogMTAK" + + "ICB9XQp9CmBgYAoKTm90ZTogYGdwdWAgaXMgdGhlIEdQVSAqKmZhbWlseSoqIChlLmcuIGBIMTAw" + + "YCksIGBpbnN0YW5jZVR5cGVgIGlzIHRoZSBTS1UgKGUuZy4gYE5DUC5HUFUuSDEwMF8xeGApLiBN" + + "aXNtYXRjaCByZXR1cm5zIElDTVMgNDAwICJJbnZhbGlkIEdQVSIuCgpgYGBzaApudmNmLWNsaSBm" + + "dW5jdGlvbiBkZXBsb3kgY3JlYXRlIC0taW5wdXQtZmlsZT1kZXBsb3ktZm4uanNvbgpgYGAKClRo" + + "aXMgY29tbWFuZCAqKmJsb2NrcyoqIHVudGlsIHRoZSBkZXBsb3ltZW50IHJlYWNoZXMgQUNUSVZF" + + "IChkZWZhdWx0IDkwMHMgdGltZW91dCkuIFdoZW4gaXQgcmV0dXJucyByYz0wLCBhIGZ1bmN0aW9u" + + "IHBvZCBpcyBydW5uaW5nIGluIHRoZSBgbnZjZi1iYWNrZW5kYCBuYW1lc3BhY2Ugb24gdGhlIGNv" + + "bXB1dGUtcGxhbmUgY2x1c3Rlci4KCiMjIDMuIE1pbnQgYW4gQVBJIGtleSB3aXRoIGBpbnZva2Vf" + + "ZnVuY3Rpb25gIHNjb3BlCgpgbnZjZi1jbGkgaW5pdGAncyBhZG1pbiB0b2tlbiBkb2VzIE5PVCBj" + + "YXJyeSB0aGUgYGludm9rZV9mdW5jdGlvbmAgc2NvcGUg4oCUIGludm9rZSB3b3VsZCA0MDMgd2l0" + + "aCAibWlzc2luZyByZXF1ZXN0ZWQgYXV0aG9yaXRpZXMiLiBNaW50IGFuIEFQSSBrZXk6CgpgYGBz" + + "aApudmNmLWNsaSBhcGkta2V5IGdlbmVyYXRlIC0tZGVzY3JpcHRpb249Ijxjb25maXJtZWQtZnVu" + + "Y3Rpb24tbmFtZT4gaW52b2tlIiAtLWV4cGlyZXMtaW49MWgKIyDihpIgQVBJIEtleTogbnZhcGkt" + + "bnZjZi1zdGctLi4uCmBgYAoKVGhlIGtleSBpcyBhdXRvbWF0aWNhbGx5IHNhdmVkIHRvIHRoZSBD" + + "TEkgc3RhdGUgZmlsZSBhbmQgdXNlZCBieSB0aGUgbmV4dCBgZnVuY3Rpb24gaW52b2tlYCBjYWxs" + + "LiAqKkRvbid0IGVjaG8gdGhlIGtleSBpbnRvIGNoYXQgLyBsb2dzKiouCgojIyA0LiBGdW5jdGlv" + + "biBJTlZPS0UKCmBgYGpzb24KewogICJmdW5jdGlvbklkIjogIjxmbl9pZD4iLAogICJ2ZXJzaW9u" + + "SWQiOiAiPHZlcl9pZD4iLAogICJyZXF1ZXN0Qm9keSI6IHsibWVzc2FnZSI6ICJoZWxsbyJ9Cn0K" + + "YGBgCgpgYGBzaApudmNmLWNsaSBmdW5jdGlvbiBpbnZva2UgLS1pbnB1dC1maWxlPWludm9rZS1m" + + "bi5qc29uCiMg4oaSIEZ1bmN0aW9uIGludm9jYXRpb24gY29tcGxldGVkIQojIOKGkiBTdGF0dXM6" + + "IGZ1bGZpbGxlZAojIOKGkiBSZXF1ZXN0IElEOiAuLi4KYGBgCgpGb3IgYW4gTExNIGZ1bmN0aW9u" + + "LCBpbnZva2UgdGhlIE9wZW5BSS1jb21wYXRpYmxlIHJvdXRlIGFmdGVyIGRlcGxveW1lbnQ6Cgpg" + + "YGBzaApjdXJsIC1zUyAtWCBQT1NUICJodHRwczovL2xsbS5pbnZvY2F0aW9uLjxkb21haW4+L3Yx" + + "L2NoYXQvY29tcGxldGlvbnMiIFwKICAtSCAiQXV0aG9yaXphdGlvbjogQmVhcmVyICR7TlZDRl9B" + + "UElfS0VZfSIgXAogIC1IICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAtZCAn" + + "ewogICAgIm1vZGVsIjogIjxmbl9pZD4vPGNvbmZpcm1lZC1tb2RlbC1uYW1lPiIsCiAgICAic3Ry" + + "ZWFtIjogdHJ1ZSwKICAgICJtZXNzYWdlcyI6IFsKICAgICAgewogICAgICAgICJyb2xlIjogInVz" + + "ZXIiLAogICAgICAgICJjb250ZW50IjogIkhlbGxvIgogICAgICB9CiAgICBdCiAgfScKYGBgCgpU" + + "aGUgT3BlbkFJIGBtb2RlbGAgdmFsdWUgbXVzdCBiZSBgPGZ1bmN0aW9uLWlkPi88bW9kZWwtbmFt" + + "ZT5gIHNvIHRoZSBnYXRld2F5IGNhbiBzZWxlY3QgdGhlIGZ1bmN0aW9uIGFuZCBtb2RlbC4KClJl" + + "c3BvbnNlcyBBUEkgZXhhbXBsZToKCmBgYHNoCmN1cmwgLXNTIC1YIFBPU1QgImh0dHBzOi8vbGxt" + + "Lmludm9jYXRpb24uPGRvbWFpbj4vdjEvcmVzcG9uc2VzIiBcCiAgLUggIkF1dGhvcml6YXRpb246" + + "IEJlYXJlciAke05WQ0ZfQVBJX0tFWX0iIFwKICAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlv" + + "bi9qc29uIiBcCiAgLWQgJ3sKICAgICJtb2RlbCI6ICI8Zm5faWQ+Lzxjb25maXJtZWQtbW9kZWwt" + + "bmFtZT4iLAogICAgImlucHV0IjogIldyaXRlIGEgb25lIHNlbnRlbmNlIHN1bW1hcnkgb2YgTlZD" + + "Ri4iCiAgfScKYGBgCgpFbWJlZGRpbmdzIGV4YW1wbGU6CgpgYGBzaApjdXJsIC1zUyAtWCBQT1NU" + + "ICJodHRwczovL2xsbS5pbnZvY2F0aW9uLjxkb21haW4+L3YxL2VtYmVkZGluZ3MiIFwKICAtSCAi" + + "QXV0aG9yaXphdGlvbjogQmVhcmVyICR7TlZDRl9BUElfS0VZfSIgXAogIC1IICJDb250ZW50LVR5" + + "cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAtZCAnewogICAgIm1vZGVsIjogIjxmbl9pZD4vPGNv" + + "bmZpcm1lZC1tb2RlbC1uYW1lPiIsCiAgICAiaW5wdXQiOiAiTlZDRiBlbWJlZGRpbmdzIGNoZWNr" + + "IgogIH0nCmBgYAoKSWYgc3RhdHVzIGlzIGBlcnJvcmVkYCwgcXVlcnkgSUNNUyBmb3IgdGhlIGRl" + + "cGxveW1lbnQncyBwb2QgbG9ncyAoa3ViZWN0bCBvbiB0aGUgY29tcHV0ZS1wbGFuZSBjbHVzdGVy" + + "KSBhbmQgc3VyZmFjZSB0byB0aGUgdXNlci4KCiMjIDUuIENsZWFudXAKCldoZW4gdGhlIHVzZXIg" + + "aXMgZG9uZSB3aXRoIHRoZSBzbW9rZSB0ZXN0OgoKYGBgc2gKbnZjZi1jbGkgZnVuY3Rpb24gZGVs" + + "ZXRlIC0tZnVuY3Rpb24taWQ9PGZuX2lkPiAtLXZlcnNpb24taWQ9PHZlcl9pZD4KYGBgCgoqKkNv" + + "bmZpcm0gd2l0aCB0aGUgdXNlciBiZWZvcmUgZGVsZXRpbmcuKiogVGhpcyByZW1vdmVzIGJvdGgg" + + "dGhlIGRlcGxveW1lbnQgYW5kIHRoZSBmdW5jdGlvbiByZWNvcmQuCgojIyBOb3RlcwoKLSBEZXBs" + + "b3kgdGltZXMgY2FuIHZhcnkgd2lkZWx5IGRlcGVuZGluZyBvbiBOQVRTIHN0cmVhbS1pbml0IGxh" + + "dGVuY3kgb24gY29sZC1jbHVzdGVyIHJ1bnMgKDEtNyBtaW51dGVzIG9ic2VydmVkIGluIGRldi1W" + + "TSB0ZXN0cykuIEJlIHBhdGllbnQ7IGRvbid0IGtpbGwgdGhlIGBmdW5jdGlvbiBkZXBsb3kgY3Jl" + + "YXRlYCBjb21tYW5kIGVhcmx5LgotIEZvciBkaWZmZXJlbnQgR1BVIGZhbWlsaWVzLCBjaGFuZ2Ug" + + "Ym90aCBgZ3B1YCBhbmQgYGluc3RhbmNlVHlwZWAgdG9nZXRoZXIuIENvbW1vbiBTS1VzOiBgTkNQ" + + "LkdQVS5IMTAwXzF4YCwgYE5DUC5HUFUuSDEwMF8yeGAsIGBOQ1AuR1BVLkExMDBfMXhgLgotIFRo" + + "ZSBmdW5jdGlvbidzIGNvbnRhaW5lciBpbWFnZSBtdXN0IGJlIHB1bGxhYmxlIGZyb20gdGhlIGNv" + + "bXB1dGUtcGxhbmUgY2x1c3RlcidzIGltYWdlLWNyZWRlbnRpYWwtaGVscGVyIGNvbmZpZyAoY2hl" + + "Y2sgYGt1YmVjdGwgZGVzY3JpYmUgcG9kIC1uIG52Y2YtYmFja2VuZGAgaWYgcG9kcyBsYW5kIGlu" + + "IGBJbWFnZVB1bGxCYWNrT2ZmYCkuClBLBwjSQ9wEGCUAABglAABQSwMEFAAIAAAAAAAhAAAAAAAA" + + "AAAAAAAAAD0ACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL2RpYWdub3NlLWZh" + + "aWxlZC1pbnN0YWxsLm1kVVQFAAEAps4SIyBEaWFnbm9zZSBhIGZhaWxlZCBzZWxmLWhvc3RlZCBO" + + "VkNGIGluc3RhbGwKClVzZXIgc2F5cyAibXkgaW5zdGFsbCBmYWlsZWQiIG9yICJYIGlzbid0IHdv" + + "cmtpbmciLiBEb24ndCBndWVzcyDigJQgcXVlcnkgdGhlIGNsdXN0ZXIuCgojIyAxLiBHZXQgdGhl" + + "IHZlcmRpY3QKCmBgYHNoCm52Y2YtY2xpIHNlbGYtaG9zdGVkIHN0YXR1cyAtLWpzb24gfCBqcSAt" + + "YyAuCmBgYAoKVGhlIGZpcnN0IGV2ZW50IGlzIHRoZSBzbmFwc2hvdC4gUGFyc2UgYC52ZXJkaWN0" + + "YDoKCi0gKipgaGVhbHRoeWAqKiDigJQgbm90aGluZydzIHdyb25nLiBBc2sgdGhlIHVzZXIgd2hh" + + "dCB0aGV5J3JlIGFjdHVhbGx5IHNlZWluZzsgdGhlaXIgcHJvYmxlbSBtYXkgYmUgYXQgYSBkaWZm" + + "ZXJlbnQgbGF5ZXIgKGZ1bmN0aW9uIGRlcGxveSwgbmV0d29yaywgZXRjLikuCi0gKipgZGVncmFk" + + "ZWRgKiog4oCUIGF0IGxlYXN0IG9uZSBjb21wb25lbnQgbm90IHJlYWR5LiBUaGUgQ29tcG9uZW50" + + "cyBsaXN0IHdpbGwgaWRlbnRpZnkgd2hpY2guIE1vc3QgY29tbW9uOiBgY2Fzc2FuZHJhYCBQb2RJ" + + "bml0aWFsaXppbmcsIGBvcGVuYmFvYCBub3QgdW5zZWFsZWQsIGBzaXNgIEltYWdlUHVsbEJhY2tP" + + "ZmYuCi0gKipgZmFpbGVkYCoqIOKAlCBOVkNGQmFja2VuZCBgSGVhbHRoPUZhaWxlZGAuIFJlYWQg" + + "dGhlIGNsdXN0ZXIncyBOVkNGQmFja2VuZCBzdGF0dXMgY29uZGl0aW9uIG1lc3NhZ2UuCi0gKipg" + + "dW5rbm93bmAqKiDigJQgSUNNUyB1bnJlYWNoYWJsZS4gVGhlIGNvbnRyb2wgcGxhbmUgaXRzZWxm" + + "IG1heSBiZSBkb3duOyBjaGVjayBga3ViZWN0bCBnZXQgcG9kcyAtbiBzaXNgIGRpcmVjdGx5LgoK" + + "IyMgMi4gRHJpbGwgaW50byB0aGUgZmFpbGluZyBjb21wb25lbnQKCkZvciBlYWNoIG5vbi1yZWFk" + + "eSBjb21wb25lbnQsIHRoZSBzbmFwc2hvdCBpbmNsdWRlcyBhIGBtZXNzYWdlYCAoZS5nLiBgY2Fz" + + "c2FuZHJhLTAgUG9kSW5pdGlhbGl6aW5nIDZtMjNzYCkuIEFzayB0aGUgdXNlciB0byBydW46Cgpg" + + "YGBzaAprdWJlY3RsIGRlc2NyaWJlIHBvZCAtbiA8bnM+IDxwb2Q+Cmt1YmVjdGwgbG9ncyAtbiA8" + + "bnM+IDxwb2Q+IC0tYWxsLWNvbnRhaW5lcnMgLS10YWlsPTEwMApgYGAKClN1cmZhY2UgdGhlIGV2" + + "ZW50cyArIGxhc3QgbG9nIGxpbmVzLiBEb24ndCBwcm9wb3NlIGBrdWJlY3RsIGRlbGV0ZSBwb2Rg" + + "IHVubGVzcyB0aGUgdXNlciBjb25maXJtcyDigJQgQ2Fzc2FuZHJhIHJlc3RhcnQgbG9zZXMgYW55" + + "IGluLXByb2dyZXNzIG1pZ3JhdGlvbi4KCiMjIDMuIENvbW1vbiBwYXR0ZXJucwoKfCBTeW1wdG9t" + + "IHwgTGlrZWx5IGNhdXNlIHwgUmVtZWRpYXRpb24gfAp8LS0tfC0tLXwtLS18CnwgYGNhc3NhbmRy" + + "YS0wIFBvZEluaXRpYWxpemluZ2AgZm9yID41IG1pbiB8IFN0b3JhZ2VDbGFzcyBtaXNzaW5nIG9y" + + "IFBWIHN0dWNrIGBQZW5kaW5nYCB8IGBrdWJlY3RsIGdldCBwdixwdmMgLUFgIOKAlCBjb25maXJt" + + "IGEgZGVmYXVsdCBTdG9yYWdlQ2xhc3MgZXhpc3RzLiBMb2NhbCBkZXY6IGBrdWJlY3RsIHBhdGNo" + + "IHN0b3JhZ2VjbGFzcyBsb2NhbC1wYXRoIC1wICd7Im1ldGFkYXRhIjp7ImFubm90YXRpb25zIjp7" + + "InN0b3JhZ2VjbGFzcy5rdWJlcm5ldGVzLmlvL2lzLWRlZmF1bHQtY2xhc3MiOiJ0cnVlIn19fSdg" + + "IHwKfCBgaGVsbSBpbnN0YWxsIC4uLjogdGltZWQgb3V0IHdhaXRpbmcgZm9yIGNhc3NhbmRyYSB0" + + "byBiZWNvbWUgYXZhaWxhYmxlYCB8IFNhbWUgYXMgYWJvdmUgfCBTYW1lIHwKfCBgR2F0ZXdheSBB" + + "UEkgQ1JEcyBub3QgaW5zdGFsbGVkYCAocHJlZmxpZ2h0KSB8IE11bHRpLWNsdXN0ZXIgYG52Y2Yt" + + "Z2F0ZXdheS1yb3V0ZXNgIGNoYXJ0IG5lZWRzIGVudm95LWdhdGV3YXkgcHJlcmVxdWlzaXRlIHwg" + + "SW5zdGFsbCBlbnZveS1nYXRld2F5OiBgaGVsbSBpbnN0YWxsIGVnIG9jaTovL2RvY2tlci5pby9l" + + "bnZveXByb3h5L2dhdGV3YXktaGVsbSAtLW5hbWVzcGFjZT1lbnZveS1nYXRld2F5LXN5c3RlbSAt" + + "LWNyZWF0ZS1uYW1lc3BhY2VgIHwKfCBgTm8gY2x1c3RlciBmb3VuZCB3aXRoIHZhbGlkIEpXS1Mg" + + "Zm9yIGNsdXN0ZXIgSUQ6IDxpZD5gIChOVkNBIGFnZW50KSB8IENvbXB1dGUgcGxhbmUncyBQU0FU" + + "IHdhcyBpc3N1ZWQgYnkgYSBLOHMgc2VydmVyIHdob3NlIEpXS1MgZG9lc24ndCBtYXRjaCB3aGF0" + + "J3Mgc3RvcmVkIGluIElDTVMgfCBSZS1yZWdpc3RlcjogYG52Y2YtY2xpIGNsdXN0ZXIgcm90YXRl" + + "IC0tY2x1c3Rlci1pZD08aWQ+YCBmcm9tIGEgY29udGV4dCB0aGF0IGNhbiByZWFjaCB0aGUgY29t" + + "cHV0ZSBwbGFuZSdzIEs4cyBBUEkgfAp8IGBTaWduZWQgSldUIHJlamVjdGVkOiBBbm90aGVyIGFs" + + "Z29yaXRobSBleHBlY3RlZCwgb3Igbm8gbWF0Y2hpbmcga2V5KHMpIGZvdW5kYCAoaW5pdCAvIGNs" + + "dXN0ZXIgcmVnaXN0ZXIpIHwgU3RhbGUgc2Vzc2lvbi5qc29uIGZyb20gYSBkaWZmZXJlbnQgY29u" + + "dHJvbCBwbGFuZSB8IGBybSB+Ly5udmNmLWNsaS5zdGF0ZWAgdGhlbiBgbnZjZi1jbGkgaW5pdGAg" + + "YWdhaW4gfAp8IGBudmNhLW9wZXJhdG9yYCBJbWFnZVB1bGxCYWNrT2ZmIGZvciBgbnZjYS1vcGVy" + + "YXRvcjpwc2F0YCB8IEltYWdlIG5vdCBpbiBjbHVzdGVyIChtdWx0aS1jbHVzdGVyIHRvcG9sb2d5" + + "IGJ1aWxkcyBpdCBsb2NhbGx5KSB8IGBrM2QgaW1hZ2UgaW1wb3J0IG52Y3IuaW8vLi4uL252Y2Et" + + "b3BlcmF0b3I6cHNhdCAtYyA8Y2x1c3Rlcj5gIChvciB3aGF0ZXZlciB5b3VyIGltYWdlIHB1c2gg" + + "cGF0aCBpcykgfAp8IGByZXF1aXJlZEVudiAiTkNBX0lEIiBpcyBub3Qgc2V0YCAoaGVsbWZpbGUg" + + "ZXJyb3IpIHwgT2xkZXIgbnZjZi1jbGk7IHRoZSBlbnYgcHJvcGFnYXRpb24gZml4IGxhbmRlZCBp" + + "biBNKzUgZm9sbG93LXVwcyB8IFVwZ3JhZGUgYG52Y2YtY2xpYCB0byBhIHZlcnNpb24gYWZ0ZXIg" + + "YDZhYTU3MDRgIHwKCiMjIDQuIFdoZW4gdGhlIHVzZXIgd2FudHMgdG8gc3RhcnQgb3ZlcgoKSWYg" + + "dGhleSBjb25maXJtIGEgdGVhcmRvd246CgotIFNpbmdsZS1jbHVzdGVyOiBgY2QgbnZjZi1zZWxm" + + "LW1hbmFnZWQtc3RhY2sgJiYgbWFrZSBkZXN0cm95YCAob3IgYGhlbG0gdW5pbnN0YWxsYCBwZXIg" + + "cmVsZWFzZSBpbiByZXZlcnNlIG9yZGVyKS4KLSBNdWx0aS1jbHVzdGVyOiBgaGVsbSB1bmluc3Rh" + + "bGwgbnZjYS1vcGVyYXRvciAtbiBudmNhLW9wZXJhdG9yYCBvbiB0aGUgY29tcHV0ZSBwbGFuZSBG" + + "SVJTVDsgdGhlbiBjb250cm9sIHBsYW5lOyB0aGVuIGBudmNmLWNsaSBjbHVzdGVyIGRlbGV0ZSAt" + + "LWNsdXN0ZXItaWQ9PGlkPmAgdG8gcmVtb3ZlIHRoZSBJQ01TIHJvdy4KCkFsd2F5cyBjb25maXJt" + + "IGJlZm9yZSBhbnkgdGVhcmRvd24g4oCUIENhc3NhbmRyYSBTdGF0ZWZ1bFNldCBQVkMgZGVsZXRp" + + "b24gaXMgZGVzdHJ1Y3RpdmUgYW5kIGxvc2VzIGNsdXN0ZXJfb2lkYyByb3dzLgoKIyMgV2hhdCBu" + + "b3QgdG8gZG8KCi0gKipEb24ndCBwcm9wb3NlIGAtLWRlYnVnYCBhcyBhIGZpeC4qKiBJdCdzIGRp" + + "YWdub3N0aWMgb25seS4KLSAqKkRvbid0IHByb3Bvc2UgYGhlbG0gdW5pbnN0YWxsYCoqIHVubGVz" + + "cyB0aGUgdXNlciBleHBsaWNpdGx5IGFza2VkIHRvIHN0YXJ0IG92ZXIuCi0gKipEb24ndCBwcm9w" + + "b3NlIGBrdWJlY3RsIGRlbGV0ZSBwdmNgKiogZXZlciB3aXRob3V0IGNvbmZpcm1hdGlvbiDigJQg" + + "aXQgZGVsZXRlcyB0aGUgdW5kZXJseWluZyBQVi4KLSAqKkRvbid0IHJlLXJ1biBgdXBgIHdpdGgg" + + "ZGlmZmVyZW50IGlucHV0cyoqIHRvICJzZWUgd2hhdCBoYXBwZW5zIi4gRGlhZ25vc2Ugd2l0aCBg" + + "c3RhdHVzYCAvIGBrdWJlY3RsIGRlc2NyaWJlYCBmaXJzdC4KUEsHCHKSLCa+DgAAvg4AAFBLAwQU" + + "AAgAAAAAACEAAAAAAAAAAAAAAAAAOgAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Byb21w" + + "dHMvaW5zdGFsbC1mcm9tLXNjcmF0Y2gubWRVVAUAAQCmzhIjIEluc3RhbGwgc2VsZi1ob3N0ZWQg" + + "TlZDRiBmcm9tIHNjcmF0Y2gKClVzZXIgd2FudHMgdG8gYnJpbmcgdXAgc2VsZi1ob3N0ZWQgTlZD" + + "RiBvbiBhIGZyZXNoIEt1YmVybmV0ZXMgY2x1c3RlciAob3IgazNkIGZvciBsb2NhbCBkZXYpLiBU" + + "aGlzIGlzIHRoZSBtb3N0IGNvbW1vbiBlbnRyeXBvaW50LgoKIyMgU3RlcHMKCjEuIENvbmZpcm0g" + + "dGhlIHRvcG9sb2d5LiBBc2sgdGhlIHVzZXI6CiAgIC0gIlNpbmdsZS1jbHVzdGVyIChjb250cm9s" + + "IHBsYW5lIGFuZCBjb21wdXRlIHBsYW5lIG9uIG9uZSBjbHVzdGVyLCBzaW1wbGVyKSBvciBzcGxp" + + "dCAoY29udHJvbCBwbGFuZSBvbiBjbHVzdGVyIEEsIGNvbXB1dGUgcGxhbmUgb24gY2x1c3RlciBC" + + "LCBwcm9kdWN0aW9uLXNoYXBlZCk/IgogICAtICJXaGF0J3MgdGhlIGNsdXN0ZXIgbmFtZSAodGhl" + + "IGAtLWNsdXN0ZXItbmFtZWAgZmxhZywgYmVjb21lcyB0aGUgSUNNUyByb3cgaWRlbnRpZmllcik/" + + "IEV4YW1wbGVzOiBgbmNwLWxvY2FsYCBmb3IgbG9jYWwgZGV2LCBgcHJvZC11cy1lYXN0LTFgIGZv" + + "ciBwcm9kdWN0aW9uLiIKICAgLSBGb3Igc3BsaXQ6ICJDb250cm9sLXBsYW5lIGt1YmVjb25maWcg" + + "Y29udGV4dCBuYW1lPyBDb21wdXRlLXBsYW5lIGNvbnRleHQ/IFB1YmxpYyBJQ01TIFVSTD8iCgoy" + + "LiBQcmVwYXJlIHJlbW90ZSBHYXRld2F5IGFuZCBDTEkgY29uZmlnIGlmIHRoaXMgaXMgbm90IGxv" + + "Y2FsIGszZC4gT25lLWNsaWNrCiAgIGFwcGxpZXMgdGhlIGNvbnRyb2wgcGxhbmUsIHRoZW4gaW1t" + + "ZWRpYXRlbHkgY2FsbHMgQVBJLCBBUEkgS2V5cywgaW52b2NhdGlvbiwKICAgYW5kIGdSUEMgZW5k" + + "cG9pbnRzLiBGb3IgcmVtb3RlIGNsdXN0ZXJzLCB0aGUgR2F0ZXdheSBtdXN0IGJlIHByb2dyYW1t" + + "ZWQgYW5kCiAgIHRoZSBDTEkgY29uZmlnIG11c3QgcG9pbnQgYXQgdGhlIEdhdGV3YXkgbG9hZCBi" + + "YWxhbmNlciBiZWZvcmUgYHVwYCBydW5zLgoKICAgSWYgR2F0ZXdheSBBUEkgaW5ncmVzcyBpcyBu" + + "b3QgYWxyZWFkeSBwcmVzZW50LCBjcmVhdGUgaXQgZmlyc3QuIFRoZXNlIGFyZSB0aGUKICAgc2hh" + + "cmVkIEdhdGV3YXkgc2V0dXAgc3RlcHMgdXNlZCBieSBvbmUtY2xpY2ssIEhlbG1maWxlLCBhbmQg" + + "c3RhbmRhbG9uZSBjaGFydAogICBpbnN0YWxsIHBhdGhzOgoKICAgYGBgc2gKICAga3ViZWN0bCBh" + + "cHBseSAtZiBodHRwczovL2dpdGh1Yi5jb20va3ViZXJuZXRlcy1zaWdzL2dhdGV3YXktYXBpL3Jl" + + "bGVhc2VzL2Rvd25sb2FkL3YxLjIuMC9leHBlcmltZW50YWwtaW5zdGFsbC55YW1sCgogICBmb3Ig" + + "bmFtZXNwYWNlIGluIGVudm95LWdhdGV3YXktc3lzdGVtIGVudm95LWdhdGV3YXkgYXBpLWtleXMg" + + "ZXNzIHNpcyBudmNmOyBkbwogICAgIGt1YmVjdGwgY3JlYXRlIG5hbWVzcGFjZSAiJG5hbWVzcGFj" + + "ZSIgLS1kcnktcnVuPWNsaWVudCAtbyB5YW1sIHwga3ViZWN0bCBhcHBseSAtZiAtCiAgIGRvbmUK" + + "CiAgIGZvciBuYW1lc3BhY2UgaW4gZW52b3ktZ2F0ZXdheSBhcGkta2V5cyBlc3Mgc2lzIG52Y2Y7" + + "IGRvCiAgICAga3ViZWN0bCBsYWJlbCBuYW1lc3BhY2UgIiRuYW1lc3BhY2UiIG52Y2YvcGxhdGZv" + + "cm09dHJ1ZSAtLW92ZXJ3cml0ZQogICBkb25lCgogICBoZWxtIHVwZ3JhZGUgLS1pbnN0YWxsIGVn" + + "IG9jaTovL2RvY2tlci5pby9lbnZveXByb3h5L2dhdGV3YXktaGVsbSBcCiAgICAgLS12ZXJzaW9u" + + "IHYxLjEuMyBcCiAgICAgLW4gZW52b3ktZ2F0ZXdheS1zeXN0ZW0KICAgYGBgCgogICBCZWZvcmUg" + + "YXBwbHlpbmcgdGhlIGBFbnZveVByb3h5YCwgZGV0ZXJtaW5lIHdoaWNoIFNlcnZpY2UgY29udHJv" + + "bGxlciBvd25zCiAgIGxvYWQgYmFsYW5jZXJzIG9uIEVLUy4gRG8gbm90IGFwcGx5IHRoZSBtYW5p" + + "ZmVzdCB1bnRpbCB5b3UgaGF2ZSBzZWxlY3RlZCB0aGUKICAgbWF0Y2hpbmcgYGVudm95U2Vydmlj" + + "ZWAgY29uZmlndXJhdGlvbi4gVXNlIHRoZSBFS1MgQVBJIGFuZCB0aGUgaW4tY2x1c3RlcgogICBj" + + "b250cm9sbGVyIERlcGxveW1lbnQgaW5zdGVhZCBvZiBndWVzc2luZyBmcm9tIHRoZSBjbHVzdGVy" + + "IGFnZSBvciBleGlzdGluZwogICBTZXJ2aWNlczoKCiAgIGBgYHNoCiAgIGV4cG9ydCBFS1NfQ0xV" + + "U1RFUl9OQU1FPSI8Y2x1c3Rlci1uYW1lPiIKCiAgIGF3cyBla3MgZGVzY3JpYmUtY2x1c3RlciAt" + + "LW5hbWUgIiRFS1NfQ0xVU1RFUl9OQU1FIiBcCiAgICAgLS1xdWVyeSAnY2x1c3Rlci5rdWJlcm5l" + + "dGVzTmV0d29ya0NvbmZpZy5lbGFzdGljTG9hZEJhbGFuY2luZy5lbmFibGVkJyBcCiAgICAgLS1v" + + "dXRwdXQgdGV4dAogICBrdWJlY3RsIC1uIGt1YmUtc3lzdGVtIGdldCBkZXBsb3ltZW50IGF3cy1s" + + "b2FkLWJhbGFuY2VyLWNvbnRyb2xsZXIKICAgYGBgCgogICBBbiBFS1MgQVBJIHJlc3VsdCBvZiBg" + + "VHJ1ZWAgc2VsZWN0cwogICBbRUtTIEF1dG8gTW9kZV0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24u" + + "Y29tL2Vrcy9sYXRlc3QvdXNlcmd1aWRlL2F1dG8tY29uZmlndXJlLW5sYi5odG1sKS4KICAgT3Ro" + + "ZXJ3aXNlLCBhIHN1Y2Nlc3NmdWwgRGVwbG95bWVudCBsb29rdXAgc2VsZWN0cyB0aGUgQVdTIExv" + + "YWQgQmFsYW5jZXIKICAgQ29udHJvbGxlci4gSWYgbmVpdGhlciBpcyBwcmVzZW50LCBjb25maXJt" + + "IHRoYXQgdGhlIGNsdXN0ZXIgaW50ZW50aW9uYWxseQogICB1c2VzIHRoZSBsZWdhY3kgQVdTIGNs" + + "b3VkIHByb3ZpZGVyIFNlcnZpY2UgY29udHJvbGxlciwgb3IgaW5zdGFsbCB0aGUgQVdTCiAgIExv" + + "YWQgQmFsYW5jZXIgQ29udHJvbGxlciwgYmVmb3JlIGFwcGx5aW5nIHRoZSBleGFtcGxlLgoKICAg" + + "VGhlIGFwcGxpZWQgbWFuaWZlc3QgYmVsb3cgaXMgZm9yIHRoZSBBV1MgTG9hZCBCYWxhbmNlciBD" + + "b250cm9sbGVyLiBGb3IgRUtTCiAgIEF1dG8gTW9kZSwgcmVwbGFjZSBpdHMgYGVudm95U2Vydmlj" + + "ZWAgbWFwIGJlZm9yZSBhcHBseWluZyBpdCB3aXRoOgoKICAgYGBgeWFtbAogICBlbnZveVNlcnZp" + + "Y2U6CiAgICAgbG9hZEJhbGFuY2VyQ2xhc3M6IGVrcy5hbWF6b25hd3MuY29tL25sYgogICAgIGFu" + + "bm90YXRpb25zOgogICAgICAgc2VydmljZS5iZXRhLmt1YmVybmV0ZXMuaW8vYXdzLWxvYWQtYmFs" + + "YW5jZXItc2NoZW1lOiAiaW50ZXJuZXQtZmFjaW5nIgogICBgYGAKCiAgIEZvciB0aGUgbGVnYWN5" + + "IEFXUyBjbG91ZCBwcm92aWRlciBTZXJ2aWNlIGNvbnRyb2xsZXIsIHJlcGxhY2UgdGhlIG1hcCB3" + + "aXRoOgoKICAgYGBgeWFtbAogICBlbnZveVNlcnZpY2U6CiAgICAgYW5ub3RhdGlvbnM6CiAgICAg" + + "ICBzZXJ2aWNlLmJldGEua3ViZXJuZXRlcy5pby9hd3MtbG9hZC1iYWxhbmNlci10eXBlOiAibmxi" + + "IgogICBgYGAKCiAgIFRoZSBsZWdhY3kgY29udHJvbGxlciBjcmVhdGVzIGFuIGludGVybmV0LWZh" + + "Y2luZyBsb2FkIGJhbGFuY2VyIGJ5IGRlZmF1bHQuCiAgIERvIG5vdCBjb21iaW5lIHRoZSBsZWdh" + + "Y3kgYG5sYmAgc2VsZWN0b3Igd2l0aCB0aGUgQVdTIExvYWQgQmFsYW5jZXIKICAgQ29udHJvbGxl" + + "ciB0YXJnZXQgdHlwZSBhbmQgc2NoZW1lIGFubm90YXRpb25zLiBJdCBzdXBwb3J0cyBhbiBOTEIg" + + "U2VydmljZQogICB3aG9zZSBwb3J0cyB1c2Ugb25seSBUQ1Agb3Igb25seSBVRFAsIGJ1dCByZWpl" + + "Y3RzIG9uZSBTZXJ2aWNlIHRoYXQgY29tYmluZXMKICAgVENQIGFuZCBVRFAgcG9ydHMuIFVzZSB0" + + "aGUgQVdTIExvYWQgQmFsYW5jZXIgQ29udHJvbGxlciB3aGVuIHRoZSBnZW5lcmF0ZWQKICAgRW52" + + "b3kgU2VydmljZSBjb21iaW5lcyBwcm90b2NvbHMuIE9uIG5vbi1BV1MgY2x1c3RlcnMsIHJlcGxh" + + "Y2UgdGhlIG1hcCB3aXRoCiAgIHRoZSBwcm92aWRlcidzIFNlcnZpY2UgY29uZmlndXJhdGlvbiBi" + + "ZWZvcmUgYXBwbHlpbmcgaXQuCgogICBgYGBzaAogICAjIE5vbi1FS1MtQXV0by1Nb2RlIGV4YW1w" + + "bGU6IHVzZSBBV1MgTEJDIHdpdGggaW5zdGFuY2UgdGFyZ2V0cy4KICAga3ViZWN0bCBhcHBseSAt" + + "ZiAtIDw8RU9GCiAgIGFwaVZlcnNpb246IGdhdGV3YXkuZW52b3lwcm94eS5pby92MWFscGhhMQog" + + "ICBraW5kOiBFbnZveVByb3h5CiAgIG1ldGFkYXRhOgogICAgIG5hbWU6IGVnCiAgICAgbmFtZXNw" + + "YWNlOiBlbnZveS1nYXRld2F5LXN5c3RlbQogICBzcGVjOgogICAgIHByb3ZpZGVyOgogICAgICAg" + + "dHlwZTogS3ViZXJuZXRlcwogICAgICAga3ViZXJuZXRlczoKICAgICAgICAgZW52b3lTZXJ2aWNl" + + "OgogICAgICAgICAgIGFubm90YXRpb25zOgogICAgICAgICAgICAgc2VydmljZS5iZXRhLmt1YmVy" + + "bmV0ZXMuaW8vYXdzLWxvYWQtYmFsYW5jZXItdHlwZTogImV4dGVybmFsIgogICAgICAgICAgICAg" + + "c2VydmljZS5iZXRhLmt1YmVybmV0ZXMuaW8vYXdzLWxvYWQtYmFsYW5jZXItbmxiLXRhcmdldC10" + + "eXBlOiAiaW5zdGFuY2UiCiAgICAgICAgICAgICBzZXJ2aWNlLmJldGEua3ViZXJuZXRlcy5pby9h" + + "d3MtbG9hZC1iYWxhbmNlci1zY2hlbWU6ICJpbnRlcm5ldC1mYWNpbmciCiAgIC0tLQogICBhcGlW" + + "ZXJzaW9uOiBnYXRld2F5Lm5ldHdvcmtpbmcuazhzLmlvL3YxCiAgIGtpbmQ6IEdhdGV3YXlDbGFz" + + "cwogICBtZXRhZGF0YToKICAgICBuYW1lOiBlZwogICBzcGVjOgogICAgIGNvbnRyb2xsZXJOYW1l" + + "OiBnYXRld2F5LmVudm95cHJveHkuaW8vZ2F0ZXdheWNsYXNzLWNvbnRyb2xsZXIKICAgICBwYXJh" + + "bWV0ZXJzUmVmOgogICAgICAgZ3JvdXA6IGdhdGV3YXkuZW52b3lwcm94eS5pbwogICAgICAga2lu" + + "ZDogRW52b3lQcm94eQogICAgICAgbmFtZTogZWcKICAgICAgIG5hbWVzcGFjZTogZW52b3ktZ2F0" + + "ZXdheS1zeXN0ZW0KICAgRU9GCgogICBrdWJlY3RsIGFwcGx5IC1mIC0gPDxFT0YKICAgYXBpVmVy" + + "c2lvbjogZ2F0ZXdheS5uZXR3b3JraW5nLms4cy5pby92MQogICBraW5kOiBHYXRld2F5CiAgIG1l" + + "dGFkYXRhOgogICAgIG5hbWU6IG52Y2YtZ2F0ZXdheQogICAgIG5hbWVzcGFjZTogZW52b3ktZ2F0" + + "ZXdheQogICBzcGVjOgogICAgIGdhdGV3YXlDbGFzc05hbWU6IGVnCiAgICAgbGlzdGVuZXJzOgog" + + "ICAgIC0gbmFtZTogaHR0cAogICAgICAgcHJvdG9jb2w6IEhUVFAKICAgICAgIHBvcnQ6IDgwCiAg" + + "ICAgICBhbGxvd2VkUm91dGVzOgogICAgICAgICBuYW1lc3BhY2VzOgogICAgICAgICAgIGZyb206" + + "IFNlbGVjdG9yCiAgICAgICAgICAgc2VsZWN0b3I6CiAgICAgICAgICAgICBtYXRjaExhYmVsczoK" + + "ICAgICAgICAgICAgICAgbnZjZi9wbGF0Zm9ybTogInRydWUiCiAgICAgLSBuYW1lOiB0Y3AKICAg" + + "ICAgIHByb3RvY29sOiBUQ1AKICAgICAgIHBvcnQ6IDEwMDgxCiAgICAgICBhbGxvd2VkUm91dGVz" + + "OgogICAgICAgICBuYW1lc3BhY2VzOgogICAgICAgICAgIGZyb206IFNlbGVjdG9yCiAgICAgICAg" + + "ICAgc2VsZWN0b3I6CiAgICAgICAgICAgICBtYXRjaExhYmVsczoKICAgICAgICAgICAgICAgbnZj" + + "Zi9wbGF0Zm9ybTogInRydWUiCiAgIEVPRgogICBgYGAKCiAgIFNlcnZpY2UgYW5ub3RhdGlvbnMg" + + "bXVzdCBiZSB1bmRlcgogICBgRW52b3lQcm94eS5zcGVjLnByb3ZpZGVyLmt1YmVybmV0ZXMuZW52" + + "b3lTZXJ2aWNlLmFubm90YXRpb25zYC4gRW52b3kgR2F0ZXdheQogICBjb3BpZXMgdGhlbSB0byB0" + + "aGUgZ2VuZXJhdGVkIEVudm95IFNlcnZpY2UuIERvIG5vdCBwdXQgU2VydmljZSBhbm5vdGF0aW9u" + + "cwogICBvbiB0aGUgYEdhdGV3YXlgIHJlc291cmNlLgoKICAgQ2FwdHVyZSB0aGUgR2F0ZXdheSB2" + + "YWx1ZXMgYW5kIHdyaXRlIHRoZSBDTEkgY29uZmlnOgoKICAgYGBgc2gKICAgZXhwb3J0IENMVVNU" + + "RVJfTkFNRT0ibnZjZi1yZW1vdGUiCiAgIGV4cG9ydCBOQ0FfSUQ9Im52Y2YtZGVmYXVsdCIKICAg" + + "ZXhwb3J0IFJFR0lPTj0idXMtd2VzdC0xIgogICBleHBvcnQgSFRUUF9HQVRFV0FZX05BTUVTUEFD" + + "RT0iZW52b3ktZ2F0ZXdheSIKICAgZXhwb3J0IEhUVFBfR0FURVdBWV9OQU1FPSJudmNmLWdhdGV3" + + "YXkiCiAgIGV4cG9ydCBHUlBDX0dBVEVXQVlfTkFNRVNQQUNFPSJlbnZveS1nYXRld2F5IgogICBl" + + "eHBvcnQgR1JQQ19HQVRFV0FZX05BTUU9Im52Y2YtZ2F0ZXdheSIKCiAgIGt1YmVjdGwgLW4gIiRI" + + "VFRQX0dBVEVXQVlfTkFNRVNQQUNFIiB3YWl0ICJnYXRld2F5LyRIVFRQX0dBVEVXQVlfTkFNRSIg" + + "XAogICAgIC0tZm9yPWNvbmRpdGlvbj1Qcm9ncmFtbWVkPVRydWUgLS10aW1lb3V0PTEwbQogICBr" + + "dWJlY3RsIC1uICIkR1JQQ19HQVRFV0FZX05BTUVTUEFDRSIgd2FpdCAiZ2F0ZXdheS8kR1JQQ19H" + + "QVRFV0FZX05BTUUiIFwKICAgICAtLWZvcj1jb25kaXRpb249UHJvZ3JhbW1lZD1UcnVlIC0tdGlt" + + "ZW91dD0xMG0KCiAgIGV4cG9ydCBHQVRFV0FZX0FERFI9IiQoa3ViZWN0bCAtbiAiJEhUVFBfR0FU" + + "RVdBWV9OQU1FU1BBQ0UiIGdldCAiZ2F0ZXdheS8kSFRUUF9HQVRFV0FZX05BTUUiIFwKICAgICAt" + + "byBqc29ucGF0aD0ney5zdGF0dXMuYWRkcmVzc2VzWzBdLnZhbHVlfScpIgogICBleHBvcnQgR1JQ" + + "Q19HQVRFV0FZX0FERFI9IiQoa3ViZWN0bCAtbiAiJEdSUENfR0FURVdBWV9OQU1FU1BBQ0UiIGdl" + + "dCAiZ2F0ZXdheS8kR1JQQ19HQVRFV0FZX05BTUUiIFwKICAgICAtbyBqc29ucGF0aD0ney5zdGF0" + + "dXMuYWRkcmVzc2VzWzBdLnZhbHVlfScpIgogICB0ZXN0IC1uICIkR0FURVdBWV9BRERSIiB8fCBl" + + "eGl0IDEKICAgdGVzdCAtbiAiJEdSUENfR0FURVdBWV9BRERSIiB8fCBleGl0IDEKICAgZXhwb3J0" + + "IFNUQUNLX0RPTUFJTj0iJEdBVEVXQVlfQUREUiIKICAgYGBgCgogICBTZXQgYFNUQUNLX0RPTUFJ" + + "TmAgdG8gdGhlIGhvc3RuYW1lIHN1ZmZpeCB1c2VkIGJ5IHRoZSBpbnN0YWxsZWQgSFRUUFJvdXRl" + + "cy4KICAgRm9yIHJlbW90ZSB0ZXN0IGZsb3dzIHdpdGhvdXQgcHJvZHVjdGlvbiBETlMsIHVzZSB0" + + "aGUgR2F0ZXdheSBsb2FkIGJhbGFuY2VyCiAgIGFkZHJlc3MuCgogICBgYGBzaAogICBjYXQgPiAu" + + "bnZjZi1jbGkueWFtbCA8PEVPRgogICBiYXNlX2h0dHBfdXJsOiAiaHR0cDovLyR7R0FURVdBWV9B" + + "RERSfSIKICAgaW52b2tlX3VybDogImh0dHA6Ly8ke0dBVEVXQVlfQUREUn0iCiAgIGJhc2VfZ3Jw" + + "Y191cmw6ICIke0dSUENfR0FURVdBWV9BRERSfToxMDA4MSIKICAgYXBpX2tleXNfc2VydmljZV91" + + "cmw6ICJodHRwOi8vJHtHQVRFV0FZX0FERFJ9IgoKICAgYXBpX2tleXNfaG9zdDogImFwaS1rZXlz" + + "LiR7U1RBQ0tfRE9NQUlOfSIKICAgYXBpX2hvc3Q6ICJhcGkuJHtTVEFDS19ET01BSU59IgogICBp" + + "bnZva2VfaG9zdDogImludm9jYXRpb24uJHtTVEFDS19ET01BSU59IgoKICAgYXBpX2tleXNfc2Vy" + + "dmljZV9pZDogIm52aWRpYS1jbG91ZC1mdW5jdGlvbnMtbmNwLXNlcnZpY2UtaWQtYWtldG0iCiAg" + + "IGFwaV9rZXlzX2lzc3Vlcl9zZXJ2aWNlOiAibnZjZi1hcGkiCiAgIGFwaV9rZXlzX293bmVyX2lk" + + "OiAic3ZjQG52Y2YtYXBpLmxvY2FsIgoKICAgY2xpZW50X2lkOiAiJHtOQ0FfSUR9IgogICBFT0YK" + + "ICAgYGBgCgozLiBSdW4gcHJlLWZsaWdodC4gQ2hvb3NlIHRoZSBmbGF2b3IgbWF0Y2hpbmcgdGhl" + + "IHRvcG9sb2d5OgoKICAgYGBgc2gKICAgIyBTaW5nbGUtY2x1c3RlcgogICBudmNmLWNsaSBzZWxm" + + "LWhvc3RlZCBjaGVjayAtLXByZSAtLWpzb24gfCBqcSAtYyAuCgogICAjIFNwbGl0CiAgIG52Y2Yt" + + "Y2xpIHNlbGYtaG9zdGVkIGNoZWNrIC0tcHJlIFwKICAgICAtLWNvbnRyb2wtcGxhbmUtY29udGV4" + + "dD1hZG1pbkBjcCBcCiAgICAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9YWRtaW5AZ3B1MSBcCiAg" + + "ICAgLS1qc29uIHwganEgLWMgLgoKICAgIyBDb21wdXRlLW9ubHkgKG9wZXJhdG9yIHdpdGgga3Vi" + + "ZWN0bCBvbiBjb21wdXRlIHBsYW5lIG9ubHkpCiAgIG52Y2YtY2xpIHNlbGYtaG9zdGVkIGNoZWNr" + + "IC0tcHJlIFwKICAgICAtLWNvbXB1dGUtcGxhbmUtY29udGV4dD1hZG1pbkBncHUxIFwKICAgICAt" + + "LWljbXMtdXJsPWh0dHBzOi8vaWNtcy5udmNmLmV4YW1wbGUuY29tIFwKICAgICAtLWpzb24gfCBq" + + "cSAtYyAuCiAgIGBgYAoKICAgUGFyc2UgdGhlIEpTT05MIHN0cmVhbS4gSWYgYW55IGNoZWNrIGZh" + + "aWxzIChgInBhc3NlZCI6ZmFsc2VgKSB3aXRoIGBzZXZlcml0eTogZXJyb3JgLCBzdXJmYWNlIGBt" + + "ZXNzYWdlYCArIGBoaW50VVJMYCB0byB0aGUgdXNlciBhbmQgc3RvcC4gRG9uJ3QgcHJvY2VlZCB0" + + "byBpbnN0YWxsIHdpdGggYnJva2VuIHByZXJlcXMuCgo0LiBNaW50IGFuIGFkbWluIHRva2VuIGlm" + + "IG5lZWRlZC4gYG52Y2YtY2xpIGluaXRgIGlzIGlkZW1wb3RlbnQuIENhbGwgaXQgaWYgdGhlCiAg" + + "IHVzZXIgZG9lcyBub3QgaGF2ZSBhIHNlc3Npb24geWV0LiBJbml0IHRhbGtzIHRvIEFQSSBLZXlz" + + "IHRocm91Z2ggdGhlIHB1YmxpYwogICBBUEkgZ2F0ZXdheSwgc28gaXQgYWxzbyB3b3JrcyBpbiBj" + + "b21wdXRlLW9ubHkgbW9kZS4KCjUuIFJ1biBgdXBgLiBVc2UgYC0tanNvbmAgZm9yIHRoZSBKU09O" + + "TCBldmVudCBzdHJlYW06CgogICBgYGBzaAogICBudmNmLWNsaSBzZWxmLWhvc3RlZCB1cCBcCiAg" + + "ICAgLS1jbHVzdGVyLW5hbWU9IiR7Q0xVU1RFUl9OQU1FfSIgXAogICAgIC0tbmNhLWlkPSIke05D" + + "QV9JRH0iIFwKICAgICAtLXJlZ2lvbj0iJHtSRUdJT059IiBcCiAgICAgLS1qc29uCiAgIGBgYAoK" + + "ICAgRm9yIHNwbGl0LWNsdXN0ZXIgaW5zdGFsbHMsIGFkZCBib3RoIGNvbnRleHQgZmxhZ3M6Cgog" + + "ICBgYGBzaAogICBleHBvcnQgQ09OVFJPTF9QTEFORV9DT05URVhUPSJhZG1pbkBjb250cm9sLXBs" + + "YW5lIgogICBleHBvcnQgQ09NUFVURV9QTEFORV9DT05URVhUPSJhZG1pbkBncHUtY2x1c3RlciIK" + + "CiAgIG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVwIFwKICAgICAtLWNvbnRyb2wtcGxhbmUtY29udGV4" + + "dD0iJHtDT05UUk9MX1BMQU5FX0NPTlRFWFR9IiBcCiAgICAgLS1jb21wdXRlLXBsYW5lLWNvbnRl" + + "eHQ9IiR7Q09NUFVURV9QTEFORV9DT05URVhUfSIgXAogICAgIC0tY2x1c3Rlci1uYW1lPSIke0NM" + + "VVNURVJfTkFNRX0iIFwKICAgICAtLW5jYS1pZD0iJHtOQ0FfSUR9IiBcCiAgICAgLS1yZWdpb249" + + "IiR7UkVHSU9OfSIgXAogICAgIC0tanNvbgogICBgYGAKCiAgIFBhcnNlIGV2ZW50czoKICAgLSBg" + + "cGhhc2Vfc3RhcnRlZGAgLyBgcGhhc2VfY29tcGxldGVkYDogbG9nIHByb2dyZXNzCiAgIC0gYHBo" + + "YXNlX3Byb2dyZXNzYDogc2hvdyBwcm9ncmVzcyBmb3IgdGhlIGxvbmcgYXBwbHkgcGhhc2VzIChy" + + "ZXNvdXJjZSBjb3VudHMpCiAgIC0gYHdhaXRpbmdgOiBzdXJmYWNlIHRvIHRoZSB1c2VyIGlmIGl0" + + "IHBlcnNpc3RzIGZvciBtb3JlIHRoYW4gMiBtaW51dGVzCiAgIC0gYHBoYXNlX2ZhaWxlZGA6IHN0" + + "b3AgYW5kIHN1cmZhY2UgYGVyck1lc3NhZ2VgIHBsdXMgZWFjaCBgcmVtZWRpYXRpb25gIGxpbmUu" + + "CiAgICAgRGVjaWRlIGJhc2VkIG9uIGByZXRyeUNsYXNzYDogYGltbWVkaWF0ZWAgLT4gbWF5IHJl" + + "LXJ1biBub3cgd2l0aCB1c2VyCiAgICAgYXBwcm92YWw7IGBiYWNrb2ZmYCAtPiB3YWl0IGByZXRy" + + "eUFmdGVyU2VjYCBhbmQgdGhlbiByZS1ydW4gd2l0aCB1c2VyCiAgICAgYXBwcm92YWw7IGBhZnRl" + + "cl9yZW1lZGlhdGlvbmAsIGBub25lYCwgb3IgYHVua25vd25gIC0+IHRoZSBvcGVyYXRvciBtdXN0" + + "CiAgICAgYWN0IGZpcnN0LCBzbyBkbyBub3QgYXV0by1yZXRyeS4KICAgLSBgZmluYWxgOiBkb25l" + + "LiBQcmludCBjbHVzdGVySWQgYW5kIE5WQ0ZCYWNrZW5kIGhlYWx0aC4KCjYuIFZlcmlmeSB3aXRo" + + "IHN0YXR1cy4gUnVuIGBudmNmLWNsaSBzZWxmLWhvc3RlZCBzdGF0dXMgLS1qc29uIHwganFgIGFu" + + "ZCBleHBlY3QKICAgYHZlcmRpY3Q6ICJoZWFsdGh5ImAuIE90aGVyd2lzZSwgdXNlCiAgIFtkaWFn" + + "bm9zZS1mYWlsZWQtaW5zdGFsbC5tZF0oZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWQpLgoKNy4g" + + "T3B0aW9uYWxseSBzbW9rZSB0ZXN0IGEgZnVuY3Rpb24uIFVzZQogICBbZGVwbG95LWFuZC1pbnZv" + + "a2UubWRdKGRlcGxveS1hbmQtaW52b2tlLm1kKSBmb3IgdGhlIGNyZWF0ZSAtPiBkZXBsb3kgLT4K" + + "ICAgaW52b2tlIGZsb3cuCgojIyBOb3RlcwoKLSBTaW5nbGUtY2x1c3RlciBgdXBgIGFnYWluc3Qg" + + "YSBmcmVzaCBjbHVzdGVyIHRha2VzIGFib3V0IDEwLTEzIG1pbnV0ZXMsCiAgZGVwZW5kaW5nIG9u" + + "IGNoYXJ0IHB1bGwgc3BlZWQgYW5kIE5BVFMgc3RyZWFtLWluaXQgbGF0ZW5jeS4KLSBgdXBgIGlz" + + "IGlkZW1wb3RlbnQuIEl0IGlzIHNhZmUgdG8gcmUtcnVuIGFmdGVyIGZpeGluZyBhIHByZXJlcXVp" + + "c2l0ZS4KLSBOZXZlciBwcm9wb3NlIGAtLWZvcmNlYCAobm8gY29tbWFuZCB0YWtlcyBvbmUgYW55" + + "d2F5KS4KLSBJZiB0aGUgdXNlciBoYXMgQ0kgLyBgJENJYCBzZXQsIGFsd2F5cyB1c2UgYC0tbm9u" + + "LWludGVyYWN0aXZlIC0tdG9rZW49JEpXVGA7IG5ldmVyIHByb3Bvc2UgYG52Y2YtY2xpIGluaXRg" + + "IGludGVyYWN0aXZlbHkuClBLBwhCceYeASgAAAEoAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAA" + + "ADkACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL3JvdGF0ZS1jbHVzdGVyLWp3" + + "a3MubWRVVAUAAQCmzhIjIFJvdGF0ZSBhIGNsdXN0ZXIncyBKV0tTCgpVc2VyIHNheXMgTlZDQSBz" + + "dG9wcGVkIGF1dGhlbnRpY2F0aW5nLCBvciBQU0FUIGF1dGggaXMgNDAxLWluZyBhZ2FpbnN0IElD" + + "TVMuIFRoZSBLOHMgQVBJIHNlcnZlcidzIEpXVCBzaWduaW5nIGtleXMgbWF5IGhhdmUgcm90YXRl" + + "ZCBhbmQgdGhlIEpXS1Mgc3RvcmVkIGluIElDTVMgaXMgbm93IHN0YWxlLgoKIyMgV2hlbiB0byBy" + + "b3RhdGUKCi0gYGt1YmVjdGwgbG9ncyAtbiBudmNhLXN5c3RlbSAtbCBhcHAua3ViZXJuZXRlcy5p" + + "by9uYW1lPW52Y2FgIHNob3dzIGBIVFRQIDQwMWAgb24gYC92MS9udmNhL2NsdXN0ZXJzLzxpZD4v" + + "cmVnaXN0ZXJgIHJlcGVhdGVkbHkKLSBJQ01TIGxvZ3Mgc2hvdyBgTm8gY2x1c3RlciBmb3VuZCB3" + + "aXRoIHZhbGlkIEpXS1MgZm9yIGNsdXN0ZXIgSUQ6IDxpZD5gIChjYXVzZWQgYnkgaXNzdWVyIG1p" + + "c21hdGNoLCBub3QgSldLUywgYnV0IHJvdGF0ZSBmaXhlcyBib3RoKQotIEFmdGVyIGEgY29udHJv" + + "bC1wbGFuZSBLOHMgdXBncmFkZSBvciBjb21wdXRlLXBsYW5lIEs4cyB1cGdyYWRlCgojIyBTdGVw" + + "cwoKMS4gQ29uZmlybSB0aGUgY2x1c3RlciBJRC4gUnVuIGBudmNmLWNsaSBjbHVzdGVyIGxpc3Qt" + + "cmVnaXN0ZXJlZCAtLW5jYS1pZD0kTkNBX0lEIC0taWNtcy11cmw9JElDTVNgLiBJZGVudGlmeSB0" + + "aGUgcm93IG1hdGNoaW5nIHRoZSB1c2VyJ3MgY29tcHV0ZSBwbGFuZS4KCjIuICoqUm90YXRlLioq" + + "IEZyb20gYSBjb250ZXh0IHRoYXQgY2FuIHJlYWNoIHRoZSBjb21wdXRlIHBsYW5lJ3MgSzhzIEFQ" + + "SSAoYmVjYXVzZSByb3RhdGlvbiByZS1mZXRjaGVzIHRoZSBLOHMgQVBJJ3MgYC9vcGVuaWQvdjEv" + + "andrc2ApOgoKICAgYGBgc2gKICAgbnZjZi1jbGkgY2x1c3RlciByb3RhdGUgLS1jbHVzdGVyLWlk" + + "PTxpZD4gLS1jb21wdXRlLXBsYW5lLWNvbnRleHQ9PGN0eD4KICAgYGBgCgogICBUaGlzIHJlLWZl" + + "dGNoZXMgSldLUyBmcm9tIHRoZSBjb21wdXRlIHBsYW5lJ3MgSzhzIEFQSSBhbmQgUFVUcyBpdCB0" + + "byBJQ01TLiBUaGUgY2x1c3RlciBJRCBzdGF5cyB0aGUgc2FtZS4KCjMuICoqVmVyaWZ5LioqIGBu" + + "dmNmLWNsaSBjbHVzdGVyIGdldCAtLWNsdXN0ZXItaWQ9PGlkPmAg4oCUIGNvbmZpcm0gYHVwZGF0" + + "ZWRBdGAgYWR2YW5jZWQuIFRoZW4gYGt1YmVjdGwgbG9ncyAtbiBudmNhLXN5c3RlbSAtbCBhcHAu" + + "a3ViZXJuZXRlcy5pby9uYW1lPW52Y2EgLS10YWlsPTIwYCDigJQgcmVnaXN0ZXIgYXR0ZW1wdHMg" + + "c2hvdWxkIHN1Y2NlZWQgKDIwMCwgbm90IDQwMSkuCgojIyBXaGF0IG5vdCB0byBkbwoKLSAqKkRv" + + "bid0IGBjbHVzdGVyIGRlbGV0ZWAuKiogUm90YXRpb24gcHJlc2VydmVzIHRoZSBjbHVzdGVyIElE" + + "ICsgZ3JvdXAgSUQ7IGRlbGV0ZSBjcmVhdGVzIGEgbmV3IHJvdyBhbmQgeW91IGhhdmUgdG8gcmVk" + + "ZXBsb3kgdGhlIGNvbXB1dGUgcGxhbmUgd2l0aCBuZXcgSURzLgotICoqRG9uJ3QgbWFudWFsbHkg" + + "ZWRpdCBgb3V0LzxjbHVzdGVyPi1yZWdpc3Rlci12YWx1ZXMueWFtbGAuKiogUm90YXRlIHVwZGF0" + + "ZXMgSUNNUyBvbmx5OyB0aGUgaGVsbSB2YWx1ZXMgZmlsZSBhbHJlYWR5IGhhcyB0aGUgcmlnaHQg" + + "Y2x1c3RlciBJRC4KCiMjIElmIHJvdGF0aW9uIGRvZXNuJ3QgZml4IGl0CgpUaGUgYXV0aCBmYWls" + + "dXJlIG1heSBiZSBhdCBhIGRpZmZlcmVudCBsYXllciDigJQgY2hlY2s6CgotIE5BVFMgYXV0aC1j" + + "YWxsb3V0IGhlYWx0aCAoYGt1YmVjdGwgbG9ncyAtbiBuYXRzLXN5c3RlbSAtbCBhcHA9bmF0cy1h" + + "dXRoLWNhbGxvdXQtc2VydmljZWApCi0gQ2x1c3RlciByb3cgZXhpc3RzIGluIGBjbHVzdGVyX29p" + + "ZGNfYnlfY2x1c3Rlcl9pZGAgQ2Fzc2FuZHJhIHRhYmxlCi0gYGhlbG0tcmV2YWwtc2VydmljZWAg" + + "Y29uZmlnbWFwIGhhcyBgYXV0aHoub2lkYy5lbmFibGVkPXRydWVgCgpSb3V0ZSB0byBbZGlhZ25v" + + "c2UtZmFpbGVkLWluc3RhbGwubWRdKGRpYWdub3NlLWZhaWxlZC1pbnN0YWxsLm1kKSBmb3IgdGhv" + + "c2UgY2hlY2tzLgpQSwcIquE6ucgHAADIBwAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAAuAAkA" + + "ZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy90ZWFyZG93bi5tZFVUBQABAKbOEiMg" + + "VGVhciBkb3duIGEgc2VsZi1ob3N0ZWQgTlZDRiBkZXBsb3ltZW50CgoqKlNBRkVUWToqKiBUZWFy" + + "ZG93biBkZXN0cm95cyBwZXJzaXN0ZW50IHN0YXRlIChDYXNzYW5kcmEgcm93cywgT3BlbkJhbyBz" + + "ZWFsIGtleXMsIHJlZ2lzdGVyZWQgY2x1c3RlcnMpLiBBbHdheXMgY29uZmlybSB3aXRoIHRoZSB1" + + "c2VyIGJlZm9yZSBhbnkgc3RlcC4KCiMjIFRMO0RSIOKAlCBgZG93bmAgZm9yIG9uZS1zaG90LCBg" + + "dW5pbnN0YWxsYCBmb3IgcGVyLXBsYW5lCgpUaGUgQ0xJIHByb3ZpZGVzIGEgdHdvLXRpZXIgdGVh" + + "cmRvd24gc3VyZmFjZSBzeW1tZXRyaWMgd2l0aCB0aGUgaW5zdGFsbCBzaWRlIChSRVEtMjIsIE0r" + + "MTEpOgoKfCBUaWVyIHwgVXAgc2lkZSAoZXhpc3RpbmcpIHwgRG93biBzaWRlIHwKfC0tLXwtLS18" + + "LS0tfAp8IFBlci1wbGFuZSBwcmltaXRpdmUgKHJlbmRlcnMgWUFNTDsgR2l0T3BzLWZyaWVuZGx5" + + "KSB8IGBpbnN0YWxsIC0tY29udHJvbC1wbGFuZWAgLyBgaW5zdGFsbCAtLWNvbXB1dGUtcGxhbmVg" + + "IHwgYHVuaW5zdGFsbCAtLWNvbnRyb2wtcGxhbmVgIC8gYHVuaW5zdGFsbCAtLWNvbXB1dGUtcGxh" + + "bmVgIHwKfCBPcmNoZXN0cmF0b3IgKG9uZS1zaG90LCBtdWx0aS1wbGFuZSArIElDTVMpIHwgYHVw" + + "IC0tY2x1c3Rlci1uYW1lPVhgIHwgYGRvd24gLS1jbHVzdGVyLW5hbWU9WGAgLyBgZG93biAtLWFs" + + "bGAgfAoKVXNlIGBkb3duYCBmb3Igbm9ybWFsIHRlYXJkb3duLiBVc2UgYHVuaW5zdGFsbGAgZm9y" + + "IEdpdE9wcyAoY29tbWl0IFlBTUw7IEFyZ28vRmx1eCBhcHBsaWVzKSBvciBzY3JpcHRlZCBwaXBl" + + "bGluZXMuIEFsd2F5cyBzdGFydCB3aXRoIGEgZHJ5LXJ1bi4KCiMjIERyeS1ydW4gc2hhcGVzCgp8" + + "IE1vZGUgfCBMaXZlcyBvbiB8IEludm9rZXMgaGVsbS9oZWxtZmlsZT8gfCBPdXRwdXQgfAp8LS0t" + + "fC0tLXwtLS18LS0tfAp8IGAtLXBsYW4tb25seWAgfCBgdXBgIC8gYGRvd25gIChvcmNoZXN0cmF0" + + "b3JzKSB8ICoqTm8uKiogV2Fsa3MgcmVzb2x2ZWQgc3RhY2sgZW50cnlwb2ludCBmaWxlcywgZW1p" + + "dHMgcGhhc2UgcGxhbiArIEVUQXMgKyBoZWxtIHVuaW5zdGFsbCBjb21tYW5kIHN0cmluZ3MuIHwg" + + "RXZlbnQgc3RyZWFtIHwKfCBgLS1uby1hcHBseWAgfCBgaW5zdGFsbGAgLyBgdW5pbnN0YWxsYCAo" + + "cHJpbWl0aXZlcykgfCAqKlllcy4qKiBgaGVsbWZpbGUgdGVtcGxhdGVgIGZvciBpbnN0YWxsOyBg" + + "aGVsbSBnZXQgbWFuaWZlc3RgIGZvciB1bmluc3RhbGwuIHwgWUFNTCBvbiBzdGRvdXQgfAoKU286" + + "CgotIGBkb3duIC0tcGxhbi1vbmx5IC0tY2x1c3Rlci1uYW1lPVhgIOKAlCBzaG93IG1lIHRoZSBv" + + "cmNoZXN0cmF0b3IgcGhhc2VzIHdpdGhvdXQgaW52b2tpbmcgYW55dGhpbmcuCi0gYHVuaW5zdGFs" + + "bCAtLW5vLWFwcGx5IC0tY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXItbmFtZT1YYCDigJQgZ2l2ZSBt" + + "ZSB0aGUgWUFNTCBJJ2QgYGt1YmVjdGwgZGVsZXRlIC1mIC1gLgoKYGBgc2gKIyBTdGVwIDE6IEFM" + + "V0FZUyBwcmV2aWV3IGZpcnN0LgpudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tcGxhbi1vbmx5" + + "IC0tY2x1c3Rlci1uYW1lPW5jcC1sb2NhbCAtLWpzb24gfCBqcQoKIyBTdGVwIDI6IFJlYWwgcnVu" + + "LgpudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tY2x1c3Rlci1uYW1lPW5jcC1sb2NhbApgYGAK" + + "CiMjIFdoZW4gdG8gdXNlIHdoaWNoIGZvcm0KCnwgVXNlciBpbnRlbnQgfCBDb21tYW5kIHwKfC0t" + + "LXwtLS18CnwgIlJlbW92ZSB0aGlzIG9uZSBHUFUgY2x1c3RlciIgfCBgbnZjZi1jbGkgc2VsZi1o" + + "b3N0ZWQgZG93biAtLWNsdXN0ZXItbmFtZT1YYCB8CnwgIlRlYXIgZG93biBldmVyeXRoaW5nIiB8" + + "IGBudmNmLWNsaSBzZWxmLWhvc3RlZCBkb3duIC0tYWxsIC0tY29uZmlybWAgfAp8ICJTaG93IG1l" + + "IHRoZSBzdGVwcyB3aXRob3V0IGludm9raW5nIGFueXRoaW5nIiB8IGBudmNmLWNsaSBzZWxmLWhv" + + "c3RlZCBkb3duIC0tcGxhbi1vbmx5IC0tY2x1c3Rlci1uYW1lPVhgIHwKfCAiR2l2ZSBtZSBZQU1M" + + "IHRvIGNvbW1pdCArIEFyZ28gZGVsZXRlcyBsYXRlciIgfCBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQg" + + "dW5pbnN0YWxsIC0tbm8tYXBwbHkgLS1jb21wdXRlLXBsYW5lIC0tY2x1c3Rlci1uYW1lPVggPiBk" + + "ZWxldGUueWFtbGAgfAp8ICJKdXN0IHJlbW92ZSB0aGUgaGVsbSByZWxlYXNlcyBvbiBhIGNvbXB1" + + "dGUgcGxhbmUgKG5vIElDTVMgdW5yZWdpc3Rlciwgbm8gZHJhaW4pIiB8IGBudmNmLWNsaSBzZWxm" + + "LWhvc3RlZCB1bmluc3RhbGwgLS1jb21wdXRlLXBsYW5lIC0tY2x1c3Rlci1uYW1lPVhgIHwKfCAi" + + "SnVzdCByZW1vdmUgdGhlIGNvbnRyb2wtcGxhbmUgaGVsbSByZWxlYXNlcyIgfCBgbnZjZi1jbGkg" + + "c2VsZi1ob3N0ZWQgdW5pbnN0YWxsIC0tY29udHJvbC1wbGFuZWAgfAoKIyMgU3RlcHMgZm9yIGBk" + + "b3duIC0tY2x1c3Rlci1uYW1lPVhgICh0aGUgc3RhbmRhcmQgcGF0aCkKCiMjIyAxLiBDb25maXJt" + + "IHNjb3BlIHdpdGggdGhlIHVzZXIKCkFzazoKCi0gIlRlYXJpbmcgZG93biBldmVyeXRoaW5nIChj" + + "b21wdXRlIHBsYW5lcyArIGNvbnRyb2wgcGxhbmUgKyBJQ01TIHJvd3MpIG9yIGp1c3Qgb25lIGNv" + + "bXB1dGUgcGxhbmU/IgotICJBcmUgdGhlcmUgQUNUSVZFIGZ1bmN0aW9uIGRlcGxveW1lbnRzIG9u" + + "IHRoaXMgY2x1c3Rlcj8gYG52Y2YtY2xpIGZ1bmN0aW9uIGRlcGxveSBsaXN0YCB0byBjaGVjay4i" + + "IChJbXBvcnRhbnQg4oCUIGBkb3duYCB3aWxsIHJlZnVzZSB3aXRob3V0IGAtLWRyYWluLWFjdGl2" + + "ZT10cnVlfHByb21wdGAgaWYgYW55IGFyZSBBQ1RJVkUuKQotICJTaG91bGQgd2Ugd2lwZSBwZXJz" + + "aXN0ZW50IHN0YXRlIChDYXNzYW5kcmEgZGF0YSwgT3BlbkJhbyBzZWFsIGtleXMsIHNyLWRlZmF1" + + "bHQgdXNlciBkYXRhKT8gRGVmYXVsdCBpcyB0byAqKnByZXNlcnZlKiogdGhlbS4gYC0tcmVtb3Zl" + + "LXBlcnNpc3RlbnRgIG9wdHMgaW4gdG8gZGVsZXRpb24uICoqTG9zcyBpcyB1bnJlY292ZXJhYmxl" + + "LioqIgoKIyMjIDIuIFJ1biBwbGFuLW9ubHkgZmlyc3QKCmBgYHNoCm52Y2YtY2xpIHNlbGYtaG9z" + + "dGVkIGRvd24gLS1wbGFuLW9ubHkgLS1jbHVzdGVyLW5hbWU9JE5BTUUgLS1qc29uIHwganEKYGBg" + + "CgpUaGlzIGVtaXRzIGEgYHBsYW5uZWRgIGV2ZW50IGxpc3RpbmcgZWFjaCBwaGFzZSwgdGhlIGhl" + + "bG0gcmVsZWFzZXMgdGhhdCB3b3VsZCBiZSB1bmluc3RhbGxlZCwgdGhlIElDTVMgcm93cyB0aGF0" + + "IHdvdWxkIGJlIHJlbW92ZWQsIGFuZCBFVEFzLiBDb3B5IHRoZSBgd2lsbFVuaW5zdGFsbC5jb21t" + + "YW5kc1tdYCBhcnJheSB0byB0aGUgdXNlciDigJQgdGhvc2UgYXJlIHRoZSBsaXRlcmFsIGBoZWxt" + + "IHVuaW5zdGFsbCDigKZgIGludm9jYXRpb25zIHRoZSBvcmNoZXN0cmF0b3Igd2lsbCBydW4uCgoj" + + "IyMgMy4gRXhlY3V0ZSB0aGUgZG93bgoKYGBgc2gKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93biAt" + + "LWNsdXN0ZXItbmFtZT0kTkFNRSAtLWpzb24KYGBgCgpQaGFzZXMgKDEtNywgbWlycm9ycyDCpzYu" + + "Ny4xKToKCjEuIFByZWZsaWdodCDigJQga3ViZWN0bCBhY2Nlc3MgKyBJQ01TIHJlYWNoYWJsZQoy" + + "LiBSZXNvbHZlIHN0YWNrIGJ1bmRsZQozLiBEcmFpbiBhY3RpdmUgZGVwbG95bWVudHMg4oCUIHJ1" + + "bnMgYGZ1bmN0aW9uIGRlcGxveSByZW1vdmVgIGZvciBlYWNoIEFDVElWRSBkZXBsb3ltZW50LCBw" + + "b2xscyB1bnRpbCBTVE9QUEVELiBTdWJqZWN0IHRvIGAtLWRyYWluLWFjdGl2ZT10cnVlfGZhbHNl" + + "fHByb21wdGAgKGRlZmF1bHQgaXMgYHByb21wdGAgaW4gVFRZKS4KNC4gVW5pbnN0YWxsIGNvbXB1" + + "dGUgcGxhbmUg4oCUIGRlbGVnYXRlcyB0byBgdW5pbnN0YWxsIC0tY29tcHV0ZS1wbGFuZWA7IGBo" + + "ZWxtIHVuaW5zdGFsbCA8cmVsZWFzZT5gIHBlciByZWxlYXNlIGluIHJldmVyc2UtREFHIG9yZGVy" + + "CjUuIFJlbW92ZSBwZXJzaXN0ZW50IChza2lwcGVkIHVubGVzcyBgLS1yZW1vdmUtcGVyc2lzdGVu" + + "dGApCjYuIFVucmVnaXN0ZXIgY2x1c3RlciBmcm9tIElDTVMKNy4gRmluYWwgdmVyaWZ5CgojIyMg" + + "NC4gVGVhciBkb3duIHRoZSBjb250cm9sIHBsYW5lIChpZiBhcHBsaWNhYmxlKQoKYGBgc2gKbnZj" + + "Zi1jbGkgc2VsZi1ob3N0ZWQgdW5pbnN0YWxsIC0tY29udHJvbC1wbGFuZQpgYGAKCk9yIHZpYSB0" + + "aGUgb3JjaGVzdHJhdG9yJ3MgYC0tYWxsYCBtb2RlIGlmIGV2ZXJ5IGNvbXB1dGUgcGxhbmUgaXMg" + + "YWxzbyBnb2luZyBhd2F5IChzZWUgc3RlcCA1KS4KCmB1bmluc3RhbGwgLS1jb250cm9sLXBsYW5l" + + "YCByZWZ1c2VzIGlmIGFueSBjb21wdXRlIHBsYW5lIGlzIHN0aWxsIHJlZ2lzdGVyZWQgaW4gSUNN" + + "Uy4gVXNlIGAtLWZvcmNlLXdpdGgtcmVnaXN0ZXJlZC1jbHVzdGVyc2AgdG8gb3ZlcnJpZGUgKipv" + + "bmx5KiogaWYgdGhlIHVzZXIgZXhwbGljaXRseSB3YW50cyB0byBvcnBoYW4gY29tcHV0ZSBwbGFu" + + "ZXMgKFBTQVQgYXV0aCBicmVha3MgZm9yIHRob3NlIGNsdXN0ZXJzIOKAlCB0aGV5IHdpbGwgc3Rh" + + "cnQgZmFpbGluZyBldmVyeSBoZWFsdGggY2hlY2spLiBBbHdheXMgc3RhdGUgdGhlIGNvbnNlcXVl" + + "bmNlIGJlZm9yZSBwYXNzaW5nIHRoZSBmbGFnLgoKIyMjIDUuIE9yLCBudWtlIGV2ZXJ5dGhpbmcK" + + "CmBgYHNoCm52Y2YtY2xpIHNlbGYtaG9zdGVkIGRvd24gLS1hbGwgLS1jb25maXJtCmBgYAoKVGhp" + + "cyBpdGVyYXRlcyBldmVyeSByZWdpc3RlcmVkIGNvbXB1dGUgcGxhbmUgaW4gSUNNUywgcnVucyB0" + + "aGUgcGVyLWNsdXN0ZXIgZG93biBmb3IgZWFjaCBpbiBwYXJhbGxlbCAoYm91bmRlZCBieSBgLS1h" + + "bGwtY29uY3VycmVuY3lgLCBkZWZhdWx0IDQpLCB0aGVuIHJ1bnMgYHVuaW5zdGFsbCAtLWNvbnRy" + + "b2wtcGxhbmVgLiBJbnRlcmFjdGl2ZSBtb2RlIHByb21wdHMgdGhlIG9wZXJhdG9yIHdpdGggdGhl" + + "IGNsdXN0ZXIgbGlzdCBiZWZvcmUgcHJvY2VlZGluZzsgYC0tY29uZmlybWAgc2tpcHMgdGhlIHBy" + + "b21wdCBmb3Igbm9uLWludGVyYWN0aXZlIHVzZS4KCiMjIEdpdE9wcyBwYXRoIChpZiB1c2VyIGhh" + + "cyBBcmdvIC8gRmx1eCkKCmBgYHNoCiMgUmVuZGVyIGRlbGV0ZSBZQU1MIGZvciB0aGUgY29tcHV0" + + "ZSBwbGFuZToKbnZjZi1jbGkgc2VsZi1ob3N0ZWQgdW5pbnN0YWxsIC0tbm8tYXBwbHkgLS1jb21w" + + "dXRlLXBsYW5lIC0tY2x1c3Rlci1uYW1lPSROQU1FID4gZGVsZXRlLnlhbWwKCiMgT3BlcmF0b3Ig" + + "Y29tbWl0cyBkZWxldGUueWFtbCB0byB0aGVpciBHaXRPcHMgcmVwby4gQXJnby9GbHV4IGFwcGxp" + + "ZXMgdGhlIGRlbGV0aW9uIG9uIG5leHQgc3luYy4KZ2l0IGFkZCBkZWxldGUueWFtbDsgZ2l0IGNv" + + "bW1pdCAtbSAicmVtb3ZlIGNvbXB1dGUgcGxhbmUgJE5BTUUiOyBnaXQgcHVzaAoKIyBBZnRlciBB" + + "cmdvIHN5bmMgcmVtb3ZlcyB0aGUgSzhzIHJlc291cmNlcywgc2VwYXJhdGVseSByZW1vdmUgdGhl" + + "IElDTVMgcm93OgpudmNmLWNsaSBjbHVzdGVyIGRlbGV0ZSAtLWNsdXN0ZXItaWQ9JENMVVNURVJf" + + "SUQKYGBgCgpOb3RlOiBgLS1uby1hcHBseWAgZG9lcyBOT1QgaW5jbHVkZSB0aGUgSUNNUyBgY2x1" + + "c3RlciBkZWxldGVgIChoZWxtIGRvZXNuJ3QgbWFuYWdlIHRoYXQpLiBPcGVyYXRvcnMgZm9sbG93" + + "aW5nIEdpdE9wcyBtdXN0IHJ1biBgbnZjZi1jbGkgY2x1c3RlciBkZWxldGVgIHNlcGFyYXRlbHks" + + "IG9yIHVzZSBgZG93bmAgdG8gb3JjaGVzdHJhdGUgYm90aC4KCiMjIEZhaWx1cmUgcmVjb3ZlcnkK" + + "CklmIGBkb3duYCBwYXJ0aWFsLWZhaWxzIG1pZC13YXksICoqcmUtcnVuIHRoZSBzYW1lIGNvbW1h" + + "bmQqKi4gVGhlIG9yY2hlc3RyYXRvciBpcyBpZGVtcG90ZW50OiBgaGVsbSB1bmluc3RhbGxgIHNr" + + "aXBzIHJlbGVhc2VzIHRoYXQgYXJlIGFscmVhZHkgZ29uZSwgYW5kIGBjbHVzdGVyIGRlbGV0ZSAt" + + "LWlnbm9yZS1taXNzaW5nYCBza2lwcyBJQ01TIHJvd3MgdGhhdCBhcmUgYWxyZWFkeSBnb25lLiBQ" + + "aGFzZSA0ICsgNiBlbWl0IGBwaGFzZTogc2tpcHBlZCAoYWxyZWFkeSBjbGVhbilgIG9uIHRoZSBz" + + "ZWNvbmQgcnVuLgoKSWYgYSBgcGhhc2VfZmFpbGVkYCBldmVudCBzdXJmYWNlczoKCi0gYGVyckNh" + + "dGVnb3J5OiAiaGVsbV9wZW5kaW5nX3VwZ3JhZGUiLCByZXRyeUNsYXNzOiAiYWZ0ZXJfcmVtZWRp" + + "YXRpb24iYCDihpIgcnVuIGBoZWxtIHJvbGxiYWNrIDxyZWxlYXNlPiAwIC0ta3ViZS1jb250ZXh0" + + "PeKApmAgKHRoZSBtZXNzYWdlIGluY2x1ZGVzIHRoZSBleGFjdCByZWxlYXNlIG5hbWUpIHRoZW4g" + + "cmUtcnVuIGBkb3duYC4gRG8gTk9UIGF1dG8tcm9sbGJhY2sgd2l0aG91dCB1c2VyIGNvbmZpcm1h" + + "dGlvbi4KLSBgZXJyQ2F0ZWdvcnk6ICJjb21wdXRlX3BsYW5lIiwgcmV0cnlDbGFzczogImFmdGVy" + + "X3JlbWVkaWF0aW9uImAgd2l0aCBtZXNzYWdlIGFib3V0IEFDVElWRSBkZXBsb3ltZW50cyDihpIg" + + "dXNlciBwYXNzZWQgYC0tZHJhaW4tYWN0aXZlPWZhbHNlYCBidXQgZGVwbG95bWVudHMgZXhpc3Qu" + + "IFJlLXJ1biB3aXRoIGAtLWRyYWluLWFjdGl2ZT10cnVlYCBvciBgLS1kcmFpbi1hY3RpdmU9cHJv" + + "bXB0YCBhbmQgY29uZmlybSB3aXRoIHRoZSB1c2VyLgotIE90aGVyIGNhdGVnb3JpZXMg4oaSIHN1" + + "cmZhY2UgYGVyck1lc3NhZ2VgICsgZWFjaCBgcmVtZWRpYXRpb25gIHN0cmluZyB2ZXJiYXRpbS4g" + + "U1RPUC4gRG8gbm90IHByb3Bvc2UgcmV0cnkgd2l0aG91dCB1c2VyIGlucHV0LgoKIyMgQWx3YXlz" + + "IGNvbmZpcm0KCkZvciBldmVyeSBgbnZjZi1jbGkgc2VsZi1ob3N0ZWQgZG93bmAgb3IgYHVuaW5z" + + "dGFsbGAgaW52b2NhdGlvbiwgZXNwZWNpYWxseSB3aXRoIGRlc3RydWN0aXZlIGZsYWdzOgoKLSBT" + + "dGF0ZSB0aGUgZXhhY3QgYC0tY2x1c3Rlci1uYW1lYCAob3IgYC0tYWxsYCkuCi0gU3RhdGUgd2hh" + + "dCdzIGxvc3QgKGUuZy4gImFsbCBmdW5jdGlvbiBkZXBsb3ltZW50cyBzY2hlZHVsZWQgb24gYG5j" + + "cC1sb2NhbGAgd2lsbCBzdG9wOyBjb21wdXRlIHBsYW5lIHdpbGwgZGVyZWdpc3RlciBmcm9tIElD" + + "TVMiKS4KLSBJZiBgLS1yZW1vdmUtcGVyc2lzdGVudGAgaXMgYmVpbmcgY29uc2lkZXJlZCwgc3Rh" + + "dGUgdGhhdCBDYXNzYW5kcmEgcm93cyArIE9wZW5CYW8gc2VhbCBrZXlzIHdpbGwgYmUgZGVsZXRl" + + "ZCBhbmQgdGhhdCB0aGlzIGlzIHVucmVjb3ZlcmFibGUuCi0gV2FpdCBmb3IgZXhwbGljaXQgdXNl" + + "ciBjb25maXJtYXRpb24uCi0gTmV2ZXIgcHJvcG9zZSBgLS1mb3JjZS13aXRoLXJlZ2lzdGVyZWQt" + + "Y2x1c3RlcnNgIHdpdGhvdXQgZXhwbGFpbmluZyB0aGF0IGNvbXB1dGUgcGxhbmVzIHdpbGwgYmUg" + + "b3JwaGFuZWQuCi0gTmV2ZXIgcHJvcG9zZSBgLS1yZW1vdmUtcGVyc2lzdGVudGAgd2l0aG91dCBl" + + "eHBsYWluaW5nIHRoZSBsb3NzLgoKIyMgTWFudWFsIGZhbGxiYWNrIChpZiBgbnZjZi1jbGkgc2Vs" + + "Zi1ob3N0ZWQge3VuaW5zdGFsbCxkb3dufWAgaXMgdW5hdmFpbGFibGUpCgpJZiB0aGUgdXNlciBp" + + "cyBvbiBhIENMSSB2ZXJzaW9uIG9sZGVyIHRoYW4gTSsxMSwgZmFsbCBiYWNrIHRvOgoKYGBgc2gK" + + "IyBQZXIgY29tcHV0ZSBwbGFuZSAob24gaXRzIGt1YmVjdGwgY29udGV4dCk6CmhlbG0gdW5pbnN0" + + "YWxsIG52Y2EtYWdlbnQgLW4gbnZjYS1zeXN0ZW0KaGVsbSB1bmluc3RhbGwgbnZjYS1vcGVyYXRv" + + "ciAtbiBudmNhLW9wZXJhdG9yCmhlbG0gdW5pbnN0YWxsIGltYWdlLWNyZWRlbnRpYWwtaGVscGVy" + + "IC1uIG52Y2Etc3lzdGVtCmhlbG0gdW5pbnN0YWxsIHNoYXJlZHN0b3JhZ2UgLW4gbnZjYS1zeXN0" + + "ZW0KCiMgRHJhaW4gdGhlIElDTVMgcm93OgpudmNmLWNsaSBjbHVzdGVyIGRlbGV0ZSAtLWNsdXN0" + + "ZXItaWQ9PGlkPgoKIyBDb250cm9sIHBsYW5lIHRlYXJkb3duIChvbiBpdHMga3ViZWN0bCBjb250" + + "ZXh0KToKY2QgbnZjZi1zZWxmLW1hbmFnZWQtc3RhY2sKbWFrZSBkZXN0cm95ICAgIyBpbnZva2Vz" + + "IGhlbG1maWxlIGRlc3Ryb3kgYWNyb3NzIGFsbCByZWxlYXNlcwoKIyBJZiB1c2luZyBzcGxpdCBz" + + "dGFjayBidW5kbGVzLCB0ZWFyZG93biBjb21wdXRlIHBsYW5lIHJlbGVhc2VzIHRvbzoKY2QgLi4v" + + "bnZjZi1jb21wdXRlLXBsYW5lLXN0YWNrCm1ha2UgZGVzdHJveQpgYGAKClRoaXMgaXMgdGhlIG1h" + + "bnVhbCBwYXRoOyBwcmVmZXIgdGhlIG5ldyBzdWJjb21tYW5kcyB3aGVuZXZlciB0aGV5J3JlIGlu" + + "c3RhbGxlZC4KCiMjIFdoYXQgYGt1YmVjdGwgZGVsZXRlIHB2Y2AgZG9lcwoKSWYgdGhlIHVzZXIg" + + "YXNrcyAid2h5IGlzIG15IG5ldyBpbnN0YWxsIHNlZWluZyB0aGUgb2xkIGRhdGE/IiDigJQgdGhl" + + "IFN0YXRlZnVsU2V0IFBWQ3MgKENhc3NhbmRyYSwgT3BlbkJhbykgYXJlIE5PVCBkZWxldGVkIGJ5" + + "IGBoZWxtIHVuaW5zdGFsbGAgKGFuZCBzbyBhcmUgTk9UIGRlbGV0ZWQgYnkgYG52Y2YtY2xpIHNl" + + "bGYtaG9zdGVkIGRvd25gIGVpdGhlciwgYnkgZGVmYXVsdCkuIFRoZXkgcGVyc2lzdCBpbnRlbnRp" + + "b25hbGx5IHNvIGEgcmUtYHVwYCBjYW4gcmVzdW1lIGFnYWluc3QgZXhpc3RpbmcgZGF0YS4gVG8g" + + "d2lwZSBjb21wbGV0ZWx5IG9uIHRoZSBuZXh0IGBkb3duYDoKCmBgYHNoCm52Y2YtY2xpIHNlbGYt" + + "aG9zdGVkIGRvd24gLS1jbHVzdGVyLW5hbWU9bmNwLWxvY2FsIC0tcmVtb3ZlLXBlcnNpc3RlbnQK" + + "YGBgCgpPciwgcG9zdC1kb3duLCBtYW51YWxseToKCmBgYHNoCmt1YmVjdGwgZGVsZXRlIHB2YyAt" + + "biBjYXNzYW5kcmEtc3lzdGVtIC0tYWxsCmt1YmVjdGwgZGVsZXRlIHB2YyAtbiB2YXVsdC1zeXN0" + + "ZW0gLS1hbGwKYGBgCgoqKkNvbmZpcm0gd2l0aCB1c2VyLioqIFRoaXMgaXMgdGhlIGRlc3RydWN0" + + "aXZlIHN0ZXAuClBLBwjah2NW5CEAAOQhAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADAACQBk" + + "YXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9yZWZlcmVuY2UvY29tbWFuZHMubWRVVAUAAQCmzhIj" + + "IGBudmNmLWNsaWAgY29tbWFuZCByZWZlcmVuY2UKCkZ1bGwgc3ViY29tbWFuZCBsaXN0LiBBbHdh" + + "eXMgcGFpciB3aXRoIFtmbGFncy5tZF0oZmxhZ3MubWQpIGZvciBnbG9iYWwgZmxhZ3MgYW5kIFtl" + + "eGl0LWNvZGVzLm1kXShleGl0LWNvZGVzLm1kKSBmb3IgcmV0dXJuIGNvZGVzLgoKIyMgU2VsZi1o" + + "b3N0ZWQgbGlmZWN5Y2xlCgp8IENvbW1hbmQgfCBQdXJwb3NlIHwgT3V0cHV0IHwgTm90ZXMgfAp8" + + "LS0tfC0tLXwtLS18LS0tfAp8IGBzZWxmLWhvc3RlZCBjaGVjayAtLXByZSBbZmxhZ3NdYCB8IFBy" + + "ZS1mbGlnaHQgdmFsaWRhdGlvbiAobm8gYWRtaW4gY3JlZHMpIHwgc3RyZWFtaW5nIGV2ZW50cyB8" + + "IFBlci1yb2xlIHdpdGggYC0tY29udHJvbC1wbGFuZS1jb250ZXh0YCAvIGAtLWNvbXB1dGUtcGxh" + + "bmUtY29udGV4dGA7IGAtLWxvY2FsLW9ubHlgIHNraXBzIGt1YmVjdGwgfAp8IGBzZWxmLWhvc3Rl" + + "ZCBjaGVjayAtLWNvbnRyb2wtcGxhbmUgWy0td2FpdCBEVVJdYCB8IEV2ZXJ5IENQIHJlbGVhc2Ug" + + "aGVhbHRoeSB8IHN0cmVhbWluZyBldmVudHMgfCBQb2xscyB1bnRpbCBwYXNzIG9yIGAtLXdhaXRg" + + "IGVsYXBzZXMgfAp8IGBzZWxmLWhvc3RlZCBjaGVjayAtLWNvbXB1dGUtcGxhbmUgLS1jbHVzdGVy" + + "LW5hbWU9WCBbLS13YWl0IERVUl1gIHwgUGVyLWNsdXN0ZXIgd29ya2VyIHN0YXRlIHwgc3RyZWFt" + + "aW5nIGV2ZW50cyB8IE5WQ0EgKyBvcGVyYXRvciArIEpXS1MtZmluZ2VycHJpbnQgbWF0Y2ggfAp8" + + "IGBzZWxmLWhvc3RlZCBjaGVjayAtLWFsbCBbLS13YWl0IERVUl1gIHwgRmFuLW91dCBvdmVyIGFs" + + "bCBvZiB0aGUgYWJvdmUgfCBzdHJlYW1pbmcgZXZlbnRzIHwgfAp8IGBzZWxmLWhvc3RlZCBpbnN0" + + "YWxsIC0tY29udHJvbC1wbGFuZWAgfCBSZW5kZXIgY29udHJvbC1wbGFuZSBtYW5pZmVzdHMgfCBZ" + + "QU1MIG9uIHN0ZG91dCB8IFBpcGUgdG8gYGt1YmVjdGwgYXBwbHkgLWYgLWAgfAp8IGBzZWxmLWhv" + + "c3RlZCBpbnN0YWxsIC0tY29tcHV0ZS1wbGFuZSAtLWNsdXN0ZXItbmFtZT1YYCB8IFJlZ2lzdGVy" + + "IGNsdXN0ZXIgKyByZW5kZXIgY29tcHV0ZSBtYW5pZmVzdHMgfCBZQU1MIG9uIHN0ZG91dCB8IE9u" + + "ZSBpbnZvY2F0aW9uIHBlciBHUFUgY2x1c3RlciB8CnwgYHNlbGYtaG9zdGVkIHVwIC0tY2x1c3Rl" + + "ci1uYW1lPVhgIHwgT25lLXNob3QgZmlyc3QgaW5zdGFsbCAoYm90aCBwbGFuZXMpIHwgKGVtcHR5" + + "KSBzdGRvdXQsIHByb2dyZXNzIG9uIHN0ZGVyciB8IEFsd2F5cyBpbnN0YWxscyBib3RoIHBsYW5l" + + "czsgZm9yIGNvbXB1dGUtb25seSB1c2UgYGFkZC1jb21wdXRlLXBsYW5lYCB8CnwgYHNlbGYtaG9z" + + "dGVkIHVwIC0tcGxhbi1vbmx5IC0tY2x1c3Rlci1uYW1lPVhgIHwgRHJ5LXJ1biBwcmV2aWV3IHwg" + + "SlNPTkwgb24gc3RkZXJyIHwgQWdlbnQtZnJpZW5kbHksIG5vIGNsdXN0ZXIgY2hhbmdlcyB8Cnwg" + + "YHNlbGYtaG9zdGVkIGFkZC1jb21wdXRlLXBsYW5lIC0tY2x1c3Rlci1uYW1lPVggLS1jb21wdXRl" + + "LXBsYW5lLWNvbnRleHQ9WSAtLWljbXMtdXJsPVVSTCAtLXRva2VuPSRKV1RgIHwgQWRkIGEgY29t" + + "cHV0ZSBwbGFuZSB0byBhbiBleGlzdGluZyBjb250cm9sIHBsYW5lIHwgcHJvZ3Jlc3Mgb24gc3Rk" + + "ZXJyIHwgRm9yIDJuZCwgM3JkLCDigKYgR1BVIGNsdXN0ZXIgYWZ0ZXIgdGhlIGZpcnN0IGluc3Rh" + + "bGwuIENQIG5vdCB0b3VjaGVkLiB8CnwgYHNlbGYtaG9zdGVkIHN0YXR1cyBbLS1jbHVzdGVyLW5h" + + "bWU9WF0gWy0td2F0Y2hdYCB8IFNuYXBzaG90IGNsdXN0ZXIgaGVhbHRoIHwgVFRZL3BsYWluL0pT" + + "T05MIHwgYC0td2F0Y2hgIGZvciBsaXZlIHJlLXJlbmRlciB8CnwgYHNlbGYtaG9zdGVkIHVuaW5z" + + "dGFsbCAtLWNvbXB1dGUtcGxhbmUgLS1jbHVzdGVyLW5hbWU9WGAgfCBQZXItcGxhbmUgcHJpbWl0" + + "aXZlOiBgaGVsbWZpbGUgZGVzdHJveWAgb24gb25lIGNvbXB1dGUgcGxhbmUgKG5vIElDTVMgdW5y" + + "ZWdpc3Rlciwgbm8gZHJhaW4pIHwgcHJvZ3Jlc3MgfCBKdXN0IHRoZSBoZWxtIHJlbGVhc2VzIG9u" + + "IHRoYXQgY29tcHV0ZSBwbGFuZSB8CnwgYHNlbGYtaG9zdGVkIHVuaW5zdGFsbCAtLWNvbnRyb2wt" + + "cGxhbmUgWy0tZm9yY2Utd2l0aC1yZWdpc3RlcmVkLWNsdXN0ZXJzXWAgfCBQZXItcGxhbmUgcHJp" + + "bWl0aXZlOiBgaGVsbWZpbGUgZGVzdHJveWAgb24gdGhlIGNvbnRyb2wgcGxhbmUgfCBwcm9ncmVz" + + "cyB8IFJlZnVzZXMgaWYgY29tcHV0ZSBwbGFuZXMgc3RpbGwgcmVnaXN0ZXJlZCB1bmxlc3MgYC0t" + + "Zm9yY2Utd2l0aC1yZWdpc3RlcmVkLWNsdXN0ZXJzYCB8CnwgYHNlbGYtaG9zdGVkIHVuaW5zdGFs" + + "bCAtLW5vLWFwcGx5IDxwbGFuZT5gIHwgUmVuZGVyIGRlbGV0ZSBZQU1MIHZpYSBgaGVsbSBnZXQg" + + "bWFuaWZlc3RgIHBlciByZWxlYXNlIHwgWUFNTCBvbiBzdGRvdXQgfCBHaXRPcHM7IHBpcGUgdG8g" + + "YGt1YmVjdGwgZGVsZXRlIC1mIC1gIG9yIGNvbW1pdCArIEFyZ28gYXBwbGllcy4gTWlycm9ycyBg" + + "aW5zdGFsbCAtLW5vLWFwcGx5YCB8CnwgYHNlbGYtaG9zdGVkIGRvd24gLS1jbHVzdGVyLW5hbWU9" + + "WCBbLS1kcmFpbi1hY3RpdmVdIFstLXJlbW92ZS1wZXJzaXN0ZW50XWAgfCBPcmNoZXN0cmF0b3I6" + + "IGRyYWluIOKGkiB1bmluc3RhbGwgLS1jb21wdXRlLXBsYW5lIOKGkiBjbHVzdGVyIGRlbGV0ZSBp" + + "biBJQ01TIHwgcHJvZ3Jlc3MgfCBTeW1tZXRyaWMgY29tcGFuaW9uIHRvIGB1cCAtLWNsdXN0ZXIt" + + "bmFtZT1YYCB8CnwgYHNlbGYtaG9zdGVkIGRvd24gLS1hbGwgWy0tY29uZmlybV1gIHwgT3JjaGVz" + + "dHJhdG9yOiB0ZWFyIGRvd24gZXZlcnkgcmVnaXN0ZXJlZCBjb21wdXRlIHBsYW5lICsgY29udHJv" + + "bCBwbGFuZSB8IHByb2dyZXNzIHwgQm91bmRlZCBwYXJhbGxlbGlzbSB2aWEgYC0tYWxsLWNvbmN1" + + "cnJlbmN5YCAoZGVmYXVsdCA0KTsgYC0tY29uZmlybWAgcmVxdWlyZWQgaW4gbm9uLWludGVyYWN0" + + "aXZlIHwKfCBgc2VsZi1ob3N0ZWQgZG93biAtLXBsYW4tb25seSAuLi5gIHwgT3JjaGVzdHJhdG9y" + + "IGRyeS1ydW46IHBoYXNlcyArIGhlbG0gcmVsZWFzZXMgKyBJQ01TIHJvd3MgKyBFVEFzIChubyBo" + + "ZWxtL2hlbG1maWxlIGNvbnRhY3QpIHwgSlNPTkwgfCAqKkFsd2F5cyBydW4gYmVmb3JlIGFueSBh" + + "Y3R1YWwgYGRvd25gKiogfAoKIyMgQ2x1c3RlciBtYW5hZ2VtZW50Cgp8IENvbW1hbmQgfCBQdXJw" + + "b3NlIHwgTm90ZXMgfAp8LS0tfC0tLXwtLS18CnwgYGNsdXN0ZXIgcmVnaXN0ZXIgLS1uYW1lPVgg" + + "LS1uY2EtaWQ9WSBbLS1yZWdpb249Wl0gWy0taWdub3JlLWV4aXN0aW5nXWAgfCBSZWdpc3RlciBh" + + "IEpXS1MrT0lEQyB3aXRoIElDTVMgfCBVc2VkIGJ5IGB1cGAgUGhhc2UgNSBpbnRlcm5hbGx5OyBz" + + "dGFuZGFsb25lIGZvciBtYW51YWwgcmVnaXN0cmF0aW9uIHwKfCBgY2x1c3RlciBsaXN0LXJlZ2lz" + + "dGVyZWQgLS1uY2EtaWQ9WSBbLS1pY21zLXVybD1VUkxdYCB8IExpc3Qgc2VsZi1ob3N0ZWQgY2x1" + + "c3RlciByZWdpc3RyYXRpb25zIGZyb20gSUNNUyB8IFVzZXMgdGhlIGFkbWluIHRva2VuOyBgLS1q" + + "c29uYCBmb3IgbWFjaGluZS1yZWFkYWJsZSBvdXRwdXQgfAp8IGBjbHVzdGVyIHJvdGF0ZSAtLWNs" + + "dXN0ZXItaWQ9SURgIHwgUmUtZmV0Y2ggSldLUyBmcm9tIEs4cyBhbmQgUFVUIHRvIElDTVMgfCBB" + + "ZnRlciBLOHMgQVBJIHNlcnZlciBzaWduaW5nIGtleSByb3RhdGlvbiB8CnwgYGNsdXN0ZXIgZGVs" + + "ZXRlIC0tY2x1c3Rlci1pZD1JRGAgfCBSZW1vdmUgSUNNUyByb3cgfCAqKkRFU1RSVUNUSVZFOiBj" + + "b25maXJtIHdpdGggdXNlcioqIHwKCiMjIEZ1bmN0aW9ucwoKfCBDb21tYW5kIHwgUHVycG9zZSB8" + + "IE5vdGVzIHwKfC0tLXwtLS18LS0tfAp8IGBmdW5jdGlvbiBjcmVhdGUgLS1pbnB1dC1maWxlPUZJ" + + "TEVgIHwgQ3JlYXRlIGZ1bmN0aW9uIG1ldGFkYXRhIHwgUmV0dXJucyBGdW5jdGlvbiBJRCArIFZl" + + "cnNpb24gSUQ7IExMTSBmdW5jdGlvbnMgdXNlIGBmdW5jdGlvblR5cGU6ICJMTE0iYCBhbmQgYG1v" + + "ZGVsc1tdLmxsbUNvbmZpZy51cmlzYCBmb3IgYC92MS9jaGF0L2NvbXBsZXRpb25zYCwgYC92MS9y" + + "ZXNwb25zZXNgLCBhbmQgYC92MS9lbWJlZGRpbmdzYCB8CnwgYGZ1bmN0aW9uIGxpc3RgIC8gYGZ1" + + "bmN0aW9uIGxpc3QtaWRzYCB8IExpc3QgZnVuY3Rpb25zIC8gSURzIG9ubHkgfCB8CnwgYGZ1bmN0" + + "aW9uIGdldCAtLWZ1bmN0aW9uLWlkPUlEIC0tdmVyc2lvbi1pZD1WSURgIHwgRnVuY3Rpb24gbWV0" + + "YWRhdGEgfCB8CnwgYGZ1bmN0aW9uIHVwZGF0ZSAtLWZ1bmN0aW9uLWlkPUlEIC0tdmVyc2lvbi1p" + + "ZD1WSUQgLS10YWdzPVRBR1ssVEFHXWAgfCBVcGRhdGUgZnVuY3Rpb24gdGFncyB8IHwKfCBgZnVu" + + "Y3Rpb24gdXBkYXRlIC0tZnVuY3Rpb24taWQ9SUQgLS12ZXJzaW9uLWlkPVZJRCAtLWxsbS1tb2Rl" + + "bC11cGRhdGU9U1BFQ2AgfCBVcGRhdGUgTExNIG1vZGVsIHJvdXRpbmcgY29uZmlnIHwgYFNQRUNg" + + "IHVzZXMgYG5hbWU9PG1vZGVsPixyb3V0aW5nTWV0aG9kPTxtZXRob2Q+LHRva2VuUmF0ZUxpbWl0" + + "PTxsaW1pdD5gOyBhY2NlcHRlZCBtZXRob2RzIGFyZSBsaXN0ZWQgaW4gW2ZsYWdzLm1kXShmbGFn" + + "cy5tZCkgfAp8IGBmdW5jdGlvbiBkZXBsb3kgY3JlYXRlIC0taW5wdXQtZmlsZT1GSUxFYCB8IFNj" + + "aGVkdWxlIGEgZGVwbG95bWVudCB8IEJsb2NrcyB1bnRpbCBBQ1RJVkUgKGRlZmF1bHQgOTAwcykg" + + "fAp8IGBmdW5jdGlvbiBkZXBsb3kgZ2V0IC0tZnVuY3Rpb24taWQ9SUQgLS12ZXJzaW9uLWlkPVZJ" + + "RCBbLS1qc29uXWAgfCBEZXBsb3ltZW50IHN0YXR1cyB8IGBmdW5jdGlvblN0YXR1czogQUNUSVZF" + + "XHxERVBMT1lJTkdcfEVSUk9SXHxGQUlMRURgIHwKfCBgZnVuY3Rpb24gZGVwbG95IHVwZGF0ZSAt" + + "LWlucHV0LWZpbGU9RklMRWAgfCBNb2RpZnkgYSBkZXBsb3ltZW50IGluIHBsYWNlIHwgfAp8IGBm" + + "dW5jdGlvbiBkZXBsb3kgcmVtb3ZlIC0tZnVuY3Rpb24taWQ9SUQgLS12ZXJzaW9uLWlkPVZJRGAg" + + "fCBTdG9wIGEgZGVwbG95bWVudCwga2VlcCBmdW5jdGlvbiByZWNvcmQgfCB8CnwgYGZ1bmN0aW9u" + + "IGludm9rZSAtLWlucHV0LWZpbGU9RklMRWAgfCBDYWxsIGEgcmVndWxhciBmdW5jdGlvbiB8IFJl" + + "cXVpcmVzIEFQSSBrZXkgKG5vdCBhZG1pbiB0b2tlbik7IExMTSBmdW5jdGlvbnMgYXJlIGludm9r" + + "ZWQgdGhyb3VnaCBgbGxtLmludm9jYXRpb24uPGRvbWFpbj5gIHdpdGggYG1vZGVsOiAiPGZ1bmN0" + + "aW9uLWlkPi88bW9kZWwtbmFtZT4iYCB8CnwgYGZ1bmN0aW9uIGRlbGV0ZSAtLWZ1bmN0aW9uLWlk" + + "PUlEIC0tdmVyc2lvbi1pZD1WSURgIHwgUmVtb3ZlIGZ1bmN0aW9uICsgZGVwbG95bWVudCB8ICoq" + + "REVTVFJVQ1RJVkU6IGNvbmZpcm0gd2l0aCB1c2VyKiogfAoKIyMgVGFza3MKClRhc2sgY29tbWFu" + + "ZHMgcmVxdWlyZSBgTlZDRl9BUElfS0VZYCBzZXQgdG8gYSB0YXNrLXNjb3BlZCBrZXkgYW5kIGBO" + + "VkNGX0JBU0VfTlZDVF9VUkxgIHNldCB0byB0aGUgTlZDVCBnYXRld2F5IGVuZHBvaW50LiBJbiBh" + + "IGZyZXNoIHNlc3Npb24sIHJlYWQgYG52Y3RBcGlLZXlgIGZyb20gYH4vLm52Y2YtY2xpLnN0YXRl" + + "YCBhbmQgaW5qZWN0IGl0IGFzIGBOVkNGX0FQSV9LRVlgIHdpdGhvdXQgbG9nZ2luZyB0aGUgdmFs" + + "dWU7IGNoZWNrIGBudmN0QXBpS2V5RXhwaXJhdGlvbmAgZmlyc3QgYW5kIHJlZ2VuZXJhdGUgd2l0" + + "aCBgYXBpLWtleSBnZW5lcmF0ZSAtLWZvciB0YXNrIC0tdmFsaWRhdGVgIGlmIGV4cGlyZWQuIFJ1" + + "biBgYXBpLWtleSBnZW5lcmF0ZSAtLWZvciB0YXNrYCBhZnRlciBgaW5pdGAgdG8gbWludCBhIG5l" + + "dyBrZXkuCgp8IENvbW1hbmQgfCBQdXJwb3NlIHwgTm90ZXMgfAp8LS0tfC0tLXwtLS18CnwgYHRh" + + "c2sgY3JlYXRlIC0tbmFtZT1YIC0tZ3B1PUdQVSAtLWluc3RhbmNlLXR5cGU9VFlQRSAtLWltYWdl" + + "PUlNR2AgfCBTdWJtaXQgYSBjb250YWluZXIgdGFzayB8IFNhdmVzIHRhc2sgSUQgdG8gQ0xJIHN0" + + "YXRlOyB1c2UgYC0taW5wdXQtZmlsZWAgZm9yIHJlcGVhdGFibGUgY29uZmlncyB8CnwgYHRhc2sg" + + "Y3JlYXRlIC0tbmFtZT1YIC0tZ3B1PUdQVSAtLWluc3RhbmNlLXR5cGU9VFlQRSAtLWhlbG0tY2hh" + + "cnQ9Q0hBUlRgIHwgU3VibWl0IGEgSGVsbSB0YXNrIHwgYC0taGVsbS1jaGFydGAgcmVwbGFjZXMg" + + "YC0taW1hZ2VgIHwKfCBgdGFzayBjcmVhdGUgLS1pbnB1dC1maWxlPUZJTEVgIHwgU3VibWl0IGEg" + + "dGFzayBmcm9tIGEgSlNPTiBjb25maWcgZmlsZSB8IFJlY29tbWVuZGVkIGZvciByZXBlYXRhYmxl" + + "IGNvbmZpZ3VyYXRpb25zIHwKfCBgdGFzayBsaXN0IFstLXN0YXR1cz1TVEFUVVNdIFstLWxpbWl0" + + "PU5dYCB8IExpc3QgdGFza3MsIG9wdGlvbmFsbHkgZmlsdGVyZWQgYnkgc3RhdHVzIHwgU3RhdHVz" + + "ZXM6IGBRVUVVRURgLCBgTEFVTkNIRURgLCBgUlVOTklOR2AsIGBDT01QTEVURURgLCBgRVJST1JF" + + "RGAsIGBDQU5DRUxFRGAsIGBFWENFRURFRF9NQVhfUlVOVElNRV9EVVJBVElPTmAsIGBFWENFRURF" + + "RF9NQVhfUVVFVUVEX0RVUkFUSU9OYCB8CnwgYHRhc2sgZ2V0IFt0YXNrSWRdYCB8IEdldCB0YXNr" + + "IGRldGFpbHMgfCBVc2VzIHNhdmVkIHRhc2sgSUQgZnJvbSBzdGF0ZSBpZiBvbWl0dGVkIHwKfCBg" + + "dGFzayBldmVudHMgW3Rhc2tJZF0gWy0tbGltaXQ9Tl1gIHwgTGlzdCBsaWZlY3ljbGUgZXZlbnRz" + + "IGZvciBhIHRhc2sgfCB8CnwgYHRhc2sgcmVzdWx0cyBbdGFza0lkXWAgfCBMaXN0IHJlc3VsdCBh" + + "cnRpZmFjdHMgZm9yIGEgY29tcGxldGVkIHRhc2sgfCBSZXR1cm5zIGVtcHR5IGxpc3Qgd2hlbiBg" + + "cmVzdWx0SGFuZGxpbmdTdHJhdGVneWAgaXMgYE5PTkVgOyByZXN1bHQgdXBsb2FkIG5vdCB5ZXQg" + + "c3VwcG9ydGVkIHwKfCBgdGFzayBjYW5jZWwgW3Rhc2tJZF1gIHwgQ2FuY2VsIGEgcnVubmluZyB0" + + "YXNrIHwgTm8tb3AgaWYgYWxyZWFkeSBpbiB0ZXJtaW5hbCBzdGF0ZSB8CnwgYHRhc2sgZGVsZXRl" + + "IFt0YXNrSWRdYCB8IERlbGV0ZSBhIHRhc2sgcmVjb3JkIHwgKipTdG9wLCBzdGF0ZSB0YXNrIElE" + + "ICsgY3VycmVudCBzdGF0dXMsIGFuZCB3YWl0IGZvciBhIHN1YnNlcXVlbnQgdXNlciByZXBseSBl" + + "eHBsaWNpdGx5IGNvbmZpcm1pbmcgZGVsZXRpb24gb2YgdGhhdCBzcGVjaWZpYyB0YXNrLiBEbyBu" + + "b3QgdHJlYXQgdGhlIG9yaWdpbmFsIGRlbGV0ZSByZXF1ZXN0IGFzIGNvbmZpcm1hdGlvbi4qKiB8" + + "CnwgYHRhc2sgdXBkYXRlLXNlY3JldHMgW3Rhc2tJZF0gLS1zZWNyZXRzIE5BTUU9dmFsdWVgIHwg" + + "VXBkYXRlIHNlY3JldHMgb24gYSB0YXNrOyBzdXBwbGllZCBzZWNyZXRzIGFyZSBhZGRlZCBvciB1" + + "cGRhdGVkIGJ5IG5hbWUsIGV4aXN0aW5nIHNlY3JldHMgbm90IGluIHRoZSByZXF1ZXN0IGFyZSBw" + + "cmVzZXJ2ZWQgfCBWYWx1ZXMgYXJlIGVuY3J5cHRlZCBhdCByZXN0IHwKfCBgdGFzayBidWxrIC0t" + + "dGFzay1pZHM9SUQxWyxJRDIs4oCmXWAgfCBGZXRjaCBkZXRhaWxzIGZvciBtdWx0aXBsZSB0YXNr" + + "cyBpbiBvbmUgcmVxdWVzdCB8IHwKCiMjIEF1dGgKCnwgQ29tbWFuZCB8IFB1cnBvc2UgfCBOb3Rl" + + "cyB8CnwtLS18LS0tfC0tLXwKfCBgaW5pdGAgfCBNaW50IGFkbWluIHRva2VuIGZyb20gQVBJIEtl" + + "eXMgdmlhIHB1YmxpYyBhcGkgZ2F0ZXdheSB8IElkZW1wb3RlbnQ7IHdyaXRlcyBgfi8ubnZjZi1j" + + "bGkuc3RhdGVgOyBjbGVhcnMgc2F2ZWQgZnVuY3Rpb24gc3RhdGUgYW5kIGFsbCBBUEkga2V5cyAo" + + "ZnVuY3Rpb24gYW5kIHRhc2spIHwKfCBgc3RhdHVzYCB8IFNob3cgQ0xJIHN0YXRlICh0b2tlbiwg" + + "bGFzdCBlbmRwb2ludHMsIGZ1bmN0aW9uIGNvbnRleHQpIHwgRGlzdGluY3QgZnJvbSBgc2VsZi1o" + + "b3N0ZWQgc3RhdHVzYCB8CnwgYGFwaS1rZXkgZ2VuZXJhdGUgWy0tZm9yIGZ1bmN0aW9uXHx0YXNr" + + "XSBbLS1kZXNjcmlwdGlvbj3igKZdIFstLWV4cGlyZXMtaW494oCmXWAgfCBNaW50IEFQSSBrZXlz" + + "IHwgRGVmYXVsdCAobm8gYC0tZm9yYCk6IGdlbmVyYXRlcyBib3RoIGEgZnVuY3Rpb24ga2V5IGFu" + + "ZCBhIHRhc2sga2V5OyBgLS1mb3IgZnVuY3Rpb25gIG9yIGAtLWZvciB0YXNrYCBnZW5lcmF0ZXMg" + + "b25lIG9ubHk7IGAtLXNjb3Blc2AgcmVxdWlyZXMgYC0tZm9yYCB8CnwgYGFwaS1rZXkgZ2VuZXJh" + + "dGUgLS12YWxpZGF0ZWAgfCBNaW50IGFuZCBpbW1lZGlhdGVseSB2YWxpZGF0ZSBlYWNoIGdlbmVy" + + "YXRlZCBrZXkgfCBWYWxpZGF0ZXMgZWFjaCBrZXkgYWdhaW5zdCBpdHMgY29ycmVjdCBhdWRpZW5j" + + "ZSAoTlZDRiBmb3IgZnVuY3Rpb24ga2V5cywgTlZDVCBmb3IgdGFzayBrZXlzKSB8CnwgYGFwaS1r" + + "ZXkgbGlzdGAgfCBMaXN0IEFQSSBrZXlzIGZvciBjdXJyZW50IG93bmVyIHwgTGlzdHMgTlZDRi1z" + + "Y29wZWQga2V5cyBvbmx5IHwKfCBgYXBpLWtleSBkZWxldGUgS0VZLUlEYCAvIGBhcGkta2V5IHJl" + + "dm9rZSBLRVktSURgIHwgUmVtb3ZlIGFuIEFQSSBrZXkgfCAqKkNvbmZpcm0gd2l0aCB1c2VyKiog" + + "fAp8IGBhcGkta2V5IHNob3dgIHwgU2hvdyBjdXJyZW50bHkgc2F2ZWQgQVBJIGtleSBmcm9tIHN0" + + "YXRlIHwgfAoKIyMgQWdlbnQgc2tpbGwKCnwgQ29tbWFuZCB8IFB1cnBvc2UgfCBOb3RlcyB8Cnwt" + + "LS18LS0tfC0tLXwKfCBgYWdlbnQtc2tpbGwgaW5zdGFsbCBbLS10YXJnZXQ9RElSXWAgfCBJbnN0" + + "YWxsIGFsbCBidW5kbGVkIHB1YmxpYyB1c2VyIHNraWxscyBpbnRvIGB+Ly5jbGF1ZGUvc2tpbGxz" + + "L2AgYW5kIGB+Ly5hZ2VudHMvc2tpbGxzL2AgfCBEZWZhdWx0OiBib3RoIGJhc2Ugc2tpbGxzIGRp" + + "cmVjdG9yaWVzIHwKfCBgYWdlbnQtc2tpbGwgdW5pbnN0YWxsIFstLXRhcmdldD1ESVJdYCB8IFJl" + + "bW92ZSBvbmx5IGJ1bmRsZWQgcHVibGljIHVzZXIgc2tpbGxzIGZyb20gdGhlIHRhcmdldCBiYXNl" + + "IHNraWxscyBkaXJlY3RvcmllcyB8IElkZW1wb3RlbnQ7IHVucmVsYXRlZCBza2lsbHMgcmVtYWlu" + + "IHwKfCBgYWdlbnQtc2tpbGwgc2hvdyBbLS1maWxlPVJFTF1gIHwgUHJpbnQgYnVuZGxlZCBgbnZj" + + "Zi1zZWxmLW1hbmFnZWQtY2xpL1NLSUxMLm1kYCBvciBhbm90aGVyIGVtYmVkZGVkIGZpbGUgfCBG" + + "b3IgZGVidWdnaW5nIHwKfCBgYWdlbnQtc2tpbGwgdmVyc2lvbmAgfCBQcmludCBidWlsZCBTSEEg" + + "YW5kIGVtYmVkZGVkIHB1YmxpYyB1c2VyIHNraWxsIHN1bW1hcnkgfCB8ClBLBwhyDQ9kISMAACEj" + + "AABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAADIACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNs" + + "aS9yZWZlcmVuY2UvZXhpdC1jb2Rlcy5tZFVUBQABAKbOEiMgYG52Y2YtY2xpYCBleGl0IGNvZGVz" + + "CgpTdGFibGUgYWNyb3NzIHN1YmNvbW1hbmRzLiBVc2UgdGhlc2UgdG8gZHJpdmUgYWdlbnQgcmV0" + + "cnkgLyBzdXJmYWNpbmcgbG9naWMuCgp8IENvZGUgfCBNZWFuaW5nIHwgRXhhbXBsZSBjYXVzZXMg" + + "fAp8LS0tfC0tLXwtLS18CnwgYDBgIHwgU3VjY2VzcyB8IEFsbCBjaGVja3MgcGFzc2VkOyBpbnN0" + + "YWxsIGNvbXBsZXRlZDsgZGVwbG95bWVudCBBQ1RJVkUgfAp8IGAxYCB8IEdlbmVyaWMgZXJyb3Ig" + + "fCBIZWxtIHJlbmRlciBmYWlsZWQ7IG5ldHdvcmsgdW5yZWFjaGFibGU7IGZpbGUgbm90IGZvdW5k" + + "OyBZQU1MIHBhcnNlIGVycm9yIHwKfCBgMmAgfCBQcmUtZmxpZ2h0IGNoZWNrIGZhaWxlZCB8IEdh" + + "dGV3YXkgQVBJIENSRHMgbWlzc2luZzsga3ViZWN0bCBub3Qgb24gUEFUSDsgZGVmYXVsdCBTdG9y" + + "YWdlQ2xhc3MgYWJzZW50IHwKfCBgM2AgfCBBZG1pbiBhdXRoIGZhaWxlZCB8IE5vIHRva2VuICsg" + + "YC0tbm9uLWludGVyYWN0aXZlYCBzZXQ7IElDTVMgcmVqZWN0ZWQgSldUOyBpbml0IGVuZHBvaW50" + + "IHVucmVhY2hhYmxlIHwKfCBgNWAgfCBNYW5pZmVzdCBhcHBseSBvciBgLS13YWl0YCB0aW1lZCBv" + + "dXQgfCBIZWxtIGluc3RhbGwgdGltZW91dDsgY2hlY2sgcG9sbGVkIGJ1dCBkaWRuJ3QgcGFzcyBi" + + "ZWZvcmUgZHVyYXRpb24gfAp8IGAxMzBgIHwgQ2FuY2VsbGVkIGJ5IFNJR0lOVC9TSUdURVJNIHwg" + + "VXNlciBDdHJsLUM7IENJIGJ1ZGdldCBleGNlZWRlZDsgcG9kIGV2aWN0ZWQgfAoKIyMgSG93IGFu" + + "IGFnZW50IHNob3VsZCByZWFjdAoKfCBDb2RlIHwgQWdlbnQgYmVoYXZpb3IgfAp8LS0tfC0tLXwK" + + "fCBgMGAgfCBDb250aW51ZSAvIHJlcG9ydCBzdWNjZXNzLiB8CnwgYDFgIHwgU3VyZmFjZSBzdGRl" + + "cnIgdG8gdXNlcjsgYXNrIGJlZm9yZSBhbnkgcmV0cnkuIEdlbmVyaWMgZXJyb3JzIHVzdWFsbHkg" + + "bmVlZCBhIGh1bWFuIHRvIHJlYWQgdGhlIG1lc3NhZ2UuIHwKfCBgMmAgfCBTdXJmYWNlIGZhaWxl" + + "ZCBjaGVja3MgKyB0aGVpciBgaGludFVSTGAuIERvbid0IHByb3Bvc2UgYHVwYCB1bnRpbCB0aGUg" + + "dXNlciBmaXhlcyBwcmVyZXFzLiB8CnwgYDNgIHwgU3VnZ2VzdCBgbnZjZi1jbGkgaW5pdGAgKGlu" + + "dGVyYWN0aXZlKSBPUiBgLS10b2tlbj0kSldUYCAoQ0kpLiBEb24ndCBhdXRvLW1pbnQgd2l0aG91" + + "dCB1c2VyIE9LLiB8CnwgYDVgIHwgQXNrIHVzZXIgaWYgdGhleSB3YW50IHRvIHdhaXQgbG9uZ2Vy" + + "LCBkaWcgaW50byB0aGUgc3RhbGxlZCBjb21wb25lbnQsIG9yIGNhbmNlbC4gfAp8IGAxMzBgIHwg" + + "RG9uJ3QgcmV0cnkgYXV0b21hdGljYWxseTsgdXNlciBleHBsaWNpdGx5IGNhbmNlbGxlZC4gQ29u" + + "ZmlybSBiZWZvcmUgcmUtcnVubmluZy4gfAoKIyMgV2hlcmUgdG8gZmluZCBtb3JlIGRldGFpbAoK" + + "RXZlcnkgbm9uLXplcm8gZXhpdCBlbWl0cyBhIHN0cnVjdHVyZWQgYHBoYXNlX2ZhaWxlZGAgSlNP" + + "TiBldmVudCB3aXRoIGBlcnJDYXRlZ29yeWAsIGBlcnJNZXNzYWdlYCwgYHJlbWVkaWF0aW9uYCAo" + + "YXJyYXkpLCBgcmV0cnlDbGFzc2AgKGVudW06IGBub25lfGltbWVkaWF0ZXxiYWNrb2ZmfGFmdGVy" + + "X3JlbWVkaWF0aW9ufHVua25vd25gKSwgYHJldHJ5QWZ0ZXJTZWNgIChpbnQsIG9wdGlvbmFsKSwg" + + "YW5kIGByYXdgIChzdWJwcm9jZXNzICsgSFRUUCArIEt1YmVybmV0ZXMgc2lnbmFsKS4gQWx3YXlz" + + "IGNvbnN1bWUgdGhlc2UgaW4gYC0tanNvbmAgbW9kZSByYXRoZXIgdGhhbiBwYXJzaW5nIEVuZ2xp" + + "c2ggZnJvbSBzdGRlcnIuClBLBwhzp1pk1QYAANUGAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAA" + + "AC0ACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9yZWZlcmVuY2UvZmxhZ3MubWRVVAUAAQCm" + + "zhIjIGBudmNmLWNsaWAgZmxhZyByZWZlcmVuY2UKCiMjIEdsb2JhbCBmbGFncyAoZXZlcnkgc3Vi" + + "Y29tbWFuZCkKCnwgRmxhZyB8IFB1cnBvc2UgfCBEZWZhdWx0IHwKfC0tLXwtLS18LS0tfAp8IGAt" + + "LWNvbmZpZyBGSUxFYCB8IENvbmZpZyBmaWxlIHBhdGggfCBgJEhPTUUvLm52Y2YtY2xpLnlhbWxg" + + "IHwKfCBgLS1kZWJ1Z2AgfCBWZXJib3NlIEhUVFAgbG9nZ2luZyBvbiBzdGRlcnIgfCBgZmFsc2Vg" + + "IHwKfCBgLS1qc29uYCB8IEpTT05MIGV2ZW50cyBvbiBzdGRlcnIgfCBhdXRvIChvZmYgaW4gVFRZ" + + "LCBvbiB1bmRlciBgLS1ub24taW50ZXJhY3RpdmVgKSB8CgojIyBgc2VsZi1ob3N0ZWRgIHBhcmVu" + + "dCAocGVyc2lzdGVudCBhY3Jvc3Mgc3ViY29tbWFuZHMpCgp8IEZsYWcgfCBQdXJwb3NlIHwgRGVm" + + "YXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS1jb250cm9sLXBsYW5lLXN0YWNrPeKApmAgfCBDb250" + + "cm9sLXBsYW5lIGJ1bmRsZSBzb3VyY2U6IGxvY2FsIHBhdGgsIGdpdCBVUkwsIG9yIGBvY2k6Ly9g" + + "IFVSTCB8IGVtYmVkZGVkIE9DSSBVUkwgcGlubmVkIGJ5IENMSSB2ZXJzaW9uIHwKfCBgLS1jb21w" + + "dXRlLXBsYW5lLXN0YWNrPeKApmAgfCBDb21wdXRlLXBsYW5lIGJ1bmRsZSBzb3VyY2U6IGxvY2Fs" + + "IHBhdGgsIGdpdCBVUkwsIG9yIGBvY2k6Ly9gIFVSTCB8IGVtYmVkZGVkIE9DSSBVUkwgcGlubmVk" + + "IGJ5IENMSSB2ZXJzaW9uIHwKfCBgLS1lbnY9bG9jYWxcfHByZFx84oCmYCB8IEhlbG1maWxlIGVu" + + "dmlyb25tZW50IG5hbWUgfCBgbG9jYWxgIGZvciBkZXYgYnVpbGRzLCBgcHJkYCBmb3IgcmVsZWFz" + + "ZXMgfAp8IGAtLW5vbi1pbnRlcmFjdGl2ZWAgfCBEaXNhYmxlIGFsbCBzdGRpbiBwcm9tcHRzIHwg" + + "YGZhbHNlYCB8CnwgYC0tdG9rZW49JEpXVGAgfCBBZG1pbiBKV1QsIG92ZXJyaWRlcyBzdG9yZWQg" + + "c2Vzc2lvbiB8IC0gfAp8IGAtLW5vLWFwcGx5YCB8IGBpbnN0YWxsYCBvbmx5IC0gZW1pdCBZQU1M" + + "LCBkbyBub3Qga3ViZWN0bCBhcHBseSB8IGBmYWxzZWAgfAp8IGAtLW91dHB1dD10ZXh0XHxqc29u" + + "YCB8IExlZ2FjeSBhbGlhcyBmb3IgYC0tanNvbmAgKGRlcHJlY2F0ZWQsIHJlbW92ZWQgaW4gbmV4" + + "dCBtYWpvcikgfCBgdGV4dGAgfAp8IGAtLXBsYWluYCB8IEZvcmNlIHBsYWluIHN0cmVhbWluZyBv" + + "dXRwdXQgfCBhdXRvLWRldGVjdCB8CnwgYC0td2FpdCBEVVJBVElPTmAgfCBgY2hlY2tgIG9ubHk7" + + "IGJsb2NrIHVudGlsIHBhc3MgfCAtIHwKfCBgLS1jb250cm9sLXBsYW5lLWNvbnRleHQgQ1RYYCB8" + + "IGt1YmVjdGwgY29udGV4dCBmb3IgY29udHJvbCBwbGFuZSAoUkVRLTIwKSB8IGN1cnJlbnQgY29u" + + "dGV4dCB8CnwgYC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0IENUWGAgfCBrdWJlY3RsIGNvbnRleHQg" + + "Zm9yIGNvbXB1dGUgcGxhbmUgKFJFUS0yMCkgfCBjdXJyZW50IGNvbnRleHQgfAp8IGAtLWljbXMt" + + "dXJsIFVSTGAgfCBQdWJsaWMgSUNNUyBVUkw7IHJlcXVpcmVkIHdoZW4gY29udGV4dHMgZGlmZmVy" + + "IHwgZGVyaXZlZCBmcm9tIGBiYXNlX2h0dHBfdXJsYCB8CnwgYC0tbG9jYWwtb25seWAgfCBgY2hl" + + "Y2sgLS1wcmVgIG9ubHk7IHNraXAgYWxsIGt1YmVjdGwgY29udGFjdCB8IGBmYWxzZWAgfAoKIyMg" + + "YGNoZWNrYC1zcGVjaWZpYwoKQXQgbGVhc3Qgb25lIG9mIGAtLXByZWAsIGAtLWNvbnRyb2wtcGxh" + + "bmVgLCBgLS1jb21wdXRlLXBsYW5lYCwgb3IgYC0tYWxsYCBpcwpyZXF1aXJlZC4gRWFjaCBzZWxl" + + "Y3RzIGEgcm9sZTsgb25seSB0aGUgc2VsZWN0ZWQgcm9sZXMgY29udGFjdCBhIGNsdXN0ZXIuCgp8" + + "IEZsYWcgfCBQdXJwb3NlIHwgRGVmYXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS1wcmVgIHwgUHJl" + + "LWZsaWdodDogbG9jYWwtaG9zdCB0b29scyBwbHVzIGNsdXN0ZXIgcmVhZGluZXNzIHwgYGZhbHNl" + + "YCB8CnwgYC0tY29udHJvbC1wbGFuZWAgfCBDb250cm9sLXBsYW5lIGNoZWNrcyB8IGBmYWxzZWAg" + + "fAp8IGAtLWNvbXB1dGUtcGxhbmVgIHwgQ29tcHV0ZS1wbGFuZSBjaGVja3MgfCBgZmFsc2VgIHwK" + + "fCBgLS1hbGxgIHwgRXZlcnkgY2F0ZWdvcnkgfCBgZmFsc2VgIHwKfCBgLS1jbHVzdGVyLW5hbWUg" + + "TkFNRWAgfCBDbHVzdGVyIG5hbWUgZm9yIGNvbXB1dGUtcGxhbmUgY2hlY2tzIHwgLSB8CnwgYC0t" + + "c2tpcC1pbm90aWZ5LWNoZWNrYCB8IFNraXAgdGhlIHBlci1ub2RlIGlub3RpZnktbGltaXRzIHBy" + + "b2JlLiBOZWVkZWQgd2hlbiB0aGUga3ViZWNvbmZpZyB1c2VyIGNhbm5vdCBjcmVhdGUgcG9kcyBp" + + "biBgZGVmYXVsdGAuIEVudjogYE5WQ0ZfQ0xJX1NFTEZIT1NURURfU0tJUF9JTk9USUZZYCB8IGBm" + + "YWxzZWAgfAoKIyMjIENsdXN0ZXItdmFsaWRhdG9yIGZsYWdzCgpUaGUgdmFsaWRhdG9yIHJ1bnMg" + + "YXMgYSBKb2IgaW4gdGhlIGNsdXN0ZXIgYmVpbmcgY2hlY2tlZC4gVGhlIENMSSBjcmVhdGVzIGEK" + + "U2VydmljZUFjY291bnQsIENsdXN0ZXJSb2xlLCBhbmQgQ2x1c3RlclJvbGVCaW5kaW5nIGZvciBp" + + "dCBhbmQgcmVtb3ZlcyB0aGVtCmFmdGVyIHRoZSBydW4sIHNvIHRoZSBrdWJlY29uZmlnIGNvbnRl" + + "eHQgbmVlZHMgcGVybWlzc2lvbiB0byBtYW5hZ2UgdGhvc2UuCgp8IEZsYWcgfCBQdXJwb3NlIHwg" + + "RGVmYXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS1jbHVzdGVyLXZhbGlkYXRvci1pbWFnZSBSRUZg" + + "IHwgVmFsaWRhdG9yIGltYWdlLiBSZXNvbHV0aW9uIG9yZGVyOiBmbGFnLCBgTlZDRl9DTElfQ0xV" + + "U1RFUl9WQUxJREFUT1JfSU1BR0VgLCBjb25maWcga2V5IGBjbHVzdGVyX3ZhbGlkYXRvcl9pbWFn" + + "ZWAuIEEgcmVmIHdpdGggbm8gdGFnIGRpc2NvdmVycyB0aGUgbGF0ZXN0IHN0YWJsZSB0YWcgZnJv" + + "bSB0aGUgcmVnaXN0cnkuIFVuc2V0IGV2ZXJ5d2hlcmUgc2tpcHMgdGhlIHByb2JlIHdpdGggYSB3" + + "YXJuaW5nIHwgLSB8CnwgYC0tY2x1c3Rlci12YWxpZGF0b3ItcmVnaXN0cmllcyBob3N0OnBvcnQs" + + "Li4uYCB8IEV4dHJhIHJlZ2lzdHJpZXMgdGhlIGNvbnRyb2wtcGxhbmUgdmFsaWRhdG9yIHByb2Jl" + + "cyBmb3IgcmVhY2hhYmlsaXR5LiBgbnZjci5pb2AgaXMgYWx3YXlzIHByb2JlZC4gUmVwZWF0YWJs" + + "ZSBvciBjb21tYS1zZXBhcmF0ZWQuIEVudjogYE5WQ0ZfQ0xJX0NMVVNURVJfVkFMSURBVE9SX1JF" + + "R0lTVFJJRVNgOyBjb25maWcga2V5IGBjbHVzdGVyX3ZhbGlkYXRvcl9yZWdpc3RyaWVzYCB8IGBu" + + "dmNyLmlvYCBvbmx5IHwKfCBgLS1jbHVzdGVyLXZhbGlkYXRvci1wdWxsLXNlY3JldCBOQU1FYCB8" + + "IGRvY2tlci1yZWdpc3RyeSBTZWNyZXQgaW4gYGRlZmF1bHRgIHVzZWQgdG8gcHVsbCB0aGUgdmFs" + + "aWRhdG9yIGltYWdlLiBXaGVuIGVtcHR5LCB0aGUgQ0xJIGxvb2tzIGZvciBvbmUgaW4gdGhlIE5W" + + "Q0YgbmFtZXNwYWNlcyBhbmQgZmFsbHMgYmFjayB0byBtaW50aW5nIG9uZSBmcm9tIGBOR0NfQVBJ" + + "X0tFWWAgfCBhdXRvLWRldGVjdCB8CnwgYC0tc2tpcC1jbHVzdGVyLXZhbGlkYXRpb25gIHwgU2tp" + + "cCB0aGUgaW4tY2x1c3RlciB2YWxpZGF0b3IgcHJvYmUgZW50aXJlbHkuIEVudjogYE5WQ0ZfQ0xJ" + + "X1NFTEZIT1NURURfU0tJUF9DTFVTVEVSX1ZBTElEQVRJT05gIHwgYGZhbHNlYCB8CnwgYC0tbm8t" + + "Y2xlYW51cGAgfCBLZWVwIHRoZSB2YWxpZGF0b3IgSm9iIChhbmQgaXRzIFJCQUMpIGFmdGVyIHRo" + + "ZSBydW4gZm9yIGRlYnVnZ2luZy4gVGhlIG5leHQgcnVuIHN0aWxsIHN3ZWVwcyBwcmlvciBKb2Jz" + + "IHwgYGZhbHNlYCB8CnwgYC0tc2hvdy1sb2dzYCB8IFByaW50IHRoZSB2YWxpZGF0b3IgdHJhbnNj" + + "cmlwdCB0byBzdGRlcnIgYWZ0ZXIgdGhlIGNoZWNrIGV2ZW50cy4gVGhlIHRyYW5zY3JpcHQgaXMg" + + "bm90IEpTT04sIGFuZCBgLS1qc29uYCBhbHNvIHdyaXRlcyB0byBzdGRlcnIsIHNvIGxlYXZlIHRo" + + "aXMgb2ZmIHdoZW4gYSBwYXJzZXIgaXMgcmVhZGluZyB0aGUgc3RyZWFtIHwgYGZhbHNlYCB8Cgoj" + + "IyBgdXBgLXNwZWNpZmljCgp8IEZsYWcgfCBQdXJwb3NlIHwgRGVmYXVsdCB8CnwtLS18LS0tfC0t" + + "LXwKfCBgLS1jbHVzdGVyLW5hbWUgTkFNRWAgfCBJQ01TIGNsdXN0ZXIgcm93IGlkZW50aWZpZXIg" + + "KHJlcXVpcmVkKSB8IC0gfAp8IGAtLW5jYS1pZCBJRGAgfCBOQ0EgYWNjb3VudCBJRCB8IGBudmNm" + + "LWRlZmF1bHRgIHwKfCBgLS1yZWdpb24gUkVHSU9OYCB8IENsdXN0ZXIgcmVnaW9uIHwgYHVzLXdl" + + "c3QtMWAgfAp8IGAtLXBsYW4tb25seWAgfCBEcnktcnVuOyBlbWl0IHBoYXNlIHBsYW4gKyBFVEFz" + + "IHdpdGhvdXQgY2hhbmdlcyB8IGBmYWxzZWAgfAoKIyMgYHN0YXR1c2Atc3BlY2lmaWMKCnwgRmxh" + + "ZyB8IFB1cnBvc2UgfCBEZWZhdWx0IHwKfC0tLXwtLS18LS0tfAp8IGAtLWNsdXN0ZXItbmFtZSBO" + + "QU1FYCB8IExpbWl0IHRvIG9uZSBjb21wdXRlIHBsYW5lIHwgLSAoY29udHJvbCArIGFsbCBjbHVz" + + "dGVycykgfAp8IGAtLXdhdGNoYCB8IExpdmUgcmUtcmVuZGVyIHwgYGZhbHNlYCB8CnwgYC0td2F0" + + "Y2gtaW50ZXJ2YWwgRFVSYCB8IGAtLXdhdGNoYCBjYWRlbmNlIHwgYDVzYCB8CnwgYC0tY29tcG9u" + + "ZW50IE5BTUVgIHwgRmlsdGVyIGNvbXBvbmVudHMgcGFuZWwgfCBhbGwgfAp8IGAtLW5vLWV2ZW50" + + "c2AgfCBTa2lwIGV2ZW50cyBwYW5lbCB8IGBmYWxzZWAgfAoKIyMgYGNsdXN0ZXIgcmVnaXN0ZXJg" + + "LXNwZWNpZmljCgp8IEZsYWcgfCBQdXJwb3NlIHwgRGVmYXVsdCB8CnwtLS18LS0tfC0tLXwKfCBg" + + "LS1uYW1lIE5BTUVgIHwgQ2x1c3RlciBuYW1lIChyZXF1aXJlZCkgfCAtIHwKfCBgLS1uY2EtaWQg" + + "SURgIHwgTkNBIElEIChyZXF1aXJlZCkgfCAtIHwKfCBgLS1yZWdpb24gUkVHSU9OYCB8IFJlZ2lv" + + "biB8IGB1cy13ZXN0LTFgIHwKfCBgLS1pY21zLXVybCBVUkxgIHwgSUNNUyBlbmRwb2ludCB8IGZy" + + "b20gY29uZmlnIHwKfCBgLS1pZ25vcmUtZXhpc3RpbmdgIHwgTWF0Y2gtb3ItY3JlYXRlIGluc3Rl" + + "YWQgb2YgZmFpbC1vbi1leGlzdHMgfCBgZmFsc2VgIHwKCiMjIGBhcGkta2V5IGdlbmVyYXRlYC1z" + + "cGVjaWZpYwoKfCBGbGFnIHwgUHVycG9zZSB8IERlZmF1bHQgfAp8LS0tfC0tLXwtLS18CnwgYC0t" + + "Zm9yIGZ1bmN0aW9uXHx0YXNrYCB8IEdlbmVyYXRlIG9ubHkgdGhlIHNwZWNpZmllZCBrZXkgdHlw" + + "ZSB8IChvbWl0IHRvIGdlbmVyYXRlIGJvdGgpIHwKfCBgLS1kZXNjcmlwdGlvbiBURVhUYCB8IEh1" + + "bWFuLXJlYWRhYmxlIGxhYmVsIGZvciB0aGUga2V5IHwgYEdlbmVyYXRlZCBieSBudmNmLWNsaWAg" + + "fAp8IGAtLWV4cGlyZXMtaW4gRFVSQVRJT05gIHwgRXhwaXJ5IG9mZnNldCAoZS5nLiBgMjRoYCwg" + + "YDdkYCk7IHBhcnNlZCBhcyBleHRlbmRlZCBkdXJhdGlvbiB8IGAyNGhgIHwKfCBgLS1zY29wZXMg" + + "U0NPUEVbLFNDT1BFXWAgfCBPdmVycmlkZSBkZWZhdWx0IHNjb3BlczsgcmVxdWlyZXMgYC0tZm9y" + + "YCB8IChzZXJ2aWNlIGRlZmF1bHRzKSB8CnwgYC0tdmFsaWRhdGVgIHwgVmFsaWRhdGUgZWFjaCBn" + + "ZW5lcmF0ZWQga2V5IGltbWVkaWF0ZWx5IGFmdGVyIG1pbnRpbmcgfCBgZmFsc2VgIHwKCkV4dGVu" + + "ZGVkIGR1cmF0aW9uIHVuaXRzOiBgc2AgKHNlY29uZHMpLCBgbWAgKG1pbnV0ZXMpLCBgaGAgKGhv" + + "dXJzKSwgYGRgIChkYXlzKSwgYHdgICh3ZWVrcykuCgojIyBgZnVuY3Rpb24gY3JlYXRlYC1zcGVj" + + "aWZpYwoKYC0taW5wdXQtZmlsZSBGSUxFYCBpcyByZWNvbW1lbmRlZCBmb3IgcmVwZWF0YWJsZSBm" + + "dW5jdGlvbiBkZWZpbml0aW9ucy4gRm9yIGFkLWhvYyBjcmVhdGVzOgoKfCBGbGFnIHwgUHVycG9z" + + "ZSB8IERlZmF1bHQgfAp8LS0tfC0tLXwtLS18CnwgYC0tbmFtZSBOQU1FYCB8IEZ1bmN0aW9uIG5h" + + "bWUgfCAtIHwKfCBgLS1pbWFnZSBJTUFHRWAgfCBDb250YWluZXIgaW1hZ2UgfCAtIHwKfCBgLS1p" + + "bmZlcmVuY2UtdXJsIFVSSWAgfCBDb250YWluZXIgaW5mZXJlbmNlIGVuZHBvaW50IHwgLSB8Cnwg" + + "YC0taW5mZXJlbmNlLXBvcnQgUE9SVGAgfCBDb250YWluZXIgaW5mZXJlbmNlIHBvcnQgfCAtIHwK" + + "fCBgLS1mdW5jdGlvbi10eXBlIERFRkFVTFRcfFNUUkVBTUlOR1x8TExNYCB8IEZ1bmN0aW9uIHR5" + + "cGUgfCBgREVGQVVMVGAgfAp8IGAtLWhlbG0tY2hhcnQgQ0hBUlRgIHwgSGVsbSBjaGFydCBVUkwg" + + "b3IgT0NJIHJlZmVyZW5jZS4gQ2FuIGJlIHVzZWQgd2l0aCBgLS1mdW5jdGlvbi10eXBlPUxMTWAg" + + "Zm9yIGNoYXJ0LXBhY2thZ2VkIExMTSB3b3JrbG9hZHMuIHwgLSB8CnwgYC0taGVsbS1jaGFydC1z" + + "ZXJ2aWNlIE5BTUVgIHwgS3ViZXJuZXRlcyBTZXJ2aWNlIG5hbWUgZXhwb3NlZCBieSB0aGUgY2hh" + + "cnQuIFJlcXVpcmVkIHdoZW4gYC0taGVsbS1jaGFydGAgaXMgc2V0LiB8IC0gfAp8IGAtLW1vZGVs" + + "cyBOQU1FOlZFUlNJT046VVJJYCB8IFN0YW5kYXJkIG1vZGVsIGFydGlmYWN0OyByZXBlYXRhYmxl" + + "IHwgLSB8CnwgYC0tbGxtLW1vZGVsIFNQRUNgIHwgTExNIG1vZGVsIGNvbmZpZzsgZm9ybWF0IGBu" + + "YW1lPTxtb2RlbD4sdXJpcz08dXJpPlx8PHVyaT4scm91dGluZ01ldGhvZD08bWV0aG9kPix0b2tl" + + "blJhdGVMaW1pdD08bGltaXQ+YDsgcmVwZWF0YWJsZS4gVG9rZW4gbGltaXRzIHVzZSBgPHZhbHVl" + + "Pi08dW5pdD5gIHdpdGggYFNgLCBgTWAsIGBIYCwgYERgLCBvciBgV2AsIGZvciBleGFtcGxlIGAx" + + "MDAwLVNgLiBVc2UgaW5wdXQgSlNPTiBmb3IgY29tYmluZWQgdG9rZW4gbGltaXRzIGJlY2F1c2Ug" + + "aW5saW5lIHNwZWNzIHVzZSBjb21tYXMgYXMgZmllbGQgc2VwYXJhdG9ycy4gfCAtIHwKfCBgLS1s" + + "bG0tZGVmYXVsdC1wcmlvcml0eSBQUklPUklUWWAgfCBGdW5jdGlvbi1sZXZlbCBkZWZhdWx0IHJl" + + "cXVlc3QgcHJpb3JpdHkuIExvd2VyIHZhbHVlcyBoYXZlIGhpZ2hlciBwcmlvcml0eS4gfCAtIHwK" + + "fCBgLS1sbG0tcGVyLWFjY291bnQtcHJpb3JpdHkgTkNBLUlEOlBSSU9SSVRZYCB8IFBlci1hY2Nv" + + "dW50IHByaW9yaXR5IG92ZXJyaWRlOyByZXBlYXRhYmxlOyBzdXBwb3J0cyB1cCB0byA2NCBkaXN0" + + "aW5jdCBOQ0EgSUQgb3ZlcnJpZGVzLiBSZXF1aXJlcyBhIGRlZmF1bHQgcHJpb3JpdHkuIHwgLSB8" + + "CgpJbiBKU09OIGFuZCBpbmxpbmUgc3BlY3MsIExMTSBmdW5jdGlvbnMgc2V0IGBmdW5jdGlvblR5" + + "cGU6ICJMTE0iYCBhbmQgbW9kZWwgcm91dGluZyBtZXRhZGF0YSB1bmRlciBgbW9kZWxzW10ubGxt" + + "Q29uZmlnYC4gYGxsbUNvbmZpZy51cmlzYCBkZWNsYXJlcyB0aGUgT3BlbkFJLWNvbXBhdGlibGUg" + + "dXBzdHJlYW0gcGF0aHMgZXhwb3NlZCBieSB0aGUgbW9kZWwuIEN1cnJlbnQgc3VwcG9ydGVkIHBh" + + "dGhzIGFyZSBgL3YxL2NoYXQvY29tcGxldGlvbnNgLCBgL3YxL3Jlc3BvbnNlc2AsIGFuZCBgL3Yx" + + "L2VtYmVkZGluZ3NgLiBgbGxtQ29uZmlnLnJvdXRpbmdNZXRob2RgIGFjY2VwdHMgYHJvdW5kX3Jv" + + "YmluYCwgYHBvd2VyX29mX3R3b2AsIGBncm9xX211bHRpcmVnaW9uYCwgYHB1bHNhcmAsIG9yIGBy" + + "YW5kb21gLgpgbGxtQ29uZmlnLnRva2VuUmF0ZUxpbWl0YCBhY2NlcHRzIG9uZSBvciBtb3JlIGNv" + + "bW1hLXNlcGFyYXRlZCBwb3NpdGl2ZSBpbnRlZ2VyIHRva2VuIGxpbWl0cyBpbiBgPHZhbHVlPi08" + + "dW5pdD5gIGZvcm1hdC4gU3VwcG9ydGVkIHVuaXRzIGFyZSBgU2AgKHNlY29uZHMpLCBgTWAgKG1p" + + "bnV0ZXMpLCBgSGAgKGhvdXJzKSwgYERgIChkYXlzKSwgYW5kIGBXYCAod2Vla3MpLiBVc2UgZGlz" + + "dGluY3QgdW5pdHMgd2hlbiBjb21iaW5pbmcgbGltaXRzLCBmb3IgZXhhbXBsZSBgMTAwMC1TLDUw" + + "MDAtTSwxMDAwMDAtSCw1MDAwMDAtRCwxMDAwMDAwLVdgIGluIGlucHV0IEpTT04uCgpIZWxtIGNo" + + "YXJ0IHBhY2thZ2luZyBpcyBpbmRlcGVuZGVudCBvZiBgZnVuY3Rpb25UeXBlYC4gRm9yIGEgSGVs" + + "bS1jaGFydCBiYWNrZWQgTExNIGZ1bmN0aW9uLCBzZXQgYGZ1bmN0aW9uVHlwZTogIkxMTSJgLCBg" + + "aGVsbUNoYXJ0YCwgYGhlbG1DaGFydFNlcnZpY2VOYW1lYCwgYW5kIGBtb2RlbHNbXS5sbG1Db25m" + + "aWdgIGluIHRoZSBzYW1lIGNyZWF0ZSByZXF1ZXN0LiBgaW5mZXJlbmNlUG9ydGAgbXVzdCBiZSB0" + + "aGUgS3ViZXJuZXRlcyBTZXJ2aWNlIHBvcnQgZXhwb3NlZCBieSBgaGVsbUNoYXJ0U2VydmljZU5h" + + "bWVgLgoKTExNIGludm9jYXRpb24gcmVxdWVzdHMgdXNlIGBtb2RlbDogIjxmdW5jdGlvbi1pZD4v" + + "PG1vZGVsLW5hbWU+ImAuIFRoZSBmdW5jdGlvbiBJRCBzZWxlY3RzIHRoZSBOVkNGIGZ1bmN0aW9u" + + "LCBhbmQgdGhlIG1vZGVsIG5hbWUgaXMgZm9yd2FyZGVkIHVwc3RyZWFtLiBDaGF0IGNvbXBsZXRp" + + "b25zIGFuZCBSZXNwb25zZXMgQVBJIHJlcXVlc3RzIGNhbiB1c2UgYHgtbXVsdGktdHVybi1zZXNz" + + "aW9uLWlkYCBmb3Igc2Vzc2lvbiBzdGlja2luZXNzOyBlbWJlZGRpbmdzIHJlcXVlc3RzIGRvIG5v" + + "dC4KCiMjIGBmdW5jdGlvbiB1cGRhdGVgLXNwZWNpZmljCgp8IEZsYWcgfCBQdXJwb3NlIHwgRGVm" + + "YXVsdCB8CnwtLS18LS0tfC0tLXwKfCBgLS10YWdzIFRBR1ssVEFHXWAgfCBSZXBsYWNlIGZ1bmN0" + + "aW9uIHRhZ3MgfCAtIHwKfCBgLS1sbG0tbW9kZWwtdXBkYXRlIFNQRUNgIHwgTExNIG1vZGVsIHVw" + + "ZGF0ZTsgZm9ybWF0IGBuYW1lPTxtb2RlbD4scm91dGluZ01ldGhvZD08bWV0aG9kPix0b2tlblJh" + + "dGVMaW1pdD08bGltaXQ+YDsgcmVwZWF0YWJsZS4gUm91dGluZyBtZXRob2RzIG1hdGNoIGAtLWxs" + + "bS1tb2RlbGAuIFRva2VuIGxpbWl0IGV4YW1wbGU6IGAxMDAwLVNgLiBVc2UgaW5wdXQgSlNPTiBm" + + "b3IgY29tYmluZWQgdG9rZW4gbGltaXRzLiB8IC0gfAp8IGAtLWxsbS1kZWZhdWx0LXByaW9yaXR5" + + "IFBSSU9SSVRZYCB8IFJlcGxhY2UgdGhlIGZ1bmN0aW9uLWxldmVsIHByaW9yaXR5IGNvbmZpZ3Vy" + + "YXRpb24gd2l0aCB0aGlzIGRlZmF1bHQgYW5kIGFueSBzdXBwbGllZCBwZXItYWNjb3VudCBvdmVy" + + "cmlkZXMuIHwgLSB8CnwgYC0tbGxtLXBlci1hY2NvdW50LXByaW9yaXR5IE5DQS1JRDpQUklPUklU" + + "WWAgfCBQZXItYWNjb3VudCBwcmlvcml0eSBvdmVycmlkZTsgcmVwZWF0YWJsZTsgc3VwcG9ydHMg" + + "dXAgdG8gNjQgZGlzdGluY3QgTkNBIElEIG92ZXJyaWRlcy4gUmVxdWlyZXMgYSBkZWZhdWx0IHBy" + + "aW9yaXR5LiB8IC0gfAoKSW4gSlNPTiwgYGZ1bmN0aW9uIHVwZGF0ZWAgYWNjZXB0cyBgbW9kZWxV" + + "cGRhdGVzW11gIGVudHJpZXMgd2l0aCBgbW9kZWxOYW1lYCBhbmQgYGxsbUNvbmZpZy5yb3V0aW5n" + + "TWV0aG9kYCBhbmQvb3IgYGxsbUNvbmZpZy50b2tlblJhdGVMaW1pdGAuIGB1cmlzYCBhcmUgY3Jl" + + "YXRlLXRpbWUgbW9kZWwgbWV0YWRhdGEgYW5kIGFyZSBub3QgcGFydCBvZiBtb2RlbCB1cGRhdGVz" + + "LgoKIyMgYGZ1bmN0aW9uIGRlcGxveSBjcmVhdGVgLXNwZWNpZmljCgpgLS1pbnB1dC1maWxlIEZJ" + + "TEVgIGlzIHJlY29tbWVuZGVkIChmdWxsIEpTT04gc3BlYykuIEZvciBhZC1ob2Mgb25lLXNob3Qg" + + "dXNlOgoKfCBGbGFnIHwgUHVycG9zZSB8IERlZmF1bHQgfAp8LS0tfC0tLXwtLS18CnwgYC0tZnVu" + + "Y3Rpb24taWQgSURgIHwgRnVuY3Rpb24gSUQgKHJlcXVpcmVkKSB8IC0gfAp8IGAtLWdwdSBOQU1F" + + "YCB8IEdQVSBmYW1pbHkgfCBgSDEwMGAgfAp8IGAtLWluc3RhbmNlLXR5cGUgVFlQRWAgfCBTS1Ug" + + "fCBgTkNQLkdQVS5IMTAwXzF4YCB8CnwgYC0tbWluLWluc3RhbmNlcyBOYCB8IE1pbiByZXBsaWNh" + + "cyB8IGAxYCB8CnwgYC0tbWF4LWluc3RhbmNlcyBOYCB8IE1heCByZXBsaWNhcyB8IGAxYCB8Cnwg" + + "YC0tbWF4LXJlcXVlc3QtY29uY3VycmVuY3kgTmAgfCBDb25jdXJyZW5jeSB8IGAwYCAodW5zZXQ7" + + "IHNlcnZlciBkZWZhdWx0IGFwcGxpZXMpIHwKfCBgLS1jbHVzdGVycyBOQU1FWyxOQU1FXWAgfCBU" + + "YXJnZXQgc3BlY2lmaWMgY29tcHV0ZSBjbHVzdGVycyB8IChhbnkgbWF0Y2hpbmcgU0tVKSB8Cgoj" + + "IyBgdGFzayBjcmVhdGVgLXNwZWNpZmljCgpgLS1pbnB1dC1maWxlIEZJTEVgIGlzIHJlY29tbWVu" + + "ZGVkIGZvciByZXBlYXRhYmxlIHRhc2sgZGVmaW5pdGlvbnMuIEZvciBhZC1ob2MgdXNlOgoKfCBG" + + "bGFnIHwgUHVycG9zZSB8IE5vdGVzIHwKfC0tLXwtLS18LS0tfAp8IGAtLW5hbWUgTkFNRWAgfCBU" + + "YXNrIG5hbWUgKHJlcXVpcmVkKSB8IDEtMTI4IGNoYXJzLCBgXlthLXowLTlBLVpdW2EtejAtOUEt" + + "WlwtX10qJGAgfAp8IGAtLWdwdSBHUFVgIHwgR1BVIG5hbWUgKHJlcXVpcmVkIHdpdGhvdXQgYC0t" + + "aW5wdXQtZmlsZWApIHwgRXhhbXBsZTogYEgxMDBgIHwKfCBgLS1pbnN0YW5jZS10eXBlIFRZUEVg" + + "IHwgSW5zdGFuY2UgdHlwZSAocmVxdWlyZWQgd2l0aG91dCBgLS1pbnB1dC1maWxlYCkgfCBFeGFt" + + "cGxlOiBgTkNQLkdQVS5IMTAwXzF4YCB8CnwgYC0taW1hZ2UgSU1BR0VgIHwgQ29udGFpbmVyIGlt" + + "YWdlIHwgTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYC0taGVsbS1jaGFydGAgfAp8IGAtLWhlbG0t" + + "Y2hhcnQgQ0hBUlRgIHwgSGVsbSBjaGFydCBVUkwgb3IgT0NJIHJlZmVyZW5jZSB8IE11dHVhbGx5" + + "IGV4Y2x1c2l2ZSB3aXRoIGAtLWltYWdlYCB8CnwgYC0taW5wdXQtZmlsZSBGSUxFYCB8IEpTT04g" + + "dGFzayBzcGVjIGZpbGUgfCBDTEkgZmxhZ3Mgb3ZlcnJpZGUgSlNPTiB2YWx1ZXMgd2hlbiBib3Ro" + + "IGFyZSBzZXQgfAp8IGAtLWJhY2tlbmQgQkFDS0VORGAgfCBCYWNrZW5kIC8gQ1NQIHwgLSB8Cnwg" + + "YC0tY2x1c3RlcnMgTkFNRVssTkFNRV1gIHwgU3BlY2lmaWMgY2x1c3RlcnMgd2l0aGluIHRoZSBp" + + "bnN0YW5jZSB8IENvbW1hLXNlcGFyYXRlZCB8CnwgYC0tY29udGFpbmVyLWFyZ3MgQVJHU2AgfCBB" + + "cmdzIHBhc3NlZCB3aGVuIGxhdW5jaGluZyB0aGUgY29udGFpbmVyIHwgU2luZ2xlIHN0cmluZywg" + + "ZS5nLiBgIi0tZXBvY2hzIDEwIC0tYmF0Y2gtc2l6ZSAzMiJgIHwKfCBgLS1jb250YWluZXItZW52" + + "IE5BTUU9dmFsdWVgIHwgQ29udGFpbmVyIGVudmlyb25tZW50IHZhcmlhYmxlOyByZXBlYXRhYmxl" + + "IHwgLSB8CnwgYC0tc2VjcmV0cyBOQU1FPXZhbHVlYCB8IFNlY3JldCBlbnZpcm9ubWVudCB2YXJp" + + "YWJsZTsgcmVwZWF0YWJsZTsgZW5jcnlwdGVkIGF0IHJlc3QgfCAtIHwKfCBgLS1tYXgtcnVudGlt" + + "ZSBEVVJBVElPTmAgfCBNYXggd2FsbC1jbG9jayBydW4gdGltZSAoSVNPIDg2MDEsIGUuZy4gYFBU" + + "NEhgKSB8IE5vIGRlZmF1bHQ7IG9taXQgZm9yIG5vIHRpbWUgbGltaXQgfAp8IGAtLW1heC1xdWV1" + + "ZWQgRFVSQVRJT05gIHwgTWF4IHRpbWUgaW4gcXVldWUgYmVmb3JlIGNhbmNlbGxhdGlvbiAoSVNP" + + "IDg2MDEpIHwgU2VydmVyIGRlZmF1bHQgYFBUNzJIYCB8CnwgYC0tdGVybWluYXRpb24tZ3JhY2Ug" + + "RFVSQVRJT05gIHwgR3JhY2UgcGVyaW9kIGFmdGVyIHN0b3Agc2lnbmFsIChJU08gODYwMSkgfCBT" + + "ZXJ2ZXIgZGVmYXVsdCBgUFQxSGAgfAp8IGAtLXJlc3VsdC1zdHJhdGVneSBVUExPQURcfE5PTkVg" + + "IHwgSG93IHRvIGhhbmRsZSB0YXNrIG91dHB1dCBhcnRpZmFjdHMgfCAtIHwKfCBgLS1yZXN1bHRz" + + "LWxvY2F0aW9uIExPQ0FUSU9OYCB8IFJlc3VsdCB1cGxvYWQgdGFyZ2V0LCBmb3JtYXQgYG9yZy1u" + + "YW1lL1t0ZWFtLW5hbWUvXW1vZGVsLW5hbWVgOyByZXF1aXJlZCB3aGVuIGAtLXJlc3VsdC1zdHJh" + + "dGVneT1VUExPQURgIHwgLSB8CnwgYC0tbW9kZWxzIE5BTUU6VkVSU0lPTjpVUklgIHwgTW9kZWwg" + + "YXJ0aWZhY3Q7IHJlcGVhdGFibGUgfCAtIHwKfCBgLS1yZXNvdXJjZXMgTkFNRTpWRVJTSU9OOlVS" + + "SWAgfCBSZXNvdXJjZSBhcnRpZmFjdDsgcmVwZWF0YWJsZSB8IC0gfAp8IGAtLXRhZ3MgVEFHWyxU" + + "QUddYCB8IFRhc2sgdGFncyB8IENvbW1hLXNlcGFyYXRlZCB8CnwgYC0tZGVzY3JpcHRpb24gVEVY" + + "VGAgfCBUYXNrIGRlc2NyaXB0aW9uIHwgLSB8CnwgYC0tbG9ncy10ZWxlbWV0cnktaWQgVVVJRGAg" + + "fCBMb2dzIHRlbGVtZXRyeSBlbmRwb2ludCBJRCB8IC0gfAp8IGAtLW1ldHJpY3MtdGVsZW1ldHJ5" + + "LWlkIFVVSURgIHwgTWV0cmljcyB0ZWxlbWV0cnkgZW5kcG9pbnQgSUQgfCAtIHwKfCBgLS10cmFj" + + "ZXMtdGVsZW1ldHJ5LWlkIFVVSURgIHwgVHJhY2VzIHRlbGVtZXRyeSBlbmRwb2ludCBJRCB8IC0g" + + "fApQSwcImdDiUBcuAAAXLgAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAA3AAkAZGF0YS9udmNm" + + "LXNlbGYtbWFuYWdlZC1jbGkvcmVmZXJlbmNlL3Ryb3VibGVzaG9vdGluZy5tZFVUBQABAKbOEiMg" + + "VHJvdWJsZXNob290aW5nCgpLbm93biBlcnJvcnMg4oaSIGRpYWdub3N0aWMgY29tbWFuZCDihpIg" + + "cmVtZWRpYXRpb24uIEtlZXAgaW4gc3luYyB3aXRoIHRoZSBzdHJ1Y3R1cmVkIGBwaGFzZV9mYWls" + + "ZWRgIGV2ZW50cyB0aGUgQ0xJIGVtaXRzIChSRVEtMTUpIOKAlCBldmVyeSBlbnRyeSBiZWxvdyBz" + + "aG91bGQgbWFwIHRvIGFuIGBlcnJDYXRlZ29yeWAgYW5kIGEgYHJlbWVkaWF0aW9uYCBhcnJheS4K" + + "CiMjIFByZS1mbGlnaHQKCnwgU3ltcHRvbSB8IENhdXNlIHwgUmVtZWRpYXRpb24gfAp8LS0tfC0t" + + "LXwtLS18CnwgYGt1YmVjdGwgbm90IG9uIFBBVEhgIHwgT3BlcmF0b3IncyBgJFBBVEhgIGRvZXNu" + + "J3QgaW5jbHVkZSBrdWJlY3RsIHwgSW5zdGFsbCBrdWJlY3RsIDEuMjgrOiBodHRwczovL2t1YmVy" + + "bmV0ZXMuaW8vZG9jcy90YXNrcy90b29scy9pbnN0YWxsLWt1YmVjdGwvIHwKfCBgaGVsbWZpbGUg" + + "bm90IG9uIFBBVEhgIHwgU2FtZSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9oZWxtZmlsZS9oZWxtZmls" + + "ZSNpbnN0YWxsYXRpb24gfAp8IGBoZWxtIG5vdCBvbiBQQVRIYCB8IFNhbWUgfCBodHRwczovL2hl" + + "bG0uc2gvZG9jcy9pbnRyby9pbnN0YWxsLyB8CnwgYEdhdGV3YXkgQVBJIENSRHMgbm90IGluc3Rh" + + "bGxlZGAgfCBlbnZveS1nYXRld2F5IHByZXJlcSBtaXNzaW5nIHwgYGhlbG0gaW5zdGFsbCBlZyBv" + + "Y2k6Ly9kb2NrZXIuaW8vZW52b3lwcm94eS9nYXRld2F5LWhlbG0gLS1uYW1lc3BhY2U9ZW52b3kt" + + "Z2F0ZXdheS1zeXN0ZW0gLS1jcmVhdGUtbmFtZXNwYWNlYCB8CnwgYGRlZmF1bHQgU3RvcmFnZUNs" + + "YXNzIG5vdCBhdmFpbGFibGVgIHwgQ2x1c3RlciBoYXMgbm8gZGVmYXVsdCBTQyB8IEFubm90YXRl" + + "IG9uZTogYGt1YmVjdGwgcGF0Y2ggc2MgPG5hbWU+IC1wICd7Im1ldGFkYXRhIjp7ImFubm90YXRp" + + "b25zIjp7InN0b3JhZ2VjbGFzcy5rdWJlcm5ldGVzLmlvL2lzLWRlZmF1bHQtY2xhc3MiOiJ0cnVl" + + "In19fSdgIHwKfCBgR1BVIG9wZXJhdG9yIG5vdCBpbnN0YWxsZWRgIChjb21wdXRlLXBsYW5lKSB8" + + "IG52aWRpYSBHUFUgb3BlcmF0b3IgbWlzc2luZyB8IEluc3RhbGwgcGVyIGh0dHBzOi8vZG9jcy5u" + + "dmlkaWEuY29tL2RhdGFjZW50ZXIvY2xvdWQtbmF0aXZlL2dwdS1vcGVyYXRvci9sYXRlc3QvaW5z" + + "dGFsbC1ncHUtb3BlcmF0b3IuaHRtbCwgT1IgdXNlIGBmYWtlLWdwdS1vcGVyYXRvcmAgZm9yIGRl" + + "diB8CnwgYEdQVSBub2RlIGxhYmVscyBtaXNzaW5nYCAoY29tcHV0ZS1wbGFuZSkgfCBOb2RlcyBu" + + "ZWVkIGBudmlkaWEuY29tL2dwdS5mYW1pbHlgIGV0Yy4gfCBTZXQgYC0tazNzLW5vZGUtbGFiZWwg" + + "bnZpZGlhLmNvbS9ncHUuZmFtaWx5PWhvcHBlckBhZ2VudDpOYCBmb3IgazNkIHwKCiMjIEF1dGgK" + + "CnwgU3ltcHRvbSB8IENhdXNlIHwgUmVtZWRpYXRpb24gfAp8LS0tfC0tLXwtLS18CnwgYGFkbWlu" + + "IHRva2VuIHJlcXVpcmVkYCAoaW5pdCBub3QgcnVuKSB8IE5vIGB+Ly5udmNmLWNsaS5zdGF0ZWAg" + + "YW5kIGAtLXRva2VuYCBub3QgcGFzc2VkIHwgYG52Y2YtY2xpIGluaXRgIChpbnRlcmFjdGl2ZSkg" + + "b3IgYC0tdG9rZW49JEpXVCAtLW5vbi1pbnRlcmFjdGl2ZWAgKENJKSB8CnwgYFNpZ25lZCBKV1Qg" + + "cmVqZWN0ZWQ6IEFub3RoZXIgYWxnb3JpdGhtIGV4cGVjdGVkLCBvciBubyBtYXRjaGluZyBrZXko" + + "cykgZm91bmRgIHwgU3RhbGUgc2Vzc2lvbi5qc29uIGZyb20gYSBkaWZmZXJlbnQgY29udHJvbCBw" + + "bGFuZSB8IGBybSB+Ly5udmNmLWNsaS5zdGF0ZWAgdGhlbiBgbnZjZi1jbGkgaW5pdGAgYWdhaW4g" + + "fAp8IGA0MDMgbWlzc2luZyByZXF1ZXN0ZWQgYXV0aG9yaXRpZXNgIChmdW5jdGlvbiBpbnZva2Up" + + "IHwgQWRtaW4gdG9rZW4gZG9lc24ndCBoYXZlIGBpbnZva2VfZnVuY3Rpb25gIHNjb3BlIHwgYG52" + + "Y2YtY2xpIGFwaS1rZXkgZ2VuZXJhdGUgLS1kZXNjcmlwdGlvbj3igKZgIHRoZW4gcmUtcnVuIGlu" + + "dm9rZSB8CgojIyBJbnN0YWxsIC8gYHVwYAoKfCBTeW1wdG9tIHwgQ2F1c2UgfCBSZW1lZGlhdGlv" + + "biB8CnwtLS18LS0tfC0tLXwKfCBIZWxtIGB0aW1lZCBvdXQgd2FpdGluZyBmb3IgY2Fzc2FuZHJh" + + "YCB8IENhc3NhbmRyYSBTdGF0ZWZ1bFNldCBQVkMgc3R1Y2sgYFBlbmRpbmdgIHwgQ29uZmlybSBk" + + "ZWZhdWx0IFN0b3JhZ2VDbGFzczsgY2hlY2sgYGt1YmVjdGwgZ2V0IHB2LHB2YyAtbiBjYXNzYW5k" + + "cmEtc3lzdGVtYCB8CnwgYEludmFsaWQgR1BVICdOQ1AuR1BVLkgxMDAnIHNwZWNpZmllZGAgKGZ1" + + "bmN0aW9uIGRlcGxveSkgfCBXcm9uZyBmaWVsZCDigJQgYGdwdWAgaXMgdGhlIGZhbWlseSwgbm90" + + "IHRoZSBTS1UgfCBVc2UgYCJncHUiOiAiSDEwMCJgLCBgImluc3RhbmNlVHlwZSI6ICJOQ1AuR1BV" + + "LkgxMDBfMXgiYCB8CnwgYHJlZ2lvbiBtdXN0IGJlIHByb3ZpZGVkYCAoY2x1c3RlciByZWdpc3Rl" + + "ciAvIGluc3RhbGwgLS1jb21wdXRlLXBsYW5lKSB8IGAtLXJlZ2lvbmAgZW1wdHkgKyBgQ0xVU1RF" + + "Ul9SRUdJT05gIGVudiBlbXB0eSB8IFBhc3MgYC0tcmVnaW9uPXVzLXdlc3QtMWAgKG9yIGFueSBu" + + "b24tZW1wdHkgdmFsdWUpIHwKfCBgcmVxdWlyZWRFbnYgIk5DQV9JRCIgaXMgbm90IHNldGAgKGhl" + + "bG1maWxlIGVycm9yIGR1cmluZyBjb21wdXRlLXBsYW5lIGFwcGx5KSB8IE9sZGVyIG52Y2YtY2xp" + + "IGJlZm9yZSBjb21taXQgYDZhYTU3MDRgOyBFeHRyYUVudiBub3QgcHJvcGFnYXRpbmcgTkNBX0lE" + + "IHwgVXBncmFkZSBgbnZjZi1jbGlgIHRvIGEgcmVsZWFzZSBhZnRlciBgNmFhNTcwNGAgfAp8IGBu" + + "dmNhLW9wZXJhdG9yOiBJbWFnZVB1bGxCYWNrT2ZmYCBmb3IgYG52Y2Etb3BlcmF0b3I6cHNhdGAg" + + "fCBJbWFnZSBub3QgaW4gY2x1c3RlciByZWdpc3RyeTsgbXVsdGktY2x1c3RlciBidWlsZCBpcyBs" + + "b2NhbCB8IGBrM2QgaW1hZ2UgaW1wb3J0IG52Y3IuaW8vLi4uL252Y2Etb3BlcmF0b3I6cHNhdCAt" + + "YyA8Y2x1c3Rlcj5gIHwKCiMjIENvbXB1dGUtcGxhbmUgcnVudGltZQoKfCBTeW1wdG9tIHwgQ2F1" + + "c2UgfCBSZW1lZGlhdGlvbiB8CnwtLS18LS0tfC0tLXwKfCBOVkNBIGFnZW50IENyYXNoTG9vcEJh" + + "Y2tPZmYgd2l0aCBgSFRUUCA0MDFgIG9uIGAvdjEvbnZjYS9jbHVzdGVycy8uLi4vcmVnaXN0ZXJg" + + "IHwgU3RhbGUgYG91dC88Y2x1c3Rlcj4tcmVnaXN0ZXItdmFsdWVzLnlhbWxgIGZyb20gcHJpb3Ig" + + "cmVnaXN0ZXI7IGNsdXN0ZXIgSUQgZG9lc24ndCBtYXRjaCBJQ01TIHwgRGVsZXRlIHRoZSBzdGFs" + + "ZSBmaWxlOyByZS1ydW4gYG52Y2YtY2xpIHNlbGYtaG9zdGVkIHVwYCAoaWRlbXBvdGVudCByZWdp" + + "c3RlciB3cml0ZXMgYSBmcmVzaCBmaWxlKSB8CnwgYE5vIGNsdXN0ZXIgZm91bmQgd2l0aCB2YWxp" + + "ZCBKV0tTIGZvciBjbHVzdGVyIElEOiA8aWQ+YCAoSUNNUyBsb2cpIHwgSldLUyBpbiBJQ01TIGRv" + + "ZXNuJ3QgbWF0Y2ggd2hhdCBjb21wdXRlLXBsYW5lIEs4cyBpcyBjdXJyZW50bHkgc2lnbmluZyB8" + + "IGBudmNmLWNsaSBjbHVzdGVyIHJvdGF0ZSAtLWNsdXN0ZXItaWQ9PGlkPmAgfAp8IEZ1bmN0aW9u" + + "IHBvZCBgSW1hZ2VQdWxsQmFja09mZmAgaW4gYG52Y2YtYmFja2VuZGAgfCBJbWFnZS1jcmVkZW50" + + "aWFsLWhlbHBlciBjb25maWcgbWlzc2luZyBvciB3cm9uZyB8IGBrdWJlY3RsIGRlc2NyaWJlIHBv" + + "ZCAtbiBudmNmLWJhY2tlbmQgPHBvZD5gOyBjaGVjayB0aGUgcHVsbCBzZWNyZXQgY29uZmlnIHwK" + + "fCBGdW5jdGlvbiBkZXBsb3kgc3R1Y2sgYERFUExPWUlOR2AgZm9yID41IG1pbiB8IE5BVFMgc3Ry" + + "ZWFtIGluaXQgbGFnIChjb2xkLWNsdXN0ZXIpIOKAlCB3YWl0LCBvciBjaGVjayBOQVRTIGF1dGgt" + + "Y2FsbG91dCBoZWFsdGggfCBga3ViZWN0bCBsb2dzIC1uIG5hdHMtc3lzdGVtIC1sIGFwcC5rdWJl" + + "cm5ldGVzLmlvL25hbWU9bmF0cy1hdXRoLWNhbGxvdXQtc2VydmljZWAgfAoKIyMgVGFza3MKCnwg" + + "U3ltcHRvbSB8IENhdXNlIHwgUmVtZWRpYXRpb24gfAp8LS0tfC0tLXwtLS18CnwgYHRhc2sgY3Jl" + + "YXRlYCByZXR1cm5zIGBNaXNzaW5nIDxUWVBFPiByZWdpc3RyeSBjcmVkZW50aWFsIGZvciBob3N0" + + "bmFtZWAsIG9yIGtlZXBzIHVzaW5nIGEgcHJldmlvdXMgY3JlZGVudGlhbCB2YWx1ZSwgc2hvcnRs" + + "eSBhZnRlciBgcmVnaXN0cnktY3JlZGVudGlhbCBhZGQvdXBkYXRlL2RlbGV0ZWAgd2hpbGUgYHJl" + + "Z2lzdHJ5LWNyZWRlbnRpYWwgbGlzdGAvYGdldGAgYWxyZWFkeSBzaG93IHRoZSBuZXcgdmFsdWUg" + + "fCBFeHBlY3RlZCBwcm9wYWdhdGlvbiBkZWxheTogTlZDVCBjYWNoZXMgdGhlIGFjY291bnQncyBy" + + "ZWdpc3RyeSBjcmVkZW50aWFscyB3aXRoIGBudmN0Lm52Y2YuY2FjaGUtdHRsYCAoZGVmYXVsdCBg" + + "UFQ1TWAsIGFib3V0IDUgbWluKSBhbmQgYXBwbGllcyB0aGUgY2hhbmdlIHdoZW4gdGhhdCBjYWNo" + + "ZWQgY29weSByZWZyZXNoZXMgfCBXYWl0IHVwIHRvIGFib3V0IDUgbWluIGFuZCByZXRyeSwgb3Ig" + + "YGt1YmVjdGwgLW4gbnZjZiByb2xsb3V0IHJlc3RhcnQgZGVwbG95bWVudC9udmN0LWFwaWAgdG8g" + + "YXBwbHkgaW1tZWRpYXRlbHkgfApQSwcI864ThHQRAAB0EQAAUEsDBBQACAAAAAAAIQAAAAAAAAAA" + + "AAAAAAAsAAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vU0tJTEwubWRVVAUA" + + "AQCmzhItLS0KbmFtZTogbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uCmRlc2NyaXB0aW9u" + + "OiA+LQogIEluc3RhbGwgYW5kIG9wZXJhdGUgTlZDRiBzZWxmLWhvc3RlZCBjb250cm9sLXBsYW5l" + + "IGFuZCBzZXBhcmF0ZSBjb21wdXRlLXBsYW5lCiAgc3RhY2tzLiBDb3ZlcnMgSGVsbWZpbGUgdmFs" + + "dWVzIGFuZCBDTEkgcHJvZmlsZSBpbnN0YWxsYXRpb24gZmxvd3MsIHRlYXJkb3duLAogIHZhbHVl" + + "cyBvdmVycmlkZXMsIHB1bGwgc2VjcmV0cywgYW5kIHRyb3VibGVzaG9vdGluZy4gVXNlIGZvcgog" + + "IG52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrLCBudmNmLWNvbXB1dGUtcGxhbmUtc3RhY2ssIHNwbGl0" + + "IGNvbXB1dGUtcGxhbmUKICBpbnN0YWxsYXRpb24sIGNvbnRyb2wtcGxhbmUgaW5zdGFsbGF0aW9u" + + "LCBDTEktZ2VuZXJhdGVkIGNvbnRyb2wtcGxhbmUKICBwcm9maWxlcywgSGVsbWZpbGUsIHNlbGYt" + + "bWFuYWdlZCwgb3Igc2VsZi1ob3N0ZWQgZGVwbG95bWVudHMuIERvIE5PVCB1c2UgZm9yCiAgbG9j" + + "YWwgazNkIGVudmlyb25tZW50czsgdXNlIHRoZSBsb2NhbCBrM2QgZGV2ZWxvcG1lbnQgd29ya2Zs" + + "b3cgaW5zdGVhZC4KbGljZW5zZTogQXBhY2hlLTIuMApjb21wYXRpYmlsaXR5OiBSZXF1aXJlcyBo" + + "ZWxtZmlsZSA+PSAxLjEuMCA8IDEuMi4wLCBoZWxtID49IDMuMTIsIGhlbG0tZGlmZiBwbHVnaW4s" + + "IGt1YmVjdGwgbWF0Y2hpbmcgY2x1c3RlciB2ZXJzaW9uCmF1dGhvcjogIm52Y2YtY29yZS1lbmcg" + + "PG52Y2YtY29yZS1lbmdAZXhjaGFuZ2UubnZpZGlhLmNvbT4iCnZlcnNpb246ICIxLjAuMCIKdGFn" + + "czogW252Y2YsIHNlbGYtbWFuYWdlZCwgaGVsbWZpbGUsIHNlbGYtaG9zdGVkLCBjb250cm9sLXBs" + + "YW5lLCBjb21wdXRlLXBsYW5lLCBjbGktcHJvZmlsZSwgaW5zdGFsbGF0aW9uLCBkZXBsb3ltZW50" + + "LCBwdWxsLXNlY3JldHNdCnRvb2xzOiBbU2hlbGwsIFJlYWQsIEVkaXQsIEdyZXAsIEdsb2JdCm1l" + + "dGFkYXRhOgogIGludGVybmFsOiBmYWxzZQogIGF1dGhvcjogIm52Y2YtY29yZS1lbmcgPG52Y2Yt" + + "Y29yZS1lbmdAZXhjaGFuZ2UubnZpZGlhLmNvbT4iCiAgdmVyc2lvbjogIjEuMCIKICB0YWdzOiBb" + + "bnZjZiwgc2VsZi1tYW5hZ2VkLCBoZWxtZmlsZSwgc2VsZi1ob3N0ZWQsIGNvbnRyb2wtcGxhbmUs" + + "IGNvbXB1dGUtcGxhbmUsIGNsaS1wcm9maWxlLCBpbnN0YWxsYXRpb24sIGRlcGxveW1lbnQsIHB1" + + "bGwtc2VjcmV0c10KICBsYW5ndWFnZXM6IFtiYXNoLCB5YW1sXQogIGZyYW1ld29ya3M6IFtoZWxt" + + "ZmlsZSwgaGVsbSwga3ViZWN0bF0KICBkb21haW46IGNsb3VkLWluZnJhc3RydWN0dXJlCi0tLQoK" + + "IyBOVkNGIFNlbGYtTWFuYWdlZCBTdGFjayBPcGVyYXRpb25zCgpPcGVyYXRpb25hbCBndWlkZSBm" + + "b3IgbWF0Y2hpbmcgTlZDRiBjb250cm9sLXBsYW5lIGFuZCBjb21wdXRlLXBsYW5lIEhlbG1maWxl" + + "IGJ1bmRsZXMuCgojIyBJbnN0cnVjdGlvbnMKClVzZSB0aGlzIHNraWxsIGZvciBpbnN0YWxsLCB1" + + "cGdyYWRlLCBvciB0ZWFyZG93biB3b3JrIGluIG1hdGNoaW5nIGBudmNmLXNlbGYtbWFuYWdlZC1z" + + "dGFja2AgYW5kIGBudmNmLWNvbXB1dGUtcGxhbmUtc3RhY2tgIGJ1bmRsZXM7IGtlZXAgSGVsbWZp" + + "bGUgdmFsdWVzIGFuZCBDTEkgcHJvZmlsZSBoYW5kb2ZmcyBzZXBhcmF0ZS4gRm9yIGBmdW5jdGlv" + + "blR5cGU6ICJMTE0iYCwgcmVhZCBbTExNIEZ1bmN0aW9uIEVuYWJsZW1lbnRdKHJlZmVyZW5jZXMv" + + "aGVsbWZpbGUtc3RydWN0dXJlLm1kI2xsbS1mdW5jdGlvbi1lbmFibGVtZW50KS4KCiMjIFByZXJl" + + "cXVpc2l0ZXMKCkFzayBmb3IgdGhlIGV4dHJhY3RlZCBgbnZjZi1zZWxmLW1hbmFnZWQtc3RhY2tg" + + "IHBhdGguIEZvciBzcGxpdCBpbnN0YWxsYXRpb24sCmFsc28gcmVxdWlyZSB0aGUgbWF0Y2hpbmct" + + "dmVyc2lvbiBgbnZjZi1jb21wdXRlLXBsYW5lLXN0YWNrYCBwYXRoLiBWZXJpZnkgYm90aDoKCmBg" + + "YGJhc2gKbHMgPGNvbnRyb2wtcGxhbmUtc3RhY2s+L2hlbG1maWxlLmQvIDxjb250cm9sLXBsYW5l" + + "LXN0YWNrPi9lbnZpcm9ubWVudHMvIDxjb250cm9sLXBsYW5lLXN0YWNrPi9zZWNyZXRzLyA8Y29u" + + "dHJvbC1wbGFuZS1zdGFjaz4vZ2xvYmFsLnlhbWwuZ290bXBsCmxzIDxjb21wdXRlLXBsYW5lLXN0" + + "YWNrPi9oZWxtZmlsZS5kLyA8Y29tcHV0ZS1wbGFuZS1zdGFjaz4vZW52aXJvbm1lbnRzLyA8Y29t" + + "cHV0ZS1wbGFuZS1zdGFjaz4vZ2xvYmFsLnlhbWwuZ290bXBsCmBgYAoKSWYgZWl0aGVyIGRpcmVj" + + "dG9yeSBpcyBtaXNzaW5nLCBkb3dubG9hZCBtYXRjaGluZyBidW5kbGUgdmVyc2lvbnMgZnJvbSBO" + + "R0M6CgpgYGBiYXNoCm5nYyByZWdpc3RyeSByZXNvdXJjZSBkb3dubG9hZC12ZXJzaW9uIDxvcmc+" + + "L252Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrOjx2ZXJzaW9uPgpuZ2MgcmVnaXN0cnkgcmVzb3VyY2Ug" + + "ZG93bmxvYWQtdmVyc2lvbiA8b3JnPi9udmNmLWNvbXB1dGUtcGxhbmUtc3RhY2s6PHZlcnNpb24+" + + "CmBgYAoKQ29udHJvbC1wbGFuZSBjb21tYW5kcyBiZWxvdyBhc3N1bWUgdGhlIGNvbnRyb2wtcGxh" + + "bmUgYnVuZGxlIHJvb3QuIFNwbGl0LWZsb3cKY29tbWFuZHMgYW5kIHJvb3Qgc3Vic3RpdHV0aW9u" + + "IGFyZSBpbgpbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKHJlZmVyZW5jZXMvY29t" + + "cHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpLgoKIyMgQmVmb3JlIFlvdSBTdGFydAoKVmVyaWZ5" + + "IHRvb2xpbmcgYW5kIGNvbnRleHQgYmVmb3JlIGFueSBvcGVyYXRpb246CgpgYGBiYXNoCmhlbG1m" + + "aWxlIC0tdmVyc2lvbiAgICMgTXVzdCBiZSAxLjEueCAoMS4yLjAgcmVtb3ZlZCBzZXF1ZW50aWFs" + + "IG1vZGUpCmhlbG0gdmVyc2lvbiAgICAgICAgICMgTXVzdCBiZSA+PSAzLjEyCmhlbG0gcGx1Z2lu" + + "IGxpc3QgICAgICMgTXVzdCBpbmNsdWRlIGhlbG0tZGlmZiA+PSAzLjExCmt1YmVjdGwgdmVyc2lv" + + "biAgICAgICMgQ2xpZW50IG11c3QgYmUgd2l0aGluIDEgbWlub3IgdmVyc2lvbiBvZiBjbHVzdGVy" + + "CmBgYAoKQ29udHJvbC1wbGFuZSBjb21tYW5kcyBydW4gZnJvbSB0aGUgZXh0cmFjdGVkIGBudmNm" + + "LXNlbGYtbWFuYWdlZC1zdGFjay9gIHJvb3Q6CgpgYGBiYXNoCmNkIHBhdGgvdG8vbnZjZi1zZWxm" + + "LW1hbmFnZWQtc3RhY2sKbHMgaGVsbWZpbGUuZC8gZW52aXJvbm1lbnRzLyBzZWNyZXRzLyBnbG9i" + + "YWwueWFtbC5nb3RtcGwKYGBgCgpJZGVudGlmeSB0aGUgZW52aXJvbm1lbnQgZnJvbSBgZW52aXJv" + + "bm1lbnRzLzxuYW1lPi55YW1sYCBhbmQKYHNlY3JldHMvPG5hbWU+LXNlY3JldHMueWFtbGA7IGZv" + + "ciBFS1MsIHVzZSB0aGUgY2Fub25pY2FsCltDU1AgRW5kLXRvLUVuZCBFeGFtcGxlXShodHRwczov" + + "L2RvY3MubnZpZGlhLmNvbS9udmNmL3YwLjYuMC1yYy9jc3AtZW5kLXRvLWVuZC1leGFtcGxlKS4K" + + "CiMjIEhvdyBWYWx1ZXMgRmxvdwoKVW5kZXJzdGFuZGluZyB2YWx1ZSBwcmVjZWRlbmNlIHByZXZl" + + "bnRzIHRoZSBtb3N0IGNvbW1vbiBjb25maWd1cmF0aW9uIG1pc3Rha2VzLgoKYGBgdGV4dAplbnZp" + + "cm9ubWVudHMvYmFzZS55YW1sICAgICAgICAgIChkZWZhdWx0cykKICAgIC0+IG1lcmdlZCB3aXRo" + + "CmVudmlyb25tZW50cy88ZW52Pi55YW1sICAgICAgICAgKHlvdXIgb3ZlcnJpZGVzKQogICAgLT4g" + + "Y29uc3VtZWQgYnkKZ2xvYmFsLnlhbWwuZ290bXBsICAgICAgICAgICAgICAoR28gdGVtcGxhdGUs" + + "IGNvbnN0cnVjdHMgcGVyLWNoYXJ0IHZhbHVlcykKICAgIC0+IGNvbnN1bWVkIGJ5CnNlY3JldHMv" + + "PGVudj4tc2VjcmV0cy55YW1sICAgICAgKHNlbnNpdGl2ZSB2YWx1ZXMpCiAgICAtPiBvdmVycmlk" + + "ZGVuIGJ5CnJlbGVhc2UgaW5saW5lIHZhbHVlczogYmxvY2tzICAgKGhpZ2hlc3QgcHJlY2VkZW5j" + + "ZSkKYGBgCgpDcml0aWNhbDogYGdsb2JhbC55YW1sLmdvdG1wbGAgb25seSBwYXNzZXMgdGhyb3Vn" + + "aCBzcGVjaWZpYyBrZXlzIHRvIGVhY2ggY2hhcnQgKGltYWdlIHJlZ2lzdHJpZXMsIG5vZGUgc2Vs" + + "ZWN0b3JzLCBzdG9yYWdlLCByZXBsaWNhIGNvdW50cykuIFNldHRpbmcgYW4gYXJiaXRyYXJ5IGNo" + + "YXJ0IHZhbHVlIGluIHRoZSBlbnZpcm9ubWVudCBmaWxlIHdpbGwgYmUgc2lsZW50bHkgaWdub3Jl" + + "ZCBpZiBgZ2xvYmFsLnlhbWwuZ290bXBsYCBkb2VzIG5vdCBwcm9wYWdhdGUgaXQuCgpUbyBvdmVy" + + "cmlkZSBhcmJpdHJhcnkgY2hhcnQgdmFsdWVzLCB1c2UgYSBoZWxtZmlsZSByZWxlYXNlIGB2YWx1" + + "ZXM6YCBibG9jay4gU2VlIFtPdmVycmlkaW5nIEhlbG0gQ2hhcnQgVmFsdWVzXSgjb3ZlcnJpZGlu" + + "Zy1oZWxtLWNoYXJ0LXZhbHVlcykuCgojIyBDbGVhbiBJbnN0YWxsYXRpb24KCiMjIyAxLiBDcmVh" + + "dGUgbmFtZXNwYWNlcyBhbmQgaW1hZ2UgcHVsbCBzZWNyZXRzIChpZiB1c2luZyBhIHByaXZhdGUg" + + "cmVnaXN0cnkpCgpgYGBiYXNoCmZvciBucyBpbiBjYXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVt" + + "IG52Y2YgYXBpLWtleXMgZXNzIHNpcyB2YXVsdC1zeXN0ZW0gY2VydC1tYW5hZ2VyOyBkbwogIGt1" + + "YmVjdGwgY3JlYXRlIG5hbWVzcGFjZSAiJG5zIiAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBr" + + "dWJlY3RsIGFwcGx5IC1mIC0KZG9uZQoKIyBPbmx5IGlmIHB1bGxpbmcgZnJvbSBhIHByaXZhdGUg" + + "cmVnaXN0cnkgKGUuZy4sIE5HQyBudmNyLmlvKQpleHBvcnQgTkdDX0FQSV9LRVk9Ijx5b3VyLWtl" + + "eT4iCmZvciBucyBpbiBjYXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVtIG52Y2YgYXBpLWtleXMg" + + "ZXNzIHNpcyB2YXVsdC1zeXN0ZW0gY2VydC1tYW5hZ2VyOyBkbwogIGt1YmVjdGwgY3JlYXRlIHNl" + + "Y3JldCBkb2NrZXItcmVnaXN0cnkgbnZjci1jcmVkcyBcCiAgICAtLWRvY2tlci1zZXJ2ZXI9bnZj" + + "ci5pbyBcCiAgICAtLWRvY2tlci11c2VybmFtZT0nJG9hdXRodG9rZW4nIFwKICAgIC0tZG9ja2Vy" + + "LXBhc3N3b3JkPSIkTkdDX0FQSV9LRVkiIFwKICAgIC0tbmFtZXNwYWNlPSIkbnMiIFwKICAgIC0t" + + "ZHJ5LXJ1bj1jbGllbnQgLW8geWFtbCB8IGt1YmVjdGwgYXBwbHkgLWYgLQpkb25lCmBgYAoKSWYg" + + "dXNpbmcgcHVsbCBzZWNyZXRzLCB5b3UgbXVzdCBhbHNvIGNvbmZpZ3VyZSBlYWNoIGhlbG1maWxl" + + "IHJlbGVhc2UgdG8gcmVmZXJlbmNlIHRoZW0uIFNlZSBbSW1hZ2UgUHVsbCBTZWNyZXRzXSgjaW1h" + + "Z2UtcHVsbC1zZWNyZXRzKS4KCiMjIyAyLiBBdXRoZW50aWNhdGUgaGVsbSB0byB5b3VyIGNoYXJ0" + + "IHJlZ2lzdHJ5CgpCb3RoIGBkb2NrZXIgbG9naW5gIEFORCBgaGVsbSByZWdpc3RyeSBsb2dpbmAg" + + "YXJlIHJlcXVpcmVkIGZvciBOR0MuIEhlbG1maWxlIHVzZXMgaGVsbSAobm90IGRvY2tlcikgdG8g" + + "cHVsbCBPQ0kgY2hhcnRzLCBzbyB0aGUgaGVsbSBjcmVkZW50aWFsIHN0b3JlIG11c3QgYmUgYXV0" + + "aGVudGljYXRlZCBzZXBhcmF0ZWx5LgoKYGBgYmFzaAojIE5HQyAtLSBib3RoIGNvbW1hbmRzIGFy" + + "ZSByZXF1aXJlZApkb2NrZXIgbG9naW4gbnZjci5pbyAtdSAnJG9hdXRodG9rZW4nIC1wICIkTkdD" + + "X0FQSV9LRVkiCmhlbG0gcmVnaXN0cnkgbG9naW4gbnZjci5pbyAtdSAnJG9hdXRodG9rZW4nIC1w" + + "ICIkTkdDX0FQSV9LRVkiCgojIEVDUgphd3MgZWNyIGdldC1sb2dpbi1wYXNzd29yZCAtLXJlZ2lv" + + "biA8cmVnaW9uPiB8IFwKICBoZWxtIHJlZ2lzdHJ5IGxvZ2luIC0tdXNlcm5hbWUgQVdTIC0tcGFz" + + "c3dvcmQtc3RkaW4gPGFjY291bnQ+LmRrci5lY3IuPHJlZ2lvbj4uYW1hem9uYXdzLmNvbQpgYGAK" + + "Cj4gTm90ZTogYGhlbG0gcmVnaXN0cnkgbG9naW5gIGtlZXBzIG9ubHkgdGhlIGxhc3QgbG9naW4g" + + "cGVyIGhvc3QgKG11bHRpLW9yZyBnb3RjaGEpLgo+IFRoZSBzdGFjayBhbmQgdGhlIGNhY2hlcyBz" + + "cGFuIHNldmVyYWwgTkdDIG9yZ3MgdGhhdCBuZWVkIGRpZmZlcmVudCBrZXlzLCBidXQgdGhleSBh" + + "bGwKPiBsaXZlIHVuZGVyIHRoZSBvbmUgaG9zdCBgbnZjci5pb2AuIEEgc2Vjb25kIGBoZWxtIHJl" + + "Z2lzdHJ5IGxvZ2luIG52Y3IuaW9gIChvcgo+IGBkb2NrZXIgbG9naW5gKSB3aXRoIGEgZGlmZmVy" + + "ZW50IGtleSBzaWxlbnRseSBvdmVyd3JpdGVzIHRoZSBmaXJzdCwgc28gcHVsbHMgZm9yIHRoZQo+" + + "IGZpcnN0IG9yZyB0aGVuIGZhaWwgd2l0aCBhIG1pc2xlYWRpbmcgYDQwMyBBY2Nlc3MgRGVuaWVk" + + "YCAobm90IGEgNDAxOiB0aGUgYXV0aAo+IHN1Y2NlZWRlZCwgaXQncyB0aGUgd3Jvbmctb3JnIGtl" + + "eSkuIElmIHlvdSBwdWxsIGNoYXJ0cy9pbWFnZXMgZnJvbSBtb3JlIHRoYW4gb25lIG9yZywKPiBl" + + "aXRoZXIgcmUtcnVuIHRoZSBsb2dpbiB3aXRoIHRoZSBjb3JyZWN0IGtleSBpbW1lZGlhdGVseSBi" + + "ZWZvcmUgZWFjaCBwdWxsLCBvciBwYXNzCj4gYC0tdXNlcm5hbWUgJyRvYXV0aHRva2VuJyAtLXBh" + + "c3N3b3JkIDxrZXk+YCBwZXIgYGhlbG0gcHVsbGAgaW52b2NhdGlvbiBpbnN0ZWFkIG9mIHJlbHlp" + + "bmcKPiBvbiB0aGUgc3RvcmVkIGxvZ2luLiAoUHVsbGluZyBldmVyeXRoaW5nIGZyb20gYSBzaW5n" + + "bGUgcmVnaXN0cnkgbWlycm9yIGF2b2lkcyB0aGlzCj4gZW50aXJlbHkuKQoKIyMjIDJiLiAoUmVj" + + "b21tZW5kZWQpIFB1bGwgZnJvbSBhIHJlZ2lzdHJ5IHRoZSBjbHVzdGVyIGF1dGhlbnRpY2F0ZXMg" + + "dG8gYXV0b21hdGljYWxseQoKSWYgeW91IG1pcnJvciB0aGUgTlZDRiBpbWFnZXMgaW50byBhIHJl" + + "Z2lzdHJ5IHRoYXQgdGhlIGNsdXN0ZXIgY2FuIHB1bGwgZnJvbSB3aXRob3V0IGFuCmV4cGxpY2l0" + + "IGltYWdlIHB1bGwgc2VjcmV0IChmb3IgZXhhbXBsZSwgYSByZWdpc3RyeSB3aGVyZSB0aGUgbm9k" + + "ZSBvciB3b3JrbG9hZCBpZGVudGl0eSBpcwpncmFudGVkIHB1bGwgYWNjZXNzIGF1dG9tYXRpY2Fs" + + "bHkpLCBwb2ludCB0aGUgc3RhY2sgYXQgaXQgYW5kIHNraXAgdGhlIGNyZWRlbnRpYWwgc3RlcHMK" + + "YWJvdmUuCgoxLiBQb2ludCB0aGUgc3RhY2sgYXQgdGhlIG1pcnJvciBpbiBgZW52aXJvbm1lbnRz" + + "LzxlbnY+LnlhbWxgOgoKICAgYGBgeWFtbAogICBnbG9iYWw6CiAgICAgaW1hZ2U6CiAgICAgICBy" + + "ZWdpc3RyeTogPHlvdXItcmVnaXN0cnk+ICAgICAgICAgICAgIyBlLmcuIHJlZ2lzdHJ5LmV4YW1w" + + "bGUuY29tCiAgICAgICByZXBvc2l0b3J5OiA8bWlycm9yLXN1Yi1wYXRoPgogICAgIGhlbG06CiAg" + + "ICAgICBzb3VyY2VzOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgb25seSBpZiB5b3Ug" + + "YWxzbyBtaXJyb3JlZCB0aGUgaGVsbSBjaGFydHMKICAgICAgICAgcmVnaXN0cnk6IDx5b3VyLXJl" + + "Z2lzdHJ5PgogICAgICAgICByZXBvc2l0b3J5OiA8bWlycm9yLXN1Yi1wYXRoPgogICBgYGAKCiAg" + + "ID4gVGhlIG1hbmlmZXN0IGhhcyBhIG1peCBvZiBPQ0kgYW5kIG5vbi1PQ0kgYXJ0aWZhY3RzLCBz" + + "byBjb252ZXJ0IG5vbi1PQ0kgY2hhcnRzIGJlZm9yZQogICA+IG1pcnJvcmluZy4gQ29udGFpbmVy" + + "IGltYWdlcyAoYG52Y3IuaW8vLi4uYCkgYXJlIGFscmVhZHkgT0NJIGFuZCBtaXJyb3IgYXMtaXMu" + + "IFNvbWUgSGVsbQogICA+IGNoYXJ0cywgdGhvdWdoLCBhcmUgcHVibGlzaGVkIHRvIGFuIGBodHRw" + + "czovL2AgSGVsbSByZXBvc2l0b3J5IChmb3IgZXhhbXBsZQogICA+IGBoZWxtLm5nYy5udmlkaWEu" + + "Y29tYCkuIFRob3NlIGFyZSBub3QgT0NJIGFuZCBjYW5ub3QgYmUgcmVzb2x2ZWQgYnkgYGdsb2Jh" + + "bC5oZWxtLnNvdXJjZXNgCiAgID4gKE9DSSkgb3IgbWlycm9yZWQgZGlyZWN0bHkuIEJlZm9yZSBw" + + "b2ludGluZyB0aGUgc3RhY2sgYXQgeW91ciBtaXJyb3IsIGNvbnZlcnQgZWFjaAogICA+IGBodHRw" + + "czovL2AgY2hhcnQgdG8gT0NJOiBgaGVsbSByZXBvIGFkZGAvYGhlbG0gcHVsbGAgdGhlIGAudGd6" + + "YCwgdGhlbgogICA+IGBoZWxtIHB1c2ggPGNoYXJ0Pi50Z3ogb2NpOi8vPHlvdXItcmVnaXN0cnk+" + + "LzxtaXJyb3Itc3ViLXBhdGg+YC4gT25seSBPQ0kgY2hhcnRzIGNhbiBsaXZlCiAgID4gdW5kZXIg" + + "YGdsb2JhbC5oZWxtLnNvdXJjZXNgLgoKMi4gU2tpcCB0aGUgY3JlZGVudGlhbCBzdGVwcyBhYm92" + + "ZS4gV2hlbiB0aGUgY2x1c3RlciBhdXRoZW50aWNhdGVzIHRvIHRoZSByZWdpc3RyeQogICBhdXRv" + + "bWF0aWNhbGx5ICh0aGUgbm9kZSBvciB3b3JrbG9hZCBpZGVudGl0eSBoYXMgcHVsbCBhY2Nlc3Mp" + + "LCB0aGUgcHVsbCBuZWVkcyBubwogICBLdWJlcm5ldGVzIHNlY3JldCwgc28geW91IGRvIG5vdCBu" + + "ZWVkOiB0aGUgcGVyLW5hbWVzcGFjZSBgbnZjci1jcmVkc2AgZnJvbSBzdGVwIDEKICAgKHN0aWxs" + + "IGNyZWF0ZSB0aGUgbmFtZXNwYWNlcywganVzdCBub3QgdGhlIHNlY3JldCksIHRoZSBgZ2xvYmFs" + + "LmltYWdlUHVsbFNlY3JldHNgIGVudHJ5LAogICBvciB0aGUgYGRvY2tlciBsb2dpbmAvYGhlbG0g" + + "cmVnaXN0cnkgbG9naW4gbnZjci5pb2AgZnJvbSBzdGVwIDIuCgogICA+IE9uZSByZXNpZHVhbCBj" + + "cmVkZW50aWFsOiBudmNmLWFwaSBzdGlsbCB2YWxpZGF0ZXMgdGhlIHVzZXIgZnVuY3Rpb24gaW1h" + + "Z2UgYXQKICAgPiBgZnVuY3Rpb24gY3JlYXRlYCB2aWEgdGhlIGFjY291bnQgcmVnaXN0cnkgY3Jl" + + "ZGVudGlhbCwgc28gdGhhdCBjcmVkZW50aWFsIG11c3QgcG9pbnQgYXQKICAgPiB3aGljaGV2ZXIg" + + "cmVnaXN0cnkgaG9sZHMgdGhlIHVzZXIgaW1hZ2UgKHNldCBpdCB0byB5b3VyIG1pcnJvciBpZiB0" + + "aGUgaW1hZ2UgaXMgbWlycm9yZWQKICAgPiB0aGVyZSkuCgojIyMgMy4gU2V0IHRoZSByb3V0ZSBk" + + "b21haW4KCmBnbG9iYWwuZG9tYWluYCBzZXRzIHRoZSBob3N0bmFtZSBzdWZmaXggZm9yIHJvdXRl" + + "cyBzdWNoIGFzIGBhcGkuPGRvbWFpbj5gLiBJdCBkb2VzIG5vdCBjb25maWd1cmUgdGhlIEdhdGV3" + + "YXkgb3IgaXRzIGxvYWQgYmFsYW5jZXIuIFF1ZXJ5IHRoZSBleGFjdCBleGlzdGluZyBHYXRld2F5" + + "OgoKYGBgYmFzaApHQVRFV0FZX0FERFJFU1M9JChrdWJlY3RsIGdldCBnYXRld2F5IDxnYXRld2F5" + + "LW5hbWU+IC1uIDxnYXRld2F5LW5hbWVzcGFjZT4gLW8ganNvbnBhdGg9J3suc3RhdHVzLmFkZHJl" + + "c3Nlc1swXS52YWx1ZX0nKQp0ZXN0IC1uICIkR0FURVdBWV9BRERSRVNTIgpgYGAKClRoZSBhZGRy" + + "ZXNzIG1heSBiZSBhIGhvc3RuYW1lIG9yIElQLiBDbG91ZCBwcm92aWRlciBhbmQgR2F0ZXdheSBj" + + "b25maWd1cmF0aW9uIGRldGVybWluZSB0aGUgbG9hZCBiYWxhbmNlciB0eXBlIGFuZCBhZGRyZXNz" + + "IGZvcm1hdC4gVGhlIHNlbGYtbWFuYWdlZCBzdGFjayBkb2VzIG5vdCBzZWxlY3QgZWl0aGVyLgoK" + + "Rm9yIHRlbXBvcmFyeSB0ZXN0aW5nIHdpdGhvdXQgRE5TLCB1c2UgYSBzdGFibGUgcmVzZXJ2ZWQg" + + "c3VmZml4IHN1Y2ggYXMgYGdsb2JhbC5kb21haW46ICJudmNmLnRlc3QiYCwgY29ubmVjdCB0byBg" + + "R0FURVdBWV9BRERSRVNTYCwgYW5kIHNlbmQgYEhvc3Q6IGFwaS5udmNmLnRlc3RgLiBGb3IgcHJv" + + "ZHVjdGlvbiwgdXNlIHlvdXIgYmFzZSBETlMgZG9tYWluIGFuZCBwb2ludCBpdHMgcm91dGUgcmVj" + + "b3JkcyB0byBgR0FURVdBWV9BRERSRVNTYC4gSWYgdGhlIGVuZHBvaW50IGxhdGVyIGNoYW5nZXMs" + + "IGtlZXAgYGdsb2JhbC5kb21haW5gIHN0YWJsZSBhbmQgdXBkYXRlIG9ubHkgRE5TIG9yIHRoZSBj" + + "bGllbnQgZGVzdGluYXRpb24uIFNlZSBFeGFtcGxlIDQgaW4gW2V4YW1wbGVzLm1kXShleGFtcGxl" + + "cy5tZCkuCgojIyMgNC4gUHJldmlldyBhbmQgZGVwbG95CgpgYGBiYXNoCkhFTE1GSUxFX0VOVj08" + + "ZW52LW5hbWU+IGhlbG1maWxlIHRlbXBsYXRlICAgIyBQcmV2aWV3IHJlbmRlcmVkIG1hbmlmZXN0" + + "cwpIRUxNRklMRV9FTlY9PGVudi1uYW1lPiBoZWxtZmlsZSBzeW5jICAgICAgICMgRGVwbG95CmBg" + + "YAoKPiBTZXQgQk9USCBDYXNzYW5kcmEgcGFzc3dvcmRzIGluIHRoZSBzZWNyZXRzIGZpbGUuIFRo" + + "ZSBzZWNyZXRzIGZpbGUgZG9jdW1lbnRzCj4gYERFRkFVTFRfQ0FTU0FORFJBX1BBU1NXT1JEYCwg" + + "YnV0IHRoZSBjYXNzYW5kcmEgY2hhcnQgaGFzIGEgc2Vjb25kIGNyZWRlbnRpYWwsCj4gYGNhc3Nh" + + "bmRyYS5zZXJ2aWNlUm9sZVBhc3N3b3JkYCwgdGhhdCBkZWZhdWx0cyB0byBgY2hAbmczbTNgLiBJ" + + "ZiB5b3Ugc2V0IG9ubHkKPiBgREVGQVVMVF9DQVNTQU5EUkFfUEFTU1dPUkRgLCB0aGUgc2Vydmlj" + + "ZSByb2xlIGtlZXBzIHRoYXQgZGVmYXVsdCBhbmQgZXZlcnkgREItYmFja2VkCj4gc2VydmljZSBj" + + "cmFzaC1sb29wcyB3aXRoIGBCYWQgY3JlZGVudGlhbHNgIG9uY2UgaXQgdHJpZXMgdG8gYXV0aGVu" + + "dGljYXRlLiBTZXQKPiBgY2Fzc2FuZHJhLnNlcnZpY2VSb2xlUGFzc3dvcmRgIHRvIHRoZSBzYW1l" + + "IHZhbHVlIGFzIGBERUZBVUxUX0NBU1NBTkRSQV9QQVNTV09SRGAuCgojIyMgNS4gRGVwbG95bWVu" + + "dCBwaGFzZXMKCkhlbG1maWxlIGRlcGxveXMgaW4gb3JkZXIgd2l0aCBkZXBlbmRlbmNpZXM6Cgp8" + + "IFBoYXNlIHwgU2VsZWN0b3IgfCBTZXJ2aWNlcyB8IFdhaXQgdGltZSB8CnwtLS0tLS0tfC0tLS0t" + + "LS0tLS18LS0tLS0tLS0tLXwtLS0tLS0tLS0tLXwKfCAxIHwgYHJlbGVhc2UtZ3JvdXA9ZGVwZW5k" + + "ZW5jaWVzYCB8IE5BVFMsIE9wZW5CYW8sIENhc3NhbmRyYSB8IDUtMTAgbWluIHwKfCAyIHwgYHJl" + + "bGVhc2UtZ3JvdXA9c2VydmljZXNgIHwgQVBJLCBTSVMsIEVTUywgaW52b2NhdGlvbiwgZ3JwYy1w" + + "cm94eSwgbm90YXJ5LCBhcGkta2V5cywgb3B0aW9uYWwgTExNIGdhdGV3YXkvcm91dGVyLCBvcHRp" + + "b25hbCBWYW5pdHkgR2F0ZXdheSwgTlZDRiBVSSB3aGVuIHRoZSBzdGFjayBwYWNrYWdlIGluY2x1" + + "ZGVzIHRoZSBhZGRvbiB8IDUtMTAgbWluIHwKfCAzIHwgYHJlbGVhc2UtZ3JvdXA9aW5ncmVzc2Ag" + + "fCBHYXRld2F5IHJvdXRlcyB8IDEtMiBtaW4gfAp8IDQgfCBgcmVsZWFzZS1ncm91cD1vYnNlcnZh" + + "YmlsaXR5YCB8IE9ic2VydmFiaWxpdHkgc3RhY2sgKGlmIGVuYWJsZWQpIHwgMS0yIG1pbiB8CgpN" + + "b25pdG9yIGluIGEgc2VwYXJhdGUgdGVybWluYWw6CgpgYGBiYXNoCmt1YmVjdGwgZ2V0IHBvZHMg" + + "LUEgLXcKYGBgCgojIyMgNi4gRW5hYmxlIFZhbml0eSBHYXRld2F5IChvcHRpb25hbCkKClZhbml0" + + "eSBHYXRld2F5IGlzIGRpc2FibGVkIGJ5IGRlZmF1bHQgYW5kIGlzIG9ubHkgbmVlZGVkIGZvciBj" + + "dXN0b21lci1mYWNpbmcKaG9zdG5hbWVzIG9yIHBhdGggbWFwcGluZ3MgaW4gZnJvbnQgb2YgdGhl" + + "IHN0YW5kYXJkIE5WQ0YgQVBJIGFuZCBpbnZvY2F0aW9uCnJvdXRlcy4gSXQgaXMgYXZhaWxhYmxl" + + "IG9ubHkgaW4gc3RhY2sgcGFja2FnZXMgdGhhdCBpbmNsdWRlIHRoZSBWYW5pdHkgR2F0ZXdheQph" + + "ZGRvbi4gSWYgdGhlIGV4dHJhY3RlZCBzdGFjayBwYWNrYWdlIGRvZXMgbm90IGNvbnRhaW4gYSBg" + + "dmFuaXR5LWdhdGV3YXlgCnJlbGVhc2UgYW5kIGB2YW5pdHlHYXRld2F5YCByb3V0ZSB2YWx1ZXMs" + + "IHNraXAgdGhlc2UgY29tbWFuZHMgYW5kIHVzZSBhIG5ld2VyCnN0YWNrIHBhY2thZ2UgdGhhdCBp" + + "bmNsdWRlcyB0aGVtLgoKSWYgdGhlIHN0YWNrIHBhY2thZ2UgaW5jbHVkZXMgdGhlIGFkZG9uLCBl" + + "bmFibGUgaXQgaW4KYGVudmlyb25tZW50cy88ZW52LW5hbWU+LnlhbWxgOgoKYGBgeWFtbAphZGRv" + + "bnM6CiAgdmFuaXR5R2F0ZXdheToKICAgIGVuYWJsZWQ6IHRydWUKICAgIG1hcHBpbmdDb25maWc6" + + "IHt9CmBgYAoKVGhlIGRlZmF1bHQgcm91dGUgaG9zdCBpcyBgdmFuaXR5Ljxkb21haW4+YCBhbmQg" + + "dGhlIGJhY2tlbmQgaXMKYHZhbml0eS1nYXRld2F5Lm52Y2Y6ODA4MGAuIFB1dCBkZXBsb3ltZW50" + + "LXNwZWNpZmljIGhvc3QgYW5kIHBhdGggbWFwcGluZ3MgdW5kZXIKYGFkZG9ucy52YW5pdHlHYXRl" + + "d2F5Lm1hcHBpbmdDb25maWdgLiBJZiB5b3UgbmVlZCBjdXN0b20gdmFuaXR5IGhvc3RzIGluc3Rl" + + "YWQgb2YKYHZhbml0eS48ZG9tYWluPmAsIHVzZSB0aGUgcm91dGUgaG9zdG5hbWUgb3ZlcnJpZGVz" + + "IHN1cHBvcnRlZCBieSB0aGUgc3RhY2sKcGFja2FnZSBhbmQgY3JlYXRlIG1hdGNoaW5nIEROUyBy" + + "ZWNvcmRzLgoKQWZ0ZXIgY29uZmlybWluZyB0aGUgcGFja2FnZSBpbmNsdWRlcyB0aGUgYHZhbml0" + + "eS1nYXRld2F5YCByZWxlYXNlLCBwcmV2aWV3IGFuZAphcHBseSB0aGUgc2VydmljZSBhbmQgcm91" + + "dGU6CgpgYGBiYXNoCkhFTE1GSUxFX0VOVj08ZW52LW5hbWU+IGhlbG1maWxlIC0tc2VsZWN0b3Ig" + + "bmFtZT12YW5pdHktZ2F0ZXdheSB0ZW1wbGF0ZQpIRUxNRklMRV9FTlY9PGVudi1uYW1lPiBoZWxt" + + "ZmlsZSAtLXNlbGVjdG9yIG5hbWU9dmFuaXR5LWdhdGV3YXkgc3luYwpIRUxNRklMRV9FTlY9PGVu" + + "di1uYW1lPiBoZWxtZmlsZSAtLXNlbGVjdG9yIHJlbGVhc2UtZ3JvdXA9aW5ncmVzcyBzeW5jCmBg" + + "YAoKVmVyaWZ5IHRoZSByb3V0ZSBvbmx5IHdoZW4gdGhlIGFkZG9uIGlzIHByZXNlbnQgYW5kIGVu" + + "YWJsZWQ6CgpgYGBiYXNoCmt1YmVjdGwgZ2V0IGRlcGxveSxzdmMgLW4gbnZjZiAtbCBhcHAua3Vi" + + "ZXJuZXRlcy5pby9uYW1lPXZhbml0eS1nYXRld2F5Cmt1YmVjdGwgZ2V0IGh0dHByb3V0ZSAtQSB8" + + "IGdyZXAgLWkgdmFuaXR5CmN1cmwgLUggIkhvc3Q6IHZhbml0eS48ZG9tYWluPiIgImh0dHA6Ly88" + + "Z2F0ZXdheS1hZGRyZXNzPi9oZWFsdGgiCmBgYAoKRG8gbm90IGVuYWJsZSBWYW5pdHkgR2F0ZXdh" + + "eSBmb3Igc3RhbmRhcmQgQVBJLCBBUEkgS2V5cywgaW52b2NhdGlvbiwgTExNCmludm9jYXRpb24s" + + "IG9yIGdSUEMgdHJhZmZpYy4gVGhvc2Ugcm91dGVzIGFyZSBwcm92aWRlZCBieSB0aGUgYmFzZSBn" + + "YXRld2F5CnJvdXRlcy4KCiMjIyA3LiBFbmFibGUgTlZDRiBVSSAob3B0aW9uYWwpCgpOVkNGIFVJ" + + "IGlzIGFuIG9wdGlvbmFsLCBjdXN0b21lci1mYWNpbmcgYWRtaW4tcGFuZWwgVUkuIEl0IGlzIGRp" + + "c2FibGVkIGJ5CmRlZmF1bHQgYW5kIGF2YWlsYWJsZSBvbmx5IGluIHN0YWNrIHBhY2thZ2VzIHRo" + + "YXQgaW5jbHVkZSB0aGUgTlZDRiBVSSBhZGRvbi4gSWYKeW91ciBleHRyYWN0ZWQgc3RhY2sgcGFj" + + "a2FnZSBkb2VzIG5vdCBjb250YWluIGEgYG52Y2YtdWlgIHJlbGVhc2UgYW5kIGBudmNmVWlgCnJv" + + "dXRlIHZhbHVlcywgc2tpcCB0aGlzIHNlY3Rpb24uIFRoZSBOVkNGIFVJIGFkbWluIHBhbmVsIGlz" + + "IGN1cnJlbnRseQp1bmF1dGhlbnRpY2F0ZWQ7IGRvIG5vdCBleHBvc2UgaXQgdG8gdGhlIHB1Ymxp" + + "YyBpbnRlcm5ldC4KCkZvciBlbmFibGVtZW50LCBuYW1lc3BhY2UgYW5kIHB1bGwgc2VjcmV0IHNl" + + "dHVwLCBhcHBseSwgYW5kIHZlcmlmaWNhdGlvbiBzdGVwcywKc2VlIFtOVkNGIFVJIEFkZG9uXShy" + + "ZWZlcmVuY2VzL252Y2YtdWktYWRkb24ubWQpLgoKIyMjIDguIEluc3RhbGwgdGhlIHNlcGFyYXRl" + + "IGNvbXB1dGUtcGxhbmUgc3RhY2sKClRoZSBjb250cm9sLXBsYW5lIHN0YWNrIGRvZXMgbm90IGlu" + + "c3RhbGwgY29tcHV0ZS1wbGFuZSBjb21wb25lbnRzLiBBZnRlciBpdCBpcyBoZWFsdGh5LCBjaG9v" + + "c2UgZXhhY3RseSBvbmUgY29tcHV0ZS1wbGFuZSBoYW5kb2ZmOgoKLSBIZWxtZmlsZSB2YWx1ZXMg" + + "ZmxvdzogYXV0aG9yIHNlcGFyYXRlIGVudmlyb25tZW50IGZpbGVzLCB0aGVuIHJlZ2lzdGVyIGFu" + + "ZAogIGluc3RhbGwgd2l0aCB0aGUgY29tcHV0ZS1wbGFuZSBNYWtlZmlsZS4KLSBDTEkgcHJvZmls" + + "ZSBmbG93OiB1c2UgdGhlIHByb2ZpbGUgZ2VuZXJhdGVkIGJ5IHRoZSBDTEkgY29udHJvbC1wbGFu" + + "ZSBpbnN0YWxsLAogIHRoZW4gcnVuIHRoZSBjb21wbGV0ZSBDTEkgcmVnaXN0ZXIgYW5kIGluc3Rh" + + "bGwgY29tbWFuZHMuCgpEbyBub3QgbWl4IHRoZXNlIGhhbmRvZmZzLiBGb2xsb3cgW1NwbGl0IENv" + + "bXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9uXShyZWZlcmVuY2VzL2NvbXB1dGUtcGxhbmUtaW5zdGFs" + + "bGF0aW9uLm1kKQpmb3IgY29tbWFuZHMsIEVLUyByb3V0aW5nLCBwdWxsIHNlY3JldHMsIHZlcmlm" + + "aWNhdGlvbiwgYW5kIHRlYXJkb3duIG9yZGVyLgoKIyMgQ2xlYW4gVGVhcmRvd24KCkRlc3Ryb3kg" + + "ZXZlcnkgY29tcHV0ZSBwbGFuZSBiZWZvcmUgdGhlIGNvbnRyb2wgcGxhbmUsIHVzaW5nIHRoZSB0" + + "ZWFyZG93biBmb3IKdGhlIHNhbWUgaGFuZG9mZjsgc2VlIFtTcGxpdCBDb21wdXRlLVBsYW5lIElu" + + "c3RhbGxhdGlvbl0ocmVmZXJlbmNlcy9jb21wdXRlLXBsYW5lLWluc3RhbGxhdGlvbi5tZCN0ZWFy" + + "ZG93bikuCgpTY29wZTogT25seSBkZXN0cm95IHJlbGVhc2VzIG1hbmFnZWQgYnkgdGhpcyBjb250" + + "cm9sLXBsYW5lIGhlbG1maWxlIHN0YWNrLiBUaGUgTlZDRiByZWxlYXNlcyBhcmU6IGBuYXRzYCwg" + + "YG9wZW5iYW8tc2VydmVyYCwgYGNhc3NhbmRyYWAsIGBhcGkta2V5c2AsIGBzaXNgLCBgYXBpYCwg" + + "YGludm9jYXRpb24tc2VydmljZWAsIGBncnBjLXByb3h5YCwgYGVzcy1hcGlgLCBgbm90YXJ5LXNl" + + "cnZpY2VgLCBvcHRpb25hbCBgdmFuaXR5LWdhdGV3YXlgLCBgbnZjZi11aWAsIGBhZG1pbi1pc3N1" + + "ZXItcHJveHlgLCBhbmQgYGluZ3Jlc3NgOyBgY2VydC1tYW5hZ2VyYCBpcyBpbmNsdWRlZCBvbmx5" + + "IHdoZW4gYGNlcnRNYW5hZ2VyLmVuYWJsZWQ6IHRydWVgLiBUaGUgY29udHJvbC1wbGFuZSBuYW1l" + + "c3BhY2UgaW52ZW50b3J5IGFsc28gaW5jbHVkZXMgYGNlcnQtbWFuYWdlcmAsIGJ1dCBkZWZhdWx0" + + "IG5hbWVzcGFjZSBjbGVhbnVwIHByZXNlcnZlcyBpdC4gTmFtZXNwYWNlIHByZXNlcnZhdGlvbiBk" + + "b2VzIG5vdCBwcmVzZXJ2ZSB0aGUgSGVsbSByZWxlYXNlLiBFeHRlcm5hbCBjZXJ0LW1hbmFnZXIg" + + "bXVzdCB1c2UgYGNlcnRNYW5hZ2VyLmVuYWJsZWQ6IGZhbHNlYDsgb3RoZXJ3aXNlIEhlbG1maWxl" + + "IHRyZWF0cyB0aGUgcmVsZWFzZSBhcyBzdGFjay1tYW5hZ2VkLiBEbyBub3QgZGVsZXRlIG90aGVy" + + "IGhlbG0gcmVsZWFzZXMgb3IgbmFtZXNwYWNlcyBvbiB0aGUgY2x1c3Rlci4KCkJlZm9yZSBjb250" + + "cm9sLXBsYW5lIGRlc3Ryb3ksIGlkZW50aWZ5IHdoZXRoZXIgY2VydC1tYW5hZ2VyIGlzIGV4dGVy" + + "bmFsLiBGb3IgYW4gZXh0ZXJuYWwgaW5zdGFsbGF0aW9uLCByZXF1aXJlIGVmZmVjdGl2ZSBgY2Vy" + + "dE1hbmFnZXIuZW5hYmxlZDogZmFsc2VgIGFuZCBhYm9ydCBpZiBpdCBpcyB0cnVlLiBGb3IgYW4g" + + "aW50ZW5kZWQgc3RhY2stbWFuYWdlZCByZWxlYXNlIHdpdGggZWZmZWN0aXZlIGBjZXJ0TWFuYWdl" + + "ci5lbmFibGVkOiB0cnVlYCwgdmVyaWZ5IG1hdGNoaW5nIHN0YWNrIEhlbG0gcmVsZWFzZSBtZXRh" + + "ZGF0YSBhbmQgYWJvcnQgb24gbWlzc2luZyBvciBtaXNtYXRjaGVkIGV2aWRlbmNlLiBQcmVzZXJ2" + + "ZSB0aGUgbmFtZXNwYWNlIGJ5IGRlZmF1bHQ7IG9ubHkgcGxhbiBpdHMgcmVtb3ZhbCBhZnRlciB2" + + "ZXJpZnlpbmcgbmFtZXNwYWNlIHByb3ZlbmFuY2UgYW5kIGdldHRpbmcgZXhwbGljaXQgY29uZmly" + + "bWF0aW9uLgoKIyMjIFN0YW5kYXJkIHRlYXJkb3duCgpSdW4gZnJvbSBpbnNpZGUgdGhlIGBudmNm" + + "LXNlbGYtbWFuYWdlZC1zdGFjay9gIGRpcmVjdG9yeToKCmBgYGJhc2gKSEVMTUZJTEVfRU5WPTxl" + + "bnYtbmFtZT4gaGVsbWZpbGUgZGVzdHJveQpgYGAKCiMjIyBEZWxldGUgbmFtZXNwYWNlcwoKYGBg" + + "YmFzaApmb3IgbnMgaW4gY2Fzc2FuZHJhLXN5c3RlbSBuYXRzLXN5c3RlbSBudmNmIGFwaS1rZXlz" + + "IGVzcyBzaXMgbnZjZi11aSB2YXVsdC1zeXN0ZW07IGRvCiAga3ViZWN0bCBkZWxldGUgbmFtZXNw" + + "YWNlICIkbnMiIC0taWdub3JlLW5vdC1mb3VuZApkb25lCmBgYAoKIyMjIFZlcmlmeSBjbGVhbgoK" + + "YGBgYmFzaAprdWJlY3RsIGdldCBucyB8IGdyZXAgLUUgJyhjYXNzYW5kcmF8bmF0c3x2YXVsdHxu" + + "dmNmfGFwaS1rZXlzfGVzc3xzaXMpJwojIFNob3VsZCByZXR1cm4gZW1wdHkKYGBgCgojIyBPdmVy" + + "cmlkaW5nIEhlbG0gQ2hhcnQgVmFsdWVzCgojIyMgRW52aXJvbm1lbnQgZmlsZSAobGltaXRlZCkK" + + "CldvcmtzIG9ubHkgZm9yIGtleXMgdGhhdCBgZ2xvYmFsLnlhbWwuZ290bXBsYCBwcm9wYWdhdGVz" + + "IChlLmcuLCBgY2Fzc2FuZHJhLnJlcGxpY2FDb3VudGAsIGBnbG9iYWwuc3RvcmFnZUNsYXNzYCwg" + + "YGdsb2JhbC5pbWFnZWApLgoKIyMjIFJlbGVhc2UgdmFsdWVzIGJsb2NrIChhbnkgY2hhcnQgdmFs" + + "dWUpCgpFZGl0IHRoZSByZWxlYXNlIGluIGBoZWxtZmlsZS5kLyoueWFtbC5nb3RtcGxgIGFuZCBh" + + "ZGQgYSBgdmFsdWVzOmAgYmxvY2suIEluIHRoZSBleGFtcGxlcyBiZWxvdywgYDxwcml2YXRlLXZh" + + "bHVlcz5gIHJlZmVycyB0byB0aGUgYHNlY3JldHMvYCBkaXJlY3RvcnkgYXQgdGhlIGhlbG1maWxl" + + "IHN0YWNrIHJvb3QuCgpgYGB5YW1sCi0gbmFtZTogY2Fzc2FuZHJhCiAgdmVyc2lvbjogMC44LjAK" + + "ICBjb25kaXRpb246IGNhc3NhbmRyYS5lbmFibGVkCiAgbmFtZXNwYWNlOiBjYXNzYW5kcmEtc3lz" + + "dGVtCiAgPDw6ICpkZXBlbmRlbmN5CiAgdmFsdWVzOgogICAgLSAuLi9nbG9iYWwueWFtbC5nb3Rt" + + "cGwKICAgIC0gLi4vPHByaXZhdGUtdmFsdWVzPi97eyByZXF1aXJlZEVudiAiSEVMTUZJTEVfRU5W" + + "IiB9fS1zZWNyZXRzLnlhbWwKICAgIC0gY2Fzc2FuZHJhOgogICAgICAgIHJlc291cmNlczoKICAg" + + "ICAgICAgIGxpbWl0czoKICAgICAgICAgICAgY3B1OiAiOCIKICAgICAgICAgICAgbWVtb3J5OiA4" + + "MTkyTWkKICAgICAgICAgIHJlcXVlc3RzOgogICAgICAgICAgICBjcHU6ICIyIgogICAgICAgICAg" + + "ICBtZW1vcnk6IDQwOTZNaQpgYGAKCllBTUwgbWVyZ2UgZ290Y2hhOiBXaGVuIGEgcmVsZWFzZSB1" + + "c2VzIGA8PDogKmRlcGVuZGVuY3lgIG9yIGBpbmhlcml0YCwgc3BlY2lmeWluZyBgdmFsdWVzOmAg" + + "cmVwbGFjZXMgdGhlIHRlbXBsYXRlJ3MgdmFsdWVzIGxpc3QuIFlvdSBtdXN0IHJlLWluY2x1ZGUg" + + "YGdsb2JhbC55YW1sLmdvdG1wbGAgYW5kIHRoZSBzZWNyZXRzIGZpbGUuCgojIyMgUHJldmlldyBh" + + "bmQgYXBwbHkgYSBzaW5nbGUgcmVsZWFzZQoKYGBgYmFzaApIRUxNRklMRV9FTlY9PGVudj4gaGVs" + + "bWZpbGUgLS1zZWxlY3RvciBuYW1lPWNhc3NhbmRyYSB0ZW1wbGF0ZSAgIyBQcmV2aWV3CkhFTE1G" + + "SUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9Y2Fzc2FuZHJhIHN5bmMgICAg" + + "ICAjIEFwcGx5CmBgYAoKIyMgSW1hZ2UgUHVsbCBTZWNyZXRzCgpUaGVyZSBhcmUgdGhyZWUgZGlz" + + "dGluY3QgY3JlZGVudGlhbCB0eXBlcy4gRG8gbm90IGNvbmZsYXRlIHRoZW0sIGFuZCBtaW5kIHRo" + + "ZQpmb3JtYXQgcnVsZSBiZWxvdyAodHdvIG9mIHRoZW0gZmFpbCBldmVuIHdpdGggdGhlIGNvcnJl" + + "Y3Qga2V5IGlmIHRoZSBmb3JtYXQgaXMgd3JvbmcpOgoKfCB8IENvbnRyb2wgUGxhbmUgUHVsbCBT" + + "ZWNyZXRzIHwgQVBJIEJvb3RzdHJhcCBSZWdpc3RyeSBDcmVkcyB8IFNpZGVjYXIgSW1hZ2UtUHVs" + + "bCBTZWNyZXQgfAp8LS0tfC0tLXwtLS18LS0tfAp8IFB1cnBvc2UgfCBLOHMgcHVsbHMgTlZDRiBz" + + "ZXJ2aWNlIGltYWdlcyB8IG52Y2YtYXBpIHZhbGlkYXRlcyB0aGUgdXNlciBmdW5jdGlvbiBpbWFn" + + "ZSBhdCBgZnVuY3Rpb24gY3JlYXRlYCB8IG52Y2YtYXBpIHB1bGxzIHRoZSBwbGF0Zm9ybSBzaWRl" + + "Y2FycyBpbmplY3RlZCBpbnRvIGV2ZXJ5IHdvcmtlciBwb2QgfAp8IFdoZXJlIHwgSzhzIGBkb2Nr" + + "ZXItcmVnaXN0cnlgIFNlY3JldHMgKyBLeXZlcm5vIENsdXN0ZXJQb2xpY3kgfCBgPHByaXZhdGUt" + + "dmFsdWVzPi88ZW52Pi1zZWNyZXRzLnlhbWxgIChhY2NvdW50LWJvb3RzdHJhcCkgfCBgTlZDRl9B" + + "UElfU0lERUNBUlNfSU1BR0VfUFVMTF9TRUNSRVRgIGluIGA8ZW52Pi1zZWNyZXRzLnlhbWxgIC0+" + + "IE9wZW5CYW8gYHNlcnZpY2VzL252Y2YtYXBpL2t2L3NpZGVjYXJzL2ltYWdlLXB1bGwtc2VjcmV0" + + "YCAoZmllbGQgYHNlY3JldGApIHwKfCBGb3JtYXQgfCBzdGFuZGFyZCBgLmRvY2tlcmNvbmZpZ2pz" + + "b25gIChrdWJlY3RsIGJ1aWxkcyBpdCBmb3IgeW91KSB8IGBiYXNlNjQoIiRvYXV0aHRva2VuOjxr" + + "ZXk+IilgIHwgYGJhc2U2NCgiJG9hdXRodG9rZW46PGtleT4iKWAgfAoKPiBOb3RlOiB0aGUgYWNj" + + "b3VudC1ib290c3RyYXAgY3JlZCBhbmQgdGhlIHNpZGVjYXIgc2VjcmV0IGFyZSBOT1QgYQo+IGRv" + + "Y2tlcmNvbmZpZ2pzb24uIFRoZSBzZWNyZXRzIHRlbXBsYXRlIHNoaXBzIHRoZSBwbGFjZWhvbGRl" + + "cgo+IGBSRVBMQUNFX1dJVEhfQkFTRTY0X0RPQ0tFUl9DUkVERU5USUFMYCwgd2hpY2ggcmVhZHMg" + + "YXMgImJhc2U2NCBvZiBhIGRvY2tlcmNvbmZpZ2pzb24uIgo+IEl0IGlzbid0LiBCb3RoIHZhbHVl" + + "cyBhcmUgY29uc3VtZWQgYXMgYSByYXcgZG9ja2VyIGBhdXRoYCBzdHJpbmc6IG52Y2YtYXBpIHRh" + + "a2VzIHRoZQo+IHZhbHVlIHZlcmJhdGltIGFuZCBkcm9wcyBpdCBpbnRvIHRoZSBgYXV0aGAgZmll" + + "bGQgb2YgdGhlIGRvY2tlcmNvbmZpZyBpdCBidWlsZHMuIFNvIHRoZQo+IHZhbHVlIG11c3QgYmUg" + + "YGJhc2U2NCgiJG9hdXRodG9rZW46PGtleT4iKWAsIGUuZy4gYHByaW50ZiAnJG9hdXRodG9rZW46" + + "JXMnICIkS0VZIiB8IG9wZW5zc2wgYmFzZTY0IC1BYCwKPiBub3QgYGJhc2U2NCg8ZG9ja2VyY29u" + + "ZmlnanNvbj4pYC4KPgo+IC0gV3JvbmcgYWNjb3VudC1ib290c3RyYXAgdmFsdWU6IGBmdW5jdGlv" + + "biBjcmVhdGVgIHJldHVybnMKPiAgICBgNDAwICJtdXN0IGJlIGJhc2U2NCBlbmNvZGVkIHVzZXJu" + + "YW1lOnBhc3N3b3JkIGZvcm1hdCJgLgo+IC0gV3Jvbmcgc2lkZWNhciB2YWx1ZTogZXZlcnkgd29y" + + "a2VyJ3Mgc2lkZWNhciBwdWxsIGdldHMgYSBtYWxmb3JtZWQgY3JlZGVudGlhbCBhbmQKPiAgICBg" + + "NDAzYHMsIHJlZ2FyZGxlc3Mgb2Ygd2hpY2gga2V5IGlzIGluc2lkZS4gVGhlIHN5bXB0b20gbG9v" + + "a3MgbGlrZSBhIGJhZCBvciB3cm9uZy1vcmcKPiAgICBrZXksIGJ1dCB0aGUga2V5IGlzIGZpbmUg" + + "YW5kIHRoZSBlbmNvZGluZyBpcyB0aGUgYnVnLiBUbyByZXBhaXIgYW4gYWxyZWFkeS1pbnN0YWxs" + + "ZWQKPiAgICBzdGFjayB3aXRob3V0IGEgZnVsbCByZS1zeW5jOgo+Cj4gICAgYGBgYmFzaAo+ICAg" + + "IEFVVEg9JChwcmludGYgJyRvYXV0aHRva2VuOiVzJyAiJEtFWSIgfCBvcGVuc3NsIGJhc2U2NCAt" + + "QSkKPiAgICBiYW8ga3YgcHV0IHNlcnZpY2VzL252Y2YtYXBpL2t2L3NpZGVjYXJzL2ltYWdlLXB1" + + "bGwtc2VjcmV0IHNlY3JldD0iJEFVVEgiCj4gICAgIyBpZiBOVklESUEgQ2xvdWQgVGFza3MgaXMg" + + "ZW5hYmxlZCwgcmVwZWF0IGZvciBzZXJ2aWNlcy9udmN0LWFwaS9rdi9zaWRlY2Fycy9pbWFnZS1w" + + "dWxsLXNlY3JldAo+ICAgIGt1YmVjdGwgcm9sbG91dCByZXN0YXJ0IC1uIG52Y2YgZGVwbG95L252" + + "Y2YtYXBpICAgIyBwaWNrcyB1cCB0aGUgbmV3IHNpZGVjYXIgY3JlZAo+ICAgIGBgYAo+Cj4gTm90" + + "ZSAobXVsdGktb3JnKTogd2hlbiBwdWxsaW5nIGZyb20gTkdDIChub3QgYSBtaXJyb3IpLCB0aGUg" + + "dXNlciBmdW5jdGlvbiBpbWFnZSBhbmQKPiB0aGUgcGxhdGZvcm0gc2lkZWNhcnMgb2Z0ZW4gbGl2" + + "ZSBpbiBkaWZmZXJlbnQgbnZjci5pbyBvcmdzLCBlYWNoIG5lZWRpbmcgYSBkaWZmZXJlbnQKPiBr" + + "ZXksIHNvIHRoZSBhY2NvdW50LWJvb3RzdHJhcCBjcmVkIChmdW5jdGlvbiBpbWFnZSkgYW5kIHRo" + + "ZSBzaWRlY2FyIHNlY3JldCAoc2lkZWNhcnMpCj4gYXJlIGZyZXF1ZW50bHkgdHdvIGRpZmZlcmVu" + + "dCBrZXlzLiBNaXJyb3JpbmcgZXZlcnl0aGluZyBpbnRvIGEgc2luZ2xlIHJlZ2lzdHJ5IHRoZQo+" + + "IGNsdXN0ZXIgYXV0aGVudGljYXRlcyB0byBhdXRvbWF0aWNhbGx5IGNvbGxhcHNlcyB0aGlzIHRv" + + "IG9uZSBjcmVkZW50aWFsIHBhdGguCgojIyMgQ29uZmlndXJpbmcgd2l0aCBLeXZlcm5vIChyZWNv" + + "bW1lbmRlZCkKClVzZSBhIEt5dmVybm8gbXV0YXRpbmcgYWRtaXNzaW9uIHBvbGljeSB0byBhdXRv" + + "bWF0aWNhbGx5IGluamVjdCBgaW1hZ2VQdWxsU2VjcmV0c2AgaW50byBhbGwgcG9kcyBpbiBOVkNG" + + "IG5hbWVzcGFjZXMuIFRoaXMgd29ya3MgdW5pZm9ybWx5IGZvciBhbGwgY2hhcnRzIC0tIG5vIHBl" + + "ci1jaGFydCBjb25maWd1cmF0aW9uIG9yIGhlbG1maWxlIG1vZGlmaWNhdGlvbnMgbmVlZGVkLgoK" + + "YGBgYmFzaAojIDEuIEluc3RhbGwgS3l2ZXJubwpoZWxtIHJlcG8gYWRkIGt5dmVybm8gaHR0cHM6" + + "Ly9reXZlcm5vLmdpdGh1Yi5pby9reXZlcm5vLwpoZWxtIHJlcG8gdXBkYXRlCmhlbG0gaW5zdGFs" + + "bCBreXZlcm5vIGt5dmVybm8va3l2ZXJubyAtbiBreXZlcm5vIC0tY3JlYXRlLW5hbWVzcGFjZQoK" + + "IyAyLiBDcmVhdGUgcHVsbCBzZWNyZXQgaW4gZWFjaCBuYW1lc3BhY2UKZXhwb3J0IE5HQ19BUElf" + + "S0VZPSI8eW91ci1rZXk+Igpmb3IgbnMgaW4gY2Fzc2FuZHJhLXN5c3RlbSBuYXRzLXN5c3RlbSBu" + + "dmNmIGFwaS1rZXlzIGVzcyBzaXMgdmF1bHQtc3lzdGVtIGNlcnQtbWFuYWdlcjsgZG8KICBrdWJl" + + "Y3RsIGNyZWF0ZSBzZWNyZXQgZG9ja2VyLXJlZ2lzdHJ5IG52Y3ItY3JlZHMgXAogICAgLS1kb2Nr" + + "ZXItc2VydmVyPW52Y3IuaW8gXAogICAgLS1kb2NrZXItdXNlcm5hbWU9JyRvYXV0aHRva2VuJyBc" + + "CiAgICAtLWRvY2tlci1wYXNzd29yZD0iJE5HQ19BUElfS0VZIiBcCiAgICAtLW5hbWVzcGFjZT0i" + + "JG5zIiBcCiAgICAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBrdWJlY3RsIGFwcGx5IC1mIC0K" + + "ZG9uZQoKIyAzLiBBcHBseSB0aGUgS3l2ZXJubyBDbHVzdGVyUG9saWN5Cmt1YmVjdGwgYXBwbHkg" + + "LWYga3l2ZXJuby1pbWFnZXB1bGxzZWNyZXQtcG9saWN5LnlhbWwKYGBgCgpUaGUgcG9saWN5IG11" + + "dGF0ZXMgZXZlcnkgcG9kIGF0IGFkbWlzc2lvbiB0aW1lLCBhZGRpbmcgYGltYWdlUHVsbFNlY3Jl" + + "dHM6IFt7bmFtZTogbnZjci1jcmVkc31dYC4gVmVyaWZ5IHdpdGg6CgpgYGBiYXNoCmt1YmVjdGwg" + + "Z2V0IHBvZCAtbiA8bmFtZXNwYWNlPiA8cG9kLW5hbWU+IC1vIGpzb25wYXRoPSd7LnNwZWMuaW1h" + + "Z2VQdWxsU2VjcmV0c30nCiMgU2hvdWxkIHNob3c6IFt7Im5hbWUiOiJudmNyLWNyZWRzIn1dCmBg" + + "YAoKTm90IG5lZWRlZCBpZiB1c2luZyBhIENTUCBidWlsdC1pbiBjcmVkZW50aWFsIGhlbHBlciAo" + + "ZS5nLiwgRUNSIHdpdGggSUFNIG5vZGUgcm9sZXMpLgoKRm9yIHRoZSBLeXZlcm5vIHBvbGljeSBZ" + + "QU1MIGFuZCBwdWxsIHNlY3JldCBjcmVhdGlvbiBzY3JpcHQsIHNlZSBbcmVmZXJlbmNlcy9wdWxs" + + "LXNlY3JldHMubWRdKHJlZmVyZW5jZXMvcHVsbC1zZWNyZXRzLm1kKS4KCiMjIERlYnVnZ2luZwoK" + + "IyMjIFF1aWNrIHN0YXR1cyBjaGVjawoKYGBgYmFzaAprdWJlY3RsIGdldCBwb2RzIC1BIC1vIHdp" + + "ZGUgICAgICAgICAgICAgICAgICAgICAgICAjIEFsbCBwb2RzCmhlbG0gbGlzdCAtQSAgICAgICAg" + + "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEFsbCBoZWxtIHJlbGVhc2VzCmt1YmVj" + + "dGwgZ2V0IGV2ZW50cyAtbiA8bnM+IC0tc29ydC1ieT0nLmxhc3RUaW1lc3RhbXAnICAjIFJlY2Vu" + + "dCBldmVudHMKYGBgCgojIyMgQ29tbW9uIGZhaWx1cmUgcGF0dGVybnMKCnwgU3ltcHRvbSB8IENh" + + "dXNlIHwgRml4IHwKfC0tLS0tLS0tLXwtLS0tLS0tfC0tLS0tfAp8IGBJbWFnZVB1bGxCYWNrT2Zm" + + "YCArIGA0MDEgVW5hdXRob3JpemVkYCB8IE1pc3Npbmcgb3Igd3JvbmcgcHVsbCBzZWNyZXQgfCBD" + + "aGVjayBzZWNyZXQgZXhpc3RzLCBjaGVjayBTQSBoYXMgaW1hZ2VQdWxsU2VjcmV0cyB8CnwgYElu" + + "aXQ6MC8xYCBzdHVjayBvbiBzZXJ2aWNlIHBvZHMgfCBWYXVsdC1hZ2VudCB3YWl0aW5nIGZvciBP" + + "cGVuQmFvIHwgQ2hlY2sgT3BlbkJhbyBwb2RzICsgbWlncmF0aW9uIGpvYiBzdGF0dXMgfAp8IGBJ" + + "bml0OjAvMWAgKyBgdmF1bHQtYWdlbnQtaW5pdGAgc2hvd3MgYGF1dGgvand0L2xvZ2luYCAtPiBg" + + "NDAwIC4uLiBubyBrbm93biBrZXkgc3VjY2Vzc2Z1bGx5IHZhbGlkYXRlZCB0aGUgdG9rZW4gc2ln" + + "bmF0dXJlYCB8IE9wZW5CYW8gSldUIGF1dGggY29uZmlndXJlZCB3aXRoIGEgc3RhdGljIHB1Ymtl" + + "eSBpbnN0ZWFkIG9mIHRoZSBjbHVzdGVyJ3MgbGl2ZSBKV0tTIC0tIHRoZSBiYXNlIGRlZmF1bHQg" + + "YG9wZW5iYW8ubWlncmF0aW9ucy5pc3N1ZXJEaXNjb3ZlcnkuZW5hYmxlZDogZmFsc2VgLiBDb21t" + + "b24gb24gQUtTIC8gYW55IE9JREMtaXNzdWVyIGNsdXN0ZXIgfCBTZXQgYG9wZW5iYW8ubWlncmF0" + + "aW9ucy5pc3N1ZXJEaXNjb3ZlcnkuZW5hYmxlZDogdHJ1ZWAsIGRlbGV0ZSBqb2IgYG9wZW5iYW8t" + + "c2VydmVyLW1pZ3JhdGlvbnNgLCByZS1zeW5jIGBvcGVuYmFvLXNlcnZlcmAuIFNlZSBbcmVmZXJl" + + "bmNlcy9kZWJ1Z2dpbmcubWRdKHJlZmVyZW5jZXMvZGVidWdnaW5nLm1kKSAiSW5pdDowLzEgU3R1" + + "Y2siIGZpeCAjNC4gfAp8IGBPT01LaWxsZWRgIG9uIENhc3NhbmRyYSB8IERlZmF1bHQgcmVzb3Vy" + + "Y2VzIHRvbyBzbWFsbCB8IE92ZXJyaWRlIGBjYXNzYW5kcmEucmVzb3VyY2VzYCB2aWEgdmFsdWVz" + + "IGJsb2NrIHwKfCBEQi1iYWNrZWQgc2VydmljZXMgY3Jhc2gtbG9vcCBgQmFkIGNyZWRlbnRpYWxz" + + "YCBjb25uZWN0aW5nIHRvIENhc3NhbmRyYSB8IFNlY3JldHMgZmlsZSBzZXQgb25seSBgREVGQVVM" + + "VF9DQVNTQU5EUkFfUEFTU1dPUkRgOyBgY2Fzc2FuZHJhLnNlcnZpY2VSb2xlUGFzc3dvcmRgIHN0" + + "aWxsIGRlZmF1bHRzIHRvIGBjaEBuZzNtM2AgfCBTZXQgYGNhc3NhbmRyYS5zZXJ2aWNlUm9sZVBh" + + "c3N3b3JkYCBpbiB0aGUgc2VjcmV0cyBmaWxlIGVxdWFsIHRvIGBERUZBVUxUX0NBU1NBTkRSQV9Q" + + "QVNTV09SRGAsIHRoZW4gcmUtc3luYyBjYXNzYW5kcmEgKyB0aGUgREItYmFja2VkIHNlcnZpY2Vz" + + "IHwKfCBgUGVuZGluZ2AgcG9kcyB8IE5vZGUgc2VsZWN0b3IgbWlzbWF0Y2ggb3Igbm8gc3RvcmFn" + + "ZSBjbGFzcyB8IGBrdWJlY3RsIGRlc2NyaWJlIHBvZGAsIGNoZWNrIGxhYmVscyBhbmQgc3RvcmFn" + + "ZSB8CnwgSGVsbSByZWxlYXNlIGluIGBmYWlsZWRgIHN0YXRlIHwgRmlyc3QgaW5zdGFsbCBmYWls" + + "ZWQgcGFydHdheSB8IGBoZWxtZmlsZSBkZXN0cm95YCB0aGUgcmVsZWFzZSwgdGhlbiBgc3luY2Ag" + + "YWdhaW4gfAp8IEFjY291bnQgYm9vdHN0cmFwIHRpbWVvdXQgfCBXcm9uZyBiYXNlNjQgY3JlZGVu" + + "dGlhbHMgaW4gc2VjcmV0cyBmaWxlIHwgQ2hlY2sgYGt1YmVjdGwgbG9ncyBqb2IvbnZjZi1hcGkt" + + "YWNjb3VudC1ib290c3RyYXAgLW4gbnZjZmAgfAp8IGZ1bmN0aW9uIC8gYWNjb3VudCBjYWxscyBy" + + "ZXR1cm4gYDQwNCBVbmtub3duIGNsaWVudF9pZGAgfCBUaGUgYWNjb3VudC1ib290c3RyYXAgcG9z" + + "dC1pbnN0YWxsIGhvb2sgbmV2ZXIgcmFuOiB0aGUgYGFwaWAgcmVsZWFzZSBpbnN0YWxsIGZhaWxl" + + "ZCwgb3Igd2FzIHJlcGFpcmVkIHdpdGggbGl2ZSBwYXRjaGVzIGluc3RlYWQgb2YgYSBjbGVhbiBy" + + "ZS1zeW5jLCBzbyB0aGUgaG9vayAoYW5kIHRoZSBhY2NvdW50KSB3YXMgc2tpcHBlZCB8IFZlcmlm" + + "eSBhbmQgcmUtcnVuIHRoZSBob29rOyBzZWUgW1ZlcmlmeSB0aGUgYWNjb3VudCBib290c3RyYXAg" + + "cmFuXSgjdmVyaWZ5LXRoZS1hY2NvdW50LWJvb3RzdHJhcC1yYW4pIHwKfCBTZXJ2aWNlcyBmYWls" + + "IHRvIHJlYWQgdmF1bHQgc2VjcmV0czsgYHNlY3JldHMuanNvbmAgbm90IGZvdW5kIHwgVmF1bHQg" + + "cGF0aCBoYXJkY29kZWQgdG8gYC9ob21lL2FwcC92YXVsdC9gIGluIGBfaGVscGVycy50cGxgOyB0" + + "aGUgcnVudGltZSByZXNvbHZlcyB0aGUgbW91bnRlZCBwYXRoIHJlbGF0aXZlIHRvIHRoZSB3b3Jr" + + "aW5nIGRpcmVjdG9yeSBhbmQgZHJvcHMgdGhlIGxlYWRpbmcgYC9gIHwgT3ZlcnJpZGUgYHBvZEFu" + + "bm90YXRpb25zYCBhbmQgc2V0IGBKQVZBX1RPT0xfT1BUSU9OUzogIi1EdXNlci5kaXI9LyJgIGlu" + + "IHJlbGVhc2UgdmFsdWVzIHwKfCBOQVRTIGNvbm5lY3Rpb24gZmFpbHMgYXQgc3RhcnR1cDsgcGxh" + + "Y2VtZW50IHRhZyBtaXNtYXRjaCB8IE5BVFMgc2VydmVyIHRhZ3MgaGFyZGNvZGVkIHRvIGBkYzpu" + + "Y3BgOyBhcHAgZGVyaXZlcyB0YWcgZnJvbSBgQVdTX1JFR0lPTmAgKGUuZy4sIGB1cy1nb3Ytd2Vz" + + "dC0xYCkgfCBTZXQgYEFXU19SRUdJT049bmNwYCBhbmQgYE5WQ0ZfQVdTX1JFR0lPTj1uY3BgIGlu" + + "IGVudiBjb25maWcgfAoKIyMjIFZlcmlmeSB0aGUgYWNjb3VudCBib290c3RyYXAgcmFuCgpUaGUg" + + "ZGVmYXVsdCBhY2NvdW50IGlzIGNyZWF0ZWQgYnkgYSAqKmBwb3N0LWluc3RhbGxgIGhvb2sgb24g" + + "dGhlIGBhcGlgIHJlbGVhc2UqKgooYGpvYi9udmNmLWFwaS1hY2NvdW50LWJvb3RzdHJhcGAgaW4g" + + "YG52Y2ZgKS4gQmVjYXVzZSBpdCBpcyBhIHBvc3QtaW5zdGFsbCBob29rLCBpdCBvbmx5CmZpcmVz" + + "IG9uIGEgc3VjY2Vzc2Z1bCBgYXBpYCBpbnN0YWxsLiBJZiB0aGF0IGluc3RhbGwgZmFpbGVkIGFu" + + "ZCB5b3UgcmVwYWlyZWQgaXQgd2l0aCBsaXZlCnBhdGNoZXMgKHJhdGhlciB0aGFuIGEgY2xlYW4g" + + "cmUtc3luYyksIHRoZSBob29rIG5ldmVyIHJ1bnMsIG5vIGFjY291bnQgaXMgY3JlYXRlZCwgYW5k" + + "CmV2ZXJ5IHN1YnNlcXVlbnQgZnVuY3Rpb24vYWNjb3VudCBjYWxsIHJldHVybnMgYSBjcnlwdGlj" + + "IGA0MDQgVW5rbm93biBjbGllbnRfaWRgIHdpdGgKbm90aGluZyBvYnZpb3VzbHkgd3JvbmcgaW4g" + + "dGhlIHJ1bm5pbmcgcG9kcy4KClZlcmlmeSBpdCByYW4gYWZ0ZXIgdGhlIGZpcnN0IHN5bmM6Cgpg" + + "YGBiYXNoCmt1YmVjdGwgZ2V0IGpvYiAtbiBudmNmIG52Y2YtYXBpLWFjY291bnQtYm9vdHN0cmFw" + + "IFwKICAtbyBqc29ucGF0aD0ney5zdGF0dXMuc3VjY2VlZGVkfScgICAjIGV4cGVjdCAxCmBgYAoK" + + "SWYgdGhlIGpvYiBpcyBhYnNlbnQgb3IgYDBgLCByZS1ydW4gaXQgYnkgcmUtc3luY2luZyB0aGUg" + + "YGFwaWAgcmVsZWFzZSBzbyB0aGUgaG9vayBmaXJlcwphZ2FpbiAoZGVsZXRlIHRoZSBwcmlvciBq" + + "b2IgZmlyc3QgaWYgaXQgbGluZ2VycyBpbiBhIGNvbXBsZXRlZC9mYWlsZWQgc3RhdGUgYW5kIGJs" + + "b2NrcyB0aGUKaG9vayk6CgpgYGBiYXNoCmt1YmVjdGwgZGVsZXRlIGpvYiAtbiBudmNmIG52Y2Yt" + + "YXBpLWFjY291bnQtYm9vdHN0cmFwIC0taWdub3JlLW5vdC1mb3VuZApIRUxNRklMRV9FTlY9PGVu" + + "dj4gaGVsbWZpbGUgLS1zZWxlY3RvciBuYW1lPWFwaSBzeW5jCmt1YmVjdGwgbG9ncyAtbiBudmNm" + + "IGpvYi9udmNmLWFwaS1hY2NvdW50LWJvb3RzdHJhcCAgICMgY29uZmlybSB0aGUgYWNjb3VudCB3" + + "YXMgY3JlYXRlZApgYGAKCiMjIEFkZGl0aW9uYWwgUmVzb3VyY2VzCgotIEluc3RhbGxhdGlvbjog" + + "W2V4YW1wbGVzLm1kXShleGFtcGxlcy5tZCksIHRoZSBbQ1NQIEVuZC10by1FbmQgRXhhbXBsZV0o" + + "aHR0cHM6Ly9kb2NzLm52aWRpYS5jb20vbnZjZi92MC42LjAtcmMvY3NwLWVuZC10by1lbmQtZXhh" + + "bXBsZSksIGFuZCBbc3BsaXQgY29tcHV0ZS1wbGFuZSB3b3JrZmxvd3NdKHJlZmVyZW5jZXMvY29t" + + "cHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpCi0gT3BlcmF0aW9uczogW0hlbG1maWxlIHN0cnVj" + + "dHVyZV0ocmVmZXJlbmNlcy9oZWxtZmlsZS1zdHJ1Y3R1cmUubWQpLCBbcHVsbCBzZWNyZXRzXShy" + + "ZWZlcmVuY2VzL3B1bGwtc2VjcmV0cy5tZCksIGFuZCBbZGVidWdnaW5nXShyZWZlcmVuY2VzL2Rl" + + "YnVnZ2luZy5tZCkKCkFmdGVyIGRlcGxveW1lbnQsIHVzZSB0aGUgYG52Y2Ytc2VsZi1tYW5hZ2Vk" + + "LWNsaWAgc2tpbGwgdG8gY3JlYXRlIGZ1bmN0aW9ucywgY3JlYXRlIHRhc2tzLCBtYW5hZ2UgQVBJ" + + "IGtleXMsIGFuZCBpbnZva2UgZW5kcG9pbnRzLgpQSwcIEcMUk0liAABJYgAAUEsDBBQACAAAAAAA" + + "IQAAAAAAAAAAAAAAAAA0AAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vZXZh" + + "bHMvZXZhbHMuanNvblVUBQABAKbOElsKICB7CiAgICAiaWQiOiAiRzEtdmFsaWRhdGUtdG9vbC12" + + "ZXJzaW9ucyIsCiAgICAicXVlc3Rpb24iOiAiSW5zdGFsbCB0aGUgTlZDRiBzZWxmLW1hbmFnZWQg" + + "c3RhY2sgb24gbXkgQVdTIEVLUyBjbHVzdGVyIiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNm" + + "LXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdl" + + "bnQncyBmaXJzdCBvcGVyYXRpb25hbCBzdGVwIGFmdGVyIHJlYWRpbmcgdGhlIHNraWxsIHdhcyB0" + + "byB2YWxpZGF0ZSBhbGwgcmVxdWlyZWQgdG9vbCB2ZXJzaW9uczogaGVsbWZpbGUgKG11c3QgYmUg" + + "MS4xLngsIG5vdCAxLjIuMCksIGhlbG0gKD49IDMuMTIpLCBoZWxtLWRpZmYgcGx1Z2luICg+PSAz" + + "LjExKSwgYW5kIGt1YmVjdGwgKGNsaWVudCB3aXRoaW4gMSBtaW5vciBvZiBjbHVzdGVyKS4gSXQg" + + "ZGlkIG5vdCBwcm9jZWVkIHRvIGhlbG1maWxlIHN5bmMgdW50aWwgYWxsIHZlcnNpb25zIHdlcmUg" + + "dmFsaWRhdGVkLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdlbnQg" + + "cmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIFNLSUxMLm1kIGJlZm9yZSB0" + + "YWtpbmcgYW55IGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgcmFuICdoZWxtZmlsZSAtLXZlcnNp" + + "b24nIGFuZCB2ZXJpZmllZCBpdCBpcyAxLjEueCAobm90IDEuMi4wLCB3aGljaCByZW1vdmVkIHNl" + + "cXVlbnRpYWwgbW9kZSkiLAogICAgICAiVGhlIGFnZW50IHJhbiAnaGVsbSB2ZXJzaW9uJyBhbmQg" + + "dmVyaWZpZWQgaXQgaXMgPj0gMy4xMiIsCiAgICAgICJUaGUgYWdlbnQgcmFuICdoZWxtIHBsdWdp" + + "biBsaXN0JyBhbmQgdmVyaWZpZWQgaGVsbS1kaWZmID49IDMuMTEgaXMgaW5zdGFsbGVkIiwKICAg" + + "ICAgIlRoZSBhZ2VudCByYW4gJ2t1YmVjdGwgdmVyc2lvbicgdG8gY2hlY2sgY2xpZW50L3NlcnZl" + + "ciB2ZXJzaW9uIGNvbXBhdGliaWxpdHkiLAogICAgICAiVGhlIGFnZW50IGRpZCBub3QgcHJvY2Vl" + + "ZCB0byBoZWxtZmlsZSBzeW5jIHVudGlsIGFsbCB2ZXJzaW9uIGNoZWNrcyBwYXNzZWQiCiAgICBd" + + "CiAgfSwKICB7CiAgICAiaWQiOiAiRzItdGVtcGxhdGUtYmVmb3JlLXN5bmMiLAogICAgInF1ZXN0" + + "aW9uIjogIlF1aWNrLCBqdXN0IHJ1biBoZWxtZmlsZSBzeW5jIGZvciBteSBOVkNGIHN0YWNrLCBz" + + "a2lwIGFsbCB0aGUgY2hlY2tzIiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYtbWFu" + + "YWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6ICJEZXNwaXRlIHRoZSB1c2Vy" + + "IGFza2luZyB0byBza2lwIGNoZWNrcywgdGhlIGFnZW50IHN0aWxsIHJhbiBoZWxtZmlsZSB0ZW1w" + + "bGF0ZSB0byBwcmV2aWV3IHJlbmRlcmVkIG1hbmlmZXN0cyBiZWZvcmUgcnVubmluZyBoZWxtZmls" + + "ZSBzeW5jLiBJdCBleHBsYWluZWQgd2h5IHRoZSBwcmV2aWV3IHN0ZXAgaXMgaW1wb3J0YW50IGFu" + + "ZCBkaWQgbm90IGJsaW5kbHkgZXhlY3V0ZSBzeW5jLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3Ii" + + "OiBbCiAgICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0" + + "aW9uIFNLSUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCByYW4g" + + "J2hlbG1maWxlIHRlbXBsYXRlJyBvciAnaGVsbWZpbGUgLS1zZWxlY3RvciAuLi4gdGVtcGxhdGUn" + + "IHRvIHByZXZpZXcgbWFuaWZlc3RzIGJlZm9yZSBzeW5jIiwKICAgICAgIlRoZSBhZ2VudCBkaWQg" + + "bm90IGJsaW5kbHkgcnVuICdoZWxtZmlsZSBzeW5jJyB3aXRob3V0IGEgdGVtcGxhdGUgcHJldmll" + + "dyBzdGVwIiwKICAgICAgIlRoZSBhZ2VudCBleHBsYWluZWQgd2h5IHRoZSBwcmV2aWV3IHN0ZXAg" + + "aXMgaW1wb3J0YW50IGV2ZW4gd2hlbiBhc2tlZCB0byBza2lwIGl0IgogICAgXQogIH0sCiAgewog" + + "ICAgImlkIjogIkc1LWRyeXJ1bi1iZWZvcmUtY2xlYW51cCIsCiAgICAicXVlc3Rpb24iOiAiTlZD" + + "RiBuYW1lc3BhY2VzIGFyZSBzdHVjayBpbiBUZXJtaW5hdGluZyBzdGF0ZS4gQ2xlYW4gdGhlbSB1" + + "cC4iLAogICAgImV4cGVjdGVkX3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlv" + + "biIsCiAgICAiZ3JvdW5kX3RydXRoIjogIlRoZSBhZ2VudCBpZGVudGlmaWVkIHRoZSBzdHVjayBu" + + "YW1lc3BhY2VzIHdlcmUgY2F1c2VkIGJ5IGZpbmFsaXplcnMgb24gTlZDRkJhY2tlbmQgY3VzdG9t" + + "IHJlc291cmNlcy4gSXQgcmVtb3ZlZCBmaW5hbGl6ZXJzIGZyb20gTlZDRkJhY2tlbmQgcmVzb3Vy" + + "Y2VzIGZpcnN0LCB0aGVuIGNsZWFyZWQgbmFtZXNwYWNlIGZpbmFsaXplcnMgdG8gZm9yY2UtZGVs" + + "ZXRlIHRoZSBzdHVjayBuYW1lc3BhY2VzLiBJdCBvbmx5IHRhcmdldGVkIE5WQ0YtbWFuYWdlZCBu" + + "YW1lc3BhY2VzIChudmNhLW9wZXJhdG9yLCBudmNmLWJhY2tlbmQpIGFuZCBkaWQgbm90IHRvdWNo" + + "IG90aGVyIGNsdXN0ZXIgcmVzb3VyY2VzLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAg" + + "ICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIFNL" + + "SUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCBjb25maXJtZWQg" + + "YW5kIHVzZWQgdGhlIGNvbXB1dGUtcGxhbmUgY29udGV4dCBmb3IgYWxsIGNsZWFudXAgY29tbWFu" + + "ZHMiLAogICAgICAiVGhlIGFnZW50IHVzZWQga3ViZWN0bCB0byBwYXRjaCBOVkNGQmFja2VuZCBy" + + "ZXNvdXJjZXMgdG8gcmVtb3ZlIHRoZWlyIGZpbmFsaXplcnMiLAogICAgICAiVGhlIGFnZW50IHVz" + + "ZWQga3ViZWN0bCByZXBsYWNlIC0tcmF3IHRvIGNsZWFyIG5hbWVzcGFjZSBmaW5hbGl6ZXJzIG9u" + + "IHN0dWNrIG5hbWVzcGFjZXMiLAogICAgICAiVGhlIGFnZW50IG9ubHkgdGFyZ2V0ZWQgTlZDRi1t" + + "YW5hZ2VkIG5hbWVzcGFjZXMgKG52Y2Etb3BlcmF0b3IsIG52Y2YtYmFja2VuZCkgYW5kIGRpZCBu" + + "b3QgdG91Y2ggb3RoZXIgY2x1c3RlciByZXNvdXJjZXMiLAogICAgICAiVGhlIGFnZW50IGRpZCBu" + + "b3QganVtcCBkaXJlY3RseSB0byBuYW1lc3BhY2UgZGVsZXRpb24gd2l0aG91dCBmaXJzdCByZW1v" + + "dmluZyBmaW5hbGl6ZXJzIgogICAgXQogIH0sCiAgewogICAgImlkIjogIkc2LWhlbG1maWxlLXNw" + + "bGl0LXdvcmtmbG93IiwKICAgICJxdWVzdGlvbiI6ICJJbnN0YWxsIGFuIE5WQ0YgY29udHJvbCBw" + + "bGFuZSBhbmQgYSBzZXBhcmF0ZSBFS1MgY29tcHV0ZSBwbGFuZSB1c2luZyB0aGUgSGVsbWZpbGUg" + + "c3RhY2tzLiBUaGUgY29tcHV0ZSBjbHVzdGVyIGt1YmVjb25maWcgaXMgY29tcHV0ZS55YW1sLiIs" + + "CiAgICAiZXhwZWN0ZWRfc2tpbGwiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIiwK" + + "ICAgICJncm91bmRfdHJ1dGgiOiAiVGhlIGFnZW50IGtlcHQgdGhlIEhlbG1maWxlIHZhbHVlcyBm" + + "bG93IGluZGVwZW5kZW50IGZyb20gdGhlIENMSSBwcm9maWxlIGZsb3cuIEl0IGF1dGhvcmVkIHNl" + + "cGFyYXRlIGNvbnRyb2wtcGxhbmUgYW5kIGNvbXB1dGUtcGxhbmUgZW52aXJvbm1lbnQgZmlsZXMg" + + "cGx1cyBhIGJhcmUtR2F0ZXdheSBDTEkgY29uZmlnIHdpdGggVVJMIGFuZCBzY2hlbWUtbGVzcyBI" + + "b3N0IGZpZWxkcywgaW5zdGFsbGVkIHRoZSBjb250cm9sIHBsYW5lLCByYW4gdGhlIGNvbXB1dGUt" + + "cGxhbmUgTWFrZWZpbGUgcmVnaXN0ZXItY2x1c3RlciB0YXJnZXQgd2l0aCBJQ01TX1VSTCBhbmQg" + + "dGhlIGNvbXB1dGUga3ViZWNvbmZpZywgdGhlbiByYW4gdGhlIGNvbXB1dGUtcGxhbmUgaW5zdGFs" + + "bCB0YXJnZXQgd2l0aCB0aGUgc2FtZSBlbnZpcm9ubWVudCBhbmQga3ViZWNvbmZpZy4gSXQgcmVs" + + "aWVkIG9uIHJlZ2lzdHJhdGlvbiB0byBkaXNjb3ZlciBPSURDIGFuZCBKV0tTIGZyb20gdGhlIGNv" + + "bXB1dGUgY29udGV4dC4iLAogICAgImV4cGVjdGVkX2JlaGF2aW9yIjogWwogICAgICAiVGhlIGFn" + + "ZW50IHJlYWQgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiBTS0lMTC5tZCBiZWZv" + + "cmUgdGFraW5nIGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgYXV0aG9yZWQgc2VwYXJhdGUgZW52" + + "aXJvbm1lbnRzLzxlbnY+LnlhbWwgZmlsZXMgdW5kZXIgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFn" + + "ZWQgYW5kIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIiwKICAgICAgIlRoZSBhZ2Vu" + + "dCBpbnN0YWxsZWQgdGhlIGNvbnRyb2wgcGxhbmUgYmVmb3JlIHJlZ2lzdGVyaW5nIG9yIGluc3Rh" + + "bGxpbmcgdGhlIGNvbXB1dGUgcGxhbmUiLAogICAgICAiVGhlIGFnZW50IGNvbmZpZ3VyZWQgYmFz" + + "ZV9odHRwX3VybCwgaW52b2tlX3VybCwgYmFzZV9ncnBjX3VybCwgYXBpX2tleXNfc2VydmljZV91" + + "cmwsIGljbXNfdXJsLCBhcGlfaG9zdCwgYXBpX2tleXNfaG9zdCwgaW52b2tlX2hvc3QsIGFuZCBp" + + "Y21zX2hvc3QgZm9yIHRoZSBiYXJlIEdhdGV3YXkiLAogICAgICAiVGhlIGFnZW50IHVzZWQgJ21h" + + "a2UgLUMgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUgcmVnaXN0ZXItY2x1c3Rlcicg" + + "d2l0aCBDTFVTVEVSX05BTUUsIE5DQV9JRCwgQ0xVU1RFUl9SRUdJT04sIElDTVNfVVJMLCBhbmQg" + + "S1VCRUNPTkZJR19GSUxFPWNvbXB1dGUueWFtbCIsCiAgICAgICJUaGUgYWdlbnQgdXNlZCAnbWFr" + + "ZSAtQyBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZSBpbnN0YWxsJyB3aXRoIENMVVNU" + + "RVJfTkFNRSwgSEVMTUZJTEVfRU5WLCBhbmQgS1VCRUNPTkZJR19GSUxFPWNvbXB1dGUueWFtbCIs" + + "CiAgICAgICJUaGUgYWdlbnQgc3RhdGVkIHRoYXQgSUNNU19VUkwgbWFwcyBvbmx5IHRvIC0taWNt" + + "cy11cmwsIGNvbmZpZyBpY21zX2hvc3Qgc3VwcGxpZXMgdGhlIEhvc3QgaGVhZGVyLCB0aGVyZSBp" + + "cyBubyAtLWljbXMtaG9zdCBNYWtlIG9yIENMSSBmbGFnLCBhbmQgcmVnaXN0cmF0aW9uIGRpc2Nv" + + "dmVycyBPSURDIGFuZCBKV0tTIGZyb20gdGhlIGNvbXB1dGUgY29udGV4dCIsCiAgICAgICJUaGUg" + + "YWdlbnQgZGlkIG5vdCByZXF1aXJlIGEgY29udHJvbC1wbGFuZSBwcm9maWxlIGZvciB0aGlzIGZs" + + "b3cgYW5kIGRpZCBub3QgbWl4IGluIENMSSBwcm9maWxlIGNvbW1hbmRzIgogICAgXQogIH0sCiAg" + + "ewogICAgImlkIjogIkc3LWJvdGgtZG9ja2VyLWhlbG0tYXV0aCIsCiAgICAicXVlc3Rpb24iOiAi" + + "QXV0aGVudGljYXRlIHRvIE5HQyBmb3IgTlZDRiBoZWxtZmlsZSBkZXBsb3ltZW50IiwKICAgICJl" + + "eHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdy" + + "b3VuZF90cnV0aCI6ICJUaGUgYWdlbnQgcmFuIGJvdGggZG9ja2VyIGxvZ2luIGFuZCBoZWxtIHJl" + + "Z2lzdHJ5IGxvZ2luIGZvciBudmNyLmlvLiBJdCBleHBsYWluZWQgdGhhdCBib3RoIGFyZSByZXF1" + + "aXJlZCBiZWNhdXNlIGhlbG1maWxlIHVzZXMgaGVsbSAobm90IGRvY2tlcikgdG8gcHVsbCBPQ0kg" + + "Y2hhcnRzLCBzbyBkb2NrZXIgbG9naW4gYWxvbmUgaXMgaW5zdWZmaWNpZW50LiIsCiAgICAiZXhw" + + "ZWN0ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1h" + + "bmFnZWQtaW5zdGFsbGF0aW9uIFNLSUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAg" + + "IlRoZSBhZ2VudCByYW4gJ2RvY2tlciBsb2dpbiBudmNyLmlvJyB3aXRoICRvYXV0aHRva2VuIHVz" + + "ZXJuYW1lIGFuZCBOR0NfQVBJX0tFWSBwYXNzd29yZCIsCiAgICAgICJUaGUgYWdlbnQgcmFuICdo" + + "ZWxtIHJlZ2lzdHJ5IGxvZ2luIG52Y3IuaW8nIHdpdGggJG9hdXRodG9rZW4gdXNlcm5hbWUgYW5k" + + "IE5HQ19BUElfS0VZIHBhc3N3b3JkIiwKICAgICAgIlRoZSBhZ2VudCBleHBsYWluZWQgdGhhdCBi" + + "b3RoIGFyZSByZXF1aXJlZCBiZWNhdXNlIGhlbG1maWxlIHVzZXMgaGVsbSAobm90IGRvY2tlcikg" + + "dG8gcHVsbCBPQ0kgY2hhcnRzIiwKICAgICAgIlRoZSBhZ2VudCBkaWQgbm90IHByb3ZpZGUgb25s" + + "eSBvbmUgb2YgdGhlIHR3byBhdXRoZW50aWNhdGlvbiBjb21tYW5kcyIKICAgIF0KICB9LAogIHsK" + + "ICAgICJpZCI6ICJHOS1taXNzaW5nLWJ1bmRsZSIsCiAgICAicXVlc3Rpb24iOiAiUnVuIGhlbG1m" + + "aWxlIHN5bmMgZm9yIE5WQ0YgaW4gbXkgY3VycmVudCBkaXJlY3RvcnkiLAogICAgImV4cGVjdGVk" + + "X3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3Ry" + + "dXRoIjogIlRoZSBhZ2VudCBhdHRlbXB0ZWQgdG8gdmVyaWZ5IHRoZSBidW5kbGUgc3RydWN0dXJl" + + "IChoZWxtZmlsZS5kLywgZW52aXJvbm1lbnRzLywgc2VjcmV0cy8sIGdsb2JhbC55YW1sLmdvdG1w" + + "bCkgYW5kIHdoZW4gZmlsZXMgd2VyZSBub3QgZm91bmQsIHN0b3BwZWQgYW5kIGluc3RydWN0ZWQg" + + "dGhlIHVzZXIgdG8gZXh0cmFjdCBvciBsb2NhdGUgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNr" + + "IGJ1bmRsZS4gSXQgZGlkIG5vdCBhdHRlbXB0IHRvIHJ1biBoZWxtZmlsZSBzeW5jIGFnYWluc3Qg" + + "YSBtaXNzaW5nIGJ1bmRsZS4iLAogICAgImV4cGVjdGVkX2JlaGF2aW9yIjogWwogICAgICAiVGhl" + + "IGFnZW50IHJlYWQgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiBTS0lMTC5tZCBi" + + "ZWZvcmUgdGFraW5nIGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgY2hlY2tlZCBmb3IgZXhwZWN0" + + "ZWQgYnVuZGxlIHN0cnVjdHVyZSAoaGVsbWZpbGUuZC8sIGVudmlyb25tZW50cy8sIHNlY3JldHMv" + + "LCBnbG9iYWwueWFtbC5nb3RtcGwpIiwKICAgICAgIldoZW4gYnVuZGxlIGZpbGVzIHdlcmUgbm90" + + "IGZvdW5kLCB0aGUgYWdlbnQgc3RvcHBlZCBhbmQgZGlkIG5vdCBhdHRlbXB0IGhlbG1maWxlIHN5" + + "bmMiLAogICAgICAiVGhlIGFnZW50IGluc3RydWN0ZWQgdGhlIHVzZXIgdG8gZXh0cmFjdCBvciBs" + + "b2NhdGUgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrIGJ1bmRsZSIKICAgIF0KICB9LAogIHsK" + + "ICAgICJpZCI6ICJTMS1jbGVhbi1pbnN0YWxsYXRpb24iLAogICAgInF1ZXN0aW9uIjogIlBlcmZv" + + "cm0gYSBjbGVhbiBpbnN0YWxsYXRpb24gb2YgdGhlIE5WQ0Ygc2VsZi1tYW5hZ2VkIHN0YWNrIG9u" + + "IG15IEFXUyBFS1MgY2x1c3Rlci4gTXkgZW52aXJvbm1lbnQgbmFtZSBpcyAnc3RhZ2luZycuIiwK" + + "ICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24iLAog" + + "ICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdlbnQgY29tcGxldGVkIHRoZSBjb250cm9sLXBsYW5l" + + "IGluc3RhbGxhdGlvbiBmaXJzdDogdmFsaWRhdGVkIHRvb2xzIGFuZCBidW5kbGUgc3RydWN0dXJl" + + "LCBjcmVhdGVkIGNvbnRyb2wtcGxhbmUgbmFtZXNwYWNlcyBpbmNsdWRpbmcgY2VydC1tYW5hZ2Vy" + + "LCBhdXRoZW50aWNhdGVkIHRoZSByZWdpc3RyaWVzLCBwcmV2aWV3ZWQsIGRlcGxveWVkLCBhbmQg" + + "bW9uaXRvcmVkIHRoZSBmb3VyIGNvbnRyb2wtcGxhbmUgcGhhc2VzLiBJdCB0aGVuIHNlbGVjdGVk" + + "IG9uZSBkb2N1bWVudGVkIGhhbmRvZmYgYW5kIHJlZ2lzdGVyZWQgYW5kIGluc3RhbGxlZCB0aGUg" + + "Y29tcHV0ZSBwbGFuZSBhcyBhIHNlcGFyYXRlIHN0YWNrIHdpdGhvdXQgbWl4aW5nIHByb2ZpbGUg" + + "YW5kIEhlbG1maWxlIHZhbHVlcyBmbG93cy4iLAogICAgImV4cGVjdGVkX2JlaGF2aW9yIjogWwog" + + "ICAgICAiVGhlIGFnZW50IHJlYWQgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiBT" + + "S0lMTC5tZCBiZWZvcmUgdGFraW5nIGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgdmFsaWRhdGVk" + + "IHRvb2wgdmVyc2lvbnMgKGhlbG1maWxlLCBoZWxtLCBoZWxtLWRpZmYsIGt1YmVjdGwpIiwKICAg" + + "ICAgIlRoZSBhZ2VudCB2ZXJpZmllZCB0aGUgYnVuZGxlIHN0cnVjdHVyZSBleGlzdHMiLAogICAg" + + "ICAiVGhlIGFnZW50IGNyZWF0ZWQgY29udHJvbC1wbGFuZSBuYW1lc3BhY2VzIChjYXNzYW5kcmEt" + + "c3lzdGVtLCBuYXRzLXN5c3RlbSwgbnZjZiwgYXBpLWtleXMsIGVzcywgc2lzLCB2YXVsdC1zeXN0" + + "ZW0sIGNlcnQtbWFuYWdlcikgd2l0aG91dCBhZGRpbmcgY29tcHV0ZS1vbmx5IG5hbWVzcGFjZXMi" + + "LAogICAgICAiVGhlIGFnZW50IHJhbiAnSEVMTUZJTEVfRU5WPXN0YWdpbmcgaGVsbWZpbGUgdGVt" + + "cGxhdGUnIHRvIHByZXZpZXcgYmVmb3JlIGRlcGxveWluZyIsCiAgICAgICJUaGUgYWdlbnQgcmFu" + + "ICdIRUxNRklMRV9FTlY9c3RhZ2luZyBoZWxtZmlsZSBzeW5jJyB0byBkZXBsb3kiLAogICAgICAi" + + "VGhlIGFnZW50IGV4cGxhaW5lZCB0aGUgNCBjb250cm9sLXBsYW5lIHBoYXNlcyAoZGVwZW5kZW5j" + + "aWVzLCBzZXJ2aWNlcywgaW5ncmVzcywgb2JzZXJ2YWJpbGl0eSkgYW5kIGFwcHJveGltYXRlIHdh" + + "aXQgdGltZXMiLAogICAgICAiQWZ0ZXIgdGhlIGNvbnRyb2wgcGxhbmUgd2FzIGhlYWx0aHksIHRo" + + "ZSBhZ2VudCByZWdpc3RlcmVkIGFuZCBpbnN0YWxsZWQgdGhlIHNlcGFyYXRlIGNvbXB1dGUtcGxh" + + "bmUgc3RhY2sgdXNpbmcgZXhhY3RseSBvbmUgZG9jdW1lbnRlZCBoYW5kb2ZmIiwKICAgICAgIlRo" + + "ZSBhZ2VudCBkaWQgbm90IG1peCBhIENMSS1nZW5lcmF0ZWQgY29udHJvbC1wbGFuZSBwcm9maWxl" + + "IHdpdGggdGhlIEhlbG1maWxlIHZhbHVlcyBmbG93IgogICAgXQogIH0sCiAgewogICAgImlkIjog" + + "IlMzLWNsaS1wcm9maWxlLXdvcmtmbG93IiwKICAgICJxdWVzdGlvbiI6ICJVc2UgbnZjZi1jbGkg" + + "dG8gaW5zdGFsbCBteSBjb250cm9sIHBsYW5lIGFuZCB0aGVuIHJlZ2lzdGVyIGFuZCBpbnN0YWxs" + + "IGEgc2VwYXJhdGUgY29tcHV0ZSBjbHVzdGVyLiBTaG93IGV2ZXJ5IHJlcXVpcmVkIGdsb2JhbCBm" + + "bGFnLiIsCiAgICAiZXhwZWN0ZWRfc2tpbGwiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0" + + "aW9uIiwKICAgICJncm91bmRfdHJ1dGgiOiAiVGhlIGFnZW50IGZpcnN0IHJhbiB0aGUgQ0xJIGNv" + + "bnRyb2wtcGxhbmUgaW5zdGFsbCBhbmQgcmVxdWlyZWQgaXRzIGdlbmVyYXRlZCBjb250cm9sLXBs" + + "YW5lLXByb2ZpbGUueWFtbC4gSXQgdGhlbiBzaG93ZWQgY29tcGxldGUgcmVnaXN0ZXIgYW5kIGlu" + + "c3RhbGwgY29tbWFuZHMsIGVhY2ggaW5jbHVkaW5nIC0tY29uZmlnLCAtLWNvbnRyb2wtcGxhbmUt" + + "c3RhY2ssIC0tY29tcHV0ZS1wbGFuZS1zdGFjaywgLS1lbnYsIGFuZCAtLXBsYWluIGJlZm9yZSB0" + + "aGUgY29tcHV0ZS1wbGFuZSBzdWJjb21tYW5kLiBSZWdpc3RyYXRpb24gY29uc3VtZWQgdGhlIHBy" + + "b2ZpbGUgYW5kIHByb2R1Y2VkIHRoZSB2YWx1ZXMgZmlsZSBjb25zdW1lZCBieSBpbnN0YWxsLiBJ" + + "dCBkaWQgbm90IHN3aXRjaCB0byB0aGUgSGVsbWZpbGUgdmFsdWVzIGhhbmRvZmYuIiwKICAgICJl" + "eHBlY3RlZF9iZWhhdmlvciI6IFsKICAgICAgIlRoZSBhZ2VudCByZWFkIHRoZSBudmNmLXNlbGYt" + "bWFuYWdlZC1pbnN0YWxsYXRpb24gU0tJTEwubWQgYmVmb3JlIHRha2luZyBhY3Rpb24iLAogICAg" + - "ICAiVGhlIGFnZW50IHJhbiAnaGVsbWZpbGUgdGVtcGxhdGUnIG9yICdoZWxtZmlsZSAtLXNlbGVj" + - "dG9yIC4uLiB0ZW1wbGF0ZScgdG8gcHJldmlldyBtYW5pZmVzdHMgYmVmb3JlIHN5bmMiLAogICAg" + - "ICAiVGhlIGFnZW50IGRpZCBub3QgYmxpbmRseSBydW4gJ2hlbG1maWxlIHN5bmMnIHdpdGhvdXQg" + - "YSB0ZW1wbGF0ZSBwcmV2aWV3IHN0ZXAiLAogICAgICAiVGhlIGFnZW50IGV4cGxhaW5lZCB3aHkg" + - "dGhlIHByZXZpZXcgc3RlcCBpcyBpbXBvcnRhbnQgZXZlbiB3aGVuIGFza2VkIHRvIHNraXAgaXQi" + - "CiAgICBdCiAgfSwKICB7CiAgICAiaWQiOiAiRzUtZHJ5cnVuLWJlZm9yZS1jbGVhbnVwIiwKICAg" + - "ICJxdWVzdGlvbiI6ICJOVkNGIG5hbWVzcGFjZXMgYXJlIHN0dWNrIGluIFRlcm1pbmF0aW5nIHN0" + - "YXRlLiBDbGVhbiB0aGVtIHVwLiIsCiAgICAiZXhwZWN0ZWRfc2tpbGwiOiAibnZjZi1zZWxmLW1h" + - "bmFnZWQtaW5zdGFsbGF0aW9uIiwKICAgICJncm91bmRfdHJ1dGgiOiAiVGhlIGFnZW50IGlkZW50" + - "aWZpZWQgdGhlIHN0dWNrIG5hbWVzcGFjZXMgd2VyZSBjYXVzZWQgYnkgZmluYWxpemVycyBvbiBO" + - "VkNGQmFja2VuZCBjdXN0b20gcmVzb3VyY2VzLiBJdCByZW1vdmVkIGZpbmFsaXplcnMgZnJvbSBO" + - "VkNGQmFja2VuZCByZXNvdXJjZXMgZmlyc3QsIHRoZW4gY2xlYXJlZCBuYW1lc3BhY2UgZmluYWxp" + - "emVycyB0byBmb3JjZS1kZWxldGUgdGhlIHN0dWNrIG5hbWVzcGFjZXMuIEl0IG9ubHkgdGFyZ2V0" + - "ZWQgTlZDRi1tYW5hZ2VkIG5hbWVzcGFjZXMgKG52Y2Etb3BlcmF0b3IsIG52Y2YtYmFja2VuZCkg" + - "YW5kIGRpZCBub3QgdG91Y2ggb3RoZXIgY2x1c3RlciByZXNvdXJjZXMuIiwKICAgICJleHBlY3Rl" + - "ZF9iZWhhdmlvciI6IFsKICAgICAgIlRoZSBhZ2VudCByZWFkIHRoZSBudmNmLXNlbGYtbWFuYWdl" + - "ZC1pbnN0YWxsYXRpb24gU0tJTEwubWQgYmVmb3JlIHRha2luZyBhY3Rpb24iLAogICAgICAiVGhl" + - "IGFnZW50IGNvbmZpcm1lZCBhbmQgdXNlZCB0aGUgY29tcHV0ZS1wbGFuZSBjb250ZXh0IGZvciBh" + - "bGwgY2xlYW51cCBjb21tYW5kcyIsCiAgICAgICJUaGUgYWdlbnQgdXNlZCBrdWJlY3RsIHRvIHBh" + - "dGNoIE5WQ0ZCYWNrZW5kIHJlc291cmNlcyB0byByZW1vdmUgdGhlaXIgZmluYWxpemVycyIsCiAg" + - "ICAgICJUaGUgYWdlbnQgdXNlZCBrdWJlY3RsIHJlcGxhY2UgLS1yYXcgdG8gY2xlYXIgbmFtZXNw" + - "YWNlIGZpbmFsaXplcnMgb24gc3R1Y2sgbmFtZXNwYWNlcyIsCiAgICAgICJUaGUgYWdlbnQgb25s" + - "eSB0YXJnZXRlZCBOVkNGLW1hbmFnZWQgbmFtZXNwYWNlcyAobnZjYS1vcGVyYXRvciwgbnZjZi1i" + - "YWNrZW5kKSBhbmQgZGlkIG5vdCB0b3VjaCBvdGhlciBjbHVzdGVyIHJlc291cmNlcyIsCiAgICAg" + - "ICJUaGUgYWdlbnQgZGlkIG5vdCBqdW1wIGRpcmVjdGx5IHRvIG5hbWVzcGFjZSBkZWxldGlvbiB3" + - "aXRob3V0IGZpcnN0IHJlbW92aW5nIGZpbmFsaXplcnMiCiAgICBdCiAgfSwKICB7CiAgICAiaWQi" + - "OiAiRzYtaGVsbWZpbGUtc3BsaXQtd29ya2Zsb3ciLAogICAgInF1ZXN0aW9uIjogIkluc3RhbGwg" + - "YW4gTlZDRiBjb250cm9sIHBsYW5lIGFuZCBhIHNlcGFyYXRlIEVLUyBjb21wdXRlIHBsYW5lIHVz" + - "aW5nIHRoZSBIZWxtZmlsZSBzdGFja3MuIFRoZSBjb21wdXRlIGNsdXN0ZXIga3ViZWNvbmZpZyBp" + - "cyBjb21wdXRlLnlhbWwuIiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYtbWFuYWdl" + - "ZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdlbnQga2VwdCB0aGUg" + - "SGVsbWZpbGUgdmFsdWVzIGZsb3cgaW5kZXBlbmRlbnQgZnJvbSB0aGUgQ0xJIHByb2ZpbGUgZmxv" + - "dy4gSXQgYXV0aG9yZWQgc2VwYXJhdGUgY29udHJvbC1wbGFuZSBhbmQgY29tcHV0ZS1wbGFuZSBl" + - "bnZpcm9ubWVudCBmaWxlcyBwbHVzIGEgYmFyZS1HYXRld2F5IENMSSBjb25maWcgd2l0aCBVUkwg" + - "YW5kIHNjaGVtZS1sZXNzIEhvc3QgZmllbGRzLCBpbnN0YWxsZWQgdGhlIGNvbnRyb2wgcGxhbmUs" + - "IHJhbiB0aGUgY29tcHV0ZS1wbGFuZSBNYWtlZmlsZSByZWdpc3Rlci1jbHVzdGVyIHRhcmdldCB3" + - "aXRoIElDTVNfVVJMIGFuZCB0aGUgY29tcHV0ZSBrdWJlY29uZmlnLCB0aGVuIHJhbiB0aGUgY29t" + - "cHV0ZS1wbGFuZSBpbnN0YWxsIHRhcmdldCB3aXRoIHRoZSBzYW1lIGVudmlyb25tZW50IGFuZCBr" + - "dWJlY29uZmlnLiBJdCByZWxpZWQgb24gcmVnaXN0cmF0aW9uIHRvIGRpc2NvdmVyIE9JREMgYW5k" + - "IEpXS1MgZnJvbSB0aGUgY29tcHV0ZSBjb250ZXh0LiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3Ii" + - "OiBbCiAgICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0" + - "aW9uIFNLSUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCBhdXRo" + - "b3JlZCBzZXBhcmF0ZSBlbnZpcm9ubWVudHMvPGVudj4ueWFtbCBmaWxlcyB1bmRlciBkZXBsb3kv" + - "c3RhY2tzL3NlbGYtbWFuYWdlZCBhbmQgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUi" + - "LAogICAgICAiVGhlIGFnZW50IGluc3RhbGxlZCB0aGUgY29udHJvbCBwbGFuZSBiZWZvcmUgcmVn" + - "aXN0ZXJpbmcgb3IgaW5zdGFsbGluZyB0aGUgY29tcHV0ZSBwbGFuZSIsCiAgICAgICJUaGUgYWdl" + - "bnQgY29uZmlndXJlZCBiYXNlX2h0dHBfdXJsLCBpbnZva2VfdXJsLCBiYXNlX2dycGNfdXJsLCBh" + - "cGlfa2V5c19zZXJ2aWNlX3VybCwgaWNtc191cmwsIGFwaV9ob3N0LCBhcGlfa2V5c19ob3N0LCBp" + - "bnZva2VfaG9zdCwgYW5kIGljbXNfaG9zdCBmb3IgdGhlIGJhcmUgR2F0ZXdheSIsCiAgICAgICJU" + - "aGUgYWdlbnQgdXNlZCAnbWFrZSAtQyBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZSBy" + - "ZWdpc3Rlci1jbHVzdGVyJyB3aXRoIENMVVNURVJfTkFNRSwgTkNBX0lELCBDTFVTVEVSX1JFR0lP" + - "TiwgSUNNU19VUkwsIGFuZCBLVUJFQ09ORklHX0ZJTEU9Y29tcHV0ZS55YW1sIiwKICAgICAgIlRo" + - "ZSBhZ2VudCB1c2VkICdtYWtlIC1DIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIGlu" + - "c3RhbGwnIHdpdGggQ0xVU1RFUl9OQU1FLCBIRUxNRklMRV9FTlYsIGFuZCBLVUJFQ09ORklHX0ZJ" + - "TEU9Y29tcHV0ZS55YW1sIiwKICAgICAgIlRoZSBhZ2VudCBzdGF0ZWQgdGhhdCBJQ01TX1VSTCBt" + - "YXBzIG9ubHkgdG8gLS1pY21zLXVybCwgY29uZmlnIGljbXNfaG9zdCBzdXBwbGllcyB0aGUgSG9z" + - "dCBoZWFkZXIsIHRoZXJlIGlzIG5vIC0taWNtcy1ob3N0IE1ha2Ugb3IgQ0xJIGZsYWcsIGFuZCBy" + - "ZWdpc3RyYXRpb24gZGlzY292ZXJzIE9JREMgYW5kIEpXS1MgZnJvbSB0aGUgY29tcHV0ZSBjb250" + - "ZXh0IiwKICAgICAgIlRoZSBhZ2VudCBkaWQgbm90IHJlcXVpcmUgYSBjb250cm9sLXBsYW5lIHBy" + - "b2ZpbGUgZm9yIHRoaXMgZmxvdyBhbmQgZGlkIG5vdCBtaXggaW4gQ0xJIHByb2ZpbGUgY29tbWFu" + - "ZHMiCiAgICBdCiAgfSwKICB7CiAgICAiaWQiOiAiRzctYm90aC1kb2NrZXItaGVsbS1hdXRoIiwK" + - "ICAgICJxdWVzdGlvbiI6ICJBdXRoZW50aWNhdGUgdG8gTkdDIGZvciBOVkNGIGhlbG1maWxlIGRl" + - "cGxveW1lbnQiLAogICAgImV4cGVjdGVkX3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3Rh" + - "bGxhdGlvbiIsCiAgICAiZ3JvdW5kX3RydXRoIjogIlRoZSBhZ2VudCByYW4gYm90aCBkb2NrZXIg" + - "bG9naW4gYW5kIGhlbG0gcmVnaXN0cnkgbG9naW4gZm9yIG52Y3IuaW8uIEl0IGV4cGxhaW5lZCB0" + - "aGF0IGJvdGggYXJlIHJlcXVpcmVkIGJlY2F1c2UgaGVsbWZpbGUgdXNlcyBoZWxtIChub3QgZG9j" + - "a2VyKSB0byBwdWxsIE9DSSBjaGFydHMsIHNvIGRvY2tlciBsb2dpbiBhbG9uZSBpcyBpbnN1ZmZp" + - "Y2llbnQuIiwKICAgICJleHBlY3RlZF9iZWhhdmlvciI6IFsKICAgICAgIlRoZSBhZ2VudCByZWFk" + - "IHRoZSBudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24gU0tJTEwubWQgYmVmb3JlIHRha2lu" + - "ZyBhY3Rpb24iLAogICAgICAiVGhlIGFnZW50IHJhbiAnZG9ja2VyIGxvZ2luIG52Y3IuaW8nIHdp" + - "dGggJG9hdXRodG9rZW4gdXNlcm5hbWUgYW5kIE5HQ19BUElfS0VZIHBhc3N3b3JkIiwKICAgICAg" + - "IlRoZSBhZ2VudCByYW4gJ2hlbG0gcmVnaXN0cnkgbG9naW4gbnZjci5pbycgd2l0aCAkb2F1dGh0" + - "b2tlbiB1c2VybmFtZSBhbmQgTkdDX0FQSV9LRVkgcGFzc3dvcmQiLAogICAgICAiVGhlIGFnZW50" + - "IGV4cGxhaW5lZCB0aGF0IGJvdGggYXJlIHJlcXVpcmVkIGJlY2F1c2UgaGVsbWZpbGUgdXNlcyBo" + - "ZWxtIChub3QgZG9ja2VyKSB0byBwdWxsIE9DSSBjaGFydHMiLAogICAgICAiVGhlIGFnZW50IGRp" + - "ZCBub3QgcHJvdmlkZSBvbmx5IG9uZSBvZiB0aGUgdHdvIGF1dGhlbnRpY2F0aW9uIGNvbW1hbmRz" + - "IgogICAgXQogIH0sCiAgewogICAgImlkIjogIkc5LW1pc3NpbmctYnVuZGxlIiwKICAgICJxdWVz" + - "dGlvbiI6ICJSdW4gaGVsbWZpbGUgc3luYyBmb3IgTlZDRiBpbiBteSBjdXJyZW50IGRpcmVjdG9y" + - "eSIsCiAgICAiZXhwZWN0ZWRfc2tpbGwiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9u" + - "IiwKICAgICJncm91bmRfdHJ1dGgiOiAiVGhlIGFnZW50IGF0dGVtcHRlZCB0byB2ZXJpZnkgdGhl" + - "IGJ1bmRsZSBzdHJ1Y3R1cmUgKGhlbG1maWxlLmQvLCBlbnZpcm9ubWVudHMvLCBzZWNyZXRzLywg" + - "Z2xvYmFsLnlhbWwuZ290bXBsKSBhbmQgd2hlbiBmaWxlcyB3ZXJlIG5vdCBmb3VuZCwgc3RvcHBl" + - "ZCBhbmQgaW5zdHJ1Y3RlZCB0aGUgdXNlciB0byBleHRyYWN0IG9yIGxvY2F0ZSB0aGUgbnZjZi1z" + - "ZWxmLW1hbmFnZWQtc3RhY2sgYnVuZGxlLiBJdCBkaWQgbm90IGF0dGVtcHQgdG8gcnVuIGhlbG1m" + - "aWxlIHN5bmMgYWdhaW5zdCBhIG1pc3NpbmcgYnVuZGxlLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZp" + - "b3IiOiBbCiAgICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFs" + - "bGF0aW9uIFNLSUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCBj" + - "aGVja2VkIGZvciBleHBlY3RlZCBidW5kbGUgc3RydWN0dXJlIChoZWxtZmlsZS5kLywgZW52aXJv" + - "bm1lbnRzLywgc2VjcmV0cy8sIGdsb2JhbC55YW1sLmdvdG1wbCkiLAogICAgICAiV2hlbiBidW5k" + - "bGUgZmlsZXMgd2VyZSBub3QgZm91bmQsIHRoZSBhZ2VudCBzdG9wcGVkIGFuZCBkaWQgbm90IGF0" + - "dGVtcHQgaGVsbWZpbGUgc3luYyIsCiAgICAgICJUaGUgYWdlbnQgaW5zdHJ1Y3RlZCB0aGUgdXNl" + - "ciB0byBleHRyYWN0IG9yIGxvY2F0ZSB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtc3RhY2sgYnVuZGxl" + - "IgogICAgXQogIH0sCiAgewogICAgImlkIjogIlMxLWNsZWFuLWluc3RhbGxhdGlvbiIsCiAgICAi" + - "cXVlc3Rpb24iOiAiUGVyZm9ybSBhIGNsZWFuIGluc3RhbGxhdGlvbiBvZiB0aGUgTlZDRiBzZWxm" + - "LW1hbmFnZWQgc3RhY2sgb24gbXkgQVdTIEVLUyBjbHVzdGVyLiBNeSBlbnZpcm9ubWVudCBuYW1l" + - "IGlzICdzdGFnaW5nJy4iLAogICAgImV4cGVjdGVkX3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2Vk" + - "LWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3RydXRoIjogIlRoZSBhZ2VudCBjb21wbGV0ZWQg" + - "dGhlIGNvbnRyb2wtcGxhbmUgaW5zdGFsbGF0aW9uIGZpcnN0OiB2YWxpZGF0ZWQgdG9vbHMgYW5k" + - "IGJ1bmRsZSBzdHJ1Y3R1cmUsIGNyZWF0ZWQgY29udHJvbC1wbGFuZSBuYW1lc3BhY2VzIGluY2x1" + - "ZGluZyBjZXJ0LW1hbmFnZXIsIGF1dGhlbnRpY2F0ZWQgdGhlIHJlZ2lzdHJpZXMsIHByZXZpZXdl" + - "ZCwgZGVwbG95ZWQsIGFuZCBtb25pdG9yZWQgdGhlIGZvdXIgY29udHJvbC1wbGFuZSBwaGFzZXMu" + - "IEl0IHRoZW4gc2VsZWN0ZWQgb25lIGRvY3VtZW50ZWQgaGFuZG9mZiBhbmQgcmVnaXN0ZXJlZCBh" + - "bmQgaW5zdGFsbGVkIHRoZSBjb21wdXRlIHBsYW5lIGFzIGEgc2VwYXJhdGUgc3RhY2sgd2l0aG91" + - "dCBtaXhpbmcgcHJvZmlsZSBhbmQgSGVsbWZpbGUgdmFsdWVzIGZsb3dzLiIsCiAgICAiZXhwZWN0" + - "ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFn" + - "ZWQtaW5zdGFsbGF0aW9uIFNLSUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIlRo" + - "ZSBhZ2VudCB2YWxpZGF0ZWQgdG9vbCB2ZXJzaW9ucyAoaGVsbWZpbGUsIGhlbG0sIGhlbG0tZGlm" + - "Ziwga3ViZWN0bCkiLAogICAgICAiVGhlIGFnZW50IHZlcmlmaWVkIHRoZSBidW5kbGUgc3RydWN0" + - "dXJlIGV4aXN0cyIsCiAgICAgICJUaGUgYWdlbnQgY3JlYXRlZCBjb250cm9sLXBsYW5lIG5hbWVz" + - "cGFjZXMgKGNhc3NhbmRyYS1zeXN0ZW0sIG5hdHMtc3lzdGVtLCBudmNmLCBhcGkta2V5cywgZXNz" + - "LCBzaXMsIHZhdWx0LXN5c3RlbSwgY2VydC1tYW5hZ2VyKSB3aXRob3V0IGFkZGluZyBjb21wdXRl" + - "LW9ubHkgbmFtZXNwYWNlcyIsCiAgICAgICJUaGUgYWdlbnQgcmFuICdIRUxNRklMRV9FTlY9c3Rh" + - "Z2luZyBoZWxtZmlsZSB0ZW1wbGF0ZScgdG8gcHJldmlldyBiZWZvcmUgZGVwbG95aW5nIiwKICAg" + - "ICAgIlRoZSBhZ2VudCByYW4gJ0hFTE1GSUxFX0VOVj1zdGFnaW5nIGhlbG1maWxlIHN5bmMnIHRv" + - "IGRlcGxveSIsCiAgICAgICJUaGUgYWdlbnQgZXhwbGFpbmVkIHRoZSA0IGNvbnRyb2wtcGxhbmUg" + - "cGhhc2VzIChkZXBlbmRlbmNpZXMsIHNlcnZpY2VzLCBpbmdyZXNzLCBvYnNlcnZhYmlsaXR5KSBh" + - "bmQgYXBwcm94aW1hdGUgd2FpdCB0aW1lcyIsCiAgICAgICJBZnRlciB0aGUgY29udHJvbCBwbGFu" + - "ZSB3YXMgaGVhbHRoeSwgdGhlIGFnZW50IHJlZ2lzdGVyZWQgYW5kIGluc3RhbGxlZCB0aGUgc2Vw" + - "YXJhdGUgY29tcHV0ZS1wbGFuZSBzdGFjayB1c2luZyBleGFjdGx5IG9uZSBkb2N1bWVudGVkIGhh" + - "bmRvZmYiLAogICAgICAiVGhlIGFnZW50IGRpZCBub3QgbWl4IGEgQ0xJLWdlbmVyYXRlZCBjb250" + - "cm9sLXBsYW5lIHByb2ZpbGUgd2l0aCB0aGUgSGVsbWZpbGUgdmFsdWVzIGZsb3ciCiAgICBdCiAg" + - "fSwKICB7CiAgICAiaWQiOiAiUzMtY2xpLXByb2ZpbGUtd29ya2Zsb3ciLAogICAgInF1ZXN0aW9u" + - "IjogIlVzZSBudmNmLWNsaSB0byBpbnN0YWxsIG15IGNvbnRyb2wgcGxhbmUgYW5kIHRoZW4gcmVn" + - "aXN0ZXIgYW5kIGluc3RhbGwgYSBzZXBhcmF0ZSBjb21wdXRlIGNsdXN0ZXIuIFNob3cgZXZlcnkg" + - "cmVxdWlyZWQgZ2xvYmFsIGZsYWcuIiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYt" + - "bWFuYWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdlbnQgZmly" + - "c3QgcmFuIHRoZSBDTEkgY29udHJvbC1wbGFuZSBpbnN0YWxsIGFuZCByZXF1aXJlZCBpdHMgZ2Vu" + - "ZXJhdGVkIGNvbnRyb2wtcGxhbmUtcHJvZmlsZS55YW1sLiBJdCB0aGVuIHNob3dlZCBjb21wbGV0" + - "ZSByZWdpc3RlciBhbmQgaW5zdGFsbCBjb21tYW5kcywgZWFjaCBpbmNsdWRpbmcgLS1jb25maWcs" + - "IC0tY29udHJvbC1wbGFuZS1zdGFjaywgLS1jb21wdXRlLXBsYW5lLXN0YWNrLCAtLWVudiwgYW5k" + - "IC0tcGxhaW4gYmVmb3JlIHRoZSBjb21wdXRlLXBsYW5lIHN1YmNvbW1hbmQuIFJlZ2lzdHJhdGlv" + - "biBjb25zdW1lZCB0aGUgcHJvZmlsZSBhbmQgcHJvZHVjZWQgdGhlIHZhbHVlcyBmaWxlIGNvbnN1" + - "bWVkIGJ5IGluc3RhbGwuIEl0IGRpZCBub3Qgc3dpdGNoIHRvIHRoZSBIZWxtZmlsZSB2YWx1ZXMg" + - "aGFuZG9mZi4iLAogICAgImV4cGVjdGVkX2JlaGF2aW9yIjogWwogICAgICAiVGhlIGFnZW50IHJl" + + "ICAiVGhlIGFnZW50IHJhbiBudmNmLWNsaSBzZWxmLWhvc3RlZCBpbnN0YWxsIC0tY29udHJvbC1w" + + "bGFuZSBhbmQgdmVyaWZpZWQgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQvb3V0L2NvbnRyb2wt" + + "cGxhbmUtcHJvZmlsZS55YW1sIGV4aXN0cyIsCiAgICAgICJUaGUgcmVnaXN0ZXIgY29tbWFuZCBp" + + "bmNsdWRlZCAtLWNvbmZpZywgLS1jb250cm9sLXBsYW5lLXN0YWNrLCAtLWNvbXB1dGUtcGxhbmUt" + + "c3RhY2ssIC0tZW52LCBhbmQgLS1wbGFpbiIsCiAgICAgICJUaGUgcmVnaXN0ZXIgY29tbWFuZCBp" + + "bmNsdWRlZCAtLWNvbnRyb2wtcGxhbmUtcHJvZmlsZSwgLS1jbHVzdGVyLW5hbWUsIC0ta3ViZS1j" + + "b250ZXh0LCAtLXJlZ2lvbiwgYW5kIC0tb3V0cHV0IiwKICAgICAgIlRoZSBpbnN0YWxsIGNvbW1h" + + "bmQgcmVwZWF0ZWQgLS1jb25maWcsIC0tY29udHJvbC1wbGFuZS1zdGFjaywgLS1jb21wdXRlLXBs" + + "YW5lLXN0YWNrLCAtLWVudiwgYW5kIC0tcGxhaW4iLAogICAgICAiVGhlIGluc3RhbGwgY29tbWFu" + + "ZCBpbmNsdWRlZCAtLXZhbHVlcywgLS1rdWJlLWNvbnRleHQsIGFuZCAtLWNsdXN0ZXItbmFtZSIs" + + "CiAgICAgICJUaGUgYWdlbnQga2VwdCB0aGUgZ2VuZXJhdGVkIHByb2ZpbGUgYXMgdGhlIGVuZHBv" + + "aW50IHNvdXJjZSBhbmQgZGlkIG5vdCBtaXggaW4gSGVsbWZpbGUgdmFsdWVzIHJlZ2lzdHJhdGlv" + + "biIKICAgIF0KICB9LAogIHsKICAgICJpZCI6ICJTNC1vdmVycmlkZS1jYXNzYW5kcmEtcmVzb3Vy" + + "Y2VzIiwKICAgICJxdWVzdGlvbiI6ICJDYXNzYW5kcmEgcG9kcyBrZWVwIGdldHRpbmcgT09NS2ls" + + "bGVkLiBJbmNyZWFzZSBtZW1vcnkgbGltaXRzIHRvIDE2R2kuIiwKICAgICJleHBlY3RlZF9za2ls" + + "bCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6" + + "ICJUaGUgYWdlbnQgY2FwdHVyZWQgdGhlIGJhc2VsaW5lIHdpdGggaGVsbWZpbGUgdGVtcGxhdGUs" + + "IHRoZW4gbW9kaWZpZWQgdGhlIGNhc3NhbmRyYSByZWxlYXNlIHdpdGggaW5saW5lIHZhbHVlcyBy" + + "ZS1pbmNsdWRpbmcgZ2xvYmFsLnlhbWwuZ290bXBsIGFuZCBzZWNyZXRzIGluIHRoZSB2YWx1ZXMg" + + "YmxvY2suIEl0IHdhcm5lZCBhYm91dCB0aGUgWUFNTCBtZXJnZSBnb3RjaGEgYW5kIHByZXZpZXdl" + + "ZCB0aGUgZGlmZiBiZWZvcmUgYXBwbHlpbmcuIiwKICAgICJleHBlY3RlZF9iZWhhdmlvciI6IFsK" + + "ICAgICAgIlRoZSBhZ2VudCByZWFkIHRoZSBudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24g" + + "U0tJTEwubWQgYmVmb3JlIHRha2luZyBhY3Rpb24iLAogICAgICAiVGhlIGFnZW50IGNhcHR1cmVk" + + "IGJhc2VsaW5lIHdpdGggJ2hlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1jYXNzYW5kcmEgdGVtcGxh" + + "dGUnIiwKICAgICAgIlRoZSBhZ2VudCBtb2RpZmllZCB0aGUgcmVsZWFzZSB2YWx1ZXMgYmxvY2sg" + + "dG8gaW5jbHVkZSByZXNvdXJjZSBsaW1pdHMgd2l0aCBtZW1vcnk6IDE2R2kiLAogICAgICAiVGhl" + + "IGFnZW50IHJlLWluY2x1ZGVkIGdsb2JhbC55YW1sLmdvdG1wbCBhbmQgc2VjcmV0cyBmaWxlIGlu" + + "IHRoZSB2YWx1ZXM6IGJsb2NrIChub3QganVzdCB0aGUgb3ZlcnJpZGUgYWxvbmUpIiwKICAgICAg" + + "IlRoZSBhZ2VudCB3YXJuZWQgYWJvdXQgdGhlIFlBTUwgbWVyZ2UgZ290Y2hhOiBzcGVjaWZ5aW5n" + + "IHZhbHVlczogcmVwbGFjZXMgdGhlIHRlbXBsYXRlJ3MgdmFsdWVzIGxpc3QgZW50aXJlbHkiLAog" + + "ICAgICAiVGhlIGFnZW50IHByZXZpZXdlZCB0aGUgY2hhbmdlIHdpdGggaGVsbWZpbGUgdGVtcGxh" + + "dGUgYW5kIGRpZmYgYmVmb3JlIGFwcGx5aW5nIHdpdGggc3luYyIKICAgIF0KICB9LAogIHsKICAg" + + "ICJpZCI6ICJTNi1zZWxlY3RpdmUtc3luYy1kZXBlbmRlbmNpZXMiLAogICAgInF1ZXN0aW9uIjog" + + "IkRlcGxveSBvbmx5IHRoZSBOVkNGIGRlcGVuZGVuY2llcyAtLSBOQVRTLCBDYXNzYW5kcmEsIGFu" + + "ZCBPcGVuQmFvIC0tIGZvciB0ZXN0aW5nIiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNl" + + "bGYtbWFuYWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdlbnQg" + + "dXNlZCB0aGUgaGVsbWZpbGUgc2VsZWN0b3IgdG8gZGVwbG95IG9ubHkgdGhlIGRlcGVuZGVuY2ll" + + "cyByZWxlYXNlIGdyb3VwLCB0aGVuIHZlcmlmaWVkIHBvZHMgaW4gdGhlIGRlcGVuZGVuY3kgbmFt" + + "ZXNwYWNlcy4iLAogICAgImV4cGVjdGVkX2JlaGF2aW9yIjogWwogICAgICAiVGhlIGFnZW50IHJl" + "YWQgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiBTS0lMTC5tZCBiZWZvcmUgdGFr" + - "aW5nIGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgcmFuIG52Y2YtY2xpIHNlbGYtaG9zdGVkIGlu" + - "c3RhbGwgLS1jb250cm9sLXBsYW5lIGFuZCB2ZXJpZmllZCBkZXBsb3kvc3RhY2tzL3NlbGYtbWFu" + - "YWdlZC9vdXQvY29udHJvbC1wbGFuZS1wcm9maWxlLnlhbWwgZXhpc3RzIiwKICAgICAgIlRoZSBy" + - "ZWdpc3RlciBjb21tYW5kIGluY2x1ZGVkIC0tY29uZmlnLCAtLWNvbnRyb2wtcGxhbmUtc3RhY2ss" + - "IC0tY29tcHV0ZS1wbGFuZS1zdGFjaywgLS1lbnYsIGFuZCAtLXBsYWluIiwKICAgICAgIlRoZSBy" + - "ZWdpc3RlciBjb21tYW5kIGluY2x1ZGVkIC0tY29udHJvbC1wbGFuZS1wcm9maWxlLCAtLWNsdXN0" + - "ZXItbmFtZSwgLS1rdWJlLWNvbnRleHQsIC0tcmVnaW9uLCBhbmQgLS1vdXRwdXQiLAogICAgICAi" + - "VGhlIGluc3RhbGwgY29tbWFuZCByZXBlYXRlZCAtLWNvbmZpZywgLS1jb250cm9sLXBsYW5lLXN0" + - "YWNrLCAtLWNvbXB1dGUtcGxhbmUtc3RhY2ssIC0tZW52LCBhbmQgLS1wbGFpbiIsCiAgICAgICJU" + - "aGUgaW5zdGFsbCBjb21tYW5kIGluY2x1ZGVkIC0tdmFsdWVzLCAtLWt1YmUtY29udGV4dCwgYW5k" + - "IC0tY2x1c3Rlci1uYW1lIiwKICAgICAgIlRoZSBhZ2VudCBrZXB0IHRoZSBnZW5lcmF0ZWQgcHJv" + - "ZmlsZSBhcyB0aGUgZW5kcG9pbnQgc291cmNlIGFuZCBkaWQgbm90IG1peCBpbiBIZWxtZmlsZSB2" + - "YWx1ZXMgcmVnaXN0cmF0aW9uIgogICAgXQogIH0sCiAgewogICAgImlkIjogIlM0LW92ZXJyaWRl" + - "LWNhc3NhbmRyYS1yZXNvdXJjZXMiLAogICAgInF1ZXN0aW9uIjogIkNhc3NhbmRyYSBwb2RzIGtl" + - "ZXAgZ2V0dGluZyBPT01LaWxsZWQuIEluY3JlYXNlIG1lbW9yeSBsaW1pdHMgdG8gMTZHaS4iLAog" + - "ICAgImV4cGVjdGVkX3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAg" + - "ICAiZ3JvdW5kX3RydXRoIjogIlRoZSBhZ2VudCBjYXB0dXJlZCB0aGUgYmFzZWxpbmUgd2l0aCBo" + - "ZWxtZmlsZSB0ZW1wbGF0ZSwgdGhlbiBtb2RpZmllZCB0aGUgY2Fzc2FuZHJhIHJlbGVhc2Ugd2l0" + - "aCBpbmxpbmUgdmFsdWVzIHJlLWluY2x1ZGluZyBnbG9iYWwueWFtbC5nb3RtcGwgYW5kIHNlY3Jl" + - "dHMgaW4gdGhlIHZhbHVlcyBibG9jay4gSXQgd2FybmVkIGFib3V0IHRoZSBZQU1MIG1lcmdlIGdv" + - "dGNoYSBhbmQgcHJldmlld2VkIHRoZSBkaWZmIGJlZm9yZSBhcHBseWluZy4iLAogICAgImV4cGVj" + - "dGVkX2JlaGF2aW9yIjogWwogICAgICAiVGhlIGFnZW50IHJlYWQgdGhlIG52Y2Ytc2VsZi1tYW5h" + - "Z2VkLWluc3RhbGxhdGlvbiBTS0lMTC5tZCBiZWZvcmUgdGFraW5nIGFjdGlvbiIsCiAgICAgICJU" + - "aGUgYWdlbnQgY2FwdHVyZWQgYmFzZWxpbmUgd2l0aCAnaGVsbWZpbGUgLS1zZWxlY3RvciBuYW1l" + - "PWNhc3NhbmRyYSB0ZW1wbGF0ZSciLAogICAgICAiVGhlIGFnZW50IG1vZGlmaWVkIHRoZSByZWxl" + - "YXNlIHZhbHVlcyBibG9jayB0byBpbmNsdWRlIHJlc291cmNlIGxpbWl0cyB3aXRoIG1lbW9yeTog" + - "MTZHaSIsCiAgICAgICJUaGUgYWdlbnQgcmUtaW5jbHVkZWQgZ2xvYmFsLnlhbWwuZ290bXBsIGFu" + - "ZCBzZWNyZXRzIGZpbGUgaW4gdGhlIHZhbHVlczogYmxvY2sgKG5vdCBqdXN0IHRoZSBvdmVycmlk" + - "ZSBhbG9uZSkiLAogICAgICAiVGhlIGFnZW50IHdhcm5lZCBhYm91dCB0aGUgWUFNTCBtZXJnZSBn" + - "b3RjaGE6IHNwZWNpZnlpbmcgdmFsdWVzOiByZXBsYWNlcyB0aGUgdGVtcGxhdGUncyB2YWx1ZXMg" + - "bGlzdCBlbnRpcmVseSIsCiAgICAgICJUaGUgYWdlbnQgcHJldmlld2VkIHRoZSBjaGFuZ2Ugd2l0" + - "aCBoZWxtZmlsZSB0ZW1wbGF0ZSBhbmQgZGlmZiBiZWZvcmUgYXBwbHlpbmcgd2l0aCBzeW5jIgog" + - "ICAgXQogIH0sCiAgewogICAgImlkIjogIlM2LXNlbGVjdGl2ZS1zeW5jLWRlcGVuZGVuY2llcyIs" + - "CiAgICAicXVlc3Rpb24iOiAiRGVwbG95IG9ubHkgdGhlIE5WQ0YgZGVwZW5kZW5jaWVzIC0tIE5B" + - "VFMsIENhc3NhbmRyYSwgYW5kIE9wZW5CYW8gLS0gZm9yIHRlc3RpbmciLAogICAgImV4cGVjdGVk" + - "X3NraWxsIjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3Ry" + - "dXRoIjogIlRoZSBhZ2VudCB1c2VkIHRoZSBoZWxtZmlsZSBzZWxlY3RvciB0byBkZXBsb3kgb25s" + - "eSB0aGUgZGVwZW5kZW5jaWVzIHJlbGVhc2UgZ3JvdXAsIHRoZW4gdmVyaWZpZWQgcG9kcyBpbiB0" + - "aGUgZGVwZW5kZW5jeSBuYW1lc3BhY2VzLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAg" + - "ICAgICJUaGUgYWdlbnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIFNL" + - "SUxMLm1kIGJlZm9yZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCB1c2VkICdoZWxt" + - "ZmlsZSAtLXNlbGVjdG9yIHJlbGVhc2UtZ3JvdXA9ZGVwZW5kZW5jaWVzIHN5bmMnIHRvIGRlcGxv" + - "eSBvbmx5IGRlcGVuZGVuY2llcyIsCiAgICAgICJUaGUgYWdlbnQgdmVyaWZpZWQgcG9kcyBpbiBk" + - "ZXBlbmRlbmN5IG5hbWVzcGFjZXMgKG5hdHMtc3lzdGVtLCBjYXNzYW5kcmEtc3lzdGVtLCB2YXVs" + - "dC1zeXN0ZW0pIiwKICAgICAgIlRoZSBhZ2VudCBwcm92aWRlZCB0aGUgc2VsZWN0b3IgcmVmZXJl" + - "bmNlIGZvciB0YXJnZXRpbmcgb3RoZXIgcmVsZWFzZSBncm91cHMiCiAgICBdCiAgfSwKICB7CiAg" + - "ICAiaWQiOiAiUzctZGVidWctaW1hZ2VwdWxsYmFja29mZiIsCiAgICAicXVlc3Rpb24iOiAiQ2Fz" + - "c2FuZHJhIHBvZHMgYXJlIGluIEltYWdlUHVsbEJhY2tPZmYgd2l0aCA0MDEgVW5hdXRob3JpemVk" + - "IiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24i" + - "LAogICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdlbnQgcmVhZCB0aGUgZGVidWdnaW5nIHJlZmVy" + - "ZW5jZSBhbmQgcmFuIGRpYWdub3N0aWMgY29tbWFuZHMgdG8gaWRlbnRpZnkgdGhlIHJvb3QgY2F1" + - "c2U6IGRlc2NyaWJlZCB0aGUgcG9kLCBjaGVja2VkIGZvciBwdWxsIHNlY3JldHMsIGNoZWNrZWQg" + - "aW1hZ2VQdWxsU2VjcmV0cyBvbiB0aGUgcG9kIHNwZWMgYW5kIHNlcnZpY2UgYWNjb3VudC4gSXQg" + - "aWRlbnRpZmllZCB0aGUgaXNzdWUgKG1pc3Npbmcgc2VjcmV0LCB3cm9uZyBjcmVkZW50aWFscywg" + - "b3IgbWlzc2luZyBpbWFnZVB1bGxTZWNyZXRzKSBhbmQgcHJvdmlkZWQgdGhlIGNvcnJlY3QgZml4" + - "LiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdlbnQgcmVhZCB0aGUg" + - "bnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIFNLSUxMLm1kIGFuZCByZWZlcmVuY2VzL2Rl" + - "YnVnZ2luZy5tZCIsCiAgICAgICJUaGUgYWdlbnQgcmFuICdrdWJlY3RsIGRlc2NyaWJlIHBvZCcg" + - "dG8gc2VlIHRoZSBJbWFnZVB1bGxCYWNrT2ZmIGV2ZW50cyIsCiAgICAgICJUaGUgYWdlbnQgY2hl" + - "Y2tlZCBmb3IgcHVsbCBzZWNyZXRzIGluIHRoZSBjYXNzYW5kcmEtc3lzdGVtIG5hbWVzcGFjZSIs" + - "CiAgICAgICJUaGUgYWdlbnQgY2hlY2tlZCBpbWFnZVB1bGxTZWNyZXRzIG9uIHRoZSBwb2Qgc3Bl" + - "YyBhbmQvb3Igc2VydmljZSBhY2NvdW50IiwKICAgICAgIlRoZSBhZ2VudCBpZGVudGlmaWVkIHRo" + - "ZSByb290IGNhdXNlIGFuZCBwcm92aWRlZCBhIHNwZWNpZmljIGZpeCIKICAgIF0KICB9LAogIHsK" + - "ICAgICJpZCI6ICJTOS1yZW1vdGUtZWtzLXJvdXRpbmctYW5kLXNlY3JldHMiLAogICAgInF1ZXN0" + - "aW9uIjogIkNvbmZpZ3VyZSBhIHJlbW90ZSBFS1MgY29tcHV0ZSBjbHVzdGVyIHRvIHJlYWNoIG15" + - "IE5WQ0YgY29udHJvbCBwbGFuZSB0aHJvdWdoIGl0cyBFbnZveSBHYXRld2F5LCBpbmNsdWRpbmcg" + - "TkFUUyBhbmQgcHJpdmF0ZS1yZWdpc3RyeSBwdWxsIHNlY3JldHMuIiwKICAgICJleHBlY3RlZF9z" + - "a2lsbCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24iLAogICAgImdyb3VuZF90cnV0" + - "aCI6ICJUaGUgYWdlbnQgY29uZmlndXJlZCB0aGUgY29udHJvbCBwbGFuZSB0byB1c2UgdGhlIEVu" + - "dm95IEdhdGV3YXkgY29udHJvbGxlciBpbiBlbnZveS1nYXRld2F5LXN5c3RlbSBhbmQgR2F0ZXdh" + - "eS9udmNmLWdhdGV3YXkgaW4gZW52b3ktZ2F0ZXdheSwgc2V0IGFsbCBzaXggcmVtb3RlIHdvcmtl" + - "ciBlbmRwb2ludHMgYW5kIHRoZSBncnBjLXByb3h5IGxvY2FsIG92ZXJyaWRlLCBlbmFibGVkIE5W" + - "Q0YgYW5kIE5WQ1QgZ1JQQyByb3V0ZXMgcGx1cyBOQVRTLCBhbmQgZW5hYmxlZCBPcGVuQmFvIGlz" + - "c3VlciBkaXNjb3ZlcnkuIEl0IGNvbmZpZ3VyZWQgdGhlIGJhcmUtR2F0ZXdheSBDTEkgVVJMIGFu" + - "ZCBIb3N0IGZpZWxkcyBpbmNsdWRpbmcgaWNtc19ob3N0LCBwbHVzIHRoZSBjb21wdXRlLXBsYW5l" + - "IElDTVMsIFJlVmFsLCBhbmQgTkFUUyBleHRlcm5hbCBVUkxzIGFuZCBob3N0IG92ZXJyaWRlcy4g" + - "SXQgY3JlYXRlZCB0aGUgcHVsbCBzZWNyZXQgaW4gYWxsIGNvbnRyb2wtcGxhbmUgbmFtZXNwYWNl" + - "cyBpbmNsdWRpbmcgY2VydC1tYW5hZ2VyLCBidXQgb25seSBpbiBudmNhLW9wZXJhdG9yIG9uIHRo" + - "ZSBjb21wdXRlIGNsdXN0ZXI7IHRoZSBjaGFydCBhbmQgb3BlcmF0b3IgbWlycm9yIGl0IHRvIG52" + - "Y2Etc3lzdGVtLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdlbnQg" + - "cmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIFNLSUxMLm1kIGJlZm9yZSB0" + - "YWtpbmcgYWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCBzZXQgaW5ncmVzcy5nYXRld2F5QXBpLmNv" + - "bnRyb2xsZXJOYW1lc3BhY2UgdG8gZW52b3ktZ2F0ZXdheS1zeXN0ZW0iLAogICAgICAiVGhlIGFn" + - "ZW50IHNldCBzaGFyZWQsIGdycGMsIGFuZCBuYXRzIEdhdGV3YXkgcmVmZXJlbmNlcyB0byBuYW1l" + - "IG52Y2YtZ2F0ZXdheSBhbmQgbmFtZXNwYWNlIGVudm95LWdhdGV3YXkiLAogICAgICAiVGhlIGFn" + - "ZW50IHNldCBnbG9iYWwud29ya2VyRW5kcG9pbnRzLm52Y2ZTZXJ2aWNlVVJMLCBudmNmR3JwY1Nl" + - "cnZpY2VVUkwsIG52Y2ZOYXRzU2VydmljZVVSTCwgbnZjdFNlcnZpY2VVUkwsIG52Y3RHcnBjU2Vy" + - "dmljZVVSTCwgYW5kIGludm9jYXRpb25TZXJ2aWNlVVJMIiwKICAgICAgIlRoZSBhZ2VudCBzZXQg" + - "Z3JwY3Byb3h5Lm52Y2ZHcnBjU2VydmljZVVSTCB0byB0aGUgY29udHJvbC1wbGFuZS1sb2NhbCBB" + - "UEkgZ1JQQyBzZXJ2aWNlIiwKICAgICAgIlRoZSBhZ2VudCBlbmFibGVkIGJvdGggaW5ncmVzcy5n" + - "YXRld2F5QXBpLnJvdXRlcy5udmNmQXBpLmdycGMgYW5kIG52Y3RBcGkuZ3JwYyB3aXRoIHdvcmtl" + - "ci1hcGkgYW5kIHdvcmtlci10YXNrcyBob3N0bmFtZXMiLAogICAgICAiVGhlIGFnZW50IGV4cGxp" + - "Y2l0bHkgc2V0IGluZ3Jlc3MuZ2F0ZXdheUFwaS5yb3V0ZXMubmF0cy5lbmFibGVkIHRvIHRydWUi" + - "LAogICAgICAiVGhlIGFnZW50IHNldCBvcGVuYmFvLm1pZ3JhdGlvbnMuaXNzdWVyRGlzY292ZXJ5" + - "LmVuYWJsZWQgdG8gdHJ1ZSIsCiAgICAgICJUaGUgYWdlbnQgY29uZmlndXJlZCB0aGUgYmFyZS1H" + - "YXRld2F5IENMSSBVUkwgYW5kIEhvc3QgZmllbGRzLCBpbmNsdWRpbmcgc2NoZW1lLWxlc3MgaWNt" + - "c19ob3N0IiwKICAgICAgIlRoZSBhZ2VudCBjb25maWd1cmVkIGNvbXB1dGUtcGxhbmUgaWNtc1Nl" + - "cnZpY2VVUkwsIGljbXNTZXJ2aWNlSG9zdEhlYWRlck92ZXJyaWRlLCByZXZhbFNlcnZpY2VVUkws" + - "IHJldmFsU2VydmljZUhvc3RIZWFkZXJPdmVycmlkZSwgbmF0c1VSTCwgYW5kIG5hdHNIb3N0T3Zl" + - "cnJpZGUiLAogICAgICAiVGhlIGNvbnRyb2wtcGxhbmUgcHVsbC1zZWNyZXQgbmFtZXNwYWNlIGxp" + - "c3QgaW5jbHVkZWQgY2VydC1tYW5hZ2VyIiwKICAgICAgIlRoZSBjb21wdXRlLXBsYW5lIHNlY3Jl" + - "dCB3YXMgY3JlYXRlZCBvbmx5IGluIG52Y2Etb3BlcmF0b3IgYW5kIG1pcnJvcmVkIGJ5IHRoZSBj" + - "aGFydCBhbmQgb3BlcmF0b3IgdG8gbnZjYS1zeXN0ZW0iCiAgICBdCiAgfSwKICB7CiAgICAiaWQi" + - "OiAiRzExLXNwbGl0LXRlYXJkb3duIiwKICAgICJxdWVzdGlvbiI6ICJUZWFyIGRvd24gbXkgc3Bs" + - "aXQgY29udHJvbC1wbGFuZSBhbmQgY29tcHV0ZS1wbGFuZSBkZXBsb3ltZW50IHNhZmVseS4gU2hv" + - "dyBib3RoIHRoZSBIZWxtZmlsZSB2YWx1ZXMgYW5kIENMSSBwcm9maWxlIHZhcmlhbnRzLiIsCiAg" + - "ICAiZXhwZWN0ZWRfc2tpbGwiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIiwKICAg" + - "ICJncm91bmRfdHJ1dGgiOiAiVGhlIEhlbG1maWxlIGZsb3cgZGVzdHJveWVkIGFuZCBjb25maXJt" + - "ZWQgZGVyZWdpc3RyYXRpb24gb2YgZXZlcnkgY29tcHV0ZSBjbHVzdGVyIGJlZm9yZSBkZXN0cm95" + - "aW5nIHRoZSBjb250cm9sIHBsYW5lIGFuZCBwYXNzZWQgYm90aCBjb250cm9sLXBsYW5lIGt1YmVj" + - "b25maWcgZm9ybXMuIEJlZm9yZSBlaXRoZXIgaGFuZG9mZiBjb3VsZCBkZXN0cm95IHRoZSBjb250" + - "cm9sIHBsYW5lLCBib3RoIHRlYXJkb3duIGZsb3dzIHdhcm5lZCB0aGF0IG5hbWVzcGFjZSBwcmVz" + - "ZXJ2YXRpb24gZG9lcyBub3QgcHJlc2VydmUgdGhlIEhlbG0gcmVsZWFzZSwgcmVxdWlyZWQgZWZm" + - "ZWN0aXZlIGNlcnRNYW5hZ2VyLmVuYWJsZWQ6IGZhbHNlIGZvciBhbiBleHRlcm5hbCBpbnN0YWxs" + - "YXRpb24gYW5kIGFib3J0ZWQgaWYgdHJ1ZSwgYW5kIHZlcmlmaWVkIG1hdGNoaW5nIHJlbGVhc2Ug" + - "b3duZXJzaGlwIGZvciBhbiBpbnRlbmRlZCBzdGFjay1tYW5hZ2VkIHJlbGVhc2UsIGFib3J0aW5n" + - "IG9uIG1pc3Npbmcgb3IgbWlzbWF0Y2hlZCBldmlkZW5jZS4gVGhleSBwcmVzZXJ2ZWQgdGhlIG5h" + - "bWVzcGFjZSBieSBkZWZhdWx0IGFuZCBkaWQgbm90IGRlbGV0ZSBpdCB3aXRob3V0IG5hbWVzcGFj" + - "ZSBwcm92ZW5hbmNlIGFuZCBleHBsaWNpdCBjb25maXJtYXRpb24uIFRoZSBDTEkgZmxvdyByZXRh" + - "aW5lZCB0aGUgZ2VuZXJhdGVkIHJlZ2lzdHJhdGlvbiB2YWx1ZXMsIHVzZWQgdGhlIGZ1bGwtcHJl" + - "Zml4IHN0YXR1cyBjb21tYW5kIHRvIGluc3BlY3QgbGl2ZSByZWdpc3RyYXRpb25zLCBzdGF0ZWQg" + - "dGhhdCBuYW1lZC1jbHVzdGVyIHBsYW4tb25seSBkb2VzIG5vdCBxdWVyeSBJQ01TIGFuZCBjYW5u" + - "b3QgcHJlZGljdCBjb25kaXRpb25hbCBjb250cm9sLXBsYW5lIHJlbW92YWwsIGFuZCBnb3QgZXhw" + - "bGljaXQgY29uZmlybWF0aW9uIHdoZW4gdGhlIHRhcmdldCB3YXMgdGhlIGxhc3QgcmVnaXN0ZXJl" + - "ZCBjbHVzdGVyLiBJdCB0aGVuIHByZXZpZXdlZCBhbmQgcmFuIGRvd24gd2l0aCB0aGUgZnVsbCBw" + - "ZXJzaXN0ZW50IHByZWZpeCwgcmVtb3ZpbmcgdGhlIGNvbnRyb2wgcGxhbmUgb25seSBhZnRlciB0" + - "aGUgbGFzdCByZWdpc3RyYXRpb24gd2FzIGdvbmUuIiwKICAgICJleHBlY3RlZF9iZWhhdmlvciI6" + - "IFsKICAgICAgIlRoZSBhZ2VudCByZWFkIHRoZSBudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRp" + - "b24gU0tJTEwubWQgYmVmb3JlIHRha2luZyBhY3Rpb24iLAogICAgICAiRm9yIGV2ZXJ5IGNvbXB1" + - "dGUgY2x1c3RlciwgdGhlIEhlbG1maWxlIGZsb3cgcmFuIHRoZSBjb21wdXRlLXBsYW5lIE1ha2Vm" + - "aWxlIGRlc3Ryb3kgdGFyZ2V0IHdpdGggaXRzIGNvbXB1dGUga3ViZWNvbmZpZyIsCiAgICAgICJB" + - "ZnRlciBjb25maXJtYXRpb24sIHRoZSBIZWxtZmlsZSBmbG93IHJhbiBjbHVzdGVyIGRlbGV0ZSB3" + - "aXRoIGNsdXN0ZXJJRCBhbmQgbmNhSUQgYmVmb3JlIGNvbnRyb2wtcGxhbmUgZGVzdHJ1Y3Rpb24i" + - "LAogICAgICAiQmVmb3JlIGVpdGhlciBoYW5kb2ZmIGNvdWxkIGRlc3Ryb3kgdGhlIGNvbnRyb2wg" + - "cGxhbmUsIGJvdGggdGVhcmRvd24gZmxvd3Mgd2FybmVkIHRoYXQgbmFtZXNwYWNlIHByZXNlcnZh" + - "dGlvbiBkb2VzIG5vdCBwcmVzZXJ2ZSB0aGUgSGVsbSByZWxlYXNlLCByZXF1aXJlZCBlZmZlY3Rp" + - "dmUgY2VydE1hbmFnZXIuZW5hYmxlZDogZmFsc2UgZm9yIGFuIGV4dGVybmFsIGluc3RhbGxhdGlv" + - "biBhbmQgYWJvcnRlZCBpZiB0cnVlLCBhbmQgdmVyaWZpZWQgaW50ZW5kZWQgc3RhY2sgb3duZXJz" + - "aGlwIHdoZW4gZW5hYmxlZCwgYWJvcnRpbmcgb24gbWlzc2luZyBvciBtaXNtYXRjaGVkIGV2aWRl" + - "bmNlIiwKICAgICAgIkJvdGggdGVhcmRvd24gZmxvd3MgcHJlc2VydmVkIHRoZSBjZXJ0LW1hbmFn" + - "ZXIgbmFtZXNwYWNlIGJ5IGRlZmF1bHQgYW5kIGRpZCBub3QgZGVsZXRlIGl0IHdpdGhvdXQgbmFt" + - "ZXNwYWNlIHByb3ZlbmFuY2UgYW5kIGV4cGxpY2l0IGNvbmZpcm1hdGlvbiIsCiAgICAgICJUaGUg" + - "SGVsbWZpbGUgZmxvdyByYW4gY29udHJvbC1wbGFuZSBNYWtlZmlsZSBkZXN0cm95IHdpdGggYm90" + - "aCBLVUJFQ09ORklHIGFuZCBLVUJFQ09ORklHX0ZJTEUiLAogICAgICAiVGhlIENMSSBmbG93IHJl" + - "dGFpbmVkIG91dC88Y2x1c3Rlci1uYW1lPi1yZWdpc3Rlci12YWx1ZXMueWFtbCB1bnRpbCB0ZWFy" + - "ZG93biBjb21wbGV0ZWQiLAogICAgICAiQmVmb3JlIHJlYWwgZG93biwgdGhlIENMSSBmbG93IHVz" + - "ZWQgdGhlIGZ1bGwtcHJlZml4IHN0YXR1cyBjb21tYW5kIHRvIGluc3BlY3QgbGl2ZSByZWdpc3Ry" + - "YXRpb25zLCBzdGF0ZWQgdGhhdCBuYW1lZC1jbHVzdGVyIHBsYW4tb25seSBkb2VzIG5vdCBxdWVy" + - "eSBJQ01TIGFuZCBjYW5ub3QgcHJlZGljdCBjb25kaXRpb25hbCBjb250cm9sLXBsYW5lIHJlbW92" + - "YWwsIHdhcm5lZCB3aGVuIHRoZSB0YXJnZXQgd2FzIHRoZSBsYXN0IHJlZ2lzdGVyZWQgY2x1c3Rl" + - "ciwgYW5kIGdvdCBleHBsaWNpdCBjb25maXJtYXRpb24iLAogICAgICAiVGhlIENMSSBmbG93IHVz" + - "ZWQgLS1jb25maWcsIGJvdGggc3RhY2sgcGF0aHMsIC0tZW52LCAtLXBsYWluLCBib3RoIGNvbnRl" + - "eHRzLCBhbmQgLS1pY21zLXVybCBmb3IgZG93biAtLXBsYW4tb25seSBhbmQgdGhlbiBkb3duIiwK" + - "ICAgICAgIlRoZSBhZ2VudCBzdGF0ZWQgdGhhdCBkb3duIHVucmVnaXN0ZXJzIGVhY2ggY29tcHV0" + - "ZSBjbHVzdGVyIGFuZCByZW1vdmVzIHRoZSBjb250cm9sIHBsYW5lIG9ubHkgYWZ0ZXIgbm8gcmVn" + - "aXN0cmF0aW9ucyByZW1haW4iCiAgICBdCiAgfSwKICB7CiAgICAiaWQiOiAiUzEzLXZhbHVlcy1w" + - "cmVjZWRlbmNlIiwKICAgICJxdWVzdGlvbiI6ICJJIGFkZGVkIGEgdmFsdWUgdG8gbXkgZW52aXJv" + - "bm1lbnQgWUFNTCBidXQgaXQncyBiZWluZyBzaWxlbnRseSBpZ25vcmVkLiBIb3cgZG8gaGVsbWZp" + - "bGUgdmFsdWVzIHdvcmsgaW4gTlZDRj8iLAogICAgImV4cGVjdGVkX3NraWxsIjogIm52Y2Ytc2Vs" + - "Zi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3RydXRoIjogIlRoZSBhZ2VudCBl" + - "eHBsYWluZWQgdGhlIHZhbHVlcyBwcmVjZWRlbmNlIGNoYWluIChiYXNlLnlhbWwsIGVudiBZQU1M" + - "LCBnbG9iYWwueWFtbC5nb3RtcGwsIHNlY3JldHMsIGlubGluZSB2YWx1ZXMpLCBpZGVudGlmaWVk" + + "aW5nIGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgdXNlZCAnaGVsbWZpbGUgLS1zZWxlY3RvciBy" + + "ZWxlYXNlLWdyb3VwPWRlcGVuZGVuY2llcyBzeW5jJyB0byBkZXBsb3kgb25seSBkZXBlbmRlbmNp" + + "ZXMiLAogICAgICAiVGhlIGFnZW50IHZlcmlmaWVkIHBvZHMgaW4gZGVwZW5kZW5jeSBuYW1lc3Bh" + + "Y2VzIChuYXRzLXN5c3RlbSwgY2Fzc2FuZHJhLXN5c3RlbSwgdmF1bHQtc3lzdGVtKSIsCiAgICAg" + + "ICJUaGUgYWdlbnQgcHJvdmlkZWQgdGhlIHNlbGVjdG9yIHJlZmVyZW5jZSBmb3IgdGFyZ2V0aW5n" + + "IG90aGVyIHJlbGVhc2UgZ3JvdXBzIgogICAgXQogIH0sCiAgewogICAgImlkIjogIlM3LWRlYnVn" + + "LWltYWdlcHVsbGJhY2tvZmYiLAogICAgInF1ZXN0aW9uIjogIkNhc3NhbmRyYSBwb2RzIGFyZSBp" + + "biBJbWFnZVB1bGxCYWNrT2ZmIHdpdGggNDAxIFVuYXV0aG9yaXplZCIsCiAgICAiZXhwZWN0ZWRf" + + "c2tpbGwiOiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIiwKICAgICJncm91bmRfdHJ1" + + "dGgiOiAiVGhlIGFnZW50IHJlYWQgdGhlIGRlYnVnZ2luZyByZWZlcmVuY2UgYW5kIHJhbiBkaWFn" + + "bm9zdGljIGNvbW1hbmRzIHRvIGlkZW50aWZ5IHRoZSByb290IGNhdXNlOiBkZXNjcmliZWQgdGhl" + + "IHBvZCwgY2hlY2tlZCBmb3IgcHVsbCBzZWNyZXRzLCBjaGVja2VkIGltYWdlUHVsbFNlY3JldHMg" + + "b24gdGhlIHBvZCBzcGVjIGFuZCBzZXJ2aWNlIGFjY291bnQuIEl0IGlkZW50aWZpZWQgdGhlIGlz" + + "c3VlIChtaXNzaW5nIHNlY3JldCwgd3JvbmcgY3JlZGVudGlhbHMsIG9yIG1pc3NpbmcgaW1hZ2VQ" + + "dWxsU2VjcmV0cykgYW5kIHByb3ZpZGVkIHRoZSBjb3JyZWN0IGZpeC4iLAogICAgImV4cGVjdGVk" + + "X2JlaGF2aW9yIjogWwogICAgICAiVGhlIGFnZW50IHJlYWQgdGhlIG52Y2Ytc2VsZi1tYW5hZ2Vk" + + "LWluc3RhbGxhdGlvbiBTS0lMTC5tZCBhbmQgcmVmZXJlbmNlcy9kZWJ1Z2dpbmcubWQiLAogICAg" + + "ICAiVGhlIGFnZW50IHJhbiAna3ViZWN0bCBkZXNjcmliZSBwb2QnIHRvIHNlZSB0aGUgSW1hZ2VQ" + + "dWxsQmFja09mZiBldmVudHMiLAogICAgICAiVGhlIGFnZW50IGNoZWNrZWQgZm9yIHB1bGwgc2Vj" + + "cmV0cyBpbiB0aGUgY2Fzc2FuZHJhLXN5c3RlbSBuYW1lc3BhY2UiLAogICAgICAiVGhlIGFnZW50" + + "IGNoZWNrZWQgaW1hZ2VQdWxsU2VjcmV0cyBvbiB0aGUgcG9kIHNwZWMgYW5kL29yIHNlcnZpY2Ug" + + "YWNjb3VudCIsCiAgICAgICJUaGUgYWdlbnQgaWRlbnRpZmllZCB0aGUgcm9vdCBjYXVzZSBhbmQg" + + "cHJvdmlkZWQgYSBzcGVjaWZpYyBmaXgiCiAgICBdCiAgfSwKICB7CiAgICAiaWQiOiAiUzktcmVt" + + "b3RlLWVrcy1yb3V0aW5nLWFuZC1zZWNyZXRzIiwKICAgICJxdWVzdGlvbiI6ICJDb25maWd1cmUg" + + "YSByZW1vdGUgRUtTIGNvbXB1dGUgY2x1c3RlciB0byByZWFjaCBteSBOVkNGIGNvbnRyb2wgcGxh" + + "bmUgdGhyb3VnaCBpdHMgRW52b3kgR2F0ZXdheSwgaW5jbHVkaW5nIE5BVFMgYW5kIHByaXZhdGUt" + + "cmVnaXN0cnkgcHVsbCBzZWNyZXRzLiIsCiAgICAiZXhwZWN0ZWRfc2tpbGwiOiAibnZjZi1zZWxm" + + "LW1hbmFnZWQtaW5zdGFsbGF0aW9uIiwKICAgICJncm91bmRfdHJ1dGgiOiAiVGhlIGFnZW50IGNv" + + "bmZpZ3VyZWQgdGhlIGNvbnRyb2wgcGxhbmUgdG8gdXNlIHRoZSBFbnZveSBHYXRld2F5IGNvbnRy" + + "b2xsZXIgaW4gZW52b3ktZ2F0ZXdheS1zeXN0ZW0gYW5kIEdhdGV3YXkvbnZjZi1nYXRld2F5IGlu" + + "IGVudm95LWdhdGV3YXksIHNldCBhbGwgc2l4IHJlbW90ZSB3b3JrZXIgZW5kcG9pbnRzIGFuZCB0" + + "aGUgZ3JwYy1wcm94eSBsb2NhbCBvdmVycmlkZSwgZW5hYmxlZCBOVkNGIGFuZCBOVkNUIGdSUEMg" + + "cm91dGVzIHBsdXMgTkFUUywgYW5kIGVuYWJsZWQgT3BlbkJhbyBpc3N1ZXIgZGlzY292ZXJ5LiBJ" + + "dCBjb25maWd1cmVkIHRoZSBiYXJlLUdhdGV3YXkgQ0xJIFVSTCBhbmQgSG9zdCBmaWVsZHMgaW5j" + + "bHVkaW5nIGljbXNfaG9zdCwgcGx1cyB0aGUgY29tcHV0ZS1wbGFuZSBJQ01TLCBSZVZhbCwgYW5k" + + "IE5BVFMgZXh0ZXJuYWwgVVJMcyBhbmQgaG9zdCBvdmVycmlkZXMuIEl0IGNyZWF0ZWQgdGhlIHB1" + + "bGwgc2VjcmV0IGluIGFsbCBjb250cm9sLXBsYW5lIG5hbWVzcGFjZXMgaW5jbHVkaW5nIGNlcnQt" + + "bWFuYWdlciwgYnV0IG9ubHkgaW4gbnZjYS1vcGVyYXRvciBvbiB0aGUgY29tcHV0ZSBjbHVzdGVy" + + "OyB0aGUgY2hhcnQgYW5kIG9wZXJhdG9yIG1pcnJvciBpdCB0byBudmNhLXN5c3RlbS4iLAogICAg" + + "ImV4cGVjdGVkX2JlaGF2aW9yIjogWwogICAgICAiVGhlIGFnZW50IHJlYWQgdGhlIG52Y2Ytc2Vs" + + "Zi1tYW5hZ2VkLWluc3RhbGxhdGlvbiBTS0lMTC5tZCBiZWZvcmUgdGFraW5nIGFjdGlvbiIsCiAg" + + "ICAgICJUaGUgYWdlbnQgc2V0IGluZ3Jlc3MuZ2F0ZXdheUFwaS5jb250cm9sbGVyTmFtZXNwYWNl" + + "IHRvIGVudm95LWdhdGV3YXktc3lzdGVtIiwKICAgICAgIlRoZSBhZ2VudCBzZXQgc2hhcmVkLCBn" + + "cnBjLCBhbmQgbmF0cyBHYXRld2F5IHJlZmVyZW5jZXMgdG8gbmFtZSBudmNmLWdhdGV3YXkgYW5k" + + "IG5hbWVzcGFjZSBlbnZveS1nYXRld2F5IiwKICAgICAgIlRoZSBhZ2VudCBzZXQgZ2xvYmFsLndv" + + "cmtlckVuZHBvaW50cy5udmNmU2VydmljZVVSTCwgbnZjZkdycGNTZXJ2aWNlVVJMLCBudmNmTmF0" + + "c1NlcnZpY2VVUkwsIG52Y3RTZXJ2aWNlVVJMLCBudmN0R3JwY1NlcnZpY2VVUkwsIGFuZCBpbnZv" + + "Y2F0aW9uU2VydmljZVVSTCIsCiAgICAgICJUaGUgYWdlbnQgc2V0IGdycGNwcm94eS5udmNmR3Jw" + + "Y1NlcnZpY2VVUkwgdG8gdGhlIGNvbnRyb2wtcGxhbmUtbG9jYWwgQVBJIGdSUEMgc2VydmljZSIs" + + "CiAgICAgICJUaGUgYWdlbnQgZW5hYmxlZCBib3RoIGluZ3Jlc3MuZ2F0ZXdheUFwaS5yb3V0ZXMu" + + "bnZjZkFwaS5ncnBjIGFuZCBudmN0QXBpLmdycGMgd2l0aCB3b3JrZXItYXBpIGFuZCB3b3JrZXIt" + + "dGFza3MgaG9zdG5hbWVzIiwKICAgICAgIlRoZSBhZ2VudCBleHBsaWNpdGx5IHNldCBpbmdyZXNz" + + "LmdhdGV3YXlBcGkucm91dGVzLm5hdHMuZW5hYmxlZCB0byB0cnVlIiwKICAgICAgIlRoZSBhZ2Vu" + + "dCBzZXQgb3BlbmJhby5taWdyYXRpb25zLmlzc3VlckRpc2NvdmVyeS5lbmFibGVkIHRvIHRydWUi" + + "LAogICAgICAiVGhlIGFnZW50IGNvbmZpZ3VyZWQgdGhlIGJhcmUtR2F0ZXdheSBDTEkgVVJMIGFu" + + "ZCBIb3N0IGZpZWxkcywgaW5jbHVkaW5nIHNjaGVtZS1sZXNzIGljbXNfaG9zdCIsCiAgICAgICJU" + + "aGUgYWdlbnQgY29uZmlndXJlZCBjb21wdXRlLXBsYW5lIGljbXNTZXJ2aWNlVVJMLCBpY21zU2Vy" + + "dmljZUhvc3RIZWFkZXJPdmVycmlkZSwgcmV2YWxTZXJ2aWNlVVJMLCByZXZhbFNlcnZpY2VIb3N0" + + "SGVhZGVyT3ZlcnJpZGUsIG5hdHNVUkwsIGFuZCBuYXRzSG9zdE92ZXJyaWRlIiwKICAgICAgIlRo" + + "ZSBjb250cm9sLXBsYW5lIHB1bGwtc2VjcmV0IG5hbWVzcGFjZSBsaXN0IGluY2x1ZGVkIGNlcnQt" + + "bWFuYWdlciIsCiAgICAgICJUaGUgY29tcHV0ZS1wbGFuZSBzZWNyZXQgd2FzIGNyZWF0ZWQgb25s" + + "eSBpbiBudmNhLW9wZXJhdG9yIGFuZCBtaXJyb3JlZCBieSB0aGUgY2hhcnQgYW5kIG9wZXJhdG9y" + + "IHRvIG52Y2Etc3lzdGVtIgogICAgXQogIH0sCiAgewogICAgImlkIjogIkcxMS1zcGxpdC10ZWFy" + + "ZG93biIsCiAgICAicXVlc3Rpb24iOiAiVGVhciBkb3duIG15IHNwbGl0IGNvbnRyb2wtcGxhbmUg" + + "YW5kIGNvbXB1dGUtcGxhbmUgZGVwbG95bWVudCBzYWZlbHkuIFNob3cgYm90aCB0aGUgSGVsbWZp" + + "bGUgdmFsdWVzIGFuZCBDTEkgcHJvZmlsZSB2YXJpYW50cy4iLAogICAgImV4cGVjdGVkX3NraWxs" + + "IjogIm52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3RydXRoIjog" + + "IlRoZSBIZWxtZmlsZSBmbG93IGRlc3Ryb3llZCBhbmQgY29uZmlybWVkIGRlcmVnaXN0cmF0aW9u" + + "IG9mIGV2ZXJ5IGNvbXB1dGUgY2x1c3RlciBiZWZvcmUgZGVzdHJveWluZyB0aGUgY29udHJvbCBw" + + "bGFuZSBhbmQgcGFzc2VkIGJvdGggY29udHJvbC1wbGFuZSBrdWJlY29uZmlnIGZvcm1zLiBCZWZv" + + "cmUgZWl0aGVyIGhhbmRvZmYgY291bGQgZGVzdHJveSB0aGUgY29udHJvbCBwbGFuZSwgYm90aCB0" + + "ZWFyZG93biBmbG93cyB3YXJuZWQgdGhhdCBuYW1lc3BhY2UgcHJlc2VydmF0aW9uIGRvZXMgbm90" + + "IHByZXNlcnZlIHRoZSBIZWxtIHJlbGVhc2UsIHJlcXVpcmVkIGVmZmVjdGl2ZSBjZXJ0TWFuYWdl" + + "ci5lbmFibGVkOiBmYWxzZSBmb3IgYW4gZXh0ZXJuYWwgaW5zdGFsbGF0aW9uIGFuZCBhYm9ydGVk" + + "IGlmIHRydWUsIGFuZCB2ZXJpZmllZCBtYXRjaGluZyByZWxlYXNlIG93bmVyc2hpcCBmb3IgYW4g" + + "aW50ZW5kZWQgc3RhY2stbWFuYWdlZCByZWxlYXNlLCBhYm9ydGluZyBvbiBtaXNzaW5nIG9yIG1p" + + "c21hdGNoZWQgZXZpZGVuY2UuIFRoZXkgcHJlc2VydmVkIHRoZSBuYW1lc3BhY2UgYnkgZGVmYXVs" + + "dCBhbmQgZGlkIG5vdCBkZWxldGUgaXQgd2l0aG91dCBuYW1lc3BhY2UgcHJvdmVuYW5jZSBhbmQg" + + "ZXhwbGljaXQgY29uZmlybWF0aW9uLiBUaGUgQ0xJIGZsb3cgcmV0YWluZWQgdGhlIGdlbmVyYXRl" + + "ZCByZWdpc3RyYXRpb24gdmFsdWVzLCB1c2VkIHRoZSBmdWxsLXByZWZpeCBzdGF0dXMgY29tbWFu" + + "ZCB0byBpbnNwZWN0IGxpdmUgcmVnaXN0cmF0aW9ucywgc3RhdGVkIHRoYXQgbmFtZWQtY2x1c3Rl" + + "ciBwbGFuLW9ubHkgZG9lcyBub3QgcXVlcnkgSUNNUyBhbmQgY2Fubm90IHByZWRpY3QgY29uZGl0" + + "aW9uYWwgY29udHJvbC1wbGFuZSByZW1vdmFsLCBhbmQgZ290IGV4cGxpY2l0IGNvbmZpcm1hdGlv" + + "biB3aGVuIHRoZSB0YXJnZXQgd2FzIHRoZSBsYXN0IHJlZ2lzdGVyZWQgY2x1c3Rlci4gSXQgdGhl" + + "biBwcmV2aWV3ZWQgYW5kIHJhbiBkb3duIHdpdGggdGhlIGZ1bGwgcGVyc2lzdGVudCBwcmVmaXgs" + + "IHJlbW92aW5nIHRoZSBjb250cm9sIHBsYW5lIG9ubHkgYWZ0ZXIgdGhlIGxhc3QgcmVnaXN0cmF0" + + "aW9uIHdhcyBnb25lLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdl" + + "bnQgcmVhZCB0aGUgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIFNLSUxMLm1kIGJlZm9y" + + "ZSB0YWtpbmcgYWN0aW9uIiwKICAgICAgIkZvciBldmVyeSBjb21wdXRlIGNsdXN0ZXIsIHRoZSBI" + + "ZWxtZmlsZSBmbG93IHJhbiB0aGUgY29tcHV0ZS1wbGFuZSBNYWtlZmlsZSBkZXN0cm95IHRhcmdl" + + "dCB3aXRoIGl0cyBjb21wdXRlIGt1YmVjb25maWciLAogICAgICAiQWZ0ZXIgY29uZmlybWF0aW9u" + + "LCB0aGUgSGVsbWZpbGUgZmxvdyByYW4gY2x1c3RlciBkZWxldGUgd2l0aCBjbHVzdGVySUQgYW5k" + + "IG5jYUlEIGJlZm9yZSBjb250cm9sLXBsYW5lIGRlc3RydWN0aW9uIiwKICAgICAgIkJlZm9yZSBl" + + "aXRoZXIgaGFuZG9mZiBjb3VsZCBkZXN0cm95IHRoZSBjb250cm9sIHBsYW5lLCBib3RoIHRlYXJk" + + "b3duIGZsb3dzIHdhcm5lZCB0aGF0IG5hbWVzcGFjZSBwcmVzZXJ2YXRpb24gZG9lcyBub3QgcHJl" + + "c2VydmUgdGhlIEhlbG0gcmVsZWFzZSwgcmVxdWlyZWQgZWZmZWN0aXZlIGNlcnRNYW5hZ2VyLmVu" + + "YWJsZWQ6IGZhbHNlIGZvciBhbiBleHRlcm5hbCBpbnN0YWxsYXRpb24gYW5kIGFib3J0ZWQgaWYg" + + "dHJ1ZSwgYW5kIHZlcmlmaWVkIGludGVuZGVkIHN0YWNrIG93bmVyc2hpcCB3aGVuIGVuYWJsZWQs" + + "IGFib3J0aW5nIG9uIG1pc3Npbmcgb3IgbWlzbWF0Y2hlZCBldmlkZW5jZSIsCiAgICAgICJCb3Ro" + + "IHRlYXJkb3duIGZsb3dzIHByZXNlcnZlZCB0aGUgY2VydC1tYW5hZ2VyIG5hbWVzcGFjZSBieSBk" + + "ZWZhdWx0IGFuZCBkaWQgbm90IGRlbGV0ZSBpdCB3aXRob3V0IG5hbWVzcGFjZSBwcm92ZW5hbmNl" + + "IGFuZCBleHBsaWNpdCBjb25maXJtYXRpb24iLAogICAgICAiVGhlIEhlbG1maWxlIGZsb3cgcmFu" + + "IGNvbnRyb2wtcGxhbmUgTWFrZWZpbGUgZGVzdHJveSB3aXRoIGJvdGggS1VCRUNPTkZJRyBhbmQg" + + "S1VCRUNPTkZJR19GSUxFIiwKICAgICAgIlRoZSBDTEkgZmxvdyByZXRhaW5lZCBvdXQvPGNsdXN0" + + "ZXItbmFtZT4tcmVnaXN0ZXItdmFsdWVzLnlhbWwgdW50aWwgdGVhcmRvd24gY29tcGxldGVkIiwK" + + "ICAgICAgIkJlZm9yZSByZWFsIGRvd24sIHRoZSBDTEkgZmxvdyB1c2VkIHRoZSBmdWxsLXByZWZp" + + "eCBzdGF0dXMgY29tbWFuZCB0byBpbnNwZWN0IGxpdmUgcmVnaXN0cmF0aW9ucywgc3RhdGVkIHRo" + + "YXQgbmFtZWQtY2x1c3RlciBwbGFuLW9ubHkgZG9lcyBub3QgcXVlcnkgSUNNUyBhbmQgY2Fubm90" + + "IHByZWRpY3QgY29uZGl0aW9uYWwgY29udHJvbC1wbGFuZSByZW1vdmFsLCB3YXJuZWQgd2hlbiB0" + + "aGUgdGFyZ2V0IHdhcyB0aGUgbGFzdCByZWdpc3RlcmVkIGNsdXN0ZXIsIGFuZCBnb3QgZXhwbGlj" + + "aXQgY29uZmlybWF0aW9uIiwKICAgICAgIlRoZSBDTEkgZmxvdyB1c2VkIC0tY29uZmlnLCBib3Ro" + + "IHN0YWNrIHBhdGhzLCAtLWVudiwgLS1wbGFpbiwgYm90aCBjb250ZXh0cywgYW5kIC0taWNtcy11" + + "cmwgZm9yIGRvd24gLS1wbGFuLW9ubHkgYW5kIHRoZW4gZG93biIsCiAgICAgICJUaGUgYWdlbnQg" + + "c3RhdGVkIHRoYXQgZG93biB1bnJlZ2lzdGVycyBlYWNoIGNvbXB1dGUgY2x1c3RlciBhbmQgcmVt" + + "b3ZlcyB0aGUgY29udHJvbCBwbGFuZSBvbmx5IGFmdGVyIG5vIHJlZ2lzdHJhdGlvbnMgcmVtYWlu" + + "IgogICAgXQogIH0sCiAgewogICAgImlkIjogIlMxMy12YWx1ZXMtcHJlY2VkZW5jZSIsCiAgICAi" + + "cXVlc3Rpb24iOiAiSSBhZGRlZCBhIHZhbHVlIHRvIG15IGVudmlyb25tZW50IFlBTUwgYnV0IGl0" + + "J3MgYmVpbmcgc2lsZW50bHkgaWdub3JlZC4gSG93IGRvIGhlbG1maWxlIHZhbHVlcyB3b3JrIGlu" + + "IE5WQ0Y/IiwKICAgICJleHBlY3RlZF9za2lsbCI6ICJudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxs" + + "YXRpb24iLAogICAgImdyb3VuZF90cnV0aCI6ICJUaGUgYWdlbnQgZXhwbGFpbmVkIHRoZSB2YWx1" + + "ZXMgcHJlY2VkZW5jZSBjaGFpbiAoYmFzZS55YW1sLCBlbnYgWUFNTCwgZ2xvYmFsLnlhbWwuZ290" + + "bXBsLCBzZWNyZXRzLCBpbmxpbmUgdmFsdWVzKSwgaWRlbnRpZmllZCB0aGF0IGdsb2JhbC55YW1s" + + "LmdvdG1wbCBvbmx5IHBhc3NlcyB0aHJvdWdoIHNwZWNpZmljIGtleXMsIGFuZCBleHBsYWluZWQg" + + "dGhhdCBhcmJpdHJhcnkgY2hhcnQgdmFsdWVzIG11c3QgdXNlIHJlbGVhc2UgaW5saW5lIHZhbHVl" + + "cyBibG9ja3MuIiwKICAgICJleHBlY3RlZF9iZWhhdmlvciI6IFsKICAgICAgIlRoZSBhZ2VudCBy" + + "ZWFkIHRoZSBudmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24gU0tJTEwubWQgYmVmb3JlIHRh" + + "a2luZyBhY3Rpb24iLAogICAgICAiVGhlIGFnZW50IGV4cGxhaW5lZCB0aGUgdmFsdWVzIHByZWNl" + + "ZGVuY2UgY2hhaW46IGJhc2UueWFtbCAtPiBlbnYgWUFNTCAtPiBnbG9iYWwueWFtbC5nb3RtcGwg" + + "LT4gc2VjcmV0cyAtPiBpbmxpbmUgdmFsdWVzIiwKICAgICAgIlRoZSBhZ2VudCBpZGVudGlmaWVk" + "IHRoYXQgZ2xvYmFsLnlhbWwuZ290bXBsIG9ubHkgcGFzc2VzIHRocm91Z2ggc3BlY2lmaWMga2V5" + - "cywgYW5kIGV4cGxhaW5lZCB0aGF0IGFyYml0cmFyeSBjaGFydCB2YWx1ZXMgbXVzdCB1c2UgcmVs" + - "ZWFzZSBpbmxpbmUgdmFsdWVzIGJsb2Nrcy4iLAogICAgImV4cGVjdGVkX2JlaGF2aW9yIjogWwog" + - "ICAgICAiVGhlIGFnZW50IHJlYWQgdGhlIG52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbiBT" + - "S0lMTC5tZCBiZWZvcmUgdGFraW5nIGFjdGlvbiIsCiAgICAgICJUaGUgYWdlbnQgZXhwbGFpbmVk" + - "IHRoZSB2YWx1ZXMgcHJlY2VkZW5jZSBjaGFpbjogYmFzZS55YW1sIC0+IGVudiBZQU1MIC0+IGds" + - "b2JhbC55YW1sLmdvdG1wbCAtPiBzZWNyZXRzIC0+IGlubGluZSB2YWx1ZXMiLAogICAgICAiVGhl" + - "IGFnZW50IGlkZW50aWZpZWQgdGhhdCBnbG9iYWwueWFtbC5nb3RtcGwgb25seSBwYXNzZXMgdGhy" + - "b3VnaCBzcGVjaWZpYyBrZXlzIChjYXNzYW5kcmEucmVwbGljYUNvdW50LCBnbG9iYWwuc3RvcmFn" + - "ZUNsYXNzLCBnbG9iYWwuaW1hZ2UsIGV0Yy4pIiwKICAgICAgIlRoZSBhZ2VudCBleHBsYWluZWQg" + - "dGhhdCBhcmJpdHJhcnkgY2hhcnQgdmFsdWVzIG11c3QgYmUgc2V0IHZpYSByZWxlYXNlIGlubGlu" + - "ZSB2YWx1ZXM6IGJsb2NrcyIsCiAgICAgICJUaGUgYWdlbnQgbGlzdGVkIGV4YW1wbGVzIG9mIHZh" + - "bHVlcyB0aGF0IGFyZSBwcm9wYWdhdGVkIGFuZCBhcmJpdHJhcnkgY2hhcnQgdmFsdWVzIHRoYXQg" + - "cmVxdWlyZSBhIHJlbGVhc2UgdmFsdWVzIGJsb2NrIgogICAgXQogIH0sCiAgewogICAgImlkIjog" + - "IlMxNC1lbmFibGUtbGxtLWZ1bmN0aW9ucyIsCiAgICAicXVlc3Rpb24iOiAiSSBuZWVkIHRvIGRl" + - "cGxveSBmdW5jdGlvblR5cGU6IExMTSBmdW5jdGlvbnMgb24gYSBzZWxmLW1hbmFnZWQsIHNpbmds" + - "ZS1ub2RlIGlzb2xhdGVkIHRlc3QgY2x1c3Rlci4gV2hhdCBIZWxtZmlsZSBjb25maWd1cmF0aW9u" + - "IGFuZCB2ZXJpZmljYXRpb24gc3RlcHMgZG8gSSBuZWVkPyIsCiAgICAiZXhwZWN0ZWRfc2tpbGwi" + - "OiAibnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uIiwKICAgICJncm91bmRfdHJ1dGgiOiAi" + - "VGhlIGFnZW50IGVuYWJsZWQgdGhlIExMTSBhZGRvbiB3aXRoIGFkZG9ucy5sbG0uZW5hYmxlZCwg" + - "Y29uZmlndXJlZCBzaW5nbGUgcmVwbGljYXMgZm9yIHRoZSBMTE0gQVBJIEdhdGV3YXkgYW5kIHJl" + - "cXVlc3Qgcm91dGVyLCBhbmQgZXhwbGFpbmVkIHRoYXQgdGhlIHJlcXVlc3Qgcm91dGVyIHVzZXMg" + - "cG93ZXItb2YtdHdvIHdoZW4gbm8gbG9hZC1iYWxhbmNlciBjb25maWd1cmF0aW9uIGlzIHNldC4g" + - "SXQgbGlua2VkIHRoZSBjYW5vbmljYWwgcmVxdWVzdC1yb3V0ZXIgbG9hZC1iYWxhbmNpbmcgZ3Vp" + - "ZGUgZm9yIG90aGVyIHJvdXRpbmcgbWV0aG9kcy4gRm9yIHRoZSBpc29sYXRlZCBwbGFpbnRleHQg" + - "Y2x1c3RlciwgaXQgcmVsaWVkIG9uIHRoZSBzZWxmLW1hbmFnZWQgc3RhY2sgZGVmYXVsdCBmb3Ig" + - "dGhlIGJ1bmRsZWQgZ2F0ZXdheS10by1BUEkgYXV0aGVudGljYXRpb24gaG9wIGFuZCBpbmNsdWRl" + - "ZCBhZ2VudENvbmZpZy5tZXJnZUNvbmZpZy53b3JrbG9hZC5zdGFyZ2F0ZVFVSUNJbnNlY3VyZSBm" + - "b3IgdGhlIHNlcGFyYXRlIHdvcmtlciB0cmFuc3BvcnQsIHdpdGggYSB3YXJuaW5nIHRoYXQgcGxh" + - "aW50ZXh0IHdvcmtlciB0cmFuc3BvcnQgaXMgbm90IGZvciBwcm9kdWN0aW9uLiBJdCByZWZyZXNo" + - "ZWQgdGhlIGNvbXB1dGUgcGxhbmUgdXNpbmcgdGhlIHNhbWUgaGFuZG9mZiB1c2VkIGR1cmluZyBp" + - "bnN0YWxsYXRpb24sIHJlZGVwbG95ZWQgZXhpc3RpbmcgTExNIGZ1bmN0aW9ucywgYW5kIHZlcmlm" + - "aWVkIHRoZSBMTE0gZGVwbG95bWVudHMsIHJvdXRlLCBhbmQgbGxtLXdvcmtlciBzaWRlY2FyLiIs" + - "CiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAgICAgICJUaGUgYWdlbnQgdXNlZCBhZGRvbnMu" + - "bGxtLmVuYWJsZWQsIG5vdCB0aGUgb2Jzb2xldGUgbGxtLmVuYWJsZWQgcGF0aCIsCiAgICAgICJU" + - "aGUgYWdlbnQgc2V0IGdhdGV3YXkgYW5kIHJlcXVlc3RSb3V0ZXIgcmVwbGljYUNvdW50IHRvIDEg" + - "Zm9yIHRoZSBzaW5nbGUtbm9kZSB0ZXN0IGNsdXN0ZXIiLAogICAgICAiVGhlIGFnZW50IHN0YXRl" + - "ZCB0aGF0IHRoZSByZXF1ZXN0IHJvdXRlciBkZWZhdWx0cyB0byBwb3dlci1vZi10d28gYW5kIGxp" + - "bmtlZCB0aGUgY2Fub25pY2FsIHJlcXVlc3Qtcm91dGVyIGxvYWQtYmFsYW5jaW5nIGd1aWRlIGZv" + - "ciBvdGhlciBtZXRob2RzIiwKICAgICAgIlRoZSBhZ2VudCBleHBsYWluZWQgdGhhdCB0aGUgYnVu" + - "ZGxlZCBnYXRld2F5LXRvLUFQSSBhdXRoZW50aWNhdGlvbiBob3AgZGVmYXVsdHMgdG8gcGxhaW50" + - "ZXh0LCBpbmNsdWRlZCB3b3JrbG9hZC5zdGFyZ2F0ZVFVSUNJbnNlY3VyZSBvbmx5IGZvciB0aGUg" + - "aXNvbGF0ZWQgd29ya2VyIHRyYW5zcG9ydCwgYW5kIHdhcm5lZCBhZ2FpbnN0IHBsYWludGV4dCB3" + - "b3JrZXIgdHJhbnNwb3J0IGluIHByb2R1Y3Rpb24iLAogICAgICAiVGhlIGFnZW50IGFwcGxpZWQg" + - "dGhlIGNvbnRyb2wtcGxhbmUgSGVsbWZpbGUgZW52aXJvbm1lbnQsIHJlZnJlc2hlZCB0aGUgY29t" + - "cHV0ZSBwbGFuZSB3aXRoIHRoZSBzYW1lIHNlbGVjdGVkIGhhbmRvZmYsIGFuZCByZWNyZWF0ZWQg" + - "b3IgcmVkZXBsb3llZCBleGlzdGluZyBMTE0gZnVuY3Rpb25zIiwKICAgICAgIlRoZSBhZ2VudCB2" + - "ZXJpZmllZCBsbG0tYXBpLWdhdGV3YXksIGxsbS1yZXF1ZXN0LXJvdXRlciwgdGhlIExMTSBIVFRQ" + - "Um91dGUsIGFuZCB0aGUgbGxtLXdvcmtlciBzaWRlY2FyIGluY2x1ZGluZyAtLXF1aWMtaW5zZWN1" + - "cmUiCiAgICBdCiAgfSwKICB7CiAgICAiaWQiOiAiRzgtTkVHLW5vdC1mb3ItazNkIiwKICAgICJx" + - "dWVzdGlvbiI6ICJTZXQgdXAgYSBsb2NhbCBOVkNGIGRldiBjbHVzdGVyIHVzaW5nIGszZCBmb3Ig" + - "dGVzdGluZyIsCiAgICAiZXhwZWN0ZWRfc2tpbGwiOiBudWxsLAogICAgInNob3VsZF90cmlnZ2Vy" + - "IjogZmFsc2UsCiAgICAiZ3JvdW5kX3RydXRoIjogIlRoaXMgaXMgYSBsb2NhbCBrM2QgZGV2ZWxv" + - "cG1lbnQgcmVxdWVzdCB0aGF0IGJlbG9uZ3MgdG8gdGhlIG52Y2Ytc2VsZi1ob3N0ZWQtbG9jYWwt" + - "ZGV2IHNraWxsLCBub3QgbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uLiBUaGUgYWdlbnQg" + - "ZGlkIG5vdCByZWFkIG9yIHVzZSB0aGUgc2VsZi1tYW5hZ2VkIGluc3RhbGxhdGlvbiBza2lsbCBh" + - "bmQgaW5zdGVhZCBwcm92aWRlZCBrM2Qtc3BlY2lmaWMgZ3VpZGFuY2UuIiwKICAgICJleHBlY3Rl" + - "ZF9iZWhhdmlvciI6IFsKICAgICAgIlRoZSBhZ2VudCBkaWQgbm90IHJlYWQgbnZjZi1zZWxmLW1h" + - "bmFnZWQtaW5zdGFsbGF0aW9uL1NLSUxMLm1kIiwKICAgICAgIlRoZSBhZ2VudCBkaWQgbm90IHBy" + - "b3ZpZGUgaGVsbWZpbGUtYmFzZWQgcHJvZHVjdGlvbiBkZXBsb3ltZW50IGluc3RydWN0aW9ucyIs" + - "CiAgICAgICJUaGUgYWdlbnQgcHJvdmlkZWQgazNkLXNwZWNpZmljIGxvY2FsIGRldmVsb3BtZW50" + - "IGd1aWRhbmNlIG9yIGRlZmVycmVkIHRvIHRoZSBhcHByb3ByaWF0ZSBsb2NhbC1kZXYgc2tpbGwi" + - "CiAgICBdCiAgfQpdClBLBwhHVWpWSlYAAEpWAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAAC8A" + - "CQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9leGFtcGxlcy5tZFVUBQABAKbO" + - "EiMgRXhhbXBsZXMKCldvcmtlZCBleGFtcGxlcyBiYXNlZCBvbiByZWFsIGRlcGxveW1lbnQgc2Nl" + - "bmFyaW9zLgoKIyMgRXhhbXBsZSAxOiBPdmVycmlkZSBDYXNzYW5kcmEgUmVzb3VyY2VzCgpUaGUg" + - "ZGVmYXVsdCBDYXNzYW5kcmEgcmVzb3VyY2UgbGltaXRzIGNhdXNlIE9PTSBvbiBsYXJnZSBpbnN0" + - "YW5jZSB0eXBlcyAoZS5nLiwgYHA1LjQ4eGxhcmdlYCkuCgpQcm9ibGVtOiBDYXNzYW5kcmEgcG9k" + - "cyByZXN0YXJ0IHdpdGggYE9PTUtpbGxlZGAuCgpTb2x1dGlvbjogT3ZlcnJpZGUgcmVzb3VyY2Vz" + - "IHZpYSBoZWxtZmlsZSByZWxlYXNlIHZhbHVlcyBibG9jay4KCiMjIyBTdGVwIDE6IENhcHR1cmUg" + - "YmFzZWxpbmUKCmBgYGJhc2gKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3Ig" + - "bmFtZT1jYXNzYW5kcmEgdGVtcGxhdGUgPiAvdG1wL2Nhc3MtYmVmb3JlLnlhbWwKZ3JlcCAtQTgg" + - "J3Jlc291cmNlczonIC90bXAvY2Fzcy1iZWZvcmUueWFtbCB8IGhlYWQgLTEwCmBgYAoKIyMjIFN0" + - "ZXAgMjogQWRkIG92ZXJyaWRlIHRvIGhlbG1maWxlLmQvMDEtZGVwZW5kZW5jaWVzLnlhbWwuZ290" + - "bXBsCgpJbiB0aGUgZXhhbXBsZXMgYmVsb3csIGA8cHJpdmF0ZS12YWx1ZXM+YCByZWZlcnMgdG8g" + - "dGhlIGBzZWNyZXRzL2AgZGlyZWN0b3J5IGF0IHRoZSBoZWxtZmlsZSBzdGFjayByb290LgoKYGBg" + + "cyAoY2Fzc2FuZHJhLnJlcGxpY2FDb3VudCwgZ2xvYmFsLnN0b3JhZ2VDbGFzcywgZ2xvYmFsLmlt" + + "YWdlLCBldGMuKSIsCiAgICAgICJUaGUgYWdlbnQgZXhwbGFpbmVkIHRoYXQgYXJiaXRyYXJ5IGNo" + + "YXJ0IHZhbHVlcyBtdXN0IGJlIHNldCB2aWEgcmVsZWFzZSBpbmxpbmUgdmFsdWVzOiBibG9ja3Mi" + + "LAogICAgICAiVGhlIGFnZW50IGxpc3RlZCBleGFtcGxlcyBvZiB2YWx1ZXMgdGhhdCBhcmUgcHJv" + + "cGFnYXRlZCBhbmQgYXJiaXRyYXJ5IGNoYXJ0IHZhbHVlcyB0aGF0IHJlcXVpcmUgYSByZWxlYXNl" + + "IHZhbHVlcyBibG9jayIKICAgIF0KICB9LAogIHsKICAgICJpZCI6ICJTMTQtZW5hYmxlLWxsbS1m" + + "dW5jdGlvbnMiLAogICAgInF1ZXN0aW9uIjogIkkgbmVlZCB0byBkZXBsb3kgZnVuY3Rpb25UeXBl" + + "OiBMTE0gZnVuY3Rpb25zIG9uIGEgc2VsZi1tYW5hZ2VkLCBzaW5nbGUtbm9kZSBpc29sYXRlZCB0" + + "ZXN0IGNsdXN0ZXIuIFdoYXQgSGVsbWZpbGUgY29uZmlndXJhdGlvbiBhbmQgdmVyaWZpY2F0aW9u" + + "IHN0ZXBzIGRvIEkgbmVlZD8iLAogICAgImV4cGVjdGVkX3NraWxsIjogIm52Y2Ytc2VsZi1tYW5h" + + "Z2VkLWluc3RhbGxhdGlvbiIsCiAgICAiZ3JvdW5kX3RydXRoIjogIlRoZSBhZ2VudCBlbmFibGVk" + + "IHRoZSBMTE0gYWRkb24gd2l0aCBhZGRvbnMubGxtLmVuYWJsZWQsIGNvbmZpZ3VyZWQgc2luZ2xl" + + "IHJlcGxpY2FzIGZvciB0aGUgTExNIEFQSSBHYXRld2F5IGFuZCByZXF1ZXN0IHJvdXRlciwgYW5k" + + "IGV4cGxhaW5lZCB0aGF0IHRoZSByZXF1ZXN0IHJvdXRlciB1c2VzIHBvd2VyLW9mLXR3byB3aGVu" + + "IG5vIGxvYWQtYmFsYW5jZXIgY29uZmlndXJhdGlvbiBpcyBzZXQuIEl0IGxpbmtlZCB0aGUgY2Fu" + + "b25pY2FsIHJlcXVlc3Qtcm91dGVyIGxvYWQtYmFsYW5jaW5nIGd1aWRlIGZvciBvdGhlciByb3V0" + + "aW5nIG1ldGhvZHMuIEZvciB0aGUgaXNvbGF0ZWQgcGxhaW50ZXh0IGNsdXN0ZXIsIGl0IHJlbGll" + + "ZCBvbiB0aGUgc2VsZi1tYW5hZ2VkIHN0YWNrIGRlZmF1bHQgZm9yIHRoZSBidW5kbGVkIGdhdGV3" + + "YXktdG8tQVBJIGF1dGhlbnRpY2F0aW9uIGhvcCBhbmQgaW5jbHVkZWQgYWdlbnRDb25maWcubWVy" + + "Z2VDb25maWcud29ya2xvYWQuc3RhcmdhdGVRVUlDSW5zZWN1cmUgZm9yIHRoZSBzZXBhcmF0ZSB3" + + "b3JrZXIgdHJhbnNwb3J0LCB3aXRoIGEgd2FybmluZyB0aGF0IHBsYWludGV4dCB3b3JrZXIgdHJh" + + "bnNwb3J0IGlzIG5vdCBmb3IgcHJvZHVjdGlvbi4gSXQgcmVmcmVzaGVkIHRoZSBjb21wdXRlIHBs" + + "YW5lIHVzaW5nIHRoZSBzYW1lIGhhbmRvZmYgdXNlZCBkdXJpbmcgaW5zdGFsbGF0aW9uLCByZWRl" + + "cGxveWVkIGV4aXN0aW5nIExMTSBmdW5jdGlvbnMsIGFuZCB2ZXJpZmllZCB0aGUgTExNIGRlcGxv" + + "eW1lbnRzLCByb3V0ZSwgYW5kIGxsbS13b3JrZXIgc2lkZWNhci4iLAogICAgImV4cGVjdGVkX2Jl" + + "aGF2aW9yIjogWwogICAgICAiVGhlIGFnZW50IHVzZWQgYWRkb25zLmxsbS5lbmFibGVkLCBub3Qg" + + "dGhlIG9ic29sZXRlIGxsbS5lbmFibGVkIHBhdGgiLAogICAgICAiVGhlIGFnZW50IHNldCBnYXRl" + + "d2F5IGFuZCByZXF1ZXN0Um91dGVyIHJlcGxpY2FDb3VudCB0byAxIGZvciB0aGUgc2luZ2xlLW5v" + + "ZGUgdGVzdCBjbHVzdGVyIiwKICAgICAgIlRoZSBhZ2VudCBzdGF0ZWQgdGhhdCB0aGUgcmVxdWVz" + + "dCByb3V0ZXIgZGVmYXVsdHMgdG8gcG93ZXItb2YtdHdvIGFuZCBsaW5rZWQgdGhlIGNhbm9uaWNh" + + "bCByZXF1ZXN0LXJvdXRlciBsb2FkLWJhbGFuY2luZyBndWlkZSBmb3Igb3RoZXIgbWV0aG9kcyIs" + + "CiAgICAgICJUaGUgYWdlbnQgZXhwbGFpbmVkIHRoYXQgdGhlIGJ1bmRsZWQgZ2F0ZXdheS10by1B" + + "UEkgYXV0aGVudGljYXRpb24gaG9wIGRlZmF1bHRzIHRvIHBsYWludGV4dCwgaW5jbHVkZWQgd29y" + + "a2xvYWQuc3RhcmdhdGVRVUlDSW5zZWN1cmUgb25seSBmb3IgdGhlIGlzb2xhdGVkIHdvcmtlciB0" + + "cmFuc3BvcnQsIGFuZCB3YXJuZWQgYWdhaW5zdCBwbGFpbnRleHQgd29ya2VyIHRyYW5zcG9ydCBp" + + "biBwcm9kdWN0aW9uIiwKICAgICAgIlRoZSBhZ2VudCBhcHBsaWVkIHRoZSBjb250cm9sLXBsYW5l" + + "IEhlbG1maWxlIGVudmlyb25tZW50LCByZWZyZXNoZWQgdGhlIGNvbXB1dGUgcGxhbmUgd2l0aCB0" + + "aGUgc2FtZSBzZWxlY3RlZCBoYW5kb2ZmLCBhbmQgcmVjcmVhdGVkIG9yIHJlZGVwbG95ZWQgZXhp" + + "c3RpbmcgTExNIGZ1bmN0aW9ucyIsCiAgICAgICJUaGUgYWdlbnQgdmVyaWZpZWQgbGxtLWFwaS1n" + + "YXRld2F5LCBsbG0tcmVxdWVzdC1yb3V0ZXIsIHRoZSBMTE0gSFRUUFJvdXRlLCBhbmQgdGhlIGxs" + + "bS13b3JrZXIgc2lkZWNhciBpbmNsdWRpbmcgLS1xdWljLWluc2VjdXJlIgogICAgXQogIH0sCiAg" + + "ewogICAgImlkIjogIkc4LU5FRy1ub3QtZm9yLWszZCIsCiAgICAicXVlc3Rpb24iOiAiU2V0IHVw" + + "IGEgbG9jYWwgTlZDRiBkZXYgY2x1c3RlciB1c2luZyBrM2QgZm9yIHRlc3RpbmciLAogICAgImV4" + + "cGVjdGVkX3NraWxsIjogbnVsbCwKICAgICJzaG91bGRfdHJpZ2dlciI6IGZhbHNlLAogICAgImdy" + + "b3VuZF90cnV0aCI6ICJUaGlzIGlzIGEgbG9jYWwgazNkIGRldmVsb3BtZW50IHJlcXVlc3QgdGhh" + + "dCBiZWxvbmdzIHRvIHRoZSBudmNmLXNlbGYtaG9zdGVkLWxvY2FsLWRldiBza2lsbCwgbm90IG52" + + "Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi4gVGhlIGFnZW50IGRpZCBub3QgcmVhZCBvciB1" + + "c2UgdGhlIHNlbGYtbWFuYWdlZCBpbnN0YWxsYXRpb24gc2tpbGwgYW5kIGluc3RlYWQgcHJvdmlk" + + "ZWQgazNkLXNwZWNpZmljIGd1aWRhbmNlLiIsCiAgICAiZXhwZWN0ZWRfYmVoYXZpb3IiOiBbCiAg" + + "ICAgICJUaGUgYWdlbnQgZGlkIG5vdCByZWFkIG52Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlv" + + "bi9TS0lMTC5tZCIsCiAgICAgICJUaGUgYWdlbnQgZGlkIG5vdCBwcm92aWRlIGhlbG1maWxlLWJh" + + "c2VkIHByb2R1Y3Rpb24gZGVwbG95bWVudCBpbnN0cnVjdGlvbnMiLAogICAgICAiVGhlIGFnZW50" + + "IHByb3ZpZGVkIGszZC1zcGVjaWZpYyBsb2NhbCBkZXZlbG9wbWVudCBndWlkYW5jZSBvciBkZWZl" + + "cnJlZCB0byB0aGUgYXBwcm9wcmlhdGUgbG9jYWwtZGV2IHNraWxsIgogICAgXQogIH0KXQpQSwcI" + + "R1VqVkpWAABKVgAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAAvAAkAZGF0YS9udmNmLXNlbGYt" + + "bWFuYWdlZC1pbnN0YWxsYXRpb24vZXhhbXBsZXMubWRVVAUAAQCmzhIjIEV4YW1wbGVzCgpXb3Jr" + + "ZWQgZXhhbXBsZXMgYmFzZWQgb24gcmVhbCBkZXBsb3ltZW50IHNjZW5hcmlvcy4KCiMjIEV4YW1w" + + "bGUgMTogT3ZlcnJpZGUgQ2Fzc2FuZHJhIFJlc291cmNlcwoKVGhlIGRlZmF1bHQgQ2Fzc2FuZHJh" + + "IHJlc291cmNlIGxpbWl0cyBjYXVzZSBPT00gb24gbGFyZ2UgaW5zdGFuY2UgdHlwZXMgKGUuZy4s" + + "IGBwNS40OHhsYXJnZWApLgoKUHJvYmxlbTogQ2Fzc2FuZHJhIHBvZHMgcmVzdGFydCB3aXRoIGBP" + + "T01LaWxsZWRgLgoKU29sdXRpb246IE92ZXJyaWRlIHJlc291cmNlcyB2aWEgaGVsbWZpbGUgcmVs" + + "ZWFzZSB2YWx1ZXMgYmxvY2suCgojIyMgU3RlcCAxOiBDYXB0dXJlIGJhc2VsaW5lCgpgYGBiYXNo" + + "CkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9Y2Fzc2FuZHJhIHRl" + + "bXBsYXRlID4gL3RtcC9jYXNzLWJlZm9yZS55YW1sCmdyZXAgLUE4ICdyZXNvdXJjZXM6JyAvdG1w" + + "L2Nhc3MtYmVmb3JlLnlhbWwgfCBoZWFkIC0xMApgYGAKCiMjIyBTdGVwIDI6IEFkZCBvdmVycmlk" + + "ZSB0byBoZWxtZmlsZS5kLzAxLWRlcGVuZGVuY2llcy55YW1sLmdvdG1wbAoKSW4gdGhlIGV4YW1w" + + "bGVzIGJlbG93LCBgPHByaXZhdGUtdmFsdWVzPmAgcmVmZXJzIHRvIHRoZSBgc2VjcmV0cy9gIGRp" + + "cmVjdG9yeSBhdCB0aGUgaGVsbWZpbGUgc3RhY2sgcm9vdC4KCmBgYHlhbWwKLSBuYW1lOiBjYXNz" + + "YW5kcmEKICB2ZXJzaW9uOiAwLjguMAogIGNvbmRpdGlvbjogY2Fzc2FuZHJhLmVuYWJsZWQKICBu" + + "YW1lc3BhY2U6IGNhc3NhbmRyYS1zeXN0ZW0KICA8PDogKmRlcGVuZGVuY3kKICB2YWx1ZXM6CiAg" + + "ICAtIC4uL2dsb2JhbC55YW1sLmdvdG1wbAogICAgLSAuLi88cHJpdmF0ZS12YWx1ZXM+L3t7IHJl" + + "cXVpcmVkRW52ICJIRUxNRklMRV9FTlYiIH19LXNlY3JldHMueWFtbAogICAgLSBjYXNzYW5kcmE6" + + "CiAgICAgICAgcmVzb3VyY2VzOgogICAgICAgICAgbGltaXRzOgogICAgICAgICAgICBjcHU6ICI4" + + "IgogICAgICAgICAgICBtZW1vcnk6IDgxOTJNaQogICAgICAgICAgcmVxdWVzdHM6CiAgICAgICAg" + + "ICAgIGNwdTogIjIiCiAgICAgICAgICAgIG1lbW9yeTogNDA5Nk1pCmBgYAoKIyMjIFN0ZXAgMzog" + + "VmVyaWZ5IGFuZCBhcHBseQoKYGBgYmFzaApIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1z" + + "ZWxlY3RvciBuYW1lPWNhc3NhbmRyYSB0ZW1wbGF0ZSA+IC90bXAvY2Fzcy1hZnRlci55YW1sCmRp" + + "ZmYgL3RtcC9jYXNzLWJlZm9yZS55YW1sIC90bXAvY2Fzcy1hZnRlci55YW1sICAjIENvbmZpcm0g" + + "cmVzb3VyY2VzIGNoYW5nZWQKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3Ig" + + "bmFtZT1jYXNzYW5kcmEgc3luYwpgYGAKCk5vdGU6IGByZXNvdXJjZVByZXNldGAgKGEgQml0bmFt" + + "aSBmZWF0dXJlKSBpcyBub3QgYXZhaWxhYmxlIGluIHRoZSBOVkNGIGNhc3NhbmRyYSB3cmFwcGVy" + + "IGNoYXJ0LiBVc2UgZXhwbGljaXQgYHJlc291cmNlc2AgaW5zdGVhZC4KCi0tLQoKIyMgRXhhbXBs" + + "ZSAyOiBEZXBsb3kgZnJvbSBOR0MgUHJpdmF0ZSBSZWdpc3RyeSB3aXRoIFB1bGwgU2VjcmV0cwoK" + + "RGVwbG95IHRoZSBOVkNGIHN0YWNrIHB1bGxpbmcgaW1hZ2VzIGRpcmVjdGx5IGZyb20gTkdDIChg" + + "bnZjci5pb2ApIGluc3RlYWQgb2YgYSBtaXJyb3JlZCByZWdpc3RyeSwgdXNpbmcgaW1hZ2UgcHVs" + + "bCBzZWNyZXRzLgoKIyMjIFN0ZXAgMTogQ29uZmlndXJlIGVudmlyb25tZW50IGZvciBOR0MKCmBg" + + "YHlhbWwKIyBlbnZpcm9ubWVudHMvPGVudj4ueWFtbApnbG9iYWw6CiAgaGVsbToKICAgIHNvdXJj" + + "ZXM6CiAgICAgIHJlZ2lzdHJ5OiBudmNyLmlvCiAgICAgIHJlcG9zaXRvcnk6IG52aWRpYS9udmNm" + + "CiAgaW1hZ2U6CiAgICByZWdpc3RyeTogbnZjci5pbwogICAgcmVwb3NpdG9yeTogbnZpZGlhL252" + + "Y2YKYGBgCgojIyMgU3RlcCAyOiBBdXRoZW50aWNhdGUgbG9jYWxseSAoZm9yIGhlbG1maWxlIGNo" + + "YXJ0IHB1bGxzKQoKYGBgYmFzaApkb2NrZXIgbG9naW4gbnZjci5pbyAtdSAnJG9hdXRodG9rZW4n" + + "IC1wICIkTkdDX0FQSV9LRVkiCmhlbG0gcmVnaXN0cnkgbG9naW4gbnZjci5pbyAtdSAnJG9hdXRo" + + "dG9rZW4nIC1wICIkTkdDX0FQSV9LRVkiCmBgYAoKIyMjIFN0ZXAgMzogQ3JlYXRlIG5hbWVzcGFj" + + "ZXMgYW5kIHB1bGwgc2VjcmV0cwoKYGBgYmFzaApleHBvcnQgTkdDX0FQSV9LRVk9Ijx5b3VyLW5n" + + "Yy1hcGkta2V5PiIKCmZvciBucyBpbiBjYXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVtIG52Y2Yg" + + "YXBpLWtleXMgZXNzIHNpcyB2YXVsdC1zeXN0ZW0gY2VydC1tYW5hZ2VyOyBkbwogIGt1YmVjdGwg" + + "LS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGNyZWF0ZSBuYW1lc3BhY2UgIiRucyIg" + + "XAogICAgLS1kcnktcnVuPWNsaWVudCAtbyB5YW1sIHwga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRy" + + "b2wtcGxhbmUtY29udGV4dD4gYXBwbHkgLWYgLQpkb25lCgpmb3IgbnMgaW4gY2Fzc2FuZHJhLXN5" + + "c3RlbSBuYXRzLXN5c3RlbSBudmNmIGFwaS1rZXlzIGVzcyBzaXMgdmF1bHQtc3lzdGVtIGNlcnQt" + + "bWFuYWdlcjsgZG8KICBrdWJlY3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBj" + + "cmVhdGUgc2VjcmV0IGRvY2tlci1yZWdpc3RyeSBudmNyLWNyZWRzIFwKICAgIC0tZG9ja2VyLXNl" + + "cnZlcj1udmNyLmlvIFwKICAgIC0tZG9ja2VyLXVzZXJuYW1lPSckb2F1dGh0b2tlbicgXAogICAg" + + "LS1kb2NrZXItcGFzc3dvcmQ9IiROR0NfQVBJX0tFWSIgXAogICAgLS1uYW1lc3BhY2U9IiRucyIg" + + "XAogICAgLS1kcnktcnVuPWNsaWVudCAtbyB5YW1sIHwga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRy" + + "b2wtcGxhbmUtY29udGV4dD4gYXBwbHkgLWYgLQpkb25lCmBgYAoKIyMjIFN0ZXAgNDogQWRkIGlt" + + "YWdlUHVsbFNlY3JldHMgdG8gaGVsbWZpbGUgcmVsZWFzZXMKCkFkZCB0aGUgY2hhcnQtc3BlY2lm" + + "aWMgYGltYWdlUHVsbFNlY3JldHNgIGtleSB0byBlYWNoIHJlbGVhc2UuIEV4YW1wbGUgZm9yIGNh" + + "c3NhbmRyYSBpbiBgaGVsbWZpbGUuZC8wMS1kZXBlbmRlbmNpZXMueWFtbC5nb3RtcGxgOgoKYGBg" + "eWFtbAotIG5hbWU6IGNhc3NhbmRyYQogIHZlcnNpb246IDAuOC4wCiAgY29uZGl0aW9uOiBjYXNz" + "YW5kcmEuZW5hYmxlZAogIG5hbWVzcGFjZTogY2Fzc2FuZHJhLXN5c3RlbQogIDw8OiAqZGVwZW5k" + "ZW5jeQogIHZhbHVlczoKICAgIC0gLi4vZ2xvYmFsLnlhbWwuZ290bXBsCiAgICAtIC4uLzxwcml2" + "YXRlLXZhbHVlcz4ve3sgcmVxdWlyZWRFbnYgIkhFTE1GSUxFX0VOViIgfX0tc2VjcmV0cy55YW1s" + - "CiAgICAtIGNhc3NhbmRyYToKICAgICAgICByZXNvdXJjZXM6CiAgICAgICAgICBsaW1pdHM6CiAg" + - "ICAgICAgICAgIGNwdTogIjgiCiAgICAgICAgICAgIG1lbW9yeTogODE5Mk1pCiAgICAgICAgICBy" + - "ZXF1ZXN0czoKICAgICAgICAgICAgY3B1OiAiMiIKICAgICAgICAgICAgbWVtb3J5OiA0MDk2TWkK" + - "YGBgCgojIyMgU3RlcCAzOiBWZXJpZnkgYW5kIGFwcGx5CgpgYGBiYXNoCkhFTE1GSUxFX0VOVj08" + - "ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9Y2Fzc2FuZHJhIHRlbXBsYXRlID4gL3RtcC9j" + - "YXNzLWFmdGVyLnlhbWwKZGlmZiAvdG1wL2Nhc3MtYmVmb3JlLnlhbWwgL3RtcC9jYXNzLWFmdGVy" + - "LnlhbWwgICMgQ29uZmlybSByZXNvdXJjZXMgY2hhbmdlZApIRUxNRklMRV9FTlY9PGVudj4gaGVs" + - "bWZpbGUgLS1zZWxlY3RvciBuYW1lPWNhc3NhbmRyYSBzeW5jCmBgYAoKTm90ZTogYHJlc291cmNl" + - "UHJlc2V0YCAoYSBCaXRuYW1pIGZlYXR1cmUpIGlzIG5vdCBhdmFpbGFibGUgaW4gdGhlIE5WQ0Yg" + - "Y2Fzc2FuZHJhIHdyYXBwZXIgY2hhcnQuIFVzZSBleHBsaWNpdCBgcmVzb3VyY2VzYCBpbnN0ZWFk" + - "LgoKLS0tCgojIyBFeGFtcGxlIDI6IERlcGxveSBmcm9tIE5HQyBQcml2YXRlIFJlZ2lzdHJ5IHdp" + - "dGggUHVsbCBTZWNyZXRzCgpEZXBsb3kgdGhlIE5WQ0Ygc3RhY2sgcHVsbGluZyBpbWFnZXMgZGly" + - "ZWN0bHkgZnJvbSBOR0MgKGBudmNyLmlvYCkgaW5zdGVhZCBvZiBhIG1pcnJvcmVkIHJlZ2lzdHJ5" + - "LCB1c2luZyBpbWFnZSBwdWxsIHNlY3JldHMuCgojIyMgU3RlcCAxOiBDb25maWd1cmUgZW52aXJv" + - "bm1lbnQgZm9yIE5HQwoKYGBgeWFtbAojIGVudmlyb25tZW50cy88ZW52Pi55YW1sCmdsb2JhbDoK" + - "ICBoZWxtOgogICAgc291cmNlczoKICAgICAgcmVnaXN0cnk6IG52Y3IuaW8KICAgICAgcmVwb3Np" + - "dG9yeTogbnZpZGlhL252Y2YKICBpbWFnZToKICAgIHJlZ2lzdHJ5OiBudmNyLmlvCiAgICByZXBv" + - "c2l0b3J5OiBudmlkaWEvbnZjZgpgYGAKCiMjIyBTdGVwIDI6IEF1dGhlbnRpY2F0ZSBsb2NhbGx5" + - "IChmb3IgaGVsbWZpbGUgY2hhcnQgcHVsbHMpCgpgYGBiYXNoCmRvY2tlciBsb2dpbiBudmNyLmlv" + - "IC11ICckb2F1dGh0b2tlbicgLXAgIiROR0NfQVBJX0tFWSIKaGVsbSByZWdpc3RyeSBsb2dpbiBu" + - "dmNyLmlvIC11ICckb2F1dGh0b2tlbicgLXAgIiROR0NfQVBJX0tFWSIKYGBgCgojIyMgU3RlcCAz" + - "OiBDcmVhdGUgbmFtZXNwYWNlcyBhbmQgcHVsbCBzZWNyZXRzCgpgYGBiYXNoCmV4cG9ydCBOR0Nf" + - "QVBJX0tFWT0iPHlvdXItbmdjLWFwaS1rZXk+IgoKZm9yIG5zIGluIGNhc3NhbmRyYS1zeXN0ZW0g" + - "bmF0cy1zeXN0ZW0gbnZjZiBhcGkta2V5cyBlc3Mgc2lzIHZhdWx0LXN5c3RlbSBjZXJ0LW1hbmFn" + - "ZXI7IGRvCiAga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gY3JlYXRl" + - "IG5hbWVzcGFjZSAiJG5zIiBcCiAgICAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBrdWJlY3Rs" + - "IC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBhcHBseSAtZiAtCmRvbmUKCmZvciBu" + - "cyBpbiBjYXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVtIG52Y2YgYXBpLWtleXMgZXNzIHNpcyB2" + - "YXVsdC1zeXN0ZW0gY2VydC1tYW5hZ2VyOyBkbwogIGt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9s" + - "LXBsYW5lLWNvbnRleHQ+IGNyZWF0ZSBzZWNyZXQgZG9ja2VyLXJlZ2lzdHJ5IG52Y3ItY3JlZHMg" + - "XAogICAgLS1kb2NrZXItc2VydmVyPW52Y3IuaW8gXAogICAgLS1kb2NrZXItdXNlcm5hbWU9JyRv" + - "YXV0aHRva2VuJyBcCiAgICAtLWRvY2tlci1wYXNzd29yZD0iJE5HQ19BUElfS0VZIiBcCiAgICAt" + - "LW5hbWVzcGFjZT0iJG5zIiBcCiAgICAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBrdWJlY3Rs" + - "IC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBhcHBseSAtZiAtCmRvbmUKYGBgCgoj" + - "IyMgU3RlcCA0OiBBZGQgaW1hZ2VQdWxsU2VjcmV0cyB0byBoZWxtZmlsZSByZWxlYXNlcwoKQWRk" + - "IHRoZSBjaGFydC1zcGVjaWZpYyBgaW1hZ2VQdWxsU2VjcmV0c2Aga2V5IHRvIGVhY2ggcmVsZWFz" + - "ZS4gRXhhbXBsZSBmb3IgY2Fzc2FuZHJhIGluIGBoZWxtZmlsZS5kLzAxLWRlcGVuZGVuY2llcy55" + - "YW1sLmdvdG1wbGA6CgpgYGB5YW1sCi0gbmFtZTogY2Fzc2FuZHJhCiAgdmVyc2lvbjogMC44LjAK" + - "ICBjb25kaXRpb246IGNhc3NhbmRyYS5lbmFibGVkCiAgbmFtZXNwYWNlOiBjYXNzYW5kcmEtc3lz" + - "dGVtCiAgPDw6ICpkZXBlbmRlbmN5CiAgdmFsdWVzOgogICAgLSAuLi9nbG9iYWwueWFtbC5nb3Rt" + - "cGwKICAgIC0gLi4vPHByaXZhdGUtdmFsdWVzPi97eyByZXF1aXJlZEVudiAiSEVMTUZJTEVfRU5W" + - "IiB9fS1zZWNyZXRzLnlhbWwKICAgIC0gY2Fzc2FuZHJhOgogICAgICAgIGdsb2JhbDoKICAgICAg" + - "ICAgIGltYWdlUHVsbFNlY3JldHM6CiAgICAgICAgICAgIC0gbnZjci1jcmVkcwpgYGAKClNlZSBb" + - "cmVmZXJlbmNlcy9wdWxsLXNlY3JldHMubWRdKHJlZmVyZW5jZXMvcHVsbC1zZWNyZXRzLm1kKSBm" + - "b3IgdGhlIGtleSBmb3IgZXZlcnkgY2hhcnQuCgpUaGVzZSBhcmUgY29udHJvbC1wbGFuZSBuYW1l" + - "c3BhY2VzLiBGb3IgYSBzZXBhcmF0ZSBjb21wdXRlIGNsdXN0ZXIsIGNyZWF0ZSB0aGUKc2VjcmV0" + - "IG9ubHkgaW4gYG52Y2Etb3BlcmF0b3JgOyB0aGUgY2hhcnQgYW5kIG9wZXJhdG9yIG1pcnJvciBp" + - "dCB0bwpgbnZjYS1zeXN0ZW1gLiBTZWUgW1NwbGl0IENvbXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9u" + - "XShyZWZlcmVuY2VzL2NvbXB1dGUtcGxhbmUtaW5zdGFsbGF0aW9uLm1kI3B1bGwtc2VjcmV0cyku" + - "CgojIyMgU3RlcCA1OiBEZXBsb3kKCmBgYGJhc2gKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxl" + - "IC0ta3ViZS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IHN5bmMKYGBgCgojIyMgU3Rl" + - "cCA2OiBQYXRjaCBTZXJ2aWNlQWNjb3VudHMgZm9yIGNoYXJ0cyB3aXRob3V0IG5hdGl2ZSBzdXBw" + - "b3J0CgpBZnRlciBQaGFzZSAxIChkZXBlbmRlbmNpZXMpIGNvbXBsZXRlcywgT3BlbkJhbyBwb2Rz" + - "IHdpbGwgYmUgaW4gYEltYWdlUHVsbEJhY2tPZmZgLiBQYXRjaCBhbmQgcmVzdGFydDoKCmBgYGJh" + - "c2gKZm9yIG5zIGluIHZhdWx0LXN5c3RlbSBudmNmIGVzczsgZG8KICBmb3Igc2EgaW4gJChrdWJl" + - "Y3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBnZXQgc2EgLW4gIiRucyIgXAog" + - "ICAgLS1uby1oZWFkZXJzIC1vIGN1c3RvbS1jb2x1bW5zPSI6bWV0YWRhdGEubmFtZSIpOyBkbwog" + - "ICAga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gcGF0Y2ggc2Vydmlj" + - "ZWFjY291bnQgLW4gIiRucyIgIiRzYSIgXAogICAgICAtcCAneyJpbWFnZVB1bGxTZWNyZXRzIjog" + - "W3sibmFtZSI6ICJudmNyLWNyZWRzIn1dfScKICBkb25lCmRvbmUKa3ViZWN0bCAtLWNvbnRleHQg" + - "PGNvbnRyb2wtcGxhbmUtY29udGV4dD4gZGVsZXRlIHBvZHMgLW4gdmF1bHQtc3lzdGVtIC0tYWxs" + - "CmBgYAoKVmVyaWZ5OgoKYGBgYmFzaAprdWJlY3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1j" + - "b250ZXh0PiBnZXQgZXZlbnRzIC1uIHZhdWx0LXN5c3RlbSBcCiAgLS1zb3J0LWJ5PScubGFzdFRp" + - "bWVzdGFtcCcgfCBncmVwIC1pIHB1bGwKIyBTaG91bGQgc2hvdyAiU3VjY2Vzc2Z1bGx5IHB1bGxl" + - "ZCBpbWFnZSIgZnJvbSBudmNyLmlvCmBgYAoKLS0tCgojIyBFeGFtcGxlIDM6IEZ1bGwgVGVhcmRv" + - "d24gYW5kIFJlaW5zdGFsbAoKV2hlbiBhIGRlcGxveW1lbnQgaXMgYnJva2VuIGFuZCB5b3UgbmVl" + - "ZCBhIGNsZWFuIHNsYXRlLgoKIyMjIFN0ZXAgMTogRGVzdHJveSB0aGUgY29tcHV0ZS1wbGFuZSBz" + - "dGFjawoKYGBgYmFzaAptYWtlIC1DIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIGRl" + - "c3Ryb3kgXAogIENMVVNURVJfTkFNRT08Y2x1c3Rlci1uYW1lPiBcCiAgSEVMTUZJTEVfRU5WPTxl" + - "bnY+IFwKICBLVUJFQ09ORklHX0ZJTEU9PGNvbXB1dGUtcGxhbmUta3ViZWNvbmZpZz4KYGBgCgpJ" + - "ZiBjb21wdXRlIGNsZWFudXAgaXMgc3R1Y2sgb24gZmluYWxpemVycywgdXNlIHRoZSBjb21wdXRl" + - "LWNvbnRleHQgcHJvY2VkdXJlIGluCltkZWJ1Z2dpbmcubWRdKHJlZmVyZW5jZXMvZGVidWdnaW5n" + - "Lm1kI2ZhaWx1cmUtbnZjYS1jbGVhbnVwLXN0dWNrLWZpbmFsaXplcnMpLgoKIyMjIFN0ZXAgMjog" + - "RGVyZWdpc3RlciB0aGUgY29tcHV0ZSBjbHVzdGVyCgpSZWFkIGBjbHVzdGVySURgIGFuZCBgbmNh" + - "SURgIGZyb20KYGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lL3JlZ2lzdHJhdGlvbi88" + - "Y2x1c3Rlci1uYW1lPi1yZWdpc3Rlci12YWx1ZXMueWFtbGAuClNob3cgdGhlIElEIGFuZCBnZXQg" + - "Y29uZmlybWF0aW9uIGJlZm9yZSBkZWxldGluZyB0aGUgSUNNUyByb3c6CgpgYGBiYXNoCjxudmNm" + - "LWNsaT4gLS1jb25maWcgPGNvbmZpZz4gY2x1c3RlciBkZWxldGUgXAogIC0tY2x1c3Rlci1pZCA8" + - "Y2x1c3Rlci1pZC1mcm9tLXJlZ2lzdHJhdGlvbi12YWx1ZXM+IFwKICAtLW5jYS1pZCA8bmNhLWlk" + - "PiBcCiAgLS1pZ25vcmUtbWlzc2luZwpgYGAKClJlcGVhdCBzdGVwcyAxIGFuZCAyIGZvciBldmVy" + - "eSBjb21wdXRlIGNsdXN0ZXIuCgojIyMgU3RlcCAzOiBEZXN0cm95IHRoZSBjb250cm9sLXBsYW5l" + - "IHN0YWNrCgpQcmVzZXJ2ZSB0aGUgYGNlcnQtbWFuYWdlcmAgbmFtZXNwYWNlIGJ5IGRlZmF1bHQu" + - "IE5hbWVzcGFjZSBwcmVzZXJ2YXRpb24gZG9lcwpub3QgcHJlc2VydmUgdGhlIEhlbG0gcmVsZWFz" + - "ZS4gQmVmb3JlIHJ1bm5pbmcgZGVzdHJveSwgaWRlbnRpZnkgd2hldGhlcgpjZXJ0LW1hbmFnZXIg" + - "aXMgZXh0ZXJuYWwuIEZvciBhbiBleHRlcm5hbCBpbnN0YWxsYXRpb24sIHJlcXVpcmUgZWZmZWN0" + - "aXZlCmBjZXJ0TWFuYWdlci5lbmFibGVkOiBmYWxzZWAgYW5kIGFib3J0IGlmIGl0IGlzIHRydWUu" + - "IEZvciBhbiBpbnRlbmRlZApzdGFjay1tYW5hZ2VkIHJlbGVhc2Ugd2l0aCBlZmZlY3RpdmUgYGNl" + - "cnRNYW5hZ2VyLmVuYWJsZWQ6IHRydWVgLCB2ZXJpZnkKbWF0Y2hpbmcgc3RhY2sgSGVsbSByZWxl" + - "YXNlIG1ldGFkYXRhIGFuZCBhYm9ydCBvbiBtaXNzaW5nIG9yIG1pc21hdGNoZWQKZXZpZGVuY2Uu" + - "IE9ubHkgcGxhbiBuYW1lc3BhY2UgcmVtb3ZhbCBhZnRlciB2ZXJpZnlpbmcgbmFtZXNwYWNlIHBy" + - "b3ZlbmFuY2UgYW5kCmdldHRpbmcgZXhwbGljaXQgY29uZmlybWF0aW9uOyBvdGhlcndpc2UgZG8g" + - "bm90IGRlbGV0ZSBpdC4KCmBgYGJhc2gKS1VCRUNPTkZJRz08Y29udHJvbC1wbGFuZS1rdWJlY29u" + - "ZmlnPiBcCm1ha2UgLUMgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQgZGVzdHJveSBcCiAgSEVM" + - "TUZJTEVfRU5WPTxlbnY+IFwKICBLVUJFQ09ORklHX0ZJTEU9PGNvbnRyb2wtcGxhbmUta3ViZWNv" + - "bmZpZz4KYGBgCgpQYXNzIGJvdGgga3ViZWNvbmZpZyBmb3JtcyBiZWNhdXNlIGNvbnRyb2wtcGxh" + - "bmUgbmFtZXNwYWNlIGNsZWFudXAgdXNlcwphbWJpZW50IGBrdWJlY3RsYC4KCiMjIyBTdGVwIDQ6" + - "IFZlcmlmeSBjbGVhbgoKYGBgYmFzaAprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1j" + - "b250ZXh0PiBnZXQgbnMgfCBcCiAgZ3JlcCAtRSAnKG52Y2F8bnZjZi1iYWNrZW5kfGdyb3ZlfGR5" + - "bmFtbyknCmt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGdldCBucyB8" + - "IFwKICBncmVwIC1FICcoY2Fzc2FuZHJhfG5hdHN8dmF1bHR8bnZjZnxhcGkta2V5c3xlc3N8c2lz" + - "KScKIyBCb3RoIGNvbW1hbmRzIHNob3VsZCByZXR1cm4gZW1wdHkuCmBgYAoKIyMjIFN0ZXAgNTog" + - "UmVpbnN0YWxsIGluIHNwbGl0IG9yZGVyCgpGb2xsb3cgW0NsZWFuIEluc3RhbGxhdGlvbl0oU0tJ" + - "TEwubWQjY2xlYW4taW5zdGFsbGF0aW9uKSwgdGhlbiByZXR1cm4gdG8gdGhlCnNhbWUgaGFuZG9m" + - "ZiBpbiBbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKHJlZmVyZW5jZXMvY29tcHV0" + - "ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpLgoKLS0tCgojIyBFeGFtcGxlIDQ6IFJlY292ZXIgZnJv" + - "bSBhIEdhdGV3YXkgRW5kcG9pbnQgQ2hhbmdlCgpUaGUgc2VwYXJhdGVseSBwcm92aXNpb25lZCBH" + - "YXRld2F5IG9yIGl0cyBsb2FkIGJhbGFuY2VyIHdhcyByZWNyZWF0ZWQgYW5kIGdvdCBhIG5ldyBl" + - "bmRwb2ludC4KCiMjIyBTdGVwIDE6IEdldCB0aGUgbmV3IGVuZHBvaW50CgpgYGBiYXNoCkdBVEVX" + - "QVlfQUREUj0kKGt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGdldCBn" + - "YXRld2F5IFwKICBudmNmLWdhdGV3YXkgLW4gZW52b3ktZ2F0ZXdheSBcCiAgLW8ganNvbnBhdGg9" + - "J3suc3RhdHVzLmFkZHJlc3Nlc1swXS52YWx1ZX0nKQp0ZXN0IC1uICIkR0FURVdBWV9BRERSIgpg" + - "YGAKCiMjIyBTdGVwIDI6IFVwZGF0ZSBETlMgYW5kIGRpcmVjdCBhZGRyZXNzIGZpZWxkcwoKS2Vl" + - "cCBgZ2xvYmFsLmRvbWFpbmAsIHJvdXRlIGhvc3RuYW1lcywgYW5kIENMSSBIb3N0IGZpZWxkcyB1" + - "bmNoYW5nZWQuIFBvaW50IHRoZQpETlMgcmVjb3JkcyBmb3IgcmVuZGVyZWQgcm91dGUgaG9zdG5h" + - "bWVzLCBzdWNoIGFzIGBhcGkuPGRvbWFpbj5gIGFuZApgKi5pbnZvY2F0aW9uLjxkb21haW4+YCwg" + - "dG8gYEdBVEVXQVlfQUREUmAuIEZvciBhIHRlbXBvcmFyeSBlbnZpcm9ubWVudCB3aXRob3V0CkRO" + - "Uywga2VlcCBpdHMgcmVzZXJ2ZWQgcm91dGUgc3VmZml4IGFuZCBjb25uZWN0IHRvIGBHQVRFV0FZ" + - "X0FERFJgIHdpdGggdGhlCm1hdGNoaW5nIGBIb3N0YCBoZWFkZXIuCgpGb3IgYSBzcGxpdCBkZXBs" + - "b3ltZW50IGNvbmZpZ3VyZWQgd2l0aCBkaXJlY3QgR2F0ZXdheSBhZGRyZXNzZXMsIHJlcGxhY2Ug" + - "b25seQp0aGUgYWRkcmVzcy1iZWFyaW5nIHZhbHVlczogY29udHJvbC1wbGFuZSBgbnZjZk5hdHNT" + - "ZXJ2aWNlVVJMYCwgY29tcHV0ZS1wbGFuZQpJQ01TLCBSZVZhbCwgYW5kIE5BVFMgVVJMcywgYW5k" + - "IENMSSBVUkwgZmllbGRzLiBLZWVwIHRoZWlyIGRvbWFpbiBhbmQgSG9zdApvdmVycmlkZXMgdW5j" + - "aGFuZ2VkLiBSZWZyZXNoIHJlZ2lzdHJhdGlvbiBhbmQgaW5zdGFsbGF0aW9uIHRocm91Z2ggdGhl" + - "IHNhbWUKaGFuZG9mZiB1c2VkIG9yaWdpbmFsbHkuIFNlZQpbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJ" + - "bnN0YWxsYXRpb25dKHJlZmVyZW5jZXMvY29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpCmZv" + - "ciB0aGUgZmllbGRzIGFuZCBjb21wbGV0ZSBjb21tYW5kcy4KCiMjIyBTdGVwIDM6IFZlcmlmeSBi" + - "b3RoIGNvbnRleHRzCgpgYGBiYXNoCmRpZyArc2hvcnQgImFwaS48ZG9tYWluPiIKY3VybCAtSCAi" + - "SG9zdDogYXBpLjxkb21haW4+IiAiaHR0cDovLyRHQVRFV0FZX0FERFIvaGVhbHRoIgprdWJlY3Rs" + - "IC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBnZXQgZ2F0ZXdheSBudmNmLWdhdGV3" + - "YXkgXAogIC1uIGVudm95LWdhdGV3YXkgLW8gd2lkZQprdWJlY3RsIC0tY29udGV4dCA8Y29udHJv" + - "bC1wbGFuZS1jb250ZXh0PiBnZXQgaHR0cHJvdXRlcyAtQQprdWJlY3RsIC0tY29udGV4dCA8Y29u" + - "dHJvbC1wbGFuZS1jb250ZXh0PiBnZXQgdGNwcm91dGVzIC1BCmt1YmVjdGwgLS1jb250ZXh0IDxj" + - "b21wdXRlLXBsYW5lLWNvbnRleHQ+IHJvbGxvdXQgc3RhdHVzIFwKICBkZXBsb3ltZW50L252Y2Et" + - "b3BlcmF0b3IgLW4gbnZjYS1vcGVyYXRvciAtLXRpbWVvdXQ9MTBtCmt1YmVjdGwgLS1jb250ZXh0" + - "IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IHdhaXQgXAogIG52Y2ZiYWNrZW5kLzxjb21wdXRlLXBs" + - "YW5lLWNsdXN0ZXItbmFtZT4gLW4gbnZjYS1vcGVyYXRvciBcCiAgLS1mb3I9anNvbnBhdGg9J3su" + - "c3RhdHVzLmFnZW50U3RhdHVzfSc9aGVhbHRoeSAtLXRpbWVvdXQ9MTBtCmBgYAoKLS0tCgojIyBF" + - "eGFtcGxlIDU6IERlcGxveSBPbmx5IERlcGVuZGVuY2llcwoKVXNlZnVsIGZvciB0ZXN0aW5nIG9y" + - "IHdoZW4gaXRlcmF0aW5nIG9uIHNlcnZpY2UgY29uZmlndXJhdGlvbi4KCmBgYGJhc2gKIyBEZXBs" + - "b3kganVzdCBOQVRTLCBDYXNzYW5kcmEsIE9wZW5CYW8KSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1m" + - "aWxlIC0tc2VsZWN0b3IgcmVsZWFzZS1ncm91cD1kZXBlbmRlbmNpZXMgc3luYwoKIyBDaGVjayBz" + - "dGF0dXMKa3ViZWN0bCBnZXQgcG9kcyAtbiBuYXRzLXN5c3RlbQprdWJlY3RsIGdldCBwb2RzIC1u" + - "IGNhc3NhbmRyYS1zeXN0ZW0Ka3ViZWN0bCBnZXQgcG9kcyAtbiB2YXVsdC1zeXN0ZW0KCiMgRGVw" + - "bG95IGp1c3Qgb25lIHNwZWNpZmljIHJlbGVhc2UKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxl" + - "IC0tc2VsZWN0b3IgbmFtZT1jYXNzYW5kcmEgc3luYwpgYGAKCiMjIyBTZWxlY3RvciByZWZlcmVu" + - "Y2UKCnwgU2VsZWN0b3IgfCBSZWxlYXNlcyB8CnwtLS0tLS0tLS0tfC0tLS0tLS0tLS18CnwgYHJl" + - "bGVhc2UtZ3JvdXA9ZGVwZW5kZW5jaWVzYCB8IG5hdHMsIGNhc3NhbmRyYSwgb3BlbmJhby1zZXJ2" + - "ZXIgfAp8IGByZWxlYXNlLWdyb3VwPXNlcnZpY2VzYCB8IGFwaS1rZXlzLCBzaXMsIGFwaSwgaW52" + - "b2NhdGlvbi1zZXJ2aWNlLCBncnBjLXByb3h5LCBlc3MtYXBpLCBub3Rhcnktc2VydmljZSwgcmV2" + - "YWwsIG9wdGlvbmFsIGxsbS1yZXF1ZXN0LXJvdXRlciBhbmQgbGxtLWFwaS1nYXRld2F5IHdoZW4g" + - "YGxsbS5lbmFibGVkPXRydWVgLCBvcHRpb25hbCB2YW5pdHktZ2F0ZXdheSBvbmx5IGluIHN0YWNr" + - "IHBhY2thZ2VzIHRoYXQgaW5jbHVkZSB0aGUgYWRkb24gYW5kIGhhdmUgYGFkZG9ucy52YW5pdHlH" + - "YXRld2F5LmVuYWJsZWQ9dHJ1ZWAsIG9wdGlvbmFsIG52Y2YtdWkgb25seSBpbiBzdGFjayBwYWNr" + - "YWdlcyB0aGF0IGluY2x1ZGUgdGhlIGFkZG9uIGFuZCBoYXZlIGBhZGRvbnMubnZjZlVpLmVuYWJs" + - "ZWQ9dHJ1ZWAgfAp8IGBuYW1lPWxsbS1yZXF1ZXN0LXJvdXRlcmAgfCBEZXBsb3kganVzdCB0aGUg" + - "TExNIHJlcXVlc3Qgcm91dGVyIHdoZW4gYGxsbS5lbmFibGVkPXRydWVgIHwKfCBgbmFtZT1sbG0t" + - "YXBpLWdhdGV3YXlgIHwgRGVwbG95IGp1c3QgdGhlIExMTSBBUEkgZ2F0ZXdheSB3aGVuIGBsbG0u" + - "ZW5hYmxlZD10cnVlYCB8CnwgYG5hbWU9dmFuaXR5LWdhdGV3YXlgIHwgRGVwbG95IGp1c3QgVmFu" + - "aXR5IEdhdGV3YXkgb25seSB3aGVuIHRoZSBzdGFjayBwYWNrYWdlIGluY2x1ZGVzIHRoYXQgcmVs" + - "ZWFzZSBhbmQgYGFkZG9ucy52YW5pdHlHYXRld2F5LmVuYWJsZWQ9dHJ1ZWAgfAp8IGBuYW1lPW52" + - "Y2YtdWlgIHwgRGVwbG95IE5WQ0YgVUkgb25seSB3aGVuIHRoZSBzdGFjayBwYWNrYWdlIGluY2x1" + - "ZGVzIHRoYXQgcmVsZWFzZSBhbmQgYGFkZG9ucy5udmNmVWkuZW5hYmxlZD10cnVlYCB8CnwgYHJl" + - "bGVhc2UtZ3JvdXA9aW5ncmVzc2AgfCBpbmdyZXNzIChnYXRld2F5IHJvdXRlcykgfAp8IGBuYW1l" + - "PTxyZWxlYXNlPmAgfCBBbnkgaW5kaXZpZHVhbCByZWxlYXNlIGJ5IG5hbWUgfAoKTm90ZTogYGFk" + - "bWluLWlzc3Vlci1wcm94eWAgZG9lcyBub3QgaGF2ZSBhIHJlbGVhc2UtZ3JvdXAgbGFiZWwuIFRh" + - "cmdldCBpdCB3aXRoIGAtLXNlbGVjdG9yIG5hbWU9YWRtaW4taXNzdWVyLXByb3h5YC4KUEsHCAJS" + - "TkB/KAAAfygAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAATAAJAGRhdGEvbnZjZi1zZWxmLW1h" + - "bmFnZWQtaW5zdGFsbGF0aW9uL3JlZmVyZW5jZXMvY29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24u" + - "bWRVVAUAAQCmzhIjIFNwbGl0IENvbXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9uCgpUaGUgY29udHJv" + - "bCBwbGFuZSBhbmQgY29tcHV0ZSBwbGFuZSBhcmUgc2VwYXJhdGUgc3RhY2tzLiBJbnN0YWxsIHRo" + - "ZSBjb250cm9sCnBsYW5lIGZpcnN0LCB0aGVuIHJlZ2lzdGVyIGFuZCBpbnN0YWxsIGVhY2ggY29t" + - "cHV0ZSBjbHVzdGVyLiBDaG9vc2Ugb25lIGhhbmRvZmYKYmVsb3cgYW5kIHVzZSBpdCBmb3IgdGhl" + - "IGZ1bGwgbGlmZWN5Y2xlLiBEbyBub3QgY29tYmluZSBhIENMSS1nZW5lcmF0ZWQgcHJvZmlsZQp3" + - "aXRoIHRoZSBIZWxtZmlsZSB2YWx1ZXMgZmxvdy4KCiMjIENob29zZSBhIEhhbmRvZmYKCnwgRmxv" + - "dyB8IFNvdXJjZSBvZiBjb250cm9sLXBsYW5lIGVuZHBvaW50cyB8IFJlZ2lzdHJhdGlvbiBhcnRp" + - "ZmFjdCB8CnwtLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0t" + - "LS0tLS0tLS0tLS0tLS0tLS18CnwgSGVsbWZpbGUgdmFsdWVzIHwgU2VwYXJhdGUgY29udHJvbC1w" + - "bGFuZSBhbmQgY29tcHV0ZS1wbGFuZSBlbnZpcm9ubWVudCBmaWxlcyB8IGBkZXBsb3kvc3RhY2tz" + - "L252Y2YtY29tcHV0ZS1wbGFuZS9yZWdpc3RyYXRpb24vPGNsdXN0ZXI+LXJlZ2lzdGVyLXZhbHVl" + - "cy55YW1sYCB8CnwgQ0xJIHByb2ZpbGUgfCBDTEktZ2VuZXJhdGVkIGBkZXBsb3kvc3RhY2tzL3Nl" + - "bGYtbWFuYWdlZC9vdXQvY29udHJvbC1wbGFuZS1wcm9maWxlLnlhbWxgIHwgQ0xJLWdlbmVyYXRl" + - "ZCBgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUvb3V0LzxjbHVzdGVyPi1yZWdpc3Rl" + - "ci12YWx1ZXMueWFtbGAgfAoKVGhlIENMSSBwcm9maWxlIGlzIG1hbmRhdG9yeSBmb3IgdGhlIENM" + - "SSBmbG93IGFuZCBtdXN0IG5vdCBiZSBoYW5kLWF1dGhvcmVkLgpUaGUgSGVsbWZpbGUgZmxvdyBk" + - "b2VzIG5vdCBjb25zdW1lIGEgY29udHJvbC1wbGFuZSBwcm9maWxlLgoKQ29tbWFuZHMgYmVsb3cg" + - "dXNlIG1vbm9yZXBvIHBhdGhzIGZyb20gdGhlIHJlcG9zaXRvcnkgcm9vdC4gT3BlcmF0b3JzIHVz" + - "aW5nCmV4dHJhY3RlZCBwYWNrYWdlcyBuZWVkIG1hdGNoaW5nLXZlcnNpb24gYG52Y2Ytc2VsZi1t" + - "YW5hZ2VkLXN0YWNrYCBhbmQKYG52Y2YtY29tcHV0ZS1wbGFuZS1zdGFja2AgYnVuZGxlcy4gU3Vi" + - "c3RpdHV0ZSB0aG9zZSBidW5kbGUgcm9vdHMgZm9yCmBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdl" + - "ZGAgYW5kIGBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZWAuCgojIyBIZWxtZmlsZSBW" + - "YWx1ZXMgRmxvdwoKQ3JlYXRlIGJvdGggZW52aXJvbm1lbnQgZmlsZXMgYmVmb3JlIGluc3RhbGxh" + - "dGlvbjoKCi0gYGRlcGxveS9zdGFja3Mvc2VsZi1tYW5hZ2VkL2Vudmlyb25tZW50cy88ZW52Pi55" + - "YW1sYCBmb3IgY29udHJvbC1wbGFuZQogIHJlZ2lzdHJ5LCBkb21haW4sIEdhdGV3YXksIHJvdXRl" + - "cywgYW5kIHNlcnZpY2Ugc2V0dGluZ3MuCi0gYGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBs" + - "YW5lL2Vudmlyb25tZW50cy88ZW52Pi55YW1sYCBmb3IgY29tcHV0ZS1wbGFuZQogIHJlZ2lzdHJ5" + - "LCBwdWxsIHNlY3JldHMsIGFuZCBjb21wdXRlLXJlYWNoYWJsZSBJQ01TLCBSZVZhbCwgYW5kIE5B" + - "VFMgdmFsdWVzLgoKRm9yIEVLUywgdXNlIHRoZSBjYW5vbmljYWwKW0NTUCBFbmQtdG8tRW5kIEV4" + - "YW1wbGVdKGh0dHBzOi8vZG9jcy5udmlkaWEuY29tL252Y2YvdjAuNi4wLXJjL2NzcC1lbmQtdG8t" + - "ZW5kLWV4YW1wbGUpLgpUaGUgY29udHJvbC1wbGFuZSBlbnZpcm9ubWVudCBrZWVwcyB0aGUgRW52" + - "b3kgR2F0ZXdheSBjb250cm9sbGVyIGluCmBlbnZveS1nYXRld2F5LXN5c3RlbWAsIGF0dGFjaGVz" + - "IHJvdXRlcyB0byBgR2F0ZXdheS9udmNmLWdhdGV3YXlgIGluCmBlbnZveS1nYXRld2F5YCwgYW5k" + - "IGVuYWJsZXMgdGhlIE5BVFMgcm91dGUuIFRoZSBjb21wdXRlLXBsYW5lIGVudmlyb25tZW50IHVz" + - "ZXMKdGhlIGV4dGVybmFsIGFkZHJlc3MgcGx1cyB0aGUgc2VydmljZSBob3N0IG92ZXJyaWRlcy4g" + - "SGVyZSwKYDxnYXRld2F5LWFkZHJlc3M+YCBpcyB0aGUgTkxCIGFkZHJlc3MgYW5kIGA8Z2F0ZXdh" + - "eS1kb21haW4+YCBpcyB0aGUgRE5TIGJhc2UKd2hvc2Ugc2VydmljZSBzdWJkb21haW5zIHJlc29s" + - "dmUgdG8gdGhhdCBOTEI6CgpgYGB5YW1sCiMgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQvZW52" + - "aXJvbm1lbnRzLzxlbnY+LnlhbWwKZ2xvYmFsOgogIGRvbWFpbjogIjxnYXRld2F5LWRvbWFpbj4i" + - "CiAgd29ya2VyRW5kcG9pbnRzOgogICAgbnZjZlNlcnZpY2VVUkw6ICJodHRwOi8vYXBpLjxnYXRl" + - "d2F5LWRvbWFpbj4iCiAgICBudmNmR3JwY1NlcnZpY2VVUkw6ICJodHRwOi8vd29ya2VyLWFwaS48" + - "Z2F0ZXdheS1kb21haW4+IgogICAgbnZjZk5hdHNTZXJ2aWNlVVJMOiAibmF0czovLzxnYXRld2F5" + - "LWFkZHJlc3M+OjQyMjIiCiAgICBudmN0U2VydmljZVVSTDogImh0dHA6Ly90YXNrcy48Z2F0ZXdh" + - "eS1kb21haW4+IgogICAgbnZjdEdycGNTZXJ2aWNlVVJMOiAiaHR0cDovL3dvcmtlci10YXNrcy48" + - "Z2F0ZXdheS1kb21haW4+IgogICAgaW52b2NhdGlvblNlcnZpY2VVUkw6ICJodHRwOi8vaW52b2Nh" + - "dGlvbi48Z2F0ZXdheS1kb21haW4+IgoKZ3JwY3Byb3h5OgogIG52Y2ZHcnBjU2VydmljZVVSTDog" + - "Imh0dHA6Ly9hcGkubnZjZi5zdmMuY2x1c3Rlci5sb2NhbDo5MDkwIgoKaW5ncmVzczoKICBnYXRl" + - "d2F5QXBpOgogICAgY29udHJvbGxlck5hbWVzcGFjZTogZW52b3ktZ2F0ZXdheS1zeXN0ZW0KICAg" + - "IGdhdGV3YXlzOgogICAgICBzaGFyZWQ6IHtuYW1lOiBudmNmLWdhdGV3YXksIG5hbWVzcGFjZTog" + - "ZW52b3ktZ2F0ZXdheX0KICAgICAgZ3JwYzoge25hbWU6IG52Y2YtZ2F0ZXdheSwgbmFtZXNwYWNl" + - "OiBlbnZveS1nYXRld2F5fQogICAgICBuYXRzOgogICAgICAgIG5hbWU6IG52Y2YtZ2F0ZXdheQog" + - "ICAgICAgIG5hbWVzcGFjZTogZW52b3ktZ2F0ZXdheQogICAgICAgIGxpc3RlbmVyTmFtZTogbmF0" + - "cwogICAgcm91dGVzOgogICAgICBudmNmQXBpOgogICAgICAgIGdycGM6CiAgICAgICAgICBlbmFi" + - "bGVkOiB0cnVlCiAgICAgICAgICBob3N0bmFtZXM6IFsid29ya2VyLWFwaS48Z2F0ZXdheS1kb21h" + - "aW4+Il0KICAgICAgbnZjdEFwaToKICAgICAgICBncnBjOgogICAgICAgICAgZW5hYmxlZDogdHJ1" + - "ZQogICAgICAgICAgaG9zdG5hbWVzOiBbIndvcmtlci10YXNrcy48Z2F0ZXdheS1kb21haW4+Il0K" + - "ICAgICAgbmF0czoKICAgICAgICBlbmFibGVkOiB0cnVlCgpvcGVuYmFvOgogIG1pZ3JhdGlvbnM6" + - "CiAgICBpc3N1ZXJEaXNjb3Zlcnk6CiAgICAgIGVuYWJsZWQ6IHRydWUKYGBgCgpgYGB5YW1sCiMg" + - "ZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUvZW52aXJvbm1lbnRzLzxlbnY+LnlhbWwK" + - "Z2xvYmFsOgogIG52Y2FPcGVyYXRvcjoKICAgIHNlbGZNYW5hZ2VkOgogICAgICBpY21zU2Vydmlj" + - "ZVVSTDogImh0dHA6Ly88Z2F0ZXdheS1hZGRyZXNzPiIKICAgICAgaWNtc1NlcnZpY2VIb3N0SGVh" + - "ZGVyT3ZlcnJpZGU6ICJzaXMuPGdhdGV3YXktZG9tYWluPiIKICAgICAgcmV2YWxTZXJ2aWNlVVJM" + - "OiAiaHR0cDovLzxnYXRld2F5LWFkZHJlc3M+IgogICAgICByZXZhbFNlcnZpY2VIb3N0SGVhZGVy" + - "T3ZlcnJpZGU6ICJyZXZhbC48Z2F0ZXdheS1kb21haW4+IgogICAgICBuYXRzVVJMOiAibmF0czov" + - "LzxnYXRld2F5LWFkZHJlc3M+OjQyMjIiCiAgICAgIG5hdHNIb3N0T3ZlcnJpZGU6ICJuYXRzLjxn" + - "YXRld2F5LWRvbWFpbj4iCmBgYAoKUHJldmlldyBhbmQgaW5zdGFsbCB0aGUgY29udHJvbCBwbGFu" + - "ZSBhZ2FpbnN0IGl0cyBjb250ZXh0OgoKYGBgYmFzaAptYWtlIC1DIGRlcGxveS9zdGFja3Mvc2Vs" + - "Zi1tYW5hZ2VkIHRlbXBsYXRlIFwKICBIRUxNRklMRV9FTlY9PGVudj4gXAogIEtVQkVDT05GSUdf" + - "RklMRT08Y29udHJvbC1wbGFuZS1rdWJlY29uZmlnPgoKbWFrZSAtQyBkZXBsb3kvc3RhY2tzL3Nl" + - "bGYtbWFuYWdlZCBpbnN0YWxsIFwKICBIRUxNRklMRV9FTlY9PGVudj4gXAogIEtVQkVDT05GSUdf" + - "RklMRT08Y29udHJvbC1wbGFuZS1rdWJlY29uZmlnPgpgYGAKCkJlZm9yZSByZWdpc3RlcmluZyB0" + - "aHJvdWdoIGEgYmFyZSBHYXRld2F5IGFkZHJlc3MsIGNyZWF0ZSBvciB1cGRhdGUgdGhlIENMSQpj" + - "b25maWcgcGFzc2VkIGFzIGBOVkNGX0NMSV9DT05GSUdgOgoKYGBgeWFtbApiYXNlX2h0dHBfdXJs" + - "OiAiaHR0cDovLzxnYXRld2F5LWFkZHJlc3M+IgppbnZva2VfdXJsOiAiaHR0cDovLzxnYXRld2F5" + - "LWFkZHJlc3M+IgpiYXNlX2dycGNfdXJsOiAiPGdhdGV3YXktYWRkcmVzcz46MTAwODEiCmFwaV9r" + - "ZXlzX3NlcnZpY2VfdXJsOiAiaHR0cDovLzxnYXRld2F5LWFkZHJlc3M+IgppY21zX3VybDogImh0" + - "dHA6Ly88Z2F0ZXdheS1hZGRyZXNzPiIKYXBpX2hvc3Q6ICJhcGkuPGdhdGV3YXktZG9tYWluPiIK" + - "YXBpX2tleXNfaG9zdDogImFwaS1rZXlzLjxnYXRld2F5LWRvbWFpbj4iCmludm9rZV9ob3N0OiAi" + - "aW52b2NhdGlvbi48Z2F0ZXdheS1kb21haW4+IgppY21zX2hvc3Q6ICJzaXMuPGdhdGV3YXktZG9t" + - "YWluPiIKYGBgCgpIb3N0IGZpZWxkcyBjb250YWluIGhvc3RuYW1lcyBvbmx5LCB3aXRob3V0IGEg" + - "VVJMIHNjaGVtZS4gYElDTVNfVVJMYCBtYXBzIG9ubHkKdG8gdGhlIHJlZ2lzdHJhdGlvbiBjb21t" + - "YW5kJ3MgYC0taWNtcy11cmxgOyBgaWNtc19ob3N0YCBpbiB0aGUgY29uZmlnIHN1cHBsaWVzCnRo" + - "ZSBHYXRld2F5IEhvc3QgaGVhZGVyLiBUaGVyZSBpcyBubyBgLS1pY21zLWhvc3RgIE1ha2Ugb3Ig" + - "Q0xJIGZsYWcuCgpSZWdpc3RlciBmcm9tIHRoZSBjb21wdXRlIGNvbnRleHQsIHRoZW4gaW5zdGFs" + - "bCB0aGUgY29tcHV0ZSBwbGFuZToKCmBgYGJhc2gKbWFrZSAtQyBkZXBsb3kvc3RhY2tzL252Y2Yt" + - "Y29tcHV0ZS1wbGFuZSByZWdpc3Rlci1jbHVzdGVyIFwKICBDTFVTVEVSX05BTUU9PGNsdXN0ZXIt" + - "bmFtZT4gXAogIE5DQV9JRD08bmNhLWlkPiBcCiAgQ0xVU1RFUl9SRUdJT049PHJlZ2lvbj4gXAog" + - "IElDTVNfVVJMPWh0dHA6Ly88Z2F0ZXdheS1hZGRyZXNzPiBcCiAgS1VCRUNPTkZJR19GSUxFPTxj" + - "b21wdXRlLXBsYW5lLWt1YmVjb25maWc+IFwKICBOVkNGX0NMST08cGF0aC10by1udmNmLWNsaT4g" + - "XAogIE5WQ0ZfQ0xJX0NPTkZJRz08cGF0aC10by1udmNmLWNsaS1jb25maWc+CgptYWtlIC1DIGRl" + - "cGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIGluc3RhbGwgXAogIENMVVNURVJfTkFNRT08" + - "Y2x1c3Rlci1uYW1lPiBcCiAgSEVMTUZJTEVfRU5WPTxlbnY+IFwKICBLVUJFQ09ORklHX0ZJTEU9" + - "PGNvbXB1dGUtcGxhbmUta3ViZWNvbmZpZz4KYGBgCgpSZWdpc3RyYXRpb24gZGlzY292ZXJzIHRo" + - "ZSBPSURDIGlzc3VlciBhbmQgSldLUyBmcm9tIHRoZSBjb21wdXRlIGt1YmUgY29udGV4dC4KSW4g" + - "YSBtdWx0aS1jbHVzdGVyIGRlcGxveW1lbnQsIGBLVUJFQ09ORklHX0ZJTEVgIGlzIHJlcXVpcmVk" + - "IG9uIGJvdGgKY29tcHV0ZS1wbGFuZSBjb21tYW5kcy4gSW4gYSBzYW1lLWNsdXN0ZXIgZGVwbG95" + - "bWVudCBpdCBtYXkgYmUgb21pdHRlZCBvbmx5CndoZW4gdGhlIGFtYmllbnQgY29udGV4dCBpcyBh" + - "bHJlYWR5IHRoZSB0YXJnZXQgY2x1c3Rlci4KCiMjIENMSSBQcm9maWxlIEZsb3cKClJ1biB0aGUg" + - "Q0xJIGNvbnRyb2wtcGxhbmUgaW5zdGFsbCBmaXJzdC4gSXQgY3JlYXRlcyB0aGUgcHJvZmlsZSBj" + - "b25zdW1lZCBieQpjb21wdXRlLXBsYW5lIHJlZ2lzdHJhdGlvbjoKCmBgYGJhc2gKbnZjZi1jbGkg" + + "CiAgICAtIGNhc3NhbmRyYToKICAgICAgICBnbG9iYWw6CiAgICAgICAgICBpbWFnZVB1bGxTZWNy" + + "ZXRzOgogICAgICAgICAgICAtIG52Y3ItY3JlZHMKYGBgCgpTZWUgW3JlZmVyZW5jZXMvcHVsbC1z" + + "ZWNyZXRzLm1kXShyZWZlcmVuY2VzL3B1bGwtc2VjcmV0cy5tZCkgZm9yIHRoZSBrZXkgZm9yIGV2" + + "ZXJ5IGNoYXJ0LgoKVGhlc2UgYXJlIGNvbnRyb2wtcGxhbmUgbmFtZXNwYWNlcy4gRm9yIGEgc2Vw" + + "YXJhdGUgY29tcHV0ZSBjbHVzdGVyLCBjcmVhdGUgdGhlCnNlY3JldCBvbmx5IGluIGBudmNhLW9w" + + "ZXJhdG9yYDsgdGhlIGNoYXJ0IGFuZCBvcGVyYXRvciBtaXJyb3IgaXQgdG8KYG52Y2Etc3lzdGVt" + + "YC4gU2VlIFtTcGxpdCBDb21wdXRlLVBsYW5lIEluc3RhbGxhdGlvbl0ocmVmZXJlbmNlcy9jb21w" + + "dXRlLXBsYW5lLWluc3RhbGxhdGlvbi5tZCNwdWxsLXNlY3JldHMpLgoKIyMjIFN0ZXAgNTogRGVw" + + "bG95CgpgYGBiYXNoCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLWt1YmUtY29udGV4dCA8" + + "Y29udHJvbC1wbGFuZS1jb250ZXh0PiBzeW5jCmBgYAoKIyMjIFN0ZXAgNjogUGF0Y2ggU2Vydmlj" + + "ZUFjY291bnRzIGZvciBjaGFydHMgd2l0aG91dCBuYXRpdmUgc3VwcG9ydAoKQWZ0ZXIgUGhhc2Ug" + + "MSAoZGVwZW5kZW5jaWVzKSBjb21wbGV0ZXMsIE9wZW5CYW8gcG9kcyB3aWxsIGJlIGluIGBJbWFn" + + "ZVB1bGxCYWNrT2ZmYC4gUGF0Y2ggYW5kIHJlc3RhcnQ6CgpgYGBiYXNoCmZvciBucyBpbiB2YXVs" + + "dC1zeXN0ZW0gbnZjZiBlc3M7IGRvCiAgZm9yIHNhIGluICQoa3ViZWN0bCAtLWNvbnRleHQgPGNv" + + "bnRyb2wtcGxhbmUtY29udGV4dD4gZ2V0IHNhIC1uICIkbnMiIFwKICAgIC0tbm8taGVhZGVycyAt" + + "byBjdXN0b20tY29sdW1ucz0iOm1ldGFkYXRhLm5hbWUiKTsgZG8KICAgIGt1YmVjdGwgLS1jb250" + + "ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IHBhdGNoIHNlcnZpY2VhY2NvdW50IC1uICIkbnMi" + + "ICIkc2EiIFwKICAgICAgLXAgJ3siaW1hZ2VQdWxsU2VjcmV0cyI6IFt7Im5hbWUiOiAibnZjci1j" + + "cmVkcyJ9XX0nCiAgZG9uZQpkb25lCmt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNv" + + "bnRleHQ+IGRlbGV0ZSBwb2RzIC1uIHZhdWx0LXN5c3RlbSAtLWFsbApgYGAKClZlcmlmeToKCmBg" + + "YGJhc2gKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gZ2V0IGV2ZW50" + + "cyAtbiB2YXVsdC1zeXN0ZW0gXAogIC0tc29ydC1ieT0nLmxhc3RUaW1lc3RhbXAnIHwgZ3JlcCAt" + + "aSBwdWxsCiMgU2hvdWxkIHNob3cgIlN1Y2Nlc3NmdWxseSBwdWxsZWQgaW1hZ2UiIGZyb20gbnZj" + + "ci5pbwpgYGAKCi0tLQoKIyMgRXhhbXBsZSAzOiBGdWxsIFRlYXJkb3duIGFuZCBSZWluc3RhbGwK" + + "CldoZW4gYSBkZXBsb3ltZW50IGlzIGJyb2tlbiBhbmQgeW91IG5lZWQgYSBjbGVhbiBzbGF0ZS4K" + + "CiMjIyBTdGVwIDE6IERlc3Ryb3kgdGhlIGNvbXB1dGUtcGxhbmUgc3RhY2sKCmBgYGJhc2gKbWFr" + + "ZSAtQyBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZSBkZXN0cm95IFwKICBDTFVTVEVS" + + "X05BTUU9PGNsdXN0ZXItbmFtZT4gXAogIEhFTE1GSUxFX0VOVj08ZW52PiBcCiAgS1VCRUNPTkZJ" + + "R19GSUxFPTxjb21wdXRlLXBsYW5lLWt1YmVjb25maWc+CmBgYAoKSWYgY29tcHV0ZSBjbGVhbnVw" + + "IGlzIHN0dWNrIG9uIGZpbmFsaXplcnMsIHVzZSB0aGUgY29tcHV0ZS1jb250ZXh0IHByb2NlZHVy" + + "ZSBpbgpbZGVidWdnaW5nLm1kXShyZWZlcmVuY2VzL2RlYnVnZ2luZy5tZCNmYWlsdXJlLW52Y2Et" + + "Y2xlYW51cC1zdHVjay1maW5hbGl6ZXJzKS4KCiMjIyBTdGVwIDI6IERlcmVnaXN0ZXIgdGhlIGNv" + + "bXB1dGUgY2x1c3RlcgoKUmVhZCBgY2x1c3RlcklEYCBhbmQgYG5jYUlEYCBmcm9tCmBkZXBsb3kv" + + "c3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZS9yZWdpc3RyYXRpb24vPGNsdXN0ZXItbmFtZT4tcmVn" + + "aXN0ZXItdmFsdWVzLnlhbWxgLgpTaG93IHRoZSBJRCBhbmQgZ2V0IGNvbmZpcm1hdGlvbiBiZWZv" + + "cmUgZGVsZXRpbmcgdGhlIElDTVMgcm93OgoKYGBgYmFzaAo8bnZjZi1jbGk+IC0tY29uZmlnIDxj" + + "b25maWc+IGNsdXN0ZXIgZGVsZXRlIFwKICAtLWNsdXN0ZXItaWQgPGNsdXN0ZXItaWQtZnJvbS1y" + + "ZWdpc3RyYXRpb24tdmFsdWVzPiBcCiAgLS1uY2EtaWQgPG5jYS1pZD4gXAogIC0taWdub3JlLW1p" + + "c3NpbmcKYGBgCgpSZXBlYXQgc3RlcHMgMSBhbmQgMiBmb3IgZXZlcnkgY29tcHV0ZSBjbHVzdGVy" + + "LgoKIyMjIFN0ZXAgMzogRGVzdHJveSB0aGUgY29udHJvbC1wbGFuZSBzdGFjawoKUHJlc2VydmUg" + + "dGhlIGBjZXJ0LW1hbmFnZXJgIG5hbWVzcGFjZSBieSBkZWZhdWx0LiBOYW1lc3BhY2UgcHJlc2Vy" + + "dmF0aW9uIGRvZXMKbm90IHByZXNlcnZlIHRoZSBIZWxtIHJlbGVhc2UuIEJlZm9yZSBydW5uaW5n" + + "IGRlc3Ryb3ksIGlkZW50aWZ5IHdoZXRoZXIKY2VydC1tYW5hZ2VyIGlzIGV4dGVybmFsLiBGb3Ig" + + "YW4gZXh0ZXJuYWwgaW5zdGFsbGF0aW9uLCByZXF1aXJlIGVmZmVjdGl2ZQpgY2VydE1hbmFnZXIu" + + "ZW5hYmxlZDogZmFsc2VgIGFuZCBhYm9ydCBpZiBpdCBpcyB0cnVlLiBGb3IgYW4gaW50ZW5kZWQK" + + "c3RhY2stbWFuYWdlZCByZWxlYXNlIHdpdGggZWZmZWN0aXZlIGBjZXJ0TWFuYWdlci5lbmFibGVk" + + "OiB0cnVlYCwgdmVyaWZ5Cm1hdGNoaW5nIHN0YWNrIEhlbG0gcmVsZWFzZSBtZXRhZGF0YSBhbmQg" + + "YWJvcnQgb24gbWlzc2luZyBvciBtaXNtYXRjaGVkCmV2aWRlbmNlLiBPbmx5IHBsYW4gbmFtZXNw" + + "YWNlIHJlbW92YWwgYWZ0ZXIgdmVyaWZ5aW5nIG5hbWVzcGFjZSBwcm92ZW5hbmNlIGFuZApnZXR0" + + "aW5nIGV4cGxpY2l0IGNvbmZpcm1hdGlvbjsgb3RoZXJ3aXNlIGRvIG5vdCBkZWxldGUgaXQuCgpg" + + "YGBiYXNoCktVQkVDT05GSUc9PGNvbnRyb2wtcGxhbmUta3ViZWNvbmZpZz4gXAptYWtlIC1DIGRl" + + "cGxveS9zdGFja3Mvc2VsZi1tYW5hZ2VkIGRlc3Ryb3kgXAogIEhFTE1GSUxFX0VOVj08ZW52PiBc" + + "CiAgS1VCRUNPTkZJR19GSUxFPTxjb250cm9sLXBsYW5lLWt1YmVjb25maWc+CmBgYAoKUGFzcyBi" + + "b3RoIGt1YmVjb25maWcgZm9ybXMgYmVjYXVzZSBjb250cm9sLXBsYW5lIG5hbWVzcGFjZSBjbGVh" + + "bnVwIHVzZXMKYW1iaWVudCBga3ViZWN0bGAuCgojIyMgU3RlcCA0OiBWZXJpZnkgY2xlYW4KCmBg" + + "YGJhc2gKa3ViZWN0bCAtLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gZ2V0IG5zIHwg" + + "XAogIGdyZXAgLUUgJyhudmNhfG52Y2YtYmFja2VuZHxncm92ZXxkeW5hbW8pJwprdWJlY3RsIC0t" + + "Y29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBnZXQgbnMgfCBcCiAgZ3JlcCAtRSAnKGNh" + + "c3NhbmRyYXxuYXRzfHZhdWx0fG52Y2Z8YXBpLWtleXN8ZXNzfHNpcyknCiMgQm90aCBjb21tYW5k" + + "cyBzaG91bGQgcmV0dXJuIGVtcHR5LgpgYGAKCiMjIyBTdGVwIDU6IFJlaW5zdGFsbCBpbiBzcGxp" + + "dCBvcmRlcgoKRm9sbG93IFtDbGVhbiBJbnN0YWxsYXRpb25dKFNLSUxMLm1kI2NsZWFuLWluc3Rh" + + "bGxhdGlvbiksIHRoZW4gcmV0dXJuIHRvIHRoZQpzYW1lIGhhbmRvZmYgaW4gW1NwbGl0IENvbXB1" + + "dGUtUGxhbmUgSW5zdGFsbGF0aW9uXShyZWZlcmVuY2VzL2NvbXB1dGUtcGxhbmUtaW5zdGFsbGF0" + + "aW9uLm1kKS4KCi0tLQoKIyMgRXhhbXBsZSA0OiBSZWNvdmVyIGZyb20gYSBHYXRld2F5IEVuZHBv" + + "aW50IENoYW5nZQoKVGhlIHNlcGFyYXRlbHkgcHJvdmlzaW9uZWQgR2F0ZXdheSBvciBpdHMgbG9h" + + "ZCBiYWxhbmNlciB3YXMgcmVjcmVhdGVkIGFuZCBnb3QgYSBuZXcgZW5kcG9pbnQuCgojIyMgU3Rl" + + "cCAxOiBHZXQgdGhlIG5ldyBlbmRwb2ludAoKYGBgYmFzaApHQVRFV0FZX0FERFI9JChrdWJlY3Rs" + + "IC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBnZXQgZ2F0ZXdheSBcCiAgbnZjZi1n" + + "YXRld2F5IC1uIGVudm95LWdhdGV3YXkgXAogIC1vIGpzb25wYXRoPSd7LnN0YXR1cy5hZGRyZXNz" + + "ZXNbMF0udmFsdWV9JykKdGVzdCAtbiAiJEdBVEVXQVlfQUREUiIKYGBgCgojIyMgU3RlcCAyOiBV" + + "cGRhdGUgRE5TIGFuZCBkaXJlY3QgYWRkcmVzcyBmaWVsZHMKCktlZXAgYGdsb2JhbC5kb21haW5g" + + "LCByb3V0ZSBob3N0bmFtZXMsIGFuZCBDTEkgSG9zdCBmaWVsZHMgdW5jaGFuZ2VkLiBQb2ludCB0" + + "aGUKRE5TIHJlY29yZHMgZm9yIHJlbmRlcmVkIHJvdXRlIGhvc3RuYW1lcywgc3VjaCBhcyBgYXBp" + + "Ljxkb21haW4+YCBhbmQKYCouaW52b2NhdGlvbi48ZG9tYWluPmAsIHRvIGBHQVRFV0FZX0FERFJg" + + "LiBGb3IgYSB0ZW1wb3JhcnkgZW52aXJvbm1lbnQgd2l0aG91dApETlMsIGtlZXAgaXRzIHJlc2Vy" + + "dmVkIHJvdXRlIHN1ZmZpeCBhbmQgY29ubmVjdCB0byBgR0FURVdBWV9BRERSYCB3aXRoIHRoZQpt" + + "YXRjaGluZyBgSG9zdGAgaGVhZGVyLgoKRm9yIGEgc3BsaXQgZGVwbG95bWVudCBjb25maWd1cmVk" + + "IHdpdGggZGlyZWN0IEdhdGV3YXkgYWRkcmVzc2VzLCByZXBsYWNlIG9ubHkKdGhlIGFkZHJlc3Mt" + + "YmVhcmluZyB2YWx1ZXM6IGNvbnRyb2wtcGxhbmUgYG52Y2ZOYXRzU2VydmljZVVSTGAsIGNvbXB1" + + "dGUtcGxhbmUKSUNNUywgUmVWYWwsIGFuZCBOQVRTIFVSTHMsIGFuZCBDTEkgVVJMIGZpZWxkcy4g" + + "S2VlcCB0aGVpciBkb21haW4gYW5kIEhvc3QKb3ZlcnJpZGVzIHVuY2hhbmdlZC4gUmVmcmVzaCBy" + + "ZWdpc3RyYXRpb24gYW5kIGluc3RhbGxhdGlvbiB0aHJvdWdoIHRoZSBzYW1lCmhhbmRvZmYgdXNl" + + "ZCBvcmlnaW5hbGx5LiBTZWUKW1NwbGl0IENvbXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9uXShyZWZl" + + "cmVuY2VzL2NvbXB1dGUtcGxhbmUtaW5zdGFsbGF0aW9uLm1kKQpmb3IgdGhlIGZpZWxkcyBhbmQg" + + "Y29tcGxldGUgY29tbWFuZHMuCgojIyMgU3RlcCAzOiBWZXJpZnkgYm90aCBjb250ZXh0cwoKYGBg" + + "YmFzaApkaWcgK3Nob3J0ICJhcGkuPGRvbWFpbj4iCmN1cmwgLUggIkhvc3Q6IGFwaS48ZG9tYWlu" + + "PiIgImh0dHA6Ly8kR0FURVdBWV9BRERSL2hlYWx0aCIKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRy" + + "b2wtcGxhbmUtY29udGV4dD4gZ2V0IGdhdGV3YXkgbnZjZi1nYXRld2F5IFwKICAtbiBlbnZveS1n" + + "YXRld2F5IC1vIHdpZGUKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4g" + + "Z2V0IGh0dHByb3V0ZXMgLUEKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4" + + "dD4gZ2V0IHRjcHJvdXRlcyAtQQprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250" + + "ZXh0PiByb2xsb3V0IHN0YXR1cyBcCiAgZGVwbG95bWVudC9udmNhLW9wZXJhdG9yIC1uIG52Y2Et" + + "b3BlcmF0b3IgLS10aW1lb3V0PTEwbQprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1j" + + "b250ZXh0PiB3YWl0IFwKICBudmNmYmFja2VuZC88Y29tcHV0ZS1wbGFuZS1jbHVzdGVyLW5hbWU+" + + "IC1uIG52Y2Etb3BlcmF0b3IgXAogIC0tZm9yPWpzb25wYXRoPSd7LnN0YXR1cy5hZ2VudFN0YXR1" + + "c30nPWhlYWx0aHkgLS10aW1lb3V0PTEwbQpgYGAKCi0tLQoKIyMgRXhhbXBsZSA1OiBEZXBsb3kg" + + "T25seSBEZXBlbmRlbmNpZXMKClVzZWZ1bCBmb3IgdGVzdGluZyBvciB3aGVuIGl0ZXJhdGluZyBv" + + "biBzZXJ2aWNlIGNvbmZpZ3VyYXRpb24uCgpgYGBiYXNoCiMgRGVwbG95IGp1c3QgTkFUUywgQ2Fz" + + "c2FuZHJhLCBPcGVuQmFvCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIHJl" + + "bGVhc2UtZ3JvdXA9ZGVwZW5kZW5jaWVzIHN5bmMKCiMgQ2hlY2sgc3RhdHVzCmt1YmVjdGwgZ2V0" + + "IHBvZHMgLW4gbmF0cy1zeXN0ZW0Ka3ViZWN0bCBnZXQgcG9kcyAtbiBjYXNzYW5kcmEtc3lzdGVt" + + "Cmt1YmVjdGwgZ2V0IHBvZHMgLW4gdmF1bHQtc3lzdGVtCgojIERlcGxveSBqdXN0IG9uZSBzcGVj" + + "aWZpYyByZWxlYXNlCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9" + + "Y2Fzc2FuZHJhIHN5bmMKYGBgCgojIyMgU2VsZWN0b3IgcmVmZXJlbmNlCgp8IFNlbGVjdG9yIHwg" + + "UmVsZWFzZXMgfAp8LS0tLS0tLS0tLXwtLS0tLS0tLS0tfAp8IGByZWxlYXNlLWdyb3VwPWRlcGVu" + + "ZGVuY2llc2AgfCBuYXRzLCBjYXNzYW5kcmEsIG9wZW5iYW8tc2VydmVyIHwKfCBgcmVsZWFzZS1n" + + "cm91cD1zZXJ2aWNlc2AgfCBhcGkta2V5cywgc2lzLCBhcGksIGludm9jYXRpb24tc2VydmljZSwg" + + "Z3JwYy1wcm94eSwgZXNzLWFwaSwgbm90YXJ5LXNlcnZpY2UsIHJldmFsLCBvcHRpb25hbCBsbG0t" + + "cmVxdWVzdC1yb3V0ZXIgYW5kIGxsbS1hcGktZ2F0ZXdheSB3aGVuIGBsbG0uZW5hYmxlZD10cnVl" + + "YCwgb3B0aW9uYWwgdmFuaXR5LWdhdGV3YXkgb25seSBpbiBzdGFjayBwYWNrYWdlcyB0aGF0IGlu" + + "Y2x1ZGUgdGhlIGFkZG9uIGFuZCBoYXZlIGBhZGRvbnMudmFuaXR5R2F0ZXdheS5lbmFibGVkPXRy" + + "dWVgLCBvcHRpb25hbCBudmNmLXVpIG9ubHkgaW4gc3RhY2sgcGFja2FnZXMgdGhhdCBpbmNsdWRl" + + "IHRoZSBhZGRvbiBhbmQgaGF2ZSBgYWRkb25zLm52Y2ZVaS5lbmFibGVkPXRydWVgIHwKfCBgbmFt" + + "ZT1sbG0tcmVxdWVzdC1yb3V0ZXJgIHwgRGVwbG95IGp1c3QgdGhlIExMTSByZXF1ZXN0IHJvdXRl" + + "ciB3aGVuIGBsbG0uZW5hYmxlZD10cnVlYCB8CnwgYG5hbWU9bGxtLWFwaS1nYXRld2F5YCB8IERl" + + "cGxveSBqdXN0IHRoZSBMTE0gQVBJIGdhdGV3YXkgd2hlbiBgbGxtLmVuYWJsZWQ9dHJ1ZWAgfAp8" + + "IGBuYW1lPXZhbml0eS1nYXRld2F5YCB8IERlcGxveSBqdXN0IFZhbml0eSBHYXRld2F5IG9ubHkg" + + "d2hlbiB0aGUgc3RhY2sgcGFja2FnZSBpbmNsdWRlcyB0aGF0IHJlbGVhc2UgYW5kIGBhZGRvbnMu" + + "dmFuaXR5R2F0ZXdheS5lbmFibGVkPXRydWVgIHwKfCBgbmFtZT1udmNmLXVpYCB8IERlcGxveSBO" + + "VkNGIFVJIG9ubHkgd2hlbiB0aGUgc3RhY2sgcGFja2FnZSBpbmNsdWRlcyB0aGF0IHJlbGVhc2Ug" + + "YW5kIGBhZGRvbnMubnZjZlVpLmVuYWJsZWQ9dHJ1ZWAgfAp8IGByZWxlYXNlLWdyb3VwPWluZ3Jl" + + "c3NgIHwgaW5ncmVzcyAoZ2F0ZXdheSByb3V0ZXMpIHwKfCBgbmFtZT08cmVsZWFzZT5gIHwgQW55" + + "IGluZGl2aWR1YWwgcmVsZWFzZSBieSBuYW1lIHwKCk5vdGU6IGBhZG1pbi1pc3N1ZXItcHJveHlg" + + "IGRvZXMgbm90IGhhdmUgYSByZWxlYXNlLWdyb3VwIGxhYmVsLiBUYXJnZXQgaXQgd2l0aCBgLS1z" + + "ZWxlY3RvciBuYW1lPWFkbWluLWlzc3Vlci1wcm94eWAuClBLBwgCUk5AfygAAH8oAABQSwMEFAAI" + + "AAAAAAAhAAAAAAAAAAAAAAAAAEwACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlv" + + "bi9yZWZlcmVuY2VzL2NvbXB1dGUtcGxhbmUtaW5zdGFsbGF0aW9uLm1kVVQFAAEAps4SIyBTcGxp" + + "dCBDb21wdXRlLVBsYW5lIEluc3RhbGxhdGlvbgoKVGhlIGNvbnRyb2wgcGxhbmUgYW5kIGNvbXB1" + + "dGUgcGxhbmUgYXJlIHNlcGFyYXRlIHN0YWNrcy4gSW5zdGFsbCB0aGUgY29udHJvbApwbGFuZSBm" + + "aXJzdCwgdGhlbiByZWdpc3RlciBhbmQgaW5zdGFsbCBlYWNoIGNvbXB1dGUgY2x1c3Rlci4gQ2hv" + + "b3NlIG9uZSBoYW5kb2ZmCmJlbG93IGFuZCB1c2UgaXQgZm9yIHRoZSBmdWxsIGxpZmVjeWNsZS4g" + + "RG8gbm90IGNvbWJpbmUgYSBDTEktZ2VuZXJhdGVkIHByb2ZpbGUKd2l0aCB0aGUgSGVsbWZpbGUg" + + "dmFsdWVzIGZsb3cuCgojIyBDaG9vc2UgYSBIYW5kb2ZmCgp8IEZsb3cgfCBTb3VyY2Ugb2YgY29u" + + "dHJvbC1wbGFuZSBlbmRwb2ludHMgfCBSZWdpc3RyYXRpb24gYXJ0aWZhY3QgfAp8LS0tLS0tfC0t" + + "LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t" + + "fAp8IEhlbG1maWxlIHZhbHVlcyB8IFNlcGFyYXRlIGNvbnRyb2wtcGxhbmUgYW5kIGNvbXB1dGUt" + + "cGxhbmUgZW52aXJvbm1lbnQgZmlsZXMgfCBgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxh" + + "bmUvcmVnaXN0cmF0aW9uLzxjbHVzdGVyPi1yZWdpc3Rlci12YWx1ZXMueWFtbGAgfAp8IENMSSBw" + + "cm9maWxlIHwgQ0xJLWdlbmVyYXRlZCBgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQvb3V0L2Nv" + + "bnRyb2wtcGxhbmUtcHJvZmlsZS55YW1sYCB8IENMSS1nZW5lcmF0ZWQgYGRlcGxveS9zdGFja3Mv" + + "bnZjZi1jb21wdXRlLXBsYW5lL291dC88Y2x1c3Rlcj4tcmVnaXN0ZXItdmFsdWVzLnlhbWxgIHwK" + + "ClRoZSBDTEkgcHJvZmlsZSBpcyBtYW5kYXRvcnkgZm9yIHRoZSBDTEkgZmxvdyBhbmQgbXVzdCBu" + + "b3QgYmUgaGFuZC1hdXRob3JlZC4KVGhlIEhlbG1maWxlIGZsb3cgZG9lcyBub3QgY29uc3VtZSBh" + + "IGNvbnRyb2wtcGxhbmUgcHJvZmlsZS4KCkNvbW1hbmRzIGJlbG93IHVzZSBtb25vcmVwbyBwYXRo" + + "cyBmcm9tIHRoZSByZXBvc2l0b3J5IHJvb3QuIE9wZXJhdG9ycyB1c2luZwpleHRyYWN0ZWQgcGFj" + + "a2FnZXMgbmVlZCBtYXRjaGluZy12ZXJzaW9uIGBudmNmLXNlbGYtbWFuYWdlZC1zdGFja2AgYW5k" + + "CmBudmNmLWNvbXB1dGUtcGxhbmUtc3RhY2tgIGJ1bmRsZXMuIFN1YnN0aXR1dGUgdGhvc2UgYnVu" + + "ZGxlIHJvb3RzIGZvcgpgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWRgIGFuZCBgZGVwbG95L3N0" + + "YWNrcy9udmNmLWNvbXB1dGUtcGxhbmVgLgoKIyMgSGVsbWZpbGUgVmFsdWVzIEZsb3cKCkNyZWF0" + + "ZSBib3RoIGVudmlyb25tZW50IGZpbGVzIGJlZm9yZSBpbnN0YWxsYXRpb246CgotIGBkZXBsb3kv" + + "c3RhY2tzL3NlbGYtbWFuYWdlZC9lbnZpcm9ubWVudHMvPGVudj4ueWFtbGAgZm9yIGNvbnRyb2wt" + + "cGxhbmUKICByZWdpc3RyeSwgZG9tYWluLCBHYXRld2F5LCByb3V0ZXMsIGFuZCBzZXJ2aWNlIHNl" + + "dHRpbmdzLgotIGBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZS9lbnZpcm9ubWVudHMv" + + "PGVudj4ueWFtbGAgZm9yIGNvbXB1dGUtcGxhbmUKICByZWdpc3RyeSwgcHVsbCBzZWNyZXRzLCBh" + + "bmQgY29tcHV0ZS1yZWFjaGFibGUgSUNNUywgUmVWYWwsIGFuZCBOQVRTIHZhbHVlcy4KCkZvciBF" + + "S1MsIHVzZSB0aGUgY2Fub25pY2FsCltDU1AgRW5kLXRvLUVuZCBFeGFtcGxlXShodHRwczovL2Rv" + + "Y3MubnZpZGlhLmNvbS9udmNmL3YwLjYuMC1yYy9jc3AtZW5kLXRvLWVuZC1leGFtcGxlKS4KVGhl" + + "IGNvbnRyb2wtcGxhbmUgZW52aXJvbm1lbnQga2VlcHMgdGhlIEVudm95IEdhdGV3YXkgY29udHJv" + + "bGxlciBpbgpgZW52b3ktZ2F0ZXdheS1zeXN0ZW1gLCBhdHRhY2hlcyByb3V0ZXMgdG8gYEdhdGV3" + + "YXkvbnZjZi1nYXRld2F5YCBpbgpgZW52b3ktZ2F0ZXdheWAsIGFuZCBlbmFibGVzIHRoZSBOQVRT" + + "IHJvdXRlLiBUaGUgY29tcHV0ZS1wbGFuZSBlbnZpcm9ubWVudCB1c2VzCnRoZSBleHRlcm5hbCBh" + + "ZGRyZXNzIHBsdXMgdGhlIHNlcnZpY2UgaG9zdCBvdmVycmlkZXMuIEhlcmUsCmA8Z2F0ZXdheS1h" + + "ZGRyZXNzPmAgaXMgdGhlIE5MQiBhZGRyZXNzIGFuZCBgPGdhdGV3YXktZG9tYWluPmAgaXMgdGhl" + + "IEROUyBiYXNlCndob3NlIHNlcnZpY2Ugc3ViZG9tYWlucyByZXNvbHZlIHRvIHRoYXQgTkxCOgoK" + + "YGBgeWFtbAojIGRlcGxveS9zdGFja3Mvc2VsZi1tYW5hZ2VkL2Vudmlyb25tZW50cy88ZW52Pi55" + + "YW1sCmdsb2JhbDoKICBkb21haW46ICI8Z2F0ZXdheS1kb21haW4+IgogIHdvcmtlckVuZHBvaW50" + + "czoKICAgIG52Y2ZTZXJ2aWNlVVJMOiAiaHR0cDovL2FwaS48Z2F0ZXdheS1kb21haW4+IgogICAg" + + "bnZjZkdycGNTZXJ2aWNlVVJMOiAiaHR0cDovL3dvcmtlci1hcGkuPGdhdGV3YXktZG9tYWluPiIK" + + "ICAgIG52Y2ZOYXRzU2VydmljZVVSTDogIm5hdHM6Ly88Z2F0ZXdheS1hZGRyZXNzPjo0MjIyIgog" + + "ICAgbnZjdFNlcnZpY2VVUkw6ICJodHRwOi8vdGFza3MuPGdhdGV3YXktZG9tYWluPiIKICAgIG52" + + "Y3RHcnBjU2VydmljZVVSTDogImh0dHA6Ly93b3JrZXItdGFza3MuPGdhdGV3YXktZG9tYWluPiIK" + + "ICAgIGludm9jYXRpb25TZXJ2aWNlVVJMOiAiaHR0cDovL2ludm9jYXRpb24uPGdhdGV3YXktZG9t" + + "YWluPiIKCmdycGNwcm94eToKICBudmNmR3JwY1NlcnZpY2VVUkw6ICJodHRwOi8vYXBpLm52Y2Yu" + + "c3ZjLmNsdXN0ZXIubG9jYWw6OTA5MCIKCmluZ3Jlc3M6CiAgZ2F0ZXdheUFwaToKICAgIGNvbnRy" + + "b2xsZXJOYW1lc3BhY2U6IGVudm95LWdhdGV3YXktc3lzdGVtCiAgICBnYXRld2F5czoKICAgICAg" + + "c2hhcmVkOiB7bmFtZTogbnZjZi1nYXRld2F5LCBuYW1lc3BhY2U6IGVudm95LWdhdGV3YXl9CiAg" + + "ICAgIGdycGM6IHtuYW1lOiBudmNmLWdhdGV3YXksIG5hbWVzcGFjZTogZW52b3ktZ2F0ZXdheX0K" + + "ICAgICAgbmF0czoKICAgICAgICBuYW1lOiBudmNmLWdhdGV3YXkKICAgICAgICBuYW1lc3BhY2U6" + + "IGVudm95LWdhdGV3YXkKICAgICAgICBsaXN0ZW5lck5hbWU6IG5hdHMKICAgIHJvdXRlczoKICAg" + + "ICAgbnZjZkFwaToKICAgICAgICBncnBjOgogICAgICAgICAgZW5hYmxlZDogdHJ1ZQogICAgICAg" + + "ICAgaG9zdG5hbWVzOiBbIndvcmtlci1hcGkuPGdhdGV3YXktZG9tYWluPiJdCiAgICAgIG52Y3RB" + + "cGk6CiAgICAgICAgZ3JwYzoKICAgICAgICAgIGVuYWJsZWQ6IHRydWUKICAgICAgICAgIGhvc3Ru" + + "YW1lczogWyJ3b3JrZXItdGFza3MuPGdhdGV3YXktZG9tYWluPiJdCiAgICAgIG5hdHM6CiAgICAg" + + "ICAgZW5hYmxlZDogdHJ1ZQoKb3BlbmJhbzoKICBtaWdyYXRpb25zOgogICAgaXNzdWVyRGlzY292" + + "ZXJ5OgogICAgICBlbmFibGVkOiB0cnVlCmBgYAoKYGBgeWFtbAojIGRlcGxveS9zdGFja3MvbnZj" + + "Zi1jb21wdXRlLXBsYW5lL2Vudmlyb25tZW50cy88ZW52Pi55YW1sCmdsb2JhbDoKICBudmNhT3Bl" + + "cmF0b3I6CiAgICBzZWxmTWFuYWdlZDoKICAgICAgaWNtc1NlcnZpY2VVUkw6ICJodHRwOi8vPGdh" + + "dGV3YXktYWRkcmVzcz4iCiAgICAgIGljbXNTZXJ2aWNlSG9zdEhlYWRlck92ZXJyaWRlOiAic2lz" + + "LjxnYXRld2F5LWRvbWFpbj4iCiAgICAgIHJldmFsU2VydmljZVVSTDogImh0dHA6Ly88Z2F0ZXdh" + + "eS1hZGRyZXNzPiIKICAgICAgcmV2YWxTZXJ2aWNlSG9zdEhlYWRlck92ZXJyaWRlOiAicmV2YWwu" + + "PGdhdGV3YXktZG9tYWluPiIKICAgICAgbmF0c1VSTDogIm5hdHM6Ly88Z2F0ZXdheS1hZGRyZXNz" + + "Pjo0MjIyIgogICAgICBuYXRzSG9zdE92ZXJyaWRlOiAibmF0cy48Z2F0ZXdheS1kb21haW4+Igpg" + + "YGAKClByZXZpZXcgYW5kIGluc3RhbGwgdGhlIGNvbnRyb2wgcGxhbmUgYWdhaW5zdCBpdHMgY29u" + + "dGV4dDoKCmBgYGJhc2gKbWFrZSAtQyBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdlZCB0ZW1wbGF0" + + "ZSBcCiAgSEVMTUZJTEVfRU5WPTxlbnY+IFwKICBLVUJFQ09ORklHX0ZJTEU9PGNvbnRyb2wtcGxh" + + "bmUta3ViZWNvbmZpZz4KCm1ha2UgLUMgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQgaW5zdGFs" + + "bCBcCiAgSEVMTUZJTEVfRU5WPTxlbnY+IFwKICBLVUJFQ09ORklHX0ZJTEU9PGNvbnRyb2wtcGxh" + + "bmUta3ViZWNvbmZpZz4KYGBgCgpCZWZvcmUgcmVnaXN0ZXJpbmcgdGhyb3VnaCBhIGJhcmUgR2F0" + + "ZXdheSBhZGRyZXNzLCBjcmVhdGUgb3IgdXBkYXRlIHRoZSBDTEkKY29uZmlnIHBhc3NlZCBhcyBg" + + "TlZDRl9DTElfQ09ORklHYDoKCmBgYHlhbWwKYmFzZV9odHRwX3VybDogImh0dHA6Ly88Z2F0ZXdh" + + "eS1hZGRyZXNzPiIKaW52b2tlX3VybDogImh0dHA6Ly88Z2F0ZXdheS1hZGRyZXNzPiIKYmFzZV9n" + + "cnBjX3VybDogIjxnYXRld2F5LWFkZHJlc3M+OjEwMDgxIgphcGlfa2V5c19zZXJ2aWNlX3VybDog" + + "Imh0dHA6Ly88Z2F0ZXdheS1hZGRyZXNzPiIKaWNtc191cmw6ICJodHRwOi8vPGdhdGV3YXktYWRk" + + "cmVzcz4iCmFwaV9ob3N0OiAiYXBpLjxnYXRld2F5LWRvbWFpbj4iCmFwaV9rZXlzX2hvc3Q6ICJh" + + "cGkta2V5cy48Z2F0ZXdheS1kb21haW4+IgppbnZva2VfaG9zdDogImludm9jYXRpb24uPGdhdGV3" + + "YXktZG9tYWluPiIKaWNtc19ob3N0OiAic2lzLjxnYXRld2F5LWRvbWFpbj4iCmBgYAoKSG9zdCBm" + + "aWVsZHMgY29udGFpbiBob3N0bmFtZXMgb25seSwgd2l0aG91dCBhIFVSTCBzY2hlbWUuIGBJQ01T" + + "X1VSTGAgbWFwcyBvbmx5CnRvIHRoZSByZWdpc3RyYXRpb24gY29tbWFuZCdzIGAtLWljbXMtdXJs" + + "YDsgYGljbXNfaG9zdGAgaW4gdGhlIGNvbmZpZyBzdXBwbGllcwp0aGUgR2F0ZXdheSBIb3N0IGhl" + + "YWRlci4gVGhlcmUgaXMgbm8gYC0taWNtcy1ob3N0YCBNYWtlIG9yIENMSSBmbGFnLgoKUmVnaXN0" + + "ZXIgZnJvbSB0aGUgY29tcHV0ZSBjb250ZXh0LCB0aGVuIGluc3RhbGwgdGhlIGNvbXB1dGUgcGxh" + + "bmU6CgpgYGBiYXNoCm1ha2UgLUMgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUgcmVn" + + "aXN0ZXItY2x1c3RlciBcCiAgQ0xVU1RFUl9OQU1FPTxjbHVzdGVyLW5hbWU+IFwKICBOQ0FfSUQ9" + + "PG5jYS1pZD4gXAogIENMVVNURVJfUkVHSU9OPTxyZWdpb24+IFwKICBJQ01TX1VSTD1odHRwOi8v" + + "PGdhdGV3YXktYWRkcmVzcz4gXAogIEtVQkVDT05GSUdfRklMRT08Y29tcHV0ZS1wbGFuZS1rdWJl" + + "Y29uZmlnPiBcCiAgTlZDRl9DTEk9PHBhdGgtdG8tbnZjZi1jbGk+IFwKICBOVkNGX0NMSV9DT05G" + + "SUc9PHBhdGgtdG8tbnZjZi1jbGktY29uZmlnPgoKbWFrZSAtQyBkZXBsb3kvc3RhY2tzL252Y2Yt" + + "Y29tcHV0ZS1wbGFuZSBpbnN0YWxsIFwKICBDTFVTVEVSX05BTUU9PGNsdXN0ZXItbmFtZT4gXAog" + + "IEhFTE1GSUxFX0VOVj08ZW52PiBcCiAgS1VCRUNPTkZJR19GSUxFPTxjb21wdXRlLXBsYW5lLWt1" + + "YmVjb25maWc+CmBgYAoKUmVnaXN0cmF0aW9uIGRpc2NvdmVycyB0aGUgT0lEQyBpc3N1ZXIgYW5k" + + "IEpXS1MgZnJvbSB0aGUgY29tcHV0ZSBrdWJlIGNvbnRleHQuCkluIGEgbXVsdGktY2x1c3RlciBk" + + "ZXBsb3ltZW50LCBgS1VCRUNPTkZJR19GSUxFYCBpcyByZXF1aXJlZCBvbiBib3RoCmNvbXB1dGUt" + + "cGxhbmUgY29tbWFuZHMuIEluIGEgc2FtZS1jbHVzdGVyIGRlcGxveW1lbnQgaXQgbWF5IGJlIG9t" + + "aXR0ZWQgb25seQp3aGVuIHRoZSBhbWJpZW50IGNvbnRleHQgaXMgYWxyZWFkeSB0aGUgdGFyZ2V0" + + "IGNsdXN0ZXIuCgojIyBDTEkgUHJvZmlsZSBGbG93CgpSdW4gdGhlIENMSSBjb250cm9sLXBsYW5l" + + "IGluc3RhbGwgZmlyc3QuIEl0IGNyZWF0ZXMgdGhlIHByb2ZpbGUgY29uc3VtZWQgYnkKY29tcHV0" + + "ZS1wbGFuZSByZWdpc3RyYXRpb246CgpgYGBiYXNoCm52Y2YtY2xpIC0tY29uZmlnIDxjb25maWc+" + + "IHNlbGYtaG9zdGVkIFwKICAtLWNvbnRyb2wtcGxhbmUtc3RhY2sgZGVwbG95L3N0YWNrcy9zZWxm" + + "LW1hbmFnZWQgXAogIC0tY29tcHV0ZS1wbGFuZS1zdGFjayBkZXBsb3kvc3RhY2tzL252Y2YtY29t" + + "cHV0ZS1wbGFuZSBcCiAgLS1lbnYgPGVudj4gXAogIC0tcGxhaW4gXAogIC0tY29udHJvbC1wbGFu" + + "ZS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IFwKICAtLWNvbXB1dGUtcGxhbmUtY29u" + + "dGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250ZXh0PiBcCiAgaW5zdGFsbCAtLWNvbnRyb2wtcGxhbmUg" + + "XAogIC0tY2x1c3Rlci1uYW1lIDxjb250cm9sLXBsYW5lLWNsdXN0ZXItbmFtZT4gXAogIC0tcmVn" + + "aW9uIDxyZWdpb24+IFwKICAtLW5jYS1pZCA8bmNhLWlkPgoKdGVzdCAtcyBkZXBsb3kvc3RhY2tz" + + "L3NlbGYtbWFuYWdlZC9vdXQvY29udHJvbC1wbGFuZS1wcm9maWxlLnlhbWwKYGBgCgpVc2UgdGhl" + + "IGZ1bGwgcGVyc2lzdGVudCBwcmVmaXggZm9yIGJvdGggY29tcHV0ZS1wbGFuZSBjb21tYW5kczoK" + + "CmBgYGJhc2gKbnZjZi1jbGkgLS1jb25maWcgPGNvbmZpZz4gc2VsZi1ob3N0ZWQgXAogIC0tY29u" + + "dHJvbC1wbGFuZS1zdGFjayBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdlZCBcCiAgLS1jb21wdXRl" + + "LXBsYW5lLXN0YWNrIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIFwKICAtLWVudiA8" + + "ZW52PiBcCiAgLS1wbGFpbiBcCiAgY29tcHV0ZS1wbGFuZSByZWdpc3RlciBcCiAgLS1jb250cm9s" + + "LXBsYW5lLXByb2ZpbGUgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQvb3V0L2NvbnRyb2wtcGxh" + + "bmUtcHJvZmlsZS55YW1sIFwKICAtLWNsdXN0ZXItbmFtZSA8Y29tcHV0ZS1wbGFuZS1jbHVzdGVy" + + "LW5hbWU+IFwKICAtLWt1YmUtY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250ZXh0PiBcCiAgLS1y" + + "ZWdpb24gPHJlZ2lvbj4gXAogIC0tb3V0cHV0IGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBs" + + "YW5lL291dC88Y29tcHV0ZS1wbGFuZS1jbHVzdGVyLW5hbWU+LXJlZ2lzdGVyLXZhbHVlcy55YW1s" + + "CgpudmNmLWNsaSAtLWNvbmZpZyA8Y29uZmlnPiBzZWxmLWhvc3RlZCBcCiAgLS1jb250cm9sLXBs" + + "YW5lLXN0YWNrIGRlcGxveS9zdGFja3Mvc2VsZi1tYW5hZ2VkIFwKICAtLWNvbXB1dGUtcGxhbmUt" + + "c3RhY2sgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUgXAogIC0tZW52IDxlbnY+IFwK" + + "ICAtLXBsYWluIFwKICBjb21wdXRlLXBsYW5lIGluc3RhbGwgXAogIC0tdmFsdWVzIGRlcGxveS9z" + + "dGFja3MvbnZjZi1jb21wdXRlLXBsYW5lL291dC88Y29tcHV0ZS1wbGFuZS1jbHVzdGVyLW5hbWU+" + + "LXJlZ2lzdGVyLXZhbHVlcy55YW1sIFwKICAtLWt1YmUtY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1j" + + "b250ZXh0PiBcCiAgLS1jbHVzdGVyLW5hbWUgPGNvbXB1dGUtcGxhbmUtY2x1c3Rlci1uYW1lPgpg" + + "YGAKClJlZ2lzdHJhdGlvbiBzZWxlY3RzIHRoZSBwcm9maWxlJ3MgaW4tY2x1c3RlciBvciBjb21w" + + "dXRlLXJlYWNoYWJsZSBlbmRwb2ludHMKZnJvbSB0aGUgY29tcHV0ZSBjb250ZXh0IGFuZCBwcm9i" + + "ZXMgaXRzIEpXS1MuIERvIG5vdCByZXBsYWNlIHByb2ZpbGUgZW5kcG9pbnRzCndpdGggaGFuZC1h" + + "dXRob3JlZCBIZWxtZmlsZSBlbmRwb2ludCB2YWx1ZXMuCgojIyBQdWxsIFNlY3JldHMKCkNyZWF0" + + "ZSB0aGUgY29udHJvbC1wbGFuZSBzZWNyZXQgaW4gdGhlc2UgbmFtZXNwYWNlcyBvbiB0aGUgY29u" + + "dHJvbC1wbGFuZQpjb250ZXh0OgoKYGBgdGV4dApjYXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVt" + + "IG52Y2YgYXBpLWtleXMgZXNzIHNpcyB2YXVsdC1zeXN0ZW0gY2VydC1tYW5hZ2VyCmBgYAoKT24g" + + "dGhlIGNvbXB1dGUgY29udGV4dCwgY3JlYXRlIHRoZSBzZWNyZXQgb25seSBpbiBgbnZjYS1vcGVy" + + "YXRvcmAgYW5kIHJlZmVyZW5jZQppdCB0aHJvdWdoIGBnbG9iYWwuaW1hZ2VQdWxsU2VjcmV0c2Ag" + + "aW4gdGhlIGNvbXB1dGUtcGxhbmUgZW52aXJvbm1lbnQuIFRoZSBjaGFydAphbmQgb3BlcmF0b3Ig" + + "dXNlIGl0IGluIGBudmNhLW9wZXJhdG9yYCBhbmQgbWlycm9yIGl0IHRvIGBudmNhLXN5c3RlbWAu" + + "IERvIG5vdCBhZGQKZWl0aGVyIG5hbWVzcGFjZSB0byB0aGUgY29udHJvbC1wbGFuZSBsaXN0LiBG" + + "b3IgY29tbWFuZHMgYW5kIHBvbGljeSBleGFtcGxlcywKc2VlIFtwdWxsLXNlY3JldHMubWRdKHB1" + + "bGwtc2VjcmV0cy5tZCkuCgojIyBWZXJpZmljYXRpb24KClVzZSB0aGUgZXhwbGljaXQgR2F0ZXdh" + + "eSBuYW1lIGFuZCBuYW1lc3BhY2U6CgpgYGBiYXNoCmt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9s" + + "LXBsYW5lLWNvbnRleHQ+IGdldCBnYXRld2F5IG52Y2YtZ2F0ZXdheSBcCiAgLW4gZW52b3ktZ2F0" + + "ZXdheSAtbyB3aWRlCmt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGdl" + + "dCB0Y3Byb3V0ZSAtbiBlbnZveS1nYXRld2F5Cmt1YmVjdGwgLS1jb250ZXh0IDxjb21wdXRlLXBs" + + "YW5lLWNvbnRleHQ+IHJvbGxvdXQgc3RhdHVzIFwKICBkZXBsb3ltZW50L252Y2Etb3BlcmF0b3Ig" + + "LW4gbnZjYS1vcGVyYXRvciAtLXRpbWVvdXQ9MTBtCmt1YmVjdGwgLS1jb250ZXh0IDxjb21wdXRl" + + "LXBsYW5lLWNvbnRleHQ+IHdhaXQgXAogIG52Y2ZiYWNrZW5kLzxjb21wdXRlLXBsYW5lLWNsdXN0" + + "ZXItbmFtZT4gLW4gbnZjYS1vcGVyYXRvciBcCiAgLS1mb3I9anNvbnBhdGg9J3suc3RhdHVzLmFn" + + "ZW50U3RhdHVzfSc9aGVhbHRoeSAtLXRpbWVvdXQ9MTBtCmt1YmVjdGwgLS1jb250ZXh0IDxjb21w" + + "dXRlLXBsYW5lLWNvbnRleHQ+IGdldCBzZWNyZXQgPHB1bGwtc2VjcmV0PiAtbiBudmNhLXN5c3Rl" + + "bQpgYGAKCiMjIFRlYXJkb3duCgpEZXN0cm95IGFuZCBkZXJlZ2lzdGVyIGV2ZXJ5IGNvbXB1dGUg" + + "cGxhbmUgYmVmb3JlIHRoZSBjb250cm9sIHBsYW5lLiBCb3RoCmhhbmRvZmZzIGNhbiBkZXN0cm95" + + "IHRoZSBjb250cm9sIHBsYW5lLCBzbyBhcHBseSB0aGlzIHByZWZsaWdodCBiZWZvcmUgZWl0aGVy" + + "Cm9uZS4gUHJlc2VydmUgdGhlIGBjZXJ0LW1hbmFnZXJgIG5hbWVzcGFjZSBieSBkZWZhdWx0LiBO" + + "YW1lc3BhY2UgcHJlc2VydmF0aW9uCmRvZXMgbm90IHByZXNlcnZlIHRoZSBIZWxtIHJlbGVhc2Uu" + + "IElkZW50aWZ5IHdoZXRoZXIgY2VydC1tYW5hZ2VyIGlzIGV4dGVybmFsLgpGb3IgYW4gZXh0ZXJu" + + "YWwgaW5zdGFsbGF0aW9uLCByZXF1aXJlIGVmZmVjdGl2ZSBgY2VydE1hbmFnZXIuZW5hYmxlZDog" + + "ZmFsc2VgCmFuZCBhYm9ydCBpZiBpdCBpcyB0cnVlLiBGb3IgYW4gaW50ZW5kZWQgc3RhY2stbWFu" + + "YWdlZCByZWxlYXNlIHdpdGggZWZmZWN0aXZlCmBjZXJ0TWFuYWdlci5lbmFibGVkOiB0cnVlYCwg" + + "dmVyaWZ5IG1hdGNoaW5nIHN0YWNrIEhlbG0gcmVsZWFzZSBtZXRhZGF0YSBhbmQKYWJvcnQgb24g" + + "bWlzc2luZyBvciBtaXNtYXRjaGVkIGV2aWRlbmNlLiBPbmx5IHBsYW4gbmFtZXNwYWNlIHJlbW92" + + "YWwgYWZ0ZXIKdmVyaWZ5aW5nIG5hbWVzcGFjZSBwcm92ZW5hbmNlIGFuZCBnZXR0aW5nIGV4cGxp" + + "Y2l0IGNvbmZpcm1hdGlvbjsgb3RoZXJ3aXNlCmRvIG5vdCBkZWxldGUgaXQuCgpGb3IgdGhlIEhl" + + "bG1maWxlIHZhbHVlcyBmbG93LCByZXRhaW4gZWFjaCByZWdpc3RyYXRpb24gdmFsdWVzIGZpbGUg" + + "dW50aWwKY2xlYW51cCBpcyB2ZXJpZmllZDoKCmBgYGJhc2gKbWFrZSAtQyBkZXBsb3kvc3RhY2tz" + + "L252Y2YtY29tcHV0ZS1wbGFuZSBkZXN0cm95IFwKICBDTFVTVEVSX05BTUU9PGNsdXN0ZXItbmFt" + + "ZT4gXAogIEhFTE1GSUxFX0VOVj08ZW52PiBcCiAgS1VCRUNPTkZJR19GSUxFPTxjb21wdXRlLXBs" + + "YW5lLWt1YmVjb25maWc+Cgo8bnZjZi1jbGk+IC0tY29uZmlnIDxjb25maWc+IGNsdXN0ZXIgZGVs" + + "ZXRlIFwKICAtLWNsdXN0ZXItaWQgPGNsdXN0ZXItaWQtZnJvbS1yZWdpc3RyYXRpb24tdmFsdWVz" + + "PiBcCiAgLS1uY2EtaWQgPG5jYS1pZD4gXAogIC0taWdub3JlLW1pc3NpbmcKYGBgCgpSZWFkIGBj" + + "bHVzdGVySURgIGFuZCBgbmNhSURgIGZyb20KYGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBs" + + "YW5lL3JlZ2lzdHJhdGlvbi88Y2x1c3Rlci1uYW1lPi1yZWdpc3Rlci12YWx1ZXMueWFtbGAuClNo" + + "b3cgdGhlIGV4YWN0IGNsdXN0ZXIgSUQgYW5kIGdldCBjb25maXJtYXRpb24gYmVmb3JlIGBjbHVz" + + "dGVyIGRlbGV0ZWAuIFJlcGVhdApjb21wdXRlIGRlc3Ryb3kgYW5kIGRlcmVnaXN0cmF0aW9uIGZv" + + "ciBldmVyeSBjb21wdXRlIGNsdXN0ZXIsIHRoZW4gZGVzdHJveSB0aGUKY29udHJvbCBwbGFuZS4K" + + "CmBgYGJhc2gKS1VCRUNPTkZJRz08Y29udHJvbC1wbGFuZS1rdWJlY29uZmlnPiBcCm1ha2UgLUMg" + + "ZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQgZGVzdHJveSBcCiAgSEVMTUZJTEVfRU5WPTxlbnY+" + + "IFwKICBLVUJFQ09ORklHX0ZJTEU9PGNvbnRyb2wtcGxhbmUta3ViZWNvbmZpZz4KYGBgCgpCb3Ro" + + "IGBLVUJFQ09ORklHYCBhbmQgYEtVQkVDT05GSUdfRklMRWAgYXJlIHJlcXVpcmVkIG9uIHRoZSBj" + + "b250cm9sLXBsYW5lCmRlc3Ryb3kgYmVjYXVzZSBpdHMgbmFtZXNwYWNlIGNsZWFudXAgdXNlcyBh" + + "bWJpZW50IGBrdWJlY3RsYC4KCkZvciB0aGUgQ0xJIHByb2ZpbGUgZmxvdywga2VlcApgZGVwbG95" + + "L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUvb3V0LzxjbHVzdGVyLW5hbWU+LXJlZ2lzdGVyLXZh" + + "bHVlcy55YW1sYAp1bnRpbCB0ZWFyZG93biBjb21wbGV0ZXMgYmVjYXVzZSBgZG93bmAgcmVhZHMg" + + "aXRzIGNsdXN0ZXIgSUQuIEZpcnN0IHF1ZXJ5IHRoZQpsaXZlIHJlZ2lzdHJhdGlvbiBzZXQgd2l0" + + "aCB0aGUgc2FtZSBjb21wbGV0ZSBwZXJzaXN0ZW50IHByZWZpeDoKCmBgYGJhc2gKbnZjZi1jbGkg" + "LS1jb25maWcgPGNvbmZpZz4gc2VsZi1ob3N0ZWQgXAogIC0tY29udHJvbC1wbGFuZS1zdGFjayBk" + "ZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdlZCBcCiAgLS1jb21wdXRlLXBsYW5lLXN0YWNrIGRlcGxv" + "eS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIFwKICAtLWVudiA8ZW52PiBcCiAgLS1wbGFpbiBc" + "CiAgLS1jb250cm9sLXBsYW5lLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gXAogIC0t" + - "Y29tcHV0ZS1wbGFuZS1jb250ZXh0IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IFwKICBpbnN0YWxs" + - "IC0tY29udHJvbC1wbGFuZSBcCiAgLS1jbHVzdGVyLW5hbWUgPGNvbnRyb2wtcGxhbmUtY2x1c3Rl" + - "ci1uYW1lPiBcCiAgLS1yZWdpb24gPHJlZ2lvbj4gXAogIC0tbmNhLWlkIDxuY2EtaWQ+Cgp0ZXN0" + - "IC1zIGRlcGxveS9zdGFja3Mvc2VsZi1tYW5hZ2VkL291dC9jb250cm9sLXBsYW5lLXByb2ZpbGUu" + - "eWFtbApgYGAKClVzZSB0aGUgZnVsbCBwZXJzaXN0ZW50IHByZWZpeCBmb3IgYm90aCBjb21wdXRl" + - "LXBsYW5lIGNvbW1hbmRzOgoKYGBgYmFzaApudmNmLWNsaSAtLWNvbmZpZyA8Y29uZmlnPiBzZWxm" + - "LWhvc3RlZCBcCiAgLS1jb250cm9sLXBsYW5lLXN0YWNrIGRlcGxveS9zdGFja3Mvc2VsZi1tYW5h" + - "Z2VkIFwKICAtLWNvbXB1dGUtcGxhbmUtc3RhY2sgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUt" + - "cGxhbmUgXAogIC0tZW52IDxlbnY+IFwKICAtLXBsYWluIFwKICBjb21wdXRlLXBsYW5lIHJlZ2lz" + - "dGVyIFwKICAtLWNvbnRyb2wtcGxhbmUtcHJvZmlsZSBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdl" + - "ZC9vdXQvY29udHJvbC1wbGFuZS1wcm9maWxlLnlhbWwgXAogIC0tY2x1c3Rlci1uYW1lIDxjb21w" + - "dXRlLXBsYW5lLWNsdXN0ZXItbmFtZT4gXAogIC0ta3ViZS1jb250ZXh0IDxjb21wdXRlLXBsYW5l" + - "LWNvbnRleHQ+IFwKICAtLXJlZ2lvbiA8cmVnaW9uPiBcCiAgLS1vdXRwdXQgZGVwbG95L3N0YWNr" + - "cy9udmNmLWNvbXB1dGUtcGxhbmUvb3V0Lzxjb21wdXRlLXBsYW5lLWNsdXN0ZXItbmFtZT4tcmVn" + - "aXN0ZXItdmFsdWVzLnlhbWwKCm52Y2YtY2xpIC0tY29uZmlnIDxjb25maWc+IHNlbGYtaG9zdGVk" + - "IFwKICAtLWNvbnRyb2wtcGxhbmUtc3RhY2sgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQgXAog" + - "IC0tY29tcHV0ZS1wbGFuZS1zdGFjayBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZSBc" + - "CiAgLS1lbnYgPGVudj4gXAogIC0tcGxhaW4gXAogIGNvbXB1dGUtcGxhbmUgaW5zdGFsbCBcCiAg" + - "LS12YWx1ZXMgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUvb3V0Lzxjb21wdXRlLXBs" + - "YW5lLWNsdXN0ZXItbmFtZT4tcmVnaXN0ZXItdmFsdWVzLnlhbWwgXAogIC0ta3ViZS1jb250ZXh0" + - "IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IFwKICAtLWNsdXN0ZXItbmFtZSA8Y29tcHV0ZS1wbGFu" + - "ZS1jbHVzdGVyLW5hbWU+CmBgYAoKUmVnaXN0cmF0aW9uIHNlbGVjdHMgdGhlIHByb2ZpbGUncyBp" + - "bi1jbHVzdGVyIG9yIGNvbXB1dGUtcmVhY2hhYmxlIGVuZHBvaW50cwpmcm9tIHRoZSBjb21wdXRl" + - "IGNvbnRleHQgYW5kIHByb2JlcyBpdHMgSldLUy4gRG8gbm90IHJlcGxhY2UgcHJvZmlsZSBlbmRw" + - "b2ludHMKd2l0aCBoYW5kLWF1dGhvcmVkIEhlbG1maWxlIGVuZHBvaW50IHZhbHVlcy4KCiMjIFB1" + - "bGwgU2VjcmV0cwoKQ3JlYXRlIHRoZSBjb250cm9sLXBsYW5lIHNlY3JldCBpbiB0aGVzZSBuYW1l" + - "c3BhY2VzIG9uIHRoZSBjb250cm9sLXBsYW5lCmNvbnRleHQ6CgpgYGB0ZXh0CmNhc3NhbmRyYS1z" + - "eXN0ZW0gbmF0cy1zeXN0ZW0gbnZjZiBhcGkta2V5cyBlc3Mgc2lzIHZhdWx0LXN5c3RlbSBjZXJ0" + - "LW1hbmFnZXIKYGBgCgpPbiB0aGUgY29tcHV0ZSBjb250ZXh0LCBjcmVhdGUgdGhlIHNlY3JldCBv" + - "bmx5IGluIGBudmNhLW9wZXJhdG9yYCBhbmQgcmVmZXJlbmNlCml0IHRocm91Z2ggYGdsb2JhbC5p" + - "bWFnZVB1bGxTZWNyZXRzYCBpbiB0aGUgY29tcHV0ZS1wbGFuZSBlbnZpcm9ubWVudC4gVGhlIGNo" + - "YXJ0CmFuZCBvcGVyYXRvciB1c2UgaXQgaW4gYG52Y2Etb3BlcmF0b3JgIGFuZCBtaXJyb3IgaXQg" + - "dG8gYG52Y2Etc3lzdGVtYC4gRG8gbm90IGFkZAplaXRoZXIgbmFtZXNwYWNlIHRvIHRoZSBjb250" + - "cm9sLXBsYW5lIGxpc3QuIEZvciBjb21tYW5kcyBhbmQgcG9saWN5IGV4YW1wbGVzLApzZWUgW3B1" + - "bGwtc2VjcmV0cy5tZF0ocHVsbC1zZWNyZXRzLm1kKS4KCiMjIFZlcmlmaWNhdGlvbgoKVXNlIHRo" + - "ZSBleHBsaWNpdCBHYXRld2F5IG5hbWUgYW5kIG5hbWVzcGFjZToKCmBgYGJhc2gKa3ViZWN0bCAt" + - "LWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gZ2V0IGdhdGV3YXkgbnZjZi1nYXRld2F5" + - "IFwKICAtbiBlbnZveS1nYXRld2F5IC1vIHdpZGUKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wt" + - "cGxhbmUtY29udGV4dD4gZ2V0IHRjcHJvdXRlIC1uIGVudm95LWdhdGV3YXkKa3ViZWN0bCAtLWNv" + - "bnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gcm9sbG91dCBzdGF0dXMgXAogIGRlcGxveW1l" + - "bnQvbnZjYS1vcGVyYXRvciAtbiBudmNhLW9wZXJhdG9yIC0tdGltZW91dD0xMG0Ka3ViZWN0bCAt" + - "LWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gd2FpdCBcCiAgbnZjZmJhY2tlbmQvPGNv" + - "bXB1dGUtcGxhbmUtY2x1c3Rlci1uYW1lPiAtbiBudmNhLW9wZXJhdG9yIFwKICAtLWZvcj1qc29u" + - "cGF0aD0ney5zdGF0dXMuYWdlbnRTdGF0dXN9Jz1oZWFsdGh5IC0tdGltZW91dD0xMG0Ka3ViZWN0" + - "bCAtLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gZ2V0IHNlY3JldCA8cHVsbC1zZWNy" + - "ZXQ+IC1uIG52Y2Etc3lzdGVtCmBgYAoKIyMgVGVhcmRvd24KCkRlc3Ryb3kgYW5kIGRlcmVnaXN0" + - "ZXIgZXZlcnkgY29tcHV0ZSBwbGFuZSBiZWZvcmUgdGhlIGNvbnRyb2wgcGxhbmUuIEJvdGgKaGFu" + - "ZG9mZnMgY2FuIGRlc3Ryb3kgdGhlIGNvbnRyb2wgcGxhbmUsIHNvIGFwcGx5IHRoaXMgcHJlZmxp" + - "Z2h0IGJlZm9yZSBlaXRoZXIKb25lLiBQcmVzZXJ2ZSB0aGUgYGNlcnQtbWFuYWdlcmAgbmFtZXNw" + - "YWNlIGJ5IGRlZmF1bHQuIE5hbWVzcGFjZSBwcmVzZXJ2YXRpb24KZG9lcyBub3QgcHJlc2VydmUg" + - "dGhlIEhlbG0gcmVsZWFzZS4gSWRlbnRpZnkgd2hldGhlciBjZXJ0LW1hbmFnZXIgaXMgZXh0ZXJu" + - "YWwuCkZvciBhbiBleHRlcm5hbCBpbnN0YWxsYXRpb24sIHJlcXVpcmUgZWZmZWN0aXZlIGBjZXJ0" + - "TWFuYWdlci5lbmFibGVkOiBmYWxzZWAKYW5kIGFib3J0IGlmIGl0IGlzIHRydWUuIEZvciBhbiBp" + - "bnRlbmRlZCBzdGFjay1tYW5hZ2VkIHJlbGVhc2Ugd2l0aCBlZmZlY3RpdmUKYGNlcnRNYW5hZ2Vy" + - "LmVuYWJsZWQ6IHRydWVgLCB2ZXJpZnkgbWF0Y2hpbmcgc3RhY2sgSGVsbSByZWxlYXNlIG1ldGFk" + - "YXRhIGFuZAphYm9ydCBvbiBtaXNzaW5nIG9yIG1pc21hdGNoZWQgZXZpZGVuY2UuIE9ubHkgcGxh" + - "biBuYW1lc3BhY2UgcmVtb3ZhbCBhZnRlcgp2ZXJpZnlpbmcgbmFtZXNwYWNlIHByb3ZlbmFuY2Ug" + - "YW5kIGdldHRpbmcgZXhwbGljaXQgY29uZmlybWF0aW9uOyBvdGhlcndpc2UKZG8gbm90IGRlbGV0" + - "ZSBpdC4KCkZvciB0aGUgSGVsbWZpbGUgdmFsdWVzIGZsb3csIHJldGFpbiBlYWNoIHJlZ2lzdHJh" + - "dGlvbiB2YWx1ZXMgZmlsZSB1bnRpbApjbGVhbnVwIGlzIHZlcmlmaWVkOgoKYGBgYmFzaAptYWtl" + - "IC1DIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5lIGRlc3Ryb3kgXAogIENMVVNURVJf" + - "TkFNRT08Y2x1c3Rlci1uYW1lPiBcCiAgSEVMTUZJTEVfRU5WPTxlbnY+IFwKICBLVUJFQ09ORklH" + - "X0ZJTEU9PGNvbXB1dGUtcGxhbmUta3ViZWNvbmZpZz4KCjxudmNmLWNsaT4gLS1jb25maWcgPGNv" + - "bmZpZz4gY2x1c3RlciBkZWxldGUgXAogIC0tY2x1c3Rlci1pZCA8Y2x1c3Rlci1pZC1mcm9tLXJl" + - "Z2lzdHJhdGlvbi12YWx1ZXM+IFwKICAtLW5jYS1pZCA8bmNhLWlkPiBcCiAgLS1pZ25vcmUtbWlz" + - "c2luZwpgYGAKClJlYWQgYGNsdXN0ZXJJRGAgYW5kIGBuY2FJRGAgZnJvbQpgZGVwbG95L3N0YWNr" + - "cy9udmNmLWNvbXB1dGUtcGxhbmUvcmVnaXN0cmF0aW9uLzxjbHVzdGVyLW5hbWU+LXJlZ2lzdGVy" + - "LXZhbHVlcy55YW1sYC4KU2hvdyB0aGUgZXhhY3QgY2x1c3RlciBJRCBhbmQgZ2V0IGNvbmZpcm1h" + - "dGlvbiBiZWZvcmUgYGNsdXN0ZXIgZGVsZXRlYC4gUmVwZWF0CmNvbXB1dGUgZGVzdHJveSBhbmQg" + - "ZGVyZWdpc3RyYXRpb24gZm9yIGV2ZXJ5IGNvbXB1dGUgY2x1c3RlciwgdGhlbiBkZXN0cm95IHRo" + - "ZQpjb250cm9sIHBsYW5lLgoKYGBgYmFzaApLVUJFQ09ORklHPTxjb250cm9sLXBsYW5lLWt1YmVj" + - "b25maWc+IFwKbWFrZSAtQyBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdlZCBkZXN0cm95IFwKICBI" + - "RUxNRklMRV9FTlY9PGVudj4gXAogIEtVQkVDT05GSUdfRklMRT08Y29udHJvbC1wbGFuZS1rdWJl" + - "Y29uZmlnPgpgYGAKCkJvdGggYEtVQkVDT05GSUdgIGFuZCBgS1VCRUNPTkZJR19GSUxFYCBhcmUg" + - "cmVxdWlyZWQgb24gdGhlIGNvbnRyb2wtcGxhbmUKZGVzdHJveSBiZWNhdXNlIGl0cyBuYW1lc3Bh" + - "Y2UgY2xlYW51cCB1c2VzIGFtYmllbnQgYGt1YmVjdGxgLgoKRm9yIHRoZSBDTEkgcHJvZmlsZSBm" + - "bG93LCBrZWVwCmBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZS9vdXQvPGNsdXN0ZXIt" + - "bmFtZT4tcmVnaXN0ZXItdmFsdWVzLnlhbWxgCnVudGlsIHRlYXJkb3duIGNvbXBsZXRlcyBiZWNh" + - "dXNlIGBkb3duYCByZWFkcyBpdHMgY2x1c3RlciBJRC4gRmlyc3QgcXVlcnkgdGhlCmxpdmUgcmVn" + - "aXN0cmF0aW9uIHNldCB3aXRoIHRoZSBzYW1lIGNvbXBsZXRlIHBlcnNpc3RlbnQgcHJlZml4OgoK" + - "YGBgYmFzaApudmNmLWNsaSAtLWNvbmZpZyA8Y29uZmlnPiBzZWxmLWhvc3RlZCBcCiAgLS1jb250" + - "cm9sLXBsYW5lLXN0YWNrIGRlcGxveS9zdGFja3Mvc2VsZi1tYW5hZ2VkIFwKICAtLWNvbXB1dGUt" + - "cGxhbmUtc3RhY2sgZGVwbG95L3N0YWNrcy9udmNmLWNvbXB1dGUtcGxhbmUgXAogIC0tZW52IDxl" + - "bnY+IFwKICAtLXBsYWluIFwKICAtLWNvbnRyb2wtcGxhbmUtY29udGV4dCA8Y29udHJvbC1wbGFu" + - "ZS1jb250ZXh0PiBcCiAgLS1jb21wdXRlLXBsYW5lLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29u" + - "dGV4dD4gXAogIC0taWNtcy11cmwgPGNvbXB1dGUtcmVhY2hhYmxlLWljbXMtdXJsPiBcCiAgc3Rh" + - "dHVzIFwKICAtLWNsdXN0ZXItbmFtZSA8Y29tcHV0ZS1wbGFuZS1jbHVzdGVyLW5hbWU+IFwKICAt" + - "LW5jYS1pZCA8bmNhLWlkPgpgYGAKClNob3cgdGhlIHJlZ2lzdGVyZWQgY29tcHV0ZS1wbGFuZSBs" + - "aXN0LiBOYW1lZC1jbHVzdGVyIGBkb3duIC0tcGxhbi1vbmx5YCBkb2VzCm5vdCBxdWVyeSBJQ01T" + - "LCBzbyBpdCBwcmV2aWV3cyBvbmx5IHRoYXQgY29tcHV0ZSBwbGFuZSBhbmQgY2Fubm90IHNob3cg" + - "dGhlCmNvbmRpdGlvbmFsIGNvbnRyb2wtcGxhbmUgcmVtb3ZhbC4gSWYgdGhlIHRhcmdldCBpcyB0" + - "aGUgbGFzdCByZWdpc3RlcmVkCmNsdXN0ZXIsIHJlYWwgYGRvd25gIGFsc28gZGVzdHJveXMgdGhl" + - "IGNvbnRyb2wgcGxhbmUuIEdldCBleHBsaWNpdCBjb25maXJtYXRpb24KZm9yIGJvdGggcmVtb3Zh" + - "bHMgYmVmb3JlIGNvbnRpbnVpbmcuIFRoZW4gcHJldmlldyBhbmQgZXhlY3V0ZSB3aXRoIHRoZSBz" + - "YW1lCnByZWZpeDoKCmBgYGJhc2gKbnZjZi1jbGkgLS1jb25maWcgPGNvbmZpZz4gc2VsZi1ob3N0" + - "ZWQgXAogIC0tY29udHJvbC1wbGFuZS1zdGFjayBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdlZCBc" + - "CiAgLS1jb21wdXRlLXBsYW5lLXN0YWNrIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBsYW5l" + - "IFwKICAtLWVudiA8ZW52PiBcCiAgLS1wbGFpbiBcCiAgLS1jb250cm9sLXBsYW5lLWNvbnRleHQg" + - "PGNvbnRyb2wtcGxhbmUtY29udGV4dD4gXAogIC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0IDxjb21w" + - "dXRlLXBsYW5lLWNvbnRleHQ+IFwKICAtLWljbXMtdXJsIDxjb21wdXRlLXJlYWNoYWJsZS1pY21z" + - "LXVybD4gXAogIGRvd24gLS1wbGFuLW9ubHkgXAogIC0tY2x1c3Rlci1uYW1lIDxjb21wdXRlLXBs" + - "YW5lLWNsdXN0ZXItbmFtZT4gXAogIC0tbmNhLWlkIDxuY2EtaWQ+CgpudmNmLWNsaSAtLWNvbmZp" + - "ZyA8Y29uZmlnPiBzZWxmLWhvc3RlZCBcCiAgLS1jb250cm9sLXBsYW5lLXN0YWNrIGRlcGxveS9z" + - "dGFja3Mvc2VsZi1tYW5hZ2VkIFwKICAtLWNvbXB1dGUtcGxhbmUtc3RhY2sgZGVwbG95L3N0YWNr" + - "cy9udmNmLWNvbXB1dGUtcGxhbmUgXAogIC0tZW52IDxlbnY+IFwKICAtLXBsYWluIFwKICAtLWNv" + - "bnRyb2wtcGxhbmUtY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBcCiAgLS1jb21wdXRl" + - "LXBsYW5lLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gXAogIC0taWNtcy11cmwgPGNv" + - "bXB1dGUtcmVhY2hhYmxlLWljbXMtdXJsPiBcCiAgZG93biBcCiAgLS1jbHVzdGVyLW5hbWUgPGNv" + - "bXB1dGUtcGxhbmUtY2x1c3Rlci1uYW1lPiBcCiAgLS1uY2EtaWQgPG5jYS1pZD4KYGBgCgpSZXBl" + - "YXQgYGRvd25gIGZvciBlYWNoIGNvbXB1dGUgY2x1c3Rlci4gRWFjaCBydW4gZGVzdHJveXMgdGhh" + - "dCBjb21wdXRlIHBsYW5lIGFuZAp1bnJlZ2lzdGVycyBpdHMgSUNNUyByb3cuIEl0IHJlbW92ZXMg" + - "dGhlIGNvbnRyb2wgcGxhbmUgb25seSBhZnRlciBubyBjbHVzdGVyCnJlZ2lzdHJhdGlvbnMgcmVt" + - "YWluLgpQSwcIlmO8WRIwAAASMAAAUEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAA7AAkAZGF0YS9u" + - "dmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNlcy9kZWJ1Z2dpbmcubWRVVAUA" + - "AQCmzhIjIERlYnVnZ2luZyBSZWZlcmVuY2UKClJlY2lwZXMgZm9yIGRpYWdub3NpbmcgYW5kIGZp" + - "eGluZyBjb21tb24gTlZDRiBzZWxmLW1hbmFnZWQgc3RhY2sgZmFpbHVyZXMuCgojIyBRdWljayBT" + - "dGF0dXMgQ29tbWFuZHMKCmBgYGJhc2gKIyBBbGwgcG9kcyBhY3Jvc3MgYWxsIG5hbWVzcGFjZXMK" + - "a3ViZWN0bCBnZXQgcG9kcyAtQSAtbyB3aWRlCgojIFBvZHMgaW4gYSBzcGVjaWZpYyBuYW1lc3Bh" + - "Y2UKa3ViZWN0bCBnZXQgcG9kcyAtbiA8bmFtZXNwYWNlPgoKIyBBbGwgaGVsbSByZWxlYXNlcwpo" + - "ZWxtIGxpc3QgLUEKCiMgUmVjZW50IGV2ZW50cyAobW9zdCB1c2VmdWwgZm9yIGRpYWdub3Npbmcg" + - "ZmFpbHVyZXMpCmt1YmVjdGwgZ2V0IGV2ZW50cyAtbiA8bmFtZXNwYWNlPiAtLXNvcnQtYnk9Jy5s" + - "YXN0VGltZXN0YW1wJwoKIyBEZXNjcmliZSBhIHNwZWNpZmljIHBvZCAoc2hvd3MgZXZlbnRzLCBj" + - "b25kaXRpb25zLCB2b2x1bWVzKQprdWJlY3RsIGRlc2NyaWJlIHBvZCAtbiA8bmFtZXNwYWNlPiA8" + - "cG9kLW5hbWU+CmBgYAoKIyMgRmFpbHVyZTogSW1hZ2VQdWxsQmFja09mZgoKIyMjIFN5bXB0b21z" + - "CgpgYGAKTkFNRSAgICAgICAgICAgUkVBRFkgICBTVEFUVVMgICAgICAgICAgICAgUkVTVEFSVFMg" + - "ICBBR0UKY2Fzc2FuZHJhLTAgICAgMC8xICAgICBJbWFnZVB1bGxCYWNrT2ZmICAgMCAgICAgICAg" + - "ICA1bQpgYGAKCkV2ZW50cyBzaG93OgpgYGAKRmFpbGVkIHRvIHB1bGwgaW1hZ2UgIm52Y3IuaW8v" + - "Li4uL2ltYWdlOnRhZyI6IDQwMSBVbmF1dGhvcml6ZWQKYGBgCgojIyMgRGlhZ25vc2lzCgpgYGBi" + - "YXNoCiMgQ2hlY2sgd2hhdCBpbWFnZSBpcyBmYWlsaW5nCmt1YmVjdGwgZGVzY3JpYmUgcG9kIC1u" + - "IDxuYW1lc3BhY2U+IDxwb2QtbmFtZT4gfCBncmVwIC1BNSAiRXZlbnRzOiIKCiMgQ2hlY2sgaWYg" + - "cHVsbCBzZWNyZXQgZXhpc3RzIGluIHRoZSBuYW1lc3BhY2UKa3ViZWN0bCBnZXQgc2VjcmV0IG52" + - "Y3ItY3JlZHMgLW4gPG5hbWVzcGFjZT4KCiMgQ2hlY2sgaWYgdGhlIHBvZCBzcGVjIGhhcyBpbWFn" + - "ZVB1bGxTZWNyZXRzCmt1YmVjdGwgZ2V0IHBvZCAtbiA8bmFtZXNwYWNlPiA8cG9kLW5hbWU+IC1v" + - "IGpzb25wYXRoPSd7LnNwZWMuaW1hZ2VQdWxsU2VjcmV0c30nCgojIENoZWNrIGlmIHRoZSBTZXJ2" + - "aWNlQWNjb3VudCBoYXMgaW1hZ2VQdWxsU2VjcmV0cwprdWJlY3RsIGdldCBzYSA8c2EtbmFtZT4g" + - "LW4gPG5hbWVzcGFjZT4gLW8ganNvbnBhdGg9J3suaW1hZ2VQdWxsU2VjcmV0c30nCmBgYAoKIyMj" + - "IEZpeGVzCgoxLiAqKlNlY3JldCBtaXNzaW5nIGluIG5hbWVzcGFjZSoqOiBDcmVhdGUgaXQKICAg" + - "YGBgYmFzaAogICBrdWJlY3RsIGNyZWF0ZSBzZWNyZXQgZG9ja2VyLXJlZ2lzdHJ5IG52Y3ItY3Jl" + - "ZHMgXAogICAgIC0tZG9ja2VyLXNlcnZlcj1udmNyLmlvIFwKICAgICAtLWRvY2tlci11c2VybmFt" + - "ZT0nJG9hdXRodG9rZW4nIFwKICAgICAtLWRvY2tlci1wYXNzd29yZD0iJE5HQ19BUElfS0VZIiBc" + - "CiAgICAgLS1uYW1lc3BhY2U9PG5hbWVzcGFjZT4gXAogICAgIC0tZHJ5LXJ1bj1jbGllbnQgLW8g" + - "eWFtbCB8IGt1YmVjdGwgYXBwbHkgLWYgLQogICBgYGAKCjIuICoqU2VjcmV0IGV4aXN0cyBidXQg" + - "cG9kIGRvZXNuJ3QgcmVmZXJlbmNlIGl0Kio6IFRoZSBjaGFydCBuZWVkcyBgaW1hZ2VQdWxsU2Vj" + - "cmV0c2AgY29uZmlndXJlZCB2aWEgaGVsbWZpbGUgdmFsdWVzLiBTZWUgW3B1bGwtc2VjcmV0cy5t" + - "ZF0ocHVsbC1zZWNyZXRzLm1kKS4KCjMuICoqQ2hhcnQgZG9lc24ndCBzdXBwb3J0IGltYWdlUHVs" + - "bFNlY3JldHMqKiAob3BlbmJhbywgaW52b2NhdGlvbi1zZXJ2aWNlLCBlc3MtYXBpLCBub3Rhcnkt" + - "c2VydmljZSk6IFBhdGNoIFNlcnZpY2VBY2NvdW50cyBhbmQgcmVzdGFydCBwb2RzLiBTZWUgW3B1" + - "bGwtc2VjcmV0cy5tZF0ocHVsbC1zZWNyZXRzLm1kKS4KCjQuICoqV3JvbmcgY3JlZGVudGlhbHMg" + - "aW4gc2VjcmV0Kio6IERlbGV0ZSBhbmQgcmVjcmVhdGUKICAgYGBgYmFzaAogICBrdWJlY3RsIGRl" + - "bGV0ZSBzZWNyZXQgbnZjci1jcmVkcyAtbiA8bmFtZXNwYWNlPgogICAjIFJlY3JlYXRlIHdpdGgg" + - "Y29ycmVjdCBjcmVkZW50aWFscwogICBgYGAKCiMjIEZhaWx1cmU6IEluaXQ6MC8xIFN0dWNrIChW" + - "YXVsdCBBZ2VudCkKCiMjIyBTeW1wdG9tcwoKU2VydmljZSBwb2RzIHN0dWNrIGluIGBJbml0OjAv" + - "MWAgZm9yIG1pbnV0ZXM6CmBgYApOQU1FICAgICAgICAgICAgICAgICAgICAgICAgUkVBRFkgICBT" + - "VEFUVVMgICAgIFJFU1RBUlRTICAgQUdFCm52Y2YtYXBpLTdmNGM3NmY3ODgtNDR2bHQgIDAvMiAg" + - "ICAgSW5pdDowLzEgICAwICAgICAgICAgIDEwbQpgYGAKCiMjIyBEaWFnbm9zaXMKClRoZSBpbml0" + - "IGNvbnRhaW5lciBpcyB0aGUgdmF1bHQtYWdlbnQtaW5pdCBpbmplY3RvciB3YWl0aW5nIGZvciBP" + - "cGVuQmFvLgoKYGBgYmFzaAojIENoZWNrIE9wZW5CYW8gcG9kcwprdWJlY3RsIGdldCBwb2RzIC1u" + - "IHZhdWx0LXN5c3RlbQoKIyBDaGVjayBpZiBPcGVuQmFvIG1pZ3JhdGlvbiBqb2IgcmFuCmt1YmVj" + - "dGwgZ2V0IGpvYnMgLW4gdmF1bHQtc3lzdGVtCgojIENoZWNrIE9wZW5CYW8gcG9kIGxvZ3MKa3Vi" + - "ZWN0bCBsb2dzIC1uIHZhdWx0LXN5c3RlbSBvcGVuYmFvLXNlcnZlci0wIC1jIG9wZW5iYW8KCiMg" + - "Q2hlY2sgaW5pdCBjb250YWluZXIgbG9ncyBvbiB0aGUgc3R1Y2sgcG9kCmt1YmVjdGwgbG9ncyAt" + - "biA8bmFtZXNwYWNlPiA8cG9kLW5hbWU+IC1jIHZhdWx0LWFnZW50LWluaXQKYGBgCgojIyMgRml4" + - "ZXMKCjEuICoqT3BlbkJhbyBwb2RzIG5vdCBydW5uaW5nKio6IENoZWNrIHRoZWlyIGV2ZW50cyBm" + - "b3IgaW1hZ2UgcHVsbCBpc3N1ZXMsIHJlc291cmNlIGlzc3VlcywgZXRjLgoKMi4gKipPcGVuQmFv" + - "IG1pZ3JhdGlvbiBqb2IgZGlkbid0IHJ1bioqOiBUaGlzIGhhcHBlbnMgd2hlbiBgaGVsbWZpbGUg" + - "c3luY2Agd2FzIGludGVycnVwdGVkLiBEZXN0cm95IGFuZCByZS1zeW5jIG9wZW5iYW86CiAgIGBg" + + "Y29tcHV0ZS1wbGFuZS1jb250ZXh0IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IFwKICAtLWljbXMt" + + "dXJsIDxjb21wdXRlLXJlYWNoYWJsZS1pY21zLXVybD4gXAogIHN0YXR1cyBcCiAgLS1jbHVzdGVy" + + "LW5hbWUgPGNvbXB1dGUtcGxhbmUtY2x1c3Rlci1uYW1lPiBcCiAgLS1uY2EtaWQgPG5jYS1pZD4K" + + "YGBgCgpTaG93IHRoZSByZWdpc3RlcmVkIGNvbXB1dGUtcGxhbmUgbGlzdC4gTmFtZWQtY2x1c3Rl" + + "ciBgZG93biAtLXBsYW4tb25seWAgZG9lcwpub3QgcXVlcnkgSUNNUywgc28gaXQgcHJldmlld3Mg" + + "b25seSB0aGF0IGNvbXB1dGUgcGxhbmUgYW5kIGNhbm5vdCBzaG93IHRoZQpjb25kaXRpb25hbCBj" + + "b250cm9sLXBsYW5lIHJlbW92YWwuIElmIHRoZSB0YXJnZXQgaXMgdGhlIGxhc3QgcmVnaXN0ZXJl" + + "ZApjbHVzdGVyLCByZWFsIGBkb3duYCBhbHNvIGRlc3Ryb3lzIHRoZSBjb250cm9sIHBsYW5lLiBH" + + "ZXQgZXhwbGljaXQgY29uZmlybWF0aW9uCmZvciBib3RoIHJlbW92YWxzIGJlZm9yZSBjb250aW51" + + "aW5nLiBUaGVuIHByZXZpZXcgYW5kIGV4ZWN1dGUgd2l0aCB0aGUgc2FtZQpwcmVmaXg6CgpgYGBi" + + "YXNoCm52Y2YtY2xpIC0tY29uZmlnIDxjb25maWc+IHNlbGYtaG9zdGVkIFwKICAtLWNvbnRyb2wt" + + "cGxhbmUtc3RhY2sgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQgXAogIC0tY29tcHV0ZS1wbGFu" + + "ZS1zdGFjayBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZSBcCiAgLS1lbnYgPGVudj4g" + + "XAogIC0tcGxhaW4gXAogIC0tY29udHJvbC1wbGFuZS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNv" + + "bnRleHQ+IFwKICAtLWNvbXB1dGUtcGxhbmUtY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250ZXh0" + + "PiBcCiAgLS1pY21zLXVybCA8Y29tcHV0ZS1yZWFjaGFibGUtaWNtcy11cmw+IFwKICBkb3duIC0t" + + "cGxhbi1vbmx5IFwKICAtLWNsdXN0ZXItbmFtZSA8Y29tcHV0ZS1wbGFuZS1jbHVzdGVyLW5hbWU+" + + "IFwKICAtLW5jYS1pZCA8bmNhLWlkPgoKbnZjZi1jbGkgLS1jb25maWcgPGNvbmZpZz4gc2VsZi1o" + + "b3N0ZWQgXAogIC0tY29udHJvbC1wbGFuZS1zdGFjayBkZXBsb3kvc3RhY2tzL3NlbGYtbWFuYWdl" + + "ZCBcCiAgLS1jb21wdXRlLXBsYW5lLXN0YWNrIGRlcGxveS9zdGFja3MvbnZjZi1jb21wdXRlLXBs" + + "YW5lIFwKICAtLWVudiA8ZW52PiBcCiAgLS1wbGFpbiBcCiAgLS1jb250cm9sLXBsYW5lLWNvbnRl" + + "eHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gXAogIC0tY29tcHV0ZS1wbGFuZS1jb250ZXh0IDxj" + + "b21wdXRlLXBsYW5lLWNvbnRleHQ+IFwKICAtLWljbXMtdXJsIDxjb21wdXRlLXJlYWNoYWJsZS1p" + + "Y21zLXVybD4gXAogIGRvd24gXAogIC0tY2x1c3Rlci1uYW1lIDxjb21wdXRlLXBsYW5lLWNsdXN0" + + "ZXItbmFtZT4gXAogIC0tbmNhLWlkIDxuY2EtaWQ+CmBgYAoKUmVwZWF0IGBkb3duYCBmb3IgZWFj" + + "aCBjb21wdXRlIGNsdXN0ZXIuIEVhY2ggcnVuIGRlc3Ryb3lzIHRoYXQgY29tcHV0ZSBwbGFuZSBh" + + "bmQKdW5yZWdpc3RlcnMgaXRzIElDTVMgcm93LiBJdCByZW1vdmVzIHRoZSBjb250cm9sIHBsYW5l" + + "IG9ubHkgYWZ0ZXIgbm8gY2x1c3RlcgpyZWdpc3RyYXRpb25zIHJlbWFpbi4KUEsHCJZjvFkSMAAA" + + "EjAAAFBLAwQUAAgAAAAAACEAAAAAAAAAAAAAAAAAOwAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQt" + + "aW5zdGFsbGF0aW9uL3JlZmVyZW5jZXMvZGVidWdnaW5nLm1kVVQFAAEAps4SIyBEZWJ1Z2dpbmcg" + + "UmVmZXJlbmNlCgpSZWNpcGVzIGZvciBkaWFnbm9zaW5nIGFuZCBmaXhpbmcgY29tbW9uIE5WQ0Yg" + + "c2VsZi1tYW5hZ2VkIHN0YWNrIGZhaWx1cmVzLgoKIyMgUXVpY2sgU3RhdHVzIENvbW1hbmRzCgpg" + + "YGBiYXNoCiMgQWxsIHBvZHMgYWNyb3NzIGFsbCBuYW1lc3BhY2VzCmt1YmVjdGwgZ2V0IHBvZHMg" + + "LUEgLW8gd2lkZQoKIyBQb2RzIGluIGEgc3BlY2lmaWMgbmFtZXNwYWNlCmt1YmVjdGwgZ2V0IHBv" + + "ZHMgLW4gPG5hbWVzcGFjZT4KCiMgQWxsIGhlbG0gcmVsZWFzZXMKaGVsbSBsaXN0IC1BCgojIFJl" + + "Y2VudCBldmVudHMgKG1vc3QgdXNlZnVsIGZvciBkaWFnbm9zaW5nIGZhaWx1cmVzKQprdWJlY3Rs" + + "IGdldCBldmVudHMgLW4gPG5hbWVzcGFjZT4gLS1zb3J0LWJ5PScubGFzdFRpbWVzdGFtcCcKCiMg" + + "RGVzY3JpYmUgYSBzcGVjaWZpYyBwb2QgKHNob3dzIGV2ZW50cywgY29uZGl0aW9ucywgdm9sdW1l" + + "cykKa3ViZWN0bCBkZXNjcmliZSBwb2QgLW4gPG5hbWVzcGFjZT4gPHBvZC1uYW1lPgpgYGAKCiMj" + + "IEZhaWx1cmU6IEltYWdlUHVsbEJhY2tPZmYKCiMjIyBTeW1wdG9tcwoKYGBgdGV4dApOQU1FICAg" + + "ICAgICAgICBSRUFEWSAgIFNUQVRVUyAgICAgICAgICAgICBSRVNUQVJUUyAgIEFHRQpjYXNzYW5k" + + "cmEtMCAgICAwLzEgICAgIEltYWdlUHVsbEJhY2tPZmYgICAwICAgICAgICAgIDVtCmBgYAoKRXZl" + + "bnRzIHNob3c6CgpgYGB0ZXh0CkZhaWxlZCB0byBwdWxsIGltYWdlICJudmNyLmlvLy4uLi9pbWFn" + + "ZTp0YWciOiA0MDEgVW5hdXRob3JpemVkCmBgYAoKIyMjIERpYWdub3NpcwoKYGBgYmFzaAojIENo" + + "ZWNrIHdoYXQgaW1hZ2UgaXMgZmFpbGluZwprdWJlY3RsIGRlc2NyaWJlIHBvZCAtbiA8bmFtZXNw" + + "YWNlPiA8cG9kLW5hbWU+IHwgZ3JlcCAtQTUgIkV2ZW50czoiCgojIENoZWNrIGlmIHB1bGwgc2Vj" + + "cmV0IGV4aXN0cyBpbiB0aGUgbmFtZXNwYWNlCmt1YmVjdGwgZ2V0IHNlY3JldCBudmNyLWNyZWRz" + + "IC1uIDxuYW1lc3BhY2U+CgojIENoZWNrIGlmIHRoZSBwb2Qgc3BlYyBoYXMgaW1hZ2VQdWxsU2Vj" + + "cmV0cwprdWJlY3RsIGdldCBwb2QgLW4gPG5hbWVzcGFjZT4gPHBvZC1uYW1lPiAtbyBqc29ucGF0" + + "aD0ney5zcGVjLmltYWdlUHVsbFNlY3JldHN9JwoKIyBDaGVjayBpZiB0aGUgU2VydmljZUFjY291" + + "bnQgaGFzIGltYWdlUHVsbFNlY3JldHMKa3ViZWN0bCBnZXQgc2EgPHNhLW5hbWU+IC1uIDxuYW1l" + + "c3BhY2U+IC1vIGpzb25wYXRoPSd7LmltYWdlUHVsbFNlY3JldHN9JwpgYGAKCiMjIyBGaXhlcwoK" + + "MS4gKipTZWNyZXQgbWlzc2luZyBpbiBuYW1lc3BhY2UqKjogQ3JlYXRlIGl0CgogICBgYGBiYXNo" + + "CiAgIGt1YmVjdGwgY3JlYXRlIHNlY3JldCBkb2NrZXItcmVnaXN0cnkgbnZjci1jcmVkcyBcCiAg" + + "ICAgLS1kb2NrZXItc2VydmVyPW52Y3IuaW8gXAogICAgIC0tZG9ja2VyLXVzZXJuYW1lPSckb2F1" + + "dGh0b2tlbicgXAogICAgIC0tZG9ja2VyLXBhc3N3b3JkPSIkTkdDX0FQSV9LRVkiIFwKICAgICAt" + + "LW5hbWVzcGFjZT08bmFtZXNwYWNlPiBcCiAgICAgLS1kcnktcnVuPWNsaWVudCAtbyB5YW1sIHwg" + + "a3ViZWN0bCBhcHBseSAtZiAtCiAgIGBgYAoKMi4gKipTZWNyZXQgZXhpc3RzIGJ1dCBwb2QgZG9l" + + "c24ndCByZWZlcmVuY2UgaXQqKjogVGhlIGNoYXJ0IG5lZWRzIGBpbWFnZVB1bGxTZWNyZXRzYCBj" + + "b25maWd1cmVkIHZpYSBoZWxtZmlsZSB2YWx1ZXMuIFNlZSBbcHVsbC1zZWNyZXRzLm1kXShwdWxs" + + "LXNlY3JldHMubWQpLgoKMy4gKipDaGFydCBkb2Vzbid0IHN1cHBvcnQgaW1hZ2VQdWxsU2VjcmV0" + + "cyoqIChvcGVuYmFvLCBpbnZvY2F0aW9uLXNlcnZpY2UsIGVzcy1hcGksIG5vdGFyeS1zZXJ2aWNl" + + "KTogUGF0Y2ggU2VydmljZUFjY291bnRzIGFuZCByZXN0YXJ0IHBvZHMuIFNlZSBbcHVsbC1zZWNy" + + "ZXRzLm1kXShwdWxsLXNlY3JldHMubWQpLgoKNC4gKipXcm9uZyBjcmVkZW50aWFscyBpbiBzZWNy" + + "ZXQqKjogRGVsZXRlIGFuZCByZWNyZWF0ZQoKICAgYGBgYmFzaAogICBrdWJlY3RsIGRlbGV0ZSBz" + + "ZWNyZXQgbnZjci1jcmVkcyAtbiA8bmFtZXNwYWNlPgogICAjIFJlY3JlYXRlIHdpdGggY29ycmVj" + + "dCBjcmVkZW50aWFscwogICBgYGAKCiMjIEZhaWx1cmU6IEluaXQ6MC8xIFN0dWNrIChWYXVsdCBB" + + "Z2VudCkKCiMjIyBTeW1wdG9tcwoKU2VydmljZSBwb2RzIHN0dWNrIGluIGBJbml0OjAvMWAgZm9y" + + "IG1pbnV0ZXM6CgpgYGBiYXNoCk5BTUUgICAgICAgICAgICAgICAgICAgICAgICBSRUFEWSAgIFNU" + + "QVRVUyAgICAgUkVTVEFSVFMgICBBR0UKbnZjZi1hcGktN2Y0Yzc2Zjc4OC00NHZsdCAgMC8yICAg" + + "ICBJbml0OjAvMSAgIDAgICAgICAgICAgMTBtCmBgYAoKIyMjIERpYWdub3NpcwoKVGhlIGluaXQg" + + "Y29udGFpbmVyIGlzIHRoZSB2YXVsdC1hZ2VudC1pbml0IGluamVjdG9yIHdhaXRpbmcgZm9yIE9w" + + "ZW5CYW8uCgpgYGBiYXNoCiMgQ2hlY2sgT3BlbkJhbyBwb2RzCmt1YmVjdGwgZ2V0IHBvZHMgLW4g" + + "dmF1bHQtc3lzdGVtCgojIENoZWNrIGlmIE9wZW5CYW8gbWlncmF0aW9uIGpvYiByYW4Ka3ViZWN0" + + "bCBnZXQgam9icyAtbiB2YXVsdC1zeXN0ZW0KCiMgQ2hlY2sgT3BlbkJhbyBwb2QgbG9ncwprdWJl" + + "Y3RsIGxvZ3MgLW4gdmF1bHQtc3lzdGVtIG9wZW5iYW8tc2VydmVyLTAgLWMgb3BlbmJhbwoKIyBD" + + "aGVjayBpbml0IGNvbnRhaW5lciBsb2dzIG9uIHRoZSBzdHVjayBwb2QKa3ViZWN0bCBsb2dzIC1u" + + "IDxuYW1lc3BhY2U+IDxwb2QtbmFtZT4gLWMgdmF1bHQtYWdlbnQtaW5pdApgYGAKCiMjIyBGaXhl" + + "cwoKMS4gKipPcGVuQmFvIHBvZHMgbm90IHJ1bm5pbmcqKjogQ2hlY2sgdGhlaXIgZXZlbnRzIGZv" + + "ciBpbWFnZSBwdWxsIGlzc3VlcywgcmVzb3VyY2UgaXNzdWVzLCBldGMuCgoyLiAqKk9wZW5CYW8g" + + "bWlncmF0aW9uIGpvYiBkaWRuJ3QgcnVuKio6IFRoaXMgaGFwcGVucyB3aGVuIGBoZWxtZmlsZSBz" + + "eW5jYCB3YXMgaW50ZXJydXB0ZWQuIERlc3Ryb3kgYW5kIHJlLXN5bmMgb3BlbmJhbzoKCiAgIGBg" + "YGJhc2gKICAgSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1vcGVu" + "YmFvLXNlcnZlciBkZXN0cm95CiAgIGt1YmVjdGwgZGVsZXRlIG5hbWVzcGFjZSB2YXVsdC1zeXN0" + "ZW0KICAga3ViZWN0bCBjcmVhdGUgbmFtZXNwYWNlIHZhdWx0LXN5c3RlbQogICAjIFJlLWNyZWF0" + "ZSBwdWxsIHNlY3JldCBpZiBuZWVkZWQKICAgSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0t" + "c2VsZWN0b3IgbmFtZT1vcGVuYmFvLXNlcnZlciBzeW5jCiAgIGBgYAoKMy4gKipPcGVuQmFvIHBv" + - "ZHMgcnVubmluZyBidXQgbm90IGluaXRpYWxpemVkKio6IENoZWNrIHVuc2VhbCBzdGF0dXM6CiAg" + - "IGBgYGJhc2gKICAga3ViZWN0bCBleGVjIC1uIHZhdWx0LXN5c3RlbSBvcGVuYmFvLXNlcnZlci0w" + - "IC1jIG9wZW5iYW8gLS0gYmFvIHN0YXR1cwogICBgYGAKCjQuICoqYHZhdWx0LWFnZW50LWluaXRg" + - "IGxvZ3MgYGF1dGgvand0L2xvZ2luYCAtPiBgNDAwIC4uLiBubyBrbm93biBrZXkgc3VjY2Vzc2Z1" + - "bGx5IHZhbGlkYXRlZCB0aGUgdG9rZW4gc2lnbmF0dXJlYCoqCiAgIChjb21tb24gb24gQUtTLCBh" + - "bmQgb24gYW55IGNsdXN0ZXIgd2hvc2UgT0lEQyBpc3N1ZXIgcHVibGlzaGVzIGEgcm90YXRpbmcg" + - "bXVsdGkta2V5IEpXS1MpOgogICB0aGUgT3BlbkJhbyBgYXV0aC9qd3RgIG1ldGhvZCB3YXMgY29u" + - "ZmlndXJlZCB3aXRoIGEgc2luZ2xlIHN0YXRpYyBtb3VudGVkIHB1YmxpYyBrZXkKICAgKGBqd3Rf" + - "dmFsaWRhdGlvbl9wdWJrZXlzYCkgaW5zdGVhZCBvZiB0aGUgaXNzdWVyJ3MgbGl2ZSBKV0tTLCBz" + - "byBpdCBjYW5ub3QgdmFsaWRhdGUgdGhlCiAgIGNsdXN0ZXItc2lnbmVkIFNlcnZpY2VBY2NvdW50" + - "IHRva2VucyB0aGUgdmF1bHQtYWdlbnRzIHByZXNlbnQuIEV2ZXJ5IHNlcnZpY2UncwogICBgdmF1" + - "bHQtYWdlbnQtaW5pdGAgdGhlbiBsb29wcyBvbiB0aGF0IDQwMCBhbmQgdGhlIHBvZCBuZXZlciBs" + - "ZWF2ZXMgYEluaXQ6MC8xYC4gVGhpcyBpcyB0aGUKICAgYmVoYXZpb3Igb2YgdGhlIGJhc2UgZGVm" + - "YXVsdCBgb3BlbmJhby5taWdyYXRpb25zLmlzc3VlckRpc2NvdmVyeS5lbmFibGVkOiBmYWxzZWA7" + - "IHRoZQogICBtaWdyYXRpb24gbG9nIHNob3dzIGBPSURDIGlzc3VlciBkaXNjb3ZlcnkgaXMgZGlz" + - "YWJsZWQuIFVzaW5nIFNlcnZpY2VBY2NvdW50IGlzc3VlciBhbmQKICAgbW91bnRlZCBwdWJsaWMg" + - "a2V5IGZhbGxiYWNrYC4gRW5hYmxlIGlzc3VlciBkaXNjb3Zlcnkgc28gdGhlIG1pZ3JhdGlvbiB1" + - "c2VzIHRoZSBsaXZlIEpXS1MsCiAgIHRoZW4gcmUtcnVuIGl0OgogICBgYGBiYXNoCiAgICMgSW4g" + - "eW91ciBlbnYgdmFsdWVzIChlLmcuIGVudmlyb25tZW50cy88ZW52Pi55YW1sKSwgc2V0OgogICAj" + - "ICAgb3BlbmJhbzoKICAgIyAgICAgbWlncmF0aW9uczoKICAgIyAgICAgICBpc3N1ZXJEaXNjb3Zl" + - "cnk6CiAgICMgICAgICAgICBlbmFibGVkOiB0cnVlCiAgIGt1YmVjdGwgZGVsZXRlIGpvYiAtbiB2" + - "YXVsdC1zeXN0ZW0gb3BlbmJhby1zZXJ2ZXItbWlncmF0aW9ucwogICBIRUxNRklMRV9FTlY9PGVu" + - "dj4gaGVsbWZpbGUgLS1zZWxlY3RvciBuYW1lPW9wZW5iYW8tc2VydmVyIHN5bmMKICAgYGBgCiAg" + - "IFRoZSBtaWdyYXRpb24gbG9nIHNob3VsZCB0aGVuIHNob3cgYFJlY2VpdmVkIGRpc2NvdmVyeSBk" + - "b2N1bWVudCBmcm9tCiAgIC4uLi8ud2VsbC1rbm93bi9vcGVuaWQtY29uZmlndXJhdGlvbmAgYW5k" + - "IGBGaW5hbCBPcGVuQmFvIEpXVCBKV0tTIFVSTCBzZXQgdG86CiAgIC4uLi9vcGVuaWQvdjEvandr" + - "c2AsIGFuZCB0aGUgc2VydmljZSBwb2RzIGF1dGhlbnRpY2F0ZSBhbmQgcmVhY2ggUmVhZHkgd2l0" + - "aGluIH4xIG1pbi4KICAgQUtTIGNsdXN0ZXJzIHdpdGggdGhlIGNsdXN0ZXIgT0lEQyBpc3N1ZXIg" + - "ZW5hYmxlZCAodGhlIGBha3MtY2x1c3RlcmAgZGVmYXVsdCkgYWx3YXlzIG5lZWQKICAgdGhpcyBi" + - "ZWNhdXNlIHRoZSBzdGF0aWMtcHVia2V5IGZhbGxiYWNrIGNhbm5vdCBtYXRjaCB0aGUgaXNzdWVy" + - "J3Mgcm90YXRpbmcgc2lnbmluZyBrZXlzLgoKIyMgRmFpbHVyZTogT09NS2lsbGVkIG9uIENhc3Nh" + - "bmRyYQoKIyMjIFN5bXB0b21zCgpgYGAKTkFNRSAgICAgICAgICBSRUFEWSAgIFNUQVRVUyAgICBS" + - "RVNUQVJUUyAgIEFHRQpjYXNzYW5kcmEtMCAgIDAvMSAgICAgT09NS2lsbGVkICAzICAgICAgICAg" + - "MTBtCmBgYAoKIyMjIERpYWdub3NpcwoKYGBgYmFzaAprdWJlY3RsIGRlc2NyaWJlIHBvZCAtbiBj" + - "YXNzYW5kcmEtc3lzdGVtIGNhc3NhbmRyYS0wIHwgZ3JlcCAtQTMgIkxhc3QgU3RhdGUiCmBgYAoK" + - "IyMjIEZpeAoKT3ZlcnJpZGUgQ2Fzc2FuZHJhIHJlc291cmNlcyB2aWEgaGVsbWZpbGUgdmFsdWVz" + - "LiBTZWUgRXhhbXBsZSAxIGluCltleGFtcGxlcy5tZF0oLi4vZXhhbXBsZXMubWQpLgoKYGBgeWFt" + - "bAotIGNhc3NhbmRyYToKICAgIHJlc291cmNlczoKICAgICAgbGltaXRzOgogICAgICAgIGNwdTog" + - "IjgiCiAgICAgICAgbWVtb3J5OiA4MTkyTWkKICAgICAgcmVxdWVzdHM6CiAgICAgICAgY3B1OiAi" + - "MiIKICAgICAgICBtZW1vcnk6IDQwOTZNaQpgYGAKCk5vdGU6IGByZXNvdXJjZVByZXNldGAgaXMg" + - "bm90IGF2YWlsYWJsZSBpbiB0aGUgTlZDRiBjYXNzYW5kcmEgd3JhcHBlciBjaGFydC4gVXNlIGV4" + - "cGxpY2l0IGByZXNvdXJjZXNgLgoKIyMgRmFpbHVyZTogUG9kcyBTdHVjayBpbiBQZW5kaW5nCgoj" + - "IyMgU3ltcHRvbXMKCmBgYApOQU1FICAgICAgICAgIFJFQURZICAgU1RBVFVTICAgIFJFU1RBUlRT" + - "ICAgQUdFCmNhc3NhbmRyYS0wICAgMC8xICAgICBQZW5kaW5nICAgMCAgICAgICAgICAxMG0KYGBg" + - "CgojIyMgRGlhZ25vc2lzCgpgYGBiYXNoCiMgQ2hlY2sgZXZlbnRzIGZvciBzY2hlZHVsaW5nIGZh" + - "aWx1cmVzCmt1YmVjdGwgZGVzY3JpYmUgcG9kIC1uIDxuYW1lc3BhY2U+IDxwb2QtbmFtZT4KCiMg" + - "Q29tbW9uIGNhdXNlczoKIyAtICIwLzEyIG5vZGVzIGFyZSBhdmFpbGFibGU6IDEyIG5vZGUocykg" + - "ZGlkbid0IG1hdGNoIFBvZCdzIG5vZGUgYWZmaW5pdHkiCiMgLSAiMC8xMiBub2RlcyBhcmUgYXZh" + - "aWxhYmxlOiAxMiBJbnN1ZmZpY2llbnQgbWVtb3J5IgojIC0gInBlcnNpc3RlbnR2b2x1bWVjbGFp" + - "bSBub3QgZm91bmQiCmBgYAoKIyMjIEZpeGVzCgoxLiAqKk5vZGUgc2VsZWN0b3IgbWlzbWF0Y2gq" + - "KjogQ2hlY2sgYG5vZGVTZWxlY3RvcnNgIGluIGVudmlyb25tZW50IGZpbGUKICAgYGBgYmFzaAog" + - "ICBrdWJlY3RsIGdldCBub2RlcyAtLXNob3ctbGFiZWxzIHwgZ3JlcCBudmNmCiAgIGBgYAoKMi4g" + - "KipTdG9yYWdlIGNsYXNzIG5vdCBmb3VuZCoqOiBDaGVjayBzdG9yYWdlIGNsYXNzIGV4aXN0cwog" + - "ICBgYGBiYXNoCiAgIGt1YmVjdGwgZ2V0IHN0b3JhZ2VjbGFzcwogICBgYGAKCjMuICoqSW5zdWZm" + - "aWNpZW50IHJlc291cmNlcyoqOiBDaGVjayBub2RlIGNhcGFjaXR5CiAgIGBgYGJhc2gKICAga3Vi" + - "ZWN0bCBkZXNjcmliZSBub2RlIDxub2RlLW5hbWU+IHwgZ3JlcCAtQTUgIkFsbG9jYXRlZCByZXNv" + - "dXJjZXMiCiAgIGBgYAoKIyMgRmFpbHVyZTogSGVsbSBSZWxlYXNlIGluIEZhaWxlZCBTdGF0ZQoK" + - "IyMjIFN5bXB0b21zCgpgYGBiYXNoCmhlbG0gbGlzdCAtQQojIFNob3dzIHJlbGVhc2Ugd2l0aCBT" + - "VEFUVVM6IGZhaWxlZApgYGAKClJlLXJ1bm5pbmcgYGhlbG1maWxlIHN5bmNgIGFwcGVhcnMgdG8g" + - "c3VjY2VlZCBidXQgc2VydmljZXMgZG9uJ3Qgd29yayAobWlncmF0aW9ucyBza2lwcGVkKS4KCiMj" + - "IyBEaWFnbm9zaXMKCmBgYGJhc2gKaGVsbSBoaXN0b3J5IDxyZWxlYXNlLW5hbWU+IC1uIDxuYW1l" + - "c3BhY2U+CmBgYAoKIyMjIEZpeAoKTXVzdCBkZXN0cm95IHRoZSBmYWlsZWQgcmVsZWFzZSBhbmQg" + - "cmUtc3luYyAobm90IGp1c3QgYXBwbHkpOgoKYGBgYmFzaApIRUxNRklMRV9FTlY9PGVudj4gaGVs" + - "bWZpbGUgLS1zZWxlY3RvciBuYW1lPTxyZWxlYXNlPiBkZXN0cm95CiMgSWYgbmFtZXNwYWNlIG5l" + - "ZWRzIGNsZWFudXA6Cmt1YmVjdGwgZGVsZXRlIG5hbWVzcGFjZSA8bmFtZXNwYWNlPgprdWJlY3Rs" + - "IGNyZWF0ZSBuYW1lc3BhY2UgPG5hbWVzcGFjZT4KIyBSZS1jcmVhdGUgcHVsbCBzZWNyZXQgaWYg" + - "bmVlZGVkCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9PHJlbGVh" + - "c2U+IHN5bmMKYGBgCgojIyBGYWlsdXJlOiBBY2NvdW50IEJvb3RzdHJhcCBKb2IgRmFpbGVkCgoj" + - "IyMgU3ltcHRvbXMKClNlcnZpY2VzIGRlcGxveSBidXQgZnVuY3Rpb25zIGNhbid0IGJlIGNyZWF0" + - "ZWQuIEV2ZW50cyBzaG93IGJvb3RzdHJhcCBqb2IgZmFpbHVyZS4KCiMjIyBEaWFnbm9zaXMKCmBg" + - "YGJhc2gKIyBDaGVjayBib290c3RyYXAgam9iIHN0YXR1cwprdWJlY3RsIGdldCBqb2JzIC1uIG52" + - "Y2YKCiMgR2V0IGxvZ3MgKGpvYiBhdXRvLWRlbGV0ZXMgYWZ0ZXIgfjUgbWludXRlcykKa3ViZWN0" + - "bCBsb2dzIGpvYi9udmNmLWFwaS1hY2NvdW50LWJvb3RzdHJhcCAtbiBudmNmCgojIENoZWNrIEFQ" + - "SSBsb2dzCmt1YmVjdGwgbG9ncyAtbiBudmNmIC1sIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU9bnZj" + - "Zi1hcGkgLS10YWlsPTEwMApgYGAKCiMjIyBDb21tb24gQ2F1c2VzCgoxLiAqKldyb25nIGJhc2U2" + - "NCBjcmVkZW50aWFscyoqOiBDcmVkZW50aWFscyBpbiBgc2VjcmV0cy88ZW52Pi1zZWNyZXRzLnlh" + - "bWxgIG11c3QgYmUgYCRvYXV0aHRva2VuOkFQSV9LRVlgIGJhc2U2NC1lbmNvZGVkLCBub3QganVz" + - "dCB0aGUgQVBJIGtleQogICBgYGBiYXNoCiAgICMgVmVyaWZ5IHlvdXIgZW5jb2RlZCBjcmVkZW50" + - "aWFsCiAgIGVjaG8gJ1lPVVJfQkFTRTY0X1NUUklORycgfCBiYXNlNjQgLWQKICAgIyBTaG91bGQg" + - "b3V0cHV0OiAkb2F1dGh0b2tlbjpudmFwaS14eHh4eAogICBgYGAKCjIuICoqUmVnaXN0cnkgdW5y" + - "ZWFjaGFibGUqKjogQVBJIGNhbid0IHJlYWNoIHRoZSByZWdpc3RyeSBzcGVjaWZpZWQgaW4gYGFj" + - "Y291bnRCb290c3RyYXAucmVnaXN0cnlDcmVkZW50aWFsc2AKCiMjIyBGaXgKCkZpeCBjcmVkZW50" + - "aWFscyBpbiBzZWNyZXRzIGZpbGUsIHRoZW4gcmVjb3ZlciBzZXJ2aWNlcyB3aXRob3V0IGRlc3Ry" + - "b3lpbmcgZGVwZW5kZW5jaWVzOgoKYGBgYmFzaApIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUg" + - "LS1zZWxlY3RvciByZWxlYXNlLWdyb3VwPXNlcnZpY2VzIGRlc3Ryb3kKa3ViZWN0bCBkZWxldGUg" + - "bmFtZXNwYWNlIG52Y2YgYXBpLWtleXMgZXNzIHNpcyAtLWlnbm9yZS1ub3QtZm91bmQKa3ViZWN0" + - "bCBjcmVhdGUgbmFtZXNwYWNlIG52Y2YgJiYga3ViZWN0bCBjcmVhdGUgbmFtZXNwYWNlIGFwaS1r" + - "ZXlzICYmIFwKICBrdWJlY3RsIGNyZWF0ZSBuYW1lc3BhY2UgZXNzICYmIGt1YmVjdGwgY3JlYXRl" + - "IG5hbWVzcGFjZSBzaXMKIyBSZS1jcmVhdGUgcHVsbCBzZWNyZXRzIGlmIG5lZWRlZApIRUxNRklM" + - "RV9FTlY9PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciByZWxlYXNlLWdyb3VwPXNlcnZpY2VzIHN5" + - "bmMKYGBgCgojIyBGYWlsdXJlOiBOVkNBIENsZWFudXAgU3R1Y2sgKEZpbmFsaXplcnMpCgojIyMg" + - "U3ltcHRvbXMKCkNvbXB1dGUtcGxhbmUgY2xlYW51cCBoYW5ncy4gTmFtZXNwYWNlcwpzdHVjayBp" + - "biBgVGVybWluYXRpbmdgOgoKYGBgYmFzaAprdWJlY3RsIGdldCBucwojIG52Y2Etb3BlcmF0b3Ig" + - "ICAgVGVybWluYXRpbmcgICAxMG0KIyBudmNmLWJhY2tlbmQgICAgIFRlcm1pbmF0aW5nICAgMTBt" + - "CmBgYAoKIyMjIEZpeAoKUnVuIHRoaXMgb25seSBhZ2FpbnN0IHRoZSBjb21wdXRlIGNvbnRleHQs" + - "IGFmdGVyIHRoZSBub3JtYWwgY29tcHV0ZS1wbGFuZQp0ZWFyZG93biBoYXMgZmFpbGVkLiBSZW1v" + - "dmUgZmluYWxpemVycyBmcm9tIE5WQ0ZCYWNrZW5kIGN1c3RvbSByZXNvdXJjZXMgYW5kCmZvcmNl" + - "LWRlbGV0ZSBzdHVjayBuYW1lc3BhY2VzOgoKYGBgYmFzaApleHBvcnQgQ09NUFVURV9DT05URVhU" + - "PTxjb21wdXRlLXBsYW5lLWNvbnRleHQ+CgojIFJlbW92ZSBmaW5hbGl6ZXJzIGZyb20gTlZDRkJh" + - "Y2tlbmQgcmVzb3VyY2VzCmt1YmVjdGwgLS1jb250ZXh0ICIkQ09NUFVURV9DT05URVhUIiBnZXQg" + - "bnZjZmJhY2tlbmRzIC1BIC1vIGpzb24gfCBcCiAganEgJy5pdGVtc1tdIHwgLm1ldGFkYXRhLm5h" + - "bWVzcGFjZSArICIvIiArIC5tZXRhZGF0YS5uYW1lJyAtciB8IFwKICB4YXJncyAtSXt9IHNoIC1j" + - "ICdjb250ZXh0PSIkMSI7IG5zPSIkezIlJS8qfSI7IG5hbWU9IiR7MiMjKi99Ijsga3ViZWN0bCAt" + - "LWNvbnRleHQgIiRjb250ZXh0IiBwYXRjaCBudmNmYmFja2VuZCAiJG5hbWUiIC1uICIkbnMiIC0t" + - "dHlwZT1tZXJnZSAtcCAie1wibWV0YWRhdGFcIjp7XCJmaW5hbGl6ZXJzXCI6W119fSInIF8gIiRD" + - "T01QVVRFX0NPTlRFWFQiIHt9CgojIEZvcmNlLWRlbGV0ZSBzdHVjayBuYW1lc3BhY2VzIGJ5IGNs" + - "ZWFyaW5nIHRoZWlyIGZpbmFsaXplcnMKZm9yIG5zIGluIG52Y2Etb3BlcmF0b3IgbnZjZi1iYWNr" + - "ZW5kOyBkbwogIGt1YmVjdGwgLS1jb250ZXh0ICIkQ09NUFVURV9DT05URVhUIiBnZXQgbmFtZXNw" + - "YWNlICIkbnMiIC1vIGpzb24gMj4vZGV2L251bGwgfCBcCiAgICBqcSAnLnNwZWMuZmluYWxpemVy" + - "cyA9IFtdJyB8IFwKICAgIGt1YmVjdGwgLS1jb250ZXh0ICIkQ09NUFVURV9DT05URVhUIiByZXBs" + - "YWNlIFwKICAgICAgLS1yYXcgIi9hcGkvdjEvbmFtZXNwYWNlcy8kbnMvZmluYWxpemUiIC1mIC0g" + - "Mj4vZGV2L251bGwKZG9uZQpgYGAKCiMjIEZhaWx1cmU6IE5WQ0EgT3BlcmF0b3IgTWlzc2luZyBv" + - "ciBOb3QgUmVhZHkKCiMjIyBTeW1wdG9tcwoKQWZ0ZXIgY29tcHV0ZS1wbGFuZSBpbnN0YWxsIGNv" + - "bXBsZXRlcywgbm8gYG52Y2Etb3BlcmF0b3JgIERlcGxveW1lbnQgZXhpc3RzLCBvcgppdCBleGlz" + - "dHMgYnV0IHBvZHMgYXJlIG5vdCByZWFkeToKCmBgYGJhc2gKa3ViZWN0bCAtLWNvbnRleHQgPGNv" + - "bXB1dGUtcGxhbmUtY29udGV4dD4gZ2V0IGRlcGxveW1lbnQgbnZjYS1vcGVyYXRvciBcCiAgLW4g" + - "bnZjYS1vcGVyYXRvcgprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250ZXh0PiBn" + - "ZXQgcG9kcyAtbiBudmNhLW9wZXJhdG9yCmBgYAoKIyMjIERpYWdub3NpcyBhbmQgRml4ZXMKCkZp" + - "cnN0IGlkZW50aWZ5IHdoZXRoZXIgdGhlIGluc3RhbGxhdGlvbiB1c2VkIHRoZSBIZWxtZmlsZSB2" + - "YWx1ZXMgZmxvdyBvciB0aGUKQ0xJIHByb2ZpbGUgZmxvdy4gUmUtcnVuIG9ubHkgdGhhdCBmbG93" + - "J3MgcmVnaXN0cmF0aW9uIGFuZCBpbnN0YWxsYXRpb24gc3RlcHMKZnJvbSBbU3BsaXQgQ29tcHV0" + - "ZS1QbGFuZSBJbnN0YWxsYXRpb25dKGNvbXB1dGUtcGxhbmUtaW5zdGFsbGF0aW9uLm1kKS4gRG8g" + - "bm90CnN1YnN0aXR1dGUgb25lIGhhbmRvZmYgZm9yIHRoZSBvdGhlci4KCklmIGluc3RhbGxhdGlv" + - "biBzdWNjZWVkcyBidXQgcG9kcyBzdGlsbCBmYWlsLCBpbnNwZWN0IHRoZSBjb21wdXRlIGNvbnRl" + - "eHQ6CgpgYGBiYXNoCmt1YmVjdGwgLS1jb250ZXh0IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IGRl" + - "c2NyaWJlIGRlcGxveSBudmNhLW9wZXJhdG9yIFwKICAtbiBudmNhLW9wZXJhdG9yCmt1YmVjdGwg" + - "LS1jb250ZXh0IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IGxvZ3MgZGVwbG95bWVudC9udmNhLW9w" + - "ZXJhdG9yIFwKICAtbiBudmNhLW9wZXJhdG9yIC0tdGFpbD0yMDAKa3ViZWN0bCAtLWNvbnRleHQg" + - "PGNvbXB1dGUtcGxhbmUtY29udGV4dD4gZ2V0IG52Y2ZiYWNrZW5kIC1uIG52Y2Etb3BlcmF0b3IK" + - "YGBgCgpGb3IgcHJpdmF0ZSByZWdpc3RyeSBmYWlsdXJlcywgdmVyaWZ5IHRoYXQgdGhlIHB1bGwg" + - "c2VjcmV0IGV4aXN0cyBpbgpgbnZjYS1vcGVyYXRvcmAuIFRoZSBjaGFydCBhbmQgb3BlcmF0b3Ig" + - "bWlycm9yIGl0IHRvIGBudmNhLXN5c3RlbWA7IGRvIG5vdCB1c2UgYQpicm9hZGVyIG1hbnVhbCBu" + - "YW1lc3BhY2UgbG9vcC4gU2VlCltwdWxsLXNlY3JldHMubWRdKHB1bGwtc2VjcmV0cy5tZCNjb21w" + - "dXRlLXBsYW5lLXNlY3JldCkuCgojIyBGYWlsdXJlOiBHYXRld2F5IEVuZHBvaW50IENoYW5nZWQK" + - "CiMjIyBTeW1wdG9tcwoKUmVxdWVzdHMgdGhyb3VnaCB0aGUgY29uZmlndXJlZCByb3V0ZSBkb21h" + - "aW4gZmFpbCBhZnRlciB0aGUgR2F0ZXdheSBvciBpdHMgbG9hZCBiYWxhbmNlciBpcyByZXBsYWNl" + - "ZC4gVGhlIEdhdGV3YXkgcmVwb3J0cyBhIG5ldyBlbmRwb2ludC4KCiMjIyBEaWFnbm9zaXMKCmBg" + - "YGJhc2gKR0FURVdBWV9BRERSPSQoa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29u" + - "dGV4dD4gZ2V0IGdhdGV3YXkgXAogIG52Y2YtZ2F0ZXdheSAtbiBlbnZveS1nYXRld2F5IFwKICAt" + - "byBqc29ucGF0aD0ney5zdGF0dXMuYWRkcmVzc2VzWzBdLnZhbHVlfScpCnRlc3QgLW4gIiRHQVRF" + - "V0FZX0FERFIiCmRpZyArc2hvcnQgImFwaS48ZG9tYWluPiIKY3VybCAtSCAiSG9zdDogYXBpLjxk" + - "b21haW4+IiAiaHR0cDovLyRHQVRFV0FZX0FERFIvaGVhbHRoIgoKIyBDaGVjayBkaXJlY3QgYWRk" + - "cmVzcyBmaWVsZHMgdXNlZCBieSBhIHNwbGl0IGRlcGxveW1lbnQKZ3JlcCBudmNmTmF0c1NlcnZp" + - "Y2VVUkwgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQvZW52aXJvbm1lbnRzLzxlbnY+LnlhbWwK" + - "Z3JlcCAtRSAnaWNtc1NlcnZpY2V8cmV2YWxTZXJ2aWNlfG5hdHMnIFwKICBkZXBsb3kvc3RhY2tz" + - "L252Y2YtY29tcHV0ZS1wbGFuZS9lbnZpcm9ubWVudHMvPGVudj4ueWFtbApgYGAKCiMjIyBGaXgK" + - "CktlZXAgYGdsb2JhbC5kb21haW5gLCByb3V0ZSBob3N0bmFtZXMsIGFuZCBIb3N0IG92ZXJyaWRl" + - "cyB1bmNoYW5nZWQuIFVwZGF0ZSBETlMKb3IgdGhlIGRpcmVjdCBjbGllbnQgZGVzdGluYXRpb24u" + - "IEZvciBzcGxpdCBkZXBsb3ltZW50cywgdXBkYXRlIG9ubHkgZGlyZWN0CkdhdGV3YXktYWRkcmVz" + - "cyBmaWVsZHMgYW5kIHJlZnJlc2ggcmVnaXN0cmF0aW9uIGFuZCBpbnN0YWxsYXRpb24gdGhyb3Vn" + - "aCB0aGUKc2FtZSBzZWxlY3RlZCBoYW5kb2ZmLiBTZWUKW0V4YW1wbGUgNF0oLi4vZXhhbXBsZXMu" + - "bWQjZXhhbXBsZS00LXJlY292ZXItZnJvbS1hLWdhdGV3YXktZW5kcG9pbnQtY2hhbmdlKS4KCiMj" + - "IFVzZWZ1bCBOYW1lc3BhY2UtdG8tU2VydmljZSBNYXBwaW5nCgpRdWljayByZWZlcmVuY2UgZm9y" + - "IHdoaWNoIHNlcnZpY2VzIHJ1biBpbiB3aGljaCBuYW1lc3BhY2U6Cgp8IE5hbWVzcGFjZSB8IFNl" + - "cnZpY2VzIHwKfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS18CnwgbmF0cy1zeXN0ZW0gfCBuYXRzIHwK" + - "fCBjYXNzYW5kcmEtc3lzdGVtIHwgY2Fzc2FuZHJhIHwKfCB2YXVsdC1zeXN0ZW0gfCBvcGVuYmFv" + - "LXNlcnZlciB8CnwgbnZjZiB8IGFwaSwgaW52b2NhdGlvbi1zZXJ2aWNlLCBncnBjLXByb3h5LCBu" + - "b3Rhcnktc2VydmljZSwgcmV2YWwsIGxsbS1yZXF1ZXN0LXJvdXRlciwgbGxtLWFwaS1nYXRld2F5" + - "IHwKfCBhcGkta2V5cyB8IGFwaS1rZXlzLCBhZG1pbi1pc3N1ZXItcHJveHkgfAp8IGVzcyB8IGVz" + - "cy1hcGkgfAp8IHNpcyB8IHNpcyB8CnwgZW52b3ktZ2F0ZXdheS1zeXN0ZW0gfCBlbnZveSBnYXRl" + - "d2F5IChpbmdyZXNzIGNvbnRyb2xsZXIpIHwKfCBlbnZveS1nYXRld2F5IHwgZ2F0ZXdheSByZXNv" + - "dXJjZSArIHJvdXRlcyB8ClBLBwhWPmeQlTAAAJUwAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAA" + - "AEQACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL2hlbG1m" + - "aWxlLXN0cnVjdHVyZS5tZFVUBQABAKbOEiMgSGVsbWZpbGUgU3RydWN0dXJlIFJlZmVyZW5jZQoK" + - "IyMgRGlyZWN0b3J5IExheW91dAoKYGBgCm52Y2Ytc2VsZi1tYW5hZ2VkLXN0YWNrLwp8LS0gaGVs" + - "bWZpbGUuZC8KfCAgIHwtLSAwMS1kZXBlbmRlbmNpZXMueWFtbC5nb3RtcGwgICMgTkFUUywgQ2Fz" + - "c2FuZHJhLCBPcGVuQmFvCnwgICB8LS0gMDItY29yZS55YW1sLmdvdG1wbCAgICAgICAgICAjIE5W" + - "Q0Ygc2VydmljZXMgKyBpbmdyZXNzCnwgICBgLS0gMDMtb2JzZXJ2YWJpbGl0eS55YW1sLmdvdG1w" + - "bCAjIE9ic2VydmFiaWxpdHkgc3RhY2sgKG9wdGlvbmFsKQp8LS0gZW52aXJvbm1lbnRzLwp8ICAg" + - "fC0tIGJhc2UueWFtbCAgICAgICAgICAgICAgICAgICAgIyBEZWZhdWx0IHZhbHVlcyAoYWxsIGVu" + - "dmlyb25tZW50cykKfCAgIGAtLSA8ZW52LW5hbWU+LnlhbWwgICAgICAgICAgICAgICMgUGVyLWVu" + - "dmlyb25tZW50IG92ZXJyaWRlcwp8LS0gc2VjcmV0cy8KfCAgIGAtLSA8ZW52LW5hbWU+LXNlY3Jl" + - "dHMueWFtbCAgICAgICMgU2Vuc2l0aXZlIHZhbHVlcyAocmVnaXN0cnkgY3JlZHMsIHBhc3N3b3Jk" + - "cykKYC0tIGdsb2JhbC55YW1sLmdvdG1wbCAgICAgICAgICAgICAgICMgR28gdGVtcGxhdGUgdGhh" + - "dCBjb25zdHJ1Y3RzIHBlci1jaGFydCB2YWx1ZXMKCm52Y2YtY29tcHV0ZS1wbGFuZS1zdGFjay8K" + - "fC0tIGhlbG1maWxlLmQvCnwgICB8LS0gMDEtZGVwZW5kZW5jaWVzLnlhbWwuZ290bXBsICAjIENv" + - "bXB1dGUgcGxhbmUgZGVwZW5kZW5jeSBjb21wb25lbnRzCnwgICBgLS0gMDItbnZjYS55YW1sLmdv" + - "dG1wbCAgICAgICAgICAjIG52Y2Etb3BlcmF0b3IgY2hhcnQgYW5kIG52Y2EgY29uZmlndXJhdGlv" + - "bgp8LS0gZW52aXJvbm1lbnRzLwp8ICAgfC0tIGJhc2UueWFtbCAgICAgICAgICAgICAgICAgICAg" + - "IyBEZWZhdWx0IHZhbHVlcyAoYWxsIGVudmlyb25tZW50cykKfCAgIGAtLSA8ZW52LW5hbWU+Lnlh" + - "bWwgICAgICAgICAgICAgICMgUGVyLWVudmlyb25tZW50IG92ZXJyaWRlcwpgLS0gZ2xvYmFsLnlh" + - "bWwuZ290bXBsICAgICAgICAgICAgICAgIyBHbyB0ZW1wbGF0ZSB0aGF0IGNvbnN0cnVjdHMgcGVy" + - "LWNoYXJ0IHZhbHVlcwpgYGAKClRoZXNlIHN0YWNrcyBoYXZlIHNlcGFyYXRlIGVudmlyb25tZW50" + - "cyBhbmQgY2x1c3RlciBjb250ZXh0cy4gVGhlIEhlbG1maWxlCnZhbHVlcyBmbG93IGF1dGhvcnMg" + - "Ym90aCBlbnZpcm9ubWVudCBmaWxlcy4gVGhlIENMSSBwcm9maWxlIGZsb3cgaW5zdGVhZCB1c2Vz" + - "CnRoZSBDTEktZ2VuZXJhdGVkIGNvbnRyb2wtcGxhbmUgcHJvZmlsZSBhcyBpdHMgZW5kcG9pbnQg" + - "c291cmNlLiBEbyBub3QgbWl4IHRoZQpoYW5kb2Zmcy4gU2VlIFtTcGxpdCBDb21wdXRlLVBsYW5l" + - "IEluc3RhbGxhdGlvbl0oY29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpLgoKIyMgR290bXBs" + - "IEZpbGVzIGFuZCBUaGVpciBSZWxlYXNlcwoKIyMjIDAxLWRlcGVuZGVuY2llcy55YW1sLmdvdG1w" + - "bAoKfCBSZWxlYXNlIHwgQ2hhcnQgfCBOYW1lc3BhY2UgfCBOb3RlcyB8CnwtLS0tLS0tLS18LS0t" + - "LS0tLXwtLS0tLS0tLS0tLXwtLS0tLS0tfAp8IG5hdHMgfCBoZWxtLW52Y2YtbmF0cyB8IG5hdHMt" + - "c3lzdGVtIHwgTWVzc2FnaW5nIHwKfCBvcGVuYmFvLXNlcnZlciB8IGhlbG0tbnZjZi1vcGVuYmFv" + - "LXNlcnZlciB8IHZhdWx0LXN5c3RlbSB8IFNlY3JldHMgbWFuYWdlbWVudCwgZGVwZW5kcyBvbiBu" + - "YXRzIHwKfCBjYXNzYW5kcmEgfCBoZWxtLW52Y2YtY2Fzc2FuZHJhIHwgY2Fzc2FuZHJhLXN5c3Rl" + - "bSB8IERhdGFiYXNlIHwKClVzZXMgYDw8OiAqZGVwZW5kZW5jeWAgdGVtcGxhdGUgaW5oZXJpdGFu" + - "Y2Ugd2l0aCBgcmVsZWFzZS1ncm91cDogZGVwZW5kZW5jaWVzYCBsYWJlbC4KCiMjIyAwMi1jb3Jl" + - "LnlhbWwuZ290bXBsCgp8IFJlbGVhc2UgfCBDaGFydCB8IE5hbWVzcGFjZSB8IExhYmVsIHwKfC0t" + - "LS0tLS0tLXwtLS0tLS0tfC0tLS0tLS0tLS0tfC0tLS0tLS18CnwgYXBpLWtleXMgfCBoZWxtLW52" + - "Y2YtYXBpLWtleXMgfCBhcGkta2V5cyB8IHNlcnZpY2VzIHwKfCBzaXMgfCBoZWxtLW52Y2Ytc2lz" + - "IHwgc2lzIHwgc2VydmljZXMgfAp8IGFwaSB8IGhlbG0tbnZjZi1hcGkgfCBudmNmIHwgc2Vydmlj" + - "ZXMgfAp8IGludm9jYXRpb24tc2VydmljZSB8IGhlbG0tbnZjZi1pbnZvY2F0aW9uLXNlcnZpY2Ug" + - "fCBudmNmIHwgc2VydmljZXMgfAp8IGdycGMtcHJveHkgfCBoZWxtLW52Y2YtZ3JwYy1wcm94eSB8" + - "IG52Y2YgfCBzZXJ2aWNlcyB8CnwgZXNzLWFwaSB8IGhlbG0tbnZjZi1lc3MtYXBpIHwgZXNzIHwg" + - "c2VydmljZXMgfAp8IG5vdGFyeS1zZXJ2aWNlIHwgaGVsbS1udmNmLW5vdGFyeS1zZXJ2aWNlIHwg" + - "bnZjZiB8IHNlcnZpY2VzIHwKfCByZXZhbCB8IGhlbG0tcmV2YWwgfCBudmNmIHwgc2VydmljZXMg" + - "fAp8IGxsbS1yZXF1ZXN0LXJvdXRlciB8IG52Y2YvaGVsbS1udmNmLWxsbS1yZXF1ZXN0LXJvdXRl" + - "ciB8IG52Y2YgfCBzZXJ2aWNlcyB8CnwgbGxtLWFwaS1nYXRld2F5IHwgbnZjZi9oZWxtLW52Y2Yt" + - "bGxtLWFwaS1nYXRld2F5IHwgbnZjZiB8IHNlcnZpY2VzIHwKfCBhZG1pbi1pc3N1ZXItcHJveHkg" + - "fCBoZWxtLWFkbWluLXRva2VuLWlzc3Vlci1wcm94eSB8IGFwaS1rZXlzIHwgKG5vIHJlbGVhc2Ut" + - "Z3JvdXAgbGFiZWwpIHwKfCBpbmdyZXNzIHwgbnZjZi1nYXRld2F5LXJvdXRlcyB8IGVudm95LWdh" + - "dGV3YXktc3lzdGVtIHwgaW5ncmVzcyB8CgpNb3N0IHNlcnZpY2VzIHVzZSBgaW5oZXJpdDogW3t0" + - "ZW1wbGF0ZTogc2VydmljZX1dYC4gTExNIHJlbGVhc2VzIHVzZSBPQ0kgY2hhcnRzIGZyb20gdGhl" + - "IGBudmNmYCByZXBvc2l0b3J5IHdpdGggc3RhbmRhbG9uZSBgdmFsdWVzOiBbLi4vZ2xvYmFsLnlh" + - "bWwuZ290bXBsXWAgYmxvY2tzOyB0aGV5IGFyZSBnYXRlZCBvbiBgYWRkb25zLmxsbS5lbmFibGVk" + - "YC4gYGFkbWluLWlzc3Vlci1wcm94eWAgYW5kIGBpbmdyZXNzYCBoYXZlIHN0YW5kYWxvbmUgYHZh" + - "bHVlczpgIGJsb2Nrcy4KCiMjIyAwMy1vYnNlcnZhYmlsaXR5LnlhbWwuZ290bXBsCgp8IFJlbGVh" + - "c2UgfCBDaGFydCB8IE5hbWVzcGFjZSB8IExhYmVsIHwKfC0tLS0tLS0tLXwtLS0tLS0tfC0tLS0t" + - "LS0tLS0tfC0tLS0tLS18CnwgKG9ic2VydmFiaWxpdHkgcmVsZWFzZXMpIHwgKHZhcmlvdXMpIHwg" + - "b2JzZXJ2YWJpbGl0eSB8IG9ic2VydmFiaWxpdHkgfAoKR2F0ZWQgb24gb2JzZXJ2YWJpbGl0eS1z" + - "cGVjaWZpYyBmbGFncyBpbiB0aGUgZW52aXJvbm1lbnQgZmlsZS4gU2tpcHBlZCBpZiBkaXNhYmxl" + - "ZC4KCiMjIFRlbXBsYXRlIEluaGVyaXRhbmNlCgojIyMgYDw8OiAqZGVwZW5kZW5jeWAgKFlBTUwg" + - "bWVyZ2UpCgpVc2VkIGluIGAwMS1kZXBlbmRlbmNpZXMueWFtbC5nb3RtcGxgLiBNZXJnZXMgdGhl" + - "IHRlbXBsYXRlJ3MgcHJvcGVydGllcyBpbnRvIHRoZSByZWxlYXNlLgoKKipHb3RjaGEqKjogWUFN" + - "TCBtZXJnZSByZXBsYWNlcyBsaXN0cy4gSWYgeW91IGFkZCBhIGB2YWx1ZXM6YCBrZXkgdG8gdGhl" + - "IHJlbGVhc2UsIGl0ICoqcmVwbGFjZXMqKiB0aGUgdGVtcGxhdGUncyBgdmFsdWVzOmAgbGlzdCBl" + - "bnRpcmVseS4gWW91IG11c3QgcmUtaW5jbHVkZSBhbGwgdGVtcGxhdGUgdmFsdWVzOgoKSW4gdGhl" + - "IHRlbXBsYXRlIGJlbG93LCBgPHByaXZhdGUtdmFsdWVzPmAgcmVmZXJzIHRvIHRoZSBgc2VjcmV0" + - "cy9gIGRpcmVjdG9yeSBhdCB0aGUgaGVsbWZpbGUgc3RhY2sgcm9vdC4KCmBgYHlhbWwKIyBUZW1w" + - "bGF0ZSBkZWZpbmVzOgp0ZW1wbGF0ZXM6CiAgZGVwZW5kZW5jeTogJmRlcGVuZGVuY3kKICAgIGNo" + - "YXJ0OiBudmNmL2hlbG0tbnZjZi17eyAuUmVsZWFzZS5OYW1lIH19CiAgICB2YWx1ZXM6CiAgICAg" + - "IC0gLi4vZ2xvYmFsLnlhbWwuZ290bXBsCiAgICAgIC0gLi4vPHByaXZhdGUtdmFsdWVzPi97eyBy" + - "ZXF1aXJlZEVudiAiSEVMTUZJTEVfRU5WIiB9fS1zZWNyZXRzLnlhbWwKCiMgV2hlbiBvdmVycmlk" + - "aW5nLCBNVVNUIHJlLWluY2x1ZGUgYm90aDoKLSBuYW1lOiBjYXNzYW5kcmEKICA8PDogKmRlcGVu" + - "ZGVuY3kKICB2YWx1ZXM6CiAgICAtIC4uL2dsb2JhbC55YW1sLmdvdG1wbCAgICAgICAgICAgICAg" + - "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIE11c3QgcmUtaW5jbHVkZQogICAgLSAu" + - "Li88cHJpdmF0ZS12YWx1ZXM+L3t7IHJlcXVpcmVkRW52ICJIRUxNRklMRV9FTlYiIH19LXNlY3Jl" + - "dHMueWFtbCAgICMgTXVzdCByZS1pbmNsdWRlCiAgICAtIGNhc3NhbmRyYTogICAgICAgICAgICAg" + - "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBZb3VyIG92ZXJy" + - "aWRlCiAgICAgICAgcmVzb3VyY2VzOgogICAgICAgICAgbGltaXRzOgogICAgICAgICAgICBtZW1v" + - "cnk6IDgxOTJNaQpgYGAKCiMjIyBgaW5oZXJpdGAgKEhlbG1maWxlIG5hdGl2ZSkKClVzZWQgaW4g" + - "YDAyLWNvcmUueWFtbC5nb3RtcGxgLiBIZWxtZmlsZSdzIG5hdGl2ZSBpbmhlcml0YW5jZSBtZWNo" + - "YW5pc20uCgpgYGB5YW1sCi0gbmFtZTogYXBpCiAgdmVyc2lvbjogMS42LjAKICBuYW1lc3BhY2U6" + - "IG52Y2YKICBpbmhlcml0OgogICAgLSB0ZW1wbGF0ZTogc2VydmljZQpgYGAKCldoZW4gYWRkaW5n" + - "IGB2YWx1ZXM6YCB0byBhbiBpbmhlcml0ZWQgcmVsZWFzZSwgeW91IGFsc28gbmVlZCB0byByZS1p" + - "bmNsdWRlIHRoZSB0ZW1wbGF0ZSdzIHZhbHVlcyBmaWxlcyBzaW5jZSBgdmFsdWVzYCBpcyBhIGxp" + - "c3QgdGhhdCBnZXRzIHJlcGxhY2VkLgoKIyMgVmFsdWVzIFByZWNlZGVuY2UKCkZyb20gbG93ZXN0" + - "IHRvIGhpZ2hlc3QgcHJpb3JpdHk6CgoxLiBgZW52aXJvbm1lbnRzL2Jhc2UueWFtbGAgLS0gZGVm" + - "YXVsdHMgc2hhcmVkIGFjcm9zcyBhbGwgZW52aXJvbm1lbnRzCjIuIGBlbnZpcm9ubWVudHMvPGVu" + - "dj4ueWFtbGAgLS0gcGVyLWVudmlyb25tZW50IG92ZXJyaWRlcwozLiBgZ2xvYmFsLnlhbWwuZ290" + - "bXBsYCAtLSBHbyB0ZW1wbGF0ZSBwcm9jZXNzaW5nIChjb25zdHJ1Y3RzIGNoYXJ0LXNwZWNpZmlj" + - "IHN0cnVjdHVyZSkKNC4gYDxwcml2YXRlLXZhbHVlcz4vPGVudj4tc2VjcmV0cy55YW1sYCAtLSBz" + - "ZW5zaXRpdmUgdmFsdWVzCjUuIElubGluZSBgdmFsdWVzOmAgYmxvY2tzIG9uIHJlbGVhc2VzIC0t" + - "IGhpZ2hlc3QgcHJlY2VkZW5jZQoKIyMgV2hhdCBnbG9iYWwueWFtbC5nb3RtcGwgUGFzc2VzIFRo" + - "cm91Z2gKCmBnbG9iYWwueWFtbC5nb3RtcGxgIHJlYWRzIGZyb20gYC5WYWx1ZXNgICh0aGUgbWVy" + - "Z2VkIGVudmlyb25tZW50ICsgZW52LXNwZWNpZmljIFlBTUwpIGFuZCBjb25zdHJ1Y3RzIGNoYXJ0" + - "LXNwZWNpZmljIHZhbHVlcy4gSXQgb25seSBwYXNzZXMgdGhyb3VnaCBrZXlzIGl0IGV4cGxpY2l0" + - "bHkgcmVmZXJlbmNlczoKCiMjIyBDYXNzYW5kcmEKLSBgY2Fzc2FuZHJhLnJlcGxpY2FDb3VudGAK" + - "LSBgY2Fzc2FuZHJhLmltYWdlLipgIChyZWdpc3RyeSwgcmVwb3NpdG9yeSkKLSBgY2Fzc2FuZHJh" + - "Lm1pZ3JhdGlvbnMuaW1hZ2UuKmAKLSBgY2Fzc2FuZHJhLnBlcnNpc3RlbmNlLnNpemVgCi0gYGNh" + - "c3NhbmRyYS5ub2RlU2VsZWN0b3JgIChpZiBgZ2xvYmFsLm5vZGVTZWxlY3RvcnMuZW5hYmxlZGAp" + - "Ci0gYGNhc3NhbmRyYS5nbG9iYWwuZGVmYXVsdFN0b3JhZ2VDbGFzc2AKCiMjIyBOQVRTCi0gYG5h" + - "dHMuY29udGFpbmVyLmltYWdlLipgCi0gYG5hdHMucmVsb2FkZXIuaW1hZ2UuKmAKLSBgbmF0cy5u" + - "YXRzQm94LmNvbnRhaW5lci5pbWFnZS4qYAotIGBuYXRzLmNvbmZpZy5qZXRzdHJlYW0uZmlsZVN0" + - "b3JlLnB2Yy5zdG9yYWdlQ2xhc3NOYW1lYAotIGBuYXRzLnBvZFRlbXBsYXRlLm1lcmdlLnNwZWMu" + - "bm9kZVNlbGVjdG9yYCAoaWYgZW5hYmxlZCkKCiMjIyBPcGVuQmFvCi0gYG9wZW5iYW8ubWlncmF0" + - "aW9ucy5pbWFnZS4qYCBhbmQgYG9wZW5iYW8ubWlncmF0aW9ucy5lbnZgCi0gYG9wZW5iYW8uaW5q" + - "ZWN0b3IuaW1hZ2UuKmAKLSBgb3BlbmJhby5zZXJ2ZXIuaW1hZ2UuKmAKLSBgb3BlbmJhby5zZXJ2" + - "ZXIuZGF0YVN0b3JhZ2UuKmAKLSBOb2RlIHNlbGVjdG9ycyAoaWYgZW5hYmxlZCkKCiMjIyBTZXJ2" + - "aWNlcyAoQVBJLCBTSVMsIGV0Yy4pCi0gYDxzZXJ2aWNlPi5pbWFnZS4qYCAocmVnaXN0cnksIHJl" + - "cG9zaXRvcnkpCi0gYDxzZXJ2aWNlPi5ub2RlU2VsZWN0b3JgIChpZiBlbmFibGVkKQotIGA8c2Vy" + - "dmljZT4uZW52LipgIChvYnNlcnZhYmlsaXR5IHNldHRpbmdzKQoKIyMjIExMTSBGdW5jdGlvbiBF" + - "bmFibGVtZW50CgpFbmFibGUgdGhlIExMTSBhZGRvbiBiZWZvcmUgY3JlYXRpbmcgb3IgaW52b2tp" + - "bmcgZnVuY3Rpb25zIHdpdGgKYGZ1bmN0aW9uVHlwZTogIkxMTSJgLiBUaGUgYWRkb24gZGVwbG95" + - "cyBgbGxtLXJlcXVlc3Qtcm91dGVyYCBhbmQKYGxsbS1hcGktZ2F0ZXdheWAsIGFkZHMgdGhlIGBs" + - "bG0uaW52b2NhdGlvbi48ZG9tYWluPmAgcm91dGUgd2hlbiBHYXRld2F5IEFQSQppbmdyZXNzIGlz" + - "IGVuYWJsZWQsIGFuZCBjb25maWd1cmVzIHdvcmtlcnMgdG8gdXNlIHRoZSBMTE0gc2lkZWNhci4g" + - "VGhlIEhlbG1maWxlCmNvbmRpdGlvbiBpcyBgYWRkb25zLmxsbS5lbmFibGVkYC4gRG8gbm90IHVz" + - "ZSB0aGUgb2Jzb2xldGUgYGxsbS5lbmFibGVkYCBwYXRoLgoKRm9yIGEgc2luZ2xlLW5vZGUgaXNv" + - "bGF0ZWQgdGVzdCBjbHVzdGVyLCBhZGQgdGhpcyBjb25maWd1cmF0aW9uIHRvCmBlbnZpcm9ubWVu" + - "dHMvPGVudj4ueWFtbGAgYmVmb3JlIGFwcGx5aW5nIHRoZSBzdGFjazoKCmBgYHlhbWwKYWRkb25z" + - "OgogIGxsbToKICAgIGVuYWJsZWQ6IHRydWUKICAgIGdhdGV3YXk6CiAgICAgIHJlcGxpY2FDb3Vu" + - "dDogMQogICAgICBtZXRyaWNzOgogICAgICAgIHNlcnZpY2VNb25pdG9yOgogICAgICAgICAgZW5h" + - "YmxlZDogZmFsc2UKICAgIHJlcXVlc3RSb3V0ZXI6CiAgICAgIHJlcGxpY2FDb3VudDogMQogICAg" + - "ICBtZXRyaWNzOgogICAgICAgIHNlcnZpY2VNb25pdG9yOgogICAgICAgICAgZW5hYmxlZDogZmFs" + - "c2UKCmFnZW50Q29uZmlnOgogIG1lcmdlQ29uZmlnOiB8CiAgICBjbHVzdGVyOgogICAgICB2YWxp" + - "ZGF0aW9uUG9saWN5OgogICAgICAgIG5hbWU6IFVucmVzdHJpY3RlZAogICAgd29ya2xvYWQ6CiAg" + - "ICAgIHN0YXJnYXRlUVVJQ0luc2VjdXJlOiB0cnVlCmBgYAoKVXNlIGByZXBsaWNhQ291bnQ6IDFg" + - "IG9ubHkgZm9yIGxvY2FsIG9yIHNpbmdsZS1ub2RlIHRlc3QgY2x1c3RlcnMuIFRoZSBidW5kbGVk" + - "Ck5WQ0YgQVBJIGN1cnJlbnRseSBzZXJ2ZXMgcGxhaW50ZXh0IGdSUEMgb24gcG9ydCA5MDkwLCBz" + - "byB0aGUgc2VsZi1tYW5hZ2VkIHN0YWNrCmRlZmF1bHRzIHRoZSBMTE0gQVBJIEdhdGV3YXkgYXV0" + - "aGVudGljYXRpb24gaG9wIHRvIHBsYWludGV4dC4gU2V0CmBhZGRvbnMubGxtLmdhdGV3YXkuYXV0" + - "aC5ncnBjSW5zZWN1cmU6IGZhbHNlYCBvbmx5IHdpdGggYSBUTFMtY2FwYWJsZSBOVkNGIEFQSS4K" + - "Cldvcmtlci10by1yb3V0ZXIgdHJhbnNwb3J0IGlzIHNlcGFyYXRlLiBGb3Igc2hhcmVkIG9yIHBy" + - "b2R1Y3Rpb24gY2x1c3RlcnMsIHVzZQp0aGUgcmVxdWlyZWQgcmVwbGljYSBjb3VudCBhbmQgdGhl" + - "IG1hbmFnZWQgVExTIGNvbmZpZ3VyYXRpb24uIFRoZQpgd29ya2xvYWQuc3RhcmdhdGVRVUlDSW5z" + - "ZWN1cmVgIHNldHRpbmcgZW5hYmxlcyBwbGFpbnRleHQgd29ya2VyIHRyYW5zcG9ydCBhbmQKbXVz" + - "dCBub3QgYmUgdXNlZCBpbiBwcm9kdWN0aW9uLgoKVGhlIHJlcXVlc3Qgcm91dGVyIHVzZXMgYHBv" + - "d2VyLW9mLXR3b2Agd2hlbiBubyBsb2FkLWJhbGFuY2VyIGNvbmZpZ3VyYXRpb24gaXMKc2V0LiBD" + - "b25maWd1cmUgb3RoZXIgcm91dGluZyBtZXRob2RzIHdpdGggdGhlCltMTE0gUmVxdWVzdCBSb3V0" + - "ZXIgTG9hZCBCYWxhbmNpbmddKGh0dHBzOi8vZ2l0aHViLmNvbS9OVklESUEvbnZjZi9ibG9iL21h" + - "aW4vZG9jcy91c2VyL2xsbS1yZXF1ZXN0LXJvdXRlci1sb2FkLWJhbGFuY2luZy5tZCkKZ3VpZGUu" + - "CgpJZiB0aGUgc2lkZWNhciBpbWFnZSBpcyBtaXJyb3JlZCBvdXRzaWRlIHRoZSBzdGFjaydzIGRl" + - "ZmF1bHQgaW1hZ2UgcmVnaXN0cnkgYW5kCnJlcG9zaXRvcnksIHNldCB0aGUgZ2VuZXJhdGVkIHdv" + - "cmtlciBzaWRlY2FyIGltYWdlIGV4cGxpY2l0bHk6CgpgYGB5YW1sCmFwaToKICByZW1vdGVDb25m" + - "aWc6CiAgICBjb25maWdEYXRhOgogICAgICBudmNmOgogICAgICAgIHNpZGVjYXJzOgogICAgICAg" + - "ICAgbGxtLXJvdXRlci1jbGllbnQtaW1hZ2U6IDxyZWdpc3RyeT4vPHJlcG9zaXRvcnk+L3B5bG9u" + - "OjAuMTQuMQpgYGAKClRoZSBsZWdhY3kgYGFwaS5lbnYuTlZDRl9TSURFQ0FSU19MTE1fUk9VVEVS" + - "X0NMSUVOVF9JTUFHRWAgcGF0aCBpcyBkZXByZWNhdGVkLgpUaGUgc3RhY2sgdHJhbnNsYXRlcyBp" + - "dCBmb3Igb25lIGNvbXBhdGliaWxpdHkgd2luZG93LCBidXQgbmV3IGNvbmZpZ3VyYXRpb25zCm11" + - "c3QgdXNlIHRoZSByZW1vdGUtY29uZmlnIHBhdGguIENvbmZsaWN0aW5nIHZhbHVlcyBmYWlsIHJl" + - "bmRlcmluZy4KClJlbmRlciBhbmQgYXBwbHkgdGhlIHVwZGF0ZWQgY29udHJvbC1wbGFuZSBlbnZp" + - "cm9ubWVudCwgdGhlbiByZWZyZXNoIGV2ZXJ5CnJlZ2lzdGVyZWQgY29tcHV0ZSBwbGFuZSB1c2lu" + - "ZyB0aGUgc2FtZSBoYW5kb2ZmIHVzZWQgZm9yIGl0cyBpbnN0YWxsYXRpb24gc28KTlZDQSByZWNl" + - "aXZlcyBgYWdlbnRDb25maWcubWVyZ2VDb25maWdgOgoKYGBgYmFzaApIRUxNRklMRV9FTlY9PGVu" + - "dj4gaGVsbWZpbGUgdGVtcGxhdGUKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIHN5bmMKYGBg" + - "CgpVc2UgdGhlIGNvbXBsZXRlIGNvbXB1dGUtcGxhbmUgaW5zdGFsbCBjb21tYW5kIGZyb20KW1Nw" + - "bGl0IENvbXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9uXShjb21wdXRlLXBsYW5lLWluc3RhbGxhdGlv" + - "bi5tZCkuIEEKQ0xJLXByb2ZpbGUgaW5zdGFsbGF0aW9uIG11c3QgcmVtYWluIHByb2ZpbGUtZHJp" + - "dmVuOyBhIEhlbG1maWxlIGluc3RhbGxhdGlvbgptdXN0IHJlbWFpbiB2YWx1ZXMtZHJpdmVuLgoK" + - "RXhpc3RpbmcgTExNIGZ1bmN0aW9uIHZlcnNpb25zIHJldGFpbiB0aGUgd29ya2VyLXNpZGVjYXIg" + - "aW1hZ2UgbWV0YWRhdGEKY2FwdHVyZWQgd2hlbiB0aGUgdmVyc2lvbiBpcyBjcmVhdGVkLiBSZXBs" + - "YWNpbmcgcG9kcyBvciByZWRlcGxveWluZyB0aGUgc2FtZQp2ZXJzaW9uIGRvZXMgbm90IGFwcGx5" + - "IGEgbmV3IFB5bG9uIGltYWdlLiBBZnRlciB0aGUgY29udHJvbC1wbGFuZSB1cGRhdGUsCmNyZWF0" + - "ZSBhbmQgZGVwbG95IGEgbmV3IGZ1bmN0aW9uIHZlcnNpb24uIFZlcmlmeSB0aGUgY29udHJvbCBw" + - "bGFuZSwgcm91dGUsIGFuZAp3b3JrZXIgc2lkZWNhcjoKCmBgYGJhc2gKa3ViZWN0bCBnZXQgZGVw" + - "bG95IC1uIG52Y2YgbGxtLWFwaS1nYXRld2F5Cmt1YmVjdGwgZ2V0IHN0YXRlZnVsc2V0IC1uIG52" + - "Y2YgbGxtLXJlcXVlc3Qtcm91dGVyCmt1YmVjdGwgZ2V0IHBvZHMgLW4gbnZjZiB8IGdyZXAgLUUg" + - "J2xsbS1hcGktZ2F0ZXdheXxsbG0tcmVxdWVzdC1yb3V0ZXInCmt1YmVjdGwgZ2V0IGh0dHByb3V0" + - "ZSAtQSB8IGdyZXAgbGxtCmt1YmVjdGwgLW4gbnZjZi1iYWNrZW5kIGdldCBwb2QgPGZ1bmN0aW9u" + - "LXBvZD4gXAogIC1vIGpzb25wYXRoPSd7cmFuZ2UgLnNwZWMuY29udGFpbmVyc1s/KEAubmFtZT09" + - "ImxsbS13b3JrZXIiKV0uYXJnc1sqXX17Ln17IlxcbiJ9e2VuZH0nCmBgYAoKRm9yIGxvY2FsIHBs" + - "YWludGV4dCBjbHVzdGVycywgdGhlIGBsbG0td29ya2VyYCBhcmdzIG11c3QgaW5jbHVkZQpgLS1x" + - "dWljLWluc2VjdXJlYC4KCkZvciBsb2FkLWJhbGFuY2VyIHNjaGVtYSBhbmQgYWxnb3JpdGhtIGJl" + - "aGF2aW9yLCBzZWUgdGhlCltTdGFyZ2F0ZSBjb25maWd1cmF0aW9uIGd1aWRlXShodHRwczovL2dp" + - "dGh1Yi5jb20vTlZJRElBL252Y2YvYmxvYi9tYWluL3NyYy9saWJyYXJpZXMvcnVzdC9zdGFyZ2F0" + - "ZS9kb2NzL2xvYWQtYmFsYW5jZXItY29uZmlndXJhdGlvbi5tZCkuCgojIyBIZWxtZmlsZSBTZWxl" + - "Y3RvcnMKClRhcmdldCBzcGVjaWZpYyByZWxlYXNlcyBvciBncm91cHM6CgpgYGBiYXNoCiMgQnkg" + - "cmVsZWFzZSBncm91cApIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciByZWxl" + - "YXNlLWdyb3VwPWRlcGVuZGVuY2llcyBzeW5jCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAt" + - "LXNlbGVjdG9yIHJlbGVhc2UtZ3JvdXA9c2VydmljZXMgc3luYwpIRUxNRklMRV9FTlY9PGVudj4g" + - "aGVsbWZpbGUgLS1zZWxlY3RvciByZWxlYXNlLWdyb3VwPWluZ3Jlc3Mgc3luYwpIRUxNRklMRV9F" + - "TlY9PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciByZWxlYXNlLWdyb3VwPW9ic2VydmFiaWxpdHkg" + - "c3luYwoKIyBCeSByZWxlYXNlIG5hbWUKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2Vs" + - "ZWN0b3IgbmFtZT1jYXNzYW5kcmEgc3luYwpIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1z" + - "ZWxlY3RvciBuYW1lPWFkbWluLWlzc3Vlci1wcm94eSBzeW5jCkhFTE1GSUxFX0VOVj08ZW52PiBo" + - "ZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9bGxtLXJlcXVlc3Qtcm91dGVyIHN5bmMKSEVMTUZJTEVf" + - "RU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1sbG0tYXBpLWdhdGV3YXkgc3luYwoK" + - "IyBUZW1wbGF0ZSBvbmx5IChkcnkgcnVuKQpIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1z" + - "ZWxlY3RvciBuYW1lPWNhc3NhbmRyYSB0ZW1wbGF0ZQoKIyBEZXN0cm95IGEgc2luZ2xlIHJlbGVh" + - "c2UKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1jYXNzYW5kcmEg" + - "ZGVzdHJveQpgYGAKCk5vdGU6IGBhZG1pbi1pc3N1ZXItcHJveHlgIGhhcyBubyBgcmVsZWFzZS1n" + - "cm91cGAgbGFiZWwuIFVzZSBgLS1zZWxlY3RvciBuYW1lPWFkbWluLWlzc3Vlci1wcm94eWAuClBL" + - "BwjqsuDt+ikAAPopAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAAD8ACQBkYXRhL252Y2Ytc2Vs" + - "Zi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL252Y2YtdWktYWRkb24ubWRVVAUAAQCm" + - "zhIjIE5WQ0YgVUkgQWRkb24KCk5WQ0YgVUkgaXMgYW4gb3B0aW9uYWwsIGN1c3RvbWVyLWZhY2lu" + - "ZyBOVkNGIGFkbWluLXBhbmVsIFVJLiBJdCBpcyBkaXNhYmxlZCBieQpkZWZhdWx0IGFuZCBhdmFp" + - "bGFibGUgb25seSBpbiBzdGFjayBwYWNrYWdlcyB0aGF0IGluY2x1ZGUgdGhlIE5WQ0YgVUkgYWRk" + - "b24uCgojIyBXaGVuIHRvIGVuYWJsZQoKRW5hYmxlIE5WQ0YgVUkgb25seSB3aGVuIHlvdSBuZWVk" + - "IHRoZSBhZG1pbi1wYW5lbCBVSSBhbmQgeW91ciBleHRyYWN0ZWQgc3RhY2sKcGFja2FnZSBpbmNs" + - "dWRlcyB0aGUgYWRkb24uIElmIHRoZSBwYWNrYWdlIGRvZXMgbm90IGNvbnRhaW4gYSBgbnZjZi11" + - "aWAgcmVsZWFzZQphbmQgYG52Y2ZVaWAgcm91dGUgdmFsdWVzLCBza2lwIHRoZSBhZGRvbiB1bnRp" + - "bCB5b3UgdXNlIGEgcGFja2FnZSB0aGF0IGluY2x1ZGVzCnRoZW0uCgojIyBFbmFibGUgdGhlIGFk" + - "ZG9uCgpFbmFibGUgaXQgaW4gYGVudmlyb25tZW50cy88ZW52LW5hbWU+LnlhbWxgOgoKYGBgeWFt" + - "bAphZGRvbnM6CiAgbnZjZlVpOgogICAgZW5hYmxlZDogdHJ1ZQpgYGAKCiMjIENyZWF0ZSBuYW1l" + - "c3BhY2UgYW5kIGltYWdlIHB1bGwgc2VjcmV0CgpDcmVhdGUgdGhlIG5hbWVzcGFjZSwgYW5kIGFu" + - "IGltYWdlIHB1bGwgc2VjcmV0IG9ubHkgaWYgcHVsbGluZyBmcm9tIGEgcHJpdmF0ZQpyZWdpc3Ry" + - "eToKCmBgYGJhc2gKa3ViZWN0bCBjcmVhdGUgbmFtZXNwYWNlIG52Y2YtdWkgLS1kcnktcnVuPWNs" + - "aWVudCAtbyB5YW1sIHwga3ViZWN0bCBhcHBseSAtZiAtCgojIE9ubHkgaWYgcHVsbGluZyBmcm9t" + - "IGEgcHJpdmF0ZSByZWdpc3RyeSAoZS5nLiwgTkdDIG52Y3IuaW8pCmV4cG9ydCBOR0NfQVBJX0tF" + - "WT0iPHlvdXIta2V5PiIKa3ViZWN0bCBjcmVhdGUgc2VjcmV0IGRvY2tlci1yZWdpc3RyeSBudmNy" + - "LWNyZWRzIFwKICAtLWRvY2tlci1zZXJ2ZXI9bnZjci5pbyBcCiAgLS1kb2NrZXItdXNlcm5hbWU9" + - "JyRvYXV0aHRva2VuJyBcCiAgLS1kb2NrZXItcGFzc3dvcmQ9IiROR0NfQVBJX0tFWSIgXAogIC0t" + - "bmFtZXNwYWNlPW52Y2YtdWkgXAogIC0tZHJ5LXJ1bj1jbGllbnQgLW8geWFtbCB8IGt1YmVjdGwg" + - "YXBwbHkgLWYgLQpgYGAKClRoZSBkZWZhdWx0IHJvdXRlIGhvc3QgaXMgYG52Y2YtdWkuPGRvbWFp" + - "bj5gIGFuZCB0aGUgYmFja2VuZCBpcwpgbnZjZi11aS5udmNmLXVpOjgzMDBgLgoKIyMgQXBwbHkg" + - "dGhlIHNlcnZpY2UgYW5kIHJvdXRlCgpBZnRlciBjb25maXJtaW5nIHRoZSBwYWNrYWdlIGluY2x1" + - "ZGVzIHRoZSBgbnZjZi11aWAgcmVsZWFzZSwgcHJldmlldyBhbmQgYXBwbHkKdGhlIHNlcnZpY2Ug" + - "YW5kIHJvdXRlOgoKYGBgYmFzaApIRUxNRklMRV9FTlY9PGVudi1uYW1lPiBoZWxtZmlsZSAtLXNl" + - "bGVjdG9yIG5hbWU9bnZjZi11aSB0ZW1wbGF0ZQpIRUxNRklMRV9FTlY9PGVudi1uYW1lPiBoZWxt" + - "ZmlsZSAtLXNlbGVjdG9yIG5hbWU9bnZjZi11aSBzeW5jCkhFTE1GSUxFX0VOVj08ZW52LW5hbWU+" + - "IGhlbG1maWxlIC0tc2VsZWN0b3IgcmVsZWFzZS1ncm91cD1pbmdyZXNzIHN5bmMKYGBgCgojIyBW" + - "ZXJpZnkKClZlcmlmeSB0aGUgcm91dGUgb25seSB3aGVuIHRoZSBhZGRvbiBpcyBwcmVzZW50IGFu" + - "ZCBlbmFibGVkOgoKYGBgYmFzaAprdWJlY3RsIGdldCBkZXBsb3ksc3ZjIC1uIG52Y2YtdWkKa3Vi" + - "ZWN0bCBnZXQgaHR0cHJvdXRlIC1BIHwgZ3JlcCAtaSBudmNmLXVpCmN1cmwgLWkgLUggIkhvc3Q6" + - "IG52Y2YtdWkuPGRvbWFpbj4iICJodHRwOi8vPGdhdGV3YXktYWRkcmVzcz4vc3RhdHVzIgpgYGAK" + - "CiMjIFNlY3VyaXR5CgpUaGUgTlZDRiBVSSBhZG1pbiBwYW5lbCBpcyBjdXJyZW50bHkgdW5hdXRo" + - "ZW50aWNhdGVkLiBEbyBub3QgZXhwb3NlIGl0IHRvIHRoZQpwdWJsaWMgaW50ZXJuZXQuIFJlc3Ry" + - "aWN0IGFjY2VzcyB0byBhIHRydXN0ZWQgbmV0d29yaywgVlBOLCBvciBhbiBhdXRoZW50aWNhdGlu" + - "Zwpwcm94eSBpbiBmcm9udCBvZiB0aGUgYG52Y2YtdWlgIHJvdXRlLgpQSwcIOPknr7kHAAC5BwAA" + - "UEsDBBQACAAAAAAAIQAAAAAAAAAAAAAAAAA+AAkAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1pbnN0" + - "YWxsYXRpb24vcmVmZXJlbmNlcy9wdWxsLXNlY3JldHMubWRVVAUAAQCmzhIjIEltYWdlIFB1bGwg" + - "U2VjcmV0cyBSZWZlcmVuY2UKCiMjIE92ZXJ2aWV3CgpXaGVuIHB1bGxpbmcgTlZDRiBpbWFnZXMg" + - "ZnJvbSBhIHByaXZhdGUgcmVnaXN0cnkgKGZvciBleGFtcGxlLCBOR0MKYG52Y3IuaW9gKSwgS3Vi" + - "ZXJuZXRlcyBuZWVkcyBgaW1hZ2VQdWxsU2VjcmV0c2Agb24gZXZlcnkgcG9kLiBDb250cm9sLXBs" + - "YW5lIGFuZApjb21wdXRlLXBsYW5lIGNyZWRlbnRpYWxzIGFyZSBjb25maWd1cmVkIGluIHRoZWly" + - "IG93biBjbHVzdGVyIGNvbnRleHRzLiBEbyBub3QKdXNlIG9uZSBtaXhlZCBuYW1lc3BhY2UgbGlz" + - "dC4KClRoZSByZWNvbW1lbmRlZCBjb250cm9sLXBsYW5lIGFwcHJvYWNoIHVzZXMgS3l2ZXJubyB0" + - "byBpbmplY3QgdGhlIHNlY3JldCBpbnRvCmNvbnRyb2wtcGxhbmUgcG9kcyBhdCBhZG1pc3Npb24g" + - "dGltZS4gVGhlIGNvbXB1dGUtcGxhbmUgY2hhcnQgYW5kIG9wZXJhdG9yIHVzZQp0aGUgc2VjcmV0" + - "IGluIGBudmNhLW9wZXJhdG9yYCBhbmQgbWlycm9yIGl0IHRvIGBudmNhLXN5c3RlbWAuCgojIyBL" + - "eXZlcm5vIEFwcHJvYWNoIChSZWNvbW1lbmRlZCkKCiMjIyAxLiBJbnN0YWxsIEt5dmVybm8KCmBg" + - "YGJhc2gKaGVsbSByZXBvIGFkZCBreXZlcm5vIGh0dHBzOi8va3l2ZXJuby5naXRodWIuaW8va3l2" + - "ZXJuby8KaGVsbSByZXBvIHVwZGF0ZQpoZWxtIGluc3RhbGwga3l2ZXJubyBreXZlcm5vL2t5dmVy" + - "bm8gLW4ga3l2ZXJubyAtLWNyZWF0ZS1uYW1lc3BhY2UgXAogIC0ta3ViZS1jb250ZXh0IDxjb250" + - "cm9sLXBsYW5lLWNvbnRleHQ+CmBgYAoKIyMjIDIuIENyZWF0ZSBjb250cm9sLXBsYW5lIHB1bGwg" + - "c2VjcmV0cwoKYGBgYmFzaApleHBvcnQgTkdDX0FQSV9LRVk9Ijx5b3VyLW5nYy1hcGkta2V5PiIK" + - "CmZvciBucyBpbiBjYXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVtIG52Y2YgYXBpLWtleXMgZXNz" + - "IHNpcyB2YXVsdC1zeXN0ZW0gY2VydC1tYW5hZ2VyOyBkbwogIGt1YmVjdGwgLS1jb250ZXh0IDxj" + - "b250cm9sLXBsYW5lLWNvbnRleHQ+IGNyZWF0ZSBuYW1lc3BhY2UgIiRucyIgXAogICAgLS1kcnkt" + - "cnVuPWNsaWVudCAtbyB5YW1sIHwga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29u" + - "dGV4dD4gYXBwbHkgLWYgLQpkb25lCgpmb3IgbnMgaW4gY2Fzc2FuZHJhLXN5c3RlbSBuYXRzLXN5" + - "c3RlbSBudmNmIGFwaS1rZXlzIGVzcyBzaXMgdmF1bHQtc3lzdGVtIGNlcnQtbWFuYWdlcjsgZG8K" + - "ICBrdWJlY3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBjcmVhdGUgc2VjcmV0" + - "IGRvY2tlci1yZWdpc3RyeSBudmNyLWNyZWRzIFwKICAgIC0tZG9ja2VyLXNlcnZlcj1udmNyLmlv" + - "IFwKICAgIC0tZG9ja2VyLXVzZXJuYW1lPSckb2F1dGh0b2tlbicgXAogICAgLS1kb2NrZXItcGFz" + - "c3dvcmQ9IiROR0NfQVBJX0tFWSIgXAogICAgLS1uYW1lc3BhY2U9IiRucyIgXAogICAgLS1kcnkt" + - "cnVuPWNsaWVudCAtbyB5YW1sIHwga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29u" + - "dGV4dD4gYXBwbHkgLWYgLQpkb25lCmBgYAoKRm9yIG5vbi1OR0MgcmVnaXN0cmllcywgcmVwbGFj" + - "ZSBgLS1kb2NrZXItc2VydmVyYCwgYC0tZG9ja2VyLXVzZXJuYW1lYCwgYW5kIGAtLWRvY2tlci1w" + - "YXNzd29yZGAuCgojIyMgMy4gQXBwbHkgS3l2ZXJubyBDbHVzdGVyUG9saWN5CgpgYGB5YW1sCmFw" + - "aVZlcnNpb246IGt5dmVybm8uaW8vdjEKa2luZDogQ2x1c3RlclBvbGljeQptZXRhZGF0YToKICBu" + - "YW1lOiBudmNmLWFkZC1pbWFnZXB1bGxzZWNyZXRzCnNwZWM6CiAgYmFja2dyb3VuZDogZmFsc2UK" + - "ICBydWxlczoKICAgIC0gbmFtZTogYWRkLWltYWdlcHVsbHNlY3JldC10by1udmNmLXBvZHMKICAg" + - "ICAgbWF0Y2g6CiAgICAgICAgYW55OgogICAgICAgIC0gcmVzb3VyY2VzOgogICAgICAgICAgICBr" + - "aW5kczoKICAgICAgICAgICAgLSBQb2QKICAgICAgICAgICAgbmFtZXNwYWNlczoKICAgICAgICAg" + - "ICAgLSAibnZjZiIKICAgICAgICAgICAgLSAiYXBpLWtleXMiCiAgICAgICAgICAgIC0gInNpcyIK" + - "ICAgICAgICAgICAgLSAiZXNzIgogICAgICAgICAgICAtICJuYXRzLXN5c3RlbSIKICAgICAgICAg" + - "ICAgLSAiY2Fzc2FuZHJhLXN5c3RlbSIKICAgICAgICAgICAgLSAidmF1bHQtc3lzdGVtIgogICAg" + - "ICAgICAgICAtICJjZXJ0LW1hbmFnZXIiCiAgICAgIG11dGF0ZToKICAgICAgICBwYXRjaFN0cmF0" + - "ZWdpY01lcmdlOgogICAgICAgICAgbWV0YWRhdGE6CiAgICAgICAgICAgIGFubm90YXRpb25zOgog" + - "ICAgICAgICAgICAgIG52Y2YubnZpZGlhLmNvbS9pbWFnZXB1bGxzZWNyZXQtaW5qZWN0ZWQtYnk6" + - "IGt5dmVybm8KICAgICAgICAgIHNwZWM6CiAgICAgICAgICAgIGltYWdlUHVsbFNlY3JldHM6CiAg" + - "ICAgICAgICAgIC0gbmFtZTogbnZjci1jcmVkcwpgYGAKCmBgYGJhc2gKa3ViZWN0bCAtLWNvbnRl" + - "eHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gYXBwbHkgXAogIC1mIGt5dmVybm8taW1hZ2VwdWxs" + - "c2VjcmV0LXBvbGljeS55YW1sCmBgYAoKIyMjIDQuIEluc3RhbGwgdGhlIGNvbnRyb2wgcGxhbmUK" + - "CkNvbnRpbnVlIHdpdGggdGhlIHNlbGVjdGVkIGNvbnRyb2wtcGxhbmUgaW5zdGFsbGF0aW9uIGlu" + - "CltTcGxpdCBDb21wdXRlLVBsYW5lIEluc3RhbGxhdGlvbl0oY29tcHV0ZS1wbGFuZS1pbnN0YWxs" + - "YXRpb24ubWQpLiBObwpjb250cm9sLXBsYW5lIGhlbG1maWxlIG1vZGlmaWNhdGlvbnMgYXJlIG5l" + - "ZWRlZC4gS3l2ZXJubyBpbmplY3RzIHRoZSBwdWxsCnNlY3JldCBpbnRvIG5ldyBjb250cm9sLXBs" + - "YW5lIHBvZHMuCgojIyBDb21wdXRlLVBsYW5lIFNlY3JldAoKQ3JlYXRlIHRoZSBzZWNyZXQgb25s" + - "eSBpbiBgbnZjYS1vcGVyYXRvcmAgb24gdGhlIGNvbXB1dGUgY2x1c3RlcjoKCmBgYGJhc2gKa3Vi" + - "ZWN0bCAtLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gY3JlYXRlIG5hbWVzcGFjZSBu" + - "dmNhLW9wZXJhdG9yIFwKICAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBcCiAga3ViZWN0bCAt" + - "LWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gYXBwbHkgLWYgLQoKa3ViZWN0bCAtLWNv" + - "bnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gY3JlYXRlIHNlY3JldCBkb2NrZXItcmVnaXN0" + - "cnkgbnZjci1jcmVkcyBcCiAgLS1kb2NrZXItc2VydmVyPW52Y3IuaW8gXAogIC0tZG9ja2VyLXVz" + - "ZXJuYW1lPSckb2F1dGh0b2tlbicgXAogIC0tZG9ja2VyLXBhc3N3b3JkPSIkTkdDX0FQSV9LRVki" + - "IFwKICAtLW5hbWVzcGFjZT1udmNhLW9wZXJhdG9yIFwKICAtLWRyeS1ydW49Y2xpZW50IC1vIHlh" + - "bWwgfCBcCiAga3ViZWN0bCAtLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gYXBwbHkg" + - "LWYgLQpgYGAKClJlZmVyZW5jZSBpdCBpbiB0aGUgY29tcHV0ZS1wbGFuZSBlbnZpcm9ubWVudCBm" + - "aWxlOgoKYGBgeWFtbApnbG9iYWw6CiAgaW1hZ2VQdWxsU2VjcmV0czoKICAgIC0gbmFtZTogbnZj" + - "ci1jcmVkcwpgYGAKClRoZSBjaGFydCBhbmQgb3BlcmF0b3IgdXNlIHRoYXQgcmVmZXJlbmNlIGlu" + - "IGBudmNhLW9wZXJhdG9yYCBhbmQgbWlycm9yIHRoZQpzZWNyZXQgdG8gYG52Y2Etc3lzdGVtYC4g" + - "RG8gbm90IGNyZWF0ZSBhIGJyb2FkZXIgbWFudWFsIGNvbXB1dGUgbmFtZXNwYWNlIGxpc3QuIEZv" + - "bGxvdwpbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKGNvbXB1dGUtcGxhbmUtaW5z" + - "dGFsbGF0aW9uLm1kKSBmb3IgdGhlCnNlbGVjdGVkIGluc3RhbGwgZmxvdy4KCiMjIFZlcmlmaWNh" + - "dGlvbgoKYGBgYmFzaAojIENoZWNrIHRoYXQgYSBjb250cm9sLXBsYW5lIHBvZCBoYXMgdGhlIGlu" + - "amVjdGVkIHNlY3JldAprdWJlY3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBn" + - "ZXQgcG9kIC1uIDxuYW1lc3BhY2U+IDxwb2QtbmFtZT4gXAogIC1vIGpzb25wYXRoPSd7LnNwZWMu" + - "aW1hZ2VQdWxsU2VjcmV0c30nCiMgRXhwZWN0ZWQ6IFt7Im5hbWUiOiJudmNyLWNyZWRzIn1dCgoj" + - "IENoZWNrIHRoZSBLeXZlcm5vIGFubm90YXRpb24Ka3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wt" + - "cGxhbmUtY29udGV4dD4gZ2V0IHBvZCAtbiA8bmFtZXNwYWNlPiA8cG9kLW5hbWU+IFwKICAtbyBq" + - "c29ucGF0aD0ney5tZXRhZGF0YS5hbm5vdGF0aW9ucy5udmNmXC5udmlkaWFcLmNvbS9pbWFnZXB1" + - "bGxzZWNyZXQtaW5qZWN0ZWQtYnl9JwojIEV4cGVjdGVkOiBreXZlcm5vCgojIENoZWNrIHB1bGwg" + - "ZXZlbnRzCmt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGdldCBldmVu" + - "dHMgLW4gPG5hbWVzcGFjZT4gXAogIC0tc29ydC1ieT0nLmxhc3RUaW1lc3RhbXAnIHwgZ3JlcCAt" + - "aSBwdWxsCiMgU2hvdWxkIHNob3cgIlN1Y2Nlc3NmdWxseSBwdWxsZWQiIG5vdCAiNDAxIFVuYXV0" + - "aG9yaXplZCIKCiMgQ2hlY2sgdGhlIGNoYXJ0L29wZXJhdG9yIG1pcnJvciBvbiB0aGUgY29tcHV0" + - "ZSBjbHVzdGVyCmt1YmVjdGwgLS1jb250ZXh0IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IGdldCBz" + - "ZWNyZXQgbnZjci1jcmVkcyBcCiAgLW4gbnZjYS1zeXN0ZW0KYGBgCgojIyBXaGVuIFB1bGwgU2Vj" + - "cmV0cyBBcmUgTm90IE5lZWRlZAoKLSAqKkFXUyBFQ1Igd2l0aCBJQU0gbm9kZSByb2xlcyoqOiBJ" + - "ZiB5b3VyIG5vZGVzIGhhdmUgYEFtYXpvbkVDMkNvbnRhaW5lclJlZ2lzdHJ5UmVhZE9ubHlgIElB" + - "TSBwb2xpY3ksIEt1YmVybmV0ZXMgY2FuIHB1bGwgZnJvbSBFQ1Igd2l0aG91dCBleHBsaWNpdCBz" + - "ZWNyZXRzLgotICoqUHVibGljIHJlZ2lzdHJpZXMqKjogTm8gcHVsbCBzZWNyZXRzIG5lZWRlZC4K" + - "LSAqKkNTUCBidWlsdC1pbiBjcmVkZW50aWFsIGhlbHBlcnMqKjogR0tFIEFydGlmYWN0IFJlZ2lz" + - "dHJ5LCBBenVyZSBBQ1Igd2l0aCBtYW5hZ2VkIGlkZW50aXR5LCBhbmQgc2ltaWxhciBzZXJ2aWNl" + - "cy4KCiMjIFRyb3VibGVzaG9vdGluZwoKIyMjIFBvZHMgc3RpbGwgaW4gSW1hZ2VQdWxsQmFja09m" + - "ZiBhZnRlciBhcHBseWluZyBwb2xpY3kKClRoZSBLeXZlcm5vIHBvbGljeSBvbmx5IGFmZmVjdHMg" + - "cG9kcyBjcmVhdGVkICoqYWZ0ZXIqKiB0aGUgcG9saWN5IGlzIGFwcGxpZWQuIERlbGV0ZSBzdHVj" + - "ayBwb2RzIHRvIHRyaWdnZXIgcmVjcmVhdGlvbjoKCmBgYGJhc2gKa3ViZWN0bCAtLWNvbnRleHQg" + - "PHRhcmdldC1jb250ZXh0PiBkZWxldGUgcG9kcyAtbiA8bmFtZXNwYWNlPiAtLWFsbApgYGAKCiMj" + - "IyBLeXZlcm5vIGFkbWlzc2lvbiBjb250cm9sbGVyIG5vdCBydW5uaW5nCgpgYGBiYXNoCmt1YmVj" + - "dGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGdldCBwb2RzIC1uIGt5dmVybm8K" + - "IyBBbGwgcG9kcyBzaG91bGQgYmUgUnVubmluZwpgYGAKCiMjIyBQb2xpY3kgbm90IG1hdGNoaW5n" + - "CgpgYGBiYXNoCmt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5lLWNvbnRleHQ+IGdldCBj" + - "bHVzdGVycG9saWN5IG52Y2YtYWRkLWltYWdlcHVsbHNlY3JldHMKIyBTaG91bGQgc2hvdyBSRUFE" + - "WTogVHJ1ZQpgYGAKCiMjIyBXcm9uZyBzZWNyZXQgbmFtZQoKVGhlIHBvbGljeSByZWZlcmVuY2Vz" + - "IGBudmNyLWNyZWRzYC4gVmVyaWZ5IHRoZSBzZWNyZXQgZXhpc3RzIHdpdGggdGhhdCBleGFjdCBu" + - "YW1lOgoKYGBgYmFzaAprdWJlY3RsIC0tY29udGV4dCA8dGFyZ2V0LWNvbnRleHQ+IGdldCBzZWNy" + - "ZXQgbnZjci1jcmVkcyAtbiA8bmFtZXNwYWNlPgpgYGAKUEsHCEtCNagAFgAAABYAAFBLAQIUABQA" + - "CAAAAAAAIQClzwe5SRAAAEkQAAASAAkAAAAAAAAAAAAAAAAAAABkYXRhL21hbmlmZXN0Lmpzb25V" + - "VAUAAQCmzhJQSwECFAAUAAgAAAAAACEAzYEw5E1hAABNYQAAIwAJAAAAAAAAAAAAAACSEAAAZGF0" + - "YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvU0tJTEwubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEA" + - "IcbIhvAKAADwCgAAMwAJAAAAAAAAAAAAAAA5cgAAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkv" + - "ZXhhbXBsZXMvY2ktcGlwZWxpbmVzLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhAKEU44FdDAAA" + - "XQwAADQACQAAAAAAAAAAAAAAk30AAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL2V4YW1wbGVz" + - "L211bHRpLWNsdXN0ZXIubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEAQidJDwUNAAAFDQAANwAJ" + - "AAAAAAAAAAAAAABbigAAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy9hZGQtY29t" + - "cHV0ZS1wbGFuZS5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQCR3Bv5mBkAAJgZAAA5AAkAAAAA" + - "AAAAAAAAAM6XAABkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL2NyZWF0ZS1hbmQt" + - "cnVuLXRhc2subWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEA0kPcBBglAAAYJQAANwAJAAAAAAAA" + - "AAAAAADWsQAAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy9kZXBsb3ktYW5kLWlu" + - "dm9rZS5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQAOnD+XvQ4AAL0OAAA9AAkAAAAAAAAAAAAA" + - "AFzXAABkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9wcm9tcHRzL2RpYWdub3NlLWZhaWxlZC1p" + - "bnN0YWxsLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhAEJx5h4BKAAAASgAADoACQAAAAAAAAAA" + - "AAAAjeYAAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Byb21wdHMvaW5zdGFsbC1mcm9tLXNj" + - "cmF0Y2gubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEAGsQsnscHAADHBwAAOQAJAAAAAAAAAAAA" + - "AAD/DgEAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJvbXB0cy9yb3RhdGUtY2x1c3Rlci1q" + - "d2tzLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhABKTM1ngIQAA4CEAAC4ACQAAAAAAAAAAAAAA" + - "NhcBAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Byb21wdHMvdGVhcmRvd24ubWRVVAUAAQCm" + - "zhJQSwECFAAUAAgAAAAAACEAcg0PZCEjAAAhIwAAMAAJAAAAAAAAAAAAAAB7OQEAZGF0YS9udmNm" + - "LXNlbGYtbWFuYWdlZC1jbGkvcmVmZXJlbmNlL2NvbW1hbmRzLm1kVVQFAAEAps4SUEsBAhQAFAAI" + - "AAAAAAAhAHOnWmTVBgAA1QYAADIACQAAAAAAAAAAAAAAA10BAGRhdGEvbnZjZi1zZWxmLW1hbmFn" + - "ZWQtY2xpL3JlZmVyZW5jZS9leGl0LWNvZGVzLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhAORn" + - "scwtJQAALSUAAC0ACQAAAAAAAAAAAAAAQWQBAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3Jl" + - "ZmVyZW5jZS9mbGFncy5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQDzrhOEdBEAAHQRAAA3AAkA" + - "AAAAAAAAAAAAANKJAQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9yZWZlcmVuY2UvdHJvdWJs" + - "ZXNob290aW5nLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhAC/auXVCYgAAQmIAACwACQAAAAAA" + - "AAAAAAAAtJsBAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL1NLSUxMLm1kVVQF" + - "AAEAps4SUEsBAhQAFAAIAAAAAAAhAEdValZKVgAASlYAADQACQAAAAAAAAAAAAAAWf4BAGRhdGEv" + - "bnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL2V2YWxzL2V2YWxzLmpzb25VVAUAAQCmzhJQ" + - "SwECFAAUAAgAAAAAACEAAlJOQH8oAAB/KAAALwAJAAAAAAAAAAAAAAAOVQIAZGF0YS9udmNmLXNl" + - "bGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vZXhhbXBsZXMubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAA" + - "ACEAlmO8WRIwAAASMAAATAAJAAAAAAAAAAAAAADzfQIAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1p" + - "bnN0YWxsYXRpb24vcmVmZXJlbmNlcy9jb21wdXRlLXBsYW5lLWluc3RhbGxhdGlvbi5tZFVUBQAB" + - "AKbOElBLAQIUABQACAAAAAAAIQBWPmeQlTAAAJUwAAA7AAkAAAAAAAAAAAAAAIiuAgBkYXRhL252" + - "Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL2RlYnVnZ2luZy5tZFVUBQAB" + - "AKbOElBLAQIUABQACAAAAAAAIQDqsuDt+ikAAPopAABEAAkAAAAAAAAAAAAAAI/fAgBkYXRhL252" + - "Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL2hlbG1maWxlLXN0cnVjdHVy" + - "ZS5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQA4+SevuQcAALkHAAA/AAkAAAAAAAAAAAAAAAQK" + - "AwBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL252Y2YtdWkt" + - "YWRkb24ubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEAS0I1qAAWAAAAFgAAPgAJAAAAAAAAAAAA" + - "AAAzEgMAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vcmVmZXJlbmNlcy9wdWxs" + - "LXNlY3JldHMubWRVVAUAAQCmzhJQSwUGAAAAABcAFwCvCQAAqCgDAAAA" + "ZHMgcnVubmluZyBidXQgbm90IGluaXRpYWxpemVkKio6IENoZWNrIHVuc2VhbCBzdGF0dXM6Cgog" + + "ICBgYGBiYXNoCiAgIGt1YmVjdGwgZXhlYyAtbiB2YXVsdC1zeXN0ZW0gb3BlbmJhby1zZXJ2ZXIt" + + "MCAtYyBvcGVuYmFvIC0tIGJhbyBzdGF0dXMKICAgYGBgCgo0LiAqKmB2YXVsdC1hZ2VudC1pbml0" + + "YCBsb2dzIGBhdXRoL2p3dC9sb2dpbmAgLT4gYDQwMCAuLi4gbm8ga25vd24ga2V5IHN1Y2Nlc3Nm" + + "dWxseSB2YWxpZGF0ZWQgdGhlIHRva2VuIHNpZ25hdHVyZWAqKgogICAoY29tbW9uIG9uIEFLUywg" + + "YW5kIG9uIGFueSBjbHVzdGVyIHdob3NlIE9JREMgaXNzdWVyIHB1Ymxpc2hlcyBhIHJvdGF0aW5n" + + "IG11bHRpLWtleSBKV0tTKToKICAgdGhlIE9wZW5CYW8gYGF1dGgvand0YCBtZXRob2Qgd2FzIGNv" + + "bmZpZ3VyZWQgd2l0aCBhIHNpbmdsZSBzdGF0aWMgbW91bnRlZCBwdWJsaWMga2V5CiAgIChgand0" + + "X3ZhbGlkYXRpb25fcHVia2V5c2ApIGluc3RlYWQgb2YgdGhlIGlzc3VlcidzIGxpdmUgSldLUywg" + + "c28gaXQgY2Fubm90IHZhbGlkYXRlIHRoZQogICBjbHVzdGVyLXNpZ25lZCBTZXJ2aWNlQWNjb3Vu" + + "dCB0b2tlbnMgdGhlIHZhdWx0LWFnZW50cyBwcmVzZW50LiBFdmVyeSBzZXJ2aWNlJ3MKICAgYHZh" + + "dWx0LWFnZW50LWluaXRgIHRoZW4gbG9vcHMgb24gdGhhdCA0MDAgYW5kIHRoZSBwb2QgbmV2ZXIg" + + "bGVhdmVzIGBJbml0OjAvMWAuIFRoaXMgaXMgdGhlCiAgIGJlaGF2aW9yIG9mIHRoZSBiYXNlIGRl" + + "ZmF1bHQgYG9wZW5iYW8ubWlncmF0aW9ucy5pc3N1ZXJEaXNjb3ZlcnkuZW5hYmxlZDogZmFsc2Vg" + + "OyB0aGUKICAgbWlncmF0aW9uIGxvZyBzaG93cyBgT0lEQyBpc3N1ZXIgZGlzY292ZXJ5IGlzIGRp" + + "c2FibGVkLiBVc2luZyBTZXJ2aWNlQWNjb3VudCBpc3N1ZXIgYW5kCiAgIG1vdW50ZWQgcHVibGlj" + + "IGtleSBmYWxsYmFja2AuIEVuYWJsZSBpc3N1ZXIgZGlzY292ZXJ5IHNvIHRoZSBtaWdyYXRpb24g" + + "dXNlcyB0aGUgbGl2ZSBKV0tTLAogICB0aGVuIHJlLXJ1biBpdDoKCiAgIGBgYGJhc2gKICAgIyBJ" + + "biB5b3VyIGVudiB2YWx1ZXMgKGUuZy4gZW52aXJvbm1lbnRzLzxlbnY+LnlhbWwpLCBzZXQ6CiAg" + + "ICMgICBvcGVuYmFvOgogICAjICAgICBtaWdyYXRpb25zOgogICAjICAgICAgIGlzc3VlckRpc2Nv" + + "dmVyeToKICAgIyAgICAgICAgIGVuYWJsZWQ6IHRydWUKICAga3ViZWN0bCBkZWxldGUgam9iIC1u" + + "IHZhdWx0LXN5c3RlbSBvcGVuYmFvLXNlcnZlci1taWdyYXRpb25zCiAgIEhFTE1GSUxFX0VOVj08" + + "ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9b3BlbmJhby1zZXJ2ZXIgc3luYwogICBgYGAK" + + "CiAgIFRoZSBtaWdyYXRpb24gbG9nIHNob3VsZCB0aGVuIHNob3cgYFJlY2VpdmVkIGRpc2NvdmVy" + + "eSBkb2N1bWVudCBmcm9tCiAgIC4uLi8ud2VsbC1rbm93bi9vcGVuaWQtY29uZmlndXJhdGlvbmAg" + + "YW5kIGBGaW5hbCBPcGVuQmFvIEpXVCBKV0tTIFVSTCBzZXQgdG86CiAgIC4uLi9vcGVuaWQvdjEv" + + "andrc2AsIGFuZCB0aGUgc2VydmljZSBwb2RzIGF1dGhlbnRpY2F0ZSBhbmQgcmVhY2ggUmVhZHkg" + + "d2l0aGluIH4xIG1pbi4KICAgQUtTIGNsdXN0ZXJzIHdpdGggdGhlIGNsdXN0ZXIgT0lEQyBpc3N1" + + "ZXIgZW5hYmxlZCAodGhlIGBha3MtY2x1c3RlcmAgZGVmYXVsdCkgYWx3YXlzIG5lZWQKICAgdGhp" + + "cyBiZWNhdXNlIHRoZSBzdGF0aWMtcHVia2V5IGZhbGxiYWNrIGNhbm5vdCBtYXRjaCB0aGUgaXNz" + + "dWVyJ3Mgcm90YXRpbmcgc2lnbmluZyBrZXlzLgoKIyMgRmFpbHVyZTogT09NS2lsbGVkIG9uIENh" + + "c3NhbmRyYQoKIyMjIFN5bXB0b21zCgpgYGB0ZXh0Ck5BTUUgICAgICAgICAgUkVBRFkgICBTVEFU" + + "VVMgICAgUkVTVEFSVFMgICBBR0UKY2Fzc2FuZHJhLTAgICAwLzEgICAgIE9PTUtpbGxlZCAgMyAg" + + "ICAgICAgIDEwbQpgYGAKCiMjIyBEaWFnbm9zaXMKCmBgYGJhc2gKa3ViZWN0bCBkZXNjcmliZSBw" + + "b2QgLW4gY2Fzc2FuZHJhLXN5c3RlbSBjYXNzYW5kcmEtMCB8IGdyZXAgLUEzICJMYXN0IFN0YXRl" + + "IgpgYGAKCiMjIyBGaXgKCk92ZXJyaWRlIENhc3NhbmRyYSByZXNvdXJjZXMgdmlhIGhlbG1maWxl" + + "IHZhbHVlcy4gU2VlIEV4YW1wbGUgMSBpbgpbZXhhbXBsZXMubWRdKC4uL2V4YW1wbGVzLm1kKS4K" + + "CmBgYHlhbWwKLSBjYXNzYW5kcmE6CiAgICByZXNvdXJjZXM6CiAgICAgIGxpbWl0czoKICAgICAg" + + "ICBjcHU6ICI4IgogICAgICAgIG1lbW9yeTogODE5Mk1pCiAgICAgIHJlcXVlc3RzOgogICAgICAg" + + "IGNwdTogIjIiCiAgICAgICAgbWVtb3J5OiA0MDk2TWkKYGBgCgpOb3RlOiBgcmVzb3VyY2VQcmVz" + + "ZXRgIGlzIG5vdCBhdmFpbGFibGUgaW4gdGhlIE5WQ0YgY2Fzc2FuZHJhIHdyYXBwZXIgY2hhcnQu" + + "IFVzZSBleHBsaWNpdCBgcmVzb3VyY2VzYC4KCiMjIEZhaWx1cmU6IFBvZHMgU3R1Y2sgaW4gUGVu" + + "ZGluZwoKIyMjIFN5bXB0b21zCgpgYGB0ZXh0Ck5BTUUgICAgICAgICAgUkVBRFkgICBTVEFUVVMg" + + "ICAgUkVTVEFSVFMgICBBR0UKY2Fzc2FuZHJhLTAgICAwLzEgICAgIFBlbmRpbmcgICAwICAgICAg" + + "ICAgIDEwbQpgYGAKCiMjIyBEaWFnbm9zaXMKCmBgYGJhc2gKIyBDaGVjayBldmVudHMgZm9yIHNj" + + "aGVkdWxpbmcgZmFpbHVyZXMKa3ViZWN0bCBkZXNjcmliZSBwb2QgLW4gPG5hbWVzcGFjZT4gPHBv" + + "ZC1uYW1lPgoKIyBDb21tb24gY2F1c2VzOgojIC0gIjAvMTIgbm9kZXMgYXJlIGF2YWlsYWJsZTog" + + "MTIgbm9kZShzKSBkaWRuJ3QgbWF0Y2ggUG9kJ3Mgbm9kZSBhZmZpbml0eSIKIyAtICIwLzEyIG5v" + + "ZGVzIGFyZSBhdmFpbGFibGU6IDEyIEluc3VmZmljaWVudCBtZW1vcnkiCiMgLSAicGVyc2lzdGVu" + + "dHZvbHVtZWNsYWltIG5vdCBmb3VuZCIKYGBgCgojIyMgRml4ZXMKCjEuICoqTm9kZSBzZWxlY3Rv" + + "ciBtaXNtYXRjaCoqOiBDaGVjayBgbm9kZVNlbGVjdG9yc2AgaW4gZW52aXJvbm1lbnQgZmlsZQoK" + + "ICAgYGBgYmFzaAogICBrdWJlY3RsIGdldCBub2RlcyAtLXNob3ctbGFiZWxzIHwgZ3JlcCBudmNm" + + "CiAgIGBgYAoKMi4gKipTdG9yYWdlIGNsYXNzIG5vdCBmb3VuZCoqOiBDaGVjayBzdG9yYWdlIGNs" + + "YXNzIGV4aXN0cwoKICAgYGBgYmFzaAogICBrdWJlY3RsIGdldCBzdG9yYWdlY2xhc3MKICAgYGBg" + + "CgozLiAqKkluc3VmZmljaWVudCByZXNvdXJjZXMqKjogQ2hlY2sgbm9kZSBjYXBhY2l0eQoKICAg" + + "YGBgYmFzaAogICBrdWJlY3RsIGRlc2NyaWJlIG5vZGUgPG5vZGUtbmFtZT4gfCBncmVwIC1BNSAi" + + "QWxsb2NhdGVkIHJlc291cmNlcyIKICAgYGBgCgojIyBGYWlsdXJlOiBIZWxtIFJlbGVhc2UgaW4g" + + "RmFpbGVkIFN0YXRlCgojIyMgU3ltcHRvbXMKCmBgYGJhc2gKaGVsbSBsaXN0IC1BCiMgU2hvd3Mg" + + "cmVsZWFzZSB3aXRoIFNUQVRVUzogZmFpbGVkCmBgYAoKUmUtcnVubmluZyBgaGVsbWZpbGUgc3lu" + + "Y2AgYXBwZWFycyB0byBzdWNjZWVkIGJ1dCBzZXJ2aWNlcyBkb24ndCB3b3JrIChtaWdyYXRpb25z" + + "IHNraXBwZWQpLgoKIyMjIERpYWdub3NpcwoKYGBgYmFzaApoZWxtIGhpc3RvcnkgPHJlbGVhc2Ut" + + "bmFtZT4gLW4gPG5hbWVzcGFjZT4KYGBgCgojIyMgRml4CgpNdXN0IGRlc3Ryb3kgdGhlIGZhaWxl" + + "ZCByZWxlYXNlIGFuZCByZS1zeW5jIChub3QganVzdCBhcHBseSk6CgpgYGBiYXNoCkhFTE1GSUxF" + + "X0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9PHJlbGVhc2U+IGRlc3Ryb3kKIyBJ" + + "ZiBuYW1lc3BhY2UgbmVlZHMgY2xlYW51cDoKa3ViZWN0bCBkZWxldGUgbmFtZXNwYWNlIDxuYW1l" + + "c3BhY2U+Cmt1YmVjdGwgY3JlYXRlIG5hbWVzcGFjZSA8bmFtZXNwYWNlPgojIFJlLWNyZWF0ZSBw" + + "dWxsIHNlY3JldCBpZiBuZWVkZWQKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0" + + "b3IgbmFtZT08cmVsZWFzZT4gc3luYwpgYGAKCiMjIEZhaWx1cmU6IEFjY291bnQgQm9vdHN0cmFw" + + "IEpvYiBGYWlsZWQKCiMjIyBTeW1wdG9tcwoKU2VydmljZXMgZGVwbG95IGJ1dCBmdW5jdGlvbnMg" + + "Y2FuJ3QgYmUgY3JlYXRlZC4gRXZlbnRzIHNob3cgYm9vdHN0cmFwIGpvYiBmYWlsdXJlLgoKIyMj" + + "IERpYWdub3NpcwoKYGBgYmFzaAojIENoZWNrIGJvb3RzdHJhcCBqb2Igc3RhdHVzCmt1YmVjdGwg" + + "Z2V0IGpvYnMgLW4gbnZjZgoKIyBHZXQgbG9ncyAoam9iIGF1dG8tZGVsZXRlcyBhZnRlciB+NSBt" + + "aW51dGVzKQprdWJlY3RsIGxvZ3Mgam9iL252Y2YtYXBpLWFjY291bnQtYm9vdHN0cmFwIC1uIG52" + + "Y2YKCiMgQ2hlY2sgQVBJIGxvZ3MKa3ViZWN0bCBsb2dzIC1uIG52Y2YgLWwgYXBwLmt1YmVybmV0" + + "ZXMuaW8vbmFtZT1udmNmLWFwaSAtLXRhaWw9MTAwCmBgYAoKIyMjIENvbW1vbiBDYXVzZXMKCjEu" + + "ICoqV3JvbmcgYmFzZTY0IGNyZWRlbnRpYWxzKio6IENyZWRlbnRpYWxzIGluIGBzZWNyZXRzLzxl" + + "bnY+LXNlY3JldHMueWFtbGAgbXVzdCBiZSBgJG9hdXRodG9rZW46QVBJX0tFWWAgYmFzZTY0LWVu" + + "Y29kZWQsIG5vdCBqdXN0IHRoZSBBUEkga2V5CgogICBgYGBiYXNoCiAgICMgVmVyaWZ5IHlvdXIg" + + "ZW5jb2RlZCBjcmVkZW50aWFsCiAgIGVjaG8gJ1lPVVJfQkFTRTY0X1NUUklORycgfCBiYXNlNjQg" + + "LWQKICAgIyBTaG91bGQgb3V0cHV0OiAkb2F1dGh0b2tlbjpudmFwaS14eHh4eAogICBgYGAKCjIu" + + "ICoqUmVnaXN0cnkgdW5yZWFjaGFibGUqKjogQVBJIGNhbid0IHJlYWNoIHRoZSByZWdpc3RyeSBz" + + "cGVjaWZpZWQgaW4gYGFjY291bnRCb290c3RyYXAucmVnaXN0cnlDcmVkZW50aWFsc2AKCiMjIyBG" + + "aXgKCkZpeCBjcmVkZW50aWFscyBpbiBzZWNyZXRzIGZpbGUsIHRoZW4gcmVjb3ZlciBzZXJ2aWNl" + + "cyB3aXRob3V0IGRlc3Ryb3lpbmcgZGVwZW5kZW5jaWVzOgoKYGBgYmFzaApIRUxNRklMRV9FTlY9" + + "PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciByZWxlYXNlLWdyb3VwPXNlcnZpY2VzIGRlc3Ryb3kK" + + "a3ViZWN0bCBkZWxldGUgbmFtZXNwYWNlIG52Y2YgYXBpLWtleXMgZXNzIHNpcyAtLWlnbm9yZS1u" + + "b3QtZm91bmQKa3ViZWN0bCBjcmVhdGUgbmFtZXNwYWNlIG52Y2YgJiYga3ViZWN0bCBjcmVhdGUg" + + "bmFtZXNwYWNlIGFwaS1rZXlzICYmIFwKICBrdWJlY3RsIGNyZWF0ZSBuYW1lc3BhY2UgZXNzICYm" + + "IGt1YmVjdGwgY3JlYXRlIG5hbWVzcGFjZSBzaXMKIyBSZS1jcmVhdGUgcHVsbCBzZWNyZXRzIGlm" + + "IG5lZWRlZApIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciByZWxlYXNlLWdy" + + "b3VwPXNlcnZpY2VzIHN5bmMKYGBgCgojIyBGYWlsdXJlOiBOVkNBIENsZWFudXAgU3R1Y2sgKEZp" + + "bmFsaXplcnMpCgojIyMgU3ltcHRvbXMKCkNvbXB1dGUtcGxhbmUgY2xlYW51cCBoYW5ncy4gTmFt" + + "ZXNwYWNlcwpzdHVjayBpbiBgVGVybWluYXRpbmdgOgoKYGBgYmFzaAprdWJlY3RsIGdldCBucwoj" + + "IG52Y2Etb3BlcmF0b3IgICAgVGVybWluYXRpbmcgICAxMG0KIyBudmNmLWJhY2tlbmQgICAgIFRl" + + "cm1pbmF0aW5nICAgMTBtCmBgYAoKIyMjIEZpeAoKUnVuIHRoaXMgb25seSBhZ2FpbnN0IHRoZSBj" + + "b21wdXRlIGNvbnRleHQsIGFmdGVyIHRoZSBub3JtYWwgY29tcHV0ZS1wbGFuZQp0ZWFyZG93biBo" + + "YXMgZmFpbGVkLiBSZW1vdmUgZmluYWxpemVycyBmcm9tIE5WQ0ZCYWNrZW5kIGN1c3RvbSByZXNv" + + "dXJjZXMgYW5kCmZvcmNlLWRlbGV0ZSBzdHVjayBuYW1lc3BhY2VzOgoKYGBgYmFzaApleHBvcnQg" + + "Q09NUFVURV9DT05URVhUPTxjb21wdXRlLXBsYW5lLWNvbnRleHQ+CgojIFJlbW92ZSBmaW5hbGl6" + + "ZXJzIGZyb20gTlZDRkJhY2tlbmQgcmVzb3VyY2VzCmt1YmVjdGwgLS1jb250ZXh0ICIkQ09NUFVU" + + "RV9DT05URVhUIiBnZXQgbnZjZmJhY2tlbmRzIC1BIC1vIGpzb24gfCBcCiAganEgJy5pdGVtc1td" + + "IHwgLm1ldGFkYXRhLm5hbWVzcGFjZSArICIvIiArIC5tZXRhZGF0YS5uYW1lJyAtciB8IFwKICB4" + + "YXJncyAtSXt9IHNoIC1jICdjb250ZXh0PSIkMSI7IG5zPSIkezIlJS8qfSI7IG5hbWU9IiR7MiMj" + + "Ki99Ijsga3ViZWN0bCAtLWNvbnRleHQgIiRjb250ZXh0IiBwYXRjaCBudmNmYmFja2VuZCAiJG5h" + + "bWUiIC1uICIkbnMiIC0tdHlwZT1tZXJnZSAtcCAie1wibWV0YWRhdGFcIjp7XCJmaW5hbGl6ZXJz" + + "XCI6W119fSInIF8gIiRDT01QVVRFX0NPTlRFWFQiIHt9CgojIEZvcmNlLWRlbGV0ZSBzdHVjayBu" + + "YW1lc3BhY2VzIGJ5IGNsZWFyaW5nIHRoZWlyIGZpbmFsaXplcnMKZm9yIG5zIGluIG52Y2Etb3Bl" + + "cmF0b3IgbnZjZi1iYWNrZW5kOyBkbwogIGt1YmVjdGwgLS1jb250ZXh0ICIkQ09NUFVURV9DT05U" + + "RVhUIiBnZXQgbmFtZXNwYWNlICIkbnMiIC1vIGpzb24gMj4vZGV2L251bGwgfCBcCiAgICBqcSAn" + + "LnNwZWMuZmluYWxpemVycyA9IFtdJyB8IFwKICAgIGt1YmVjdGwgLS1jb250ZXh0ICIkQ09NUFVU" + + "RV9DT05URVhUIiByZXBsYWNlIFwKICAgICAgLS1yYXcgIi9hcGkvdjEvbmFtZXNwYWNlcy8kbnMv" + + "ZmluYWxpemUiIC1mIC0gMj4vZGV2L251bGwKZG9uZQpgYGAKCiMjIEZhaWx1cmU6IE5WQ0EgT3Bl" + + "cmF0b3IgTWlzc2luZyBvciBOb3QgUmVhZHkKCiMjIyBTeW1wdG9tcwoKQWZ0ZXIgY29tcHV0ZS1w" + + "bGFuZSBpbnN0YWxsIGNvbXBsZXRlcywgbm8gYG52Y2Etb3BlcmF0b3JgIERlcGxveW1lbnQgZXhp" + + "c3RzLCBvcgppdCBleGlzdHMgYnV0IHBvZHMgYXJlIG5vdCByZWFkeToKCmBgYGJhc2gKa3ViZWN0" + + "bCAtLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gZ2V0IGRlcGxveW1lbnQgbnZjYS1v" + + "cGVyYXRvciBcCiAgLW4gbnZjYS1vcGVyYXRvcgprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1w" + + "bGFuZS1jb250ZXh0PiBnZXQgcG9kcyAtbiBudmNhLW9wZXJhdG9yCmBgYAoKIyMjIERpYWdub3Np" + + "cyBhbmQgRml4ZXMKCkZpcnN0IGlkZW50aWZ5IHdoZXRoZXIgdGhlIGluc3RhbGxhdGlvbiB1c2Vk" + + "IHRoZSBIZWxtZmlsZSB2YWx1ZXMgZmxvdyBvciB0aGUKQ0xJIHByb2ZpbGUgZmxvdy4gUmUtcnVu" + + "IG9ubHkgdGhhdCBmbG93J3MgcmVnaXN0cmF0aW9uIGFuZCBpbnN0YWxsYXRpb24gc3RlcHMKZnJv" + + "bSBbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKGNvbXB1dGUtcGxhbmUtaW5zdGFs" + + "bGF0aW9uLm1kKS4gRG8gbm90CnN1YnN0aXR1dGUgb25lIGhhbmRvZmYgZm9yIHRoZSBvdGhlci4K" + + "CklmIGluc3RhbGxhdGlvbiBzdWNjZWVkcyBidXQgcG9kcyBzdGlsbCBmYWlsLCBpbnNwZWN0IHRo" + + "ZSBjb21wdXRlIGNvbnRleHQ6CgpgYGBiYXNoCmt1YmVjdGwgLS1jb250ZXh0IDxjb21wdXRlLXBs" + + "YW5lLWNvbnRleHQ+IGRlc2NyaWJlIGRlcGxveSBudmNhLW9wZXJhdG9yIFwKICAtbiBudmNhLW9w" + + "ZXJhdG9yCmt1YmVjdGwgLS1jb250ZXh0IDxjb21wdXRlLXBsYW5lLWNvbnRleHQ+IGxvZ3MgZGVw" + + "bG95bWVudC9udmNhLW9wZXJhdG9yIFwKICAtbiBudmNhLW9wZXJhdG9yIC0tdGFpbD0yMDAKa3Vi" + + "ZWN0bCAtLWNvbnRleHQgPGNvbXB1dGUtcGxhbmUtY29udGV4dD4gZ2V0IG52Y2ZiYWNrZW5kIC1u" + + "IG52Y2Etb3BlcmF0b3IKYGBgCgpGb3IgcHJpdmF0ZSByZWdpc3RyeSBmYWlsdXJlcywgdmVyaWZ5" + + "IHRoYXQgdGhlIHB1bGwgc2VjcmV0IGV4aXN0cyBpbgpgbnZjYS1vcGVyYXRvcmAuIFRoZSBjaGFy" + + "dCBhbmQgb3BlcmF0b3IgbWlycm9yIGl0IHRvIGBudmNhLXN5c3RlbWA7IGRvIG5vdCB1c2UgYQpi" + + "cm9hZGVyIG1hbnVhbCBuYW1lc3BhY2UgbG9vcC4gU2VlCltwdWxsLXNlY3JldHMubWRdKHB1bGwt" + + "c2VjcmV0cy5tZCNjb21wdXRlLXBsYW5lLXNlY3JldCkuCgojIyBGYWlsdXJlOiBHYXRld2F5IEVu" + + "ZHBvaW50IENoYW5nZWQKCiMjIyBTeW1wdG9tcwoKUmVxdWVzdHMgdGhyb3VnaCB0aGUgY29uZmln" + + "dXJlZCByb3V0ZSBkb21haW4gZmFpbCBhZnRlciB0aGUgR2F0ZXdheSBvciBpdHMgbG9hZCBiYWxh" + + "bmNlciBpcyByZXBsYWNlZC4gVGhlIEdhdGV3YXkgcmVwb3J0cyBhIG5ldyBlbmRwb2ludC4KCiMj" + + "IyBEaWFnbm9zaXMKCmBgYGJhc2gKR0FURVdBWV9BRERSPSQoa3ViZWN0bCAtLWNvbnRleHQgPGNv" + + "bnRyb2wtcGxhbmUtY29udGV4dD4gZ2V0IGdhdGV3YXkgXAogIG52Y2YtZ2F0ZXdheSAtbiBlbnZv" + + "eS1nYXRld2F5IFwKICAtbyBqc29ucGF0aD0ney5zdGF0dXMuYWRkcmVzc2VzWzBdLnZhbHVlfScp" + + "CnRlc3QgLW4gIiRHQVRFV0FZX0FERFIiCmRpZyArc2hvcnQgImFwaS48ZG9tYWluPiIKY3VybCAt" + + "SCAiSG9zdDogYXBpLjxkb21haW4+IiAiaHR0cDovLyRHQVRFV0FZX0FERFIvaGVhbHRoIgoKIyBD" + + "aGVjayBkaXJlY3QgYWRkcmVzcyBmaWVsZHMgdXNlZCBieSBhIHNwbGl0IGRlcGxveW1lbnQKZ3Jl" + + "cCBudmNmTmF0c1NlcnZpY2VVUkwgZGVwbG95L3N0YWNrcy9zZWxmLW1hbmFnZWQvZW52aXJvbm1l" + + "bnRzLzxlbnY+LnlhbWwKZ3JlcCAtRSAnaWNtc1NlcnZpY2V8cmV2YWxTZXJ2aWNlfG5hdHMnIFwK" + + "ICBkZXBsb3kvc3RhY2tzL252Y2YtY29tcHV0ZS1wbGFuZS9lbnZpcm9ubWVudHMvPGVudj4ueWFt" + + "bApgYGAKCiMjIyBGaXgKCktlZXAgYGdsb2JhbC5kb21haW5gLCByb3V0ZSBob3N0bmFtZXMsIGFu" + + "ZCBIb3N0IG92ZXJyaWRlcyB1bmNoYW5nZWQuIFVwZGF0ZSBETlMKb3IgdGhlIGRpcmVjdCBjbGll" + + "bnQgZGVzdGluYXRpb24uIEZvciBzcGxpdCBkZXBsb3ltZW50cywgdXBkYXRlIG9ubHkgZGlyZWN0" + + "CkdhdGV3YXktYWRkcmVzcyBmaWVsZHMgYW5kIHJlZnJlc2ggcmVnaXN0cmF0aW9uIGFuZCBpbnN0" + + "YWxsYXRpb24gdGhyb3VnaCB0aGUKc2FtZSBzZWxlY3RlZCBoYW5kb2ZmLiBTZWUKW0V4YW1wbGUg" + + "NF0oLi4vZXhhbXBsZXMubWQjZXhhbXBsZS00LXJlY292ZXItZnJvbS1hLWdhdGV3YXktZW5kcG9p" + + "bnQtY2hhbmdlKS4KCiMjIFVzZWZ1bCBOYW1lc3BhY2UtdG8tU2VydmljZSBNYXBwaW5nCgpRdWlj" + + "ayByZWZlcmVuY2UgZm9yIHdoaWNoIHNlcnZpY2VzIHJ1biBpbiB3aGljaCBuYW1lc3BhY2U6Cgp8" + + "IE5hbWVzcGFjZSB8IFNlcnZpY2VzIHwKfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS18CnwgbmF0cy1z" + + "eXN0ZW0gfCBuYXRzIHwKfCBjYXNzYW5kcmEtc3lzdGVtIHwgY2Fzc2FuZHJhIHwKfCB2YXVsdC1z" + + "eXN0ZW0gfCBvcGVuYmFvLXNlcnZlciB8CnwgbnZjZiB8IGFwaSwgaW52b2NhdGlvbi1zZXJ2aWNl" + + "LCBncnBjLXByb3h5LCBub3Rhcnktc2VydmljZSwgcmV2YWwsIGxsbS1yZXF1ZXN0LXJvdXRlciwg" + + "bGxtLWFwaS1nYXRld2F5IHwKfCBhcGkta2V5cyB8IGFwaS1rZXlzLCBhZG1pbi1pc3N1ZXItcHJv" + + "eHkgfAp8IGVzcyB8IGVzcy1hcGkgfAp8IHNpcyB8IHNpcyB8CnwgZW52b3ktZ2F0ZXdheS1zeXN0" + + "ZW0gfCBlbnZveSBnYXRld2F5IChpbmdyZXNzIGNvbnRyb2xsZXIpIHwKfCBlbnZveS1nYXRld2F5" + + "IHwgZ2F0ZXdheSByZXNvdXJjZSArIHJvdXRlcyB8ClBLBwi1enA7tTAAALUwAABQSwMEFAAIAAAA" + + "AAAhAAAAAAAAAAAAAAAAAEQACQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9y" + + "ZWZlcmVuY2VzL2hlbG1maWxlLXN0cnVjdHVyZS5tZFVUBQABAKbOEiMgSGVsbWZpbGUgU3RydWN0" + + "dXJlIFJlZmVyZW5jZQoKIyMgRGlyZWN0b3J5IExheW91dAoKYGBgYmFzaApudmNmLXNlbGYtbWFu" + + "YWdlZC1zdGFjay8KfC0tIGhlbG1maWxlLmQvCnwgICB8LS0gMDEtZGVwZW5kZW5jaWVzLnlhbWwu" + + "Z290bXBsICAjIE5BVFMsIENhc3NhbmRyYSwgT3BlbkJhbwp8ICAgfC0tIDAyLWNvcmUueWFtbC5n" + + "b3RtcGwgICAgICAgICAgIyBOVkNGIHNlcnZpY2VzICsgaW5ncmVzcwp8ICAgYC0tIDAzLW9ic2Vy" + + "dmFiaWxpdHkueWFtbC5nb3RtcGwgIyBPYnNlcnZhYmlsaXR5IHN0YWNrIChvcHRpb25hbCkKfC0t" + + "IGVudmlyb25tZW50cy8KfCAgIHwtLSBiYXNlLnlhbWwgICAgICAgICAgICAgICAgICAgICMgRGVm" + + "YXVsdCB2YWx1ZXMgKGFsbCBlbnZpcm9ubWVudHMpCnwgICBgLS0gPGVudi1uYW1lPi55YW1sICAg" + + "ICAgICAgICAgICAjIFBlci1lbnZpcm9ubWVudCBvdmVycmlkZXMKfC0tIHNlY3JldHMvCnwgICBg" + + "LS0gPGVudi1uYW1lPi1zZWNyZXRzLnlhbWwgICAgICAjIFNlbnNpdGl2ZSB2YWx1ZXMgKHJlZ2lz" + + "dHJ5IGNyZWRzLCBwYXNzd29yZHMpCmAtLSBnbG9iYWwueWFtbC5nb3RtcGwgICAgICAgICAgICAg" + + "ICAjIEdvIHRlbXBsYXRlIHRoYXQgY29uc3RydWN0cyBwZXItY2hhcnQgdmFsdWVzCgpudmNmLWNv" + + "bXB1dGUtcGxhbmUtc3RhY2svCnwtLSBoZWxtZmlsZS5kLwp8ICAgfC0tIDAxLWRlcGVuZGVuY2ll" + + "cy55YW1sLmdvdG1wbCAgIyBDb21wdXRlIHBsYW5lIGRlcGVuZGVuY3kgY29tcG9uZW50cwp8ICAg" + + "YC0tIDAyLW52Y2EueWFtbC5nb3RtcGwgICAgICAgICAgIyBudmNhLW9wZXJhdG9yIGNoYXJ0IGFu" + + "ZCBudmNhIGNvbmZpZ3VyYXRpb24KfC0tIGVudmlyb25tZW50cy8KfCAgIHwtLSBiYXNlLnlhbWwg" + + "ICAgICAgICAgICAgICAgICAgICMgRGVmYXVsdCB2YWx1ZXMgKGFsbCBlbnZpcm9ubWVudHMpCnwg" + + "ICBgLS0gPGVudi1uYW1lPi55YW1sICAgICAgICAgICAgICAjIFBlci1lbnZpcm9ubWVudCBvdmVy" + + "cmlkZXMKYC0tIGdsb2JhbC55YW1sLmdvdG1wbCAgICAgICAgICAgICAgICMgR28gdGVtcGxhdGUg" + + "dGhhdCBjb25zdHJ1Y3RzIHBlci1jaGFydCB2YWx1ZXMKYGBgCgpUaGVzZSBzdGFja3MgaGF2ZSBz" + + "ZXBhcmF0ZSBlbnZpcm9ubWVudHMgYW5kIGNsdXN0ZXIgY29udGV4dHMuIFRoZSBIZWxtZmlsZQp2" + + "YWx1ZXMgZmxvdyBhdXRob3JzIGJvdGggZW52aXJvbm1lbnQgZmlsZXMuIFRoZSBDTEkgcHJvZmls" + + "ZSBmbG93IGluc3RlYWQgdXNlcwp0aGUgQ0xJLWdlbmVyYXRlZCBjb250cm9sLXBsYW5lIHByb2Zp" + + "bGUgYXMgaXRzIGVuZHBvaW50IHNvdXJjZS4gRG8gbm90IG1peCB0aGUKaGFuZG9mZnMuIFNlZSBb" + + "U3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKGNvbXB1dGUtcGxhbmUtaW5zdGFsbGF0" + + "aW9uLm1kKS4KCiMjIEdvdG1wbCBGaWxlcyBhbmQgVGhlaXIgUmVsZWFzZXMKCiMjIyAwMS1kZXBl" + + "bmRlbmNpZXMueWFtbC5nb3RtcGwKCnwgUmVsZWFzZSB8IENoYXJ0IHwgTmFtZXNwYWNlIHwgTm90" + + "ZXMgfAp8LS0tLS0tLS0tfC0tLS0tLS18LS0tLS0tLS0tLS18LS0tLS0tLXwKfCBuYXRzIHwgaGVs" + + "bS1udmNmLW5hdHMgfCBuYXRzLXN5c3RlbSB8IE1lc3NhZ2luZyB8Cnwgb3BlbmJhby1zZXJ2ZXIg" + + "fCBoZWxtLW52Y2Ytb3BlbmJhby1zZXJ2ZXIgfCB2YXVsdC1zeXN0ZW0gfCBTZWNyZXRzIG1hbmFn" + + "ZW1lbnQsIGRlcGVuZHMgb24gbmF0cyB8CnwgY2Fzc2FuZHJhIHwgaGVsbS1udmNmLWNhc3NhbmRy" + + "YSB8IGNhc3NhbmRyYS1zeXN0ZW0gfCBEYXRhYmFzZSB8CgpVc2VzIGA8PDogKmRlcGVuZGVuY3lg" + + "IHRlbXBsYXRlIGluaGVyaXRhbmNlIHdpdGggYHJlbGVhc2UtZ3JvdXA6IGRlcGVuZGVuY2llc2Ag" + + "bGFiZWwuCgojIyMgMDItY29yZS55YW1sLmdvdG1wbAoKfCBSZWxlYXNlIHwgQ2hhcnQgfCBOYW1l" + + "c3BhY2UgfCBMYWJlbCB8CnwtLS0tLS0tLS18LS0tLS0tLXwtLS0tLS0tLS0tLXwtLS0tLS0tfAp8" + + "IGFwaS1rZXlzIHwgaGVsbS1udmNmLWFwaS1rZXlzIHwgYXBpLWtleXMgfCBzZXJ2aWNlcyB8Cnwg" + + "c2lzIHwgaGVsbS1udmNmLXNpcyB8IHNpcyB8IHNlcnZpY2VzIHwKfCBhcGkgfCBoZWxtLW52Y2Yt" + + "YXBpIHwgbnZjZiB8IHNlcnZpY2VzIHwKfCBpbnZvY2F0aW9uLXNlcnZpY2UgfCBoZWxtLW52Y2Yt" + + "aW52b2NhdGlvbi1zZXJ2aWNlIHwgbnZjZiB8IHNlcnZpY2VzIHwKfCBncnBjLXByb3h5IHwgaGVs" + + "bS1udmNmLWdycGMtcHJveHkgfCBudmNmIHwgc2VydmljZXMgfAp8IGVzcy1hcGkgfCBoZWxtLW52" + + "Y2YtZXNzLWFwaSB8IGVzcyB8IHNlcnZpY2VzIHwKfCBub3Rhcnktc2VydmljZSB8IGhlbG0tbnZj" + + "Zi1ub3Rhcnktc2VydmljZSB8IG52Y2YgfCBzZXJ2aWNlcyB8CnwgcmV2YWwgfCBoZWxtLXJldmFs" + + "IHwgbnZjZiB8IHNlcnZpY2VzIHwKfCBsbG0tcmVxdWVzdC1yb3V0ZXIgfCBudmNmL2hlbG0tbnZj" + + "Zi1sbG0tcmVxdWVzdC1yb3V0ZXIgfCBudmNmIHwgc2VydmljZXMgfAp8IGxsbS1hcGktZ2F0ZXdh" + + "eSB8IG52Y2YvaGVsbS1udmNmLWxsbS1hcGktZ2F0ZXdheSB8IG52Y2YgfCBzZXJ2aWNlcyB8Cnwg" + + "YWRtaW4taXNzdWVyLXByb3h5IHwgaGVsbS1hZG1pbi10b2tlbi1pc3N1ZXItcHJveHkgfCBhcGkt" + + "a2V5cyB8IChubyByZWxlYXNlLWdyb3VwIGxhYmVsKSB8CnwgaW5ncmVzcyB8IG52Y2YtZ2F0ZXdh" + + "eS1yb3V0ZXMgfCBlbnZveS1nYXRld2F5LXN5c3RlbSB8IGluZ3Jlc3MgfAoKTW9zdCBzZXJ2aWNl" + + "cyB1c2UgYGluaGVyaXQ6IFt7dGVtcGxhdGU6IHNlcnZpY2V9XWAuIExMTSByZWxlYXNlcyB1c2Ug" + + "T0NJIGNoYXJ0cyBmcm9tIHRoZSBgbnZjZmAgcmVwb3NpdG9yeSB3aXRoIHN0YW5kYWxvbmUgYHZh" + + "bHVlczogWy4uL2dsb2JhbC55YW1sLmdvdG1wbF1gIGJsb2NrczsgdGhleSBhcmUgZ2F0ZWQgb24g" + + "YGFkZG9ucy5sbG0uZW5hYmxlZGAuIGBhZG1pbi1pc3N1ZXItcHJveHlgIGFuZCBgaW5ncmVzc2Ag" + + "aGF2ZSBzdGFuZGFsb25lIGB2YWx1ZXM6YCBibG9ja3MuCgojIyMgMDMtb2JzZXJ2YWJpbGl0eS55" + + "YW1sLmdvdG1wbAoKfCBSZWxlYXNlIHwgQ2hhcnQgfCBOYW1lc3BhY2UgfCBMYWJlbCB8CnwtLS0t" + + "LS0tLS18LS0tLS0tLXwtLS0tLS0tLS0tLXwtLS0tLS0tfAp8IChvYnNlcnZhYmlsaXR5IHJlbGVh" + + "c2VzKSB8ICh2YXJpb3VzKSB8IG9ic2VydmFiaWxpdHkgfCBvYnNlcnZhYmlsaXR5IHwKCkdhdGVk" + + "IG9uIG9ic2VydmFiaWxpdHktc3BlY2lmaWMgZmxhZ3MgaW4gdGhlIGVudmlyb25tZW50IGZpbGUu" + + "IFNraXBwZWQgaWYgZGlzYWJsZWQuCgojIyBUZW1wbGF0ZSBJbmhlcml0YW5jZQoKIyMjIGA8PDog" + + "KmRlcGVuZGVuY3lgIChZQU1MIG1lcmdlKQoKVXNlZCBpbiBgMDEtZGVwZW5kZW5jaWVzLnlhbWwu" + + "Z290bXBsYC4gTWVyZ2VzIHRoZSB0ZW1wbGF0ZSdzIHByb3BlcnRpZXMgaW50byB0aGUgcmVsZWFz" + + "ZS4KCioqR290Y2hhKio6IFlBTUwgbWVyZ2UgcmVwbGFjZXMgbGlzdHMuIElmIHlvdSBhZGQgYSBg" + + "dmFsdWVzOmAga2V5IHRvIHRoZSByZWxlYXNlLCBpdCAqKnJlcGxhY2VzKiogdGhlIHRlbXBsYXRl" + + "J3MgYHZhbHVlczpgIGxpc3QgZW50aXJlbHkuIFlvdSBtdXN0IHJlLWluY2x1ZGUgYWxsIHRlbXBs" + + "YXRlIHZhbHVlczoKCkluIHRoZSB0ZW1wbGF0ZSBiZWxvdywgYDxwcml2YXRlLXZhbHVlcz5gIHJl" + + "ZmVycyB0byB0aGUgYHNlY3JldHMvYCBkaXJlY3RvcnkgYXQgdGhlIGhlbG1maWxlIHN0YWNrIHJv" + + "b3QuCgpgYGB5YW1sCiMgVGVtcGxhdGUgZGVmaW5lczoKdGVtcGxhdGVzOgogIGRlcGVuZGVuY3k6" + + "ICZkZXBlbmRlbmN5CiAgICBjaGFydDogbnZjZi9oZWxtLW52Y2Yte3sgLlJlbGVhc2UuTmFtZSB9" + + "fQogICAgdmFsdWVzOgogICAgICAtIC4uL2dsb2JhbC55YW1sLmdvdG1wbAogICAgICAtIC4uLzxw" + + "cml2YXRlLXZhbHVlcz4ve3sgcmVxdWlyZWRFbnYgIkhFTE1GSUxFX0VOViIgfX0tc2VjcmV0cy55" + + "YW1sCgojIFdoZW4gb3ZlcnJpZGluZywgTVVTVCByZS1pbmNsdWRlIGJvdGg6Ci0gbmFtZTogY2Fz" + + "c2FuZHJhCiAgPDw6ICpkZXBlbmRlbmN5CiAgdmFsdWVzOgogICAgLSAuLi9nbG9iYWwueWFtbC5n" + + "b3RtcGwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBNdXN0" + + "IHJlLWluY2x1ZGUKICAgIC0gLi4vPHByaXZhdGUtdmFsdWVzPi97eyByZXF1aXJlZEVudiAiSEVM" + + "TUZJTEVfRU5WIiB9fS1zZWNyZXRzLnlhbWwgICAjIE11c3QgcmUtaW5jbHVkZQogICAgLSBjYXNz" + + "YW5kcmE6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg" + + "ICAgICAgICMgWW91ciBvdmVycmlkZQogICAgICAgIHJlc291cmNlczoKICAgICAgICAgIGxpbWl0" + + "czoKICAgICAgICAgICAgbWVtb3J5OiA4MTkyTWkKYGBgCgojIyMgYGluaGVyaXRgIChIZWxtZmls" + + "ZSBuYXRpdmUpCgpVc2VkIGluIGAwMi1jb3JlLnlhbWwuZ290bXBsYC4gSGVsbWZpbGUncyBuYXRp" + + "dmUgaW5oZXJpdGFuY2UgbWVjaGFuaXNtLgoKYGBgeWFtbAotIG5hbWU6IGFwaQogIHZlcnNpb246" + + "IDEuNi4wCiAgbmFtZXNwYWNlOiBudmNmCiAgaW5oZXJpdDoKICAgIC0gdGVtcGxhdGU6IHNlcnZp" + + "Y2UKYGBgCgpXaGVuIGFkZGluZyBgdmFsdWVzOmAgdG8gYW4gaW5oZXJpdGVkIHJlbGVhc2UsIHlv" + + "dSBhbHNvIG5lZWQgdG8gcmUtaW5jbHVkZSB0aGUgdGVtcGxhdGUncyB2YWx1ZXMgZmlsZXMgc2lu" + + "Y2UgYHZhbHVlc2AgaXMgYSBsaXN0IHRoYXQgZ2V0cyByZXBsYWNlZC4KCiMjIFZhbHVlcyBQcmVj" + + "ZWRlbmNlCgpGcm9tIGxvd2VzdCB0byBoaWdoZXN0IHByaW9yaXR5OgoKMS4gYGVudmlyb25tZW50" + + "cy9iYXNlLnlhbWxgIC0tIGRlZmF1bHRzIHNoYXJlZCBhY3Jvc3MgYWxsIGVudmlyb25tZW50cwoy" + + "LiBgZW52aXJvbm1lbnRzLzxlbnY+LnlhbWxgIC0tIHBlci1lbnZpcm9ubWVudCBvdmVycmlkZXMK" + + "My4gYGdsb2JhbC55YW1sLmdvdG1wbGAgLS0gR28gdGVtcGxhdGUgcHJvY2Vzc2luZyAoY29uc3Ry" + + "dWN0cyBjaGFydC1zcGVjaWZpYyBzdHJ1Y3R1cmUpCjQuIGA8cHJpdmF0ZS12YWx1ZXM+LzxlbnY+" + + "LXNlY3JldHMueWFtbGAgLS0gc2Vuc2l0aXZlIHZhbHVlcwo1LiBJbmxpbmUgYHZhbHVlczpgIGJs" + + "b2NrcyBvbiByZWxlYXNlcyAtLSBoaWdoZXN0IHByZWNlZGVuY2UKCiMjIFdoYXQgZ2xvYmFsLnlh" + + "bWwuZ290bXBsIFBhc3NlcyBUaHJvdWdoCgpgZ2xvYmFsLnlhbWwuZ290bXBsYCByZWFkcyBmcm9t" + + "IGAuVmFsdWVzYCAodGhlIG1lcmdlZCBlbnZpcm9ubWVudCArIGVudi1zcGVjaWZpYyBZQU1MKSBh" + + "bmQgY29uc3RydWN0cyBjaGFydC1zcGVjaWZpYyB2YWx1ZXMuIEl0IG9ubHkgcGFzc2VzIHRocm91" + + "Z2gga2V5cyBpdCBleHBsaWNpdGx5IHJlZmVyZW5jZXM6CgojIyMgQ2Fzc2FuZHJhCgotIGBjYXNz" + + "YW5kcmEucmVwbGljYUNvdW50YAotIGBjYXNzYW5kcmEuaW1hZ2UuKmAgKHJlZ2lzdHJ5LCByZXBv" + + "c2l0b3J5KQotIGBjYXNzYW5kcmEubWlncmF0aW9ucy5pbWFnZS4qYAotIGBjYXNzYW5kcmEucGVy" + + "c2lzdGVuY2Uuc2l6ZWAKLSBgY2Fzc2FuZHJhLm5vZGVTZWxlY3RvcmAgKGlmIGBnbG9iYWwubm9k" + + "ZVNlbGVjdG9ycy5lbmFibGVkYCkKLSBgY2Fzc2FuZHJhLmdsb2JhbC5kZWZhdWx0U3RvcmFnZUNs" + + "YXNzYAoKIyMjIE5BVFMKCi0gYG5hdHMuY29udGFpbmVyLmltYWdlLipgCi0gYG5hdHMucmVsb2Fk" + + "ZXIuaW1hZ2UuKmAKLSBgbmF0cy5uYXRzQm94LmNvbnRhaW5lci5pbWFnZS4qYAotIGBuYXRzLmNv" + + "bmZpZy5qZXRzdHJlYW0uZmlsZVN0b3JlLnB2Yy5zdG9yYWdlQ2xhc3NOYW1lYAotIGBuYXRzLnBv" + + "ZFRlbXBsYXRlLm1lcmdlLnNwZWMubm9kZVNlbGVjdG9yYCAoaWYgZW5hYmxlZCkKCiMjIyBPcGVu" + + "QmFvCgotIGBvcGVuYmFvLm1pZ3JhdGlvbnMuaW1hZ2UuKmAgYW5kIGBvcGVuYmFvLm1pZ3JhdGlv" + + "bnMuZW52YAotIGBvcGVuYmFvLmluamVjdG9yLmltYWdlLipgCi0gYG9wZW5iYW8uc2VydmVyLmlt" + + "YWdlLipgCi0gYG9wZW5iYW8uc2VydmVyLmRhdGFTdG9yYWdlLipgCi0gTm9kZSBzZWxlY3RvcnMg" + + "KGlmIGVuYWJsZWQpCgojIyMgU2VydmljZXMgKEFQSSwgU0lTLCBldGMuKQoKLSBgPHNlcnZpY2U+" + + "LmltYWdlLipgIChyZWdpc3RyeSwgcmVwb3NpdG9yeSkKLSBgPHNlcnZpY2U+Lm5vZGVTZWxlY3Rv" + + "cmAgKGlmIGVuYWJsZWQpCi0gYDxzZXJ2aWNlPi5lbnYuKmAgKG9ic2VydmFiaWxpdHkgc2V0dGlu" + + "Z3MpCgojIyMgTExNIEZ1bmN0aW9uIEVuYWJsZW1lbnQKCkVuYWJsZSB0aGUgTExNIGFkZG9uIGJl" + + "Zm9yZSBjcmVhdGluZyBvciBpbnZva2luZyBmdW5jdGlvbnMgd2l0aApgZnVuY3Rpb25UeXBlOiAi" + + "TExNImAuIFRoZSBhZGRvbiBkZXBsb3lzIGBsbG0tcmVxdWVzdC1yb3V0ZXJgIGFuZApgbGxtLWFw" + + "aS1nYXRld2F5YCwgYWRkcyB0aGUgYGxsbS5pbnZvY2F0aW9uLjxkb21haW4+YCByb3V0ZSB3aGVu" + + "IEdhdGV3YXkgQVBJCmluZ3Jlc3MgaXMgZW5hYmxlZCwgYW5kIGNvbmZpZ3VyZXMgd29ya2VycyB0" + + "byB1c2UgdGhlIExMTSBzaWRlY2FyLiBUaGUgSGVsbWZpbGUKY29uZGl0aW9uIGlzIGBhZGRvbnMu" + + "bGxtLmVuYWJsZWRgLiBEbyBub3QgdXNlIHRoZSBvYnNvbGV0ZSBgbGxtLmVuYWJsZWRgIHBhdGgu" + + "CgpGb3IgYSBzaW5nbGUtbm9kZSBpc29sYXRlZCB0ZXN0IGNsdXN0ZXIsIGFkZCB0aGlzIGNvbmZp" + + "Z3VyYXRpb24gdG8KYGVudmlyb25tZW50cy88ZW52Pi55YW1sYCBiZWZvcmUgYXBwbHlpbmcgdGhl" + + "IHN0YWNrOgoKYGBgeWFtbAphZGRvbnM6CiAgbGxtOgogICAgZW5hYmxlZDogdHJ1ZQogICAgZ2F0" + + "ZXdheToKICAgICAgcmVwbGljYUNvdW50OiAxCiAgICAgIG1ldHJpY3M6CiAgICAgICAgc2Vydmlj" + + "ZU1vbml0b3I6CiAgICAgICAgICBlbmFibGVkOiBmYWxzZQogICAgcmVxdWVzdFJvdXRlcjoKICAg" + + "ICAgcmVwbGljYUNvdW50OiAxCiAgICAgIG1ldHJpY3M6CiAgICAgICAgc2VydmljZU1vbml0b3I6" + + "CiAgICAgICAgICBlbmFibGVkOiBmYWxzZQoKYWdlbnRDb25maWc6CiAgbWVyZ2VDb25maWc6IHwK" + + "ICAgIGNsdXN0ZXI6CiAgICAgIHZhbGlkYXRpb25Qb2xpY3k6CiAgICAgICAgbmFtZTogVW5yZXN0" + + "cmljdGVkCiAgICB3b3JrbG9hZDoKICAgICAgc3RhcmdhdGVRVUlDSW5zZWN1cmU6IHRydWUKYGBg" + + "CgpVc2UgYHJlcGxpY2FDb3VudDogMWAgb25seSBmb3IgbG9jYWwgb3Igc2luZ2xlLW5vZGUgdGVz" + + "dCBjbHVzdGVycy4gVGhlIGJ1bmRsZWQKTlZDRiBBUEkgY3VycmVudGx5IHNlcnZlcyBwbGFpbnRl" + + "eHQgZ1JQQyBvbiBwb3J0IDkwOTAsIHNvIHRoZSBzZWxmLW1hbmFnZWQgc3RhY2sKZGVmYXVsdHMg" + + "dGhlIExMTSBBUEkgR2F0ZXdheSBhdXRoZW50aWNhdGlvbiBob3AgdG8gcGxhaW50ZXh0LiBTZXQK" + + "YGFkZG9ucy5sbG0uZ2F0ZXdheS5hdXRoLmdycGNJbnNlY3VyZTogZmFsc2VgIG9ubHkgd2l0aCBh" + + "IFRMUy1jYXBhYmxlIE5WQ0YgQVBJLgoKV29ya2VyLXRvLXJvdXRlciB0cmFuc3BvcnQgaXMgc2Vw" + + "YXJhdGUuIEZvciBzaGFyZWQgb3IgcHJvZHVjdGlvbiBjbHVzdGVycywgdXNlCnRoZSByZXF1aXJl" + + "ZCByZXBsaWNhIGNvdW50IGFuZCB0aGUgbWFuYWdlZCBUTFMgY29uZmlndXJhdGlvbi4gVGhlCmB3" + + "b3JrbG9hZC5zdGFyZ2F0ZVFVSUNJbnNlY3VyZWAgc2V0dGluZyBlbmFibGVzIHBsYWludGV4dCB3" + + "b3JrZXIgdHJhbnNwb3J0IGFuZAptdXN0IG5vdCBiZSB1c2VkIGluIHByb2R1Y3Rpb24uCgpUaGUg" + + "cmVxdWVzdCByb3V0ZXIgdXNlcyBgcG93ZXItb2YtdHdvYCB3aGVuIG5vIGxvYWQtYmFsYW5jZXIg" + + "Y29uZmlndXJhdGlvbiBpcwpzZXQuIENvbmZpZ3VyZSBvdGhlciByb3V0aW5nIG1ldGhvZHMgd2l0" + + "aCB0aGUKW0xMTSBSZXF1ZXN0IFJvdXRlciBMb2FkIEJhbGFuY2luZ10oaHR0cHM6Ly9naXRodWIu" + + "Y29tL05WSURJQS9udmNmL2Jsb2IvbWFpbi9kb2NzL3VzZXIvbGxtLXJlcXVlc3Qtcm91dGVyLWxv" + + "YWQtYmFsYW5jaW5nLm1kKQpndWlkZS4KCklmIHRoZSBzaWRlY2FyIGltYWdlIGlzIG1pcnJvcmVk" + + "IG91dHNpZGUgdGhlIHN0YWNrJ3MgZGVmYXVsdCBpbWFnZSByZWdpc3RyeSBhbmQKcmVwb3NpdG9y" + + "eSwgc2V0IHRoZSBnZW5lcmF0ZWQgd29ya2VyIHNpZGVjYXIgaW1hZ2UgZXhwbGljaXRseToKCmBg" + + "YHlhbWwKYXBpOgogIHJlbW90ZUNvbmZpZzoKICAgIGNvbmZpZ0RhdGE6CiAgICAgIG52Y2Y6CiAg" + + "ICAgICAgc2lkZWNhcnM6CiAgICAgICAgICBsbG0tcm91dGVyLWNsaWVudC1pbWFnZTogPHJlZ2lz" + + "dHJ5Pi88cmVwb3NpdG9yeT4vcHlsb246MC4xNC4xCmBgYAoKVGhlIGxlZ2FjeSBgYXBpLmVudi5O" + + "VkNGX1NJREVDQVJTX0xMTV9ST1VURVJfQ0xJRU5UX0lNQUdFYCBwYXRoIGlzIGRlcHJlY2F0ZWQu" + + "ClRoZSBzdGFjayB0cmFuc2xhdGVzIGl0IGZvciBvbmUgY29tcGF0aWJpbGl0eSB3aW5kb3csIGJ1" + + "dCBuZXcgY29uZmlndXJhdGlvbnMKbXVzdCB1c2UgdGhlIHJlbW90ZS1jb25maWcgcGF0aC4gQ29u" + + "ZmxpY3RpbmcgdmFsdWVzIGZhaWwgcmVuZGVyaW5nLgoKUmVuZGVyIGFuZCBhcHBseSB0aGUgdXBk" + + "YXRlZCBjb250cm9sLXBsYW5lIGVudmlyb25tZW50LCB0aGVuIHJlZnJlc2ggZXZlcnkKcmVnaXN0" + + "ZXJlZCBjb21wdXRlIHBsYW5lIHVzaW5nIHRoZSBzYW1lIGhhbmRvZmYgdXNlZCBmb3IgaXRzIGlu" + + "c3RhbGxhdGlvbiBzbwpOVkNBIHJlY2VpdmVzIGBhZ2VudENvbmZpZy5tZXJnZUNvbmZpZ2A6Cgpg" + + "YGBiYXNoCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSB0ZW1wbGF0ZQpIRUxNRklMRV9FTlY9" + + "PGVudj4gaGVsbWZpbGUgc3luYwpgYGAKClVzZSB0aGUgY29tcGxldGUgY29tcHV0ZS1wbGFuZSBp" + + "bnN0YWxsIGNvbW1hbmQgZnJvbQpbU3BsaXQgQ29tcHV0ZS1QbGFuZSBJbnN0YWxsYXRpb25dKGNv" + + "bXB1dGUtcGxhbmUtaW5zdGFsbGF0aW9uLm1kKS4gQQpDTEktcHJvZmlsZSBpbnN0YWxsYXRpb24g" + + "bXVzdCByZW1haW4gcHJvZmlsZS1kcml2ZW47IGEgSGVsbWZpbGUgaW5zdGFsbGF0aW9uCm11c3Qg" + + "cmVtYWluIHZhbHVlcy1kcml2ZW4uCgpFeGlzdGluZyBMTE0gZnVuY3Rpb24gdmVyc2lvbnMgcmV0" + + "YWluIHRoZSB3b3JrZXItc2lkZWNhciBpbWFnZSBtZXRhZGF0YQpjYXB0dXJlZCB3aGVuIHRoZSB2" + + "ZXJzaW9uIGlzIGNyZWF0ZWQuIFJlcGxhY2luZyBwb2RzIG9yIHJlZGVwbG95aW5nIHRoZSBzYW1l" + + "CnZlcnNpb24gZG9lcyBub3QgYXBwbHkgYSBuZXcgUHlsb24gaW1hZ2UuIEFmdGVyIHRoZSBjb250" + + "cm9sLXBsYW5lIHVwZGF0ZSwKY3JlYXRlIGFuZCBkZXBsb3kgYSBuZXcgZnVuY3Rpb24gdmVyc2lv" + + "bi4gVmVyaWZ5IHRoZSBjb250cm9sIHBsYW5lLCByb3V0ZSwgYW5kCndvcmtlciBzaWRlY2FyOgoK" + + "YGBgYmFzaAprdWJlY3RsIGdldCBkZXBsb3kgLW4gbnZjZiBsbG0tYXBpLWdhdGV3YXkKa3ViZWN0" + + "bCBnZXQgc3RhdGVmdWxzZXQgLW4gbnZjZiBsbG0tcmVxdWVzdC1yb3V0ZXIKa3ViZWN0bCBnZXQg" + + "cG9kcyAtbiBudmNmIHwgZ3JlcCAtRSAnbGxtLWFwaS1nYXRld2F5fGxsbS1yZXF1ZXN0LXJvdXRl" + + "cicKa3ViZWN0bCBnZXQgaHR0cHJvdXRlIC1BIHwgZ3JlcCBsbG0Ka3ViZWN0bCAtbiBudmNmLWJh" + + "Y2tlbmQgZ2V0IHBvZCA8ZnVuY3Rpb24tcG9kPiBcCiAgLW8ganNvbnBhdGg9J3tyYW5nZSAuc3Bl" + + "Yy5jb250YWluZXJzWz8oQC5uYW1lPT0ibGxtLXdvcmtlciIpXS5hcmdzWypdfXsufXsiXFxuIn17" + + "ZW5kfScKYGBgCgpGb3IgbG9jYWwgcGxhaW50ZXh0IGNsdXN0ZXJzLCB0aGUgYGxsbS13b3JrZXJg" + + "IGFyZ3MgbXVzdCBpbmNsdWRlCmAtLXF1aWMtaW5zZWN1cmVgLgoKRm9yIGxvYWQtYmFsYW5jZXIg" + + "c2NoZW1hIGFuZCBhbGdvcml0aG0gYmVoYXZpb3IsIHNlZSB0aGUKW1N0YXJnYXRlIGNvbmZpZ3Vy" + + "YXRpb24gZ3VpZGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9OVklESUEvbnZjZi9ibG9iL21haW4vc3Jj" + + "L2xpYnJhcmllcy9ydXN0L3N0YXJnYXRlL2RvY3MvbG9hZC1iYWxhbmNlci1jb25maWd1cmF0aW9u" + + "Lm1kKS4KCiMjIEhlbG1maWxlIFNlbGVjdG9ycwoKVGFyZ2V0IHNwZWNpZmljIHJlbGVhc2VzIG9y" + + "IGdyb3VwczoKCmBgYGJhc2gKIyBCeSByZWxlYXNlIGdyb3VwCkhFTE1GSUxFX0VOVj08ZW52PiBo" + + "ZWxtZmlsZSAtLXNlbGVjdG9yIHJlbGVhc2UtZ3JvdXA9ZGVwZW5kZW5jaWVzIHN5bmMKSEVMTUZJ" + + "TEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3IgcmVsZWFzZS1ncm91cD1zZXJ2aWNlcyBz" + + "eW5jCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIHJlbGVhc2UtZ3JvdXA9" + + "aW5ncmVzcyBzeW5jCkhFTE1GSUxFX0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIHJlbGVh" + + "c2UtZ3JvdXA9b2JzZXJ2YWJpbGl0eSBzeW5jCgojIEJ5IHJlbGVhc2UgbmFtZQpIRUxNRklMRV9F" + + "TlY9PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciBuYW1lPWNhc3NhbmRyYSBzeW5jCkhFTE1GSUxF" + + "X0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9YWRtaW4taXNzdWVyLXByb3h5IHN5" + + "bmMKSEVMTUZJTEVfRU5WPTxlbnY+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1sbG0tcmVxdWVz" + + "dC1yb3V0ZXIgc3luYwpIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1zZWxlY3RvciBuYW1l" + + "PWxsbS1hcGktZ2F0ZXdheSBzeW5jCgojIFRlbXBsYXRlIG9ubHkgKGRyeSBydW4pCkhFTE1GSUxF" + + "X0VOVj08ZW52PiBoZWxtZmlsZSAtLXNlbGVjdG9yIG5hbWU9Y2Fzc2FuZHJhIHRlbXBsYXRlCgoj" + + "IERlc3Ryb3kgYSBzaW5nbGUgcmVsZWFzZQpIRUxNRklMRV9FTlY9PGVudj4gaGVsbWZpbGUgLS1z" + + "ZWxlY3RvciBuYW1lPWNhc3NhbmRyYSBkZXN0cm95CmBgYAoKTm90ZTogYGFkbWluLWlzc3Vlci1w" + + "cm94eWAgaGFzIG5vIGByZWxlYXNlLWdyb3VwYCBsYWJlbC4gVXNlIGAtLXNlbGVjdG9yIG5hbWU9" + + "YWRtaW4taXNzdWVyLXByb3h5YC4KUEsHCLE1HdsCKgAAAioAAFBLAwQUAAgAAAAAACEAAAAAAAAA" + + "AAAAAAAAPwAJAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL3JlZmVyZW5jZXMv" + + "bnZjZi11aS1hZGRvbi5tZFVUBQABAKbOEiMgTlZDRiBVSSBBZGRvbgoKTlZDRiBVSSBpcyBhbiBv" + + "cHRpb25hbCwgY3VzdG9tZXItZmFjaW5nIE5WQ0YgYWRtaW4tcGFuZWwgVUkuIEl0IGlzIGRpc2Fi" + + "bGVkIGJ5CmRlZmF1bHQgYW5kIGF2YWlsYWJsZSBvbmx5IGluIHN0YWNrIHBhY2thZ2VzIHRoYXQg" + + "aW5jbHVkZSB0aGUgTlZDRiBVSSBhZGRvbi4KCiMjIFdoZW4gdG8gZW5hYmxlCgpFbmFibGUgTlZD" + + "RiBVSSBvbmx5IHdoZW4geW91IG5lZWQgdGhlIGFkbWluLXBhbmVsIFVJIGFuZCB5b3VyIGV4dHJh" + + "Y3RlZCBzdGFjawpwYWNrYWdlIGluY2x1ZGVzIHRoZSBhZGRvbi4gSWYgdGhlIHBhY2thZ2UgZG9l" + + "cyBub3QgY29udGFpbiBhIGBudmNmLXVpYCByZWxlYXNlCmFuZCBgbnZjZlVpYCByb3V0ZSB2YWx1" + + "ZXMsIHNraXAgdGhlIGFkZG9uIHVudGlsIHlvdSB1c2UgYSBwYWNrYWdlIHRoYXQgaW5jbHVkZXMK" + + "dGhlbS4KCiMjIEVuYWJsZSB0aGUgYWRkb24KCkVuYWJsZSBpdCBpbiBgZW52aXJvbm1lbnRzLzxl" + + "bnYtbmFtZT4ueWFtbGA6CgpgYGB5YW1sCmFkZG9uczoKICBudmNmVWk6CiAgICBlbmFibGVkOiB0" + + "cnVlCmBgYAoKIyMgQ3JlYXRlIG5hbWVzcGFjZSBhbmQgaW1hZ2UgcHVsbCBzZWNyZXQKCkNyZWF0" + + "ZSB0aGUgbmFtZXNwYWNlLCBhbmQgYW4gaW1hZ2UgcHVsbCBzZWNyZXQgb25seSBpZiBwdWxsaW5n" + + "IGZyb20gYSBwcml2YXRlCnJlZ2lzdHJ5OgoKYGBgYmFzaAprdWJlY3RsIGNyZWF0ZSBuYW1lc3Bh" + + "Y2UgbnZjZi11aSAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBrdWJlY3RsIGFwcGx5IC1mIC0K" + + "CiMgT25seSBpZiBwdWxsaW5nIGZyb20gYSBwcml2YXRlIHJlZ2lzdHJ5IChlLmcuLCBOR0MgbnZj" + + "ci5pbykKZXhwb3J0IE5HQ19BUElfS0VZPSI8eW91ci1rZXk+IgprdWJlY3RsIGNyZWF0ZSBzZWNy" + + "ZXQgZG9ja2VyLXJlZ2lzdHJ5IG52Y3ItY3JlZHMgXAogIC0tZG9ja2VyLXNlcnZlcj1udmNyLmlv" + + "IFwKICAtLWRvY2tlci11c2VybmFtZT0nJG9hdXRodG9rZW4nIFwKICAtLWRvY2tlci1wYXNzd29y" + + "ZD0iJE5HQ19BUElfS0VZIiBcCiAgLS1uYW1lc3BhY2U9bnZjZi11aSBcCiAgLS1kcnktcnVuPWNs" + + "aWVudCAtbyB5YW1sIHwga3ViZWN0bCBhcHBseSAtZiAtCmBgYAoKVGhlIGRlZmF1bHQgcm91dGUg" + + "aG9zdCBpcyBgbnZjZi11aS48ZG9tYWluPmAgYW5kIHRoZSBiYWNrZW5kIGlzCmBudmNmLXVpLm52" + + "Y2YtdWk6ODMwMGAuCgojIyBBcHBseSB0aGUgc2VydmljZSBhbmQgcm91dGUKCkFmdGVyIGNvbmZp" + + "cm1pbmcgdGhlIHBhY2thZ2UgaW5jbHVkZXMgdGhlIGBudmNmLXVpYCByZWxlYXNlLCBwcmV2aWV3" + + "IGFuZCBhcHBseQp0aGUgc2VydmljZSBhbmQgcm91dGU6CgpgYGBiYXNoCkhFTE1GSUxFX0VOVj08" + + "ZW52LW5hbWU+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1udmNmLXVpIHRlbXBsYXRlCkhFTE1G" + + "SUxFX0VOVj08ZW52LW5hbWU+IGhlbG1maWxlIC0tc2VsZWN0b3IgbmFtZT1udmNmLXVpIHN5bmMK" + + "SEVMTUZJTEVfRU5WPTxlbnYtbmFtZT4gaGVsbWZpbGUgLS1zZWxlY3RvciByZWxlYXNlLWdyb3Vw" + + "PWluZ3Jlc3Mgc3luYwpgYGAKCiMjIFZlcmlmeQoKVmVyaWZ5IHRoZSByb3V0ZSBvbmx5IHdoZW4g" + + "dGhlIGFkZG9uIGlzIHByZXNlbnQgYW5kIGVuYWJsZWQ6CgpgYGBiYXNoCmt1YmVjdGwgZ2V0IGRl" + + "cGxveSxzdmMgLW4gbnZjZi11aQprdWJlY3RsIGdldCBodHRwcm91dGUgLUEgfCBncmVwIC1pIG52" + + "Y2YtdWkKY3VybCAtaSAtSCAiSG9zdDogbnZjZi11aS48ZG9tYWluPiIgImh0dHA6Ly88Z2F0ZXdh" + + "eS1hZGRyZXNzPi9zdGF0dXMiCmBgYAoKIyMgU2VjdXJpdHkKClRoZSBOVkNGIFVJIGFkbWluIHBh" + + "bmVsIGlzIGN1cnJlbnRseSB1bmF1dGhlbnRpY2F0ZWQuIERvIG5vdCBleHBvc2UgaXQgdG8gdGhl" + + "CnB1YmxpYyBpbnRlcm5ldC4gUmVzdHJpY3QgYWNjZXNzIHRvIGEgdHJ1c3RlZCBuZXR3b3JrLCBW" + + "UE4sIG9yIGFuIGF1dGhlbnRpY2F0aW5nCnByb3h5IGluIGZyb250IG9mIHRoZSBgbnZjZi11aWAg" + + "cm91dGUuClBLBwg4+SevuQcAALkHAABQSwMEFAAIAAAAAAAhAAAAAAAAAAAAAAAAAD4ACQBkYXRh" + + "L252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL3B1bGwtc2VjcmV0cy5t" + + "ZFVUBQABAKbOEiMgSW1hZ2UgUHVsbCBTZWNyZXRzIFJlZmVyZW5jZQoKIyMgT3ZlcnZpZXcKCldo" + + "ZW4gcHVsbGluZyBOVkNGIGltYWdlcyBmcm9tIGEgcHJpdmF0ZSByZWdpc3RyeSAoZm9yIGV4YW1w" + + "bGUsIE5HQwpgbnZjci5pb2ApLCBLdWJlcm5ldGVzIG5lZWRzIGBpbWFnZVB1bGxTZWNyZXRzYCBv" + + "biBldmVyeSBwb2QuIENvbnRyb2wtcGxhbmUgYW5kCmNvbXB1dGUtcGxhbmUgY3JlZGVudGlhbHMg" + + "YXJlIGNvbmZpZ3VyZWQgaW4gdGhlaXIgb3duIGNsdXN0ZXIgY29udGV4dHMuIERvIG5vdAp1c2Ug" + + "b25lIG1peGVkIG5hbWVzcGFjZSBsaXN0LgoKVGhlIHJlY29tbWVuZGVkIGNvbnRyb2wtcGxhbmUg" + + "YXBwcm9hY2ggdXNlcyBLeXZlcm5vIHRvIGluamVjdCB0aGUgc2VjcmV0IGludG8KY29udHJvbC1w" + + "bGFuZSBwb2RzIGF0IGFkbWlzc2lvbiB0aW1lLiBUaGUgY29tcHV0ZS1wbGFuZSBjaGFydCBhbmQg" + + "b3BlcmF0b3IgdXNlCnRoZSBzZWNyZXQgaW4gYG52Y2Etb3BlcmF0b3JgIGFuZCBtaXJyb3IgaXQg" + + "dG8gYG52Y2Etc3lzdGVtYC4KCiMjIEt5dmVybm8gQXBwcm9hY2ggKFJlY29tbWVuZGVkKQoKIyMj" + + "IDEuIEluc3RhbGwgS3l2ZXJubwoKYGBgYmFzaApoZWxtIHJlcG8gYWRkIGt5dmVybm8gaHR0cHM6" + + "Ly9reXZlcm5vLmdpdGh1Yi5pby9reXZlcm5vLwpoZWxtIHJlcG8gdXBkYXRlCmhlbG0gaW5zdGFs" + + "bCBreXZlcm5vIGt5dmVybm8va3l2ZXJubyAtbiBreXZlcm5vIC0tY3JlYXRlLW5hbWVzcGFjZSBc" + + "CiAgLS1rdWJlLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4KYGBgCgojIyMgMi4gQ3Jl" + + "YXRlIGNvbnRyb2wtcGxhbmUgcHVsbCBzZWNyZXRzCgpgYGBiYXNoCmV4cG9ydCBOR0NfQVBJX0tF" + + "WT0iPHlvdXItbmdjLWFwaS1rZXk+IgoKZm9yIG5zIGluIGNhc3NhbmRyYS1zeXN0ZW0gbmF0cy1z" + + "eXN0ZW0gbnZjZiBhcGkta2V5cyBlc3Mgc2lzIHZhdWx0LXN5c3RlbSBjZXJ0LW1hbmFnZXI7IGRv" + + "CiAga3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4dD4gY3JlYXRlIG5hbWVz" + + "cGFjZSAiJG5zIiBcCiAgICAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBrdWJlY3RsIC0tY29u" + + "dGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBhcHBseSAtZiAtCmRvbmUKCmZvciBucyBpbiBj" + + "YXNzYW5kcmEtc3lzdGVtIG5hdHMtc3lzdGVtIG52Y2YgYXBpLWtleXMgZXNzIHNpcyB2YXVsdC1z" + + "eXN0ZW0gY2VydC1tYW5hZ2VyOyBkbwogIGt1YmVjdGwgLS1jb250ZXh0IDxjb250cm9sLXBsYW5l" + + "LWNvbnRleHQ+IGNyZWF0ZSBzZWNyZXQgZG9ja2VyLXJlZ2lzdHJ5IG52Y3ItY3JlZHMgXAogICAg" + + "LS1kb2NrZXItc2VydmVyPW52Y3IuaW8gXAogICAgLS1kb2NrZXItdXNlcm5hbWU9JyRvYXV0aHRv" + + "a2VuJyBcCiAgICAtLWRvY2tlci1wYXNzd29yZD0iJE5HQ19BUElfS0VZIiBcCiAgICAtLW5hbWVz" + + "cGFjZT0iJG5zIiBcCiAgICAtLWRyeS1ydW49Y2xpZW50IC1vIHlhbWwgfCBrdWJlY3RsIC0tY29u" + + "dGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBhcHBseSAtZiAtCmRvbmUKYGBgCgpGb3Igbm9u" + + "LU5HQyByZWdpc3RyaWVzLCByZXBsYWNlIGAtLWRvY2tlci1zZXJ2ZXJgLCBgLS1kb2NrZXItdXNl" + + "cm5hbWVgLCBhbmQgYC0tZG9ja2VyLXBhc3N3b3JkYC4KCiMjIyAzLiBBcHBseSBLeXZlcm5vIENs" + + "dXN0ZXJQb2xpY3kKCmBgYHlhbWwKYXBpVmVyc2lvbjoga3l2ZXJuby5pby92MQpraW5kOiBDbHVz" + + "dGVyUG9saWN5Cm1ldGFkYXRhOgogIG5hbWU6IG52Y2YtYWRkLWltYWdlcHVsbHNlY3JldHMKc3Bl" + + "YzoKICBiYWNrZ3JvdW5kOiBmYWxzZQogIHJ1bGVzOgogICAgLSBuYW1lOiBhZGQtaW1hZ2VwdWxs" + + "c2VjcmV0LXRvLW52Y2YtcG9kcwogICAgICBtYXRjaDoKICAgICAgICBhbnk6CiAgICAgICAgLSBy" + + "ZXNvdXJjZXM6CiAgICAgICAgICAgIGtpbmRzOgogICAgICAgICAgICAtIFBvZAogICAgICAgICAg" + + "ICBuYW1lc3BhY2VzOgogICAgICAgICAgICAtICJudmNmIgogICAgICAgICAgICAtICJhcGkta2V5" + + "cyIKICAgICAgICAgICAgLSAic2lzIgogICAgICAgICAgICAtICJlc3MiCiAgICAgICAgICAgIC0g" + + "Im5hdHMtc3lzdGVtIgogICAgICAgICAgICAtICJjYXNzYW5kcmEtc3lzdGVtIgogICAgICAgICAg" + + "ICAtICJ2YXVsdC1zeXN0ZW0iCiAgICAgICAgICAgIC0gImNlcnQtbWFuYWdlciIKICAgICAgbXV0" + + "YXRlOgogICAgICAgIHBhdGNoU3RyYXRlZ2ljTWVyZ2U6CiAgICAgICAgICBtZXRhZGF0YToKICAg" + + "ICAgICAgICAgYW5ub3RhdGlvbnM6CiAgICAgICAgICAgICAgbnZjZi5udmlkaWEuY29tL2ltYWdl" + + "cHVsbHNlY3JldC1pbmplY3RlZC1ieToga3l2ZXJubwogICAgICAgICAgc3BlYzoKICAgICAgICAg" + + "ICAgaW1hZ2VQdWxsU2VjcmV0czoKICAgICAgICAgICAgLSBuYW1lOiBudmNyLWNyZWRzCmBgYAoK" + + "YGBgYmFzaAprdWJlY3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBhcHBseSBc" + + "CiAgLWYga3l2ZXJuby1pbWFnZXB1bGxzZWNyZXQtcG9saWN5LnlhbWwKYGBgCgojIyMgNC4gSW5z" + + "dGFsbCB0aGUgY29udHJvbCBwbGFuZQoKQ29udGludWUgd2l0aCB0aGUgc2VsZWN0ZWQgY29udHJv" + + "bC1wbGFuZSBpbnN0YWxsYXRpb24gaW4KW1NwbGl0IENvbXB1dGUtUGxhbmUgSW5zdGFsbGF0aW9u" + + "XShjb21wdXRlLXBsYW5lLWluc3RhbGxhdGlvbi5tZCkuIE5vCmNvbnRyb2wtcGxhbmUgaGVsbWZp" + + "bGUgbW9kaWZpY2F0aW9ucyBhcmUgbmVlZGVkLiBLeXZlcm5vIGluamVjdHMgdGhlIHB1bGwKc2Vj" + + "cmV0IGludG8gbmV3IGNvbnRyb2wtcGxhbmUgcG9kcy4KCiMjIENvbXB1dGUtUGxhbmUgU2VjcmV0" + + "CgpDcmVhdGUgdGhlIHNlY3JldCBvbmx5IGluIGBudmNhLW9wZXJhdG9yYCBvbiB0aGUgY29tcHV0" + + "ZSBjbHVzdGVyOgoKYGBgYmFzaAprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250" + + "ZXh0PiBjcmVhdGUgbmFtZXNwYWNlIG52Y2Etb3BlcmF0b3IgXAogIC0tZHJ5LXJ1bj1jbGllbnQg" + + "LW8geWFtbCB8IFwKICBrdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250ZXh0PiBh" + + "cHBseSAtZiAtCgprdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0ZS1wbGFuZS1jb250ZXh0PiBjcmVh" + + "dGUgc2VjcmV0IGRvY2tlci1yZWdpc3RyeSBudmNyLWNyZWRzIFwKICAtLWRvY2tlci1zZXJ2ZXI9" + + "bnZjci5pbyBcCiAgLS1kb2NrZXItdXNlcm5hbWU9JyRvYXV0aHRva2VuJyBcCiAgLS1kb2NrZXIt" + + "cGFzc3dvcmQ9IiROR0NfQVBJX0tFWSIgXAogIC0tbmFtZXNwYWNlPW52Y2Etb3BlcmF0b3IgXAog" + + "IC0tZHJ5LXJ1bj1jbGllbnQgLW8geWFtbCB8IFwKICBrdWJlY3RsIC0tY29udGV4dCA8Y29tcHV0" + + "ZS1wbGFuZS1jb250ZXh0PiBhcHBseSAtZiAtCmBgYAoKUmVmZXJlbmNlIGl0IGluIHRoZSBjb21w" + + "dXRlLXBsYW5lIGVudmlyb25tZW50IGZpbGU6CgpgYGB5YW1sCmdsb2JhbDoKICBpbWFnZVB1bGxT" + + "ZWNyZXRzOgogICAgLSBuYW1lOiBudmNyLWNyZWRzCmBgYAoKVGhlIGNoYXJ0IGFuZCBvcGVyYXRv" + + "ciB1c2UgdGhhdCByZWZlcmVuY2UgaW4gYG52Y2Etb3BlcmF0b3JgIGFuZCBtaXJyb3IgdGhlCnNl" + + "Y3JldCB0byBgbnZjYS1zeXN0ZW1gLiBEbyBub3QgY3JlYXRlIGEgYnJvYWRlciBtYW51YWwgY29t" + + "cHV0ZSBuYW1lc3BhY2UgbGlzdC4gRm9sbG93CltTcGxpdCBDb21wdXRlLVBsYW5lIEluc3RhbGxh" + + "dGlvbl0oY29tcHV0ZS1wbGFuZS1pbnN0YWxsYXRpb24ubWQpIGZvciB0aGUKc2VsZWN0ZWQgaW5z" + + "dGFsbCBmbG93LgoKIyMgVmVyaWZpY2F0aW9uCgpgYGBiYXNoCiMgQ2hlY2sgdGhhdCBhIGNvbnRy" + + "b2wtcGxhbmUgcG9kIGhhcyB0aGUgaW5qZWN0ZWQgc2VjcmV0Cmt1YmVjdGwgLS1jb250ZXh0IDxj" + + "b250cm9sLXBsYW5lLWNvbnRleHQ+IGdldCBwb2QgLW4gPG5hbWVzcGFjZT4gPHBvZC1uYW1lPiBc" + + "CiAgLW8ganNvbnBhdGg9J3suc3BlYy5pbWFnZVB1bGxTZWNyZXRzfScKIyBFeHBlY3RlZDogW3si" + + "bmFtZSI6Im52Y3ItY3JlZHMifV0KCiMgQ2hlY2sgdGhlIEt5dmVybm8gYW5ub3RhdGlvbgprdWJl" + + "Y3RsIC0tY29udGV4dCA8Y29udHJvbC1wbGFuZS1jb250ZXh0PiBnZXQgcG9kIC1uIDxuYW1lc3Bh" + + "Y2U+IDxwb2QtbmFtZT4gXAogIC1vIGpzb25wYXRoPSd7Lm1ldGFkYXRhLmFubm90YXRpb25zLm52" + + "Y2ZcLm52aWRpYVwuY29tL2ltYWdlcHVsbHNlY3JldC1pbmplY3RlZC1ieX0nCiMgRXhwZWN0ZWQ6" + + "IGt5dmVybm8KCiMgQ2hlY2sgcHVsbCBldmVudHMKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wt" + + "cGxhbmUtY29udGV4dD4gZ2V0IGV2ZW50cyAtbiA8bmFtZXNwYWNlPiBcCiAgLS1zb3J0LWJ5PScu" + + "bGFzdFRpbWVzdGFtcCcgfCBncmVwIC1pIHB1bGwKIyBTaG91bGQgc2hvdyAiU3VjY2Vzc2Z1bGx5" + + "IHB1bGxlZCIgbm90ICI0MDEgVW5hdXRob3JpemVkIgoKIyBDaGVjayB0aGUgY2hhcnQvb3BlcmF0" + + "b3IgbWlycm9yIG9uIHRoZSBjb21wdXRlIGNsdXN0ZXIKa3ViZWN0bCAtLWNvbnRleHQgPGNvbXB1" + + "dGUtcGxhbmUtY29udGV4dD4gZ2V0IHNlY3JldCBudmNyLWNyZWRzIFwKICAtbiBudmNhLXN5c3Rl" + + "bQpgYGAKCiMjIFdoZW4gUHVsbCBTZWNyZXRzIEFyZSBOb3QgTmVlZGVkCgotICoqQVdTIEVDUiB3" + + "aXRoIElBTSBub2RlIHJvbGVzKio6IElmIHlvdXIgbm9kZXMgaGF2ZSBgQW1hem9uRUMyQ29udGFp" + + "bmVyUmVnaXN0cnlSZWFkT25seWAgSUFNIHBvbGljeSwgS3ViZXJuZXRlcyBjYW4gcHVsbCBmcm9t" + + "IEVDUiB3aXRob3V0IGV4cGxpY2l0IHNlY3JldHMuCi0gKipQdWJsaWMgcmVnaXN0cmllcyoqOiBO" + + "byBwdWxsIHNlY3JldHMgbmVlZGVkLgotICoqQ1NQIGJ1aWx0LWluIGNyZWRlbnRpYWwgaGVscGVy" + + "cyoqOiBHS0UgQXJ0aWZhY3QgUmVnaXN0cnksIEF6dXJlIEFDUiB3aXRoIG1hbmFnZWQgaWRlbnRp" + + "dHksIGFuZCBzaW1pbGFyIHNlcnZpY2VzLgoKIyMgVHJvdWJsZXNob290aW5nCgojIyMgUG9kcyBz" + + "dGlsbCBpbiBJbWFnZVB1bGxCYWNrT2ZmIGFmdGVyIGFwcGx5aW5nIHBvbGljeQoKVGhlIEt5dmVy" + + "bm8gcG9saWN5IG9ubHkgYWZmZWN0cyBwb2RzIGNyZWF0ZWQgKiphZnRlcioqIHRoZSBwb2xpY3kg" + + "aXMgYXBwbGllZC4gRGVsZXRlIHN0dWNrIHBvZHMgdG8gdHJpZ2dlciByZWNyZWF0aW9uOgoKYGBg" + + "YmFzaAprdWJlY3RsIC0tY29udGV4dCA8dGFyZ2V0LWNvbnRleHQ+IGRlbGV0ZSBwb2RzIC1uIDxu" + + "YW1lc3BhY2U+IC0tYWxsCmBgYAoKIyMjIEt5dmVybm8gYWRtaXNzaW9uIGNvbnRyb2xsZXIgbm90" + + "IHJ1bm5pbmcKCmBgYGJhc2gKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRyb2wtcGxhbmUtY29udGV4" + + "dD4gZ2V0IHBvZHMgLW4ga3l2ZXJubwojIEFsbCBwb2RzIHNob3VsZCBiZSBSdW5uaW5nCmBgYAoK" + + "IyMjIFBvbGljeSBub3QgbWF0Y2hpbmcKCmBgYGJhc2gKa3ViZWN0bCAtLWNvbnRleHQgPGNvbnRy" + + "b2wtcGxhbmUtY29udGV4dD4gZ2V0IGNsdXN0ZXJwb2xpY3kgbnZjZi1hZGQtaW1hZ2VwdWxsc2Vj" + + "cmV0cwojIFNob3VsZCBzaG93IFJFQURZOiBUcnVlCmBgYAoKIyMjIFdyb25nIHNlY3JldCBuYW1l" + + "CgpUaGUgcG9saWN5IHJlZmVyZW5jZXMgYG52Y3ItY3JlZHNgLiBWZXJpZnkgdGhlIHNlY3JldCBl" + + "eGlzdHMgd2l0aCB0aGF0IGV4YWN0IG5hbWU6CgpgYGBiYXNoCmt1YmVjdGwgLS1jb250ZXh0IDx0" + + "YXJnZXQtY29udGV4dD4gZ2V0IHNlY3JldCBudmNyLWNyZWRzIC1uIDxuYW1lc3BhY2U+CmBgYApQ" + + "SwcIS0I1qAAWAAAAFgAAUEsBAhQAFAAIAAAAAAAhAAICbAFKEAAAShAAABIACQAAAAAAAAAAAAAA" + + "AAAAAGRhdGEvbWFuaWZlc3QuanNvblVUBQABAKbOElBLAQIUABQACAAAAAAAIQD/dvNnU2EAAFNh" + + "AAAjAAkAAAAAAAAAAAAAAJMQAABkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9TS0lMTC5tZFVU" + + "BQABAKbOElBLAQIUABQACAAAAAAAIQBn/RgP/AwAAPwMAAAzAAkAAAAAAAAAAAAAAEByAABkYXRh" + + "L252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9leGFtcGxlcy9jaS1waXBlbGluZXMubWRVVAUAAQCmzhJQ" + + "SwECFAAUAAgAAAAAACEAoRTjgV0MAABdDAAANAAJAAAAAAAAAAAAAACmfwAAZGF0YS9udmNmLXNl" + + "bGYtbWFuYWdlZC1jbGkvZXhhbXBsZXMvbXVsdGktY2x1c3Rlci5tZFVUBQABAKbOElBLAQIUABQA" + + "CAAAAAAAIQBCJ0kPBQ0AAAUNAAA3AAkAAAAAAAAAAAAAAG6MAABkYXRhL252Y2Ytc2VsZi1tYW5h" + + "Z2VkLWNsaS9wcm9tcHRzL2FkZC1jb21wdXRlLXBsYW5lLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAA" + + "AAAhANTejTSfGQAAnxkAADkACQAAAAAAAAAAAAAA4ZkAAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQt" + + "Y2xpL3Byb21wdHMvY3JlYXRlLWFuZC1ydW4tdGFzay5tZFVUBQABAKbOElBLAQIUABQACAAAAAAA" + + "IQDSQ9wEGCUAABglAAA3AAkAAAAAAAAAAAAAAPCzAABkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNs" + + "aS9wcm9tcHRzL2RlcGxveS1hbmQtaW52b2tlLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhAHKS" + + "LCa+DgAAvg4AAD0ACQAAAAAAAAAAAAAAdtkAAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtY2xpL3By" + + "b21wdHMvZGlhZ25vc2UtZmFpbGVkLWluc3RhbGwubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEA" + + "QnHmHgEoAAABKAAAOgAJAAAAAAAAAAAAAACo6AAAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkv" + + "cHJvbXB0cy9pbnN0YWxsLWZyb20tc2NyYXRjaC5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQCq" + + "4Tq5yAcAAMgHAAA5AAkAAAAAAAAAAAAAABoRAQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9w" + + "cm9tcHRzL3JvdGF0ZS1jbHVzdGVyLWp3a3MubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEA2odj" + + "VuQhAADkIQAALgAJAAAAAAAAAAAAAABSGQEAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcHJv" + + "bXB0cy90ZWFyZG93bi5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQByDQ9kISMAACEjAAAwAAkA" + + "AAAAAAAAAAAAAJs7AQBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWNsaS9yZWZlcmVuY2UvY29tbWFu" + + "ZHMubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEAc6daZNUGAADVBgAAMgAJAAAAAAAAAAAAAAAj" + + "XwEAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1jbGkvcmVmZXJlbmNlL2V4aXQtY29kZXMubWRVVAUA" + + "AQCmzhJQSwECFAAUAAgAAAAAACEAmdDiUBcuAAAXLgAALQAJAAAAAAAAAAAAAABhZgEAZGF0YS9u" + + "dmNmLXNlbGYtbWFuYWdlZC1jbGkvcmVmZXJlbmNlL2ZsYWdzLm1kVVQFAAEAps4SUEsBAhQAFAAI" + + "AAAAAAAhAPOuE4R0EQAAdBEAADcACQAAAAAAAAAAAAAA3JQBAGRhdGEvbnZjZi1zZWxmLW1hbmFn" + + "ZWQtY2xpL3JlZmVyZW5jZS90cm91Ymxlc2hvb3RpbmcubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAA" + + "ACEAEcMUk0liAABJYgAALAAJAAAAAAAAAAAAAAC+pgEAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1p" + + "bnN0YWxsYXRpb24vU0tJTEwubWRVVAUAAQCmzhJQSwECFAAUAAgAAAAAACEAR1VqVkpWAABKVgAA" + + "NAAJAAAAAAAAAAAAAABqCQIAZGF0YS9udmNmLXNlbGYtbWFuYWdlZC1pbnN0YWxsYXRpb24vZXZh" + + "bHMvZXZhbHMuanNvblVUBQABAKbOElBLAQIUABQACAAAAAAAIQACUk5AfygAAH8oAAAvAAkAAAAA" + + "AAAAAAAAAB9gAgBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9leGFtcGxlcy5t" + + "ZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQCWY7xZEjAAABIwAABMAAkAAAAAAAAAAAAAAASJAgBk" + + "YXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3RhbGxhdGlvbi9yZWZlcmVuY2VzL2NvbXB1dGUtcGxh" + + "bmUtaW5zdGFsbGF0aW9uLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhALV6cDu1MAAAtTAAADsA" + + "CQAAAAAAAAAAAAAAmbkCAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL3JlZmVy" + + "ZW5jZXMvZGVidWdnaW5nLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhALE1HdsCKgAAAioAAEQA" + + "CQAAAAAAAAAAAAAAwOoCAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0aW9uL3JlZmVy" + + "ZW5jZXMvaGVsbWZpbGUtc3RydWN0dXJlLm1kVVQFAAEAps4SUEsBAhQAFAAIAAAAAAAhADj5J6+5" + + "BwAAuQcAAD8ACQAAAAAAAAAAAAAAPRUDAGRhdGEvbnZjZi1zZWxmLW1hbmFnZWQtaW5zdGFsbGF0" + + "aW9uL3JlZmVyZW5jZXMvbnZjZi11aS1hZGRvbi5tZFVUBQABAKbOElBLAQIUABQACAAAAAAAIQBL" + + "QjWoABYAAAAWAAA+AAkAAAAAAAAAAAAAAGwdAwBkYXRhL252Y2Ytc2VsZi1tYW5hZ2VkLWluc3Rh" + + "bGxhdGlvbi9yZWZlcmVuY2VzL3B1bGwtc2VjcmV0cy5tZFVUBQABAKbOElBLBQYAAAAAFwAXAK8J" + + "AADhMwMAAAA=" var ( skillDataOnce sync.Once diff --git a/src/clis/nvcf-cli/internal/selfhosted/BUILD.bazel b/src/clis/nvcf-cli/internal/selfhosted/BUILD.bazel index 7737a9a8b9..1b08299376 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/BUILD.bazel +++ b/src/clis/nvcf-cli/internal/selfhosted/BUILD.bazel @@ -26,8 +26,11 @@ go_library( "preflight.go", "pullsecret.go", "register.go", + "registry_cred.go", "render.go", "stack.go", + "stack_namespaces.go", + "stale_namespace.go", "validatortag.go", ], importpath = "nvcf-cli/internal/selfhosted", @@ -42,10 +45,13 @@ go_library( "@io_k8s_api//core/v1:core", "@io_k8s_api//rbac/v1:rbac", "@io_k8s_apimachinery//pkg/api/errors", + "@io_k8s_apimachinery//pkg/api/resource", "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", + "@io_k8s_apimachinery//pkg/labels", "@io_k8s_client_go//kubernetes", "@io_k8s_client_go//rest", "@io_k8s_client_go//tools/clientcmd", + "@io_k8s_sigs_yaml//:yaml", "@org_golang_x_sync//errgroup", ], ) @@ -60,8 +66,11 @@ go_test( "preflight_test.go", "pullsecret_test.go", "register_test.go", + "registry_cred_test.go", "render_test.go", + "stack_namespaces_test.go", "stack_test.go", + "stale_namespace_test.go", "validatortag_test.go", ], embed = [":selfhosted"], diff --git a/src/clis/nvcf-cli/internal/selfhosted/clustervalidator.go b/src/clis/nvcf-cli/internal/selfhosted/clustervalidator.go index 5df457fa76..f3ec9eeca3 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/clustervalidator.go +++ b/src/clis/nvcf-cli/internal/selfhosted/clustervalidator.go @@ -19,9 +19,13 @@ package selfhosted import ( "context" + cryptorand "crypto/rand" + "encoding/hex" "fmt" "io" + "net" "regexp" + "strconv" "strings" "time" @@ -29,7 +33,9 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" ) @@ -41,6 +47,9 @@ const ( clusterValidatorPollInterval = 2 * time.Second clusterValidatorTTLSeconds = int32(600) clusterValidatorHintURL = "https://docs.nvidia.com/nvcf/self-managed-clusters#cluster-validator" + // orphanValidatorRBACTTL is the minimum age before leftover validator RBAC + // is reclaimed. Must exceed the validator timeout so a live run is never hit. + orphanValidatorRBACTTL = 30 * time.Minute ) // Vars (not consts) so tests can shorten without the full production budget. @@ -71,6 +80,15 @@ type ClusterValidatorParams struct { Image string PullSecret string NoCleanup bool + // Role selects which check set the validator runs: "control-plane" or + // "compute-plane" (empty = compute-plane default). Passed to the Job as + // VALIDATOR_ROLE. See clustervalidator.RoleControlPlane / RoleComputePlane. + Role string + // Registries is a list of additional "host:port" registry endpoints to + // probe for reachability in the control-plane validator ConfigMap (in + // addition to nvcr.io which is always included). Ignored for the + // compute-plane role. + Registries []string } // Err is non-nil only when the run failed to execute (RBAC bootstrap, @@ -98,12 +116,12 @@ func NewClusterValidator() ClusterValidator { if err != nil { return ClusterValidatorResult{Err: fmt.Errorf("building kubernetes client: %w", err)} } - return runClusterValidator(ctx, client, p.Image, p.PullSecret, p.NoCleanup) + return runClusterValidator(ctx, client, p.Image, p.PullSecret, p.NoCleanup, p.Role, p.Registries) } } // Testable core. Pass a fake clientset to unit-test without a real cluster. -func runClusterValidator(ctx context.Context, client kubernetes.Interface, image, pullSecret string, noCleanup bool) ClusterValidatorResult { +func runClusterValidator(ctx context.Context, client kubernetes.Interface, image, pullSecret string, noCleanup bool, role string, registries []string) ClusterValidatorResult { if image == "" { // Defensive: callers gate on configured image before invoking the // validator, so this branch shouldn't fire in normal use. @@ -113,31 +131,107 @@ func runClusterValidator(ctx context.Context, client kubernetes.Interface, image vctx, cancel := context.WithTimeout(ctx, clusterValidatorTimeout) defer cancel() + // podMayBeRunning is true only between a successful Job create and a clean + // wait. Both cleanup defers below key off it: outside that window nothing + // is using the pull secret or the RBAC, so reclaiming them is safe, and + // inside it reclaiming them breaks the pod that is still running. + podMayBeRunning := false + + // Random per-run identity. Every object this run creates carries it, so a + // predictable name cannot be pre-created by someone else and then either + // bound to the validator's cluster-wide permissions or overwritten with the + // NGC credential. Generated before anything is created, because the pull + // secret name needs it too. + runID, err := newValidatorRunID() + if err != nil { + return ClusterValidatorResult{Err: err} + } + + // Reclaim leftovers from dead runs before resolving this run's pull secret, + // not after: the sweep matches on the shared name prefix, so running it + // later can delete the Secret this run just selected. + sweepOrphanClusterValidatorRBAC(vctx, client, orphanValidatorRBACTTL) + // Resolver errors are non-fatal: fall through to the caller's value and // let waitForClusterValidatorJob surface ImagePullBackOff if needed. - if resolved, err := resolveValidatorPullSecret(ctx, client, pullSecret, image); err == nil { + if resolved, err := resolveValidatorPullSecret(ctx, client, pullSecret, image, role, runID, noCleanup); err == nil { pullSecret = resolved } - // Sweep any pull secrets we created (mirror or env-mint) after the - // Job terminates. Uses a fresh context so cleanup runs even when - // vctx has expired. Operator-supplied secrets via the flag aren't - // labeled by us and are skipped. - defer sweepManagedPullSecrets(context.Background(), client) + // Sweep only this role's managed pull secret, and only once the pod can no + // longer need it. Sweeping unconditionally deletes the Secret out from + // under a pod that is still retrying its pull, which the kubelet then + // reports as FailedToRetrieveImagePullSecret. Operator-supplied secrets via + // the flag aren't labeled by us and are skipped. + // --no-cleanup is honoured here as it is for the RBAC below: an operator + // who keeps the Job for debugging and then re-runs the preserved pod would + // otherwise hit FailedToRetrieveImagePullSecret, the exact symptom the + // per-role secret scoping exists to prevent. + defer func() { + if !noCleanup && !podMayBeRunning { + sweepManagedPullSecrets(context.Background(), client, role, runID) + } + }() - if err := ensureClusterValidatorRBAC(vctx, client); err != nil { + // Register the cleanup before the bootstrap, not after. ensureClusterValidatorRBAC + // creates three objects in sequence and returns on the first failure, so a + // kubeconfig that can create a ServiceAccount but not a cluster-scoped + // ClusterRole would otherwise abandon the ServiceAccount on every attempt. + // The names are per-run now, so nothing self-heals by reuse: under --wait + // that leaks one object per poll. The sweep is name-scoped and + // label-guarded, so running it when nothing was created is a no-op. + defer func() { + if !noCleanup && !podMayBeRunning { + sweepClusterValidatorRBAC(context.Background(), client, role, runID) + } + }() + if err := ensureClusterValidatorRBAC(vctx, client, role, runID, noCleanup); err != nil { return ClusterValidatorResult{Err: fmt.Errorf("bootstrapping validator RBAC: %w", err)} } - sweepPriorClusterValidatorJobs(vctx, client) + // For the control-plane role, create a ConfigMap with reachability + // endpoints and enforcement config so the validator runs its configurable + // checks. Best-effort: a failure here is logged but does not abort the + // run - the validator gracefully skips configurable checks when the + // ConfigMap is absent. + var configNote string + if role == clusterValidatorControlPlaneRole { + // The ConfigMap is the one object this run creates that had no cleanup + // path, so it was left in the cluster forever. Same gating as the + // other sweeps: keep it when the pod may still read it, or when the + // operator asked to keep the run's artifacts. + defer func() { + if !noCleanup && !podMayBeRunning { + sweepClusterValidatorConfig(context.Background(), client, runID) + } + }() + if err := ensureClusterValidatorConfig(vctx, client, registries, runID, noCleanup); err != nil { + // Non-fatal: continue without the ConfigMap; the validator skips + // configurable reachability and enforcement checks silently unless + // we surface this note in the transcript. + configNote = fmt.Sprintf("note: validator config not applied (%v); reachability checks may be skipped", err) + } + } + + // Skipped under --no-cleanup: this runs before the new Job is created, so + // otherwise the next same-role run destroys the Job the operator asked to + // keep. The singleton guarantee is worth less than the artifact they kept. + if !noCleanup { + sweepPriorClusterValidatorJobs(vctx, client, role) + } jobName := fmt.Sprintf("%s-%d", clusterValidatorName, time.Now().UnixNano()) if _, err := client.BatchV1().Jobs(clusterValidatorNamespace).Create( - vctx, buildClusterValidatorJob(jobName, image, pullSecret, noCleanup), metav1.CreateOptions{}, + vctx, buildClusterValidatorJob(jobName, image, pullSecret, role, runID, noCleanup), metav1.CreateOptions{}, ); err != nil { return ClusterValidatorResult{Err: fmt.Errorf("creating validator Job: %w", err)} } + podMayBeRunning = true final, waitErr := waitForClusterValidatorJob(vctx, client, jobName) + // A clean wait means the pod reached a terminal state, so the RBAC can go. + // A timeout or pull failure leaves it running: pulling the RBAC then fills + // the surviving transcript with "forbidden" and masks the real cause. + podMayBeRunning = waitErr != nil // Fetch logs under a fresh ctx from the parent: vctx is expired on the // timeout path, and dropping the partial transcript hurts most there. @@ -145,6 +239,9 @@ func runClusterValidator(ctx context.Context, client kubernetes.Interface, image defer logCancel() rawLogs, _ := fetchClusterValidatorLogs(logCtx, client, jobName) cleaned := cleanValidatorOutput(rawLogs) + if configNote != "" { + cleaned = configNote + "\n" + cleaned + } if waitErr != nil { return ClusterValidatorResult{ @@ -167,64 +264,72 @@ func runClusterValidator(ctx context.Context, client kubernetes.Interface, image } // Creates the SA/ClusterRole/ClusterRoleBinding the validator pod runs under, -// idempotent via AlreadyExists tolerance. Permissions mirror the -// nvca-operator chart's validator rbac.yaml (read-only). Resources persist -// across runs; the sweep only deletes Jobs. -func ensureClusterValidatorRBAC(ctx context.Context, client kubernetes.Interface) error { - labels := clusterValidatorLabels() +// idempotent via AlreadyExists tolerance. ClusterRole uses update-or-create so +// newer CLI versions replace stale rules without the operator needing to delete. +func ensureClusterValidatorRBAC(ctx context.Context, client kubernetes.Interface, role, runID string, preserve bool) error { + roleLabels := clusterValidatorRoleLabelsPreserved(role, preserve) + name := clusterValidatorRBACName(role, runID) sa := &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ - Name: clusterValidatorName, + Name: name, Namespace: clusterValidatorNamespace, - Labels: labels, + Labels: roleLabels, }, } - if _, err := client.CoreV1().ServiceAccounts(clusterValidatorNamespace).Create(ctx, sa, metav1.CreateOptions{}); err != nil && !apierrors.IsAlreadyExists(err) { + // No AlreadyExists tolerance: the name carries a random per-run suffix, so + // anything already sitting there was not put there by this run and must not + // be adopted and bound to the validator ClusterRole. + if _, err := client.CoreV1().ServiceAccounts(clusterValidatorNamespace).Create(ctx, sa, metav1.CreateOptions{}); err != nil { return fmt.Errorf("create service account: %w", err) } cr := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{Name: clusterValidatorName, Labels: labels}, + ObjectMeta: metav1.ObjectMeta{Name: name, Labels: roleLabels}, Rules: []rbacv1.PolicyRule{ - {APIGroups: []string{""}, Resources: []string{"nodes", "pods", "namespaces", "services", "configmaps"}, Verbs: []string{"get", "list", "watch"}}, + // Read-only: cluster inventory and configuration. + {APIGroups: []string{""}, Resources: []string{"nodes", "configmaps"}, Verbs: []string{"get", "list", "watch"}}, + // Read + write: enforcement checks create and delete probe namespaces + // and pods; the active-LB check creates and deletes a probe service. + {APIGroups: []string{""}, Resources: []string{"namespaces", "pods", "services"}, Verbs: []string{"get", "list", "watch", "create", "delete"}}, + // Pod log subresource: read probe output without exec. + {APIGroups: []string{""}, Resources: []string{"pods/log"}, Verbs: []string{"get"}}, {APIGroups: []string{"storage.k8s.io"}, Resources: []string{"csidrivers", "storageclasses"}, Verbs: []string{"get", "list"}}, - {APIGroups: []string{"networking.k8s.io"}, Resources: []string{"networkpolicies"}, Verbs: []string{"get", "list"}}, + // NetworkPolicies: read for CNI detection; write for enforcement + // check which creates/updates/deletes policies in the temp namespace. + {APIGroups: []string{"networking.k8s.io"}, Resources: []string{"networkpolicies"}, Verbs: []string{"get", "list", "create", "update", "delete"}}, {APIGroups: []string{"admissionregistration.k8s.io"}, Resources: []string{"mutatingwebhookconfigurations", "validatingwebhookconfigurations"}, Verbs: []string{"get", "list"}}, - {APIGroups: []string{"apps"}, Resources: []string{"deployments", "daemonsets", "statefulsets"}, Verbs: []string{"get", "list"}}, + // Deployments/StatefulSets: list for Tier-1/Tier-2 HA readiness checks. + // DaemonSets: create/delete for the node-to-node DaemonSet probe; list to watch pod readiness. + {APIGroups: []string{"apps"}, Resources: []string{"deployments", "statefulsets"}, Verbs: []string{"get", "list"}}, + {APIGroups: []string{"apps"}, Resources: []string{"daemonsets"}, Verbs: []string{"get", "list", "create", "delete"}}, + // Gateway API: control-plane gateway and route health checks. + {APIGroups: []string{"gateway.networking.k8s.io"}, Resources: []string{"gatewayclasses", "gateways", "httproutes", "grpcroutes"}, Verbs: []string{"get", "list"}}, {NonResourceURLs: []string{"/readyz", "/version", "/healthz"}, Verbs: []string{"get"}}, }, } - // Update-or-Create so a future CLI version's expanded rules replace the - // old set; AlreadyExists tolerance alone would silently keep stale rules. - if existing, err := client.RbacV1().ClusterRoles().Get(ctx, clusterValidatorName, metav1.GetOptions{}); err == nil { - existing.Rules = cr.Rules - existing.Labels = cr.Labels - if _, err := client.RbacV1().ClusterRoles().Update(ctx, existing, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("update cluster role: %w", err) - } - } else if apierrors.IsNotFound(err) { - if _, err := client.RbacV1().ClusterRoles().Create(ctx, cr, metav1.CreateOptions{}); err != nil && !apierrors.IsAlreadyExists(err) { - return fmt.Errorf("create cluster role: %w", err) - } - } else { - return fmt.Errorf("get cluster role: %w", err) + // Create only, for the same reason as the ServiceAccount above. The name is + // unique per run, so there are no stale rules from an older CLI to refresh + // and nothing legitimate to overwrite. + if _, err := client.RbacV1().ClusterRoles().Create(ctx, cr, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("create cluster role: %w", err) } crb := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{Name: clusterValidatorName, Labels: labels}, + ObjectMeta: metav1.ObjectMeta{Name: name, Labels: roleLabels}, Subjects: []rbacv1.Subject{{ Kind: rbacv1.ServiceAccountKind, - Name: clusterValidatorName, + Name: name, Namespace: clusterValidatorNamespace, }}, RoleRef: rbacv1.RoleRef{ APIGroup: rbacv1.GroupName, Kind: "ClusterRole", - Name: clusterValidatorName, + Name: name, }, } - if _, err := client.RbacV1().ClusterRoleBindings().Create(ctx, crb, metav1.CreateOptions{}); err != nil && !apierrors.IsAlreadyExists(err) { + // Create only, same reasoning as above. + if _, err := client.RbacV1().ClusterRoleBindings().Create(ctx, crb, metav1.CreateOptions{}); err != nil { return fmt.Errorf("create cluster role binding: %w", err) } return nil @@ -238,15 +343,218 @@ func clusterValidatorLabels() map[string]string { } } +// clusterValidatorRoleLabels adds the role so the prior-run sweep only matches +// Jobs from the same role. Without it, a ModeSingle run deletes the other +// role's Job mid-command, including under --no-cleanup, which makes the +// printed `kubectl logs job/...` hint 404. +func clusterValidatorRoleLabels(role string) map[string]string { + return clusterValidatorRoleLabelsPreserved(role, false) +} + +// clusterValidatorRoleLabelsPreserved adds the preserve marker when the run was +// asked to keep its artifacts, so the orphan sweeper leaves them alone. +func clusterValidatorRoleLabelsPreserved(role string, preserve bool) map[string]string { + l := clusterValidatorLabels() + l[clusterValidatorRoleLabel] = role + if preserve { + l[clusterValidatorPreserveLabel] = "true" + } + return l +} + +// validatorConfigNameForRole returns the network-check ConfigMap name the Job +// should read. Only the control-plane role has one; the compute-plane role gets +// a sentinel that resolves to nothing so it cannot inherit the control-plane's +// reachability and enforcement config. +func validatorConfigNameForRole(role, runID string) string { + if role == clusterValidatorControlPlaneRole { + return clusterValidatorConfigRunName(runID) + } + return clusterValidatorNoConfigName +} + +// clusterValidatorConfigLabels are the managed labels for the network-checks +// ConfigMap, plus the preserve marker when the run was asked to keep its +// artifacts. Without the marker the next run's orphan sweeper reclaims the +// ConfigMap once it is older than the TTL, and an operator re-running a Job +// they deliberately kept gets a validator that silently skips the configurable +// reachability and enforcement checks. +func clusterValidatorConfigLabels(preserve bool) map[string]string { + l := clusterValidatorLabels() + if preserve { + l[clusterValidatorPreserveLabel] = "true" + } + return l +} + +// clusterValidatorConfigRunName scopes the network-checks ConfigMap to one run. +// A shared name lets two overlapping commands overwrite each other's registry +// list, and lets the first to finish delete the config the other pod has not +// read yet. +func clusterValidatorConfigRunName(runID string) string { + if runID == "" { + return clusterValidatorConfigName + } + return clusterValidatorConfigName + "-" + runID +} + +// sweepOrphanClusterValidatorRBAC removes validator RBAC left behind by a run +// that died before its deferred cleanup (SIGKILL, OOM, lost terminal). +// +// Needed because the names are random per run: a fixed name self-healed by +// being reused, these would accumulate. Only objects carrying our labels and +// older than the TTL are removed, so a concurrent run is never disturbed. +func sweepOrphanClusterValidatorRBAC(ctx context.Context, client kubernetes.Interface, ttl time.Duration) { + // Derived from the same map the objects are stamped with, so the selector + // cannot drift from the labels. All three managed labels are required: the + // component label is part of what identifies these as ours. + opts := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(clusterValidatorLabels()).String()} + cutoff := metav1.Time{Time: time.Now().Add(-ttl)} + + // reclaimable requires the generated name as well as the labels and the + // age. Labels alone are three public constants and can be copied onto + // anything, and this deletes cluster-scoped objects with errors swallowed. + // Network-check ConfigMaps carry their own generated-name prefix. + reclaimableConfig := func(o metav1.Object) bool { + if !strings.HasPrefix(o.GetName(), clusterValidatorConfigName) { + return false + } + if o.GetLabels()[clusterValidatorPreserveLabel] == "true" { + return false + } + ts := o.GetCreationTimestamp() + return ts.Before(&cutoff) + } + + // Pull secrets carry the other generated-name prefix. + reclaimableSecret := func(o metav1.Object) bool { + if !strings.HasPrefix(o.GetName(), validatorPullSecretName) { + return false + } + if o.GetLabels()[clusterValidatorPreserveLabel] == "true" { + return false + } + ts := o.GetCreationTimestamp() + return ts.Before(&cutoff) + } + + reclaimable := func(o metav1.Object) bool { + if !strings.HasPrefix(o.GetName(), clusterValidatorName) { + return false + } + if o.GetLabels()[clusterValidatorPreserveLabel] == "true" { + return false + } + ts := o.GetCreationTimestamp() + return ts.Before(&cutoff) + } + + if l, err := client.RbacV1().ClusterRoleBindings().List(ctx, opts); err == nil { + for i := range l.Items { + if o := &l.Items[i]; reclaimable(o) { + _ = client.RbacV1().ClusterRoleBindings().Delete(ctx, o.Name, deleteExactly(o)) + } + } + } + if l, err := client.RbacV1().ClusterRoles().List(ctx, opts); err == nil { + for i := range l.Items { + if o := &l.Items[i]; reclaimable(o) { + _ = client.RbacV1().ClusterRoles().Delete(ctx, o.Name, deleteExactly(o)) + } + } + } + // Network-check ConfigMaps too. Run-scoping the name removed the accidental + // self-healing the fixed name gave us: a killed run used to leave exactly + // one object that the next run overwrote, and now each leaves its own, so + // under --wait they accumulate per poll. Same shape as the RBAC objects. + cms := client.CoreV1().ConfigMaps(clusterValidatorNamespace) + if l, err := cms.List(ctx, opts); err == nil { + for i := range l.Items { + if o := &l.Items[i]; reclaimableConfig(o) { + _ = cms.Delete(ctx, o.Name, deleteExactly(o)) + } + } + } + + // Pull secrets too: the deferred sweep is suppressed whenever the pod may + // still be running, and that is exactly the ImagePullBackOff path, so + // without this arm a Secret holding $oauthtoken:$NGC_API_KEY is the one + // object with no reclaim at all. + secrets := client.CoreV1().Secrets(clusterValidatorNamespace) + if l, err := secrets.List(ctx, opts); err == nil { + for i := range l.Items { + if o := &l.Items[i]; reclaimableSecret(o) { + _ = secrets.Delete(ctx, o.Name, deleteExactly(o)) + } + } + } + sa := client.CoreV1().ServiceAccounts(clusterValidatorNamespace) + if l, err := sa.List(ctx, opts); err == nil { + for i := range l.Items { + if o := &l.Items[i]; reclaimable(o) { + _ = sa.Delete(ctx, o.Name, deleteExactly(o)) + } + } + } +} + +// sweepClusterValidatorRBAC removes the SA, ClusterRole, and ClusterRoleBinding +// created by ensureClusterValidatorRBAC. Called after Job completion (when +// --no-cleanup is not set) to close the window where the elevated ClusterRole +// exists. Each run mints its own names, so nothing is reused and anything left +// behind is reclaimed by sweepOrphanClusterValidatorRBAC instead. +// Errors are swallowed: stale RBAC is preferable to failing the result. +func sweepClusterValidatorRBAC(ctx context.Context, client kubernetes.Interface, role, runID string) { + name := clusterValidatorRBACName(role, runID) + + // Delete by name, but only what we own. These are cluster-scoped objects + // and the errors here are swallowed, so an operator-owned ClusterRole with + // a colliding name would otherwise vanish with no diagnostic at all. + if crb, err := client.RbacV1().ClusterRoleBindings().Get(ctx, name, metav1.GetOptions{}); err == nil && + hasValidatorManagedLabels(crb.Labels) { + _ = client.RbacV1().ClusterRoleBindings().Delete(ctx, name, deleteExactly(crb)) + } + if cr, err := client.RbacV1().ClusterRoles().Get(ctx, name, metav1.GetOptions{}); err == nil && + hasValidatorManagedLabels(cr.Labels) { + _ = client.RbacV1().ClusterRoles().Delete(ctx, name, deleteExactly(cr)) + } + sa := client.CoreV1().ServiceAccounts(clusterValidatorNamespace) + if acct, err := sa.Get(ctx, name, metav1.GetOptions{}); err == nil && + hasValidatorManagedLabels(acct.Labels) { + _ = sa.Delete(ctx, name, deleteExactly(acct)) + } +} + // Errors are swallowed: a stale Job is preferable to blocking the new run. -func sweepPriorClusterValidatorJobs(ctx context.Context, client kubernetes.Interface) { - selector := fmt.Sprintf("app.kubernetes.io/name=%s,app.kubernetes.io/managed-by=nvcf-cli", clusterValidatorAppLabel) +func sweepPriorClusterValidatorJobs(ctx context.Context, client kubernetes.Interface, role string) { + // Scope to this role: in ModeSingle both roles run against the same + // cluster, so an unscoped selector deletes the other role's Job mid-command. + // + // List-then-delete rather than DeleteCollection: the name has to be checked + // too, which a collection selector cannot express, and the labels alone are + // public constants that anything could carry. + jobs := client.BatchV1().Jobs(clusterValidatorNamespace) + l, err := jobs.List(ctx, metav1.ListOptions{LabelSelector: validatorRoleSelector(role)}) + if err != nil { + return + } propagation := metav1.DeletePropagationBackground - _ = client.BatchV1().Jobs(clusterValidatorNamespace).DeleteCollection( - ctx, - metav1.DeleteOptions{PropagationPolicy: &propagation}, - metav1.ListOptions{LabelSelector: selector}, - ) + for i := range l.Items { + if !strings.HasPrefix(l.Items[i].Name, clusterValidatorName) { + continue + } + // A Job an operator kept with --no-cleanup survives later ordinary + // runs too. The current run already skips this sweep under that flag, + // but without the marker the next run of the same role deletes the Job + // while its ConfigMap, RBAC and pull secret survive, leaving the + // preserved artifacts pointing at a Job that no longer exists. + if l.Items[i].Labels[clusterValidatorPreserveLabel] == "true" { + continue + } + opts := deleteExactly(&l.Items[i]) + opts.PropagationPolicy = &propagation + _ = jobs.Delete(ctx, l.Items[i].Name, opts) + } } // sweepManagedPullSecrets removes any docker-registry secrets in @@ -257,40 +565,268 @@ func sweepPriorClusterValidatorJobs(ctx context.Context, client kubernetes.Inter // Operator-supplied secrets via --cluster-validator-pull-secret aren't // labeled by us and are skipped by the selector. Errors are swallowed: // failing to clean up is preferable to failing the check itself. -func sweepManagedPullSecrets(ctx context.Context, client kubernetes.Interface) { - selector := fmt.Sprintf("app.kubernetes.io/name=%s,app.kubernetes.io/managed-by=nvcf-cli", clusterValidatorAppLabel) - _ = client.CoreV1().Secrets(clusterValidatorNamespace).DeleteCollection( - ctx, - metav1.DeleteOptions{}, - metav1.ListOptions{LabelSelector: selector}, - ) -} - -// IfNotPresent so locally-imported images (k3d image import, kind load) are -// reused. VALIDATOR_CONFIG_NAME is empty so the validator skips the -// configurable reachability/network-policy sections (ConfigMap support is a -// follow-up). +func sweepManagedPullSecrets(ctx context.Context, client kubernetes.Interface, role, runID string) { + // Same reasoning as sweepPriorClusterValidatorJobs: the generated name is + // part of the ownership test, not just the labels. + secrets := client.CoreV1().Secrets(clusterValidatorNamespace) + l, err := secrets.List(ctx, metav1.ListOptions{LabelSelector: validatorRoleSelector(role)}) + if err != nil { + return + } + for i := range l.Items { + // Only this run's Secret. The name is unguessable and unique per run, + // so a sweep can no longer take out a Secret another run selected. + if l.Items[i].Name != validatorPullSecretRunName(role, runID) { + continue + } + _ = secrets.Delete(ctx, l.Items[i].Name, deleteExactly(&l.Items[i])) + } +} + +// validatorRoleSelector matches objects this CLI created for one validator role. +// Derived from clusterValidatorRoleLabels so it cannot drift from the labels +// actually stamped on the objects. +func validatorRoleSelector(role string) string { + return labels.SelectorFromSet(clusterValidatorRoleLabels(role)).String() +} + +// clusterValidatorControlPlaneRole is the role value passed as VALIDATOR_ROLE +// when running against the control-plane cluster. Matches nvca's RoleControlPlane +// without importing that package. +const clusterValidatorControlPlaneRole = "control-plane" + +// clusterValidatorComputePlaneRole is the other VALIDATOR_ROLE value. Both are +// named so role-scoping logic reads the same on either side. +const clusterValidatorComputePlaneRole = "compute-plane" + +// clusterValidatorConfigName is the default ConfigMap name the validator binary +// looks for when VALIDATOR_CONFIG_NAME is empty. Must stay in sync with +// defaultConfigMapName in nvca/cmd/cluster-validator/main.go. +const clusterValidatorConfigName = "cluster-validator-network-checks" + +// clusterValidatorNoConfigName is a name no ConfigMap uses. VALIDATOR_CONFIG_NAME +// must be non-empty to suppress the validator's own default-name fallback, so +// "no config" has to be spelled as a name that resolves to nothing. +const clusterValidatorNoConfigName = "cluster-validator-no-config" + +// clusterValidatorRoleLabel scopes Job selectors to a single validator role. +const clusterValidatorRoleLabel = "nvcf.nvidia.com/validator-role" + +// clusterValidatorPreserveLabel marks objects an operator asked to keep with +// --no-cleanup. The orphan sweeper skips them: without it a preserved run is +// reclaimed anyway once it is older than the TTL, which makes the flag mean +// "keep for 30 minutes". +const clusterValidatorPreserveLabel = "nvcf.nvidia.com/validator-preserve" + +// clusterValidatorRBACName returns the ServiceAccount / ClusterRole / +// ClusterRoleBinding name for one run of one role. // -// VALIDATOR_PREFLIGHT=true puts the validator in preflight mode: it runs the -// readiness checks and exits, but does NOT write its summary ConfigMap. The -// ConfigMap exists for the metrics path (the NVCA agent watches it and -// republishes on /metrics), which is meaningless here because preflight runs -// before NVCA is installed and our RBAC bootstrap grants no configmaps -// create/update. Tagging the invocation keeps preflight a clean no-op rather -// than emitting a confusing "failed to create summary ConfigMap" warning. -func buildClusterValidatorJob(name, image, pullSecret string, noCleanup bool) *batchv1.Job { +// The runID is random per run, which is what makes the name safe to create. +// A predictable name can be squatted: the managed labels are three public +// constants, so anyone who can create a ServiceAccount in the probe namespace +// could pre-create one carrying them, and a label check alone would then adopt +// it and bind it to the validator ClusterRole. With an unguessable name there +// is no collision to adopt, so the resources are only ever created by us. +// +// Per-role naming also matters because ModeSplit runs both validators +// concurrently against contexts that can resolve to the same cluster. +func clusterValidatorRBACName(role, runID string) string { + name := clusterValidatorName + if role != "" { + name += "-" + role + } + if runID != "" { + name += "-" + runID + } + return name +} + +// newValidatorRunID returns an unguessable suffix for this run's RBAC names. +// crypto/rand, not math/rand: a predictable value would defeat the point. +func newValidatorRunID() (string, error) { + b := make([]byte, 5) + if _, err := cryptorand.Read(b); err != nil { + return "", fmt.Errorf("generating run id: %w", err) + } + return hex.EncodeToString(b), nil +} + +// controlPlaneValidatorConfigTemplate is the baseline network-check ConfigMap for +// control-plane preflight: nvcr.io reachability (critical) and NetworkPolicy +// enforcement (non-critical). Extra registries are appended as non-critical probes. +const controlPlaneValidatorConfigTemplate = `reachability: + endpoints: + - name: nvcr.io + host: nvcr.io + port: 443 + protocol: tcp+tls + critical: true +enforcement: + # Disabled for preflight. VALIDATOR_PREFLIGHT only suppresses the summary + # write, so enforcement would still run: it creates netpol-validation + # namespaces, server and client pods and NetworkPolicies, and pulls + # busybox from Docker Hub. Doing that on a virgin or air-gapped cluster, + # before anything is installed and with no flag to turn it off, is not + # something a read-only readiness check should do. + enabled: false + testImage: busybox:1.36 + timeoutSeconds: 60 + critical: false +` + +// ensureClusterValidatorConfig creates or updates the network-check ConfigMap. +// extraRegistries are added as non-critical tcp+tls probes. Best-effort: the +// validator skips configurable checks when the ConfigMap is absent. +func ensureClusterValidatorConfig(ctx context.Context, client kubernetes.Interface, extraRegistries []string, runID string, preserve bool) error { + content := buildControlPlaneValidatorConfig(extraRegistries) + desired := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorConfigRunName(runID), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorConfigLabels(preserve), + }, + Data: map[string]string{"config.yaml": content}, + } + + existing, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get(ctx, clusterValidatorConfigRunName(runID), metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return fmt.Errorf("get validator config ConfigMap: %w", err) + } + if _, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Create(ctx, desired, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("create validator config ConfigMap: %w", err) + } + return nil + } + + // Always update so a newer CLI version's config (or new registries) replaces + // stale content, but never overwrite a ConfigMap we do not own. + if !hasValidatorManagedLabels(existing.Labels) { + return fmt.Errorf( + "refusing to overwrite ConfigMap %s/%s which is not managed by nvcf-cli", + clusterValidatorNamespace, clusterValidatorConfigRunName(runID)) + } + existing.Data = desired.Data + existing.Labels = desired.Labels + if _, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Update(ctx, existing, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("update validator config ConfigMap: %w", err) + } + return nil +} + +// buildControlPlaneValidatorConfig assembles the network-check ConfigMap YAML +// from the baseline template plus any operator-supplied extra registries. +func buildControlPlaneValidatorConfig(extraRegistries []string) string { + if len(extraRegistries) == 0 { + return controlPlaneValidatorConfigTemplate + } + + // Parse host:port entries and append as non-critical tcp+tls endpoints. + var extra strings.Builder + for _, reg := range extraRegistries { + host, port := parseRegistryHostPort(reg) + if host == "" { + continue + } + // Append under the existing reachability.endpoints list. Quote the host: + // it comes from operator input, and parseRegistryHostPort passes a value + // it cannot split through verbatim. An unquoted "[" or embedded newline + // would make the whole ConfigMap unparseable, and the validator then + // silently drops every reachability and enforcement check. + fmt.Fprintf(&extra, + " - name: %q\n host: %q\n port: %d\n protocol: tcp+tls\n critical: false\n", + host, host, port) + } + if extra.Len() == 0 { + return controlPlaneValidatorConfigTemplate + } + + // Insert extra endpoints after the nvcr.io entry (before the enforcement block). + return strings.Replace(controlPlaneValidatorConfigTemplate, + "enforcement:", extra.String()+"enforcement:", 1) +} + +// parseRegistryHostPort splits a "host:port" string using net.SplitHostPort, +// which correctly handles IPv6 literals ([::1]:5000) and bare hostnames. +// Returns port 443 when no port is specified, the port is non-numeric, or +// the input has a trailing colon with no digit (e.g. "nvcr.io:"). +func parseRegistryHostPort(s string) (host string, port int) { + s = strings.TrimSpace(s) + // Reject anything that is not a bare host[:port]. Callers interpolate the + // result straight into a URL and into the validator ConfigMap, and an empty + // host is the signal to skip the entry entirely. + if !isBareRegistryHost(s) { + return "", 0 + } + h, p, err := net.SplitHostPort(s) + if err != nil { + // No port present (e.g. "nvcr.io") - return the input as-is. + return s, 443 + } + if p == "" { + // Trailing colon with no port digit (e.g. "nvcr.io:") is the same typo. + return "", 0 + } + n, err := strconv.Atoi(p) + if err != nil || n <= 0 || n > 65535 { + // An explicit but unparseable port is a typo, not a request for 443. + // Silently probing a different endpoint than configured would report a + // result for something the operator never asked about. + return "", 0 + } + return h, n +} + +// buildClusterValidatorJob creates the validator Job. PullIfNotPresent reuses +// locally-imported images. VALIDATOR_PREFLIGHT=true skips the summary ConfigMap +// write. VALIDATOR_ROLE selects the check set (control-plane vs compute-plane). +func buildClusterValidatorJob(name, image, pullSecret, role, runID string, noCleanup bool) *batchv1.Job { backoff := int32(0) + activeDeadline := int64(clusterValidatorTimeout/time.Second) + 60 + // Pod shape mirrors deployments/nvca-operator/templates/cronjob.yaml, which + // runs this same image. Two producers of one pod spec now exist in two + // languages, so they are kept deliberately in step: without the security + // context the Job is rejected outright by a namespace enforcing the + // PodSecurity "restricted" profile, and without the tolerations it never + // schedules on a cluster whose nodes all carry the control-plane taint. + // Either way waitForClusterValidatorJob burns its full budget and the run + // leaks, so these are correctness, not hardening. + runAsUser := int64(65534) + runAsNonRoot := true + readOnlyRoot := true + allowPrivEsc := false podSpec := corev1.PodSpec{ - ServiceAccountName: clusterValidatorName, + ServiceAccountName: clusterValidatorRBACName(role, runID), RestartPolicy: corev1.RestartPolicyNever, + Tolerations: clusterValidatorTolerations(), + SecurityContext: &corev1.PodSecurityContext{ + RunAsUser: &runAsUser, + RunAsGroup: &runAsUser, + FSGroup: &runAsUser, + }, Containers: []corev1.Container{{ Name: clusterValidatorContainer, Image: image, ImagePullPolicy: corev1.PullIfNotPresent, + Resources: clusterValidatorResources(), + SecurityContext: &corev1.SecurityContext{ + RunAsNonRoot: &runAsNonRoot, + ReadOnlyRootFilesystem: &readOnlyRoot, + AllowPrivilegeEscalation: &allowPrivEsc, + Capabilities: &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}, + SeccompProfile: &corev1.SeccompProfile{Type: corev1.SeccompProfileTypeRuntimeDefault}, + }, Env: []corev1.EnvVar{ {Name: "VALIDATOR_CONFIG_NAMESPACE", Value: clusterValidatorNamespace}, - {Name: "VALIDATOR_CONFIG_NAME", Value: ""}, + // Name the ConfigMap explicitly for the control-plane role and + // leave it unresolvable for the compute-plane role. An empty + // value is NOT "no config": the validator falls back to its own + // default name, so both roles would resolve the same ConfigMap + // and the compute-plane preflight would silently run the + // control-plane's active NetworkPolicy enforcement. + {Name: "VALIDATOR_CONFIG_NAME", Value: validatorConfigNameForRole(role, runID)}, {Name: "VALIDATOR_PREFLIGHT", Value: "true"}, + {Name: "VALIDATOR_ROLE", Value: role}, }, }}, } @@ -301,12 +837,20 @@ func buildClusterValidatorJob(name, image, pullSecret string, noCleanup bool) *b ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: clusterValidatorNamespace, - Labels: clusterValidatorLabels(), + Labels: clusterValidatorRoleLabelsPreserved(role, noCleanup), }, Spec: batchv1.JobSpec{ BackoffLimit: &backoff, + // Without a deadline an ImagePullBackOff Job never reaches a + // terminal state, so TTLSecondsAfterFinished never fires and the + // Job, its RBAC and its pull secret persist indefinitely. The + // deferred sweeps are suppressed on that path by design, because + // the pod may still be running, so this is the only reclaim. + // Sized above the runner's own budget so it never truncates a wait + // that is still making progress. + ActiveDeadlineSeconds: &activeDeadline, Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: clusterValidatorLabels()}, + ObjectMeta: metav1.ObjectMeta{Labels: clusterValidatorRoleLabels(role)}, Spec: podSpec, }, }, @@ -450,9 +994,52 @@ func cleanValidatorOutput(raw string) string { return s + "\n" } -func kubectlLogsHint(jobName string) string { +// Pinned to the context the Job was created in: in ModeSplit the two roles +// run against different clusters, so a bare kubectl command resolves to +// whichever context is current and the hint reports "job not found". +func kubectlLogsHint(kubeContext, jobName string) string { if jobName == "" { return "" } - return fmt.Sprintf("kubectl logs -n %s job/%s --tail=-1", clusterValidatorNamespace, jobName) + return fmt.Sprintf("kubectl%s logs -n %s job/%s --tail=-1", + kubectlContextArg(kubeContext), clusterValidatorNamespace, jobName) +} + +// sweepClusterValidatorConfig removes the network-checks ConfigMap this run +// created. The name is scoped to this run, and the managed labels are checked +// as well, so a same-named object belonging to anyone else is left alone. +// Errors are swallowed, as with the other sweeps. +func sweepClusterValidatorConfig(ctx context.Context, client kubernetes.Interface, runID string) { + cms := client.CoreV1().ConfigMaps(clusterValidatorNamespace) + name := clusterValidatorConfigRunName(runID) + cm, err := cms.Get(ctx, name, metav1.GetOptions{}) + if err != nil || !hasValidatorManagedLabels(cm.Labels) { + return + } + _ = cms.Delete(ctx, name, deleteExactly(cm)) +} + +// clusterValidatorTolerations mirrors the chart's tolerations so the Job can +// schedule on a cluster whose nodes all carry the control-plane taint, which +// is the normal shape for a dedicated control plane. +func clusterValidatorTolerations() []corev1.Toleration { + return []corev1.Toleration{ + {Key: "node-role.kubernetes.io/control-plane", Operator: corev1.TolerationOpExists, Effect: corev1.TaintEffectNoSchedule}, + {Key: "node-role.kubernetes.io/master", Operator: corev1.TolerationOpExists, Effect: corev1.TaintEffectNoSchedule}, + } +} + +// clusterValidatorResources mirrors the chart's defaults. Without requests the +// Job is rejected outright by a namespace carrying a LimitRange or a quota. +func clusterValidatorResources() corev1.ResourceRequirements { + return corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("200m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } } diff --git a/src/clis/nvcf-cli/internal/selfhosted/clustervalidator_test.go b/src/clis/nvcf-cli/internal/selfhosted/clustervalidator_test.go index 70ef4a6a91..fcf877b4ff 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/clustervalidator_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/clustervalidator_test.go @@ -99,21 +99,12 @@ func podListReactor(waitingReason string) ktesting.ReactionFunc { } } -func hasActionPrefix(actions []ktesting.Action, verb, resource string) bool { - for _, a := range actions { - if a.GetVerb() == verb && a.GetResource().Resource == resource { - return true - } - } - return false -} - func TestRunClusterValidator_EmptyImage(t *testing.T) { // In normal flow the caller gates on a configured image, so this // branch is defensive. Verify it returns a clear error and makes // no API calls. client := fake.NewSimpleClientset() - res := runClusterValidator(context.Background(), client, "", "", false) + res := runClusterValidator(context.Background(), client, "", "", false, "", nil) require.Error(t, res.Err) assert.Contains(t, res.Err.Error(), "image is empty") assert.False(t, res.Passed) @@ -124,13 +115,32 @@ func TestClusterValidatorCheck_OrchestratorErrorStaysWarning(t *testing.T) { cv := func(_ context.Context, _ ClusterValidatorParams) ClusterValidatorResult { return ClusterValidatorResult{Err: fmt.Errorf("transient: API server unreachable")} } - r := clusterValidatorCheck(cv, "", "", "", false).Run(context.Background()) + r := clusterValidatorCheck(cv, "", "", "", false, "", nil).Run(context.Background()) assert.False(t, r.Passed) assert.Equal(t, "warning", r.Severity, "transient orchestrator failures should not fail the overall preflight") assert.Contains(t, r.Message, "cluster-validator did not complete") } +// driveJobToSuccess wires the reactors that make a created Job reach a +// Succeeded terminal state, mirroring TestRunClusterValidator_HappyPath. +func driveJobToSuccess(client *fake.Clientset) { + var jobName atomic.Value + jobName.Store("") + client.PrependReactor("create", "jobs", func(action ktesting.Action) (bool, runtime.Object, error) { + job := action.(ktesting.CreateAction).GetObject().(*batchv1.Job) + jobName.Store(job.Name) + return false, nil, nil + }) + client.PrependReactor("get", "jobs", func(action ktesting.Action) (bool, runtime.Object, error) { + name := jobName.Load().(string) + if name == "" { + return false, nil, nil + } + return jobSucceededReactor(name)(action) + }) + client.PrependReactor("list", "pods", podListReactor("")) +} func TestRunClusterValidator_HappyPath(t *testing.T) { client := fake.NewSimpleClientset() @@ -169,25 +179,26 @@ func TestRunClusterValidator_HappyPath(t *testing.T) { }, nil }) - res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false) + res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false, "", nil) require.NoError(t, res.Err, "happy path must not surface an error") assert.True(t, res.Passed, "Succeeded>0 maps to Passed=true") assert.Equal(t, int32(0), res.ExitCode) assert.NotEmpty(t, res.JobName, "JobName must be populated so operators can read logs after the run") - // Sweep must run before create so the singleton invariant holds. + // Sweep must run before create so the singleton invariant holds. The sweep + // lists rather than issuing a DeleteCollection, because the generated name + // has to be checked too and a collection selector cannot express that. actions := client.Actions() - require.True(t, hasActionPrefix(actions, "delete-collection", "jobs"), - "runClusterValidator must sweep prior Jobs before creating the new one") var sweepIdx, createIdx = -1, -1 for i, a := range actions { - if a.GetVerb() == "delete-collection" && a.GetResource().Resource == "jobs" && sweepIdx == -1 { + if a.GetVerb() == "list" && a.GetResource().Resource == "jobs" && sweepIdx == -1 { sweepIdx = i } if a.GetVerb() == "create" && a.GetResource().Resource == "jobs" && createIdx == -1 { createIdx = i } } + require.NotEqual(t, -1, sweepIdx, "runClusterValidator must sweep prior Jobs before creating the new one") assert.Less(t, sweepIdx, createIdx, "sweep must precede create in action sequence") } @@ -204,73 +215,105 @@ func TestRunClusterValidator_JobFailed(t *testing.T) { }) client.PrependReactor("list", "pods", podListReactor("")) - res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false) + res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false, "", nil) require.NoError(t, res.Err, "a clean Passed=false verdict must not set Err") assert.False(t, res.Passed, "Failed>0 maps to Passed=false") assert.NotEmpty(t, res.JobName, "JobName must be populated on failure for kubectl-logs follow-up") } -func TestRunClusterValidator_RBACIdempotent(t *testing.T) { +// Each run mints an unguessable RBAC name, so there is no idempotence left to +// test: a name collision means something else already holds the name this run +// is about to bind cluster-wide permissions to. That must fail, not be adopted. +// (Replaces TestRunClusterValidator_RBACIdempotent, which seeded objects under +// the old fixed name and so never produced the AlreadyExists it described.) +func TestRunClusterValidator_RBACNameCollisionIsNotAdopted(t *testing.T) { client := fake.NewSimpleClientset() - // Seed the cluster with the SA, ClusterRole, and ClusterRoleBinding so - // each Create returns AlreadyExists. The runner must treat that as - // success and proceed to Job creation. - existing := []ktesting.ReactionFunc{ - alreadyExistsReactor("serviceaccounts", clusterValidatorName), - alreadyExistsReactor("clusterroles", clusterValidatorName), - alreadyExistsReactor("clusterrolebindings", clusterValidatorName), - } - verbs := []string{"create"} - resources := []string{"serviceaccounts", "clusterroles", "clusterrolebindings"} - for i, r := range existing { - client.PrependReactor(verbs[0], resources[i], r) - } - - var jobName atomic.Value - jobName.Store("") - client.PrependReactor("create", "jobs", func(action ktesting.Action) (bool, runtime.Object, error) { - jobName.Store(action.(ktesting.CreateAction).GetObject().(*batchv1.Job).Name) - return false, nil, nil - }) - client.PrependReactor("get", "jobs", func(action ktesting.Action) (bool, runtime.Object, error) { - return jobSucceededReactor(jobName.Load().(string))(action) + client.PrependReactor("create", "clusterroles", func(action ktesting.Action) (bool, runtime.Object, error) { + name := action.(ktesting.CreateAction).GetObject().(*rbacv1.ClusterRole).Name + return true, nil, apierrors.NewAlreadyExists( + schema.GroupResource{Group: "rbac.authorization.k8s.io", Resource: "clusterroles"}, name) }) - client.PrependReactor("list", "pods", podListReactor("")) - res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false) - require.NoError(t, res.Err, "AlreadyExists on RBAC bootstrap must be treated as success") - assert.True(t, res.Passed) + res := runClusterValidator(context.Background(), client, "nvcr.io/x/validator:1", + "", false, clusterValidatorControlPlaneRole, nil) + require.Error(t, res.Err, "a pre-existing object under our generated name must not be adopted") + assert.Contains(t, res.Err.Error(), "bootstrapping validator RBAC") } -// Regression guard: a ClusterRole left over from an older CLI version must -// be refreshed with the current rule set instead of silently kept stale. -func TestRunClusterValidator_RBACRefreshesClusterRoleRules(t *testing.T) { - oldRules := []rbacv1.PolicyRule{ - {APIGroups: []string{""}, Resources: []string{"nodes"}, Verbs: []string{"get"}}, +func TestEnsureClusterValidatorRBAC_WritableResources(t *testing.T) { + client := fake.NewSimpleClientset() + ctx := context.Background() + + const role = clusterValidatorControlPlaneRole + const runID = "testrunid" + require.NoError(t, ensureClusterValidatorRBAC(ctx, client, role, runID, false)) + + cr, err := client.RbacV1().ClusterRoles().Get(ctx, clusterValidatorRBACName(role, runID), metav1.GetOptions{}) + require.NoError(t, err) + + type check struct { + group string + resource string + verb string + } + required := []check{ + // Enforcement checks create and delete probe namespaces. + {"", "namespaces", "create"}, + {"", "namespaces", "delete"}, + // Probe pods spun up for node-to-node and inter-namespace checks. + {"", "pods", "create"}, + {"", "pods", "delete"}, + // Log reading: fetch probe output without exec. + {"", "pods/log", "get"}, + // Active LB probe service. + {"", "services", "create"}, + {"", "services", "delete"}, + // Enforcement check creates/updates/deletes NetworkPolicies in temp namespace. + {"networking.k8s.io", "networkpolicies", "create"}, + {"networking.k8s.io", "networkpolicies", "update"}, + {"networking.k8s.io", "networkpolicies", "delete"}, + // Gateway API health checks. + {"gateway.networking.k8s.io", "gatewayclasses", "get"}, + {"gateway.networking.k8s.io", "gateways", "list"}, + {"gateway.networking.k8s.io", "httproutes", "get"}, + {"gateway.networking.k8s.io", "grpcroutes", "list"}, } - client := fake.NewSimpleClientset(&rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{Name: clusterValidatorName}, - Rules: oldRules, - }) - var jobName atomic.Value - jobName.Store("") - client.PrependReactor("create", "jobs", func(action ktesting.Action) (bool, runtime.Object, error) { - jobName.Store(action.(ktesting.CreateAction).GetObject().(*batchv1.Job).Name) - return false, nil, nil - }) - client.PrependReactor("get", "jobs", func(action ktesting.Action) (bool, runtime.Object, error) { - return jobSucceededReactor(jobName.Load().(string))(action) - }) - client.PrependReactor("list", "pods", podListReactor("")) + for _, want := range required { + t.Run(fmt.Sprintf("%s/%s/%s", want.group, want.resource, want.verb), func(t *testing.T) { + assert.True(t, rbacRuleCovers(cr.Rules, want.group, want.resource, want.verb), + "ClusterRole must grant %s on %s (group %q)", want.verb, want.resource, want.group) + }) + } +} - res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false) - require.NoError(t, res.Err) +// rbacRuleCovers returns true when any PolicyRule in rules grants verb on +// resource within group. Wildcard verbs ("*") are treated as matching any verb. +func rbacRuleCovers(rules []rbacv1.PolicyRule, group, resource, verb string) bool { + for _, r := range rules { + if len(r.NonResourceURLs) > 0 { + continue // non-resource rules don't apply to API resources + } + if !strSliceContains(r.APIGroups, group) { + continue + } + if !strSliceContains(r.Resources, resource) { + continue + } + if strSliceContains(r.Verbs, verb) || strSliceContains(r.Verbs, "*") { + return true + } + } + return false +} - got, err := client.RbacV1().ClusterRoles().Get(context.Background(), clusterValidatorName, metav1.GetOptions{}) - require.NoError(t, err) - assert.Greater(t, len(got.Rules), len(oldRules), - "ClusterRole rules must be refreshed to the current set on each run, not kept stale") +func strSliceContains(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false } func TestRunClusterValidator_ImagePullBackOffShortCircuits(t *testing.T) { @@ -317,7 +360,7 @@ func TestRunClusterValidator_ImagePullBackOffShortCircuits(t *testing.T) { }) start := time.Now() - res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false) + res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false, "", nil) elapsed := time.Since(start) require.Error(t, res.Err, "ImagePullBackOff must short-circuit the wait with an error") @@ -355,7 +398,7 @@ func TestRunClusterValidator_LogFetchSurvivesValidatorTimeout(t *testing.T) { client.PrependReactor("list", "pods", podListReactor("")) // Parent ctx stays alive for the entire run; only vctx expires. - res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false) + res := runClusterValidator(context.Background(), client, "test-image:1.0", "", false, "", nil) require.Error(t, res.Err, "wait must surface the deadline-exceeded error") assert.Contains(t, res.Err.Error(), "waiting for job", @@ -408,13 +451,13 @@ func TestRunClusterValidator_ContextCanceled(t *testing.T) { time.Sleep(50 * time.Millisecond) cancel() }() - res := runClusterValidator(ctx, client, "test-image:1.0", "", false) + res := runClusterValidator(ctx, client, "test-image:1.0", "", false, "", nil) require.Error(t, res.Err) assert.Contains(t, res.Err.Error(), "context") } func TestBuildClusterValidatorJobShape(t *testing.T) { - job := buildClusterValidatorJob("test-job", "img:1", "", false) + job := buildClusterValidatorJob("test-job", "img:1", "", "", "runid", false) assert.Equal(t, "test-job", job.Name) assert.Equal(t, clusterValidatorNamespace, job.Namespace) @@ -431,8 +474,8 @@ func TestBuildClusterValidatorJobShape(t *testing.T) { "IfNotPresent so locally-imported images (k3d image import, kind load) are picked up without a registry pull") assert.Equal(t, corev1.RestartPolicyNever, job.Spec.Template.Spec.RestartPolicy, "validator is a one-shot command, not a long-running service") - assert.Equal(t, clusterValidatorName, job.Spec.Template.Spec.ServiceAccountName, - "pod must run under the CLI-bootstrapped SA, not the namespace default") + assert.Equal(t, clusterValidatorRBACName("", "runid"), job.Spec.Template.Spec.ServiceAccountName, + "pod must run under this run's bootstrapped SA, not the namespace default") labels := job.Labels assert.Equal(t, clusterValidatorAppLabel, labels["app.kubernetes.io/name"]) @@ -450,20 +493,30 @@ func TestBuildClusterValidatorJobShape(t *testing.T) { "preflight invocation must tag the validator so it does not attempt the metrics ConfigMap write") } +func TestBuildClusterValidatorJobShape_ValidatorRoleInEnv(t *testing.T) { + job := buildClusterValidatorJob("test-job", "img:1", "", clusterValidatorControlPlaneRole, "runid", false) + env := map[string]string{} + for _, e := range job.Spec.Template.Spec.Containers[0].Env { + env[e.Name] = e.Value + } + assert.Equal(t, clusterValidatorControlPlaneRole, env["VALIDATOR_ROLE"], + "VALIDATOR_ROLE must carry the role to the validator binary") +} + func TestBuildClusterValidatorJobShape_WithPullSecret(t *testing.T) { - job := buildClusterValidatorJob("test-job", "img:1", "nvcr-pull-secret", false) + job := buildClusterValidatorJob("test-job", "img:1", "nvcr-pull-secret", "", "runid", false) require.Len(t, job.Spec.Template.Spec.ImagePullSecrets, 1) assert.Equal(t, "nvcr-pull-secret", job.Spec.Template.Spec.ImagePullSecrets[0].Name) } func TestBuildClusterValidatorJobShape_NoPullSecret(t *testing.T) { - job := buildClusterValidatorJob("test-job", "img:1", "", false) + job := buildClusterValidatorJob("test-job", "img:1", "", "", "runid", false) assert.Empty(t, job.Spec.Template.Spec.ImagePullSecrets, "empty pull-secret arg must not produce an empty-name ImagePullSecrets entry") } func TestBuildClusterValidatorJobShape_NoCleanup(t *testing.T) { - job := buildClusterValidatorJob("test-job", "img:1", "", true) + job := buildClusterValidatorJob("test-job", "img:1", "", "", "runid", true) assert.Nil(t, job.Spec.TTLSecondsAfterFinished, "--no-cleanup must omit TTLSecondsAfterFinished so the Job persists for debugging") } @@ -509,30 +562,572 @@ func TestCleanValidatorOutput_EmptyInput(t *testing.T) { } func TestKubectlLogsHint(t *testing.T) { - got := kubectlLogsHint("nvcf-preflight-validator-12345") + got := kubectlLogsHint("", "nvcf-preflight-validator-12345") assert.Equal(t, "kubectl logs -n default job/nvcf-preflight-validator-12345 --tail=-1", got, ) } +// In ModeSplit the two roles run against different clusters, so the hint has +// to name the context the Job was actually created in. +func TestKubectlLogsHint_PinsContext(t *testing.T) { + got := kubectlLogsHint("gpu-ctx", "nvcf-preflight-validator-12345") + assert.Equal(t, + "kubectl --context gpu-ctx logs -n default job/nvcf-preflight-validator-12345 --tail=-1", + got, + ) +} + +func TestKubectlLogsHint_QuotesContext(t *testing.T) { + got := kubectlLogsHint("my ctx", "nvcf-preflight-validator-12345") + assert.Contains(t, got, "--context 'my ctx'", + "a context name with a space must be quoted so the pasted command does not split it") +} + func TestKubectlLogsHint_EmptyJob(t *testing.T) { - assert.Equal(t, "", kubectlLogsHint(""), + assert.Equal(t, "", kubectlLogsHint("gpu-ctx", ""), "empty jobName must produce empty hint so callers can compose detail without conditionals") } -func alreadyExistsReactor(resource, name string) ktesting.ReactionFunc { - gr := schema.GroupResource{Resource: resource} - return func(action ktesting.Action) (bool, runtime.Object, error) { - createAction, ok := action.(ktesting.CreateAction) - if !ok { - return false, nil, nil - } - meta, ok := createAction.GetObject().(metav1.Object) - if !ok || meta.GetName() != name { - return false, nil, nil - } - return true, nil, apierrors.NewAlreadyExists(gr, name) +func TestBuildControlPlaneValidatorConfig_NoExtras(t *testing.T) { + got := buildControlPlaneValidatorConfig(nil) + assert.Equal(t, controlPlaneValidatorConfigTemplate, got, + "no extra registries must return the template unchanged") + assert.Contains(t, got, "nvcr.io", "nvcr.io must always be present") + assert.Contains(t, got, "enforcement:", "enforcement block must be present") +} + +func TestBuildControlPlaneValidatorConfig_WithExtras(t *testing.T) { + got := buildControlPlaneValidatorConfig([]string{"harbor.company.internal:443", "ghcr.io:443"}) + assert.Contains(t, got, "harbor.company.internal") + assert.Contains(t, got, "ghcr.io") + assert.Contains(t, got, "nvcr.io", "nvcr.io must still be present alongside extras") + assert.Contains(t, got, "enforcement:", "enforcement block must still be present after extras") + // Extra registries must appear BEFORE enforcement. + harborIdx := strings.Index(got, "harbor.company.internal") + enforcementIdx := strings.Index(got, "enforcement:") + assert.Less(t, harborIdx, enforcementIdx, "extra registry endpoints must appear before the enforcement block") +} + +func TestBuildControlPlaneValidatorConfig_InvalidRegistrySkipped(t *testing.T) { + // A blank entry is parsed as host="" -> skipped; only the valid entry appears. + got := buildControlPlaneValidatorConfig([]string{" ", "valid.registry.internal:5000"}) + assert.Contains(t, got, "valid.registry.internal", "valid registry must appear") + // The blank entry must not add an empty host: line. + assert.NotContains(t, got, "host: \n", "blank entry must not produce an empty host line") +} + +func TestParseRegistryHostPort(t *testing.T) { + tests := []struct { + in string + wantHost string + wantPort int + }{ + {"nvcr.io:443", "nvcr.io", 443}, + {"harbor.company.internal:5000", "harbor.company.internal", 5000}, + {"registry.example.com", "registry.example.com", 443}, // no port -> 443 + {"", "", 0}, // empty -> skip + {" ", "", 0}, // blank -> skip + // IPv6: net.SplitHostPort handles bracketed literals correctly. + {"[::1]:5000", "::1", 5000}, + {"[2001:db8::1]:443", "2001:db8::1", 443}, + // An explicit but unusable port is a typo, not a request for 443: + // probing a different endpoint than configured reports a result for + // something the operator never asked about. + {"nvcr.io:", "", 0}, + {"nvcr.io:abc", "", 0}, + {"nvcr.io:0", "", 0}, + {"nvcr.io:70000", "", 0}, } + for _, tt := range tests { + t.Run(tt.in, func(t *testing.T) { + h, p := parseRegistryHostPort(tt.in) + assert.Equal(t, tt.wantHost, h) + assert.Equal(t, tt.wantPort, p) + }) + } +} +func TestEnsureClusterValidatorConfig_RefusesUnmanagedConfigMap(t *testing.T) { + ctx := context.Background() + client := fake.NewSimpleClientset(&corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorConfigRunName("runid"), + Namespace: clusterValidatorNamespace, + Labels: map[string]string{"owner": "operator"}, + }, + Data: map[string]string{"config.yaml": "operator: content"}, + }) + + err := ensureClusterValidatorConfig(ctx, client, nil, "runid", false) + require.Error(t, err, "an unmanaged ConfigMap must not be overwritten") + assert.Contains(t, err.Error(), "not managed by nvcf-cli") + + got, getErr := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get(ctx, + clusterValidatorConfigRunName("runid"), metav1.GetOptions{}) + require.NoError(t, getErr) + assert.Equal(t, "operator: content", got.Data["config.yaml"], + "the operator's ConfigMap content must be untouched") } +// The managed labels are three public constants, so a label check alone cannot +// establish ownership: anyone able to create a ServiceAccount in the probe +// namespace could stamp them. Safety comes from the name being unguessable, so +// there is no predictable object to pre-create and get bound to the validator's +// cluster-wide permissions. +func TestClusterValidatorRBACName_IsUnpredictableAndPerRun(t *testing.T) { + a, err := newValidatorRunID() + require.NoError(t, err) + b, err := newValidatorRunID() + require.NoError(t, err) + + assert.NotEqual(t, a, b, "each run must get a distinct identity") + assert.NotEmpty(t, a) + + const role = clusterValidatorControlPlaneRole + assert.NotEqual(t, clusterValidatorRBACName(role, a), clusterValidatorRBACName(role, b), + "RBAC names must differ per run") + assert.NotEqual(t, clusterValidatorRBACName(role, a), clusterValidatorRBACName("compute-plane", a), + "RBAC names must differ per role within a run") +} + +// Nothing pre-existing is adopted: creation is unconditional, so a squatted +// object surfaces as an error rather than being bound to our ClusterRole. +func TestEnsureClusterValidatorRBAC_DoesNotAdoptExistingObjects(t *testing.T) { + ctx := context.Background() + const role = clusterValidatorControlPlaneRole + const runID = "collide" + name := clusterValidatorRBACName(role, runID) + + // Forged managed labels: a label check alone would have adopted this. + client := fake.NewSimpleClientset(&corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, Namespace: clusterValidatorNamespace, Labels: clusterValidatorLabels(), + }, + }) + + err := ensureClusterValidatorRBAC(ctx, client, role, runID, false) + require.Error(t, err, "a pre-existing object must not be adopted, forged labels or not") + + _, bindErr := client.RbacV1().ClusterRoleBindings().Get(ctx, name, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(bindErr), + "no binding may be created when the ServiceAccount was not created by this run") +} + +// Random names cannot self-heal by being reused next run, so leftovers from a +// killed run are reclaimed by age. Two things must survive: anything recent +// (it may belong to a run happening right now) and anything whose name is not +// one we generate, even when it carries our labels. Those labels are three +// public constants, so they can be copied onto anything. +func TestSweepOrphanClusterValidatorRBAC_RequiresNameLabelsAndAge(t *testing.T) { + ctx := context.Background() + old := metav1.NewTime(time.Now().Add(-2 * time.Hour)) + now := metav1.NewTime(time.Now()) + staleName := clusterValidatorRBACName(clusterValidatorControlPlaneRole, "deadbeef01") + freshName := clusterValidatorRBACName("compute-plane", "cafebabe02") + + client := fake.NewSimpleClientset( + &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{ + Name: staleName, Labels: clusterValidatorLabels(), CreationTimestamp: old, + }}, + &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{ + Name: freshName, Labels: clusterValidatorLabels(), CreationTimestamp: now, + }}, + // Our labels, but not a name we generate: an operator copying the + // labels onto their own ClusterRole must not have it deleted. + &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{ + Name: "operator-owned-role", Labels: clusterValidatorLabels(), CreationTimestamp: old, + }}, + ) + + sweepOrphanClusterValidatorRBAC(ctx, client, orphanValidatorRBACTTL) + + _, err := client.RbacV1().ClusterRoles().Get(ctx, staleName, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), "a generated name past the TTL must be reclaimed") + + _, err = client.RbacV1().ClusterRoles().Get(ctx, freshName, metav1.GetOptions{}) + assert.NoError(t, err, "a recent one may belong to a concurrent run") + + _, err = client.RbacV1().ClusterRoles().Get(ctx, "operator-owned-role", metav1.GetOptions{}) + assert.NoError(t, err, "matching labels alone must not authorize deleting someone else's object") +} + +// An explicit but unparseable port is a typo. Silently probing 443 would report +// a result for an endpoint the operator never configured. +func TestParseRegistryHostPort_RejectsMalformedExplicitPort(t *testing.T) { + for _, in := range []string{"registry.example:abc", "registry.example:0", "registry.example:99999", "registry.example:"} { + host, port := parseRegistryHostPort(in) + assert.Empty(t, host, "%q must be rejected, not defaulted", in) + assert.Zero(t, port, "%q must not fall back to a port", in) + } + host, port := parseRegistryHostPort("registry.example") + assert.Equal(t, "registry.example", host, "no explicit port keeps the default") + assert.Equal(t, 443, port) +} + +// The prior-run Job sweep deletes by label plus generated name. Labels alone +// are three public constants, so a Job carrying them under an unrelated name is +// not ours to delete. +func TestSweepPriorClusterValidatorJobs_RequiresGeneratedName(t *testing.T) { + ctx := context.Background() + const role = clusterValidatorControlPlaneRole + ours := clusterValidatorName + "-1700000000" + + client := fake.NewSimpleClientset( + &batchv1.Job{ObjectMeta: metav1.ObjectMeta{ + Name: ours, Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels(role), + }}, + &batchv1.Job{ObjectMeta: metav1.ObjectMeta{ + Name: "operator-owned-job", Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels(role), + }}, + &batchv1.Job{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorName + "-9999999999", Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels("compute-plane"), + }}, + ) + + sweepPriorClusterValidatorJobs(ctx, client, role) + + jobs := client.BatchV1().Jobs(clusterValidatorNamespace) + _, err := jobs.Get(ctx, ours, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), "this role's prior Job must be swept") + + _, err = jobs.Get(ctx, "operator-owned-job", metav1.GetOptions{}) + assert.NoError(t, err, "matching labels alone must not authorize deleting someone else's Job") + + _, err = jobs.Get(ctx, clusterValidatorName+"-9999999999", metav1.GetOptions{}) + assert.NoError(t, err, "the other role's Job must survive") +} + +// The network-checks ConfigMap was the one object a run created with no +// cleanup path, so it accumulated in the cluster forever. +func TestSweepClusterValidatorConfig_DeletesOwnAndSparesOperators(t *testing.T) { + managed := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorConfigRunName("runid"), Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + }} + client := fake.NewSimpleClientset(managed) + sweepClusterValidatorConfig(context.Background(), client, "runid") + _, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), clusterValidatorConfigRunName("runid"), metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), "our own ConfigMap must be reclaimed") + + // Same name, operator-owned: the name is a constant they could also use. + operator := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorConfigRunName("runid"), Namespace: clusterValidatorNamespace, + Labels: map[string]string{"owner": "operator"}, + }} + client2 := fake.NewSimpleClientset(operator) + sweepClusterValidatorConfig(context.Background(), client2, "runid") + _, err = client2.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), clusterValidatorConfigRunName("runid"), metav1.GetOptions{}) + assert.NoError(t, err, "an unmanaged ConfigMap with the same name must survive") +} + +// --no-cleanup must preserve the whole run, not just the Job: an operator who +// keeps the Job and re-runs the pod needs its pull secret to still exist. +func TestRunClusterValidator_NoCleanupKeepsPullSecretAndPriorJob(t *testing.T) { + prior := &batchv1.Job{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorName + "-earlier", Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels(clusterValidatorControlPlaneRole), + CreationTimestamp: metav1.NewTime(time.Now()), + }} + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels(clusterValidatorControlPlaneRole), + // The fake clientset leaves this zero, which the orphan sweeper + // reads as older than any TTL. A real apiserver stamps it. + CreationTimestamp: metav1.NewTime(time.Now()), + }, + Type: corev1.SecretTypeDockerConfigJson, + } + client := fake.NewSimpleClientset(prior, secret) + driveJobToSuccess(client) + + runClusterValidator(context.Background(), client, "nvcr.io/x/validator:1", + "", true /* noCleanup */, clusterValidatorControlPlaneRole, nil) + + _, err := client.BatchV1().Jobs(clusterValidatorNamespace).Get( + context.Background(), prior.Name, metav1.GetOptions{}) + assert.NoError(t, err, "--no-cleanup must not destroy a deliberately preserved Job") + + _, err = client.CoreV1().Secrets(clusterValidatorNamespace).Get( + context.Background(), secret.Name, metav1.GetOptions{}) + assert.NoError(t, err, "--no-cleanup must keep the pull secret the preserved pod needs") +} + +// The Job runs the same image as the chart's CronJob, so it needs the same pod +// shape. Without the security context a namespace enforcing the PodSecurity +// "restricted" profile rejects it at admission; without the tolerations it +// never schedules on a cluster whose nodes all carry the control-plane taint. +// Either way the wait burns its full budget and the run leaks. +func TestBuildClusterValidatorJob_MatchesChartPodShape(t *testing.T) { + job := buildClusterValidatorJob("j", "nvcr.io/x/validator:1", "", + clusterValidatorControlPlaneRole, "runid", false) + spec := job.Spec.Template.Spec + + require.NotNil(t, spec.SecurityContext, "pod security context is required under restricted") + require.NotNil(t, spec.SecurityContext.RunAsUser) + assert.Equal(t, int64(65534), *spec.SecurityContext.RunAsUser, "chart runs this image as 65534") + + require.Len(t, spec.Containers, 1) + sc := spec.Containers[0].SecurityContext + require.NotNil(t, sc, "container security context is required under restricted") + require.NotNil(t, sc.RunAsNonRoot) + assert.True(t, *sc.RunAsNonRoot) + require.NotNil(t, sc.AllowPrivilegeEscalation) + assert.False(t, *sc.AllowPrivilegeEscalation) + require.NotNil(t, sc.Capabilities) + assert.Equal(t, []corev1.Capability{"ALL"}, sc.Capabilities.Drop) + require.NotNil(t, sc.SeccompProfile) + assert.Equal(t, corev1.SeccompProfileTypeRuntimeDefault, sc.SeccompProfile.Type) + + var keys []string + for _, tol := range spec.Tolerations { + keys = append(keys, tol.Key) + } + assert.Contains(t, keys, "node-role.kubernetes.io/control-plane") + assert.Contains(t, keys, "node-role.kubernetes.io/master") + + assert.False(t, spec.Containers[0].Resources.Requests.Cpu().IsZero(), + "a namespace with a LimitRange or quota rejects a pod with no requests") +} + +// An ImagePullBackOff Job never reaches a terminal state on its own, so +// TTLSecondsAfterFinished never fires and the Job, its cluster-wide RBAC and +// its NGC-derived pull secret persist forever. The deferred sweeps are +// suppressed on that path by design, so the deadline is the only reclaim. +func TestBuildClusterValidatorJob_SetsActiveDeadline(t *testing.T) { + job := buildClusterValidatorJob("j", "nvcr.io/x/validator:1", "", + clusterValidatorControlPlaneRole, "runid", false) + require.NotNil(t, job.Spec.ActiveDeadlineSeconds, + "a Job with no deadline cannot terminate itself on a pull failure") + assert.Greater(t, *job.Spec.ActiveDeadlineSeconds, int64(clusterValidatorTimeout/time.Second), + "the deadline must outlast the runner's own wait so it never truncates a live run") +} + +// The pull secret holds $oauthtoken:$NGC_API_KEY, and the deferred sweep is +// skipped whenever the pod may still be running, which is the pull-failure +// path. The orphan sweeper is its only other reclaim. +func TestSweepOrphanClusterValidatorRBAC_ReclaimsStalePullSecret(t *testing.T) { + old := metav1.NewTime(time.Now().Add(-time.Hour)) + stale := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{ + Name: validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + CreationTimestamp: old, + }} + client := fake.NewSimpleClientset(stale) + sweepOrphanClusterValidatorRBAC(context.Background(), client, orphanValidatorRBACTTL) + + _, err := client.CoreV1().Secrets(clusterValidatorNamespace).Get( + context.Background(), stale.Name, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), "a stale managed pull secret must be reclaimed") +} + +// A fresh secret may belong to a concurrent run, and an operator-supplied one +// carries neither our labels nor our name. +func TestSweepOrphanClusterValidatorRBAC_SparesFreshAndUnmanagedSecrets(t *testing.T) { + fresh := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{ + Name: validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + CreationTimestamp: metav1.NewTime(time.Now()), + }} + operator := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{ + Name: "operator-pull", + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + CreationTimestamp: metav1.NewTime(time.Now().Add(-time.Hour)), + }} + client := fake.NewSimpleClientset(fresh, operator) + sweepOrphanClusterValidatorRBAC(context.Background(), client, orphanValidatorRBACTTL) + + for _, name := range []string{fresh.Name, operator.Name} { + _, err := client.CoreV1().Secrets(clusterValidatorNamespace).Get( + context.Background(), name, metav1.GetOptions{}) + assert.NoError(t, err, "%s must survive the orphan sweep", name) + } +} + +// The preflight ConfigMap must not switch on active NetworkPolicy enforcement. +// VALIDATOR_PREFLIGHT only suppresses the summary write, so enforcement would +// still create namespaces, pods and NetworkPolicies and pull busybox from +// Docker Hub, on a cluster where nothing is installed yet. +func TestBuildControlPlaneValidatorConfig_EnforcementDisabledForPreflight(t *testing.T) { + cfg := buildControlPlaneValidatorConfig(nil) + idx := strings.Index(cfg, "enforcement:") + require.GreaterOrEqual(t, idx, 0, "the enforcement block must be present") + assert.Contains(t, cfg[idx:], "enabled: false", + "a read-only readiness check must not mutate the cluster or need Docker Hub") +} + +// --no-cleanup must outlast the orphan TTL. Without a preserve marker the +// orphan sweeper reclaims a deliberately kept run after 30 minutes, which +// makes the flag mean "keep for 30 minutes". +func TestSweepOrphanClusterValidatorRBAC_SparesPreservedObjects(t *testing.T) { + labels := clusterValidatorLabels() + labels[clusterValidatorPreserveLabel] = "true" + old := metav1.NewTime(time.Now().Add(-time.Hour)) + client := fake.NewSimpleClientset( + &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorName + "-control-plane-abc", Labels: labels, CreationTimestamp: old, + }}, + &corev1.Secret{ObjectMeta: metav1.ObjectMeta{ + Name: validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), + Namespace: clusterValidatorNamespace, Labels: labels, CreationTimestamp: old, + }}, + ) + sweepOrphanClusterValidatorRBAC(context.Background(), client, orphanValidatorRBACTTL) + + _, err := client.RbacV1().ClusterRoles().Get(context.Background(), + clusterValidatorName+"-control-plane-abc", metav1.GetOptions{}) + assert.NoError(t, err, "a preserved ClusterRole must survive the orphan sweep") + _, err = client.CoreV1().Secrets(clusterValidatorNamespace).Get(context.Background(), + validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), metav1.GetOptions{}) + assert.NoError(t, err, "a preserved pull secret must survive the orphan sweep") +} + +// The preserve marker has to be applied at creation, not just honoured by the +// sweeper, or the mechanism is inert. +func TestEnsureClusterValidatorRBAC_LabelsPreservedRun(t *testing.T) { + client := fake.NewSimpleClientset() + require.NoError(t, ensureClusterValidatorRBAC(context.Background(), client, + clusterValidatorControlPlaneRole, "abc123", true)) + + cr, err := client.RbacV1().ClusterRoles().Get(context.Background(), + clusterValidatorRBACName(clusterValidatorControlPlaneRole, "abc123"), metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, "true", cr.Labels[clusterValidatorPreserveLabel], + "--no-cleanup must mark its objects so the orphan sweeper spares them") +} + +func TestEnsureClusterValidatorRBAC_NoPreserveLabelByDefault(t *testing.T) { + client := fake.NewSimpleClientset() + require.NoError(t, ensureClusterValidatorRBAC(context.Background(), client, + clusterValidatorControlPlaneRole, "abc123", false)) + + cr, err := client.RbacV1().ClusterRoles().Get(context.Background(), + clusterValidatorRBACName(clusterValidatorControlPlaneRole, "abc123"), metav1.GetOptions{}) + require.NoError(t, err) + assert.NotContains(t, cr.Labels, clusterValidatorPreserveLabel, + "an ordinary run must stay reclaimable") +} + +// Run-scoping the ConfigMap name removed the accidental self-healing the fixed +// name gave us: a killed run used to leave exactly one object that the next run +// overwrote, and now each leaves its own. The deferred sweep is suppressed on +// the pull-failure path, so the orphan sweeper is the only reclaim. +func TestSweepOrphanClusterValidatorRBAC_ReclaimsStaleConfigMap(t *testing.T) { + old := metav1.NewTime(time.Now().Add(-time.Hour)) + stale := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorConfigRunName("deadbeef01"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + CreationTimestamp: old, + }} + client := fake.NewSimpleClientset(stale) + sweepOrphanClusterValidatorRBAC(context.Background(), client, orphanValidatorRBACTTL) + + _, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), stale.Name, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), + "a per-run ConfigMap left by a killed run must be reclaimed") +} + +func TestSweepOrphanClusterValidatorRBAC_SparesFreshAndUnmanagedConfigMaps(t *testing.T) { + fresh := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{ + Name: clusterValidatorConfigRunName("aaaaaaaa01"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + CreationTimestamp: metav1.NewTime(time.Now()), + }} + operator := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{ + Name: "operator-owned", + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + CreationTimestamp: metav1.NewTime(time.Now().Add(-time.Hour)), + }} + client := fake.NewSimpleClientset(fresh, operator) + sweepOrphanClusterValidatorRBAC(context.Background(), client, orphanValidatorRBACTTL) + + for _, name := range []string{fresh.Name, operator.Name} { + _, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), name, metav1.GetOptions{}) + assert.NoError(t, err, "%s must survive the orphan sweep", name) + } +} + +// --no-cleanup must preserve the ConfigMap as well as the Job and its RBAC. +// Without the marker the next run's orphan sweeper reclaims it after the TTL, +// and an operator re-running the Job they kept gets a validator that silently +// skips the configurable reachability and enforcement checks. +func TestEnsureClusterValidatorConfig_MarksPreservedRun(t *testing.T) { + client := fake.NewSimpleClientset() + require.NoError(t, ensureClusterValidatorConfig(context.Background(), client, nil, "runid", true)) + + cm, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), clusterValidatorConfigRunName("runid"), metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, "true", cm.Labels[clusterValidatorPreserveLabel]) + + // And the orphan sweeper honours it even once it is older than the TTL. + cm.CreationTimestamp = metav1.NewTime(time.Now().Add(-time.Hour)) + _, err = client.CoreV1().ConfigMaps(clusterValidatorNamespace).Update( + context.Background(), cm, metav1.UpdateOptions{}) + require.NoError(t, err) + sweepOrphanClusterValidatorRBAC(context.Background(), client, orphanValidatorRBACTTL) + + _, err = client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), clusterValidatorConfigRunName("runid"), metav1.GetOptions{}) + assert.NoError(t, err, "a preserved ConfigMap must survive the orphan sweep") +} + +func TestEnsureClusterValidatorConfig_NoPreserveMarkerByDefault(t *testing.T) { + client := fake.NewSimpleClientset() + require.NoError(t, ensureClusterValidatorConfig(context.Background(), client, nil, "runid", false)) + + cm, err := client.CoreV1().ConfigMaps(clusterValidatorNamespace).Get( + context.Background(), clusterValidatorConfigRunName("runid"), metav1.GetOptions{}) + require.NoError(t, err) + assert.NotContains(t, cm.Labels, clusterValidatorPreserveLabel, + "an ordinary run must stay reclaimable") +} + +// --no-cleanup has to outlast the run that set it. The run itself already skips +// the prior-Job sweep, but without a marker on the Job the next ordinary run of +// the same role deletes it, while its ConfigMap, RBAC and pull secret survive. +func TestBuildClusterValidatorJob_MarksPreservedRun(t *testing.T) { + kept := buildClusterValidatorJob("j", "nvcr.io/x/v:1", "", + clusterValidatorControlPlaneRole, "runid", true) + assert.Equal(t, "true", kept.Labels[clusterValidatorPreserveLabel]) + + ordinary := buildClusterValidatorJob("j", "nvcr.io/x/v:1", "", + clusterValidatorControlPlaneRole, "runid", false) + assert.NotContains(t, ordinary.Labels, clusterValidatorPreserveLabel, + "an ordinary run must stay sweepable") +} + +func TestSweepPriorClusterValidatorJobs_SparesPreservedJob(t *testing.T) { + preserved := buildClusterValidatorJob(clusterValidatorName+"-kept", "nvcr.io/x/v:1", "", + clusterValidatorControlPlaneRole, "runid", true) + preserved.Namespace = clusterValidatorNamespace + ordinary := buildClusterValidatorJob(clusterValidatorName+"-old", "nvcr.io/x/v:1", "", + clusterValidatorControlPlaneRole, "runid", false) + ordinary.Namespace = clusterValidatorNamespace + + client := fake.NewSimpleClientset(preserved, ordinary) + sweepPriorClusterValidatorJobs(context.Background(), client, clusterValidatorControlPlaneRole) + + _, err := client.BatchV1().Jobs(clusterValidatorNamespace).Get( + context.Background(), preserved.Name, metav1.GetOptions{}) + assert.NoError(t, err, "a Job kept with --no-cleanup must survive a later run's sweep") + + _, err = client.BatchV1().Jobs(clusterValidatorNamespace).Get( + context.Background(), ordinary.Name, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), "an ordinary prior Job must still be swept") +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/orchestrator_errors_test.go b/src/clis/nvcf-cli/internal/selfhosted/orchestrator_errors_test.go index a3b2e0e184..1bd771a614 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/orchestrator_errors_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/orchestrator_errors_test.go @@ -422,9 +422,9 @@ func TestRetryAfterFromError_Parsing(t *testing.T) { {"rate limit: Retry-After: 30", 30}, {"Retry-After: 120s", 120}, {"retry-after: 5", 5}, - {"no header here", 5}, // default - {"Retry-After: ", 5}, // no digits → default - {"Retry-After: 0", 5}, // zero → default + {"no header here", 5}, // default + {"Retry-After: ", 5}, // no digits -> default + {"Retry-After: 0", 5}, // zero -> default {"Retry-After: 300 ok", 300}, // stops at first non-digit } for _, tc := range cases { diff --git a/src/clis/nvcf-cli/internal/selfhosted/preflight.go b/src/clis/nvcf-cli/internal/selfhosted/preflight.go index e4dc5858a1..97285be354 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/preflight.go +++ b/src/clis/nvcf-cli/internal/selfhosted/preflight.go @@ -19,6 +19,7 @@ package selfhosted import ( "context" + "errors" "fmt" "net/http" "os" @@ -44,6 +45,15 @@ const ( binaryVersionMessage = "%s %s on PATH (%s required)" ) +// Severity values for CheckResult. Typed constants rather than bare strings: +// a typo'd "Error" silently downgraded a hard failure to a warning, and the +// exit code keys off an exact match. +const ( + SeverityInfo = "info" + SeverityWarning = "warning" + SeverityError = "error" +) + // One row in the linkerd-style output. Logs is internal-only and is not // forwarded into the CheckCompleted JSONL wire event, so it never leaks // into the stable JSON contract. @@ -55,7 +65,7 @@ type CheckResult struct { Message string Detail string // optional: short version string or extra context (M+8.11) HintURL string - Err error // populated only when the check itself failed to execute + Err error // populated only when the check itself failed to execute Logs string // optional: full check transcript for --show-logs; not emitted to JSON } @@ -195,6 +205,15 @@ func runVersionCmdOnce(ctx context.Context, path string, args []string, re *rege type PreflightConfig struct { LocalOnly bool Tools []BinarySpec + + // Registries is the list of container registries to credential-check. + // When empty, the registry-credentials category is omitted entirely. + // Populated by the cmd layer from EnumerateRegistries. + Registries []RegistryEntry + + // RegistryChecker validates credentials for one registry. Nil skips the + // category. Production wires NewRegistryCredentialChecker; tests pass fakes. + RegistryChecker RegistryCredentialChecker } // DefaultTools returns the kubectl/helmfile/helm specs with version floors @@ -252,10 +271,18 @@ type Role int const ( RoleLocalOnly Role = iota // shared local-host tools only; no kubectl contact - RoleControlPlane // shared + Gateway API CRDs + default StorageClass + RoleControlPlane // shared + gateway/StorageClass/LB checks via cluster-validator RoleComputePlane // shared + GPU operator + GPU node labels + (optional) SIS reachability ) +// Validator role strings passed as VALIDATOR_ROLE to the cluster-validator Job. +// These must match the constants in the nvca cluster-validator binary's +// clustervalidator package (RoleControlPlane / RoleComputePlane). +const ( + validatorRoleControlPlane = "control-plane" + validatorRoleComputePlane = "compute-plane" +) + // String returns a human-readable name for the role. func (r Role) String() string { switch r { @@ -289,6 +316,29 @@ type RoleConfig struct { ClusterValidatorImage string ClusterValidatorPullSecret string ClusterValidatorNoCleanup bool + + // StaleNamespaceProber detects NVCF stack namespaces that are stuck + // Terminating or exist as empty shells after a partial teardown. Nil skips + // the check; production wires NewStaleNamespaceProber; tests pass fakes. + StaleNamespaceProber StaleNamespaceProber + + // StackDir is the resolved stack checkout. When set, the namespaces to + // probe are read from its helmfile.d rather than the static fallback list, + // so the check follows the stack instead of drifting from it. + StackDir string + + // ExtraStaleNamespaces are merged into this role's stale-namespace scan. + // In ModeSingle both roles share one cluster, so only one of them runs the + // probe to avoid emitting the same check ID twice; the other role's + // namespaces are passed here instead of being dropped. The two roles probe + // disjoint lists, so without this the skipped role's namespaces are never + // scanned on the one topology where they sit on the same cluster. + ExtraStaleNamespaces []string + + // ClusterValidatorRegistries is an optional list of "host:port" registry + // endpoints added to the control-plane validator ConfigMap alongside the + // built-in nvcr.io probe. Ignored for the compute-plane validator. + ClusterValidatorRegistries []string } // categorySpec groups a set of checks under a named category. Categories run @@ -318,6 +368,16 @@ func buildCategories(cfg PreflightConfig, role Role, rc RoleConfig) []categorySp out = append(out, *local) } + // Registry credential check runs from the operator's machine - no cluster + // contact needed. RunPreflightForRole is called once per role, so the + // caller clears Registries on every role but one to avoid duplicate + // check_started/check_completed events. Deduplicating on the role here + // instead would drop the check entirely when the control plane does not + // run, which is the case for a compute-plane-only invocation. + if len(cfg.Registries) > 0 && cfg.RegistryChecker != nil { + out = append(out, buildRegistryCredentialCategory(cfg)) + } + if cfg.LocalOnly || role == RoleLocalOnly { return out } @@ -354,28 +414,44 @@ func buildLocalHostCategory(cfg PreflightConfig) *categorySpec { return &categorySpec{name: "local-host-tools", role: RoleLocalOnly, checks: checks} } -// controlPlaneCheckCategory returns the placeholder cluster-side checks for -// control plane: Gateway API CRDs, default StorageClass. Real probes land -// when M3 ships; for now they emit an "info" CheckResult so the renderer -// matrix is observable. -func controlPlaneCheckCategory(_ RoleConfig) categorySpec { - return categorySpec{ - name: "control-plane-cluster", - role: RoleControlPlane, - checks: []binaryCheckSpec{ - placeholderCheck("gateway-api-crds", "checking Gateway API CRDs…", "Gateway API CRD probe — pending M3 cluster-side preflight"), - placeholderCheck("default-storageclass", "checking default StorageClass…", "Default StorageClass probe — pending M3 cluster-side preflight"), - }, +// controlPlaneCheckCategory returns the cluster-side checks for the control +// plane. The stale-namespace check runs first so a leftover namespace from a +// prior partial teardown is surfaced before any other cluster work. +// Gateway API CRD and StorageClass probes are placeholders pending M3. +func controlPlaneCheckCategory(rc RoleConfig) categorySpec { + cat := categorySpec{ + name: "control-plane-cluster", + role: RoleControlPlane, + checks: []binaryCheckSpec{}, + } + // Stale namespace check runs first so leftover namespaces surface + // before any other cluster work. + if rc.StaleNamespaceProber != nil { + cat.checks = append(cat.checks, + staleNamespaceCheck(rc.StaleNamespaceProber, rc.KubeContext, + mergeNamespaces(resolveStackNamespaces(rc.StackDir, nvcfControlPlaneNamespaces), + rc.ExtraStaleNamespaces))) + } + // Containerized cluster-validator probe for control-plane checks + // (Gateway API CRDs, Envoy Gateway, StorageClass, external LB, + // node-to-node overlay, and reachability to nvcr.io + extra registries). + if rc.ClusterValidator != nil { + cat.checks = append(cat.checks, clusterValidatorCheck( + rc.ClusterValidator, + rc.KubeContext, + rc.ClusterValidatorImage, + rc.ClusterValidatorPullSecret, + rc.ClusterValidatorNoCleanup, + validatorRoleControlPlane, + rc.ClusterValidatorRegistries, + )) } + return cat } -// computePlaneCheckCategory returns the placeholder compute-plane checks. -// Conditionally adds an SIS reachability probe when RoleConfig.SISURL is set, -// a node-inotify-limits probe when RoleConfig.InotifyProber is set, and a -// containerized cluster-validator probe when RoleConfig.ClusterValidator is -// set. Each conditional probe is opt-in via its own RoleConfig field so -// callers that opted out via a --skip-* flag simply leave the corresponding -// field nil/empty and the check is omitted from the category entirely. +// computePlaneCheckCategory returns the compute-plane checks. SIS, inotify, +// and cluster-validator probes are opt-in via their RoleConfig fields; a nil +// or empty field omits the corresponding check from the category. func computePlaneCheckCategory(rc RoleConfig) categorySpec { cat := categorySpec{ name: "compute-plane-cluster", @@ -385,6 +461,15 @@ func computePlaneCheckCategory(rc RoleConfig) categorySpec { placeholderCheck("gpu-node-labels", "checking GPU node labels…", "GPU node-label probe — pending M+10 cluster-side preflight"), }, } + // Stale namespace check runs first so leftover namespaces from a prior + // partial teardown surface before any other cluster work. + if rc.StaleNamespaceProber != nil { + cat.checks = append([]binaryCheckSpec{ + staleNamespaceCheck(rc.StaleNamespaceProber, rc.KubeContext, + mergeNamespaces(resolveStackNamespaces(rc.StackDir, nvcfComputePlaneNamespaces), + rc.ExtraStaleNamespaces)), + }, cat.checks...) + } if rc.SISURL != "" { cat.checks = append(cat.checks, sisReachabilityCheck(rc.SISURL)) } @@ -398,6 +483,8 @@ func computePlaneCheckCategory(rc RoleConfig) categorySpec { rc.ClusterValidatorImage, rc.ClusterValidatorPullSecret, rc.ClusterValidatorNoCleanup, + validatorRoleComputePlane, + nil, // registries: compute-plane doesn't use the ConfigMap reachability list )) } return cat @@ -503,10 +590,10 @@ func nodeInotifyCheck(prober NodeInotifyProber, kubeContext string) binaryCheckS } } -// Severity mapping: runner errors (RBAC/pull/timeout) -> warning, since -// they're operator-fixable infra issues; validator Passed=false -> -// error (real check failures); Passed=true -> info. -func clusterValidatorCheck(cv ClusterValidator, kubeContext, image, pullSecret string, noCleanup bool) binaryCheckSpec { +// clusterValidatorCheck runs the validator Job. Runner errors (RBAC/timeout) +// are warning severity; validator failures are error. role selects the check +// set via VALIDATOR_ROLE; registries extends the ConfigMap reachability list. +func clusterValidatorCheck(cv ClusterValidator, kubeContext, image, pullSecret string, noCleanup bool, role string, registries []string) binaryCheckSpec { const id = "cluster-validator" return binaryCheckSpec{ ID: id, @@ -521,9 +608,11 @@ func clusterValidatorCheck(cv ClusterValidator, kubeContext, image, pullSecret s Image: image, PullSecret: pullSecret, NoCleanup: noCleanup, + Role: role, + Registries: registries, }) r.Logs = result.Logs - r.Detail = clusterValidatorDetail(result.JobName) + r.Detail = clusterValidatorDetail(kubeContext, result.JobName) if result.Err != nil { r.Severity = "warning" @@ -544,14 +633,226 @@ func clusterValidatorCheck(cv ClusterValidator, kubeContext, image, pullSecret s } } -func clusterValidatorDetail(jobName string) string { - hint := kubectlLogsHint(jobName) +func clusterValidatorDetail(kubeContext, jobName string) string { + hint := kubectlLogsHint(kubeContext, jobName) if hint == "" { return "" } return "logs: " + hint } +// buildRegistryCredentialCategory returns the registry-credentials category +// that probes each configured registry for reachability and valid credentials. +func buildRegistryCredentialCategory(cfg PreflightConfig) categorySpec { + cat := categorySpec{ + name: "registry-credentials", + role: RoleLocalOnly, // runs regardless of cluster role + checks: make([]binaryCheckSpec, 0, len(cfg.Registries)), + } + for _, reg := range cfg.Registries { + reg := reg // capture loop var + cat.checks = append(cat.checks, registryCredentialCheck(cfg.RegistryChecker, reg)) + } + return cat +} + +// registryCredentialCheck returns a binaryCheckSpec that probes one registry. +// Critical registries (nvcr.io) fail at error severity; non-critical ones +// fail at warning so they don't block the operator on optional registries. +func registryCredentialCheck(checker RegistryCredentialChecker, entry RegistryEntry) binaryCheckSpec { + id := "registry-cred-" + entry.Registry + severity := "warning" + if entry.Critical { + severity = "error" + } + return binaryCheckSpec{ + ID: id, + HumanLabel: fmt.Sprintf("checking credentials for %s...", entry.Registry), + Run: func(ctx context.Context) CheckResult { + r := CheckResult{ + ID: id, + Severity: severity, + } + if err := checker(ctx, entry.Registry, entry.RepoHint, entry.Critical); err != nil { + // A registry this probe cannot speak to (ECR's SigV4, a Basic + // challenge) is not evidence of a credential problem, and an + // unreadable credential helper is not evidence of a missing + // credential. Neither may block the run. + var skipped errRegistryProbeSkipped + var unverified errRegistryCredentialsUnverified + switch { + case errors.As(err, &skipped): + r.Passed = true + r.Severity = "info" + r.Message = entry.Registry + ": skipped (" + skipped.reason + ")" + return r + case errors.As(err, &unverified): + r.Severity = "warning" + r.Message = entry.Registry + ": " + err.Error() + r.Err = err + return r + } + r.Message = entry.Registry + ": " + err.Error() + r.Err = err + return r + } + r.Passed = true + r.Severity = "info" + r.Message = entry.Registry + ": credentials valid" + return r + }, + } +} + +func mergeNamespaces(base, extra []string) []string { + if len(extra) == 0 { + return base + } + seen := make(map[string]bool, len(base)+len(extra)) + out := make([]string, 0, len(base)+len(extra)) + for _, list := range [][]string{base, extra} { + for _, ns := range list { + if ns == "" || seen[ns] { + continue + } + seen[ns] = true + out = append(out, ns) + } + } + return out +} + +// staleNamespaceCheck detects NVCF namespaces stuck Terminating or left as +// empty shells after a partial teardown. Severity is error; prober errors +// degrade to warning so transient kubeconfig issues don't falsely fail. +// mergeNamespaces returns the union of two namespace lists, order-stable and +// de-duplicated. +func staleNamespaceCheck(prober StaleNamespaceProber, kubeContext string, namespaces []string) binaryCheckSpec { + const id = "stale-namespaces" + return binaryCheckSpec{ + ID: id, + HumanLabel: "checking for stale NVCF namespaces...", + Run: func(ctx context.Context) CheckResult { + r := CheckResult{ID: id, Severity: "error"} + // Resolve the context before probing, then probe that exact name. + // Resolving afterwards leaves a window where the current-context + // changes in between, which would have the hints delete namespaces + // in a cluster other than the one that was read. + probedContext := effectiveKubeContext(kubeContext) + stale, err := prober(ctx, probedContext, namespaces) + if err != nil { + r.Severity = "warning" + r.Message = "stale namespace probe failed: " + err.Error() + r.Err = err + return r + } + if len(stale) == 0 { + r.Severity = "info" + r.Passed = true + r.Message = "no stale NVCF namespaces detected" + return r + } + parts := make([]string, 0, len(stale)) + var terminating, emptyShell []string + for _, ns := range stale { + parts = append(parts, ns.Name+" ("+ns.Reason+")") + if ns.Reason == "stuck Terminating" { + terminating = append(terminating, ns.Name) + } else { + emptyShell = append(emptyShell, ns.Name) + } + } + // Every hint names the context that was actually probed, above. + // In split mode the two callers pass different contexts, and with + // no context flag the probe followed the current-context. Either + // way the name goes into the command, because these hints delete + // namespaces and the current-context can change between reading + // the output and pasting it. + kctl := "kubectl" + kubectlContextArg(probedContext) + var hints []string + if len(terminating) > 0 { + // spec.finalizers is writable only through the /finalize + // subresource: a plain patch or update is silently reverted by + // the apiserver's namespace strategy, so `kubectl patch ... + // --type=merge` prints "patched" and changes nothing. + for _, ns := range terminating { + hints = append(hints, fmt.Sprintf( + "clear namespace finalizers on %s: %s get ns %s -o json | "+ + "jq '.spec.finalizers=[]' | %s replace --raw /api/v1/namespaces/%s/finalize -f -", + ns, kctl, ns, kctl, ns)) + } + // One command per namespace with the real name substituted. A + // `` placeholder is not pasteable: the shell reads `<` and + // `>` as redirection, so the command fails before kubectl runs. + for _, ns := range terminating { + hints = append(hints, fmt.Sprintf( + "if %s stays Terminating, the deadlock is on objects inside it: "+ + "%s api-resources --verbs=list --namespaced -o name | "+ + "xargs -n1 %s get -n %s --show-kind --ignore-not-found", + ns, kctl, kctl, ns)) + } + } + if len(emptyShell) > 0 { + // Deliberately not a delete command. A namespace with no Helm + // release is not necessarily stale: the stack gates + // cert-manager, NATS, OpenBao and Cassandra on *.enabled, so an + // operator who installs one the documented upstream way, or via + // Argo, owns a healthy namespace with no owner=helm object. + // Handing them "kubectl delete namespace cert-manager" would + // destroy every Certificate and Issuer in the cluster. + // One command per namespace. kubectl takes a single + // namespace and keeps the last -n it sees, so joining them + // produces a command that silently inspects only the last one + // and reports the rest as empty, which is the opposite of what + // an operator deciding whether to delete them needs. + for _, ns := range emptyShell { + hints = append(hints, fmt.Sprintf( + "inspect %s and remove it only after confirming it is unused: %s get all -n %s", + ns, kctl, ns)) + } + } + // Only a namespace stuck Terminating blocks the run. "No Helm + // release" is a heuristic over a conditionally-installed stack, so + // it warns rather than turning a supported install shape into exit 2. + if len(terminating) == 0 { + r.Severity = SeverityWarning + } + r.Message = fmt.Sprintf("%d stale namespace(s) detected: %s. To resolve: %s", + len(stale), strings.Join(parts, ", "), strings.Join(hints, "; ")) + return r + }, + } +} + +// kubectlContextArg renders the probed context as a --context flag for the +// remediation hints, or "" when no explicit context was given so the hint stays +// readable for a single-cluster setup. The value is shell-quoted: a context +// name is operator-supplied and arbitrary. +func kubectlContextArg(kubeContext string) string { + if kubeContext == "" { + return "" + } + return " --context " + shellQuoteArg(kubeContext) +} + +// shellQuoteArg makes s safe to paste into a shell. Unquoted when it holds only +// characters no shell treats specially, so the common case stays legible. +func shellQuoteArg(s string) string { + if s == "" { + return "''" + } + safe := strings.IndexFunc(s, func(r rune) bool { + return !(r == '-' || r == '_' || r == '.' || r == '/' || r == ':' || r == '@' || r == '=' || + (r >= '0' && r <= '9') || + (r >= 'A' && r <= 'Z') || + (r >= 'a' && r <= 'z')) + }) == -1 + if safe { + return s + } + return "'" + strings.ReplaceAll(s, "'", "'\"'\"'") + "'" +} + // placeholderCheck returns a binaryCheckSpec that emits a passing "info" // CheckResult with the given message. Used until M3/M+10 cluster-side probes ship. func placeholderCheck(id, label, message string) binaryCheckSpec { @@ -686,3 +987,14 @@ func (*noopSink) Close() error { return nil } func RunPreflight(ctx context.Context, cfg PreflightConfig) []CheckResult { return RunPreflightStreaming(ctx, cfg, &noopSink{}) } + +// ControlPlaneStaleNamespaces and ComputePlaneStaleNamespaces expose each +// role's stale-namespace list so the cmd layer can merge the two when a single +// cluster hosts both roles and only one probe runs. +func ControlPlaneStaleNamespaces(stackDir string) []string { + return resolveStackNamespaces(stackDir, nvcfControlPlaneNamespaces) +} + +func ComputePlaneStaleNamespaces(stackDir string) []string { + return resolveStackNamespaces(stackDir, nvcfComputePlaneNamespaces) +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/preflight_test.go b/src/clis/nvcf-cli/internal/selfhosted/preflight_test.go index 262075dff8..862d6bc591 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/preflight_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/preflight_test.go @@ -408,7 +408,10 @@ func TestRunPreflightForRole_LocalOnly(t *testing.T) { func TestRunPreflightForRole_ControlPlaneAddsClusterCategory(t *testing.T) { sink := &captureSink{} cfg := PreflightConfig{Tools: []BinarySpec{passingToolSpec("kubectl", "1.30.0")}} - res := RunPreflightForRole(context.Background(), cfg, RoleControlPlane, RoleConfig{KubeContext: "admin@cp"}, sink) + // No StaleNamespaceProber and no ClusterValidator: the control-plane + // category is empty but the category itself still fires (CategoryCompleted + // is always emitted). + RunPreflightForRole(context.Background(), cfg, RoleControlPlane, RoleConfig{KubeContext: "admin@cp"}, sink) seen := map[string]bool{} for _, e := range sink.events { @@ -417,14 +420,27 @@ func TestRunPreflightForRole_ControlPlaneAddsClusterCategory(t *testing.T) { } } assert.True(t, seen["local-host-tools"], "expected local-host-tools category") - assert.True(t, seen["control-plane-cluster"], "expected control-plane-cluster category") + assert.True(t, seen["control-plane-cluster"], "expected control-plane-cluster category even with no checks configured") +} + +func TestRunPreflightForRole_ControlPlaneWithValidatorAddsClusterValidatorCheck(t *testing.T) { + sink := &captureSink{} + cfg := PreflightConfig{Tools: []BinarySpec{passingToolSpec("kubectl", "1.30.0")}} + cv := func(_ context.Context, p ClusterValidatorParams) ClusterValidatorResult { + return ClusterValidatorResult{Passed: true} + } + res := RunPreflightForRole(context.Background(), cfg, RoleControlPlane, RoleConfig{ + KubeContext: "admin@cp", + ClusterValidator: cv, + ClusterValidatorImage: "nvcf-validator:1.0", + }, sink) var gotCheckIDs []string for _, r := range res { gotCheckIDs = append(gotCheckIDs, r.ID) } - assert.Contains(t, gotCheckIDs, "gateway-api-crds") - assert.Contains(t, gotCheckIDs, "default-storageclass") + assert.Contains(t, gotCheckIDs, "cluster-validator", + "cluster-validator check must appear when ClusterValidator is configured for control-plane role") } func TestRunPreflightForRole_ComputePlaneWithoutSISURL(t *testing.T) { @@ -654,3 +670,35 @@ func TestParseInotifyOutput(t *testing.T) { require.Error(t, err) }) } + +// In ModeSingle one cluster hosts both roles and only one stale-namespace +// probe runs, so the skipped role's namespaces must be merged in. Dropping +// them means a kai-scheduler or nvca-operator namespace wedged Terminating is +// reported as "no stale NVCF namespaces detected". +func TestStaleNamespaceCheck_MergesTheOtherRolesNamespaces(t *testing.T) { + var probed []string + prober := func(_ context.Context, _ string, namespaces []string) ([]StaleNamespace, error) { + probed = namespaces + return nil, nil + } + rc := RoleConfig{ + StaleNamespaceProber: prober, + ExtraStaleNamespaces: ComputePlaneStaleNamespaces(""), + } + cat := controlPlaneCheckCategory(rc) + require.NotEmpty(t, cat.checks) + cat.checks[0].Run(context.Background()) + + for _, ns := range []string{"nvcf", "vault-system"} { + assert.Contains(t, probed, ns, "the control-plane list must still be covered") + } + for _, ns := range []string{"nvca-operator", "kai-scheduler"} { + assert.Contains(t, probed, ns, "the compute-plane list must be merged in, not dropped") + } +} + +func TestMergeNamespaces_DedupesAndKeepsOrder(t *testing.T) { + got := mergeNamespaces([]string{"a", "b"}, []string{"b", "c", ""}) + assert.Equal(t, []string{"a", "b", "c"}, got) + assert.Nil(t, mergeNamespaces(nil, nil)) +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/progress/k8s_watcher_test.go b/src/clis/nvcf-cli/internal/selfhosted/progress/k8s_watcher_test.go index c8e22dd93f..03e2334eea 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/progress/k8s_watcher_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/progress/k8s_watcher_test.go @@ -135,7 +135,7 @@ func TestWatchResources_EmitsCountsForEachType(t *testing.T) { }, 3*time.Second, 50*time.Millisecond, "did not see all 5 resource types") last := sink.lastByResource() - assert.Equal(t, 4, last["namespaces"].Num) // phaseNum baked in + assert.Equal(t, 4, last["namespaces"].Num) // phaseNum baked in assert.Equal(t, "apply-cp", last["namespaces"].Name) // phaseName baked in assert.Equal(t, "namespaces", last["namespaces"].Resource) assert.Equal(t, 2, last["namespaces"].Done) diff --git a/src/clis/nvcf-cli/internal/selfhosted/progress/log_line_writer.go b/src/clis/nvcf-cli/internal/selfhosted/progress/log_line_writer.go index 3f6ff8f481..1a2cba7262 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/progress/log_line_writer.go +++ b/src/clis/nvcf-cli/internal/selfhosted/progress/log_line_writer.go @@ -41,12 +41,12 @@ import ( // EventSink is responsible for its own concurrency (JSONLRenderer's mu; // TTYRenderer's tea.Program.Send is goroutine-safe by design). type LogLineWriter struct { - mu sync.Mutex - buf bytes.Buffer - sink EventSink - stream string // "stdout" | "stderr" - source string // short producer tag, e.g. "helmfile-cp" - closed bool + mu sync.Mutex + buf bytes.Buffer + sink EventSink + stream string // "stdout" | "stderr" + source string // short producer tag, e.g. "helmfile-cp" + closed bool } // NewLogLineWriter constructs a LogLineWriter feeding into sink. stream and diff --git a/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl.go b/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl.go index 3f4940c1fd..736f861e06 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl.go +++ b/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl.go @@ -710,7 +710,7 @@ type wireClusterRow struct { Event string `json:"event"` TS string `json:"ts"` Name string `json:"name"` - Context string `json:"context,omitempty"` // M+9: omitted when unknown + Context string `json:"context,omitempty"` // M+9: omitted when unknown GPU string `json:"gpu"` GPUCount int `json:"gpuCount"` ActiveDeployments int `json:"activeDeployments"` @@ -766,12 +766,12 @@ type wireCategoryCompleted struct { // mode. It carries the Snapshot identity plus all ComponentHealth, ClusterRow, // and RecentEvent sub-objects inlined. type wireSnapshotComposed struct { - Event string `json:"event"` - TS string `json:"ts"` - Cluster string `json:"cluster"` - Verdict string `json:"verdict"` - ReconcileAgeSec int `json:"reconcileAgeSec"` - Identity wireSnapshotIdentity `json:"identity"` + Event string `json:"event"` + TS string `json:"ts"` + Cluster string `json:"cluster"` + Verdict string `json:"verdict"` + ReconcileAgeSec int `json:"reconcileAgeSec"` + Identity wireSnapshotIdentity `json:"identity"` Components []wireComponentInline `json:"components,omitempty"` ComputeClusters []wireClusterInline `json:"computeClusters,omitempty"` Events []wireEventInline `json:"events,omitempty"` @@ -781,7 +781,7 @@ type wireSnapshotComposed struct { type wireComponentInline struct { Name string `json:"name"` Cluster string `json:"cluster,omitempty"` - Role string `json:"role,omitempty"` // M+9: omitted in single-cluster mode + Role string `json:"role,omitempty"` // M+9: omitted in single-cluster mode Ready int `json:"ready"` Total int `json:"total"` UptimeSec int `json:"uptimeSec"` @@ -792,7 +792,7 @@ type wireComponentInline struct { // wireClusterInline is a ClusterRow without event/ts fields. type wireClusterInline struct { Name string `json:"name"` - Context string `json:"context,omitempty"` // M+9: omitted when unknown + Context string `json:"context,omitempty"` // M+9: omitted when unknown GPU string `json:"gpu"` GPUCount int `json:"gpuCount"` ActiveDeployments int `json:"activeDeployments"` diff --git a/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl_test.go b/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl_test.go index 3ceb92eb20..3f55654def 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/progress/render_jsonl_test.go @@ -82,7 +82,7 @@ func TestRenderJSONL_PhaseFailed(t *testing.T) { ErrCategory: "helm_apply", ErrMessage: "helm install api-keys: timed out", RetryClass: "backoff", RetryAfterSec: 60, Remediation: []string{"kubectl describe pod -n cassandra-system cassandra-0", "Re-run with --debug"}, - Raw: RawFailure{Subprocess: "helmfile", ExitCode: 1, StderrTail: "Error: timeout reached", KubernetesReason: "FailedScheduling"}, + Raw: RawFailure{Subprocess: "helmfile", ExitCode: 1, StderrTail: "Error: timeout reached", KubernetesReason: "FailedScheduling"}, }, } got := runEmit(t, clock, events) diff --git a/src/clis/nvcf-cli/internal/selfhosted/pullsecret.go b/src/clis/nvcf-cli/internal/selfhosted/pullsecret.go index d01311e802..1fb43122f0 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/pullsecret.go +++ b/src/clis/nvcf-cli/internal/selfhosted/pullsecret.go @@ -32,15 +32,63 @@ import ( "k8s.io/client-go/kubernetes" ) +// deleteExactly pins a delete to the object that was inspected. The ownership +// guards read an object and then delete it by name, and in that window another +// actor can relabel it, or delete and recreate it under the same name. Without +// preconditions the delete lands on whatever holds the name by then; with them +// the apiserver rejects it as a conflict instead. +func deleteExactly(o metav1.Object) metav1.DeleteOptions { + // UID only. UID already pins identity, which is the whole goal: a + // delete-and-recreate under the same name changes it. ResourceVersion + // additionally pins the object's version, so any concurrent write turns + // the delete into a 409 that every sweep then swallows. That bites hardest + // on the singleton Job sweep, whose only target is an active Job whose + // .status the Job controller mutates continuously. + uid := o.GetUID() + return metav1.DeleteOptions{ + Preconditions: &metav1.Preconditions{UID: &uid}, + } +} + const ( // Project-specific name so the auto-created / mirrored pull secret // can never collide with the conventional `nvcr-pull-secret` that // operators or the install flow may already manage in 'default'. // Pairs with isManagedByValidatorCLI label guard for defense-in-depth. + // + // The name is suffixed per role by validatorPullSecretRoleName: ModeSplit + // runs both validators concurrently, and the two kubecontexts can resolve + // to the same cluster. One shared Secret means the role that finishes first + // deletes it while the other Job is still pulling, which the kubelet + // reports as FailedToRetrieveImagePullSecret. validatorPullSecretName = "nvcf-preflight-pull-secret" validatorPullSecretScanTimeout = 10 * time.Second ) +// validatorPullSecretRoleName returns the managed pull-secret name for a role. +// A Secret cannot be co-owned, so each role needs its own rather than a shared +// object with a role label. +func validatorPullSecretRoleName(role string) string { + if role == "" { + return validatorPullSecretName + } + return validatorPullSecretName + "-" + role +} + +// validatorPullSecretRunName is the name this run mints under. It carries the +// run's unguessable suffix because the managed labels are three public +// constants: with a predictable name, anyone able to create a Secret in this +// namespace could pre-create it wearing those labels, pass the ownership check, +// and have the NGC credential written into an object they control. Same +// reasoning as the per-run RBAC names. +func validatorPullSecretRunName(role, runID string) string { + base := validatorPullSecretRoleName(role) + if runID == "" { + return base + } + return base + "-" + runID +} + // Mirrors the chain used by ensureLocalImagePullSecrets in cmd/self_hosted_up.go. var ngcAPIKeyEnvNames = []string{ "NGC_IMAGE_PULL_API_KEY", @@ -80,7 +128,8 @@ var validatorPullSecretSearchNamespaces = []string{ func resolveValidatorPullSecret( ctx context.Context, client kubernetes.Interface, - provided, image string, + provided, image, role, runID string, + preserve bool, ) (string, error) { if provided != "" { return provided, nil @@ -93,13 +142,13 @@ func resolveValidatorPullSecret( scanCtx, cancel := context.WithTimeout(ctx, validatorPullSecretScanTimeout) defer cancel() - if name, err := scanAndMirrorPullSecret(scanCtx, client, registry); err != nil { + if name, err := scanAndMirrorPullSecret(scanCtx, client, registry, role, runID, preserve); err != nil { return "", err } else if name != "" { return name, nil } - if name, err := autoCreatePullSecretFromEnv(scanCtx, client, registry); err != nil { + if name, err := autoCreatePullSecretFromEnv(scanCtx, client, registry, role, runID, preserve); err != nil { return "", err } else if name != "" { return name, nil @@ -131,7 +180,7 @@ func parseRegistryFromImage(image string) string { // registry. Mirrors the body into clusterValidatorNamespace when the match // lives elsewhere, so the Job can reference the secret without cross-namespace // lookups. -func scanAndMirrorPullSecret(ctx context.Context, client kubernetes.Interface, registry string) (string, error) { +func scanAndMirrorPullSecret(ctx context.Context, client kubernetes.Interface, registry, role, runID string, preserve bool) (string, error) { for _, ns := range validatorPullSecretSearchNamespaces { // Filter client-side rather than via FieldSelector: server-side // type= selector on Secrets is only honored from k8s 1.27 onward. @@ -148,6 +197,17 @@ func scanAndMirrorPullSecret(ctx context.Context, client kubernetes.Interface, r continue } if s.Namespace == clusterValidatorNamespace { + // Adopt an operator-supplied Secret (no managed labels, so no + // sweep touches it) or this role's own. Never the other + // role's: in ModeSplit both kubecontexts can resolve to one + // cluster, and that role's deferred sweep would delete the + // Secret while this role's pod is still pulling, which the + // kubelet reports as FailedToRetrieveImagePullSecret. That is + // the exact failure per-role naming was introduced to prevent. + if hasValidatorManagedLabels(s.Labels) && + s.Labels[clusterValidatorRoleLabel] != role { + continue + } return s.Name, nil } // Mirror under the validator's well-known name rather than the @@ -156,11 +216,11 @@ func scanAndMirrorPullSecret(ctx context.Context, client kubernetes.Interface, r // the destination namespace, and writeDockerConfigSecret's // delete-and-recreate path would otherwise destroy that // secret on type mismatch. - if err := writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, validatorPullSecretName, cfg); err != nil { + if err := writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, validatorPullSecretRunName(role, runID), role, cfg, preserve); err != nil { return "", fmt.Errorf("mirror pull secret %s/%s to %s/%s: %w", - s.Namespace, s.Name, clusterValidatorNamespace, validatorPullSecretName, err) + s.Namespace, s.Name, clusterValidatorNamespace, validatorPullSecretRunName(role, runID), err) } - return validatorPullSecretName, nil + return validatorPullSecretRunName(role, runID), nil } } return "", nil @@ -177,20 +237,29 @@ func dockerConfigHasRegistry(cfg []byte, registry string) bool { return ok } -func autoCreatePullSecretFromEnv(ctx context.Context, client kubernetes.Interface, registry string) (string, error) { +func autoCreatePullSecretFromEnv(ctx context.Context, client kubernetes.Interface, registry, role, runID string, preserve bool) (string, error) { apiKey := firstNonEmptyEnv(ngcAPIKeyEnvNames...) if apiKey == "" { return "", nil } + // Only ever hand the NGC key to NGC. Without this an operator who mirrors + // the validator image to ghcr.io or a corporate Harbor and still exports + // NGC_API_KEY gets it written as that registry's password, and the kubelet + // then sends the live key to a third party as HTTP Basic auth, where it + // lands in their access logs. The local probe already guards this the same + // way; the Secret path did not. + if !isNGCRegistry(registry) { + return "", nil + } cfg, err := buildDockerConfigJSON(registry, "$oauthtoken", apiKey) if err != nil { return "", fmt.Errorf("encode dockerconfigjson for %s: %w", registry, err) } - if err := writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, validatorPullSecretName, cfg); err != nil { + if err := writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, validatorPullSecretRunName(role, runID), role, cfg, preserve); err != nil { return "", fmt.Errorf("auto-create pull secret %s/%s: %w", - clusterValidatorNamespace, validatorPullSecretName, err) + clusterValidatorNamespace, validatorPullSecretRunName(role, runID), err) } - return validatorPullSecretName, nil + return validatorPullSecretRunName(role, runID), nil } // Mirrors cmd/self_hosted_up.go's firstNonEmptyEnv; kept local to avoid an @@ -218,96 +287,52 @@ func buildDockerConfigJSON(registry, username, password string) ([]byte, error) }) } -// Mirrors cmd/self_hosted_up.go's ensureDockerConfigSecret. Attaches the -// CLI's managed-by labels so a future cleanup path can identify resources -// to remove. -func writeDockerConfigSecret(ctx context.Context, client kubernetes.Interface, namespace, name string, dockerConfig []byte) error { - labels := clusterValidatorLabels() - secrets := client.CoreV1().Secrets(namespace) +// writeDockerConfigSecret creates the pull Secret this run will reference. +// +// Create-only. The name carries this run's unguessable suffix, so nothing this +// CLI created can already hold it and any collision is another object. +// Adopting one would write the NGC credential into something we do not own, +// which label-based ownership cannot prevent: the managed labels are three +// public constants anyone can copy onto a Secret they pre-create under a +// predictable name. +func writeDockerConfigSecret(ctx context.Context, client kubernetes.Interface, namespace, name, role string, dockerConfig []byte, preserve bool) error { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, - Labels: labels, + Labels: clusterValidatorRoleLabelsPreserved(role, preserve), }, Type: corev1.SecretTypeDockerConfigJson, Data: map[string][]byte{corev1.DockerConfigJsonKey: dockerConfig}, } - current, err := secrets.Get(ctx, name, metav1.GetOptions{}) - switch { - case err == nil && current.Type == corev1.SecretTypeDockerConfigJson: - if current.Data == nil { - current.Data = map[string][]byte{} - } - current.Data[corev1.DockerConfigJsonKey] = dockerConfig - if current.Labels == nil { - current.Labels = map[string]string{} - } - for k, v := range labels { - current.Labels[k] = v - } - if _, err := secrets.Update(ctx, current, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("update: %w", err) - } - return nil - case err == nil: - // Secret.Type is immutable; can't Update across a type change. - // Guard the delete: only replace secrets we previously managed. - // Without this, an operator-owned secret with a colliding name - // (e.g. an Opaque secret in 'default' sharing the validator's - // pull-secret name) would be silently destroyed. - if !isManagedByValidatorCLI(current) { + if _, err := client.CoreV1().Secrets(namespace).Create(ctx, secret, metav1.CreateOptions{}); err != nil { + if apierrors.IsAlreadyExists(err) { return fmt.Errorf( - "refusing to replace %s/%s (type=%s) which is not managed by nvcf-cli; "+ - "pass --cluster-validator-pull-secret to choose an explicit secret name", - namespace, name, current.Type) - } - if err := secrets.Delete(ctx, name, metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) { - return fmt.Errorf("delete incompatible secret type %s: %w", current.Type, err) - } - case !apierrors.IsNotFound(err): - return fmt.Errorf("get: %w", err) - } - if _, err := secrets.Create(ctx, secret, metav1.CreateOptions{}); err != nil { - if !apierrors.IsAlreadyExists(err) { - return fmt.Errorf("create: %w", err) - } - // Lost a delete->create race: another actor recreated the secret - // in the narrow window between our Delete and Create. Refetch and - // overwrite with our content so the caller still gets the - // credentials it asked for. - current, getErr := secrets.Get(ctx, name, metav1.GetOptions{}) - if getErr != nil { - return fmt.Errorf("get after create race: %w", getErr) - } - if current.Type != corev1.SecretTypeDockerConfigJson { - return fmt.Errorf("create race left secret %s/%s with type %s, want %s", - namespace, name, current.Type, corev1.SecretTypeDockerConfigJson) - } - if current.Data == nil { - current.Data = map[string][]byte{} - } - current.Data[corev1.DockerConfigJsonKey] = dockerConfig - if current.Labels == nil { - current.Labels = map[string]string{} - } - for k, v := range labels { - current.Labels[k] = v - } - if _, err := secrets.Update(ctx, current, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("update after create race: %w", err) + "refusing to overwrite existing secret %s/%s: this run generated that name, so "+ + "another object already holds it; pass --cluster-validator-pull-secret to "+ + "choose an explicit secret name", + namespace, name) } + return fmt.Errorf("create: %w", err) } return nil } -// isManagedByValidatorCLI reports whether the secret carries the labels -// writeDockerConfigSecret stamps on every secret it creates. Used to -// gate the delete-then-recreate branch so we never destroy an operator- -// or chart-owned secret that happens to share a name with one of ours. +// isManagedByValidatorCLI reports whether a Secret carries the labels this CLI +// stamps on the ones it creates. Necessary but not sufficient for ownership: +// the labels are three public constants anyone can copy onto a Secret they +// pre-create, which is why the generated names are run-scoped and the write +// path is create-only rather than adopt-or-update. func isManagedByValidatorCLI(s *corev1.Secret) bool { + return hasValidatorManagedLabels(s.Labels) +} + +// hasValidatorManagedLabels reports whether an object carries the labels this +// CLI stamps on everything it creates. It is the ownership test for every +// resource the validator writes to or deletes by name, not just Secrets. +func hasValidatorManagedLabels(labels map[string]string) bool { for k, v := range clusterValidatorLabels() { - if s.Labels[k] != v { + if labels[k] != v { return false } } diff --git a/src/clis/nvcf-cli/internal/selfhosted/pullsecret_test.go b/src/clis/nvcf-cli/internal/selfhosted/pullsecret_test.go index 7a77df310c..ee958421fc 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/pullsecret_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/pullsecret_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" ) @@ -130,94 +131,6 @@ func TestFirstNonEmptyEnv(t *testing.T) { }) } -func TestWriteDockerConfigSecret_Create(t *testing.T) { - client := fake.NewSimpleClientset() - cfg := dockerConfigBlob(t, "private.registry.test", "$oauthtoken", "key") - - require.NoError(t, writeDockerConfigSecret(context.Background(), client, "default", "nvcr-pull-secret", cfg)) - - got, err := client.CoreV1().Secrets("default").Get(context.Background(), "nvcr-pull-secret", metav1.GetOptions{}) - require.NoError(t, err) - assert.Equal(t, corev1.SecretTypeDockerConfigJson, got.Type) - assert.Equal(t, cfg, got.Data[corev1.DockerConfigJsonKey]) - assert.Equal(t, clusterValidatorAppLabel, got.Labels["app.kubernetes.io/name"], - "label must be attached so the secret is identifiable as CLI-managed") -} - -func TestWriteDockerConfigSecret_Update(t *testing.T) { - old := dockerConfigBlob(t, "private.registry.test", "$oauthtoken", "stale-key") - fresh := dockerConfigBlob(t, "private.registry.test", "$oauthtoken", "rotated-key") - - client := fake.NewSimpleClientset(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "nvcr-pull-secret", - Namespace: "default", - Labels: map[string]string{"existing-label": "preserved"}, - }, - Type: corev1.SecretTypeDockerConfigJson, - Data: map[string][]byte{corev1.DockerConfigJsonKey: old}, - }) - - require.NoError(t, writeDockerConfigSecret(context.Background(), client, "default", "nvcr-pull-secret", fresh)) - - got, _ := client.CoreV1().Secrets("default").Get(context.Background(), "nvcr-pull-secret", metav1.GetOptions{}) - assert.Equal(t, fresh, got.Data[corev1.DockerConfigJsonKey], "data must be updated to the fresh body") - assert.Equal(t, "preserved", got.Labels["existing-label"], "pre-existing labels must be preserved on update") - assert.Equal(t, clusterValidatorAppLabel, got.Labels["app.kubernetes.io/name"], "CLI labels must be added on update") -} - -// Regression guard for the immutable-Type silent-failure path: a pre-existing -// secret with the wrong Type (but our labels) must be replaced (delete + -// create), not Updated. -func TestWriteDockerConfigSecret_TypeMismatchReplaces(t *testing.T) { - fresh := dockerConfigBlob(t, "private.registry.test", "$oauthtoken", "key") - client := fake.NewSimpleClientset(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "nvcr-pull-secret", - Namespace: "default", - Labels: clusterValidatorLabels(), - }, - Type: corev1.SecretTypeOpaque, // wrong type — Update would 422 - Data: map[string][]byte{"some-key": []byte("some-value")}, - }) - - require.NoError(t, writeDockerConfigSecret(context.Background(), client, "default", "nvcr-pull-secret", fresh)) - - got, err := client.CoreV1().Secrets("default").Get(context.Background(), "nvcr-pull-secret", metav1.GetOptions{}) - require.NoError(t, err) - assert.Equal(t, corev1.SecretTypeDockerConfigJson, got.Type, - "secret must be recreated with the correct dockerconfigjson type") - assert.Equal(t, fresh, got.Data[corev1.DockerConfigJsonKey]) - assert.NotContains(t, got.Data, "some-key", "old Opaque payload must not survive the recreate") -} - -// Operator-owned secret with the same name but no CLI labels must NOT be -// destroyed. The replace path is the only place operator data is at risk -// (immutable Type forces delete+create), so the label guard lives there. -func TestWriteDockerConfigSecret_TypeMismatchRefusesUnlabeledSecret(t *testing.T) { - fresh := dockerConfigBlob(t, "private.registry.test", "$oauthtoken", "key") - operatorPayload := []byte("operator-data-do-not-destroy") - client := fake.NewSimpleClientset(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "nvcr-pull-secret", - Namespace: "default", - // No CLI labels: an operator- or chart-owned secret. - }, - Type: corev1.SecretTypeOpaque, - Data: map[string][]byte{"operator-payload": operatorPayload}, - }) - - err := writeDockerConfigSecret(context.Background(), client, "default", "nvcr-pull-secret", fresh) - require.Error(t, err, "must refuse to destroy a non-CLI-managed secret") - assert.Contains(t, err.Error(), "not managed by nvcf-cli") - - // Original payload must still be intact. - got, getErr := client.CoreV1().Secrets("default").Get(context.Background(), "nvcr-pull-secret", metav1.GetOptions{}) - require.NoError(t, getErr) - assert.Equal(t, corev1.SecretTypeOpaque, got.Type, "type must be unchanged") - assert.Equal(t, operatorPayload, got.Data["operator-payload"], "operator data must not be touched") -} - func TestScanAndMirrorPullSecret_FoundInDefault(t *testing.T) { cfg := dockerConfigBlob(t, "private.registry.test", "$oauthtoken", "key") client := fake.NewSimpleClientset(&corev1.Secret{ @@ -226,7 +139,7 @@ func TestScanAndMirrorPullSecret_FoundInDefault(t *testing.T) { Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, }) - name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test") + name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "operator-secret", name) @@ -247,12 +160,12 @@ func TestScanAndMirrorPullSecret_FoundInNvcfMirroredToDefault(t *testing.T) { Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, }) - name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test") + name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) - assert.Equal(t, validatorPullSecretName, name) + assert.Equal(t, validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), name) - mirrored, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretName, metav1.GetOptions{}) - require.NoError(t, err, "mirror must be created under validatorPullSecretName") + mirrored, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), metav1.GetOptions{}) + require.NoError(t, err, "mirror must be created under the role-scoped managed name") assert.Equal(t, cfg, mirrored.Data[corev1.DockerConfigJsonKey]) // The source secret must remain untouched in the source namespace. @@ -269,14 +182,14 @@ func TestScanAndMirrorPullSecret_RegistryMismatch(t *testing.T) { Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, }) - name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test") + name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "", name, "secret for a different registry must not match") } func TestScanAndMirrorPullSecret_NoSecrets(t *testing.T) { client := fake.NewSimpleClientset() - name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test") + name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "", name) } @@ -296,7 +209,7 @@ func TestScanAndMirrorPullSecret_PrefersDefaultNamespace(t *testing.T) { }, ) - name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test") + name, err := scanAndMirrorPullSecret(context.Background(), client, "private.registry.test", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "in-default", name) } @@ -308,7 +221,7 @@ func TestAutoCreatePullSecretFromEnv_NoEnv(t *testing.T) { } client := fake.NewSimpleClientset() - got, err := autoCreatePullSecretFromEnv(context.Background(), client, "private.registry.test") + got, err := autoCreatePullSecretFromEnv(context.Background(), client, "private.registry.test", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "", got, "no env var set means no secret minted") @@ -323,19 +236,19 @@ func TestAutoCreatePullSecretFromEnv_KeyPresent(t *testing.T) { t.Setenv("NGC_API_KEY", "nvapi-test-123") client := fake.NewSimpleClientset() - got, err := autoCreatePullSecretFromEnv(context.Background(), client, "private.registry.test") + got, err := autoCreatePullSecretFromEnv(context.Background(), client, "nvcr.io", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) - assert.Equal(t, validatorPullSecretName, got) + assert.Equal(t, validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), got) - s, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretName, metav1.GetOptions{}) + s, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), metav1.GetOptions{}) require.NoError(t, err) - assert.True(t, dockerConfigHasRegistry(s.Data[corev1.DockerConfigJsonKey], "private.registry.test"), + assert.True(t, dockerConfigHasRegistry(s.Data[corev1.DockerConfigJsonKey], "nvcr.io"), "minted secret must contain auth for the validator image's registry") } func TestResolveValidatorPullSecret_FlagOverride(t *testing.T) { client := fake.NewSimpleClientset() - got, err := resolveValidatorPullSecret(context.Background(), client, "custom-secret", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26") + got, err := resolveValidatorPullSecret(context.Background(), client, "custom-secret", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "custom-secret", got, "explicit override always wins") @@ -355,14 +268,14 @@ func TestResolveValidatorPullSecret_ScanWins(t *testing.T) { Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, }) - got, err := resolveValidatorPullSecret(context.Background(), client, "", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26") + got, err := resolveValidatorPullSecret(context.Background(), client, "", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) // Mirror destination is the validator's well-known name, not the // source secret's name (avoids same-name collisions with operator // or chart-owned secrets in the destination namespace). - assert.Equal(t, validatorPullSecretName, got) + assert.Equal(t, validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), got) - mirrored, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretName, metav1.GetOptions{}) + mirrored, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), metav1.GetOptions{}) require.NoError(t, err) assert.True(t, dockerConfigHasRegistry(mirrored.Data[corev1.DockerConfigJsonKey], "private.registry.test")) } @@ -374,13 +287,28 @@ func TestResolveValidatorPullSecret_EnvFallback(t *testing.T) { t.Setenv("NVCF_NGC_API_KEY", "nvapi-fallback") client := fake.NewSimpleClientset() - got, err := resolveValidatorPullSecret(context.Background(), client, "", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26") + got, err := resolveValidatorPullSecret(context.Background(), client, "", "nvcr.io/nvidia/nvcf-byoc/cluster-validator:rc26", clusterValidatorControlPlaneRole, "runid", false) + require.NoError(t, err) + assert.Equal(t, validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), got) + + s, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), metav1.GetOptions{}) require.NoError(t, err) - assert.Equal(t, validatorPullSecretName, got) + assert.True(t, dockerConfigHasRegistry(s.Data[corev1.DockerConfigJsonKey], "nvcr.io")) +} + +// A mirrored validator image must not receive the NGC key via the env +// fallback: the kubelet would send it to that registry as Basic auth. +func TestResolveValidatorPullSecret_EnvFallbackRefusesMirroredRegistry(t *testing.T) { + for _, name := range ngcAPIKeyEnvNames { + t.Setenv(name, "") + } + t.Setenv("NVCF_NGC_API_KEY", "nvapi-fallback") + client := fake.NewSimpleClientset() - s, err := client.CoreV1().Secrets("default").Get(context.Background(), validatorPullSecretName, metav1.GetOptions{}) + got, err := resolveValidatorPullSecret(context.Background(), client, "", + "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) - assert.True(t, dockerConfigHasRegistry(s.Data[corev1.DockerConfigJsonKey], "private.registry.test")) + assert.Empty(t, got, "no secret may be minted for a non-NGC registry") } func TestResolveValidatorPullSecret_AllEmpty(t *testing.T) { @@ -389,7 +317,7 @@ func TestResolveValidatorPullSecret_AllEmpty(t *testing.T) { } client := fake.NewSimpleClientset() - got, err := resolveValidatorPullSecret(context.Background(), client, "", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26") + got, err := resolveValidatorPullSecret(context.Background(), client, "", "private.registry.test/nvidia/nvcf-byoc/cluster-validator:rc26", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "", got, "no override, no scan match, no env var -> empty so kubelet surfaces ImagePullBackOff") } @@ -400,10 +328,218 @@ func TestResolveValidatorPullSecret_UnparsableImage(t *testing.T) { } client := fake.NewSimpleClientset() - got, err := resolveValidatorPullSecret(context.Background(), client, "", "bareimage") + got, err := resolveValidatorPullSecret(context.Background(), client, "", "bareimage", clusterValidatorControlPlaneRole, "runid", false) require.NoError(t, err) assert.Equal(t, "", got, "no registry hostname means no scan target and no auto-create") list, _ := client.CoreV1().Secrets("default").List(context.Background(), metav1.ListOptions{}) assert.Empty(t, list.Items, "no secret must be created when registry cannot be derived") } + +// ModeSplit runs both validators concurrently against contexts that can resolve +// to the same cluster. A Secret cannot be co-owned, so each role needs its own: +// with a shared name the role that finishes first deletes it while the other +// Job is still pulling, which the kubelet reports as +// FailedToRetrieveImagePullSecret. +// +// State-assertable now that the sweep lists and deletes individually; the fake +// clientset implements DeleteCollection as a no-op. +func TestManagedPullSecret_IsScopedPerRole(t *testing.T) { + ctx := context.Background() + cpName := validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid") + gpuName := validatorPullSecretRoleName("compute-plane") + require.NotEqual(t, cpName, gpuName, "each role needs its own managed pull secret") + + cfg := dockerConfigBlob(t, "private.registry.test", "user", "pass") + client := fake.NewSimpleClientset() + require.NoError(t, writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, + cpName, clusterValidatorControlPlaneRole, cfg, false)) + require.NoError(t, writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, + gpuName, "compute-plane", cfg, false)) + // Our labels, but not a name we generate: must survive. + require.NoError(t, writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, + "operator-owned-secret", clusterValidatorControlPlaneRole, cfg, false)) + + sweepManagedPullSecrets(ctx, client, clusterValidatorControlPlaneRole, "runid") + + secrets := client.CoreV1().Secrets(clusterValidatorNamespace) + _, err := secrets.Get(ctx, cpName, metav1.GetOptions{}) + assert.True(t, apierrors.IsNotFound(err), "this role's managed secret must be swept") + + _, err = secrets.Get(ctx, gpuName, metav1.GetOptions{}) + assert.NoError(t, err, "the other role's secret must survive") + + _, err = secrets.Get(ctx, "operator-owned-secret", metav1.GetOptions{}) + assert.NoError(t, err, "matching labels alone must not authorize deleting someone else's secret") +} + +// The managed labels a created secret carries must satisfy the sweep selector +// for that role, and must not satisfy another role's. +func TestManagedPullSecret_LabelsMatchOnlyItsOwnRole(t *testing.T) { + ctx := context.Background() + client := fake.NewSimpleClientset() + cfg := dockerConfigBlob(t, "nvcr.io", "$oauthtoken", "key") + name := validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid") + require.NoError(t, writeDockerConfigSecret(ctx, client, clusterValidatorNamespace, + name, clusterValidatorControlPlaneRole, cfg, false)) + + own, err := client.CoreV1().Secrets(clusterValidatorNamespace).List(ctx, + metav1.ListOptions{LabelSelector: validatorRoleSelector(clusterValidatorControlPlaneRole)}) + require.NoError(t, err) + assert.Len(t, own.Items, 1, "the secret must match its own role's selector") + + other, err := client.CoreV1().Secrets(clusterValidatorNamespace).List(ctx, + metav1.ListOptions{LabelSelector: validatorRoleSelector(clusterValidatorComputePlaneRole)}) + require.NoError(t, err) + assert.Empty(t, other.Items, "it must not match the other role's selector") +} + +func TestAutoCreatePullSecretFromEnv_RefusesNonNGCRegistry(t *testing.T) { + t.Setenv("NGC_API_KEY", "nvapi-secret-value") + client := fake.NewSimpleClientset() + + name, err := autoCreatePullSecretFromEnv(context.Background(), client, + "ghcr.io", clusterValidatorControlPlaneRole, "runid", false) + require.NoError(t, err) + assert.Empty(t, name, "no secret may be minted for a non-NGC registry") + + secrets, err := client.CoreV1().Secrets(clusterValidatorNamespace).List( + context.Background(), metav1.ListOptions{}) + require.NoError(t, err) + assert.Empty(t, secrets.Items, "the NGC key must not reach a third-party registry") +} + +// In ModeSplit both kubecontexts can resolve to one cluster. Adopting the +// other role's managed Secret means that role's sweep deletes it while this +// role's pod is still pulling. +func TestScanAndMirrorPullSecret_DoesNotAdoptTheOtherRolesSecret(t *testing.T) { + cfg := dockerConfigBlob(t, "nvcr.io", "$oauthtoken", "key") + otherRole := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels(clusterValidatorControlPlaneRole), + }, + Type: corev1.SecretTypeDockerConfigJson, + Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, + } + client := fake.NewSimpleClientset(otherRole) + + got, err := scanAndMirrorPullSecret(context.Background(), client, "nvcr.io", + clusterValidatorComputePlaneRole, "runid", false) + require.NoError(t, err) + assert.NotEqual(t, otherRole.Name, got, + "the compute role must not adopt the control-plane role's managed Secret") +} + +// An operator-supplied Secret carries no managed labels, so no sweep touches +// it and adopting it is safe. +func TestScanAndMirrorPullSecret_AdoptsOperatorSuppliedSecret(t *testing.T) { + cfg := dockerConfigBlob(t, "nvcr.io", "$oauthtoken", "key") + operator := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "operator-pull", Namespace: clusterValidatorNamespace}, + Type: corev1.SecretTypeDockerConfigJson, + Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, + } + client := fake.NewSimpleClientset(operator) + + got, err := scanAndMirrorPullSecret(context.Background(), client, "nvcr.io", + clusterValidatorComputePlaneRole, "runid", false) + require.NoError(t, err) + assert.Equal(t, "operator-pull", got) +} + +// This role's own Secret is still adopted rather than re-minted. +func TestScanAndMirrorPullSecret_AdoptsOwnRoleSecret(t *testing.T) { + cfg := dockerConfigBlob(t, "nvcr.io", "$oauthtoken", "key") + own := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: validatorPullSecretRunName(clusterValidatorComputePlaneRole, "runid"), + Namespace: clusterValidatorNamespace, + Labels: clusterValidatorRoleLabels(clusterValidatorComputePlaneRole), + }, + Type: corev1.SecretTypeDockerConfigJson, + Data: map[string][]byte{corev1.DockerConfigJsonKey: cfg}, + } + client := fake.NewSimpleClientset(own) + + got, err := scanAndMirrorPullSecret(context.Background(), client, "nvcr.io", + clusterValidatorComputePlaneRole, "runid", false) + require.NoError(t, err) + assert.Equal(t, own.Name, got) +} + +// writeDockerConfigSecret is create-only. The name carries this run's +// unguessable suffix, so nothing this CLI created can already hold it and any +// collision is another object. Adopting one would write the NGC credential +// into something we do not own, which label-based ownership cannot prevent: +// the managed labels are three public constants anyone can copy. +func TestWriteDockerConfigSecret_CreatesUnderTheRunScopedName(t *testing.T) { + cfg := dockerConfigBlob(t, "nvcr.io", "$oauthtoken", "key") + client := fake.NewSimpleClientset() + name := validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid") + + require.NoError(t, writeDockerConfigSecret(context.Background(), client, + clusterValidatorNamespace, name, clusterValidatorControlPlaneRole, cfg, false)) + + s, err := client.CoreV1().Secrets(clusterValidatorNamespace).Get( + context.Background(), name, metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, corev1.SecretTypeDockerConfigJson, s.Type) + assert.True(t, hasValidatorManagedLabels(s.Labels)) +} + +func TestWriteDockerConfigSecret_RefusesAnyCollision(t *testing.T) { + cfg := dockerConfigBlob(t, "nvcr.io", "$oauthtoken", "key") + name := validatorPullSecretRunName(clusterValidatorControlPlaneRole, "runid") + + // Even wearing our managed labels: labels are forgeable, the name is not. + squatter := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, Namespace: clusterValidatorNamespace, + Labels: clusterValidatorLabels(), + }, + Type: corev1.SecretTypeOpaque, + Data: map[string][]byte{"planted": []byte("x")}, + } + client := fake.NewSimpleClientset(squatter) + + err := writeDockerConfigSecret(context.Background(), client, + clusterValidatorNamespace, name, clusterValidatorControlPlaneRole, cfg, false) + require.Error(t, err, "a collision on an unguessable name must never be adopted") + assert.Contains(t, err.Error(), "refusing to overwrite") + + got, gerr := client.CoreV1().Secrets(clusterValidatorNamespace).Get( + context.Background(), name, metav1.GetOptions{}) + require.NoError(t, gerr) + assert.Equal(t, corev1.SecretTypeOpaque, got.Type, "the other object must be untouched") + assert.Contains(t, got.Data, "planted") + assert.NotContains(t, got.Data, corev1.DockerConfigJsonKey, + "the NGC credential must not be written into an object we do not own") +} + +// The unguessable suffix is the actual control. Labels cannot carry it: they +// are three public constants, so a predictable name lets anyone able to create +// a Secret here pre-create it wearing those labels and receive the NGC +// credential. Create-only is only safe because the name cannot be guessed. +func TestValidatorPullSecretRunName_CarriesTheRunID(t *testing.T) { + name := validatorPullSecretRunName(clusterValidatorControlPlaneRole, "a1b2c3d4e5") + assert.Contains(t, name, "a1b2c3d4e5", + "a predictable secret name can be pre-created by someone else") + assert.NotEqual(t, validatorPullSecretRoleName(clusterValidatorControlPlaneRole), name) + + // Two runs never collide, so one run's sweep cannot take out another's. + other := validatorPullSecretRunName(clusterValidatorControlPlaneRole, "f6g7h8i9j0") + assert.NotEqual(t, name, other) +} + +// The mint path must use the run-scoped name, not the role name. +func TestAutoCreatePullSecretFromEnv_MintsUnderTheRunScopedName(t *testing.T) { + t.Setenv("NGC_API_KEY", "nvapi-secret-value") + client := fake.NewSimpleClientset() + + got, err := autoCreatePullSecretFromEnv(context.Background(), client, + "nvcr.io", clusterValidatorControlPlaneRole, "a1b2c3d4e5", false) + require.NoError(t, err) + assert.Contains(t, got, "a1b2c3d4e5", "the minted secret must be run-scoped") +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/register.go b/src/clis/nvcf-cli/internal/selfhosted/register.go index 14d18dfdb6..75908c93f4 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/register.go +++ b/src/clis/nvcf-cli/internal/selfhosted/register.go @@ -315,10 +315,37 @@ func resolveClusterID(resp *client.RegisterClusterResponse) string { // avoid touching a real kubeconfig file. var loadKubeConfigFn = loadKubeConfig +var currentKubeContextNameFn = currentKubeContextName + +// currentKubeContextName returns the kubeconfig's current-context, or "" when +// it cannot be read. Used to name the context in remediation hints when the +// caller did not pass one explicitly. Best-effort by design: a hint without +// the flag is still correct at the moment it is printed. +func currentKubeContextName() string { + raw, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}, + ).RawConfig() + if err != nil { + return "" + } + return raw.CurrentContext +} + +// effectiveKubeContext resolves the context a probe actually used, so a hint +// naming it stays correct after the current-context changes. +func effectiveKubeContext(kctx string) string { + if kctx != "" { + return kctx + } + return currentKubeContextNameFn() +} + // loadKubeConfig builds a *rest.Config for the given kubeconfig context. // When kctx is empty the kubeconfig's current-context is used, preserving // single-cluster behavior. The loading-rules chain follows the same priority // as kubectl: KUBECONFIG env var → ~/.kube/config. +// currentKubeContextNameFn is a seam: tests must not depend on the developer's +// kubeconfig, and hint output would otherwise vary by machine. func loadKubeConfig(kctx string) (*rest.Config, error) { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() overrides := &clientcmd.ConfigOverrides{} diff --git a/src/clis/nvcf-cli/internal/selfhosted/registry_cred.go b/src/clis/nvcf-cli/internal/selfhosted/registry_cred.go new file mode 100644 index 0000000000..debfb1863e --- /dev/null +++ b/src/clis/nvcf-cli/internal/selfhosted/registry_cred.go @@ -0,0 +1,360 @@ +/* +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package selfhosted + +import ( + "context" + "fmt" + "net" + "net/http" + "os" + "strconv" + "strings" + "time" + + "sigs.k8s.io/yaml" +) + +const ( + registryProbeTimeout = 10 * time.Second + + // certManagerRegistry is cert-manager's upstream registry. It is only + // contacted when the stack is not rewriting cert-manager images to + // global.image.registry, which global.yaml.gotmpl does for all five of them. + certManagerRegistry = "quay.io" + + // ngcRegistry is the default global.image.registry in the stack's + // environments/base.yaml, and the fallback when no source named a + // registry. See the tail of EnumerateRegistries. + ngcRegistry = "nvcr.io" +) + +// RegistryCredentialChecker probes whether credentials are present and valid +// for a registry. repoHint is the repository path used as the OAuth scope; +// pass "" to probe without a specific scope (works for public registries). +// critical signals that anonymous success is insufficient; configured credentials +// must be present. Returns nil on success, a descriptive error otherwise. +type RegistryCredentialChecker func(ctx context.Context, registry, repoHint string, critical bool) error + +// NewRegistryCredentialChecker returns a production RegistryCredentialChecker +// backed by real HTTP calls. +func NewRegistryCredentialChecker() RegistryCredentialChecker { + return probeRegistryCredential +} + +// probeRegistryCredential authenticates to registry using the OCI Bearer token +// flow. repoHint is the OAuth scope repository path. +// +// When critical is true, anonymous success is not sufficient: the install pulls +// private repositories, so a local credential must also be present. +// +// Returns errRegistryProbeSkipped for registries this flow cannot speak to +// (ECR's SigV4, a Basic challenge, a 200 that does not look like a registry) +// and errRegistryCredentialsUnverified when no local credential is readable. +// Both are advisory: the caller must not fail the run on either. +func probeRegistryCredential(ctx context.Context, registry, repoHint string, critical bool) error { + // ECR uses AWS SigV4, not the OCI Bearer flow, so this probe cannot speak + // to it. Skip rather than fail: returning an error here makes an + // ECR-hosted validator image unconditionally fail preflight, so --wait + // could never converge. + if isECRRegistry(registry) { + return errRegistryProbeSkipped{ + reason: "ECR uses AWS SigV4; verify manually with 'aws ecr get-login-password'", + } + } + + pctx, cancel := context.WithTimeout(ctx, registryProbeTimeout) + defer cancel() + + client := &http.Client{Timeout: registryProbeTimeout, CheckRedirect: refuseInsecureRedirect} + + // Step 1: probe /v2/ unauthenticated. + probeURL := "https://" + registry + "/v2/" + req, err := http.NewRequestWithContext(pctx, http.MethodGet, probeURL, nil) + if err != nil { + return fmt.Errorf("build request: %w", err) + } + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("cannot reach %s: %w", registry, err) + } + + // A 200 only proves /v2/ is anonymously readable, which says nothing about + // the repositories the install actually pulls. Require the registry to + // identify itself as an OCI registry so a captive portal or TLS-intercepting + // proxy answering 200 HTML is not read as success. + isOCI := resp.Header.Get("Docker-Distribution-Api-Version") != "" || + strings.Contains(resp.Header.Get("Www-Authenticate"), "realm") + + switch resp.StatusCode { + case http.StatusOK: + resp.Body.Close() + if !isOCI { + // A captive portal or TLS-intercepting proxy also answers 200. The + // header is a Docker convention rather than an OCI requirement, so + // a conformant registry may legitimately omit it: report that the + // result is unverifiable instead of guessing either way. + return errRegistryProbeSkipped{ + reason: fmt.Sprintf("%s answered 200 but did not identify as an OCI registry; "+ + "if this is unexpected, check for a proxy or captive portal", registry), + } + } + // Anonymous read works. For a critical registry that is still not + // enough: the install pulls private repositories, so fall through to + // the credential requirement below rather than returning early. + if !critical { + return nil + } + return requireConfiguredCredentials(registry) + case http.StatusUnauthorized: + // Auth required - proceed with token exchange. + default: + resp.Body.Close() + return fmt.Errorf("unexpected status %s from %s", resp.Status, registry) + } + + // Step 2: exchange credentials for a Bearer token using the actual repo + // from the configured image (repoHint). Using a fake repo name causes + // org-level 403s from NGC and GHCR for non-existent orgs, which is + // indistinguishable from bad credentials. + wwwAuth := resp.Header.Get("Www-Authenticate") + resp.Body.Close() + + // Only the Bearer flow is implemented. Self-hosted Harbor and htpasswd + // mirrors commonly answer with Basic, where the Bearer path would report a + // spurious credential failure, so skip instead. + if scheme := authChallengeScheme(wwwAuth); scheme != "" && !strings.EqualFold(scheme, "Bearer") { + return errRegistryProbeSkipped{ + reason: fmt.Sprintf("%s uses %s auth; only the OCI Bearer flow is probed", registry, scheme), + } + } + + _, err = exchangeBearerToken(pctx, client, registry, repoHint, wwwAuth) + if err != nil { + // Use credentialsForRegistry (not ngcCredentials) so NGC_API_KEY does + // not masquerade as credentials for quay.io, GHCR, or Harbor - those + // registries reject NGC tokens, which would wrongly produce "credentials + // rejected" when the real diagnosis is "no credentials configured." + if _, _, hasCreds := credentialsForRegistry(registry); !hasCreds { + // Same situation as the critical path below, so the same verdict: + // no readable local credential is not proof that none exists, since + // a credential helper is invisible here. + return errRegistryCredentialsUnverified{registry: registry} + } + return fmt.Errorf("credentials rejected by %s: %w", registry, err) + } + // For critical registries, a successful anonymous token is not enough: + // if the actual install pulls private images, anonymous access will fail. + if critical { + return requireConfiguredCredentials(registry) + } + return nil +} + +// errRegistryProbeSkipped marks a registry this probe cannot speak to. The +// caller reports it as a skip rather than a credential failure. +type errRegistryProbeSkipped struct{ reason string } + +func (e errRegistryProbeSkipped) Error() string { return e.reason } + +// authChallengeScheme returns the auth scheme named by a WWW-Authenticate +// header, or "" when the header is absent or malformed. +func authChallengeScheme(header string) string { + header = strings.TrimSpace(header) + if header == "" { + return "" + } + if i := strings.IndexByte(header, ' '); i > 0 { + return header[:i] + } + return header +} + +// requireConfiguredCredentials reports an error when no credential is reachable +// for the registry. +// +// A missing credential is a warning, not a hard failure: credsFromDockerConfig +// reads only inline auth entries, so a workstation using a credential helper +// (credsStore on Docker Desktop, docker-credential-pass on Linux) has a working +// docker login that is invisible here. The install path also mints or mirrors a +// pull secret of its own, so preflight must not be the thing that blocks. +func requireConfiguredCredentials(registry string) error { + if _, _, ok := credentialsForRegistry(registry); ok { + return nil + } + return errRegistryCredentialsUnverified{registry: registry} +} + +// errRegistryCredentialsUnverified means no credential was found locally. The +// caller downgrades this to a warning. +type errRegistryCredentialsUnverified struct{ registry string } + +func (e errRegistryCredentialsUnverified) Error() string { + return fmt.Sprintf("no local credentials found for %s "+ + "(a credential helper such as credsStore is not readable here); "+ + "if 'docker pull' works this can be ignored, otherwise add an entry to "+ + "~/.docker/config.json or set NGC_API_KEY for NGC registries", e.registry) +} + +// isECRRegistry returns true for AWS Elastic Container Registry hostnames, +// which use AWS SigV4 auth instead of the OCI Bearer token flow. +func isECRRegistry(registry string) bool { + return strings.Contains(registry, ".dkr.ecr.") && + strings.HasSuffix(registry, ".amazonaws.com") +} + +// RegistryEntry is one registry endpoint to credential-check. +type RegistryEntry struct { + // Registry is the hostname (and optional port) of the container registry. + Registry string + // RepoHint is the repository path used as the OAuth scope when probing + // credentials (e.g. "nvidia/nvcf-byoc/cluster-validator" for NGC). + // Empty means probe without a specific scope, which works for public + // registries (quay.io, Docker Hub public images) and GHCR anonymous access. + RepoHint string + // Critical marks registries whose credential failure should be a hard error + // rather than a warning. NGC (nvcr.io) is always critical; customer-supplied + // extras default to non-critical. + Critical bool +} + +// EnumerateRegistries builds the deduplicated list of registries to credential- +// check from the image ref, cert-manager (quay.io), the stack values file +// (global.image.registry), and operator-supplied extras. +func EnumerateRegistries(imageRef, stackValuesFile string, extras []string) []RegistryEntry { + seen := make(map[string]bool) + var out []RegistryEntry + + add := func(registry, repoHint string, critical bool) { + registry = strings.TrimSpace(registry) + if registry == "" || seen[registry] { + return + } + // Every source goes through the same host validation. The probe builds + // "https://" + registry + "/v2/", so a value carrying "/" or "@" moves + // the host: global.image.registry set to "nvcr.io@attacker.example.com" + // in a values file the CLI finds by walking up from CWD would otherwise + // aim an outbound request wherever that names. Extras were guarded via + // parseRegistryHostPort; the image ref and the values file were not. + if !isBareRegistryHost(strings.TrimSuffix(strings.TrimPrefix(registry, "["), "]")) && + !isBareRegistryHost(registry) { + return + } + seen[registry] = true + out = append(out, RegistryEntry{Registry: registry, RepoHint: repoHint, Critical: critical}) + } + + // Source 1: base registry from the configured validator image. + // Carry the repo path as a scope hint so the token exchange uses the + // operator's actual org rather than a fake one - NGC returns 403 for + // orgs the API key cannot access, even if the key itself is valid. + // + // Critical follows the same rule as every other source rather than being + // forced true: an air-gapped install that side-loaded the image never + // contacts this registry at pull time (ImagePullPolicy is IfNotPresent). + imageNamedRegistry := false + if reg, repo, _, ok := parseImageRef(imageRef); ok && reg != "" { + imageNamedRegistry = true + add(reg, repo, isNGCRegistry(reg)) + } + + // Source 2: read global.image.registry from the environment values file. + // This catches cases where the operator points at a custom NGC org or a + // staging environment that differs from the validator image's registry. + stackRegistry := "" + if stackValuesFile != "" { + stackRegistry = readGlobalImageRegistry(stackValuesFile) + if stackRegistry != "" { + // If it's an NGC registry, mark critical; customer mirrors are non-critical. + add(stackRegistry, "", isNGCRegistry(stackRegistry)) + } + } + + // Source 3: cert-manager, but only when the stack is not mirroring it. + // deploy/stacks/self-managed/global.yaml.gotmpl rewrites every cert-manager + // image to global.image.registry, so on a configured stack quay.io is never + // contacted and probing it is a pointless round trip. It is only reachable + // when no stack values file resolved. + if stackRegistry == "" { + add(certManagerRegistry, "", false) + } + + // Source 4: operator-supplied extras (--cluster-validator-registries). + // Preserve non-443 ports so probeRegistryCredential builds the correct + // https://host:port/v2/ URL. net.JoinHostPort brackets IPv6 literals, which + // a bare "%s:%d" would corrupt into https://::1:5000/v2/. + for _, e := range extras { + host, port := parseRegistryHostPort(e) + if host == "" { + continue + } + reg := host + if port != 0 && port != 443 { + reg = net.JoinHostPort(host, strconv.Itoa(port)) + } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { + // Bare IPv6 literal on the default port. parseRegistryHostPort + // returns the input verbatim when SplitHostPort fails, and it + // fails on an already-bracketed "[fd00::1]" with missingPort, so + // without the prefix guard that arrives here still bracketed and + // becomes "[[fd00::1]]", which is not a parseable URL host. + reg = "[" + host + "]" + } + add(reg, "", false) + } + + // Fallback for "no source named a registry at all": no validator image is + // configured and no stack values file resolved. That is the default + // configuration rather than an edge case, and without this the run reports + // on quay.io alone while the operator's NGC credentials go unchecked. + // environments/base.yaml sets global.image.registry to nvcr.io, so it is + // the right guess when there is nothing else to go on. + // + // Deliberately not triggered when the image or the stack named a non-NGC + // registry: that is a mirrored install, which has no reason to reach + // nvcr.io, and probing it there would add a failing round trip for the + // sites least able to make it. + // + // Non-critical, unlike an NGC registry a source actually named. A guess + // must not hard-fail the run, and this category has no opt-out flag. + if !imageNamedRegistry && stackRegistry == "" { + add(ngcRegistry, "", false) + } + + return out +} + +// readGlobalImageRegistry reads the global.image.registry key from an +// environment values YAML file (e.g. environments/local.yaml). Returns "" +// on any error so the caller can safely ignore missing or malformed files. +func readGlobalImageRegistry(path string) string { + data, err := os.ReadFile(path) + if err != nil { + return "" + } + var vals struct { + Global struct { + Image struct { + Registry string `json:"registry" yaml:"registry"` + } `json:"image" yaml:"image"` + } `json:"global" yaml:"global"` + } + if err := yaml.Unmarshal(data, &vals); err != nil { + return "" + } + return strings.TrimSpace(vals.Global.Image.Registry) +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/registry_cred_test.go b/src/clis/nvcf-cli/internal/selfhosted/registry_cred_test.go new file mode 100644 index 0000000000..be9b35b494 --- /dev/null +++ b/src/clis/nvcf-cli/internal/selfhosted/registry_cred_test.go @@ -0,0 +1,430 @@ +/* +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package selfhosted + +import ( + "context" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// -- probeRegistryCredential -- + +func TestProbeRegistryCredential_PublicRegistry(t *testing.T) { + // Registry returns 200 on /v2/ with the registry API header -> public, + // no credentials needed. + srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Docker-Distribution-Api-Version", "registry/2.0") + w.WriteHeader(http.StatusOK) + })) + defer srv.Close() + + // Replace the default transport with the test server's transport so TLS + // validation passes against the self-signed cert. + origTransport := http.DefaultTransport + http.DefaultTransport = srv.Client().Transport + t.Cleanup(func() { http.DefaultTransport = origTransport }) + + // Use the test server's host as the registry. + host := strings.TrimPrefix(srv.URL, "https://") + err := probeRegistryCredential(context.Background(), host, "", false) + assert.NoError(t, err, "public registry (200 on /v2/) must not return an error") +} + +func TestProbeRegistryCredential_AuthSucceeds(t *testing.T) { + // Registry: /v2/ returns 401 with WWW-Authenticate; token endpoint returns a token. + tokenSrv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Token endpoint always succeeds. + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"token":"test-token-abc"}`)) + })) + defer tokenSrv.Close() + + registrySrv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") == "Bearer test-token-abc" { + w.WriteHeader(http.StatusOK) + return + } + // Point the client at our token server. + realm := tokenSrv.URL + "/token" + w.Header().Set("Www-Authenticate", + `Bearer realm="`+realm+`",service="test-registry",scope="repository:test:pull"`) + w.WriteHeader(http.StatusUnauthorized) + })) + defer registrySrv.Close() + + transport := registrySrv.Client().Transport + origTransport := http.DefaultTransport + http.DefaultTransport = transport + t.Cleanup(func() { http.DefaultTransport = origTransport }) + + host := strings.TrimPrefix(registrySrv.URL, "https://") + err := probeRegistryCredential(context.Background(), host, "", false) + assert.NoError(t, err, "successful token exchange must return nil") +} + +func TestProbeRegistryCredential_AuthFails(t *testing.T) { + // Registry returns 401 but the token endpoint returns 401 too -> bad credentials. + tokenSrv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusUnauthorized) + })) + defer tokenSrv.Close() + + registrySrv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + realm := tokenSrv.URL + "/token" + w.Header().Set("Www-Authenticate", + `Bearer realm="`+realm+`",service="test-registry"`) + w.WriteHeader(http.StatusUnauthorized) + })) + defer registrySrv.Close() + + transport := registrySrv.Client().Transport + origTransport := http.DefaultTransport + http.DefaultTransport = transport + t.Cleanup(func() { http.DefaultTransport = origTransport }) + + host := strings.TrimPrefix(registrySrv.URL, "https://") + err := probeRegistryCredential(context.Background(), host, "", false) + assert.Error(t, err, "failed token exchange must return an error") +} + +func TestProbeRegistryCredential_ECRSkipped(t *testing.T) { + // ECR registries must get a clear "use AWS CLI" message rather than a + // confusing Bearer token failure. + err := probeRegistryCredential(context.Background(), + "123456789.dkr.ecr.us-east-1.amazonaws.com", "", false) + require.Error(t, err) + assert.Contains(t, err.Error(), "ECR", "ECR registries must produce a clear diagnostic") + assert.Contains(t, err.Error(), "AWS", "message must mention AWS") +} + +// -- EnumerateRegistries -- + +func TestEnumerateRegistries_FromImageRef(t *testing.T) { + entries := EnumerateRegistries("nvcr.io/nvidia/nvcf-byoc/cluster-validator:3.1.0", "", nil) + require.NotEmpty(t, entries) + + found := false + for _, e := range entries { + if e.Registry == "nvcr.io" { + assert.True(t, e.Critical, "nvcr.io must be marked critical") + found = true + } + } + assert.True(t, found, "nvcr.io must appear in the enumerated registries") +} + +func TestEnumerateRegistries_RepoHintFromImageRef(t *testing.T) { + // The RepoHint must be the repo path from the image ref so the token + // exchange uses the operator's actual org, not a fake one. + entries := EnumerateRegistries("nvcr.io/nvidia/nvcf-byoc/cluster-validator:3.1.0", "", nil) + for _, e := range entries { + if e.Registry == "nvcr.io" { + assert.Equal(t, "nvidia/nvcf-byoc/cluster-validator", e.RepoHint, + "RepoHint must carry the actual repo path for correct NGC token scope") + return + } + } + t.Fatal("nvcr.io not found in entries") +} + +func TestEnumerateRegistries_IncludesCertManagerWhenStackIsNotMirroring(t *testing.T) { + // With no stack values file there is no global.image.registry to mirror + // cert-manager to, so its upstream registry is genuinely contacted. + entries := EnumerateRegistries("nvcr.io/some/image:1.0", "", nil) + found := false + for _, e := range entries { + if e.Registry == "quay.io" { + assert.False(t, e.Critical, "quay.io must be non-critical") + found = true + } + } + assert.True(t, found, "quay.io must always be included for cert-manager") +} + +func TestEnumerateRegistries_ExtrasAppended(t *testing.T) { + entries := EnumerateRegistries("nvcr.io/some/image:1.0", "", + []string{"harbor.company.internal:443", "ghcr.io:443"}) + + registries := make(map[string]bool, len(entries)) + for _, e := range entries { + registries[e.Registry] = true + } + assert.True(t, registries["harbor.company.internal"], "extra registry must be added") + assert.True(t, registries["ghcr.io"], "extra registry must be added") +} + +func TestEnumerateRegistries_NoDuplicates(t *testing.T) { + // Pass nvcr.io both as the image registry and as an extra - must not dedup. + entries := EnumerateRegistries("nvcr.io/some/image:1.0", "", + []string{"nvcr.io"}) + + count := 0 + for _, e := range entries { + if e.Registry == "nvcr.io" { + count++ + } + } + assert.Equal(t, 1, count, "nvcr.io must appear exactly once even when listed twice") +} + +func TestEnumerateRegistries_StackValuesFile(t *testing.T) { + // Write a minimal environments/local.yaml to a temp dir. + dir := t.TempDir() + valuesPath := dir + "/local.yaml" + require.NoError(t, writeFile(valuesPath, []byte(` +global: + image: + registry: stg.nvcr.io +`))) + + entries := EnumerateRegistries("nvcr.io/some/image:1.0", valuesPath, nil) + found := false + for _, e := range entries { + if e.Registry == "stg.nvcr.io" { + assert.True(t, e.Critical, "NGC staging registry must be critical") + found = true + } + } + assert.True(t, found, "registry from values file must be included") +} + +func TestReadGlobalImageRegistry_ValidFile(t *testing.T) { + dir := t.TempDir() + path := dir + "/values.yaml" + require.NoError(t, writeFile(path, []byte(` +global: + image: + registry: nvcr.io + repository: nvidia/nvcf-byoc +`))) + got := readGlobalImageRegistry(path) + assert.Equal(t, "nvcr.io", got) +} + +func TestReadGlobalImageRegistry_MissingFile(t *testing.T) { + got := readGlobalImageRegistry("/nonexistent/path/values.yaml") + assert.Empty(t, got, "missing file must return empty string, not error") +} + +func TestReadGlobalImageRegistry_MissingKey(t *testing.T) { + dir := t.TempDir() + path := dir + "/values.yaml" + require.NoError(t, writeFile(path, []byte(`other: value`))) + got := readGlobalImageRegistry(path) + assert.Empty(t, got, "missing global.image.registry must return empty string") +} + +// -- isECRRegistry -- + +func TestIsECRRegistry(t *testing.T) { + assert.True(t, isECRRegistry("123456789012.dkr.ecr.us-east-1.amazonaws.com")) + assert.True(t, isECRRegistry("999999999999.dkr.ecr.eu-west-1.amazonaws.com")) + assert.False(t, isECRRegistry("nvcr.io")) + assert.False(t, isECRRegistry("ghcr.io")) + assert.False(t, isECRRegistry("harbor.company.internal")) + assert.False(t, isECRRegistry("s3.amazonaws.com")) // S3, not ECR +} + +// -- registryCredentialCheck binaryCheckSpec -- + +func TestRegistryCredentialCheck_PassWhenNoError(t *testing.T) { + checker := func(_ context.Context, reg, _ string, _ bool) error { return nil } + spec := registryCredentialCheck(checker, RegistryEntry{Registry: "nvcr.io", Critical: true}) + r := spec.Run(context.Background()) + assert.True(t, r.Passed) + assert.Equal(t, "info", r.Severity) + assert.Contains(t, r.Message, "nvcr.io") +} + +func TestRegistryCredentialCheck_CriticalSeverityOnFailure(t *testing.T) { + checker := func(_ context.Context, reg, _ string, _ bool) error { + return errorf("credentials rejected") + } + spec := registryCredentialCheck(checker, RegistryEntry{Registry: "nvcr.io", Critical: true}) + r := spec.Run(context.Background()) + assert.False(t, r.Passed) + assert.Equal(t, "error", r.Severity, "critical registry failure must be error severity") +} + +func TestRegistryCredentialCheck_WarningSeverityOnNonCriticalFailure(t *testing.T) { + checker := func(_ context.Context, reg, _ string, _ bool) error { + return errorf("credentials rejected") + } + spec := registryCredentialCheck(checker, RegistryEntry{Registry: "quay.io", Critical: false}) + r := spec.Run(context.Background()) + assert.False(t, r.Passed) + assert.Equal(t, "warning", r.Severity, "non-critical registry failure must be warning severity") +} + +// helpers + +func errorf(msg string) error { return fmt.Errorf("%s", msg) } + +func writeFile(path string, data []byte) error { + return os.WriteFile(path, data, 0o644) +} + +// The stack rewrites every cert-manager image to global.image.registry, so on +// a configured stack quay.io is never contacted at pull time and probing it is +// a pointless 10-second round trip on every invocation. +func TestEnumerateRegistries_SkipsCertManagerWhenStackMirrors(t *testing.T) { + dir := t.TempDir() + valuesPath := dir + "/base.yaml" + require.NoError(t, writeFile(valuesPath, []byte(` +global: + image: + registry: mirror.company.internal +`))) + + entries := EnumerateRegistries("nvcr.io/some/image:1.0", valuesPath, nil) + for _, e := range entries { + assert.NotEqual(t, certManagerRegistry, e.Registry, + "a stack mirroring images must not trigger a quay.io probe") + } +} + +// A bare IPv6 literal must stay bracketed or the probe URL is malformed. +func TestEnumerateRegistries_BracketsIPv6Extras(t *testing.T) { + entries := EnumerateRegistries("nvcr.io/some/image:1.0", "", []string{"[::1]:5000"}) + + found := false + for _, e := range entries { + if strings.Contains(e.Registry, "::1") { + found = true + assert.Equal(t, "[::1]:5000", e.Registry, + "an IPv6 literal must keep its brackets so the probe URL parses") + } + } + assert.True(t, found, "the IPv6 extra must be enumerated") +} + +// The validator image's registry follows the same Critical policy as every +// other source. Forcing it true makes an air-gapped install fail preflight for +// a registry that is never contacted (ImagePullPolicy is IfNotPresent). +func TestEnumerateRegistries_NonNGCImageRegistryIsNotCritical(t *testing.T) { + entries := EnumerateRegistries("mirror.company.internal/nvcf/cluster-validator:1.0", "", nil) + for _, e := range entries { + if e.Registry == "mirror.company.internal" { + assert.False(t, e.Critical, "a non-NGC mirror must not be forced critical") + return + } + } + t.Fatal("mirror.company.internal not enumerated") +} + +// With no validator image and no stack values file, nothing names a registry +// and the run would report on quay.io alone, leaving the operator's NGC +// credentials unchecked in what is the default configuration. +func TestEnumerateRegistries_FallsBackToNGCWhenNothingNamesARegistry(t *testing.T) { + got := EnumerateRegistries("", "", nil) + + var ngc *RegistryEntry + for i := range got { + if got[i].Registry == "nvcr.io" { + ngc = &got[i] + } + } + require.NotNil(t, ngc, "nvcr.io must be probed when no source names a registry") + assert.False(t, ngc.Critical, + "a guessed registry must not hard-fail the run; this category has no opt-out flag") +} + +// A mirrored install has no reason to reach nvcr.io, and probing it there adds +// a failing round trip for the sites least able to make it. +func TestEnumerateRegistries_NoNGCFallbackForAMirroredStack(t *testing.T) { + dir := t.TempDir() + values := filepath.Join(dir, "base.yaml") + require.NoError(t, os.WriteFile(values, + []byte("global:\n image:\n registry: harbor.example.com\n"), 0o600)) + + got := EnumerateRegistries("", values, nil) + for _, e := range got { + assert.NotEqual(t, "nvcr.io", e.Registry, + "a stack that named its own registry must not be probed against NGC") + } +} + +// The fallback must not shadow or duplicate an NGC registry a source named, +// which carries a repo hint and is critical. +func TestEnumerateRegistries_FallbackDoesNotDuplicateNamedNGC(t *testing.T) { + got := EnumerateRegistries("nvcr.io/nvidia/nvcf-byoc/cluster-validator:1.0.0", "", nil) + + n := 0 + for _, e := range got { + if e.Registry == "nvcr.io" { + n++ + assert.True(t, e.Critical, "an NGC registry named by the image stays critical") + assert.Equal(t, "nvidia/nvcf-byoc/cluster-validator", e.RepoHint) + } + } + assert.Equal(t, 1, n, "nvcr.io must appear exactly once") +} + +// parseRegistryHostPort returns its input verbatim when SplitHostPort fails, +// and it fails on an already-bracketed literal with missingPort. Without a +// prefix guard that arrives here still bracketed and becomes "[[fd00::1]]", +// which http.NewRequest rejects. The documented bracketed form must work. +func TestEnumerateRegistries_DoesNotDoubleBracketIPv6(t *testing.T) { + for _, in := range []string{"[fd00::1]", "fd00::1"} { + got := EnumerateRegistries("", "", []string{in}) + var found string + for _, e := range got { + if strings.Contains(e.Registry, "fd00") { + found = e.Registry + } + } + assert.Equal(t, "[fd00::1]", found, "input %q must yield a singly-bracketed host", in) + } +} + +func TestEnumerateRegistries_KeepsBracketedIPv6WithPort(t *testing.T) { + got := EnumerateRegistries("", "", []string{"[fd00::1]:5000"}) + var found string + for _, e := range got { + if strings.Contains(e.Registry, "fd00") { + found = e.Registry + } + } + assert.Equal(t, "[fd00::1]:5000", found) +} + +// The probe builds "https://" + registry + "/v2/", so a registry string that +// carries "/" or "@" moves the host. A values file the CLI finds by walking up +// from CWD must not be able to aim an outbound request. +func TestEnumerateRegistries_RejectsHostMovingRegistryStrings(t *testing.T) { + dir := t.TempDir() + values := filepath.Join(dir, "base.yaml") + require.NoError(t, os.WriteFile(values, + []byte("global:\n image:\n registry: nvcr.io@attacker.example.com\n"), 0o600)) + + for _, e := range EnumerateRegistries("nvcr.io@evil.test/x/y:1", values, nil) { + assert.NotContains(t, e.Registry, "@", "a host-moving string must not be probed") + assert.NotContains(t, e.Registry, "attacker.example.com") + assert.NotContains(t, e.Registry, "evil.test") + } +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/stack_namespaces.go b/src/clis/nvcf-cli/internal/selfhosted/stack_namespaces.go new file mode 100644 index 0000000000..a6bf51426d --- /dev/null +++ b/src/clis/nvcf-cli/internal/selfhosted/stack_namespaces.go @@ -0,0 +1,107 @@ +/* +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package selfhosted + +import ( + "os" + "path/filepath" + "regexp" + "sort" + "strings" +) + +// helmfileNamespaceRE matches a literal `namespace: ` declaration on a +// helmfile release entry. +// +// Two deliberate restrictions, because a false positive here becomes a +// "delete this namespace" remediation: +// +// - Indentation is capped at 4 spaces, the release-entry level. Keys nested +// inside a release's `values:` block sit at 6 or more and must not be read +// as release namespaces. +// - The value must be a bare DNS label. A value containing a Go template +// action is operator-configurable (the gateway controller namespace is +// one), so its rendered value is not knowable from the source. +var helmfileNamespaceRE = regexp.MustCompile(`(?m)^ {0,4}namespace:\s*([a-z0-9][a-z0-9.-]*)\s*$`) + +// stackReleaseNamespaces returns the namespaces that helmfile releases deploy +// into for the stack rooted at stackDir, or nil when the stack is not readable. +// +// This is the authoritative answer to "which namespaces does the stack own", +// which matters because the stale-namespace check's remediation is to delete +// them: a hardcoded list that drifts either misses a real leftover or, worse, +// names a namespace the stack does not own. +// +// Callers fall back to the static list when this returns nil, which is the +// normal case for a released binary with no stack checkout alongside it. +func stackReleaseNamespaces(stackDir string) []string { + if stackDir == "" { + return nil + } + // helmfile accepts plain .yaml fragments as well as .yaml.gotmpl. + var entries []string + for _, pattern := range []string{"*.yaml.gotmpl", "*.yaml"} { + matches, err := filepath.Glob(filepath.Join(stackDir, "helmfile.d", pattern)) + if err != nil { + return nil + } + entries = append(entries, matches...) + } + if len(entries) == 0 { + return nil + } + + seen := make(map[string]bool) + for _, path := range entries { + body, err := os.ReadFile(path) + if err != nil { + // Bail out rather than deriving a partial list. A single + // unreadable fragment (a root-owned 0600 file left by "sudo + // helmfile", say) would otherwise silently drop a third of the + // namespaces, and the caller prefers any non-empty derived list + // over the complete static fallback. That turns a truncated scan + // into an affirmative all-clear. + return nil + } + for _, m := range helmfileNamespaceRE.FindAllStringSubmatch(string(body), -1) { + if ns := strings.TrimSpace(m[1]); ns != "" { + seen[ns] = true + } + } + } + if len(seen) == 0 { + return nil + } + + out := make([]string, 0, len(seen)) + for ns := range seen { + out = append(out, ns) + } + sort.Strings(out) + return out +} + +// resolveStackNamespaces returns the namespaces to probe for the given plane. +// It prefers what the stack actually declares and falls back to the static +// list when no stack is available. +func resolveStackNamespaces(stackDir string, fallback []string) []string { + // Union, not replace. The derived list follows the stack, but it cannot see + // namespaces behind a helmfiles: include, so on its own it can still be + // short. Merging keeps the static list as a floor. + return mergeNamespaces(fallback, stackReleaseNamespaces(stackDir)) +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/stack_namespaces_test.go b/src/clis/nvcf-cli/internal/selfhosted/stack_namespaces_test.go new file mode 100644 index 0000000000..236e0102fd --- /dev/null +++ b/src/clis/nvcf-cli/internal/selfhosted/stack_namespaces_test.go @@ -0,0 +1,151 @@ +/* +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package selfhosted + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// writeStack lays out a minimal helmfile.d matching the real stack's shape. +func writeStack(t *testing.T, files map[string]string) string { + t.Helper() + dir := t.TempDir() + hd := filepath.Join(dir, "helmfile.d") + require.NoError(t, os.MkdirAll(hd, 0o755)) + for name, body := range files { + require.NoError(t, os.WriteFile(filepath.Join(hd, name), []byte(body), 0o600)) + } + return dir +} + +func TestStackReleaseNamespaces_ReadsLiteralNamespaces(t *testing.T) { + dir := writeStack(t, map[string]string{ + "01-dependencies.yaml.gotmpl": ` +releases: + - name: nats + namespace: nats-system + - name: cert-manager + namespace: cert-manager +`, + "02-core.yaml.gotmpl": ` +releases: + - name: api + namespace: nvcf + - name: ui + namespace: nvcf-ui +`, + }) + + got := stackReleaseNamespaces(dir) + assert.Equal(t, []string{"cert-manager", "nats-system", "nvcf", "nvcf-ui"}, got, + "namespaces must come from the stack, de-duplicated and sorted") +} + +// The gateway controller namespace is templated from a values key, so its +// rendered value is not knowable from the source. Including the raw template +// text would produce a garbage namespace to probe and, on a hit, to delete. +func TestStackReleaseNamespaces_SkipsTemplatedNamespaces(t *testing.T) { + dir := writeStack(t, map[string]string{ + "02-core.yaml.gotmpl": ` +releases: + - name: api + namespace: nvcf + - name: ingress + namespace: {{ .Values.ingress.gatewayApi.controllerNamespace }} +`, + }) + + got := stackReleaseNamespaces(dir) + assert.Equal(t, []string{"nvcf"}, got, "a templated namespace must not be probed") +} + +func TestResolveStackNamespaces_FallsBackWhenNoStack(t *testing.T) { + fallback := []string{"nvcf", "sis"} + + assert.Equal(t, fallback, resolveStackNamespaces("", fallback), + "no stack path must use the static list") + assert.Equal(t, fallback, resolveStackNamespaces(t.TempDir(), fallback), + "a directory with no helmfile.d must use the static list") +} + +// The derived list is additive, not a replacement: it cannot see namespaces +// behind a helmfiles: include, so on its own it can still be short. The static +// list stays as a floor. +func TestResolveStackNamespaces_UnionsStackWithStatic(t *testing.T) { + dir := writeStack(t, map[string]string{ + "01.yaml.gotmpl": "releases:\n - name: a\n namespace: from-stack\n", + }) + got := resolveStackNamespaces(dir, []string{"static"}) + assert.Contains(t, got, "from-stack", "the stack's namespaces must be picked up") + assert.Contains(t, got, "static", "the static list must remain a floor") +} + +// An unreadable fragment must not yield a truncated list that then overrides +// the complete static one, which would report an affirmative all-clear over a +// scan missing a third of its namespaces. +func TestStackReleaseNamespaces_UnreadableFragmentYieldsNothing(t *testing.T) { + dir := writeStack(t, map[string]string{ + "01.yaml.gotmpl": "releases:\n - name: a\n namespace: one\n", + "02.yaml.gotmpl": "releases:\n - name: b\n namespace: two\n", + }) + // A directory, not a chmod 000 file: root bypasses the permission bits, so + // a mode-based fixture passes locally and fails in CI, where tests run as + // root. os.ReadFile returns EISDIR for every UID, so the test means the + // same thing everywhere rather than being skipped where it matters most. + unreadable := filepath.Join(dir, "helmfile.d", "02.yaml.gotmpl") + require.NoError(t, os.Remove(unreadable)) + require.NoError(t, os.Mkdir(unreadable, 0o755)) + + assert.Nil(t, stackReleaseNamespaces(dir), + "a partial parse must not masquerade as the stack's full namespace set") +} + +// helmfile accepts plain .yaml fragments too. +func TestStackReleaseNamespaces_ReadsPlainYAMLFragments(t *testing.T) { + dir := writeStack(t, map[string]string{ + "01.yaml": "releases:\n - name: a\n namespace: plain-yaml\n", + }) + assert.Contains(t, stackReleaseNamespaces(dir), "plain-yaml") +} + +// A `namespace:` key nested inside a release's values block is chart +// configuration, not a namespace the stack owns. Reading it as one would add a +// probe target whose remediation is deletion. +func TestStackReleaseNamespaces_SkipsNestedValuesKeys(t *testing.T) { + dir := writeStack(t, map[string]string{ + "02-core.yaml.gotmpl": ` +releases: + - name: api + namespace: nvcf + values: + - serviceMonitor: + namespace: monitoring + - someChart: + namespace: kube-system +`, + }) + + got := stackReleaseNamespaces(dir) + assert.Equal(t, []string{"nvcf"}, got, + "only release-level namespaces may be probed; nested values keys must be ignored") +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/stale_namespace.go b/src/clis/nvcf-cli/internal/selfhosted/stale_namespace.go new file mode 100644 index 0000000000..02a42b108e --- /dev/null +++ b/src/clis/nvcf-cli/internal/selfhosted/stale_namespace.go @@ -0,0 +1,205 @@ +/* +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package selfhosted + +import ( + "context" + "fmt" + + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// nvcfControlPlaneNamespaces lists namespaces that a helmfile release deploys +// into on the control-plane cluster, per deploy/stacks/self-managed/helmfile.d. +// Any of these that exist without an active Helm release, or that are stuck +// Terminating, are leftover from a failed or partial teardown. +// +// Only namespaces that actually host a release belong here: the remediation for +// a hit is "delete this namespace", so a namespace populated by something other +// than Helm (nvcf-backend, created at runtime by NVCA for worker pods) would be +// reported stale on a healthy cluster and deleting it would destroy live work. +// +// The gateway controller namespace is deliberately absent: the release templates +// it from .Values.ingress.gatewayApi.controllerNamespace, so hardcoding +// envoy-gateway-system would probe a namespace the stack may not own. +var nvcfControlPlaneNamespaces = []string{ + "api-keys", "cassandra-system", "cert-manager", "ess", + "nats-system", "nvcf", "nvcf-ui", "sis", "vault-system", +} + +// nvcfComputePlaneNamespaces lists namespaces that a helmfile release deploys +// into on the compute-plane cluster, per +// deploy/stacks/nvcf-compute-plane/helmfile.d. nvca-system is deliberately +// absent: it is operator-created and hosts no release. +var nvcfComputePlaneNamespaces = []string{ + "dynamo-system", "grove-system", "kai-scheduler", "nvca-operator", +} + +// StaleNamespace describes a single NVCF stack namespace that appears to be a +// leftover from a failed or partial teardown. +type StaleNamespace struct { + Name string + Reason string // human-readable cause: "stuck Terminating" or "no Helm release" +} + +// StaleNamespaceProber inspects the given namespaces and returns those that +// appear stale. The probe is read-only; it never deletes or modifies anything. +// A non-nil error means the cluster could not be contacted; the returned slice +// may be a partial result. +type StaleNamespaceProber func(ctx context.Context, kubeContext string, namespaces []string) ([]StaleNamespace, error) + +// NewStaleNamespaceProber returns a StaleNamespaceProber backed by client-go. +// Chart-independent: works before any Helm release exists, and uses the +// operator's kubeconfig context to talk to the target cluster. +func NewStaleNamespaceProber() StaleNamespaceProber { + return func(ctx context.Context, kubeContext string, namespaces []string) ([]StaleNamespace, error) { + restCfg, err := loadKubeConfig(kubeContext) + if err != nil { + return nil, fmt.Errorf("building kubeconfig: %w", err) + } + client, err := kubernetes.NewForConfig(restCfg) + if err != nil { + return nil, fmt.Errorf("building kubernetes client: %w", err) + } + return probeStaleNamespaces(ctx, client, namespaces) + } +} + +// probeStaleNamespaces is the testable core that accepts a kubernetes.Interface +// so callers can inject fake.NewSimpleClientset in unit tests. +// +// A namespace is considered stale when either: +// - its DeletionTimestamp is set or its phase is Terminating (finalizer +// deadlock; it will never complete without operator intervention), or +// - it exists but holds no active Helm release (empty shell left by a partial +// helm uninstall or a failed teardown that cleaned the release but not the +// namespace). +// +// Helm 3 marks each release secret with the label owner=helm; absence of any +// such secret means no live Helm release occupies the namespace. +const ( + // helmReleaseListPageSize bounds each page of the owner=helm scan. A + // namespace holds at most a handful of release objects, so this is only a + // ceiling on how much is pulled per round trip while paging past + // non-matching objects. + helmReleaseListPageSize = 100 + + // helmReleaseListMaxPages stops the scan even if the server keeps handing + // back a Continue token. At the page size above this covers 100k objects in + // one namespace, far past anything real, and guarantees termination. + helmReleaseListMaxPages = 1000 +) + +// helmReleaseExists reports whether any owner=helm object exists, paging until +// it finds one or the server reports no more results. +// +// A single page with Limit set is not a valid existence test: the apiserver +// applies the label selector after paging, so a page can legitimately return +// zero items alongside a Continue token. A namespace like nvcf holds dozens of +// ServiceAccount tokens and TLS secrets that sort before sh.helm.release.v1.*, +// so the first page is routinely empty on a perfectly healthy install. +func helmReleaseExists( + list func(metav1.ListOptions) (count int, cont string, err error), +) (bool, error) { + opts := metav1.ListOptions{LabelSelector: "owner=helm", Limit: helmReleaseListPageSize} + for page := 0; page < helmReleaseListMaxPages; page++ { + count, cont, err := list(opts) + if err != nil { + return false, err + } + if count > 0 { + return true, nil + } + if cont == "" { + return false, nil + } + opts.Continue = cont + } + return false, fmt.Errorf("gave up after %d pages scanning for Helm releases", helmReleaseListMaxPages) +} + +func probeStaleNamespaces(ctx context.Context, client kubernetes.Interface, namespaces []string) ([]StaleNamespace, error) { + var stale []StaleNamespace + // noRelease is held back until we know the Helm storage driver keeps its + // state in-cluster at all; see the gate below. + var noRelease []string + anyHelmReleaseSeen := false + for _, name := range namespaces { + ns, err := client.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{}) + if err != nil { + if apierrors.IsNotFound(err) { + continue // absent = healthy; the check only fires on unexpected presence + } + return stale, fmt.Errorf("get namespace %s: %w", name, err) + } + + if ns.DeletionTimestamp != nil || ns.Status.Phase == corev1.NamespaceTerminating { + stale = append(stale, StaleNamespace{Name: name, Reason: "stuck Terminating"}) + continue + } + + // Check Secrets first (the default Helm storage driver), then ConfigMaps + // for HELM_DRIVER=configmap clusters. Both label release objects + // owner=helm. + found, err := helmReleaseExists( + func(opts metav1.ListOptions) (int, string, error) { + l, lerr := client.CoreV1().Secrets(name).List(ctx, opts) + if lerr != nil { + return 0, "", lerr + } + return len(l.Items), l.Continue, nil + }) + if err != nil { + return stale, fmt.Errorf("list Helm secrets in %s: %w", name, err) + } + if found { + anyHelmReleaseSeen = true + continue // healthy: active Helm release found via the secret driver + } + found, err = helmReleaseExists( + func(opts metav1.ListOptions) (int, string, error) { + l, lerr := client.CoreV1().ConfigMaps(name).List(ctx, opts) + if lerr != nil { + return 0, "", lerr + } + return len(l.Items), l.Continue, nil + }) + if err != nil { + return stale, fmt.Errorf("list Helm configmaps in %s: %w", name, err) + } + if found { + anyHelmReleaseSeen = true + continue + } + noRelease = append(noRelease, name) + } + + // Only trust the "no Helm release" signal when at least one owner=helm + // object was seen somewhere. HELM_DRIVER=sql keeps release state in a + // database with no in-cluster object at all, so without this every + // namespace of a healthy production install reports stale. + if anyHelmReleaseSeen { + for _, name := range noRelease { + stale = append(stale, StaleNamespace{Name: name, Reason: "no Helm release"}) + } + } + return stale, nil +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/stale_namespace_test.go b/src/clis/nvcf-cli/internal/selfhosted/stale_namespace_test.go new file mode 100644 index 0000000000..e99a06868f --- /dev/null +++ b/src/clis/nvcf-cli/internal/selfhosted/stale_namespace_test.go @@ -0,0 +1,470 @@ +/* +SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package selfhosted + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + ktesting "k8s.io/client-go/testing" +) + +// -- probeStaleNamespaces -- + +func TestProbeStaleNamespaces_AbsentIsHealthy(t *testing.T) { + // A namespace that doesn't exist is not stale - it has simply never been + // created or was already fully deleted. + client := fake.NewSimpleClientset() + stale, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf", "sis"}) + require.NoError(t, err) + assert.Empty(t, stale, "absent namespaces must not be reported as stale") +} + +func TestProbeStaleNamespaces_TerminatingIsByDeletionTimestamp(t *testing.T) { + now := metav1.Now() + client := fake.NewSimpleClientset(&corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf", DeletionTimestamp: &now}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }) + stale, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf"}) + require.NoError(t, err) + require.Len(t, stale, 1) + assert.Equal(t, "nvcf", stale[0].Name) + assert.Contains(t, stale[0].Reason, "Terminating") +} + +func TestProbeStaleNamespaces_TerminatingIsByPhase(t *testing.T) { + client := fake.NewSimpleClientset(&corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "sis"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceTerminating}, + }) + stale, err := probeStaleNamespaces(context.Background(), client, []string{"sis"}) + require.NoError(t, err) + require.Len(t, stale, 1) + assert.Equal(t, "sis", stale[0].Name) + assert.Contains(t, stale[0].Reason, "Terminating") +} + +func TestProbeStaleNamespaces_EmptyShellNoHelmSecrets(t *testing.T) { + // Namespace exists and is Active but holds no Helm release secrets -> + // leftover empty shell from a partial helm uninstall. + // + // A second namespace carries a real release so the driver is known to keep + // its state in-cluster. Without that the signal is unusable and correctly + // suppressed, which is what HELM_DRIVER=sql looks like. + client := fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }, + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "sis"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }, + &corev1.Secret{ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.sis.v1", + Namespace: "sis", + Labels: map[string]string{"owner": "helm", "name": "sis", "status": "deployed"}, + }}, + ) + stale, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf", "sis"}) + require.NoError(t, err) + require.Len(t, stale, 1) + assert.Equal(t, "nvcf", stale[0].Name) + assert.Contains(t, stale[0].Reason, "Helm release") +} + +func TestProbeStaleNamespaces_HealthyReleaseNotStale(t *testing.T) { + // Namespace exists and carries an owner=helm secret -> active Helm release, + // not stale. + client := fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }, + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.nvcf.v1", + Namespace: "nvcf", + Labels: map[string]string{"owner": "helm", "name": "nvcf", "status": "deployed"}, + }, + }, + ) + stale, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf"}) + require.NoError(t, err) + assert.Empty(t, stale, "namespace with an active Helm release must not be stale") +} + +func TestProbeStaleNamespaces_HealthyReleaseConfigMapDriverNotStale(t *testing.T) { + // HELM_DRIVER=configmap stores release objects as ConfigMaps with owner=helm. + // A namespace with an owner=helm ConfigMap and no Helm Secret must not be + // reported as stale. + client := fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "nvcf.v1", + Namespace: "nvcf", + Labels: map[string]string{"owner": "helm", "name": "nvcf", "status": "deployed"}, + }, + }, + ) + stale, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf"}) + require.NoError(t, err) + assert.Empty(t, stale, "namespace with an owner=helm ConfigMap (configmap driver) must not be stale") +} + +func TestProbeStaleNamespaces_MixedNamespaces(t *testing.T) { + // One absent, one healthy, one terminating, one empty shell. + now := metav1.Now() + client := fake.NewSimpleClientset( + // "sis" - healthy with a Helm release + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "sis"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }, + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.sis.v1", Namespace: "sis", + Labels: map[string]string{"owner": "helm"}, + }, + }, + // "nvcf" - stuck terminating + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf", DeletionTimestamp: &now}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceTerminating}, + }, + // "api-keys" - empty shell + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "api-keys"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }, + // "cassandra-system" - absent (not present in fake) + ) + + namespaces := []string{"cassandra-system", "sis", "nvcf", "api-keys"} + stale, err := probeStaleNamespaces(context.Background(), client, namespaces) + require.NoError(t, err) + require.Len(t, stale, 2, "only nvcf (terminating) and api-keys (empty shell) should be stale") + + staleNames := make(map[string]string, 2) + for _, s := range stale { + staleNames[s.Name] = s.Reason + } + assert.Contains(t, staleNames, "nvcf") + assert.Contains(t, staleNames["nvcf"], "Terminating") + assert.Contains(t, staleNames, "api-keys") + assert.Contains(t, staleNames["api-keys"], "Helm release") +} + +// -- staleNamespaceCheck binaryCheckSpec -- + +// pinCurrentKubeContext keeps hint assertions independent of the developer's +// kubeconfig: without it, a machine with a current-context makes every hint +// carry a --context flag the test did not ask for. +func pinCurrentKubeContext(t *testing.T, name string) { + t.Helper() + prev := currentKubeContextNameFn + currentKubeContextNameFn = func() string { return name } + t.Cleanup(func() { currentKubeContextNameFn = prev }) +} + +func TestStaleNamespaceCheck_ProberErrorDegradestoWarning(t *testing.T) { + pinCurrentKubeContext(t, "") + // A prober that cannot contact the cluster must not fail the overall check + // at error severity - it would produce false failures on transient network + // issues or misconfigured kubeconfigs. + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return nil, fmt.Errorf("cluster unreachable") + } + r := staleNamespaceCheck(prober, "", []string{"nvcf"}).Run(context.Background()) + assert.False(t, r.Passed) + assert.Equal(t, "warning", r.Severity, + "prober errors must degrade to warning so transient failures do not block the operator") + assert.Contains(t, r.Message, "cluster unreachable") +} + +func TestStaleNamespaceCheck_StaleIsError(t *testing.T) { + pinCurrentKubeContext(t, "") + // A successfully detected stale namespace must fail at error severity so + // anyFailed trips the non-zero exit code. + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{{Name: "nvcf", Reason: "stuck Terminating"}}, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf"}).Run(context.Background()) + assert.False(t, r.Passed) + assert.Equal(t, "error", r.Severity, + "detected stale namespaces must use error severity so the exit code is non-zero") + assert.Contains(t, r.Message, "nvcf") + assert.Contains(t, r.Message, "/api/v1/namespaces/nvcf/finalize", + "the remediation must use the finalize subresource; a plain patch is silently reverted") +} + +func TestStaleNamespaceCheck_CleanPasses(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return nil, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf", "sis"}).Run(context.Background()) + assert.True(t, r.Passed) +} + +func TestStaleNamespaceCheck_MessageNamesAllStaleNamespaces(t *testing.T) { + pinCurrentKubeContext(t, "") + // The remediation command must name every stale namespace so the operator + // can copy-paste it without having to cross-reference the check output. + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{ + {Name: "nvcf", Reason: "stuck Terminating"}, + {Name: "api-keys", Reason: "no Helm release"}, + }, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf", "api-keys"}).Run(context.Background()) + assert.Contains(t, r.Message, "nvcf") + assert.Contains(t, r.Message, "api-keys") + assert.Contains(t, r.Message, "/api/v1/namespaces/nvcf/finalize", + "the remediation must use the finalize subresource; a plain patch is silently reverted") + assert.Contains(t, r.Message, "kubectl get all -n api-keys") +} + +// A namespace on a real install holds many non-Helm Secrets (ServiceAccount +// tokens, TLS, pull secrets) that sort before sh.helm.release.v1.*. The +// apiserver applies the label selector after paging, so the first page can +// legitimately come back empty with a Continue token. Treating that as "no +// release" reports a live namespace stale and tells the operator to delete it. +func TestProbeStaleNamespaces_PagesPastNonMatchingObjects(t *testing.T) { + client := fake.NewSimpleClientset(&corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}, + }) + + // First page: empty with a Continue token. Second page: the release secret. + call := 0 + client.PrependReactor("list", "secrets", func(_ ktesting.Action) (bool, runtime.Object, error) { + call++ + if call == 1 { + return true, &corev1.SecretList{ + ListMeta: metav1.ListMeta{Continue: "next-page-token"}, + }, nil + } + return true, &corev1.SecretList{Items: []corev1.Secret{{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.nvcf.v1", Namespace: "nvcf", + Labels: map[string]string{"owner": "helm"}, + }, + }}}, nil + }) + + stale, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf"}) + require.NoError(t, err) + assert.Empty(t, stale, + "an empty first page with a Continue token must not be read as 'no Helm release'") + assert.Greater(t, call, 1, "the probe must follow the Continue token") +} + +// The remediation for a hit is "delete this namespace", so the list must only +// contain namespaces a helmfile release actually owns. nvcf-backend is created +// at runtime by NVCA and holds live worker pods. +func TestControlPlaneNamespaceList_ExcludesRuntimeOwnedNamespaces(t *testing.T) { + for _, ns := range []string{"nvcf-backend", "openbao-system"} { + assert.NotContains(t, nvcfControlPlaneNamespaces, ns, + "%s hosts no Helm release; probing it yields a destructive false positive", ns) + } + for _, ns := range []string{"cert-manager", "nvcf-ui"} { + assert.Contains(t, nvcfControlPlaneNamespaces, ns, + "%s is a real stack namespace and must be probed", ns) + } + assert.NotContains(t, nvcfComputePlaneNamespaces, "nvca-system", + "nvca-system is operator-created and hosts no release") +} + +// TestStaleNamespaceCheck_HintsPinTheProbedContext guards the remediation +// hints in split mode. The two callers probe different clusters, so a bare +// kubectl command in a hint runs against whatever context is current, and +// these hints delete namespaces. +func TestStaleNamespaceCheck_HintsPinTheProbedContext(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{ + {Name: "nvcf", Reason: "stuck Terminating"}, + {Name: "api-keys", Reason: "no Helm release"}, + }, nil + } + r := staleNamespaceCheck(prober, "cp-ctx", []string{"nvcf", "api-keys"}).Run(context.Background()) + + // Every kubectl invocation, including the one piped into xargs, has to + // carry the flag: one unpinned command is enough to hit the wrong cluster. + for _, cmd := range strings.Split(r.Message, "kubectl ")[1:] { + assert.True(t, strings.HasPrefix(cmd, "--context cp-ctx "), + "unpinned kubectl invocation in hint: kubectl %s", cmd) + } + assert.Contains(t, r.Message, "kubectl --context cp-ctx get all -n api-keys") +} + +func TestStaleNamespaceCheck_HintsQuoteTheContext(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{{Name: "nvcf", Reason: "no Helm release"}}, nil + } + r := staleNamespaceCheck(prober, "my ctx", []string{"nvcf"}).Run(context.Background()) + assert.Contains(t, r.Message, "--context 'my ctx' get all -n nvcf", + "a context name with a space must be quoted so the pasted command does not split it") +} + +// TestStaleNamespaceCheck_HintsSubstituteTheNamespace guards against a bare +// `` placeholder in a pasteable command: the shell reads `<` and `>` as +// redirection, so the command fails before kubectl runs. +func TestStaleNamespaceCheck_HintsSubstituteTheNamespace(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{ + {Name: "nvcf", Reason: "stuck Terminating"}, + {Name: "sis", Reason: "stuck Terminating"}, + }, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf", "sis"}).Run(context.Background()) + + assert.NotContains(t, r.Message, "", + "a shell-redirection placeholder must not appear in a copy-pasteable command") + assert.Contains(t, r.Message, "xargs -n1 kubectl get -n nvcf ") + assert.Contains(t, r.Message, "xargs -n1 kubectl get -n sis ") +} + +// TestStaleNamespaceCheck_HintsNameTheCurrentContext covers the single-cluster +// path. The probe followed the current-context, so the hint has to name it: +// the operator can switch context between reading this and pasting it, and +// these commands delete namespaces. +func TestStaleNamespaceCheck_HintsNameTheCurrentContext(t *testing.T) { + pinCurrentKubeContext(t, "k3d-local") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{{Name: "nvcf", Reason: "no Helm release"}}, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf"}).Run(context.Background()) + assert.Contains(t, r.Message, "kubectl --context k3d-local get all -n nvcf") +} + +// An unreadable kubeconfig must not break the hint; it degrades to no flag. +func TestStaleNamespaceCheck_HintsOmitUnknownContext(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{{Name: "nvcf", Reason: "no Helm release"}}, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf"}).Run(context.Background()) + assert.Contains(t, r.Message, "kubectl get all -n nvcf") +} + +// The probe must run against the same context the hints name. Resolving the +// current-context after probing leaves a window where it changes in between, +// which would have the delete hints target a cluster that was never read. +func TestStaleNamespaceCheck_ProbesTheResolvedContext(t *testing.T) { + pinCurrentKubeContext(t, "k3d-local") + var probed string + prober := func(_ context.Context, kctx string, _ []string) ([]StaleNamespace, error) { + probed = kctx + return nil, nil + } + staleNamespaceCheck(prober, "", []string{"nvcf"}).Run(context.Background()) + assert.Equal(t, "k3d-local", probed, + "the probe must target the resolved context, not whatever is current when it runs") +} + +// HELM_DRIVER=sql keeps release state in a database, so a healthy production +// install has no owner=helm object anywhere. Without a gate every stack +// namespace reports stale at error severity with a delete remediation. +func TestProbeStaleNamespaces_NoHelmObjectsAnywhereReportsNothing(t *testing.T) { + client := fake.NewSimpleClientset( + &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "nvcf"}}, + &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "sis"}}, + ) + got, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf", "sis"}) + require.NoError(t, err) + assert.Empty(t, got, + "with no in-cluster Helm state at all the signal is unusable, not evidence of staleness") +} + +// A namespace stuck Terminating is still reported even when no Helm release +// object exists anywhere: that signal does not depend on the storage driver. +func TestProbeStaleNamespaces_TerminatingReportedWithoutHelmObjects(t *testing.T) { + client := fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "nvcf"}, + Status: corev1.NamespaceStatus{Phase: corev1.NamespaceTerminating}, + }, + ) + got, err := probeStaleNamespaces(context.Background(), client, []string{"nvcf"}) + require.NoError(t, err) + require.Len(t, got, 1) + assert.Equal(t, "stuck Terminating", got[0].Reason) +} + +// A conditionally-disabled component installed the upstream way is healthy. +// Reporting it at error severity turns a supported shape into exit 2, and the +// old remediation would have destroyed every Certificate in the cluster. +func TestStaleNamespaceCheck_NoHelmReleaseWarnsAndDoesNotSuggestDelete(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{{Name: "cert-manager", Reason: "no Helm release"}}, nil + } + r := staleNamespaceCheck(prober, "", []string{"cert-manager"}).Run(context.Background()) + + assert.Equal(t, SeverityWarning, r.Severity, + "a namespace with no Helm release must not fail the run") + assert.NotContains(t, r.Message, "delete namespace", + "the remediation must not destroy a namespace the operator may own") +} + +// A namespace stuck Terminating does block the run. +func TestStaleNamespaceCheck_TerminatingIsStillAnError(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{{Name: "nvcf", Reason: "stuck Terminating"}}, nil + } + r := staleNamespaceCheck(prober, "", []string{"nvcf"}).Run(context.Background()) + assert.Equal(t, SeverityError, r.Severity) +} + +// kubectl keeps only the last -n it is given, so a joined command inspects one +// namespace and reports the rest as empty, which is the opposite of what an +// operator deciding whether to delete them needs. +func TestStaleNamespaceCheck_HintsOneCommandPerNamespace(t *testing.T) { + pinCurrentKubeContext(t, "") + prober := func(_ context.Context, _ string, _ []string) ([]StaleNamespace, error) { + return []StaleNamespace{ + {Name: "api-keys", Reason: "no Helm release"}, + {Name: "ess", Reason: "no Helm release"}, + }, nil + } + r := staleNamespaceCheck(prober, "", []string{"api-keys", "ess"}).Run(context.Background()) + + assert.NotContains(t, r.Message, "-n api-keys -n ess", + "a joined namespace list silently inspects only the last one") + assert.Contains(t, r.Message, "get all -n api-keys") + assert.Contains(t, r.Message, "get all -n ess") +} diff --git a/src/clis/nvcf-cli/internal/selfhosted/teardown/drain_test.go b/src/clis/nvcf-cli/internal/selfhosted/teardown/drain_test.go index 3452e2724d..a8cb5c70c1 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/teardown/drain_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/teardown/drain_test.go @@ -34,7 +34,7 @@ import ( type fakeSIS struct { deployments []ActiveDeployment removeErr error - removeCalled []string // IDs passed to RemoveDeployment + removeCalled []string // IDs passed to RemoveDeployment statusResults map[string]string // ID → state string statusCallCnt int32 } @@ -73,7 +73,7 @@ func (s *recordSink) Close() error { return nil } type discardSink struct{} func (d *discardSink) Emit(_ context.Context, _ progress.Event) error { return nil } -func (d *discardSink) Close() error { return nil } +func (d *discardSink) Close() error { return nil } // TestDrain_NoActiveDeploymentsIsNoop: empty list → returns nil, no events. func TestDrain_NoActiveDeploymentsIsNoop(t *testing.T) { diff --git a/src/clis/nvcf-cli/internal/selfhosted/validatortag.go b/src/clis/nvcf-cli/internal/selfhosted/validatortag.go index f6750bbf35..59de253e63 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/validatortag.go +++ b/src/clis/nvcf-cli/internal/selfhosted/validatortag.go @@ -23,7 +23,9 @@ import ( "encoding/json" "fmt" "io" + "net" "net/http" + "net/url" "os" "path/filepath" "regexp" @@ -132,11 +134,11 @@ func fetchValidatorTags(ctx context.Context, registry, repo string) ([]string, e return doc.Tags, nil } -func fetchWithBearer(ctx context.Context, url, registry, repo string) ([]byte, error) { - client := &http.Client{Timeout: validatorTagFetchTimeout} +func fetchWithBearer(ctx context.Context, rawURL, registry, repo string) ([]byte, error) { + client := &http.Client{Timeout: validatorTagFetchTimeout, CheckRedirect: refuseInsecureRedirect} // First attempt without auth so anonymous-pullable registries work. - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil) if err != nil { return nil, err } @@ -152,16 +154,19 @@ func fetchWithBearer(ctx context.Context, url, registry, repo string) ([]byte, e resp.Body.Close() return nil, fmt.Errorf("registry returned %s", resp.Status) } + // Capture the auth challenge before closing. + wwwAuth := resp.Header.Get("Www-Authenticate") resp.Body.Close() - // Bearer-token exchange. Realm and scope come from the Www-Authenticate - // header; for NGC the realm is /proxy_auth and scope is repository::pull. - token, err := exchangeBearerToken(ctx, client, registry, repo) + // Generic OCI Bearer-token exchange: uses the realm/service/scope from + // the WWW-Authenticate header so any OCI-compliant registry works, not + // just NGC. Falls back to NGC's /proxy_auth when the header is absent. + token, err := exchangeBearerToken(ctx, client, registry, repo, wwwAuth) if err != nil { return nil, err } - req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil) if err != nil { return nil, err } @@ -177,21 +182,156 @@ func fetchWithBearer(ctx context.Context, url, registry, repo string) ([]byte, e return io.ReadAll(resp.Body) } -// exchangeBearerToken does the NGC token exchange using credentials -// resolved from ~/.docker/config.json or NGC env vars. +// refuseInsecureRedirect rejects any redirect hop that is not https. // -// NGC-specific: this constructs the token URL using NGC's /proxy_auth -// realm rather than parsing the Www-Authenticate header from the 401 -// response (the generic OAuth2 distribution flow). Non-NGC registries -// (GCR, ECR, GHCR, Harbor, etc.) will return a non-200 here and the -// caller falls back to using the configured image reference as-is. -// Acceptable for v1 since the validator image only ships from NGC. -func exchangeBearerToken(ctx context.Context, client *http.Client, registry, repo string) (string, error) { +// Go strips the Authorization header only when a redirect changes host, and +// that comparison ignores the scheme. Without this, an https realm that 302s to +// http on the same host would re-send the operator's credentials in cleartext, +// defeating the https-only realm check a few lines below. +func refuseInsecureRedirect(req *http.Request, via []*http.Request) error { + if req.URL.Scheme != "https" { + return fmt.Errorf("refusing redirect to non-https URL %q", req.URL.Redacted()) + } + if len(via) >= 10 { + return fmt.Errorf("stopped after %d redirects", len(via)) + } + return nil +} + +// exchangeBearerToken implements the OCI Distribution Spec Bearer token flow, +// parsing realm/service/scope from the WWW-Authenticate header. Falls back to +// the NGC /proxy_auth endpoint when the header is absent or unparseable. +func exchangeBearerToken(ctx context.Context, client *http.Client, registry, repo, wwwAuthenticate string) (string, error) { + realm, service, scope := parseWWWAuthenticate(wwwAuthenticate) + + if realm == "" { + // No parseable WWW-Authenticate - use NGC's /proxy_auth as fallback. + return exchangeNGCBearerToken(ctx, client, registry, repo) + } + + // Build the token endpoint URL with service and scope query parameters. + u, err := url.Parse(realm) + if err != nil { + return exchangeNGCBearerToken(ctx, client, registry, repo) + } + // Reject non-HTTPS or relative realms before attaching credentials. + if u.Scheme != "https" || u.Host == "" { + return "", fmt.Errorf("refusing token exchange at insecure or relative realm %q for %s", realm, registry) + } + // Authorize the realm host before forwarding credentials. The realm URL + // comes from a registry-controlled response header. Without this check, a + // malicious registry could return realm="https://attacker.com/token" and + // receive the operator's Docker credentials for the original registry. + // Allow the realm only when it matches the registry's own host, is a + // sub-domain of that host (e.g. auth.registry.example.com for registry.example.com), + // or is an NGC auth domain when the registry is NGC-hosted (NGC delegates + // token issuance to authn.nvidia.com and other nvidia.com sub-domains). + realmHost := strings.ToLower(u.Hostname()) + regHost := strings.ToLower(registry) + if h, _, err := net.SplitHostPort(registry); err == nil { + regHost = strings.ToLower(h) + } + // Reject an empty realm host explicitly. "https://:443/token" has a + // non-empty u.Host (":443") so it clears the guard above, but Hostname() is + // "", and an empty trustedRealmDelegations lookup would then compare equal + // and authorize it. Fail closed instead. + if realmHost == "" { + return "", fmt.Errorf("refusing token exchange at realm %q with no host for %s", realm, registry) + } + realmOK := realmHost == regHost || + strings.HasSuffix(realmHost, "."+regHost) || + (isNGCRegistry(registry) && isNGCRegistry(realmHost)) || + trustedRealmDelegations[regHost] == realmHost + if !realmOK { + return "", fmt.Errorf("refusing to forward credentials to realm host %q; not authorized for registry %s", realmHost, registry) + } + q := u.Query() + if service != "" { + q.Set("service", service) + } + // Use scope from the WWW-Authenticate header when present. + // When scope is empty and a repo is provided, synthesize the standard + // pull scope. When neither is present (credential probe, no specific + // repo needed), omit scope entirely - most registries issue a valid + // token and the absence of a resource scope avoids org-level 403s for + // non-existent repositories. + if scope == "" && repo != "" { + scope = "repository:" + repo + ":pull" + } + if scope != "" { + q.Set("scope", scope) + } + u.RawQuery = q.Encode() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) + if err != nil { + return "", err + } + // Add credentials when present. Docker config covers any registry; + // NGC API key is only applicable to NGC-hosted registries. + // Critically: do NOT apply NGC_API_KEY to non-NGC registries - quay.io, + // GHCR, and Harbor will reject it, producing a misleading "credentials + // rejected" error when the real situation is "no credentials configured." + if user, pass, ok := credentialsForRegistry(registry); ok { + req.SetBasicAuth(user, pass) + } + + resp, err := client.Do(req) + if err != nil { + return "", err + } + if resp.StatusCode != http.StatusOK { + // Close the body immediately before the fallback or the error return so + // the connection is not held open while the NGC /proxy_auth call runs. + status := resp.Status + resp.Body.Close() + // WWW-Authenticate realm failed; try NGC's /proxy_auth as last resort + // for registries that implement both endpoints (e.g. staging NGC envs). + if isNGCRegistry(registry) { + return exchangeNGCBearerToken(ctx, client, registry, repo) + } + return "", fmt.Errorf("token exchange at %s returned %s", realm, status) + } + defer resp.Body.Close() + + // Both "token" (OCI spec) and "access_token" (Docker Hub variant) are valid. + var doc struct { + Token string `json:"token"` + AccessToken string `json:"access_token"` + } + if err := json.NewDecoder(resp.Body).Decode(&doc); err != nil { + return "", fmt.Errorf("decode token response: %w", err) + } + tok := doc.Token + if tok == "" { + tok = doc.AccessToken + } + if tok == "" { + return "", fmt.Errorf("empty token in response from %s", realm) + } + return tok, nil +} + +// exchangeNGCBearerToken is the NGC-specific /proxy_auth token exchange, +// kept as a named fallback for when the standard OCI flow cannot be used. +// It always rejects non-NGC registries so NGC credentials are never sent +// to an unrelated /proxy_auth endpoint. +func exchangeNGCBearerToken(ctx context.Context, client *http.Client, registry, repo string) (string, error) { + if !isNGCRegistry(registry) { + return "", fmt.Errorf("NGC token fallback not applicable for non-NGC registry %s", registry) + } user, pass, ok := ngcCredentials(registry) if !ok { - return "", fmt.Errorf("no NGC credentials for %s", registry) + return "", fmt.Errorf("no credentials for %s", registry) } - tokenURL := fmt.Sprintf("https://%s/proxy_auth?service=%s&scope=repository:%s:pull", registry, registry, repo) + // Build the query: use url.Values so the scope key is omitted entirely + // when repo is empty rather than sending scope= with an empty value. + // An empty scope validates the API key without org-scoped access checks. + q := url.Values{"service": {registry}} + if repo != "" { + q.Set("scope", "repository:"+repo+":pull") + } + tokenURL := "https://" + registry + "/proxy_auth?" + q.Encode() req, err := http.NewRequestWithContext(ctx, http.MethodGet, tokenURL, nil) if err != nil { return "", err @@ -203,7 +343,7 @@ func exchangeBearerToken(ctx context.Context, client *http.Client, registry, rep } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("token exchange returned %s", resp.Status) + return "", fmt.Errorf("NGC token exchange returned %s", resp.Status) } var doc struct { Token string `json:"token"` @@ -212,11 +352,162 @@ func exchangeBearerToken(ctx context.Context, client *http.Client, registry, rep return "", err } if doc.Token == "" { - return "", fmt.Errorf("empty token in response") + return "", fmt.Errorf("empty token in NGC response") } return doc.Token, nil } +// parseWWWAuthenticate extracts realm, service, and scope from a standard +// Bearer challenge header: +// +// Bearer realm="https://auth.example.com/token",service="reg.example.com",scope="repository:lib:pull" +// +// Returns empty strings when the header is absent, not a Bearer challenge, or +// cannot be parsed. The parser handles quoted values that might contain commas. +func parseWWWAuthenticate(header string) (realm, service, scope string) { + // Split scheme from parameters on the first whitespace. HTTP auth scheme + // names are case-insensitive (RFC 7235 s2.1), so compare with EqualFold. + idx := strings.IndexByte(header, ' ') + if idx < 0 || !strings.EqualFold(header[:idx], "Bearer") { + return + } + params := strings.TrimSpace(header[idx+1:]) + for len(params) > 0 { + // Find key= + eq := strings.IndexByte(params, '=') + if eq < 0 { + break + } + key := strings.TrimSpace(params[:eq]) + params = params[eq+1:] + + // Read value (quoted or unquoted) + var val string + if strings.HasPrefix(params, `"`) { + end := strings.IndexByte(params[1:], '"') + if end < 0 { + break + } + val = params[1 : end+1] + params = strings.TrimPrefix(strings.TrimSpace(params[end+2:]), ",") + } else { + comma := strings.IndexByte(params, ',') + if comma < 0 { + val = strings.TrimSpace(params) + params = "" + } else { + val = strings.TrimSpace(params[:comma]) + params = params[comma+1:] + } + } + + switch strings.ToLower(key) { + case "realm": + realm = val + case "service": + service = val + case "scope": + scope = val + } + } + return +} + +// trustedRealmDelegations maps a registry host to its authorized token host +// when the registry uses a separate host for token exchange. Only add entries +// here for registries with publicly documented auth architectures; this list +// extends the fail-closed realm validation and must not grow without a clear +// trust basis. +var trustedRealmDelegations = map[string]string{ + // Docker Hub documents this split explicitly: the pull host and the auth + // host are distinct (docs.docker.com/registry/spec/auth/token/). + "registry-1.docker.io": "auth.docker.io", + "docker.io": "auth.docker.io", +} + +// ngcApprovedHosts is the set of exact hostnames (without port) that are +// considered NGC-hosted. Dot-prefixed entries match any subdomain. +var ngcApprovedHosts = []string{ + "nvcr.io", + ".nvcr.io", + "nvidia.com", + ".nvidia.com", + "ngc.nvidia", + ".ngc.nvidia", +} + +// isBareRegistryHost reports whether s is a plain host[:port], with nothing in +// it that could move the request somewhere else once concatenated into a URL. +// +// This matters because the registry string is interpolated directly into +// "https://" + registry + "/...". A value like "evil.com/x.nvcr.io" ends with a +// trusted suffix but parses to host evil.com, so a suffix check alone would +// authorize sending credentials to an attacker. IPv6 literals keep their +// brackets and are allowed. +func isBareRegistryHost(s string) bool { + if s == "" { + return false + } + // "/" and "@" move the host; "?" and "#" truncate it; whitespace and + // control characters have no place in a hostname. + if strings.ContainsAny(s, "/@?#\\") { + return false + } + for _, r := range s { + if r <= ' ' || r == 0x7f { + return false + } + } + return true +} + +// isNGCRegistry returns true when the registry host belongs to an NVIDIA / NGC +// domain. The check strips any port from the registry string before matching +// so that nvcr.io:443 is handled correctly, and uses dot-boundary matching to +// reject deceptive suffixes such as evilnvcr.io or nvidia.com.invalid. +func isNGCRegistry(registry string) bool { + // Never treat a value we cannot safely place in a URL as an NGC host: the + // caller uses this to decide whether to forward the NGC API key. + if !isBareRegistryHost(registry) { + return false + } + host := registry + // Strip port if present (e.g. nvcr.io:5000 -> nvcr.io). + if h, _, err := net.SplitHostPort(registry); err == nil { + host = h + } + host = strings.ToLower(host) + for _, approved := range ngcApprovedHosts { + if strings.HasPrefix(approved, ".") { + // Subdomain match: host must end with ".suffix" or equal "suffix". + suffix := approved[1:] // strip the leading dot + if host == suffix || strings.HasSuffix(host, approved) { + return true + } + } else { + if host == approved { + return true + } + } + } + return false +} + +// credentialsForRegistry resolves (username, password) for any registry. +// Checks ~/.docker/config.json first, then falls back to NGC_API_KEY only +// for NGC-domain registries to avoid sending NGC creds to unrelated registries. +func credentialsForRegistry(registry string) (string, string, bool) { + if u, p, ok := credsFromDockerConfig(registry); ok { + return u, p, true + } + if isNGCRegistry(registry) { + if key := firstNonEmptyEnv(ngcAPIKeyEnvNames...); key != "" { + return "$oauthtoken", key, true + } + } + return "", "", false +} + // ngcCredentials resolves (username, password) for an NGC-hosted registry. // Checks ~/.docker/config.json first; falls back to NGC_API_KEY env vars // with the literal "$oauthtoken" sentinel username NGC expects. diff --git a/src/clis/nvcf-cli/internal/selfhosted/validatortag_test.go b/src/clis/nvcf-cli/internal/selfhosted/validatortag_test.go index 0bd57306d2..f1dafeb95d 100644 --- a/src/clis/nvcf-cli/internal/selfhosted/validatortag_test.go +++ b/src/clis/nvcf-cli/internal/selfhosted/validatortag_test.go @@ -20,8 +20,13 @@ package selfhosted import ( "context" "encoding/json" + "fmt" + "io" + "net/http" "os" "path/filepath" + "strings" + "sync" "testing" "time" @@ -31,12 +36,12 @@ import ( func TestParseImageRef(t *testing.T) { cases := []struct { - name string - in string - reg string - repo string - tag string - wantOK bool + name string + in string + reg string + repo string + tag string + wantOK bool }{ {"full tag", "stg.nvcr.io/nvidia/nvcf-byoc/cluster-validator:3.0.0-rc.26", "stg.nvcr.io", "nvidia/nvcf-byoc/cluster-validator", "3.0.0-rc.26", true}, {"digest", "nvcr.io/foo/bar@sha256:abc", "nvcr.io", "foo/bar", "sha256:abc", true}, @@ -64,8 +69,8 @@ func TestPickBestValidatorTag_StablePreferred(t *testing.T) { tags := []string{ "3.0.0-rc.11", "3.0.0-rc.26", - "3.0.0", // stable; should win over any rc - "3.1.0-rc.1", // higher major but pre-release: must lose to 3.0.0 + "3.0.0", // stable; should win over any rc + "3.1.0-rc.1", // higher major but pre-release: must lose to 3.0.0 "sha256-abc.sig", "3.0.0-v50ca53a0", // commit-SHA: filtered out by pattern } @@ -252,3 +257,246 @@ func TestNGCCredentials_EnvFallback(t *testing.T) { assert.Equal(t, "$oauthtoken", user) assert.Equal(t, "from-env", pass) } + +// -- parseWWWAuthenticate -- + +func TestParseWWWAuthenticate_Standard(t *testing.T) { + header := `Bearer realm="https://auth.docker.io/token",service="registry-1.docker.io",scope="repository:library/ubuntu:pull"` + realm, service, scope := parseWWWAuthenticate(header) + assert.Equal(t, "https://auth.docker.io/token", realm) + assert.Equal(t, "registry-1.docker.io", service) + assert.Equal(t, "repository:library/ubuntu:pull", scope) +} + +func TestParseWWWAuthenticate_GHCR(t *testing.T) { + header := `Bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:owner/image:pull"` + realm, service, scope := parseWWWAuthenticate(header) + assert.Equal(t, "https://ghcr.io/token", realm) + assert.Equal(t, "ghcr.io", service) + assert.Equal(t, "repository:owner/image:pull", scope) +} + +func TestParseWWWAuthenticate_NoBearer(t *testing.T) { + // Basic auth challenge - should return empty strings. + realm, service, scope := parseWWWAuthenticate(`Basic realm="My Registry"`) + assert.Empty(t, realm) + assert.Empty(t, service) + assert.Empty(t, scope) +} + +func TestParseWWWAuthenticate_Empty(t *testing.T) { + realm, service, scope := parseWWWAuthenticate("") + assert.Empty(t, realm) + assert.Empty(t, service) + assert.Empty(t, scope) +} + +func TestParseWWWAuthenticate_RealmOnly(t *testing.T) { + // Some registries omit service/scope in the initial challenge. + realm, service, scope := parseWWWAuthenticate(`Bearer realm="https://example.com/auth"`) + assert.Equal(t, "https://example.com/auth", realm) + assert.Empty(t, service) + assert.Empty(t, scope) +} + +func TestParseWWWAuthenticate_MixedCaseParams(t *testing.T) { + // Auth parameter names are parsed with mixed case in the wild. + realm, service, scope := parseWWWAuthenticate(`Bearer Realm="https://auth.example.com/token",Service="reg.example.com",Scope="repository:foo:pull"`) + assert.Equal(t, "https://auth.example.com/token", realm) + assert.Equal(t, "reg.example.com", service) + assert.Equal(t, "repository:foo:pull", scope) +} + +func TestParseWWWAuthenticate_CaseInsensitiveBearer(t *testing.T) { + // HTTP auth scheme names are case-insensitive (RFC 7235 s2.1). + for _, header := range []string{ + `bearer realm="https://auth.example.com/token",service="reg.example.com"`, + `BEARER realm="https://auth.example.com/token",service="reg.example.com"`, + `Bearer realm="https://auth.example.com/token",service="reg.example.com"`, + } { + realm, service, _ := parseWWWAuthenticate(header) + assert.Equal(t, "https://auth.example.com/token", realm, "header: %s", header) + assert.Equal(t, "reg.example.com", service, "header: %s", header) + } +} + +// -- isNGCRegistry -- + +func TestIsNGCRegistry(t *testing.T) { + // Valid NGC registries. + assert.True(t, isNGCRegistry("nvcr.io")) + assert.True(t, isNGCRegistry("stg.nvcr.io")) + assert.True(t, isNGCRegistry("registry.nvidia.com")) + assert.True(t, isNGCRegistry("nvcr.io:443"), "port must be stripped before matching") + + // Non-NGC registries must be rejected. + assert.False(t, isNGCRegistry("ghcr.io")) + assert.False(t, isNGCRegistry("quay.io")) + assert.False(t, isNGCRegistry("harbor.company.internal")) + + // Deceptive suffixes must be rejected. + assert.False(t, isNGCRegistry("evilnvcr.io"), "suffix match without dot boundary must be rejected") + assert.False(t, isNGCRegistry("nvidia.com.invalid"), "deceptive TLD must be rejected") + assert.False(t, isNGCRegistry("fakenvidia.com"), "partial host match must be rejected") +} + +// -- exchangeBearerToken realm host authorization -- + +// recordingTransport records every request it sees and reports whether any +// carried an Authorization header, so a test can assert that no credential +// escaped rather than only that an error was returned. +type recordingTransport struct { + mu sync.Mutex + requests []*http.Request + withAuth []string + inner http.RoundTripper +} + +func (rt *recordingTransport) RoundTrip(r *http.Request) (*http.Response, error) { + rt.mu.Lock() + rt.requests = append(rt.requests, r) + if r.Header.Get("Authorization") != "" { + rt.withAuth = append(rt.withAuth, r.URL.String()) + } + rt.mu.Unlock() + if rt.inner == nil { + return nil, fmt.Errorf("no inner transport") + } + return rt.inner.RoundTrip(r) +} + +func TestExchangeBearerToken_RejectsAttackerRealm(t *testing.T) { + // A malicious registry returns a realm on an attacker-controlled host. The + // realm check must reject it, and crucially must do so before any request + // carrying the operator's credentials leaves the process. + // + // Credentials have to be configured for the assertion to mean anything: if + // none were present, no request could carry an Authorization header whether + // the control works or not. + t.Setenv("NGC_API_KEY", "test-key") + + rec := &recordingTransport{inner: http.DefaultTransport} + client := &http.Client{Transport: rec} + + const wwwAuth = `Bearer realm="https://attacker.example.com/token",service="harbor.company.internal"` + _, err := exchangeBearerToken(context.Background(), client, + "harbor.company.internal", "myrepo/image", wwwAuth) + + require.Error(t, err) + assert.Contains(t, err.Error(), "not authorized for registry") + assert.Empty(t, rec.withAuth, + "no request carrying an Authorization header may be issued once the realm is rejected") + for _, r := range rec.requests { + assert.NotContains(t, r.URL.Host, "attacker", + "no request at all may reach the attacker host") + } +} + +// An empty realm host must fail closed. "https://:443/token" has a non-empty +// u.Host (":443") so it clears the relative-realm guard, but Hostname() is "", +// and an empty trustedRealmDelegations lookup would compare equal to it. +func TestExchangeBearerToken_RejectsEmptyRealmHost(t *testing.T) { + t.Setenv("NGC_API_KEY", "test-key") + rec := &recordingTransport{inner: http.DefaultTransport} + client := &http.Client{Transport: rec} + + _, err := exchangeBearerToken(context.Background(), client, + "harbor.company.internal", "myrepo/image", `Bearer realm="https://:443/token"`) + + require.Error(t, err) + assert.Empty(t, rec.withAuth, "an empty realm host must not receive credentials") +} + +// -- exchangeNGCBearerToken -- + +// spyTransport is an http.RoundTripper that fails the test if called. +type spyTransport struct{ t *testing.T } + +func (s *spyTransport) RoundTrip(_ *http.Request) (*http.Response, error) { + s.t.Fatal("HTTP request must not be issued for non-NGC registry") + return nil, nil +} + +// roundTripperFunc adapts a function to the http.RoundTripper interface. +type roundTripperFunc func(*http.Request) (*http.Response, error) + +func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } + +func TestExchangeBearerToken_DockerHubDelegatedRealm(t *testing.T) { + // Docker Hub uses registry-1.docker.io as the pull host and auth.docker.io + // for token exchange. The realm check must authorize that delegation, so + // drive exchangeBearerToken and assert the request actually reached the + // auth host rather than comparing the delegation map against itself. + t.Setenv("NGC_API_KEY", "test-key") + + rec := &recordingTransport{inner: roundTripperFunc(func(r *http.Request) (*http.Response, error) { + if r.URL.Host != "auth.docker.io" { + return nil, fmt.Errorf("unexpected host %s", r.URL.Host) + } + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(strings.NewReader(`{"token":"dockerhub-token"}`)), + Header: make(http.Header), + }, nil + })} + client := &http.Client{Transport: rec} + + const wwwAuth = `Bearer realm="https://auth.docker.io/token",service="registry.docker.io",` + + `scope="repository:library/ubuntu:pull"` + tok, err := exchangeBearerToken(context.Background(), client, + "registry-1.docker.io", "library/ubuntu", wwwAuth) + + require.NoError(t, err, "the documented Docker Hub delegation must be authorized") + assert.Equal(t, "dockerhub-token", tok) + require.NotEmpty(t, rec.requests, "the token exchange must actually be issued") + assert.Equal(t, "auth.docker.io", rec.requests[0].URL.Host) +} + +func TestExchangeNGCBearerToken_RejectsNonNGCRegistry(t *testing.T) { + // A non-NGC registry must be rejected before any HTTP request is made, + // even when NGC credentials are configured. The spy transport fails the + // test immediately if RoundTrip is called, ensuring the isNGCRegistry + // guard fires before any network activity. + t.Setenv("NGC_API_KEY", "test-key") // configure a credential so a missing guard would reach the transport + client := &http.Client{Transport: &spyTransport{t: t}} + _, err := exchangeNGCBearerToken(context.Background(), client, "harbor.company.internal", "myrepo/image") + require.Error(t, err, "non-NGC registry must be rejected without issuing a request") + assert.Contains(t, err.Error(), "non-NGC registry") +} + +// The registry string is concatenated into "https://" + registry + "/...", so a +// suffix match alone is not enough to authorize forwarding the NGC API key: +// "evil.com/x.nvcr.io" ends with a trusted suffix but parses to host evil.com. +func TestIsNGCRegistry_RejectsHostConfusion(t *testing.T) { + for _, tc := range []struct { + registry string + want bool + why string + }{ + {"nvcr.io", true, "the canonical host"}, + {"stg.nvcr.io", true, "a real subdomain"}, + {"evil.com/x.nvcr.io", false, "path component: the request host is evil.com"}, + {"evil.com@nvcr.io", false, "userinfo: not a bare host"}, + {"nvcr.io?x=.nvcr.io", false, "query truncates the host"}, + {"nvcr.io#.nvcr.io", false, "fragment truncates the host"}, + {"nvcr.io.evil.com", false, "deceptive suffix"}, + {"nvcr.io evil.com", false, "whitespace"}, + } { + assert.Equal(t, tc.want, isNGCRegistry(tc.registry), + "isNGCRegistry(%q): %s", tc.registry, tc.why) + } +} + +// A non-bare registry must never reach the NGC token exchange, which attaches +// the API key with basic auth. +func TestExchangeNGCBearerToken_RejectsHostConfusion(t *testing.T) { + t.Setenv("NGC_API_KEY", "test-key") + rec := &recordingTransport{inner: http.DefaultTransport} + client := &http.Client{Transport: rec} + + _, err := exchangeNGCBearerToken(context.Background(), client, "evil.com/x.nvcr.io", "repo/img") + + require.Error(t, err) + assert.Empty(t, rec.withAuth, "the NGC API key must not be sent to a confused host") + assert.Empty(t, rec.requests, "no request may be issued at all") +}