From a1ca6921d0cd3e8c0d343d647e643a7203365d2c Mon Sep 17 00:00:00 2001 From: zachaller Date: Wed, 18 Jan 2023 09:54:34 -0600 Subject: [PATCH] feat: metrics plugin system based on hashicorp go-plugin Signed-off-by: zachaller --- Makefile | 11 +- cmd/rollouts-controller/main.go | 15 +- .../internal/plugin/plugin.go | 183 +++ .../internal/plugin/plugin_test.go | 107 ++ cmd/sample-metrics-plugin/main.go | 37 + controller/controller.go | 3 + docs/analysis/plugins.md | 62 + .../features/kustomize/rollout_cr_schema.json | 24 + go.mod | 6 + go.sum | 15 +- manifests/crds/analysis-run-crd.yaml | 5 + manifests/crds/analysis-template-crd.yaml | 5 + .../crds/cluster-analysis-template-crd.yaml | 5 + manifests/install.yaml | 15 + metric/provider.go | 21 + metricproviders/metricproviders.go | 80 +- metricproviders/plugin/plugin.go | 232 +++ metricproviders/plugin/plugin_test.go | 162 +++ .../plugin/plugin_test_implementation.go | 57 + mkdocs.yml | 1 + pkg/apis/rollouts/v1alpha1/analysis_types.go | 8 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 1281 ++++++++++------- pkg/apis/rollouts/v1alpha1/generated.proto | 9 + .../rollouts/v1alpha1/openapi_generated.go | 27 +- .../v1alpha1/zz_generated.deepcopy.go | 26 + rollout/controller_test.go | 3 + utils/analysis/factory.go | 3 + utils/defaults/defaults.go | 28 + utils/defaults/defaults_test.go | 15 + utils/plugin/plugin.go | 125 ++ utils/plugin/plugin_test.go | 72 + 31 files changed, 2091 insertions(+), 552 deletions(-) create mode 100644 cmd/sample-metrics-plugin/internal/plugin/plugin.go create mode 100644 cmd/sample-metrics-plugin/internal/plugin/plugin_test.go create mode 100644 cmd/sample-metrics-plugin/main.go create mode 100644 docs/analysis/plugins.md create mode 100644 metric/provider.go create mode 100644 metricproviders/plugin/plugin.go create mode 100644 metricproviders/plugin/plugin_test.go create mode 100644 metricproviders/plugin/plugin_test_implementation.go create mode 100644 utils/plugin/plugin.go create mode 100644 utils/plugin/plugin_test.go diff --git a/Makefile b/Makefile index 3f5126d912..4e1d4c1d2f 100644 --- a/Makefile +++ b/Makefile @@ -209,7 +209,7 @@ lint: go-mod-vendor .PHONY: test test: test-kustomize - go test -covermode=count -coverprofile=coverage.out ${TEST_TARGET} + @make test-unit .PHONY: test-kustomize test-kustomize: @@ -225,7 +225,7 @@ test-e2e: install-devtools-local .PHONY: test-unit test-unit: install-devtools-local - ${DIST_DIR}/gotestsum --junitfile=junit.xml --format=testname --packages="./..." -- -covermode=count -coverprofile=coverage.out ./... + ${DIST_DIR}/gotestsum --junitfile=junit.xml --format=testname -- -covermode=count -coverprofile=coverage.out `go list ./... | grep -v ./cmd/sample-metrics-plugin` .PHONY: coverage @@ -279,3 +279,10 @@ trivy: .PHONY: checksums checksums: shasum -a 256 ./dist/kubectl-argo-rollouts-* | awk -F './dist/' '{print $$1 $$2}' > ./dist/argo-rollouts-checksums.txt + +# Build sample plugin with debug info +# https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html +.PHONY: build-sample-metric-plugin-debug +build-sample-metric-plugin-debug: + go build -gcflags="all=-N -l" -o metrics-plugin cmd/sample-metrics-plugin/main.go + diff --git a/cmd/rollouts-controller/main.go b/cmd/rollouts-controller/main.go index 4aadf9ad82..820634c1c0 100644 --- a/cmd/rollouts-controller/main.go +++ b/cmd/rollouts-controller/main.go @@ -6,6 +6,9 @@ import ( "strings" "time" + "github.com/argoproj/argo-rollouts/utils/plugin" + + "github.com/argoproj/pkg/kubeclientmetrics" smiclientset "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -20,8 +23,6 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" "k8s.io/client-go/tools/clientcmd" - "github.com/argoproj/pkg/kubeclientmetrics" - "github.com/argoproj/argo-rollouts/controller" "github.com/argoproj/argo-rollouts/controller/metrics" jobprovider "github.com/argoproj/argo-rollouts/metricproviders/job" @@ -70,6 +71,8 @@ func newCommand() *cobra.Command { awsVerifyTargetGroup bool namespaced bool printVersion bool + metricPluginLocation string + metricPluginSha256 string ) electOpts := controller.NewLeaderElectionOptions() var command = cobra.Command{ @@ -199,6 +202,12 @@ func newCommand() *cobra.Command { controllerNamespaceInformerFactory, jobInformerFactory) + defaults.SetMetricPluginLocation(metricPluginLocation) + err = plugin.InitMetricsPlugin(metricPluginLocation, plugin.FileDownloaderImpl{}, metricPluginSha256) + if err != nil { + log.Fatalf("Failed to init metric plugin: %v", err) + } + if err = cm.Run(ctx, rolloutThreads, serviceThreads, ingressThreads, experimentThreads, analysisThreads, electOpts); err != nil { log.Fatalf("Error running controller: %s", err.Error()) } @@ -240,6 +249,8 @@ func newCommand() *cobra.Command { command.Flags().DurationVar(&electOpts.LeaderElectionLeaseDuration, "leader-election-lease-duration", controller.DefaultLeaderElectionLeaseDuration, "The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled.") command.Flags().DurationVar(&electOpts.LeaderElectionRenewDeadline, "leader-election-renew-deadline", controller.DefaultLeaderElectionRenewDeadline, "The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled.") command.Flags().DurationVar(&electOpts.LeaderElectionRetryPeriod, "leader-election-retry-period", controller.DefaultLeaderElectionRetryPeriod, "The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled.") + command.Flags().StringVar(&metricPluginLocation, "metric-plugin-location", defaults.DefaultMetricsPluginLocation, "The file path to the location of the metric plugin binary") + command.Flags().StringVar(&metricPluginSha256, "metric-plugin-sha256", "", "The expected sha256 of the metric plugin binary") return &command } diff --git a/cmd/sample-metrics-plugin/internal/plugin/plugin.go b/cmd/sample-metrics-plugin/internal/plugin/plugin.go new file mode 100644 index 0000000000..78127c7cb1 --- /dev/null +++ b/cmd/sample-metrics-plugin/internal/plugin/plugin.go @@ -0,0 +1,183 @@ +package plugin + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/url" + "os" + "time" + + "github.com/argoproj/argo-rollouts/metricproviders/plugin" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/evaluate" + metricutil "github.com/argoproj/argo-rollouts/utils/metric" + timeutil "github.com/argoproj/argo-rollouts/utils/time" + "github.com/prometheus/client_golang/api" + v1 "github.com/prometheus/client_golang/api/prometheus/v1" + "github.com/prometheus/common/model" + log "github.com/sirupsen/logrus" +) + +const EnvVarArgoRolloutsPrometheusAddress string = "ARGO_ROLLOUTS_PROMETHEUS_ADDRESS" + +// Here is a real implementation of MetricsPlugin +type RpcPlugin struct { + LogCtx log.Entry + api v1.API +} + +type Config struct { + // Address is the HTTP address and port of the prometheus server + Address string `json:"address,omitempty" protobuf:"bytes,1,opt,name=address"` + // Query is a raw prometheus query to perform + Query string `json:"query,omitempty" protobuf:"bytes,2,opt,name=query"` +} + +func (g *RpcPlugin) NewMetricsPlugin(metric v1alpha1.Metric) error { + config := Config{} + err := json.Unmarshal(metric.Provider.Plugin.Config, &config) + if err != nil { + return err + } + + api, err := newPrometheusAPI(config.Address) + g.api = api + + return err +} + +func (g *RpcPlugin) Run(anaysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric) v1alpha1.Measurement { + startTime := timeutil.MetaNow() + newMeasurement := v1alpha1.Measurement{ + StartedAt: &startTime, + } + + config := Config{} + json.Unmarshal(metric.Provider.Plugin.Config, &config) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + response, warnings, err := g.api.Query(ctx, config.Query, time.Now()) + if err != nil { + return metricutil.MarkMeasurementError(newMeasurement, err) + } + + newValue, newStatus, err := g.processResponse(metric, response) + if err != nil { + return metricutil.MarkMeasurementError(newMeasurement, err) + + } + newMeasurement.Value = newValue + if len(warnings) > 0 { + warningMetadata := "" + for _, warning := range warnings { + warningMetadata = fmt.Sprintf(`%s"%s", `, warningMetadata, warning) + } + warningMetadata = warningMetadata[:len(warningMetadata)-2] + if warningMetadata != "" { + newMeasurement.Metadata = map[string]string{"warnings": warningMetadata} + g.LogCtx.Warnf("Prometheus returned the following warnings: %s", warningMetadata) + } + } + + newMeasurement.Phase = newStatus + finishedTime := timeutil.MetaNow() + newMeasurement.FinishedAt = &finishedTime + return newMeasurement +} + +func (g *RpcPlugin) Resume(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, measurement v1alpha1.Measurement) v1alpha1.Measurement { + return measurement +} + +func (g *RpcPlugin) Terminate(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, measurement v1alpha1.Measurement) v1alpha1.Measurement { + return measurement +} + +func (g *RpcPlugin) GarbageCollect(*v1alpha1.AnalysisRun, v1alpha1.Metric, int) error { + return nil +} + +func (g *RpcPlugin) Type() string { + return plugin.ProviderType +} + +func (g *RpcPlugin) GetMetadata(metric v1alpha1.Metric) map[string]string { + metricsMetadata := make(map[string]string) + + config := Config{} + json.Unmarshal(metric.Provider.Plugin.Config, &config) + if config.Query != "" { + metricsMetadata["ResolvedPrometheusQuery"] = config.Query + } + return metricsMetadata +} + +func (g *RpcPlugin) processResponse(metric v1alpha1.Metric, response model.Value) (string, v1alpha1.AnalysisPhase, error) { + switch value := response.(type) { + case *model.Scalar: + valueStr := value.Value.String() + result := float64(value.Value) + newStatus, err := evaluate.EvaluateResult(result, metric, g.LogCtx) + return valueStr, newStatus, err + case model.Vector: + results := make([]float64, 0, len(value)) + valueStr := "[" + for _, s := range value { + if s != nil { + valueStr = valueStr + s.Value.String() + "," + results = append(results, float64(s.Value)) + } + } + // if we appended to the string, we should remove the last comma on the string + if len(valueStr) > 1 { + valueStr = valueStr[:len(valueStr)-1] + } + valueStr = valueStr + "]" + newStatus, err := evaluate.EvaluateResult(results, metric, g.LogCtx) + return valueStr, newStatus, err + default: + return "", v1alpha1.AnalysisPhaseError, fmt.Errorf("Prometheus metric type not supported") + } +} + +func newPrometheusAPI(address string) (v1.API, error) { + envValuesByKey := make(map[string]string) + if value, ok := os.LookupEnv(fmt.Sprintf("%s", EnvVarArgoRolloutsPrometheusAddress)); ok { + envValuesByKey[EnvVarArgoRolloutsPrometheusAddress] = value + log.Debugf("ARGO_ROLLOUTS_PROMETHEUS_ADDRESS: %v", envValuesByKey[EnvVarArgoRolloutsPrometheusAddress]) + } + if len(address) != 0 { + if !isUrl(address) { + return nil, errors.New("prometheus address is not is url format") + } + } else if envValuesByKey[EnvVarArgoRolloutsPrometheusAddress] != "" { + if isUrl(envValuesByKey[EnvVarArgoRolloutsPrometheusAddress]) { + address = envValuesByKey[EnvVarArgoRolloutsPrometheusAddress] + } else { + return nil, errors.New("prometheus address is not is url format") + } + } else { + return nil, errors.New("prometheus address is not configured") + } + client, err := api.NewClient(api.Config{ + Address: address, + }) + if err != nil { + log.Errorf("Error in getting prometheus client: %v", err) + return nil, err + } + return v1.NewAPI(client), nil +} + +func isUrl(str string) bool { + u, err := url.Parse(str) + if err != nil { + log.Errorf("Error in parsing url: %v", err) + } + log.Debugf("Parsed url: %v", u) + return err == nil && u.Scheme != "" && u.Host != "" +} diff --git a/cmd/sample-metrics-plugin/internal/plugin/plugin_test.go b/cmd/sample-metrics-plugin/internal/plugin/plugin_test.go new file mode 100644 index 0000000000..12d8bf3f78 --- /dev/null +++ b/cmd/sample-metrics-plugin/internal/plugin/plugin_test.go @@ -0,0 +1,107 @@ +package plugin + +import ( + "context" + "encoding/json" + "testing" + "time" + + rolloutsPlugin "github.com/argoproj/argo-rollouts/metricproviders/plugin" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + log "github.com/sirupsen/logrus" + + goPlugin "github.com/hashicorp/go-plugin" +) + +var testHandshake = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "metrics", +} + +// This is just an example of how to test a plugin. +func TestRunSuccessfully(t *testing.T) { + //Skip test because this is just an example of how to test a plugin. + t.Skip("Skipping test because it requires a running prometheus server") + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logCtx := *log.WithFields(log.Fields{"plugin-test": "prometheus"}) + + rpcPluginImp := &RpcPlugin{ + LogCtx: logCtx, + } + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcMetricsPlugin": &rolloutsPlugin.RpcMetricsPlugin{Impl: rpcPluginImp}, + } + + ch := make(chan *goPlugin.ReattachConfig, 1) + closeCh := make(chan struct{}) + go goPlugin.Serve(&goPlugin.ServeConfig{ + HandshakeConfig: testHandshake, + Plugins: pluginMap, + Test: &goPlugin.ServeTestConfig{ + Context: ctx, + ReattachConfigCh: ch, + CloseCh: closeCh, + }, + }) + + // We should get a config + var config *goPlugin.ReattachConfig + select { + case config = <-ch: + case <-time.After(2000 * time.Millisecond): + t.Fatal("should've received reattach") + } + if config == nil { + t.Fatal("config should not be nil") + } + + // Connect! + c := goPlugin.NewClient(&goPlugin.ClientConfig{ + Cmd: nil, + HandshakeConfig: testHandshake, + Plugins: pluginMap, + Reattach: config, + }) + client, err := c.Client() + if err != nil { + t.Fatalf("err: %s", err) + } + + // Pinging should work + if err := client.Ping(); err != nil { + t.Fatalf("should not err: %s", err) + } + + // Kill which should do nothing + c.Kill() + if err := client.Ping(); err != nil { + t.Fatalf("should not err: %s", err) + } + + // Request the plugin + raw, err := client.Dispense("RpcMetricsPlugin") + if err != nil { + t.Fail() + } + + plugin := raw.(rolloutsPlugin.MetricsPlugin) + + err = plugin.NewMetricsPlugin(v1alpha1.Metric{ + Provider: v1alpha1.MetricProvider{ + Plugin: &v1alpha1.PluginMetric{Config: json.RawMessage(`{"address":"http://prometheus.local", "query":"machine_cpu_cores"}`)}, + }, + }) + if err != nil { + t.Fail() + } + + // Canceling should cause an exit + cancel() + <-closeCh +} diff --git a/cmd/sample-metrics-plugin/main.go b/cmd/sample-metrics-plugin/main.go new file mode 100644 index 0000000000..3f0b082de5 --- /dev/null +++ b/cmd/sample-metrics-plugin/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "github.com/argoproj/argo-rollouts/cmd/sample-metrics-plugin/internal/plugin" + rolloutsPlugin "github.com/argoproj/argo-rollouts/metricproviders/plugin" + goPlugin "github.com/hashicorp/go-plugin" + log "github.com/sirupsen/logrus" +) + +// handshakeConfigs are used to just do a basic handshake between +// a plugin and host. If the handshake fails, a user friendly error is shown. +// This prevents users from executing bad plugins or executing a plugin +// directory. It is a UX feature, not a security feature. +var handshakeConfig = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "metrics", +} + +func main() { + logCtx := *log.WithFields(log.Fields{"plugin": "prometheus"}) + + rpcPluginImp := &plugin.RpcPlugin{ + LogCtx: logCtx, + } + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcMetricsPlugin": &rolloutsPlugin.RpcMetricsPlugin{Impl: rpcPluginImp}, + } + + logCtx.Debug("message from plugin", "foo", "bar") + + goPlugin.Serve(&goPlugin.ServeConfig{ + HandshakeConfig: handshakeConfig, + Plugins: pluginMap, + }) +} diff --git a/controller/controller.go b/controller/controller.go index 55ef4a45f8..058cff4906 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -9,6 +9,8 @@ import ( "sync" "time" + goPlugin "github.com/hashicorp/go-plugin" + "k8s.io/apimachinery/pkg/util/wait" istioutil "github.com/argoproj/argo-rollouts/utils/istio" @@ -423,6 +425,7 @@ func (c *Manager) Run(ctx context.Context, rolloutThreadiness, serviceThreadines }) } log.Info("Shutting down workers") + goPlugin.CleanupClients() c.serviceWorkqueue.ShutDownWithDrain() c.ingressWorkqueue.ShutDownWithDrain() diff --git a/docs/analysis/plugins.md b/docs/analysis/plugins.md new file mode 100644 index 0000000000..1d65bc8887 --- /dev/null +++ b/docs/analysis/plugins.md @@ -0,0 +1,62 @@ +# Metric Plugins + +!!! important Available since v1.5 + +Argo Rollouts supports getting analysis metrics via 3rd party plugin system. This allows users to extend the capabilities of Rollouts +to support metrics that are not natively supported by Rollouts. Rollouts uses a plugin library called +[go-plugin](https://github.com/hashicorp/go-plugin) to do this. You can find a sample plugin +here: [sample-rollouts-metric-plugin](https://github.com/argoproj-labs/sample-rollouts-metric-plugin) + +## Using a Metric Plugin + +There are two methods to installing and using an argo rollouts plugin. The first method is to mount up the plugin executable +into the rollouts controller container. The second method is to use a HTTP(S) server to host the plugin executable. + +### Mounting the plugin executable into the rollouts controller container + +To use this method, you will need to build or download the plugin executable and then mount it into the rollouts controller container. +The plugin executable must be mounted into the rollouts controller container at the path specified by the `--metric-plugin-location` flag. + +There are a few ways to mount the plugin executable into the rollouts controller container. Some of these will depend on your +particular infrastructure. Here are a few methods: + +* Using an init container to download the plugin executable +* Using a Kubernetes volume mount with a shared volume such as NFS, EBS, etc. +* Building the plugin into the rollouts controller container + +### Using a HTTP(S) server to host the plugin executable + +Argo Rollouts supports downloading the plugin executable from a HTTP(S) server. To use this method, you will need to specify the +`--metric-plugin-location` flag to point to the HTTP(S) server that hosts the plugin executable. Example: + +```bash +./rollouts-controller --metric-plugin-location=https://example.com/metric-plugin +``` + +You can also specify a sha256 checksum of the plugin executable. This is useful for ensuring the plugin executable has not been tampered with. +To use this feature, you will need to specify the `--metric-plugin-sha256` flag. Example: + +```bash +./rollouts-controller --metric-plugin-location=https://example.com/metric-plugin --metric-plugin-sha256=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef +``` + +## Some words of caution + +Depending on which method you use to install and the plugin, there are some things to be aware of. +The rollouts controller will not start if it can not download or find the plugin executable. This means that if you are using +a method of installation that requires a download of the plugin and the server hosting the plugin for some reason is not available and the rollouts +controllers pod got deleted while the server was down or is coming up for the first time, it will not be able to start until +the server hosting the plugin is available again. + +Argo Rollouts will download the plugin at startup only once but if the pod is deleted it will need to download the plugin again on next startup. Running +Argo Rollouts in HA mode can help a little with this situation because each pod will download the plugin at startup. So if a single pod gets +deleted during a server outage, the other pods will still be able to take over because there will already be a plugin executable available to it. However, +it is up to you to define your risk for and decide how you want to install the plugin executable. + +## List of Available Plugins (alphabetical order) + +#### Add Your Plugin Here + * If you have created a plugin, please submit a PR to add it to this list. +#### [sample-rollouts-metric-plugin](https://github.com/argoproj-labs/sample-rollouts-metric-plugin) + * This is just a sample plugin that can be used as a starting point for creating your own plugin. +It is not meant to be used in production. It is based on the built-in prometheus provider. diff --git a/docs/features/kustomize/rollout_cr_schema.json b/docs/features/kustomize/rollout_cr_schema.json index fbff809be6..8751fe00a9 100644 --- a/docs/features/kustomize/rollout_cr_schema.json +++ b/docs/features/kustomize/rollout_cr_schema.json @@ -4165,6 +4165,14 @@ ], "type": "object" }, + "plugin": { + "properties": { + "config": { + "x-kubernetes-preserve-unknown-fields": true + } + }, + "type": "object" + }, "prometheus": { "properties": { "address": { @@ -8433,6 +8441,14 @@ ], "type": "object" }, + "plugin": { + "properties": { + "config": { + "x-kubernetes-preserve-unknown-fields": true + } + }, + "type": "object" + }, "prometheus": { "properties": { "address": { @@ -12701,6 +12717,14 @@ ], "type": "object" }, + "plugin": { + "properties": { + "config": { + "x-kubernetes-preserve-unknown-fields": true + } + }, + "type": "object" + }, "prometheus": { "properties": { "address": { diff --git a/go.mod b/go.mod index fecb2d5f4d..bcff977f84 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/hashicorp/go-plugin v1.4.8 github.com/influxdata/influxdb-client-go/v2 v2.12.1 github.com/juju/ansiterm v1.0.0 github.com/mitchellh/mapstructure v1.5.0 @@ -90,6 +91,7 @@ require ( github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/color v1.7.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.2.3 // indirect @@ -112,7 +114,9 @@ require ( github.com/gregdel/pushover v1.1.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-hclog v0.14.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect @@ -127,6 +131,7 @@ require ( github.com/mattn/go-isatty v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.2.0 // indirect @@ -135,6 +140,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oklog/run v1.0.0 // indirect github.com/onsi/ginkgo v1.16.4 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.13 // indirect diff --git a/go.sum b/go.sum index 902c3e9107..e0a29d6733 100644 --- a/go.sum +++ b/go.sum @@ -291,6 +291,7 @@ github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htX github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= @@ -520,11 +521,14 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-retryablehttp v0.5.1/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= @@ -541,6 +545,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/heketi/heketi v10.3.0+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= @@ -562,6 +568,7 @@ github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf/go.mod h1 github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8= github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -648,12 +655,14 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.10/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -675,6 +684,7 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -723,6 +733,8 @@ github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rR github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= @@ -1165,6 +1177,7 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/manifests/crds/analysis-run-crd.yaml b/manifests/crds/analysis-run-crd.yaml index da21888bde..cc2da51d06 100644 --- a/manifests/crds/analysis-run-crd.yaml +++ b/manifests/crds/analysis-run-crd.yaml @@ -2700,6 +2700,11 @@ spec: required: - query type: object + plugin: + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object prometheus: properties: address: diff --git a/manifests/crds/analysis-template-crd.yaml b/manifests/crds/analysis-template-crd.yaml index 1e37db2dd0..784e088dad 100644 --- a/manifests/crds/analysis-template-crd.yaml +++ b/manifests/crds/analysis-template-crd.yaml @@ -2696,6 +2696,11 @@ spec: required: - query type: object + plugin: + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object prometheus: properties: address: diff --git a/manifests/crds/cluster-analysis-template-crd.yaml b/manifests/crds/cluster-analysis-template-crd.yaml index fb149f2fa3..d309aa0169 100644 --- a/manifests/crds/cluster-analysis-template-crd.yaml +++ b/manifests/crds/cluster-analysis-template-crd.yaml @@ -2696,6 +2696,11 @@ spec: required: - query type: object + plugin: + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object prometheus: properties: address: diff --git a/manifests/install.yaml b/manifests/install.yaml index c90546d8b7..11130bd027 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -2701,6 +2701,11 @@ spec: required: - query type: object + plugin: + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object prometheus: properties: address: @@ -5578,6 +5583,11 @@ spec: required: - query type: object + plugin: + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object prometheus: properties: address: @@ -8341,6 +8351,11 @@ spec: required: - query type: object + plugin: + properties: + config: + x-kubernetes-preserve-unknown-fields: true + type: object prometheus: properties: address: diff --git a/metric/provider.go b/metric/provider.go new file mode 100644 index 0000000000..aba5ddbd0c --- /dev/null +++ b/metric/provider.go @@ -0,0 +1,21 @@ +package metric + +import "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + +// Provider methods to query an external systems and generate a measurement +type Provider interface { + // Run start a new external system call for a measurement + // Should be idempotent and do nothing if a call has already been started + Run(*v1alpha1.AnalysisRun, v1alpha1.Metric) v1alpha1.Measurement + // Checks if the external system call is finished and returns the current measurement + Resume(*v1alpha1.AnalysisRun, v1alpha1.Metric, v1alpha1.Measurement) v1alpha1.Measurement + // Terminate will terminate an in-progress measurement + Terminate(*v1alpha1.AnalysisRun, v1alpha1.Metric, v1alpha1.Measurement) v1alpha1.Measurement + // GarbageCollect is used to garbage collect completed measurements to the specified limit + GarbageCollect(*v1alpha1.AnalysisRun, v1alpha1.Metric, int) error + // Type gets the provider type + Type() string + // GetMetadata returns any additional metadata which providers need to store/display as part + // of the metric result. For example, Prometheus uses is to store the final resolved queries. + GetMetadata(metric v1alpha1.Metric) map[string]string +} diff --git a/metricproviders/metricproviders.go b/metricproviders/metricproviders.go index d8a1637acf..799bd9eb88 100644 --- a/metricproviders/metricproviders.go +++ b/metricproviders/metricproviders.go @@ -2,8 +2,13 @@ package metricproviders import ( "fmt" + "os/exec" + "github.com/argoproj/argo-rollouts/metric" "github.com/argoproj/argo-rollouts/metricproviders/influxdb" + "github.com/argoproj/argo-rollouts/metricproviders/plugin" + "github.com/argoproj/argo-rollouts/utils/defaults" + goPlugin "github.com/hashicorp/go-plugin" "github.com/argoproj/argo-rollouts/metricproviders/cloudwatch" "github.com/argoproj/argo-rollouts/metricproviders/datadog" @@ -23,27 +28,16 @@ import ( "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" ) -// Provider methods to query a external systems and generate a measurement +// Provider this is here just for backwards compatibility the interface is now in the metric package type Provider interface { - // Run start a new external system call for a measurement - // Should be idempotent and do nothing if a call has already been started - Run(*v1alpha1.AnalysisRun, v1alpha1.Metric) v1alpha1.Measurement - // Checks if the external system call is finished and returns the current measurement - Resume(*v1alpha1.AnalysisRun, v1alpha1.Metric, v1alpha1.Measurement) v1alpha1.Measurement - // Terminate will terminate an in-progress measurement - Terminate(*v1alpha1.AnalysisRun, v1alpha1.Metric, v1alpha1.Measurement) v1alpha1.Measurement - // GarbageCollect is used to garbage collect completed measurements to the specified limit - GarbageCollect(*v1alpha1.AnalysisRun, v1alpha1.Metric, int) error - // Type gets the provider type - Type() string - // GetMetadata returns any additional metadata which providers need to store/display as part - // of the metric result. For example, Prometheus uses is to store the final resolved queries. - GetMetadata(metric v1alpha1.Metric) map[string]string + metric.Provider } type ProviderFactory struct { - KubeClient kubernetes.Interface - JobLister batchlisters.JobLister + KubeClient kubernetes.Interface + JobLister batchlisters.JobLister + pluginClient *goPlugin.Client + plugin plugin.MetricsPlugin } type ProviderFactoryFunc func(logCtx log.Entry, metric v1alpha1.Metric) (Provider, error) @@ -101,6 +95,9 @@ func (f *ProviderFactory) NewProvider(logCtx log.Entry, metric v1alpha1.Metric) return nil, err } return influxdb.NewInfluxdbProvider(client, logCtx), nil + case plugin.ProviderType: + _, plugin, err := f.startPluginSystem(metric) + return plugin, err default: return nil, fmt.Errorf("no valid provider in metric '%s'", metric.Name) } @@ -127,7 +124,56 @@ func Type(metric v1alpha1.Metric) string { return graphite.ProviderType } else if metric.Provider.Influxdb != nil { return influxdb.ProviderType + } else if metric.Provider.Plugin != nil { + return plugin.ProviderType } return "Unknown Provider" } + +func (f *ProviderFactory) startPluginSystem(metric v1alpha1.Metric) (*goPlugin.Client, plugin.MetricsPlugin, error) { + if defaults.GetMetricPluginLocation() == "" { + return nil, nil, fmt.Errorf("no plugin location specified") + } + + var handshakeConfig = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "metrics", + } + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcMetricsPlugin": &plugin.RpcMetricsPlugin{}, + } + + if f.pluginClient == nil || f.pluginClient.Exited() { + f.pluginClient = goPlugin.NewClient(&goPlugin.ClientConfig{ + HandshakeConfig: handshakeConfig, + Plugins: pluginMap, + VersionedPlugins: nil, + Cmd: exec.Command(defaults.GetMetricPluginLocation()), + Managed: true, + }) + + rpcClient, err := f.pluginClient.Client() + if err != nil { + return nil, nil, err + } + + // Request the plugin + raw, err := rpcClient.Dispense("RpcMetricsPlugin") + if err != nil { + return nil, nil, err + } + + f.plugin = raw.(plugin.MetricsPlugin) + + err = f.plugin.NewMetricsPlugin(metric) + if err != nil { + return nil, nil, err + } + } + + return f.pluginClient, f.plugin, nil +} diff --git a/metricproviders/plugin/plugin.go b/metricproviders/plugin/plugin.go new file mode 100644 index 0000000000..6cb929514e --- /dev/null +++ b/metricproviders/plugin/plugin.go @@ -0,0 +1,232 @@ +package plugin + +import ( + "encoding/gob" + "fmt" + "net/rpc" + + "github.com/argoproj/argo-rollouts/metric" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + metricutil "github.com/argoproj/argo-rollouts/utils/metric" + "github.com/hashicorp/go-plugin" + log "github.com/sirupsen/logrus" +) + +const ProviderType = "RPCPlugin" + +type RunArgs struct { + AnalysisRun *v1alpha1.AnalysisRun + Metric v1alpha1.Metric +} + +type TerminateAndResumeArgs struct { + AnalysisRun *v1alpha1.AnalysisRun + Metric v1alpha1.Metric + Measurement v1alpha1.Measurement +} + +type GarbageCollectArgs struct { + AnalysisRun *v1alpha1.AnalysisRun + Metric v1alpha1.Metric + Limit int +} + +type InitMetricsPluginAndGetMetadataArgs struct { + Metric v1alpha1.Metric +} + +func init() { + gob.RegisterName("RunArgs", new(RunArgs)) + gob.RegisterName("TerminateAndResumeArgs", new(TerminateAndResumeArgs)) + gob.RegisterName("GarbageCollectArgs", new(GarbageCollectArgs)) + gob.RegisterName("InitMetricsPluginAndGetMetadataArgs", new(InitMetricsPluginAndGetMetadataArgs)) +} + +// MetricsPlugin is the interface that we're exposing as a plugin. It needs to match metricproviders.Providers but we can +// not import that package because it would create a circular dependency. +type MetricsPlugin interface { + NewMetricsPlugin(metric v1alpha1.Metric) error + metric.Provider +} + +// MetricsPluginRPC Here is an implementation that talks over RPC +type MetricsPluginRPC struct{ client *rpc.Client } + +func (g *MetricsPluginRPC) NewMetricsPlugin(metric v1alpha1.Metric) error { + var resp error + var args interface{} = InitMetricsPluginAndGetMetadataArgs{ + Metric: metric, + } + err := g.client.Call("Plugin.NewMetricsPlugin", &args, &resp) + if err != nil { + return err + } + return resp +} + +func (g *MetricsPluginRPC) Run(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric) v1alpha1.Measurement { + var resp v1alpha1.Measurement + var args interface{} = RunArgs{ + AnalysisRun: analysisRun, + Metric: metric, + } + err := g.client.Call("Plugin.Run", &args, &resp) + if err != nil { + return metricutil.MarkMeasurementError(resp, err) + } + return resp +} + +func (g *MetricsPluginRPC) Resume(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, measurement v1alpha1.Measurement) v1alpha1.Measurement { + var resp v1alpha1.Measurement + var args interface{} = TerminateAndResumeArgs{ + AnalysisRun: analysisRun, + Metric: metric, + Measurement: measurement, + } + err := g.client.Call("Plugin.Resume", &args, &resp) + if err != nil { + return metricutil.MarkMeasurementError(resp, err) + } + return resp +} + +func (g *MetricsPluginRPC) Terminate(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, measurement v1alpha1.Measurement) v1alpha1.Measurement { + var resp v1alpha1.Measurement + var args interface{} = TerminateAndResumeArgs{ + AnalysisRun: analysisRun, + Metric: metric, + Measurement: measurement, + } + err := g.client.Call("Plugin.Terminate", &args, &resp) + if err != nil { + return metricutil.MarkMeasurementError(resp, err) + } + return resp +} + +func (g *MetricsPluginRPC) GarbageCollect(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, limit int) error { + var resp error + var args interface{} = GarbageCollectArgs{ + AnalysisRun: analysisRun, + Metric: metric, + Limit: limit, + } + err := g.client.Call("Plugin.GarbageCollect", &args, &resp) + if err != nil { + return err + } + return resp +} + +func (g *MetricsPluginRPC) Type() string { + var resp string + err := g.client.Call("Plugin.Type", new(interface{}), &resp) + if err != nil { + return err.Error() + } + + return resp +} + +func (g *MetricsPluginRPC) GetMetadata(metric v1alpha1.Metric) map[string]string { + var resp map[string]string + var args interface{} = InitMetricsPluginAndGetMetadataArgs{ + Metric: metric, + } + err := g.client.Call("Plugin.GetMetadata", &args, &resp) + if err != nil { + log.Errorf("Error calling GetMetadata: %v", err) + return map[string]string{"error": err.Error()} + } + return resp +} + +// MetricsRPCServer Here is the RPC server that MetricsPluginRPC talks to, conforming to +// the requirements of net/rpc +type MetricsRPCServer struct { + // This is the real implementation + Impl MetricsPlugin +} + +func (s *MetricsRPCServer) NewMetricsPlugin(args interface{}, resp *error) error { + initArgs, ok := args.(*InitMetricsPluginAndGetMetadataArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + *resp = s.Impl.NewMetricsPlugin(initArgs.Metric) + return nil +} + +func (s *MetricsRPCServer) Run(args interface{}, resp *v1alpha1.Measurement) error { + runArgs, ok := args.(*RunArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + *resp = s.Impl.Run(runArgs.AnalysisRun, runArgs.Metric) + return nil +} + +func (s *MetricsRPCServer) Resume(args interface{}, resp *v1alpha1.Measurement) error { + resumeArgs, ok := args.(*TerminateAndResumeArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + *resp = s.Impl.Resume(resumeArgs.AnalysisRun, resumeArgs.Metric, resumeArgs.Measurement) + return nil +} + +func (s *MetricsRPCServer) Terminate(args interface{}, resp *v1alpha1.Measurement) error { + resumeArgs, ok := args.(*TerminateAndResumeArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + *resp = s.Impl.Terminate(resumeArgs.AnalysisRun, resumeArgs.Metric, resumeArgs.Measurement) + return nil +} + +func (s *MetricsRPCServer) GarbageCollect(args interface{}, resp *error) error { + gcArgs, ok := args.(*GarbageCollectArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + *resp = s.Impl.GarbageCollect(gcArgs.AnalysisRun, gcArgs.Metric, gcArgs.Limit) + return nil +} + +func (s *MetricsRPCServer) Type(args interface{}, resp *string) error { + *resp = s.Impl.Type() + return nil +} + +func (s *MetricsRPCServer) GetMetadata(args interface{}, resp *map[string]string) error { + getMetadataArgs, ok := args.(*InitMetricsPluginAndGetMetadataArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + *resp = s.Impl.GetMetadata(getMetadataArgs.Metric) + return nil +} + +// RpcMetricsPlugin This is the implementation of plugin.Plugin so we can serve/consume +// +// This has two methods: Server must return an RPC server for this plugin +// type. We construct a MetricsRPCServer for this. +// +// Client must return an implementation of our interface that communicates +// over an RPC client. We return MetricsPluginRPC for this. +// +// Ignore MuxBroker. That is used to create more multiplexed streams on our +// plugin connection and is a more advanced use case. +type RpcMetricsPlugin struct { + // Impl Injection + Impl MetricsPlugin +} + +func (p *RpcMetricsPlugin) Server(*plugin.MuxBroker) (interface{}, error) { + return &MetricsRPCServer{Impl: p.Impl}, nil +} + +func (RpcMetricsPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { + return &MetricsPluginRPC{client: c}, nil +} diff --git a/metricproviders/plugin/plugin_test.go b/metricproviders/plugin/plugin_test.go new file mode 100644 index 0000000000..985c93832f --- /dev/null +++ b/metricproviders/plugin/plugin_test.go @@ -0,0 +1,162 @@ +package plugin + +import ( + "context" + "encoding/json" + "testing" + "time" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + goPlugin "github.com/hashicorp/go-plugin" + "github.com/tj/assert" +) + +var testHandshake = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "metrics", +} + +func pluginClient(t *testing.T) (MetricsPlugin, goPlugin.ClientProtocol, func(), chan struct{}) { + ctx, cancel := context.WithCancel(context.Background()) + + rpcPluginImp := &testRpcPlugin{} + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcMetricsPlugin": &RpcMetricsPlugin{Impl: rpcPluginImp}, + } + + ch := make(chan *goPlugin.ReattachConfig, 1) + closeCh := make(chan struct{}) + go goPlugin.Serve(&goPlugin.ServeConfig{ + HandshakeConfig: testHandshake, + Plugins: pluginMap, + Test: &goPlugin.ServeTestConfig{ + Context: ctx, + ReattachConfigCh: ch, + CloseCh: closeCh, + }, + }) + + // We should get a config + var config *goPlugin.ReattachConfig + select { + case config = <-ch: + case <-time.After(2000 * time.Millisecond): + t.Fatal("should've received reattach") + } + if config == nil { + t.Fatal("config should not be nil") + } + + // Connect! + c := goPlugin.NewClient(&goPlugin.ClientConfig{ + Cmd: nil, + HandshakeConfig: testHandshake, + Plugins: pluginMap, + Reattach: config, + }) + client, err := c.Client() + if err != nil { + t.Fatalf("err: %s", err) + } + + // Request the plugin + raw, err := client.Dispense("RpcMetricsPlugin") + if err != nil { + t.Fail() + } + + plugin, ok := raw.(MetricsPlugin) + if !ok { + t.Fail() + } + + return plugin, client, cancel, closeCh +} + +func TestPlugin(t *testing.T) { + plugin, _, cancel, closeCh := pluginClient(t) + defer cancel() + + err := plugin.NewMetricsPlugin(v1alpha1.Metric{ + Provider: v1alpha1.MetricProvider{ + Plugin: &v1alpha1.PluginMetric{Config: json.RawMessage(`{"address":"http://prometheus.local", "query":"machine_cpu_cores"}`)}, + }, + }) + if err != nil { + t.Fail() + } + + runMeasurement := plugin.Run(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}) + assert.Equal(t, "TestCompleted", string(runMeasurement.Phase)) + + runMeasurementErr := plugin.Run(nil, v1alpha1.Metric{}) + assert.Equal(t, "Error", string(runMeasurementErr.Phase)) + assert.Equal(t, "analysisRun is nil", runMeasurementErr.Message) + + resumeMeasurement := plugin.Resume(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, v1alpha1.Measurement{ + Phase: "TestCompletedResume", + Message: "Check to see if we get same phase back", + }) + assert.Equal(t, "TestCompletedResume", string(resumeMeasurement.Phase)) + + terminateMeasurement := plugin.Terminate(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, v1alpha1.Measurement{ + Phase: "TestCompletedTerminate", + Message: "Check to see if we get same phase back", + }) + assert.Equal(t, "TestCompletedTerminate", string(terminateMeasurement.Phase)) + + gcError := plugin.GarbageCollect(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, 0) + assert.NoError(t, gcError) + + typeTest := plugin.Type() + assert.Equal(t, "TestRPCPlugin", typeTest) + + metadata := plugin.GetMetadata(v1alpha1.Metric{ + Name: "testMetric", + }) + assert.Equal(t, "testMetric", metadata["metricName"]) + + // Canceling should cause an exit + cancel() + <-closeCh +} + +func TestPluginClosedConnection(t *testing.T) { + plugin, client, cancel, closeCh := pluginClient(t) + defer cancel() + + client.Close() + time.Sleep(100 * time.Millisecond) + + const expectedError = "connection is shut down" + + newMetrics := plugin.NewMetricsPlugin(v1alpha1.Metric{}) + assert.Equal(t, expectedError, newMetrics.Error()) + + measurement := plugin.Terminate(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, v1alpha1.Measurement{}) + assert.Equal(t, expectedError, measurement.Message) + + measurement = plugin.Run(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}) + assert.Equal(t, expectedError, measurement.Message) + + measurement = plugin.Resume(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, v1alpha1.Measurement{}) + assert.Equal(t, expectedError, measurement.Message) + + measurement = plugin.Terminate(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, v1alpha1.Measurement{}) + assert.Equal(t, expectedError, measurement.Message) + + typeStr := plugin.Type() + assert.Equal(t, expectedError, typeStr) + + metadata := plugin.GetMetadata(v1alpha1.Metric{}) + assert.Equal(t, expectedError, metadata["error"]) + + gcError := plugin.GarbageCollect(&v1alpha1.AnalysisRun{}, v1alpha1.Metric{}, 0) + assert.Equal(t, expectedError, gcError.Error()) + + cancel() + <-closeCh +} diff --git a/metricproviders/plugin/plugin_test_implementation.go b/metricproviders/plugin/plugin_test_implementation.go new file mode 100644 index 0000000000..1ba5a2579e --- /dev/null +++ b/metricproviders/plugin/plugin_test_implementation.go @@ -0,0 +1,57 @@ +package plugin + +import ( + "fmt" + "time" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + metricutil "github.com/argoproj/argo-rollouts/utils/metric" + timeutil "github.com/argoproj/argo-rollouts/utils/time" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type testRpcPlugin struct{} + +func (g *testRpcPlugin) NewMetricsPlugin(metric v1alpha1.Metric) error { + return nil +} + +func (g *testRpcPlugin) Run(anaysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric) v1alpha1.Measurement { + startTime := timeutil.MetaNow() + finishTime := v1.Time{Time: startTime.Add(10 * time.Second)} + newMeasurement := v1alpha1.Measurement{ + Phase: "TestCompleted", + Message: "Test run completed", + StartedAt: &startTime, + FinishedAt: &finishTime, + Value: "", + Metadata: nil, + ResumeAt: nil, + } + if anaysisRun == nil { + return metricutil.MarkMeasurementError(newMeasurement, fmt.Errorf("analysisRun is nil")) + } + return newMeasurement +} + +func (g *testRpcPlugin) Resume(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, measurement v1alpha1.Measurement) v1alpha1.Measurement { + return measurement +} + +func (g *testRpcPlugin) Terminate(analysisRun *v1alpha1.AnalysisRun, metric v1alpha1.Metric, measurement v1alpha1.Measurement) v1alpha1.Measurement { + return measurement +} + +func (g *testRpcPlugin) GarbageCollect(*v1alpha1.AnalysisRun, v1alpha1.Metric, int) error { + return nil +} + +func (g *testRpcPlugin) Type() string { + return "TestRPCPlugin" +} + +func (g *testRpcPlugin) GetMetadata(metric v1alpha1.Metric) map[string]string { + metricsMetadata := make(map[string]string) + metricsMetadata["metricName"] = metric.Name + return metricsMetadata +} diff --git a/mkdocs.yml b/mkdocs.yml index 9e63a2f89e..8413ed001e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,6 +53,7 @@ nav: - Traefik: features/traffic-management/traefik.md - Analysis: - Overview: features/analysis.md + - Plugins: analysis/plugins.md - Prometheus: analysis/prometheus.md - DataDog: analysis/datadog.md - NewRelic: analysis/newrelic.md diff --git a/pkg/apis/rollouts/v1alpha1/analysis_types.go b/pkg/apis/rollouts/v1alpha1/analysis_types.go index f26fc91585..742c7bec61 100644 --- a/pkg/apis/rollouts/v1alpha1/analysis_types.go +++ b/pkg/apis/rollouts/v1alpha1/analysis_types.go @@ -173,6 +173,14 @@ type MetricProvider struct { Graphite *GraphiteMetric `json:"graphite,omitempty" protobuf:"bytes,9,opt,name=graphite"` // Influxdb specifies the influxdb metric to query Influxdb *InfluxdbMetric `json:"influxdb,omitempty" protobuf:"bytes,10,opt,name=influxdb"` + // Plugin specifies the hashicorp go-plugin metric to query + Plugin *PluginMetric `json:"plugin,omitempty" protobuf:"bytes,11,opt,name=plugin"` +} + +type PluginMetric struct { + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + Config json.RawMessage `json:"config,omitempty" protobuf:"bytes,1,rep,name=config"` } // AnalysisPhase is the overall phase of an AnalysisRun, MetricResult, or Measurement diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index 35baf606ba..aaea5c09a5 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -1868,10 +1868,38 @@ func (m *PingPongSpec) XXX_DiscardUnknown() { var xxx_messageInfo_PingPongSpec proto.InternalMessageInfo +func (m *PluginMetric) Reset() { *m = PluginMetric{} } +func (*PluginMetric) ProtoMessage() {} +func (*PluginMetric) Descriptor() ([]byte, []int) { + return fileDescriptor_e0e705f843545fab, []int{65} +} +func (m *PluginMetric) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PluginMetric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PluginMetric) XXX_Merge(src proto.Message) { + xxx_messageInfo_PluginMetric.Merge(m, src) +} +func (m *PluginMetric) XXX_Size() int { + return m.Size() +} +func (m *PluginMetric) XXX_DiscardUnknown() { + xxx_messageInfo_PluginMetric.DiscardUnknown(m) +} + +var xxx_messageInfo_PluginMetric proto.InternalMessageInfo + func (m *PodTemplateMetadata) Reset() { *m = PodTemplateMetadata{} } func (*PodTemplateMetadata) ProtoMessage() {} func (*PodTemplateMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{65} + return fileDescriptor_e0e705f843545fab, []int{66} } func (m *PodTemplateMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1901,7 +1929,7 @@ func (m *PreferredDuringSchedulingIgnoredDuringExecution) Reset() { } func (*PreferredDuringSchedulingIgnoredDuringExecution) ProtoMessage() {} func (*PreferredDuringSchedulingIgnoredDuringExecution) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{66} + return fileDescriptor_e0e705f843545fab, []int{67} } func (m *PreferredDuringSchedulingIgnoredDuringExecution) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1929,7 +1957,7 @@ var xxx_messageInfo_PreferredDuringSchedulingIgnoredDuringExecution proto.Intern func (m *PrometheusMetric) Reset() { *m = PrometheusMetric{} } func (*PrometheusMetric) ProtoMessage() {} func (*PrometheusMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{67} + return fileDescriptor_e0e705f843545fab, []int{68} } func (m *PrometheusMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1959,7 +1987,7 @@ func (m *RequiredDuringSchedulingIgnoredDuringExecution) Reset() { } func (*RequiredDuringSchedulingIgnoredDuringExecution) ProtoMessage() {} func (*RequiredDuringSchedulingIgnoredDuringExecution) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{68} + return fileDescriptor_e0e705f843545fab, []int{69} } func (m *RequiredDuringSchedulingIgnoredDuringExecution) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1987,7 +2015,7 @@ var xxx_messageInfo_RequiredDuringSchedulingIgnoredDuringExecution proto.Interna func (m *RollbackWindowSpec) Reset() { *m = RollbackWindowSpec{} } func (*RollbackWindowSpec) ProtoMessage() {} func (*RollbackWindowSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{69} + return fileDescriptor_e0e705f843545fab, []int{70} } func (m *RollbackWindowSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2015,7 +2043,7 @@ var xxx_messageInfo_RollbackWindowSpec proto.InternalMessageInfo func (m *Rollout) Reset() { *m = Rollout{} } func (*Rollout) ProtoMessage() {} func (*Rollout) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{70} + return fileDescriptor_e0e705f843545fab, []int{71} } func (m *Rollout) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2043,7 +2071,7 @@ var xxx_messageInfo_Rollout proto.InternalMessageInfo func (m *RolloutAnalysis) Reset() { *m = RolloutAnalysis{} } func (*RolloutAnalysis) ProtoMessage() {} func (*RolloutAnalysis) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{71} + return fileDescriptor_e0e705f843545fab, []int{72} } func (m *RolloutAnalysis) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2071,7 +2099,7 @@ var xxx_messageInfo_RolloutAnalysis proto.InternalMessageInfo func (m *RolloutAnalysisBackground) Reset() { *m = RolloutAnalysisBackground{} } func (*RolloutAnalysisBackground) ProtoMessage() {} func (*RolloutAnalysisBackground) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{72} + return fileDescriptor_e0e705f843545fab, []int{73} } func (m *RolloutAnalysisBackground) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2099,7 +2127,7 @@ var xxx_messageInfo_RolloutAnalysisBackground proto.InternalMessageInfo func (m *RolloutAnalysisRunStatus) Reset() { *m = RolloutAnalysisRunStatus{} } func (*RolloutAnalysisRunStatus) ProtoMessage() {} func (*RolloutAnalysisRunStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{73} + return fileDescriptor_e0e705f843545fab, []int{74} } func (m *RolloutAnalysisRunStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2127,7 +2155,7 @@ var xxx_messageInfo_RolloutAnalysisRunStatus proto.InternalMessageInfo func (m *RolloutAnalysisTemplate) Reset() { *m = RolloutAnalysisTemplate{} } func (*RolloutAnalysisTemplate) ProtoMessage() {} func (*RolloutAnalysisTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{74} + return fileDescriptor_e0e705f843545fab, []int{75} } func (m *RolloutAnalysisTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2155,7 +2183,7 @@ var xxx_messageInfo_RolloutAnalysisTemplate proto.InternalMessageInfo func (m *RolloutCondition) Reset() { *m = RolloutCondition{} } func (*RolloutCondition) ProtoMessage() {} func (*RolloutCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{75} + return fileDescriptor_e0e705f843545fab, []int{76} } func (m *RolloutCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2183,7 +2211,7 @@ var xxx_messageInfo_RolloutCondition proto.InternalMessageInfo func (m *RolloutExperimentStep) Reset() { *m = RolloutExperimentStep{} } func (*RolloutExperimentStep) ProtoMessage() {} func (*RolloutExperimentStep) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{76} + return fileDescriptor_e0e705f843545fab, []int{77} } func (m *RolloutExperimentStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2213,7 +2241,7 @@ func (m *RolloutExperimentStepAnalysisTemplateRef) Reset() { } func (*RolloutExperimentStepAnalysisTemplateRef) ProtoMessage() {} func (*RolloutExperimentStepAnalysisTemplateRef) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{77} + return fileDescriptor_e0e705f843545fab, []int{78} } func (m *RolloutExperimentStepAnalysisTemplateRef) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2241,7 +2269,7 @@ var xxx_messageInfo_RolloutExperimentStepAnalysisTemplateRef proto.InternalMessa func (m *RolloutExperimentTemplate) Reset() { *m = RolloutExperimentTemplate{} } func (*RolloutExperimentTemplate) ProtoMessage() {} func (*RolloutExperimentTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{78} + return fileDescriptor_e0e705f843545fab, []int{79} } func (m *RolloutExperimentTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2269,7 +2297,7 @@ var xxx_messageInfo_RolloutExperimentTemplate proto.InternalMessageInfo func (m *RolloutList) Reset() { *m = RolloutList{} } func (*RolloutList) ProtoMessage() {} func (*RolloutList) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{79} + return fileDescriptor_e0e705f843545fab, []int{80} } func (m *RolloutList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2297,7 +2325,7 @@ var xxx_messageInfo_RolloutList proto.InternalMessageInfo func (m *RolloutPause) Reset() { *m = RolloutPause{} } func (*RolloutPause) ProtoMessage() {} func (*RolloutPause) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{80} + return fileDescriptor_e0e705f843545fab, []int{81} } func (m *RolloutPause) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2325,7 +2353,7 @@ var xxx_messageInfo_RolloutPause proto.InternalMessageInfo func (m *RolloutSpec) Reset() { *m = RolloutSpec{} } func (*RolloutSpec) ProtoMessage() {} func (*RolloutSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{81} + return fileDescriptor_e0e705f843545fab, []int{82} } func (m *RolloutSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2353,7 +2381,7 @@ var xxx_messageInfo_RolloutSpec proto.InternalMessageInfo func (m *RolloutStatus) Reset() { *m = RolloutStatus{} } func (*RolloutStatus) ProtoMessage() {} func (*RolloutStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{82} + return fileDescriptor_e0e705f843545fab, []int{83} } func (m *RolloutStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2381,7 +2409,7 @@ var xxx_messageInfo_RolloutStatus proto.InternalMessageInfo func (m *RolloutStrategy) Reset() { *m = RolloutStrategy{} } func (*RolloutStrategy) ProtoMessage() {} func (*RolloutStrategy) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{83} + return fileDescriptor_e0e705f843545fab, []int{84} } func (m *RolloutStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2409,7 +2437,7 @@ var xxx_messageInfo_RolloutStrategy proto.InternalMessageInfo func (m *RolloutTrafficRouting) Reset() { *m = RolloutTrafficRouting{} } func (*RolloutTrafficRouting) ProtoMessage() {} func (*RolloutTrafficRouting) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{84} + return fileDescriptor_e0e705f843545fab, []int{85} } func (m *RolloutTrafficRouting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2437,7 +2465,7 @@ var xxx_messageInfo_RolloutTrafficRouting proto.InternalMessageInfo func (m *RouteMatch) Reset() { *m = RouteMatch{} } func (*RouteMatch) ProtoMessage() {} func (*RouteMatch) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{85} + return fileDescriptor_e0e705f843545fab, []int{86} } func (m *RouteMatch) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2465,7 +2493,7 @@ var xxx_messageInfo_RouteMatch proto.InternalMessageInfo func (m *RunSummary) Reset() { *m = RunSummary{} } func (*RunSummary) ProtoMessage() {} func (*RunSummary) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{86} + return fileDescriptor_e0e705f843545fab, []int{87} } func (m *RunSummary) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2493,7 +2521,7 @@ var xxx_messageInfo_RunSummary proto.InternalMessageInfo func (m *SMITrafficRouting) Reset() { *m = SMITrafficRouting{} } func (*SMITrafficRouting) ProtoMessage() {} func (*SMITrafficRouting) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{87} + return fileDescriptor_e0e705f843545fab, []int{88} } func (m *SMITrafficRouting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2521,7 +2549,7 @@ var xxx_messageInfo_SMITrafficRouting proto.InternalMessageInfo func (m *ScopeDetail) Reset() { *m = ScopeDetail{} } func (*ScopeDetail) ProtoMessage() {} func (*ScopeDetail) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{88} + return fileDescriptor_e0e705f843545fab, []int{89} } func (m *ScopeDetail) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2549,7 +2577,7 @@ var xxx_messageInfo_ScopeDetail proto.InternalMessageInfo func (m *SecretKeyRef) Reset() { *m = SecretKeyRef{} } func (*SecretKeyRef) ProtoMessage() {} func (*SecretKeyRef) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{89} + return fileDescriptor_e0e705f843545fab, []int{90} } func (m *SecretKeyRef) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2577,7 +2605,7 @@ var xxx_messageInfo_SecretKeyRef proto.InternalMessageInfo func (m *SetCanaryScale) Reset() { *m = SetCanaryScale{} } func (*SetCanaryScale) ProtoMessage() {} func (*SetCanaryScale) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{90} + return fileDescriptor_e0e705f843545fab, []int{91} } func (m *SetCanaryScale) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2605,7 +2633,7 @@ var xxx_messageInfo_SetCanaryScale proto.InternalMessageInfo func (m *SetHeaderRoute) Reset() { *m = SetHeaderRoute{} } func (*SetHeaderRoute) ProtoMessage() {} func (*SetHeaderRoute) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{91} + return fileDescriptor_e0e705f843545fab, []int{92} } func (m *SetHeaderRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2633,7 +2661,7 @@ var xxx_messageInfo_SetHeaderRoute proto.InternalMessageInfo func (m *SetMirrorRoute) Reset() { *m = SetMirrorRoute{} } func (*SetMirrorRoute) ProtoMessage() {} func (*SetMirrorRoute) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{92} + return fileDescriptor_e0e705f843545fab, []int{93} } func (m *SetMirrorRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2661,7 +2689,7 @@ var xxx_messageInfo_SetMirrorRoute proto.InternalMessageInfo func (m *StickinessConfig) Reset() { *m = StickinessConfig{} } func (*StickinessConfig) ProtoMessage() {} func (*StickinessConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{93} + return fileDescriptor_e0e705f843545fab, []int{94} } func (m *StickinessConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2689,7 +2717,7 @@ var xxx_messageInfo_StickinessConfig proto.InternalMessageInfo func (m *StringMatch) Reset() { *m = StringMatch{} } func (*StringMatch) ProtoMessage() {} func (*StringMatch) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{94} + return fileDescriptor_e0e705f843545fab, []int{95} } func (m *StringMatch) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2717,7 +2745,7 @@ var xxx_messageInfo_StringMatch proto.InternalMessageInfo func (m *TCPRoute) Reset() { *m = TCPRoute{} } func (*TCPRoute) ProtoMessage() {} func (*TCPRoute) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{95} + return fileDescriptor_e0e705f843545fab, []int{96} } func (m *TCPRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2745,7 +2773,7 @@ var xxx_messageInfo_TCPRoute proto.InternalMessageInfo func (m *TLSRoute) Reset() { *m = TLSRoute{} } func (*TLSRoute) ProtoMessage() {} func (*TLSRoute) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{96} + return fileDescriptor_e0e705f843545fab, []int{97} } func (m *TLSRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2773,7 +2801,7 @@ var xxx_messageInfo_TLSRoute proto.InternalMessageInfo func (m *TemplateService) Reset() { *m = TemplateService{} } func (*TemplateService) ProtoMessage() {} func (*TemplateService) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{97} + return fileDescriptor_e0e705f843545fab, []int{98} } func (m *TemplateService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2801,7 +2829,7 @@ var xxx_messageInfo_TemplateService proto.InternalMessageInfo func (m *TemplateSpec) Reset() { *m = TemplateSpec{} } func (*TemplateSpec) ProtoMessage() {} func (*TemplateSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{98} + return fileDescriptor_e0e705f843545fab, []int{99} } func (m *TemplateSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2829,7 +2857,7 @@ var xxx_messageInfo_TemplateSpec proto.InternalMessageInfo func (m *TemplateStatus) Reset() { *m = TemplateStatus{} } func (*TemplateStatus) ProtoMessage() {} func (*TemplateStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{99} + return fileDescriptor_e0e705f843545fab, []int{100} } func (m *TemplateStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2857,7 +2885,7 @@ var xxx_messageInfo_TemplateStatus proto.InternalMessageInfo func (m *TraefikTrafficRouting) Reset() { *m = TraefikTrafficRouting{} } func (*TraefikTrafficRouting) ProtoMessage() {} func (*TraefikTrafficRouting) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{100} + return fileDescriptor_e0e705f843545fab, []int{101} } func (m *TraefikTrafficRouting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2885,7 +2913,7 @@ var xxx_messageInfo_TraefikTrafficRouting proto.InternalMessageInfo func (m *TrafficWeights) Reset() { *m = TrafficWeights{} } func (*TrafficWeights) ProtoMessage() {} func (*TrafficWeights) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{101} + return fileDescriptor_e0e705f843545fab, []int{102} } func (m *TrafficWeights) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2913,7 +2941,7 @@ var xxx_messageInfo_TrafficWeights proto.InternalMessageInfo func (m *ValueFrom) Reset() { *m = ValueFrom{} } func (*ValueFrom) ProtoMessage() {} func (*ValueFrom) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{102} + return fileDescriptor_e0e705f843545fab, []int{103} } func (m *ValueFrom) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2941,7 +2969,7 @@ var xxx_messageInfo_ValueFrom proto.InternalMessageInfo func (m *WavefrontMetric) Reset() { *m = WavefrontMetric{} } func (*WavefrontMetric) ProtoMessage() {} func (*WavefrontMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{103} + return fileDescriptor_e0e705f843545fab, []int{104} } func (m *WavefrontMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2969,7 +2997,7 @@ var xxx_messageInfo_WavefrontMetric proto.InternalMessageInfo func (m *WebMetric) Reset() { *m = WebMetric{} } func (*WebMetric) ProtoMessage() {} func (*WebMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{104} + return fileDescriptor_e0e705f843545fab, []int{105} } func (m *WebMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2997,7 +3025,7 @@ var xxx_messageInfo_WebMetric proto.InternalMessageInfo func (m *WebMetricHeader) Reset() { *m = WebMetricHeader{} } func (*WebMetricHeader) ProtoMessage() {} func (*WebMetricHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{105} + return fileDescriptor_e0e705f843545fab, []int{106} } func (m *WebMetricHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3025,7 +3053,7 @@ var xxx_messageInfo_WebMetricHeader proto.InternalMessageInfo func (m *WeightDestination) Reset() { *m = WeightDestination{} } func (*WeightDestination) ProtoMessage() {} func (*WeightDestination) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{106} + return fileDescriptor_e0e705f843545fab, []int{107} } func (m *WeightDestination) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3119,6 +3147,7 @@ func init() { proto.RegisterType((*ObjectRef)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.ObjectRef") proto.RegisterType((*PauseCondition)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PauseCondition") proto.RegisterType((*PingPongSpec)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PingPongSpec") + proto.RegisterType((*PluginMetric)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PluginMetric") proto.RegisterType((*PodTemplateMetadata)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata") proto.RegisterMapType((map[string]string)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata.AnnotationsEntry") proto.RegisterMapType((map[string]string)(nil), "github.aaakk.us.kg.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata.LabelsEntry") @@ -3171,493 +3200,497 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 7773 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x23, 0xd7, - 0x75, 0xb0, 0x87, 0x14, 0x25, 0xf2, 0xe8, 0xff, 0xae, 0x36, 0x2b, 0xcb, 0xde, 0xa5, 0x33, 0x0e, - 0xfc, 0x39, 0xdf, 0xe7, 0x48, 0x89, 0x7f, 0xbe, 0xcf, 0x89, 0x0d, 0x7f, 0x25, 0xa5, 0x5d, 0xaf, - 0xd6, 0xd2, 0x2e, 0xf7, 0x52, 0xbb, 0x9b, 0x38, 0x71, 0x92, 0x11, 0x79, 0x45, 0xcd, 0x8a, 0x9c, - 0x61, 0x66, 0x86, 0xd2, 0xca, 0x31, 0x12, 0x3b, 0x81, 0xdd, 0xb4, 0x48, 0x10, 0xb7, 0x49, 0x50, - 0x14, 0x05, 0x8a, 0xa0, 0x30, 0xd0, 0x9f, 0xe4, 0x29, 0x68, 0xd1, 0x97, 0x00, 0x2d, 0x9a, 0x9f, - 0xa6, 0x0f, 0x29, 0x92, 0x87, 0x36, 0x3f, 0x40, 0xd8, 0x5a, 0xe9, 0x4b, 0x8b, 0x16, 0x41, 0x81, - 0x14, 0x45, 0xf6, 0xa9, 0xb8, 0xbf, 0x73, 0x67, 0x38, 0xd4, 0x52, 0xe2, 0x68, 0x63, 0xb4, 0x79, - 0x23, 0xef, 0x39, 0xf7, 0x9c, 0x73, 0x7f, 0xcf, 0xbd, 0xe7, 0x9e, 0x73, 0x06, 0xd6, 0x1a, 0x76, - 0xb0, 0xdd, 0xd9, 0x5c, 0xac, 0xb9, 0xad, 0x25, 0xcb, 0x6b, 0xb8, 0x6d, 0xcf, 0xbd, 0xc9, 0x7e, - 0xbc, 0xcb, 0x73, 0x9b, 0x4d, 0xb7, 0x13, 0xf8, 0x4b, 0xed, 0x9d, 0xc6, 0x92, 0xd5, 0xb6, 0xfd, - 0x25, 0x55, 0xb2, 0xfb, 0x1e, 0xab, 0xd9, 0xde, 0xb6, 0xde, 0xb3, 0xd4, 0x20, 0x0e, 0xf1, 0xac, - 0x80, 0xd4, 0x17, 0xdb, 0x9e, 0x1b, 0xb8, 0xe8, 0xe9, 0x90, 0xda, 0xa2, 0xa4, 0xc6, 0x7e, 0x7c, - 0x44, 0xd6, 0x5d, 0x6c, 0xef, 0x34, 0x16, 0x29, 0xb5, 0x45, 0x55, 0x22, 0xa9, 0x2d, 0xbc, 0x4b, - 0x93, 0xa5, 0xe1, 0x36, 0xdc, 0x25, 0x46, 0x74, 0xb3, 0xb3, 0xc5, 0xfe, 0xb1, 0x3f, 0xec, 0x17, - 0x67, 0xb6, 0xf0, 0xe0, 0xce, 0x93, 0xfe, 0xa2, 0xed, 0x52, 0xd9, 0x96, 0x36, 0xad, 0xa0, 0xb6, - 0xbd, 0xb4, 0xdb, 0x23, 0xd1, 0x82, 0xa9, 0x21, 0xd5, 0x5c, 0x8f, 0x24, 0xe1, 0x3c, 0x1e, 0xe2, - 0xb4, 0xac, 0xda, 0xb6, 0xed, 0x10, 0x6f, 0x3f, 0x6c, 0x75, 0x8b, 0x04, 0x56, 0x52, 0xad, 0xa5, - 0x7e, 0xb5, 0xbc, 0x8e, 0x13, 0xd8, 0x2d, 0xd2, 0x53, 0xe1, 0xff, 0xde, 0xa9, 0x82, 0x5f, 0xdb, - 0x26, 0x2d, 0xab, 0xa7, 0xde, 0x63, 0xfd, 0xea, 0x75, 0x02, 0xbb, 0xb9, 0x64, 0x3b, 0x81, 0x1f, - 0x78, 0xf1, 0x4a, 0xe6, 0x37, 0xb3, 0x50, 0x28, 0xad, 0x95, 0xab, 0x81, 0x15, 0x74, 0x7c, 0xf4, - 0x9a, 0x01, 0x13, 0x4d, 0xd7, 0xaa, 0x97, 0xad, 0xa6, 0xe5, 0xd4, 0x88, 0x37, 0x6f, 0x3c, 0x60, - 0x3c, 0x3c, 0xfe, 0xe8, 0xda, 0xe2, 0x30, 0xe3, 0xb5, 0x58, 0xda, 0xf3, 0x31, 0xf1, 0xdd, 0x8e, - 0x57, 0x23, 0x98, 0x6c, 0x95, 0xe7, 0xbe, 0xd3, 0x2d, 0xde, 0x73, 0xd0, 0x2d, 0x4e, 0xac, 0x69, - 0x9c, 0x70, 0x84, 0x2f, 0xfa, 0x92, 0x01, 0xb3, 0x35, 0xcb, 0xb1, 0xbc, 0xfd, 0x0d, 0xcb, 0x6b, - 0x90, 0xe0, 0x59, 0xcf, 0xed, 0xb4, 0xe7, 0x33, 0x27, 0x20, 0xcd, 0xbd, 0x42, 0x9a, 0xd9, 0xe5, - 0x38, 0x3b, 0xdc, 0x2b, 0x01, 0x93, 0xcb, 0x0f, 0xac, 0xcd, 0x26, 0xd1, 0xe5, 0xca, 0x9e, 0xa4, - 0x5c, 0xd5, 0x38, 0x3b, 0xdc, 0x2b, 0x81, 0xf9, 0x6a, 0x16, 0x66, 0x4b, 0x6b, 0xe5, 0x0d, 0xcf, - 0xda, 0xda, 0xb2, 0x6b, 0xd8, 0xed, 0x04, 0xb6, 0xd3, 0x40, 0xef, 0x84, 0x31, 0xdb, 0x69, 0x78, - 0xc4, 0xf7, 0xd9, 0x40, 0x16, 0xca, 0xd3, 0x82, 0xe8, 0xd8, 0x2a, 0x2f, 0xc6, 0x12, 0x8e, 0x9e, - 0x80, 0x71, 0x9f, 0x78, 0xbb, 0x76, 0x8d, 0x54, 0x5c, 0x2f, 0x60, 0x3d, 0x9d, 0x2b, 0x9f, 0x12, - 0xe8, 0xe3, 0xd5, 0x10, 0x84, 0x75, 0x3c, 0x5a, 0xcd, 0x73, 0xdd, 0x40, 0xc0, 0x59, 0x47, 0x14, - 0xc2, 0x6a, 0x38, 0x04, 0x61, 0x1d, 0x0f, 0xbd, 0x6e, 0xc0, 0x8c, 0x1f, 0xd8, 0xb5, 0x1d, 0xdb, - 0x21, 0xbe, 0xbf, 0xec, 0x3a, 0x5b, 0x76, 0x63, 0x3e, 0xc7, 0x7a, 0xf1, 0xf2, 0x70, 0xbd, 0x58, - 0x8d, 0x51, 0x2d, 0xcf, 0x1d, 0x74, 0x8b, 0x33, 0xf1, 0x52, 0xdc, 0xc3, 0x1d, 0xad, 0xc0, 0x8c, - 0xe5, 0x38, 0x6e, 0x60, 0x05, 0xb6, 0xeb, 0x54, 0x3c, 0xb2, 0x65, 0xdf, 0x9a, 0x1f, 0x61, 0xcd, - 0x99, 0x17, 0xcd, 0x99, 0x29, 0xc5, 0xe0, 0xb8, 0xa7, 0x86, 0xb9, 0x02, 0xf3, 0xa5, 0xd6, 0xa6, - 0xe5, 0xfb, 0x56, 0xdd, 0xf5, 0x62, 0xa3, 0xf1, 0x30, 0xe4, 0x5b, 0x56, 0xbb, 0x6d, 0x3b, 0x0d, - 0x3a, 0x1c, 0xd9, 0x87, 0x0b, 0xe5, 0x89, 0x83, 0x6e, 0x31, 0xbf, 0x2e, 0xca, 0xb0, 0x82, 0x9a, - 0x3f, 0xca, 0xc0, 0x78, 0xc9, 0xb1, 0x9a, 0xfb, 0xbe, 0xed, 0xe3, 0x8e, 0x83, 0x3e, 0x0a, 0x79, - 0xba, 0xbb, 0xd4, 0xad, 0xc0, 0x12, 0x2b, 0xf2, 0xdd, 0x8b, 0x7c, 0xb1, 0x2f, 0xea, 0x8b, 0x3d, - 0xec, 0x17, 0x8a, 0xbd, 0xb8, 0xfb, 0x9e, 0xc5, 0x2b, 0x9b, 0x37, 0x49, 0x2d, 0x58, 0x27, 0x81, - 0x55, 0x46, 0xa2, 0x15, 0x10, 0x96, 0x61, 0x45, 0x15, 0xb9, 0x30, 0xe2, 0xb7, 0x49, 0x4d, 0xac, - 0xb0, 0xf5, 0x21, 0x67, 0x72, 0x28, 0x7a, 0xb5, 0x4d, 0x6a, 0xe5, 0x09, 0xc1, 0x7a, 0x84, 0xfe, - 0xc3, 0x8c, 0x11, 0xda, 0x83, 0x51, 0x9f, 0xed, 0x39, 0x62, 0xf1, 0x5c, 0x49, 0x8f, 0x25, 0x23, - 0x5b, 0x9e, 0x12, 0x4c, 0x47, 0xf9, 0x7f, 0x2c, 0xd8, 0x99, 0x3f, 0x36, 0xe0, 0x94, 0x86, 0x5d, - 0xf2, 0x1a, 0x9d, 0x16, 0x71, 0x02, 0xf4, 0x00, 0x8c, 0x38, 0x56, 0x8b, 0x88, 0x85, 0xa2, 0x44, - 0xbe, 0x6c, 0xb5, 0x08, 0x66, 0x10, 0xf4, 0x20, 0xe4, 0x76, 0xad, 0x66, 0x87, 0xb0, 0x4e, 0x2a, - 0x94, 0x27, 0x05, 0x4a, 0xee, 0x3a, 0x2d, 0xc4, 0x1c, 0x86, 0x5e, 0x82, 0x02, 0xfb, 0x71, 0xc1, - 0x73, 0x5b, 0x29, 0x35, 0x4d, 0x48, 0x78, 0x5d, 0x92, 0x2d, 0x4f, 0x1e, 0x74, 0x8b, 0x05, 0xf5, - 0x17, 0x87, 0x0c, 0xcd, 0x7f, 0x30, 0x60, 0x5a, 0x6b, 0xdc, 0x9a, 0xed, 0x07, 0xe8, 0x43, 0x3d, - 0x93, 0x67, 0x71, 0xb0, 0xc9, 0x43, 0x6b, 0xb3, 0xa9, 0x33, 0x23, 0x5a, 0x9a, 0x97, 0x25, 0xda, - 0xc4, 0x71, 0x20, 0x67, 0x07, 0xa4, 0xe5, 0xcf, 0x67, 0x1e, 0xc8, 0x3e, 0x3c, 0xfe, 0xe8, 0x6a, - 0x6a, 0xc3, 0x18, 0xf6, 0xef, 0x2a, 0xa5, 0x8f, 0x39, 0x1b, 0xf3, 0x6b, 0x23, 0x91, 0x16, 0xd2, - 0x19, 0x85, 0x5c, 0x18, 0x6b, 0x91, 0xc0, 0xb3, 0x6b, 0x7c, 0x5d, 0x8d, 0x3f, 0xba, 0x32, 0x9c, - 0x14, 0xeb, 0x8c, 0x58, 0xb8, 0x59, 0xf2, 0xff, 0x3e, 0x96, 0x5c, 0xd0, 0x36, 0x8c, 0x58, 0x5e, - 0x43, 0xb6, 0xf9, 0x42, 0x3a, 0xe3, 0x1b, 0xce, 0xb9, 0x92, 0xd7, 0xf0, 0x31, 0xe3, 0x80, 0x96, - 0xa0, 0x10, 0x10, 0xaf, 0x65, 0x3b, 0x56, 0xc0, 0x77, 0xd7, 0x7c, 0x79, 0x56, 0xa0, 0x15, 0x36, - 0x24, 0x00, 0x87, 0x38, 0xa8, 0x09, 0xa3, 0x75, 0x6f, 0x1f, 0x77, 0x9c, 0xf9, 0x91, 0x34, 0xba, - 0x62, 0x85, 0xd1, 0x0a, 0x17, 0x13, 0xff, 0x8f, 0x05, 0x0f, 0xf4, 0x86, 0x01, 0x73, 0x2d, 0x62, - 0xf9, 0x1d, 0x8f, 0xd0, 0x26, 0x60, 0x12, 0x10, 0x87, 0xee, 0x86, 0xf3, 0x39, 0xc6, 0x1c, 0x0f, - 0x3b, 0x0e, 0xbd, 0x94, 0xcb, 0xf7, 0x0b, 0x51, 0xe6, 0x92, 0xa0, 0x38, 0x51, 0x1a, 0xf3, 0x47, - 0x23, 0x30, 0xdb, 0xb3, 0x43, 0xa0, 0xc7, 0x21, 0xd7, 0xde, 0xb6, 0x7c, 0xb9, 0xe4, 0xcf, 0xc9, - 0xf9, 0x56, 0xa1, 0x85, 0xb7, 0xbb, 0xc5, 0x49, 0x59, 0x85, 0x15, 0x60, 0x8e, 0x4c, 0x75, 0x6a, - 0x8b, 0xf8, 0xbe, 0xd5, 0x90, 0xfb, 0x80, 0x36, 0x4d, 0x58, 0x31, 0x96, 0x70, 0xf4, 0xeb, 0x06, - 0x4c, 0xf2, 0x29, 0x83, 0x89, 0xdf, 0x69, 0x06, 0x74, 0xaf, 0xa3, 0xdd, 0x72, 0x29, 0x8d, 0xe9, - 0xc9, 0x49, 0x96, 0x4f, 0x0b, 0xee, 0x93, 0x7a, 0xa9, 0x8f, 0xa3, 0x7c, 0xd1, 0x0d, 0x28, 0xf8, - 0x81, 0xe5, 0x05, 0xa4, 0x5e, 0x0a, 0x98, 0x56, 0x1b, 0x7f, 0xf4, 0x7f, 0x0f, 0xb6, 0x09, 0x6c, - 0xd8, 0x2d, 0xc2, 0x37, 0x9c, 0xaa, 0x24, 0x80, 0x43, 0x5a, 0xe8, 0x25, 0x00, 0xaf, 0xe3, 0x54, - 0x3b, 0xad, 0x96, 0xe5, 0xed, 0x0b, 0x0d, 0x7e, 0x71, 0xb8, 0xe6, 0x61, 0x45, 0x2f, 0xd4, 0x59, - 0x61, 0x19, 0xd6, 0xf8, 0xa1, 0x57, 0x0c, 0x98, 0xe4, 0x33, 0x51, 0x4a, 0x30, 0x9a, 0xb2, 0x04, - 0xb3, 0xb4, 0x6b, 0x57, 0x74, 0x16, 0x38, 0xca, 0xd1, 0xfc, 0xbb, 0xa8, 0x3e, 0xa9, 0x06, 0xf4, - 0x74, 0xdd, 0xd8, 0x47, 0x1f, 0x84, 0x7b, 0xfd, 0x4e, 0xad, 0x46, 0x7c, 0x7f, 0xab, 0xd3, 0xc4, - 0x1d, 0xe7, 0xa2, 0xed, 0x07, 0xae, 0xb7, 0xbf, 0x66, 0xb7, 0xec, 0x80, 0xcd, 0xb8, 0x5c, 0xf9, - 0xec, 0x41, 0xb7, 0x78, 0x6f, 0xb5, 0x1f, 0x12, 0xee, 0x5f, 0x1f, 0x59, 0x70, 0x5f, 0xc7, 0xe9, - 0x4f, 0x9e, 0x9f, 0xde, 0x8a, 0x07, 0xdd, 0xe2, 0x7d, 0xd7, 0xfa, 0xa3, 0xe1, 0xc3, 0x68, 0x98, - 0xff, 0x62, 0xc0, 0x8c, 0x6c, 0xd7, 0x06, 0x69, 0xb5, 0x9b, 0x74, 0x77, 0x39, 0xf9, 0x83, 0x48, - 0x10, 0x39, 0x88, 0xe0, 0x74, 0xd4, 0x89, 0x94, 0xbf, 0xdf, 0x69, 0xc4, 0xfc, 0x67, 0x03, 0xe6, - 0xe2, 0xc8, 0x77, 0x41, 0x79, 0xfa, 0x51, 0xe5, 0x79, 0x39, 0xdd, 0xd6, 0xf6, 0xd1, 0xa0, 0xaf, - 0x8d, 0xf4, 0xb6, 0xf5, 0xbf, 0xbb, 0x1a, 0x0d, 0xb5, 0x62, 0xf6, 0x97, 0xa9, 0x15, 0x47, 0xde, - 0x52, 0x5a, 0xf1, 0x8f, 0x46, 0x60, 0xa2, 0xe4, 0x04, 0x76, 0x69, 0x6b, 0xcb, 0x76, 0xec, 0x60, - 0x1f, 0x7d, 0x36, 0x03, 0x4b, 0x6d, 0x8f, 0x6c, 0x11, 0xcf, 0x23, 0xf5, 0x95, 0x8e, 0x67, 0x3b, - 0x8d, 0x6a, 0x6d, 0x9b, 0xd4, 0x3b, 0x4d, 0xdb, 0x69, 0xac, 0x36, 0x1c, 0x57, 0x15, 0x9f, 0xbf, - 0x45, 0x6a, 0x1d, 0xd6, 0x24, 0xbe, 0x28, 0x5a, 0xc3, 0x35, 0xa9, 0x72, 0x34, 0xa6, 0xe5, 0xc7, - 0x0e, 0xba, 0xc5, 0xa5, 0x23, 0x56, 0xc2, 0x47, 0x6d, 0x1a, 0xfa, 0x4c, 0x06, 0x16, 0x3d, 0xf2, - 0xb1, 0x8e, 0x3d, 0x78, 0x6f, 0xf0, 0x5d, 0xab, 0x39, 0xa4, 0xfa, 0x39, 0x12, 0xcf, 0xf2, 0xa3, - 0x07, 0xdd, 0xe2, 0x11, 0xeb, 0xe0, 0x23, 0xb6, 0xcb, 0xac, 0xc0, 0x78, 0xa9, 0x6d, 0xfb, 0xf6, - 0x2d, 0x7a, 0x97, 0x25, 0x03, 0xdc, 0x95, 0x8a, 0x90, 0xf3, 0x3a, 0x4d, 0xc2, 0xd7, 0x76, 0xa1, - 0x5c, 0xa0, 0xbb, 0x10, 0xa6, 0x05, 0x98, 0x97, 0x9b, 0x9f, 0xa2, 0x3b, 0x2e, 0x23, 0x19, 0xbb, - 0x25, 0xdf, 0x84, 0x9c, 0x47, 0x99, 0x88, 0x99, 0x35, 0xec, 0x85, 0x22, 0x94, 0x5a, 0x08, 0x41, - 0x7f, 0x62, 0xce, 0xc2, 0xfc, 0x46, 0x06, 0x4e, 0x97, 0xda, 0xed, 0x75, 0xe2, 0x6f, 0xc7, 0xa4, - 0xf8, 0xbc, 0x01, 0x53, 0xbb, 0xb6, 0x17, 0x74, 0xac, 0xa6, 0xb4, 0x6d, 0x70, 0x79, 0xaa, 0xc3, - 0xca, 0xc3, 0xb8, 0x5d, 0x8f, 0x90, 0x2e, 0xa3, 0x83, 0x6e, 0x71, 0x2a, 0x5a, 0x86, 0x63, 0xec, - 0xd1, 0xef, 0x18, 0x30, 0x23, 0x8a, 0x2e, 0xbb, 0x75, 0xa2, 0x1b, 0xc4, 0xae, 0xa5, 0x29, 0x93, - 0x22, 0xce, 0x2d, 0x27, 0xf1, 0x52, 0xdc, 0x23, 0x84, 0xf9, 0x6f, 0x19, 0x38, 0xd3, 0x87, 0x06, - 0xfa, 0x43, 0x03, 0xe6, 0xb8, 0x15, 0x4d, 0x03, 0x61, 0xb2, 0x25, 0x7a, 0xf3, 0x03, 0x69, 0x4b, - 0x8e, 0xe9, 0x12, 0x27, 0x4e, 0x8d, 0x94, 0xe7, 0xe9, 0x6e, 0xb8, 0x9c, 0xc0, 0x1a, 0x27, 0x0a, - 0xc4, 0x24, 0xe5, 0x76, 0xb5, 0x98, 0xa4, 0x99, 0xbb, 0x22, 0x69, 0x35, 0x81, 0x35, 0x4e, 0x14, - 0xc8, 0xfc, 0xff, 0x70, 0xdf, 0x21, 0xe4, 0xee, 0xbc, 0x38, 0xcd, 0x17, 0xd4, 0xac, 0x8f, 0xce, - 0xb9, 0x01, 0xd6, 0xb5, 0x09, 0xa3, 0x6c, 0xe9, 0xc8, 0x85, 0x0d, 0x54, 0xfd, 0xb1, 0x35, 0xe5, - 0x63, 0x01, 0x31, 0xbf, 0x61, 0x40, 0xfe, 0x08, 0x66, 0x95, 0x62, 0xd4, 0xac, 0x52, 0xe8, 0x31, - 0xa9, 0x04, 0xbd, 0x26, 0x95, 0x67, 0x87, 0x1b, 0x8d, 0x41, 0x4c, 0x29, 0x3f, 0x33, 0x60, 0xb6, - 0xc7, 0xf4, 0x82, 0xb6, 0x61, 0xae, 0xed, 0xd6, 0xe5, 0xb1, 0xe9, 0xa2, 0xe5, 0x6f, 0x33, 0x98, - 0x68, 0xde, 0xe3, 0x74, 0x24, 0x2b, 0x09, 0xf0, 0xdb, 0xdd, 0xe2, 0xbc, 0x22, 0x12, 0x43, 0xc0, - 0x89, 0x14, 0x51, 0x1b, 0xf2, 0x5b, 0x36, 0x69, 0xd6, 0xc3, 0x29, 0x38, 0xe4, 0x01, 0xe9, 0x82, - 0xa0, 0xc6, 0xad, 0x8e, 0xf2, 0x1f, 0x56, 0x5c, 0xcc, 0xab, 0x30, 0x15, 0xb5, 0x41, 0x0f, 0x30, - 0x78, 0x67, 0x21, 0x6b, 0x79, 0x8e, 0x18, 0xba, 0x71, 0x81, 0x90, 0x2d, 0xe1, 0xcb, 0x98, 0x96, - 0x9b, 0xbf, 0x18, 0x81, 0xe9, 0x72, 0xb3, 0x43, 0x9e, 0xf5, 0x08, 0x91, 0xd7, 0xee, 0x12, 0x4c, - 0xb7, 0x3d, 0xb2, 0x6b, 0x93, 0xbd, 0x2a, 0x69, 0x92, 0x5a, 0xe0, 0x7a, 0x82, 0xfe, 0x19, 0x51, - 0x7d, 0xba, 0x12, 0x05, 0xe3, 0x38, 0x3e, 0x7a, 0x06, 0xa6, 0xac, 0x5a, 0x60, 0xef, 0x12, 0x45, - 0x81, 0x0b, 0xf0, 0x36, 0x41, 0x61, 0xaa, 0x14, 0x81, 0xe2, 0x18, 0x36, 0xfa, 0x10, 0xcc, 0xfb, - 0x35, 0xab, 0x49, 0xae, 0xb5, 0x05, 0xab, 0xe5, 0x6d, 0x52, 0xdb, 0xa9, 0xb8, 0xb6, 0x13, 0x08, - 0x23, 0xcb, 0x03, 0x82, 0xd2, 0x7c, 0xb5, 0x0f, 0x1e, 0xee, 0x4b, 0x01, 0xfd, 0x85, 0x01, 0x67, - 0xdb, 0x1e, 0xa9, 0x78, 0x6e, 0xcb, 0xa5, 0xda, 0xb3, 0xc7, 0xf2, 0x20, 0x6e, 0xe0, 0xd7, 0x87, - 0x3c, 0x26, 0xf0, 0x92, 0x5e, 0xcb, 0xe7, 0xdb, 0x0f, 0xba, 0xc5, 0xb3, 0x95, 0xc3, 0x04, 0xc0, - 0x87, 0xcb, 0x87, 0xfe, 0xca, 0x80, 0x73, 0x6d, 0xd7, 0x0f, 0x0e, 0x69, 0x42, 0xee, 0x44, 0x9b, - 0x60, 0x1e, 0x74, 0x8b, 0xe7, 0x2a, 0x87, 0x4a, 0x80, 0xef, 0x20, 0xa1, 0x79, 0x30, 0x0e, 0xb3, - 0xda, 0xdc, 0x13, 0xd7, 0xf2, 0xa7, 0x60, 0x52, 0x4e, 0x86, 0x50, 0xad, 0x17, 0x42, 0x33, 0x4a, - 0x49, 0x07, 0xe2, 0x28, 0x2e, 0x9d, 0x77, 0x6a, 0x2a, 0xf2, 0xda, 0xb1, 0x79, 0x57, 0x89, 0x40, - 0x71, 0x0c, 0x1b, 0xad, 0xc2, 0x29, 0x51, 0x82, 0x49, 0xbb, 0x69, 0xd7, 0xac, 0x65, 0xb7, 0x23, - 0xa6, 0x5c, 0xae, 0x7c, 0xe6, 0xa0, 0x5b, 0x3c, 0x55, 0xe9, 0x05, 0xe3, 0xa4, 0x3a, 0x68, 0x0d, - 0xe6, 0xac, 0x4e, 0xe0, 0xaa, 0xf6, 0x9f, 0x77, 0xa8, 0xa6, 0xa8, 0xb3, 0xa9, 0x95, 0xe7, 0x2a, - 0xa5, 0x94, 0x00, 0xc7, 0x89, 0xb5, 0x50, 0x25, 0x46, 0xad, 0x4a, 0x6a, 0xae, 0x53, 0xe7, 0xa3, - 0x9c, 0x0b, 0x2f, 0x17, 0xa5, 0x04, 0x1c, 0x9c, 0x58, 0x13, 0x35, 0x61, 0xaa, 0x65, 0xdd, 0xba, - 0xe6, 0x58, 0xbb, 0x96, 0xdd, 0xa4, 0x4c, 0x84, 0x69, 0xa6, 0xbf, 0xbd, 0xa0, 0x13, 0xd8, 0xcd, - 0x45, 0xfe, 0x4a, 0xb9, 0xb8, 0xea, 0x04, 0x57, 0xbc, 0x6a, 0x40, 0x0f, 0xa1, 0xfc, 0x70, 0xb4, - 0x1e, 0xa1, 0x85, 0x63, 0xb4, 0xd1, 0x15, 0x38, 0xcd, 0x96, 0xe3, 0x8a, 0xbb, 0xe7, 0xac, 0x90, - 0xa6, 0xb5, 0x2f, 0x1b, 0x30, 0xc6, 0x1a, 0x70, 0xef, 0x41, 0xb7, 0x78, 0xba, 0x9a, 0x84, 0x80, - 0x93, 0xeb, 0x21, 0x0b, 0xee, 0x8b, 0x02, 0x30, 0xd9, 0xb5, 0x7d, 0xdb, 0x75, 0xb8, 0x81, 0x25, - 0x1f, 0x1a, 0x58, 0xaa, 0xfd, 0xd1, 0xf0, 0x61, 0x34, 0xd0, 0xef, 0x19, 0x30, 0x97, 0xb4, 0x0c, - 0xe7, 0x0b, 0x69, 0xbc, 0xc1, 0xc4, 0x96, 0x16, 0x9f, 0x11, 0x89, 0x9b, 0x42, 0xa2, 0x10, 0xe8, - 0x65, 0x03, 0x26, 0x2c, 0xed, 0x72, 0x38, 0x0f, 0x4c, 0xaa, 0x4b, 0xc3, 0x9a, 0x28, 0x42, 0x8a, - 0xe5, 0x99, 0x83, 0x6e, 0x31, 0x72, 0x01, 0xc5, 0x11, 0x8e, 0xe8, 0xf7, 0x0d, 0x38, 0x9d, 0xb8, - 0xc6, 0xe7, 0xc7, 0x4f, 0xa2, 0x87, 0xd8, 0x24, 0x49, 0xde, 0x73, 0x92, 0xc5, 0x40, 0xaf, 0x1b, - 0x4a, 0x95, 0xad, 0x4b, 0x23, 0xd1, 0x04, 0x13, 0xed, 0xea, 0x90, 0xf7, 0xe1, 0xf0, 0x40, 0x20, - 0x09, 0x97, 0x4f, 0x69, 0x9a, 0x51, 0x16, 0xe2, 0x38, 0x7b, 0xf4, 0x39, 0x43, 0xaa, 0x46, 0x25, - 0xd1, 0xe4, 0x49, 0x49, 0x84, 0x42, 0x4d, 0xab, 0x04, 0x8a, 0x31, 0x47, 0x1f, 0x86, 0x05, 0x6b, - 0xd3, 0xf5, 0x82, 0xc4, 0xc5, 0x37, 0x3f, 0xc5, 0x96, 0xd1, 0xb9, 0x83, 0x6e, 0x71, 0xa1, 0xd4, - 0x17, 0x0b, 0x1f, 0x42, 0xc1, 0xfc, 0x6a, 0x0e, 0x26, 0xf8, 0x21, 0x5f, 0xa8, 0xae, 0xaf, 0x1b, - 0x70, 0x7f, 0xad, 0xe3, 0x79, 0xc4, 0x09, 0xaa, 0x01, 0x69, 0xf7, 0x2a, 0x2e, 0xe3, 0x44, 0x15, - 0xd7, 0x03, 0x07, 0xdd, 0xe2, 0xfd, 0xcb, 0x87, 0xf0, 0xc7, 0x87, 0x4a, 0x87, 0xfe, 0xd6, 0x00, - 0x53, 0x20, 0x94, 0xad, 0xda, 0x4e, 0xc3, 0x73, 0x3b, 0x4e, 0xbd, 0xb7, 0x11, 0x99, 0x13, 0x6d, - 0xc4, 0x43, 0x07, 0xdd, 0xa2, 0xb9, 0x7c, 0x47, 0x29, 0xf0, 0x00, 0x92, 0xa2, 0x67, 0x61, 0x56, - 0x60, 0x9d, 0xbf, 0xd5, 0x26, 0x9e, 0x4d, 0x8f, 0xd3, 0xc2, 0x4d, 0x20, 0xf4, 0xbc, 0x88, 0x23, - 0xe0, 0xde, 0x3a, 0xc8, 0x87, 0xb1, 0x3d, 0x62, 0x37, 0xb6, 0x03, 0x79, 0x7c, 0x1a, 0xd2, 0xdd, - 0x42, 0x5c, 0xf8, 0x6f, 0x70, 0x9a, 0xe5, 0xf1, 0x83, 0x6e, 0x71, 0x4c, 0xfc, 0xc1, 0x92, 0x13, - 0xba, 0x0c, 0x53, 0xfc, 0x0a, 0x56, 0xb1, 0x9d, 0x46, 0xc5, 0x75, 0xb8, 0x93, 0x42, 0xa1, 0xfc, - 0x90, 0x54, 0xf8, 0xd5, 0x08, 0xf4, 0x76, 0xb7, 0x38, 0x21, 0x7f, 0x6f, 0xec, 0xb7, 0x09, 0x8e, - 0xd5, 0x36, 0xbf, 0x3d, 0x0a, 0x20, 0xa7, 0x2b, 0x69, 0xa3, 0xff, 0x03, 0x05, 0x9f, 0x04, 0x9c, - 0xab, 0x78, 0x13, 0xe0, 0x4f, 0x2d, 0xb2, 0x10, 0x87, 0x70, 0xb4, 0x03, 0xb9, 0xb6, 0xd5, 0xf1, - 0x89, 0x18, 0xfc, 0x4b, 0xa9, 0x0c, 0x7e, 0x85, 0x52, 0xe4, 0x77, 0x2e, 0xf6, 0x13, 0x73, 0x1e, - 0xe8, 0xd3, 0x06, 0x00, 0x89, 0x0e, 0xd8, 0xd0, 0xb6, 0x0f, 0xc1, 0x32, 0x1c, 0x53, 0xda, 0x07, - 0xe5, 0xa9, 0x83, 0x6e, 0x11, 0xb4, 0xa1, 0xd7, 0xd8, 0xa2, 0x3d, 0xc8, 0x5b, 0x72, 0xcf, 0x1f, - 0x39, 0x89, 0x3d, 0x9f, 0x5d, 0x85, 0xd4, 0xa4, 0x55, 0xcc, 0xd0, 0x67, 0x0c, 0x98, 0xf2, 0x49, - 0x20, 0x86, 0x8a, 0xee, 0x3c, 0xe2, 0xc0, 0x3b, 0xe4, 0xa4, 0xab, 0x46, 0x68, 0xf2, 0x1d, 0x34, - 0x5a, 0x86, 0x63, 0x7c, 0xa5, 0x28, 0x17, 0x89, 0x55, 0x27, 0x1e, 0xbb, 0x69, 0x8b, 0x93, 0xd4, - 0xf0, 0xa2, 0x68, 0x34, 0x95, 0x28, 0x5a, 0x19, 0x8e, 0xf1, 0x95, 0xa2, 0xac, 0xdb, 0x9e, 0xe7, - 0x0a, 0x51, 0xf2, 0x29, 0x89, 0xa2, 0xd1, 0x54, 0xa2, 0x68, 0x65, 0x38, 0xc6, 0xd7, 0xfc, 0xf2, - 0x24, 0x4c, 0xc9, 0x85, 0x14, 0x9e, 0xec, 0xb9, 0x61, 0xa7, 0xcf, 0xc9, 0x7e, 0x59, 0x07, 0xe2, - 0x28, 0x2e, 0xad, 0xcc, 0x97, 0x6a, 0xf4, 0x60, 0xaf, 0x2a, 0x57, 0x75, 0x20, 0x8e, 0xe2, 0xa2, - 0x16, 0xe4, 0xfc, 0x80, 0xb4, 0xe5, 0xf3, 0xee, 0x90, 0xaf, 0x8f, 0xe1, 0xfe, 0x10, 0x3e, 0xe0, - 0xd0, 0x7f, 0x3e, 0xe6, 0x5c, 0x98, 0x6d, 0x32, 0x88, 0x98, 0x2b, 0xc5, 0xe2, 0x48, 0x67, 0x7d, - 0x46, 0x2d, 0xa1, 0x7c, 0x34, 0xa2, 0x65, 0x38, 0xc6, 0x3e, 0xe1, 0xb0, 0x9f, 0x3b, 0xc1, 0xc3, - 0xfe, 0xf3, 0x90, 0x6f, 0x59, 0xb7, 0xaa, 0x1d, 0xaf, 0x71, 0xfc, 0x4b, 0x85, 0xf0, 0xbc, 0xe2, - 0x54, 0xb0, 0xa2, 0x87, 0x5e, 0x31, 0xb4, 0x2d, 0x67, 0x8c, 0x11, 0xbf, 0x91, 0xee, 0x96, 0xa3, - 0x74, 0x65, 0xdf, 0xcd, 0xa7, 0xe7, 0xe8, 0x9d, 0xbf, 0xeb, 0x47, 0x6f, 0x7a, 0x8c, 0xe4, 0x0b, - 0x44, 0x1d, 0x23, 0x0b, 0x27, 0x7a, 0x8c, 0x5c, 0x8e, 0x30, 0xc3, 0x31, 0xe6, 0x4c, 0x1e, 0xbe, - 0xe6, 0x94, 0x3c, 0x70, 0xa2, 0xf2, 0x54, 0x23, 0xcc, 0x70, 0x8c, 0x79, 0xff, 0xfb, 0xe6, 0xf8, - 0xc9, 0xdc, 0x37, 0x27, 0x52, 0xb8, 0x6f, 0x1e, 0x7e, 0x14, 0x9f, 0x1c, 0xf6, 0x28, 0x8e, 0x2e, - 0x01, 0xaa, 0xef, 0x3b, 0x56, 0xcb, 0xae, 0x89, 0xcd, 0x92, 0xa9, 0xcd, 0x29, 0x66, 0x8f, 0x58, - 0x10, 0x1b, 0x19, 0x5a, 0xe9, 0xc1, 0xc0, 0x09, 0xb5, 0x50, 0x00, 0xf9, 0xb6, 0x3c, 0x71, 0x4d, - 0xa7, 0x31, 0xfb, 0xe5, 0x09, 0x8c, 0x7b, 0x00, 0xd0, 0x85, 0x27, 0x4b, 0xb0, 0xe2, 0x84, 0xd6, - 0x60, 0xae, 0x65, 0x3b, 0x15, 0xb7, 0xee, 0x57, 0x88, 0x27, 0xac, 0x2d, 0x55, 0x12, 0xcc, 0xcf, - 0xb0, 0xbe, 0x61, 0x37, 0xe8, 0xf5, 0x04, 0x38, 0x4e, 0xac, 0x65, 0xfe, 0x87, 0x01, 0x33, 0xcb, - 0x4d, 0xb7, 0x53, 0xbf, 0x61, 0x05, 0xb5, 0x6d, 0xfe, 0xf8, 0x8d, 0x9e, 0x81, 0xbc, 0xed, 0x04, - 0xc4, 0xdb, 0xb5, 0x9a, 0x42, 0x3f, 0x99, 0xd2, 0x3f, 0x60, 0x55, 0x94, 0xdf, 0xee, 0x16, 0xa7, - 0x56, 0x3a, 0x1e, 0xf3, 0x2a, 0xe5, 0xbb, 0x15, 0x56, 0x75, 0xd0, 0x97, 0x0d, 0x98, 0xe5, 0xcf, - 0xe7, 0x2b, 0x56, 0x60, 0x5d, 0xed, 0x10, 0xcf, 0x26, 0xf2, 0x01, 0x7d, 0xc8, 0x8d, 0x2a, 0x2e, - 0xab, 0x64, 0xb0, 0x1f, 0x1e, 0xd4, 0xd7, 0xe3, 0x9c, 0x71, 0xaf, 0x30, 0xe6, 0x17, 0xb2, 0x70, - 0x6f, 0x5f, 0x5a, 0x68, 0x01, 0x32, 0x76, 0x5d, 0x34, 0x1d, 0x04, 0xdd, 0xcc, 0x6a, 0x1d, 0x67, - 0xec, 0x3a, 0x5a, 0x64, 0x67, 0x4e, 0x8f, 0xf8, 0xbe, 0x7c, 0x4b, 0x2d, 0xa8, 0xe3, 0xa1, 0x28, - 0xc5, 0x1a, 0x06, 0x2a, 0x42, 0xae, 0x69, 0x6d, 0x92, 0xa6, 0xb8, 0x4f, 0xb0, 0x53, 0xec, 0x1a, - 0x2d, 0xc0, 0xbc, 0x1c, 0x7d, 0xca, 0x00, 0xe0, 0x02, 0xd2, 0xdb, 0x88, 0xd0, 0x92, 0x38, 0xdd, - 0x6e, 0xa2, 0x94, 0xb9, 0x94, 0xe1, 0x7f, 0xac, 0x71, 0x45, 0x1b, 0x30, 0x4a, 0x0f, 0xb4, 0x6e, - 0xfd, 0xd8, 0x4a, 0x91, 0x3d, 0xb2, 0x54, 0x18, 0x0d, 0x2c, 0x68, 0xd1, 0xbe, 0xf2, 0x48, 0xd0, - 0xf1, 0x1c, 0xda, 0xb5, 0x4c, 0x0d, 0xe6, 0xb9, 0x14, 0x58, 0x95, 0x62, 0x0d, 0xc3, 0xfc, 0xf3, - 0x0c, 0xcc, 0x25, 0x89, 0x4e, 0xb5, 0xcd, 0x28, 0x97, 0x56, 0x5c, 0x8d, 0xdf, 0x9f, 0x7e, 0xff, - 0x08, 0x4f, 0x10, 0xe5, 0x2f, 0x21, 0x7c, 0xd5, 0x04, 0x5f, 0xf4, 0x7e, 0xd5, 0x43, 0x99, 0x63, - 0xf6, 0x90, 0xa2, 0x1c, 0xeb, 0xa5, 0x07, 0x60, 0xc4, 0xa7, 0x23, 0x9f, 0x8d, 0x3e, 0x60, 0xb0, - 0x31, 0x62, 0x10, 0x8a, 0xd1, 0x71, 0xec, 0x40, 0xb8, 0x7a, 0x2b, 0x8c, 0x6b, 0x8e, 0x1d, 0x60, - 0x06, 0x31, 0xbf, 0x94, 0x81, 0x85, 0xfe, 0x8d, 0x42, 0x5f, 0x32, 0x00, 0xea, 0xf4, 0xba, 0x42, - 0xa7, 0xa4, 0xf4, 0x9c, 0xb1, 0x4e, 0xaa, 0x0f, 0x57, 0x24, 0xa7, 0xd0, 0x8d, 0x4a, 0x15, 0xf9, - 0x58, 0x13, 0x04, 0x3d, 0x2a, 0xa7, 0xfe, 0x65, 0xab, 0x25, 0x8f, 0xb3, 0xaa, 0xce, 0xba, 0x82, - 0x60, 0x0d, 0x8b, 0xde, 0x47, 0x1d, 0xab, 0x45, 0xfc, 0xb6, 0xa5, 0x7c, 0xf9, 0xd9, 0x7d, 0xf4, - 0xb2, 0x2c, 0xc4, 0x21, 0xdc, 0x6c, 0xc2, 0x83, 0x03, 0xc8, 0x99, 0x92, 0x5f, 0xb5, 0xf9, 0xef, - 0x06, 0x9c, 0x59, 0x6e, 0x76, 0xfc, 0x80, 0x78, 0xff, 0x63, 0xbc, 0xd2, 0xfe, 0xd3, 0x80, 0xfb, - 0xfa, 0xb4, 0xf9, 0x2e, 0x38, 0xa7, 0xbd, 0x18, 0x75, 0x4e, 0xbb, 0x36, 0xec, 0x94, 0x4e, 0x6c, - 0x47, 0x1f, 0x1f, 0xb5, 0x00, 0x26, 0xe9, 0xae, 0x55, 0x77, 0x1b, 0x29, 0xe9, 0xcd, 0x07, 0x21, - 0xf7, 0x31, 0xaa, 0x7f, 0xe2, 0x73, 0x8c, 0x29, 0x25, 0xcc, 0x61, 0xe6, 0xd3, 0x20, 0x3c, 0xb9, - 0x62, 0x8b, 0xc7, 0x18, 0x64, 0xf1, 0x98, 0x7f, 0x9f, 0x01, 0xcd, 0x8e, 0x71, 0x17, 0x26, 0xa5, - 0x13, 0x99, 0x94, 0x43, 0xde, 0xc1, 0x35, 0xab, 0x4c, 0xbf, 0x90, 0x8d, 0xdd, 0x58, 0xc8, 0xc6, - 0xe5, 0xd4, 0x38, 0x1e, 0x1e, 0xb1, 0xf1, 0x03, 0x03, 0xee, 0x0b, 0x91, 0x7b, 0x4d, 0x8c, 0x77, - 0xde, 0x61, 0x9e, 0x80, 0x71, 0x2b, 0xac, 0x26, 0xe6, 0x80, 0x8a, 0x52, 0xd2, 0x28, 0x62, 0x1d, - 0x2f, 0x74, 0x10, 0xcf, 0x1e, 0xd3, 0x41, 0x7c, 0xe4, 0x70, 0x07, 0x71, 0xf3, 0xe7, 0x19, 0x38, - 0xdb, 0xdb, 0x32, 0xb9, 0x36, 0x06, 0x7b, 0x81, 0x7f, 0x12, 0x26, 0x02, 0x51, 0x41, 0xdb, 0xe9, - 0x55, 0x8c, 0xdd, 0x86, 0x06, 0xc3, 0x11, 0x4c, 0x5a, 0xb3, 0xc6, 0x57, 0x65, 0xb5, 0xe6, 0xb6, - 0x65, 0x78, 0x81, 0xaa, 0xb9, 0xac, 0xc1, 0x70, 0x04, 0x53, 0x39, 0x6e, 0x8e, 0x9c, 0xb8, 0xe3, - 0x66, 0x15, 0x4e, 0x4b, 0x57, 0xb5, 0x0b, 0xae, 0xb7, 0xec, 0xb6, 0xda, 0x4d, 0x22, 0x02, 0x0c, - 0xa8, 0xb0, 0x67, 0x45, 0x95, 0xd3, 0x38, 0x09, 0x09, 0x27, 0xd7, 0x35, 0x7f, 0x90, 0x85, 0x53, - 0x61, 0xb7, 0x2f, 0xbb, 0x4e, 0xdd, 0x66, 0x0e, 0x7f, 0x4f, 0xc1, 0x48, 0xb0, 0xdf, 0x96, 0x9d, - 0xfd, 0xbf, 0xa4, 0x38, 0x1b, 0xfb, 0x6d, 0x3a, 0xda, 0x67, 0x12, 0xaa, 0x30, 0x23, 0x2f, 0xab, - 0x84, 0xd6, 0xd4, 0xea, 0xe0, 0x23, 0xf0, 0x78, 0x74, 0x36, 0xdf, 0xee, 0x16, 0x13, 0x42, 0x4c, - 0x17, 0x15, 0xa5, 0xe8, 0x9c, 0x47, 0x37, 0x61, 0xaa, 0x69, 0xf9, 0xc1, 0xb5, 0x76, 0xdd, 0x0a, - 0xc8, 0x86, 0xdd, 0x22, 0x62, 0xcd, 0x1d, 0xc5, 0x6b, 0x5f, 0xbd, 0x4a, 0xaf, 0x45, 0x28, 0xe1, - 0x18, 0x65, 0xb4, 0x0b, 0x88, 0x96, 0x6c, 0x78, 0x96, 0xe3, 0xf3, 0x56, 0x51, 0x7e, 0x47, 0x8f, - 0x12, 0x50, 0x97, 0xbc, 0xb5, 0x1e, 0x6a, 0x38, 0x81, 0x03, 0x7a, 0x08, 0x46, 0x3d, 0x62, 0xf9, - 0x62, 0x30, 0x0b, 0xe1, 0xfa, 0xc7, 0xac, 0x14, 0x0b, 0xa8, 0xbe, 0xa0, 0x46, 0xef, 0xb0, 0xa0, - 0x7e, 0x62, 0xc0, 0x54, 0x38, 0x4c, 0x77, 0x41, 0x49, 0xb6, 0xa2, 0x4a, 0xf2, 0x62, 0x5a, 0x5b, - 0x62, 0x1f, 0xbd, 0xf8, 0xd7, 0xa3, 0x7a, 0xfb, 0x98, 0xd7, 0xf6, 0xc7, 0xa1, 0x20, 0x57, 0xb5, - 0x3c, 0x7d, 0x0e, 0x79, 0x57, 0x8e, 0x9c, 0x4b, 0xb4, 0x68, 0x23, 0xc1, 0x04, 0x87, 0xfc, 0xa8, - 0x5a, 0xae, 0x0b, 0x95, 0x2b, 0xa6, 0xbd, 0x52, 0xcb, 0x52, 0x15, 0x27, 0xa9, 0x65, 0x59, 0x07, - 0x5d, 0x83, 0x33, 0x6d, 0xcf, 0x65, 0x11, 0xa8, 0x2b, 0xc4, 0xaa, 0x37, 0x6d, 0x87, 0x48, 0x83, - 0x04, 0x77, 0x8a, 0xb8, 0xef, 0xa0, 0x5b, 0x3c, 0x53, 0x49, 0x46, 0xc1, 0xfd, 0xea, 0x46, 0xa3, - 0xa6, 0x46, 0x06, 0x88, 0x9a, 0xfa, 0x0d, 0x65, 0xf6, 0x23, 0xbe, 0x88, 0x5d, 0xfa, 0x60, 0x5a, - 0x43, 0x99, 0xb0, 0xad, 0x87, 0x53, 0xaa, 0x24, 0x98, 0x62, 0xc5, 0xbe, 0xbf, 0x6d, 0x69, 0xf4, - 0x98, 0xb6, 0xa5, 0xd0, 0xf9, 0x7d, 0xec, 0x97, 0xe9, 0xfc, 0x9e, 0x7f, 0x4b, 0x39, 0xbf, 0xbf, - 0x9a, 0x83, 0x99, 0xf8, 0x09, 0xe4, 0xe4, 0x23, 0xc2, 0x7e, 0xdb, 0x80, 0x19, 0xb9, 0x7a, 0x38, - 0x4f, 0x22, 0x5f, 0x0d, 0xd6, 0x52, 0x5a, 0xb4, 0xfc, 0x2c, 0xa5, 0x62, 0x96, 0x37, 0x62, 0xdc, - 0x70, 0x0f, 0x7f, 0xf4, 0x02, 0x8c, 0x2b, 0xe3, 0xfa, 0xb1, 0xc2, 0xc3, 0xa6, 0xd9, 0x29, 0x2a, - 0x24, 0x81, 0x75, 0x7a, 0xe8, 0x55, 0x03, 0xa0, 0x26, 0xd5, 0x9c, 0x5c, 0x5d, 0x57, 0xd3, 0x5a, - 0x5d, 0x4a, 0x81, 0x86, 0x87, 0x65, 0x55, 0xe4, 0x63, 0x8d, 0x31, 0xfa, 0x02, 0x33, 0xab, 0xab, - 0xd3, 0x1d, 0x5d, 0x4f, 0xd9, 0xe1, 0x1d, 0x7b, 0x0f, 0x39, 0x98, 0x86, 0x47, 0x29, 0x0d, 0xe4, - 0xe3, 0x88, 0x10, 0xe6, 0x53, 0xa0, 0x5c, 0x31, 0xe9, 0xb6, 0xc5, 0x9c, 0x31, 0x2b, 0x56, 0xb0, - 0x2d, 0xa6, 0xa0, 0xda, 0xb6, 0x2e, 0x48, 0x00, 0x0e, 0x71, 0xcc, 0x8f, 0xc2, 0xd4, 0xb3, 0x9e, - 0xd5, 0xde, 0xb6, 0x99, 0xf9, 0x9a, 0xde, 0x93, 0xde, 0x09, 0x63, 0x56, 0xbd, 0x9e, 0x14, 0xf1, - 0x5f, 0xe2, 0xc5, 0x58, 0xc2, 0x07, 0xbb, 0x12, 0x7d, 0xdb, 0x00, 0x14, 0x3e, 0x01, 0xda, 0x4e, - 0x63, 0x9d, 0xde, 0xf6, 0xe9, 0xfd, 0x68, 0x9b, 0x95, 0x26, 0xdd, 0x8f, 0x2e, 0x2a, 0x08, 0xd6, - 0xb0, 0xd0, 0x4b, 0x30, 0xce, 0xff, 0x5d, 0x57, 0x97, 0xfd, 0xa1, 0xdd, 0xfb, 0xb9, 0x42, 0x61, - 0x32, 0xf1, 0x59, 0x78, 0x31, 0xe4, 0x80, 0x75, 0x76, 0xb4, 0xab, 0x56, 0x9d, 0xad, 0x66, 0xe7, - 0x56, 0x7d, 0x33, 0xec, 0xaa, 0xb6, 0xe7, 0x6e, 0xd9, 0x4d, 0x12, 0xef, 0xaa, 0x0a, 0x2f, 0xc6, - 0x12, 0x3e, 0x58, 0x57, 0x7d, 0xd3, 0x80, 0xb9, 0x55, 0x3f, 0xb0, 0xdd, 0x15, 0xe2, 0x07, 0x54, - 0xad, 0xd0, 0xcd, 0xa7, 0xd3, 0x1c, 0xc4, 0xab, 0x7a, 0x05, 0x66, 0xc4, 0x73, 0x64, 0x67, 0xd3, - 0x27, 0x81, 0x76, 0x8e, 0x57, 0xeb, 0x78, 0x39, 0x06, 0xc7, 0x3d, 0x35, 0x28, 0x15, 0xf1, 0x2e, - 0x19, 0x52, 0xc9, 0x46, 0xa9, 0x54, 0x63, 0x70, 0xdc, 0x53, 0xc3, 0xfc, 0x5e, 0x16, 0x4e, 0xb1, - 0x66, 0xc4, 0x22, 0x22, 0x3e, 0xd7, 0x2f, 0x22, 0x62, 0xc8, 0xa5, 0xcc, 0x78, 0x1d, 0x23, 0x1e, - 0xe2, 0xb7, 0x0c, 0x98, 0xae, 0x47, 0x7b, 0x3a, 0x1d, 0xf3, 0x4c, 0xd2, 0x18, 0x72, 0xef, 0xab, - 0x58, 0x21, 0x8e, 0xf3, 0x47, 0x5f, 0x34, 0x60, 0x3a, 0x2a, 0xa6, 0xdc, 0xdd, 0x4f, 0xa0, 0x93, - 0x94, 0xbb, 0x74, 0xb4, 0xdc, 0xc7, 0x71, 0x11, 0xcc, 0xef, 0x66, 0xc4, 0x90, 0x9e, 0x84, 0xbb, - 0x3f, 0xda, 0x83, 0x42, 0xd0, 0xf4, 0x79, 0xa1, 0x68, 0xed, 0x90, 0x37, 0xc2, 0x8d, 0xb5, 0x2a, - 0xf7, 0x04, 0x08, 0x0f, 0x6d, 0xa2, 0x84, 0x1e, 0x3e, 0x25, 0x2f, 0xc6, 0xb8, 0xd6, 0x16, 0x8c, - 0x53, 0xb9, 0x8a, 0x6e, 0x2c, 0x57, 0xe2, 0x8c, 0x45, 0x09, 0x65, 0x2c, 0x79, 0x99, 0x5f, 0x31, - 0xa0, 0x70, 0xc9, 0x95, 0xfb, 0xc8, 0x87, 0x53, 0x30, 0xf4, 0xa8, 0xf3, 0xa0, 0x7a, 0x71, 0x0c, - 0xaf, 0x18, 0xcf, 0x44, 0xcc, 0x3c, 0xf7, 0x6b, 0xb4, 0x17, 0x59, 0x36, 0x23, 0x4a, 0xea, 0x92, - 0xbb, 0xd9, 0xd7, 0x8a, 0xf8, 0x07, 0x39, 0x98, 0x7c, 0xce, 0xda, 0x27, 0x4e, 0x60, 0x1d, 0x5d, - 0x49, 0x3c, 0x01, 0xe3, 0x56, 0x9b, 0x3d, 0x69, 0x69, 0x67, 0xfc, 0xd0, 0x72, 0x12, 0x82, 0xb0, - 0x8e, 0x17, 0x6e, 0x68, 0x3c, 0xb9, 0x4a, 0xd2, 0x56, 0xb4, 0x1c, 0x83, 0xe3, 0x9e, 0x1a, 0xe8, - 0x12, 0x20, 0x11, 0x2a, 0x5a, 0xaa, 0xd5, 0xdc, 0x8e, 0xc3, 0xb7, 0x34, 0x6e, 0x54, 0x51, 0x97, - 0xcd, 0xf5, 0x1e, 0x0c, 0x9c, 0x50, 0x0b, 0x7d, 0x08, 0xe6, 0x6b, 0x8c, 0xb2, 0xb8, 0x7a, 0xe8, - 0x14, 0xf9, 0xf5, 0x53, 0xb9, 0xfc, 0x2f, 0xf7, 0xc1, 0xc3, 0x7d, 0x29, 0x50, 0x49, 0xfd, 0xc0, - 0xf5, 0xac, 0x06, 0xd1, 0xe9, 0x8e, 0x46, 0x25, 0xad, 0xf6, 0x60, 0xe0, 0x84, 0x5a, 0xe8, 0x93, - 0x50, 0x08, 0xb6, 0x3d, 0xe2, 0x6f, 0xbb, 0xcd, 0xba, 0x70, 0x41, 0x18, 0xd2, 0xd2, 0x26, 0x46, - 0x7f, 0x43, 0x52, 0xd5, 0xa6, 0xb7, 0x2c, 0xc2, 0x21, 0x4f, 0xe4, 0xc1, 0xa8, 0x5f, 0x73, 0xdb, - 0xc4, 0x17, 0x47, 0xf6, 0x4b, 0xa9, 0x70, 0x67, 0x96, 0x23, 0xcd, 0xc6, 0xc7, 0x38, 0x60, 0xc1, - 0xc9, 0xfc, 0x56, 0x06, 0x26, 0x74, 0xc4, 0x01, 0xf6, 0xa6, 0x4f, 0x1b, 0x30, 0x51, 0x73, 0x9d, - 0xc0, 0x73, 0x9b, 0xdc, 0x7e, 0x95, 0xce, 0x89, 0x82, 0x92, 0x5a, 0x21, 0x81, 0x65, 0x37, 0x35, - 0x53, 0x98, 0xc6, 0x06, 0x47, 0x98, 0xa2, 0xcf, 0x1a, 0x30, 0x1d, 0x7a, 0xac, 0x85, 0x86, 0xb4, - 0x54, 0x05, 0x51, 0x5b, 0xfd, 0xf9, 0x28, 0x27, 0x1c, 0x67, 0x6d, 0x6e, 0xc2, 0x4c, 0x7c, 0xb4, - 0x69, 0x57, 0xb6, 0x2d, 0xb1, 0xd6, 0xb3, 0x61, 0x57, 0x56, 0x2c, 0xdf, 0xc7, 0x0c, 0x82, 0x1e, - 0x81, 0x7c, 0xcb, 0xf2, 0x1a, 0xb6, 0x63, 0x35, 0x59, 0x2f, 0x66, 0xb5, 0x0d, 0x49, 0x94, 0x63, - 0x85, 0x61, 0xbe, 0x1b, 0x26, 0xd6, 0x2d, 0xa7, 0x41, 0xea, 0x62, 0x1f, 0xbe, 0x73, 0xc0, 0xd9, - 0x4f, 0x47, 0x60, 0x5c, 0xbb, 0x9b, 0x9d, 0xfc, 0x3d, 0x2b, 0x92, 0xef, 0x22, 0x9b, 0x62, 0xbe, - 0x8b, 0xe7, 0x01, 0xb6, 0x6c, 0xc7, 0xf6, 0xb7, 0x8f, 0x99, 0x49, 0x83, 0x3d, 0xd1, 0x5e, 0x50, - 0x14, 0xb0, 0x46, 0x2d, 0x7c, 0x07, 0xcb, 0x1d, 0x92, 0x5f, 0xe8, 0x55, 0x43, 0x53, 0x37, 0xa3, - 0x69, 0xbc, 0xfb, 0x6b, 0x03, 0xb3, 0x28, 0xd5, 0xcf, 0x79, 0x27, 0xf0, 0xf6, 0x0f, 0xd5, 0x4a, - 0x1b, 0x90, 0xf7, 0x88, 0xdf, 0x69, 0xd1, 0x1b, 0xe3, 0xd8, 0x91, 0xbb, 0x81, 0x79, 0x60, 0x60, - 0x51, 0x1f, 0x2b, 0x4a, 0x0b, 0x4f, 0xc1, 0x64, 0x44, 0x04, 0x34, 0x03, 0xd9, 0x1d, 0xb2, 0xcf, - 0xe7, 0x09, 0xa6, 0x3f, 0xd1, 0x5c, 0xe4, 0xb5, 0x50, 0x74, 0xcb, 0xfb, 0x32, 0x4f, 0x1a, 0xa6, - 0x0b, 0x89, 0x06, 0x80, 0xe3, 0x3c, 0xe6, 0xd0, 0xb1, 0x68, 0x6a, 0xa9, 0x34, 0xd4, 0x58, 0x70, - 0x3f, 0x1b, 0x0e, 0x33, 0x7f, 0x3e, 0x0a, 0xe2, 0x29, 0x7b, 0x80, 0xed, 0x4a, 0x7f, 0xc1, 0xca, - 0x1c, 0xe3, 0x05, 0xeb, 0x12, 0x4c, 0xd8, 0x8e, 0x1d, 0xd8, 0x56, 0x93, 0x19, 0x77, 0x84, 0x3a, - 0x95, 0x8e, 0xc8, 0x13, 0xab, 0x1a, 0x2c, 0x81, 0x4e, 0xa4, 0x2e, 0xba, 0x0a, 0x39, 0xa6, 0x6f, - 0xc4, 0x04, 0x3e, 0xfa, 0x7b, 0x3b, 0x73, 0xb5, 0xe0, 0xd1, 0x49, 0x9c, 0x12, 0xbb, 0x7c, 0xf0, - 0x5c, 0x22, 0xea, 0xfa, 0x2d, 0xe6, 0x71, 0x78, 0xf9, 0x88, 0xc1, 0x71, 0x4f, 0x0d, 0x4a, 0x65, - 0xcb, 0xb2, 0x9b, 0x1d, 0x8f, 0x84, 0x54, 0x46, 0xa3, 0x54, 0x2e, 0xc4, 0xe0, 0xb8, 0xa7, 0x06, - 0xda, 0x82, 0x09, 0x51, 0xc6, 0xbd, 0xa7, 0xc6, 0x8e, 0xd9, 0x4a, 0xe6, 0x25, 0x77, 0x41, 0xa3, - 0x84, 0x23, 0x74, 0x51, 0x07, 0x66, 0x6d, 0xa7, 0xe6, 0x3a, 0xb5, 0x66, 0xc7, 0xb7, 0x77, 0x49, - 0x18, 0x1a, 0x74, 0x1c, 0x66, 0xa7, 0x0f, 0xba, 0xc5, 0xd9, 0xd5, 0x38, 0x39, 0xdc, 0xcb, 0x01, - 0xbd, 0x62, 0xc0, 0xe9, 0x9a, 0xeb, 0xf8, 0x2c, 0x38, 0x7f, 0x97, 0x9c, 0xf7, 0x3c, 0xd7, 0xe3, - 0xbc, 0x0b, 0xc7, 0xe4, 0xcd, 0x6c, 0x8a, 0xcb, 0x49, 0x24, 0x71, 0x32, 0x27, 0xf4, 0x22, 0xe4, - 0xdb, 0x9e, 0xbb, 0x6b, 0xd7, 0x89, 0x27, 0x3c, 0xf1, 0xd6, 0xd2, 0x48, 0x16, 0x52, 0x11, 0x34, - 0xc3, 0xad, 0x47, 0x96, 0x60, 0xc5, 0xcf, 0x7c, 0xa3, 0x00, 0x53, 0x51, 0x74, 0xf4, 0x09, 0x80, - 0xb6, 0xe7, 0xb6, 0x48, 0xb0, 0x4d, 0x54, 0x88, 0xc7, 0xe5, 0x61, 0x73, 0x52, 0x48, 0x7a, 0xd2, - 0x7b, 0x85, 0x6e, 0x17, 0x61, 0x29, 0xd6, 0x38, 0x22, 0x0f, 0xc6, 0x76, 0xb8, 0xda, 0x15, 0xa7, - 0x90, 0xe7, 0x52, 0x39, 0x33, 0x09, 0xce, 0x2c, 0x36, 0x41, 0x14, 0x61, 0xc9, 0x08, 0x6d, 0x42, - 0x76, 0x8f, 0x6c, 0xa6, 0x13, 0x10, 0x7d, 0x83, 0x88, 0xdb, 0x4c, 0x79, 0xec, 0xa0, 0x5b, 0xcc, - 0xde, 0x20, 0x9b, 0x98, 0x12, 0xa7, 0xed, 0xaa, 0xf3, 0x77, 0x78, 0xb1, 0x55, 0x0c, 0xd9, 0xae, - 0xc8, 0xa3, 0x3e, 0x6f, 0x97, 0x28, 0xc2, 0x92, 0x11, 0x7a, 0x11, 0x0a, 0x7b, 0xd6, 0x2e, 0xd9, - 0xf2, 0x5c, 0x27, 0x10, 0x2e, 0x53, 0x43, 0x7a, 0xfd, 0xdf, 0x90, 0xe4, 0x04, 0x5f, 0xa6, 0xde, - 0x55, 0x21, 0x0e, 0xd9, 0xa1, 0x5d, 0xc8, 0x3b, 0x64, 0x0f, 0x93, 0xa6, 0x5d, 0x4b, 0xc7, 0xcb, - 0xfe, 0xb2, 0xa0, 0x26, 0x38, 0x33, 0xbd, 0x27, 0xcb, 0xb0, 0xe2, 0x45, 0xc7, 0xf2, 0xa6, 0xbb, - 0x29, 0x36, 0xaa, 0x21, 0xc7, 0x52, 0xdd, 0x4c, 0xf9, 0x58, 0x5e, 0x72, 0x37, 0x31, 0x25, 0x4e, - 0xd7, 0x48, 0x4d, 0xf9, 0xeb, 0x88, 0x6d, 0xea, 0x72, 0xba, 0x7e, 0x4a, 0x7c, 0x8d, 0x84, 0xa5, - 0x58, 0xe3, 0x48, 0xfb, 0xb6, 0x21, 0x8c, 0x95, 0x62, 0xa3, 0x1a, 0xb2, 0x6f, 0xa3, 0xa6, 0x4f, - 0xde, 0xb7, 0xb2, 0x0c, 0x2b, 0x5e, 0x94, 0xaf, 0x2d, 0x2c, 0x7f, 0xe9, 0x6c, 0x55, 0x51, 0x3b, - 0x22, 0xe7, 0x2b, 0xcb, 0xb0, 0xe2, 0x65, 0x7e, 0x65, 0x14, 0x26, 0xf4, 0xa4, 0x6c, 0x03, 0x9c, - 0x11, 0xd4, 0xb9, 0x38, 0x73, 0x94, 0x73, 0x31, 0xbd, 0x08, 0x69, 0x6f, 0x1c, 0xd2, 0x08, 0xb3, - 0x9a, 0xda, 0xb1, 0x30, 0xbc, 0x08, 0x69, 0x85, 0x3e, 0x8e, 0x30, 0x3d, 0x82, 0xdb, 0x03, 0x3d, - 0x5c, 0xf1, 0xe3, 0x47, 0x2e, 0x7a, 0xb8, 0x8a, 0x1c, 0x28, 0x1e, 0x05, 0x08, 0x93, 0x93, 0x89, - 0xb7, 0x2f, 0x75, 0x6a, 0xd3, 0x92, 0xa6, 0x69, 0x58, 0xe8, 0x21, 0x18, 0xa5, 0x0a, 0x9a, 0xd4, - 0x45, 0xdc, 0xaf, 0xba, 0x6d, 0x5e, 0x60, 0xa5, 0x58, 0x40, 0xd1, 0x93, 0xf4, 0x2c, 0x15, 0xaa, - 0x55, 0x11, 0xce, 0x3b, 0x17, 0x9e, 0xa5, 0x42, 0x18, 0x8e, 0x60, 0x52, 0xd1, 0x09, 0xd5, 0x82, - 0x6c, 0x06, 0x6b, 0xa2, 0x33, 0xd5, 0x88, 0x39, 0x8c, 0x59, 0x3f, 0x62, 0x5a, 0x93, 0xcd, 0xbc, - 0x9c, 0x66, 0xfd, 0x88, 0xc1, 0x71, 0x4f, 0x0d, 0xda, 0x18, 0xf1, 0x6c, 0x37, 0xce, 0xbd, 0x3b, - 0xfb, 0x3c, 0xb8, 0xbd, 0xa6, 0xdf, 0x08, 0x26, 0xd8, 0xd0, 0xbf, 0x3f, 0xbd, 0x04, 0x83, 0x83, - 0x5f, 0x09, 0x86, 0x3b, 0xbc, 0x7f, 0x14, 0xa6, 0xa2, 0x7b, 0x65, 0xea, 0xf6, 0xf9, 0xbf, 0xc9, - 0xc2, 0xa9, 0xcb, 0x0d, 0xdb, 0x89, 0x27, 0x1c, 0x4a, 0x4a, 0xfc, 0x6b, 0x1c, 0x35, 0xf1, 0x6f, - 0x18, 0x40, 0x24, 0x32, 0x2b, 0x27, 0x07, 0x10, 0xc9, 0xb4, 0xcb, 0x51, 0x5c, 0xf4, 0x13, 0x03, - 0xee, 0xb7, 0xea, 0xfc, 0xf4, 0x6a, 0x35, 0x45, 0x69, 0xc8, 0x54, 0xae, 0x68, 0x7f, 0x48, 0x5d, - 0xd4, 0xdb, 0xf8, 0xc5, 0xd2, 0x21, 0x5c, 0xf9, 0x88, 0xbf, 0x43, 0xb4, 0xe0, 0xfe, 0xc3, 0x50, - 0xf1, 0xa1, 0xe2, 0x2f, 0x5c, 0x81, 0xb7, 0xdf, 0x91, 0xd1, 0x91, 0x66, 0xcb, 0xa7, 0x0d, 0x28, - 0x70, 0xf3, 0x29, 0x26, 0x5b, 0x74, 0xab, 0xb0, 0xda, 0xf6, 0x75, 0xe2, 0xf9, 0x32, 0x23, 0x99, - 0x76, 0xc1, 0x2b, 0x55, 0x56, 0x05, 0x04, 0x6b, 0x58, 0x74, 0x33, 0xde, 0xb1, 0x9d, 0xba, 0x18, - 0x26, 0xb5, 0x19, 0x3f, 0x67, 0x3b, 0x75, 0xcc, 0x20, 0x6a, 0xbb, 0xce, 0xf6, 0x35, 0x6b, 0xbc, - 0x61, 0xc0, 0x14, 0x8b, 0x9a, 0x0c, 0xaf, 0x1e, 0x4f, 0x28, 0x9f, 0x16, 0x2e, 0xc6, 0xd9, 0xa8, - 0x4f, 0xcb, 0xed, 0x6e, 0x71, 0x9c, 0xc7, 0x59, 0x46, 0x5d, 0x5c, 0x3e, 0x28, 0xec, 0x15, 0xcc, - 0xf3, 0x26, 0x73, 0xe4, 0xeb, 0xb4, 0xb2, 0xe7, 0x55, 0x25, 0x11, 0x1c, 0xd2, 0x33, 0x5f, 0x82, - 0x09, 0x3d, 0xfc, 0x01, 0x3d, 0x01, 0xe3, 0x6d, 0xdb, 0x69, 0x44, 0xc3, 0xe4, 0x94, 0x4d, 0xb7, - 0x12, 0x82, 0xb0, 0x8e, 0xc7, 0xaa, 0xb9, 0x61, 0xb5, 0x98, 0x29, 0xb8, 0xe2, 0xea, 0xd5, 0xc2, - 0x3f, 0xe6, 0x9f, 0x66, 0xe1, 0x54, 0x42, 0x98, 0x0d, 0x7a, 0xd5, 0x80, 0x51, 0xe6, 0xa5, 0x2f, - 0xbd, 0x56, 0x5e, 0x48, 0x3d, 0x94, 0x67, 0x91, 0x05, 0x03, 0x88, 0x79, 0xac, 0xb6, 0x4f, 0x5e, - 0x88, 0x05, 0x73, 0xf4, 0xbb, 0x06, 0x8c, 0x5b, 0xda, 0x52, 0xe3, 0x8e, 0x3c, 0x9b, 0xe9, 0x0b, - 0xd3, 0xb3, 0xb2, 0x34, 0x07, 0xc4, 0x70, 0x21, 0xe9, 0xb2, 0x2c, 0xbc, 0x17, 0xc6, 0xb5, 0x26, - 0x1c, 0x65, 0x85, 0x2c, 0x3c, 0x03, 0x33, 0x43, 0xad, 0xb0, 0x0f, 0xc0, 0x51, 0x13, 0xec, 0x51, - 0x85, 0xb5, 0xa7, 0x87, 0x32, 0xab, 0x1e, 0x17, 0xb1, 0xcc, 0x02, 0x6a, 0x6e, 0xc2, 0x4c, 0xfc, - 0x72, 0x95, 0xfa, 0xbb, 0xf5, 0xbb, 0xe1, 0x88, 0x29, 0xf1, 0xcc, 0xf3, 0x80, 0xb0, 0xdb, 0x6c, - 0x6e, 0x5a, 0xb5, 0x9d, 0x1b, 0xb6, 0x53, 0x77, 0xf7, 0xd8, 0x5a, 0x59, 0x82, 0x82, 0x27, 0xa2, - 0xa8, 0x7c, 0xd1, 0x2c, 0xb5, 0xd8, 0x64, 0x78, 0x95, 0x8f, 0x43, 0x1c, 0xf3, 0xbb, 0x19, 0x18, - 0x13, 0x21, 0x7f, 0x77, 0xc1, 0x05, 0x78, 0x27, 0xf2, 0x36, 0xb4, 0x9a, 0x4a, 0xa4, 0x62, 0x5f, - 0xff, 0x5f, 0x3f, 0xe6, 0xff, 0xfb, 0x5c, 0x3a, 0xec, 0x0e, 0x77, 0xfe, 0x7d, 0x63, 0x04, 0xa6, - 0x63, 0x21, 0x94, 0xf4, 0xc4, 0xd3, 0xe3, 0xf3, 0x76, 0x2d, 0xd5, 0x28, 0x4d, 0xe5, 0x9e, 0x7e, - 0xb8, 0xfb, 0x9b, 0x1f, 0x49, 0x60, 0x7a, 0x35, 0xb5, 0xdc, 0xe7, 0xbf, 0xca, 0x65, 0x7a, 0x54, - 0x77, 0xae, 0x7f, 0x32, 0xe0, 0xde, 0xbe, 0x91, 0xb6, 0x2c, 0x51, 0x8b, 0x17, 0x85, 0x8a, 0x05, - 0x99, 0x72, 0x3e, 0x01, 0xf5, 0x50, 0x13, 0xcf, 0xad, 0x11, 0x67, 0x8f, 0x1e, 0x87, 0x09, 0xa6, - 0xa1, 0xe9, 0xd6, 0x14, 0x90, 0xb6, 0xb0, 0x33, 0x33, 0x8b, 0x63, 0x55, 0x2b, 0xc7, 0x11, 0x2c, - 0xf3, 0xcb, 0x06, 0xcc, 0xf7, 0x4b, 0xdb, 0x31, 0xc0, 0xfd, 0xf2, 0xff, 0xc5, 0x7c, 0x94, 0x8b, - 0x3d, 0x3e, 0xca, 0xb1, 0x1b, 0xa6, 0x74, 0x47, 0xd6, 0x2e, 0x77, 0xd9, 0x3b, 0xb8, 0xe0, 0x7e, - 0xce, 0x80, 0x33, 0x7d, 0x56, 0x53, 0x8f, 0xaf, 0xba, 0x71, 0x6c, 0x5f, 0xf5, 0xcc, 0xa0, 0xbe, - 0xea, 0xe6, 0xf7, 0xb3, 0x30, 0x23, 0xe4, 0x09, 0x8f, 0x69, 0x4f, 0x46, 0x3c, 0xbd, 0xdf, 0x11, - 0xf3, 0xf4, 0x9e, 0x8b, 0xe3, 0xff, 0xca, 0xcd, 0xfb, 0xad, 0xe5, 0xe6, 0xfd, 0x8b, 0x0c, 0x9c, - 0x4e, 0xcc, 0x26, 0x82, 0x3e, 0x93, 0xa0, 0x1a, 0x6e, 0xa4, 0x9c, 0xb6, 0x64, 0x40, 0xe5, 0x30, - 0xac, 0x6f, 0xf4, 0x17, 0x75, 0x9f, 0x64, 0xbe, 0xd5, 0x6f, 0x9d, 0x40, 0x02, 0x96, 0x23, 0xba, - 0x27, 0x9b, 0xbf, 0x99, 0x85, 0x87, 0x07, 0x25, 0xf4, 0x16, 0x0d, 0x5f, 0xf1, 0x23, 0xe1, 0x2b, - 0x77, 0x49, 0x6d, 0x9f, 0x48, 0x24, 0xcb, 0x57, 0xb2, 0x4a, 0xed, 0xf5, 0xce, 0xcf, 0x81, 0x1e, - 0x25, 0xc7, 0xe8, 0xd1, 0x4e, 0xe6, 0x18, 0x0d, 0xb7, 0xc2, 0xb1, 0x2a, 0x2f, 0xbe, 0xdd, 0x2d, - 0xce, 0x86, 0x31, 0xed, 0xa2, 0x10, 0xcb, 0x4a, 0xe8, 0x61, 0xc8, 0x7b, 0x1c, 0x2a, 0x1d, 0xf6, - 0xc5, 0xcb, 0x2e, 0x2f, 0xc3, 0x0a, 0x8a, 0x3e, 0xa9, 0x9d, 0x85, 0x47, 0x4e, 0x2a, 0x75, 0xc3, - 0x61, 0x0f, 0xd6, 0x2f, 0x40, 0xde, 0x97, 0xd9, 0x42, 0xf9, 0xab, 0xc2, 0x63, 0x03, 0xc6, 0x81, - 0xd0, 0x1b, 0x98, 0x4c, 0x1d, 0xca, 0xdb, 0xa7, 0x12, 0x8b, 0x2a, 0x92, 0xc8, 0x54, 0x97, 0x1f, - 0x6e, 0xaa, 0x84, 0x84, 0x8b, 0xcf, 0x0f, 0x0c, 0x18, 0x17, 0xa3, 0x75, 0x17, 0x42, 0x53, 0x6e, - 0x46, 0x43, 0x53, 0xce, 0xa7, 0xb2, 0x77, 0xf4, 0x89, 0x4b, 0xb9, 0x09, 0x13, 0x7a, 0x42, 0x29, - 0xf4, 0xbc, 0xb6, 0xf7, 0x19, 0xc3, 0xa4, 0x68, 0x91, 0xbb, 0x63, 0xb8, 0x2f, 0x9a, 0x5f, 0x2d, - 0xa8, 0x5e, 0x64, 0x57, 0x34, 0x7d, 0x0e, 0x1a, 0x87, 0xce, 0x41, 0x7d, 0x0a, 0x64, 0xd2, 0x9f, - 0x02, 0x57, 0x21, 0x2f, 0x37, 0x28, 0xa1, 0xc6, 0x1f, 0xd4, 0x9d, 0xf5, 0xe8, 0x59, 0x80, 0x12, - 0xd3, 0x26, 0x2e, 0xbb, 0x6a, 0xa9, 0x31, 0x54, 0x1b, 0xa7, 0x22, 0x83, 0x5e, 0x84, 0xf1, 0x3d, - 0xd7, 0xdb, 0x69, 0xba, 0x16, 0xcb, 0x03, 0x0c, 0x69, 0xbc, 0x0f, 0x29, 0xbb, 0x19, 0xf7, 0x98, - 0xbe, 0x11, 0xd2, 0xc7, 0x3a, 0x33, 0x54, 0x82, 0xe9, 0x96, 0xed, 0x60, 0x62, 0xd5, 0x55, 0x04, - 0xca, 0x08, 0x4f, 0x54, 0x2a, 0x0f, 0xb9, 0xeb, 0x51, 0x30, 0x8e, 0xe3, 0xa3, 0xcf, 0x1a, 0x30, - 0xe5, 0x45, 0x2e, 0xd5, 0x22, 0x1b, 0x61, 0x65, 0xf8, 0xc9, 0x18, 0xbd, 0xa8, 0x73, 0x97, 0xe1, - 0x68, 0x39, 0x8e, 0xf1, 0x46, 0x1f, 0x87, 0xbc, 0x2f, 0xb2, 0x45, 0xa5, 0xf3, 0xb0, 0xa8, 0xae, - 0xb0, 0x9c, 0x68, 0x38, 0x94, 0xb2, 0x04, 0x2b, 0x86, 0x68, 0x0d, 0xe6, 0xa4, 0x95, 0x20, 0xf2, - 0xad, 0x96, 0xd1, 0x30, 0xb9, 0x08, 0x4e, 0x80, 0xe3, 0xc4, 0x5a, 0xf4, 0x50, 0xc5, 0x12, 0xb5, - 0xf1, 0x97, 0x0e, 0xed, 0x71, 0x80, 0xad, 0xbf, 0x3a, 0x16, 0xd0, 0xc3, 0x02, 0xac, 0xf2, 0x43, - 0x04, 0x58, 0x55, 0xe1, 0x74, 0x1c, 0xc4, 0xb2, 0xc6, 0xb0, 0x44, 0x35, 0x9a, 0x32, 0xab, 0x24, - 0x21, 0xe1, 0xe4, 0xba, 0xe8, 0x06, 0x14, 0x3c, 0xc2, 0xae, 0x3b, 0x25, 0xe9, 0xca, 0x70, 0x64, - 0xa7, 0x2d, 0x2c, 0x09, 0xe0, 0x90, 0x16, 0x1d, 0x77, 0x2b, 0x9a, 0x3a, 0xf4, 0x6a, 0x8a, 0x5f, - 0x9b, 0x13, 0x63, 0xdf, 0x27, 0x9b, 0x93, 0xf9, 0xe6, 0x14, 0x4c, 0x46, 0x4c, 0x1d, 0xe8, 0x41, - 0xc8, 0xb1, 0x34, 0x3a, 0x6c, 0xb7, 0xca, 0x87, 0x3b, 0x2a, 0xef, 0x1c, 0x0e, 0x43, 0x9f, 0x37, - 0x60, 0xba, 0x1d, 0xb1, 0x2d, 0xcb, 0x8d, 0x7c, 0xc8, 0xd7, 0xcb, 0xa8, 0xc1, 0x5a, 0x4b, 0xba, - 0x1d, 0x65, 0x86, 0xe3, 0xdc, 0xe9, 0x7e, 0x20, 0x3c, 0x1f, 0x9b, 0xc4, 0x63, 0xd8, 0xe2, 0xc8, - 0xa5, 0x48, 0x2c, 0x47, 0xc1, 0x38, 0x8e, 0x4f, 0x47, 0x98, 0xb5, 0x6e, 0x98, 0xcf, 0x50, 0x95, - 0x24, 0x01, 0x1c, 0xd2, 0x42, 0xcf, 0xc0, 0x94, 0xc8, 0x18, 0x59, 0x71, 0xeb, 0x17, 0x2d, 0x7f, - 0x5b, 0xdc, 0x35, 0xd4, 0xdd, 0x68, 0x39, 0x02, 0xc5, 0x31, 0x6c, 0xd6, 0xb6, 0x30, 0x2d, 0x27, - 0x23, 0x30, 0x1a, 0xcd, 0x49, 0xbe, 0x1c, 0x05, 0xe3, 0x38, 0x3e, 0x7a, 0x44, 0x53, 0x43, 0xfc, - 0xf5, 0x51, 0xed, 0x06, 0x09, 0xaa, 0xa8, 0x04, 0xd3, 0x1d, 0x76, 0x35, 0xab, 0x4b, 0xa0, 0x58, - 0x8f, 0x8a, 0xe1, 0xb5, 0x28, 0x18, 0xc7, 0xf1, 0xd1, 0x53, 0x30, 0xe9, 0xd1, 0xcd, 0x56, 0x11, - 0xe0, 0x4f, 0x92, 0xea, 0xc5, 0x09, 0xeb, 0x40, 0x1c, 0xc5, 0x45, 0xcf, 0xc2, 0x6c, 0x98, 0x60, - 0x4d, 0x12, 0xe0, 0x6f, 0x94, 0x2a, 0xdb, 0x4f, 0x29, 0x8e, 0x80, 0x7b, 0xeb, 0xa0, 0x5f, 0x83, - 0x19, 0xad, 0x27, 0x56, 0x9d, 0x3a, 0xb9, 0x25, 0x92, 0x60, 0xb1, 0xcf, 0x47, 0x2c, 0xc7, 0x60, - 0xb8, 0x07, 0x1b, 0xbd, 0x0f, 0xa6, 0x6a, 0x6e, 0xb3, 0xc9, 0xf6, 0x38, 0x9e, 0x0f, 0x9b, 0x67, - 0xbb, 0xe2, 0x79, 0xc1, 0x22, 0x10, 0x1c, 0xc3, 0x44, 0x97, 0x00, 0xb9, 0x9b, 0x3e, 0xf1, 0x76, - 0x49, 0xfd, 0x59, 0xfe, 0x61, 0x5b, 0x7a, 0xe2, 0x98, 0x8c, 0xfa, 0x5d, 0x5f, 0xe9, 0xc1, 0xc0, - 0x09, 0xb5, 0x58, 0xb2, 0x20, 0x2d, 0x4e, 0x6d, 0x2a, 0x8d, 0x4f, 0x32, 0xc5, 0x0d, 0x09, 0x77, - 0x0c, 0x52, 0xf3, 0x60, 0x94, 0xbb, 0xc1, 0xa7, 0x93, 0xf6, 0x4a, 0x4f, 0x8d, 0x1b, 0xea, 0x08, - 0x5e, 0x8a, 0x05, 0x27, 0xf4, 0x09, 0x28, 0x6c, 0xca, 0x3c, 0xe9, 0x2c, 0xd7, 0xd5, 0xd0, 0x7a, - 0x31, 0x96, 0xf2, 0x3f, 0xbc, 0x28, 0x2b, 0x00, 0x0e, 0x59, 0xa2, 0x87, 0x60, 0xfc, 0x62, 0xa5, - 0xa4, 0x66, 0xe1, 0x2c, 0x1b, 0xfd, 0x11, 0x5a, 0x05, 0xeb, 0x00, 0xba, 0xc2, 0xd4, 0xf1, 0x0d, - 0xb1, 0x21, 0x0e, 0xf5, 0x6d, 0xef, 0x69, 0x8c, 0x62, 0xb3, 0x47, 0x56, 0x5c, 0x9d, 0x3f, 0x15, - 0xc3, 0x16, 0xe5, 0x58, 0x61, 0xa0, 0x17, 0x60, 0x5c, 0xe8, 0x0b, 0xb6, 0x37, 0xcd, 0x1d, 0x2f, - 0x06, 0x12, 0x87, 0x24, 0xb0, 0x4e, 0x8f, 0xbd, 0x9d, 0xb1, 0xf4, 0xd1, 0xe4, 0x42, 0xa7, 0xd9, - 0x9c, 0x3f, 0xcd, 0xf6, 0xcd, 0xf0, 0xed, 0x2c, 0x04, 0x61, 0x1d, 0x0f, 0x3d, 0x26, 0xfd, 0x41, - 0xde, 0x16, 0x79, 0x4c, 0x54, 0xfe, 0x20, 0xea, 0xd0, 0xdd, 0xc7, 0x4d, 0xfa, 0xcc, 0x1d, 0x1c, - 0x31, 0x36, 0x61, 0x41, 0x9e, 0xf8, 0x7a, 0x17, 0xc9, 0xfc, 0x7c, 0xc4, 0x68, 0xb1, 0x70, 0xa3, - 0x2f, 0x26, 0x3e, 0x84, 0x0a, 0xda, 0x84, 0xac, 0xd5, 0xdc, 0x9c, 0xbf, 0x37, 0x8d, 0xa3, 0xab, - 0xfa, 0x50, 0x35, 0x77, 0x6d, 0x2a, 0xad, 0x95, 0x31, 0x25, 0x6e, 0xbe, 0x92, 0x51, 0x8f, 0x04, - 0x2a, 0x1d, 0xe8, 0x4b, 0xfa, 0xac, 0x36, 0xd2, 0xf8, 0x10, 0x6b, 0xcf, 0xc7, 0x04, 0xb8, 0x42, - 0x4a, 0x9c, 0xd3, 0x6d, 0xb5, 0x8e, 0x53, 0xc9, 0xce, 0x12, 0x4d, 0x75, 0xca, 0x2f, 0x97, 0xd1, - 0x55, 0x6c, 0xfe, 0x38, 0xaf, 0x6c, 0x62, 0x31, 0x07, 0x07, 0x0f, 0x72, 0xb6, 0x1f, 0xd8, 0x6e, - 0x8a, 0xf1, 0x7a, 0xb1, 0x1c, 0xa1, 0xcc, 0x1d, 0x98, 0x01, 0x30, 0x67, 0x45, 0x79, 0x3a, 0x0d, - 0xdb, 0xb9, 0x25, 0x9a, 0x7f, 0x35, 0x75, 0xcf, 0x05, 0xce, 0x93, 0x01, 0x30, 0x67, 0x85, 0x6e, - 0xf2, 0x99, 0x96, 0xce, 0x47, 0x77, 0xe3, 0xdf, 0xd2, 0x8e, 0xce, 0x38, 0xca, 0xcb, 0x6f, 0xd9, - 0xe2, 0x0c, 0x33, 0x24, 0xaf, 0xea, 0xfa, 0x6a, 0x12, 0xaf, 0xea, 0xfa, 0x2a, 0xa6, 0x4c, 0xd0, - 0x6b, 0x06, 0x80, 0xa5, 0x3e, 0x2a, 0x9d, 0xce, 0x97, 0x37, 0xfa, 0x7d, 0xa4, 0x9a, 0x7b, 0xf0, - 0x85, 0x50, 0xac, 0x71, 0x46, 0x2f, 0xc2, 0x98, 0xc5, 0xbf, 0x1b, 0x24, 0x9c, 0x23, 0xd3, 0xf9, - 0x18, 0x56, 0x4c, 0x02, 0xe6, 0x15, 0x2a, 0x40, 0x58, 0x32, 0xa4, 0xbc, 0x03, 0xcf, 0x22, 0x5b, - 0xf6, 0x8e, 0xf0, 0x92, 0xac, 0x0e, 0x9d, 0xfe, 0x9b, 0x12, 0x4b, 0xe2, 0x2d, 0x40, 0x58, 0x32, - 0xe4, 0xdf, 0x71, 0xb5, 0x1c, 0x4b, 0x85, 0xbc, 0xa4, 0x13, 0x18, 0xa5, 0x07, 0xd1, 0x68, 0xdf, - 0x71, 0xd5, 0x19, 0xe1, 0x28, 0x5f, 0xb4, 0x0b, 0xa3, 0x16, 0xfb, 0xa2, 0x99, 0xb8, 0x1f, 0xe1, - 0x34, 0xbe, 0x8e, 0x16, 0xeb, 0x03, 0xb6, 0xb9, 0x88, 0xef, 0xa6, 0x09, 0x6e, 0xe6, 0xcf, 0xb2, - 0x00, 0x4c, 0x04, 0x1e, 0xfe, 0xdd, 0x62, 0x29, 0x03, 0xb7, 0xdd, 0x7a, 0x3a, 0x1f, 0x69, 0xd3, - 0xa3, 0xb8, 0x41, 0xe4, 0x07, 0xdc, 0x76, 0xeb, 0x58, 0x30, 0x41, 0x0d, 0x18, 0x69, 0x5b, 0xc1, - 0x76, 0xfa, 0x21, 0xe3, 0x79, 0x1e, 0x07, 0x15, 0x6c, 0x63, 0xc6, 0x00, 0xbd, 0x6c, 0xc0, 0x18, - 0x0f, 0x1a, 0x97, 0x16, 0xf7, 0xa1, 0x9f, 0x95, 0x65, 0x9f, 0x2d, 0xf2, 0xc8, 0x74, 0xe1, 0xfa, - 0xa1, 0x54, 0xb2, 0x28, 0xc5, 0x92, 0xed, 0xc2, 0xab, 0x06, 0x4c, 0xe8, 0xa8, 0x09, 0x4e, 0x1b, - 0x1f, 0xd1, 0x9d, 0x36, 0xd2, 0xec, 0x0f, 0xdd, 0xff, 0xe3, 0x5f, 0x0d, 0xd0, 0xbe, 0xba, 0x1b, - 0xba, 0x6c, 0x1a, 0x03, 0xbb, 0x6c, 0x66, 0x8e, 0xe8, 0xb2, 0x99, 0x3d, 0x92, 0xcb, 0xe6, 0xc8, - 0xd1, 0x5d, 0x36, 0x73, 0xfd, 0x5d, 0x36, 0xcd, 0xd7, 0x0d, 0x98, 0xed, 0xd9, 0x87, 0xe9, 0xb1, - 0xcd, 0x73, 0xdd, 0xa0, 0x8f, 0xa7, 0x14, 0x0e, 0x41, 0x58, 0xc7, 0x43, 0x2b, 0x30, 0x23, 0x12, - 0x64, 0x57, 0xdb, 0x4d, 0x3b, 0x31, 0x9c, 0x7f, 0x23, 0x06, 0xc7, 0x3d, 0x35, 0xcc, 0xbf, 0x34, - 0x60, 0x5c, 0x0b, 0x02, 0xa4, 0xed, 0x60, 0xc1, 0x92, 0x42, 0x8c, 0x30, 0x37, 0x38, 0x7b, 0xe1, - 0xe0, 0x30, 0xfe, 0xd8, 0xd6, 0xd0, 0xd2, 0xa7, 0x86, 0x8f, 0x6d, 0xb4, 0x14, 0x0b, 0x28, 0x4f, - 0x8c, 0x49, 0xda, 0xac, 0xd3, 0xb3, 0x7a, 0x62, 0x4c, 0xd2, 0xc6, 0x0c, 0xc2, 0xd8, 0xd1, 0xf3, - 0xab, 0xf0, 0xe6, 0xd5, 0x52, 0x91, 0x5b, 0x5e, 0x80, 0x39, 0x0c, 0x9d, 0x85, 0x2c, 0x71, 0xea, - 0xe2, 0xb2, 0xad, 0x3e, 0xff, 0x75, 0xde, 0xa9, 0x63, 0x5a, 0x6e, 0x5e, 0x81, 0x89, 0x2a, 0xa9, - 0x79, 0x24, 0x78, 0x8e, 0xec, 0x0f, 0xfc, 0x3d, 0x31, 0x3a, 0xdb, 0x63, 0xdf, 0x13, 0xa3, 0xd5, - 0x69, 0xb9, 0xf9, 0x27, 0x06, 0xc4, 0xf2, 0xe5, 0x6b, 0x86, 0x77, 0xa3, 0x9f, 0xe1, 0x3d, 0x62, - 0x22, 0xce, 0x1c, 0x6a, 0x22, 0xbe, 0x04, 0xa8, 0x45, 0x97, 0x42, 0xe4, 0xeb, 0x10, 0xc2, 0xce, - 0x11, 0x86, 0x1c, 0xf7, 0x60, 0xe0, 0x84, 0x5a, 0xe6, 0x1f, 0x73, 0x61, 0xf5, 0x0c, 0xfa, 0x77, - 0xee, 0x80, 0x0e, 0xe4, 0x18, 0x29, 0x61, 0xec, 0x19, 0xd2, 0x50, 0xda, 0x9b, 0xba, 0x23, 0x1c, - 0x48, 0xb1, 0xe4, 0x19, 0x37, 0xf3, 0xfb, 0x5c, 0x56, 0x2d, 0xc5, 0xfe, 0x00, 0xb2, 0xb6, 0xa2, - 0xb2, 0x5e, 0x4c, 0x6b, 0xaf, 0x4c, 0x96, 0x11, 0x2d, 0x02, 0xb4, 0x89, 0x57, 0x23, 0x4e, 0x20, - 0x9d, 0xcc, 0x73, 0x22, 0x28, 0x47, 0x95, 0x62, 0x0d, 0xc3, 0x7c, 0xd9, 0x80, 0x99, 0x6a, 0x60, - 0xd7, 0x76, 0x6c, 0x87, 0x07, 0x99, 0x6d, 0xd9, 0x0d, 0x7a, 0x3b, 0x22, 0xe2, 0x53, 0x59, 0xdc, - 0xfc, 0xa6, 0xb6, 0x62, 0xf9, 0x85, 0x2c, 0x09, 0x47, 0x25, 0x98, 0x96, 0x8f, 0x0e, 0xd2, 0x66, - 0xca, 0x83, 0x63, 0x95, 0x8d, 0x66, 0x25, 0x0a, 0xc6, 0x71, 0x7c, 0xf3, 0x93, 0x30, 0xae, 0xed, - 0xaf, 0x6c, 0x2b, 0xba, 0x65, 0xd5, 0x82, 0xf8, 0x12, 0x3e, 0x4f, 0x0b, 0x31, 0x87, 0x31, 0xd3, - 0x2e, 0xf7, 0x42, 0x8e, 0x2d, 0x61, 0xe1, 0x7b, 0x2c, 0xa0, 0x94, 0x98, 0x47, 0x1a, 0xe4, 0x96, - 0x4c, 0xd4, 0x2a, 0x89, 0x61, 0x5a, 0x88, 0x39, 0xcc, 0x7c, 0x04, 0xf2, 0x32, 0x85, 0x01, 0x8b, - 0x03, 0x96, 0x66, 0x47, 0x3d, 0x0e, 0xd8, 0xf5, 0x02, 0xcc, 0x20, 0xe6, 0x75, 0xc8, 0xcb, 0x4c, - 0x0b, 0x77, 0xc6, 0xa6, 0xab, 0xca, 0x77, 0xec, 0x8b, 0xae, 0x1f, 0xc8, 0xf4, 0x10, 0xfc, 0x65, - 0xe4, 0xf2, 0x2a, 0x2b, 0xc3, 0x0a, 0x6a, 0xce, 0xc2, 0xb4, 0x7a, 0xf2, 0x10, 0x6e, 0xa1, 0xdf, - 0xca, 0xc2, 0x44, 0xe4, 0xeb, 0xd3, 0x77, 0x9e, 0x6e, 0x83, 0xaf, 0xe2, 0x84, 0xa7, 0x8b, 0xec, - 0x11, 0x9f, 0x2e, 0xf4, 0xb7, 0xa2, 0x91, 0x93, 0x7d, 0x2b, 0xca, 0xa5, 0xf3, 0x56, 0x14, 0xc0, - 0x98, 0x2f, 0x14, 0xd5, 0x68, 0x1a, 0x46, 0x9c, 0xd8, 0x88, 0xf1, 0xb3, 0xb1, 0xd4, 0x77, 0x92, - 0x95, 0xf9, 0xf5, 0x1c, 0x4c, 0x45, 0x73, 0x4c, 0x0d, 0x30, 0x92, 0x8f, 0xf4, 0x8c, 0xe4, 0x11, - 0x6d, 0xa5, 0xd9, 0x61, 0x6d, 0xa5, 0x23, 0xc3, 0xda, 0x4a, 0x73, 0xc7, 0xb0, 0x95, 0xf6, 0x5a, - 0x3a, 0x47, 0x07, 0xb6, 0x74, 0x3e, 0xad, 0xfc, 0x8e, 0xc6, 0x22, 0x0f, 0xf5, 0xa1, 0xdf, 0x11, - 0x8a, 0x0e, 0xc3, 0xb2, 0x5b, 0x4f, 0xf4, 0xdf, 0xca, 0xdf, 0xc1, 0x26, 0xe4, 0x25, 0xba, 0x09, - 0x1d, 0xfd, 0x39, 0xe6, 0x6d, 0x47, 0x70, 0x11, 0x7a, 0x02, 0xc6, 0xc5, 0x7c, 0x62, 0x67, 0x25, - 0x88, 0x9e, 0xb3, 0xaa, 0x21, 0x08, 0xeb, 0x78, 0xec, 0x4b, 0xa2, 0xd1, 0x4f, 0xa7, 0x32, 0xd3, - 0xb3, 0xfe, 0x25, 0xd1, 0xd8, 0xa7, 0x56, 0xe3, 0xf8, 0xe6, 0xc7, 0xe1, 0x74, 0xe2, 0x4d, 0x90, - 0x99, 0xc6, 0x98, 0x1a, 0x27, 0x75, 0x81, 0xa0, 0x89, 0x11, 0x4b, 0x41, 0xbc, 0x70, 0xa3, 0x2f, - 0x26, 0x3e, 0x84, 0x8a, 0xf9, 0xb5, 0x2c, 0x4c, 0x45, 0x3f, 0x43, 0x85, 0xf6, 0x94, 0xdd, 0x28, - 0x15, 0x93, 0x15, 0x27, 0xab, 0xe5, 0x2d, 0xea, 0x6b, 0x04, 0xde, 0x63, 0xf3, 0x6b, 0x53, 0x25, - 0x51, 0x3a, 0x39, 0xc6, 0xc2, 0xfa, 0x2a, 0xd8, 0xb1, 0x2f, 0x4d, 0x85, 0xc1, 0x23, 0xe2, 0xda, - 0x95, 0x3a, 0xf7, 0x30, 0x1c, 0x44, 0xb1, 0xc2, 0x1a, 0x5b, 0xaa, 0x5b, 0x76, 0x89, 0x67, 0x6f, - 0xd9, 0xea, 0x13, 0x9a, 0x6c, 0xe7, 0xbe, 0x2e, 0xca, 0xb0, 0x82, 0x9a, 0x2f, 0x67, 0x20, 0xfc, - 0x60, 0x30, 0xfb, 0x56, 0x8b, 0xaf, 0x1d, 0x71, 0xc5, 0xb0, 0x5d, 0x1a, 0xf6, 0x83, 0x48, 0x21, - 0x45, 0xe1, 0x13, 0xaa, 0x95, 0xe0, 0x08, 0xc7, 0x5f, 0xc2, 0x87, 0x82, 0x2d, 0x98, 0x8e, 0x85, - 0xd4, 0xa6, 0xee, 0xbf, 0xff, 0xd3, 0x2c, 0x14, 0x54, 0x50, 0x32, 0x7a, 0x6f, 0xc4, 0xde, 0x50, - 0x28, 0xbf, 0x5d, 0xfb, 0x90, 0xc0, 0xb6, 0x5b, 0xbf, 0xdd, 0x2d, 0x4e, 0x2b, 0xe4, 0x98, 0xed, - 0xe0, 0x2c, 0x64, 0x3b, 0x5e, 0x33, 0x7e, 0xa1, 0xb8, 0x86, 0xd7, 0x30, 0x2d, 0x47, 0xb7, 0xe2, - 0x17, 0xfe, 0xf5, 0x94, 0x02, 0xa9, 0xf9, 0xc9, 0xbb, 0xff, 0x45, 0x9f, 0x6a, 0xc9, 0x4d, 0xb7, - 0xbe, 0x1f, 0xff, 0xf0, 0x40, 0xd9, 0xad, 0xef, 0x63, 0x06, 0x41, 0xcf, 0xc0, 0x54, 0x60, 0xb7, - 0x88, 0xdb, 0x09, 0xf4, 0xcf, 0xb1, 0x66, 0xc3, 0x47, 0xcd, 0x8d, 0x08, 0x14, 0xc7, 0xb0, 0xa9, - 0x96, 0xbd, 0xe9, 0xbb, 0x0e, 0xcb, 0x26, 0x38, 0x1a, 0x7d, 0x01, 0xb9, 0x54, 0xbd, 0x72, 0x99, - 0xd9, 0x3d, 0x14, 0x06, 0xc5, 0xb6, 0x59, 0x04, 0xa2, 0x47, 0x84, 0x4f, 0xc1, 0x4c, 0x98, 0x9f, - 0x82, 0x97, 0x63, 0x85, 0x81, 0x56, 0x38, 0x6d, 0x2a, 0x2d, 0xd3, 0x28, 0x13, 0xe5, 0x87, 0x25, - 0x5d, 0x5a, 0x76, 0xbb, 0x5b, 0x9c, 0x27, 0x4e, 0xcd, 0xad, 0xdb, 0x4e, 0x63, 0x89, 0x22, 0x2e, - 0x62, 0x6b, 0x4f, 0xaa, 0x1a, 0x55, 0xd3, 0xbc, 0x06, 0xd3, 0xb1, 0x0e, 0x93, 0x17, 0x40, 0x23, - 0xf9, 0x02, 0x38, 0xd8, 0xb7, 0x02, 0xfe, 0xcc, 0x80, 0xd9, 0x9e, 0x2d, 0x60, 0xd0, 0xf0, 0x94, - 0xb8, 0x32, 0xca, 0x1c, 0x5f, 0x19, 0x65, 0x8f, 0xa6, 0x8c, 0xca, 0x9b, 0xdf, 0x79, 0xf3, 0xdc, - 0x3d, 0xdf, 0x7b, 0xf3, 0xdc, 0x3d, 0x3f, 0x7c, 0xf3, 0xdc, 0x3d, 0x2f, 0x1f, 0x9c, 0x33, 0xbe, - 0x73, 0x70, 0xce, 0xf8, 0xde, 0xc1, 0x39, 0xe3, 0x87, 0x07, 0xe7, 0x8c, 0x7f, 0x3c, 0x38, 0x67, - 0xbc, 0xfe, 0xd3, 0x73, 0xf7, 0x3c, 0xff, 0x74, 0x38, 0x41, 0x97, 0xe4, 0x04, 0x65, 0x3f, 0xde, - 0x25, 0xa7, 0xe3, 0x52, 0x7b, 0xa7, 0xb1, 0x44, 0x27, 0xe8, 0x92, 0x2a, 0x91, 0x13, 0xf4, 0xbf, - 0x02, 0x00, 0x00, 0xff, 0xff, 0x3e, 0xb7, 0xa2, 0x97, 0xc8, 0x95, 0x00, 0x00, + // 7827 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5b, 0x6c, 0x24, 0xd7, + 0x75, 0xa0, 0xaa, 0x9b, 0x4d, 0x76, 0x1f, 0xbe, 0xef, 0x70, 0x3c, 0x14, 0xa5, 0x99, 0x96, 0x4b, + 0x86, 0x56, 0xde, 0x95, 0x49, 0x5b, 0x8f, 0x5d, 0xd9, 0x12, 0xb4, 0xdb, 0x4d, 0xce, 0x68, 0x38, + 0x22, 0x39, 0x3d, 0xb7, 0x39, 0x33, 0xb6, 0x6c, 0xd9, 0x2e, 0x76, 0x5f, 0x36, 0x6b, 0xd8, 0x5d, + 0xd5, 0xae, 0xaa, 0x26, 0x87, 0xb2, 0x60, 0x4b, 0x36, 0xa4, 0xf5, 0x2e, 0x6c, 0x58, 0xbb, 0xb6, + 0xb1, 0x58, 0x2c, 0xb0, 0x30, 0x16, 0x06, 0x36, 0x89, 0xfd, 0x65, 0x24, 0xc8, 0x8f, 0x81, 0x04, + 0xf1, 0x23, 0xce, 0x87, 0x03, 0xfb, 0x23, 0xf1, 0x03, 0x70, 0x27, 0xa2, 0xf3, 0x93, 0x20, 0x81, + 0x11, 0xc0, 0x41, 0xe0, 0xf9, 0x0a, 0xee, 0xb3, 0x6e, 0x55, 0x57, 0x73, 0x9a, 0xec, 0xe2, 0x58, + 0x48, 0xfc, 0xd7, 0x7d, 0xcf, 0xb9, 0xe7, 0x9c, 0xfb, 0x3c, 0xf7, 0x9e, 0x7b, 0xce, 0x29, 0x58, + 0x6b, 0xd8, 0xc1, 0x4e, 0x67, 0x6b, 0xb1, 0xe6, 0xb6, 0x96, 0x2c, 0xaf, 0xe1, 0xb6, 0x3d, 0xf7, + 0x16, 0xfb, 0xf1, 0x1e, 0xcf, 0x6d, 0x36, 0xdd, 0x4e, 0xe0, 0x2f, 0xb5, 0x77, 0x1b, 0x4b, 0x56, + 0xdb, 0xf6, 0x97, 0x54, 0xc9, 0xde, 0xfb, 0xac, 0x66, 0x7b, 0xc7, 0x7a, 0xdf, 0x52, 0x83, 0x38, + 0xc4, 0xb3, 0x02, 0x52, 0x5f, 0x6c, 0x7b, 0x6e, 0xe0, 0xa2, 0x67, 0x43, 0x6a, 0x8b, 0x92, 0x1a, + 0xfb, 0xf1, 0x31, 0x59, 0x77, 0xb1, 0xbd, 0xdb, 0x58, 0xa4, 0xd4, 0x16, 0x55, 0x89, 0xa4, 0xb6, + 0xf0, 0x1e, 0x4d, 0x96, 0x86, 0xdb, 0x70, 0x97, 0x18, 0xd1, 0xad, 0xce, 0x36, 0xfb, 0xc7, 0xfe, + 0xb0, 0x5f, 0x9c, 0xd9, 0xc2, 0xc3, 0xbb, 0x4f, 0xfb, 0x8b, 0xb6, 0x4b, 0x65, 0x5b, 0xda, 0xb2, + 0x82, 0xda, 0xce, 0xd2, 0x5e, 0x8f, 0x44, 0x0b, 0xa6, 0x86, 0x54, 0x73, 0x3d, 0x92, 0x84, 0xf3, + 0x64, 0x88, 0xd3, 0xb2, 0x6a, 0x3b, 0xb6, 0x43, 0xbc, 0x83, 0xb0, 0xd5, 0x2d, 0x12, 0x58, 0x49, + 0xb5, 0x96, 0xfa, 0xd5, 0xf2, 0x3a, 0x4e, 0x60, 0xb7, 0x48, 0x4f, 0x85, 0xff, 0x78, 0xb7, 0x0a, + 0x7e, 0x6d, 0x87, 0xb4, 0xac, 0x9e, 0x7a, 0x4f, 0xf4, 0xab, 0xd7, 0x09, 0xec, 0xe6, 0x92, 0xed, + 0x04, 0x7e, 0xe0, 0xc5, 0x2b, 0x99, 0xdf, 0xc9, 0x42, 0xa1, 0xb4, 0x56, 0xae, 0x06, 0x56, 0xd0, + 0xf1, 0xd1, 0x1b, 0x06, 0x4c, 0x34, 0x5d, 0xab, 0x5e, 0xb6, 0x9a, 0x96, 0x53, 0x23, 0xde, 0xbc, + 0xf1, 0x90, 0xf1, 0xe8, 0xf8, 0xe3, 0x6b, 0x8b, 0xc3, 0x8c, 0xd7, 0x62, 0x69, 0xdf, 0xc7, 0xc4, + 0x77, 0x3b, 0x5e, 0x8d, 0x60, 0xb2, 0x5d, 0x9e, 0xfb, 0x7e, 0xb7, 0x78, 0xdf, 0x61, 0xb7, 0x38, + 0xb1, 0xa6, 0x71, 0xc2, 0x11, 0xbe, 0xe8, 0x2b, 0x06, 0xcc, 0xd6, 0x2c, 0xc7, 0xf2, 0x0e, 0x36, + 0x2d, 0xaf, 0x41, 0x82, 0xe7, 0x3d, 0xb7, 0xd3, 0x9e, 0xcf, 0x9c, 0x82, 0x34, 0xf7, 0x0b, 0x69, + 0x66, 0x97, 0xe3, 0xec, 0x70, 0xaf, 0x04, 0x4c, 0x2e, 0x3f, 0xb0, 0xb6, 0x9a, 0x44, 0x97, 0x2b, + 0x7b, 0x9a, 0x72, 0x55, 0xe3, 0xec, 0x70, 0xaf, 0x04, 0xe6, 0xeb, 0x59, 0x98, 0x2d, 0xad, 0x95, + 0x37, 0x3d, 0x6b, 0x7b, 0xdb, 0xae, 0x61, 0xb7, 0x13, 0xd8, 0x4e, 0x03, 0xbd, 0x1b, 0xc6, 0x6c, + 0xa7, 0xe1, 0x11, 0xdf, 0x67, 0x03, 0x59, 0x28, 0x4f, 0x0b, 0xa2, 0x63, 0xab, 0xbc, 0x18, 0x4b, + 0x38, 0x7a, 0x0a, 0xc6, 0x7d, 0xe2, 0xed, 0xd9, 0x35, 0x52, 0x71, 0xbd, 0x80, 0xf5, 0x74, 0xae, + 0x7c, 0x46, 0xa0, 0x8f, 0x57, 0x43, 0x10, 0xd6, 0xf1, 0x68, 0x35, 0xcf, 0x75, 0x03, 0x01, 0x67, + 0x1d, 0x51, 0x08, 0xab, 0xe1, 0x10, 0x84, 0x75, 0x3c, 0xf4, 0xa6, 0x01, 0x33, 0x7e, 0x60, 0xd7, + 0x76, 0x6d, 0x87, 0xf8, 0xfe, 0xb2, 0xeb, 0x6c, 0xdb, 0x8d, 0xf9, 0x1c, 0xeb, 0xc5, 0x8d, 0xe1, + 0x7a, 0xb1, 0x1a, 0xa3, 0x5a, 0x9e, 0x3b, 0xec, 0x16, 0x67, 0xe2, 0xa5, 0xb8, 0x87, 0x3b, 0x5a, + 0x81, 0x19, 0xcb, 0x71, 0xdc, 0xc0, 0x0a, 0x6c, 0xd7, 0xa9, 0x78, 0x64, 0xdb, 0xbe, 0x3d, 0x3f, + 0xc2, 0x9a, 0x33, 0x2f, 0x9a, 0x33, 0x53, 0x8a, 0xc1, 0x71, 0x4f, 0x0d, 0x73, 0x05, 0xe6, 0x4b, + 0xad, 0x2d, 0xcb, 0xf7, 0xad, 0xba, 0xeb, 0xc5, 0x46, 0xe3, 0x51, 0xc8, 0xb7, 0xac, 0x76, 0xdb, + 0x76, 0x1a, 0x74, 0x38, 0xb2, 0x8f, 0x16, 0xca, 0x13, 0x87, 0xdd, 0x62, 0x7e, 0x5d, 0x94, 0x61, + 0x05, 0x35, 0x7f, 0x9a, 0x81, 0xf1, 0x92, 0x63, 0x35, 0x0f, 0x7c, 0xdb, 0xc7, 0x1d, 0x07, 0x7d, + 0x1c, 0xf2, 0x74, 0x77, 0xa9, 0x5b, 0x81, 0x25, 0x56, 0xe4, 0x7b, 0x17, 0xf9, 0x62, 0x5f, 0xd4, + 0x17, 0x7b, 0xd8, 0x2f, 0x14, 0x7b, 0x71, 0xef, 0x7d, 0x8b, 0x57, 0xb7, 0x6e, 0x91, 0x5a, 0xb0, + 0x4e, 0x02, 0xab, 0x8c, 0x44, 0x2b, 0x20, 0x2c, 0xc3, 0x8a, 0x2a, 0x72, 0x61, 0xc4, 0x6f, 0x93, + 0x9a, 0x58, 0x61, 0xeb, 0x43, 0xce, 0xe4, 0x50, 0xf4, 0x6a, 0x9b, 0xd4, 0xca, 0x13, 0x82, 0xf5, + 0x08, 0xfd, 0x87, 0x19, 0x23, 0xb4, 0x0f, 0xa3, 0x3e, 0xdb, 0x73, 0xc4, 0xe2, 0xb9, 0x9a, 0x1e, + 0x4b, 0x46, 0xb6, 0x3c, 0x25, 0x98, 0x8e, 0xf2, 0xff, 0x58, 0xb0, 0x33, 0x7f, 0x66, 0xc0, 0x19, + 0x0d, 0xbb, 0xe4, 0x35, 0x3a, 0x2d, 0xe2, 0x04, 0xe8, 0x21, 0x18, 0x71, 0xac, 0x16, 0x11, 0x0b, + 0x45, 0x89, 0xbc, 0x61, 0xb5, 0x08, 0x66, 0x10, 0xf4, 0x30, 0xe4, 0xf6, 0xac, 0x66, 0x87, 0xb0, + 0x4e, 0x2a, 0x94, 0x27, 0x05, 0x4a, 0xee, 0x06, 0x2d, 0xc4, 0x1c, 0x86, 0x5e, 0x81, 0x02, 0xfb, + 0x71, 0xc9, 0x73, 0x5b, 0x29, 0x35, 0x4d, 0x48, 0x78, 0x43, 0x92, 0x2d, 0x4f, 0x1e, 0x76, 0x8b, + 0x05, 0xf5, 0x17, 0x87, 0x0c, 0xcd, 0xbf, 0x32, 0x60, 0x5a, 0x6b, 0xdc, 0x9a, 0xed, 0x07, 0xe8, + 0x23, 0x3d, 0x93, 0x67, 0x71, 0xb0, 0xc9, 0x43, 0x6b, 0xb3, 0xa9, 0x33, 0x23, 0x5a, 0x9a, 0x97, + 0x25, 0xda, 0xc4, 0x71, 0x20, 0x67, 0x07, 0xa4, 0xe5, 0xcf, 0x67, 0x1e, 0xca, 0x3e, 0x3a, 0xfe, + 0xf8, 0x6a, 0x6a, 0xc3, 0x18, 0xf6, 0xef, 0x2a, 0xa5, 0x8f, 0x39, 0x1b, 0xf3, 0x9b, 0x23, 0x91, + 0x16, 0xd2, 0x19, 0x85, 0x5c, 0x18, 0x6b, 0x91, 0xc0, 0xb3, 0x6b, 0x7c, 0x5d, 0x8d, 0x3f, 0xbe, + 0x32, 0x9c, 0x14, 0xeb, 0x8c, 0x58, 0xb8, 0x59, 0xf2, 0xff, 0x3e, 0x96, 0x5c, 0xd0, 0x0e, 0x8c, + 0x58, 0x5e, 0x43, 0xb6, 0xf9, 0x52, 0x3a, 0xe3, 0x1b, 0xce, 0xb9, 0x92, 0xd7, 0xf0, 0x31, 0xe3, + 0x80, 0x96, 0xa0, 0x10, 0x10, 0xaf, 0x65, 0x3b, 0x56, 0xc0, 0x77, 0xd7, 0x7c, 0x79, 0x56, 0xa0, + 0x15, 0x36, 0x25, 0x00, 0x87, 0x38, 0xa8, 0x09, 0xa3, 0x75, 0xef, 0x00, 0x77, 0x9c, 0xf9, 0x91, + 0x34, 0xba, 0x62, 0x85, 0xd1, 0x0a, 0x17, 0x13, 0xff, 0x8f, 0x05, 0x0f, 0xf4, 0x35, 0x03, 0xe6, + 0x5a, 0xc4, 0xf2, 0x3b, 0x1e, 0xa1, 0x4d, 0xc0, 0x24, 0x20, 0x0e, 0xdd, 0x0d, 0xe7, 0x73, 0x8c, + 0x39, 0x1e, 0x76, 0x1c, 0x7a, 0x29, 0x97, 0x1f, 0x14, 0xa2, 0xcc, 0x25, 0x41, 0x71, 0xa2, 0x34, + 0xe6, 0x4f, 0x47, 0x60, 0xb6, 0x67, 0x87, 0x40, 0x4f, 0x42, 0xae, 0xbd, 0x63, 0xf9, 0x72, 0xc9, + 0x5f, 0x90, 0xf3, 0xad, 0x42, 0x0b, 0xef, 0x74, 0x8b, 0x93, 0xb2, 0x0a, 0x2b, 0xc0, 0x1c, 0x99, + 0xea, 0xd4, 0x16, 0xf1, 0x7d, 0xab, 0x21, 0xf7, 0x01, 0x6d, 0x9a, 0xb0, 0x62, 0x2c, 0xe1, 0xe8, + 0xbf, 0x1a, 0x30, 0xc9, 0xa7, 0x0c, 0x26, 0x7e, 0xa7, 0x19, 0xd0, 0xbd, 0x8e, 0x76, 0xcb, 0x95, + 0x34, 0xa6, 0x27, 0x27, 0x59, 0x3e, 0x2b, 0xb8, 0x4f, 0xea, 0xa5, 0x3e, 0x8e, 0xf2, 0x45, 0x37, + 0xa1, 0xe0, 0x07, 0x96, 0x17, 0x90, 0x7a, 0x29, 0x60, 0x5a, 0x6d, 0xfc, 0xf1, 0x7f, 0x3f, 0xd8, + 0x26, 0xb0, 0x69, 0xb7, 0x08, 0xdf, 0x70, 0xaa, 0x92, 0x00, 0x0e, 0x69, 0xa1, 0x57, 0x00, 0xbc, + 0x8e, 0x53, 0xed, 0xb4, 0x5a, 0x96, 0x77, 0x20, 0x34, 0xf8, 0xe5, 0xe1, 0x9a, 0x87, 0x15, 0xbd, + 0x50, 0x67, 0x85, 0x65, 0x58, 0xe3, 0x87, 0x5e, 0x33, 0x60, 0x92, 0xcf, 0x44, 0x29, 0xc1, 0x68, + 0xca, 0x12, 0xcc, 0xd2, 0xae, 0x5d, 0xd1, 0x59, 0xe0, 0x28, 0x47, 0xf3, 0x2f, 0xa2, 0xfa, 0xa4, + 0x1a, 0xd0, 0xd3, 0x75, 0xe3, 0x00, 0x7d, 0x18, 0xee, 0xf7, 0x3b, 0xb5, 0x1a, 0xf1, 0xfd, 0xed, + 0x4e, 0x13, 0x77, 0x9c, 0xcb, 0xb6, 0x1f, 0xb8, 0xde, 0xc1, 0x9a, 0xdd, 0xb2, 0x03, 0x36, 0xe3, + 0x72, 0xe5, 0xf3, 0x87, 0xdd, 0xe2, 0xfd, 0xd5, 0x7e, 0x48, 0xb8, 0x7f, 0x7d, 0x64, 0xc1, 0x03, + 0x1d, 0xa7, 0x3f, 0x79, 0x7e, 0x7a, 0x2b, 0x1e, 0x76, 0x8b, 0x0f, 0x5c, 0xef, 0x8f, 0x86, 0x8f, + 0xa2, 0x61, 0xfe, 0x9d, 0x01, 0x33, 0xb2, 0x5d, 0x9b, 0xa4, 0xd5, 0x6e, 0xd2, 0xdd, 0xe5, 0xf4, + 0x0f, 0x22, 0x41, 0xe4, 0x20, 0x82, 0xd3, 0x51, 0x27, 0x52, 0xfe, 0x7e, 0xa7, 0x11, 0xf3, 0x6f, + 0x0d, 0x98, 0x8b, 0x23, 0xdf, 0x03, 0xe5, 0xe9, 0x47, 0x95, 0xe7, 0x46, 0xba, 0xad, 0xed, 0xa3, + 0x41, 0xdf, 0x18, 0xe9, 0x6d, 0xeb, 0xbf, 0x76, 0x35, 0x1a, 0x6a, 0xc5, 0xec, 0x6f, 0x52, 0x2b, + 0x8e, 0xbc, 0xad, 0xb4, 0xe2, 0xef, 0x8c, 0xc0, 0x44, 0xc9, 0x09, 0xec, 0xd2, 0xf6, 0xb6, 0xed, + 0xd8, 0xc1, 0x01, 0xfa, 0x7c, 0x06, 0x96, 0xda, 0x1e, 0xd9, 0x26, 0x9e, 0x47, 0xea, 0x2b, 0x1d, + 0xcf, 0x76, 0x1a, 0xd5, 0xda, 0x0e, 0xa9, 0x77, 0x9a, 0xb6, 0xd3, 0x58, 0x6d, 0x38, 0xae, 0x2a, + 0xbe, 0x78, 0x9b, 0xd4, 0x3a, 0xac, 0x49, 0x7c, 0x51, 0xb4, 0x86, 0x6b, 0x52, 0xe5, 0x78, 0x4c, + 0xcb, 0x4f, 0x1c, 0x76, 0x8b, 0x4b, 0xc7, 0xac, 0x84, 0x8f, 0xdb, 0x34, 0xf4, 0xb9, 0x0c, 0x2c, + 0x7a, 0xe4, 0x13, 0x1d, 0x7b, 0xf0, 0xde, 0xe0, 0xbb, 0x56, 0x73, 0x48, 0xf5, 0x73, 0x2c, 0x9e, + 0xe5, 0xc7, 0x0f, 0xbb, 0xc5, 0x63, 0xd6, 0xc1, 0xc7, 0x6c, 0x97, 0x59, 0x81, 0xf1, 0x52, 0xdb, + 0xf6, 0xed, 0xdb, 0xf4, 0x2e, 0x4b, 0x06, 0xb8, 0x2b, 0x15, 0x21, 0xe7, 0x75, 0x9a, 0x84, 0xaf, + 0xed, 0x42, 0xb9, 0x40, 0x77, 0x21, 0x4c, 0x0b, 0x30, 0x2f, 0x37, 0x3f, 0x43, 0x77, 0x5c, 0x46, + 0x32, 0x76, 0x4b, 0xbe, 0x05, 0x39, 0x8f, 0x32, 0x11, 0x33, 0x6b, 0xd8, 0x0b, 0x45, 0x28, 0xb5, + 0x10, 0x82, 0xfe, 0xc4, 0x9c, 0x85, 0xf9, 0xed, 0x0c, 0x9c, 0x2d, 0xb5, 0xdb, 0xeb, 0xc4, 0xdf, + 0x89, 0x49, 0xf1, 0x45, 0x03, 0xa6, 0xf6, 0x6c, 0x2f, 0xe8, 0x58, 0x4d, 0x69, 0xdb, 0xe0, 0xf2, + 0x54, 0x87, 0x95, 0x87, 0x71, 0xbb, 0x11, 0x21, 0x5d, 0x46, 0x87, 0xdd, 0xe2, 0x54, 0xb4, 0x0c, + 0xc7, 0xd8, 0xa3, 0xff, 0x65, 0xc0, 0x8c, 0x28, 0xda, 0x70, 0xeb, 0x44, 0x37, 0x88, 0x5d, 0x4f, + 0x53, 0x26, 0x45, 0x9c, 0x5b, 0x4e, 0xe2, 0xa5, 0xb8, 0x47, 0x08, 0xf3, 0x1f, 0x32, 0x70, 0xae, + 0x0f, 0x0d, 0xf4, 0xff, 0x0d, 0x98, 0xe3, 0x56, 0x34, 0x0d, 0x84, 0xc9, 0xb6, 0xe8, 0xcd, 0x0f, + 0xa5, 0x2d, 0x39, 0xa6, 0x4b, 0x9c, 0x38, 0x35, 0x52, 0x9e, 0xa7, 0xbb, 0xe1, 0x72, 0x02, 0x6b, + 0x9c, 0x28, 0x10, 0x93, 0x94, 0xdb, 0xd5, 0x62, 0x92, 0x66, 0xee, 0x89, 0xa4, 0xd5, 0x04, 0xd6, + 0x38, 0x51, 0x20, 0xf3, 0x3f, 0xc3, 0x03, 0x47, 0x90, 0xbb, 0xfb, 0xe2, 0x34, 0x5f, 0x52, 0xb3, + 0x3e, 0x3a, 0xe7, 0x06, 0x58, 0xd7, 0x26, 0x8c, 0xb2, 0xa5, 0x23, 0x17, 0x36, 0x50, 0xf5, 0xc7, + 0xd6, 0x94, 0x8f, 0x05, 0xc4, 0xfc, 0xb6, 0x01, 0xf9, 0x63, 0x98, 0x55, 0x8a, 0x51, 0xb3, 0x4a, + 0xa1, 0xc7, 0xa4, 0x12, 0xf4, 0x9a, 0x54, 0x9e, 0x1f, 0x6e, 0x34, 0x06, 0x31, 0xa5, 0xfc, 0xd2, + 0x80, 0xd9, 0x1e, 0xd3, 0x0b, 0xda, 0x81, 0xb9, 0xb6, 0x5b, 0x97, 0xc7, 0xa6, 0xcb, 0x96, 0xbf, + 0xc3, 0x60, 0xa2, 0x79, 0x4f, 0xd2, 0x91, 0xac, 0x24, 0xc0, 0xef, 0x74, 0x8b, 0xf3, 0x8a, 0x48, + 0x0c, 0x01, 0x27, 0x52, 0x44, 0x6d, 0xc8, 0x6f, 0xdb, 0xa4, 0x59, 0x0f, 0xa7, 0xe0, 0x90, 0x07, + 0xa4, 0x4b, 0x82, 0x1a, 0xb7, 0x3a, 0xca, 0x7f, 0x58, 0x71, 0x31, 0xaf, 0xc1, 0x54, 0xd4, 0x06, + 0x3d, 0xc0, 0xe0, 0x9d, 0x87, 0xac, 0xe5, 0x39, 0x62, 0xe8, 0xc6, 0x05, 0x42, 0xb6, 0x84, 0x37, + 0x30, 0x2d, 0x37, 0x7f, 0x3d, 0x02, 0xd3, 0xe5, 0x66, 0x87, 0x3c, 0xef, 0x11, 0x22, 0xaf, 0xdd, + 0x25, 0x98, 0x6e, 0x7b, 0x64, 0xcf, 0x26, 0xfb, 0x55, 0xd2, 0x24, 0xb5, 0xc0, 0xf5, 0x04, 0xfd, + 0x73, 0xa2, 0xfa, 0x74, 0x25, 0x0a, 0xc6, 0x71, 0x7c, 0xf4, 0x1c, 0x4c, 0x59, 0xb5, 0xc0, 0xde, + 0x23, 0x8a, 0x02, 0x17, 0xe0, 0x1d, 0x82, 0xc2, 0x54, 0x29, 0x02, 0xc5, 0x31, 0x6c, 0xf4, 0x11, + 0x98, 0xf7, 0x6b, 0x56, 0x93, 0x5c, 0x6f, 0x0b, 0x56, 0xcb, 0x3b, 0xa4, 0xb6, 0x5b, 0x71, 0x6d, + 0x27, 0x10, 0x46, 0x96, 0x87, 0x04, 0xa5, 0xf9, 0x6a, 0x1f, 0x3c, 0xdc, 0x97, 0x02, 0xfa, 0x23, + 0x03, 0xce, 0xb7, 0x3d, 0x52, 0xf1, 0xdc, 0x96, 0x4b, 0xb5, 0x67, 0x8f, 0xe5, 0x41, 0xdc, 0xc0, + 0x6f, 0x0c, 0x79, 0x4c, 0xe0, 0x25, 0xbd, 0x96, 0xcf, 0x77, 0x1e, 0x76, 0x8b, 0xe7, 0x2b, 0x47, + 0x09, 0x80, 0x8f, 0x96, 0x0f, 0xfd, 0x89, 0x01, 0x17, 0xda, 0xae, 0x1f, 0x1c, 0xd1, 0x84, 0xdc, + 0xa9, 0x36, 0xc1, 0x3c, 0xec, 0x16, 0x2f, 0x54, 0x8e, 0x94, 0x00, 0xdf, 0x45, 0x42, 0xf3, 0x70, + 0x1c, 0x66, 0xb5, 0xb9, 0x27, 0xae, 0xe5, 0xcf, 0xc0, 0xa4, 0x9c, 0x0c, 0xa1, 0x5a, 0x2f, 0x84, + 0x66, 0x94, 0x92, 0x0e, 0xc4, 0x51, 0x5c, 0x3a, 0xef, 0xd4, 0x54, 0xe4, 0xb5, 0x63, 0xf3, 0xae, + 0x12, 0x81, 0xe2, 0x18, 0x36, 0x5a, 0x85, 0x33, 0xa2, 0x04, 0x93, 0x76, 0xd3, 0xae, 0x59, 0xcb, + 0x6e, 0x47, 0x4c, 0xb9, 0x5c, 0xf9, 0xdc, 0x61, 0xb7, 0x78, 0xa6, 0xd2, 0x0b, 0xc6, 0x49, 0x75, + 0xd0, 0x1a, 0xcc, 0x59, 0x9d, 0xc0, 0x55, 0xed, 0xbf, 0xe8, 0x50, 0x4d, 0x51, 0x67, 0x53, 0x2b, + 0xcf, 0x55, 0x4a, 0x29, 0x01, 0x8e, 0x13, 0x6b, 0xa1, 0x4a, 0x8c, 0x5a, 0x95, 0xd4, 0x5c, 0xa7, + 0xce, 0x47, 0x39, 0x17, 0x5e, 0x2e, 0x4a, 0x09, 0x38, 0x38, 0xb1, 0x26, 0x6a, 0xc2, 0x54, 0xcb, + 0xba, 0x7d, 0xdd, 0xb1, 0xf6, 0x2c, 0xbb, 0x49, 0x99, 0x08, 0xd3, 0x4c, 0x7f, 0x7b, 0x41, 0x27, + 0xb0, 0x9b, 0x8b, 0xfc, 0x95, 0x72, 0x71, 0xd5, 0x09, 0xae, 0x7a, 0xd5, 0x80, 0x1e, 0x42, 0xf9, + 0xe1, 0x68, 0x3d, 0x42, 0x0b, 0xc7, 0x68, 0xa3, 0xab, 0x70, 0x96, 0x2d, 0xc7, 0x15, 0x77, 0xdf, + 0x59, 0x21, 0x4d, 0xeb, 0x40, 0x36, 0x60, 0x8c, 0x35, 0xe0, 0xfe, 0xc3, 0x6e, 0xf1, 0x6c, 0x35, + 0x09, 0x01, 0x27, 0xd7, 0x43, 0x16, 0x3c, 0x10, 0x05, 0x60, 0xb2, 0x67, 0xfb, 0xb6, 0xeb, 0x70, + 0x03, 0x4b, 0x3e, 0x34, 0xb0, 0x54, 0xfb, 0xa3, 0xe1, 0xa3, 0x68, 0xa0, 0xff, 0x63, 0xc0, 0x5c, + 0xd2, 0x32, 0x9c, 0x2f, 0xa4, 0xf1, 0x06, 0x13, 0x5b, 0x5a, 0x7c, 0x46, 0x24, 0x6e, 0x0a, 0x89, + 0x42, 0xa0, 0x57, 0x0d, 0x98, 0xb0, 0xb4, 0xcb, 0xe1, 0x3c, 0x30, 0xa9, 0xae, 0x0c, 0x6b, 0xa2, + 0x08, 0x29, 0x96, 0x67, 0x0e, 0xbb, 0xc5, 0xc8, 0x05, 0x14, 0x47, 0x38, 0xa2, 0xff, 0x6b, 0xc0, + 0xd9, 0xc4, 0x35, 0x3e, 0x3f, 0x7e, 0x1a, 0x3d, 0xc4, 0x26, 0x49, 0xf2, 0x9e, 0x93, 0x2c, 0x06, + 0x7a, 0xd3, 0x50, 0xaa, 0x6c, 0x5d, 0x1a, 0x89, 0x26, 0x98, 0x68, 0xd7, 0x86, 0xbc, 0x0f, 0x87, + 0x07, 0x02, 0x49, 0xb8, 0x7c, 0x46, 0xd3, 0x8c, 0xb2, 0x10, 0xc7, 0xd9, 0xa3, 0x2f, 0x18, 0x52, + 0x35, 0x2a, 0x89, 0x26, 0x4f, 0x4b, 0x22, 0x14, 0x6a, 0x5a, 0x25, 0x50, 0x8c, 0x39, 0xfa, 0x28, + 0x2c, 0x58, 0x5b, 0xae, 0x17, 0x24, 0x2e, 0xbe, 0xf9, 0x29, 0xb6, 0x8c, 0x2e, 0x1c, 0x76, 0x8b, + 0x0b, 0xa5, 0xbe, 0x58, 0xf8, 0x08, 0x0a, 0xe6, 0x37, 0x72, 0x30, 0xc1, 0x0f, 0xf9, 0x42, 0x75, + 0x7d, 0xcb, 0x80, 0x07, 0x6b, 0x1d, 0xcf, 0x23, 0x4e, 0x50, 0x0d, 0x48, 0xbb, 0x57, 0x71, 0x19, + 0xa7, 0xaa, 0xb8, 0x1e, 0x3a, 0xec, 0x16, 0x1f, 0x5c, 0x3e, 0x82, 0x3f, 0x3e, 0x52, 0x3a, 0xf4, + 0xe7, 0x06, 0x98, 0x02, 0xa1, 0x6c, 0xd5, 0x76, 0x1b, 0x9e, 0xdb, 0x71, 0xea, 0xbd, 0x8d, 0xc8, + 0x9c, 0x6a, 0x23, 0x1e, 0x39, 0xec, 0x16, 0xcd, 0xe5, 0xbb, 0x4a, 0x81, 0x07, 0x90, 0x14, 0x3d, + 0x0f, 0xb3, 0x02, 0xeb, 0xe2, 0xed, 0x36, 0xf1, 0x6c, 0x7a, 0x9c, 0x16, 0x6e, 0x02, 0xa1, 0xe7, + 0x45, 0x1c, 0x01, 0xf7, 0xd6, 0x41, 0x3e, 0x8c, 0xed, 0x13, 0xbb, 0xb1, 0x13, 0xc8, 0xe3, 0xd3, + 0x90, 0xee, 0x16, 0xe2, 0xc2, 0x7f, 0x93, 0xd3, 0x2c, 0x8f, 0x1f, 0x76, 0x8b, 0x63, 0xe2, 0x0f, + 0x96, 0x9c, 0xd0, 0x06, 0x4c, 0xf1, 0x2b, 0x58, 0xc5, 0x76, 0x1a, 0x15, 0xd7, 0xe1, 0x4e, 0x0a, + 0x85, 0xf2, 0x23, 0x52, 0xe1, 0x57, 0x23, 0xd0, 0x3b, 0xdd, 0xe2, 0x84, 0xfc, 0xbd, 0x79, 0xd0, + 0x26, 0x38, 0x56, 0xdb, 0xfc, 0xde, 0x28, 0x80, 0x9c, 0xae, 0xa4, 0x8d, 0xfe, 0x03, 0x14, 0x7c, + 0x12, 0x70, 0xae, 0xe2, 0x4d, 0x80, 0x3f, 0xb5, 0xc8, 0x42, 0x1c, 0xc2, 0xd1, 0x2e, 0xe4, 0xda, + 0x56, 0xc7, 0x27, 0x62, 0xf0, 0xaf, 0xa4, 0x32, 0xf8, 0x15, 0x4a, 0x91, 0xdf, 0xb9, 0xd8, 0x4f, + 0xcc, 0x79, 0xa0, 0xcf, 0x1a, 0x00, 0x24, 0x3a, 0x60, 0x43, 0xdb, 0x3e, 0x04, 0xcb, 0x70, 0x4c, + 0x69, 0x1f, 0x94, 0xa7, 0x0e, 0xbb, 0x45, 0xd0, 0x86, 0x5e, 0x63, 0x8b, 0xf6, 0x21, 0x6f, 0xc9, + 0x3d, 0x7f, 0xe4, 0x34, 0xf6, 0x7c, 0x76, 0x15, 0x52, 0x93, 0x56, 0x31, 0x43, 0x9f, 0x33, 0x60, + 0xca, 0x27, 0x81, 0x18, 0x2a, 0xba, 0xf3, 0x88, 0x03, 0xef, 0x90, 0x93, 0xae, 0x1a, 0xa1, 0xc9, + 0x77, 0xd0, 0x68, 0x19, 0x8e, 0xf1, 0x95, 0xa2, 0x5c, 0x26, 0x56, 0x9d, 0x78, 0xec, 0xa6, 0x2d, + 0x4e, 0x52, 0xc3, 0x8b, 0xa2, 0xd1, 0x54, 0xa2, 0x68, 0x65, 0x38, 0xc6, 0x57, 0x8a, 0xb2, 0x6e, + 0x7b, 0x9e, 0x2b, 0x44, 0xc9, 0xa7, 0x24, 0x8a, 0x46, 0x53, 0x89, 0xa2, 0x95, 0xe1, 0x18, 0x5f, + 0xf3, 0xab, 0x93, 0x30, 0x25, 0x17, 0x52, 0x78, 0xb2, 0xe7, 0x86, 0x9d, 0x3e, 0x27, 0xfb, 0x65, + 0x1d, 0x88, 0xa3, 0xb8, 0xb4, 0x32, 0x5f, 0xaa, 0xd1, 0x83, 0xbd, 0xaa, 0x5c, 0xd5, 0x81, 0x38, + 0x8a, 0x8b, 0x5a, 0x90, 0xf3, 0x03, 0xd2, 0x96, 0xcf, 0xbb, 0x43, 0xbe, 0x3e, 0x86, 0xfb, 0x43, + 0xf8, 0x80, 0x43, 0xff, 0xf9, 0x98, 0x73, 0x61, 0xb6, 0xc9, 0x20, 0x62, 0xae, 0x14, 0x8b, 0x23, + 0x9d, 0xf5, 0x19, 0xb5, 0x84, 0xf2, 0xd1, 0x88, 0x96, 0xe1, 0x18, 0xfb, 0x84, 0xc3, 0x7e, 0xee, + 0x14, 0x0f, 0xfb, 0x2f, 0x42, 0xbe, 0x65, 0xdd, 0xae, 0x76, 0xbc, 0xc6, 0xc9, 0x2f, 0x15, 0xc2, + 0xf3, 0x8a, 0x53, 0xc1, 0x8a, 0x1e, 0x7a, 0xcd, 0xd0, 0xb6, 0x9c, 0x31, 0x46, 0xfc, 0x66, 0xba, + 0x5b, 0x8e, 0xd2, 0x95, 0x7d, 0x37, 0x9f, 0x9e, 0xa3, 0x77, 0xfe, 0x9e, 0x1f, 0xbd, 0xe9, 0x31, + 0x92, 0x2f, 0x10, 0x75, 0x8c, 0x2c, 0x9c, 0xea, 0x31, 0x72, 0x39, 0xc2, 0x0c, 0xc7, 0x98, 0x33, + 0x79, 0xf8, 0x9a, 0x53, 0xf2, 0xc0, 0xa9, 0xca, 0x53, 0x8d, 0x30, 0xc3, 0x31, 0xe6, 0xfd, 0xef, + 0x9b, 0xe3, 0xa7, 0x73, 0xdf, 0x9c, 0x48, 0xe1, 0xbe, 0x79, 0xf4, 0x51, 0x7c, 0x72, 0xd8, 0xa3, + 0x38, 0xba, 0x02, 0xa8, 0x7e, 0xe0, 0x58, 0x2d, 0xbb, 0x26, 0x36, 0x4b, 0xa6, 0x36, 0xa7, 0x98, + 0x3d, 0x62, 0x41, 0x6c, 0x64, 0x68, 0xa5, 0x07, 0x03, 0x27, 0xd4, 0x42, 0x01, 0xe4, 0xdb, 0xf2, + 0xc4, 0x35, 0x9d, 0xc6, 0xec, 0x97, 0x27, 0x30, 0xee, 0x01, 0x40, 0x17, 0x9e, 0x2c, 0xc1, 0x8a, + 0x13, 0x5a, 0x83, 0xb9, 0x96, 0xed, 0x54, 0xdc, 0xba, 0x5f, 0x21, 0x9e, 0xb0, 0xb6, 0x54, 0x49, + 0x30, 0x3f, 0xc3, 0xfa, 0x86, 0xdd, 0xa0, 0xd7, 0x13, 0xe0, 0x38, 0xb1, 0x96, 0xf9, 0x4f, 0x06, + 0xcc, 0x2c, 0x37, 0xdd, 0x4e, 0xfd, 0xa6, 0x15, 0xd4, 0x76, 0xf8, 0xe3, 0x37, 0x7a, 0x0e, 0xf2, + 0xb6, 0x13, 0x10, 0x6f, 0xcf, 0x6a, 0x0a, 0xfd, 0x64, 0x4a, 0xff, 0x80, 0x55, 0x51, 0x7e, 0xa7, + 0x5b, 0x9c, 0x5a, 0xe9, 0x78, 0xcc, 0xab, 0x94, 0xef, 0x56, 0x58, 0xd5, 0x41, 0x5f, 0x35, 0x60, + 0x96, 0x3f, 0x9f, 0xaf, 0x58, 0x81, 0x75, 0xad, 0x43, 0x3c, 0x9b, 0xc8, 0x07, 0xf4, 0x21, 0x37, + 0xaa, 0xb8, 0xac, 0x92, 0xc1, 0x41, 0x78, 0x50, 0x5f, 0x8f, 0x73, 0xc6, 0xbd, 0xc2, 0x98, 0x5f, + 0xca, 0xc2, 0xfd, 0x7d, 0x69, 0xa1, 0x05, 0xc8, 0xd8, 0x75, 0xd1, 0x74, 0x10, 0x74, 0x33, 0xab, + 0x75, 0x9c, 0xb1, 0xeb, 0x68, 0x91, 0x9d, 0x39, 0x3d, 0xe2, 0xfb, 0xf2, 0x2d, 0xb5, 0xa0, 0x8e, + 0x87, 0xa2, 0x14, 0x6b, 0x18, 0xa8, 0x08, 0xb9, 0xa6, 0xb5, 0x45, 0x9a, 0xe2, 0x3e, 0xc1, 0x4e, + 0xb1, 0x6b, 0xb4, 0x00, 0xf3, 0x72, 0xf4, 0x19, 0x03, 0x80, 0x0b, 0x48, 0x6f, 0x23, 0x42, 0x4b, + 0xe2, 0x74, 0xbb, 0x89, 0x52, 0xe6, 0x52, 0x86, 0xff, 0xb1, 0xc6, 0x15, 0x6d, 0xc2, 0x28, 0x3d, + 0xd0, 0xba, 0xf5, 0x13, 0x2b, 0x45, 0xf6, 0xc8, 0x52, 0x61, 0x34, 0xb0, 0xa0, 0x45, 0xfb, 0xca, + 0x23, 0x41, 0xc7, 0x73, 0x68, 0xd7, 0x32, 0x35, 0x98, 0xe7, 0x52, 0x60, 0x55, 0x8a, 0x35, 0x0c, + 0xf3, 0x0f, 0x33, 0x30, 0x97, 0x24, 0x3a, 0xd5, 0x36, 0xa3, 0x5c, 0x5a, 0x71, 0x35, 0xfe, 0x60, + 0xfa, 0xfd, 0x23, 0x3c, 0x41, 0x94, 0xbf, 0x84, 0xf0, 0x55, 0x13, 0x7c, 0xd1, 0x07, 0x55, 0x0f, + 0x65, 0x4e, 0xd8, 0x43, 0x8a, 0x72, 0xac, 0x97, 0x1e, 0x82, 0x11, 0x9f, 0x8e, 0x7c, 0x36, 0xfa, + 0x80, 0xc1, 0xc6, 0x88, 0x41, 0x28, 0x46, 0xc7, 0xb1, 0x03, 0xe1, 0xea, 0xad, 0x30, 0xae, 0x3b, + 0x76, 0x80, 0x19, 0xc4, 0xfc, 0x4a, 0x06, 0x16, 0xfa, 0x37, 0x0a, 0x7d, 0xc5, 0x00, 0xa8, 0xd3, + 0xeb, 0x0a, 0x9d, 0x92, 0xd2, 0x73, 0xc6, 0x3a, 0xad, 0x3e, 0x5c, 0x91, 0x9c, 0x42, 0x37, 0x2a, + 0x55, 0xe4, 0x63, 0x4d, 0x10, 0xf4, 0xb8, 0x9c, 0xfa, 0x1b, 0x56, 0x4b, 0x1e, 0x67, 0x55, 0x9d, + 0x75, 0x05, 0xc1, 0x1a, 0x16, 0xbd, 0x8f, 0x3a, 0x56, 0x8b, 0xf8, 0x6d, 0x4b, 0xf9, 0xf2, 0xb3, + 0xfb, 0xe8, 0x86, 0x2c, 0xc4, 0x21, 0xdc, 0x6c, 0xc2, 0xc3, 0x03, 0xc8, 0x99, 0x92, 0x5f, 0xb5, + 0xf9, 0x8f, 0x06, 0x9c, 0x5b, 0x6e, 0x76, 0xfc, 0x80, 0x78, 0xff, 0x66, 0xbc, 0xd2, 0xfe, 0xd9, + 0x80, 0x07, 0xfa, 0xb4, 0xf9, 0x1e, 0x38, 0xa7, 0xbd, 0x1c, 0x75, 0x4e, 0xbb, 0x3e, 0xec, 0x94, + 0x4e, 0x6c, 0x47, 0x1f, 0x1f, 0xb5, 0x00, 0x26, 0xe9, 0xae, 0x55, 0x77, 0x1b, 0x29, 0xe9, 0xcd, + 0x87, 0x21, 0xf7, 0x09, 0xaa, 0x7f, 0xe2, 0x73, 0x8c, 0x29, 0x25, 0xcc, 0x61, 0xe6, 0xb3, 0x20, + 0x3c, 0xb9, 0x62, 0x8b, 0xc7, 0x18, 0x64, 0xf1, 0x98, 0x7f, 0x99, 0x01, 0xcd, 0x8e, 0x71, 0x0f, + 0x26, 0xa5, 0x13, 0x99, 0x94, 0x43, 0xde, 0xc1, 0x35, 0xab, 0x4c, 0xbf, 0x90, 0x8d, 0xbd, 0x58, + 0xc8, 0xc6, 0x46, 0x6a, 0x1c, 0x8f, 0x8e, 0xd8, 0xf8, 0xb1, 0x01, 0x0f, 0x84, 0xc8, 0xbd, 0x26, + 0xc6, 0xbb, 0xef, 0x30, 0x4f, 0xc1, 0xb8, 0x15, 0x56, 0x13, 0x73, 0x40, 0x45, 0x29, 0x69, 0x14, + 0xb1, 0x8e, 0x17, 0x3a, 0x88, 0x67, 0x4f, 0xe8, 0x20, 0x3e, 0x72, 0xb4, 0x83, 0xb8, 0xf9, 0xab, + 0x0c, 0x9c, 0xef, 0x6d, 0x99, 0x5c, 0x1b, 0x83, 0xbd, 0xc0, 0x3f, 0x0d, 0x13, 0x81, 0xa8, 0xa0, + 0xed, 0xf4, 0x2a, 0xc6, 0x6e, 0x53, 0x83, 0xe1, 0x08, 0x26, 0xad, 0x59, 0xe3, 0xab, 0xb2, 0x5a, + 0x73, 0xdb, 0x32, 0xbc, 0x40, 0xd5, 0x5c, 0xd6, 0x60, 0x38, 0x82, 0xa9, 0x1c, 0x37, 0x47, 0x4e, + 0xdd, 0x71, 0xb3, 0x0a, 0x67, 0xa5, 0xab, 0xda, 0x25, 0xd7, 0x5b, 0x76, 0x5b, 0xed, 0x26, 0x11, + 0x01, 0x06, 0x54, 0xd8, 0xf3, 0xa2, 0xca, 0x59, 0x9c, 0x84, 0x84, 0x93, 0xeb, 0x9a, 0x3f, 0xce, + 0xc2, 0x99, 0xb0, 0xdb, 0x97, 0x5d, 0xa7, 0x6e, 0x33, 0x87, 0xbf, 0x67, 0x60, 0x24, 0x38, 0x68, + 0xcb, 0xce, 0xfe, 0x77, 0x52, 0x9c, 0xcd, 0x83, 0x36, 0x1d, 0xed, 0x73, 0x09, 0x55, 0x98, 0x91, + 0x97, 0x55, 0x42, 0x6b, 0x6a, 0x75, 0xf0, 0x11, 0x78, 0x32, 0x3a, 0x9b, 0xef, 0x74, 0x8b, 0x09, + 0x21, 0xa6, 0x8b, 0x8a, 0x52, 0x74, 0xce, 0xa3, 0x5b, 0x30, 0xd5, 0xb4, 0xfc, 0xe0, 0x7a, 0xbb, + 0x6e, 0x05, 0x64, 0xd3, 0x6e, 0x11, 0xb1, 0xe6, 0x8e, 0xe3, 0xb5, 0xaf, 0x5e, 0xa5, 0xd7, 0x22, + 0x94, 0x70, 0x8c, 0x32, 0xda, 0x03, 0x44, 0x4b, 0x36, 0x3d, 0xcb, 0xf1, 0x79, 0xab, 0x28, 0xbf, + 0xe3, 0x47, 0x09, 0xa8, 0x4b, 0xde, 0x5a, 0x0f, 0x35, 0x9c, 0xc0, 0x01, 0x3d, 0x02, 0xa3, 0x1e, + 0xb1, 0x7c, 0x31, 0x98, 0x85, 0x70, 0xfd, 0x63, 0x56, 0x8a, 0x05, 0x54, 0x5f, 0x50, 0xa3, 0x77, + 0x59, 0x50, 0x3f, 0x37, 0x60, 0x2a, 0x1c, 0xa6, 0x7b, 0xa0, 0x24, 0x5b, 0x51, 0x25, 0x79, 0x39, + 0xad, 0x2d, 0xb1, 0x8f, 0x5e, 0xfc, 0xd3, 0x51, 0xbd, 0x7d, 0xcc, 0x6b, 0xfb, 0x93, 0x50, 0x90, + 0xab, 0x5a, 0x9e, 0x3e, 0x87, 0xbc, 0x2b, 0x47, 0xce, 0x25, 0x5a, 0xb4, 0x91, 0x60, 0x82, 0x43, + 0x7e, 0x54, 0x2d, 0xd7, 0x85, 0xca, 0x15, 0xd3, 0x5e, 0xa9, 0x65, 0xa9, 0x8a, 0x93, 0xd4, 0xb2, + 0xac, 0x83, 0xae, 0xc3, 0xb9, 0xb6, 0xe7, 0xb2, 0x08, 0xd4, 0x15, 0x62, 0xd5, 0x9b, 0xb6, 0x43, + 0xa4, 0x41, 0x82, 0x3b, 0x45, 0x3c, 0x70, 0xd8, 0x2d, 0x9e, 0xab, 0x24, 0xa3, 0xe0, 0x7e, 0x75, + 0xa3, 0x51, 0x53, 0x23, 0x03, 0x44, 0x4d, 0xfd, 0x37, 0x65, 0xf6, 0x23, 0xbe, 0x88, 0x5d, 0xfa, + 0x70, 0x5a, 0x43, 0x99, 0xb0, 0xad, 0x87, 0x53, 0xaa, 0x24, 0x98, 0x62, 0xc5, 0xbe, 0xbf, 0x6d, + 0x69, 0xf4, 0x84, 0xb6, 0xa5, 0xd0, 0xf9, 0x7d, 0xec, 0x37, 0xe9, 0xfc, 0x9e, 0x7f, 0x5b, 0x39, + 0xbf, 0xbf, 0x9e, 0x83, 0x99, 0xf8, 0x09, 0xe4, 0xf4, 0x23, 0xc2, 0xfe, 0xa7, 0x01, 0x33, 0x72, + 0xf5, 0x70, 0x9e, 0x44, 0xbe, 0x1a, 0xac, 0xa5, 0xb4, 0x68, 0xf9, 0x59, 0x4a, 0xc5, 0x2c, 0x6f, + 0xc6, 0xb8, 0xe1, 0x1e, 0xfe, 0xe8, 0x25, 0x18, 0x57, 0xc6, 0xf5, 0x13, 0x85, 0x87, 0x4d, 0xb3, + 0x53, 0x54, 0x48, 0x02, 0xeb, 0xf4, 0xd0, 0xeb, 0x06, 0x40, 0x4d, 0xaa, 0x39, 0xb9, 0xba, 0xae, + 0xa5, 0xb5, 0xba, 0x94, 0x02, 0x0d, 0x0f, 0xcb, 0xaa, 0xc8, 0xc7, 0x1a, 0x63, 0xf4, 0x25, 0x66, + 0x56, 0x57, 0xa7, 0x3b, 0xba, 0x9e, 0xb2, 0xc3, 0x3b, 0xf6, 0x1e, 0x71, 0x30, 0x0d, 0x8f, 0x52, + 0x1a, 0xc8, 0xc7, 0x11, 0x21, 0xcc, 0x67, 0x40, 0xb9, 0x62, 0xd2, 0x6d, 0x8b, 0x39, 0x63, 0x56, + 0xac, 0x60, 0x47, 0x4c, 0x41, 0xb5, 0x6d, 0x5d, 0x92, 0x00, 0x1c, 0xe2, 0x98, 0x1f, 0x87, 0xa9, + 0xe7, 0x3d, 0xab, 0xbd, 0x63, 0x33, 0xf3, 0x35, 0xbd, 0x27, 0xbd, 0x1b, 0xc6, 0xac, 0x7a, 0x3d, + 0x29, 0xe2, 0xbf, 0xc4, 0x8b, 0xb1, 0x84, 0x0f, 0x76, 0x25, 0xfa, 0x9e, 0x01, 0x28, 0x7c, 0x02, + 0xb4, 0x9d, 0xc6, 0x3a, 0xbd, 0xed, 0xd3, 0xfb, 0xd1, 0x0e, 0x2b, 0x4d, 0xba, 0x1f, 0x5d, 0x56, + 0x10, 0xac, 0x61, 0xa1, 0x57, 0x60, 0x9c, 0xff, 0xbb, 0xa1, 0x2e, 0xfb, 0x43, 0xbb, 0xf7, 0x73, + 0x85, 0xc2, 0x64, 0xe2, 0xb3, 0xf0, 0x72, 0xc8, 0x01, 0xeb, 0xec, 0x68, 0x57, 0xad, 0x3a, 0xdb, + 0xcd, 0xce, 0xed, 0xfa, 0x56, 0xd8, 0x55, 0x6d, 0xcf, 0xdd, 0xb6, 0x9b, 0x24, 0xde, 0x55, 0x15, + 0x5e, 0x8c, 0x25, 0x7c, 0xb0, 0xae, 0xfa, 0x8e, 0x01, 0x73, 0xab, 0x7e, 0x60, 0xbb, 0x2b, 0xc4, + 0x0f, 0xa8, 0x5a, 0xa1, 0x9b, 0x4f, 0xa7, 0x39, 0x88, 0x57, 0xf5, 0x0a, 0xcc, 0x88, 0xe7, 0xc8, + 0xce, 0x96, 0x4f, 0x02, 0xed, 0x1c, 0xaf, 0xd6, 0xf1, 0x72, 0x0c, 0x8e, 0x7b, 0x6a, 0x50, 0x2a, + 0xe2, 0x5d, 0x32, 0xa4, 0x92, 0x8d, 0x52, 0xa9, 0xc6, 0xe0, 0xb8, 0xa7, 0x86, 0xf9, 0xc3, 0x2c, + 0x9c, 0x61, 0xcd, 0x88, 0x45, 0x44, 0x7c, 0xa1, 0x5f, 0x44, 0xc4, 0x90, 0x4b, 0x99, 0xf1, 0x3a, + 0x41, 0x3c, 0xc4, 0xff, 0x30, 0x60, 0xba, 0x1e, 0xed, 0xe9, 0x74, 0xcc, 0x33, 0x49, 0x63, 0xc8, + 0xbd, 0xaf, 0x62, 0x85, 0x38, 0xce, 0x1f, 0x7d, 0xd9, 0x80, 0xe9, 0xa8, 0x98, 0x72, 0x77, 0x3f, + 0x85, 0x4e, 0x52, 0xee, 0xd2, 0xd1, 0x72, 0x1f, 0xc7, 0x45, 0x30, 0x7f, 0x90, 0x11, 0x43, 0x7a, + 0x1a, 0xee, 0xfe, 0x68, 0x1f, 0x0a, 0x41, 0xd3, 0xe7, 0x85, 0xa2, 0xb5, 0x43, 0xde, 0x08, 0x37, + 0xd7, 0xaa, 0xdc, 0x13, 0x20, 0x3c, 0xb4, 0x89, 0x12, 0x7a, 0xf8, 0x94, 0xbc, 0x18, 0xe3, 0x5a, + 0x5b, 0x30, 0x4e, 0xe5, 0x2a, 0xba, 0xb9, 0x5c, 0x89, 0x33, 0x16, 0x25, 0x94, 0xb1, 0xe4, 0x65, + 0x7e, 0xdd, 0x80, 0xc2, 0x15, 0x57, 0xee, 0x23, 0x1f, 0x4d, 0xc1, 0xd0, 0xa3, 0xce, 0x83, 0xea, + 0xc5, 0x31, 0xbc, 0x62, 0x3c, 0x17, 0x31, 0xf3, 0x3c, 0xa8, 0xd1, 0x5e, 0x64, 0xd9, 0x8c, 0x28, + 0xa9, 0x2b, 0xee, 0x56, 0x5f, 0x2b, 0xe2, 0xff, 0xcb, 0xc1, 0xe4, 0x0b, 0xd6, 0x01, 0x71, 0x02, + 0xeb, 0xf8, 0x4a, 0xe2, 0x29, 0x18, 0xb7, 0xda, 0xec, 0x49, 0x4b, 0x3b, 0xe3, 0x87, 0x96, 0x93, + 0x10, 0x84, 0x75, 0xbc, 0x70, 0x43, 0xe3, 0xc9, 0x55, 0x92, 0xb6, 0xa2, 0xe5, 0x18, 0x1c, 0xf7, + 0xd4, 0x40, 0x57, 0x00, 0x89, 0x50, 0xd1, 0x52, 0xad, 0xe6, 0x76, 0x1c, 0xbe, 0xa5, 0x71, 0xa3, + 0x8a, 0xba, 0x6c, 0xae, 0xf7, 0x60, 0xe0, 0x84, 0x5a, 0xe8, 0x23, 0x30, 0x5f, 0x63, 0x94, 0xc5, + 0xd5, 0x43, 0xa7, 0xc8, 0xaf, 0x9f, 0xca, 0xe5, 0x7f, 0xb9, 0x0f, 0x1e, 0xee, 0x4b, 0x81, 0x4a, + 0xea, 0x07, 0xae, 0x67, 0x35, 0x88, 0x4e, 0x77, 0x34, 0x2a, 0x69, 0xb5, 0x07, 0x03, 0x27, 0xd4, + 0x42, 0x9f, 0x86, 0x42, 0xb0, 0xe3, 0x11, 0x7f, 0xc7, 0x6d, 0xd6, 0x85, 0x0b, 0xc2, 0x90, 0x96, + 0x36, 0x31, 0xfa, 0x9b, 0x92, 0xaa, 0x36, 0xbd, 0x65, 0x11, 0x0e, 0x79, 0x22, 0x0f, 0x46, 0xfd, + 0x9a, 0xdb, 0x26, 0xbe, 0x38, 0xb2, 0x5f, 0x49, 0x85, 0x3b, 0xb3, 0x1c, 0x69, 0x36, 0x3e, 0xc6, + 0x01, 0x0b, 0x4e, 0xe6, 0x77, 0x33, 0x30, 0xa1, 0x23, 0x0e, 0xb0, 0x37, 0x7d, 0xd6, 0x80, 0x89, + 0x9a, 0xeb, 0x04, 0x9e, 0xdb, 0xe4, 0xf6, 0xab, 0x74, 0x4e, 0x14, 0x94, 0xd4, 0x0a, 0x09, 0x2c, + 0xbb, 0xa9, 0x99, 0xc2, 0x34, 0x36, 0x38, 0xc2, 0x14, 0x7d, 0xde, 0x80, 0xe9, 0xd0, 0x63, 0x2d, + 0x34, 0xa4, 0xa5, 0x2a, 0x88, 0xda, 0xea, 0x2f, 0x46, 0x39, 0xe1, 0x38, 0x6b, 0x73, 0x0b, 0x66, + 0xe2, 0xa3, 0x4d, 0xbb, 0xb2, 0x6d, 0x89, 0xb5, 0x9e, 0x0d, 0xbb, 0xb2, 0x62, 0xf9, 0x3e, 0x66, + 0x10, 0xf4, 0x18, 0xe4, 0x5b, 0x96, 0xd7, 0xb0, 0x1d, 0xab, 0xc9, 0x7a, 0x31, 0xab, 0x6d, 0x48, + 0xa2, 0x1c, 0x2b, 0x0c, 0xf3, 0xbd, 0x30, 0xb1, 0x6e, 0x39, 0x0d, 0x52, 0x17, 0xfb, 0xf0, 0xdd, + 0x03, 0xce, 0x7e, 0x31, 0x02, 0xe3, 0xda, 0xdd, 0xec, 0xf4, 0xef, 0x59, 0x91, 0x7c, 0x17, 0xd9, + 0x14, 0xf3, 0x5d, 0xbc, 0x08, 0xb0, 0x6d, 0x3b, 0xb6, 0xbf, 0x73, 0xc2, 0x4c, 0x1a, 0xec, 0x89, + 0xf6, 0x92, 0xa2, 0x80, 0x35, 0x6a, 0xe1, 0x3b, 0x58, 0xee, 0x88, 0xfc, 0x42, 0xaf, 0x1b, 0x9a, + 0xba, 0x19, 0x4d, 0xe3, 0xdd, 0x5f, 0x1b, 0x98, 0x45, 0xa9, 0x7e, 0x2e, 0x3a, 0x81, 0x77, 0x70, + 0xa4, 0x56, 0xda, 0x84, 0xbc, 0x47, 0xfc, 0x4e, 0x8b, 0xde, 0x18, 0xc7, 0x8e, 0xdd, 0x0d, 0xcc, + 0x03, 0x03, 0x8b, 0xfa, 0x58, 0x51, 0x5a, 0x78, 0x06, 0x26, 0x23, 0x22, 0xa0, 0x19, 0xc8, 0xee, + 0x92, 0x03, 0x3e, 0x4f, 0x30, 0xfd, 0x89, 0xe6, 0x22, 0xaf, 0x85, 0xa2, 0x5b, 0x3e, 0x90, 0x79, + 0xda, 0x30, 0x5d, 0x48, 0x34, 0x00, 0x9c, 0xe4, 0x31, 0x87, 0x8e, 0x45, 0x53, 0x4b, 0xa5, 0xa1, + 0xc6, 0x82, 0xfb, 0xd9, 0x70, 0x98, 0xf9, 0xab, 0x51, 0x10, 0x4f, 0xd9, 0x03, 0x6c, 0x57, 0xfa, + 0x0b, 0x56, 0xe6, 0x04, 0x2f, 0x58, 0x57, 0x60, 0xc2, 0x76, 0xec, 0xc0, 0xb6, 0x9a, 0xcc, 0xb8, + 0x23, 0xd4, 0xa9, 0x74, 0x44, 0x9e, 0x58, 0xd5, 0x60, 0x09, 0x74, 0x22, 0x75, 0xd1, 0x35, 0xc8, + 0x31, 0x7d, 0x23, 0x26, 0xf0, 0xf1, 0xdf, 0xdb, 0x99, 0xab, 0x05, 0x8f, 0x4e, 0xe2, 0x94, 0xd8, + 0xe5, 0x83, 0xe7, 0x12, 0x51, 0xd7, 0x6f, 0x31, 0x8f, 0xc3, 0xcb, 0x47, 0x0c, 0x8e, 0x7b, 0x6a, + 0x50, 0x2a, 0xdb, 0x96, 0xdd, 0xec, 0x78, 0x24, 0xa4, 0x32, 0x1a, 0xa5, 0x72, 0x29, 0x06, 0xc7, + 0x3d, 0x35, 0xd0, 0x36, 0x4c, 0x88, 0x32, 0xee, 0x3d, 0x35, 0x76, 0xc2, 0x56, 0x32, 0x2f, 0xb9, + 0x4b, 0x1a, 0x25, 0x1c, 0xa1, 0x8b, 0x3a, 0x30, 0x6b, 0x3b, 0x35, 0xd7, 0xa9, 0x35, 0x3b, 0xbe, + 0xbd, 0x47, 0xc2, 0xd0, 0xa0, 0x93, 0x30, 0x3b, 0x7b, 0xd8, 0x2d, 0xce, 0xae, 0xc6, 0xc9, 0xe1, + 0x5e, 0x0e, 0xe8, 0x35, 0x03, 0xce, 0xd6, 0x5c, 0xc7, 0x67, 0xc1, 0xf9, 0x7b, 0xe4, 0xa2, 0xe7, + 0xb9, 0x1e, 0xe7, 0x5d, 0x38, 0x21, 0x6f, 0x66, 0x53, 0x5c, 0x4e, 0x22, 0x89, 0x93, 0x39, 0xa1, + 0x97, 0x21, 0xdf, 0xf6, 0xdc, 0x3d, 0xbb, 0x4e, 0x3c, 0xe1, 0x89, 0xb7, 0x96, 0x46, 0xb2, 0x90, + 0x8a, 0xa0, 0x19, 0x6e, 0x3d, 0xb2, 0x04, 0x2b, 0x7e, 0xe6, 0x97, 0x01, 0xa6, 0xa2, 0xe8, 0xe8, + 0x53, 0x00, 0x6d, 0xcf, 0x6d, 0x91, 0x60, 0x87, 0xa8, 0x10, 0x8f, 0x8d, 0x61, 0x73, 0x52, 0x48, + 0x7a, 0xd2, 0x7b, 0x85, 0x6e, 0x17, 0x61, 0x29, 0xd6, 0x38, 0x22, 0x0f, 0xc6, 0x76, 0xb9, 0xda, + 0x15, 0xa7, 0x90, 0x17, 0x52, 0x39, 0x33, 0x09, 0xce, 0x2c, 0x36, 0x41, 0x14, 0x61, 0xc9, 0x08, + 0x6d, 0x41, 0x76, 0x9f, 0x6c, 0xa5, 0x13, 0x10, 0x7d, 0x93, 0x88, 0xdb, 0x4c, 0x79, 0xec, 0xb0, + 0x5b, 0xcc, 0xde, 0x24, 0x5b, 0x98, 0x12, 0xa7, 0xed, 0xaa, 0xf3, 0x77, 0x78, 0xb1, 0x55, 0x0c, + 0xd9, 0xae, 0xc8, 0xa3, 0x3e, 0x6f, 0x97, 0x28, 0xc2, 0x92, 0x11, 0x7a, 0x19, 0x0a, 0xfb, 0xd6, + 0x1e, 0xd9, 0xf6, 0x5c, 0x27, 0x10, 0x2e, 0x53, 0x43, 0x7a, 0xfd, 0xdf, 0x94, 0xe4, 0x04, 0x5f, + 0xa6, 0xde, 0x55, 0x21, 0x0e, 0xd9, 0xa1, 0x3d, 0xc8, 0x3b, 0x64, 0x1f, 0x93, 0xa6, 0x5d, 0x4b, + 0xc7, 0xcb, 0x7e, 0x43, 0x50, 0x13, 0x9c, 0x99, 0xde, 0x93, 0x65, 0x58, 0xf1, 0xa2, 0x63, 0x79, + 0xcb, 0xdd, 0x12, 0x1b, 0xd5, 0x90, 0x63, 0xa9, 0x6e, 0xa6, 0x7c, 0x2c, 0xaf, 0xb8, 0x5b, 0x98, + 0x12, 0xa7, 0x6b, 0xa4, 0xa6, 0xfc, 0x75, 0xc4, 0x36, 0xb5, 0x91, 0xae, 0x9f, 0x12, 0x5f, 0x23, + 0x61, 0x29, 0xd6, 0x38, 0xd2, 0xbe, 0x6d, 0x08, 0x63, 0xa5, 0xd8, 0xa8, 0x86, 0xec, 0xdb, 0xa8, + 0xe9, 0x93, 0xf7, 0xad, 0x2c, 0xc3, 0x8a, 0x17, 0xe5, 0x6b, 0x0b, 0xcb, 0x5f, 0x3a, 0x5b, 0x55, + 0xd4, 0x8e, 0xc8, 0xf9, 0xca, 0x32, 0xac, 0x78, 0x21, 0x07, 0x46, 0xdb, 0xcd, 0x4e, 0xc3, 0x76, + 0x44, 0xb8, 0xe2, 0xb0, 0x1e, 0xac, 0x8c, 0x96, 0xe0, 0xc9, 0x3d, 0x02, 0x59, 0x09, 0x16, 0x5c, + 0xcc, 0xaf, 0x8f, 0xc2, 0x84, 0x9e, 0x04, 0x6e, 0x80, 0x33, 0x89, 0x3a, 0x87, 0x67, 0x8e, 0x73, + 0x0e, 0xa7, 0x17, 0x2f, 0xed, 0x4d, 0x45, 0x1a, 0x7d, 0x56, 0x53, 0x3b, 0x86, 0x86, 0x17, 0x2f, + 0xad, 0xd0, 0xc7, 0x11, 0xa6, 0xc7, 0x70, 0xb3, 0xa0, 0x87, 0x39, 0x7e, 0xdc, 0xc9, 0x45, 0x0f, + 0x73, 0x91, 0x03, 0xcc, 0xe3, 0x00, 0x61, 0x32, 0x34, 0xf1, 0xd6, 0xa6, 0x4e, 0x89, 0x5a, 0x92, + 0x36, 0x0d, 0x0b, 0x3d, 0x02, 0xa3, 0xf4, 0x40, 0x40, 0xea, 0x22, 0xce, 0x58, 0xdd, 0x6e, 0x2f, + 0xb1, 0x52, 0x2c, 0xa0, 0xe8, 0x69, 0x7a, 0x76, 0x0b, 0xd5, 0xb8, 0x08, 0x1f, 0x9e, 0x0b, 0xcf, + 0x6e, 0x21, 0x0c, 0x47, 0x30, 0xa9, 0xe8, 0x84, 0x6a, 0x5d, 0xb6, 0x62, 0x34, 0xd1, 0x99, 0x2a, + 0xc6, 0x1c, 0xc6, 0xac, 0x2d, 0x31, 0x2d, 0xcd, 0x66, 0x7a, 0x4e, 0xb3, 0xb6, 0xc4, 0xe0, 0xb8, + 0xa7, 0x06, 0x6d, 0x8c, 0x78, 0x26, 0x1c, 0xe7, 0xde, 0xa4, 0x7d, 0x1e, 0xf8, 0xde, 0xd0, 0x6f, + 0x20, 0x13, 0x6c, 0xe8, 0x3f, 0x98, 0x5e, 0x42, 0xc3, 0xc1, 0xaf, 0x20, 0xc3, 0x5d, 0x16, 0x3e, + 0x0e, 0x53, 0xd1, 0xbd, 0x39, 0xf5, 0xf7, 0x80, 0x3f, 0xcb, 0xc2, 0x99, 0x8d, 0x86, 0xed, 0xc4, + 0x13, 0x1c, 0x25, 0x25, 0x1a, 0x36, 0x8e, 0x9b, 0x68, 0x38, 0x0c, 0x58, 0x12, 0x99, 0x9c, 0x93, + 0x03, 0x96, 0x64, 0x9a, 0xe7, 0x28, 0x2e, 0xfa, 0xb9, 0x01, 0x0f, 0x5a, 0x75, 0x7e, 0x5a, 0xb6, + 0x9a, 0xa2, 0x34, 0x64, 0x2a, 0x57, 0xb4, 0x3f, 0xa4, 0xee, 0xeb, 0x6d, 0xfc, 0x62, 0xe9, 0x08, + 0xae, 0x7c, 0xc4, 0xdf, 0x25, 0x5a, 0xf0, 0xe0, 0x51, 0xa8, 0xf8, 0x48, 0xf1, 0x17, 0xae, 0xc2, + 0x3b, 0xef, 0xca, 0xe8, 0x58, 0xb3, 0xe5, 0xb3, 0x06, 0x14, 0xb8, 0xb9, 0x16, 0x93, 0x6d, 0xba, + 0x55, 0x58, 0x6d, 0xfb, 0x06, 0xf1, 0x7c, 0x99, 0x01, 0x4d, 0xbb, 0x50, 0x96, 0x2a, 0xab, 0x02, + 0x82, 0x35, 0x2c, 0xba, 0x19, 0xef, 0xda, 0x4e, 0x5d, 0x0c, 0x93, 0xda, 0x8c, 0x5f, 0xb0, 0x9d, + 0x3a, 0x66, 0x10, 0xb5, 0x5d, 0x67, 0xfb, 0x9a, 0x51, 0xbe, 0x66, 0xc0, 0x14, 0x8b, 0xd2, 0x0c, + 0xaf, 0x3a, 0x4f, 0x29, 0x1f, 0x1a, 0x2e, 0xc6, 0xf9, 0xa8, 0x0f, 0xcd, 0x9d, 0x6e, 0x71, 0x9c, + 0xc7, 0x75, 0x46, 0x5d, 0x6a, 0x3e, 0x2c, 0xec, 0x23, 0xcc, 0xd3, 0x27, 0x73, 0xec, 0xeb, 0xbb, + 0xb2, 0x1f, 0x56, 0x25, 0x11, 0x1c, 0xd2, 0x33, 0x5f, 0x81, 0x09, 0x3d, 0xdc, 0x02, 0x3d, 0x05, + 0xe3, 0x6d, 0xdb, 0x69, 0x44, 0xc3, 0xf2, 0x94, 0x0d, 0xb9, 0x12, 0x82, 0xb0, 0x8e, 0xc7, 0xaa, + 0xb9, 0x61, 0xb5, 0x98, 0xe9, 0xb9, 0xe2, 0xea, 0xd5, 0xc2, 0x3f, 0xe6, 0x06, 0x4c, 0xe8, 0xaa, + 0x12, 0x3d, 0x07, 0xa3, 0xdc, 0x6c, 0xcb, 0x18, 0x4f, 0xb0, 0xe0, 0xe6, 0x51, 0x6e, 0xe2, 0xbd, + 0xd3, 0x2d, 0xce, 0x13, 0xa7, 0xe6, 0xd6, 0x6d, 0xa7, 0xb1, 0x74, 0xcb, 0x77, 0x9d, 0x45, 0x6c, + 0xed, 0x4b, 0xed, 0x21, 0x6a, 0x99, 0xbf, 0x9f, 0x85, 0x33, 0x09, 0x61, 0x42, 0xe8, 0x75, 0x03, + 0x46, 0x59, 0x94, 0x81, 0xf4, 0xba, 0x79, 0x29, 0xf5, 0x50, 0xa4, 0x45, 0x16, 0xcc, 0x20, 0xd6, + 0x85, 0xda, 0x8e, 0x79, 0x21, 0x16, 0xcc, 0xd1, 0xff, 0x36, 0x60, 0xdc, 0xd2, 0x96, 0x2e, 0x77, + 0x44, 0xda, 0x4a, 0x5f, 0x98, 0x9e, 0x95, 0xaa, 0x39, 0x50, 0x86, 0x0b, 0x53, 0x97, 0x65, 0xe1, + 0xfd, 0x30, 0xae, 0x35, 0xe1, 0x38, 0x2b, 0x6e, 0xe1, 0x39, 0x98, 0x19, 0x6a, 0xc5, 0x7e, 0x08, + 0x8e, 0x9b, 0x20, 0x90, 0x2a, 0xc0, 0x7d, 0x3d, 0x14, 0x5b, 0xf5, 0xb8, 0x88, 0xc5, 0x16, 0x50, + 0x73, 0x0b, 0x66, 0xe2, 0x97, 0xc3, 0xd4, 0xdf, 0xdd, 0xdf, 0x0b, 0xc7, 0x4c, 0xe9, 0x67, 0x5e, + 0x04, 0x84, 0xdd, 0x66, 0x73, 0xcb, 0xaa, 0xed, 0xde, 0xb4, 0x9d, 0xba, 0xbb, 0xcf, 0xd6, 0xde, + 0x12, 0x14, 0x3c, 0x11, 0x05, 0xe6, 0x8b, 0x66, 0xa9, 0xc5, 0x2b, 0xc3, 0xc3, 0x7c, 0x1c, 0xe2, + 0x98, 0x3f, 0xc8, 0xc0, 0x98, 0x08, 0x59, 0xbc, 0x07, 0x2e, 0xcc, 0xbb, 0x91, 0xb7, 0xad, 0xd5, + 0x54, 0x22, 0x2d, 0xfb, 0xfa, 0x2f, 0xfb, 0x31, 0xff, 0xe5, 0x17, 0xd2, 0x61, 0x77, 0xb4, 0xf3, + 0xf2, 0xd7, 0x46, 0x60, 0x3a, 0x16, 0x02, 0x4a, 0x4f, 0x50, 0x3d, 0x3e, 0x7b, 0xd7, 0x53, 0x8d, + 0x32, 0x55, 0xee, 0xf5, 0x47, 0xbb, 0xef, 0xf9, 0x91, 0x04, 0xac, 0xd7, 0x52, 0xcb, 0xdd, 0xfe, + 0xdb, 0x5c, 0xac, 0xc7, 0x75, 0x47, 0xfb, 0x1b, 0x03, 0xee, 0xef, 0x1b, 0x29, 0xcc, 0x12, 0xcd, + 0x78, 0x51, 0xa8, 0x58, 0x90, 0x29, 0xe7, 0x43, 0x50, 0x0f, 0x4d, 0xf1, 0xdc, 0x20, 0x71, 0xf6, + 0xe8, 0x49, 0x98, 0x60, 0x1a, 0x9f, 0x6e, 0x4d, 0x01, 0x69, 0x0b, 0x3b, 0x39, 0xb3, 0x98, 0x56, + 0xb5, 0x72, 0x1c, 0xc1, 0x32, 0xbf, 0x6a, 0xc0, 0x7c, 0xbf, 0xb4, 0x23, 0x03, 0xdc, 0x57, 0xff, + 0x53, 0xcc, 0xc7, 0xba, 0xd8, 0xe3, 0x63, 0x1d, 0xbb, 0xb1, 0x4a, 0x77, 0x6a, 0xed, 0xb2, 0x98, + 0xbd, 0x8b, 0x0b, 0xf1, 0x17, 0x0c, 0x38, 0xd7, 0x67, 0x35, 0xf5, 0xf8, 0xda, 0x1b, 0x27, 0xf6, + 0xb5, 0xcf, 0x0c, 0xea, 0x6b, 0x6f, 0xfe, 0x28, 0x0b, 0x33, 0x42, 0x9e, 0xf0, 0xd8, 0xf7, 0x74, + 0xc4, 0x53, 0xfd, 0x5d, 0x31, 0x4f, 0xf5, 0xb9, 0x38, 0xfe, 0x6f, 0xdd, 0xd4, 0xdf, 0x5e, 0x6e, + 0xea, 0xbf, 0xce, 0xc0, 0xd9, 0xc4, 0x6c, 0x28, 0xe8, 0x73, 0x09, 0xaa, 0xe1, 0x66, 0xca, 0x69, + 0x57, 0x06, 0x54, 0x0e, 0xc3, 0xfa, 0x76, 0x7f, 0x59, 0xf7, 0xa9, 0xe6, 0x5b, 0xfd, 0xf6, 0x29, + 0x24, 0x90, 0x39, 0xa6, 0x7b, 0xb5, 0xf9, 0xdf, 0xb3, 0xf0, 0xe8, 0xa0, 0x84, 0xde, 0xa6, 0xe1, + 0x37, 0x7e, 0x24, 0xfc, 0xe6, 0x1e, 0xa9, 0xed, 0x53, 0x89, 0xc4, 0xf9, 0x7a, 0x56, 0xa9, 0xbd, + 0xde, 0xf9, 0x39, 0xd0, 0xa3, 0xea, 0x18, 0x3d, 0xda, 0xc9, 0x1c, 0xa9, 0xe1, 0x56, 0x38, 0x56, + 0xe5, 0xc5, 0x77, 0xba, 0xc5, 0xd9, 0x30, 0x26, 0x5f, 0x14, 0x62, 0x59, 0x09, 0x3d, 0x0a, 0x79, + 0x8f, 0x43, 0x65, 0xc0, 0x81, 0x78, 0x99, 0xe6, 0x65, 0x58, 0x41, 0xd1, 0xa7, 0xb5, 0xb3, 0xf0, + 0xc8, 0x69, 0xa5, 0x9e, 0x38, 0xea, 0xc1, 0xfd, 0x25, 0xc8, 0xfb, 0x32, 0xdb, 0x29, 0x7f, 0x15, + 0x79, 0x62, 0xc0, 0x38, 0x16, 0x7a, 0x03, 0x93, 0xa9, 0x4f, 0x79, 0xfb, 0x54, 0x62, 0x54, 0x45, + 0x12, 0x99, 0xea, 0xf2, 0xc3, 0x4d, 0x9f, 0x90, 0x70, 0xf1, 0xf9, 0xb1, 0x01, 0xe3, 0x62, 0xb4, + 0xee, 0x41, 0x68, 0xcd, 0xad, 0x68, 0x68, 0xcd, 0xc5, 0x54, 0xf6, 0x8e, 0x3e, 0x71, 0x35, 0xb7, + 0x60, 0x42, 0x4f, 0x88, 0x85, 0x5e, 0xd4, 0xf6, 0x3e, 0x63, 0x98, 0x14, 0x33, 0x72, 0x77, 0x0c, + 0xf7, 0x45, 0xf3, 0x1b, 0x05, 0xd5, 0x8b, 0xec, 0x8a, 0xa6, 0xcf, 0x41, 0xe3, 0xc8, 0x39, 0xa8, + 0x4f, 0x81, 0x4c, 0xfa, 0x53, 0xe0, 0x1a, 0xe4, 0xe5, 0x06, 0x25, 0xd4, 0xf8, 0xc3, 0xba, 0xb3, + 0x21, 0x3d, 0x0b, 0x50, 0x62, 0xda, 0xc4, 0x65, 0x57, 0x2d, 0x35, 0x86, 0x6a, 0xe3, 0x54, 0x64, + 0xd0, 0xcb, 0x30, 0xbe, 0xef, 0x7a, 0xbb, 0x4d, 0xd7, 0x62, 0x79, 0x8c, 0x21, 0x8d, 0xf7, 0x2d, + 0x65, 0x87, 0xe3, 0x1e, 0xdf, 0x37, 0x43, 0xfa, 0x58, 0x67, 0x86, 0x4a, 0x30, 0xdd, 0xb2, 0x1d, + 0x4c, 0xac, 0xba, 0x8a, 0xa0, 0x19, 0xe1, 0x89, 0x56, 0xe5, 0x21, 0x77, 0x3d, 0x0a, 0xc6, 0x71, + 0x7c, 0xf4, 0x79, 0x03, 0xa6, 0xbc, 0xc8, 0xa5, 0x5a, 0x64, 0x53, 0xac, 0x0c, 0x3f, 0x19, 0xa3, + 0x17, 0x75, 0xee, 0xf2, 0x1c, 0x2d, 0xc7, 0x31, 0xde, 0xe8, 0x93, 0x90, 0xf7, 0x45, 0xb6, 0xab, + 0x74, 0x1e, 0x46, 0xd5, 0x15, 0x96, 0x13, 0x0d, 0x87, 0x52, 0x96, 0x60, 0xc5, 0x10, 0xad, 0xc1, + 0x9c, 0xb4, 0x12, 0x44, 0xbe, 0x35, 0x33, 0x1a, 0x26, 0x47, 0xc1, 0x09, 0x70, 0x9c, 0x58, 0x8b, + 0x1e, 0xaa, 0x58, 0xa2, 0x39, 0xfe, 0x72, 0xa2, 0x3d, 0x36, 0xb0, 0xf5, 0x57, 0xc7, 0x02, 0x7a, + 0x54, 0x80, 0x58, 0x7e, 0x88, 0x00, 0xb1, 0x2a, 0x9c, 0x8d, 0x83, 0x58, 0xd6, 0x1b, 0x96, 0x68, + 0x47, 0x53, 0x66, 0x95, 0x24, 0x24, 0x9c, 0x5c, 0x17, 0xdd, 0x84, 0x82, 0x47, 0xd8, 0x75, 0xa7, + 0x24, 0x5d, 0x31, 0x8e, 0xed, 0x74, 0x86, 0x25, 0x01, 0x1c, 0xd2, 0xa2, 0xe3, 0x6e, 0x45, 0x53, + 0x9f, 0x5e, 0x4b, 0xf1, 0x6b, 0x79, 0x62, 0xec, 0xfb, 0x64, 0xa3, 0x32, 0xdf, 0x9a, 0x82, 0xc9, + 0x88, 0xa9, 0x03, 0x3d, 0x0c, 0x39, 0x96, 0x06, 0x88, 0xed, 0x56, 0xf9, 0x70, 0x47, 0xe5, 0x9d, + 0xc3, 0x61, 0xe8, 0x8b, 0x06, 0x4c, 0xb7, 0x23, 0xb6, 0x6a, 0xb9, 0x91, 0x0f, 0xf9, 0xfa, 0x1a, + 0x35, 0x80, 0x6b, 0x49, 0xc3, 0xa3, 0xcc, 0x70, 0x9c, 0x3b, 0xdd, 0x0f, 0x84, 0xe7, 0x66, 0x93, + 0x78, 0x0c, 0x5b, 0x1c, 0xb9, 0x14, 0x89, 0xe5, 0x28, 0x18, 0xc7, 0xf1, 0xe9, 0x08, 0xb3, 0xd6, + 0x0d, 0xf3, 0x19, 0xad, 0x92, 0x24, 0x80, 0x43, 0x5a, 0xe8, 0x39, 0x98, 0x12, 0x19, 0x2f, 0x2b, + 0x6e, 0xfd, 0xb2, 0xe5, 0xef, 0x88, 0xbb, 0x86, 0xba, 0x1b, 0x2d, 0x47, 0xa0, 0x38, 0x86, 0xcd, + 0xda, 0x16, 0xa6, 0x15, 0x65, 0x04, 0x46, 0xa3, 0x39, 0xd5, 0x97, 0xa3, 0x60, 0x1c, 0xc7, 0x47, + 0x8f, 0x69, 0x6a, 0x88, 0xbf, 0x66, 0xaa, 0xdd, 0x20, 0x41, 0x15, 0x95, 0x60, 0xba, 0xc3, 0xae, + 0x66, 0x75, 0x09, 0x14, 0xeb, 0x51, 0x31, 0xbc, 0x1e, 0x05, 0xe3, 0x38, 0x3e, 0x7a, 0x06, 0x26, + 0x3d, 0xba, 0xd9, 0x2a, 0x02, 0xfc, 0x89, 0x53, 0xbd, 0x60, 0x61, 0x1d, 0x88, 0xa3, 0xb8, 0xe8, + 0x79, 0x98, 0x0d, 0x13, 0xc4, 0x49, 0x02, 0xfc, 0xcd, 0x53, 0x65, 0x2b, 0x2a, 0xc5, 0x11, 0x70, + 0x6f, 0x1d, 0xf4, 0x5f, 0x60, 0x46, 0xeb, 0x89, 0x55, 0xa7, 0x4e, 0x6e, 0x8b, 0x24, 0x5e, 0xec, + 0xf3, 0x17, 0xcb, 0x31, 0x18, 0xee, 0xc1, 0x46, 0x1f, 0x80, 0xa9, 0x9a, 0xdb, 0x6c, 0xb2, 0x3d, + 0x8e, 0xe7, 0xf3, 0xe6, 0xd9, 0xba, 0x78, 0x5e, 0xb3, 0x08, 0x04, 0xc7, 0x30, 0xd1, 0x15, 0x40, + 0xee, 0x96, 0x4f, 0xbc, 0x3d, 0x52, 0x7f, 0x9e, 0x7f, 0x98, 0x97, 0x9e, 0x38, 0x26, 0xa3, 0x7e, + 0xe3, 0x57, 0x7b, 0x30, 0x70, 0x42, 0x2d, 0x96, 0xec, 0x48, 0x8b, 0xb3, 0x9b, 0x4a, 0xe3, 0x93, + 0x52, 0x71, 0x43, 0xc2, 0x5d, 0x83, 0xec, 0x3c, 0x18, 0xe5, 0x6e, 0xfc, 0xe9, 0xa4, 0xed, 0xd2, + 0x53, 0xfb, 0x86, 0x3a, 0x82, 0x97, 0x62, 0xc1, 0x09, 0x7d, 0x0a, 0x0a, 0x5b, 0x32, 0xcf, 0x3b, + 0xcb, 0xd5, 0x35, 0xb4, 0x5e, 0x8c, 0x7d, 0xb2, 0x20, 0xbc, 0x28, 0x2b, 0x00, 0x0e, 0x59, 0xa2, + 0x47, 0x60, 0xfc, 0x72, 0xa5, 0xa4, 0x66, 0xe1, 0x2c, 0x1b, 0xfd, 0x11, 0x5a, 0x05, 0xeb, 0x00, + 0xba, 0xc2, 0xd4, 0xf1, 0x0d, 0xb1, 0x21, 0x0e, 0xf5, 0x6d, 0xef, 0x69, 0x8c, 0x62, 0xb3, 0x47, + 0x5b, 0x5c, 0x9d, 0x3f, 0x13, 0xc3, 0x16, 0xe5, 0x58, 0x61, 0xa0, 0x97, 0x60, 0x5c, 0xe8, 0x0b, + 0xb6, 0x37, 0xcd, 0x9d, 0x2c, 0x86, 0x13, 0x87, 0x24, 0xb0, 0x4e, 0x8f, 0xbd, 0xc5, 0xb1, 0xf4, + 0xd7, 0xe4, 0x52, 0xa7, 0xd9, 0x9c, 0x3f, 0xcb, 0xf6, 0xcd, 0xf0, 0x2d, 0x2e, 0x04, 0x61, 0x1d, + 0x0f, 0x3d, 0x21, 0xfd, 0x4b, 0xde, 0x11, 0x79, 0x9c, 0x54, 0xfe, 0x25, 0xea, 0xd0, 0xdd, 0xc7, + 0xcd, 0xfb, 0xdc, 0x5d, 0x1c, 0x3b, 0xb6, 0x60, 0x41, 0x9e, 0xf8, 0x7a, 0x17, 0xc9, 0xfc, 0x7c, + 0xc4, 0x68, 0xb1, 0x70, 0xb3, 0x2f, 0x26, 0x3e, 0x82, 0x0a, 0xda, 0x82, 0xac, 0xd5, 0xdc, 0x9a, + 0xbf, 0x3f, 0x8d, 0xa3, 0xab, 0xfa, 0xd0, 0x36, 0x77, 0xcd, 0x2a, 0xad, 0x95, 0x31, 0x25, 0x6e, + 0xbe, 0x96, 0x51, 0x8f, 0x04, 0x2a, 0x9d, 0xe9, 0x2b, 0xfa, 0xac, 0x36, 0xd2, 0xf8, 0x90, 0x6c, + 0xcf, 0xc7, 0x10, 0xb8, 0x42, 0x4a, 0x9c, 0xd3, 0x6d, 0xb5, 0x8e, 0x53, 0xc9, 0x2e, 0x13, 0x4d, + 0xd5, 0xca, 0x2f, 0x97, 0xd1, 0x55, 0x6c, 0xfe, 0x2c, 0xaf, 0x6c, 0x62, 0x31, 0x87, 0x09, 0x0f, + 0x72, 0xb6, 0x1f, 0xd8, 0x6e, 0x8a, 0xf1, 0x86, 0xb1, 0x1c, 0xa7, 0xcc, 0x9d, 0x99, 0x01, 0x30, + 0x67, 0x45, 0x79, 0x3a, 0x0d, 0xdb, 0xb9, 0x2d, 0x9a, 0x7f, 0x2d, 0x75, 0x4f, 0x08, 0xce, 0x93, + 0x01, 0x30, 0x67, 0x85, 0x6e, 0xf1, 0x99, 0x96, 0xce, 0x47, 0x83, 0xe3, 0xdf, 0x02, 0x8f, 0xce, + 0x38, 0xca, 0xcb, 0x6f, 0xd9, 0xe2, 0x0c, 0x33, 0x24, 0xaf, 0xea, 0xfa, 0x6a, 0x12, 0xaf, 0xea, + 0xfa, 0x2a, 0xa6, 0x4c, 0xd0, 0x1b, 0x06, 0x80, 0xa5, 0x3e, 0x8a, 0x9d, 0xce, 0x97, 0x43, 0xfa, + 0x7d, 0x64, 0x9b, 0x7b, 0x20, 0x86, 0x50, 0xac, 0x71, 0x46, 0x2f, 0xc3, 0x98, 0xc5, 0xbf, 0x7b, + 0x24, 0x9c, 0x3b, 0xd3, 0xf9, 0x98, 0x57, 0x4c, 0x02, 0xe6, 0xd5, 0x2a, 0x40, 0x58, 0x32, 0xa4, + 0xbc, 0x03, 0xcf, 0x22, 0xdb, 0xf6, 0xae, 0xf0, 0xf2, 0xac, 0x0e, 0x9d, 0xbe, 0x9c, 0x12, 0x4b, + 0xe2, 0x2d, 0x40, 0x58, 0x32, 0xe4, 0xdf, 0xa1, 0xb5, 0x1c, 0x4b, 0x85, 0xec, 0xa4, 0x13, 0xd8, + 0xa5, 0x07, 0x01, 0x69, 0xdf, 0xa1, 0xd5, 0x19, 0xe1, 0x28, 0x5f, 0xb4, 0x07, 0xa3, 0x16, 0xfb, + 0x22, 0x9b, 0xb8, 0x1f, 0xe1, 0x34, 0xbe, 0xee, 0x16, 0xeb, 0x03, 0xb6, 0xb9, 0x88, 0xef, 0xbe, + 0x09, 0x6e, 0xe6, 0x2f, 0xb3, 0x00, 0x4c, 0x04, 0x1e, 0xbe, 0xde, 0x62, 0x29, 0x0f, 0x77, 0xdc, + 0x7a, 0x3a, 0x1f, 0x99, 0xd3, 0xa3, 0xd0, 0x41, 0xe4, 0x37, 0xdc, 0x71, 0xeb, 0x58, 0x30, 0x41, + 0x0d, 0x18, 0x69, 0x5b, 0xc1, 0x4e, 0xfa, 0x21, 0xef, 0x79, 0x1e, 0xc7, 0x15, 0xec, 0x60, 0xc6, + 0x00, 0xbd, 0x6a, 0xc0, 0x18, 0x0f, 0x7a, 0x97, 0x16, 0xf7, 0xa1, 0x9f, 0x95, 0x65, 0x9f, 0x2d, + 0xf2, 0xc8, 0x7a, 0xe1, 0xfa, 0xa1, 0x54, 0xb2, 0x28, 0xc5, 0x92, 0xed, 0xc2, 0xeb, 0x06, 0x4c, + 0xe8, 0xa8, 0x09, 0x4e, 0x1b, 0x1f, 0xd3, 0x9d, 0x36, 0xd2, 0xec, 0x0f, 0xdd, 0xff, 0xe3, 0xef, + 0x0d, 0xd0, 0xbe, 0x1a, 0x1c, 0xba, 0x80, 0x1a, 0x03, 0xbb, 0x80, 0x66, 0x8e, 0xe9, 0x02, 0x9a, + 0x3d, 0x96, 0x0b, 0xe8, 0xc8, 0xf1, 0x5d, 0x40, 0x73, 0xfd, 0x5d, 0x40, 0xcd, 0x37, 0x0d, 0x98, + 0xed, 0xd9, 0x87, 0xe9, 0xb1, 0xcd, 0x73, 0xdd, 0xa0, 0x8f, 0xe7, 0x15, 0x0e, 0x41, 0x58, 0xc7, + 0x43, 0x2b, 0x30, 0x23, 0x12, 0x7c, 0x57, 0xdb, 0x4d, 0x3b, 0x31, 0x1d, 0xc1, 0x66, 0x0c, 0x8e, + 0x7b, 0x6a, 0x98, 0x7f, 0x6c, 0xc0, 0xb8, 0x16, 0xc4, 0x48, 0xdb, 0xc1, 0x82, 0x3d, 0x85, 0x18, + 0x61, 0x6e, 0x73, 0xf6, 0xc2, 0xc1, 0x61, 0xfc, 0xb1, 0xad, 0xa1, 0xa5, 0x7f, 0x0d, 0x1f, 0xdb, + 0x68, 0x29, 0x16, 0x50, 0x9e, 0xd8, 0x93, 0xb4, 0x59, 0xa7, 0x67, 0xf5, 0xc4, 0x9e, 0xa4, 0x8d, + 0x19, 0x84, 0xb1, 0xa3, 0xe7, 0x57, 0xe1, 0x1d, 0xac, 0xa5, 0x52, 0xb7, 0xbc, 0x00, 0x73, 0x18, + 0x3a, 0x0f, 0x59, 0xe2, 0xd4, 0xc5, 0x65, 0x5b, 0x7d, 0xbe, 0xec, 0xa2, 0x53, 0xc7, 0xb4, 0xdc, + 0xbc, 0x0a, 0x13, 0x55, 0x52, 0xf3, 0x48, 0xf0, 0x02, 0x39, 0x18, 0xf8, 0x7b, 0x68, 0x74, 0xb6, + 0xc7, 0xbe, 0x87, 0x46, 0xab, 0xd3, 0x72, 0xf3, 0xf7, 0x0c, 0x88, 0xe5, 0xfb, 0xd7, 0x0c, 0xef, + 0x46, 0x3f, 0xc3, 0x7b, 0xc4, 0x44, 0x9c, 0x39, 0xd2, 0x44, 0x7c, 0x05, 0x50, 0x8b, 0x2e, 0x85, + 0xc8, 0xd7, 0x2d, 0x84, 0x9d, 0x23, 0x0c, 0x99, 0xee, 0xc1, 0xc0, 0x09, 0xb5, 0xcc, 0xdf, 0xe5, + 0xc2, 0xea, 0x5f, 0x00, 0xb8, 0x7b, 0x07, 0x74, 0x20, 0xc7, 0x48, 0x09, 0x63, 0xcf, 0x90, 0x86, + 0xd2, 0xde, 0xd4, 0x23, 0xe1, 0x40, 0x8a, 0x25, 0xcf, 0xb8, 0x99, 0x3f, 0xe2, 0xb2, 0x6a, 0x9f, + 0x08, 0x18, 0x40, 0xd6, 0x56, 0x54, 0xd6, 0xcb, 0x69, 0xed, 0x95, 0xc9, 0x32, 0xa2, 0x45, 0x80, + 0x36, 0xf1, 0x6a, 0xc4, 0x09, 0xa4, 0xd3, 0x7a, 0x4e, 0x04, 0x15, 0xa9, 0x52, 0xac, 0x61, 0x98, + 0xaf, 0x1a, 0x30, 0x53, 0x0d, 0xec, 0xda, 0xae, 0xed, 0xf0, 0x20, 0xb9, 0x6d, 0xbb, 0x41, 0x6f, + 0x47, 0x44, 0x7c, 0xea, 0x8b, 0x9b, 0xdf, 0xd4, 0x56, 0x2c, 0xbf, 0xf0, 0x25, 0xe1, 0xa8, 0x04, + 0xd3, 0xf2, 0xd1, 0x41, 0xda, 0x4c, 0x79, 0x70, 0xaf, 0xb2, 0xd1, 0xac, 0x44, 0xc1, 0x38, 0x8e, + 0x6f, 0x7e, 0x1a, 0xc6, 0xb5, 0xfd, 0x95, 0x6d, 0x45, 0xb7, 0xad, 0x5a, 0x10, 0x5f, 0xc2, 0x17, + 0x69, 0x21, 0xe6, 0x30, 0x66, 0xda, 0xe5, 0x5e, 0xcd, 0xb1, 0x25, 0x2c, 0x7c, 0x99, 0x05, 0x94, + 0x12, 0xf3, 0x48, 0x83, 0xdc, 0x96, 0x89, 0x66, 0x25, 0x31, 0x4c, 0x0b, 0x31, 0x87, 0x99, 0x8f, + 0x41, 0x5e, 0xa6, 0x60, 0x60, 0x71, 0xcc, 0xd2, 0xec, 0xa8, 0xc7, 0x31, 0xbb, 0x5e, 0x80, 0x19, + 0xc4, 0xbc, 0x01, 0x79, 0x99, 0x29, 0xe2, 0xee, 0xd8, 0x74, 0x55, 0xf9, 0x8e, 0x7d, 0xd9, 0xf5, + 0x03, 0x99, 0xde, 0x82, 0xbf, 0x8c, 0x6c, 0xac, 0xb2, 0x32, 0xac, 0xa0, 0xe6, 0x2c, 0x4c, 0xab, + 0x27, 0x0f, 0xe1, 0x66, 0xfa, 0xdd, 0x2c, 0x4c, 0x44, 0xbe, 0x9e, 0x7d, 0xf7, 0xe9, 0x36, 0xf8, + 0x2a, 0x4e, 0x78, 0xba, 0xc8, 0x1e, 0xf3, 0xe9, 0x42, 0x7f, 0x2b, 0x1a, 0x39, 0xdd, 0xb7, 0xa2, + 0x5c, 0x3a, 0x6f, 0x45, 0x01, 0x8c, 0xf9, 0x42, 0x51, 0x8d, 0xa6, 0x61, 0xc4, 0x89, 0x8d, 0x18, + 0x3f, 0x1b, 0x4b, 0x7d, 0x27, 0x59, 0x99, 0xdf, 0xca, 0xc1, 0x54, 0x34, 0x47, 0xd6, 0x00, 0x23, + 0xf9, 0x58, 0xcf, 0x48, 0x1e, 0xd3, 0x56, 0x9a, 0x1d, 0xd6, 0x56, 0x3a, 0x32, 0xac, 0xad, 0x34, + 0x77, 0x02, 0x5b, 0x69, 0xaf, 0xa5, 0x73, 0x74, 0x60, 0x4b, 0xe7, 0xb3, 0xca, 0xef, 0x68, 0x2c, + 0xf2, 0x50, 0x1f, 0xfa, 0x1d, 0xa1, 0xe8, 0x30, 0x2c, 0xbb, 0xf5, 0x44, 0xff, 0xad, 0xfc, 0x5d, + 0x6c, 0x42, 0x5e, 0xa2, 0x9b, 0xd0, 0xf1, 0x9f, 0x63, 0xde, 0x71, 0x0c, 0x17, 0xa1, 0xa7, 0x60, + 0x5c, 0xcc, 0x27, 0x76, 0x56, 0x82, 0xe8, 0x39, 0xab, 0x1a, 0x82, 0xb0, 0x8e, 0xc7, 0xbe, 0x84, + 0x1a, 0xfd, 0xf4, 0x2b, 0x33, 0x3d, 0xeb, 0x5f, 0x42, 0x8d, 0x7d, 0x2a, 0x36, 0x8e, 0x6f, 0x7e, + 0x12, 0xce, 0x26, 0xde, 0x04, 0x99, 0x69, 0x8c, 0xa9, 0x71, 0x52, 0x17, 0x08, 0x9a, 0x18, 0xb1, + 0x14, 0xca, 0x0b, 0x37, 0xfb, 0x62, 0xe2, 0x23, 0xa8, 0x98, 0xdf, 0xcc, 0xc2, 0x54, 0xf4, 0x33, + 0x5a, 0x68, 0x5f, 0xd9, 0x8d, 0x52, 0x31, 0x59, 0x71, 0xb2, 0x5a, 0xde, 0xa5, 0xbe, 0x46, 0xe0, + 0x7d, 0x36, 0xbf, 0xb6, 0x54, 0x12, 0xa8, 0xd3, 0x63, 0x2c, 0xac, 0xaf, 0x82, 0x1d, 0xfb, 0x52, + 0x56, 0x18, 0x8c, 0x22, 0xae, 0x5d, 0xa9, 0x73, 0x0f, 0xc3, 0x4b, 0x14, 0x2b, 0xac, 0xb1, 0xa5, + 0xba, 0x65, 0x8f, 0x78, 0xf6, 0xb6, 0xad, 0x3e, 0x01, 0xca, 0x76, 0xee, 0x1b, 0xa2, 0x0c, 0x2b, + 0xa8, 0xf9, 0x6a, 0x06, 0xc2, 0x0f, 0x1e, 0xb3, 0x6f, 0xcd, 0xf8, 0xda, 0x11, 0x57, 0x0c, 0xdb, + 0x95, 0x61, 0x3f, 0xe8, 0x14, 0x52, 0x14, 0x3e, 0xa1, 0x5a, 0x09, 0x8e, 0x70, 0xfc, 0x0d, 0x7c, + 0xe8, 0xd8, 0x82, 0xe9, 0x58, 0x48, 0x70, 0xea, 0xfe, 0xfb, 0xbf, 0xc8, 0x42, 0x41, 0x05, 0x55, + 0xa3, 0xf7, 0x47, 0xec, 0x0d, 0x85, 0xf2, 0x3b, 0xb5, 0x0f, 0x21, 0xec, 0xb8, 0xf5, 0x3b, 0xdd, + 0xe2, 0xb4, 0x42, 0x8e, 0xd9, 0x0e, 0xce, 0x43, 0xb6, 0xe3, 0x35, 0xe3, 0x17, 0x8a, 0xeb, 0x78, + 0x0d, 0xd3, 0x72, 0x74, 0x3b, 0x7e, 0xe1, 0x5f, 0x4f, 0x29, 0x10, 0x9c, 0x9f, 0xbc, 0xfb, 0x5f, + 0xf4, 0xa9, 0x96, 0xdc, 0x72, 0xeb, 0x07, 0xf1, 0x0f, 0x27, 0x94, 0xdd, 0xfa, 0x01, 0x66, 0x10, + 0xf4, 0x1c, 0x4c, 0x05, 0x76, 0x8b, 0xb8, 0x9d, 0x40, 0xff, 0x9c, 0x6c, 0x36, 0x7c, 0xd4, 0xdc, + 0x8c, 0x40, 0x71, 0x0c, 0x9b, 0x6a, 0xd9, 0x5b, 0xbe, 0xeb, 0xb0, 0x6c, 0x88, 0xa3, 0xd1, 0x17, + 0x90, 0x2b, 0xd5, 0xab, 0x1b, 0xcc, 0xee, 0xa1, 0x30, 0x28, 0xb6, 0xcd, 0x22, 0x1a, 0x3d, 0x22, + 0x7c, 0x0a, 0x66, 0xc2, 0xfc, 0x1a, 0xbc, 0x1c, 0x2b, 0x0c, 0xb4, 0xc2, 0x69, 0x53, 0x69, 0x99, + 0x46, 0x99, 0x28, 0x3f, 0x2a, 0xe9, 0xd2, 0xb2, 0x23, 0x23, 0x83, 0x54, 0x4d, 0xf3, 0x3a, 0x4c, + 0xc7, 0x3a, 0x4c, 0x5e, 0x00, 0x8d, 0xe4, 0x0b, 0xe0, 0x60, 0xdf, 0x3a, 0xf8, 0x03, 0x03, 0x66, + 0x7b, 0xb6, 0x80, 0x41, 0xc3, 0x53, 0xe2, 0xca, 0x28, 0x73, 0x72, 0x65, 0x94, 0x3d, 0x9e, 0x32, + 0x2a, 0x6f, 0x7d, 0xff, 0xad, 0x0b, 0xf7, 0xfd, 0xf0, 0xad, 0x0b, 0xf7, 0xfd, 0xe4, 0xad, 0x0b, + 0xf7, 0xbd, 0x7a, 0x78, 0xc1, 0xf8, 0xfe, 0xe1, 0x05, 0xe3, 0x87, 0x87, 0x17, 0x8c, 0x9f, 0x1c, + 0x5e, 0x30, 0xfe, 0xfa, 0xf0, 0x82, 0xf1, 0xe6, 0x2f, 0x2e, 0xdc, 0xf7, 0xe2, 0xb3, 0xe1, 0x04, + 0x5d, 0x92, 0x13, 0x94, 0xfd, 0x78, 0x8f, 0x9c, 0x8e, 0x4b, 0xed, 0xdd, 0xc6, 0x12, 0x9d, 0xa0, + 0x4b, 0xaa, 0x44, 0x4e, 0xd0, 0x7f, 0x09, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xa1, 0xef, 0x00, 0x88, + 0x96, 0x00, 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -6898,6 +6931,18 @@ func (m *MetricProvider) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Plugin != nil { + { + size, err := m.Plugin.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } if m.Influxdb != nil { { size, err := m.Influxdb.MarshalToSizedBuffer(dAtA[:i]) @@ -7322,6 +7367,36 @@ func (m *PingPongSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PluginMetric) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PluginMetric) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PluginMetric) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Config != nil { + i -= len(m.Config) + copy(dAtA[i:], m.Config) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Config))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *PodTemplateMetadata) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10842,6 +10917,10 @@ func (m *MetricProvider) Size() (n int) { l = m.Influxdb.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Plugin != nil { + l = m.Plugin.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -10956,6 +11035,19 @@ func (m *PingPongSpec) Size() (n int) { return n } +func (m *PluginMetric) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Config != nil { + l = len(m.Config) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *PodTemplateMetadata) Size() (n int) { if m == nil { return 0 @@ -12687,6 +12779,7 @@ func (this *MetricProvider) String() string { `CloudWatch:` + strings.Replace(this.CloudWatch.String(), "CloudWatchMetric", "CloudWatchMetric", 1) + `,`, `Graphite:` + strings.Replace(this.Graphite.String(), "GraphiteMetric", "GraphiteMetric", 1) + `,`, `Influxdb:` + strings.Replace(this.Influxdb.String(), "InfluxdbMetric", "InfluxdbMetric", 1) + `,`, + `Plugin:` + strings.Replace(this.Plugin.String(), "PluginMetric", "PluginMetric", 1) + `,`, `}`, }, "") return s @@ -12794,6 +12887,16 @@ func (this *PingPongSpec) String() string { }, "") return s } +func (this *PluginMetric) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PluginMetric{`, + `Config:` + valueToStringGenerated(this.Config) + `,`, + `}`, + }, "") + return s +} func (this *PodTemplateMetadata) String() string { if this == nil { return "nil" @@ -23659,6 +23762,42 @@ func (m *MetricProvider) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Plugin", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Plugin == nil { + m.Plugin = &PluginMetric{} + } + if err := m.Plugin.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -24851,6 +24990,90 @@ func (m *PingPongSpec) Unmarshal(dAtA []byte) error { } return nil } +func (m *PluginMetric) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PluginMetric: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PluginMetric: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Config", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Config = append(m.Config[:0], dAtA[iNdEx:postIndex]...) + if m.Config == nil { + m.Config = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *PodTemplateMetadata) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index df63a7f33c..9d9d027d60 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -976,6 +976,9 @@ message MetricProvider { // Influxdb specifies the influxdb metric to query optional InfluxdbMetric influxdb = 10; + + // Plugin specifies the hashicorp go-plugin metric to query + optional PluginMetric plugin = 11; } // MetricResult contain a list of the most recent measurements for a single metric along with @@ -1072,6 +1075,12 @@ message PingPongSpec { optional string pongService = 2; } +message PluginMetric { + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + optional bytes config = 1; +} + // PodTemplateMetadata extra labels to add to the template message PodTemplateMetadata { // Labels Additional labels to add to the experiment diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index d124a2acf3..be10fbd4cd 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -95,6 +95,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.ObjectRef": schema_pkg_apis_rollouts_v1alpha1_ObjectRef(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PauseCondition": schema_pkg_apis_rollouts_v1alpha1_PauseCondition(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PingPongSpec": schema_pkg_apis_rollouts_v1alpha1_PingPongSpec(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginMetric": schema_pkg_apis_rollouts_v1alpha1_PluginMetric(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PodTemplateMetadata": schema_pkg_apis_rollouts_v1alpha1_PodTemplateMetadata(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PreferredDuringSchedulingIgnoredDuringExecution": schema_pkg_apis_rollouts_v1alpha1_PreferredDuringSchedulingIgnoredDuringExecution(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PrometheusMetric": schema_pkg_apis_rollouts_v1alpha1_PrometheusMetric(ref), @@ -2925,11 +2926,17 @@ func schema_pkg_apis_rollouts_v1alpha1_MetricProvider(ref common.ReferenceCallba Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.InfluxdbMetric"), }, }, + "plugin": { + SchemaProps: spec.SchemaProps{ + Description: "Plugin specifies the hashicorp go-plugin metric to query", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginMetric"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.CloudWatchMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.DatadogMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.GraphiteMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.InfluxdbMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.JobMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.KayentaMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.NewRelicMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PrometheusMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WavefrontMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WebMetric"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.CloudWatchMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.DatadogMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.GraphiteMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.InfluxdbMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.JobMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.KayentaMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.NewRelicMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PrometheusMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WavefrontMetric", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WebMetric"}, } } @@ -3217,6 +3224,24 @@ func schema_pkg_apis_rollouts_v1alpha1_PingPongSpec(ref common.ReferenceCallback } } +func schema_pkg_apis_rollouts_v1alpha1_PluginMetric(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "config": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + }, + }, + } +} + func schema_pkg_apis_rollouts_v1alpha1_PodTemplateMetadata(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go index dad43fb3e0..db989aa202 100644 --- a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go @@ -1663,6 +1663,11 @@ func (in *MetricProvider) DeepCopyInto(out *MetricProvider) { *out = new(InfluxdbMetric) **out = **in } + if in.Plugin != nil { + in, out := &in.Plugin, &out.Plugin + *out = new(PluginMetric) + (*in).DeepCopyInto(*out) + } return } @@ -1794,6 +1799,27 @@ func (in *PingPongSpec) DeepCopy() *PingPongSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PluginMetric) DeepCopyInto(out *PluginMetric) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginMetric. +func (in *PluginMetric) DeepCopy() *PluginMetric { + if in == nil { + return nil + } + out := new(PluginMetric) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodTemplateMetadata) DeepCopyInto(out *PodTemplateMetadata) { *out = *in diff --git a/rollout/controller_test.go b/rollout/controller_test.go index d7683fddec..1d9a738254 100644 --- a/rollout/controller_test.go +++ b/rollout/controller_test.go @@ -1944,6 +1944,9 @@ func TestWriteBackToInformer(t *testing.T) { roKey := getKey(r1, t) f.runController(roKey, true, false, c, i, k8sI) + // Give controller a little time to process the rollout + time.Sleep(250 * time.Millisecond) + // Verify the informer was updated with the new unstructured object after reconciliation obj, exists, err := c.rolloutsIndexer.GetByKey(roKey) assert.NoError(t, err) diff --git a/utils/analysis/factory.go b/utils/analysis/factory.go index 0fb57030f5..56ea1d3798 100644 --- a/utils/analysis/factory.go +++ b/utils/analysis/factory.go @@ -225,6 +225,9 @@ func ValidateMetric(metric v1alpha1.Metric) error { if metric.Provider.Influxdb != nil { numProviders++ } + if metric.Provider.Plugin != nil { + numProviders++ + } if numProviders == 0 { return fmt.Errorf("no provider specified") } diff --git a/utils/defaults/defaults.go b/utils/defaults/defaults.go index db605eb99c..37b90365dc 100644 --- a/utils/defaults/defaults.go +++ b/utils/defaults/defaults.go @@ -2,6 +2,7 @@ package defaults import ( "io/ioutil" + "net/url" "os" "strconv" "strings" @@ -45,6 +46,10 @@ const ( // DefaultMetricCleanupDelay is the default time to delay metrics removal upon object removal, gives time for metrics // to be collected DefaultMetricCleanupDelay = int32(65) + // DefaultMetricsPluginLocation is the default path to the metrics plugin binary + DefaultMetricsPluginLocation = "" + // DefaultPluginHttpFileLocation is the default path to the metrics plugin when downloaded via http(s) + DefaultPluginHttpFileLocation = "/tmp/metric-plugin" ) const ( @@ -68,6 +73,7 @@ var ( targetGroupBindingAPIVersion = DefaultTargetGroupBindingAPIVersion appmeshCRDVersion = DefaultAppMeshCRDVersion defaultMetricCleanupDelay = DefaultMetricCleanupDelay + metricPluginLocation = &url.URL{Path: DefaultMetricsPluginLocation} ) const ( @@ -320,3 +326,25 @@ func GetMetricCleanupDelaySeconds() time.Duration { func SetMetricCleanupDelaySeconds(seconds int32) { defaultMetricCleanupDelay = seconds } + +// GetMetricPluginLocation returns the location of the metric plugin binary +func GetMetricPluginLocation() string { + switch metricPluginLocation.Scheme { + case "http", "https": + return DefaultPluginHttpFileLocation // return relative path to the plugin + case "file": + return metricPluginLocation.Path + default: + return "" + } +} + +// SetMetricPluginLocation sets the location of the metric plugin binary +func SetMetricPluginLocation(pluginLocation string) error { + urlObj, err := url.ParseRequestURI(pluginLocation) + if err != nil { + return err + } + metricPluginLocation = urlObj + return nil +} diff --git a/utils/defaults/defaults_test.go b/utils/defaults/defaults_test.go index 2162f1be82..7ffa9e9157 100644 --- a/utils/defaults/defaults_test.go +++ b/utils/defaults/defaults_test.go @@ -411,4 +411,19 @@ func TestSetDefaults(t *testing.T) { assert.Equal(t, DefaultMetricCleanupDelay, int32(GetMetricCleanupDelaySeconds().Seconds())) SetMetricCleanupDelaySeconds(24) assert.Equal(t, time.Duration(24)*time.Second, GetMetricCleanupDelaySeconds()) + + assert.Equal(t, DefaultMetricsPluginLocation, "") + err := SetMetricPluginLocation("file:///tmp/metric-plugin") + assert.NoError(t, err) + assert.Equal(t, "/tmp/metric-plugin", GetMetricPluginLocation()) + + assert.Equal(t, DefaultMetricsPluginLocation, "") + err = SetMetricPluginLocation("http://localhost:8080/metric-plugin") + assert.NoError(t, err) + assert.Equal(t, DefaultPluginHttpFileLocation, GetMetricPluginLocation()) + + err = SetMetricPluginLocation("foo://localhost:8080/metric-plugin") + assert.NoError(t, err) + urlStr := GetMetricPluginLocation() + assert.Equal(t, "", urlStr) } diff --git a/utils/plugin/plugin.go b/utils/plugin/plugin.go new file mode 100644 index 0000000000..6b7222cd3b --- /dev/null +++ b/utils/plugin/plugin.go @@ -0,0 +1,125 @@ +package plugin + +import ( + "crypto/sha256" + "fmt" + "io" + "net/http" + "net/url" + "os" + "path/filepath" + + "github.com/argoproj/argo-rollouts/utils/defaults" + "github.com/argoproj/argo-rollouts/utils/time" + log "github.com/sirupsen/logrus" +) + +type FileDownloader interface { + Get(url string) (resp *http.Response, err error) +} + +type FileDownloaderImpl struct { + FileDownloader +} + +func (fd FileDownloaderImpl) Get(url string) (resp *http.Response, err error) { + return http.Get(url) +} + +// CheckPluginExists this function checks if the plugin exists in the configured path if not we panic +func checkPluginExists() error { + if defaults.GetMetricPluginLocation() != "" { + //Check for plugin executable existence + _, err := os.Stat(defaults.GetMetricPluginLocation()) + if err != nil { + return err + } + } + return nil +} + +func checkShaOfPlugin(pluginLocation string, expectedSha256 string) (bool, error) { + hasher := sha256.New() + fileBytes, err := os.ReadFile(pluginLocation) + if err != nil { + return false, err + } + fileSha256 := fmt.Sprintf("%x", hasher.Sum(fileBytes)) + log.Printf("exected sha256: %s, actual sha256: %s, of downloaded metric plugin", expectedSha256, fileSha256) + return fileSha256 == expectedSha256, nil +} + +func downloadFile(filepath string, url string, downloader FileDownloader) error { + // Get the data + resp, err := downloader.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + // Create the file + out, err := os.Create(filepath) + if err != nil { + return err + } + defer out.Close() + + // Write the body to file + _, err = io.Copy(out, resp.Body) + if err != nil { + return err + } + + // Set the file permissions, to allow execution + err = os.Chmod(filepath, 0700) + if err != nil { + return err + } + + return err +} + +// InitMetricsPlugin this function downloads and/or checks that a plugin executable exits on the filesystem +func InitMetricsPlugin(pluginPath string, fd FileDownloader, expectedSha256Hash string) error { + if pluginPath == "" { + return nil + } + + urlObj, err := url.ParseRequestURI(pluginPath) + if err != nil { + return err + } + + switch urlObj.Scheme { + case "http", "https": + log.Printf("Downloading plugin from: %s", pluginPath) + startTime := time.Now() + err = downloadFile(defaults.DefaultPluginHttpFileLocation, urlObj.String(), fd) + if err != nil { + return err + } + timeTakenToDownload := time.Now().Sub(startTime) + log.Printf("Download complete, it took %s", timeTakenToDownload) + defaults.SetMetricPluginLocation("file://" + defaults.DefaultPluginHttpFileLocation) + + if expectedSha256Hash != "" { + sha256Matched, err := checkShaOfPlugin(defaults.DefaultPluginHttpFileLocation, expectedSha256Hash) + if err != nil { + return err + } + if !sha256Matched { + return fmt.Errorf("sha256 hash of downloaded plugin does not match expected hash") + } + } + case "file": + pluginPath, err = filepath.Abs(urlObj.Host + urlObj.Path) + if err != nil { + return err + } + defaults.SetMetricPluginLocation(urlObj.Scheme + "://" + pluginPath) + default: + return fmt.Errorf("plugin location must be of http(s) or file scheme") + } + + return checkPluginExists() +} diff --git a/utils/plugin/plugin_test.go b/utils/plugin/plugin_test.go new file mode 100644 index 0000000000..a56587e9be --- /dev/null +++ b/utils/plugin/plugin_test.go @@ -0,0 +1,72 @@ +package plugin + +import ( + "bytes" + "io" + "net/http" + "os" + "path/filepath" + "testing" + + "github.com/argoproj/argo-rollouts/utils/defaults" + "github.com/tj/assert" +) + +type MockFileDownloader struct { + FileDownloader +} + +func (m MockFileDownloader) Get(url string) (*http.Response, error) { + responseBody := io.NopCloser(bytes.NewReader([]byte(`test`))) + return &http.Response{ + Status: "200", + StatusCode: 200, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: nil, + Body: responseBody, + ContentLength: 4, + }, nil +} + +func TestInitPlugin(t *testing.T) { + fd := &MockFileDownloader{} + + err := InitMetricsPlugin("file://./plugin.go", fd, "") + assert.NoError(t, err) + + err = InitMetricsPlugin("file://plugin.go", fd, "") + assert.NoError(t, err) + + err = InitMetricsPlugin("file://./file-not-found.go", fd, "") + assert.Error(t, err) + + err = InitMetricsPlugin("file://file-not-found.go", fd, "") + assert.Error(t, err) + + err = InitMetricsPlugin("file://./../../Dockerfile", fd, "") + assert.NoError(t, err) + + f, err := filepath.Abs("plugin.go") + if err != nil { + t.Fatal(err) + } + err = InitMetricsPlugin("file://"+f, fd, "") + assert.NoError(t, err) + + f, err = filepath.Abs("file-not-found.go") + if err != nil { + t.Fatal(err) + } + err = InitMetricsPlugin("file://"+f, fd, "") + assert.Error(t, err) + + err = InitMetricsPlugin("http://mock-host:8080/plugin", fd, "74657374e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + assert.NoError(t, err) + + err = InitMetricsPlugin("http://mock-host:8080/plugin", fd, "bad-sha") + assert.Error(t, err) + + os.Remove(defaults.DefaultPluginHttpFileLocation) +}