From 031a885b333781d8bcc0c814d7b156d3e5eff0f3 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 5 Apr 2024 15:34:31 -0400 Subject: [PATCH 01/41] making code for step plugin Signed-off-by: Alexandre Gaudreault --- Makefile | 3 + controller/controller.go | 3 + go.mod | 6 +- go.sum | 12 + hack/update-mocks.sh | 13 +- pkg/apiclient/rollout/rollout.swagger.json | 56 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 2181 +++++++++++------ pkg/apis/rollouts/v1alpha1/generated.proto | 35 + pkg/apis/rollouts/v1alpha1/types.go | 39 + pkg/apis/rollouts/validation/validation.go | 10 +- rollout/canary.go | 9 +- rollout/controller.go | 6 +- rollout/stepplugin.go | 72 + rollout/stepplugin_test.go | 186 ++ rollout/steps/plugin/client/client.go | 101 + rollout/steps/plugin/mocks/Resolver.go | 54 + rollout/steps/plugin/mocks/StepPlugin.go | 115 + rollout/steps/plugin/plugin.go | 107 + rollout/steps/plugin/resolver.go | 32 + rollout/steps/plugin/rpc/rpc.go | 197 ++ rollout/steps/plugin/rpc/rpc_test.go | 171 ++ .../plugin/rpc/rpc_test_implementation.go | 29 + .../internal/plugin/docs.go | 3 + .../internal/plugin/plugin.go | 215 ++ test/cmd/step-plugin-sample/main.go | 86 + utils/plugin/types/steps.go | 28 + utils/plugin/types/types.go | 12 + utils/rollout/rolloututil.go | 3 + 28 files changed, 3068 insertions(+), 716 deletions(-) create mode 100644 rollout/stepplugin.go create mode 100644 rollout/stepplugin_test.go create mode 100644 rollout/steps/plugin/client/client.go create mode 100644 rollout/steps/plugin/mocks/Resolver.go create mode 100644 rollout/steps/plugin/mocks/StepPlugin.go create mode 100644 rollout/steps/plugin/plugin.go create mode 100644 rollout/steps/plugin/resolver.go create mode 100644 rollout/steps/plugin/rpc/rpc.go create mode 100644 rollout/steps/plugin/rpc/rpc_test.go create mode 100644 rollout/steps/plugin/rpc/rpc_test_implementation.go create mode 100644 test/cmd/step-plugin-sample/internal/plugin/docs.go create mode 100644 test/cmd/step-plugin-sample/internal/plugin/plugin.go create mode 100644 test/cmd/step-plugin-sample/main.go create mode 100644 utils/plugin/types/steps.go diff --git a/Makefile b/Makefile index a17bf33676..6768de81a7 100644 --- a/Makefile +++ b/Makefile @@ -146,6 +146,9 @@ gen-crd: install-go-tools-local ## generate crd manifests gen-mocks: install-go-tools-local ## generate mock files ./hack/update-mocks.sh +gen-mocks-fast: + ./hack/update-mocks.sh + # generates openapi_generated.go .PHONY: gen-openapi gen-openapi: $(DIST_DIR)/openapi-gen ## generate openapi files diff --git a/controller/controller.go b/controller/controller.go index e9509cd78e..16af0b34b5 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -13,6 +13,7 @@ import ( istioutil "github.com/argoproj/argo-rollouts/utils/istio" + stepPlugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" rolloutsConfig "github.com/argoproj/argo-rollouts/utils/config" goPlugin "github.com/hashicorp/go-plugin" @@ -303,6 +304,7 @@ func NewManager( serviceWorkqueue := workqueue.NewNamedRateLimitingQueue(queue.DefaultArgoRolloutsRateLimiter(), "Services") ingressWorkqueue := workqueue.NewNamedRateLimitingQueue(queue.DefaultArgoRolloutsRateLimiter(), "Ingresses") + stepPluginResolver := stepPlugin.NewResolver() refResolver := rollout.NewInformerBasedWorkloadRefResolver(namespace, dynamicclientset, discoveryClient, argoprojclientset, rolloutsInformer.Informer()) apiFactory := notificationapi.NewFactory(record.NewAPIFactorySettings(analysisRunInformer), defaults.Namespace(), notificationSecretInformerFactory.Core().V1().Secrets().Informer(), notificationConfigMapInformerFactory.Core().V1().ConfigMaps().Informer()) recorder := record.NewEventRecorder(kubeclientset, metrics.MetricRolloutEventsTotal, metrics.MetricNotificationFailedTotal, metrics.MetricNotificationSuccessTotal, metrics.MetricNotificationSend, apiFactory) @@ -345,6 +347,7 @@ func NewManager( IngressWorkQueue: ingressWorkqueue, MetricsServer: metricsServer, Recorder: recorder, + StepPluginResolver: stepPluginResolver, }) experimentController := experiments.NewController(experiments.ControllerConfig{ diff --git a/go.mod b/go.mod index 5e423a2e93..c30016a9fb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/argoproj/argo-rollouts -go 1.20 +go 1.21 + +toolchain go1.22.0 require ( github.com/antonmedv/expr v1.15.5 @@ -17,6 +19,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.3 + github.com/google/uuid v1.6.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/go-plugin v1.6.0 github.com/influxdata/influxdb-client-go/v2 v2.13.0 @@ -118,7 +121,6 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect diff --git a/go.sum b/go.sum index 5c5c9f6e16..b6e32badba 100644 --- a/go.sum +++ b/go.sum @@ -88,6 +88,7 @@ github.com/argoproj/notifications-engine v0.4.1-0.20240219110818-7a069766e954/go github.com/argoproj/pkg v0.13.6 h1:36WPD9MNYECHcO1/R1pj6teYspiK7uMQLCgLGft2abM= github.com/argoproj/pkg v0.13.6/go.mod h1:I698DoJBKuvNFaixh4vFl2C88cNIT1WS7KCbz5ewyF8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.44.39/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.116 h1:NpLIhcvLWXJZAEwvPj3TDHeqp7DleK6ZUVYyW01WNHY= @@ -139,6 +140,7 @@ github.com/bombsimon/logrusr/v4 v4.1.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhO github.com/bradleyfalzon/ghinstallation/v2 v2.5.0 h1:yaYcGQ7yEIGbsJfW/9z7v1sLiZg/5rSNNXwmMct5XaE= github.com/bradleyfalzon/ghinstallation/v2 v2.5.0/go.mod h1:amcvPQMrRkWNdueWOjPytGL25xQGzox7425qMgzo+Vo= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= @@ -181,6 +183,7 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20220417044921-416226498f94 h1:VIy7cdK7ufs7ctpTFkXJHm1uP3dJSnCGSPysEICB1so= +github.com/elazarl/goproxy v0.0.0-20220417044921-416226498f94/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= @@ -208,6 +211,7 @@ github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBd github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -408,6 +412,7 @@ github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf/go.mod h1 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.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= 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= @@ -444,6 +449,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -540,6 +546,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -547,6 +554,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.13 h1:nV98dkBpqaYbDnhefmOQ+Rn4hE+jD6AtjYHXaU5WyJI= @@ -589,10 +597,12 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/servicemeshinterface/smi-sdk-go v0.5.0 h1:9cZdhvGbGDlmnp9qqmcQL+RL6KZ3IzHfDLoA5Axg8n0= github.com/servicemeshinterface/smi-sdk-go v0.5.0/go.mod h1:nm1Slf3pfaZPP3g2tE/K5wDmQ1uWVSP0p3uu5rQAQLc= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= @@ -809,6 +819,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1103,6 +1114,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/hack/update-mocks.sh b/hack/update-mocks.sh index 6f1bcfad4a..ee4dfd8869 100755 --- a/hack/update-mocks.sh +++ b/hack/update-mocks.sh @@ -12,12 +12,17 @@ mockery \ --name Provider \ --output "${PROJECT_ROOT}"/metricproviders/mocks -mockery \ - --dir "${PROJECT_ROOT}"/utils/aws \ - --name ELBv2APIClient \ - --output "${PROJECT_ROOT}"/utils/aws/mocks +# mockery \ +# --dir "${PROJECT_ROOT}"/utils/aws \ +# --name ELBv2APIClient \ +# --output "${PROJECT_ROOT}"/utils/aws/mocks mockery \ --dir "${PROJECT_ROOT}"/rollout/trafficrouting \ --name TrafficRoutingReconciler \ --output "${PROJECT_ROOT}"/rollout/mocks + +mockery \ + --dir "${PROJECT_ROOT}"/rollout/steps/plugin \ + --name "Resolver|StepPlugin" \ + --output "${PROJECT_ROOT}"/rollout/steps/plugin/mocks diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index 7279aea5e3..277d7ef5d2 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -965,6 +965,13 @@ "stablePingPong": { "type": "string", "title": "StablePingPong For the ping-pong feature holds the current stable service, ping or pong" + }, + "stepPluginStatuses": { + "type": "array", + "items": { + "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StepPluginStatus" + }, + "title": "StepPluginStatuses Hold the status of the step plugins executed" } }, "title": "CanaryStatus status fields that only pertain to the canary rollout" @@ -1000,6 +1007,10 @@ "setMirrorRoute": { "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.SetMirrorRoute", "title": "SetMirrorRoutes Mirrors traffic that matches rules to a particular destination\n+optional" + }, + "plugin": { + "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PluginStep", + "title": "Plugin defines a plugin to execute for a step" } }, "description": "CanaryStep defines a step of a canary deployment." @@ -1741,6 +1752,23 @@ }, "description": "PingPongSpec holds the ping and pong service name." }, + "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PluginStep": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Name the name of the hashicorp go-plugin step to query" + }, + "abortOnFailure": { + "type": "boolean" + }, + "config": { + "type": "string", + "format": "byte", + "title": "+kubebuilder:validation:Schemaless\n+kubebuilder:pruning:PreserveUnknownFields\n+kubebuilder:validation:Type=object\nConfig the configuration object for the specified plugin" + } + } + }, "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata": { "type": "object", "properties": { @@ -2499,6 +2527,34 @@ } } }, + "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StepPluginStatus": { + "type": "object", + "properties": { + "index": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "phase": { + "type": "string" + }, + "message": { + "type": "string" + }, + "startedAt": { + "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" + }, + "finishedAt": { + "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" + }, + "status": { + "type": "string", + "format": "byte" + } + } + }, "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StickinessConfig": { "type": "object", "properties": { diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index f1b6428971..31459cd842 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -1951,10 +1951,38 @@ func (m *PingPongSpec) XXX_DiscardUnknown() { var xxx_messageInfo_PingPongSpec proto.InternalMessageInfo +func (m *PluginStep) Reset() { *m = PluginStep{} } +func (*PluginStep) ProtoMessage() {} +func (*PluginStep) Descriptor() ([]byte, []int) { + return fileDescriptor_e0e705f843545fab, []int{68} +} +func (m *PluginStep) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PluginStep) 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 *PluginStep) XXX_Merge(src proto.Message) { + xxx_messageInfo_PluginStep.Merge(m, src) +} +func (m *PluginStep) XXX_Size() int { + return m.Size() +} +func (m *PluginStep) XXX_DiscardUnknown() { + xxx_messageInfo_PluginStep.DiscardUnknown(m) +} + +var xxx_messageInfo_PluginStep proto.InternalMessageInfo + func (m *PodTemplateMetadata) Reset() { *m = PodTemplateMetadata{} } func (*PodTemplateMetadata) ProtoMessage() {} func (*PodTemplateMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{68} + return fileDescriptor_e0e705f843545fab, []int{69} } func (m *PodTemplateMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1984,7 +2012,7 @@ func (m *PreferredDuringSchedulingIgnoredDuringExecution) Reset() { } func (*PreferredDuringSchedulingIgnoredDuringExecution) ProtoMessage() {} func (*PreferredDuringSchedulingIgnoredDuringExecution) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{69} + return fileDescriptor_e0e705f843545fab, []int{70} } func (m *PreferredDuringSchedulingIgnoredDuringExecution) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2012,7 +2040,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{70} + return fileDescriptor_e0e705f843545fab, []int{71} } func (m *PrometheusMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2042,7 +2070,7 @@ func (m *RequiredDuringSchedulingIgnoredDuringExecution) Reset() { } func (*RequiredDuringSchedulingIgnoredDuringExecution) ProtoMessage() {} func (*RequiredDuringSchedulingIgnoredDuringExecution) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{71} + return fileDescriptor_e0e705f843545fab, []int{72} } func (m *RequiredDuringSchedulingIgnoredDuringExecution) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2070,7 +2098,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{72} + return fileDescriptor_e0e705f843545fab, []int{73} } func (m *RollbackWindowSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2098,7 +2126,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{73} + return fileDescriptor_e0e705f843545fab, []int{74} } func (m *Rollout) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2126,7 +2154,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{74} + return fileDescriptor_e0e705f843545fab, []int{75} } func (m *RolloutAnalysis) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2154,7 +2182,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{75} + return fileDescriptor_e0e705f843545fab, []int{76} } func (m *RolloutAnalysisBackground) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2182,7 +2210,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{76} + return fileDescriptor_e0e705f843545fab, []int{77} } func (m *RolloutAnalysisRunStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2210,7 +2238,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{77} + return fileDescriptor_e0e705f843545fab, []int{78} } func (m *RolloutAnalysisTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2238,7 +2266,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{78} + return fileDescriptor_e0e705f843545fab, []int{79} } func (m *RolloutCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2266,7 +2294,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{79} + return fileDescriptor_e0e705f843545fab, []int{80} } func (m *RolloutExperimentStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2296,7 +2324,7 @@ func (m *RolloutExperimentStepAnalysisTemplateRef) Reset() { } func (*RolloutExperimentStepAnalysisTemplateRef) ProtoMessage() {} func (*RolloutExperimentStepAnalysisTemplateRef) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{80} + return fileDescriptor_e0e705f843545fab, []int{81} } func (m *RolloutExperimentStepAnalysisTemplateRef) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2324,7 +2352,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{81} + return fileDescriptor_e0e705f843545fab, []int{82} } func (m *RolloutExperimentTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2352,7 +2380,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{82} + return fileDescriptor_e0e705f843545fab, []int{83} } func (m *RolloutList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2380,7 +2408,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{83} + return fileDescriptor_e0e705f843545fab, []int{84} } func (m *RolloutPause) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2408,7 +2436,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{84} + return fileDescriptor_e0e705f843545fab, []int{85} } func (m *RolloutSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2436,7 +2464,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{85} + return fileDescriptor_e0e705f843545fab, []int{86} } func (m *RolloutStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2464,7 +2492,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{86} + return fileDescriptor_e0e705f843545fab, []int{87} } func (m *RolloutStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2492,7 +2520,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{87} + return fileDescriptor_e0e705f843545fab, []int{88} } func (m *RolloutTrafficRouting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2520,7 +2548,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{88} + return fileDescriptor_e0e705f843545fab, []int{89} } func (m *RouteMatch) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2548,7 +2576,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{89} + return fileDescriptor_e0e705f843545fab, []int{90} } func (m *RunSummary) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2576,7 +2604,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{90} + return fileDescriptor_e0e705f843545fab, []int{91} } func (m *SMITrafficRouting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2604,7 +2632,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{91} + return fileDescriptor_e0e705f843545fab, []int{92} } func (m *ScopeDetail) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2632,7 +2660,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{92} + return fileDescriptor_e0e705f843545fab, []int{93} } func (m *SecretKeyRef) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2660,7 +2688,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{93} + return fileDescriptor_e0e705f843545fab, []int{94} } func (m *SetCanaryScale) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2688,7 +2716,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{94} + return fileDescriptor_e0e705f843545fab, []int{95} } func (m *SetHeaderRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2716,7 +2744,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{95} + return fileDescriptor_e0e705f843545fab, []int{96} } func (m *SetMirrorRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2744,7 +2772,7 @@ var xxx_messageInfo_SetMirrorRoute proto.InternalMessageInfo func (m *Sigv4Config) Reset() { *m = Sigv4Config{} } func (*Sigv4Config) ProtoMessage() {} func (*Sigv4Config) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{96} + return fileDescriptor_e0e705f843545fab, []int{97} } func (m *Sigv4Config) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2772,7 +2800,7 @@ var xxx_messageInfo_Sigv4Config proto.InternalMessageInfo func (m *SkyWalkingMetric) Reset() { *m = SkyWalkingMetric{} } func (*SkyWalkingMetric) ProtoMessage() {} func (*SkyWalkingMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{97} + return fileDescriptor_e0e705f843545fab, []int{98} } func (m *SkyWalkingMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2797,10 +2825,38 @@ func (m *SkyWalkingMetric) XXX_DiscardUnknown() { var xxx_messageInfo_SkyWalkingMetric proto.InternalMessageInfo +func (m *StepPluginStatus) Reset() { *m = StepPluginStatus{} } +func (*StepPluginStatus) ProtoMessage() {} +func (*StepPluginStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_e0e705f843545fab, []int{99} +} +func (m *StepPluginStatus) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StepPluginStatus) 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 *StepPluginStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_StepPluginStatus.Merge(m, src) +} +func (m *StepPluginStatus) XXX_Size() int { + return m.Size() +} +func (m *StepPluginStatus) XXX_DiscardUnknown() { + xxx_messageInfo_StepPluginStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_StepPluginStatus proto.InternalMessageInfo + func (m *StickinessConfig) Reset() { *m = StickinessConfig{} } func (*StickinessConfig) ProtoMessage() {} func (*StickinessConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{98} + return fileDescriptor_e0e705f843545fab, []int{100} } func (m *StickinessConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2828,7 +2884,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{99} + return fileDescriptor_e0e705f843545fab, []int{101} } func (m *StringMatch) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2856,7 +2912,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{100} + return fileDescriptor_e0e705f843545fab, []int{102} } func (m *TCPRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2884,7 +2940,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{101} + return fileDescriptor_e0e705f843545fab, []int{103} } func (m *TLSRoute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2912,7 +2968,7 @@ var xxx_messageInfo_TLSRoute proto.InternalMessageInfo func (m *TTLStrategy) Reset() { *m = TTLStrategy{} } func (*TTLStrategy) ProtoMessage() {} func (*TTLStrategy) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{102} + return fileDescriptor_e0e705f843545fab, []int{104} } func (m *TTLStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2940,7 +2996,7 @@ var xxx_messageInfo_TTLStrategy proto.InternalMessageInfo func (m *TemplateService) Reset() { *m = TemplateService{} } func (*TemplateService) ProtoMessage() {} func (*TemplateService) Descriptor() ([]byte, []int) { - return fileDescriptor_e0e705f843545fab, []int{103} + return fileDescriptor_e0e705f843545fab, []int{105} } func (m *TemplateService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2968,7 +3024,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{104} + return fileDescriptor_e0e705f843545fab, []int{106} } func (m *TemplateSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2996,7 +3052,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{105} + return fileDescriptor_e0e705f843545fab, []int{107} } func (m *TemplateStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3024,7 +3080,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{106} + return fileDescriptor_e0e705f843545fab, []int{108} } func (m *TraefikTrafficRouting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3052,7 +3108,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{107} + return fileDescriptor_e0e705f843545fab, []int{109} } func (m *TrafficWeights) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3080,7 +3136,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{108} + return fileDescriptor_e0e705f843545fab, []int{110} } func (m *ValueFrom) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3108,7 +3164,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{109} + return fileDescriptor_e0e705f843545fab, []int{111} } func (m *WavefrontMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3136,7 +3192,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{110} + return fileDescriptor_e0e705f843545fab, []int{112} } func (m *WebMetric) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3164,7 +3220,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{111} + return fileDescriptor_e0e705f843545fab, []int{113} } func (m *WebMetricHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3192,7 +3248,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{112} + return fileDescriptor_e0e705f843545fab, []int{114} } func (m *WeightDestination) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3293,6 +3349,7 @@ func init() { proto.RegisterType((*ObjectRef)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.ObjectRef") proto.RegisterType((*PauseCondition)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PauseCondition") proto.RegisterType((*PingPongSpec)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PingPongSpec") + proto.RegisterType((*PluginStep)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PluginStep") proto.RegisterType((*PodTemplateMetadata)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata") proto.RegisterMapType((map[string]string)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata.AnnotationsEntry") proto.RegisterMapType((map[string]string)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.PodTemplateMetadata.LabelsEntry") @@ -3327,6 +3384,7 @@ func init() { proto.RegisterType((*SetMirrorRoute)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.SetMirrorRoute") proto.RegisterType((*Sigv4Config)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.Sigv4Config") proto.RegisterType((*SkyWalkingMetric)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.SkyWalkingMetric") + proto.RegisterType((*StepPluginStatus)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StepPluginStatus") proto.RegisterType((*StickinessConfig)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StickinessConfig") proto.RegisterType((*StringMatch)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StringMatch") proto.RegisterType((*TCPRoute)(nil), "github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.TCPRoute") @@ -3349,543 +3407,553 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 8566 bytes of a gzipped FileDescriptorProto + // 8727 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x6c, 0x24, 0xd9, - 0x71, 0x98, 0x9a, 0xc3, 0x21, 0x39, 0x35, 0x5c, 0x92, 0xfb, 0x76, 0xf7, 0x8e, 0xc7, 0xbb, 0xdd, - 0x59, 0xf5, 0x39, 0x97, 0x3d, 0xeb, 0x44, 0x4a, 0x7b, 0x77, 0xc9, 0x49, 0xa7, 0x5c, 0x32, 0x43, - 0xee, 0xde, 0x72, 0x8f, 0xdc, 0xe5, 0xd5, 0x70, 0x6f, 0x6d, 0x49, 0x67, 0xab, 0x39, 0xf3, 0x38, - 0xec, 0xe5, 0x4c, 0xf7, 0xa8, 0xbb, 0x87, 0xbb, 0x3c, 0x1d, 0xac, 0x93, 0x84, 0x53, 0x14, 0x41, - 0x82, 0x95, 0xd8, 0x42, 0x10, 0x24, 0x08, 0x14, 0xc3, 0x80, 0x93, 0xd8, 0x3f, 0x02, 0xc3, 0x41, - 0xf2, 0xc3, 0x40, 0x8c, 0x38, 0x76, 0x14, 0x20, 0x0e, 0xe4, 0x1f, 0x89, 0x9c, 0x00, 0xa6, 0x23, - 0x3a, 0x7f, 0x62, 0x24, 0x10, 0x12, 0x28, 0x30, 0xb2, 0x3f, 0x82, 0xe0, 0x7d, 0xf6, 0xeb, 0x9e, - 0x1e, 0xee, 0x90, 0xd3, 0x5c, 0x9d, 0x13, 0xff, 0x9b, 0x79, 0x55, 0xaf, 0xaa, 0xfa, 0x7d, 0xd6, - 0xab, 0x57, 0x55, 0x0f, 0xd6, 0x5a, 0x6e, 0xb4, 0xd3, 0xdb, 0x5a, 0x6c, 0xf8, 0x9d, 0x25, 0x27, - 0x68, 0xf9, 0xdd, 0xc0, 0xbf, 0xc7, 0x7f, 0x7c, 0x34, 0xf0, 0xdb, 0x6d, 0xbf, 0x17, 0x85, 0x4b, - 0xdd, 0xdd, 0xd6, 0x92, 0xd3, 0x75, 0xc3, 0x25, 0x5d, 0xb2, 0xf7, 0x71, 0xa7, 0xdd, 0xdd, 0x71, - 0x3e, 0xbe, 0xd4, 0xa2, 0x1e, 0x0d, 0x9c, 0x88, 0x36, 0x17, 0xbb, 0x81, 0x1f, 0xf9, 0xe4, 0x53, - 0x31, 0xb5, 0x45, 0x45, 0x8d, 0xff, 0xf8, 0x59, 0x55, 0x77, 0xb1, 0xbb, 0xdb, 0x5a, 0x64, 0xd4, - 0x16, 0x75, 0x89, 0xa2, 0xb6, 0xf0, 0x51, 0x43, 0x96, 0x96, 0xdf, 0xf2, 0x97, 0x38, 0xd1, 0xad, - 0xde, 0x36, 0xff, 0xc7, 0xff, 0xf0, 0x5f, 0x82, 0xd9, 0xc2, 0xb3, 0xbb, 0xaf, 0x84, 0x8b, 0xae, - 0xcf, 0x64, 0x5b, 0xda, 0x72, 0xa2, 0xc6, 0xce, 0xd2, 0x5e, 0x9f, 0x44, 0x0b, 0xb6, 0x81, 0xd4, - 0xf0, 0x03, 0x9a, 0x85, 0xf3, 0x52, 0x8c, 0xd3, 0x71, 0x1a, 0x3b, 0xae, 0x47, 0x83, 0xfd, 0xf8, - 0xab, 0x3b, 0x34, 0x72, 0xb2, 0x6a, 0x2d, 0x0d, 0xaa, 0x15, 0xf4, 0xbc, 0xc8, 0xed, 0xd0, 0xbe, - 0x0a, 0x7f, 0xe9, 0x51, 0x15, 0xc2, 0xc6, 0x0e, 0xed, 0x38, 0x7d, 0xf5, 0x5e, 0x1c, 0x54, 0xaf, - 0x17, 0xb9, 0xed, 0x25, 0xd7, 0x8b, 0xc2, 0x28, 0x48, 0x57, 0xb2, 0x7f, 0x58, 0x80, 0x52, 0x75, - 0xad, 0x56, 0x8f, 0x9c, 0xa8, 0x17, 0x92, 0xaf, 0x5a, 0x30, 0xdd, 0xf6, 0x9d, 0x66, 0xcd, 0x69, - 0x3b, 0x5e, 0x83, 0x06, 0xf3, 0xd6, 0x65, 0xeb, 0x4a, 0xf9, 0xea, 0xda, 0xe2, 0x28, 0xfd, 0xb5, - 0x58, 0xbd, 0x1f, 0x22, 0x0d, 0xfd, 0x5e, 0xd0, 0xa0, 0x48, 0xb7, 0x6b, 0xe7, 0xbf, 0x7b, 0x50, - 0xf9, 0xd0, 0xe1, 0x41, 0x65, 0x7a, 0xcd, 0xe0, 0x84, 0x09, 0xbe, 0xe4, 0xdb, 0x16, 0x9c, 0x6d, - 0x38, 0x9e, 0x13, 0xec, 0x6f, 0x3a, 0x41, 0x8b, 0x46, 0xaf, 0x07, 0x7e, 0xaf, 0x3b, 0x3f, 0x76, - 0x0a, 0xd2, 0x3c, 0x25, 0xa5, 0x39, 0xbb, 0x9c, 0x66, 0x87, 0xfd, 0x12, 0x70, 0xb9, 0xc2, 0xc8, - 0xd9, 0x6a, 0x53, 0x53, 0xae, 0xc2, 0x69, 0xca, 0x55, 0x4f, 0xb3, 0xc3, 0x7e, 0x09, 0xc8, 0xf3, - 0x30, 0xe9, 0x7a, 0xad, 0x80, 0x86, 0xe1, 0xfc, 0xf8, 0x65, 0xeb, 0x4a, 0xa9, 0x36, 0x2b, 0xab, - 0x4f, 0xae, 0x8a, 0x62, 0x54, 0x70, 0xfb, 0xd7, 0x0b, 0x70, 0xb6, 0xba, 0x56, 0xdb, 0x0c, 0x9c, - 0xed, 0x6d, 0xb7, 0x81, 0x7e, 0x2f, 0x72, 0xbd, 0x96, 0x49, 0xc0, 0x3a, 0x9a, 0x00, 0x79, 0x19, - 0xca, 0x21, 0x0d, 0xf6, 0xdc, 0x06, 0xdd, 0xf0, 0x83, 0x88, 0x77, 0x4a, 0xb1, 0x76, 0x4e, 0xa2, - 0x97, 0xeb, 0x31, 0x08, 0x4d, 0x3c, 0x56, 0x2d, 0xf0, 0xfd, 0x48, 0xc2, 0x79, 0x9b, 0x95, 0xe2, - 0x6a, 0x18, 0x83, 0xd0, 0xc4, 0x23, 0x2b, 0x30, 0xe7, 0x78, 0x9e, 0x1f, 0x39, 0x91, 0xeb, 0x7b, - 0x1b, 0x01, 0xdd, 0x76, 0x1f, 0xc8, 0x4f, 0x9c, 0x97, 0x75, 0xe7, 0xaa, 0x29, 0x38, 0xf6, 0xd5, - 0x20, 0xdf, 0xb2, 0x60, 0x2e, 0x8c, 0xdc, 0xc6, 0xae, 0xeb, 0xd1, 0x30, 0x5c, 0xf6, 0xbd, 0x6d, - 0xb7, 0x35, 0x5f, 0xe4, 0xdd, 0x76, 0x6b, 0xb4, 0x6e, 0xab, 0xa7, 0xa8, 0xd6, 0xce, 0x33, 0x91, - 0xd2, 0xa5, 0xd8, 0xc7, 0x9d, 0x7c, 0x04, 0x4a, 0xb2, 0x45, 0x69, 0x38, 0x3f, 0x71, 0xb9, 0x70, - 0xa5, 0x54, 0x3b, 0x73, 0x78, 0x50, 0x29, 0xad, 0xaa, 0x42, 0x8c, 0xe1, 0xf6, 0x0a, 0xcc, 0x57, - 0x3b, 0x5b, 0x4e, 0x18, 0x3a, 0x4d, 0x3f, 0x48, 0x75, 0xdd, 0x15, 0x98, 0xea, 0x38, 0xdd, 0xae, - 0xeb, 0xb5, 0x58, 0xdf, 0x31, 0x3a, 0xd3, 0x87, 0x07, 0x95, 0xa9, 0x75, 0x59, 0x86, 0x1a, 0x6a, - 0xff, 0xc7, 0x31, 0x28, 0x57, 0x3d, 0xa7, 0xbd, 0x1f, 0xba, 0x21, 0xf6, 0x3c, 0xf2, 0x39, 0x98, - 0x62, 0xab, 0x56, 0xd3, 0x89, 0x1c, 0x39, 0xd3, 0x3f, 0xb6, 0x28, 0x16, 0x91, 0x45, 0x73, 0x11, - 0x89, 0x3f, 0x9f, 0x61, 0x2f, 0xee, 0x7d, 0x7c, 0xf1, 0xf6, 0xd6, 0x3d, 0xda, 0x88, 0xd6, 0x69, - 0xe4, 0xd4, 0x88, 0xec, 0x05, 0x88, 0xcb, 0x50, 0x53, 0x25, 0x3e, 0x8c, 0x87, 0x5d, 0xda, 0x90, - 0x33, 0x77, 0x7d, 0xc4, 0x19, 0x12, 0x8b, 0x5e, 0xef, 0xd2, 0x46, 0x6d, 0x5a, 0xb2, 0x1e, 0x67, - 0xff, 0x90, 0x33, 0x22, 0xf7, 0x61, 0x22, 0xe4, 0x6b, 0x99, 0x9c, 0x94, 0xb7, 0xf3, 0x63, 0xc9, - 0xc9, 0xd6, 0x66, 0x24, 0xd3, 0x09, 0xf1, 0x1f, 0x25, 0x3b, 0xfb, 0x3f, 0x59, 0x70, 0xce, 0xc0, - 0xae, 0x06, 0xad, 0x5e, 0x87, 0x7a, 0x11, 0xb9, 0x0c, 0xe3, 0x9e, 0xd3, 0xa1, 0x72, 0x56, 0x69, - 0x91, 0x6f, 0x39, 0x1d, 0x8a, 0x1c, 0x42, 0x9e, 0x85, 0xe2, 0x9e, 0xd3, 0xee, 0x51, 0xde, 0x48, - 0xa5, 0xda, 0x19, 0x89, 0x52, 0x7c, 0x8b, 0x15, 0xa2, 0x80, 0x91, 0x77, 0xa1, 0xc4, 0x7f, 0x5c, - 0x0f, 0xfc, 0x4e, 0x4e, 0x9f, 0x26, 0x25, 0x7c, 0x4b, 0x91, 0x15, 0xc3, 0x4f, 0xff, 0xc5, 0x98, - 0xa1, 0xfd, 0x47, 0x16, 0xcc, 0x1a, 0x1f, 0xb7, 0xe6, 0x86, 0x11, 0xf9, 0x6c, 0xdf, 0xe0, 0x59, - 0x1c, 0x6e, 0xf0, 0xb0, 0xda, 0x7c, 0xe8, 0xcc, 0xc9, 0x2f, 0x9d, 0x52, 0x25, 0xc6, 0xc0, 0xf1, - 0xa0, 0xe8, 0x46, 0xb4, 0x13, 0xce, 0x8f, 0x5d, 0x2e, 0x5c, 0x29, 0x5f, 0x5d, 0xcd, 0xad, 0x1b, - 0xe3, 0xf6, 0x5d, 0x65, 0xf4, 0x51, 0xb0, 0xb1, 0x7f, 0xa3, 0x90, 0xe8, 0xbe, 0x75, 0x25, 0xc7, - 0xfb, 0x16, 0x4c, 0xb4, 0x9d, 0x2d, 0xda, 0x16, 0x73, 0xab, 0x7c, 0xf5, 0xed, 0xdc, 0x24, 0x51, - 0x3c, 0x16, 0xd7, 0x38, 0xfd, 0x6b, 0x5e, 0x14, 0xec, 0xc7, 0xc3, 0x4b, 0x14, 0xa2, 0x64, 0x4e, - 0xfe, 0x8e, 0x05, 0xe5, 0x78, 0x55, 0x53, 0xcd, 0xb2, 0x95, 0xbf, 0x30, 0xf1, 0x62, 0x2a, 0x25, - 0xd2, 0x4b, 0xb4, 0x01, 0x41, 0x53, 0x96, 0x85, 0x4f, 0x40, 0xd9, 0xf8, 0x04, 0x32, 0x07, 0x85, - 0x5d, 0xba, 0x2f, 0x06, 0x3c, 0xb2, 0x9f, 0xe4, 0x7c, 0x62, 0x84, 0xcb, 0x21, 0xfd, 0xc9, 0xb1, - 0x57, 0xac, 0x85, 0xd7, 0x60, 0x2e, 0xcd, 0xf0, 0x38, 0xf5, 0xed, 0x7f, 0x52, 0x4c, 0x0c, 0x4c, - 0xb6, 0x10, 0x10, 0x1f, 0x26, 0x3b, 0x34, 0x0a, 0xdc, 0x86, 0xea, 0xb2, 0x95, 0xd1, 0x5a, 0x69, - 0x9d, 0x13, 0x8b, 0x37, 0x44, 0xf1, 0x3f, 0x44, 0xc5, 0x85, 0xec, 0xc0, 0xb8, 0x13, 0xb4, 0x54, - 0x9f, 0x5c, 0xcf, 0x67, 0x5a, 0xc6, 0x4b, 0x45, 0x35, 0x68, 0x85, 0xc8, 0x39, 0x90, 0x25, 0x28, - 0x45, 0x34, 0xe8, 0xb8, 0x9e, 0x13, 0x89, 0x1d, 0x74, 0xaa, 0x76, 0x56, 0xa2, 0x95, 0x36, 0x15, - 0x00, 0x63, 0x1c, 0xd2, 0x86, 0x89, 0x66, 0xb0, 0x8f, 0x3d, 0x6f, 0x7e, 0x3c, 0x8f, 0xa6, 0x58, - 0xe1, 0xb4, 0xe2, 0x41, 0x2a, 0xfe, 0xa3, 0xe4, 0x41, 0x7e, 0xd9, 0x82, 0xf3, 0x1d, 0xea, 0x84, - 0xbd, 0x80, 0xb2, 0x4f, 0x40, 0x1a, 0x51, 0x8f, 0x75, 0xec, 0x7c, 0x91, 0x33, 0xc7, 0x51, 0xfb, - 0xa1, 0x9f, 0x72, 0xed, 0x19, 0x29, 0xca, 0xf9, 0x2c, 0x28, 0x66, 0x4a, 0x43, 0xde, 0x85, 0x72, - 0x14, 0xb5, 0xeb, 0x11, 0xd3, 0x83, 0x5b, 0xfb, 0xf3, 0x13, 0x7c, 0xf1, 0x1a, 0x71, 0x85, 0xd9, - 0xdc, 0x5c, 0x53, 0x04, 0x6b, 0xb3, 0x6c, 0xb6, 0x18, 0x05, 0x68, 0xb2, 0xb3, 0xff, 0x79, 0x11, - 0xce, 0xf6, 0x6d, 0x2b, 0xe4, 0x25, 0x28, 0x76, 0x77, 0x9c, 0x50, 0xed, 0x13, 0x97, 0xd4, 0x22, - 0xb5, 0xc1, 0x0a, 0x1f, 0x1e, 0x54, 0xce, 0xa8, 0x2a, 0xbc, 0x00, 0x05, 0x32, 0xd3, 0xda, 0x3a, - 0x34, 0x0c, 0x9d, 0x96, 0xda, 0x3c, 0x8c, 0x41, 0xca, 0x8b, 0x51, 0xc1, 0xc9, 0x5f, 0xb7, 0xe0, - 0x8c, 0x18, 0xb0, 0x48, 0xc3, 0x5e, 0x3b, 0x62, 0x1b, 0x24, 0xeb, 0x94, 0x9b, 0x79, 0x4c, 0x0e, - 0x41, 0xb2, 0x76, 0x41, 0x72, 0x3f, 0x63, 0x96, 0x86, 0x98, 0xe4, 0x4b, 0xee, 0x42, 0x29, 0x8c, - 0x9c, 0x20, 0xa2, 0xcd, 0x6a, 0xc4, 0x55, 0xb9, 0xf2, 0xd5, 0x9f, 0x1c, 0x6e, 0xe7, 0xd8, 0x74, - 0x3b, 0x54, 0xec, 0x52, 0x75, 0x45, 0x00, 0x63, 0x5a, 0xe4, 0x5d, 0x80, 0xa0, 0xe7, 0xd5, 0x7b, - 0x9d, 0x8e, 0x13, 0xec, 0x4b, 0xed, 0xee, 0xc6, 0x68, 0x9f, 0x87, 0x9a, 0x5e, 0xac, 0xe8, 0xc4, - 0x65, 0x68, 0xf0, 0x23, 0x5f, 0xb2, 0xe0, 0x8c, 0x98, 0x07, 0x4a, 0x82, 0x89, 0x9c, 0x25, 0x38, - 0xcb, 0x9a, 0x76, 0xc5, 0x64, 0x81, 0x49, 0x8e, 0xe4, 0x6d, 0x28, 0x37, 0xfc, 0x4e, 0xb7, 0x4d, - 0x45, 0xe3, 0x4e, 0x1e, 0xbb, 0x71, 0xf9, 0xd0, 0x5d, 0x8e, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0xf7, - 0x49, 0x1d, 0x47, 0x0d, 0x69, 0xf2, 0x19, 0x78, 0x2a, 0xec, 0x35, 0x1a, 0x34, 0x0c, 0xb7, 0x7b, - 0x6d, 0xec, 0x79, 0x37, 0xdc, 0x30, 0xf2, 0x83, 0xfd, 0x35, 0xb7, 0xe3, 0x46, 0x7c, 0x40, 0x17, - 0x6b, 0x17, 0x0f, 0x0f, 0x2a, 0x4f, 0xd5, 0x07, 0x21, 0xe1, 0xe0, 0xfa, 0xc4, 0x81, 0xa7, 0x7b, - 0xde, 0x60, 0xf2, 0xe2, 0xf8, 0x51, 0x39, 0x3c, 0xa8, 0x3c, 0x7d, 0x67, 0x30, 0x1a, 0x1e, 0x45, - 0xc3, 0xfe, 0x13, 0x8b, 0x6d, 0x43, 0xe2, 0xbb, 0x36, 0x69, 0xa7, 0xdb, 0x66, 0x4b, 0xe7, 0xe9, - 0x2b, 0xc7, 0x51, 0x42, 0x39, 0xc6, 0x7c, 0xf6, 0x72, 0x25, 0xff, 0x20, 0x0d, 0xd9, 0xfe, 0xaf, - 0x16, 0x9c, 0x4f, 0x23, 0x3f, 0x06, 0x85, 0x2e, 0x4c, 0x2a, 0x74, 0xb7, 0xf2, 0xfd, 0xda, 0x01, - 0x5a, 0xdd, 0x57, 0xc7, 0xfb, 0xbf, 0xf5, 0xff, 0x75, 0x1d, 0x21, 0xde, 0xf2, 0x0b, 0x3f, 0xce, - 0x2d, 0x7f, 0xfc, 0x83, 0xb4, 0xe5, 0xdb, 0xff, 0x70, 0x1c, 0xa6, 0xab, 0x5e, 0xe4, 0x56, 0xb7, - 0xb7, 0x5d, 0xcf, 0x8d, 0xf6, 0xc9, 0x37, 0xc6, 0x60, 0xa9, 0x1b, 0xd0, 0x6d, 0x1a, 0x04, 0xb4, - 0xb9, 0xd2, 0x0b, 0x5c, 0xaf, 0x55, 0x6f, 0xec, 0xd0, 0x66, 0xaf, 0xed, 0x7a, 0xad, 0xd5, 0x96, - 0xe7, 0xeb, 0xe2, 0x6b, 0x0f, 0x68, 0xa3, 0xc7, 0x3f, 0x49, 0x4c, 0x8a, 0xce, 0x68, 0x9f, 0xb4, - 0x71, 0x3c, 0xa6, 0xb5, 0x17, 0x0f, 0x0f, 0x2a, 0x4b, 0xc7, 0xac, 0x84, 0xc7, 0xfd, 0x34, 0xf2, - 0xb5, 0x31, 0x58, 0x0c, 0xe8, 0xe7, 0x7b, 0xee, 0xf0, 0xad, 0x21, 0x56, 0xad, 0xf6, 0x88, 0xbb, - 0xdb, 0xb1, 0x78, 0xd6, 0xae, 0x1e, 0x1e, 0x54, 0x8e, 0x59, 0x07, 0x8f, 0xf9, 0x5d, 0xf6, 0x06, - 0x94, 0xab, 0x5d, 0x37, 0x74, 0x1f, 0xa0, 0xdf, 0x8b, 0xe8, 0x10, 0xe7, 0xf7, 0x0a, 0x14, 0x83, - 0x5e, 0x9b, 0x8a, 0xb9, 0x5d, 0xaa, 0x95, 0xd8, 0x2a, 0x84, 0xac, 0x00, 0x45, 0xb9, 0xfd, 0x65, - 0xb6, 0xe2, 0x72, 0x92, 0x29, 0xcb, 0xcd, 0x3d, 0x28, 0x06, 0x8c, 0x89, 0x1c, 0x59, 0xa3, 0x1e, - 0x72, 0x63, 0xa9, 0xa5, 0x10, 0xec, 0x27, 0x0a, 0x16, 0xf6, 0x6f, 0x8f, 0xc1, 0x85, 0x6a, 0xb7, - 0xbb, 0x4e, 0xc3, 0x9d, 0x94, 0x14, 0x3f, 0x6f, 0xc1, 0xcc, 0x9e, 0x1b, 0x44, 0x3d, 0xa7, 0xad, - 0x8c, 0x73, 0x42, 0x9e, 0xfa, 0xa8, 0xf2, 0x70, 0x6e, 0x6f, 0x25, 0x48, 0xd7, 0xc8, 0xe1, 0x41, - 0x65, 0x26, 0x59, 0x86, 0x29, 0xf6, 0xe4, 0x6f, 0x5b, 0x30, 0x27, 0x8b, 0x6e, 0xf9, 0x4d, 0x6a, - 0x1a, 0x7f, 0xef, 0xe4, 0x29, 0x93, 0x26, 0x2e, 0x8c, 0x76, 0xe9, 0x52, 0xec, 0x13, 0xc2, 0xfe, - 0xef, 0x63, 0xf0, 0xe4, 0x00, 0x1a, 0xe4, 0x57, 0x2c, 0x38, 0x2f, 0x2c, 0xc6, 0x06, 0x08, 0xe9, - 0xb6, 0x6c, 0xcd, 0x9f, 0xce, 0x5b, 0x72, 0x64, 0x53, 0x9c, 0x7a, 0x0d, 0x5a, 0x9b, 0x67, 0xab, - 0xe1, 0x72, 0x06, 0x6b, 0xcc, 0x14, 0x88, 0x4b, 0x2a, 0x6c, 0xc8, 0x29, 0x49, 0xc7, 0x1e, 0x8b, - 0xa4, 0xf5, 0x0c, 0xd6, 0x98, 0x29, 0x90, 0xfd, 0x57, 0xe1, 0xe9, 0x23, 0xc8, 0x3d, 0x7a, 0x72, - 0xda, 0x6f, 0xeb, 0x51, 0x9f, 0x1c, 0x73, 0x43, 0xcc, 0x6b, 0x1b, 0x26, 0xf8, 0xd4, 0x51, 0x13, - 0x1b, 0xd8, 0xf6, 0xc7, 0xe7, 0x54, 0x88, 0x12, 0x62, 0xff, 0xb6, 0x05, 0x53, 0xc7, 0x30, 0xf5, - 0x55, 0x92, 0xa6, 0xbe, 0x52, 0x9f, 0x99, 0x2f, 0xea, 0x37, 0xf3, 0xbd, 0x3e, 0x5a, 0x6f, 0x0c, - 0x63, 0xde, 0xfb, 0xa1, 0x05, 0x67, 0xfb, 0xcc, 0x81, 0x64, 0x07, 0xce, 0x77, 0xfd, 0xa6, 0x52, - 0x9b, 0x6e, 0x38, 0xe1, 0x0e, 0x87, 0xc9, 0xcf, 0x7b, 0x89, 0xf5, 0xe4, 0x46, 0x06, 0xfc, 0xe1, - 0x41, 0x65, 0x5e, 0x13, 0x49, 0x21, 0x60, 0x26, 0x45, 0xd2, 0x85, 0xa9, 0x6d, 0x97, 0xb6, 0x9b, - 0xf1, 0x10, 0x1c, 0x51, 0x41, 0xba, 0x2e, 0xa9, 0x09, 0x4b, 0xb8, 0xfa, 0x87, 0x9a, 0x8b, 0xfd, - 0x23, 0x0b, 0x66, 0xaa, 0xbd, 0x68, 0x87, 0xa9, 0x07, 0x0d, 0x6e, 0x7c, 0x22, 0x1e, 0x14, 0x43, - 0xb7, 0xb5, 0xf7, 0x52, 0x3e, 0x8b, 0x71, 0x9d, 0x91, 0x92, 0x37, 0x02, 0x5a, 0x37, 0xe5, 0x85, - 0x28, 0xd8, 0x90, 0x00, 0x26, 0x7c, 0xa7, 0x17, 0xed, 0x5c, 0x95, 0x9f, 0x3c, 0xe2, 0x41, 0xfc, - 0x36, 0xfb, 0x9c, 0xab, 0x92, 0xa3, 0xd6, 0xd6, 0x44, 0x29, 0x4a, 0x4e, 0xf6, 0x17, 0x61, 0x26, - 0x79, 0xcd, 0x34, 0xc4, 0x98, 0xbd, 0x08, 0x05, 0x27, 0xf0, 0xe4, 0x88, 0x2d, 0x4b, 0x84, 0x42, - 0x15, 0x6f, 0x21, 0x2b, 0x27, 0x2f, 0xc0, 0xd4, 0x76, 0xaf, 0xdd, 0x66, 0x15, 0xe4, 0x9d, 0x8e, - 0x3e, 0x05, 0x5c, 0x97, 0xe5, 0xa8, 0x31, 0xec, 0xff, 0x3d, 0x0e, 0xb3, 0xb5, 0x76, 0x8f, 0xbe, - 0x1e, 0x50, 0xaa, 0x4c, 0x1f, 0x55, 0x98, 0xed, 0x06, 0x74, 0xcf, 0xa5, 0xf7, 0xeb, 0xb4, 0x4d, - 0x1b, 0x91, 0x1f, 0x48, 0x69, 0x9e, 0x94, 0x84, 0x66, 0x37, 0x92, 0x60, 0x4c, 0xe3, 0x93, 0xd7, - 0x60, 0xc6, 0x69, 0x44, 0xee, 0x1e, 0xd5, 0x14, 0x84, 0xb8, 0x4f, 0x48, 0x0a, 0x33, 0xd5, 0x04, - 0x14, 0x53, 0xd8, 0xe4, 0xb3, 0x30, 0x1f, 0x36, 0x9c, 0x36, 0xbd, 0xd3, 0x95, 0xac, 0x96, 0x77, - 0x68, 0x63, 0x77, 0xc3, 0x77, 0xbd, 0x48, 0x9a, 0xd9, 0x2e, 0x4b, 0x4a, 0xf3, 0xf5, 0x01, 0x78, - 0x38, 0x90, 0x02, 0xf9, 0x17, 0x16, 0x5c, 0xec, 0x06, 0x74, 0x23, 0xf0, 0x3b, 0x3e, 0x1b, 0x6a, - 0x7d, 0xd6, 0x1f, 0x69, 0x05, 0x79, 0x6b, 0x44, 0x5d, 0x4a, 0x94, 0xf4, 0x5f, 0x59, 0x7c, 0xf8, - 0xf0, 0xa0, 0x72, 0x71, 0xe3, 0x28, 0x01, 0xf0, 0x68, 0xf9, 0xc8, 0xbf, 0xb4, 0xe0, 0x52, 0xd7, - 0x0f, 0xa3, 0x23, 0x3e, 0xa1, 0x78, 0xaa, 0x9f, 0x60, 0x1f, 0x1e, 0x54, 0x2e, 0x6d, 0x1c, 0x29, - 0x01, 0x3e, 0x42, 0x42, 0xfb, 0xb0, 0x0c, 0x67, 0x8d, 0xb1, 0x27, 0x6d, 0x17, 0xaf, 0xc2, 0x19, - 0x35, 0x18, 0x62, 0xdd, 0xa7, 0x14, 0x9b, 0xb2, 0xaa, 0x26, 0x10, 0x93, 0xb8, 0x6c, 0xdc, 0xe9, - 0xa1, 0x28, 0x6a, 0xa7, 0xc6, 0xdd, 0x46, 0x02, 0x8a, 0x29, 0x6c, 0xb2, 0x0a, 0xe7, 0x64, 0x09, - 0xd2, 0x6e, 0xdb, 0x6d, 0x38, 0xcb, 0x7e, 0x4f, 0x0e, 0xb9, 0x62, 0xed, 0xc9, 0xc3, 0x83, 0xca, - 0xb9, 0x8d, 0x7e, 0x30, 0x66, 0xd5, 0x21, 0x6b, 0x70, 0xde, 0xe9, 0x45, 0xbe, 0xfe, 0xfe, 0x6b, - 0x1e, 0xdb, 0x4e, 0x9b, 0x7c, 0x68, 0x4d, 0x89, 0x7d, 0xb7, 0x9a, 0x01, 0xc7, 0xcc, 0x5a, 0x64, - 0x23, 0x45, 0xad, 0x4e, 0x1b, 0xbe, 0xd7, 0x14, 0xbd, 0x5c, 0x8c, 0x4f, 0x60, 0xd5, 0x0c, 0x1c, - 0xcc, 0xac, 0x49, 0xda, 0x30, 0xd3, 0x71, 0x1e, 0xdc, 0xf1, 0x9c, 0x3d, 0xc7, 0x6d, 0x33, 0x26, - 0xd2, 0x3c, 0x36, 0xd8, 0xa8, 0xd2, 0x8b, 0xdc, 0xf6, 0xa2, 0x70, 0x5b, 0x58, 0x5c, 0xf5, 0xa2, - 0xdb, 0x41, 0x3d, 0x62, 0x9a, 0xba, 0xd0, 0x20, 0xd7, 0x13, 0xb4, 0x30, 0x45, 0x9b, 0xdc, 0x86, - 0x0b, 0x7c, 0x3a, 0xae, 0xf8, 0xf7, 0xbd, 0x15, 0xda, 0x76, 0xf6, 0xd5, 0x07, 0x4c, 0xf2, 0x0f, - 0x78, 0xea, 0xf0, 0xa0, 0x72, 0xa1, 0x9e, 0x85, 0x80, 0xd9, 0xf5, 0x88, 0x03, 0x4f, 0x27, 0x01, - 0x48, 0xf7, 0xdc, 0xd0, 0xf5, 0x3d, 0x61, 0x85, 0x9a, 0x8a, 0xad, 0x50, 0xf5, 0xc1, 0x68, 0x78, - 0x14, 0x0d, 0xf2, 0x77, 0x2d, 0x38, 0x9f, 0x35, 0x0d, 0xe7, 0x4b, 0x79, 0x5c, 0x9e, 0xa6, 0xa6, - 0x96, 0x18, 0x11, 0x99, 0x8b, 0x42, 0xa6, 0x10, 0xe4, 0x3d, 0x0b, 0xa6, 0x1d, 0xe3, 0x04, 0x3d, - 0x0f, 0x79, 0xec, 0x5a, 0xe6, 0x99, 0xbc, 0x36, 0x77, 0x78, 0x50, 0x49, 0x9c, 0xd2, 0x31, 0xc1, - 0x91, 0xfc, 0x7d, 0x0b, 0x2e, 0x64, 0xce, 0xf1, 0xf9, 0xf2, 0x69, 0xb4, 0x10, 0x1f, 0x24, 0xd9, - 0x6b, 0x4e, 0xb6, 0x18, 0xe4, 0x5b, 0x96, 0xde, 0xca, 0xd4, 0x7d, 0xda, 0xfc, 0x34, 0x17, 0xed, - 0xcd, 0x11, 0x8d, 0x06, 0xb1, 0xd6, 0xa4, 0x08, 0xd7, 0xce, 0x19, 0x3b, 0xa3, 0x2a, 0xc4, 0x34, - 0x7b, 0xf2, 0x4d, 0x4b, 0x6d, 0x8d, 0x5a, 0xa2, 0x33, 0xa7, 0x25, 0x11, 0x89, 0x77, 0x5a, 0x2d, - 0x50, 0x8a, 0x39, 0xf9, 0x19, 0x58, 0x70, 0xb6, 0xfc, 0x20, 0xca, 0x9c, 0x7c, 0xf3, 0x33, 0x7c, - 0x1a, 0x5d, 0x3a, 0x3c, 0xa8, 0x2c, 0x54, 0x07, 0x62, 0xe1, 0x11, 0x14, 0xec, 0x5f, 0x2b, 0xc2, - 0xb4, 0x38, 0x09, 0xc9, 0xad, 0xeb, 0x37, 0x2d, 0x78, 0xa6, 0xd1, 0x0b, 0x02, 0xea, 0x45, 0xf5, - 0x88, 0x76, 0xfb, 0x37, 0x2e, 0xeb, 0x54, 0x37, 0xae, 0xcb, 0x87, 0x07, 0x95, 0x67, 0x96, 0x8f, - 0xe0, 0x8f, 0x47, 0x4a, 0x47, 0xfe, 0x9d, 0x05, 0xb6, 0x44, 0xa8, 0x39, 0x8d, 0xdd, 0x56, 0xe0, - 0xf7, 0xbc, 0x66, 0xff, 0x47, 0x8c, 0x9d, 0xea, 0x47, 0x3c, 0x77, 0x78, 0x50, 0xb1, 0x97, 0x1f, - 0x29, 0x05, 0x0e, 0x21, 0x29, 0x79, 0x1d, 0xce, 0x4a, 0xac, 0x6b, 0x0f, 0xba, 0x34, 0x70, 0xd9, - 0x99, 0x43, 0x2a, 0x8e, 0xb1, 0x2b, 0x56, 0x1a, 0x01, 0xfb, 0xeb, 0x90, 0x10, 0x26, 0xef, 0x53, - 0xb7, 0xb5, 0x13, 0x29, 0xf5, 0x69, 0x44, 0xff, 0x2b, 0x69, 0x15, 0xb9, 0x2b, 0x68, 0xd6, 0xca, - 0x87, 0x07, 0x95, 0x49, 0xf9, 0x07, 0x15, 0x27, 0x72, 0x0b, 0x66, 0xc4, 0x39, 0x75, 0xc3, 0xf5, - 0x5a, 0x1b, 0xbe, 0x27, 0x9c, 0x88, 0x4a, 0xb5, 0xe7, 0xd4, 0x86, 0x5f, 0x4f, 0x40, 0x1f, 0x1e, - 0x54, 0xa6, 0xd5, 0xef, 0xcd, 0xfd, 0x2e, 0xc5, 0x54, 0x6d, 0xfb, 0x77, 0x27, 0x00, 0xd4, 0x70, - 0xa5, 0x5d, 0xf2, 0x11, 0x28, 0x85, 0x34, 0x12, 0x5c, 0xe5, 0xc5, 0x89, 0xb8, 0xee, 0x52, 0x85, - 0x18, 0xc3, 0xc9, 0x2e, 0x14, 0xbb, 0x4e, 0x2f, 0xa4, 0xf9, 0x9c, 0x1f, 0x64, 0xe7, 0x6f, 0x30, - 0x8a, 0xe2, 0x60, 0xca, 0x7f, 0xa2, 0xe0, 0x41, 0xbe, 0x62, 0x01, 0xd0, 0x64, 0x87, 0x8d, 0x6c, - 0x20, 0x92, 0x2c, 0xe3, 0x3e, 0x65, 0x6d, 0x50, 0x9b, 0x39, 0x3c, 0xa8, 0x80, 0xd1, 0xf5, 0x06, - 0x5b, 0x72, 0x1f, 0xa6, 0x1c, 0xb5, 0xe6, 0x8f, 0x9f, 0xc6, 0x9a, 0xcf, 0xcf, 0x8b, 0x7a, 0xd0, - 0x6a, 0x66, 0xe4, 0x6b, 0x16, 0xcc, 0x84, 0x34, 0x92, 0x5d, 0xc5, 0x56, 0x1e, 0xa9, 0xf0, 0x8e, - 0x38, 0xe8, 0xea, 0x09, 0x9a, 0x62, 0x05, 0x4d, 0x96, 0x61, 0x8a, 0xaf, 0x12, 0xe5, 0x06, 0x75, - 0x9a, 0x34, 0xe0, 0xe6, 0x08, 0xa9, 0x49, 0x8d, 0x2e, 0x8a, 0x41, 0x53, 0x8b, 0x62, 0x94, 0x61, - 0x8a, 0xaf, 0x12, 0x65, 0xdd, 0x0d, 0x02, 0x5f, 0x8a, 0x32, 0x95, 0x93, 0x28, 0x06, 0x4d, 0x2d, - 0x8a, 0x51, 0x86, 0x29, 0xbe, 0xf6, 0x77, 0xce, 0xc0, 0x8c, 0x9a, 0x48, 0xb1, 0x66, 0x2f, 0xac, - 0x5f, 0x03, 0x34, 0xfb, 0x65, 0x13, 0x88, 0x49, 0x5c, 0x56, 0x59, 0x4c, 0xd5, 0xa4, 0x62, 0xaf, - 0x2b, 0xd7, 0x4d, 0x20, 0x26, 0x71, 0x49, 0x07, 0x8a, 0x61, 0x44, 0xbb, 0xea, 0x8a, 0x7d, 0xc4, - 0x1b, 0xe0, 0x78, 0x7d, 0x30, 0x2c, 0x09, 0x8c, 0x3c, 0x0a, 0x2e, 0xdc, 0x80, 0x1b, 0x25, 0x6c, - 0xba, 0x72, 0x72, 0xe4, 0x33, 0x3f, 0x93, 0xe6, 0x62, 0xd1, 0x1b, 0xc9, 0x32, 0x4c, 0xb1, 0xcf, - 0x50, 0xf6, 0x8b, 0xa7, 0xa8, 0xec, 0x7f, 0x1a, 0xa6, 0x3a, 0xce, 0x83, 0x7a, 0x2f, 0x68, 0x9d, - 0xfc, 0x50, 0x21, 0x5d, 0x26, 0x05, 0x15, 0xd4, 0xf4, 0xc8, 0x97, 0x2c, 0x63, 0xc9, 0x11, 0xf7, - 0xe9, 0x77, 0xf3, 0x5d, 0x72, 0xf4, 0x5e, 0x39, 0x70, 0xf1, 0xe9, 0x53, 0xbd, 0xa7, 0x1e, 0xbb, - 0xea, 0xcd, 0xd4, 0x48, 0x31, 0x41, 0xb4, 0x1a, 0x59, 0x3a, 0x55, 0x35, 0x72, 0x39, 0xc1, 0x0c, - 0x53, 0xcc, 0xb9, 0x3c, 0x62, 0xce, 0x69, 0x79, 0xe0, 0x54, 0xe5, 0xa9, 0x27, 0x98, 0x61, 0x8a, - 0xf9, 0xe0, 0xf3, 0x66, 0xf9, 0x74, 0xce, 0x9b, 0xd3, 0x39, 0x9c, 0x37, 0x8f, 0x56, 0xc5, 0xcf, - 0x8c, 0xaa, 0x8a, 0x93, 0x9b, 0x40, 0x9a, 0xfb, 0x9e, 0xd3, 0x71, 0x1b, 0x72, 0xb1, 0xe4, 0xdb, - 0xe6, 0x0c, 0xb7, 0x47, 0x2c, 0xc8, 0x85, 0x8c, 0xac, 0xf4, 0x61, 0x60, 0x46, 0x2d, 0x12, 0xc1, - 0x54, 0x57, 0x69, 0x5c, 0xb3, 0x79, 0x8c, 0x7e, 0xa5, 0x81, 0x09, 0x37, 0x09, 0x36, 0xf1, 0x54, - 0x09, 0x6a, 0x4e, 0x64, 0x0d, 0xce, 0x77, 0x5c, 0x6f, 0xc3, 0x6f, 0x86, 0x1b, 0x34, 0x90, 0xd6, - 0x96, 0x3a, 0x8d, 0xe6, 0xe7, 0x78, 0xdb, 0xf0, 0x13, 0xf4, 0x7a, 0x06, 0x1c, 0x33, 0x6b, 0xd9, - 0xff, 0xcb, 0x82, 0xb9, 0xe5, 0xb6, 0xdf, 0x6b, 0xde, 0x75, 0xa2, 0xc6, 0x8e, 0xf0, 0x10, 0x20, - 0xaf, 0xc1, 0x94, 0xeb, 0x45, 0x34, 0xd8, 0x73, 0xda, 0x72, 0x7f, 0xb2, 0x95, 0xf9, 0x74, 0x55, - 0x96, 0x3f, 0x3c, 0xa8, 0xcc, 0xac, 0xf4, 0x02, 0x6e, 0xa5, 0x16, 0xab, 0x15, 0xea, 0x3a, 0xe4, - 0x3b, 0x16, 0x9c, 0x15, 0x3e, 0x06, 0x2b, 0x4e, 0xe4, 0xbc, 0xd9, 0xa3, 0x81, 0x4b, 0x95, 0x97, - 0xc1, 0x88, 0x0b, 0x55, 0x5a, 0x56, 0xc5, 0x60, 0x3f, 0x56, 0xd4, 0xd7, 0xd3, 0x9c, 0xb1, 0x5f, - 0x18, 0xfb, 0x17, 0x0a, 0xf0, 0xd4, 0x40, 0x5a, 0x64, 0x01, 0xc6, 0xdc, 0xa6, 0xfc, 0x74, 0x90, - 0x74, 0xc7, 0x56, 0x9b, 0x38, 0xe6, 0x36, 0xc9, 0x22, 0xd7, 0x39, 0x03, 0x1a, 0x86, 0xea, 0xc2, - 0xb9, 0xa4, 0xd5, 0x43, 0x59, 0x8a, 0x06, 0x06, 0xa9, 0x40, 0x91, 0xbb, 0xcb, 0xca, 0xf3, 0x04, - 0xd7, 0x62, 0xb9, 0x67, 0x2a, 0x8a, 0x72, 0xf2, 0x65, 0x0b, 0x40, 0x08, 0xc8, 0x4e, 0x23, 0x72, - 0x97, 0xc4, 0x7c, 0x9b, 0x89, 0x51, 0x16, 0x52, 0xc6, 0xff, 0xd1, 0xe0, 0x4a, 0x36, 0x61, 0x82, - 0x29, 0xb4, 0x7e, 0xf3, 0xc4, 0x9b, 0x22, 0xbf, 0x89, 0xda, 0xe0, 0x34, 0x50, 0xd2, 0x62, 0x6d, - 0x15, 0xd0, 0xa8, 0x17, 0x78, 0xac, 0x69, 0xf9, 0x36, 0x38, 0x25, 0xa4, 0x40, 0x5d, 0x8a, 0x06, - 0x86, 0xfd, 0xcf, 0xc6, 0xe0, 0x7c, 0x96, 0xe8, 0x6c, 0xb7, 0x99, 0x10, 0xd2, 0xca, 0xa3, 0xf1, - 0x4f, 0xe5, 0xdf, 0x3e, 0xd2, 0x5d, 0x46, 0x5f, 0x53, 0x48, 0x7f, 0x41, 0xc9, 0x97, 0xfc, 0x94, - 0x6e, 0xa1, 0xb1, 0x13, 0xb6, 0x90, 0xa6, 0x9c, 0x6a, 0xa5, 0xcb, 0x30, 0x1e, 0xb2, 0x9e, 0x2f, - 0x24, 0xaf, 0x3b, 0x78, 0x1f, 0x71, 0x08, 0xc3, 0xe8, 0x79, 0x6e, 0x24, 0x63, 0x4c, 0x34, 0xc6, - 0x1d, 0xcf, 0x8d, 0x90, 0x43, 0xec, 0x6f, 0x8f, 0xc1, 0xc2, 0xe0, 0x8f, 0x22, 0xdf, 0xb6, 0x00, - 0x9a, 0xec, 0xb8, 0x12, 0x72, 0x47, 0x6d, 0xe1, 0x5e, 0xe4, 0x9c, 0x56, 0x1b, 0xae, 0x28, 0x4e, - 0xb1, 0xaf, 0x99, 0x2e, 0x0a, 0xd1, 0x10, 0x84, 0x5c, 0x55, 0x43, 0x9f, 0x5f, 0xd5, 0x88, 0xc9, - 0xa4, 0xeb, 0xac, 0x6b, 0x08, 0x1a, 0x58, 0xec, 0x3c, 0xea, 0x39, 0x1d, 0x1a, 0x76, 0x1d, 0x1d, - 0xb1, 0xc3, 0xcf, 0xa3, 0xb7, 0x54, 0x21, 0xc6, 0x70, 0xbb, 0x0d, 0xcf, 0x0e, 0x21, 0x67, 0x4e, - 0x01, 0x11, 0xf6, 0xff, 0xb0, 0xe0, 0xc9, 0xe5, 0x76, 0x2f, 0x8c, 0x68, 0xf0, 0xff, 0x8d, 0xeb, - 0xde, 0x9f, 0x5a, 0xf0, 0xf4, 0x80, 0x6f, 0x7e, 0x0c, 0x1e, 0x7c, 0xef, 0x24, 0x3d, 0xf8, 0xee, - 0x8c, 0x3a, 0xa4, 0x33, 0xbf, 0x63, 0x80, 0x23, 0xdf, 0xbf, 0x29, 0xc0, 0x19, 0xb6, 0x6c, 0x35, - 0xfd, 0x56, 0x4e, 0x1b, 0xe7, 0xb3, 0x50, 0xfc, 0x3c, 0xdb, 0x80, 0xd2, 0x83, 0x8c, 0xef, 0x4a, - 0x28, 0x60, 0xe4, 0x2b, 0x16, 0x4c, 0x7e, 0x5e, 0xee, 0xa9, 0xe2, 0x2c, 0x37, 0xe2, 0x62, 0x98, - 0xf8, 0x86, 0x45, 0xb9, 0x43, 0x8a, 0x38, 0x0b, 0xed, 0x3b, 0xa8, 0xb6, 0x52, 0xc5, 0x99, 0x3c, - 0x0f, 0x93, 0xdb, 0x7e, 0xd0, 0xe9, 0xb5, 0x9d, 0x74, 0x70, 0xdf, 0x75, 0x51, 0x8c, 0x0a, 0xce, - 0x26, 0xb9, 0xd3, 0x75, 0xdf, 0xa2, 0x41, 0x28, 0xdc, 0xee, 0x13, 0x93, 0xbc, 0xaa, 0x21, 0x68, - 0x60, 0xf1, 0x3a, 0xad, 0x56, 0x40, 0x5b, 0x4e, 0xe4, 0x07, 0x7c, 0xe7, 0x30, 0xeb, 0x68, 0x08, - 0x1a, 0x58, 0x0b, 0x9f, 0x84, 0x69, 0x53, 0xf8, 0x63, 0xc5, 0x6c, 0x7c, 0x0a, 0xa4, 0x13, 0x61, - 0x6a, 0x49, 0xb2, 0x86, 0x59, 0x92, 0xec, 0xff, 0x30, 0x06, 0x86, 0x75, 0xe8, 0x31, 0x4c, 0x75, - 0x2f, 0x31, 0xd5, 0x47, 0xb4, 0x6c, 0x18, 0xb6, 0xae, 0x41, 0x11, 0x6c, 0x7b, 0xa9, 0x08, 0xb6, - 0x5b, 0xb9, 0x71, 0x3c, 0x3a, 0x80, 0xed, 0xfb, 0x16, 0x3c, 0x1d, 0x23, 0xf7, 0x1b, 0x6e, 0x1f, - 0xbd, 0x6e, 0xbf, 0x0c, 0x65, 0x27, 0xae, 0x26, 0x27, 0x96, 0x11, 0x3e, 0xa4, 0x41, 0x68, 0xe2, - 0xc5, 0xa1, 0x0f, 0x85, 0x13, 0x86, 0x3e, 0x8c, 0x1f, 0x1d, 0xfa, 0x60, 0xff, 0x68, 0x0c, 0x2e, - 0xf6, 0x7f, 0x99, 0x5a, 0x71, 0x86, 0xf3, 0x82, 0x78, 0x05, 0xa6, 0x23, 0x59, 0xc1, 0xd8, 0x3f, - 0x75, 0x28, 0xf3, 0xa6, 0x01, 0xc3, 0x04, 0x26, 0xab, 0xd9, 0x10, 0x6b, 0x5d, 0xbd, 0xe1, 0x77, - 0x55, 0xd8, 0x8e, 0xae, 0xb9, 0x6c, 0xc0, 0x30, 0x81, 0xa9, 0x7d, 0x86, 0xc7, 0x4f, 0xdd, 0x67, - 0xb8, 0x0e, 0x17, 0x94, 0x97, 0xe4, 0x75, 0x3f, 0x90, 0xfe, 0xff, 0x6a, 0x05, 0x99, 0xaa, 0x5d, - 0x94, 0x55, 0x2e, 0x60, 0x16, 0x12, 0x66, 0xd7, 0xb5, 0xbf, 0x5f, 0x80, 0x73, 0x71, 0xb3, 0x2f, - 0xfb, 0x5e, 0xd3, 0xe5, 0x8e, 0x36, 0xaf, 0xc2, 0x78, 0xb4, 0xdf, 0x55, 0x8d, 0xfd, 0x17, 0x95, - 0x38, 0x9b, 0xfb, 0x5d, 0xd6, 0xdb, 0x4f, 0x66, 0x54, 0xe1, 0xa6, 0x73, 0x5e, 0x89, 0xac, 0xe9, - 0xd9, 0x21, 0x7a, 0xe0, 0xa5, 0xe4, 0x68, 0x7e, 0x78, 0x50, 0xc9, 0x88, 0xe4, 0x5f, 0xd4, 0x94, - 0x92, 0x63, 0x9e, 0xdc, 0x83, 0x99, 0xb6, 0x13, 0x46, 0x77, 0xba, 0x4d, 0x27, 0xa2, 0x9b, 0xae, - 0x74, 0x61, 0x39, 0x5e, 0xc8, 0x84, 0xbe, 0xeb, 0x5f, 0x4b, 0x50, 0xc2, 0x14, 0x65, 0xb2, 0x07, - 0x84, 0x95, 0x6c, 0x06, 0x8e, 0x17, 0x8a, 0xaf, 0x62, 0xfc, 0x8e, 0x1f, 0xff, 0xa2, 0x8f, 0xce, - 0x6b, 0x7d, 0xd4, 0x30, 0x83, 0x03, 0x79, 0x0e, 0x26, 0x02, 0xea, 0x84, 0x7a, 0x3b, 0xd0, 0xf3, - 0x1f, 0x79, 0x29, 0x4a, 0xa8, 0x39, 0xa1, 0x26, 0x1e, 0x31, 0xa1, 0xfe, 0xd0, 0x82, 0x99, 0xb8, - 0x9b, 0x1e, 0x83, 0xea, 0xd1, 0x49, 0xaa, 0x1e, 0x37, 0xf2, 0x5a, 0x12, 0x07, 0x68, 0x1b, 0x7f, - 0x32, 0x69, 0x7e, 0x1f, 0x0f, 0x18, 0xf8, 0x02, 0x94, 0xd4, 0xac, 0x56, 0x3a, 0xfd, 0x88, 0x16, - 0x88, 0x84, 0xb6, 0x67, 0x44, 0xf1, 0x49, 0x26, 0x18, 0xf3, 0x63, 0xba, 0x4e, 0x53, 0xea, 0x31, - 0x72, 0xd8, 0x6b, 0x5d, 0x47, 0xe9, 0x37, 0x59, 0xba, 0x8e, 0xaa, 0x43, 0xee, 0xc0, 0x93, 0xdd, - 0xc0, 0xe7, 0xb1, 0xe4, 0x2b, 0xd4, 0x69, 0xb6, 0x5d, 0x8f, 0x2a, 0x33, 0x8f, 0x70, 0x35, 0x79, - 0xfa, 0xf0, 0xa0, 0xf2, 0xe4, 0x46, 0x36, 0x0a, 0x0e, 0xaa, 0x9b, 0x8c, 0x46, 0x1c, 0x1f, 0x22, - 0x1a, 0xf1, 0x6f, 0x68, 0x63, 0x2a, 0x0d, 0x65, 0x4c, 0xe0, 0x67, 0xf2, 0xea, 0xca, 0x8c, 0x65, - 0x3d, 0x1e, 0x52, 0x55, 0xc9, 0x14, 0x35, 0xfb, 0xc1, 0x16, 0xbb, 0x89, 0x13, 0x5a, 0xec, 0xe2, - 0xb8, 0x8b, 0xc9, 0x1f, 0x67, 0xdc, 0xc5, 0xd4, 0x07, 0x2a, 0xd4, 0xf2, 0x3b, 0x16, 0x9c, 0x73, - 0xfa, 0xa3, 0x8c, 0xf3, 0x31, 0x1e, 0x67, 0x84, 0x2f, 0xd7, 0x9e, 0x96, 0x42, 0x66, 0x05, 0x73, - 0x63, 0x96, 0x28, 0xf6, 0xfb, 0x45, 0x98, 0x4b, 0x2b, 0x49, 0xa7, 0x1f, 0x8e, 0xf9, 0xb7, 0x2c, - 0x98, 0x53, 0x13, 0x5c, 0xf0, 0xd4, 0x47, 0x8c, 0xb5, 0x9c, 0xd6, 0x15, 0xa1, 0xee, 0xe9, 0x2c, - 0x19, 0x9b, 0x29, 0x6e, 0xd8, 0xc7, 0x9f, 0xbc, 0x0d, 0x65, 0x7d, 0xab, 0x72, 0xa2, 0xd8, 0x4c, - 0x1e, 0x3e, 0x58, 0x8d, 0x49, 0xa0, 0x49, 0x8f, 0xbc, 0x6f, 0x01, 0x34, 0xd4, 0x4e, 0xac, 0x16, - 0x80, 0x37, 0xf3, 0x5a, 0x00, 0xf4, 0x1e, 0x1f, 0xeb, 0xf3, 0xba, 0x28, 0x44, 0x83, 0x31, 0xf9, - 0x05, 0x7e, 0x9f, 0xa2, 0x47, 0x82, 0xc8, 0xbe, 0x31, 0xb2, 0xdb, 0xfb, 0x11, 0xba, 0x73, 0xac, - 0xed, 0x19, 0xa0, 0x10, 0x13, 0x42, 0xd8, 0xaf, 0x82, 0x76, 0x54, 0x66, 0x2b, 0x2b, 0x77, 0x55, - 0xde, 0x70, 0xa2, 0x1d, 0x39, 0x04, 0xf5, 0xca, 0x7a, 0x5d, 0x01, 0x30, 0xc6, 0xb1, 0x3f, 0x07, - 0x33, 0xaf, 0x07, 0x4e, 0x77, 0xc7, 0xe5, 0xf7, 0x16, 0xec, 0x7c, 0xfc, 0x3c, 0x4c, 0x3a, 0xcd, - 0x66, 0x56, 0x42, 0x97, 0xaa, 0x28, 0x46, 0x05, 0x1f, 0xea, 0x28, 0x6c, 0xff, 0xae, 0x05, 0x24, - 0xbe, 0xfb, 0x75, 0xbd, 0xd6, 0xba, 0x13, 0x35, 0x76, 0xd8, 0x11, 0x6e, 0x87, 0x97, 0x66, 0x1d, - 0xe1, 0x6e, 0x68, 0x08, 0x1a, 0x58, 0xe4, 0x5d, 0x28, 0x8b, 0x7f, 0x6f, 0xe9, 0x03, 0xe2, 0xe8, - 0xfe, 0xd6, 0x7c, 0xcf, 0xe3, 0x32, 0x89, 0x51, 0x78, 0x23, 0xe6, 0x80, 0x26, 0x3b, 0xd6, 0x54, - 0xab, 0xde, 0x76, 0xbb, 0xf7, 0xa0, 0xb9, 0x15, 0x37, 0x55, 0x37, 0xf0, 0xb7, 0xdd, 0x36, 0x4d, - 0x37, 0xd5, 0x86, 0x28, 0x46, 0x05, 0x1f, 0xae, 0xa9, 0xfe, 0x95, 0x05, 0xe7, 0x57, 0xc3, 0xc8, - 0xf5, 0x57, 0x68, 0x18, 0xb1, 0x9d, 0x8f, 0xad, 0x8f, 0xbd, 0xf6, 0x30, 0x31, 0x07, 0x2b, 0x30, - 0x27, 0xef, 0xa1, 0x7b, 0x5b, 0x21, 0x8d, 0x8c, 0xa3, 0x86, 0x9e, 0xc7, 0xcb, 0x29, 0x38, 0xf6, - 0xd5, 0x60, 0x54, 0xe4, 0x85, 0x74, 0x4c, 0xa5, 0x90, 0xa4, 0x52, 0x4f, 0xc1, 0xb1, 0xaf, 0x86, - 0xfd, 0xbd, 0x02, 0x9c, 0xe3, 0x9f, 0x91, 0x8a, 0x17, 0xfa, 0xe6, 0xa0, 0x78, 0xa1, 0x11, 0xa7, - 0x32, 0xe7, 0x75, 0x82, 0x68, 0xa1, 0xbf, 0x69, 0xc1, 0x6c, 0x33, 0xd9, 0xd2, 0xf9, 0xd8, 0xe5, - 0xb2, 0xfa, 0x50, 0xb8, 0xdd, 0xa5, 0x0a, 0x31, 0xcd, 0x9f, 0xfc, 0xa2, 0x05, 0xb3, 0x49, 0x31, - 0xd5, 0xea, 0x7e, 0x0a, 0x8d, 0xa4, 0xfd, 0xe4, 0x93, 0xe5, 0x21, 0xa6, 0x45, 0xb0, 0x7f, 0x6f, - 0x4c, 0x76, 0xe9, 0x69, 0x04, 0xc3, 0x90, 0xfb, 0x50, 0x8a, 0xda, 0xa1, 0x28, 0x94, 0x5f, 0x3b, - 0xe2, 0xa1, 0x75, 0x73, 0xad, 0x2e, 0x5c, 0x40, 0x62, 0xbd, 0x52, 0x96, 0x30, 0xfd, 0x58, 0xf1, - 0xe2, 0x8c, 0x1b, 0x5d, 0xc9, 0x38, 0x97, 0xd3, 0xf2, 0xe6, 0xf2, 0x46, 0x9a, 0xb1, 0x2c, 0x61, - 0x8c, 0x15, 0x2f, 0xfb, 0x57, 0x2d, 0x28, 0xdd, 0xf4, 0xd5, 0x3a, 0xf2, 0x33, 0x39, 0xd8, 0xa2, - 0xb4, 0xca, 0xaa, 0x95, 0x96, 0xf8, 0x14, 0xf4, 0x5a, 0xc2, 0x12, 0xf5, 0x8c, 0x41, 0x7b, 0x91, - 0xe7, 0xb5, 0x63, 0xa4, 0x6e, 0xfa, 0x5b, 0x03, 0xcd, 0xc7, 0xbf, 0x54, 0x84, 0x33, 0x6f, 0x38, - 0xfb, 0xd4, 0x8b, 0x9c, 0xe3, 0x6f, 0x12, 0x2f, 0x43, 0xd9, 0xe9, 0xf2, 0xbb, 0x4c, 0xe3, 0x18, - 0x12, 0x1b, 0x77, 0x62, 0x10, 0x9a, 0x78, 0xf1, 0x82, 0x26, 0x22, 0x53, 0xb2, 0x96, 0xa2, 0xe5, - 0x14, 0x1c, 0xfb, 0x6a, 0x90, 0x9b, 0x40, 0x64, 0x20, 0x75, 0xb5, 0xd1, 0xf0, 0x7b, 0x9e, 0x58, - 0xd2, 0x84, 0xdd, 0x47, 0x9f, 0x87, 0xd7, 0xfb, 0x30, 0x30, 0xa3, 0x16, 0xf9, 0x2c, 0xcc, 0x37, - 0x38, 0x65, 0x79, 0x3a, 0x32, 0x29, 0x8a, 0x13, 0xb2, 0x8e, 0xf5, 0x58, 0x1e, 0x80, 0x87, 0x03, - 0x29, 0x30, 0x49, 0xc3, 0xc8, 0x0f, 0x9c, 0x16, 0x35, 0xe9, 0x4e, 0x24, 0x25, 0xad, 0xf7, 0x61, - 0x60, 0x46, 0x2d, 0xf2, 0x45, 0x28, 0x45, 0x3b, 0x01, 0x0d, 0x77, 0xfc, 0x76, 0x53, 0xfa, 0x9e, - 0x8c, 0x68, 0x0c, 0x94, 0xbd, 0xbf, 0xa9, 0xa8, 0x1a, 0xc3, 0x5b, 0x15, 0x61, 0xcc, 0x93, 0x04, - 0x30, 0x11, 0x36, 0xfc, 0x2e, 0x0d, 0xe5, 0xa9, 0xe2, 0x66, 0x2e, 0xdc, 0xb9, 0x71, 0xcb, 0x30, - 0x43, 0x72, 0x0e, 0x28, 0x39, 0xd9, 0xbf, 0x33, 0x06, 0xd3, 0x26, 0xe2, 0x10, 0x6b, 0xd3, 0x57, - 0x2c, 0x98, 0x6e, 0xf8, 0x5e, 0x14, 0xf8, 0x6d, 0x61, 0x62, 0xcb, 0x47, 0xa3, 0x60, 0xa4, 0x56, - 0x68, 0xe4, 0xb8, 0x6d, 0xc3, 0x5a, 0x67, 0xb0, 0xc1, 0x04, 0x53, 0xf2, 0x0d, 0x0b, 0x66, 0x63, - 0x57, 0xc5, 0xd8, 0xd6, 0x97, 0xab, 0x20, 0x7a, 0xa9, 0xbf, 0x96, 0xe4, 0x84, 0x69, 0xd6, 0xf6, - 0x16, 0xcc, 0xa5, 0x7b, 0x9b, 0x35, 0x65, 0xd7, 0x91, 0x73, 0xbd, 0x10, 0x37, 0xe5, 0x86, 0x13, - 0x86, 0xc8, 0x21, 0xe4, 0x05, 0x98, 0xea, 0x38, 0x41, 0xcb, 0xf5, 0x9c, 0x36, 0x6f, 0xc5, 0x82, - 0xb1, 0x20, 0xc9, 0x72, 0xd4, 0x18, 0xf6, 0xc7, 0x60, 0x7a, 0xdd, 0xf1, 0x5a, 0xb4, 0x29, 0xd7, - 0xe1, 0x47, 0x87, 0x63, 0xfe, 0xf1, 0x38, 0x94, 0x8d, 0xe3, 0xe3, 0xe9, 0x9f, 0xb3, 0x12, 0xc9, - 0x66, 0x0a, 0x39, 0x26, 0x9b, 0xf9, 0x34, 0xc0, 0xb6, 0xeb, 0xb9, 0xe1, 0xce, 0x09, 0xd3, 0xd8, - 0xf0, 0xbb, 0xf9, 0xeb, 0x9a, 0x02, 0x1a, 0xd4, 0xe2, 0x0b, 0xd0, 0xe2, 0x11, 0x19, 0xe1, 0xde, - 0xb7, 0x8c, 0xed, 0x66, 0x22, 0x0f, 0x87, 0x0f, 0xa3, 0x63, 0x16, 0xd5, 0xf6, 0x23, 0xee, 0xa6, - 0x8e, 0xda, 0x95, 0x36, 0x61, 0x2a, 0xa0, 0x61, 0xaf, 0x43, 0x4f, 0x94, 0x70, 0x86, 0xbb, 0xde, - 0xa0, 0xac, 0x8f, 0x9a, 0xd2, 0xc2, 0xab, 0x70, 0x26, 0x21, 0xc2, 0xb1, 0x6e, 0x98, 0x7c, 0xc8, - 0xb4, 0x51, 0x9c, 0xe4, 0xbe, 0x89, 0xf5, 0x45, 0xdb, 0x48, 0x34, 0xa3, 0xfb, 0x42, 0x38, 0x58, - 0x09, 0x98, 0xfd, 0xa3, 0x09, 0x90, 0x3e, 0x0c, 0x43, 0x2c, 0x57, 0xe6, 0xcd, 0xe5, 0xd8, 0x09, - 0x6e, 0x2e, 0x6f, 0xc2, 0xb4, 0xeb, 0xb9, 0x91, 0xeb, 0xb4, 0xb9, 0xfd, 0x49, 0x6e, 0xa7, 0xca, - 0x03, 0x7d, 0x7a, 0xd5, 0x80, 0x65, 0xd0, 0x49, 0xd4, 0x25, 0x6f, 0x42, 0x91, 0xef, 0x37, 0x72, - 0x00, 0x1f, 0xdf, 0xd1, 0x82, 0xfb, 0xd8, 0x88, 0xb0, 0x34, 0x41, 0x89, 0x1f, 0x3e, 0x44, 0xa6, - 0x1d, 0x7d, 0xfc, 0x96, 0xe3, 0x38, 0x3e, 0x7c, 0xa4, 0xe0, 0xd8, 0x57, 0x83, 0x51, 0xd9, 0x76, - 0xdc, 0x76, 0x2f, 0xa0, 0x31, 0x95, 0x89, 0x24, 0x95, 0xeb, 0x29, 0x38, 0xf6, 0xd5, 0x20, 0xdb, - 0x30, 0x2d, 0xcb, 0x84, 0xdb, 0xdc, 0xe4, 0x09, 0xbf, 0x92, 0xbb, 0x47, 0x5e, 0x37, 0x28, 0x61, - 0x82, 0x2e, 0xe9, 0xc1, 0x59, 0xd7, 0x6b, 0xf8, 0x5e, 0xa3, 0xdd, 0x0b, 0xdd, 0x3d, 0x1a, 0xc7, - 0x84, 0x9d, 0x84, 0xd9, 0x85, 0xc3, 0x83, 0xca, 0xd9, 0xd5, 0x34, 0x39, 0xec, 0xe7, 0x40, 0xbe, - 0x64, 0xc1, 0x85, 0x86, 0xef, 0x85, 0x3c, 0x75, 0xc5, 0x1e, 0xbd, 0x16, 0x04, 0x7e, 0x20, 0x78, - 0x97, 0x4e, 0xc8, 0x9b, 0x9b, 0x3d, 0x97, 0xb3, 0x48, 0x62, 0x36, 0x27, 0xf2, 0x0e, 0x4c, 0x75, - 0x03, 0x7f, 0xcf, 0x6d, 0xd2, 0x40, 0xba, 0x60, 0xae, 0xe5, 0x91, 0x4a, 0x67, 0x43, 0xd2, 0x8c, - 0x97, 0x1e, 0x55, 0x82, 0x9a, 0x9f, 0xfd, 0x7f, 0xca, 0x30, 0x93, 0x44, 0x27, 0x3f, 0x07, 0xd0, - 0x0d, 0xfc, 0x0e, 0x8d, 0x76, 0xa8, 0x8e, 0xed, 0xb9, 0x35, 0x6a, 0xc6, 0x16, 0x45, 0x4f, 0xb9, - 0x2d, 0xb1, 0xe5, 0x22, 0x2e, 0x45, 0x83, 0x23, 0x09, 0x60, 0x72, 0x57, 0x6c, 0xbb, 0x52, 0x0b, - 0x79, 0x23, 0x17, 0x9d, 0x49, 0x72, 0xe6, 0x41, 0x29, 0xb2, 0x08, 0x15, 0x23, 0xb2, 0x05, 0x85, - 0xfb, 0x74, 0x2b, 0x9f, 0x74, 0x01, 0x77, 0xa9, 0x3c, 0xcd, 0xd4, 0x26, 0x0f, 0x0f, 0x2a, 0x85, - 0xbb, 0x74, 0x0b, 0x19, 0x71, 0xf6, 0x5d, 0x4d, 0xe1, 0xbb, 0x20, 0x97, 0x8a, 0x37, 0x72, 0x74, - 0x84, 0x10, 0xdf, 0x25, 0x8b, 0x50, 0x31, 0x22, 0xef, 0x40, 0xe9, 0xbe, 0xb3, 0x47, 0xb7, 0x03, - 0xdf, 0x8b, 0xa4, 0xaf, 0xdc, 0x88, 0xe1, 0x1e, 0x77, 0x15, 0x39, 0xc9, 0x97, 0x6f, 0xef, 0xba, - 0x10, 0x63, 0x76, 0x64, 0x0f, 0xa6, 0x3c, 0x7a, 0x1f, 0x69, 0xdb, 0x6d, 0xe4, 0x13, 0x5e, 0x71, - 0x4b, 0x52, 0x93, 0x9c, 0xf9, 0xbe, 0xa7, 0xca, 0x50, 0xf3, 0x62, 0x7d, 0x79, 0xcf, 0xdf, 0x92, - 0x0b, 0xd5, 0x88, 0x7d, 0xa9, 0x4f, 0xa6, 0xa2, 0x2f, 0x6f, 0xfa, 0x5b, 0xc8, 0x88, 0xb3, 0x39, - 0xd2, 0xd0, 0x8e, 0x5a, 0x72, 0x99, 0xba, 0x95, 0xaf, 0x83, 0x9a, 0x98, 0x23, 0x71, 0x29, 0x1a, - 0x1c, 0x59, 0xdb, 0xb6, 0xa4, 0xb1, 0x52, 0x2e, 0x54, 0x23, 0xb6, 0x6d, 0xd2, 0xf4, 0x29, 0xda, - 0x56, 0x95, 0xa1, 0xe6, 0xc5, 0xf8, 0xba, 0xd2, 0xf2, 0x97, 0xcf, 0x52, 0x95, 0xb4, 0x23, 0x0a, - 0xbe, 0xaa, 0x0c, 0x35, 0x2f, 0xd6, 0xde, 0xe1, 0xee, 0xfe, 0x7d, 0xa7, 0xbd, 0xeb, 0x7a, 0x2d, - 0x19, 0xab, 0x3a, 0x6a, 0xd6, 0xe9, 0xdd, 0xfd, 0xbb, 0x82, 0x9e, 0xd9, 0xde, 0x71, 0x29, 0x1a, - 0x1c, 0xc9, 0xdf, 0xb3, 0x60, 0xa2, 0xdb, 0xee, 0xb5, 0x5c, 0x6f, 0x7e, 0x3a, 0x0f, 0x27, 0xa6, - 0xe4, 0x92, 0xbb, 0xb8, 0xc1, 0x49, 0x0b, 0x45, 0xf1, 0x27, 0xb5, 0xdf, 0x25, 0x2f, 0xfc, 0xfa, - 0x1f, 0x55, 0xe6, 0xa9, 0xd7, 0xf0, 0x9b, 0xae, 0xd7, 0x5a, 0xba, 0x17, 0xfa, 0xde, 0x22, 0x3a, - 0xf7, 0x95, 0x8e, 0x2e, 0x65, 0x5a, 0xf8, 0x04, 0x94, 0x0d, 0x12, 0x8f, 0x52, 0xf4, 0xa6, 0x4d, - 0x45, 0xef, 0x57, 0x27, 0x60, 0xda, 0xcc, 0x35, 0x39, 0x84, 0xf6, 0xa5, 0x4f, 0x1c, 0x63, 0xc7, - 0x39, 0x71, 0xb0, 0x23, 0xa6, 0x71, 0xc1, 0xa5, 0xcc, 0x5b, 0xab, 0xb9, 0x29, 0xdc, 0xf1, 0x11, - 0xd3, 0x28, 0x0c, 0x31, 0xc1, 0xf4, 0x18, 0x3e, 0x2f, 0x4c, 0x6d, 0x15, 0x8a, 0x5d, 0x31, 0xa9, - 0xb6, 0x26, 0x54, 0xb5, 0xab, 0x00, 0x71, 0x52, 0x44, 0x79, 0xf1, 0xa9, 0xf5, 0x61, 0x23, 0x59, - 0xa3, 0x81, 0x45, 0x9e, 0x83, 0x09, 0xa6, 0xfa, 0xd0, 0xa6, 0x0c, 0xa5, 0xd7, 0xe7, 0xf8, 0xeb, - 0xbc, 0x14, 0x25, 0x94, 0xbc, 0xc2, 0xb4, 0xd4, 0x58, 0x61, 0x91, 0x11, 0xf2, 0xe7, 0x63, 0x2d, - 0x35, 0x86, 0x61, 0x02, 0x93, 0x89, 0x4e, 0x99, 0x7e, 0xc1, 0xd7, 0x06, 0x43, 0x74, 0xae, 0x74, - 0xa0, 0x80, 0x71, 0xbb, 0x52, 0x4a, 0x1f, 0xe1, 0x73, 0xba, 0x68, 0xd8, 0x95, 0x52, 0x70, 0xec, - 0xab, 0xc1, 0x3e, 0x46, 0xde, 0xd9, 0x96, 0x85, 0xc3, 0xf4, 0x80, 0xdb, 0xd6, 0xaf, 0x9a, 0x67, - 0xad, 0x1c, 0xe7, 0x90, 0x18, 0xb5, 0xc3, 0x1f, 0xb6, 0x46, 0x3b, 0x16, 0x7d, 0x0e, 0x66, 0x92, - 0xbb, 0x50, 0xee, 0x37, 0x1f, 0x5f, 0x1b, 0x87, 0x73, 0xb7, 0x5a, 0xae, 0x97, 0x4e, 0x74, 0x96, - 0x95, 0xc4, 0xdf, 0x3a, 0x76, 0x12, 0x7f, 0x1d, 0x93, 0x27, 0x53, 0xe4, 0x67, 0xc7, 0xe4, 0xa9, - 0xf7, 0x0a, 0x92, 0xb8, 0xe4, 0x0f, 0x2d, 0x78, 0xc6, 0x69, 0x8a, 0x73, 0x81, 0xd3, 0x96, 0xa5, - 0x46, 0xee, 0x69, 0x39, 0xa3, 0xc3, 0x11, 0x77, 0xf9, 0xfe, 0x8f, 0x5f, 0xac, 0x1e, 0xc1, 0x55, - 0xf4, 0xf8, 0x4f, 0xc8, 0x2f, 0x78, 0xe6, 0x28, 0x54, 0x3c, 0x52, 0x7c, 0xf2, 0x57, 0x60, 0x36, - 0xf1, 0xc1, 0xd2, 0x12, 0x5e, 0x12, 0x17, 0x16, 0xf5, 0x24, 0x08, 0xd3, 0xb8, 0x0b, 0xb7, 0xe1, - 0xc3, 0x8f, 0x94, 0xf3, 0x58, 0x83, 0xed, 0xbb, 0x16, 0x4c, 0x9b, 0x39, 0x89, 0xc8, 0x0b, 0x30, - 0x15, 0xf9, 0xbb, 0xd4, 0xbb, 0x13, 0x28, 0x87, 0x5d, 0x3d, 0xd0, 0x37, 0x79, 0x39, 0xae, 0xa1, - 0xc6, 0x60, 0xd8, 0x8d, 0xb6, 0x4b, 0xbd, 0x68, 0xb5, 0x29, 0xbb, 0x59, 0x63, 0x2f, 0x8b, 0xf2, - 0x15, 0xd4, 0x18, 0xc2, 0xc7, 0x8e, 0xfd, 0xae, 0xd3, 0x46, 0x40, 0x95, 0x7b, 0xbf, 0xe1, 0x63, - 0x17, 0xc3, 0x30, 0x81, 0x49, 0x6c, 0x6d, 0xe2, 0x1c, 0x8f, 0xef, 0x35, 0x52, 0x26, 0xc9, 0xdf, - 0xb0, 0xa0, 0x24, 0x4c, 0xf4, 0x48, 0xb7, 0x53, 0x2e, 0xb6, 0x29, 0x23, 0x42, 0x75, 0x63, 0x35, - 0xcb, 0xc5, 0xf6, 0x32, 0x8c, 0xef, 0xba, 0x9e, 0xfa, 0x12, 0xbd, 0x2d, 0xbd, 0xe1, 0x7a, 0x4d, - 0xe4, 0x10, 0xbd, 0x71, 0x15, 0x06, 0x6e, 0x5c, 0x4b, 0x50, 0xd2, 0x8e, 0x27, 0x72, 0xf9, 0xd7, - 0xd6, 0x5b, 0xed, 0xa8, 0x82, 0x31, 0x8e, 0xfd, 0xcb, 0x16, 0xcc, 0xf0, 0x18, 0xee, 0xf8, 0x3c, - 0xfc, 0xb2, 0xf6, 0x05, 0x13, 0x72, 0x5f, 0x4c, 0xfa, 0x82, 0x3d, 0x3c, 0xa8, 0x94, 0x45, 0xd4, - 0x77, 0xd2, 0x35, 0xec, 0x33, 0xd2, 0x88, 0xc6, 0x3d, 0xd6, 0xc6, 0x8e, 0x6d, 0xe3, 0x89, 0xc5, - 0x54, 0x44, 0x30, 0xa6, 0x67, 0xbf, 0x0b, 0xd3, 0x66, 0x30, 0x16, 0x79, 0x19, 0xca, 0x5d, 0xd7, - 0x6b, 0x25, 0x83, 0x76, 0xf5, 0x45, 0xc3, 0x46, 0x0c, 0x42, 0x13, 0x8f, 0x57, 0xf3, 0xe3, 0x6a, - 0xa9, 0xfb, 0x89, 0x0d, 0xdf, 0xac, 0x16, 0xff, 0xe1, 0x79, 0xff, 0x33, 0x82, 0xfe, 0x72, 0xcf, - 0xfb, 0x9f, 0xc1, 0xe3, 0xc7, 0x97, 0xf7, 0x3f, 0x4b, 0x98, 0x3f, 0x5b, 0x79, 0xff, 0x7f, 0x1a, - 0x8e, 0x9b, 0x13, 0x95, 0xed, 0xf5, 0xf7, 0xcd, 0xc4, 0x0a, 0xba, 0xc5, 0x65, 0x66, 0x05, 0x09, - 0xb5, 0x7f, 0xab, 0x00, 0x73, 0xe9, 0x23, 0x7f, 0xde, 0xde, 0x14, 0xe4, 0x1b, 0x16, 0xcc, 0x38, - 0x89, 0xfc, 0x73, 0x39, 0x3d, 0x22, 0x94, 0xa0, 0x69, 0xe4, 0x3f, 0x4b, 0x94, 0x63, 0x8a, 0x37, - 0xf9, 0x0b, 0x30, 0x19, 0xb9, 0x1d, 0xea, 0xf7, 0x84, 0x21, 0xb0, 0x20, 0x0e, 0xe4, 0x9b, 0xa2, - 0x08, 0x15, 0x8c, 0x2d, 0xca, 0x2e, 0xd7, 0xa0, 0x02, 0x2a, 0x3d, 0x83, 0xe7, 0x62, 0xcb, 0xa5, - 0x28, 0x47, 0x8d, 0x41, 0x1e, 0xc0, 0xa4, 0xf0, 0xbb, 0x50, 0x0e, 0x36, 0xeb, 0x39, 0x99, 0x26, - 0x84, 0x6b, 0x47, 0xdc, 0x05, 0xe2, 0x7f, 0x88, 0x8a, 0x9d, 0xfd, 0x31, 0x38, 0x66, 0x92, 0x58, - 0xfb, 0x1a, 0x10, 0xf4, 0xdb, 0xed, 0x2d, 0xa7, 0xb1, 0x7b, 0xd7, 0xf5, 0x9a, 0xfe, 0x7d, 0xbe, - 0x14, 0x2d, 0x41, 0x29, 0x90, 0x21, 0xb3, 0xa1, 0x1c, 0x35, 0x7a, 0x2d, 0x53, 0xb1, 0xb4, 0x21, - 0xc6, 0x38, 0xf6, 0xef, 0x8d, 0xc1, 0xa4, 0x8c, 0xef, 0x7e, 0x0c, 0x91, 0x09, 0xbb, 0x89, 0xfb, - 0xe0, 0xd5, 0x5c, 0xc2, 0xd2, 0x07, 0x86, 0x25, 0x84, 0xa9, 0xb0, 0x84, 0x37, 0xf2, 0x61, 0x77, - 0x74, 0x4c, 0xc2, 0xbf, 0x2e, 0xc2, 0x6c, 0x2a, 0x5e, 0x9e, 0xe9, 0xe2, 0x7d, 0xae, 0xb8, 0x77, - 0x72, 0x0d, 0xc9, 0xd7, 0xb1, 0x48, 0x47, 0x7b, 0xe5, 0x86, 0x89, 0x94, 0xde, 0xf9, 0xf9, 0x32, - 0xfe, 0x79, 0x76, 0xef, 0xbc, 0xbc, 0x4c, 0x8b, 0x1f, 0x1c, 0x2f, 0xd3, 0xff, 0x62, 0xc1, 0x53, - 0x03, 0x33, 0x3f, 0xf0, 0xc4, 0x61, 0x41, 0x12, 0x2a, 0xd7, 0x8c, 0x9c, 0xf3, 0xdb, 0xe8, 0xfb, - 0xe3, 0x74, 0xae, 0xa7, 0x34, 0x7b, 0xf2, 0x12, 0x4c, 0x73, 0x1d, 0x8d, 0xad, 0x9e, 0x11, 0xed, - 0xca, 0xeb, 0x2f, 0x7e, 0x11, 0x52, 0x37, 0xca, 0x31, 0x81, 0x65, 0x7f, 0xc7, 0x82, 0xf9, 0x41, - 0x69, 0xa4, 0x86, 0x30, 0xce, 0xfc, 0xe5, 0x54, 0x74, 0x47, 0xa5, 0x2f, 0xba, 0x23, 0x65, 0x9e, - 0x51, 0x81, 0x1c, 0x86, 0x65, 0xa4, 0xf0, 0x88, 0xe0, 0x85, 0x6f, 0x5a, 0xf0, 0xe4, 0x80, 0x09, - 0xdf, 0x17, 0xe5, 0x63, 0x9d, 0x38, 0xca, 0x67, 0x6c, 0xd8, 0x28, 0x1f, 0xfb, 0xf7, 0x0b, 0x30, - 0x27, 0xe5, 0x89, 0x15, 0xf5, 0x57, 0x12, 0x31, 0x32, 0x3f, 0x91, 0x8a, 0x91, 0x39, 0x9f, 0xc6, - 0xff, 0xf3, 0x00, 0x99, 0x0f, 0x56, 0x80, 0xcc, 0xd7, 0x8b, 0x70, 0x21, 0x33, 0xbb, 0x15, 0xf9, - 0x5a, 0xc6, 0xee, 0x75, 0x37, 0xe7, 0x34, 0x5a, 0x43, 0xee, 0x5f, 0xa3, 0x46, 0x95, 0xfc, 0xa2, - 0x19, 0xcd, 0x21, 0x76, 0xa3, 0xed, 0x53, 0x48, 0x08, 0x76, 0xdc, 0xc0, 0x8e, 0xc7, 0xfb, 0xe4, - 0xd5, 0x9f, 0x81, 0xad, 0xe7, 0xeb, 0x05, 0xb8, 0x32, 0x6c, 0xcb, 0x7e, 0x40, 0x23, 0x21, 0xc3, - 0x44, 0x24, 0xe4, 0x63, 0x52, 0xb5, 0x4e, 0x25, 0x28, 0xf2, 0x1f, 0x8c, 0x6b, 0x3d, 0xa0, 0x7f, - 0xc2, 0x0e, 0xe5, 0x3c, 0x32, 0xc9, 0xd4, 0x71, 0x95, 0x29, 0x3d, 0xde, 0x1b, 0x26, 0xeb, 0xa2, - 0xf8, 0xe1, 0x41, 0xe5, 0x6c, 0x9c, 0x74, 0x46, 0x16, 0xa2, 0xaa, 0x44, 0xae, 0xc0, 0x54, 0x20, - 0xa0, 0x2a, 0xf6, 0x4b, 0x7a, 0xe0, 0x88, 0x32, 0xd4, 0x50, 0xf2, 0x45, 0xe3, 0xfc, 0x32, 0x7e, - 0x5a, 0xb9, 0x95, 0x8e, 0x72, 0x2c, 0x7a, 0x1b, 0xa6, 0x42, 0x95, 0xce, 0x5b, 0x4c, 0xa7, 0x17, - 0x87, 0x0c, 0x29, 0x74, 0xb6, 0x68, 0x5b, 0xe5, 0xf6, 0x16, 0xdf, 0xa7, 0x33, 0x7f, 0x6b, 0x92, - 0xc4, 0xd6, 0xf6, 0x00, 0x71, 0xf1, 0x01, 0xfd, 0xb6, 0x00, 0x12, 0xc1, 0xa4, 0x7c, 0xc2, 0x56, - 0xde, 0xc8, 0xae, 0xe7, 0x14, 0x9b, 0x23, 0x3d, 0xb7, 0xf9, 0x31, 0x5b, 0xd9, 0xa5, 0x14, 0x2b, - 0xfb, 0xfb, 0x16, 0x94, 0xe5, 0x18, 0x79, 0x0c, 0xb1, 0x95, 0xf7, 0x92, 0xb1, 0x95, 0xd7, 0x72, - 0x59, 0xc2, 0x07, 0x04, 0x56, 0xde, 0x83, 0x69, 0x33, 0xcf, 0x24, 0xf9, 0xb4, 0xb1, 0x05, 0x59, - 0xa3, 0x64, 0x6e, 0x53, 0x9b, 0x54, 0xbc, 0x3d, 0xd9, 0xbf, 0x56, 0xd2, 0xad, 0xc8, 0x0f, 0xf3, - 0xe6, 0xc8, 0xb7, 0x8e, 0x1c, 0xf9, 0xe6, 0xc0, 0x1b, 0xcb, 0x7f, 0xe0, 0xbd, 0x09, 0x53, 0x6a, - 0x59, 0x94, 0xda, 0xd4, 0xb3, 0xa6, 0x2b, 0x37, 0x53, 0xc9, 0x18, 0x31, 0x63, 0xba, 0xf0, 0x43, - 0x79, 0x6c, 0x2d, 0x57, 0xcb, 0xb5, 0x26, 0x43, 0xde, 0x81, 0xf2, 0x7d, 0x3f, 0xd8, 0x6d, 0xfb, - 0x0e, 0x7f, 0x43, 0x01, 0xf2, 0xf0, 0x1e, 0xd0, 0x16, 0x6f, 0x11, 0x4f, 0x73, 0x37, 0xa6, 0x8f, - 0x26, 0x33, 0x52, 0x85, 0xd9, 0x8e, 0xeb, 0x21, 0x75, 0x9a, 0x3a, 0x84, 0x72, 0x5c, 0xe4, 0x2f, - 0x57, 0x67, 0x8d, 0xf5, 0x24, 0x18, 0xd3, 0xf8, 0xdc, 0x1a, 0x16, 0x24, 0xcc, 0x2f, 0x32, 0x49, - 0xf1, 0xc6, 0xe8, 0x83, 0x31, 0x69, 0xd2, 0x11, 0x01, 0x25, 0xc9, 0x72, 0x4c, 0xf1, 0x26, 0x5f, - 0x80, 0xa9, 0x50, 0x3d, 0x0e, 0x59, 0xcc, 0xf1, 0x14, 0xa6, 0x1f, 0x88, 0xd4, 0x5d, 0xa9, 0x5f, - 0x88, 0xd4, 0x0c, 0xc9, 0x1a, 0x9c, 0x57, 0xf6, 0xa4, 0xc4, 0x3b, 0x77, 0x13, 0x71, 0xce, 0x31, - 0xcc, 0x80, 0x63, 0x66, 0x2d, 0xa6, 0xdb, 0xf2, 0xfc, 0xad, 0xe2, 0xb6, 0xd6, 0xb8, 0xe0, 0xe4, - 0xf3, 0xaf, 0x89, 0x12, 0x7a, 0x54, 0x84, 0xf0, 0xd4, 0x08, 0x11, 0xc2, 0x75, 0xb8, 0x90, 0x06, - 0xf1, 0x64, 0x72, 0x3c, 0x7f, 0x9d, 0xb1, 0x85, 0x6e, 0x64, 0x21, 0x61, 0x76, 0x5d, 0x72, 0x17, - 0x4a, 0x01, 0xe5, 0xa7, 0xce, 0xaa, 0x72, 0x74, 0x3b, 0xb6, 0x4b, 0x2f, 0x2a, 0x02, 0x18, 0xd3, - 0x62, 0xfd, 0xee, 0x24, 0x33, 0x8a, 0xbf, 0x99, 0xe3, 0xeb, 0xd1, 0xb2, 0xef, 0x07, 0x24, 0x79, - 0xb4, 0xff, 0xed, 0x2c, 0x9c, 0x49, 0x18, 0xc5, 0xc8, 0xb3, 0x50, 0xe4, 0xd9, 0xf5, 0xf8, 0x6a, - 0x35, 0x15, 0xaf, 0xa8, 0xa2, 0x71, 0x04, 0x8c, 0xfc, 0xbc, 0x05, 0xb3, 0xdd, 0xc4, 0x25, 0x8f, - 0x5a, 0xc8, 0x47, 0xb4, 0x24, 0x27, 0x6f, 0x8e, 0x8c, 0xb7, 0x38, 0x92, 0xcc, 0x30, 0xcd, 0x9d, - 0xad, 0x07, 0xd2, 0x2f, 0xbe, 0x4d, 0x03, 0x8e, 0x2d, 0x15, 0x3d, 0x4d, 0x62, 0x39, 0x09, 0xc6, - 0x34, 0x3e, 0xeb, 0x61, 0xfe, 0x75, 0xa3, 0xbc, 0x10, 0x5a, 0x55, 0x04, 0x30, 0xa6, 0x45, 0x5e, - 0x83, 0x19, 0x99, 0x48, 0x7a, 0xc3, 0x6f, 0xde, 0x70, 0xc2, 0x1d, 0x79, 0xe4, 0xd3, 0x47, 0xd4, - 0xe5, 0x04, 0x14, 0x53, 0xd8, 0xfc, 0xdb, 0xe2, 0x6c, 0xdd, 0x9c, 0xc0, 0x44, 0xf2, 0xa9, 0x92, - 0xe5, 0x24, 0x18, 0xd3, 0xf8, 0xe4, 0x05, 0x63, 0x1b, 0x12, 0x1e, 0x14, 0x7a, 0x35, 0xc8, 0xd8, - 0x8a, 0xaa, 0x30, 0xdb, 0xe3, 0x27, 0xe4, 0xa6, 0x02, 0xca, 0xf9, 0xa8, 0x19, 0xde, 0x49, 0x82, - 0x31, 0x8d, 0x4f, 0x5e, 0x85, 0x33, 0x01, 0x5b, 0x6c, 0x35, 0x01, 0xe1, 0x56, 0xa1, 0x6f, 0xcd, - 0xd1, 0x04, 0x62, 0x12, 0x97, 0xbc, 0x0e, 0x67, 0xe3, 0xbc, 0xab, 0x8a, 0x80, 0xf0, 0xb3, 0xd0, - 0x49, 0x00, 0xab, 0x69, 0x04, 0xec, 0xaf, 0x43, 0xfe, 0x1a, 0xcc, 0x19, 0x2d, 0xb1, 0xea, 0x35, - 0xe9, 0x03, 0x99, 0x1b, 0x93, 0x3f, 0xbd, 0xb5, 0x9c, 0x82, 0x61, 0x1f, 0x36, 0xf9, 0x24, 0xcc, - 0x34, 0xfc, 0x76, 0x9b, 0xaf, 0x71, 0xe2, 0x99, 0x0c, 0x91, 0x04, 0x53, 0xa4, 0x0b, 0x4d, 0x40, - 0x30, 0x85, 0x49, 0x6e, 0x02, 0xf1, 0xb7, 0x98, 0x7a, 0x45, 0x9b, 0xaf, 0x53, 0x8f, 0x4a, 0x8d, - 0xe3, 0x4c, 0x32, 0x2a, 0xe7, 0x76, 0x1f, 0x06, 0x66, 0xd4, 0xe2, 0x39, 0x04, 0x8d, 0x28, 0xe6, - 0x99, 0x3c, 0x9e, 0xb3, 0x4c, 0xdb, 0x73, 0x1e, 0x19, 0xc2, 0x1c, 0xc0, 0x84, 0x08, 0x92, 0xca, - 0x27, 0x1b, 0xa6, 0x99, 0x31, 0x3f, 0xde, 0x23, 0x44, 0x29, 0x4a, 0x4e, 0xe4, 0xe7, 0xa0, 0xb4, - 0xa5, 0x9e, 0x4f, 0xe1, 0x29, 0x30, 0x47, 0xde, 0x17, 0x53, 0x2f, 0x01, 0xc5, 0xf6, 0x0a, 0x0d, - 0xc0, 0x98, 0x25, 0x79, 0x0e, 0xca, 0x37, 0x36, 0xaa, 0x7a, 0x14, 0x9e, 0xe5, 0xbd, 0x3f, 0xce, - 0xaa, 0xa0, 0x09, 0x60, 0x33, 0x4c, 0xab, 0x6f, 0x24, 0xe9, 0x3a, 0x90, 0xa1, 0x8d, 0x31, 0x6c, - 0xee, 0x0b, 0x81, 0xf5, 0xf9, 0x73, 0x29, 0x6c, 0x59, 0x8e, 0x1a, 0x83, 0xbc, 0x0d, 0x65, 0xb9, - 0x5f, 0xf0, 0xb5, 0xe9, 0xfc, 0xc9, 0x22, 0xe4, 0x31, 0x26, 0x81, 0x26, 0x3d, 0x7e, 0x89, 0xcd, - 0x5f, 0x95, 0xa0, 0xd7, 0x7b, 0xed, 0xf6, 0xfc, 0x05, 0xbe, 0x6e, 0xc6, 0x97, 0xd8, 0x31, 0x08, - 0x4d, 0x3c, 0xf2, 0xa2, 0xf2, 0x69, 0x7b, 0x22, 0x71, 0xab, 0xaf, 0x7d, 0xda, 0xb4, 0xd2, 0x3d, - 0x20, 0x88, 0xe6, 0xc9, 0x47, 0x38, 0x93, 0x6d, 0xc1, 0x82, 0xd2, 0xf8, 0xfa, 0x27, 0xc9, 0xfc, - 0x7c, 0xc2, 0x76, 0xb4, 0x70, 0x77, 0x20, 0x26, 0x1e, 0x41, 0x85, 0x6c, 0x41, 0xc1, 0x69, 0x6f, - 0xcd, 0x3f, 0x95, 0x87, 0xea, 0x5a, 0x5d, 0xab, 0xc9, 0x11, 0xc5, 0x1d, 0x5f, 0xab, 0x6b, 0x35, - 0x64, 0xc4, 0x89, 0x0b, 0xe3, 0x4e, 0x7b, 0x2b, 0x9c, 0x5f, 0xe0, 0x73, 0x36, 0x37, 0x26, 0xb1, - 0xf1, 0x60, 0xad, 0x16, 0x22, 0x67, 0x61, 0x7f, 0x69, 0x4c, 0xdf, 0x5c, 0xe9, 0x84, 0xe4, 0xef, - 0x9a, 0x13, 0x48, 0x1c, 0x77, 0x6e, 0xe7, 0x36, 0x81, 0xa4, 0x7a, 0x71, 0x66, 0xe0, 0xf4, 0xe9, - 0xea, 0x25, 0x23, 0x97, 0x4c, 0x66, 0xc9, 0x64, 0xeb, 0xe2, 0xf4, 0x9c, 0x5c, 0x30, 0xec, 0x2f, - 0x97, 0xb5, 0x15, 0x34, 0xe5, 0x0f, 0x16, 0x40, 0xd1, 0x0d, 0x23, 0xd7, 0xcf, 0x31, 0x70, 0x3c, - 0x95, 0xa5, 0x9c, 0xc7, 0xa5, 0x70, 0x00, 0x0a, 0x56, 0x8c, 0xa7, 0xd7, 0x72, 0xbd, 0x07, 0xf2, - 0xf3, 0xdf, 0xcc, 0xdd, 0xd1, 0x4b, 0xf0, 0xe4, 0x00, 0x14, 0xac, 0xc8, 0x3d, 0x31, 0xa8, 0x0b, - 0x79, 0xf4, 0x75, 0x75, 0xad, 0x96, 0xe2, 0x97, 0x1c, 0xdc, 0xf7, 0xa0, 0x10, 0x76, 0x5c, 0xa9, - 0x2e, 0x8d, 0xc8, 0xab, 0xbe, 0xbe, 0x9a, 0xc5, 0xab, 0xbe, 0xbe, 0x8a, 0x8c, 0x09, 0xf9, 0xaa, - 0x05, 0xe0, 0x74, 0xb6, 0x9c, 0x30, 0x74, 0x9a, 0xda, 0x3a, 0x33, 0xe2, 0xeb, 0x23, 0x55, 0x4d, - 0x2f, 0xc5, 0x9a, 0xbb, 0x36, 0xc7, 0x50, 0x34, 0x38, 0x93, 0x77, 0x60, 0xd2, 0x11, 0xcf, 0x3b, - 0x4a, 0x2f, 0xfd, 0x7c, 0xde, 0x2c, 0x4d, 0x49, 0xc0, 0xcd, 0x34, 0x12, 0x84, 0x8a, 0x21, 0xe3, - 0x1d, 0x05, 0x0e, 0xdd, 0x76, 0x77, 0xa5, 0x71, 0xa8, 0x3e, 0xf2, 0x03, 0x24, 0x8c, 0x58, 0x16, - 0x6f, 0x09, 0x42, 0xc5, 0x50, 0xbc, 0xe6, 0xef, 0x78, 0x8e, 0x8e, 0xbd, 0xcc, 0x27, 0x42, 0xd7, - 0x8c, 0xe6, 0x34, 0x5e, 0xf3, 0x37, 0x19, 0x61, 0x92, 0x2f, 0xd9, 0x83, 0x09, 0x87, 0x3f, 0x3c, - 0x2b, 0x8f, 0x62, 0x98, 0xc7, 0x23, 0xb6, 0xa9, 0x36, 0xe0, 0x8b, 0x8b, 0x7c, 0xde, 0x56, 0x72, - 0x23, 0xbf, 0x62, 0xc1, 0xa4, 0x70, 0x20, 0x67, 0x0a, 0x29, 0xfb, 0xf6, 0xcf, 0x9d, 0xc2, 0x6b, - 0x07, 0xd2, 0xb9, 0x5d, 0xba, 0x44, 0x7d, 0x44, 0x7b, 0xc7, 0x8a, 0xd2, 0x23, 0xdd, 0xdb, 0x95, - 0x74, 0x4c, 0xf5, 0xed, 0x38, 0x0f, 0x12, 0xcf, 0xcb, 0x98, 0xaa, 0xef, 0x7a, 0x0a, 0x86, 0x7d, - 0xd8, 0x0b, 0x9f, 0x84, 0x69, 0x53, 0x8e, 0x63, 0xb9, 0xc8, 0xff, 0xb0, 0x00, 0xc0, 0xbb, 0x4a, - 0xe4, 0x6b, 0xe9, 0xf0, 0xe4, 0xce, 0x3b, 0x7e, 0x33, 0xa7, 0x67, 0x2e, 0x8d, 0xb4, 0x2b, 0x20, - 0x33, 0x39, 0xef, 0xf8, 0x4d, 0x94, 0x4c, 0x48, 0x0b, 0xc6, 0xbb, 0x4e, 0xb4, 0x93, 0x7f, 0x8e, - 0x97, 0x29, 0x11, 0xb8, 0x1c, 0xed, 0x20, 0x67, 0x40, 0xde, 0xb3, 0x62, 0x6f, 0xa3, 0x42, 0x3e, - 0x3e, 0x21, 0xaa, 0xcd, 0x16, 0xa5, 0x7f, 0x51, 0x2a, 0x4d, 0x6b, 0xda, 0xeb, 0x68, 0xe1, 0x7d, - 0x0b, 0xa6, 0x4d, 0xd4, 0x8c, 0x6e, 0xfa, 0x59, 0xb3, 0x9b, 0xf2, 0x6c, 0x0f, 0xb3, 0xc7, 0xff, - 0x9b, 0x05, 0x80, 0x3d, 0xaf, 0xde, 0xeb, 0x74, 0x98, 0xda, 0xae, 0x23, 0x01, 0xac, 0xa1, 0x23, - 0x01, 0xc6, 0x8e, 0x19, 0x09, 0x50, 0x38, 0x56, 0x24, 0xc0, 0xf8, 0xf1, 0x23, 0x01, 0x8a, 0x83, - 0x23, 0x01, 0xec, 0x6f, 0x59, 0x70, 0xb6, 0x6f, 0xbf, 0x62, 0x9a, 0x74, 0xe0, 0xfb, 0xd1, 0x00, - 0x2f, 0x52, 0x8c, 0x41, 0x68, 0xe2, 0x91, 0x15, 0x98, 0x93, 0x4f, 0x99, 0xd4, 0xbb, 0x6d, 0x37, - 0x33, 0xff, 0xce, 0x66, 0x0a, 0x8e, 0x7d, 0x35, 0xec, 0xdf, 0xb2, 0xa0, 0x6c, 0x44, 0xed, 0xb3, - 0xef, 0xe0, 0xae, 0xc4, 0x52, 0x8c, 0xf8, 0x15, 0x17, 0x7e, 0xd5, 0x25, 0x60, 0xe2, 0x1a, 0xba, - 0x65, 0x24, 0xba, 0x8f, 0xaf, 0xa1, 0x59, 0x29, 0x4a, 0xa8, 0x48, 0x61, 0x4e, 0xbb, 0xbc, 0xd1, - 0x0b, 0x66, 0x0a, 0x73, 0xda, 0x45, 0x0e, 0xe1, 0xec, 0xd8, 0x91, 0x42, 0x7a, 0x09, 0x1b, 0x8f, - 0xc6, 0x38, 0x41, 0x84, 0x02, 0x46, 0x2e, 0x42, 0x81, 0x7a, 0x4d, 0x69, 0xff, 0xd0, 0xcf, 0xba, - 0x5e, 0xf3, 0x9a, 0xc8, 0xca, 0xed, 0xdb, 0x30, 0x2d, 0x3c, 0xa4, 0xdf, 0xa0, 0xfb, 0x43, 0xbf, - 0x13, 0xcb, 0x46, 0x7b, 0xea, 0x9d, 0x58, 0x56, 0x9d, 0x95, 0xdb, 0xff, 0xd8, 0x82, 0xd4, 0xcb, - 0x46, 0xc6, 0x0d, 0x8c, 0x35, 0xf0, 0x06, 0xc6, 0xb4, 0xda, 0x8f, 0x1d, 0x69, 0xb5, 0xbf, 0x09, - 0xa4, 0xc3, 0xa6, 0x42, 0x72, 0xa1, 0x2d, 0x24, 0x9f, 0x9b, 0x58, 0xef, 0xc3, 0xc0, 0x8c, 0x5a, - 0xf6, 0x3f, 0x12, 0xc2, 0x9a, 0x6f, 0x1d, 0x3d, 0xba, 0x01, 0x7a, 0x50, 0xe4, 0xa4, 0xa4, 0xfd, - 0x6d, 0x44, 0xdb, 0x75, 0x7f, 0xae, 0xad, 0xb8, 0x23, 0xe5, 0x94, 0xe7, 0xdc, 0xec, 0xdf, 0x17, - 0xb2, 0x1a, 0x8f, 0x21, 0x0d, 0x21, 0x6b, 0x27, 0x29, 0xeb, 0x8d, 0xbc, 0xd6, 0xca, 0x6c, 0x19, - 0xc9, 0x22, 0x40, 0x97, 0x06, 0x0d, 0xea, 0x45, 0x2a, 0x76, 0xa9, 0x28, 0xa3, 0x68, 0x75, 0x29, - 0x1a, 0x18, 0xf6, 0x37, 0xd9, 0x04, 0x8a, 0x5f, 0x50, 0x26, 0x57, 0xd2, 0xee, 0xb7, 0xe9, 0xc9, - 0xa1, 0xbd, 0x6f, 0x8d, 0x88, 0x96, 0xb1, 0x47, 0x44, 0xb4, 0x3c, 0x0f, 0x93, 0x81, 0xdf, 0xa6, - 0xd5, 0xc0, 0x4b, 0xfb, 0x0c, 0x21, 0x2b, 0xc6, 0x5b, 0xa8, 0xe0, 0xf6, 0x2f, 0x59, 0x30, 0x97, - 0x0e, 0xb9, 0xcb, 0xdd, 0x27, 0xd8, 0xcc, 0x0b, 0x50, 0x38, 0x7e, 0x5e, 0x00, 0xfb, 0x3d, 0x26, - 0x64, 0xe4, 0x36, 0x76, 0x5d, 0x4f, 0x84, 0xd2, 0xb3, 0x96, 0x7b, 0x1e, 0x26, 0xa9, 0x7c, 0x09, - 0x56, 0x98, 0x91, 0xb5, 0x90, 0xea, 0x01, 0x58, 0x05, 0x27, 0x55, 0x98, 0x55, 0x97, 0x67, 0xca, - 0xf6, 0x2f, 0x52, 0x80, 0x68, 0x5b, 0xe3, 0x4a, 0x12, 0x8c, 0x69, 0x7c, 0xfb, 0x8b, 0x50, 0x36, - 0x36, 0x25, 0xbe, 0x7e, 0x3f, 0x70, 0x1a, 0x51, 0x7a, 0xdd, 0xbb, 0xc6, 0x0a, 0x51, 0xc0, 0xf8, - 0x15, 0x85, 0x88, 0x08, 0x4a, 0xad, 0x7b, 0x32, 0x0e, 0x48, 0x42, 0x19, 0xb1, 0x80, 0xb6, 0xe8, - 0x03, 0xf5, 0x0e, 0x81, 0x22, 0x86, 0xac, 0x10, 0x05, 0xcc, 0x7e, 0x01, 0xa6, 0x54, 0xa2, 0x26, - 0x9e, 0xed, 0x44, 0x99, 0xcf, 0xcd, 0x6c, 0x27, 0x7e, 0x10, 0x21, 0x87, 0xd8, 0x6f, 0xc1, 0x94, - 0xca, 0x27, 0xf5, 0x68, 0x6c, 0xb6, 0x14, 0x85, 0x9e, 0x7b, 0xc3, 0x0f, 0x23, 0x95, 0x04, 0x4b, - 0xdc, 0xf0, 0xdd, 0x5a, 0xe5, 0x65, 0xa8, 0xa1, 0xf6, 0x9f, 0x5a, 0x50, 0xde, 0xdc, 0x5c, 0xd3, - 0x07, 0x7f, 0x84, 0x27, 0x42, 0xd1, 0x42, 0xd5, 0xed, 0x88, 0x9a, 0xae, 0x04, 0x62, 0xe1, 0x5b, - 0x38, 0x3c, 0xa8, 0x3c, 0x51, 0xcf, 0xc4, 0xc0, 0x01, 0x35, 0xc9, 0x2a, 0x9c, 0x33, 0x21, 0x32, - 0x39, 0x81, 0x5c, 0x23, 0xf9, 0xd3, 0xc1, 0xf5, 0x7e, 0x30, 0x66, 0xd5, 0x49, 0x93, 0x92, 0xdb, - 0xbd, 0xf9, 0x0a, 0x71, 0xbd, 0x1f, 0x8c, 0x59, 0x75, 0xec, 0x17, 0x61, 0x36, 0x75, 0xc7, 0x3d, - 0x44, 0x52, 0x98, 0xdf, 0x29, 0xc0, 0xb4, 0x79, 0xd5, 0x39, 0xc4, 0xfa, 0x35, 0xfc, 0xb6, 0x90, - 0x71, 0x3d, 0x59, 0x38, 0xe6, 0xf5, 0xa4, 0x79, 0x1f, 0x3c, 0x7e, 0xba, 0xf7, 0xc1, 0xc5, 0x7c, - 0xee, 0x83, 0x0d, 0xbf, 0x85, 0x89, 0xc7, 0xe7, 0xb7, 0xf0, 0x9b, 0x45, 0x98, 0x49, 0x66, 0x19, - 0x1d, 0xa2, 0x27, 0x5f, 0xe8, 0xeb, 0xc9, 0x63, 0xde, 0x87, 0x14, 0x46, 0xbd, 0x0f, 0x19, 0x1f, - 0xf5, 0x3e, 0xa4, 0x78, 0x82, 0xfb, 0x90, 0xfe, 0xdb, 0x8c, 0x89, 0xa1, 0x6f, 0x33, 0x3e, 0xa5, - 0x5d, 0x3c, 0x27, 0x13, 0x2e, 0x40, 0xb1, 0x8b, 0x27, 0x49, 0x76, 0xc3, 0xb2, 0xdf, 0xcc, 0x74, - 0x95, 0x9d, 0x7a, 0x84, 0xdd, 0x37, 0xc8, 0xf4, 0xc8, 0x3c, 0xfe, 0x95, 0xeb, 0x13, 0xc7, 0xf0, - 0xc6, 0x7c, 0x19, 0xca, 0x72, 0x3c, 0x71, 0xe5, 0x1b, 0x92, 0x8a, 0x7b, 0x3d, 0x06, 0xa1, 0x89, - 0xc7, 0x06, 0x46, 0x37, 0x9e, 0x20, 0xfc, 0x66, 0xae, 0x9c, 0xbc, 0x99, 0xdb, 0x48, 0x82, 0x31, - 0x8d, 0x6f, 0x7f, 0x01, 0x2e, 0x64, 0x9a, 0x60, 0xb8, 0xf9, 0x9b, 0xeb, 0x85, 0xb4, 0x29, 0x11, - 0x0c, 0x31, 0x52, 0x8f, 0x8f, 0x2c, 0xdc, 0x1d, 0x88, 0x89, 0x47, 0x50, 0xb1, 0x7f, 0xbd, 0x00, - 0x33, 0xc9, 0x17, 0x68, 0xc9, 0x7d, 0x6d, 0xb0, 0xcd, 0xc5, 0x56, 0x2c, 0xc8, 0x1a, 0x99, 0x2b, - 0x07, 0x5e, 0xf4, 0xdc, 0xe7, 0xe3, 0x6b, 0x4b, 0xa7, 0xd1, 0x3c, 0x3d, 0xc6, 0xf2, 0x86, 0x45, - 0xb2, 0xe3, 0x8f, 0xcc, 0xc6, 0x41, 0xae, 0xf2, 0x1c, 0x9f, 0x3b, 0xf7, 0x38, 0x58, 0x53, 0xb3, - 0x42, 0x83, 0x2d, 0xdb, 0x5b, 0xf6, 0x68, 0xe0, 0x6e, 0xbb, 0xfa, 0xf5, 0x7c, 0xbe, 0x72, 0xbf, - 0x25, 0xcb, 0x50, 0x43, 0xed, 0xf7, 0xc6, 0xa0, 0xc4, 0x73, 0x72, 0x5d, 0x0f, 0xfc, 0x0e, 0x7f, - 0xa6, 0x31, 0x34, 0xce, 0x4c, 0xb2, 0xdb, 0x6e, 0x8e, 0xfa, 0x16, 0x6a, 0x4c, 0x51, 0xba, 0xdf, - 0x1b, 0x25, 0x98, 0xe0, 0x48, 0xba, 0x30, 0xb5, 0x2d, 0x73, 0x08, 0xcb, 0xbe, 0x1b, 0x31, 0x0f, - 0xa6, 0xca, 0x48, 0x2c, 0x9a, 0x40, 0xfd, 0x43, 0xcd, 0xc5, 0x76, 0x60, 0x36, 0x95, 0x54, 0x25, - 0xf7, 0xcc, 0xc3, 0xff, 0x73, 0x1c, 0x4a, 0x3a, 0xf6, 0x8b, 0x7c, 0x22, 0x61, 0xc0, 0x2a, 0xd5, - 0x3e, 0x6c, 0xbc, 0x21, 0xb6, 0xe3, 0x37, 0x1f, 0x1e, 0x54, 0x66, 0x35, 0x72, 0xca, 0x18, 0x75, - 0x11, 0x0a, 0xbd, 0xa0, 0x9d, 0x3e, 0xa1, 0xde, 0xc1, 0x35, 0x64, 0xe5, 0x66, 0xbc, 0x5a, 0xe1, - 0xb1, 0xc6, 0xab, 0xb1, 0x5d, 0x72, 0xcb, 0x6f, 0xee, 0xa7, 0xdf, 0x1c, 0xab, 0xf9, 0xcd, 0x7d, - 0xe4, 0x10, 0xf2, 0x1a, 0xcc, 0xc8, 0x20, 0x3c, 0xa5, 0xc4, 0x14, 0xb9, 0x9e, 0xaa, 0x1d, 0x17, - 0x36, 0x13, 0x50, 0x4c, 0x61, 0xb3, 0x5d, 0xf6, 0x5e, 0xe8, 0x7b, 0x3c, 0x9f, 0xf4, 0x44, 0xf2, - 0x96, 0xf3, 0x66, 0xfd, 0xf6, 0x2d, 0x6e, 0x48, 0xd3, 0x18, 0x89, 0x38, 0xbf, 0xc9, 0x47, 0xc6, - 0xf9, 0xad, 0x08, 0xda, 0x4c, 0x5a, 0xbe, 0xa3, 0x4c, 0xd7, 0xae, 0x28, 0xba, 0xac, 0xec, 0xe1, - 0xc1, 0x11, 0x46, 0x52, 0x5d, 0x33, 0x2b, 0x22, 0xb2, 0xf4, 0xe3, 0x8b, 0x88, 0xb4, 0xef, 0xc0, - 0x6c, 0xaa, 0xff, 0x94, 0x81, 0xc3, 0xca, 0x36, 0x70, 0x0c, 0xf7, 0x6a, 0xd9, 0x3f, 0xb5, 0xe0, - 0x6c, 0xdf, 0x8a, 0x34, 0x6c, 0x68, 0x6a, 0x7a, 0x6f, 0x1c, 0x3b, 0xf9, 0xde, 0x58, 0x38, 0xde, - 0xde, 0x58, 0xdb, 0xfa, 0xee, 0x0f, 0x2e, 0x7d, 0xe8, 0x7b, 0x3f, 0xb8, 0xf4, 0xa1, 0x3f, 0xf8, - 0xc1, 0xa5, 0x0f, 0xbd, 0x77, 0x78, 0xc9, 0xfa, 0xee, 0xe1, 0x25, 0xeb, 0x7b, 0x87, 0x97, 0xac, - 0x3f, 0x38, 0xbc, 0x64, 0xfd, 0xe7, 0xc3, 0x4b, 0xd6, 0xb7, 0xfe, 0xf8, 0xd2, 0x87, 0x3e, 0xfd, - 0xa9, 0xb8, 0xa7, 0x96, 0x54, 0x4f, 0xf1, 0x1f, 0x1f, 0x55, 0xfd, 0xb2, 0xd4, 0xdd, 0x6d, 0x2d, - 0xb1, 0x9e, 0x5a, 0xd2, 0x25, 0xaa, 0xa7, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x10, 0xcd, - 0x1f, 0xc0, 0x63, 0xa6, 0x00, 0x00, + 0x71, 0x98, 0x9a, 0xc3, 0x21, 0x39, 0x35, 0xfc, 0xda, 0xb7, 0xbb, 0x77, 0x3c, 0xde, 0xed, 0xce, + 0xaa, 0xcf, 0xb9, 0xec, 0x59, 0x27, 0x52, 0xda, 0xbb, 0x73, 0x4e, 0x3a, 0xe5, 0x92, 0x19, 0x72, + 0xf7, 0x96, 0x7b, 0xe4, 0x2e, 0xaf, 0x86, 0x7b, 0x6b, 0x7d, 0x9c, 0xad, 0xe6, 0xcc, 0xe3, 0xb0, + 0x97, 0x33, 0xdd, 0xa3, 0xee, 0x1e, 0xee, 0xf2, 0x74, 0xb0, 0x4e, 0x12, 0x4e, 0x56, 0x04, 0x09, + 0x56, 0x62, 0x0b, 0x41, 0x3e, 0x10, 0x28, 0x86, 0x01, 0x27, 0x71, 0x10, 0x24, 0x86, 0x82, 0xe4, + 0x87, 0x81, 0x18, 0x71, 0x9c, 0xc8, 0x40, 0x1c, 0xc8, 0x3f, 0x12, 0x39, 0x01, 0x4c, 0x47, 0x74, + 0xfe, 0xc4, 0x48, 0x20, 0x24, 0x50, 0x60, 0xe4, 0x7e, 0x04, 0xc1, 0xfb, 0xec, 0xd7, 0x3d, 0x3d, + 0xfc, 0x9a, 0xe6, 0xea, 0x9c, 0xf8, 0xdf, 0xcc, 0xab, 0x7a, 0x55, 0xd5, 0xef, 0xb3, 0x5e, 0xbd, + 0xaa, 0x7a, 0xb0, 0xda, 0x72, 0xa3, 0xed, 0xde, 0xe6, 0x42, 0xc3, 0xef, 0x2c, 0x3a, 0x41, 0xcb, + 0xef, 0x06, 0xfe, 0x7d, 0xfe, 0xe3, 0xc3, 0x81, 0xdf, 0x6e, 0xfb, 0xbd, 0x28, 0x5c, 0xec, 0xee, + 0xb4, 0x16, 0x9d, 0xae, 0x1b, 0x2e, 0xea, 0x92, 0xdd, 0x8f, 0x3a, 0xed, 0xee, 0xb6, 0xf3, 0xd1, + 0xc5, 0x16, 0xf5, 0x68, 0xe0, 0x44, 0xb4, 0xb9, 0xd0, 0x0d, 0xfc, 0xc8, 0x27, 0x9f, 0x88, 0xa9, + 0x2d, 0x28, 0x6a, 0xfc, 0xc7, 0xcf, 0xaa, 0xba, 0x0b, 0xdd, 0x9d, 0xd6, 0x02, 0xa3, 0xb6, 0xa0, + 0x4b, 0x14, 0xb5, 0xf9, 0x0f, 0x1b, 0xb2, 0xb4, 0xfc, 0x96, 0xbf, 0xc8, 0x89, 0x6e, 0xf6, 0xb6, + 0xf8, 0x3f, 0xfe, 0x87, 0xff, 0x12, 0xcc, 0xe6, 0x9f, 0xde, 0x79, 0x29, 0x5c, 0x70, 0x7d, 0x26, + 0xdb, 0xe2, 0xa6, 0x13, 0x35, 0xb6, 0x17, 0x77, 0xfb, 0x24, 0x9a, 0xb7, 0x0d, 0xa4, 0x86, 0x1f, + 0xd0, 0x2c, 0x9c, 0x17, 0x62, 0x9c, 0x8e, 0xd3, 0xd8, 0x76, 0x3d, 0x1a, 0xec, 0xc5, 0x5f, 0xdd, + 0xa1, 0x91, 0x93, 0x55, 0x6b, 0x71, 0x50, 0xad, 0xa0, 0xe7, 0x45, 0x6e, 0x87, 0xf6, 0x55, 0xf8, + 0xa9, 0xa3, 0x2a, 0x84, 0x8d, 0x6d, 0xda, 0x71, 0xfa, 0xea, 0x3d, 0x3f, 0xa8, 0x5e, 0x2f, 0x72, + 0xdb, 0x8b, 0xae, 0x17, 0x85, 0x51, 0x90, 0xae, 0x64, 0xff, 0xb0, 0x00, 0xa5, 0xea, 0x6a, 0xad, + 0x1e, 0x39, 0x51, 0x2f, 0x24, 0x5f, 0xb1, 0x60, 0xb2, 0xed, 0x3b, 0xcd, 0x9a, 0xd3, 0x76, 0xbc, + 0x06, 0x0d, 0xe6, 0xac, 0x2b, 0xd6, 0xd5, 0xf2, 0xb5, 0xd5, 0x85, 0x61, 0xfa, 0x6b, 0xa1, 0xfa, + 0x20, 0x44, 0x1a, 0xfa, 0xbd, 0xa0, 0x41, 0x91, 0x6e, 0xd5, 0x2e, 0x7c, 0x77, 0xbf, 0xf2, 0x81, + 0x83, 0xfd, 0xca, 0xe4, 0xaa, 0xc1, 0x09, 0x13, 0x7c, 0xc9, 0xb7, 0x2c, 0x38, 0xd7, 0x70, 0x3c, + 0x27, 0xd8, 0xdb, 0x70, 0x82, 0x16, 0x8d, 0x5e, 0x0d, 0xfc, 0x5e, 0x77, 0x6e, 0xe4, 0x0c, 0xa4, + 0x79, 0x42, 0x4a, 0x73, 0x6e, 0x29, 0xcd, 0x0e, 0xfb, 0x25, 0xe0, 0x72, 0x85, 0x91, 0xb3, 0xd9, + 0xa6, 0xa6, 0x5c, 0x85, 0xb3, 0x94, 0xab, 0x9e, 0x66, 0x87, 0xfd, 0x12, 0x90, 0x67, 0x61, 0xdc, + 0xf5, 0x5a, 0x01, 0x0d, 0xc3, 0xb9, 0xd1, 0x2b, 0xd6, 0xd5, 0x52, 0x6d, 0x46, 0x56, 0x1f, 0x5f, + 0x11, 0xc5, 0xa8, 0xe0, 0xf6, 0xaf, 0x17, 0xe0, 0x5c, 0x75, 0xb5, 0xb6, 0x11, 0x38, 0x5b, 0x5b, + 0x6e, 0x03, 0xfd, 0x5e, 0xe4, 0x7a, 0x2d, 0x93, 0x80, 0x75, 0x38, 0x01, 0xf2, 0x22, 0x94, 0x43, + 0x1a, 0xec, 0xba, 0x0d, 0xba, 0xee, 0x07, 0x11, 0xef, 0x94, 0x62, 0xed, 0xbc, 0x44, 0x2f, 0xd7, + 0x63, 0x10, 0x9a, 0x78, 0xac, 0x5a, 0xe0, 0xfb, 0x91, 0x84, 0xf3, 0x36, 0x2b, 0xc5, 0xd5, 0x30, + 0x06, 0xa1, 0x89, 0x47, 0x96, 0x61, 0xd6, 0xf1, 0x3c, 0x3f, 0x72, 0x22, 0xd7, 0xf7, 0xd6, 0x03, + 0xba, 0xe5, 0x3e, 0x94, 0x9f, 0x38, 0x27, 0xeb, 0xce, 0x56, 0x53, 0x70, 0xec, 0xab, 0x41, 0xbe, + 0x69, 0xc1, 0x6c, 0x18, 0xb9, 0x8d, 0x1d, 0xd7, 0xa3, 0x61, 0xb8, 0xe4, 0x7b, 0x5b, 0x6e, 0x6b, + 0xae, 0xc8, 0xbb, 0xed, 0xf6, 0x70, 0xdd, 0x56, 0x4f, 0x51, 0xad, 0x5d, 0x60, 0x22, 0xa5, 0x4b, + 0xb1, 0x8f, 0x3b, 0xf9, 0x10, 0x94, 0x64, 0x8b, 0xd2, 0x70, 0x6e, 0xec, 0x4a, 0xe1, 0x6a, 0xa9, + 0x36, 0x75, 0xb0, 0x5f, 0x29, 0xad, 0xa8, 0x42, 0x8c, 0xe1, 0xf6, 0x32, 0xcc, 0x55, 0x3b, 0x9b, + 0x4e, 0x18, 0x3a, 0x4d, 0x3f, 0x48, 0x75, 0xdd, 0x55, 0x98, 0xe8, 0x38, 0xdd, 0xae, 0xeb, 0xb5, + 0x58, 0xdf, 0x31, 0x3a, 0x93, 0x07, 0xfb, 0x95, 0x89, 0x35, 0x59, 0x86, 0x1a, 0x6a, 0xff, 0xc7, + 0x11, 0x28, 0x57, 0x3d, 0xa7, 0xbd, 0x17, 0xba, 0x21, 0xf6, 0x3c, 0xf2, 0x59, 0x98, 0x60, 0xab, + 0x56, 0xd3, 0x89, 0x1c, 0x39, 0xd3, 0x3f, 0xb2, 0x20, 0x16, 0x91, 0x05, 0x73, 0x11, 0x89, 0x3f, + 0x9f, 0x61, 0x2f, 0xec, 0x7e, 0x74, 0xe1, 0xce, 0xe6, 0x7d, 0xda, 0x88, 0xd6, 0x68, 0xe4, 0xd4, + 0x88, 0xec, 0x05, 0x88, 0xcb, 0x50, 0x53, 0x25, 0x3e, 0x8c, 0x86, 0x5d, 0xda, 0x90, 0x33, 0x77, + 0x6d, 0xc8, 0x19, 0x12, 0x8b, 0x5e, 0xef, 0xd2, 0x46, 0x6d, 0x52, 0xb2, 0x1e, 0x65, 0xff, 0x90, + 0x33, 0x22, 0x0f, 0x60, 0x2c, 0xe4, 0x6b, 0x99, 0x9c, 0x94, 0x77, 0xf2, 0x63, 0xc9, 0xc9, 0xd6, + 0xa6, 0x25, 0xd3, 0x31, 0xf1, 0x1f, 0x25, 0x3b, 0xfb, 0x3f, 0x59, 0x70, 0xde, 0xc0, 0xae, 0x06, + 0xad, 0x5e, 0x87, 0x7a, 0x11, 0xb9, 0x02, 0xa3, 0x9e, 0xd3, 0xa1, 0x72, 0x56, 0x69, 0x91, 0x6f, + 0x3b, 0x1d, 0x8a, 0x1c, 0x42, 0x9e, 0x86, 0xe2, 0xae, 0xd3, 0xee, 0x51, 0xde, 0x48, 0xa5, 0xda, + 0x94, 0x44, 0x29, 0xbe, 0xc1, 0x0a, 0x51, 0xc0, 0xc8, 0xdb, 0x50, 0xe2, 0x3f, 0x6e, 0x04, 0x7e, + 0x27, 0xa7, 0x4f, 0x93, 0x12, 0xbe, 0xa1, 0xc8, 0x8a, 0xe1, 0xa7, 0xff, 0x62, 0xcc, 0xd0, 0xfe, + 0x43, 0x0b, 0x66, 0x8c, 0x8f, 0x5b, 0x75, 0xc3, 0x88, 0x7c, 0xa6, 0x6f, 0xf0, 0x2c, 0x1c, 0x6f, + 0xf0, 0xb0, 0xda, 0x7c, 0xe8, 0xcc, 0xca, 0x2f, 0x9d, 0x50, 0x25, 0xc6, 0xc0, 0xf1, 0xa0, 0xe8, + 0x46, 0xb4, 0x13, 0xce, 0x8d, 0x5c, 0x29, 0x5c, 0x2d, 0x5f, 0x5b, 0xc9, 0xad, 0x1b, 0xe3, 0xf6, + 0x5d, 0x61, 0xf4, 0x51, 0xb0, 0xb1, 0xbf, 0x53, 0x48, 0x74, 0xdf, 0x9a, 0x92, 0xe3, 0x5d, 0x0b, + 0xc6, 0xda, 0xce, 0x26, 0x6d, 0x8b, 0xb9, 0x55, 0xbe, 0xf6, 0x66, 0x6e, 0x92, 0x28, 0x1e, 0x0b, + 0xab, 0x9c, 0xfe, 0x75, 0x2f, 0x0a, 0xf6, 0xe2, 0xe1, 0x25, 0x0a, 0x51, 0x32, 0x27, 0x7f, 0xc3, + 0x82, 0x72, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, 0x25, + 0xda, 0x80, 0xa0, 0x29, 0xcb, 0xfc, 0xc7, 0xa0, 0x6c, 0x7c, 0x02, 0x99, 0x85, 0xc2, 0x0e, 0xdd, + 0x13, 0x03, 0x1e, 0xd9, 0x4f, 0x72, 0x21, 0x31, 0xc2, 0xe5, 0x90, 0xfe, 0xf8, 0xc8, 0x4b, 0xd6, + 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x2e, 0x26, 0x06, 0x26, 0x5b, 0x08, + 0x88, 0x0f, 0xe3, 0x1d, 0x1a, 0x05, 0x6e, 0x43, 0x75, 0xd9, 0xf2, 0x70, 0xad, 0xb4, 0xc6, 0x89, + 0xc5, 0x1b, 0xa2, 0xf8, 0x1f, 0xa2, 0xe2, 0x42, 0xb6, 0x61, 0xd4, 0x09, 0x5a, 0xaa, 0x4f, 0x6e, + 0xe4, 0x33, 0x2d, 0xe3, 0xa5, 0xa2, 0x1a, 0xb4, 0x42, 0xe4, 0x1c, 0xc8, 0x22, 0x94, 0x22, 0x1a, + 0x74, 0x5c, 0xcf, 0x89, 0xc4, 0x0e, 0x3a, 0x51, 0x3b, 0x27, 0xd1, 0x4a, 0x1b, 0x0a, 0x80, 0x31, + 0x0e, 0x69, 0xc3, 0x58, 0x33, 0xd8, 0xc3, 0x9e, 0x37, 0x37, 0x9a, 0x47, 0x53, 0x2c, 0x73, 0x5a, + 0xf1, 0x20, 0x15, 0xff, 0x51, 0xf2, 0x20, 0xbf, 0x62, 0xc1, 0x85, 0x0e, 0x75, 0xc2, 0x5e, 0x40, + 0xd9, 0x27, 0x20, 0x8d, 0xa8, 0xc7, 0x3a, 0x76, 0xae, 0xc8, 0x99, 0xe3, 0xb0, 0xfd, 0xd0, 0x4f, + 0xb9, 0xf6, 0x94, 0x14, 0xe5, 0x42, 0x16, 0x14, 0x33, 0xa5, 0x21, 0x6f, 0x43, 0x39, 0x8a, 0xda, + 0xf5, 0x88, 0xe9, 0xc1, 0xad, 0xbd, 0xb9, 0x31, 0xbe, 0x78, 0x0d, 0xb9, 0xc2, 0x6c, 0x6c, 0xac, + 0x2a, 0x82, 0xb5, 0x19, 0x36, 0x5b, 0x8c, 0x02, 0x34, 0xd9, 0xd9, 0xff, 0xbc, 0x08, 0xe7, 0xfa, + 0xb6, 0x15, 0xf2, 0x02, 0x14, 0xbb, 0xdb, 0x4e, 0xa8, 0xf6, 0x89, 0xcb, 0x6a, 0x91, 0x5a, 0x67, + 0x85, 0xef, 0xed, 0x57, 0xa6, 0x54, 0x15, 0x5e, 0x80, 0x02, 0x99, 0x69, 0x6d, 0x1d, 0x1a, 0x86, + 0x4e, 0x4b, 0x6d, 0x1e, 0xc6, 0x20, 0xe5, 0xc5, 0xa8, 0xe0, 0xe4, 0xe7, 0x2d, 0x98, 0x12, 0x03, + 0x16, 0x69, 0xd8, 0x6b, 0x47, 0x6c, 0x83, 0x64, 0x9d, 0x72, 0x2b, 0x8f, 0xc9, 0x21, 0x48, 0xd6, + 0x2e, 0x4a, 0xee, 0x53, 0x66, 0x69, 0x88, 0x49, 0xbe, 0xe4, 0x1e, 0x94, 0xc2, 0xc8, 0x09, 0x22, + 0xda, 0xac, 0x46, 0x5c, 0x95, 0x2b, 0x5f, 0xfb, 0xc9, 0xe3, 0xed, 0x1c, 0x1b, 0x6e, 0x87, 0x8a, + 0x5d, 0xaa, 0xae, 0x08, 0x60, 0x4c, 0x8b, 0xbc, 0x0d, 0x10, 0xf4, 0xbc, 0x7a, 0xaf, 0xd3, 0x71, + 0x82, 0x3d, 0xa9, 0xdd, 0xdd, 0x1c, 0xee, 0xf3, 0x50, 0xd3, 0x8b, 0x15, 0x9d, 0xb8, 0x0c, 0x0d, + 0x7e, 0xe4, 0x8b, 0x16, 0x4c, 0x89, 0x79, 0xa0, 0x24, 0x18, 0xcb, 0x59, 0x82, 0x73, 0xac, 0x69, + 0x97, 0x4d, 0x16, 0x98, 0xe4, 0x48, 0xde, 0x84, 0x72, 0xc3, 0xef, 0x74, 0xdb, 0x54, 0x34, 0xee, + 0xf8, 0x89, 0x1b, 0x97, 0x0f, 0xdd, 0xa5, 0x98, 0x04, 0x9a, 0xf4, 0xec, 0x7f, 0x9f, 0xd4, 0x71, + 0xd4, 0x90, 0x26, 0x9f, 0x86, 0x27, 0xc2, 0x5e, 0xa3, 0x41, 0xc3, 0x70, 0xab, 0xd7, 0xc6, 0x9e, + 0x77, 0xd3, 0x0d, 0x23, 0x3f, 0xd8, 0x5b, 0x75, 0x3b, 0x6e, 0xc4, 0x07, 0x74, 0xb1, 0x76, 0xe9, + 0x60, 0xbf, 0xf2, 0x44, 0x7d, 0x10, 0x12, 0x0e, 0xae, 0x4f, 0x1c, 0x78, 0xb2, 0xe7, 0x0d, 0x26, + 0x2f, 0x8e, 0x1f, 0x95, 0x83, 0xfd, 0xca, 0x93, 0x77, 0x07, 0xa3, 0xe1, 0x61, 0x34, 0xec, 0x3f, + 0xb6, 0xd8, 0x36, 0x24, 0xbe, 0x6b, 0x83, 0x76, 0xba, 0x6d, 0xb6, 0x74, 0x9e, 0xbd, 0x72, 0x1c, + 0x25, 0x94, 0x63, 0xcc, 0x67, 0x2f, 0x57, 0xf2, 0x0f, 0xd2, 0x90, 0xed, 0xff, 0x6a, 0xc1, 0x85, + 0x34, 0xf2, 0x23, 0x50, 0xe8, 0xc2, 0xa4, 0x42, 0x77, 0x3b, 0xdf, 0xaf, 0x1d, 0xa0, 0xd5, 0x7d, + 0x65, 0xb4, 0xff, 0x5b, 0xff, 0x5f, 0xd7, 0x11, 0xe2, 0x2d, 0xbf, 0xf0, 0xe3, 0xdc, 0xf2, 0x47, + 0xdf, 0x4f, 0x5b, 0xbe, 0xfd, 0xf7, 0x46, 0x61, 0xb2, 0xea, 0x45, 0x6e, 0x75, 0x6b, 0xcb, 0xf5, + 0xdc, 0x68, 0x8f, 0x7c, 0x7d, 0x04, 0x16, 0xbb, 0x01, 0xdd, 0xa2, 0x41, 0x40, 0x9b, 0xcb, 0xbd, + 0xc0, 0xf5, 0x5a, 0xf5, 0xc6, 0x36, 0x6d, 0xf6, 0xda, 0xae, 0xd7, 0x5a, 0x69, 0x79, 0xbe, 0x2e, + 0xbe, 0xfe, 0x90, 0x36, 0x7a, 0xfc, 0x93, 0xc4, 0xa4, 0xe8, 0x0c, 0xf7, 0x49, 0xeb, 0x27, 0x63, + 0x5a, 0x7b, 0xfe, 0x60, 0xbf, 0xb2, 0x78, 0xc2, 0x4a, 0x78, 0xd2, 0x4f, 0x23, 0x5f, 0x1d, 0x81, + 0x85, 0x80, 0x7e, 0xae, 0xe7, 0x1e, 0xbf, 0x35, 0xc4, 0xaa, 0xd5, 0x1e, 0x72, 0x77, 0x3b, 0x11, + 0xcf, 0xda, 0xb5, 0x83, 0xfd, 0xca, 0x09, 0xeb, 0xe0, 0x09, 0xbf, 0xcb, 0x5e, 0x87, 0x72, 0xb5, + 0xeb, 0x86, 0xee, 0x43, 0xf4, 0x7b, 0x11, 0x3d, 0xc6, 0xf9, 0xbd, 0x02, 0xc5, 0xa0, 0xd7, 0xa6, + 0x62, 0x6e, 0x97, 0x6a, 0x25, 0xb6, 0x0a, 0x21, 0x2b, 0x40, 0x51, 0x6e, 0x7f, 0x89, 0xad, 0xb8, + 0x9c, 0x64, 0xca, 0x72, 0x73, 0x1f, 0x8a, 0x01, 0x63, 0x22, 0x47, 0xd6, 0xb0, 0x87, 0xdc, 0x58, + 0x6a, 0x29, 0x04, 0xfb, 0x89, 0x82, 0x85, 0xfd, 0x5b, 0x23, 0x70, 0xb1, 0xda, 0xed, 0xae, 0xd1, + 0x70, 0x3b, 0x25, 0xc5, 0x2f, 0x58, 0x30, 0xbd, 0xeb, 0x06, 0x51, 0xcf, 0x69, 0x2b, 0xe3, 0x9c, + 0x90, 0xa7, 0x3e, 0xac, 0x3c, 0x9c, 0xdb, 0x1b, 0x09, 0xd2, 0x35, 0x72, 0xb0, 0x5f, 0x99, 0x4e, + 0x96, 0x61, 0x8a, 0x3d, 0xf9, 0xeb, 0x16, 0xcc, 0xca, 0xa2, 0xdb, 0x7e, 0x93, 0x9a, 0xc6, 0xdf, + 0xbb, 0x79, 0xca, 0xa4, 0x89, 0x0b, 0xa3, 0x5d, 0xba, 0x14, 0xfb, 0x84, 0xb0, 0xff, 0xfb, 0x08, + 0x3c, 0x3e, 0x80, 0x06, 0xf9, 0x55, 0x0b, 0x2e, 0x08, 0x8b, 0xb1, 0x01, 0x42, 0xba, 0x25, 0x5b, + 0xf3, 0x93, 0x79, 0x4b, 0x8e, 0x6c, 0x8a, 0x53, 0xaf, 0x41, 0x6b, 0x73, 0x6c, 0x35, 0x5c, 0xca, + 0x60, 0x8d, 0x99, 0x02, 0x71, 0x49, 0x85, 0x0d, 0x39, 0x25, 0xe9, 0xc8, 0x23, 0x91, 0xb4, 0x9e, + 0xc1, 0x1a, 0x33, 0x05, 0xb2, 0xff, 0x12, 0x3c, 0x79, 0x08, 0xb9, 0xa3, 0x27, 0xa7, 0xfd, 0xa6, + 0x1e, 0xf5, 0xc9, 0x31, 0x77, 0x8c, 0x79, 0x6d, 0xc3, 0x18, 0x9f, 0x3a, 0x6a, 0x62, 0x03, 0xdb, + 0xfe, 0xf8, 0x9c, 0x0a, 0x51, 0x42, 0xec, 0xdf, 0xb2, 0x60, 0xe2, 0x04, 0xa6, 0xbe, 0x4a, 0xd2, + 0xd4, 0x57, 0xea, 0x33, 0xf3, 0x45, 0xfd, 0x66, 0xbe, 0x57, 0x87, 0xeb, 0x8d, 0xe3, 0x98, 0xf7, + 0x7e, 0x68, 0xc1, 0xb9, 0x3e, 0x73, 0x20, 0xd9, 0x86, 0x0b, 0x5d, 0xbf, 0xa9, 0xd4, 0xa6, 0x9b, + 0x4e, 0xb8, 0xcd, 0x61, 0xf2, 0xf3, 0x5e, 0x60, 0x3d, 0xb9, 0x9e, 0x01, 0x7f, 0x6f, 0xbf, 0x32, + 0xa7, 0x89, 0xa4, 0x10, 0x30, 0x93, 0x22, 0xe9, 0xc2, 0xc4, 0x96, 0x4b, 0xdb, 0xcd, 0x78, 0x08, + 0x0e, 0xa9, 0x20, 0xdd, 0x90, 0xd4, 0x84, 0x25, 0x5c, 0xfd, 0x43, 0xcd, 0xc5, 0xfe, 0x91, 0x05, + 0xd3, 0xd5, 0x5e, 0xb4, 0xcd, 0xd4, 0x83, 0x06, 0x37, 0x3e, 0x11, 0x0f, 0x8a, 0xa1, 0xdb, 0xda, + 0x7d, 0x21, 0x9f, 0xc5, 0xb8, 0xce, 0x48, 0xc9, 0x1b, 0x01, 0xad, 0x9b, 0xf2, 0x42, 0x14, 0x6c, + 0x48, 0x00, 0x63, 0xbe, 0xd3, 0x8b, 0xb6, 0xaf, 0xc9, 0x4f, 0x1e, 0xf2, 0x20, 0x7e, 0x87, 0x7d, + 0xce, 0x35, 0xc9, 0x51, 0x6b, 0x6b, 0xa2, 0x14, 0x25, 0x27, 0xfb, 0x0b, 0x30, 0x9d, 0xbc, 0x66, + 0x3a, 0xc6, 0x98, 0xbd, 0x04, 0x05, 0x27, 0xf0, 0xe4, 0x88, 0x2d, 0x4b, 0x84, 0x42, 0x15, 0x6f, + 0x23, 0x2b, 0x27, 0xcf, 0xc1, 0xc4, 0x56, 0xaf, 0xdd, 0x66, 0x15, 0xe4, 0x9d, 0x8e, 0x3e, 0x05, + 0xdc, 0x90, 0xe5, 0xa8, 0x31, 0xec, 0xff, 0x3d, 0x0a, 0x33, 0xb5, 0x76, 0x8f, 0xbe, 0x1a, 0x50, + 0xaa, 0x4c, 0x1f, 0x55, 0x98, 0xe9, 0x06, 0x74, 0xd7, 0xa5, 0x0f, 0xea, 0xb4, 0x4d, 0x1b, 0x91, + 0x1f, 0x48, 0x69, 0x1e, 0x97, 0x84, 0x66, 0xd6, 0x93, 0x60, 0x4c, 0xe3, 0x93, 0x57, 0x60, 0xda, + 0x69, 0x44, 0xee, 0x2e, 0xd5, 0x14, 0x84, 0xb8, 0x8f, 0x49, 0x0a, 0xd3, 0xd5, 0x04, 0x14, 0x53, + 0xd8, 0xe4, 0x33, 0x30, 0x17, 0x36, 0x9c, 0x36, 0xbd, 0xdb, 0x95, 0xac, 0x96, 0xb6, 0x69, 0x63, + 0x67, 0xdd, 0x77, 0xbd, 0x48, 0x9a, 0xd9, 0xae, 0x48, 0x4a, 0x73, 0xf5, 0x01, 0x78, 0x38, 0x90, + 0x02, 0xf9, 0x17, 0x16, 0x5c, 0xea, 0x06, 0x74, 0x3d, 0xf0, 0x3b, 0x3e, 0x1b, 0x6a, 0x7d, 0xd6, + 0x1f, 0x69, 0x05, 0x79, 0x63, 0x48, 0x5d, 0x4a, 0x94, 0xf4, 0x5f, 0x59, 0x7c, 0xf0, 0x60, 0xbf, + 0x72, 0x69, 0xfd, 0x30, 0x01, 0xf0, 0x70, 0xf9, 0xc8, 0xbf, 0xb4, 0xe0, 0x72, 0xd7, 0x0f, 0xa3, + 0x43, 0x3e, 0xa1, 0x78, 0xa6, 0x9f, 0x60, 0x1f, 0xec, 0x57, 0x2e, 0xaf, 0x1f, 0x2a, 0x01, 0x1e, + 0x21, 0xa1, 0x7d, 0x50, 0x86, 0x73, 0xc6, 0xd8, 0x93, 0xb6, 0x8b, 0x97, 0x61, 0x4a, 0x0d, 0x86, + 0x58, 0xf7, 0x29, 0xc5, 0xa6, 0xac, 0xaa, 0x09, 0xc4, 0x24, 0x2e, 0x1b, 0x77, 0x7a, 0x28, 0x8a, + 0xda, 0xa9, 0x71, 0xb7, 0x9e, 0x80, 0x62, 0x0a, 0x9b, 0xac, 0xc0, 0x79, 0x59, 0x82, 0xb4, 0xdb, + 0x76, 0x1b, 0xce, 0x92, 0xdf, 0x93, 0x43, 0xae, 0x58, 0x7b, 0xfc, 0x60, 0xbf, 0x72, 0x7e, 0xbd, + 0x1f, 0x8c, 0x59, 0x75, 0xc8, 0x2a, 0x5c, 0x70, 0x7a, 0x91, 0xaf, 0xbf, 0xff, 0xba, 0xc7, 0xb6, + 0xd3, 0x26, 0x1f, 0x5a, 0x13, 0x62, 0xdf, 0xad, 0x66, 0xc0, 0x31, 0xb3, 0x16, 0x59, 0x4f, 0x51, + 0xab, 0xd3, 0x86, 0xef, 0x35, 0x45, 0x2f, 0x17, 0xe3, 0x13, 0x58, 0x35, 0x03, 0x07, 0x33, 0x6b, + 0x92, 0x36, 0x4c, 0x77, 0x9c, 0x87, 0x77, 0x3d, 0x67, 0xd7, 0x71, 0xdb, 0x8c, 0x89, 0x34, 0x8f, + 0x0d, 0x36, 0xaa, 0xf4, 0x22, 0xb7, 0xbd, 0x20, 0xdc, 0x16, 0x16, 0x56, 0xbc, 0xe8, 0x4e, 0x50, + 0x8f, 0x98, 0xa6, 0x2e, 0x34, 0xc8, 0xb5, 0x04, 0x2d, 0x4c, 0xd1, 0x26, 0x77, 0xe0, 0x22, 0x9f, + 0x8e, 0xcb, 0xfe, 0x03, 0x6f, 0x99, 0xb6, 0x9d, 0x3d, 0xf5, 0x01, 0xe3, 0xfc, 0x03, 0x9e, 0x38, + 0xd8, 0xaf, 0x5c, 0xac, 0x67, 0x21, 0x60, 0x76, 0x3d, 0xe2, 0xc0, 0x93, 0x49, 0x00, 0xd2, 0x5d, + 0x37, 0x74, 0x7d, 0x4f, 0x58, 0xa1, 0x26, 0x62, 0x2b, 0x54, 0x7d, 0x30, 0x1a, 0x1e, 0x46, 0x83, + 0xfc, 0x2d, 0x0b, 0x2e, 0x64, 0x4d, 0xc3, 0xb9, 0x52, 0x1e, 0x97, 0xa7, 0xa9, 0xa9, 0x25, 0x46, + 0x44, 0xe6, 0xa2, 0x90, 0x29, 0x04, 0x79, 0xc7, 0x82, 0x49, 0xc7, 0x38, 0x41, 0xcf, 0x41, 0x1e, + 0xbb, 0x96, 0x79, 0x26, 0xaf, 0xcd, 0x1e, 0xec, 0x57, 0x12, 0xa7, 0x74, 0x4c, 0x70, 0x24, 0x7f, + 0xc7, 0x82, 0x8b, 0x99, 0x73, 0x7c, 0xae, 0x7c, 0x16, 0x2d, 0xc4, 0x07, 0x49, 0xf6, 0x9a, 0x93, + 0x2d, 0x06, 0xf9, 0xa6, 0xa5, 0xb7, 0x32, 0x75, 0x9f, 0x36, 0x37, 0xc9, 0x45, 0x7b, 0x7d, 0x48, + 0xa3, 0x41, 0xac, 0x35, 0x29, 0xc2, 0xb5, 0xf3, 0xc6, 0xce, 0xa8, 0x0a, 0x31, 0xcd, 0x9e, 0x7c, + 0xc3, 0x52, 0x5b, 0xa3, 0x96, 0x68, 0xea, 0xac, 0x24, 0x22, 0xf1, 0x4e, 0xab, 0x05, 0x4a, 0x31, + 0x27, 0x3f, 0x03, 0xf3, 0xce, 0xa6, 0x1f, 0x44, 0x99, 0x93, 0x6f, 0x6e, 0x9a, 0x4f, 0xa3, 0xcb, + 0x07, 0xfb, 0x95, 0xf9, 0xea, 0x40, 0x2c, 0x3c, 0x84, 0x82, 0xfd, 0x3b, 0x63, 0x30, 0x29, 0x4e, + 0x42, 0x72, 0xeb, 0xfa, 0x0d, 0x0b, 0x9e, 0x6a, 0xf4, 0x82, 0x80, 0x7a, 0x51, 0x3d, 0xa2, 0xdd, + 0xfe, 0x8d, 0xcb, 0x3a, 0xd3, 0x8d, 0xeb, 0xca, 0xc1, 0x7e, 0xe5, 0xa9, 0xa5, 0x43, 0xf8, 0xe3, + 0xa1, 0xd2, 0x91, 0x7f, 0x67, 0x81, 0x2d, 0x11, 0x6a, 0x4e, 0x63, 0xa7, 0x15, 0xf8, 0x3d, 0xaf, + 0xd9, 0xff, 0x11, 0x23, 0x67, 0xfa, 0x11, 0xcf, 0x1c, 0xec, 0x57, 0xec, 0xa5, 0x23, 0xa5, 0xc0, + 0x63, 0x48, 0x4a, 0x5e, 0x85, 0x73, 0x12, 0xeb, 0xfa, 0xc3, 0x2e, 0x0d, 0x5c, 0x76, 0xe6, 0x90, + 0x8a, 0x63, 0xec, 0x8a, 0x95, 0x46, 0xc0, 0xfe, 0x3a, 0x24, 0x84, 0xf1, 0x07, 0xd4, 0x6d, 0x6d, + 0x47, 0x4a, 0x7d, 0x1a, 0xd2, 0xff, 0x4a, 0x5a, 0x45, 0xee, 0x09, 0x9a, 0xb5, 0xf2, 0xc1, 0x7e, + 0x65, 0x5c, 0xfe, 0x41, 0xc5, 0x89, 0xdc, 0x86, 0x69, 0x71, 0x4e, 0x5d, 0x77, 0xbd, 0xd6, 0xba, + 0xef, 0x09, 0x27, 0xa2, 0x52, 0xed, 0x19, 0xb5, 0xe1, 0xd7, 0x13, 0xd0, 0xf7, 0xf6, 0x2b, 0x93, + 0xea, 0xf7, 0xc6, 0x5e, 0x97, 0x62, 0xaa, 0x36, 0xf9, 0x9b, 0x16, 0x90, 0x30, 0xa2, 0xdd, 0xf5, + 0x76, 0xaf, 0xe5, 0xca, 0x26, 0x92, 0xee, 0x40, 0x39, 0x78, 0x26, 0x25, 0xe9, 0xd6, 0xe6, 0xa5, + 0x90, 0xa4, 0xde, 0xc7, 0x11, 0x33, 0xa4, 0xb0, 0xbf, 0x33, 0x0e, 0xa0, 0xe6, 0x12, 0xed, 0x92, + 0x0f, 0x41, 0x29, 0xa4, 0x91, 0x68, 0x12, 0x79, 0xab, 0x23, 0xee, 0xe2, 0x54, 0x21, 0xc6, 0x70, + 0xb2, 0x03, 0xc5, 0xae, 0xd3, 0x0b, 0x69, 0x3e, 0x87, 0x1b, 0x39, 0x32, 0xd7, 0x19, 0x45, 0x71, + 0x6a, 0xe6, 0x3f, 0x51, 0xf0, 0x20, 0x5f, 0xb6, 0x00, 0x68, 0x72, 0x34, 0x0d, 0x6d, 0xbd, 0x92, + 0x2c, 0xe3, 0x01, 0xc7, 0xda, 0xa0, 0x36, 0x7d, 0xb0, 0x5f, 0x01, 0x63, 0x5c, 0x1a, 0x6c, 0xc9, + 0x03, 0x98, 0x70, 0xd4, 0x86, 0x34, 0x7a, 0x16, 0x1b, 0x12, 0x3f, 0xcc, 0xea, 0x19, 0xa5, 0x99, + 0x91, 0xaf, 0x5a, 0x30, 0x1d, 0xd2, 0x48, 0x76, 0x15, 0x5b, 0x16, 0xa5, 0x36, 0x3e, 0xe4, 0x8c, + 0xa8, 0x27, 0x68, 0x8a, 0xe5, 0x3d, 0x59, 0x86, 0x29, 0xbe, 0x4a, 0x94, 0x9b, 0xd4, 0x69, 0xd2, + 0x80, 0xdb, 0x4a, 0xa4, 0x9a, 0x37, 0xbc, 0x28, 0x06, 0x4d, 0x2d, 0x8a, 0x51, 0x86, 0x29, 0xbe, + 0x4a, 0x94, 0x35, 0x37, 0x08, 0x7c, 0x29, 0xca, 0x44, 0x4e, 0xa2, 0x18, 0x34, 0xb5, 0x28, 0x46, + 0x19, 0xa6, 0xf8, 0x92, 0x36, 0x8c, 0x75, 0xf9, 0xd4, 0x92, 0xaa, 0xdc, 0x90, 0x57, 0xc2, 0x6a, + 0x9a, 0xd2, 0xae, 0xb0, 0x49, 0x89, 0xff, 0x28, 0x79, 0xd8, 0xdf, 0x9e, 0x82, 0x69, 0x35, 0x6d, + 0xe3, 0x43, 0x8e, 0x30, 0x04, 0x0e, 0x38, 0xe4, 0x2c, 0x99, 0x40, 0x4c, 0xe2, 0xb2, 0xca, 0x62, + 0xd5, 0x4a, 0x9e, 0x71, 0x74, 0xe5, 0xba, 0x09, 0xc4, 0x24, 0x2e, 0xe9, 0x40, 0x91, 0xad, 0x2c, + 0xca, 0xdb, 0x60, 0xc8, 0x2f, 0x8f, 0x57, 0x23, 0xc3, 0xa8, 0xc2, 0xc8, 0xa3, 0xe0, 0xc2, 0x6d, + 0xd9, 0x51, 0xc2, 0xbc, 0x2d, 0xa7, 0x62, 0x3e, 0xab, 0x41, 0xd2, 0x72, 0x2e, 0xfa, 0x3e, 0x59, + 0x86, 0x29, 0xf6, 0x19, 0xe7, 0x9e, 0xe2, 0x19, 0x9e, 0x7b, 0x3e, 0x05, 0x13, 0x1d, 0xe7, 0x61, + 0xbd, 0x17, 0xb4, 0x4e, 0x7f, 0xbe, 0x92, 0xde, 0xa3, 0x82, 0x0a, 0x6a, 0x7a, 0xe4, 0x8b, 0x96, + 0xb1, 0xc0, 0x09, 0xd7, 0x82, 0x7b, 0xf9, 0x2e, 0x70, 0x5a, 0x6d, 0x18, 0xb8, 0xd4, 0xf5, 0x9d, + 0x42, 0x26, 0x1e, 0xf9, 0x29, 0x84, 0x69, 0xd4, 0x62, 0x82, 0x68, 0x8d, 0xba, 0x74, 0xa6, 0x1a, + 0xf5, 0x52, 0x82, 0x19, 0xa6, 0x98, 0x73, 0x79, 0xc4, 0x9c, 0xd3, 0xf2, 0xc0, 0x99, 0xca, 0x53, + 0x4f, 0x30, 0xc3, 0x14, 0xf3, 0xc1, 0x47, 0xef, 0xf2, 0xd9, 0x1c, 0xbd, 0x27, 0x73, 0x38, 0x7a, + 0x1f, 0x7e, 0x2a, 0x99, 0x1a, 0xf6, 0x54, 0x42, 0x6e, 0x01, 0x69, 0xee, 0x79, 0x4e, 0xc7, 0x6d, + 0xc8, 0xc5, 0x92, 0x6f, 0xd2, 0xd3, 0xdc, 0x34, 0xa3, 0xb5, 0xb2, 0xe5, 0x3e, 0x0c, 0xcc, 0xa8, + 0x45, 0x22, 0x98, 0xe8, 0x2a, 0xe5, 0x73, 0x26, 0x8f, 0xd1, 0xaf, 0x94, 0x51, 0xe1, 0x31, 0xc2, + 0x26, 0x9e, 0x2a, 0x41, 0xcd, 0x89, 0xac, 0xc2, 0x85, 0x8e, 0xeb, 0xad, 0xfb, 0xcd, 0x70, 0x9d, + 0x06, 0xd2, 0xf0, 0x54, 0xa7, 0xd1, 0xdc, 0x2c, 0x6f, 0x1b, 0x6e, 0x4c, 0x58, 0xcb, 0x80, 0x63, + 0x66, 0x2d, 0xfb, 0x7f, 0x59, 0x30, 0xbb, 0xd4, 0xf6, 0x7b, 0xcd, 0x7b, 0x4e, 0xd4, 0xd8, 0x16, + 0xce, 0x12, 0xe4, 0x15, 0x98, 0x70, 0xbd, 0x88, 0x06, 0xbb, 0x4e, 0x5b, 0xee, 0x4f, 0xb6, 0xb2, + 0x24, 0xaf, 0xc8, 0xf2, 0xf7, 0xf6, 0x2b, 0xd3, 0xcb, 0xbd, 0x80, 0x1b, 0xec, 0xc5, 0x6a, 0x85, + 0xba, 0x0e, 0xf9, 0xb6, 0x05, 0xe7, 0x84, 0xbb, 0xc5, 0xb2, 0x13, 0x39, 0xaf, 0xf7, 0x68, 0xe0, + 0x52, 0xe5, 0x70, 0x31, 0xe4, 0x42, 0x95, 0x96, 0x55, 0x31, 0xd8, 0x8b, 0xcf, 0x2c, 0x6b, 0x69, + 0xce, 0xd8, 0x2f, 0x8c, 0xfd, 0x8b, 0x05, 0x78, 0x62, 0x20, 0x2d, 0x32, 0x0f, 0x23, 0x6e, 0x53, + 0x7e, 0x3a, 0x48, 0xba, 0x23, 0x2b, 0x4d, 0x1c, 0x71, 0x9b, 0x64, 0x81, 0x6b, 0xb8, 0x01, 0x0d, + 0x43, 0x75, 0xf7, 0x5e, 0xd2, 0xca, 0xa8, 0x2c, 0x45, 0x03, 0x83, 0x54, 0xa0, 0xc8, 0x3d, 0x87, + 0xe5, 0xd1, 0x8a, 0xeb, 0xcc, 0xdc, 0x49, 0x17, 0x45, 0x39, 0xf9, 0x92, 0x05, 0x20, 0x04, 0x64, + 0xfa, 0xbe, 0xdc, 0x25, 0x31, 0xdf, 0x66, 0x62, 0x94, 0x85, 0x94, 0xf1, 0x7f, 0x34, 0xb8, 0x92, + 0x0d, 0x18, 0x63, 0xea, 0xb3, 0xdf, 0x3c, 0xf5, 0xa6, 0x28, 0x14, 0x20, 0x4e, 0x03, 0x25, 0x2d, + 0xd6, 0x56, 0x01, 0x8d, 0x7a, 0x81, 0xc7, 0x9a, 0x96, 0x6f, 0x83, 0x13, 0x42, 0x0a, 0xd4, 0xa5, + 0x68, 0x60, 0xd8, 0xff, 0x6c, 0x04, 0x2e, 0x64, 0x89, 0xce, 0x76, 0x9b, 0x31, 0x21, 0xad, 0xb4, + 0x12, 0xfc, 0x74, 0xfe, 0xed, 0x23, 0x3d, 0x87, 0xf4, 0x8d, 0x8d, 0x74, 0x9d, 0x94, 0x7c, 0xc9, + 0x4f, 0xeb, 0x16, 0x1a, 0x39, 0x65, 0x0b, 0x69, 0xca, 0xa9, 0x56, 0xba, 0x02, 0xa3, 0x21, 0xeb, + 0xf9, 0x42, 0xf2, 0xe6, 0x87, 0xf7, 0x11, 0x87, 0x30, 0x8c, 0x9e, 0xe7, 0x46, 0x32, 0xdc, 0x46, + 0x63, 0xdc, 0xf5, 0xdc, 0x08, 0x39, 0xc4, 0xfe, 0xd6, 0x08, 0xcc, 0x0f, 0xfe, 0x28, 0xf2, 0x2d, + 0x0b, 0xa0, 0xc9, 0x0e, 0x47, 0x21, 0xf7, 0x59, 0x17, 0x9e, 0x56, 0xce, 0x59, 0xb5, 0xe1, 0xb2, + 0xe2, 0x14, 0xbb, 0xdd, 0xe9, 0xa2, 0x10, 0x0d, 0x41, 0xc8, 0x35, 0x35, 0xf4, 0xf9, 0xad, 0x95, + 0x98, 0x4c, 0xba, 0xce, 0x9a, 0x86, 0xa0, 0x81, 0xc5, 0x4e, 0xbf, 0x9e, 0xd3, 0xa1, 0x61, 0xd7, + 0xd1, 0xc1, 0x4b, 0xfc, 0xf4, 0x7b, 0x5b, 0x15, 0x62, 0x0c, 0xb7, 0xdb, 0xf0, 0xf4, 0x31, 0xe4, + 0xcc, 0x29, 0x36, 0xc4, 0xfe, 0x1f, 0x16, 0x3c, 0xbe, 0xd4, 0xee, 0x85, 0x11, 0x0d, 0xfe, 0xbf, + 0xf1, 0x62, 0xfc, 0x13, 0x0b, 0x9e, 0x1c, 0xf0, 0xcd, 0x8f, 0xc0, 0x99, 0xf1, 0xad, 0xa4, 0x33, + 0xe3, 0xdd, 0x61, 0x87, 0x74, 0xe6, 0x77, 0x0c, 0xf0, 0x69, 0xfc, 0x9d, 0x02, 0x4c, 0xb1, 0x65, + 0xab, 0xe9, 0xb7, 0x72, 0xda, 0x38, 0x9f, 0x86, 0xe2, 0xe7, 0xd8, 0x06, 0x94, 0x1e, 0x64, 0x7c, + 0x57, 0x42, 0x01, 0x23, 0x5f, 0xb6, 0x60, 0xfc, 0x73, 0x72, 0x4f, 0x15, 0x67, 0xb9, 0x21, 0x17, + 0xc3, 0xc4, 0x37, 0x2c, 0xc8, 0x1d, 0x52, 0x84, 0x9c, 0x68, 0x37, 0x4a, 0xb5, 0x95, 0x2a, 0xce, + 0xe4, 0x59, 0x18, 0xdf, 0xf2, 0x83, 0x4e, 0xaf, 0xed, 0xa4, 0xe3, 0x1c, 0x6f, 0x88, 0x62, 0x54, + 0x70, 0x36, 0xc9, 0x9d, 0xae, 0xfb, 0x06, 0x0d, 0x42, 0x11, 0x81, 0x90, 0x98, 0xe4, 0x55, 0x0d, + 0x41, 0x03, 0x8b, 0xd7, 0x69, 0xb5, 0x02, 0xda, 0x72, 0x22, 0x3f, 0xe0, 0x3b, 0x87, 0x59, 0x47, + 0x43, 0xd0, 0xc0, 0x9a, 0xff, 0x38, 0x4c, 0x9a, 0xc2, 0x9f, 0x28, 0x7c, 0xe5, 0x13, 0x20, 0xfd, + 0x29, 0x53, 0x4b, 0x92, 0x75, 0x9c, 0x25, 0xc9, 0xfe, 0x0f, 0x23, 0x60, 0xd8, 0xa2, 0x1e, 0xc1, + 0x54, 0xf7, 0x12, 0x53, 0x7d, 0x48, 0x3b, 0x8a, 0x61, 0x59, 0x1b, 0x14, 0xcc, 0xb7, 0x9b, 0x0a, + 0xe6, 0xbb, 0x9d, 0x1b, 0xc7, 0xc3, 0x63, 0xf9, 0xbe, 0x6f, 0xc1, 0x93, 0x31, 0x72, 0xbf, 0x0d, + 0xfb, 0xe8, 0x75, 0xfb, 0x45, 0x28, 0x3b, 0x71, 0x35, 0x39, 0xb1, 0x8c, 0x48, 0x2a, 0x0d, 0x42, + 0x13, 0x2f, 0x8e, 0x02, 0x29, 0x9c, 0x32, 0x0a, 0x64, 0xf4, 0xf0, 0x28, 0x10, 0xfb, 0x47, 0x23, + 0x70, 0xa9, 0xff, 0xcb, 0xd4, 0x8a, 0x73, 0x3c, 0x87, 0x90, 0x97, 0x60, 0x32, 0x92, 0x15, 0x8c, + 0xfd, 0x53, 0x47, 0x75, 0x6f, 0x18, 0x30, 0x4c, 0x60, 0xb2, 0x9a, 0x0d, 0xb1, 0xd6, 0xd5, 0x1b, + 0x7e, 0x57, 0x45, 0x30, 0xe9, 0x9a, 0x4b, 0x06, 0x0c, 0x13, 0x98, 0xda, 0x7d, 0x7a, 0xf4, 0xcc, + 0xdd, 0xa7, 0xeb, 0x70, 0x51, 0x39, 0x8c, 0xde, 0xf0, 0x03, 0x19, 0x0a, 0xa1, 0x56, 0x90, 0x89, + 0xda, 0x25, 0x59, 0xe5, 0x22, 0x66, 0x21, 0x61, 0x76, 0x5d, 0xfb, 0xfb, 0x05, 0x38, 0x1f, 0x37, + 0xfb, 0x92, 0xef, 0x35, 0x5d, 0xee, 0x73, 0xf4, 0x32, 0x8c, 0x46, 0x7b, 0x5d, 0xd5, 0xd8, 0x7f, + 0x5e, 0x89, 0xb3, 0xb1, 0xd7, 0x65, 0xbd, 0xfd, 0x78, 0x46, 0x15, 0x7e, 0x8b, 0xc0, 0x2b, 0x91, + 0x55, 0x3d, 0x3b, 0x44, 0x0f, 0xbc, 0x90, 0x1c, 0xcd, 0xef, 0xed, 0x57, 0x32, 0x92, 0x1a, 0x2c, + 0x68, 0x4a, 0xc9, 0x31, 0x4f, 0xee, 0xc3, 0x74, 0xdb, 0x09, 0xa3, 0xbb, 0xdd, 0xa6, 0x13, 0xd1, + 0x0d, 0x57, 0x7a, 0xf3, 0x9c, 0x2c, 0x7a, 0x44, 0xbb, 0x3d, 0xac, 0x26, 0x28, 0x61, 0x8a, 0x32, + 0xd9, 0x05, 0xc2, 0x4a, 0x36, 0x02, 0xc7, 0x0b, 0xc5, 0x57, 0x31, 0x7e, 0x27, 0x0f, 0x05, 0xd2, + 0x47, 0xe7, 0xd5, 0x3e, 0x6a, 0x98, 0xc1, 0x81, 0x3c, 0x03, 0x63, 0x01, 0x75, 0x42, 0xbd, 0x1d, + 0xe8, 0xf9, 0x8f, 0xbc, 0x14, 0x25, 0xd4, 0x9c, 0x50, 0x63, 0x47, 0x4c, 0xa8, 0x3f, 0xb0, 0x60, + 0x3a, 0xee, 0xa6, 0x47, 0xa0, 0x7a, 0x74, 0x92, 0xaa, 0xc7, 0xcd, 0xbc, 0x96, 0xc4, 0x01, 0xda, + 0xc6, 0x1f, 0x8f, 0x9b, 0xdf, 0xc7, 0x63, 0x27, 0x3e, 0x0f, 0x25, 0x35, 0xab, 0x95, 0x4e, 0x3f, + 0xa4, 0x05, 0x22, 0xa1, 0xed, 0x19, 0x01, 0x8d, 0x92, 0x09, 0xc6, 0xfc, 0x98, 0xae, 0xd3, 0x94, + 0x7a, 0x8c, 0x1c, 0xf6, 0x5a, 0xd7, 0x51, 0xfa, 0x4d, 0x96, 0xae, 0xa3, 0xea, 0x90, 0xbb, 0xf0, + 0x78, 0x37, 0xf0, 0x79, 0x58, 0xfd, 0x32, 0x75, 0x9a, 0x6d, 0xd7, 0xa3, 0xca, 0xcc, 0x23, 0xbc, + 0x6e, 0x9e, 0x3c, 0xd8, 0xaf, 0x3c, 0xbe, 0x9e, 0x8d, 0x82, 0x83, 0xea, 0x26, 0x03, 0x33, 0x47, + 0x8f, 0x11, 0x98, 0xf9, 0x57, 0xb4, 0x31, 0x95, 0x86, 0x32, 0x3c, 0xf2, 0xd3, 0x79, 0x75, 0x65, + 0xc6, 0xb2, 0x1e, 0x0f, 0xa9, 0xaa, 0x64, 0x8a, 0x9a, 0xfd, 0x60, 0x8b, 0xdd, 0xd8, 0x29, 0x2d, + 0x76, 0x71, 0x08, 0xca, 0xf8, 0x8f, 0x33, 0x04, 0x65, 0xe2, 0x7d, 0x15, 0x75, 0xfa, 0x6d, 0x0b, + 0xce, 0x3b, 0xfd, 0x01, 0xd7, 0xf9, 0x18, 0x8f, 0x33, 0x22, 0xb9, 0x6b, 0x4f, 0x4a, 0x21, 0xb3, + 0xe2, 0xda, 0x31, 0x4b, 0x14, 0xfb, 0xdd, 0x22, 0xcc, 0xa6, 0x95, 0xa4, 0xb3, 0x8f, 0x4c, 0xfd, + 0x6b, 0x16, 0xcc, 0xaa, 0x09, 0xae, 0x6f, 0xc0, 0xc5, 0x11, 0x63, 0x35, 0xa7, 0x75, 0x45, 0xa8, + 0x7b, 0x3a, 0x61, 0xc8, 0x46, 0x8a, 0x1b, 0xf6, 0xf1, 0x27, 0x6f, 0x42, 0x59, 0xdf, 0xaa, 0x9c, + 0x2a, 0x4c, 0x95, 0x47, 0x52, 0x56, 0x63, 0x12, 0x68, 0xd2, 0x23, 0xef, 0x5a, 0x00, 0x0d, 0xb5, + 0x13, 0xab, 0x05, 0xe0, 0xf5, 0xbc, 0x16, 0x00, 0xbd, 0xc7, 0xc7, 0xfa, 0xbc, 0x2e, 0x0a, 0xd1, + 0x60, 0x4c, 0x7e, 0x91, 0xdf, 0xa7, 0xe8, 0x91, 0xa0, 0x3c, 0x0f, 0x3e, 0x99, 0xf7, 0x52, 0x14, + 0xfb, 0x92, 0x68, 0x6d, 0xcf, 0x00, 0x85, 0x98, 0x10, 0xc2, 0x7e, 0x19, 0xb4, 0xcf, 0x36, 0x5b, + 0x59, 0xb9, 0xd7, 0xf6, 0xba, 0x13, 0x6d, 0xcb, 0x21, 0xa8, 0x57, 0xd6, 0x1b, 0x0a, 0x80, 0x31, + 0x8e, 0xfd, 0x59, 0x98, 0x7e, 0x35, 0x70, 0xba, 0xdb, 0x2e, 0xbf, 0xb7, 0x60, 0xe7, 0xe3, 0x67, + 0x61, 0xdc, 0x69, 0x36, 0xb3, 0x72, 0xdb, 0x54, 0x45, 0x31, 0x2a, 0xf8, 0xb1, 0x8e, 0xc2, 0xf6, + 0xbf, 0xb6, 0x80, 0xc4, 0x37, 0xcd, 0xae, 0xd7, 0x5a, 0x73, 0xa2, 0xc6, 0x36, 0x3b, 0xc2, 0x6d, + 0xf3, 0xd2, 0xac, 0x23, 0xdc, 0x4d, 0x0d, 0x41, 0x03, 0x8b, 0xbc, 0x0d, 0x65, 0xf1, 0xef, 0x0d, + 0x7d, 0x40, 0x1c, 0xde, 0xf5, 0x9c, 0xef, 0x79, 0x5c, 0x26, 0x31, 0x0a, 0x6f, 0xc6, 0x1c, 0xd0, + 0x64, 0xc7, 0x9a, 0x6a, 0xc5, 0xdb, 0x6a, 0xf7, 0x1e, 0x36, 0x37, 0xe3, 0xa6, 0xea, 0x06, 0xfe, + 0x96, 0xdb, 0xa6, 0xe9, 0xa6, 0x5a, 0x17, 0xc5, 0xa8, 0xe0, 0xc7, 0x6b, 0xaa, 0x7f, 0x65, 0xc1, + 0x85, 0x95, 0x30, 0x72, 0xfd, 0x65, 0x1a, 0x46, 0x6c, 0xe7, 0x63, 0xeb, 0x63, 0xaf, 0x7d, 0x9c, + 0xf0, 0x8b, 0x65, 0x98, 0x95, 0xf7, 0xd0, 0xbd, 0xcd, 0x90, 0x46, 0xc6, 0x51, 0x43, 0xcf, 0xe3, + 0xa5, 0x14, 0x1c, 0xfb, 0x6a, 0x30, 0x2a, 0xf2, 0x42, 0x3a, 0xa6, 0x52, 0x48, 0x52, 0xa9, 0xa7, + 0xe0, 0xd8, 0x57, 0xc3, 0xfe, 0x5e, 0x01, 0xce, 0xf3, 0xcf, 0x48, 0x85, 0x4e, 0x7d, 0x63, 0x50, + 0xe8, 0xd4, 0x90, 0x53, 0x99, 0xf3, 0x3a, 0x45, 0xe0, 0xd4, 0x5f, 0xb5, 0x60, 0xa6, 0x99, 0x6c, + 0xe9, 0x7c, 0xec, 0x72, 0x59, 0x7d, 0x28, 0x3c, 0x10, 0x53, 0x85, 0x98, 0xe6, 0x4f, 0x7e, 0xc9, + 0x82, 0x99, 0xa4, 0x98, 0x6a, 0x75, 0x3f, 0x83, 0x46, 0xd2, 0x21, 0x03, 0xc9, 0xf2, 0x10, 0xd3, + 0x22, 0xd8, 0xbf, 0x3b, 0x22, 0xbb, 0xf4, 0x2c, 0xe2, 0x82, 0xc8, 0x03, 0x28, 0x45, 0xed, 0x50, + 0x14, 0xca, 0xaf, 0x1d, 0xf2, 0xd0, 0xba, 0xb1, 0x5a, 0x17, 0x0e, 0x27, 0xb1, 0x5e, 0x29, 0x4b, + 0x98, 0x7e, 0xac, 0x78, 0x71, 0xc6, 0x8d, 0xae, 0x64, 0x9c, 0xcb, 0x69, 0x79, 0x63, 0x69, 0x3d, + 0xcd, 0x58, 0x96, 0x30, 0xc6, 0x8a, 0x97, 0xfd, 0x6b, 0x16, 0x94, 0x6e, 0xf9, 0x6a, 0x1d, 0xf9, + 0x99, 0x1c, 0x6c, 0x51, 0x5a, 0x65, 0xd5, 0x4a, 0x4b, 0x7c, 0x0a, 0x7a, 0x25, 0x61, 0x89, 0x7a, + 0xca, 0xa0, 0xbd, 0xc0, 0x53, 0xfc, 0x31, 0x52, 0xb7, 0xfc, 0xcd, 0x81, 0xe6, 0xe3, 0x5f, 0x2e, + 0xc2, 0xd4, 0x6b, 0xce, 0x1e, 0xf5, 0x22, 0xe7, 0xe4, 0x9b, 0xc4, 0x8b, 0x50, 0x76, 0xba, 0xfc, + 0x2e, 0xd3, 0x38, 0x86, 0xc4, 0xc6, 0x9d, 0x18, 0x84, 0x26, 0x5e, 0xbc, 0xa0, 0x89, 0x20, 0x9d, + 0xac, 0xa5, 0x68, 0x29, 0x05, 0xc7, 0xbe, 0x1a, 0xe4, 0x16, 0x10, 0x19, 0x53, 0x5e, 0x6d, 0x34, + 0xfc, 0x9e, 0x27, 0x96, 0x34, 0x61, 0xf7, 0xd1, 0xe7, 0xe1, 0xb5, 0x3e, 0x0c, 0xcc, 0xa8, 0x45, + 0x3e, 0x03, 0x73, 0x0d, 0x4e, 0x59, 0x9e, 0x8e, 0x4c, 0x8a, 0xe2, 0x84, 0xac, 0xc3, 0x5e, 0x96, + 0x06, 0xe0, 0xe1, 0x40, 0x0a, 0x4c, 0xd2, 0x30, 0xf2, 0x03, 0xa7, 0x45, 0x4d, 0xba, 0x63, 0x49, + 0x49, 0xeb, 0x7d, 0x18, 0x98, 0x51, 0x8b, 0x7c, 0x01, 0x4a, 0xd1, 0x76, 0x40, 0xc3, 0x6d, 0xbf, + 0xdd, 0x94, 0xbe, 0x27, 0x43, 0x1a, 0x03, 0x65, 0xef, 0x6f, 0x28, 0xaa, 0xc6, 0xf0, 0x56, 0x45, + 0x18, 0xf3, 0x24, 0x01, 0x8c, 0x85, 0x0d, 0xbf, 0x4b, 0x43, 0x79, 0xaa, 0xb8, 0x95, 0x0b, 0x77, + 0x6e, 0xdc, 0x32, 0xcc, 0x90, 0x9c, 0x03, 0x4a, 0x4e, 0xf6, 0x6f, 0x8f, 0xc0, 0xa4, 0x89, 0x78, + 0x8c, 0xb5, 0xe9, 0xcb, 0x16, 0x4c, 0x36, 0x7c, 0x2f, 0x0a, 0xfc, 0xb6, 0x30, 0xb1, 0xe5, 0xa3, + 0x51, 0x30, 0x52, 0xcb, 0x34, 0x72, 0xdc, 0xb6, 0x61, 0xad, 0x33, 0xd8, 0x60, 0x82, 0x29, 0xf9, + 0xba, 0x05, 0x33, 0xb1, 0x63, 0x64, 0x6c, 0xeb, 0xcb, 0x55, 0x10, 0xbd, 0xd4, 0x5f, 0x4f, 0x72, + 0xc2, 0x34, 0x6b, 0x7b, 0x13, 0x66, 0xd3, 0xbd, 0xcd, 0x9a, 0xb2, 0xeb, 0xc8, 0xb9, 0x5e, 0x88, + 0x9b, 0x72, 0xdd, 0x09, 0x43, 0xe4, 0x10, 0xf2, 0x1c, 0x4c, 0x74, 0x9c, 0xa0, 0xe5, 0x7a, 0x4e, + 0x9b, 0xb7, 0x62, 0xc1, 0x58, 0x90, 0x64, 0x39, 0x6a, 0x0c, 0xfb, 0x23, 0x30, 0xb9, 0xe6, 0x78, + 0x2d, 0xda, 0x94, 0xeb, 0xf0, 0xd1, 0x91, 0xa9, 0x7f, 0x34, 0x0a, 0x65, 0xe3, 0xf8, 0x78, 0xf6, + 0xe7, 0xac, 0x44, 0xde, 0x9d, 0x42, 0x8e, 0x79, 0x77, 0x3e, 0x05, 0xb0, 0xe5, 0x7a, 0x6e, 0xb8, + 0x7d, 0xca, 0x8c, 0x3e, 0xfc, 0x6e, 0xfe, 0x86, 0xa6, 0x80, 0x06, 0xb5, 0xf8, 0x02, 0xb4, 0x78, + 0x48, 0x72, 0xbc, 0x77, 0x2d, 0x63, 0xbb, 0x19, 0xcb, 0xc3, 0xe1, 0xc3, 0xe8, 0x98, 0x05, 0xb5, + 0xfd, 0x88, 0xbb, 0xa9, 0xc3, 0x76, 0xa5, 0x0d, 0x98, 0x08, 0x68, 0xd8, 0xeb, 0xd0, 0x53, 0xe5, + 0xde, 0xe1, 0xae, 0x37, 0x28, 0xeb, 0xa3, 0xa6, 0x34, 0xff, 0x32, 0x4c, 0x25, 0x44, 0x38, 0xd1, + 0x0d, 0x93, 0x0f, 0x99, 0x36, 0x8a, 0xd3, 0xdc, 0x37, 0xb1, 0xbe, 0x68, 0x1b, 0x39, 0x77, 0x74, + 0x5f, 0x08, 0x07, 0x2b, 0x01, 0xb3, 0x7f, 0x34, 0x06, 0xd2, 0x87, 0xe1, 0x18, 0xcb, 0x95, 0x79, + 0x73, 0x39, 0x72, 0x8a, 0x9b, 0xcb, 0x5b, 0x30, 0xe9, 0x7a, 0x6e, 0xe4, 0x3a, 0x6d, 0x6e, 0x7f, + 0x92, 0xdb, 0xa9, 0x72, 0xc6, 0x9f, 0x5c, 0x31, 0x60, 0x19, 0x74, 0x12, 0x75, 0xc9, 0xeb, 0x50, + 0xe4, 0xfb, 0x8d, 0x1c, 0xc0, 0x27, 0x77, 0xb4, 0xe0, 0x3e, 0x36, 0x22, 0x42, 0x4f, 0x50, 0xe2, + 0x87, 0x0f, 0x91, 0x74, 0x48, 0x1f, 0xbf, 0xe5, 0x38, 0x8e, 0x0f, 0x1f, 0x29, 0x38, 0xf6, 0xd5, + 0x60, 0x54, 0xb6, 0x1c, 0xb7, 0xdd, 0x0b, 0x68, 0x4c, 0x65, 0x2c, 0x49, 0xe5, 0x46, 0x0a, 0x8e, + 0x7d, 0x35, 0xc8, 0x16, 0x4c, 0xca, 0x32, 0xe1, 0x36, 0x37, 0x7e, 0xca, 0xaf, 0xe4, 0xee, 0x91, + 0x37, 0x0c, 0x4a, 0x98, 0xa0, 0x4b, 0x7a, 0x70, 0xce, 0xf5, 0x1a, 0xbe, 0xd7, 0x68, 0xf7, 0x42, + 0x77, 0x97, 0xc6, 0xe1, 0x71, 0xa7, 0x61, 0x76, 0xf1, 0x60, 0xbf, 0x72, 0x6e, 0x25, 0x4d, 0x0e, + 0xfb, 0x39, 0x90, 0x2f, 0x5a, 0x70, 0xb1, 0xe1, 0x7b, 0x21, 0xcf, 0xe2, 0xb1, 0x4b, 0xaf, 0x07, + 0x81, 0x1f, 0x08, 0xde, 0xa5, 0x53, 0xf2, 0xe6, 0x66, 0xcf, 0xa5, 0x2c, 0x92, 0x98, 0xcd, 0x89, + 0xbc, 0x05, 0x13, 0xdd, 0xc0, 0xdf, 0x75, 0x9b, 0x34, 0x90, 0x2e, 0x98, 0xab, 0x79, 0x64, 0x15, + 0x5a, 0x97, 0x34, 0xe3, 0xa5, 0x47, 0x95, 0xa0, 0xe6, 0x67, 0xff, 0x9f, 0x32, 0x4c, 0x27, 0xd1, + 0xc9, 0xcf, 0x01, 0x74, 0x03, 0xbf, 0x43, 0xa3, 0x6d, 0xaa, 0xc3, 0x9c, 0x6e, 0x0f, 0x9b, 0xbc, + 0x46, 0xd1, 0x53, 0x6e, 0x4b, 0x6c, 0xb9, 0x88, 0x4b, 0xd1, 0xe0, 0x48, 0x02, 0x18, 0xdf, 0x11, + 0xdb, 0xae, 0xd4, 0x42, 0x5e, 0xcb, 0x45, 0x67, 0x92, 0x9c, 0x79, 0x7c, 0x8e, 0x2c, 0x42, 0xc5, + 0x88, 0x6c, 0x42, 0xe1, 0x01, 0xdd, 0xcc, 0x27, 0x73, 0xc2, 0x3d, 0x2a, 0x4f, 0x33, 0xb5, 0xf1, + 0x83, 0xfd, 0x4a, 0xe1, 0x1e, 0xdd, 0x44, 0x46, 0x9c, 0x7d, 0x57, 0x53, 0xf8, 0x2e, 0xc8, 0xa5, + 0xe2, 0xb5, 0x1c, 0x1d, 0x21, 0xc4, 0x77, 0xc9, 0x22, 0x54, 0x8c, 0xc8, 0x5b, 0x50, 0x7a, 0xe0, + 0xec, 0xd2, 0xad, 0xc0, 0xf7, 0x22, 0xe9, 0x2b, 0x37, 0x64, 0x70, 0xc9, 0x3d, 0x45, 0x4e, 0xf2, + 0xe5, 0xdb, 0xbb, 0x2e, 0xc4, 0x98, 0x1d, 0xd9, 0x85, 0x09, 0x8f, 0x3e, 0x40, 0xda, 0x76, 0x1b, + 0xf9, 0x04, 0x73, 0xdc, 0x96, 0xd4, 0x24, 0x67, 0xbe, 0xef, 0xa9, 0x32, 0xd4, 0xbc, 0x58, 0x5f, + 0xde, 0xf7, 0x37, 0xe5, 0x42, 0x35, 0x64, 0x5f, 0xea, 0x93, 0xa9, 0xe8, 0xcb, 0x5b, 0xfe, 0x26, + 0x32, 0xe2, 0x6c, 0x8e, 0x34, 0xb4, 0xa3, 0x96, 0x5c, 0xa6, 0x6e, 0xe7, 0xeb, 0xa0, 0x26, 0xe6, + 0x48, 0x5c, 0x8a, 0x06, 0x47, 0xd6, 0xb6, 0x2d, 0x69, 0xac, 0x94, 0x0b, 0xd5, 0x90, 0x6d, 0x9b, + 0x34, 0x7d, 0x8a, 0xb6, 0x55, 0x65, 0xa8, 0x79, 0x31, 0xbe, 0xae, 0xb4, 0xfc, 0xe5, 0xb3, 0x54, + 0x25, 0xed, 0x88, 0x82, 0xaf, 0x2a, 0x43, 0xcd, 0x8b, 0xb5, 0x77, 0xb8, 0xb3, 0xf7, 0xc0, 0x69, + 0xef, 0xb8, 0x5e, 0x4b, 0x86, 0xed, 0x0e, 0x1b, 0xe6, 0xb6, 0xb3, 0x77, 0x4f, 0xd0, 0x33, 0xdb, + 0x3b, 0x2e, 0x45, 0x83, 0x23, 0xf9, 0xdb, 0x96, 0x0e, 0xc5, 0x99, 0xcc, 0xc3, 0x89, 0x29, 0xb9, + 0xe4, 0xca, 0xc8, 0x1c, 0xa1, 0x28, 0xfe, 0xa4, 0xf6, 0xbb, 0xe4, 0x85, 0x5f, 0xfb, 0xc3, 0xca, + 0x1c, 0xf5, 0x1a, 0x7e, 0xd3, 0xf5, 0x5a, 0x8b, 0xf7, 0x43, 0xdf, 0x5b, 0x40, 0xe7, 0x81, 0xd2, + 0xd1, 0xa5, 0x4c, 0xf3, 0x1f, 0x83, 0xb2, 0x41, 0xe2, 0x28, 0x45, 0x6f, 0xd2, 0x54, 0xf4, 0x7e, + 0x6d, 0x0c, 0x26, 0xcd, 0xb4, 0x9b, 0xc7, 0xd0, 0xbe, 0xf4, 0x89, 0x63, 0xe4, 0x24, 0x27, 0x0e, + 0x76, 0xc4, 0x34, 0x2e, 0xb8, 0x94, 0x79, 0x6b, 0x25, 0x37, 0x85, 0x3b, 0x3e, 0x62, 0x1a, 0x85, + 0x21, 0x26, 0x98, 0x9e, 0xc0, 0xe7, 0x85, 0xa9, 0xad, 0x42, 0xb1, 0x2b, 0x26, 0xd5, 0xd6, 0x84, + 0xaa, 0x76, 0x0d, 0x20, 0xce, 0x0f, 0x29, 0x2f, 0x3e, 0xb5, 0x3e, 0x6c, 0xe4, 0xad, 0x34, 0xb0, + 0xc8, 0x33, 0x30, 0xc6, 0x54, 0x1f, 0xda, 0x94, 0x59, 0x05, 0xf4, 0x39, 0xfe, 0x06, 0x2f, 0x45, + 0x09, 0x25, 0x2f, 0x31, 0x2d, 0x35, 0x56, 0x58, 0x64, 0xb2, 0x80, 0x0b, 0xb1, 0x96, 0x1a, 0xc3, + 0x30, 0x81, 0xc9, 0x44, 0xa7, 0x4c, 0xbf, 0xe0, 0x6b, 0x83, 0x21, 0x3a, 0x57, 0x3a, 0x50, 0xc0, + 0xb8, 0x5d, 0x29, 0xa5, 0x8f, 0xf0, 0x39, 0x5d, 0x34, 0xec, 0x4a, 0x29, 0x38, 0xf6, 0xd5, 0x60, + 0x1f, 0x23, 0xef, 0x6c, 0xcb, 0xc2, 0x61, 0x7a, 0xc0, 0x6d, 0xeb, 0x57, 0xcc, 0xb3, 0x56, 0x8e, + 0x73, 0x48, 0x8c, 0xda, 0xe3, 0x1f, 0xb6, 0x86, 0x3b, 0x16, 0x7d, 0x16, 0xa6, 0x93, 0xbb, 0x50, + 0xee, 0x37, 0x1f, 0x5f, 0x1d, 0x85, 0xf3, 0xb7, 0x5b, 0xae, 0x97, 0xce, 0xf9, 0x96, 0xf5, 0x9e, + 0x81, 0x75, 0xe2, 0xf7, 0x0c, 0x74, 0x4c, 0x9e, 0x7c, 0x2d, 0x20, 0x3b, 0x26, 0x4f, 0x3d, 0xdd, + 0x90, 0xc4, 0x25, 0x7f, 0x60, 0xc1, 0x53, 0x4e, 0x53, 0x9c, 0x0b, 0x9c, 0xb6, 0x2c, 0x35, 0xd2, + 0x70, 0xcb, 0x19, 0x1d, 0x0e, 0xb9, 0xcb, 0xf7, 0x7f, 0xfc, 0x42, 0xf5, 0x10, 0xae, 0xa2, 0xc7, + 0x7f, 0x42, 0x7e, 0xc1, 0x53, 0x87, 0xa1, 0xe2, 0xa1, 0xe2, 0x93, 0xbf, 0x08, 0x33, 0x89, 0x0f, + 0x96, 0x96, 0xf0, 0x92, 0xb8, 0xb0, 0xa8, 0x27, 0x41, 0x98, 0xc6, 0x9d, 0xbf, 0x03, 0x1f, 0x3c, + 0x52, 0xce, 0x13, 0x0d, 0xb6, 0xef, 0x5a, 0x30, 0x69, 0xa6, 0x67, 0x22, 0xcf, 0xc1, 0x44, 0xe4, + 0xef, 0x50, 0xef, 0x6e, 0xa0, 0x1c, 0x76, 0xf5, 0x40, 0xdf, 0xe0, 0xe5, 0xb8, 0x8a, 0x1a, 0x83, + 0x61, 0x37, 0xda, 0x2e, 0xf5, 0xa2, 0x95, 0xa6, 0xec, 0x66, 0x8d, 0xbd, 0x24, 0xca, 0x97, 0x51, + 0x63, 0x08, 0x1f, 0x3b, 0xf6, 0xbb, 0x4e, 0x1b, 0x01, 0x55, 0xee, 0xfd, 0x86, 0x8f, 0x5d, 0x0c, + 0xc3, 0x04, 0x26, 0xb1, 0xb5, 0x89, 0x73, 0x34, 0xbe, 0xd7, 0x48, 0x99, 0x24, 0xbf, 0x63, 0x41, + 0x49, 0x98, 0xe8, 0x91, 0x6e, 0xa5, 0x5c, 0x6c, 0x53, 0x46, 0x84, 0xea, 0xfa, 0x4a, 0x96, 0x8b, + 0xed, 0x15, 0x18, 0xdd, 0x71, 0x3d, 0xf5, 0x25, 0x7a, 0x5b, 0x7a, 0xcd, 0xf5, 0x9a, 0xc8, 0x21, + 0x7a, 0xe3, 0x2a, 0x0c, 0xdc, 0xb8, 0x16, 0xa1, 0xa4, 0x1d, 0x4f, 0xe4, 0xf2, 0xaf, 0xad, 0xb7, + 0xda, 0x51, 0x05, 0x63, 0x1c, 0xfb, 0x57, 0x2c, 0x98, 0xe6, 0x11, 0xe3, 0xf1, 0x79, 0xf8, 0x45, + 0xed, 0x0b, 0x26, 0xe4, 0xbe, 0x94, 0xf4, 0x05, 0x7b, 0x6f, 0xbf, 0x52, 0x16, 0x31, 0xe6, 0x49, + 0xd7, 0xb0, 0x4f, 0x4b, 0x23, 0x1a, 0xf7, 0x58, 0x1b, 0x39, 0xb1, 0x8d, 0x27, 0x16, 0x53, 0x11, + 0xc1, 0x98, 0x9e, 0xfd, 0x36, 0x4c, 0x9a, 0xc1, 0x58, 0xe4, 0x45, 0x28, 0x77, 0x5d, 0xaf, 0x95, + 0x0c, 0xda, 0xd5, 0x17, 0x0d, 0xeb, 0x31, 0x08, 0x4d, 0x3c, 0x5e, 0xcd, 0x8f, 0xab, 0xa5, 0xee, + 0x27, 0xd6, 0x7d, 0xb3, 0x5a, 0xfc, 0xc7, 0xfe, 0x47, 0x16, 0x40, 0x1c, 0x5a, 0x7c, 0x2c, 0xeb, + 0xcd, 0x34, 0x8f, 0x79, 0xbb, 0xe3, 0x49, 0x7b, 0x80, 0x74, 0xe8, 0x8c, 0xb3, 0x6e, 0x25, 0xa0, + 0x98, 0xc2, 0x26, 0xaf, 0xc0, 0x98, 0xb8, 0x3c, 0x10, 0xda, 0x0c, 0x4f, 0x33, 0x31, 0x26, 0xa6, + 0xc8, 0x7b, 0xfb, 0x87, 0x69, 0x4b, 0xa2, 0x16, 0x7f, 0xb3, 0x21, 0x23, 0x4a, 0x31, 0xf7, 0x37, + 0x1b, 0x32, 0x78, 0xfc, 0xf8, 0xde, 0x6c, 0xc8, 0x12, 0xe6, 0x4f, 0xd7, 0x9b, 0x0d, 0x9f, 0x84, + 0x93, 0xe6, 0xb3, 0x65, 0xca, 0xc9, 0x03, 0x33, 0xef, 0x84, 0x6e, 0x71, 0x99, 0x78, 0x42, 0x42, + 0xed, 0xdf, 0x2c, 0xc0, 0x6c, 0xda, 0x46, 0x91, 0xb7, 0xfb, 0x07, 0xf9, 0xba, 0x05, 0xd3, 0x4e, + 0x22, 0x77, 0x60, 0x4e, 0x0f, 0x40, 0x25, 0x68, 0x1a, 0xb3, 0x28, 0x51, 0x8e, 0x29, 0xde, 0xe4, + 0xcf, 0xc1, 0x78, 0xe4, 0x76, 0xa8, 0xdf, 0x13, 0x96, 0xcb, 0x82, 0xb0, 0x20, 0x6c, 0x88, 0x22, + 0x54, 0x30, 0xb6, 0x8b, 0xb8, 0x5c, 0xe5, 0x0b, 0xa8, 0x74, 0x65, 0x9e, 0x8d, 0x4d, 0xad, 0xa2, + 0x1c, 0x35, 0x06, 0x79, 0x08, 0xe3, 0xc2, 0x51, 0x44, 0x79, 0x04, 0xad, 0xe5, 0x64, 0x4b, 0x11, + 0xbe, 0x28, 0x71, 0x17, 0x88, 0xff, 0x21, 0x2a, 0x76, 0xf6, 0x47, 0xe0, 0x84, 0x09, 0x7e, 0xed, + 0xeb, 0x40, 0xd0, 0x6f, 0xb7, 0x37, 0x9d, 0xc6, 0xce, 0x3d, 0xd7, 0x6b, 0xfa, 0x0f, 0xf8, 0xda, + 0xb9, 0x08, 0xa5, 0x40, 0xc6, 0xf8, 0x86, 0x72, 0xd4, 0xe8, 0xc5, 0x57, 0x05, 0xff, 0x86, 0x18, + 0xe3, 0xd8, 0xbf, 0x3b, 0x02, 0xe3, 0x32, 0x20, 0xfd, 0x11, 0x84, 0x52, 0xec, 0x24, 0x2e, 0xb0, + 0x57, 0x72, 0x89, 0xa3, 0x1f, 0x18, 0x47, 0x11, 0xa6, 0xe2, 0x28, 0x5e, 0xcb, 0x87, 0xdd, 0xe1, + 0x41, 0x14, 0xff, 0xa6, 0x08, 0x33, 0xa9, 0x00, 0x7f, 0x76, 0x78, 0xe8, 0xf3, 0x1d, 0xbe, 0x9b, + 0x6b, 0x0e, 0x01, 0x1d, 0x3c, 0x75, 0xb8, 0x1b, 0x71, 0x98, 0x48, 0xc7, 0x9e, 0x9f, 0xf3, 0xe5, + 0x9f, 0x65, 0x66, 0xcf, 0xcb, 0x2d, 0xb6, 0xf8, 0xfe, 0x71, 0x8b, 0xfd, 0x2f, 0x16, 0x3c, 0x31, + 0x30, 0x55, 0x05, 0x4f, 0xfa, 0x16, 0x24, 0xa1, 0x72, 0xcd, 0xc8, 0x39, 0xfd, 0x8f, 0xbe, 0xf0, + 0x4e, 0xe7, 0xe9, 0x4a, 0xb3, 0x27, 0x2f, 0xc0, 0x24, 0x57, 0x2a, 0xd9, 0xea, 0x19, 0xd1, 0xae, + 0xbc, 0xaf, 0xe3, 0x37, 0x37, 0x75, 0xa3, 0x1c, 0x13, 0x58, 0xf6, 0xb7, 0x2d, 0x98, 0x1b, 0x94, + 0x02, 0xec, 0x18, 0xda, 0xe0, 0x5f, 0x48, 0x85, 0xa3, 0x54, 0xfa, 0xc2, 0x51, 0x52, 0xf6, 0x24, + 0x15, 0x79, 0x62, 0x98, 0x72, 0x0a, 0x47, 0x44, 0x5b, 0x7c, 0xc3, 0x82, 0xc7, 0x07, 0x4c, 0xf8, + 0xbe, 0xb0, 0x24, 0xeb, 0xd4, 0x61, 0x49, 0x23, 0xc7, 0x0d, 0x4b, 0xb2, 0x7f, 0xaf, 0x00, 0xb3, + 0x52, 0x9e, 0xf8, 0x64, 0xf1, 0x52, 0x22, 0xa8, 0xe7, 0x27, 0x52, 0x41, 0x3d, 0x17, 0xd2, 0xf8, + 0x7f, 0x16, 0xd1, 0xf3, 0xfe, 0x8a, 0xe8, 0xf9, 0x5a, 0x11, 0x2e, 0x66, 0x26, 0xff, 0x22, 0x5f, + 0xcd, 0xd8, 0xbd, 0xee, 0xe5, 0x9c, 0x65, 0xec, 0x98, 0xfb, 0xd7, 0xb0, 0x61, 0x30, 0xbf, 0x64, + 0x86, 0x9f, 0x88, 0xdd, 0x68, 0xeb, 0x0c, 0xf2, 0xa5, 0x9d, 0x34, 0x12, 0xe5, 0xd1, 0x3e, 0x57, + 0xf6, 0xa7, 0x60, 0xeb, 0xf9, 0x5a, 0x01, 0xae, 0x1e, 0xb7, 0x65, 0xdf, 0xa7, 0xa1, 0x9b, 0x61, + 0x22, 0x74, 0xf3, 0x11, 0xa9, 0x5a, 0x67, 0x12, 0xc5, 0xf9, 0x77, 0x47, 0xb5, 0x1e, 0xd0, 0x3f, + 0x61, 0x8f, 0x65, 0x2f, 0x19, 0x67, 0xea, 0xb8, 0xca, 0x72, 0x1f, 0xef, 0x0d, 0xe3, 0x75, 0x51, + 0xfc, 0xde, 0x7e, 0xe5, 0x5c, 0x9c, 0x25, 0x47, 0x16, 0xa2, 0xaa, 0x44, 0xae, 0xc2, 0x44, 0x20, + 0xa0, 0x2a, 0x58, 0x4d, 0xba, 0x0c, 0x89, 0x32, 0xd4, 0x50, 0xf2, 0x05, 0xe3, 0xfc, 0x32, 0x7a, + 0x56, 0xc9, 0xa0, 0x0e, 0xf3, 0x84, 0x7a, 0x13, 0x26, 0x42, 0x95, 0x8a, 0x5d, 0x4c, 0xa7, 0xe7, + 0x8f, 0x19, 0x03, 0xe9, 0x6c, 0xd2, 0xb6, 0xca, 0xcb, 0x2e, 0xbe, 0x4f, 0x67, 0x6d, 0xd7, 0x24, + 0x89, 0xad, 0xed, 0x01, 0xe2, 0xa6, 0x06, 0xfa, 0x6d, 0x01, 0x24, 0x82, 0x71, 0xf9, 0xfc, 0xb0, + 0xbc, 0x42, 0x5e, 0xcb, 0x29, 0x98, 0x48, 0xba, 0x9a, 0xf3, 0x63, 0xb6, 0x32, 0xa4, 0x29, 0x56, + 0xf6, 0xf7, 0x2d, 0x28, 0xcb, 0x31, 0xf2, 0x08, 0x82, 0x41, 0xef, 0x27, 0x83, 0x41, 0xaf, 0xe7, + 0xb2, 0x84, 0x0f, 0x88, 0x04, 0xbd, 0x0f, 0x93, 0x66, 0x1a, 0x4e, 0xf2, 0x29, 0x63, 0x0b, 0xb2, + 0x86, 0x49, 0x35, 0xa7, 0x36, 0xa9, 0x78, 0x7b, 0xb2, 0xff, 0x61, 0x49, 0xb7, 0x22, 0x3f, 0xcc, + 0x9b, 0x23, 0xdf, 0x3a, 0x74, 0xe4, 0x9b, 0x03, 0x6f, 0x24, 0xff, 0x81, 0xf7, 0x3a, 0x4c, 0xa8, + 0x65, 0x51, 0x6a, 0x53, 0x4f, 0x9b, 0xbe, 0xe7, 0x4c, 0x25, 0x63, 0xc4, 0x8c, 0xe9, 0xc2, 0x0f, + 0xe5, 0xb1, 0x79, 0x5f, 0x2d, 0xd7, 0x9a, 0x0c, 0x79, 0x0b, 0xca, 0x0f, 0xfc, 0x60, 0xa7, 0xed, + 0x3b, 0xfc, 0xfd, 0x0b, 0xc8, 0xc3, 0xdd, 0x41, 0x9b, 0xe8, 0x45, 0x00, 0xd0, 0xbd, 0x98, 0x3e, + 0x9a, 0xcc, 0x48, 0x15, 0x66, 0x3a, 0xae, 0x87, 0xd4, 0x69, 0xea, 0x98, 0xcf, 0x51, 0x91, 0x7b, + 0x5e, 0x9d, 0x35, 0xd6, 0x92, 0x60, 0x4c, 0xe3, 0x73, 0x6b, 0x58, 0x90, 0x30, 0xbf, 0xc8, 0x04, + 0xd3, 0xeb, 0xc3, 0x0f, 0xc6, 0xa4, 0x49, 0x47, 0x44, 0xc0, 0x24, 0xcb, 0x31, 0xc5, 0x9b, 0x7c, + 0x1e, 0x26, 0x42, 0xf5, 0xb0, 0x67, 0x31, 0xc7, 0x53, 0x98, 0x7e, 0xdc, 0x53, 0x77, 0xa5, 0x7e, + 0xdd, 0x53, 0x33, 0x24, 0xab, 0x70, 0x41, 0xd9, 0x93, 0x12, 0x6f, 0x14, 0x8e, 0xc5, 0x49, 0xd2, + 0x30, 0x03, 0x8e, 0x99, 0xb5, 0x98, 0x6e, 0xcb, 0xd3, 0xdb, 0x8a, 0xeb, 0x65, 0xe3, 0x46, 0x96, + 0xcf, 0xbf, 0x26, 0x4a, 0xe8, 0x61, 0x21, 0xcd, 0x13, 0x43, 0x84, 0x34, 0xd7, 0xe1, 0x62, 0x1a, + 0xc4, 0xed, 0xf9, 0x3c, 0xe1, 0x9e, 0xb1, 0x85, 0xae, 0x67, 0x21, 0x61, 0x76, 0x5d, 0x72, 0x0f, + 0x4a, 0x01, 0xe5, 0xa7, 0xce, 0xaa, 0xf2, 0xcc, 0x3b, 0xb1, 0x0f, 0x32, 0x2a, 0x02, 0x18, 0xd3, + 0x62, 0xfd, 0xee, 0x24, 0xb3, 0xc1, 0xbf, 0x9e, 0xe3, 0xcb, 0xdf, 0xb2, 0xef, 0x07, 0x64, 0xa5, + 0xb4, 0xff, 0xed, 0x0c, 0x4c, 0x25, 0x8c, 0x62, 0xe4, 0x69, 0x28, 0xf2, 0xcb, 0x0e, 0xbe, 0x5a, + 0x4d, 0xc4, 0x2b, 0xaa, 0x68, 0x1c, 0x01, 0x23, 0xbf, 0x60, 0xc1, 0x4c, 0x37, 0x71, 0x2b, 0xa5, + 0x16, 0xf2, 0x21, 0x2d, 0xc9, 0xc9, 0xab, 0x2e, 0xe3, 0x1d, 0x95, 0x24, 0x33, 0x4c, 0x73, 0x67, + 0xeb, 0x81, 0x74, 0xe4, 0x6f, 0xd3, 0x80, 0x63, 0x4b, 0x45, 0x4f, 0x93, 0x58, 0x4a, 0x82, 0x31, + 0x8d, 0xcf, 0x7a, 0x98, 0x7f, 0xdd, 0x30, 0xaf, 0xbb, 0x56, 0x15, 0x01, 0x8c, 0x69, 0x91, 0x57, + 0x60, 0x5a, 0x26, 0x01, 0x5f, 0xf7, 0x9b, 0x37, 0x9d, 0x70, 0x5b, 0x1e, 0xf9, 0xf4, 0x11, 0x75, + 0x29, 0x01, 0xc5, 0x14, 0x36, 0xff, 0xb6, 0x38, 0xd3, 0x3a, 0x27, 0x30, 0x96, 0x7c, 0x66, 0x66, + 0x29, 0x09, 0xc6, 0x34, 0x3e, 0x79, 0xce, 0xd8, 0x86, 0x84, 0xcb, 0x87, 0x5e, 0x0d, 0x32, 0xb6, + 0xa2, 0x2a, 0xcc, 0xf4, 0xf8, 0x09, 0xb9, 0xa9, 0x80, 0x72, 0x3e, 0x6a, 0x86, 0x77, 0x93, 0x60, + 0x4c, 0xe3, 0x93, 0x97, 0x61, 0x2a, 0x60, 0x8b, 0xad, 0x26, 0x20, 0xfc, 0x40, 0xf4, 0x35, 0x3f, + 0x9a, 0x40, 0x4c, 0xe2, 0x92, 0x57, 0xe1, 0x5c, 0x9c, 0x28, 0x56, 0x11, 0x10, 0x8e, 0x21, 0x3a, + 0x6b, 0x61, 0x35, 0x8d, 0x80, 0xfd, 0x75, 0xc8, 0x5f, 0x86, 0x59, 0xa3, 0x25, 0x56, 0xbc, 0x26, + 0x7d, 0x28, 0x93, 0x79, 0xf2, 0x67, 0xd3, 0x96, 0x52, 0x30, 0xec, 0xc3, 0x26, 0x1f, 0x87, 0xe9, + 0x86, 0xdf, 0x6e, 0xf3, 0x35, 0x4e, 0x3c, 0x71, 0x22, 0xb2, 0x76, 0x8a, 0xfc, 0xa6, 0x09, 0x08, + 0xa6, 0x30, 0xc9, 0x2d, 0x20, 0xfe, 0x26, 0x53, 0xaf, 0x68, 0xf3, 0x55, 0xea, 0x51, 0xa9, 0x71, + 0x4c, 0x25, 0xc3, 0x88, 0xee, 0xf4, 0x61, 0x60, 0x46, 0x2d, 0x9e, 0xf4, 0xd0, 0x08, 0xbb, 0x9e, + 0xce, 0x23, 0xcd, 0x7a, 0xda, 0x9e, 0x73, 0x64, 0xcc, 0x75, 0x00, 0x63, 0x22, 0xaa, 0x2b, 0x9f, + 0xf4, 0x9d, 0xe6, 0x6b, 0x07, 0xf1, 0x1e, 0x21, 0x4a, 0x51, 0x72, 0x22, 0x3f, 0x07, 0xa5, 0x4d, + 0xf5, 0xf4, 0x0d, 0xcf, 0xd9, 0x39, 0xf4, 0xbe, 0x98, 0x7a, 0xc5, 0x29, 0xb6, 0x57, 0x68, 0x00, + 0xc6, 0x2c, 0xc9, 0x33, 0x50, 0xbe, 0xb9, 0x5e, 0xd5, 0xa3, 0xf0, 0x1c, 0xef, 0xfd, 0x51, 0x56, + 0x05, 0x4d, 0x00, 0x9b, 0x61, 0x5a, 0x7d, 0x23, 0x49, 0x5f, 0x87, 0x0c, 0x6d, 0x8c, 0x61, 0x73, + 0xe7, 0x0d, 0xac, 0xcf, 0x9d, 0x4f, 0x61, 0xcb, 0x72, 0xd4, 0x18, 0xe4, 0x4d, 0x28, 0xcb, 0xfd, + 0x82, 0xaf, 0x4d, 0x17, 0x4e, 0x17, 0xd2, 0x8f, 0x31, 0x09, 0x34, 0xe9, 0xf1, 0x5b, 0x77, 0xfe, + 0x22, 0x08, 0xbd, 0xd1, 0x6b, 0xb7, 0xe7, 0x2e, 0xf2, 0x75, 0x33, 0xbe, 0x75, 0x8f, 0x41, 0x68, + 0xe2, 0x91, 0xe7, 0x95, 0x13, 0xde, 0x63, 0x09, 0x37, 0x04, 0xed, 0x84, 0xa7, 0x95, 0xee, 0x01, + 0x51, 0x3f, 0x8f, 0x1f, 0xe1, 0xfd, 0xb6, 0x09, 0xf3, 0x4a, 0xe3, 0xeb, 0x9f, 0x24, 0x73, 0x73, + 0x09, 0xdb, 0xd1, 0xfc, 0xbd, 0x81, 0x98, 0x78, 0x08, 0x15, 0xb2, 0x09, 0x05, 0xa7, 0xbd, 0x39, + 0xf7, 0x44, 0x1e, 0xaa, 0x6b, 0x75, 0xb5, 0x26, 0x47, 0x14, 0xf7, 0xd4, 0xad, 0xae, 0xd6, 0x90, + 0x11, 0x27, 0x2e, 0x8c, 0x3a, 0xed, 0xcd, 0x70, 0x6e, 0x9e, 0xcf, 0xd9, 0xdc, 0x98, 0xc4, 0xc6, + 0x83, 0xd5, 0x5a, 0x88, 0x9c, 0x85, 0xfd, 0xc5, 0x11, 0x7d, 0x73, 0xa5, 0x33, 0xa8, 0xbf, 0x6d, + 0x4e, 0x20, 0x71, 0xdc, 0xb9, 0x93, 0xdb, 0x04, 0x92, 0xea, 0xc5, 0xd4, 0xc0, 0xe9, 0xd3, 0xd5, + 0x4b, 0x46, 0x2e, 0xa9, 0xd7, 0x92, 0xd9, 0xe1, 0xc5, 0xe9, 0x39, 0xb9, 0x60, 0xd8, 0x5f, 0x2a, + 0x6b, 0x2b, 0x68, 0xca, 0x81, 0x2d, 0x80, 0xa2, 0x1b, 0x46, 0xae, 0x9f, 0x63, 0xa4, 0x7b, 0x2a, + 0xad, 0x3a, 0x0f, 0xa4, 0xe1, 0x00, 0x14, 0xac, 0x18, 0x4f, 0xaf, 0xe5, 0x7a, 0x0f, 0xe5, 0xe7, + 0xbf, 0x9e, 0xbb, 0x67, 0x9a, 0xe0, 0xc9, 0x01, 0x28, 0x58, 0x91, 0xfb, 0x62, 0x50, 0x17, 0xf2, + 0xe8, 0xeb, 0xea, 0x6a, 0x2d, 0xc5, 0x2f, 0x39, 0xb8, 0xef, 0x43, 0x21, 0xec, 0xb8, 0x52, 0x5d, + 0x1a, 0x92, 0x57, 0x7d, 0x6d, 0x25, 0x8b, 0x57, 0x7d, 0x6d, 0x05, 0x19, 0x13, 0xf2, 0x15, 0x0b, + 0xc0, 0xe9, 0x6c, 0x3a, 0x61, 0xe8, 0x34, 0xb5, 0x75, 0x66, 0xc8, 0x97, 0x63, 0xaa, 0x9a, 0x5e, + 0x8a, 0x35, 0xf7, 0xc5, 0x8e, 0xa1, 0x68, 0x70, 0x26, 0x6f, 0xc1, 0xb8, 0x23, 0x9e, 0xe6, 0x94, + 0x61, 0x05, 0xf9, 0xbc, 0x37, 0x9b, 0x92, 0x80, 0x9b, 0x69, 0x24, 0x08, 0x15, 0x43, 0xc6, 0x3b, + 0x0a, 0x1c, 0xba, 0xe5, 0xee, 0x48, 0xe3, 0x50, 0x7d, 0xe8, 0xc7, 0x63, 0x18, 0xb1, 0x2c, 0xde, + 0x12, 0x84, 0x8a, 0x21, 0xf9, 0x79, 0x0b, 0xa6, 0x3a, 0x8e, 0xe7, 0xe8, 0x60, 0xd1, 0x7c, 0x42, + 0x8a, 0xcd, 0xf0, 0xd3, 0x58, 0x43, 0x5c, 0x33, 0x19, 0x61, 0x92, 0x2f, 0xd9, 0x85, 0x31, 0x87, + 0x3f, 0x1a, 0x2c, 0x8f, 0x62, 0x98, 0xc7, 0x03, 0xc4, 0xa9, 0x36, 0xe0, 0x8b, 0x8b, 0x7c, 0x9a, + 0x58, 0x72, 0x23, 0xbf, 0x6a, 0xc1, 0xb8, 0xf0, 0x78, 0x67, 0x0a, 0x29, 0xfb, 0xf6, 0xcf, 0x9e, + 0xc1, 0xf3, 0x0c, 0xd2, 0x1b, 0x5f, 0xba, 0x44, 0x7d, 0x48, 0xbb, 0xf3, 0x8a, 0xd2, 0x43, 0xfd, + 0xf1, 0x95, 0x74, 0x4c, 0xf5, 0xed, 0x38, 0x0f, 0x13, 0x4f, 0x03, 0x99, 0xaa, 0xef, 0x5a, 0x0a, + 0x86, 0x7d, 0xd8, 0xf3, 0x1f, 0x87, 0x49, 0x53, 0x8e, 0x13, 0xf9, 0xf4, 0xff, 0xb0, 0x00, 0xc0, + 0xbb, 0x4a, 0x24, 0x98, 0xe9, 0xf0, 0x6c, 0xd4, 0xdb, 0x7e, 0x33, 0xa7, 0x27, 0x4a, 0x8d, 0x3c, + 0x31, 0x20, 0x53, 0x4f, 0x6f, 0xfb, 0x4d, 0x94, 0x4c, 0x48, 0x0b, 0x46, 0xbb, 0x4e, 0xb4, 0x9d, + 0x7f, 0x52, 0x9a, 0x09, 0x11, 0x69, 0x1d, 0x6d, 0x23, 0x67, 0x40, 0xde, 0xb1, 0x62, 0x6f, 0xa3, + 0x42, 0x3e, 0x3e, 0x21, 0xaa, 0xcd, 0x16, 0xa4, 0x7f, 0x51, 0x2a, 0xaf, 0x6c, 0xda, 0xeb, 0x68, + 0xfe, 0x5d, 0x0b, 0x26, 0x4d, 0xd4, 0x8c, 0x6e, 0xfa, 0x59, 0xb3, 0x9b, 0xf2, 0x6c, 0x0f, 0xb3, + 0xc7, 0xff, 0x9b, 0x05, 0x80, 0x3d, 0xaf, 0xde, 0xeb, 0x74, 0x98, 0xda, 0xae, 0x43, 0x17, 0xac, + 0x63, 0x87, 0x2e, 0x8c, 0x9c, 0x30, 0x74, 0xa1, 0x70, 0xa2, 0xd0, 0x85, 0xd1, 0x93, 0x87, 0x2e, + 0x14, 0x07, 0x87, 0x2e, 0xd8, 0xdf, 0xb4, 0xe0, 0x5c, 0xdf, 0x7e, 0xc5, 0x34, 0xe9, 0xc0, 0xf7, + 0xa3, 0x01, 0x6e, 0xaf, 0x18, 0x83, 0xd0, 0xc4, 0x23, 0xcb, 0x30, 0x2b, 0xdf, 0x5e, 0xa9, 0x77, + 0xdb, 0x6e, 0x66, 0xc2, 0xa0, 0x8d, 0x14, 0x1c, 0xfb, 0x6a, 0xd8, 0xbf, 0x69, 0x41, 0xd9, 0x48, + 0x33, 0xc0, 0xbe, 0x83, 0xfb, 0x3e, 0x4b, 0x31, 0xe2, 0x67, 0x67, 0xf8, 0x55, 0x97, 0x80, 0x89, + 0x6b, 0xe8, 0x96, 0x91, 0x99, 0x3f, 0xbe, 0x86, 0x66, 0xa5, 0x28, 0xa1, 0x22, 0xe7, 0x3a, 0xed, + 0xf2, 0x46, 0x2f, 0x98, 0x39, 0xd7, 0x69, 0x17, 0x39, 0x84, 0xb3, 0x63, 0x47, 0x0a, 0xe9, 0xd6, + 0x6c, 0xbc, 0x72, 0xe3, 0x04, 0x11, 0x0a, 0x18, 0xb9, 0x04, 0x05, 0xea, 0x35, 0xa5, 0xfd, 0x43, + 0x3f, 0xc9, 0x7b, 0xdd, 0x6b, 0x22, 0x2b, 0xb7, 0xef, 0xc0, 0xa4, 0x70, 0xe9, 0x7e, 0x8d, 0xee, + 0x1d, 0xfb, 0x8d, 0x5f, 0x36, 0xda, 0x53, 0x6f, 0xfc, 0xb2, 0xea, 0xac, 0xdc, 0xfe, 0x07, 0x16, + 0xa4, 0x1e, 0x7e, 0x32, 0x6e, 0x60, 0xac, 0x81, 0x37, 0x30, 0xa6, 0xd5, 0x7e, 0xe4, 0x50, 0xab, + 0xfd, 0x2d, 0x20, 0x1d, 0x36, 0x15, 0x92, 0x0b, 0x6d, 0x21, 0xf9, 0x3e, 0xc6, 0x5a, 0x1f, 0x06, + 0x66, 0xd4, 0xb2, 0xff, 0xbe, 0x10, 0xd6, 0x7c, 0x0a, 0xea, 0xe8, 0x06, 0xe8, 0x41, 0x91, 0x93, + 0x92, 0xf6, 0xb7, 0x21, 0x6d, 0xd7, 0xfd, 0xc9, 0xc1, 0xe2, 0x8e, 0x94, 0x53, 0x9e, 0x73, 0xb3, + 0x7f, 0x4f, 0xc8, 0x6a, 0xbe, 0x15, 0x75, 0xb4, 0xac, 0x9d, 0xa4, 0xac, 0x37, 0xf3, 0x5a, 0x2b, + 0xb3, 0x65, 0x24, 0x0b, 0x00, 0x5d, 0x1a, 0x34, 0xa8, 0x17, 0xa9, 0x60, 0xab, 0xa2, 0x0c, 0xfb, + 0xd5, 0xa5, 0x68, 0x60, 0xd8, 0xdf, 0x60, 0x13, 0x28, 0x7e, 0xfd, 0x9a, 0x5c, 0x4d, 0xbb, 0xdf, + 0xa6, 0x27, 0x87, 0xf6, 0xbe, 0x35, 0x42, 0x70, 0x46, 0x8e, 0x08, 0xc1, 0x79, 0x16, 0xc6, 0x03, + 0xbf, 0x4d, 0xab, 0x81, 0x97, 0xf6, 0x19, 0x42, 0x56, 0x8c, 0xb7, 0x51, 0xc1, 0xed, 0x5f, 0xb6, + 0x60, 0x36, 0x1d, 0x23, 0x98, 0xbb, 0x4f, 0xb0, 0x99, 0xc8, 0xa0, 0x70, 0xf2, 0x44, 0x06, 0xf6, + 0x3f, 0x29, 0xc0, 0x6c, 0xfa, 0x55, 0x3e, 0xc6, 0xd9, 0xe5, 0xc6, 0xb6, 0xd4, 0xea, 0x2f, 0xac, + 0x6c, 0x02, 0xa6, 0xc7, 0xcb, 0xc8, 0xc0, 0xf1, 0xf2, 0x53, 0xc9, 0xa4, 0xd2, 0x57, 0xd2, 0x16, + 0x86, 0x99, 0x98, 0xf1, 0x29, 0xd3, 0x4a, 0x27, 0x53, 0x8b, 0x14, 0xcf, 0x2c, 0xb5, 0xc8, 0x58, + 0xae, 0xa9, 0x45, 0x5e, 0xd1, 0xde, 0x56, 0xe3, 0x71, 0xf8, 0x81, 0xf6, 0xb4, 0x3a, 0x24, 0xfc, + 0x40, 0x3a, 0xb8, 0xbe, 0xc3, 0x06, 0x56, 0xe4, 0x36, 0x76, 0x5c, 0x4f, 0xe4, 0x6b, 0x60, 0xa3, + 0xfd, 0x59, 0x18, 0xa7, 0xf2, 0xe5, 0x65, 0x61, 0xfa, 0xd7, 0x8d, 0xa6, 0x1e, 0x5c, 0x56, 0x70, + 0x52, 0x85, 0x19, 0x75, 0xe1, 0xa9, 0xee, 0x6b, 0x44, 0x9e, 0x19, 0x6d, 0x1f, 0x5e, 0x4e, 0x82, + 0x31, 0x8d, 0x6f, 0x7f, 0x01, 0xca, 0x86, 0x22, 0xc1, 0xf7, 0xdc, 0x87, 0x4e, 0x23, 0x4a, 0xef, + 0x55, 0xd7, 0x59, 0x21, 0x0a, 0x18, 0xbf, 0x56, 0x12, 0x61, 0x67, 0xa9, 0xbd, 0x4a, 0x06, 0x9b, + 0x49, 0x28, 0x23, 0x16, 0xd0, 0x16, 0x7d, 0xa8, 0x1e, 0xbb, 0x50, 0xc4, 0x90, 0x15, 0xa2, 0x80, + 0xd9, 0xcf, 0xc1, 0x84, 0xca, 0x06, 0xc6, 0x53, 0xea, 0xa8, 0x2b, 0x0f, 0x33, 0xa5, 0x8e, 0x1f, + 0x44, 0xc8, 0x21, 0xf6, 0x1b, 0x30, 0xa1, 0x92, 0x96, 0x1d, 0x8d, 0xcd, 0xb6, 0x8f, 0xd0, 0x73, + 0x6f, 0xfa, 0x61, 0xa4, 0x32, 0xad, 0x89, 0x5b, 0xd9, 0xdb, 0x2b, 0xbc, 0x0c, 0x35, 0xd4, 0xfe, + 0x13, 0x0b, 0xca, 0x1b, 0x1b, 0xab, 0xda, 0x58, 0x83, 0xf0, 0x58, 0x28, 0x5a, 0xa8, 0xba, 0x15, + 0x51, 0xd3, 0xfd, 0x43, 0xcc, 0xa4, 0xf9, 0x83, 0xfd, 0xca, 0x63, 0xf5, 0x4c, 0x0c, 0x1c, 0x50, + 0x93, 0xac, 0xc0, 0x79, 0x13, 0xa2, 0x22, 0x5e, 0x46, 0xe2, 0xa7, 0xba, 0xeb, 0xfd, 0x60, 0xcc, + 0xaa, 0x93, 0x26, 0x25, 0x55, 0x34, 0xf3, 0xd5, 0xef, 0x7a, 0x3f, 0x18, 0xb3, 0xea, 0xd8, 0xcf, + 0xc3, 0x4c, 0xca, 0x2f, 0xe1, 0x18, 0x99, 0x87, 0x7e, 0xbb, 0x00, 0x93, 0xe6, 0xf5, 0xf4, 0x31, + 0xf6, 0x9c, 0xe3, 0x6f, 0xe5, 0x19, 0x57, 0xca, 0x85, 0x13, 0x5e, 0x29, 0x9b, 0x77, 0xf8, 0xa3, + 0x67, 0x7b, 0x87, 0x5f, 0xcc, 0xe7, 0x0e, 0xdf, 0xf0, 0x35, 0x19, 0x7b, 0x74, 0xbe, 0x26, 0xbf, + 0x51, 0x84, 0xe9, 0x64, 0x2a, 0xdb, 0x63, 0xf4, 0xe4, 0x73, 0x7d, 0x3d, 0x79, 0xc2, 0x3b, 0xac, + 0xc2, 0xb0, 0x77, 0x58, 0xa3, 0xc3, 0xde, 0x61, 0x15, 0x4f, 0x71, 0x87, 0xd5, 0x7f, 0x03, 0x35, + 0x76, 0xec, 0x1b, 0xa8, 0x4f, 0x24, 0x36, 0x8a, 0xd8, 0x6d, 0x2b, 0xde, 0x2c, 0x48, 0xb2, 0x1b, + 0x96, 0xfc, 0x66, 0xa6, 0x7b, 0xf3, 0xc4, 0x11, 0xdb, 0x68, 0x90, 0xe9, 0x45, 0x7b, 0xf2, 0x6b, + 0xf2, 0xc7, 0x4e, 0xe0, 0x41, 0xfb, 0x22, 0x94, 0xe5, 0x78, 0xe2, 0x07, 0x26, 0x48, 0x1e, 0xb6, + 0xea, 0x31, 0x08, 0x4d, 0x3c, 0x36, 0x30, 0xba, 0xf1, 0x04, 0xe1, 0xb7, 0xa9, 0xe5, 0xe4, 0x6d, + 0xea, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xfb, 0xf3, 0x70, 0x31, 0xd3, 0x6c, 0xc6, 0xaf, 0x2c, 0xb8, + 0x2e, 0x4f, 0x9b, 0x12, 0xc1, 0x10, 0x23, 0xf5, 0xc2, 0xcd, 0xfc, 0xbd, 0x81, 0x98, 0x78, 0x08, + 0x15, 0xfb, 0xd7, 0x0b, 0x30, 0x9d, 0x7c, 0xf1, 0x99, 0x3c, 0xd0, 0x46, 0xf6, 0x5c, 0xec, 0xfb, + 0x82, 0xac, 0x91, 0x1e, 0x75, 0xe0, 0xe5, 0xdc, 0x03, 0x3e, 0xbe, 0x36, 0x75, 0xae, 0xd6, 0xb3, + 0x63, 0x2c, 0x6f, 0xc5, 0x24, 0x3b, 0xfe, 0x6e, 0x72, 0x1c, 0x49, 0x2d, 0x6d, 0x2f, 0xb9, 0x73, + 0x8f, 0x23, 0x82, 0x35, 0x2b, 0x34, 0xd8, 0xb2, 0xbd, 0x65, 0x97, 0x06, 0xee, 0x96, 0x4b, 0x9b, + 0x32, 0x75, 0x3e, 0x5f, 0xb9, 0xdf, 0x90, 0x65, 0xa8, 0xa1, 0xf6, 0x3b, 0x23, 0x50, 0xe2, 0x89, + 0xdf, 0x6e, 0x04, 0x7e, 0x87, 0xbf, 0x05, 0x1a, 0x1a, 0xe7, 0x5c, 0xd9, 0x6d, 0xb7, 0x86, 0x7d, + 0xde, 0x37, 0xa6, 0x28, 0x43, 0x26, 0x8c, 0x12, 0x4c, 0x70, 0x24, 0x5d, 0x98, 0xd8, 0x92, 0x89, + 0xaa, 0x65, 0xdf, 0x0d, 0x99, 0x6c, 0x55, 0xa5, 0xbd, 0x16, 0x4d, 0xa0, 0xfe, 0xa1, 0xe6, 0x62, + 0x3b, 0x30, 0x93, 0xca, 0xdc, 0x93, 0x7b, 0x7a, 0xeb, 0xff, 0x39, 0x0a, 0x25, 0x1d, 0xaf, 0x47, + 0x3e, 0x96, 0x30, 0x3a, 0x96, 0x6a, 0x1f, 0x34, 0x1e, 0xaa, 0xdb, 0xf6, 0x9b, 0xec, 0xfc, 0xa0, + 0x91, 0x53, 0x06, 0xc4, 0x4b, 0x50, 0xe8, 0x05, 0xed, 0xb4, 0x55, 0xe1, 0x2e, 0xae, 0x22, 0x2b, + 0x37, 0x63, 0x0c, 0x0b, 0x8f, 0x34, 0xc6, 0x90, 0xed, 0x92, 0x9b, 0x7e, 0x73, 0x2f, 0xfd, 0xb0, + 0x5d, 0xcd, 0x6f, 0xee, 0x21, 0x87, 0x90, 0x57, 0x60, 0x5a, 0x06, 0x4e, 0x2a, 0x25, 0xa6, 0xc8, + 0xf5, 0x54, 0xed, 0x6c, 0xb2, 0x91, 0x80, 0x62, 0x0a, 0x9b, 0xed, 0xb2, 0xec, 0xd8, 0xc0, 0x93, + 0x96, 0x8f, 0x25, 0x6f, 0xa6, 0x6f, 0xd5, 0xef, 0xdc, 0xe6, 0xc6, 0x4f, 0x8d, 0x91, 0x88, 0xcd, + 0x1c, 0x3f, 0x32, 0x36, 0x73, 0x59, 0xd0, 0x66, 0xd2, 0xf2, 0x1d, 0x65, 0xb2, 0x76, 0x55, 0xd1, + 0x65, 0x65, 0x87, 0x9e, 0x5d, 0x74, 0xcd, 0xac, 0x28, 0xd6, 0xd2, 0x8f, 0x2f, 0x8a, 0xd5, 0xbe, + 0x0b, 0x33, 0xa9, 0xfe, 0x53, 0x46, 0x29, 0x2b, 0xdb, 0x28, 0x75, 0xbc, 0xa7, 0xf1, 0xfe, 0xa9, + 0x05, 0xe7, 0xfa, 0x56, 0xa4, 0xe3, 0x86, 0x13, 0xa7, 0xf7, 0xc6, 0x91, 0xd3, 0xef, 0x8d, 0x85, + 0x93, 0xed, 0x8d, 0xb5, 0xcd, 0xef, 0xfe, 0xe0, 0xf2, 0x07, 0xbe, 0xf7, 0x83, 0xcb, 0x1f, 0xf8, + 0xfd, 0x1f, 0x5c, 0xfe, 0xc0, 0x3b, 0x07, 0x97, 0xad, 0xef, 0x1e, 0x5c, 0xb6, 0xbe, 0x77, 0x70, + 0xd9, 0xfa, 0xfd, 0x83, 0xcb, 0xd6, 0x7f, 0x3e, 0xb8, 0x6c, 0x7d, 0xf3, 0x8f, 0x2e, 0x7f, 0xe0, + 0x53, 0x9f, 0x88, 0x7b, 0x6a, 0x51, 0xf5, 0x14, 0xff, 0xf1, 0x61, 0xd5, 0x2f, 0x8b, 0xdd, 0x9d, + 0xd6, 0x22, 0xeb, 0xa9, 0x45, 0x5d, 0xa2, 0x7a, 0xea, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x46, + 0x26, 0x31, 0x21, 0xd3, 0xa9, 0x00, 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -5321,6 +5389,20 @@ func (m *CanaryStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.StepPluginStatuses) > 0 { + for iNdEx := len(m.StepPluginStatuses) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.StepPluginStatuses[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } i -= len(m.StablePingPong) copy(dAtA[i:], m.StablePingPong) i = encodeVarintGenerated(dAtA, i, uint64(len(m.StablePingPong))) @@ -5390,6 +5472,18 @@ func (m *CanaryStep) 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] = 0x4a + } if m.SetMirrorRoute != nil { { size, err := m.SetMirrorRoute.MarshalToSizedBuffer(dAtA[:i]) @@ -7855,6 +7949,49 @@ func (m *PingPongSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PluginStep) 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 *PluginStep) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PluginStep) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i-- + if m.AbortOnFailure { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + if m.Config != nil { + i -= len(m.Config) + copy(dAtA[i:], m.Config) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Config))) + i-- + dAtA[i] = 0x12 + } + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *PodTemplateMetadata) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -9702,6 +9839,78 @@ func (m *SkyWalkingMetric) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *StepPluginStatus) 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 *StepPluginStatus) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Status != nil { + i -= len(m.Status) + copy(dAtA[i:], m.Status) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status))) + i-- + dAtA[i] = 0x3a + } + if m.FinishedAt != nil { + { + size, err := m.FinishedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if m.StartedAt != nil { + { + size, err := m.StartedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0x22 + i -= len(m.Phase) + copy(dAtA[i:], m.Phase) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Phase))) + i-- + dAtA[i] = 0x1a + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + i = encodeVarintGenerated(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x8 + return len(dAtA) - i, nil +} + func (m *StickinessConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10939,6 +11148,12 @@ func (m *CanaryStatus) Size() (n int) { } l = len(m.StablePingPong) n += 1 + l + sovGenerated(uint64(l)) + if len(m.StepPluginStatuses) > 0 { + for _, e := range m.StepPluginStatuses { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -10975,6 +11190,10 @@ func (m *CanaryStep) Size() (n int) { l = m.SetMirrorRoute.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Plugin != nil { + l = m.Plugin.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -11865,19 +12084,35 @@ func (m *PingPongSpec) Size() (n int) { return n } -func (m *PodTemplateMetadata) Size() (n int) { +func (m *PluginStep) Size() (n int) { if m == nil { return 0 } var l int _ = l - if len(m.Labels) > 0 { - for k, v := range m.Labels { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) - n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) - } + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + if m.Config != nil { + l = len(m.Config) + n += 1 + l + sovGenerated(uint64(l)) + } + n += 2 + return n +} + +func (m *PodTemplateMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Labels) > 0 { + for k, v := range m.Labels { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } } if len(m.Annotations) > 0 { for k, v := range m.Annotations { @@ -12531,6 +12766,34 @@ func (m *SkyWalkingMetric) Size() (n int) { return n } +func (m *StepPluginStatus) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovGenerated(uint64(m.Index)) + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Phase) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Message) + n += 1 + l + sovGenerated(uint64(l)) + if m.StartedAt != nil { + l = m.StartedAt.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.FinishedAt != nil { + l = m.FinishedAt.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.Status != nil { + l = len(m.Status) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *StickinessConfig) Size() (n int) { if m == nil { return 0 @@ -13192,12 +13455,18 @@ func (this *CanaryStatus) String() string { if this == nil { return "nil" } + repeatedStringForStepPluginStatuses := "[]StepPluginStatus{" + for _, f := range this.StepPluginStatuses { + repeatedStringForStepPluginStatuses += strings.Replace(strings.Replace(f.String(), "StepPluginStatus", "StepPluginStatus", 1), `&`, ``, 1) + "," + } + repeatedStringForStepPluginStatuses += "}" s := strings.Join([]string{`&CanaryStatus{`, `CurrentStepAnalysisRunStatus:` + strings.Replace(this.CurrentStepAnalysisRunStatus.String(), "RolloutAnalysisRunStatus", "RolloutAnalysisRunStatus", 1) + `,`, `CurrentBackgroundAnalysisRunStatus:` + strings.Replace(this.CurrentBackgroundAnalysisRunStatus.String(), "RolloutAnalysisRunStatus", "RolloutAnalysisRunStatus", 1) + `,`, `CurrentExperiment:` + fmt.Sprintf("%v", this.CurrentExperiment) + `,`, `Weights:` + strings.Replace(this.Weights.String(), "TrafficWeights", "TrafficWeights", 1) + `,`, `StablePingPong:` + fmt.Sprintf("%v", this.StablePingPong) + `,`, + `StepPluginStatuses:` + repeatedStringForStepPluginStatuses + `,`, `}`, }, "") return s @@ -13214,6 +13483,7 @@ func (this *CanaryStep) String() string { `SetCanaryScale:` + strings.Replace(this.SetCanaryScale.String(), "SetCanaryScale", "SetCanaryScale", 1) + `,`, `SetHeaderRoute:` + strings.Replace(this.SetHeaderRoute.String(), "SetHeaderRoute", "SetHeaderRoute", 1) + `,`, `SetMirrorRoute:` + strings.Replace(this.SetMirrorRoute.String(), "SetMirrorRoute", "SetMirrorRoute", 1) + `,`, + `Plugin:` + strings.Replace(this.Plugin.String(), "PluginStep", "PluginStep", 1) + `,`, `}`, }, "") return s @@ -13891,6 +14161,18 @@ func (this *PingPongSpec) String() string { }, "") return s } +func (this *PluginStep) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PluginStep{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Config:` + valueToStringGenerated(this.Config) + `,`, + `AbortOnFailure:` + fmt.Sprintf("%v", this.AbortOnFailure) + `,`, + `}`, + }, "") + return s +} func (this *PodTemplateMetadata) String() string { if this == nil { return "nil" @@ -14415,6 +14697,22 @@ func (this *SkyWalkingMetric) String() string { }, "") return s } +func (this *StepPluginStatus) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&StepPluginStatus{`, + `Index:` + fmt.Sprintf("%v", this.Index) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Phase:` + fmt.Sprintf("%v", this.Phase) + `,`, + `Message:` + fmt.Sprintf("%v", this.Message) + `,`, + `StartedAt:` + strings.Replace(fmt.Sprintf("%v", this.StartedAt), "Time", "v1.Time", 1) + `,`, + `FinishedAt:` + strings.Replace(fmt.Sprintf("%v", this.FinishedAt), "Time", "v1.Time", 1) + `,`, + `Status:` + valueToStringGenerated(this.Status) + `,`, + `}`, + }, "") + return s +} func (this *StickinessConfig) String() string { if this == nil { return "nil" @@ -19027,6 +19325,40 @@ func (m *CanaryStatus) Unmarshal(dAtA []byte) error { } m.StablePingPong = PingPongType(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StepPluginStatuses", 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 + } + m.StepPluginStatuses = append(m.StepPluginStatuses, StepPluginStatus{}) + if err := m.StepPluginStatuses[len(m.StepPluginStatuses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -19313,6 +19645,42 @@ func (m *CanaryStep) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 9: + 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 = &PluginStep{} + } + if err := m.Plugin.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -27272,7 +27640,7 @@ func (m *PingPongSpec) Unmarshal(dAtA []byte) error { } return nil } -func (m *PodTemplateMetadata) Unmarshal(dAtA []byte) error { +func (m *PluginStep) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -27295,17 +27663,17 @@ func (m *PodTemplateMetadata) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: PodTemplateMetadata: wiretype end group for non-group") + return fmt.Errorf("proto: PluginStep: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: PodTemplateMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: PluginStep: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -27315,124 +27683,29 @@ func (m *PodTemplateMetadata) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthGenerated } if postIndex > l { return io.ErrUnexpectedEOF } - if m.Labels == nil { - m.Labels = make(map[string]string) - } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := 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) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLengthGenerated - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthGenerated - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue < 0 { - return ErrInvalidLengthGenerated - } - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.Labels[mapkey] = mapvalue + m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Config", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -27442,26 +27715,257 @@ func (m *PodTemplateMetadata) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthGenerated } if postIndex > l { return io.ErrUnexpectedEOF } - if m.Annotations == nil { - m.Annotations = make(map[string]string) + m.Config = append(m.Config[:0], dAtA[iNdEx:postIndex]...) + if m.Config == nil { + m.Config = []byte{} } - var mapkey string - var mapvalue string + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AbortOnFailure", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AbortOnFailure = bool(v != 0) + 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 + 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: PodTemplateMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodTemplateMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Labels", 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.Labels == nil { + m.Labels = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := 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) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Labels[mapkey] = mapvalue + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", 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.Annotations == nil { + m.Annotations = make(map[string]string) + } + var mapkey string + var mapvalue string for iNdEx < postIndex { entryPreIndex := iNdEx var wire uint64 @@ -33124,6 +33628,277 @@ func (m *SkyWalkingMetric) Unmarshal(dAtA []byte) error { } return nil } +func (m *StepPluginStatus) 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: StepPluginStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StepPluginStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Phase", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Phase = StepPluginPhase(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Message = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StartedAt", 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.StartedAt == nil { + m.StartedAt = &v1.Time{} + } + if err := m.StartedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FinishedAt", 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.FinishedAt == nil { + m.FinishedAt = &v1.Time{} + } + if err := m.FinishedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", 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.Status = append(m.Status[:0], dAtA[iNdEx:postIndex]...) + if m.Status == nil { + m.Status = []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 *StickinessConfig) 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 6e225848b9..e43255cc07 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -433,6 +433,9 @@ message CanaryStatus { // StablePingPong For the ping-pong feature holds the current stable service, ping or pong optional string stablePingPong = 5; + + // StepPluginStatuses Hold the status of the step plugins executed + repeated StepPluginStatus stepPluginStatuses = 6; } // CanaryStep defines a step of a canary deployment. @@ -462,6 +465,9 @@ message CanaryStep { // SetMirrorRoutes Mirrors traffic that matches rules to a particular destination // +optional optional SetMirrorRoute setMirrorRoute = 8; + + // Plugin defines a plugin to execute for a step + optional PluginStep plugin = 9; } // CanaryStrategy defines parameters for a Replica Based Canary @@ -1163,6 +1169,19 @@ message PingPongSpec { optional string pongService = 2; } +message PluginStep { + // Name the name of the hashicorp go-plugin step to query + optional string name = 1; + + optional bool abortOnFailure = 3; + + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Type=object + // Config the configuration object for the specified plugin + optional bytes config = 2; +} + // PodTemplateMetadata extra labels to add to the template message PodTemplateMetadata { // Labels Additional labels to add to the experiment @@ -1732,6 +1751,22 @@ message SkyWalkingMetric { optional string interval = 3; } +message StepPluginStatus { + optional int32 index = 1; + + optional string name = 2; + + optional string phase = 3; + + optional string message = 4; + + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 5; + + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 6; + + optional bytes status = 7; +} + message StickinessConfig { optional bool enabled = 1; diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 32b8441689..57f00caeb1 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -636,6 +636,22 @@ type CanaryStep struct { // SetMirrorRoutes Mirrors traffic that matches rules to a particular destination // +optional SetMirrorRoute *SetMirrorRoute `json:"setMirrorRoute,omitempty" protobuf:"bytes,8,opt,name=setMirrorRoute"` + // Plugin defines a plugin to execute for a step + Plugin *PluginStep `json:"plugin,omitempty" protobuf:"bytes,9,opt,name=plugin"` +} + +type PluginStep struct { + // Name the name of the hashicorp go-plugin step to query + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + + AbortOnFailure bool + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Type=object + // Config the configuration object for the specified plugin + Config json.RawMessage `json:"config,omitempty" protobuf:"bytes,2,opt,name=config"` + + // json.RawMessage `json:"config,omitempty" protobuf:"bytes,2,opt,name=config"` } type SetMirrorRoute struct { @@ -984,6 +1000,8 @@ type CanaryStatus struct { Weights *TrafficWeights `json:"weights,omitempty" protobuf:"bytes,4,opt,name=weights"` // StablePingPong For the ping-pong feature holds the current stable service, ping or pong StablePingPong PingPongType `json:"stablePingPong,omitempty" protobuf:"bytes,5,opt,name=stablePingPong"` + // StepPluginStatuses Hold the status of the step plugins executed + StepPluginStatuses []StepPluginStatus `json:"stepPluginStatuses,omitempty" protobuf:"bytes,6,rep,name=stepPluginStatuses"` } type PingPongType string @@ -1021,6 +1039,27 @@ type RolloutAnalysisRunStatus struct { Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"` } +type StepPluginStatus struct { + Index int32 `json:"index" protobuf:"bytes,1,opt,name=index"` + Name string `json:"name" protobuf:"bytes,2,opt,name=name"` + Phase StepPluginPhase `json:"phase" protobuf:"bytes,3,opt,name=phase"` + Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"` + StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,5,opt,name=startedAt"` + FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,6,opt,name=finishedAt"` + Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,7,opt,name=status"` +} + +// StepPluginPhase is the overall phase of a StepPlugin +type StepPluginPhase string + +// Possible StepPluginPhase values +const ( + StepPluginPhaseRunning StepPluginPhase = "Running" + StepPluginPhaseSuccessful StepPluginPhase = "Successful" + StepPluginPhaseFailed StepPluginPhase = "Failed" + StepPluginPhaseError StepPluginPhase = "Error" +) + type ALBStatus struct { LoadBalancer AwsResourceRef `json:"loadBalancer,omitempty" protobuf:"bytes,1,opt,name=loadBalancer"` CanaryTargetGroup AwsResourceRef `json:"canaryTargetGroup,omitempty" protobuf:"bytes,2,opt,name=canaryTargetGroup"` diff --git a/pkg/apis/rollouts/validation/validation.go b/pkg/apis/rollouts/validation/validation.go index 9bb3f24af6..dd34db596d 100644 --- a/pkg/apis/rollouts/validation/validation.go +++ b/pkg/apis/rollouts/validation/validation.go @@ -48,8 +48,8 @@ const ( InvalidDurationMessage = "Duration needs to be greater than 0" // InvalidMaxSurgeMaxUnavailable indicates both maxSurge and MaxUnavailable can not be set to zero InvalidMaxSurgeMaxUnavailable = "MaxSurge and MaxUnavailable both can not be zero" - // InvalidStepMessage indicates that a step must have either setWeight or pause set - InvalidStepMessage = "Step must have one of the following set: experiment, setWeight, setCanaryScale or pause" + // InvalidStepMessage indicates that a step must have either experiment, setWeight, setCanaryScale, plugin or pause + InvalidStepMessage = "Step must have one of the following set: experiment, setWeight, setCanaryScale, plugin or pause" // InvalidStrategyMessage indicates that multiple strategies can not be listed InvalidStrategyMessage = "Multiple Strategies can not be listed" // DuplicatedServicesBlueGreenMessage the message to indicate that the rollout uses the same service for the active and preview services @@ -310,9 +310,9 @@ func ValidateRolloutStrategyCanary(rollout *v1alpha1.Rollout, fldPath *field.Pat stepFldPath := fldPath.Child("steps").Index(i) allErrs = append(allErrs, hasMultipleStepsType(step, stepFldPath)...) if step.Experiment == nil && step.Pause == nil && step.SetWeight == nil && step.Analysis == nil && step.SetCanaryScale == nil && - step.SetHeaderRoute == nil && step.SetMirrorRoute == nil { - errVal := fmt.Sprintf("step.Experiment: %t step.Pause: %t step.SetWeight: %t step.Analysis: %t step.SetCanaryScale: %t step.SetHeaderRoute: %t step.SetMirrorRoutes: %t", - step.Experiment == nil, step.Pause == nil, step.SetWeight == nil, step.Analysis == nil, step.SetCanaryScale == nil, step.SetHeaderRoute == nil, step.SetMirrorRoute == nil) + step.SetHeaderRoute == nil && step.SetMirrorRoute == nil && step.Plugin == nil { + errVal := fmt.Sprintf("step.Experiment: %t step.Pause: %t step.SetWeight: %t step.Analysis: %t step.SetCanaryScale: %t step.SetHeaderRoute: %t step.SetMirrorRoutes: %t step.SetMirrorRoutes: %t", + step.Experiment == nil, step.Pause == nil, step.SetWeight == nil, step.Analysis == nil, step.SetCanaryScale == nil, step.SetHeaderRoute == nil, step.SetMirrorRoute == nil, step.Plugin == nil) allErrs = append(allErrs, field.Invalid(stepFldPath, errVal, InvalidStepMessage)) } diff --git a/rollout/canary.go b/rollout/canary.go index ed27bd0a79..3826cd2637 100644 --- a/rollout/canary.go +++ b/rollout/canary.go @@ -87,6 +87,11 @@ func (c *rolloutContext) rolloutCanary() error { return c.syncRolloutStatusCanary() } + err = c.reconcileCanaryPluginStep() + if err != nil { + return err + } + return c.syncRolloutStatusCanary() } @@ -315,7 +320,7 @@ func (c *rolloutContext) completedCurrentCanaryStep() bool { if c.rollout.Spec.Paused { return false } - currentStep, _ := replicasetutil.GetCurrentCanaryStep(c.rollout) + currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) if currentStep == nil { return false } @@ -344,6 +349,8 @@ func (c *rolloutContext) completedCurrentCanaryStep() bool { return true case currentStep.SetMirrorRoute != nil: return true + case currentStep.Plugin != nil: + return c.isPluginStepCompleted(*currentStepIndex) } return false } diff --git a/rollout/controller.go b/rollout/controller.go index 1d7d8cde92..e9f8b11c70 100644 --- a/rollout/controller.go +++ b/rollout/controller.go @@ -42,6 +42,7 @@ import ( clientset "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned" informers "github.com/argoproj/argo-rollouts/pkg/client/informers/externalversions/rollouts/v1alpha1" listers "github.com/argoproj/argo-rollouts/pkg/client/listers/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin" "github.com/argoproj/argo-rollouts/rollout/trafficrouting" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/ambassador" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/appmesh" @@ -112,6 +113,7 @@ type ControllerConfig struct { IngressWorkQueue workqueue.RateLimitingInterface MetricsServer *metrics.MetricsServer Recorder record.EventRecorder + StepPluginResolver plugin.Resolver } // reconcilerBase is a shared datastructure containing all clients and configuration necessary to @@ -126,7 +128,8 @@ type reconcilerBase struct { dynamicclientset dynamic.Interface smiclientset smiclientset.Interface - refResolver TemplateRefResolver + refResolver TemplateRefResolver + stepPluginResolver plugin.Resolver replicaSetLister appslisters.ReplicaSetLister replicaSetSynced cache.InformerSynced @@ -199,6 +202,7 @@ func NewController(cfg ControllerConfig) *Controller { resyncPeriod: cfg.ResyncPeriod, podRestarter: podRestarter, refResolver: cfg.RefResolver, + stepPluginResolver: cfg.StepPluginResolver, } controller := &Controller{ diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go new file mode 100644 index 0000000000..1f6619cf79 --- /dev/null +++ b/rollout/stepplugin.go @@ -0,0 +1,72 @@ +package rollout + +import ( + "fmt" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + replicasetutil "github.com/argoproj/argo-rollouts/utils/replicaset" +) + +func (c *rolloutContext) reconcileCanaryPluginStep() error { + currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) + if currentStep == nil || currentStep.Plugin == nil { + return nil + } + + stepPlugin, err := c.stepPluginResolver.Resolve(*currentStepIndex, *currentStep.Plugin) + if err != nil { + return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) + } + + status, result, err := stepPlugin.Run(c.rollout) + if err != nil { + return fmt.Errorf("TODO") + } + + // Update new status and preserve order + pluginStatuses := []v1alpha1.StepPluginStatus{} + statusAdded := false + for _, s := range c.rollout.Status.Canary.StepPluginStatuses { + if s.Index == *currentStepIndex { + pluginStatuses = append(pluginStatuses, *status) + statusAdded = true + continue + } + pluginStatuses = append(pluginStatuses, s) + } + if !statusAdded { + pluginStatuses = append(pluginStatuses, *status) + } + c.newStatus.Canary.StepPluginStatuses = pluginStatuses + + if status.Phase == v1alpha1.StepPluginPhaseRunning && result.RequeueAfter != nil { + c.enqueueRolloutAfter(c.rollout, *result.RequeueAfter) + } + + if status.Phase == v1alpha1.StepPluginPhaseFailed { + c.pauseContext.AddAbort(status.Message) + // Call each plugin in reverse order? + } + + if status.Phase == v1alpha1.StepPluginPhaseError { + c.persistRolloutStatus(&c.newStatus) + } + + return nil +} + +func (c *rolloutContext) isPluginStepCompleted(stepIndex int32) bool { + status := findCurrentStepStatus(c.rollout.Status.Canary.StepPluginStatuses, stepIndex) + return status != nil && (status.Phase == v1alpha1.StepPluginPhaseSuccessful || + status.Phase == v1alpha1.StepPluginPhaseFailed || + status.Phase == v1alpha1.StepPluginPhaseError) +} + +func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32) *v1alpha1.StepPluginStatus { + for _, s := range status { + if s.Index == stepIndex { + return &s + } + } + return nil +} diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go new file mode 100644 index 0000000000..e98571ca7f --- /dev/null +++ b/rollout/stepplugin_test.go @@ -0,0 +1,186 @@ +package rollout + +import ( + "encoding/json" + "testing" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/mocks" + logutil "github.com/argoproj/argo-rollouts/utils/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/pointer" +) + +func newStepPluginRollout() *v1alpha1.Rollout { + steps := []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + } + return newCanaryRollout("foo", 3, nil, steps, pointer.Int32(0), intstr.FromInt(1), intstr.FromInt(0)) +} + +func newStepPluginStatus() *v1alpha1.StepPluginStatus { + return &v1alpha1.StepPluginStatus{ + Index: 0, + Name: "test-plugin", + Status: json.RawMessage("value"), + } +} + +func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { + setup := func(t *testing.T) (*rolloutContext, *v1alpha1.StepPluginStatus) { + stepPluginResolver := mocks.NewResolver(t) + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything).Return(stepPluginMock, nil) + + r := newStepPluginRollout() + roCtx := &rolloutContext{ + rollout: r, + log: logutil.WithRollout(r), + reconcilerBase: reconcilerBase{ + stepPluginResolver: stepPluginResolver, + }, + } + + runStatus := newStepPluginStatus() + stepPluginMock.On("Run", r).Return(runStatus, nil, nil) + runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + return roCtx, runStatus + } + + t.Run("Status is added when not present", func(t *testing.T) { + roCtx, runStatus := setup(t) + runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + }) + t.Run("Status is updated when existing", func(t *testing.T) { + roCtx, runStatus := setup(t) + runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + + existingStatus := runStatus.DeepCopy() + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{} + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + }) +} + +//Controller: +// Add test for plugin config +// Add InitPlugin call test + +//Reconcile: +// Add disable feature + +//RPC: +// Test config +// Test state on first tun +// Test state with existing + +// if running || failed || success, state saved +// if running, requeue after +// if failed, abort +// if success, next step, else current step + +//if run error, save message+phase, but not state + +//When promote-full, terminate called on current step +//When abort, abort all steps? validate status? validate order + +//error during run? +//error during abort? +//error during terminate? safe to ignore? + +// cannot modify ptr reference of rollout input object + +//input rollout contains all plugin status state + +// Helper: write helper functions? + +func TestReconcileCanaryPluginStep(t *testing.T) { + t.Run("The plugin is skippped if it is disabled globally", func(t *testing.T) { + t.Fail() + }) + + t.Run("The plugin receives the Rollout user configuration", func(t *testing.T) { + + t.Fail() + }) + + t.Run("The plugin receives an empty state the first time it is executed", func(t *testing.T) { + + t.Fail() + }) + + t.Run("The plugin receives the existing state if it is present", func(t *testing.T) { + + t.Fail() + }) +} + +// func Test_rolloutContext_reconcileCanaryPluginStep(t *testing.T) { +// type fields struct { +// reconcilerBase reconcilerBase +// log *log.Entry +// rollout *v1alpha1.Rollout +// newRollout *v1alpha1.Rollout +// newRS *appsv1.ReplicaSet +// stableRS *appsv1.ReplicaSet +// allRSs []*appsv1.ReplicaSet +// olderRSs []*appsv1.ReplicaSet +// otherRSs []*appsv1.ReplicaSet +// currentArs analysisutil.CurrentAnalysisRuns +// otherArs []*v1alpha1.AnalysisRun +// currentEx *v1alpha1.Experiment +// otherExs []*v1alpha1.Experiment +// newStatus v1alpha1.RolloutStatus +// pauseContext *pauseContext +// targetsVerified *bool +// } +// tests := []struct { +// name string +// fields fields +// wantErr bool +// }{ +// // TODO: Add test cases. +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// c := &rolloutContext{ +// reconcilerBase: tt.fields.reconcilerBase, +// log: tt.fields.log, +// rollout: tt.fields.rollout, +// newRollout: tt.fields.newRollout, +// newRS: tt.fields.newRS, +// stableRS: tt.fields.stableRS, +// allRSs: tt.fields.allRSs, +// olderRSs: tt.fields.olderRSs, +// otherRSs: tt.fields.otherRSs, +// currentArs: tt.fields.currentArs, +// otherArs: tt.fields.otherArs, +// currentEx: tt.fields.currentEx, +// otherExs: tt.fields.otherExs, +// newStatus: tt.fields.newStatus, +// pauseContext: tt.fields.pauseContext, +// targetsVerified: tt.fields.targetsVerified, +// } +// if err := c.reconcileCanaryPluginStep(); (err != nil) != tt.wantErr { +// t.Errorf("rolloutContext.reconcileCanaryPluginStep() error = %v, wantErr %v", err, tt.wantErr) +// } +// }) +// } +// } diff --git a/rollout/steps/plugin/client/client.go b/rollout/steps/plugin/client/client.go new file mode 100644 index 0000000000..bb19ec9ab1 --- /dev/null +++ b/rollout/steps/plugin/client/client.go @@ -0,0 +1,101 @@ +package client + +import ( + "fmt" + "os/exec" + "sync" + + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/utils/plugin" + goPlugin "github.com/hashicorp/go-plugin" +) + +type stepPlugin struct { + client map[string]*goPlugin.Client + plugin map[string]rpc.StepPlugin +} + +var pluginClients *stepPlugin +var once sync.Once +var mutex sync.Mutex + +var handshakeConfig = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "step", +} + +// pluginMap is the map of plugins we can dispense. +var pluginMap = map[string]goPlugin.Plugin{ + "RpcStepPlugin": &rpc.RpcStepPlugin{}, +} + +// GetPlugin returns a singleton plugin client for the given plugin. Calling this multiple times +// returns the same plugin client instance for the plugin name defined in the rollout object. +func GetPlugin(pluginName string) (rpc.StepPlugin, error) { + once.Do(func() { + pluginClients = &stepPlugin{ + client: make(map[string]*goPlugin.Client), + plugin: make(map[string]rpc.StepPlugin), + } + }) + plugin, err := pluginClients.startPlugin(pluginName) + if err != nil { + return nil, fmt.Errorf("unable to start plugin system: %w", err) + } + return plugin, nil +} + +func (t *stepPlugin) startPlugin(pluginName string) (rpc.StepPlugin, error) { + mutex.Lock() + defer mutex.Unlock() + + if t.client[pluginName] == nil || t.client[pluginName].Exited() { + + pluginPath, args, err := plugin.GetPluginInfo(pluginName) + if err != nil { + return nil, fmt.Errorf("unable to find plugin (%s): %w", pluginName, err) + } + + t.client[pluginName] = goPlugin.NewClient(&goPlugin.ClientConfig{ + HandshakeConfig: handshakeConfig, + Plugins: pluginMap, + Cmd: exec.Command(pluginPath, args...), + Managed: true, + }) + + rpcClient, err := t.client[pluginName].Client() + if err != nil { + return nil, fmt.Errorf("unable to get plugin client (%s): %w", pluginName, err) + } + + // Request the plugin + plugin, err := rpcClient.Dispense("RpcStepPlugin") + if err != nil { + return nil, fmt.Errorf("unable to dispense plugin (%s): %w", pluginName, err) + } + + pluginType, ok := plugin.(rpc.StepPlugin) + if !ok { + return nil, fmt.Errorf("unexpected type from plugin") + } + t.plugin[pluginName] = pluginType + + resp := t.plugin[pluginName].InitPlugin() + if resp.HasError() { + return nil, fmt.Errorf("unable to initialize plugin via rpc (%s): %w", pluginName, resp) + } + } + + client, err := t.client[pluginName].Client() + if err != nil { + return nil, fmt.Errorf("unable to get plugin client (%s) for ping: %w", pluginName, err) + } + if err := client.Ping(); err != nil { + t.client[pluginName].Kill() + t.client[pluginName] = nil + return nil, fmt.Errorf("could not ping plugin will cleanup process so we can restart it next reconcile (%w)", err) + } + + return t.plugin[pluginName], nil +} diff --git a/rollout/steps/plugin/mocks/Resolver.go b/rollout/steps/plugin/mocks/Resolver.go new file mode 100644 index 0000000000..dcd198f3b0 --- /dev/null +++ b/rollout/steps/plugin/mocks/Resolver.go @@ -0,0 +1,54 @@ +// Code generated by mockery v2.32.0. DO NOT EDIT. + +package mocks + +import ( + v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + plugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" + mock "github.com/stretchr/testify/mock" +) + +// Resolver is an autogenerated mock type for the Resolver type +type Resolver struct { + mock.Mock +} + +// Resolve provides a mock function with given fields: index, _a1 +func (_m *Resolver) Resolve(index int32, _a1 v1alpha1.PluginStep) (plugin.StepPlugin, error) { + ret := _m.Called(index, _a1) + + var r0 plugin.StepPlugin + var r1 error + if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep) (plugin.StepPlugin, error)); ok { + return rf(index, _a1) + } + if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep) plugin.StepPlugin); ok { + r0 = rf(index, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(plugin.StepPlugin) + } + } + + if rf, ok := ret.Get(1).(func(int32, v1alpha1.PluginStep) error); ok { + r1 = rf(index, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewResolver creates a new instance of Resolver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResolver(t interface { + mock.TestingT + Cleanup(func()) +}) *Resolver { + mock := &Resolver{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/rollout/steps/plugin/mocks/StepPlugin.go b/rollout/steps/plugin/mocks/StepPlugin.go new file mode 100644 index 0000000000..0bc8884ce9 --- /dev/null +++ b/rollout/steps/plugin/mocks/StepPlugin.go @@ -0,0 +1,115 @@ +// Code generated by mockery v2.32.0. DO NOT EDIT. + +package mocks + +import ( + v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + plugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" + mock "github.com/stretchr/testify/mock" +) + +// StepPlugin is an autogenerated mock type for the StepPlugin type +type StepPlugin struct { + mock.Mock +} + +// Abort provides a mock function with given fields: _a0 +func (_m *StepPlugin) Abort(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + ret := _m.Called(_a0) + + var r0 *v1alpha1.StepPluginStatus + var r1 error + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) *v1alpha1.StepPluginStatus); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1alpha1.StepPluginStatus) + } + } + + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Run provides a mock function with given fields: _a0 +func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *plugin.StepResult, error) { + ret := _m.Called(_a0) + + var r0 *v1alpha1.StepPluginStatus + var r1 *plugin.StepResult + var r2 error + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *plugin.StepResult, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) *v1alpha1.StepPluginStatus); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1alpha1.StepPluginStatus) + } + } + + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout) *plugin.StepResult); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*plugin.StepResult) + } + } + + if rf, ok := ret.Get(2).(func(*v1alpha1.Rollout) error); ok { + r2 = rf(_a0) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// Terminate provides a mock function with given fields: _a0 +func (_m *StepPlugin) Terminate(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + ret := _m.Called(_a0) + + var r0 *v1alpha1.StepPluginStatus + var r1 error + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) *v1alpha1.StepPluginStatus); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1alpha1.StepPluginStatus) + } + } + + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewStepPlugin creates a new instance of StepPlugin. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStepPlugin(t interface { + mock.TestingT + Cleanup(func()) +}) *StepPlugin { + mock := &StepPlugin{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go new file mode 100644 index 0000000000..907ce668c6 --- /dev/null +++ b/rollout/steps/plugin/plugin.go @@ -0,0 +1,107 @@ +package plugin + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + metatime "github.com/argoproj/argo-rollouts/utils/time" +) + +type stepPlugin struct { + rpc rpc.StepPlugin + index int32 + name string + config json.RawMessage +} + +type StepResult struct { + RequeueAfter *time.Duration +} + +type StepPlugin interface { + Run(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *StepResult, error) + Terminate(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) + Abort(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) +} + +var ( + minRequeueDuration = time.Second * 10 + defaultRequeuDuration = time.Second * 30 +) + +// Run exectues a plugin +func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *StepResult, error) { + result := &StepResult{} + + stepStatus := p.getStepStatus(rollout) + if stepStatus == nil { + now := metatime.MetaNow() + stepStatus = &v1alpha1.StepPluginStatus{ + Index: p.index, + Name: p.name, + StartedAt: &now, + Phase: v1alpha1.StepPluginPhaseRunning, + } + } + resp, err := p.rpc.Run(rollout.DeepCopy(), p.getStepContext(stepStatus)) + finishedAt := metatime.MetaNow() + if err.HasError() { + stepStatus.Phase = v1alpha1.StepPluginPhaseError + stepStatus.Message = err.Error() + stepStatus.FinishedAt = &finishedAt + // return err nil ? + return stepStatus, result, fmt.Errorf("failed to run step via plugin: %w", err) + } + + stepStatus.Message = resp.Message + if resp.Phase != "" { + stepStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + } + // validate phase or Error + if stepStatus.Phase == v1alpha1.StepPluginPhaseSuccessful || stepStatus.Phase == v1alpha1.StepPluginPhaseFailed { + stepStatus.FinishedAt = &finishedAt + } + + stepStatus.Status = resp.Status + + if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { + result.RequeueAfter = &defaultRequeuDuration + if resp.RequeueAfter > minRequeueDuration { + result.RequeueAfter = &resp.RequeueAfter + } + } + + return stepStatus, result, nil +} + +func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, fmt.Errorf("Not implemented") +} +func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, fmt.Errorf("Not implemented") +} + +func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout) *v1alpha1.StepPluginStatus { + for _, s := range rollout.Status.Canary.StepPluginStatuses { + if s.Index == p.index && s.Name == p.name { + return &s + } + } + return nil +} + +func (p *stepPlugin) getStepContext(stepStatus *v1alpha1.StepPluginStatus) *types.RpcStepContext { + var status json.RawMessage = nil + if stepStatus != nil { + status = stepStatus.Status + } + return &types.RpcStepContext{ + PluginName: p.name, + Config: p.config, + Status: status, + } +} diff --git a/rollout/steps/plugin/resolver.go b/rollout/steps/plugin/resolver.go new file mode 100644 index 0000000000..c1f328aaaa --- /dev/null +++ b/rollout/steps/plugin/resolver.go @@ -0,0 +1,32 @@ +package plugin + +import ( + "fmt" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/client" +) + +type resolver struct{} + +type Resolver interface { + Resolve(index int32, plugin v1alpha1.PluginStep) (StepPlugin, error) +} + +func NewResolver() Resolver { + return &resolver{} +} + +func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep) (StepPlugin, error) { + pluginClient, err := client.GetPlugin(plugin.Name) + if err != nil { + return nil, fmt.Errorf("failed to get step plugin %s: %w", plugin.Name, err) + } + + return &stepPlugin{ + rpc: pluginClient, + index: index, + name: plugin.Name, + config: plugin.Config, + }, nil +} diff --git a/rollout/steps/plugin/rpc/rpc.go b/rollout/steps/plugin/rpc/rpc.go new file mode 100644 index 0000000000..56f4ff6989 --- /dev/null +++ b/rollout/steps/plugin/rpc/rpc.go @@ -0,0 +1,197 @@ +package rpc + +import ( + "encoding/gob" + "fmt" + "net/rpc" + + "github.com/argoproj/argo-rollouts/utils/plugin/types" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/hashicorp/go-plugin" +) + +type RunArgs struct { + Rollout *v1alpha1.Rollout + Context types.RpcStepContext +} + +type TerminateArgs struct { + Rollout *v1alpha1.Rollout + Context types.RpcStepContext +} + +type AbortArgs struct { + Rollout *v1alpha1.Rollout + Context types.RpcStepContext +} + +type Response struct { + Result types.RpcStepResult + Error types.RpcError +} + +func init() { + gob.RegisterName("step.RunArgs", new(RunArgs)) + gob.RegisterName("step.TerminateArgs", new(TerminateArgs)) + gob.RegisterName("step.AbortArgs", new(AbortArgs)) +} + +// StepPlugin 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 StepPlugin interface { + InitPlugin() types.RpcError + types.RpcStep +} + +// StepPluginRPC Here is an implementation that talks over RPC +type StepPluginRPC struct{ client *rpc.Client } + +// InitPlugin is the client aka the controller side function that calls the server side rpc (plugin) +// this gets called once during startup of the plugin and can be used to set up informers, k8s clients, etc. +func (g *StepPluginRPC) InitPlugin() types.RpcError { + var resp types.RpcError + err := g.client.Call("Plugin.InitPlugin", new(any), &resp) + if err != nil { + return types.RpcError{ErrorString: fmt.Sprintf("InitPlugin rpc call error: %s", err)} + } + return resp +} + +// Run executes the step +func (g *StepPluginRPC) Run(rollout *v1alpha1.Rollout, context types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + var resp Response + var args any = RunArgs{ + Rollout: rollout, + Context: context, + } + err := g.client.Call("Plugin.Run", &args, &resp) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Run rpc call error: %s", err)} + } + return resp.Result, resp.Error +} + +// Terminate stops the execution of a running step and exits early +func (g *StepPluginRPC) Terminate(rollout *v1alpha1.Rollout, context types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + var resp Response + var args any = TerminateArgs{ + Rollout: rollout, + Context: context, + } + err := g.client.Call("Plugin.Terminate", &args, &resp) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Terminate rpc call error: %s", err)} + } + return resp.Result, resp.Error +} + +// Abort reverts previous operation executed by the step if necessary +func (g *StepPluginRPC) Abort(rollout *v1alpha1.Rollout, context types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + var resp Response + var args any = AbortArgs{ + Rollout: rollout, + Context: context, + } + err := g.client.Call("Plugin.Abort", &args, &resp) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Abort rpc call error: %s", err)} + } + return resp.Result, resp.Error +} + +// Type returns the type of the traffic routing reconciler +func (g *StepPluginRPC) Type() string { + var resp string + err := g.client.Call("Plugin.Type", new(any), &resp) + if err != nil { + return fmt.Sprintf("Type rpc call error: %s", err) + } + + return resp +} + +// StepRPCServer Here is the RPC server that MetricsPluginRPC talks to, conforming to +// the requirements of net/rpc +type StepRPCServer struct { + // This is the real implementation + Impl StepPlugin +} + +// InitPlugin this is the server aka the controller side function that receives calls from the client side rpc (controller) +// this gets called once during startup of the plugin and can be used to set up informers or k8s clients etc. +func (s *StepRPCServer) InitPlugin(args any, resp *types.RpcError) error { + *resp = s.Impl.InitPlugin() + return nil +} + +// Run executes the step +func (s *StepRPCServer) Run(args any, resp *Response) error { + runArgs, ok := args.(*RunArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + result, err := s.Impl.Run(runArgs.Rollout, &runArgs.Context) + *resp = Response{ + Result: result, + Error: err, + } + return nil +} + +// Terminate stops the execution of a running step and exits early +func (s *StepRPCServer) Terminate(args any, resp *Response) error { + runArgs, ok := args.(*TerminateArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + result, err := s.Impl.Terminate(runArgs.Rollout, &runArgs.Context) + *resp = Response{ + Result: result, + Error: err, + } + return nil +} + +// Abort reverts previous operation executed by the step if necessary +func (s *StepRPCServer) Abort(args any, resp *Response) error { + runArgs, ok := args.(*AbortArgs) + if !ok { + return fmt.Errorf("invalid args %s", args) + } + result, err := s.Impl.Abort(runArgs.Rollout, &runArgs.Context) + *resp = Response{ + Result: result, + Error: err, + } + return nil +} + +// Type returns the type of the traffic routing reconciler +func (s *StepRPCServer) Type(args any, resp *string) error { + *resp = s.Impl.Type() + return nil +} + +// RpcStepPlugin 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 StepRPCServer for this. +// +// Client must return an implementation of our interface that communicates +// over an RPC client. We return StepPluginRPC for this. +// +// Ignore MuxBroker. That is used to create more multiplexed streams on our +// plugin connection and is a more advanced use case. +type RpcStepPlugin struct { + // Impl Injection + Impl StepPlugin +} + +func (p *RpcStepPlugin) Server(*plugin.MuxBroker) (any, error) { + return &StepRPCServer{Impl: p.Impl}, nil +} + +func (RpcStepPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (any, error) { + return &StepPluginRPC{client: c}, nil +} diff --git a/rollout/steps/plugin/rpc/rpc_test.go b/rollout/steps/plugin/rpc/rpc_test.go new file mode 100644 index 0000000000..9469c17af9 --- /dev/null +++ b/rollout/steps/plugin/rpc/rpc_test.go @@ -0,0 +1,171 @@ +package rpc + +import ( + "context" + "testing" + "time" + + "github.com/argoproj/argo-rollouts/utils/plugin/types" + + "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: "step", +} + +func pluginClient(t *testing.T) (StepPlugin, goPlugin.ClientProtocol, func(), chan struct{}) { + ctx, cancel := context.WithCancel(context.Background()) + + pluginImpl := &testRpcPlugin{} + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcStepPlugin": &RpcStepPlugin{Impl: pluginImpl}, + } + + 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("RpcStepPlugin") + if err != nil { + t.Fail() + } + + plugin, ok := raw.(StepPlugin) + if !ok { + t.Fail() + } + + return plugin, client, cancel, closeCh +} + +func TestPlugin(t *testing.T) { + plugin, _, cancel, closeCh := pluginClient(t) + defer cancel() + + err := plugin.InitPlugin() + if err.Error() != "" { + t.Fail() + } + + ro := v1alpha1.Rollout{} + + err = plugin.RemoveManagedRoutes(&ro) + assert.Equal(t, "", err.Error()) + + err = plugin.SetMirrorRoute(&ro, &v1alpha1.SetMirrorRoute{}) + assert.Equal(t, "", err.Error()) + + err = plugin.SetHeaderRoute(&ro, &v1alpha1.SetHeaderRoute{}) + assert.Equal(t, "", err.Error()) + + err = plugin.SetWeight(&ro, 0, []v1alpha1.WeightDestination{}) + assert.Equal(t, "", err.Error()) + + b, err := plugin.VerifyWeight(&ro, 0, []v1alpha1.WeightDestination{}) + assert.Equal(t, "", err.Error()) + assert.Equal(t, true, *b.IsVerified()) + + err = plugin.UpdateHash(&ro, "canary-hash", "stable-hash", []v1alpha1.WeightDestination{}) + assert.Equal(t, "", err.Error()) + + typeString := plugin.Type() + assert.Equal(t, "TestRPCPlugin", typeString) + + // 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" + + err := plugin.InitPlugin() + assert.Contains(t, err.Error(), expectedError) + + _, err = plugin.Run(&v1alpha1.Rollout{}, &types.RpcStepContext{}) + assert.Contains(t, err.Error(), expectedError) + + _, err = plugin.Terminate(&v1alpha1.Rollout{}, &types.RpcStepContext{}) + assert.Contains(t, err.Error(), expectedError) + + _, err = plugin.Abort(&v1alpha1.Rollout{}, &types.RpcStepContext{}) + assert.Contains(t, err.Error(), expectedError) + + cancel() + <-closeCh +} + +func TestInvalidArgs(t *testing.T) { + server := TrafficRouterRPCServer{} + badtype := struct { + Args string + }{} + + var errRpc types.RpcError + err := server.SetMirrorRoute(badtype, &errRpc) + assert.Error(t, err) + + err = server.RemoveManagedRoutes(badtype, &errRpc) + assert.Error(t, err) + + var vw VerifyWeightResponse + err = server.VerifyWeight(badtype, &vw) + assert.Error(t, err) + + err = server.SetMirrorRoute(badtype, &errRpc) + assert.Error(t, err) + + err = server.SetHeaderRoute(badtype, &errRpc) + assert.Error(t, err) + + err = server.SetWeight(badtype, &errRpc) + assert.Error(t, err) + + err = server.UpdateHash(badtype, &errRpc) + assert.Error(t, err) +} diff --git a/rollout/steps/plugin/rpc/rpc_test_implementation.go b/rollout/steps/plugin/rpc/rpc_test_implementation.go new file mode 100644 index 0000000000..db577edf94 --- /dev/null +++ b/rollout/steps/plugin/rpc/rpc_test_implementation.go @@ -0,0 +1,29 @@ +package rpc + +import ( + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/plugin/types" +) + +type testRpcPlugin struct{} + +func (p *testRpcPlugin) InitPlugin() types.RpcError { + return types.RpcError{} +} + +func (p *testRpcPlugin) Run(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + return types.RpcStepResult{}, types.RpcError{} +} + +func (p *testRpcPlugin) Terminate(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + return types.RpcStepResult{}, types.RpcError{} +} + +func (p *testRpcPlugin) Abort(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + return types.RpcStepResult{}, types.RpcError{} +} + +// Type returns the type of the step plugin +func (p *testRpcPlugin) Type() string { + return "StepPlugin Test" +} diff --git a/test/cmd/step-plugin-sample/internal/plugin/docs.go b/test/cmd/step-plugin-sample/internal/plugin/docs.go new file mode 100644 index 0000000000..65fc77527e --- /dev/null +++ b/test/cmd/step-plugin-sample/internal/plugin/docs.go @@ -0,0 +1,3 @@ +package plugin + +// The goal of this plugin is to diff --git a/test/cmd/step-plugin-sample/internal/plugin/plugin.go b/test/cmd/step-plugin-sample/internal/plugin/plugin.go new file mode 100644 index 0000000000..44bec6e9da --- /dev/null +++ b/test/cmd/step-plugin-sample/internal/plugin/plugin.go @@ -0,0 +1,215 @@ +package plugin + +import ( + "encoding/json" + "fmt" + "math/rand" + "strconv" + "sync" + "time" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + "github.com/google/uuid" + "github.com/sirupsen/logrus" +) + +type Config struct { + Async bool + Aggregate bool +} + +type State struct { + Id string + SharedId string + + Value string +} + +type Result struct { + Value int + Id string +} + +type rpcPlugin struct { + LogCtx *logrus.Entry + Seed int64 + + lock *sync.RWMutex + generator *rand.Rand + randomMap map[string]*Result +} + +func New(logCtx *logrus.Entry, seed int64) rpc.StepPlugin { + return &rpcPlugin{ + LogCtx: logCtx, + Seed: seed, + lock: &sync.RWMutex{}, + } +} + +func (p *rpcPlugin) InitPlugin() types.RpcError { + p.lock.Lock() + defer p.lock.Unlock() + + p.LogCtx.Infof("InitPlugin with seed %d", p.Seed) + rand.New(rand.NewSource(p.Seed)) + p.randomMap = map[string]*Result{} + return types.RpcError{} +} + +func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + // if !p.validate(rollout) { + + // } + + // Get configs + var config Config + var state State + if context != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: "could not unmarshal config"} + } + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: "could not unmarshal status"} + } + } + + // Already completed + if state.Value != "" { + return CompletedResult(state) + } + + if config.Aggregate && state.SharedId != "" { + lastStep := getLastStep(rollout, context.PluginName) + if lastStep != nil { + var lastState State + if err := json.Unmarshal(lastStep.Status, &lastState); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: "could not unmarshal last step status"} + } + if lastState.SharedId != "" { + state.SharedId = lastState.SharedId + } else { + state.SharedId = lastState.Id + } + } + } + + // Already started + if state.Id != "" { + p.lock.RLock() + v, ok := p.randomMap[state.getId()] + p.lock.RUnlock() + if ok { + if v.Id == state.Id { + state.Value = strconv.Itoa(v.Value) + return CompletedResult(state) + } + } + return RunningResult(state) + } + + state.Id = uuid.New().String() + if config.Async { + go func(state State) { + time.Sleep(60 * time.Second) + p.generate(state) + }(state) + return RunningResult(state) + } else { + state.Value = strconv.Itoa(p.generate(state).Value) + } + + return CompletedResult(state) + +} + +func (p *rpcPlugin) Terminate(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + + // probably need to use channel to cancel the sleep and not generate a number + panic("not implemented") // TODO: Implement +} + +func (p *rpcPlugin) Abort(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + + // just for show, set value to zero + panic("not implemented") // TODO: Implement +} + +func (p *rpcPlugin) Type() string { + return "plugin-example" +} + +// func (p *RpcPlugin) validate(rollout *v1alpha1.Rollout) bool { +// if rollout == nil || rollout.Status == nil || rollout.Status.Canary == nil {} +// } + +func (p *rpcPlugin) generate(state State) *Result { + p.lock.Lock() + defer p.lock.Unlock() + + base := 0 + if state.SharedId != "" { + v, ok := p.randomMap[state.SharedId] + if ok { + base = v.Value + } + } + + result := &Result{ + Value: p.generator.Intn(100) + base, + Id: state.Id, + } + p.randomMap[state.getId()] = result + + return result +} + +func (s State) getId() string { + if s.SharedId != "" { + return s.SharedId + } + return s.Id +} + +func getLastStep(rollout *v1alpha1.Rollout, name string) *v1alpha1.StepPluginStatus { + var last *v1alpha1.StepPluginStatus + currentStepIndex := *rollout.Status.CurrentStepIndex + for _, status := range rollout.Status.Canary.StepPluginStatuses { + if status.Name != name || status.Index == currentStepIndex { + continue + } + + if last == nil || status.Index > last.Index { + last = &status + } + } + return last +} + +func CompletedResult(state State) (types.RpcStepResult, types.RpcError) { + stateRaw, err := json.Marshal(state) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Could not marshal state: %v", err)} + } + + return types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "Operation completed", + Status: stateRaw, + }, types.RpcError{} +} + +func RunningResult(state State) (types.RpcStepResult, types.RpcError) { + stateRaw, err := json.Marshal(state) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Could not marshal state: %v", err)} + } + + return types.RpcStepResult{ + Phase: types.PhaseRunning, + RequeueAfter: 15 * time.Second, + Status: stateRaw, + }, types.RpcError{} +} diff --git a/test/cmd/step-plugin-sample/main.go b/test/cmd/step-plugin-sample/main.go new file mode 100644 index 0000000000..77b5ec2801 --- /dev/null +++ b/test/cmd/step-plugin-sample/main.go @@ -0,0 +1,86 @@ +package main + +import ( + "os" + "strconv" + "strings" + "time" + + rolloutsPlugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/test/cmd/step-plugin-sample/internal/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: "step", +} + +func main() { + logCtx := log.WithFields(log.Fields{"plugin": "step"}) + + setLogLevel("debug") + log.SetFormatter(createFormatter("text")) + + seed := time.Now().UnixNano() + + args := os.Args[1:] + if len(args) > 0 { + if args[0] == "--seed" { + if len(args) >= 2 { + n, err := strconv.ParseInt(args[1], 10, 64) + if err != nil { + log.Fatal(err) + } + seed = int64(n) + } else { + log.Fatal("No value for --seed argument") + } + } + } + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcStepPlugin": &rolloutsPlugin.RpcStepPlugin{Impl: plugin.New(logCtx, seed)}, + } + + logCtx.Debug("message from plugin", "foo", "bar") + + goPlugin.Serve(&goPlugin.ServeConfig{ + HandshakeConfig: handshakeConfig, + Plugins: pluginMap, + }) +} + +func createFormatter(logFormat string) log.Formatter { + var formatType log.Formatter + switch strings.ToLower(logFormat) { + case "json": + formatType = &log.JSONFormatter{} + case "text": + formatType = &log.TextFormatter{ + FullTimestamp: true, + } + default: + log.Infof("Unknown format: %s. Using text logformat", logFormat) + formatType = &log.TextFormatter{ + FullTimestamp: true, + } + } + + return formatType +} + +func setLogLevel(logLevel string) { + level, err := log.ParseLevel(logLevel) + if err != nil { + log.Fatal(err) + } + log.SetLevel(level) +} diff --git a/utils/plugin/types/steps.go b/utils/plugin/types/steps.go new file mode 100644 index 0000000000..5c774ae68d --- /dev/null +++ b/utils/plugin/types/steps.go @@ -0,0 +1,28 @@ +package types + +import ( + "encoding/json" + "time" +) + +type Phase string + +const ( + PhaseRunning Phase = "Running" + PhaseSuccessful Phase = "Successful" + PhaseFailed Phase = "Failed" + PhaseError Phase = "Error" +) + +type RpcStepContext struct { + PluginName string + Config json.RawMessage + Status json.RawMessage +} + +type RpcStepResult struct { + Phase Phase + Message string + RequeueAfter time.Duration + Status json.RawMessage +} diff --git a/utils/plugin/types/types.go b/utils/plugin/types/types.go index e89ba40f2a..931c7fdb14 100644 --- a/utils/plugin/types/types.go +++ b/utils/plugin/types/types.go @@ -85,6 +85,14 @@ type RpcTrafficRoutingReconciler interface { Type() string } +type RpcStep interface { + Run(*v1alpha1.Rollout, *RpcStepContext) (RpcStepResult, RpcError) + Terminate(*v1alpha1.Rollout, *RpcStepContext) (RpcStepResult, RpcError) + Abort(*v1alpha1.Rollout, *RpcStepContext) (RpcStepResult, RpcError) + // Type returns the type of the step plugin + Type() string +} + //type Plugin struct { // MetricProviders []PluginItem `json:"metricProviders" yaml:"metricProviders"` // TrafficRouters []PluginItem `json:"trafficRouters" yaml:"trafficRouters"` @@ -98,6 +106,10 @@ type MetricProviderPlugins struct { MetricProviders []PluginItem `json:"metricProviderPlugins" yaml:"metricProviderPlugins"` } +type StepPlugins struct { + Steps []PluginItem `json:"stepPlugins" yaml:"stepPlugins"` +} + type PluginItem struct { Name string `json:"name" yaml:"name"` Location string `json:"location" yaml:"location"` diff --git a/utils/rollout/rolloututil.go b/utils/rollout/rolloututil.go index 0b7df7ff38..45e22d4d38 100644 --- a/utils/rollout/rolloututil.go +++ b/utils/rollout/rolloututil.go @@ -179,6 +179,9 @@ func CanaryStepString(c v1alpha1.CanaryStep) string { return fmt.Sprintf("setCanaryScale{replicas: %d}", *c.SetCanaryScale.Replicas) } } + if c.Plugin != nil { + return fmt.Sprintf("plugin: %s", c.Plugin.Name) + } return "invalid" } From fc18d4b5aca20aac9ab85e2a9e78fa8d64dd5360 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 09:34:08 -0400 Subject: [PATCH 02/41] codegen Signed-off-by: Alexandre Gaudreault --- hack/update-mocks.sh | 8 +- manifests/crds/rollout-crd.yaml | 37 + manifests/install.yaml | 37 + pkg/apiclient/rollout/rollout.swagger.json | 3 - pkg/apis/api-rules/violation_exceptions.list | 1 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 975 +++++++++--------- pkg/apis/rollouts/v1alpha1/generated.proto | 2 - .../rollouts/v1alpha1/openapi_generated.go | 119 ++- pkg/apis/rollouts/v1alpha1/types.go | 1 - .../v1alpha1/zz_generated.deepcopy.go | 62 ++ rollout/steps/plugin/mocks/Resolver.go | 6 +- rollout/steps/plugin/mocks/StepPlugin.go | 14 +- ui/src/models/rollout/generated/api.ts | 6 - 13 files changed, 748 insertions(+), 523 deletions(-) diff --git a/hack/update-mocks.sh b/hack/update-mocks.sh index ee4dfd8869..5412469908 100755 --- a/hack/update-mocks.sh +++ b/hack/update-mocks.sh @@ -12,10 +12,10 @@ mockery \ --name Provider \ --output "${PROJECT_ROOT}"/metricproviders/mocks -# mockery \ -# --dir "${PROJECT_ROOT}"/utils/aws \ -# --name ELBv2APIClient \ -# --output "${PROJECT_ROOT}"/utils/aws/mocks +mockery \ + --dir "${PROJECT_ROOT}"/utils/aws \ + --name ELBv2APIClient \ + --output "${PROJECT_ROOT}"/utils/aws/mocks mockery \ --dir "${PROJECT_ROOT}"/rollout/trafficrouting \ diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index 04e187dbea..297472042f 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -662,6 +662,16 @@ spec: - type: string x-kubernetes-int-or-string: true type: object + plugin: + properties: + config: + type: object + x-kubernetes-preserve-unknown-fields: true + name: + type: string + required: + - name + type: object setCanaryScale: properties: matchTrafficWeight: @@ -3717,6 +3727,33 @@ spec: type: object stablePingPong: type: string + stepPluginStatuses: + items: + properties: + finishedAt: + format: date-time + type: string + index: + format: int32 + type: integer + message: + type: string + name: + type: string + phase: + type: string + startedAt: + format: date-time + type: string + status: + format: byte + type: string + required: + - index + - name + - phase + type: object + type: array weights: properties: additional: diff --git a/manifests/install.yaml b/manifests/install.yaml index dfb8d18768..27d0fcd178 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -13152,6 +13152,16 @@ spec: - type: string x-kubernetes-int-or-string: true type: object + plugin: + properties: + config: + type: object + x-kubernetes-preserve-unknown-fields: true + name: + type: string + required: + - name + type: object setCanaryScale: properties: matchTrafficWeight: @@ -16207,6 +16217,33 @@ spec: type: object stablePingPong: type: string + stepPluginStatuses: + items: + properties: + finishedAt: + format: date-time + type: string + index: + format: int32 + type: integer + message: + type: string + name: + type: string + phase: + type: string + startedAt: + format: date-time + type: string + status: + format: byte + type: string + required: + - index + - name + - phase + type: object + type: array weights: properties: additional: diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index 7b8a022fd4..5388e53696 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -1772,9 +1772,6 @@ "type": "string", "title": "Name the name of the hashicorp go-plugin step to query" }, - "abortOnFailure": { - "type": "boolean" - }, "config": { "type": "string", "format": "byte", diff --git a/pkg/apis/api-rules/violation_exceptions.list b/pkg/apis/api-rules/violation_exceptions.list index ea9a241837..c4c0952a74 100644 --- a/pkg/apis/api-rules/violation_exceptions.list +++ b/pkg/apis/api-rules/violation_exceptions.list @@ -12,6 +12,7 @@ API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,AnalysisTemplateSpec,Templates API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,ApisixRoute,Rules API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,AppMeshVirtualService,Routes +API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,CanaryStatus,StepPluginStatuses API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,CanaryStrategy,Steps API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,CloudWatchMetric,MetricDataQueries API rule violation: list_type_missing,github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1,CloudWatchMetricStatMetric,Dimensions diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index cfa7870ac6..8e790ef4c3 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -3407,176 +3407,176 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 8735 bytes of a gzipped FileDescriptorProto + // 8715 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x6c, 0x64, 0xd7, - 0x75, 0x98, 0x1f, 0x87, 0x43, 0xce, 0x9c, 0xe1, 0x92, 0xdc, 0xbb, 0xbb, 0x12, 0x45, 0x49, 0x3b, - 0xeb, 0xa7, 0x54, 0x95, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, + 0x75, 0x98, 0x1e, 0x87, 0x43, 0xce, 0x9c, 0xe1, 0x92, 0xdc, 0xbb, 0xbb, 0x12, 0x45, 0x49, 0x3b, + 0x9b, 0xa7, 0x54, 0x95, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, 0x72, 0x45, 0xee, 0x52, 0x67, 0xb8, 0xda, 0xf8, 0x43, 0x89, 0x1f, 0x67, 0x2e, 0x87, 0x6f, 0x39, 0xf3, 0xde, 0xf8, 0xbd, 0x37, 0xdc, 0xa5, 0x2c, 0xc4, 0xb2, 0x0d, 0x39, 0x8e, 0x6b, 0x23, 0x6e, - 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0x29, 0x8a, 0x36, 0x70, 0xd1, 0xfe, 0x08, + 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0xe9, 0x8f, 0x36, 0x70, 0xd1, 0xfe, 0x08, 0xd0, 0xa0, 0x6e, 0x0a, 0x07, 0x68, 0x0a, 0xe7, 0x47, 0xeb, 0xb4, 0x40, 0x98, 0x9a, 0xe9, 0x9f, 0x06, 0x2d, 0x8c, 0x16, 0x2e, 0x82, 0xea, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, - 0x9a, 0xc7, 0x95, 0xd2, 0xe4, 0xdf, 0xcc, 0x3d, 0xe7, 0x9e, 0x73, 0xde, 0xfd, 0x3c, 0xf7, 0xdc, + 0x9a, 0xc7, 0x95, 0xd2, 0xe6, 0xdf, 0xcc, 0x3d, 0xe7, 0x9e, 0x73, 0xde, 0xfd, 0x3c, 0xf7, 0xdc, 0x73, 0xce, 0x85, 0xd5, 0xb6, 0x1b, 0x6d, 0xf7, 0x37, 0x17, 0x9a, 0x7e, 0x77, 0xd1, 0x09, 0xda, 0x7e, 0x2f, 0xf0, 0xef, 0xf2, 0x1f, 0x1f, 0x0e, 0xfc, 0x4e, 0xc7, 0xef, 0x47, 0xe1, 0x62, 0x6f, 0xa7, 0xbd, 0xe8, 0xf4, 0xdc, 0x70, 0x51, 0x97, 0xec, 0x7e, 0xd4, 0xe9, 0xf4, 0xb6, 0x9d, 0x8f, 0x2e, 0xb6, 0xa9, 0x47, 0x03, 0x27, 0xa2, 0xad, 0x85, 0x5e, 0xe0, 0x47, 0x3e, 0xf9, 0x44, 0x4c, - 0x6d, 0x41, 0x51, 0xe3, 0x3f, 0x7e, 0x56, 0xd5, 0x5d, 0xe8, 0xed, 0xb4, 0x17, 0x18, 0xb5, 0x05, + 0x6d, 0x41, 0x51, 0xe3, 0x3f, 0x7e, 0x4e, 0xd5, 0x5d, 0xe8, 0xed, 0xb4, 0x17, 0x18, 0xb5, 0x05, 0x5d, 0xa2, 0xa8, 0xcd, 0x7f, 0xd8, 0x90, 0xa5, 0xed, 0xb7, 0xfd, 0x45, 0x4e, 0x74, 0xb3, 0xbf, - 0xc5, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x60, 0x36, 0xff, 0xc4, 0xce, 0x8b, 0xe1, 0x82, 0xeb, 0x33, + 0xc5, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x60, 0x36, 0xff, 0xe4, 0xce, 0x4b, 0xe1, 0x82, 0xeb, 0x33, 0xd9, 0x16, 0x37, 0x9d, 0xa8, 0xb9, 0xbd, 0xb8, 0x3b, 0x20, 0xd1, 0xbc, 0x6d, 0x20, 0x35, 0xfd, - 0x80, 0x66, 0xe1, 0x3c, 0x1f, 0xe3, 0x74, 0x9d, 0xe6, 0xb6, 0xeb, 0xd1, 0x60, 0x2f, 0xfe, 0xea, + 0x80, 0x66, 0xe1, 0xbc, 0x10, 0xe3, 0x74, 0x9d, 0xe6, 0xb6, 0xeb, 0xd1, 0x60, 0x2f, 0xfe, 0xea, 0x2e, 0x8d, 0x9c, 0xac, 0x5a, 0x8b, 0xc3, 0x6a, 0x05, 0x7d, 0x2f, 0x72, 0xbb, 0x74, 0xa0, 0xc2, - 0x4f, 0x1d, 0x55, 0x21, 0x6c, 0x6e, 0xd3, 0xae, 0x33, 0x50, 0xef, 0xb9, 0x61, 0xf5, 0xfa, 0x91, + 0x4f, 0x1f, 0x55, 0x21, 0x6c, 0x6e, 0xd3, 0xae, 0x33, 0x50, 0xef, 0xf9, 0x61, 0xf5, 0xfa, 0x91, 0xdb, 0x59, 0x74, 0xbd, 0x28, 0x8c, 0x82, 0x74, 0x25, 0xfb, 0x47, 0x05, 0x28, 0xd7, 0x56, 0xeb, 0x8d, 0xc8, 0x89, 0xfa, 0x21, 0xf9, 0x8a, 0x05, 0x53, 0x1d, 0xdf, 0x69, 0xd5, 0x9d, 0x8e, 0xe3, - 0x35, 0x69, 0x30, 0x67, 0x5d, 0xb1, 0x9e, 0xaa, 0x3c, 0xbb, 0xba, 0x30, 0x4a, 0x7f, 0x2d, 0xd4, - 0xee, 0x85, 0x48, 0x43, 0xbf, 0x1f, 0x34, 0x29, 0xd2, 0xad, 0xfa, 0xc5, 0xef, 0xed, 0x57, 0x3f, - 0x70, 0xb0, 0x5f, 0x9d, 0x5a, 0x35, 0x38, 0x61, 0x82, 0x2f, 0xf9, 0x96, 0x05, 0xe7, 0x9b, 0x8e, - 0xe7, 0x04, 0x7b, 0x1b, 0x4e, 0xd0, 0xa6, 0xd1, 0x2b, 0x81, 0xdf, 0xef, 0xcd, 0x8d, 0x9d, 0x81, - 0x34, 0x8f, 0x48, 0x69, 0xce, 0x2f, 0xa5, 0xd9, 0xe1, 0xa0, 0x04, 0x5c, 0xae, 0x30, 0x72, 0x36, - 0x3b, 0xd4, 0x94, 0xab, 0x70, 0x96, 0x72, 0x35, 0xd2, 0xec, 0x70, 0x50, 0x02, 0xf2, 0x34, 0x4c, - 0xba, 0x5e, 0x3b, 0xa0, 0x61, 0x38, 0x37, 0x7e, 0xc5, 0x7a, 0xaa, 0x5c, 0x9f, 0x91, 0xd5, 0x27, - 0x57, 0x44, 0x31, 0x2a, 0xb8, 0xfd, 0x1b, 0x05, 0x38, 0x5f, 0x5b, 0xad, 0x6f, 0x04, 0xce, 0xd6, - 0x96, 0xdb, 0x44, 0xbf, 0x1f, 0xb9, 0x5e, 0xdb, 0x24, 0x60, 0x1d, 0x4e, 0x80, 0xbc, 0x00, 0x95, - 0x90, 0x06, 0xbb, 0x6e, 0x93, 0xae, 0xfb, 0x41, 0xc4, 0x3b, 0xa5, 0x58, 0xbf, 0x20, 0xd1, 0x2b, - 0x8d, 0x18, 0x84, 0x26, 0x1e, 0xab, 0x16, 0xf8, 0x7e, 0x24, 0xe1, 0xbc, 0xcd, 0xca, 0x71, 0x35, - 0x8c, 0x41, 0x68, 0xe2, 0x91, 0x65, 0x98, 0x75, 0x3c, 0xcf, 0x8f, 0x9c, 0xc8, 0xf5, 0xbd, 0xf5, - 0x80, 0x6e, 0xb9, 0xf7, 0xe5, 0x27, 0xce, 0xc9, 0xba, 0xb3, 0xb5, 0x14, 0x1c, 0x07, 0x6a, 0x90, - 0x6f, 0x5a, 0x30, 0x1b, 0x46, 0x6e, 0x73, 0xc7, 0xf5, 0x68, 0x18, 0x2e, 0xf9, 0xde, 0x96, 0xdb, - 0x9e, 0x2b, 0xf2, 0x6e, 0xbb, 0x39, 0x5a, 0xb7, 0x35, 0x52, 0x54, 0xeb, 0x17, 0x99, 0x48, 0xe9, - 0x52, 0x1c, 0xe0, 0x4e, 0x3e, 0x04, 0x65, 0xd9, 0xa2, 0x34, 0x9c, 0x9b, 0xb8, 0x52, 0x78, 0xaa, - 0x5c, 0x3f, 0x77, 0xb0, 0x5f, 0x2d, 0xaf, 0xa8, 0x42, 0x8c, 0xe1, 0xf6, 0x32, 0xcc, 0xd5, 0xba, - 0x9b, 0x4e, 0x18, 0x3a, 0x2d, 0x3f, 0x48, 0x75, 0xdd, 0x53, 0x50, 0xea, 0x3a, 0xbd, 0x9e, 0xeb, - 0xb5, 0x59, 0xdf, 0x31, 0x3a, 0x53, 0x07, 0xfb, 0xd5, 0xd2, 0x9a, 0x2c, 0x43, 0x0d, 0xb5, 0xff, - 0xd3, 0x18, 0x54, 0x6a, 0x9e, 0xd3, 0xd9, 0x0b, 0xdd, 0x10, 0xfb, 0x1e, 0xf9, 0x2c, 0x94, 0xd8, - 0xaa, 0xd5, 0x72, 0x22, 0x47, 0xce, 0xf4, 0x8f, 0x2c, 0x88, 0x45, 0x64, 0xc1, 0x5c, 0x44, 0xe2, - 0xcf, 0x67, 0xd8, 0x0b, 0xbb, 0x1f, 0x5d, 0xb8, 0xb5, 0x79, 0x97, 0x36, 0xa3, 0x35, 0x1a, 0x39, - 0x75, 0x22, 0x7b, 0x01, 0xe2, 0x32, 0xd4, 0x54, 0x89, 0x0f, 0xe3, 0x61, 0x8f, 0x36, 0xe5, 0xcc, - 0x5d, 0x1b, 0x71, 0x86, 0xc4, 0xa2, 0x37, 0x7a, 0xb4, 0x59, 0x9f, 0x92, 0xac, 0xc7, 0xd9, 0x3f, - 0xe4, 0x8c, 0xc8, 0x3d, 0x98, 0x08, 0xf9, 0x5a, 0x26, 0x27, 0xe5, 0xad, 0xfc, 0x58, 0x72, 0xb2, - 0xf5, 0x69, 0xc9, 0x74, 0x42, 0xfc, 0x47, 0xc9, 0xce, 0xfe, 0xcf, 0x16, 0x5c, 0x30, 0xb0, 0x6b, - 0x41, 0xbb, 0xdf, 0xa5, 0x5e, 0x44, 0xae, 0xc0, 0xb8, 0xe7, 0x74, 0xa9, 0x9c, 0x55, 0x5a, 0xe4, - 0x9b, 0x4e, 0x97, 0x22, 0x87, 0x90, 0x27, 0xa0, 0xb8, 0xeb, 0x74, 0xfa, 0x94, 0x37, 0x52, 0xb9, - 0x7e, 0x4e, 0xa2, 0x14, 0x5f, 0x67, 0x85, 0x28, 0x60, 0xe4, 0x2d, 0x28, 0xf3, 0x1f, 0xd7, 0x02, - 0xbf, 0x9b, 0xd3, 0xa7, 0x49, 0x09, 0x5f, 0x57, 0x64, 0xc5, 0xf0, 0xd3, 0x7f, 0x31, 0x66, 0x68, - 0xff, 0xa1, 0x05, 0x33, 0xc6, 0xc7, 0xad, 0xba, 0x61, 0x44, 0x3e, 0x33, 0x30, 0x78, 0x16, 0x8e, - 0x37, 0x78, 0x58, 0x6d, 0x3e, 0x74, 0x66, 0xe5, 0x97, 0x96, 0x54, 0x89, 0x31, 0x70, 0x3c, 0x28, - 0xba, 0x11, 0xed, 0x86, 0x73, 0x63, 0x57, 0x0a, 0x4f, 0x55, 0x9e, 0x5d, 0xc9, 0xad, 0x1b, 0xe3, - 0xf6, 0x5d, 0x61, 0xf4, 0x51, 0xb0, 0xb1, 0xbf, 0x53, 0x48, 0x74, 0xdf, 0x9a, 0x92, 0xe3, 0x1d, - 0x0b, 0x26, 0x3a, 0xce, 0x26, 0xed, 0x88, 0xb9, 0x55, 0x79, 0xf6, 0x8d, 0xdc, 0x24, 0x51, 0x3c, - 0x16, 0x56, 0x39, 0xfd, 0xab, 0x5e, 0x14, 0xec, 0xc5, 0xc3, 0x4b, 0x14, 0xa2, 0x64, 0x4e, 0xfe, - 0x96, 0x05, 0x95, 0x78, 0x55, 0x53, 0xcd, 0xb2, 0x99, 0xbf, 0x30, 0xf1, 0x62, 0x2a, 0x25, 0xd2, - 0x4b, 0xb4, 0x01, 0x41, 0x53, 0x96, 0xf9, 0x8f, 0x41, 0xc5, 0xf8, 0x04, 0x32, 0x0b, 0x85, 0x1d, - 0xba, 0x27, 0x06, 0x3c, 0xb2, 0x9f, 0xe4, 0x62, 0x62, 0x84, 0xcb, 0x21, 0xfd, 0xf1, 0xb1, 0x17, - 0xad, 0xf9, 0x97, 0x61, 0x36, 0xcd, 0xf0, 0x24, 0xf5, 0xed, 0x7f, 0x5a, 0x4c, 0x0c, 0x4c, 0xb6, - 0x10, 0x10, 0x1f, 0x26, 0xbb, 0x34, 0x0a, 0xdc, 0xa6, 0xea, 0xb2, 0xe5, 0xd1, 0x5a, 0x69, 0x8d, - 0x13, 0x8b, 0x37, 0x44, 0xf1, 0x3f, 0x44, 0xc5, 0x85, 0x6c, 0xc3, 0xb8, 0x13, 0xb4, 0x55, 0x9f, - 0x5c, 0xcb, 0x67, 0x5a, 0xc6, 0x4b, 0x45, 0x2d, 0x68, 0x87, 0xc8, 0x39, 0x90, 0x45, 0x28, 0x47, - 0x34, 0xe8, 0xba, 0x9e, 0x13, 0x89, 0x1d, 0xb4, 0x54, 0x3f, 0x2f, 0xd1, 0xca, 0x1b, 0x0a, 0x80, - 0x31, 0x0e, 0xe9, 0xc0, 0x44, 0x2b, 0xd8, 0xc3, 0xbe, 0x37, 0x37, 0x9e, 0x47, 0x53, 0x2c, 0x73, - 0x5a, 0xf1, 0x20, 0x15, 0xff, 0x51, 0xf2, 0x20, 0xbf, 0x6a, 0xc1, 0xc5, 0x2e, 0x75, 0xc2, 0x7e, - 0x40, 0xd9, 0x27, 0x20, 0x8d, 0xa8, 0xc7, 0x3a, 0x76, 0xae, 0xc8, 0x99, 0xe3, 0xa8, 0xfd, 0x30, - 0x48, 0xb9, 0xfe, 0x98, 0x14, 0xe5, 0x62, 0x16, 0x14, 0x33, 0xa5, 0x21, 0x6f, 0x41, 0x25, 0x8a, - 0x3a, 0x8d, 0x88, 0xe9, 0xc1, 0xed, 0xbd, 0xb9, 0x09, 0xbe, 0x78, 0x8d, 0xb8, 0xc2, 0x6c, 0x6c, - 0xac, 0x2a, 0x82, 0xf5, 0x19, 0x36, 0x5b, 0x8c, 0x02, 0x34, 0xd9, 0xd9, 0xff, 0xb2, 0x08, 0xe7, - 0x07, 0xb6, 0x15, 0xf2, 0x3c, 0x14, 0x7b, 0xdb, 0x4e, 0xa8, 0xf6, 0x89, 0xcb, 0x6a, 0x91, 0x5a, - 0x67, 0x85, 0xef, 0xee, 0x57, 0xcf, 0xa9, 0x2a, 0xbc, 0x00, 0x05, 0x32, 0xd3, 0xda, 0xba, 0x34, - 0x0c, 0x9d, 0xb6, 0xda, 0x3c, 0x8c, 0x41, 0xca, 0x8b, 0x51, 0xc1, 0xc9, 0xcf, 0x5b, 0x70, 0x4e, - 0x0c, 0x58, 0xa4, 0x61, 0xbf, 0x13, 0xb1, 0x0d, 0x92, 0x75, 0xca, 0x8d, 0x3c, 0x26, 0x87, 0x20, - 0x59, 0xbf, 0x24, 0xb9, 0x9f, 0x33, 0x4b, 0x43, 0x4c, 0xf2, 0x25, 0x77, 0xa0, 0x1c, 0x46, 0x4e, - 0x10, 0xd1, 0x56, 0x2d, 0xe2, 0xaa, 0x5c, 0xe5, 0xd9, 0x9f, 0x3c, 0xde, 0xce, 0xb1, 0xe1, 0x76, - 0xa9, 0xd8, 0xa5, 0x1a, 0x8a, 0x00, 0xc6, 0xb4, 0xc8, 0x5b, 0x00, 0x41, 0xdf, 0x6b, 0xf4, 0xbb, - 0x5d, 0x27, 0xd8, 0x93, 0xda, 0xdd, 0xf5, 0xd1, 0x3e, 0x0f, 0x35, 0xbd, 0x58, 0xd1, 0x89, 0xcb, - 0xd0, 0xe0, 0x47, 0xbe, 0x68, 0xc1, 0x39, 0x31, 0x0f, 0x94, 0x04, 0x13, 0x39, 0x4b, 0x70, 0x9e, - 0x35, 0xed, 0xb2, 0xc9, 0x02, 0x93, 0x1c, 0xc9, 0x1b, 0x50, 0x69, 0xfa, 0xdd, 0x5e, 0x87, 0x8a, - 0xc6, 0x9d, 0x3c, 0x71, 0xe3, 0xf2, 0xa1, 0xbb, 0x14, 0x93, 0x40, 0x93, 0x9e, 0xfd, 0x1f, 0x92, - 0x3a, 0x8e, 0x1a, 0xd2, 0xe4, 0xd3, 0xf0, 0x48, 0xd8, 0x6f, 0x36, 0x69, 0x18, 0x6e, 0xf5, 0x3b, - 0xd8, 0xf7, 0xae, 0xbb, 0x61, 0xe4, 0x07, 0x7b, 0xab, 0x6e, 0xd7, 0x8d, 0xf8, 0x80, 0x2e, 0xd6, - 0x1f, 0x3f, 0xd8, 0xaf, 0x3e, 0xd2, 0x18, 0x86, 0x84, 0xc3, 0xeb, 0x13, 0x07, 0x1e, 0xed, 0x7b, - 0xc3, 0xc9, 0x8b, 0xe3, 0x47, 0xf5, 0x60, 0xbf, 0xfa, 0xe8, 0xed, 0xe1, 0x68, 0x78, 0x18, 0x0d, - 0xfb, 0x8f, 0x2d, 0xb6, 0x0d, 0x89, 0xef, 0xda, 0xa0, 0xdd, 0x5e, 0x87, 0x2d, 0x9d, 0x67, 0xaf, - 0x1c, 0x47, 0x09, 0xe5, 0x18, 0xf3, 0xd9, 0xcb, 0x95, 0xfc, 0xc3, 0x34, 0x64, 0xfb, 0xbf, 0x59, - 0x70, 0x31, 0x8d, 0xfc, 0x00, 0x14, 0xba, 0x30, 0xa9, 0xd0, 0xdd, 0xcc, 0xf7, 0x6b, 0x87, 0x68, - 0x75, 0xbf, 0x60, 0x0c, 0x58, 0x85, 0x8a, 0x74, 0x8b, 0xbc, 0x08, 0x53, 0x91, 0xfc, 0x7b, 0x33, - 0x56, 0xce, 0xb5, 0x61, 0x62, 0xc3, 0x80, 0x61, 0x02, 0x93, 0xd5, 0x6c, 0x76, 0xfa, 0x61, 0x44, - 0x83, 0x46, 0xd3, 0xef, 0x89, 0x65, 0xb7, 0x14, 0xd7, 0x5c, 0x32, 0x60, 0x98, 0xc0, 0xb4, 0xff, - 0x5a, 0x71, 0xb0, 0xdd, 0xff, 0x7f, 0xd7, 0x57, 0x62, 0xf5, 0xa3, 0xf0, 0x5e, 0xaa, 0x1f, 0xe3, - 0xef, 0x2b, 0xf5, 0xe3, 0x4b, 0x16, 0xd3, 0xe2, 0xc4, 0x00, 0x08, 0xa5, 0x6a, 0xf4, 0x5a, 0xbe, - 0xd3, 0x01, 0xe9, 0x96, 0xa9, 0x18, 0x4a, 0x5e, 0x18, 0xb3, 0xb5, 0xff, 0xc1, 0x38, 0x4c, 0xd5, - 0xbc, 0xc8, 0xad, 0x6d, 0x6d, 0xb9, 0x9e, 0x1b, 0xed, 0x91, 0xaf, 0x8f, 0xc1, 0x62, 0x2f, 0xa0, - 0x5b, 0x34, 0x08, 0x68, 0x6b, 0xb9, 0x1f, 0xb8, 0x5e, 0xbb, 0xd1, 0xdc, 0xa6, 0xad, 0x7e, 0xc7, - 0xf5, 0xda, 0x2b, 0x6d, 0xcf, 0xd7, 0xc5, 0x57, 0xef, 0xd3, 0x66, 0x9f, 0xb7, 0xab, 0x58, 0x25, - 0xba, 0xa3, 0xc9, 0xbe, 0x7e, 0x32, 0xa6, 0xf5, 0xe7, 0x0e, 0xf6, 0xab, 0x8b, 0x27, 0xac, 0x84, - 0x27, 0xfd, 0x34, 0xf2, 0xd5, 0x31, 0x58, 0x08, 0xe8, 0xe7, 0xfa, 0xee, 0xf1, 0x5b, 0x43, 0x2c, - 0xe3, 0x9d, 0x11, 0xb7, 0xfb, 0x13, 0xf1, 0xac, 0x3f, 0x7b, 0xb0, 0x5f, 0x3d, 0x61, 0x1d, 0x3c, - 0xe1, 0x77, 0xd9, 0xeb, 0x50, 0xa9, 0xf5, 0xdc, 0xd0, 0xbd, 0x8f, 0x7e, 0x3f, 0xa2, 0xc7, 0x30, - 0x68, 0x54, 0xa1, 0x18, 0xf4, 0x3b, 0x54, 0x2c, 0x30, 0xe5, 0x7a, 0x99, 0x2d, 0xcb, 0xc8, 0x0a, - 0x50, 0x94, 0xdb, 0x5f, 0x62, 0x5b, 0x10, 0x27, 0x99, 0x32, 0x65, 0xdd, 0x85, 0x62, 0xc0, 0x98, - 0xc8, 0x91, 0x35, 0xea, 0xa9, 0x3f, 0x96, 0x5a, 0x0a, 0xc1, 0x7e, 0xa2, 0x60, 0x61, 0x7f, 0x77, - 0x0c, 0x2e, 0xd5, 0x7a, 0xbd, 0x35, 0x1a, 0x6e, 0xa7, 0xa4, 0xf8, 0x45, 0x0b, 0xa6, 0x77, 0xdd, - 0x20, 0xea, 0x3b, 0x1d, 0x65, 0xad, 0x14, 0xf2, 0x34, 0x46, 0x95, 0x87, 0x73, 0x7b, 0x3d, 0x41, - 0xba, 0x4e, 0x0e, 0xf6, 0xab, 0xd3, 0xc9, 0x32, 0x4c, 0xb1, 0x27, 0x7f, 0xd3, 0x82, 0x59, 0x59, - 0x74, 0xd3, 0x6f, 0x51, 0xd3, 0x1a, 0x7e, 0x3b, 0x4f, 0x99, 0x34, 0x71, 0x61, 0xc5, 0x4c, 0x97, - 0xe2, 0x80, 0x10, 0xf6, 0xff, 0x18, 0x83, 0x87, 0x87, 0xd0, 0x20, 0xbf, 0x66, 0xc1, 0x45, 0x61, - 0x42, 0x37, 0x40, 0x48, 0xb7, 0x64, 0x6b, 0x7e, 0x32, 0x6f, 0xc9, 0x91, 0x4d, 0x71, 0xea, 0x35, - 0x69, 0x7d, 0x8e, 0x2d, 0xc9, 0x4b, 0x19, 0xac, 0x31, 0x53, 0x20, 0x2e, 0xa9, 0x30, 0xaa, 0xa7, - 0x24, 0x1d, 0x7b, 0x20, 0x92, 0x36, 0x32, 0x58, 0x63, 0xa6, 0x40, 0xf6, 0x5f, 0x81, 0x47, 0x0f, - 0x21, 0x77, 0xf4, 0xe4, 0xb4, 0xdf, 0xd0, 0xa3, 0x3e, 0x39, 0xe6, 0x8e, 0x31, 0xaf, 0x6d, 0x98, - 0xe0, 0x53, 0x47, 0x4d, 0x6c, 0x60, 0x7b, 0x30, 0x9f, 0x53, 0x21, 0x4a, 0x88, 0xfd, 0x5d, 0x0b, - 0x4a, 0x27, 0xb0, 0x7d, 0x56, 0x93, 0xb6, 0xcf, 0xf2, 0x80, 0xdd, 0x33, 0x1a, 0xb4, 0x7b, 0xbe, - 0x32, 0x5a, 0x6f, 0x1c, 0xc7, 0xde, 0xf9, 0x23, 0x0b, 0xce, 0x0f, 0xd8, 0x47, 0xc9, 0x36, 0x5c, - 0xec, 0xf9, 0x2d, 0xb5, 0x9d, 0x5e, 0x77, 0xc2, 0x6d, 0x0e, 0x93, 0x9f, 0xf7, 0x3c, 0xeb, 0xc9, - 0xf5, 0x0c, 0xf8, 0xbb, 0xfb, 0xd5, 0x39, 0x4d, 0x24, 0x85, 0x80, 0x99, 0x14, 0x49, 0x0f, 0x4a, - 0x5b, 0x2e, 0xed, 0xb4, 0xe2, 0x21, 0x38, 0xa2, 0x96, 0x76, 0x4d, 0x52, 0x13, 0x57, 0x03, 0xea, - 0x1f, 0x6a, 0x2e, 0xf6, 0x8f, 0x2d, 0x98, 0xae, 0xf5, 0xa3, 0x6d, 0xa6, 0xa3, 0x34, 0xb9, 0x35, - 0x8e, 0x78, 0x50, 0x0c, 0xdd, 0xf6, 0xee, 0xf3, 0xf9, 0x2c, 0xc6, 0x0d, 0x46, 0x4a, 0x5e, 0x91, - 0x68, 0x65, 0x9d, 0x17, 0xa2, 0x60, 0x43, 0x02, 0x98, 0xf0, 0x9d, 0x7e, 0xb4, 0xfd, 0xac, 0xfc, - 0xe4, 0x11, 0x2d, 0x13, 0xb7, 0xd8, 0xe7, 0x3c, 0x2b, 0x39, 0x6a, 0x95, 0x51, 0x94, 0xa2, 0xe4, - 0x64, 0x7f, 0x01, 0xa6, 0x93, 0xf7, 0x6e, 0xc7, 0x18, 0xb3, 0x8f, 0x43, 0xc1, 0x09, 0x3c, 0x39, - 0x62, 0x2b, 0x12, 0xa1, 0x50, 0xc3, 0x9b, 0xc8, 0xca, 0xc9, 0x33, 0x50, 0xda, 0xea, 0x77, 0x3a, - 0xfc, 0x5c, 0x21, 0x2e, 0xb9, 0xf4, 0xb1, 0xe8, 0x9a, 0x2c, 0x47, 0x8d, 0x61, 0xff, 0x9f, 0x71, - 0x98, 0xa9, 0x77, 0xfa, 0xf4, 0x95, 0x80, 0x52, 0x65, 0x0b, 0xaa, 0xc1, 0x4c, 0x2f, 0xa0, 0xbb, - 0x2e, 0xbd, 0xd7, 0xa0, 0x1d, 0xda, 0x8c, 0xfc, 0x40, 0x4a, 0xf3, 0xb0, 0x24, 0x34, 0xb3, 0x9e, - 0x04, 0x63, 0x1a, 0x9f, 0xbc, 0x0c, 0xd3, 0x4e, 0x33, 0x72, 0x77, 0xa9, 0xa6, 0x20, 0xc4, 0x7d, - 0x48, 0x52, 0x98, 0xae, 0x25, 0xa0, 0x98, 0xc2, 0x26, 0x9f, 0x81, 0xb9, 0xb0, 0xe9, 0x74, 0xe8, - 0xed, 0x9e, 0x64, 0xb5, 0xb4, 0x4d, 0x9b, 0x3b, 0xeb, 0xbe, 0xeb, 0x45, 0xd2, 0xee, 0x78, 0x45, - 0x52, 0x9a, 0x6b, 0x0c, 0xc1, 0xc3, 0xa1, 0x14, 0xc8, 0xbf, 0xb2, 0xe0, 0xf1, 0x5e, 0x40, 0xd7, - 0x03, 0xbf, 0xeb, 0xb3, 0xa1, 0x36, 0x60, 0x0e, 0x93, 0x66, 0xa1, 0xd7, 0x47, 0xd4, 0xa5, 0x44, - 0xc9, 0xe0, 0x1d, 0xce, 0x07, 0x0f, 0xf6, 0xab, 0x8f, 0xaf, 0x1f, 0x26, 0x00, 0x1e, 0x2e, 0x1f, - 0xf9, 0xd7, 0x16, 0x5c, 0xee, 0xf9, 0x61, 0x74, 0xc8, 0x27, 0x14, 0xcf, 0xf4, 0x13, 0xec, 0x83, + 0x35, 0x69, 0x30, 0x67, 0x5d, 0xb1, 0x9e, 0xae, 0x3c, 0xb7, 0xba, 0x30, 0x4a, 0x7f, 0x2d, 0xd4, + 0xee, 0x85, 0x48, 0x43, 0xbf, 0x1f, 0x34, 0x29, 0xd2, 0xad, 0xfa, 0xc5, 0xef, 0xed, 0x57, 0x1f, + 0x3a, 0xd8, 0xaf, 0x4e, 0xad, 0x1a, 0x9c, 0x30, 0xc1, 0x97, 0x7c, 0xcb, 0x82, 0xf3, 0x4d, 0xc7, + 0x73, 0x82, 0xbd, 0x0d, 0x27, 0x68, 0xd3, 0xe8, 0xd5, 0xc0, 0xef, 0xf7, 0xe6, 0xc6, 0xce, 0x40, + 0x9a, 0x47, 0xa5, 0x34, 0xe7, 0x97, 0xd2, 0xec, 0x70, 0x50, 0x02, 0x2e, 0x57, 0x18, 0x39, 0x9b, + 0x1d, 0x6a, 0xca, 0x55, 0x38, 0x4b, 0xb9, 0x1a, 0x69, 0x76, 0x38, 0x28, 0x01, 0x79, 0x06, 0x26, + 0x5d, 0xaf, 0x1d, 0xd0, 0x30, 0x9c, 0x1b, 0xbf, 0x62, 0x3d, 0x5d, 0xae, 0xcf, 0xc8, 0xea, 0x93, + 0x2b, 0xa2, 0x18, 0x15, 0xdc, 0xfe, 0xcd, 0x02, 0x9c, 0xaf, 0xad, 0xd6, 0x37, 0x02, 0x67, 0x6b, + 0xcb, 0x6d, 0xa2, 0xdf, 0x8f, 0x5c, 0xaf, 0x6d, 0x12, 0xb0, 0x0e, 0x27, 0x40, 0x5e, 0x84, 0x4a, + 0x48, 0x83, 0x5d, 0xb7, 0x49, 0xd7, 0xfd, 0x20, 0xe2, 0x9d, 0x52, 0xac, 0x5f, 0x90, 0xe8, 0x95, + 0x46, 0x0c, 0x42, 0x13, 0x8f, 0x55, 0x0b, 0x7c, 0x3f, 0x92, 0x70, 0xde, 0x66, 0xe5, 0xb8, 0x1a, + 0xc6, 0x20, 0x34, 0xf1, 0xc8, 0x32, 0xcc, 0x3a, 0x9e, 0xe7, 0x47, 0x4e, 0xe4, 0xfa, 0xde, 0x7a, + 0x40, 0xb7, 0xdc, 0xfb, 0xf2, 0x13, 0xe7, 0x64, 0xdd, 0xd9, 0x5a, 0x0a, 0x8e, 0x03, 0x35, 0xc8, + 0x37, 0x2d, 0x98, 0x0d, 0x23, 0xb7, 0xb9, 0xe3, 0x7a, 0x34, 0x0c, 0x97, 0x7c, 0x6f, 0xcb, 0x6d, + 0xcf, 0x15, 0x79, 0xb7, 0xdd, 0x1c, 0xad, 0xdb, 0x1a, 0x29, 0xaa, 0xf5, 0x8b, 0x4c, 0xa4, 0x74, + 0x29, 0x0e, 0x70, 0x27, 0x1f, 0x82, 0xb2, 0x6c, 0x51, 0x1a, 0xce, 0x4d, 0x5c, 0x29, 0x3c, 0x5d, + 0xae, 0x9f, 0x3b, 0xd8, 0xaf, 0x96, 0x57, 0x54, 0x21, 0xc6, 0x70, 0x7b, 0x19, 0xe6, 0x6a, 0xdd, + 0x4d, 0x27, 0x0c, 0x9d, 0x96, 0x1f, 0xa4, 0xba, 0xee, 0x69, 0x28, 0x75, 0x9d, 0x5e, 0xcf, 0xf5, + 0xda, 0xac, 0xef, 0x18, 0x9d, 0xa9, 0x83, 0xfd, 0x6a, 0x69, 0x4d, 0x96, 0xa1, 0x86, 0xda, 0xff, + 0x71, 0x0c, 0x2a, 0x35, 0xcf, 0xe9, 0xec, 0x85, 0x6e, 0x88, 0x7d, 0x8f, 0x7c, 0x16, 0x4a, 0x6c, + 0xd5, 0x6a, 0x39, 0x91, 0x23, 0x67, 0xfa, 0x47, 0x16, 0xc4, 0x22, 0xb2, 0x60, 0x2e, 0x22, 0xf1, + 0xe7, 0x33, 0xec, 0x85, 0xdd, 0x8f, 0x2e, 0xdc, 0xda, 0xbc, 0x4b, 0x9b, 0xd1, 0x1a, 0x8d, 0x9c, + 0x3a, 0x91, 0xbd, 0x00, 0x71, 0x19, 0x6a, 0xaa, 0xc4, 0x87, 0xf1, 0xb0, 0x47, 0x9b, 0x72, 0xe6, + 0xae, 0x8d, 0x38, 0x43, 0x62, 0xd1, 0x1b, 0x3d, 0xda, 0xac, 0x4f, 0x49, 0xd6, 0xe3, 0xec, 0x1f, + 0x72, 0x46, 0xe4, 0x1e, 0x4c, 0x84, 0x7c, 0x2d, 0x93, 0x93, 0xf2, 0x56, 0x7e, 0x2c, 0x39, 0xd9, + 0xfa, 0xb4, 0x64, 0x3a, 0x21, 0xfe, 0xa3, 0x64, 0x67, 0xff, 0x27, 0x0b, 0x2e, 0x18, 0xd8, 0xb5, + 0xa0, 0xdd, 0xef, 0x52, 0x2f, 0x22, 0x57, 0x60, 0xdc, 0x73, 0xba, 0x54, 0xce, 0x2a, 0x2d, 0xf2, + 0x4d, 0xa7, 0x4b, 0x91, 0x43, 0xc8, 0x93, 0x50, 0xdc, 0x75, 0x3a, 0x7d, 0xca, 0x1b, 0xa9, 0x5c, + 0x3f, 0x27, 0x51, 0x8a, 0x6f, 0xb0, 0x42, 0x14, 0x30, 0xf2, 0x36, 0x94, 0xf9, 0x8f, 0x6b, 0x81, + 0xdf, 0xcd, 0xe9, 0xd3, 0xa4, 0x84, 0x6f, 0x28, 0xb2, 0x62, 0xf8, 0xe9, 0xbf, 0x18, 0x33, 0xb4, + 0xff, 0xc8, 0x82, 0x19, 0xe3, 0xe3, 0x56, 0xdd, 0x30, 0x22, 0x9f, 0x19, 0x18, 0x3c, 0x0b, 0xc7, + 0x1b, 0x3c, 0xac, 0x36, 0x1f, 0x3a, 0xb3, 0xf2, 0x4b, 0x4b, 0xaa, 0xc4, 0x18, 0x38, 0x1e, 0x14, + 0xdd, 0x88, 0x76, 0xc3, 0xb9, 0xb1, 0x2b, 0x85, 0xa7, 0x2b, 0xcf, 0xad, 0xe4, 0xd6, 0x8d, 0x71, + 0xfb, 0xae, 0x30, 0xfa, 0x28, 0xd8, 0xd8, 0xdf, 0x29, 0x24, 0xba, 0x6f, 0x4d, 0xc9, 0xf1, 0xae, + 0x05, 0x13, 0x1d, 0x67, 0x93, 0x76, 0xc4, 0xdc, 0xaa, 0x3c, 0xf7, 0x66, 0x6e, 0x92, 0x28, 0x1e, + 0x0b, 0xab, 0x9c, 0xfe, 0x55, 0x2f, 0x0a, 0xf6, 0xe2, 0xe1, 0x25, 0x0a, 0x51, 0x32, 0x27, 0x7f, + 0xcb, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, + 0x25, 0xda, 0x80, 0xa0, 0x29, 0xcb, 0xfc, 0xc7, 0xa0, 0x62, 0x7c, 0x02, 0x99, 0x85, 0xc2, 0x0e, + 0xdd, 0x13, 0x03, 0x1e, 0xd9, 0x4f, 0x72, 0x31, 0x31, 0xc2, 0xe5, 0x90, 0xfe, 0xf8, 0xd8, 0x4b, + 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x29, 0x26, 0x06, 0x26, 0x5b, + 0x08, 0x88, 0x0f, 0x93, 0x5d, 0x1a, 0x05, 0x6e, 0x53, 0x75, 0xd9, 0xf2, 0x68, 0xad, 0xb4, 0xc6, + 0x89, 0xc5, 0x1b, 0xa2, 0xf8, 0x1f, 0xa2, 0xe2, 0x42, 0xb6, 0x61, 0xdc, 0x09, 0xda, 0xaa, 0x4f, + 0xae, 0xe5, 0x33, 0x2d, 0xe3, 0xa5, 0xa2, 0x16, 0xb4, 0x43, 0xe4, 0x1c, 0xc8, 0x22, 0x94, 0x23, + 0x1a, 0x74, 0x5d, 0xcf, 0x89, 0xc4, 0x0e, 0x5a, 0xaa, 0x9f, 0x97, 0x68, 0xe5, 0x0d, 0x05, 0xc0, + 0x18, 0x87, 0x74, 0x60, 0xa2, 0x15, 0xec, 0x61, 0xdf, 0x9b, 0x1b, 0xcf, 0xa3, 0x29, 0x96, 0x39, + 0xad, 0x78, 0x90, 0x8a, 0xff, 0x28, 0x79, 0x90, 0x5f, 0xb3, 0xe0, 0x62, 0x97, 0x3a, 0x61, 0x3f, + 0xa0, 0xec, 0x13, 0x90, 0x46, 0xd4, 0x63, 0x1d, 0x3b, 0x57, 0xe4, 0xcc, 0x71, 0xd4, 0x7e, 0x18, + 0xa4, 0x5c, 0x7f, 0x5c, 0x8a, 0x72, 0x31, 0x0b, 0x8a, 0x99, 0xd2, 0x90, 0xb7, 0xa1, 0x12, 0x45, + 0x9d, 0x46, 0xc4, 0xf4, 0xe0, 0xf6, 0xde, 0xdc, 0x04, 0x5f, 0xbc, 0x46, 0x5c, 0x61, 0x36, 0x36, + 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x51, 0x84, 0xf3, + 0x03, 0xdb, 0x0a, 0x79, 0x01, 0x8a, 0xbd, 0x6d, 0x27, 0x54, 0xfb, 0xc4, 0x65, 0xb5, 0x48, 0xad, + 0xb3, 0xc2, 0xf7, 0xf6, 0xab, 0xe7, 0x54, 0x15, 0x5e, 0x80, 0x02, 0x99, 0x69, 0x6d, 0x5d, 0x1a, + 0x86, 0x4e, 0x5b, 0x6d, 0x1e, 0xc6, 0x20, 0xe5, 0xc5, 0xa8, 0xe0, 0xe4, 0x17, 0x2c, 0x38, 0x27, + 0x06, 0x2c, 0xd2, 0xb0, 0xdf, 0x89, 0xd8, 0x06, 0xc9, 0x3a, 0xe5, 0x46, 0x1e, 0x93, 0x43, 0x90, + 0xac, 0x5f, 0x92, 0xdc, 0xcf, 0x99, 0xa5, 0x21, 0x26, 0xf9, 0x92, 0x3b, 0x50, 0x0e, 0x23, 0x27, + 0x88, 0x68, 0xab, 0x16, 0x71, 0x55, 0xae, 0xf2, 0xdc, 0x4f, 0x1d, 0x6f, 0xe7, 0xd8, 0x70, 0xbb, + 0x54, 0xec, 0x52, 0x0d, 0x45, 0x00, 0x63, 0x5a, 0xe4, 0x6d, 0x80, 0xa0, 0xef, 0x35, 0xfa, 0xdd, + 0xae, 0x13, 0xec, 0x49, 0xed, 0xee, 0xfa, 0x68, 0x9f, 0x87, 0x9a, 0x5e, 0xac, 0xe8, 0xc4, 0x65, + 0x68, 0xf0, 0x23, 0x5f, 0xb4, 0xe0, 0x9c, 0x98, 0x07, 0x4a, 0x82, 0x89, 0x9c, 0x25, 0x38, 0xcf, + 0x9a, 0x76, 0xd9, 0x64, 0x81, 0x49, 0x8e, 0xe4, 0x4d, 0xa8, 0x34, 0xfd, 0x6e, 0xaf, 0x43, 0x45, + 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0xf7, 0x49, + 0x1d, 0x47, 0x0d, 0x69, 0xf2, 0x69, 0x78, 0x34, 0xec, 0x37, 0x9b, 0x34, 0x0c, 0xb7, 0xfa, 0x1d, + 0xec, 0x7b, 0xd7, 0xdd, 0x30, 0xf2, 0x83, 0xbd, 0x55, 0xb7, 0xeb, 0x46, 0x7c, 0x40, 0x17, 0xeb, + 0x4f, 0x1c, 0xec, 0x57, 0x1f, 0x6d, 0x0c, 0x43, 0xc2, 0xe1, 0xf5, 0x89, 0x03, 0x8f, 0xf5, 0xbd, + 0xe1, 0xe4, 0xc5, 0xf1, 0xa3, 0x7a, 0xb0, 0x5f, 0x7d, 0xec, 0xf6, 0x70, 0x34, 0x3c, 0x8c, 0x86, + 0xfd, 0x27, 0x16, 0xdb, 0x86, 0xc4, 0x77, 0x6d, 0xd0, 0x6e, 0xaf, 0xc3, 0x96, 0xce, 0xb3, 0x57, + 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0x5f, 0x2d, + 0xb8, 0x98, 0x46, 0x7e, 0x00, 0x0a, 0x5d, 0x98, 0x54, 0xe8, 0x6e, 0xe6, 0xfb, 0xb5, 0x43, 0xb4, + 0xba, 0x5f, 0x34, 0x06, 0xac, 0x42, 0x45, 0xba, 0x45, 0x5e, 0x82, 0xa9, 0x48, 0xfe, 0xbd, 0x19, + 0x2b, 0xe7, 0xda, 0x30, 0xb1, 0x61, 0xc0, 0x30, 0x81, 0xc9, 0x6a, 0x36, 0x3b, 0xfd, 0x30, 0xa2, + 0x41, 0xa3, 0xe9, 0xf7, 0xc4, 0xb2, 0x5b, 0x8a, 0x6b, 0x2e, 0x19, 0x30, 0x4c, 0x60, 0xda, 0x7f, + 0xad, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, + 0x0f, 0x94, 0xfa, 0xf1, 0x25, 0x8b, 0x69, 0x71, 0x62, 0x00, 0x84, 0x52, 0x35, 0x7a, 0x3d, 0xdf, + 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x60, 0x1c, 0xa6, 0x6a, + 0x5e, 0xe4, 0xd6, 0xb6, 0xb6, 0x5c, 0xcf, 0x8d, 0xf6, 0xc8, 0xd7, 0xc7, 0x60, 0xb1, 0x17, 0xd0, + 0x2d, 0x1a, 0x04, 0xb4, 0xb5, 0xdc, 0x0f, 0x5c, 0xaf, 0xdd, 0x68, 0x6e, 0xd3, 0x56, 0xbf, 0xe3, + 0x7a, 0xed, 0x95, 0xb6, 0xe7, 0xeb, 0xe2, 0xab, 0xf7, 0x69, 0xb3, 0xcf, 0xdb, 0x55, 0xac, 0x12, + 0xdd, 0xd1, 0x64, 0x5f, 0x3f, 0x19, 0xd3, 0xfa, 0xf3, 0x07, 0xfb, 0xd5, 0xc5, 0x13, 0x56, 0xc2, + 0x93, 0x7e, 0x1a, 0xf9, 0xea, 0x18, 0x2c, 0x04, 0xf4, 0x73, 0x7d, 0xf7, 0xf8, 0xad, 0x21, 0x96, + 0xf1, 0xce, 0x88, 0xdb, 0xfd, 0x89, 0x78, 0xd6, 0x9f, 0x3b, 0xd8, 0xaf, 0x9e, 0xb0, 0x0e, 0x9e, + 0xf0, 0xbb, 0xec, 0x75, 0xa8, 0xd4, 0x7a, 0x6e, 0xe8, 0xde, 0x47, 0xbf, 0x1f, 0xd1, 0x63, 0x18, + 0x34, 0xaa, 0x50, 0x0c, 0xfa, 0x1d, 0x2a, 0x16, 0x98, 0x72, 0xbd, 0xcc, 0x96, 0x65, 0x64, 0x05, + 0x28, 0xca, 0xed, 0x2f, 0xb1, 0x2d, 0x88, 0x93, 0x4c, 0x99, 0xb2, 0xee, 0x42, 0x31, 0x60, 0x4c, + 0xe4, 0xc8, 0x1a, 0xf5, 0xd4, 0x1f, 0x4b, 0x2d, 0x85, 0x60, 0x3f, 0x51, 0xb0, 0xb0, 0xbf, 0x3b, + 0x06, 0x97, 0x6a, 0xbd, 0xde, 0x1a, 0x0d, 0xb7, 0x53, 0x52, 0xfc, 0x92, 0x05, 0xd3, 0xbb, 0x6e, + 0x10, 0xf5, 0x9d, 0x8e, 0xb2, 0x56, 0x0a, 0x79, 0x1a, 0xa3, 0xca, 0xc3, 0xb9, 0xbd, 0x91, 0x20, + 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x69, 0xc1, 0xac, 0x2c, + 0xba, 0xe9, 0xb7, 0xa8, 0x69, 0x0d, 0xbf, 0x9d, 0xa7, 0x4c, 0x9a, 0xb8, 0xb0, 0x62, 0xa6, 0x4b, + 0x71, 0x40, 0x08, 0xfb, 0xbf, 0x8f, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, + 0xa1, 0x1b, 0x20, 0xa4, 0x5b, 0xb2, 0x35, 0x3f, 0x99, 0xb7, 0xe4, 0xc8, 0xa6, 0x38, 0xf5, 0x9a, + 0xb4, 0x3e, 0xc7, 0x96, 0xe4, 0xa5, 0x0c, 0xd6, 0x98, 0x29, 0x10, 0x97, 0x54, 0x18, 0xd5, 0x53, + 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc0, 0x63, 0x87, + 0x90, 0x3b, 0x7a, 0x72, 0xda, 0x6f, 0xea, 0x51, 0x9f, 0x1c, 0x73, 0xc7, 0x98, 0xd7, 0x36, 0x4c, + 0xf0, 0xa9, 0xa3, 0x26, 0x36, 0xb0, 0x3d, 0x98, 0xcf, 0xa9, 0x10, 0x25, 0xc4, 0xfe, 0xae, 0x05, + 0xa5, 0x13, 0xd8, 0x3e, 0xab, 0x49, 0xdb, 0x67, 0x79, 0xc0, 0xee, 0x19, 0x0d, 0xda, 0x3d, 0x5f, + 0x1d, 0xad, 0x37, 0x8e, 0x63, 0xef, 0xfc, 0x91, 0x05, 0xe7, 0x07, 0xec, 0xa3, 0x64, 0x1b, 0x2e, + 0xf6, 0xfc, 0x96, 0xda, 0x4e, 0xaf, 0x3b, 0xe1, 0x36, 0x87, 0xc9, 0xcf, 0x7b, 0x81, 0xf5, 0xe4, + 0x7a, 0x06, 0xfc, 0xbd, 0xfd, 0xea, 0x9c, 0x26, 0x92, 0x42, 0xc0, 0x4c, 0x8a, 0xa4, 0x07, 0xa5, + 0x2d, 0x97, 0x76, 0x5a, 0xf1, 0x10, 0x1c, 0x51, 0x4b, 0xbb, 0x26, 0xa9, 0x89, 0xab, 0x01, 0xf5, + 0x0f, 0x35, 0x17, 0xfb, 0xc7, 0x16, 0x4c, 0xd7, 0xfa, 0xd1, 0x36, 0xd3, 0x51, 0x9a, 0xdc, 0x1a, + 0x47, 0x3c, 0x28, 0x86, 0x6e, 0x7b, 0xf7, 0x85, 0x7c, 0x16, 0xe3, 0x06, 0x23, 0x25, 0xaf, 0x48, + 0xb4, 0xb2, 0xce, 0x0b, 0x51, 0xb0, 0x21, 0x01, 0x4c, 0xf8, 0x4e, 0x3f, 0xda, 0x7e, 0x4e, 0x7e, + 0xf2, 0x88, 0x96, 0x89, 0x5b, 0xec, 0x73, 0x9e, 0x93, 0x1c, 0xb5, 0xca, 0x28, 0x4a, 0x51, 0x72, + 0xb2, 0xbf, 0x00, 0xd3, 0xc9, 0x7b, 0xb7, 0x63, 0x8c, 0xd9, 0x27, 0xa0, 0xe0, 0x04, 0x9e, 0x1c, + 0xb1, 0x15, 0x89, 0x50, 0xa8, 0xe1, 0x4d, 0x64, 0xe5, 0xe4, 0x59, 0x28, 0x6d, 0xf5, 0x3b, 0x1d, + 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0xf7, 0x38, + 0xcc, 0xd4, 0x3b, 0x7d, 0xfa, 0x6a, 0x40, 0xa9, 0xb2, 0x05, 0xd5, 0x60, 0xa6, 0x17, 0xd0, 0x5d, + 0x97, 0xde, 0x6b, 0xd0, 0x0e, 0x6d, 0x46, 0x7e, 0x20, 0xa5, 0x79, 0x44, 0x12, 0x9a, 0x59, 0x4f, + 0x82, 0x31, 0x8d, 0x4f, 0x5e, 0x81, 0x69, 0xa7, 0x19, 0xb9, 0xbb, 0x54, 0x53, 0x10, 0xe2, 0x3e, + 0x2c, 0x29, 0x4c, 0xd7, 0x12, 0x50, 0x4c, 0x61, 0x93, 0xcf, 0xc0, 0x5c, 0xd8, 0x74, 0x3a, 0xf4, + 0x76, 0x4f, 0xb2, 0x5a, 0xda, 0xa6, 0xcd, 0x9d, 0x75, 0xdf, 0xf5, 0x22, 0x69, 0x77, 0xbc, 0x22, + 0x29, 0xcd, 0x35, 0x86, 0xe0, 0xe1, 0x50, 0x0a, 0xe4, 0x5f, 0x5a, 0xf0, 0x44, 0x2f, 0xa0, 0xeb, + 0x81, 0xdf, 0xf5, 0xd9, 0x50, 0x1b, 0x30, 0x87, 0x49, 0xb3, 0xd0, 0x1b, 0x23, 0xea, 0x52, 0xa2, + 0x64, 0xf0, 0x0e, 0xe7, 0x27, 0x0e, 0xf6, 0xab, 0x4f, 0xac, 0x1f, 0x26, 0x00, 0x1e, 0x2e, 0x1f, + 0xf9, 0x57, 0x16, 0x5c, 0xee, 0xf9, 0x61, 0x74, 0xc8, 0x27, 0x14, 0xcf, 0xf4, 0x13, 0xec, 0x83, 0xfd, 0xea, 0xe5, 0xf5, 0x43, 0x25, 0xc0, 0x23, 0x24, 0xb4, 0x0f, 0x2a, 0x70, 0xde, 0x18, 0x7b, - 0xd2, 0x98, 0xf3, 0x12, 0x9c, 0x53, 0x83, 0x21, 0xd6, 0x7d, 0xca, 0xb1, 0x6d, 0xaf, 0x66, 0x02, + 0xd2, 0x98, 0xf3, 0x32, 0x9c, 0x53, 0x83, 0x21, 0xd6, 0x7d, 0xca, 0xb1, 0x6d, 0xaf, 0x66, 0x02, 0x31, 0x89, 0xcb, 0xc6, 0x9d, 0x1e, 0x8a, 0xa2, 0x76, 0x6a, 0xdc, 0xad, 0x27, 0xa0, 0x98, 0xc2, 0x26, 0x2b, 0x70, 0x41, 0x96, 0x20, 0xed, 0x75, 0xdc, 0xa6, 0xb3, 0xe4, 0xf7, 0xe5, 0x90, 0x2b, - 0xd6, 0x1f, 0x3e, 0xd8, 0xaf, 0x5e, 0x58, 0x1f, 0x04, 0x63, 0x56, 0x1d, 0xb2, 0x0a, 0x17, 0x9d, + 0xd6, 0x1f, 0x39, 0xd8, 0xaf, 0x5e, 0x58, 0x1f, 0x04, 0x63, 0x56, 0x1d, 0xb2, 0x0a, 0x17, 0x9d, 0x7e, 0xe4, 0xeb, 0xef, 0xbf, 0xea, 0xb1, 0xed, 0xb4, 0xc5, 0x87, 0x56, 0x49, 0xec, 0xbb, 0xb5, 0x0c, 0x38, 0x66, 0xd6, 0x22, 0xeb, 0x29, 0x6a, 0x0d, 0xda, 0xf4, 0xbd, 0x96, 0xe8, 0xe5, 0x62, 0x7c, 0x0c, 0xac, 0x65, 0xe0, 0x60, 0x66, 0x4d, 0xd2, 0x81, 0xe9, 0xae, 0x73, 0xff, 0xb6, 0xe7, 0xec, 0x3a, 0x6e, 0x87, 0x31, 0x91, 0xf6, 0xc2, 0xe1, 0x56, 0xa6, 0x7e, 0xe4, 0x76, 0x16, 0x84, 0x1f, 0xc7, 0xc2, 0x8a, 0x17, 0xdd, 0x0a, 0x1a, 0x11, 0xd3, 0xd4, 0x85, 0x06, 0xb9, 0x96, 0xa0, 0x85, 0x29, 0xda, 0xe4, 0x16, 0x5c, 0xe2, 0xd3, 0x71, 0xd9, 0xbf, 0xe7, 0x2d, 0xd3, 0x8e, 0xb3, - 0xa7, 0x3e, 0x60, 0x92, 0x7f, 0xc0, 0x23, 0x07, 0xfb, 0xd5, 0x4b, 0x8d, 0x2c, 0x04, 0xcc, 0xae, - 0x47, 0x1c, 0x78, 0x34, 0x09, 0x40, 0xba, 0xeb, 0x86, 0xae, 0xef, 0x09, 0xb3, 0x5c, 0x29, 0x36, + 0xa7, 0x3e, 0x60, 0x92, 0x7f, 0xc0, 0xa3, 0x07, 0xfb, 0xd5, 0x4b, 0x8d, 0x2c, 0x04, 0xcc, 0xae, + 0x47, 0x1c, 0x78, 0x2c, 0x09, 0x40, 0xba, 0xeb, 0x86, 0xae, 0xef, 0x09, 0xb3, 0x5c, 0x29, 0x36, 0xcb, 0x35, 0x86, 0xa3, 0xe1, 0x61, 0x34, 0xc8, 0xdf, 0xb1, 0xe0, 0x62, 0xd6, 0x34, 0x9c, 0x2b, - 0xe7, 0x71, 0x9b, 0x9c, 0x9a, 0x5a, 0x62, 0x44, 0x64, 0x2e, 0x0a, 0x99, 0x42, 0x90, 0xb7, 0x2d, + 0xe7, 0x71, 0x9b, 0x9c, 0x9a, 0x5a, 0x62, 0x44, 0x64, 0x2e, 0x0a, 0x99, 0x42, 0x90, 0x77, 0x2c, 0x98, 0x72, 0x8c, 0x13, 0xf4, 0x1c, 0xe4, 0xb1, 0x6b, 0x99, 0x67, 0xf2, 0xfa, 0xec, 0xc1, 0x7e, 0x35, 0x71, 0x4a, 0xc7, 0x04, 0x47, 0xf2, 0xf7, 0x2c, 0xb8, 0x94, 0x39, 0xc7, 0xe7, 0x2a, 0x67, 0xd1, 0x42, 0x7c, 0x90, 0x64, 0xaf, 0x39, 0xd9, 0x62, 0x90, 0x6f, 0x5a, 0x7a, 0x2b, 0x53, 0x17, 0x8c, 0x73, 0x53, 0x5c, 0xb4, 0x11, 0x0d, 0x1e, 0x86, 0x1a, 0xa5, 0x08, 0xd7, 0x2f, 0x18, 0x3b, 0xa3, 0x2a, 0xc4, 0x34, 0x7b, 0xf2, 0x0d, 0x4b, 0x6d, 0x8d, 0x5a, 0xa2, 0x73, 0x67, 0x25, 0x11, - 0x89, 0x77, 0x5a, 0x2d, 0x50, 0x8a, 0x39, 0xf9, 0x19, 0x98, 0x77, 0x36, 0xfd, 0x20, 0xca, 0x9c, + 0x89, 0x77, 0x5a, 0x2d, 0x50, 0x8a, 0x39, 0xf9, 0x59, 0x98, 0x77, 0x36, 0xfd, 0x20, 0xca, 0x9c, 0x7c, 0x73, 0xd3, 0x7c, 0x1a, 0x5d, 0x3e, 0xd8, 0xaf, 0xce, 0xd7, 0x86, 0x62, 0xe1, 0x21, 0x14, - 0xec, 0xdf, 0x99, 0x80, 0x29, 0x71, 0x12, 0x92, 0x5b, 0xd7, 0x6f, 0x5a, 0xf0, 0x58, 0xb3, 0x1f, + 0xec, 0xdf, 0x9d, 0x80, 0x29, 0x71, 0x12, 0x92, 0x5b, 0xd7, 0x6f, 0x59, 0xf0, 0x78, 0xb3, 0x1f, 0x04, 0xd4, 0x8b, 0x1a, 0x11, 0xed, 0x0d, 0x6e, 0x5c, 0xd6, 0x99, 0x6e, 0x5c, 0x57, 0x0e, 0xf6, - 0xab, 0x8f, 0x2d, 0x1d, 0xc2, 0x1f, 0x0f, 0x95, 0x8e, 0xfc, 0x7b, 0x0b, 0x6c, 0x89, 0x50, 0x77, - 0x9a, 0x3b, 0xed, 0xc0, 0xef, 0x7b, 0xad, 0xc1, 0x8f, 0x18, 0x3b, 0xd3, 0x8f, 0x78, 0xf2, 0x60, - 0xbf, 0x6a, 0x2f, 0x1d, 0x29, 0x05, 0x1e, 0x43, 0x52, 0xf2, 0x0a, 0x9c, 0x97, 0x58, 0x57, 0xef, + 0xab, 0x8f, 0x2f, 0x1d, 0xc2, 0x1f, 0x0f, 0x95, 0x8e, 0xfc, 0x3b, 0x0b, 0x6c, 0x89, 0x50, 0x77, + 0x9a, 0x3b, 0xed, 0xc0, 0xef, 0x7b, 0xad, 0xc1, 0x8f, 0x18, 0x3b, 0xd3, 0x8f, 0x78, 0xea, 0x60, + 0xbf, 0x6a, 0x2f, 0x1d, 0x29, 0x05, 0x1e, 0x43, 0x52, 0xf2, 0x2a, 0x9c, 0x97, 0x58, 0x57, 0xef, 0xf7, 0x68, 0xe0, 0xb2, 0x33, 0x87, 0x54, 0x1c, 0x63, 0xdf, 0xb4, 0x34, 0x02, 0x0e, 0xd6, 0x21, 0x21, 0x4c, 0xde, 0xa3, 0x6e, 0x7b, 0x3b, 0x52, 0xea, 0xd3, 0x88, 0x0e, 0x69, 0xd2, 0x2a, 0x72, 0x47, 0xd0, 0xac, 0x57, 0x0e, 0xf6, 0xab, 0x93, 0xf2, 0x0f, 0x2a, 0x4e, 0xe4, 0x26, 0x4c, 0x8b, - 0x73, 0xea, 0xba, 0xeb, 0xb5, 0xd7, 0x7d, 0x4f, 0x78, 0x55, 0x95, 0xeb, 0x4f, 0xaa, 0x0d, 0xbf, - 0x91, 0x80, 0xbe, 0xbb, 0x5f, 0x9d, 0x52, 0xbf, 0x37, 0xf6, 0x7a, 0x14, 0x53, 0xb5, 0xc9, 0xdf, + 0x73, 0xea, 0xba, 0xeb, 0xb5, 0xd7, 0x7d, 0x4f, 0x78, 0x55, 0x95, 0xeb, 0x4f, 0xa9, 0x0d, 0xbf, + 0x91, 0x80, 0xbe, 0xb7, 0x5f, 0x9d, 0x52, 0xbf, 0x37, 0xf6, 0x7a, 0x14, 0x53, 0xb5, 0xc9, 0xdf, 0xb6, 0x80, 0x84, 0x11, 0xed, 0xad, 0x77, 0xfa, 0x6d, 0x57, 0x36, 0x91, 0xf4, 0x8f, 0xca, 0xc1, 0x55, 0x2b, 0x49, 0xb7, 0x3e, 0x2f, 0x85, 0x24, 0x8d, 0x01, 0x8e, 0x98, 0x21, 0x85, 0xfd, 0x9d, 0x49, 0x00, 0x35, 0x97, 0x68, 0x8f, 0x7c, 0x08, 0xca, 0x21, 0x8d, 0x44, 0x93, 0xc8, 0x6b, 0x2e, @@ -3605,355 +3605,354 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0x65, 0xcb, 0x03, 0x18, 0x98, 0x51, 0x8b, 0x44, 0x50, 0xea, 0x29, 0xe5, 0x73, 0x26, 0x8f, 0xd1, 0xaf, 0x94, 0x51, 0xe1, 0x42, 0xc3, 0x26, 0x9e, 0x2a, 0x41, 0xcd, 0x89, 0xac, 0xc2, 0xc5, 0xae, 0xeb, 0xad, 0xfb, 0xad, 0x70, 0x9d, 0x06, 0xd2, 0xf0, 0xd4, 0xa0, 0xd1, 0xdc, 0x2c, 0x6f, 0x1b, - 0x6e, 0x4c, 0x58, 0xcb, 0x80, 0x63, 0x66, 0x2d, 0xfb, 0x7f, 0x5b, 0x30, 0xbb, 0xd4, 0xf1, 0xfb, - 0xad, 0x3b, 0x4e, 0xd4, 0xdc, 0x16, 0x1e, 0x1b, 0xe4, 0x65, 0x28, 0xb9, 0x5e, 0x44, 0x83, 0x5d, - 0xa7, 0x23, 0xf7, 0x27, 0x5b, 0x59, 0x92, 0x57, 0x64, 0xf9, 0xbb, 0xfb, 0xd5, 0xe9, 0xe5, 0x7e, + 0x6e, 0x4c, 0x58, 0xcb, 0x80, 0x63, 0x66, 0x2d, 0xfb, 0x7f, 0x59, 0x30, 0xbb, 0xd4, 0xf1, 0xfb, + 0xad, 0x3b, 0x4e, 0xd4, 0xdc, 0x16, 0x1e, 0x1b, 0xe4, 0x15, 0x28, 0xb9, 0x5e, 0x44, 0x83, 0x5d, + 0xa7, 0x23, 0xf7, 0x27, 0x5b, 0x59, 0x92, 0x57, 0x64, 0xf9, 0x7b, 0xfb, 0xd5, 0xe9, 0xe5, 0x7e, 0xc0, 0x0d, 0xf6, 0x62, 0xb5, 0x42, 0x5d, 0x87, 0x7c, 0xdb, 0x82, 0xf3, 0xc2, 0xe7, 0x63, 0xd9, - 0x89, 0x9c, 0xd7, 0xfa, 0x34, 0x70, 0xa9, 0xf2, 0xfa, 0x18, 0x71, 0xa1, 0x4a, 0xcb, 0xaa, 0x18, - 0xec, 0xc5, 0x67, 0x96, 0xb5, 0x34, 0x67, 0x1c, 0x14, 0xc6, 0xfe, 0xa5, 0x02, 0x3c, 0x32, 0x94, + 0x89, 0x9c, 0xd7, 0xfb, 0x34, 0x70, 0xa9, 0xf2, 0xfa, 0x18, 0x71, 0xa1, 0x4a, 0xcb, 0xaa, 0x18, + 0xec, 0xc5, 0x67, 0x96, 0xb5, 0x34, 0x67, 0x1c, 0x14, 0xc6, 0xfe, 0xe5, 0x02, 0x3c, 0x3a, 0x94, 0x16, 0x99, 0x87, 0x31, 0xb7, 0x25, 0x3f, 0x1d, 0x24, 0xdd, 0xb1, 0x95, 0x16, 0x8e, 0xb9, 0x2d, 0xb2, 0xc0, 0x35, 0xdc, 0x80, 0x86, 0xa1, 0xba, 0x7b, 0x2f, 0x6b, 0x65, 0x54, 0x96, 0xa2, 0x81, 0x41, 0xaa, 0x50, 0xe4, 0xae, 0xd4, 0xf2, 0x68, 0xc5, 0x75, 0x66, 0xee, 0xb5, 0x8c, 0xa2, 0x9c, 0x7c, 0xc9, 0x02, 0x10, 0x02, 0x32, 0x7d, 0x5f, 0xee, 0x92, 0x98, 0x6f, 0x33, 0x31, 0xca, 0x42, 0xca, 0xf8, 0x3f, 0x1a, 0x5c, 0xc9, 0x06, 0x4c, 0x30, 0xf5, 0xd9, 0x6f, 0x9d, 0x7a, 0x53, 0x14, 0x0a, 0x10, 0xa7, 0x81, 0x92, 0x16, 0x6b, 0xab, 0x80, 0x46, 0xfd, 0xc0, 0x63, 0x4d, 0xcb, 0xb7, - 0xc1, 0x92, 0x90, 0x02, 0x75, 0x29, 0x1a, 0x18, 0xf6, 0xbf, 0x18, 0x83, 0x8b, 0x59, 0xa2, 0xb3, - 0xdd, 0x66, 0x42, 0x48, 0x2b, 0xad, 0x04, 0x3f, 0x9d, 0x7f, 0xfb, 0x48, 0xf7, 0x25, 0x7d, 0x63, - 0x23, 0x7d, 0x49, 0x25, 0x5f, 0xf2, 0xd3, 0xba, 0x85, 0xc6, 0x4e, 0xd9, 0x42, 0x9a, 0x72, 0xaa, + 0xc1, 0x92, 0x90, 0x02, 0x75, 0x29, 0x1a, 0x18, 0xf6, 0x3f, 0x1f, 0x83, 0x8b, 0x59, 0xa2, 0xb3, + 0xdd, 0x66, 0x42, 0x48, 0x2b, 0xad, 0x04, 0x3f, 0x93, 0x7f, 0xfb, 0x48, 0xf7, 0x25, 0x7d, 0x63, + 0x23, 0x7d, 0x49, 0x25, 0x5f, 0xf2, 0x33, 0xba, 0x85, 0xc6, 0x4e, 0xd9, 0x42, 0x9a, 0x72, 0xaa, 0x95, 0xae, 0xc0, 0x78, 0xc8, 0x7a, 0xbe, 0x90, 0xbc, 0xf9, 0xe1, 0x7d, 0xc4, 0x21, 0x0c, 0xa3, 0xef, 0xb9, 0x91, 0x8c, 0x3f, 0xd2, 0x18, 0xb7, 0x3d, 0x37, 0x42, 0x0e, 0xb1, 0xbf, 0x35, 0x06, 0xf3, 0xc3, 0x3f, 0x8a, 0x7c, 0xcb, 0x02, 0x68, 0xb1, 0xc3, 0x51, 0xc8, 0x9d, 0xf8, 0x85, 0xbb, 0x97, 0x73, 0x56, 0x6d, 0xb8, 0xac, 0x38, 0xc5, 0x7e, 0x88, 0xba, 0x28, 0x44, 0x43, 0x10, 0xf2, - 0xac, 0x1a, 0xfa, 0xfc, 0xd6, 0x4a, 0x4c, 0x26, 0x5d, 0x67, 0x4d, 0x43, 0xd0, 0xc0, 0x62, 0xa7, + 0x9c, 0x1a, 0xfa, 0xfc, 0xd6, 0x4a, 0x4c, 0x26, 0x5d, 0x67, 0x4d, 0x43, 0xd0, 0xc0, 0x62, 0xa7, 0x5f, 0xcf, 0xe9, 0xd2, 0xb0, 0xe7, 0xe8, 0x68, 0x2e, 0x7e, 0xfa, 0xbd, 0xa9, 0x0a, 0x31, 0x86, - 0xdb, 0x1d, 0x78, 0xe2, 0x18, 0x72, 0xe6, 0x14, 0x2c, 0x63, 0xff, 0x4f, 0x0b, 0x1e, 0x96, 0x9e, - 0x78, 0x7f, 0x66, 0xdc, 0x3a, 0xff, 0xc4, 0x82, 0x47, 0x87, 0x7c, 0xf3, 0x03, 0xf0, 0xee, 0x7c, - 0x33, 0xe9, 0xdd, 0x79, 0x7b, 0xd4, 0x21, 0x9d, 0xf9, 0x1d, 0x43, 0x9c, 0x3c, 0x7f, 0xa7, 0x00, - 0xe7, 0xd8, 0xb2, 0xd5, 0xf2, 0xdb, 0x39, 0x6d, 0x9c, 0x4f, 0x40, 0xf1, 0x73, 0x6c, 0x03, 0x4a, - 0x0f, 0x32, 0xbe, 0x2b, 0xa1, 0x80, 0x91, 0x2f, 0x5b, 0x30, 0xf9, 0x39, 0xb9, 0xa7, 0x8a, 0xb3, - 0xdc, 0x88, 0x8b, 0x61, 0xe2, 0x1b, 0x16, 0xe4, 0x0e, 0x29, 0x62, 0x70, 0xb4, 0x2f, 0xa7, 0xda, - 0x4a, 0x15, 0x67, 0xf2, 0x34, 0x4c, 0x6e, 0xf9, 0x41, 0xb7, 0xdf, 0x71, 0xd2, 0x81, 0x9f, 0xd7, - 0x44, 0x31, 0x2a, 0x38, 0x9b, 0xe4, 0x4e, 0xcf, 0x7d, 0x9d, 0x06, 0xa1, 0x08, 0xc9, 0x48, 0x4c, - 0xf2, 0x9a, 0x86, 0xa0, 0x81, 0xc5, 0xeb, 0xb4, 0xdb, 0x01, 0x6d, 0x3b, 0x91, 0x1f, 0xf0, 0x9d, - 0xc3, 0xac, 0xa3, 0x21, 0x68, 0x60, 0xcd, 0x7f, 0x1c, 0xa6, 0x4c, 0xe1, 0x4f, 0x14, 0xcf, 0xf3, - 0x09, 0x90, 0x4e, 0x9d, 0xa9, 0x25, 0xc9, 0x3a, 0xce, 0x92, 0x64, 0xff, 0xc7, 0x31, 0x30, 0x6c, - 0x51, 0x0f, 0x60, 0xaa, 0x7b, 0x89, 0xa9, 0x3e, 0xa2, 0x1d, 0xc5, 0xb0, 0xac, 0x0d, 0x8b, 0x6e, - 0xdc, 0x4d, 0x45, 0x37, 0xde, 0xcc, 0x8d, 0xe3, 0xe1, 0xc1, 0x8d, 0x3f, 0xb0, 0xe0, 0xd1, 0x18, - 0x79, 0xd0, 0x86, 0x7d, 0xf4, 0xba, 0xfd, 0x02, 0x54, 0x9c, 0xb8, 0x9a, 0x9c, 0x58, 0x46, 0x68, - 0x99, 0x06, 0xa1, 0x89, 0x17, 0x87, 0xc5, 0x14, 0x4e, 0x19, 0x16, 0x33, 0x7e, 0x78, 0x58, 0x8c, - 0xfd, 0xe3, 0x31, 0x78, 0x7c, 0xf0, 0xcb, 0x4c, 0x5f, 0xf1, 0xa3, 0xbf, 0x2d, 0xed, 0x4d, 0x3e, - 0x76, 0x6a, 0x6f, 0xf2, 0xc2, 0x71, 0xbd, 0xc9, 0xb5, 0x0f, 0xf7, 0xf8, 0x99, 0xfb, 0x70, 0x37, - 0xe0, 0x92, 0x72, 0x18, 0xbd, 0xe6, 0x07, 0x32, 0x36, 0x44, 0xad, 0x20, 0xa5, 0xfa, 0xe3, 0xb2, - 0xca, 0x25, 0xcc, 0x42, 0xc2, 0xec, 0xba, 0xf6, 0x0f, 0x0a, 0x70, 0x21, 0x6e, 0xf6, 0x25, 0xdf, - 0x6b, 0xb9, 0xdc, 0xe7, 0xe8, 0x25, 0x18, 0x8f, 0xf6, 0x7a, 0xaa, 0xb1, 0xff, 0xa2, 0x12, 0x67, - 0x63, 0xaf, 0xc7, 0x7a, 0xfb, 0xe1, 0x8c, 0x2a, 0xfc, 0x16, 0x81, 0x57, 0x22, 0xab, 0x7a, 0x76, - 0x88, 0x1e, 0x78, 0x3e, 0x39, 0x9a, 0xdf, 0xdd, 0xaf, 0x66, 0x64, 0x79, 0x58, 0xd0, 0x94, 0x92, - 0x63, 0x9e, 0xdc, 0x85, 0xe9, 0x8e, 0x13, 0x46, 0xb7, 0x7b, 0x2d, 0x27, 0xa2, 0x1b, 0xae, 0xf4, - 0xe6, 0x39, 0x59, 0x38, 0x8d, 0x76, 0x7b, 0x58, 0x4d, 0x50, 0xc2, 0x14, 0x65, 0xb2, 0x0b, 0x84, - 0x95, 0x6c, 0x04, 0x8e, 0x17, 0x8a, 0xaf, 0x62, 0xfc, 0x4e, 0x1e, 0x1b, 0xa5, 0x8f, 0xce, 0xab, - 0x03, 0xd4, 0x30, 0x83, 0x03, 0x79, 0x12, 0x26, 0x02, 0xea, 0x84, 0x7a, 0x3b, 0xd0, 0xf3, 0x1f, - 0x79, 0x29, 0x4a, 0xa8, 0x39, 0xa1, 0x26, 0x8e, 0x98, 0x50, 0x7f, 0x60, 0xc1, 0x74, 0xdc, 0x4d, - 0x0f, 0x40, 0xf5, 0xe8, 0x26, 0x55, 0x8f, 0xeb, 0x79, 0x2d, 0x89, 0x43, 0xb4, 0x8d, 0x3f, 0x9e, - 0x34, 0xbf, 0x8f, 0x07, 0x70, 0x7c, 0xde, 0xf4, 0xe7, 0xb7, 0xf2, 0x88, 0xaa, 0x4b, 0x68, 0x7b, - 0x87, 0x3a, 0xf2, 0x33, 0x5d, 0xa7, 0x25, 0xf5, 0x18, 0x39, 0xec, 0xb5, 0xae, 0xa3, 0xf4, 0x9b, - 0x2c, 0x5d, 0x47, 0xd5, 0x21, 0xb7, 0xe1, 0xe1, 0x5e, 0xe0, 0xf3, 0x3c, 0x03, 0xcb, 0xd4, 0x69, - 0x75, 0x5c, 0x8f, 0x2a, 0x33, 0x8f, 0xf0, 0xba, 0x79, 0xf4, 0x60, 0xbf, 0xfa, 0xf0, 0x7a, 0x36, - 0x0a, 0x0e, 0xab, 0x9b, 0x8c, 0x54, 0x1d, 0x3f, 0x46, 0xa4, 0xea, 0x2f, 0x68, 0x63, 0xaa, 0x0e, - 0x8a, 0xf8, 0x74, 0x5e, 0x5d, 0x99, 0x15, 0x1e, 0xa1, 0x87, 0x54, 0x4d, 0x32, 0x45, 0xcd, 0x7e, - 0xb8, 0xc5, 0x6e, 0xe2, 0x94, 0x16, 0xbb, 0x38, 0x0e, 0x66, 0xf2, 0xbd, 0x8c, 0x83, 0x29, 0xbd, - 0xaf, 0xe2, 0x60, 0xbe, 0x6d, 0xc1, 0x05, 0x67, 0x30, 0x02, 0x3d, 0x1f, 0xe3, 0x71, 0x46, 0x68, - 0x7b, 0xfd, 0x51, 0x29, 0x64, 0x56, 0xa0, 0x3f, 0x66, 0x89, 0x62, 0xbf, 0x53, 0x84, 0xd9, 0xb4, - 0x92, 0x74, 0xf6, 0xa1, 0xba, 0x7f, 0xc3, 0x82, 0x59, 0x35, 0xc1, 0xf5, 0x0d, 0xb8, 0x38, 0x62, - 0xac, 0xe6, 0xb4, 0xae, 0x08, 0x75, 0x4f, 0x67, 0x50, 0xd9, 0x48, 0x71, 0xc3, 0x01, 0xfe, 0xe4, - 0x0d, 0xa8, 0xe8, 0x5b, 0x95, 0x53, 0xc5, 0xed, 0xf2, 0xd0, 0xd2, 0x5a, 0x4c, 0x02, 0x4d, 0x7a, - 0xe4, 0x1d, 0x0b, 0xa0, 0xa9, 0x76, 0xe2, 0x9c, 0xa2, 0xa2, 0x32, 0xb4, 0x85, 0x58, 0x9f, 0xd7, - 0x45, 0x21, 0x1a, 0x8c, 0xc9, 0x2f, 0xf1, 0xfb, 0x14, 0x3d, 0x12, 0x94, 0xe7, 0xc1, 0x27, 0xf3, - 0x5e, 0x8a, 0x62, 0x5f, 0x12, 0xad, 0xed, 0x19, 0xa0, 0x10, 0x13, 0x42, 0xd8, 0x2f, 0x81, 0xf6, - 0xd9, 0x66, 0x2b, 0x2b, 0xf7, 0xda, 0x5e, 0x77, 0xa2, 0x6d, 0x39, 0x04, 0xf5, 0xca, 0x7a, 0x4d, - 0x01, 0x30, 0xc6, 0xb1, 0x3f, 0x0b, 0xd3, 0xaf, 0x04, 0x4e, 0x6f, 0xdb, 0xe5, 0xf7, 0x16, 0xec, - 0x7c, 0xfc, 0x34, 0x4c, 0x3a, 0xad, 0x56, 0x56, 0xb2, 0x9f, 0x9a, 0x28, 0x46, 0x05, 0x3f, 0xd6, - 0x51, 0xd8, 0xfe, 0xb7, 0x16, 0x90, 0xf8, 0xa6, 0xd9, 0xf5, 0xda, 0x6b, 0x4e, 0xd4, 0xdc, 0x66, - 0x47, 0xb8, 0x6d, 0x5e, 0x9a, 0x75, 0x84, 0xbb, 0xae, 0x21, 0x68, 0x60, 0x91, 0xb7, 0xa0, 0x22, - 0xfe, 0xbd, 0xae, 0x0f, 0x88, 0xa3, 0xbb, 0x9e, 0xf3, 0x3d, 0x8f, 0xcb, 0x24, 0x46, 0xe1, 0xf5, - 0x98, 0x03, 0x9a, 0xec, 0x58, 0x53, 0xad, 0x78, 0x5b, 0x9d, 0xfe, 0xfd, 0xd6, 0x66, 0xdc, 0x54, - 0xbd, 0xc0, 0xdf, 0x72, 0x3b, 0x34, 0xdd, 0x54, 0xeb, 0xa2, 0x18, 0x15, 0xfc, 0x78, 0x4d, 0xf5, - 0x6f, 0x2c, 0xb8, 0xb8, 0x12, 0x46, 0xae, 0xbf, 0x4c, 0xc3, 0x88, 0xed, 0x7c, 0x6c, 0x7d, 0xec, - 0x77, 0x8e, 0x13, 0x7e, 0xb1, 0x0c, 0xb3, 0xf2, 0x1e, 0xba, 0xbf, 0x19, 0xd2, 0xc8, 0x38, 0x6a, - 0xe8, 0x79, 0xbc, 0x94, 0x82, 0xe3, 0x40, 0x0d, 0x46, 0x45, 0x5e, 0x48, 0xc7, 0x54, 0x0a, 0x49, - 0x2a, 0x8d, 0x14, 0x1c, 0x07, 0x6a, 0xd8, 0xdf, 0x2f, 0xc0, 0x05, 0xfe, 0x19, 0xa9, 0xd0, 0xa9, - 0x6f, 0x0c, 0x0b, 0x9d, 0x1a, 0x71, 0x2a, 0x73, 0x5e, 0xa7, 0x08, 0x9c, 0xfa, 0xeb, 0x16, 0xcc, - 0xb4, 0x92, 0x2d, 0x9d, 0x8f, 0x5d, 0x2e, 0xab, 0x0f, 0x85, 0x07, 0x62, 0xaa, 0x10, 0xd3, 0xfc, - 0xc9, 0x2f, 0x5b, 0x30, 0x93, 0x14, 0x53, 0xad, 0xee, 0x67, 0xd0, 0x48, 0x3a, 0x64, 0x20, 0x59, - 0x1e, 0x62, 0x5a, 0x04, 0xfb, 0x77, 0xc7, 0x64, 0x97, 0x9e, 0x45, 0x5c, 0x10, 0xb9, 0x07, 0xe5, - 0xa8, 0x13, 0x8a, 0x42, 0xf9, 0xb5, 0x23, 0x1e, 0x5a, 0x37, 0x56, 0x1b, 0xc2, 0xe1, 0x24, 0xd6, - 0x2b, 0x65, 0x09, 0xd3, 0x8f, 0x15, 0x2f, 0xce, 0xb8, 0xd9, 0x93, 0x8c, 0x73, 0x39, 0x2d, 0x6f, - 0x2c, 0xad, 0xa7, 0x19, 0xcb, 0x12, 0xc6, 0x58, 0xf1, 0xb2, 0x7f, 0xdd, 0x82, 0xf2, 0x0d, 0x5f, - 0xad, 0x23, 0x3f, 0x93, 0x83, 0x2d, 0x4a, 0xab, 0xac, 0x5a, 0x69, 0x89, 0x4f, 0x41, 0x2f, 0x27, - 0x2c, 0x51, 0x8f, 0x19, 0xb4, 0x17, 0x78, 0xce, 0x43, 0x46, 0xea, 0x86, 0xbf, 0x39, 0xd4, 0x7c, - 0xfc, 0x2b, 0x45, 0x38, 0xf7, 0xaa, 0xb3, 0x47, 0xbd, 0xc8, 0x39, 0xf9, 0x26, 0xf1, 0x02, 0x54, - 0x9c, 0x1e, 0xbf, 0xcb, 0x34, 0x8e, 0x21, 0xb1, 0x71, 0x27, 0x06, 0xa1, 0x89, 0x17, 0x2f, 0x68, - 0x22, 0x48, 0x27, 0x6b, 0x29, 0x5a, 0x4a, 0xc1, 0x71, 0xa0, 0x06, 0xb9, 0x01, 0x44, 0x06, 0xb6, - 0xd7, 0x9a, 0x4d, 0xbf, 0xef, 0x89, 0x25, 0x4d, 0xd8, 0x7d, 0xf4, 0x79, 0x78, 0x6d, 0x00, 0x03, - 0x33, 0x6a, 0x91, 0xcf, 0xc0, 0x5c, 0x93, 0x53, 0x96, 0xa7, 0x23, 0x93, 0xa2, 0x38, 0x21, 0xeb, - 0xb0, 0x97, 0xa5, 0x21, 0x78, 0x38, 0x94, 0x02, 0x93, 0x34, 0x8c, 0xfc, 0xc0, 0x69, 0x53, 0x93, - 0xee, 0x44, 0x52, 0xd2, 0xc6, 0x00, 0x06, 0x66, 0xd4, 0x22, 0x5f, 0x80, 0x72, 0xb4, 0x1d, 0xd0, - 0x70, 0xdb, 0xef, 0xb4, 0xa4, 0xef, 0xc9, 0x88, 0xc6, 0x40, 0xd9, 0xfb, 0x1b, 0x8a, 0xaa, 0x31, - 0xbc, 0x55, 0x11, 0xc6, 0x3c, 0x49, 0x00, 0x13, 0x61, 0xd3, 0xef, 0xd1, 0x50, 0x9e, 0x2a, 0x6e, - 0xe4, 0xc2, 0x9d, 0x1b, 0xb7, 0x0c, 0x33, 0x24, 0xe7, 0x80, 0x92, 0x93, 0xfd, 0xdb, 0x63, 0x30, - 0x65, 0x22, 0x1e, 0x63, 0x6d, 0xfa, 0xb2, 0x05, 0x53, 0x4d, 0xdf, 0x8b, 0x02, 0xbf, 0x13, 0x27, - 0x6c, 0x18, 0x5d, 0xa3, 0x60, 0xa4, 0x96, 0x69, 0xe4, 0xb8, 0x1d, 0xc3, 0x5a, 0x67, 0xb0, 0xc1, - 0x04, 0x53, 0xf2, 0x75, 0x0b, 0x66, 0x62, 0xc7, 0xc8, 0xd8, 0xd6, 0x97, 0xab, 0x20, 0x7a, 0xa9, - 0xbf, 0x9a, 0xe4, 0x84, 0x69, 0xd6, 0xf6, 0x26, 0xcc, 0xa6, 0x7b, 0x9b, 0x35, 0x65, 0xcf, 0x91, - 0x73, 0xbd, 0x10, 0x37, 0xe5, 0xba, 0x13, 0x86, 0xc8, 0x21, 0xe4, 0x19, 0x28, 0x75, 0x9d, 0xa0, - 0xed, 0x7a, 0x4e, 0x87, 0xb7, 0x62, 0xc1, 0x58, 0x90, 0x64, 0x39, 0x6a, 0x0c, 0xfb, 0x23, 0x30, - 0xb5, 0xe6, 0x78, 0x6d, 0xda, 0x92, 0xeb, 0xf0, 0xd1, 0x91, 0xa9, 0x7f, 0x34, 0x0e, 0x15, 0xe3, - 0xf8, 0x78, 0xf6, 0xe7, 0xac, 0x44, 0x22, 0xa2, 0x42, 0x8e, 0x89, 0x88, 0x3e, 0x05, 0xb0, 0xe5, - 0x7a, 0x6e, 0xb8, 0x7d, 0xca, 0x14, 0x47, 0xfc, 0x6e, 0xfe, 0x9a, 0xa6, 0x80, 0x06, 0xb5, 0xf8, - 0x02, 0xb4, 0x78, 0x48, 0xb6, 0xc0, 0x77, 0x2c, 0x63, 0xbb, 0x99, 0xc8, 0xc3, 0xe1, 0xc3, 0xe8, - 0x98, 0x05, 0xb5, 0xfd, 0x88, 0xbb, 0xa9, 0xc3, 0x76, 0xa5, 0x0d, 0x28, 0x05, 0x34, 0xec, 0x77, - 0xe9, 0xa9, 0x92, 0x11, 0x71, 0xd7, 0x1b, 0x94, 0xf5, 0x51, 0x53, 0x9a, 0x7f, 0x09, 0xce, 0x25, - 0x44, 0x38, 0xd1, 0x0d, 0x93, 0x0f, 0x99, 0x36, 0x8a, 0xd3, 0xdc, 0x37, 0xb1, 0xbe, 0xe8, 0x18, - 0x49, 0x88, 0x74, 0x5f, 0x08, 0x07, 0x2b, 0x01, 0xb3, 0x7f, 0x3c, 0x01, 0xd2, 0x87, 0xe1, 0x18, - 0xcb, 0x95, 0x79, 0x73, 0x39, 0x76, 0x8a, 0x9b, 0xcb, 0x1b, 0x30, 0xe5, 0x7a, 0x6e, 0xe4, 0x3a, - 0x1d, 0x6e, 0x7f, 0x92, 0xdb, 0xa9, 0x72, 0xc6, 0x9f, 0x5a, 0x31, 0x60, 0x19, 0x74, 0x12, 0x75, - 0xc9, 0x6b, 0x50, 0xe4, 0xfb, 0x8d, 0x1c, 0xc0, 0x27, 0x77, 0xb4, 0xe0, 0x3e, 0x36, 0x22, 0x42, - 0x4f, 0x50, 0xe2, 0x87, 0x0f, 0x91, 0x85, 0x49, 0x1f, 0xbf, 0xe5, 0x38, 0x8e, 0x0f, 0x1f, 0x29, - 0x38, 0x0e, 0xd4, 0x60, 0x54, 0xb6, 0x1c, 0xb7, 0xd3, 0x0f, 0x68, 0x4c, 0x65, 0x22, 0x49, 0xe5, - 0x5a, 0x0a, 0x8e, 0x03, 0x35, 0xc8, 0x16, 0x4c, 0xc9, 0x32, 0xe1, 0x36, 0x37, 0x79, 0xca, 0xaf, - 0xe4, 0xee, 0x91, 0xd7, 0x0c, 0x4a, 0x98, 0xa0, 0x4b, 0xfa, 0x70, 0xde, 0xf5, 0x9a, 0xbe, 0xd7, - 0xec, 0xf4, 0x43, 0x77, 0x97, 0xc6, 0xe1, 0x71, 0xa7, 0x61, 0x76, 0xe9, 0x60, 0xbf, 0x7a, 0x7e, - 0x25, 0x4d, 0x0e, 0x07, 0x39, 0x90, 0x2f, 0x5a, 0x70, 0xa9, 0xe9, 0x7b, 0x21, 0xcf, 0xe2, 0xb1, - 0x4b, 0xaf, 0x06, 0x81, 0x1f, 0x08, 0xde, 0xe5, 0x53, 0xf2, 0xe6, 0x66, 0xcf, 0xa5, 0x2c, 0x92, - 0x98, 0xcd, 0x89, 0xbc, 0x09, 0xa5, 0x5e, 0xe0, 0xef, 0xba, 0x2d, 0x1a, 0x48, 0x17, 0xcc, 0xd5, - 0x3c, 0x52, 0x1b, 0xad, 0x4b, 0x9a, 0xf1, 0xd2, 0xa3, 0x4a, 0x50, 0xf3, 0xb3, 0xff, 0x6f, 0x05, - 0xa6, 0x93, 0xe8, 0xe4, 0xe7, 0x00, 0x7a, 0x81, 0xdf, 0xa5, 0xd1, 0x36, 0xd5, 0x61, 0x4e, 0x37, - 0x47, 0x4d, 0x5e, 0xa3, 0xe8, 0x29, 0xb7, 0x25, 0xb6, 0x5c, 0xc4, 0xa5, 0x68, 0x70, 0x24, 0x01, - 0x4c, 0xee, 0x88, 0x6d, 0x57, 0x6a, 0x21, 0xaf, 0xe6, 0xa2, 0x33, 0x49, 0xce, 0x3c, 0x3e, 0x47, - 0x16, 0xa1, 0x62, 0x44, 0x36, 0xa1, 0x70, 0x8f, 0x6e, 0xe6, 0x93, 0x39, 0xe1, 0x0e, 0x95, 0xa7, - 0x99, 0xfa, 0xe4, 0xc1, 0x7e, 0xb5, 0x70, 0x87, 0x6e, 0x22, 0x23, 0xce, 0xbe, 0xab, 0x25, 0x7c, - 0x17, 0xe4, 0x52, 0xf1, 0x6a, 0x8e, 0x8e, 0x10, 0xe2, 0xbb, 0x64, 0x11, 0x2a, 0x46, 0xe4, 0x4d, - 0x28, 0xdf, 0x73, 0x76, 0xe9, 0x56, 0xe0, 0x7b, 0x91, 0xf4, 0x95, 0x1b, 0x31, 0xb8, 0xe4, 0x8e, - 0x22, 0x27, 0xf9, 0xf2, 0xed, 0x5d, 0x17, 0x62, 0xcc, 0x8e, 0xec, 0x42, 0xc9, 0xa3, 0xf7, 0x90, - 0x76, 0xdc, 0x66, 0x3e, 0xc1, 0x1c, 0x37, 0x25, 0x35, 0xc9, 0x99, 0xef, 0x7b, 0xaa, 0x0c, 0x35, - 0x2f, 0xd6, 0x97, 0x77, 0xfd, 0x4d, 0xb9, 0x50, 0x8d, 0xd8, 0x97, 0xfa, 0x64, 0x2a, 0xfa, 0xf2, - 0x86, 0xbf, 0x89, 0x8c, 0x38, 0x9b, 0x23, 0x4d, 0xed, 0xa8, 0x25, 0x97, 0xa9, 0x9b, 0xf9, 0x3a, - 0xa8, 0x89, 0x39, 0x12, 0x97, 0xa2, 0xc1, 0x91, 0xb5, 0x6d, 0x5b, 0x1a, 0x2b, 0xe5, 0x42, 0x35, - 0x62, 0xdb, 0x26, 0x4d, 0x9f, 0xa2, 0x6d, 0x55, 0x19, 0x6a, 0x5e, 0x8c, 0xaf, 0x2b, 0x2d, 0x7f, - 0xf9, 0x2c, 0x55, 0x49, 0x3b, 0xa2, 0xe0, 0xab, 0xca, 0x50, 0xf3, 0x62, 0xed, 0x1d, 0xee, 0xec, - 0xdd, 0x73, 0x3a, 0x3b, 0xae, 0xd7, 0x96, 0x61, 0xbb, 0xa3, 0x86, 0xb9, 0xed, 0xec, 0xdd, 0x11, - 0xf4, 0xcc, 0xf6, 0x8e, 0x4b, 0xd1, 0xe0, 0x48, 0xfe, 0xae, 0xa5, 0x43, 0x71, 0xa6, 0xf2, 0x70, - 0x62, 0x4a, 0x2e, 0xb9, 0x32, 0x32, 0x47, 0x28, 0x8a, 0x3f, 0xa9, 0xfd, 0x2e, 0x79, 0xe1, 0xd7, - 0xfe, 0xb0, 0x3a, 0x47, 0xbd, 0xa6, 0xdf, 0x72, 0xbd, 0xf6, 0xe2, 0xdd, 0xd0, 0xf7, 0x16, 0xd0, - 0xb9, 0xa7, 0x74, 0x74, 0x29, 0xd3, 0xfc, 0xc7, 0xa0, 0x62, 0x90, 0x38, 0x4a, 0xd1, 0x9b, 0x32, - 0x15, 0xbd, 0x5f, 0x9f, 0x80, 0x29, 0x33, 0x0f, 0xe9, 0x31, 0xb4, 0x2f, 0x7d, 0xe2, 0x18, 0x3b, - 0xc9, 0x89, 0x83, 0x1d, 0x31, 0x8d, 0x0b, 0x2e, 0x65, 0xde, 0x5a, 0xc9, 0x4d, 0xe1, 0x8e, 0x8f, - 0x98, 0x46, 0x61, 0x88, 0x09, 0xa6, 0x27, 0xf0, 0x79, 0x61, 0x6a, 0xab, 0x50, 0xec, 0x8a, 0x49, - 0xb5, 0x35, 0xa1, 0xaa, 0x3d, 0x0b, 0x10, 0x27, 0xcc, 0x94, 0x17, 0x9f, 0x5a, 0x1f, 0x36, 0x12, - 0x79, 0x1a, 0x58, 0xe4, 0x49, 0x98, 0x60, 0xaa, 0x0f, 0x6d, 0xc9, 0xac, 0x02, 0xfa, 0x1c, 0x7f, - 0x8d, 0x97, 0xa2, 0x84, 0x92, 0x17, 0x99, 0x96, 0x1a, 0x2b, 0x2c, 0x32, 0x59, 0xc0, 0xc5, 0x58, - 0x4b, 0x8d, 0x61, 0x98, 0xc0, 0x64, 0xa2, 0x53, 0xa6, 0x5f, 0xf0, 0xb5, 0xc1, 0x10, 0x9d, 0x2b, - 0x1d, 0x28, 0x60, 0xdc, 0xae, 0x94, 0xd2, 0x47, 0xf8, 0x9c, 0x2e, 0x1a, 0x76, 0xa5, 0x14, 0x1c, - 0x07, 0x6a, 0xb0, 0x8f, 0x91, 0x77, 0xb6, 0x15, 0xe1, 0x30, 0x3d, 0xe4, 0xb6, 0xf5, 0x2b, 0xe6, - 0x59, 0x2b, 0xc7, 0x39, 0x24, 0x46, 0xed, 0xf1, 0x0f, 0x5b, 0xa3, 0x1d, 0x8b, 0x3e, 0x0b, 0xd3, - 0xc9, 0x5d, 0x28, 0xf7, 0x9b, 0x8f, 0xaf, 0x8e, 0xc3, 0x85, 0x9b, 0x6d, 0xd7, 0x4b, 0xe7, 0x7c, - 0xcb, 0x7a, 0xe0, 0xc1, 0x3a, 0xf1, 0x03, 0x0f, 0x3a, 0x26, 0x4f, 0x3e, 0x9f, 0x90, 0x1d, 0x93, - 0xa7, 0xde, 0xb2, 0x48, 0xe2, 0x92, 0x3f, 0xb0, 0xe0, 0x31, 0xa7, 0x25, 0xce, 0x05, 0x4e, 0x47, - 0x96, 0x1a, 0x79, 0xc9, 0xe5, 0x8c, 0x0e, 0x47, 0xdc, 0xe5, 0x07, 0x3f, 0x7e, 0xa1, 0x76, 0x08, - 0x57, 0xd1, 0xe3, 0x3f, 0x21, 0xbf, 0xe0, 0xb1, 0xc3, 0x50, 0xf1, 0x50, 0xf1, 0xc9, 0x5f, 0x86, - 0x99, 0xc4, 0x07, 0x4b, 0x4b, 0x78, 0x59, 0x5c, 0x58, 0x34, 0x92, 0x20, 0x4c, 0xe3, 0xce, 0xdf, - 0x82, 0x0f, 0x1e, 0x29, 0xe7, 0x89, 0x06, 0xdb, 0xf7, 0x2c, 0x98, 0x32, 0xd3, 0x33, 0x91, 0x67, - 0xa0, 0x14, 0xf9, 0x3b, 0xd4, 0xbb, 0x1d, 0x28, 0x87, 0x5d, 0x3d, 0xd0, 0x37, 0x78, 0x39, 0xae, - 0xa2, 0xc6, 0x60, 0xd8, 0xcd, 0x8e, 0x4b, 0xbd, 0x68, 0xa5, 0x25, 0xbb, 0x59, 0x63, 0x2f, 0x89, - 0xf2, 0x65, 0xd4, 0x18, 0xc2, 0xc7, 0x8e, 0xfd, 0x6e, 0xd0, 0x66, 0x40, 0x95, 0x7b, 0xbf, 0xe1, - 0x63, 0x17, 0xc3, 0x30, 0x81, 0x49, 0x6c, 0x6d, 0xe2, 0x1c, 0x8f, 0xef, 0x35, 0x52, 0x26, 0xc9, - 0xef, 0x58, 0x50, 0x16, 0x26, 0x7a, 0xa4, 0x5b, 0x29, 0x17, 0xdb, 0x94, 0x11, 0xa1, 0xb6, 0xbe, - 0x92, 0xe5, 0x62, 0x7b, 0x05, 0xc6, 0x77, 0x5c, 0x4f, 0x7d, 0x89, 0xde, 0x96, 0x5e, 0x75, 0xbd, - 0x16, 0x72, 0x88, 0xde, 0xb8, 0x0a, 0x43, 0x37, 0xae, 0x45, 0x28, 0x6b, 0xc7, 0x13, 0xb9, 0xfc, - 0x6b, 0xeb, 0xad, 0x76, 0x54, 0xc1, 0x18, 0xc7, 0xfe, 0x55, 0x0b, 0xa6, 0x79, 0xc4, 0x78, 0x7c, - 0x1e, 0x7e, 0x41, 0xfb, 0x82, 0x09, 0xb9, 0x1f, 0x4f, 0xfa, 0x82, 0xbd, 0xbb, 0x5f, 0xad, 0x88, - 0x18, 0xf3, 0xa4, 0x6b, 0xd8, 0xa7, 0xa5, 0x11, 0x8d, 0x7b, 0xac, 0x8d, 0x9d, 0xd8, 0xc6, 0x13, - 0x8b, 0xa9, 0x88, 0x60, 0x4c, 0xcf, 0x7e, 0x0b, 0xa6, 0xcc, 0x60, 0x2c, 0xf2, 0x02, 0x54, 0x7a, - 0xae, 0xd7, 0x4e, 0x06, 0xed, 0xea, 0x8b, 0x86, 0xf5, 0x18, 0x84, 0x26, 0x1e, 0xaf, 0xe6, 0xc7, - 0xd5, 0x52, 0xf7, 0x13, 0xeb, 0xbe, 0x59, 0x2d, 0xfe, 0x63, 0xff, 0x13, 0x0b, 0x20, 0x0e, 0x2d, - 0x3e, 0x96, 0xf5, 0x66, 0x9a, 0xc7, 0xbc, 0xdd, 0xf2, 0xa4, 0x3d, 0x40, 0x3a, 0x74, 0xc6, 0x59, - 0xb7, 0x12, 0x50, 0x4c, 0x61, 0x93, 0x97, 0x61, 0x42, 0x5c, 0x1e, 0x08, 0x6d, 0x86, 0xa7, 0x99, - 0x98, 0x10, 0x53, 0xe4, 0xdd, 0xfd, 0xc3, 0xb4, 0x25, 0x51, 0x8b, 0x3f, 0x62, 0x91, 0x11, 0xa5, - 0x98, 0xfb, 0x23, 0x16, 0x19, 0x3c, 0xde, 0xbb, 0x47, 0x2c, 0xb2, 0x84, 0xf9, 0xd3, 0xf5, 0x88, - 0xc5, 0x27, 0xe1, 0xa4, 0xf9, 0x6c, 0x99, 0x72, 0x72, 0xcf, 0xcc, 0x3b, 0xa1, 0x5b, 0x5c, 0x26, - 0x9e, 0x90, 0x50, 0xfb, 0xb7, 0x0a, 0x30, 0x9b, 0xb6, 0x51, 0xe4, 0xed, 0xfe, 0x41, 0xbe, 0x6e, - 0xc1, 0xb4, 0x93, 0xc8, 0x1d, 0x98, 0xd3, 0x8b, 0x58, 0x09, 0x9a, 0xc6, 0x2c, 0x4a, 0x94, 0x63, - 0x8a, 0x37, 0xf9, 0x0b, 0x30, 0x19, 0xb9, 0x5d, 0xea, 0xf7, 0x85, 0xe5, 0xb2, 0x20, 0x2c, 0x08, - 0x1b, 0xa2, 0x08, 0x15, 0x8c, 0xed, 0x22, 0x2e, 0x57, 0xf9, 0x02, 0x2a, 0x5d, 0x99, 0x67, 0x63, - 0x53, 0xab, 0x28, 0x47, 0x8d, 0x41, 0xee, 0xc3, 0xa4, 0x70, 0x14, 0x51, 0x1e, 0x41, 0x6b, 0x39, - 0xd9, 0x52, 0x84, 0x2f, 0x4a, 0xdc, 0x05, 0xe2, 0x7f, 0x88, 0x8a, 0x9d, 0xfd, 0x11, 0x38, 0x61, - 0x82, 0x5f, 0xfb, 0x2a, 0x10, 0xf4, 0x3b, 0x9d, 0x4d, 0xa7, 0xb9, 0x73, 0xc7, 0xf5, 0x5a, 0xfe, - 0x3d, 0xbe, 0x76, 0x2e, 0x42, 0x39, 0x90, 0x31, 0xbe, 0xa1, 0x1c, 0x35, 0x7a, 0xf1, 0x55, 0xc1, - 0xbf, 0x21, 0xc6, 0x38, 0xf6, 0xef, 0x8e, 0xc1, 0xa4, 0x0c, 0x48, 0x7f, 0x00, 0xa1, 0x14, 0x3b, - 0x89, 0x0b, 0xec, 0x95, 0x5c, 0xe2, 0xe8, 0x87, 0xc6, 0x51, 0x84, 0xa9, 0x38, 0x8a, 0x57, 0xf3, - 0x61, 0x77, 0x78, 0x10, 0xc5, 0x77, 0x8b, 0x30, 0x93, 0x0a, 0xf0, 0x4f, 0xe5, 0x02, 0xb7, 0xde, - 0x93, 0x5c, 0xe0, 0x24, 0x4c, 0xe4, 0x83, 0xcf, 0xcf, 0xf1, 0xf2, 0xcf, 0x53, 0xc3, 0xe7, 0xe5, - 0x12, 0x5b, 0x7c, 0xff, 0xb8, 0xc4, 0xfe, 0x57, 0x0b, 0x1e, 0x19, 0x9a, 0xa6, 0x82, 0x27, 0x7c, - 0x0b, 0x92, 0x50, 0xb9, 0x5e, 0xe4, 0x9c, 0xfa, 0x47, 0x5f, 0x76, 0xa7, 0x73, 0x74, 0xa5, 0xd9, - 0x93, 0xe7, 0x61, 0x8a, 0x2b, 0x94, 0x6c, 0xe5, 0x8c, 0x68, 0x4f, 0xde, 0xd5, 0xf1, 0x5b, 0x9b, - 0x86, 0x51, 0x8e, 0x09, 0x2c, 0xfb, 0xdb, 0x16, 0xcc, 0x0d, 0x4b, 0xff, 0x75, 0x0c, 0x4d, 0xf0, - 0x2f, 0xa5, 0x42, 0x51, 0xaa, 0x03, 0xa1, 0x28, 0x29, 0x5b, 0x92, 0x8a, 0x3a, 0x31, 0xcc, 0x38, - 0x85, 0x23, 0x22, 0x2d, 0x7e, 0xaf, 0x00, 0xb3, 0x52, 0xc4, 0x58, 0x8b, 0x7f, 0x31, 0x11, 0x40, - 0xf3, 0x13, 0xa9, 0x00, 0x9a, 0x8b, 0x69, 0xfc, 0x3f, 0x8f, 0x9e, 0x79, 0x7f, 0x45, 0xcf, 0x7c, - 0xad, 0x08, 0x97, 0x32, 0x13, 0x6d, 0x91, 0xaf, 0x66, 0xec, 0x14, 0x77, 0x72, 0xce, 0xe8, 0xa5, - 0x03, 0x6d, 0xcf, 0x36, 0xe4, 0xe4, 0x97, 0xcd, 0x50, 0x0f, 0xb1, 0xfa, 0x6f, 0x9d, 0x41, 0x6e, - 0xb2, 0x93, 0x46, 0x7d, 0x3c, 0xd8, 0xb7, 0xd2, 0xfe, 0x14, 0x2c, 0xf5, 0x5f, 0x2b, 0xc0, 0x53, - 0xc7, 0x6d, 0xd9, 0xf7, 0x69, 0x98, 0x64, 0x98, 0x08, 0x93, 0x7c, 0x40, 0xaa, 0xcd, 0x99, 0x44, - 0x4c, 0xfe, 0xfd, 0x71, 0xbd, 0xef, 0x0e, 0x4e, 0xd8, 0x63, 0xd9, 0x26, 0x26, 0x99, 0xea, 0xab, - 0x32, 0xca, 0xc7, 0x7b, 0xc3, 0x64, 0x43, 0x14, 0xbf, 0xbb, 0x5f, 0x3d, 0x1f, 0x67, 0xa4, 0x91, - 0x85, 0xa8, 0x2a, 0x91, 0xa7, 0xa0, 0x14, 0x08, 0xa8, 0x0a, 0x0c, 0x93, 0xee, 0x39, 0xa2, 0x0c, - 0x35, 0x94, 0x7c, 0xc1, 0x38, 0x2b, 0x8c, 0x9f, 0x55, 0xe2, 0xa5, 0xc3, 0xbc, 0x8e, 0xde, 0x80, - 0x52, 0xa8, 0xd2, 0x9e, 0x8b, 0xe9, 0xf4, 0xdc, 0x31, 0xe3, 0x0d, 0x9d, 0x4d, 0xda, 0x51, 0x39, - 0xd0, 0xc5, 0xf7, 0xe9, 0x0c, 0xe9, 0x9a, 0x24, 0xb1, 0xf5, 0xd9, 0x5b, 0xdc, 0x8a, 0xc0, 0xe0, - 0xb9, 0x9b, 0x44, 0x30, 0x29, 0xdf, 0x3e, 0x96, 0xd7, 0xb5, 0x6b, 0x39, 0x05, 0xee, 0x48, 0xb7, - 0x6e, 0x7e, 0xa4, 0x55, 0x46, 0x2b, 0xc5, 0xca, 0xfe, 0x81, 0x05, 0x15, 0x39, 0x46, 0x1e, 0x40, - 0xe0, 0xe5, 0xdd, 0x64, 0xe0, 0xe5, 0xd5, 0x5c, 0x96, 0xf0, 0x21, 0x51, 0x97, 0x77, 0x61, 0xca, - 0x4c, 0x79, 0x49, 0x3e, 0x65, 0x6c, 0x41, 0xd6, 0x28, 0x69, 0xdd, 0xd4, 0x26, 0x15, 0x6f, 0x4f, - 0xf6, 0x3f, 0x2e, 0xeb, 0x56, 0xe4, 0x07, 0x67, 0x73, 0xe4, 0x5b, 0x87, 0x8e, 0x7c, 0x73, 0xe0, - 0x8d, 0xe5, 0x3f, 0xf0, 0x5e, 0x83, 0x92, 0x5a, 0x16, 0xa5, 0x36, 0xf5, 0x84, 0xe9, 0xe7, 0xcd, - 0x54, 0x32, 0x46, 0xcc, 0x98, 0x2e, 0xfc, 0x00, 0x1c, 0x9b, 0xd2, 0xd5, 0x72, 0xad, 0xc9, 0x90, - 0x37, 0xa1, 0x72, 0xcf, 0x0f, 0x76, 0x3a, 0xbe, 0xc3, 0xdf, 0x9a, 0x80, 0x3c, 0x5c, 0x0b, 0xb4, - 0x39, 0x5c, 0x04, 0xdb, 0xdc, 0x89, 0xe9, 0xa3, 0xc9, 0x8c, 0xd4, 0x60, 0xa6, 0xeb, 0x7a, 0x48, - 0x9d, 0x96, 0x8e, 0xaf, 0x1c, 0x17, 0x79, 0xde, 0x95, 0x6e, 0xbf, 0x96, 0x04, 0x63, 0x1a, 0x9f, - 0x5b, 0x9e, 0x82, 0x84, 0xa9, 0x43, 0x26, 0x73, 0x5e, 0x1f, 0x7d, 0x30, 0x26, 0xcd, 0x27, 0x22, - 0xda, 0x24, 0x59, 0x8e, 0x29, 0xde, 0xe4, 0xf3, 0x50, 0x0a, 0xd5, 0xab, 0xa2, 0xc5, 0x1c, 0x4f, - 0x3d, 0xfa, 0x65, 0x51, 0xdd, 0x95, 0xfa, 0x69, 0x51, 0xcd, 0x90, 0xac, 0xc2, 0x45, 0x65, 0xbb, - 0x49, 0x3c, 0x90, 0x38, 0x11, 0x27, 0x24, 0xc3, 0x0c, 0x38, 0x66, 0xd6, 0x62, 0xba, 0x2d, 0x4f, - 0x25, 0x2b, 0xae, 0x72, 0x8d, 0xdb, 0x4f, 0x3e, 0xff, 0x5a, 0x28, 0xa1, 0x87, 0x85, 0x0f, 0x97, - 0x46, 0x08, 0x1f, 0x6e, 0xc0, 0xa5, 0x34, 0x88, 0xdb, 0xce, 0x79, 0x72, 0x3b, 0x63, 0x0b, 0x5d, - 0xcf, 0x42, 0xc2, 0xec, 0xba, 0xe4, 0x0e, 0x94, 0x03, 0xca, 0x4f, 0x79, 0x35, 0xe5, 0x05, 0x77, - 0x62, 0x7f, 0x5f, 0x54, 0x04, 0x30, 0xa6, 0xc5, 0xfa, 0xdd, 0x49, 0x66, 0x5e, 0x7f, 0x2d, 0xc7, - 0x67, 0xc7, 0x65, 0xdf, 0x0f, 0xc9, 0x00, 0x69, 0xff, 0xbb, 0x19, 0x38, 0x97, 0x30, 0x40, 0x91, - 0x27, 0xa0, 0xc8, 0x2f, 0x16, 0xf8, 0x6a, 0x55, 0x8a, 0x57, 0x54, 0xd1, 0x38, 0x02, 0x46, 0x7e, - 0xd1, 0x82, 0x99, 0x5e, 0xe2, 0x06, 0x48, 0x2d, 0xe4, 0x23, 0x5a, 0x6d, 0x93, 0xd7, 0x4a, 0xc6, - 0x9b, 0x25, 0x49, 0x66, 0x98, 0xe6, 0xce, 0xd6, 0x03, 0xe9, 0x34, 0xdf, 0xa1, 0x01, 0xc7, 0x96, - 0x8a, 0x9e, 0x26, 0xb1, 0x94, 0x04, 0x63, 0x1a, 0x9f, 0xf5, 0x30, 0xff, 0xba, 0x51, 0x9e, 0x96, - 0xad, 0x29, 0x02, 0x18, 0xd3, 0x22, 0x2f, 0xc3, 0xb4, 0x4c, 0xb8, 0xbd, 0xee, 0xb7, 0xae, 0x3b, - 0xe1, 0xb6, 0x3c, 0xf2, 0xe9, 0x23, 0xea, 0x52, 0x02, 0x8a, 0x29, 0x6c, 0xfe, 0x6d, 0x71, 0x56, - 0x73, 0x4e, 0x60, 0x22, 0xf9, 0xa4, 0xcb, 0x52, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0x8c, 0xb1, 0x0d, - 0x09, 0xf7, 0x0a, 0xbd, 0x1a, 0x64, 0x6c, 0x45, 0x35, 0x98, 0xe9, 0xf3, 0x13, 0x72, 0x4b, 0x01, - 0xe5, 0x7c, 0xd4, 0x0c, 0x6f, 0x27, 0xc1, 0x98, 0xc6, 0x27, 0x2f, 0xc1, 0xb9, 0x80, 0x2d, 0xb6, - 0x9a, 0x80, 0xf0, 0xb9, 0xd0, 0x57, 0xea, 0x68, 0x02, 0x31, 0x89, 0x4b, 0x5e, 0x81, 0xf3, 0x71, - 0x52, 0x56, 0x45, 0x40, 0x38, 0x61, 0xe8, 0x0c, 0x81, 0xb5, 0x34, 0x02, 0x0e, 0xd6, 0x21, 0x7f, - 0x15, 0x66, 0x8d, 0x96, 0x58, 0xf1, 0x5a, 0xf4, 0xbe, 0x4c, 0x9c, 0xc9, 0x9f, 0x28, 0x5b, 0x4a, - 0xc1, 0x70, 0x00, 0x9b, 0x7c, 0x1c, 0xa6, 0x9b, 0x7e, 0xa7, 0xc3, 0xd7, 0x38, 0xf1, 0x9c, 0x88, - 0xc8, 0x90, 0x29, 0x72, 0x89, 0x26, 0x20, 0x98, 0xc2, 0x24, 0x37, 0x80, 0xf8, 0x9b, 0x4c, 0xbd, - 0xa2, 0xad, 0x57, 0xa8, 0x47, 0xa5, 0xc6, 0x71, 0x2e, 0x19, 0xb2, 0x73, 0x6b, 0x00, 0x03, 0x33, - 0x6a, 0xf1, 0x04, 0x83, 0x46, 0x88, 0xf3, 0x74, 0x1e, 0x29, 0xcd, 0xd3, 0xf6, 0x9c, 0x23, 0xe3, - 0x9b, 0x03, 0x98, 0x10, 0x11, 0x54, 0xf9, 0xa4, 0xca, 0x34, 0x5f, 0x16, 0x88, 0xf7, 0x08, 0x51, - 0x8a, 0x92, 0x13, 0xf9, 0x39, 0x28, 0x6f, 0xaa, 0x67, 0x66, 0x78, 0x7e, 0xcc, 0x91, 0xf7, 0xc5, - 0xd4, 0x8b, 0x49, 0xb1, 0xbd, 0x42, 0x03, 0x30, 0x66, 0x49, 0x9e, 0x84, 0xca, 0xf5, 0xf5, 0x9a, - 0x1e, 0x85, 0xe7, 0x79, 0xef, 0x8f, 0xb3, 0x2a, 0x68, 0x02, 0xd8, 0x0c, 0xd3, 0xea, 0x1b, 0x49, - 0xfa, 0x15, 0x64, 0x68, 0x63, 0x0c, 0x9b, 0x3b, 0x4a, 0x60, 0x63, 0xee, 0x42, 0x0a, 0x5b, 0x96, - 0xa3, 0xc6, 0x20, 0x6f, 0x40, 0x45, 0xee, 0x17, 0x7c, 0x6d, 0xba, 0x78, 0xba, 0xf0, 0x79, 0x8c, - 0x49, 0xa0, 0x49, 0x8f, 0xdf, 0x70, 0xf3, 0xd7, 0x37, 0xe8, 0xb5, 0x7e, 0xa7, 0x33, 0x77, 0x89, - 0xaf, 0x9b, 0xf1, 0x0d, 0x77, 0x0c, 0x42, 0x13, 0x8f, 0x3c, 0xa7, 0x1c, 0xde, 0x1e, 0x4a, 0x5c, - 0xf9, 0x6b, 0x87, 0x37, 0xad, 0x74, 0x0f, 0x89, 0xb0, 0x79, 0xf8, 0x08, 0x4f, 0xb3, 0x4d, 0x98, - 0x57, 0x1a, 0xdf, 0xe0, 0x24, 0x99, 0x9b, 0x4b, 0xd8, 0x8e, 0xe6, 0xef, 0x0c, 0xc5, 0xc4, 0x43, - 0xa8, 0x90, 0x4d, 0x28, 0x38, 0x9d, 0xcd, 0xb9, 0x47, 0xf2, 0x50, 0x5d, 0x6b, 0xab, 0x75, 0x39, - 0xa2, 0xb8, 0x57, 0x6c, 0x6d, 0xb5, 0x8e, 0x8c, 0x38, 0x71, 0x61, 0xdc, 0xe9, 0x6c, 0x86, 0x73, - 0xf3, 0x7c, 0xce, 0xe6, 0xc6, 0x24, 0x36, 0x1e, 0xac, 0xd6, 0x43, 0xe4, 0x2c, 0xec, 0x2f, 0x8e, - 0xe9, 0x5b, 0x22, 0x9d, 0xad, 0xfc, 0x2d, 0x73, 0x02, 0x89, 0xe3, 0xce, 0xad, 0xdc, 0x26, 0x90, - 0x54, 0x2f, 0xce, 0x0d, 0x9d, 0x3e, 0x3d, 0xbd, 0x64, 0xe4, 0x92, 0xe6, 0x2c, 0x99, 0x89, 0x5d, - 0x9c, 0x9e, 0x93, 0x0b, 0x86, 0xfd, 0xa5, 0x8a, 0xb6, 0x82, 0xa6, 0x9c, 0xc5, 0x02, 0x28, 0xba, - 0x61, 0xe4, 0xfa, 0x39, 0x46, 0x95, 0xa7, 0x52, 0x98, 0xf3, 0xa0, 0x15, 0x0e, 0x40, 0xc1, 0x8a, - 0xf1, 0xf4, 0xda, 0xae, 0x77, 0x5f, 0x7e, 0xfe, 0x6b, 0xb9, 0x7b, 0x81, 0x09, 0x9e, 0x1c, 0x80, - 0x82, 0x15, 0xb9, 0x2b, 0x06, 0x75, 0x21, 0x8f, 0xbe, 0xae, 0xad, 0xd6, 0x53, 0xfc, 0x92, 0x83, - 0xfb, 0x2e, 0x14, 0xc2, 0xae, 0x2b, 0xd5, 0xa5, 0x11, 0x79, 0x35, 0xd6, 0x56, 0xb2, 0x78, 0x35, - 0xd6, 0x56, 0x90, 0x31, 0x21, 0x5f, 0xb1, 0x00, 0x9c, 0xee, 0xa6, 0x13, 0x86, 0x4e, 0x4b, 0x5b, - 0x67, 0x46, 0x7c, 0xa5, 0xa5, 0xa6, 0xe9, 0xa5, 0x58, 0x73, 0xbf, 0xe7, 0x18, 0x8a, 0x06, 0x67, - 0xf2, 0x26, 0x4c, 0x3a, 0xe2, 0x19, 0x4c, 0xe9, 0xc2, 0x9f, 0xcf, 0xdb, 0xae, 0x29, 0x09, 0xb8, - 0x99, 0x46, 0x82, 0x50, 0x31, 0x64, 0xbc, 0xa3, 0xc0, 0xa1, 0x5b, 0xee, 0x8e, 0x34, 0x0e, 0x35, - 0x46, 0x7e, 0xa8, 0x85, 0x11, 0xcb, 0xe2, 0x2d, 0x41, 0xa8, 0x18, 0x92, 0x9f, 0xb7, 0xe0, 0x5c, - 0xd7, 0xf1, 0x1c, 0x1d, 0x98, 0x99, 0x4f, 0xf8, 0xae, 0x19, 0xea, 0x19, 0x6b, 0x88, 0x6b, 0x26, - 0x23, 0x4c, 0xf2, 0x25, 0xbb, 0x30, 0xe1, 0xf0, 0x07, 0x7a, 0xe5, 0x51, 0x0c, 0xf3, 0x78, 0xec, - 0x37, 0xd5, 0x06, 0x7c, 0x71, 0x91, 0xcf, 0x00, 0x4b, 0x6e, 0xe4, 0xd7, 0x2c, 0x98, 0x14, 0xde, - 0xe5, 0x4c, 0x21, 0x65, 0xdf, 0xfe, 0xd9, 0x33, 0x78, 0x0a, 0x41, 0x7a, 0xbe, 0x4b, 0xf7, 0xa3, - 0x0f, 0x69, 0xd7, 0x59, 0x51, 0x7a, 0xa8, 0xef, 0xbb, 0x92, 0x8e, 0xa9, 0xbe, 0x5d, 0xe7, 0x7e, - 0xe2, 0x19, 0x1e, 0x53, 0xf5, 0x5d, 0x4b, 0xc1, 0x70, 0x00, 0x7b, 0xfe, 0xe3, 0x30, 0x65, 0xca, - 0x71, 0x22, 0xff, 0xf9, 0x1f, 0x15, 0x00, 0x78, 0x57, 0x89, 0x64, 0x2e, 0x5d, 0x9e, 0xf9, 0x79, - 0xdb, 0x6f, 0xe5, 0xf4, 0x1c, 0xa8, 0x91, 0x93, 0x05, 0x64, 0x9a, 0xe7, 0x6d, 0xbf, 0x85, 0x92, - 0x09, 0x69, 0xc3, 0x78, 0xcf, 0x89, 0xb6, 0xf3, 0x4f, 0x00, 0x53, 0x12, 0x51, 0xcd, 0xd1, 0x36, - 0x72, 0x06, 0xe4, 0x6d, 0x2b, 0xf6, 0xec, 0x29, 0xe4, 0x91, 0xbc, 0x36, 0x6e, 0xb3, 0x05, 0xe9, - 0xcb, 0x93, 0xca, 0xe1, 0x9a, 0xf6, 0xf0, 0x99, 0x7f, 0xc7, 0x82, 0x29, 0x13, 0x35, 0xa3, 0x9b, - 0x7e, 0xd6, 0xec, 0xa6, 0x3c, 0xdb, 0xc3, 0xec, 0xf1, 0xff, 0x6e, 0x01, 0x60, 0xdf, 0x6b, 0xf4, - 0xbb, 0x5d, 0xa6, 0xb6, 0xeb, 0x30, 0x01, 0xeb, 0xd8, 0x61, 0x02, 0x63, 0x27, 0x0c, 0x13, 0x28, - 0x9c, 0x28, 0x4c, 0x60, 0xfc, 0xe4, 0x61, 0x02, 0xc5, 0xe1, 0x61, 0x02, 0xf6, 0x37, 0x2d, 0x38, - 0x3f, 0xb0, 0x5f, 0x31, 0x4d, 0x3a, 0xf0, 0xfd, 0x68, 0x88, 0x8b, 0x29, 0xc6, 0x20, 0x34, 0xf1, - 0xc8, 0x32, 0xcc, 0xca, 0x77, 0x4e, 0x1a, 0xbd, 0x8e, 0x9b, 0x99, 0x9c, 0x67, 0x23, 0x05, 0xc7, - 0x81, 0x1a, 0xf6, 0x6f, 0x59, 0x50, 0x31, 0x42, 0xfa, 0xd9, 0x77, 0x70, 0x3f, 0x63, 0x29, 0x46, - 0xfc, 0xc4, 0x0b, 0xbf, 0xea, 0x12, 0x30, 0x71, 0x0d, 0xdd, 0x36, 0xb2, 0xe0, 0xc7, 0xd7, 0xd0, - 0xac, 0x14, 0x25, 0x54, 0xe4, 0x37, 0xa7, 0x3d, 0xde, 0xe8, 0x05, 0x33, 0xbf, 0x39, 0xed, 0x21, - 0x87, 0x70, 0x76, 0xec, 0x48, 0x21, 0x5d, 0x88, 0x8d, 0x17, 0x65, 0x9c, 0x20, 0x42, 0x01, 0x23, - 0x8f, 0x43, 0x81, 0x7a, 0x2d, 0x69, 0xff, 0xd0, 0xcf, 0xdf, 0x5e, 0xf5, 0x5a, 0xc8, 0xca, 0xed, - 0x5b, 0x30, 0x25, 0xdc, 0xa7, 0x5f, 0xa5, 0x7b, 0xc7, 0x7e, 0x4f, 0x97, 0x8d, 0xf6, 0xd4, 0x7b, - 0xba, 0xac, 0x3a, 0x2b, 0xb7, 0xff, 0x91, 0x05, 0xa9, 0x47, 0x96, 0x8c, 0x1b, 0x18, 0x6b, 0xe8, - 0x0d, 0x8c, 0x69, 0xb5, 0x1f, 0x3b, 0xd4, 0x6a, 0x7f, 0x03, 0x48, 0x97, 0x4d, 0x85, 0xe4, 0x42, - 0x5b, 0x48, 0xbe, 0x45, 0xb1, 0x36, 0x80, 0x81, 0x19, 0xb5, 0xec, 0x7f, 0x28, 0x84, 0x35, 0x9f, - 0x5d, 0x3a, 0xba, 0x01, 0xfa, 0x50, 0xe4, 0xa4, 0xa4, 0xfd, 0x6d, 0x44, 0xdb, 0xf5, 0x60, 0x22, - 0xae, 0xb8, 0x23, 0xe5, 0x94, 0xe7, 0xdc, 0xec, 0xdf, 0x13, 0xb2, 0x9a, 0xef, 0x32, 0x1d, 0x2d, - 0x6b, 0x37, 0x29, 0xeb, 0xf5, 0xbc, 0xd6, 0xca, 0x6c, 0x19, 0xc9, 0x02, 0x40, 0x8f, 0x06, 0x4d, - 0xea, 0x45, 0x2a, 0xb0, 0xa9, 0x28, 0x43, 0x6c, 0x75, 0x29, 0x1a, 0x18, 0xf6, 0x37, 0xd8, 0x04, - 0x8a, 0x5f, 0x9a, 0x26, 0x4f, 0xa5, 0x5d, 0x5d, 0xd3, 0x93, 0x43, 0x7b, 0xba, 0x1a, 0xe1, 0x2e, - 0x63, 0x47, 0x84, 0xbb, 0x3c, 0x0d, 0x93, 0x81, 0xdf, 0xa1, 0xb5, 0xc0, 0x4b, 0xfb, 0xe8, 0x20, - 0x2b, 0xc6, 0x9b, 0xa8, 0xe0, 0xf6, 0xaf, 0x58, 0x30, 0x9b, 0x8e, 0xc7, 0xcb, 0xdd, 0xff, 0xd6, - 0x4c, 0x1a, 0x50, 0x38, 0x79, 0xd2, 0x00, 0xfb, 0x9f, 0x15, 0x60, 0x36, 0xfd, 0x02, 0x1e, 0xe3, - 0xec, 0x72, 0x63, 0x5b, 0x6a, 0xf5, 0x17, 0x56, 0x36, 0x01, 0xd3, 0xe3, 0x65, 0x6c, 0xe8, 0x78, - 0xf9, 0xa9, 0x64, 0x02, 0xe7, 0x2b, 0x69, 0x0b, 0xc3, 0x4c, 0xcc, 0xf8, 0x94, 0x29, 0x9c, 0x93, - 0x69, 0x3c, 0x8a, 0x67, 0x96, 0xc6, 0x63, 0x22, 0xd7, 0x34, 0x1e, 0x2f, 0x6b, 0x6f, 0xab, 0xc9, - 0xd8, 0xd5, 0x5f, 0x7b, 0x5a, 0x1d, 0xe2, 0xea, 0x2f, 0x9d, 0x49, 0xdf, 0x66, 0x03, 0x2b, 0x72, - 0x9b, 0x3b, 0xae, 0x27, 0x72, 0x23, 0xb0, 0xd1, 0xfe, 0x34, 0x4c, 0x52, 0xf9, 0xca, 0xb1, 0x30, - 0xfd, 0xeb, 0x46, 0x53, 0x8f, 0x1b, 0x2b, 0x38, 0xa9, 0xc1, 0x8c, 0xba, 0xf0, 0x54, 0xf7, 0x35, - 0x22, 0xa7, 0x8b, 0xb6, 0x0f, 0x2f, 0x27, 0xc1, 0x98, 0xc6, 0xb7, 0xbf, 0x00, 0x15, 0x43, 0x91, - 0xe0, 0x7b, 0xee, 0x7d, 0xa7, 0x19, 0xa5, 0xf7, 0xaa, 0xab, 0xac, 0x10, 0x05, 0x8c, 0x5f, 0x2b, - 0x89, 0x10, 0xaf, 0xd4, 0x5e, 0x25, 0x03, 0xbb, 0x24, 0x94, 0x11, 0x0b, 0x68, 0x9b, 0xde, 0x57, - 0x0f, 0x4b, 0x28, 0x62, 0xc8, 0x0a, 0x51, 0xc0, 0xec, 0x67, 0xa0, 0xa4, 0x32, 0x6f, 0xf1, 0xf4, - 0x35, 0xea, 0xca, 0xc3, 0x4c, 0x5f, 0xe3, 0x07, 0x11, 0x72, 0x88, 0xfd, 0x3a, 0x94, 0x54, 0x82, - 0xb0, 0xa3, 0xb1, 0xd9, 0xf6, 0x11, 0x7a, 0xee, 0x75, 0x3f, 0x8c, 0x54, 0x56, 0x33, 0x71, 0x2b, - 0x7b, 0x73, 0x85, 0x97, 0xa1, 0x86, 0xda, 0x7f, 0x62, 0x41, 0x65, 0x63, 0x63, 0x55, 0x1b, 0x6b, - 0x10, 0x1e, 0x0a, 0x45, 0x0b, 0xd5, 0xb6, 0x22, 0x6a, 0xba, 0x7f, 0x88, 0x99, 0x34, 0x7f, 0xb0, - 0x5f, 0x7d, 0xa8, 0x91, 0x89, 0x81, 0x43, 0x6a, 0x92, 0x15, 0xb8, 0x60, 0x42, 0x54, 0x74, 0xc9, - 0x58, 0xfc, 0x2c, 0x76, 0x63, 0x10, 0x8c, 0x59, 0x75, 0xd2, 0xa4, 0xa4, 0x8a, 0x66, 0xbe, 0xb0, - 0xdd, 0x18, 0x04, 0x63, 0x56, 0x1d, 0xfb, 0x39, 0x98, 0x49, 0xf9, 0x25, 0x1c, 0x23, 0xcb, 0xcf, - 0x6f, 0x17, 0x60, 0xca, 0xbc, 0x9e, 0x3e, 0xc6, 0x9e, 0x73, 0xfc, 0xad, 0x3c, 0xe3, 0x4a, 0xb9, - 0x70, 0xc2, 0x2b, 0x65, 0xf3, 0x0e, 0x7f, 0xfc, 0x6c, 0xef, 0xf0, 0x8b, 0xf9, 0xdc, 0xe1, 0x1b, - 0xbe, 0x26, 0x13, 0x0f, 0xce, 0xd7, 0xe4, 0x37, 0x8b, 0x30, 0x9d, 0x4c, 0x1b, 0x7b, 0x8c, 0x9e, - 0x7c, 0x66, 0xa0, 0x27, 0x4f, 0x78, 0x87, 0x55, 0x18, 0xf5, 0x0e, 0x6b, 0x7c, 0xd4, 0x3b, 0xac, - 0xe2, 0x29, 0xee, 0xb0, 0x06, 0x6f, 0xa0, 0x26, 0x8e, 0x7d, 0x03, 0xf5, 0x89, 0xc4, 0x46, 0x11, - 0xbb, 0x6d, 0xc5, 0x9b, 0x05, 0x49, 0x76, 0xc3, 0x92, 0xdf, 0xca, 0x74, 0x27, 0x2e, 0x1d, 0xb1, - 0x8d, 0x06, 0x99, 0x5e, 0xb4, 0x27, 0xbf, 0x26, 0x7f, 0xe8, 0x04, 0x1e, 0xb4, 0x2f, 0x40, 0x45, - 0x8e, 0x27, 0x7e, 0x60, 0x82, 0xe4, 0x61, 0xab, 0x11, 0x83, 0xd0, 0xc4, 0x63, 0x03, 0xa3, 0x17, - 0x4f, 0x10, 0x7e, 0x9b, 0x5a, 0x49, 0xde, 0xa6, 0xae, 0x27, 0xc1, 0x98, 0xc6, 0xb7, 0x3f, 0x0f, - 0x97, 0x32, 0xcd, 0x66, 0xfc, 0xca, 0x82, 0xeb, 0xf2, 0xb4, 0x25, 0x11, 0x0c, 0x31, 0x52, 0xaf, - 0xc9, 0xcc, 0xdf, 0x19, 0x8a, 0x89, 0x87, 0x50, 0xb1, 0x7f, 0xa3, 0x00, 0xd3, 0xc9, 0xd7, 0x95, - 0xc9, 0x3d, 0x6d, 0x64, 0xcf, 0xc5, 0xbe, 0x2f, 0xc8, 0x1a, 0xa9, 0x48, 0x87, 0x5e, 0xce, 0xdd, - 0xe3, 0xe3, 0x6b, 0x53, 0xe7, 0x45, 0x3d, 0x3b, 0xc6, 0xf2, 0x56, 0x4c, 0xb2, 0xe3, 0x6f, 0x14, - 0xc7, 0x51, 0xcb, 0xd2, 0xf6, 0x92, 0x3b, 0xf7, 0x38, 0xfa, 0x56, 0xb3, 0x42, 0x83, 0x2d, 0xdb, - 0x5b, 0x76, 0x69, 0xe0, 0x6e, 0xb9, 0xb4, 0x25, 0xd3, 0xd4, 0xf3, 0x95, 0xfb, 0x75, 0x59, 0x86, - 0x1a, 0x6a, 0xbf, 0x3d, 0x06, 0x65, 0x9e, 0x64, 0xed, 0x5a, 0xe0, 0x77, 0xf9, 0xbb, 0x9b, 0xa1, - 0x71, 0xce, 0x95, 0xdd, 0x76, 0x63, 0xd4, 0xa7, 0x74, 0x63, 0x8a, 0x32, 0x44, 0xc1, 0x28, 0xc1, - 0x04, 0x47, 0xd2, 0x83, 0xd2, 0x96, 0x4c, 0x0a, 0x2d, 0xfb, 0x6e, 0xc4, 0xc4, 0xa6, 0x2a, 0xc5, - 0xb4, 0x68, 0x02, 0xf5, 0x0f, 0x35, 0x17, 0xdb, 0x81, 0x99, 0x54, 0x96, 0x9c, 0xdc, 0x53, 0x49, - 0xff, 0xaf, 0x71, 0x28, 0xeb, 0xd8, 0x38, 0xf2, 0xb1, 0x84, 0xd1, 0xb1, 0x5c, 0xff, 0xa0, 0xf1, - 0x28, 0xdc, 0xb6, 0xdf, 0x62, 0xe7, 0x07, 0x8d, 0x9c, 0x32, 0x20, 0x3e, 0x0e, 0x85, 0x7e, 0xd0, - 0x49, 0x5b, 0x15, 0x6e, 0xe3, 0x2a, 0xb2, 0x72, 0x33, 0x9e, 0xaf, 0xf0, 0x40, 0xe3, 0xf9, 0xd8, - 0x2e, 0xb9, 0xe9, 0xb7, 0xf6, 0xd2, 0x8f, 0xc8, 0xd5, 0xfd, 0xd6, 0x1e, 0x72, 0x08, 0x79, 0x19, - 0xa6, 0x65, 0x90, 0xa2, 0x52, 0x62, 0x8a, 0x5c, 0x4f, 0xd5, 0xce, 0x26, 0x1b, 0x09, 0x28, 0xa6, - 0xb0, 0xd9, 0x2e, 0xcb, 0x8e, 0x0d, 0x3c, 0x41, 0xf8, 0x44, 0xf2, 0x66, 0xfa, 0x46, 0xe3, 0xd6, - 0x4d, 0x6e, 0xfc, 0xd4, 0x18, 0x89, 0x38, 0xc8, 0xc9, 0x23, 0xe3, 0x20, 0x97, 0x05, 0x6d, 0x26, - 0x2d, 0xdf, 0x51, 0xa6, 0xea, 0x4f, 0x29, 0xba, 0xac, 0xec, 0xd0, 0xb3, 0x8b, 0xae, 0x99, 0x15, - 0x31, 0x5a, 0x7e, 0xef, 0x22, 0x46, 0xed, 0xdb, 0x30, 0x93, 0xea, 0x3f, 0x65, 0x94, 0xb2, 0xb2, - 0x8d, 0x52, 0xc7, 0x7b, 0x86, 0xee, 0x9f, 0x5b, 0x70, 0x7e, 0x60, 0x45, 0x3a, 0x6e, 0xe8, 0x6e, - 0x7a, 0x6f, 0x1c, 0x3b, 0xfd, 0xde, 0x58, 0x38, 0xd9, 0xde, 0x58, 0xdf, 0xfc, 0xde, 0x0f, 0x2f, - 0x7f, 0xe0, 0xfb, 0x3f, 0xbc, 0xfc, 0x81, 0xdf, 0xff, 0xe1, 0xe5, 0x0f, 0xbc, 0x7d, 0x70, 0xd9, - 0xfa, 0xde, 0xc1, 0x65, 0xeb, 0xfb, 0x07, 0x97, 0xad, 0xdf, 0x3f, 0xb8, 0x6c, 0xfd, 0x97, 0x83, - 0xcb, 0xd6, 0x37, 0xff, 0xe8, 0xf2, 0x07, 0x3e, 0xf5, 0x89, 0xb8, 0xa7, 0x16, 0x55, 0x4f, 0xf1, - 0x1f, 0x1f, 0x56, 0xfd, 0xb2, 0xd8, 0xdb, 0x69, 0x2f, 0xb2, 0x9e, 0x5a, 0xd4, 0x25, 0xaa, 0xa7, - 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x06, 0xea, 0x0d, 0x6f, 0x50, 0xaa, 0x00, 0x00, + 0xdb, 0x1d, 0x78, 0xf2, 0x18, 0x72, 0xe6, 0x14, 0x2c, 0x63, 0xff, 0x0f, 0x0b, 0x1e, 0x91, 0x9e, + 0x78, 0xff, 0xdf, 0xb8, 0x75, 0xfe, 0xa9, 0x05, 0x8f, 0x0d, 0xf9, 0xe6, 0x07, 0xe0, 0xdd, 0xf9, + 0x56, 0xd2, 0xbb, 0xf3, 0xf6, 0xa8, 0x43, 0x3a, 0xf3, 0x3b, 0x86, 0x38, 0x79, 0xfe, 0x6e, 0x01, + 0xce, 0xb1, 0x65, 0xab, 0xe5, 0xb7, 0x73, 0xda, 0x38, 0x9f, 0x84, 0xe2, 0xe7, 0xd8, 0x06, 0x94, + 0x1e, 0x64, 0x7c, 0x57, 0x42, 0x01, 0x23, 0x5f, 0xb6, 0x60, 0xf2, 0x73, 0x72, 0x4f, 0x15, 0x67, + 0xb9, 0x11, 0x17, 0xc3, 0xc4, 0x37, 0x2c, 0xc8, 0x1d, 0x52, 0xc4, 0xe0, 0x68, 0x5f, 0x4e, 0xb5, + 0x95, 0x2a, 0xce, 0xe4, 0x19, 0x98, 0xdc, 0xf2, 0x83, 0x6e, 0xbf, 0xe3, 0xa4, 0x03, 0x3f, 0xaf, + 0x89, 0x62, 0x54, 0x70, 0x36, 0xc9, 0x9d, 0x9e, 0xfb, 0x06, 0x0d, 0x42, 0x11, 0x92, 0x91, 0x98, + 0xe4, 0x35, 0x0d, 0x41, 0x03, 0x8b, 0xd7, 0x69, 0xb7, 0x03, 0xda, 0x76, 0x22, 0x3f, 0xe0, 0x3b, + 0x87, 0x59, 0x47, 0x43, 0xd0, 0xc0, 0x9a, 0xff, 0x38, 0x4c, 0x99, 0xc2, 0x9f, 0x28, 0x9e, 0xe7, + 0x13, 0x20, 0x9d, 0x3a, 0x53, 0x4b, 0x92, 0x75, 0x9c, 0x25, 0xc9, 0xfe, 0x0f, 0x63, 0x60, 0xd8, + 0xa2, 0x1e, 0xc0, 0x54, 0xf7, 0x12, 0x53, 0x7d, 0x44, 0x3b, 0x8a, 0x61, 0x59, 0x1b, 0x16, 0xdd, + 0xb8, 0x9b, 0x8a, 0x6e, 0xbc, 0x99, 0x1b, 0xc7, 0xc3, 0x83, 0x1b, 0x7f, 0x60, 0xc1, 0x63, 0x31, + 0xf2, 0xa0, 0x0d, 0xfb, 0xe8, 0x75, 0xfb, 0x45, 0xa8, 0x38, 0x71, 0x35, 0x39, 0xb1, 0x8c, 0xd0, + 0x32, 0x0d, 0x42, 0x13, 0x2f, 0x0e, 0x8b, 0x29, 0x9c, 0x32, 0x2c, 0x66, 0xfc, 0xf0, 0xb0, 0x18, + 0xfb, 0xc7, 0x63, 0xf0, 0xc4, 0xe0, 0x97, 0x99, 0xbe, 0xe2, 0x47, 0x7f, 0x5b, 0xda, 0x9b, 0x7c, + 0xec, 0xd4, 0xde, 0xe4, 0x85, 0xe3, 0x7a, 0x93, 0x6b, 0x1f, 0xee, 0xf1, 0x33, 0xf7, 0xe1, 0x6e, + 0xc0, 0x25, 0xe5, 0x30, 0x7a, 0xcd, 0x0f, 0x64, 0x6c, 0x88, 0x5a, 0x41, 0x4a, 0xf5, 0x27, 0x64, + 0x95, 0x4b, 0x98, 0x85, 0x84, 0xd9, 0x75, 0xed, 0x1f, 0x14, 0xe0, 0x42, 0xdc, 0xec, 0x4b, 0xbe, + 0xd7, 0x72, 0xb9, 0xcf, 0xd1, 0xcb, 0x30, 0x1e, 0xed, 0xf5, 0x54, 0x63, 0xff, 0x45, 0x25, 0xce, + 0xc6, 0x5e, 0x8f, 0xf5, 0xf6, 0x23, 0x19, 0x55, 0xf8, 0x2d, 0x02, 0xaf, 0x44, 0x56, 0xf5, 0xec, + 0x10, 0x3d, 0xf0, 0x42, 0x72, 0x34, 0xbf, 0xb7, 0x5f, 0xcd, 0xc8, 0xf2, 0xb0, 0xa0, 0x29, 0x25, + 0xc7, 0x3c, 0xb9, 0x0b, 0xd3, 0x1d, 0x27, 0x8c, 0x6e, 0xf7, 0x5a, 0x4e, 0x44, 0x37, 0x5c, 0xe9, + 0xcd, 0x73, 0xb2, 0x70, 0x1a, 0xed, 0xf6, 0xb0, 0x9a, 0xa0, 0x84, 0x29, 0xca, 0x64, 0x17, 0x08, + 0x2b, 0xd9, 0x08, 0x1c, 0x2f, 0x14, 0x5f, 0xc5, 0xf8, 0x9d, 0x3c, 0x36, 0x4a, 0x1f, 0x9d, 0x57, + 0x07, 0xa8, 0x61, 0x06, 0x07, 0xf2, 0x14, 0x4c, 0x04, 0xd4, 0x09, 0xf5, 0x76, 0xa0, 0xe7, 0x3f, + 0xf2, 0x52, 0x94, 0x50, 0x73, 0x42, 0x4d, 0x1c, 0x31, 0xa1, 0xfe, 0xd0, 0x82, 0xe9, 0xb8, 0x9b, + 0x1e, 0x80, 0xea, 0xd1, 0x4d, 0xaa, 0x1e, 0xd7, 0xf3, 0x5a, 0x12, 0x87, 0x68, 0x1b, 0x7f, 0x32, + 0x69, 0x7e, 0x1f, 0x0f, 0xe0, 0xf8, 0xbc, 0xe9, 0xcf, 0x6f, 0xe5, 0x11, 0x55, 0x97, 0xd0, 0xf6, + 0x0e, 0x75, 0xe4, 0x67, 0xba, 0x4e, 0x4b, 0xea, 0x31, 0x72, 0xd8, 0x6b, 0x5d, 0x47, 0xe9, 0x37, + 0x59, 0xba, 0x8e, 0xaa, 0x43, 0x6e, 0xc3, 0x23, 0xbd, 0xc0, 0xe7, 0x79, 0x06, 0x96, 0xa9, 0xd3, + 0xea, 0xb8, 0x1e, 0x55, 0x66, 0x1e, 0xe1, 0x75, 0xf3, 0xd8, 0xc1, 0x7e, 0xf5, 0x91, 0xf5, 0x6c, + 0x14, 0x1c, 0x56, 0x37, 0x19, 0xa9, 0x3a, 0x7e, 0x8c, 0x48, 0xd5, 0x5f, 0xd4, 0xc6, 0x54, 0x1d, + 0x14, 0xf1, 0xe9, 0xbc, 0xba, 0x32, 0x2b, 0x3c, 0x42, 0x0f, 0xa9, 0x9a, 0x64, 0x8a, 0x9a, 0xfd, + 0x70, 0x8b, 0xdd, 0xc4, 0x29, 0x2d, 0x76, 0x71, 0x1c, 0xcc, 0xe4, 0xfb, 0x19, 0x07, 0x53, 0xfa, + 0x40, 0xc5, 0xc1, 0x7c, 0xdb, 0x82, 0x0b, 0xce, 0x60, 0x04, 0x7a, 0x3e, 0xc6, 0xe3, 0x8c, 0xd0, + 0xf6, 0xfa, 0x63, 0x52, 0xc8, 0xac, 0x40, 0x7f, 0xcc, 0x12, 0xc5, 0x7e, 0xb7, 0x08, 0xb3, 0x69, + 0x25, 0xe9, 0xec, 0x43, 0x75, 0xff, 0x86, 0x05, 0xb3, 0x6a, 0x82, 0xeb, 0x1b, 0x70, 0x71, 0xc4, + 0x58, 0xcd, 0x69, 0x5d, 0x11, 0xea, 0x9e, 0xce, 0xa0, 0xb2, 0x91, 0xe2, 0x86, 0x03, 0xfc, 0xc9, + 0x9b, 0x50, 0xd1, 0xb7, 0x2a, 0xa7, 0x8a, 0xdb, 0xe5, 0xa1, 0xa5, 0xb5, 0x98, 0x04, 0x9a, 0xf4, + 0xc8, 0xbb, 0x16, 0x40, 0x53, 0xed, 0xc4, 0x39, 0x45, 0x45, 0x65, 0x68, 0x0b, 0xb1, 0x3e, 0xaf, + 0x8b, 0x42, 0x34, 0x18, 0x93, 0x5f, 0xe6, 0xf7, 0x29, 0x7a, 0x24, 0x28, 0xcf, 0x83, 0x4f, 0xe6, + 0xbd, 0x14, 0xc5, 0xbe, 0x24, 0x5a, 0xdb, 0x33, 0x40, 0x21, 0x26, 0x84, 0xb0, 0x5f, 0x06, 0xed, + 0xb3, 0xcd, 0x56, 0x56, 0xee, 0xb5, 0xbd, 0xee, 0x44, 0xdb, 0x72, 0x08, 0xea, 0x95, 0xf5, 0x9a, + 0x02, 0x60, 0x8c, 0x63, 0x7f, 0x16, 0xa6, 0x5f, 0x0d, 0x9c, 0xde, 0xb6, 0xcb, 0xef, 0x2d, 0xd8, + 0xf9, 0xf8, 0x19, 0x98, 0x74, 0x5a, 0xad, 0xac, 0x64, 0x3f, 0x35, 0x51, 0x8c, 0x0a, 0x7e, 0xac, + 0xa3, 0xb0, 0xfd, 0x6f, 0x2c, 0x20, 0xf1, 0x4d, 0xb3, 0xeb, 0xb5, 0xd7, 0x9c, 0xa8, 0xb9, 0xcd, + 0x8e, 0x70, 0xdb, 0xbc, 0x34, 0xeb, 0x08, 0x77, 0x5d, 0x43, 0xd0, 0xc0, 0x22, 0x6f, 0x43, 0x45, + 0xfc, 0x7b, 0x43, 0x1f, 0x10, 0x47, 0x77, 0x3d, 0xe7, 0x7b, 0x1e, 0x97, 0x49, 0x8c, 0xc2, 0xeb, + 0x31, 0x07, 0x34, 0xd9, 0xb1, 0xa6, 0x5a, 0xf1, 0xb6, 0x3a, 0xfd, 0xfb, 0xad, 0xcd, 0xb8, 0xa9, + 0x7a, 0x81, 0xbf, 0xe5, 0x76, 0x68, 0xba, 0xa9, 0xd6, 0x45, 0x31, 0x2a, 0xf8, 0xf1, 0x9a, 0xea, + 0x5f, 0x5b, 0x70, 0x71, 0x25, 0x8c, 0x5c, 0x7f, 0x99, 0x86, 0x11, 0xdb, 0xf9, 0xd8, 0xfa, 0xd8, + 0xef, 0x1c, 0x27, 0xfc, 0x62, 0x19, 0x66, 0xe5, 0x3d, 0x74, 0x7f, 0x33, 0xa4, 0x91, 0x71, 0xd4, + 0xd0, 0xf3, 0x78, 0x29, 0x05, 0xc7, 0x81, 0x1a, 0x8c, 0x8a, 0xbc, 0x90, 0x8e, 0xa9, 0x14, 0x92, + 0x54, 0x1a, 0x29, 0x38, 0x0e, 0xd4, 0xb0, 0xbf, 0x5f, 0x80, 0x0b, 0xfc, 0x33, 0x52, 0xa1, 0x53, + 0xdf, 0x18, 0x16, 0x3a, 0x35, 0xe2, 0x54, 0xe6, 0xbc, 0x4e, 0x11, 0x38, 0xf5, 0xd7, 0x2d, 0x98, + 0x69, 0x25, 0x5b, 0x3a, 0x1f, 0xbb, 0x5c, 0x56, 0x1f, 0x0a, 0x0f, 0xc4, 0x54, 0x21, 0xa6, 0xf9, + 0x93, 0x5f, 0xb1, 0x60, 0x26, 0x29, 0xa6, 0x5a, 0xdd, 0xcf, 0xa0, 0x91, 0x74, 0xc8, 0x40, 0xb2, + 0x3c, 0xc4, 0xb4, 0x08, 0xf6, 0xef, 0x8d, 0xc9, 0x2e, 0x3d, 0x8b, 0xb8, 0x20, 0x72, 0x0f, 0xca, + 0x51, 0x27, 0x14, 0x85, 0xf2, 0x6b, 0x47, 0x3c, 0xb4, 0x6e, 0xac, 0x36, 0x84, 0xc3, 0x49, 0xac, + 0x57, 0xca, 0x12, 0xa6, 0x1f, 0x2b, 0x5e, 0x9c, 0x71, 0xb3, 0x27, 0x19, 0xe7, 0x72, 0x5a, 0xde, + 0x58, 0x5a, 0x4f, 0x33, 0x96, 0x25, 0x8c, 0xb1, 0xe2, 0x65, 0xff, 0x86, 0x05, 0xe5, 0x1b, 0xbe, + 0x5a, 0x47, 0x7e, 0x36, 0x07, 0x5b, 0x94, 0x56, 0x59, 0xb5, 0xd2, 0x12, 0x9f, 0x82, 0x5e, 0x49, + 0x58, 0xa2, 0x1e, 0x37, 0x68, 0x2f, 0xf0, 0x9c, 0x87, 0x8c, 0xd4, 0x0d, 0x7f, 0x73, 0xa8, 0xf9, + 0xf8, 0x57, 0x8b, 0x70, 0xee, 0x35, 0x67, 0x8f, 0x7a, 0x91, 0x73, 0xf2, 0x4d, 0xe2, 0x45, 0xa8, + 0x38, 0x3d, 0x7e, 0x97, 0x69, 0x1c, 0x43, 0x62, 0xe3, 0x4e, 0x0c, 0x42, 0x13, 0x2f, 0x5e, 0xd0, + 0x44, 0x90, 0x4e, 0xd6, 0x52, 0xb4, 0x94, 0x82, 0xe3, 0x40, 0x0d, 0x72, 0x03, 0x88, 0x0c, 0x6c, + 0xaf, 0x35, 0x9b, 0x7e, 0xdf, 0x13, 0x4b, 0x9a, 0xb0, 0xfb, 0xe8, 0xf3, 0xf0, 0xda, 0x00, 0x06, + 0x66, 0xd4, 0x22, 0x9f, 0x81, 0xb9, 0x26, 0xa7, 0x2c, 0x4f, 0x47, 0x26, 0x45, 0x71, 0x42, 0xd6, + 0x61, 0x2f, 0x4b, 0x43, 0xf0, 0x70, 0x28, 0x05, 0x26, 0x69, 0x18, 0xf9, 0x81, 0xd3, 0xa6, 0x26, + 0xdd, 0x89, 0xa4, 0xa4, 0x8d, 0x01, 0x0c, 0xcc, 0xa8, 0x45, 0xbe, 0x00, 0xe5, 0x68, 0x3b, 0xa0, + 0xe1, 0xb6, 0xdf, 0x69, 0x49, 0xdf, 0x93, 0x11, 0x8d, 0x81, 0xb2, 0xf7, 0x37, 0x14, 0x55, 0x63, + 0x78, 0xab, 0x22, 0x8c, 0x79, 0x92, 0x00, 0x26, 0xc2, 0xa6, 0xdf, 0xa3, 0xa1, 0x3c, 0x55, 0xdc, + 0xc8, 0x85, 0x3b, 0x37, 0x6e, 0x19, 0x66, 0x48, 0xce, 0x01, 0x25, 0x27, 0xfb, 0x77, 0xc6, 0x60, + 0xca, 0x44, 0x3c, 0xc6, 0xda, 0xf4, 0x65, 0x0b, 0xa6, 0x9a, 0xbe, 0x17, 0x05, 0x7e, 0x27, 0x4e, + 0xd8, 0x30, 0xba, 0x46, 0xc1, 0x48, 0x2d, 0xd3, 0xc8, 0x71, 0x3b, 0x86, 0xb5, 0xce, 0x60, 0x83, + 0x09, 0xa6, 0xe4, 0xeb, 0x16, 0xcc, 0xc4, 0x8e, 0x91, 0xb1, 0xad, 0x2f, 0x57, 0x41, 0xf4, 0x52, + 0x7f, 0x35, 0xc9, 0x09, 0xd3, 0xac, 0xed, 0x4d, 0x98, 0x4d, 0xf7, 0x36, 0x6b, 0xca, 0x9e, 0x23, + 0xe7, 0x7a, 0x21, 0x6e, 0xca, 0x75, 0x27, 0x0c, 0x91, 0x43, 0xc8, 0xb3, 0x50, 0xea, 0x3a, 0x41, + 0xdb, 0xf5, 0x9c, 0x0e, 0x6f, 0xc5, 0x82, 0xb1, 0x20, 0xc9, 0x72, 0xd4, 0x18, 0xf6, 0x47, 0x60, + 0x6a, 0xcd, 0xf1, 0xda, 0xb4, 0x25, 0xd7, 0xe1, 0xa3, 0x23, 0x53, 0xff, 0x78, 0x1c, 0x2a, 0xc6, + 0xf1, 0xf1, 0xec, 0xcf, 0x59, 0x89, 0x44, 0x44, 0x85, 0x1c, 0x13, 0x11, 0x7d, 0x0a, 0x60, 0xcb, + 0xf5, 0xdc, 0x70, 0xfb, 0x94, 0x29, 0x8e, 0xf8, 0xdd, 0xfc, 0x35, 0x4d, 0x01, 0x0d, 0x6a, 0xf1, + 0x05, 0x68, 0xf1, 0x90, 0x6c, 0x81, 0xef, 0x5a, 0xc6, 0x76, 0x33, 0x91, 0x87, 0xc3, 0x87, 0xd1, + 0x31, 0x0b, 0x6a, 0xfb, 0x11, 0x77, 0x53, 0x87, 0xed, 0x4a, 0x1b, 0x50, 0x0a, 0x68, 0xd8, 0xef, + 0xd2, 0x53, 0x25, 0x23, 0xe2, 0xae, 0x37, 0x28, 0xeb, 0xa3, 0xa6, 0x34, 0xff, 0x32, 0x9c, 0x4b, + 0x88, 0x70, 0xa2, 0x1b, 0x26, 0x1f, 0x32, 0x6d, 0x14, 0xa7, 0xb9, 0x6f, 0x62, 0x7d, 0xd1, 0x31, + 0x92, 0x10, 0xe9, 0xbe, 0x10, 0x0e, 0x56, 0x02, 0x66, 0xff, 0x78, 0x02, 0xa4, 0x0f, 0xc3, 0x31, + 0x96, 0x2b, 0xf3, 0xe6, 0x72, 0xec, 0x14, 0x37, 0x97, 0x37, 0x60, 0xca, 0xf5, 0xdc, 0xc8, 0x75, + 0x3a, 0xdc, 0xfe, 0x24, 0xb7, 0x53, 0xe5, 0x8c, 0x3f, 0xb5, 0x62, 0xc0, 0x32, 0xe8, 0x24, 0xea, + 0x92, 0xd7, 0xa1, 0xc8, 0xf7, 0x1b, 0x39, 0x80, 0x4f, 0xee, 0x68, 0xc1, 0x7d, 0x6c, 0x44, 0x84, + 0x9e, 0xa0, 0xc4, 0x0f, 0x1f, 0x22, 0x0b, 0x93, 0x3e, 0x7e, 0xcb, 0x71, 0x1c, 0x1f, 0x3e, 0x52, + 0x70, 0x1c, 0xa8, 0xc1, 0xa8, 0x6c, 0x39, 0x6e, 0xa7, 0x1f, 0xd0, 0x98, 0xca, 0x44, 0x92, 0xca, + 0xb5, 0x14, 0x1c, 0x07, 0x6a, 0x90, 0x2d, 0x98, 0x92, 0x65, 0xc2, 0x6d, 0x6e, 0xf2, 0x94, 0x5f, + 0xc9, 0xdd, 0x23, 0xaf, 0x19, 0x94, 0x30, 0x41, 0x97, 0xf4, 0xe1, 0xbc, 0xeb, 0x35, 0x7d, 0xaf, + 0xd9, 0xe9, 0x87, 0xee, 0x2e, 0x8d, 0xc3, 0xe3, 0x4e, 0xc3, 0xec, 0xd2, 0xc1, 0x7e, 0xf5, 0xfc, + 0x4a, 0x9a, 0x1c, 0x0e, 0x72, 0x20, 0x5f, 0xb4, 0xe0, 0x52, 0xd3, 0xf7, 0x42, 0x9e, 0xc5, 0x63, + 0x97, 0x5e, 0x0d, 0x02, 0x3f, 0x10, 0xbc, 0xcb, 0xa7, 0xe4, 0xcd, 0xcd, 0x9e, 0x4b, 0x59, 0x24, + 0x31, 0x9b, 0x13, 0x79, 0x0b, 0x4a, 0xbd, 0xc0, 0xdf, 0x75, 0x5b, 0x34, 0x90, 0x2e, 0x98, 0xab, + 0x79, 0xa4, 0x36, 0x5a, 0x97, 0x34, 0xe3, 0xa5, 0x47, 0x95, 0xa0, 0xe6, 0x67, 0xff, 0x9f, 0x0a, + 0x4c, 0x27, 0xd1, 0xc9, 0xcf, 0x03, 0xf4, 0x02, 0xbf, 0x4b, 0xa3, 0x6d, 0xaa, 0xc3, 0x9c, 0x6e, + 0x8e, 0x9a, 0xbc, 0x46, 0xd1, 0x53, 0x6e, 0x4b, 0x6c, 0xb9, 0x88, 0x4b, 0xd1, 0xe0, 0x48, 0x02, + 0x98, 0xdc, 0x11, 0xdb, 0xae, 0xd4, 0x42, 0x5e, 0xcb, 0x45, 0x67, 0x92, 0x9c, 0x79, 0x7c, 0x8e, + 0x2c, 0x42, 0xc5, 0x88, 0x6c, 0x42, 0xe1, 0x1e, 0xdd, 0xcc, 0x27, 0x73, 0xc2, 0x1d, 0x2a, 0x4f, + 0x33, 0xf5, 0xc9, 0x83, 0xfd, 0x6a, 0xe1, 0x0e, 0xdd, 0x44, 0x46, 0x9c, 0x7d, 0x57, 0x4b, 0xf8, + 0x2e, 0xc8, 0xa5, 0xe2, 0xb5, 0x1c, 0x1d, 0x21, 0xc4, 0x77, 0xc9, 0x22, 0x54, 0x8c, 0xc8, 0x5b, + 0x50, 0xbe, 0xe7, 0xec, 0xd2, 0xad, 0xc0, 0xf7, 0x22, 0xe9, 0x2b, 0x37, 0x62, 0x70, 0xc9, 0x1d, + 0x45, 0x4e, 0xf2, 0xe5, 0xdb, 0xbb, 0x2e, 0xc4, 0x98, 0x1d, 0xd9, 0x85, 0x92, 0x47, 0xef, 0x21, + 0xed, 0xb8, 0xcd, 0x7c, 0x82, 0x39, 0x6e, 0x4a, 0x6a, 0x92, 0x33, 0xdf, 0xf7, 0x54, 0x19, 0x6a, + 0x5e, 0xac, 0x2f, 0xef, 0xfa, 0x9b, 0x72, 0xa1, 0x1a, 0xb1, 0x2f, 0xf5, 0xc9, 0x54, 0xf4, 0xe5, + 0x0d, 0x7f, 0x13, 0x19, 0x71, 0x36, 0x47, 0x9a, 0xda, 0x51, 0x4b, 0x2e, 0x53, 0x37, 0xf3, 0x75, + 0x50, 0x13, 0x73, 0x24, 0x2e, 0x45, 0x83, 0x23, 0x6b, 0xdb, 0xb6, 0x34, 0x56, 0xca, 0x85, 0x6a, + 0xc4, 0xb6, 0x4d, 0x9a, 0x3e, 0x45, 0xdb, 0xaa, 0x32, 0xd4, 0xbc, 0x18, 0x5f, 0x57, 0x5a, 0xfe, + 0xf2, 0x59, 0xaa, 0x92, 0x76, 0x44, 0xc1, 0x57, 0x95, 0xa1, 0xe6, 0xc5, 0xda, 0x3b, 0xdc, 0xd9, + 0xbb, 0xe7, 0x74, 0x76, 0x5c, 0xaf, 0x2d, 0xc3, 0x76, 0x47, 0x0d, 0x73, 0xdb, 0xd9, 0xbb, 0x23, + 0xe8, 0x99, 0xed, 0x1d, 0x97, 0xa2, 0xc1, 0x91, 0xfc, 0x5d, 0x4b, 0x87, 0xe2, 0x4c, 0xe5, 0xe1, + 0xc4, 0x94, 0x5c, 0x72, 0x65, 0x64, 0x8e, 0x50, 0x14, 0x7f, 0x4a, 0xfb, 0x5d, 0xf2, 0xc2, 0xaf, + 0xfd, 0x51, 0x75, 0x8e, 0x7a, 0x4d, 0xbf, 0xe5, 0x7a, 0xed, 0xc5, 0xbb, 0xa1, 0xef, 0x2d, 0xa0, + 0x73, 0x4f, 0xe9, 0xe8, 0x52, 0xa6, 0xf9, 0x8f, 0x41, 0xc5, 0x20, 0x71, 0x94, 0xa2, 0x37, 0x65, + 0x2a, 0x7a, 0xbf, 0x31, 0x01, 0x53, 0x66, 0x1e, 0xd2, 0x63, 0x68, 0x5f, 0xfa, 0xc4, 0x31, 0x76, + 0x92, 0x13, 0x07, 0x3b, 0x62, 0x1a, 0x17, 0x5c, 0xca, 0xbc, 0xb5, 0x92, 0x9b, 0xc2, 0x1d, 0x1f, + 0x31, 0x8d, 0xc2, 0x10, 0x13, 0x4c, 0x4f, 0xe0, 0xf3, 0xc2, 0xd4, 0x56, 0xa1, 0xd8, 0x15, 0x93, + 0x6a, 0x6b, 0x42, 0x55, 0x7b, 0x0e, 0x20, 0x4e, 0x98, 0x29, 0x2f, 0x3e, 0xb5, 0x3e, 0x6c, 0x24, + 0xf2, 0x34, 0xb0, 0xc8, 0x53, 0x30, 0xc1, 0x54, 0x1f, 0xda, 0x92, 0x59, 0x05, 0xf4, 0x39, 0xfe, + 0x1a, 0x2f, 0x45, 0x09, 0x25, 0x2f, 0x31, 0x2d, 0x35, 0x56, 0x58, 0x64, 0xb2, 0x80, 0x8b, 0xb1, + 0x96, 0x1a, 0xc3, 0x30, 0x81, 0xc9, 0x44, 0xa7, 0x4c, 0xbf, 0xe0, 0x6b, 0x83, 0x21, 0x3a, 0x57, + 0x3a, 0x50, 0xc0, 0xb8, 0x5d, 0x29, 0xa5, 0x8f, 0xf0, 0x39, 0x5d, 0x34, 0xec, 0x4a, 0x29, 0x38, + 0x0e, 0xd4, 0x60, 0x1f, 0x23, 0xef, 0x6c, 0x2b, 0xc2, 0x61, 0x7a, 0xc8, 0x6d, 0xeb, 0x57, 0xcc, + 0xb3, 0x56, 0x8e, 0x73, 0x48, 0x8c, 0xda, 0xe3, 0x1f, 0xb6, 0x46, 0x3b, 0x16, 0x7d, 0x16, 0xa6, + 0x93, 0xbb, 0x50, 0xee, 0x37, 0x1f, 0x5f, 0x1d, 0x87, 0x0b, 0x37, 0xdb, 0xae, 0x97, 0xce, 0xf9, + 0x96, 0xf5, 0xc0, 0x83, 0x75, 0xe2, 0x07, 0x1e, 0x74, 0x4c, 0x9e, 0x7c, 0x3e, 0x21, 0x3b, 0x26, + 0x4f, 0xbd, 0x65, 0x91, 0xc4, 0x25, 0x7f, 0x68, 0xc1, 0xe3, 0x4e, 0x4b, 0x9c, 0x0b, 0x9c, 0x8e, + 0x2c, 0x35, 0xf2, 0x92, 0xcb, 0x19, 0x1d, 0x8e, 0xb8, 0xcb, 0x0f, 0x7e, 0xfc, 0x42, 0xed, 0x10, + 0xae, 0xa2, 0xc7, 0x7f, 0x52, 0x7e, 0xc1, 0xe3, 0x87, 0xa1, 0xe2, 0xa1, 0xe2, 0x93, 0xbf, 0x0c, + 0x33, 0x89, 0x0f, 0x96, 0x96, 0xf0, 0xb2, 0xb8, 0xb0, 0x68, 0x24, 0x41, 0x98, 0xc6, 0x9d, 0xbf, + 0x05, 0x3f, 0x71, 0xa4, 0x9c, 0x27, 0x1a, 0x6c, 0xdf, 0xb3, 0x60, 0xca, 0x4c, 0xcf, 0x44, 0x9e, + 0x85, 0x52, 0xe4, 0xef, 0x50, 0xef, 0x76, 0xa0, 0x1c, 0x76, 0xf5, 0x40, 0xdf, 0xe0, 0xe5, 0xb8, + 0x8a, 0x1a, 0x83, 0x61, 0x37, 0x3b, 0x2e, 0xf5, 0xa2, 0x95, 0x96, 0xec, 0x66, 0x8d, 0xbd, 0x24, + 0xca, 0x97, 0x51, 0x63, 0x08, 0x1f, 0x3b, 0xf6, 0xbb, 0x41, 0x9b, 0x01, 0x55, 0xee, 0xfd, 0x86, + 0x8f, 0x5d, 0x0c, 0xc3, 0x04, 0x26, 0xb1, 0xb5, 0x89, 0x73, 0x3c, 0xbe, 0xd7, 0x48, 0x99, 0x24, + 0xbf, 0x63, 0x41, 0x59, 0x98, 0xe8, 0x91, 0x6e, 0xa5, 0x5c, 0x6c, 0x53, 0x46, 0x84, 0xda, 0xfa, + 0x4a, 0x96, 0x8b, 0xed, 0x15, 0x18, 0xdf, 0x71, 0x3d, 0xf5, 0x25, 0x7a, 0x5b, 0x7a, 0xcd, 0xf5, + 0x5a, 0xc8, 0x21, 0x7a, 0xe3, 0x2a, 0x0c, 0xdd, 0xb8, 0x16, 0xa1, 0xac, 0x1d, 0x4f, 0xe4, 0xf2, + 0xaf, 0xad, 0xb7, 0xda, 0x51, 0x05, 0x63, 0x1c, 0xfb, 0xd7, 0x2c, 0x98, 0xe6, 0x11, 0xe3, 0xf1, + 0x79, 0xf8, 0x45, 0xed, 0x0b, 0x26, 0xe4, 0x7e, 0x22, 0xe9, 0x0b, 0xf6, 0xde, 0x7e, 0xb5, 0x22, + 0x62, 0xcc, 0x93, 0xae, 0x61, 0x9f, 0x96, 0x46, 0x34, 0xee, 0xb1, 0x36, 0x76, 0x62, 0x1b, 0x4f, + 0x2c, 0xa6, 0x22, 0x82, 0x31, 0x3d, 0xfb, 0x6d, 0x98, 0x32, 0x83, 0xb1, 0xc8, 0x8b, 0x50, 0xe9, + 0xb9, 0x5e, 0x3b, 0x19, 0xb4, 0xab, 0x2f, 0x1a, 0xd6, 0x63, 0x10, 0x9a, 0x78, 0xbc, 0x9a, 0x1f, + 0x57, 0x4b, 0xdd, 0x4f, 0xac, 0xfb, 0x66, 0xb5, 0xf8, 0x8f, 0xed, 0x01, 0xc4, 0x91, 0xc5, 0xc7, + 0x32, 0xde, 0x4c, 0x08, 0xdb, 0xbf, 0x50, 0x46, 0x78, 0x96, 0x88, 0x09, 0x31, 0xc2, 0xdf, 0xdb, + 0x3f, 0x4c, 0xd9, 0x11, 0xb5, 0xf8, 0x1b, 0x14, 0x19, 0x41, 0x86, 0xb9, 0xbf, 0x41, 0x91, 0xc1, + 0xe3, 0xfd, 0x7b, 0x83, 0x22, 0x4b, 0x98, 0x3f, 0x5b, 0x6f, 0x50, 0x7c, 0x12, 0x4e, 0x9a, 0x8e, + 0x96, 0xe9, 0x16, 0xf7, 0xcc, 0xb4, 0x11, 0xba, 0xc5, 0x65, 0xde, 0x08, 0x09, 0xb5, 0x7f, 0xbb, + 0x00, 0xb3, 0x69, 0x13, 0x43, 0xde, 0xde, 0x1b, 0xe4, 0xeb, 0x16, 0x4c, 0x3b, 0x89, 0xd4, 0x7f, + 0x39, 0x3d, 0x68, 0x95, 0xa0, 0x69, 0xa4, 0x9e, 0x4b, 0x94, 0x63, 0x8a, 0x37, 0xf9, 0x0b, 0x30, + 0x19, 0xb9, 0x5d, 0xea, 0xf7, 0x85, 0xe1, 0xb1, 0x20, 0x0c, 0x00, 0x1b, 0xa2, 0x08, 0x15, 0x8c, + 0x6d, 0x02, 0x2e, 0xd7, 0xd8, 0x02, 0x2a, 0x3d, 0x91, 0x67, 0x63, 0x4b, 0xa9, 0x28, 0x47, 0x8d, + 0x41, 0xee, 0xc3, 0xa4, 0xf0, 0xf3, 0x50, 0x0e, 0x3d, 0x6b, 0x39, 0x99, 0x42, 0x84, 0x2b, 0x49, + 0xdc, 0x05, 0xe2, 0x7f, 0x88, 0x8a, 0x9d, 0xfd, 0x11, 0x38, 0x61, 0x7e, 0x5e, 0xfb, 0x2a, 0x10, + 0xf4, 0x3b, 0x9d, 0x4d, 0xa7, 0xb9, 0x73, 0xc7, 0xf5, 0x5a, 0xfe, 0x3d, 0xbe, 0xf4, 0x2d, 0x42, + 0x39, 0x90, 0x21, 0xba, 0xa1, 0x1c, 0x35, 0x7a, 0xed, 0x54, 0xb1, 0xbb, 0x21, 0xc6, 0x38, 0xf6, + 0xef, 0x8d, 0xc1, 0xa4, 0x8c, 0x27, 0x7f, 0x00, 0x91, 0x10, 0x3b, 0x89, 0xfb, 0xe7, 0x95, 0x5c, + 0xc2, 0xe0, 0x87, 0x86, 0x41, 0x84, 0xa9, 0x30, 0x88, 0xd7, 0xf2, 0x61, 0x77, 0x78, 0x0c, 0xc4, + 0x77, 0x8b, 0x30, 0x93, 0x8a, 0xcf, 0x4f, 0xa5, 0xf2, 0xb6, 0xde, 0x97, 0x54, 0xde, 0x24, 0x4c, + 0xa4, 0x73, 0xcf, 0xcf, 0x6f, 0xf2, 0xcf, 0x33, 0xbb, 0xe7, 0xe5, 0xd1, 0x5a, 0xfc, 0xe0, 0x78, + 0xb4, 0xfe, 0x17, 0x0b, 0x1e, 0x1d, 0x9a, 0x65, 0x82, 0xe7, 0x6b, 0x0b, 0x92, 0x50, 0xb9, 0x5e, + 0xe4, 0x9c, 0xb9, 0x47, 0xdf, 0x55, 0xa7, 0x53, 0x6c, 0xa5, 0xd9, 0x93, 0x17, 0x60, 0x8a, 0xeb, + 0x83, 0x6c, 0xe5, 0x8c, 0x68, 0x4f, 0x5e, 0xb5, 0xf1, 0x4b, 0x97, 0x86, 0x51, 0x8e, 0x09, 0x2c, + 0xfb, 0xdb, 0x16, 0xcc, 0x0d, 0xcb, 0xde, 0x75, 0x0c, 0x4d, 0xee, 0x2f, 0xa5, 0x22, 0x49, 0xaa, + 0x03, 0x91, 0x24, 0x29, 0x53, 0x90, 0x0a, 0x1a, 0x31, 0xac, 0x30, 0x85, 0x23, 0x02, 0x25, 0x7e, + 0xbf, 0x00, 0xb3, 0x52, 0xc4, 0x58, 0x09, 0x7f, 0x29, 0x11, 0xff, 0xf2, 0x93, 0xa9, 0xf8, 0x97, + 0x8b, 0x69, 0xfc, 0x3f, 0x0f, 0x7e, 0xf9, 0x60, 0x05, 0xbf, 0x7c, 0xad, 0x08, 0x97, 0x32, 0xf3, + 0x64, 0x91, 0xaf, 0x66, 0xec, 0x14, 0x77, 0x72, 0x4e, 0xc8, 0xa5, 0xe3, 0x64, 0xcf, 0x36, 0x62, + 0xe4, 0x57, 0xcc, 0x48, 0x0d, 0xb1, 0xfa, 0x6f, 0x9d, 0x41, 0x6a, 0xb1, 0x93, 0x06, 0x6d, 0x3c, + 0xd8, 0xa7, 0xce, 0xfe, 0x0c, 0x2c, 0xf5, 0x5f, 0x2b, 0xc0, 0xd3, 0xc7, 0x6d, 0xd9, 0x0f, 0x68, + 0x94, 0x63, 0x98, 0x88, 0x72, 0x7c, 0x40, 0xaa, 0xcd, 0x99, 0x04, 0x3c, 0xfe, 0xfd, 0x71, 0xbd, + 0xef, 0x0e, 0x4e, 0xd8, 0x63, 0xd9, 0x16, 0x26, 0x99, 0xea, 0xab, 0x12, 0xc2, 0xc7, 0x7b, 0xc3, + 0x64, 0x43, 0x14, 0xbf, 0xb7, 0x5f, 0x3d, 0x1f, 0x27, 0x94, 0x91, 0x85, 0xa8, 0x2a, 0x91, 0xa7, + 0xa1, 0x14, 0x08, 0xa8, 0x8a, 0xeb, 0x92, 0xde, 0x35, 0xa2, 0x0c, 0x35, 0x94, 0x7c, 0xc1, 0x38, + 0x2b, 0x8c, 0x9f, 0x55, 0xde, 0xa4, 0xc3, 0x9c, 0x86, 0xde, 0x84, 0x52, 0xa8, 0xb2, 0x96, 0x8b, + 0xe9, 0xf4, 0xfc, 0x31, 0xc3, 0x05, 0x9d, 0x4d, 0xda, 0x51, 0x29, 0xcc, 0xc5, 0xf7, 0xe9, 0x04, + 0xe7, 0x9a, 0x24, 0xb1, 0xf5, 0xd9, 0x5b, 0x5c, 0x6a, 0xc0, 0xe0, 0xb9, 0x9b, 0x44, 0x30, 0x29, + 0x9f, 0x2e, 0x96, 0xb7, 0xad, 0x6b, 0x39, 0xc5, 0xdd, 0x48, 0xaf, 0x6c, 0x7e, 0xa4, 0x55, 0x36, + 0x27, 0xc5, 0xca, 0xfe, 0x81, 0x05, 0x15, 0x39, 0x46, 0x1e, 0x40, 0xdc, 0xe4, 0xdd, 0x64, 0xdc, + 0xe4, 0xd5, 0x5c, 0x96, 0xf0, 0x21, 0x41, 0x93, 0x77, 0x61, 0xca, 0xcc, 0x58, 0x49, 0x3e, 0x65, + 0x6c, 0x41, 0xd6, 0x28, 0x59, 0xd9, 0xd4, 0x26, 0x15, 0x6f, 0x4f, 0xf6, 0x3f, 0x2e, 0xeb, 0x56, + 0xe4, 0x07, 0x67, 0x73, 0xe4, 0x5b, 0x87, 0x8e, 0x7c, 0x73, 0xe0, 0x8d, 0xe5, 0x3f, 0xf0, 0x5e, + 0x87, 0x92, 0x5a, 0x16, 0xa5, 0x36, 0xf5, 0xa4, 0xe9, 0xa6, 0xcd, 0x54, 0x32, 0x46, 0xcc, 0x98, + 0x2e, 0xfc, 0x00, 0x1c, 0x5b, 0xc2, 0xd5, 0x72, 0xad, 0xc9, 0x90, 0xb7, 0xa0, 0x72, 0xcf, 0x0f, + 0x76, 0x3a, 0xbe, 0xc3, 0x9f, 0x8a, 0x80, 0x3c, 0x3c, 0x03, 0xb4, 0x35, 0x5b, 0xc4, 0xca, 0xdc, + 0x89, 0xe9, 0xa3, 0xc9, 0x8c, 0xd4, 0x60, 0xa6, 0xeb, 0x7a, 0x48, 0x9d, 0x96, 0x0e, 0x8f, 0x1c, + 0x17, 0x69, 0xda, 0x95, 0x6e, 0xbf, 0x96, 0x04, 0x63, 0x1a, 0x9f, 0x5b, 0x9e, 0x82, 0x84, 0xa9, + 0x43, 0xe6, 0x62, 0x5e, 0x1f, 0x7d, 0x30, 0x26, 0xcd, 0x27, 0x22, 0x58, 0x24, 0x59, 0x8e, 0x29, + 0xde, 0xe4, 0xf3, 0x50, 0x0a, 0xd5, 0xa3, 0xa0, 0xc5, 0x1c, 0x4f, 0x3d, 0xfa, 0x61, 0x50, 0xdd, + 0x95, 0xfa, 0x65, 0x50, 0xcd, 0x90, 0xac, 0xc2, 0x45, 0x65, 0xbb, 0x49, 0xbc, 0x6f, 0x38, 0x11, + 0xe7, 0x13, 0xc3, 0x0c, 0x38, 0x66, 0xd6, 0x62, 0xba, 0x2d, 0xcf, 0x04, 0x2b, 0x6e, 0x62, 0x8d, + 0xcb, 0x4b, 0x3e, 0xff, 0x5a, 0x28, 0xa1, 0x87, 0x45, 0xff, 0x96, 0x46, 0x88, 0xfe, 0x6d, 0xc0, + 0xa5, 0x34, 0x88, 0x27, 0x8a, 0xe3, 0xb9, 0xe9, 0x8c, 0x2d, 0x74, 0x3d, 0x0b, 0x09, 0xb3, 0xeb, + 0x92, 0x3b, 0x50, 0x0e, 0x28, 0x3f, 0xe5, 0xd5, 0x94, 0x13, 0xdb, 0x89, 0xdd, 0x75, 0x51, 0x11, + 0xc0, 0x98, 0x16, 0xeb, 0x77, 0x27, 0x99, 0x38, 0xfd, 0xf5, 0x1c, 0x5f, 0x0d, 0x97, 0x7d, 0x3f, + 0x24, 0x81, 0xa3, 0xfd, 0x6f, 0x67, 0xe0, 0x5c, 0xc2, 0x00, 0x45, 0x9e, 0x84, 0x22, 0xcf, 0x9c, + 0xc7, 0x57, 0xab, 0x52, 0xbc, 0xa2, 0x8a, 0xc6, 0x11, 0x30, 0xf2, 0x4b, 0x16, 0xcc, 0xf4, 0x12, + 0x17, 0x38, 0x6a, 0x21, 0x1f, 0xd1, 0x6a, 0x9b, 0xbc, 0x15, 0x32, 0x9e, 0x1c, 0x49, 0x32, 0xc3, + 0x34, 0x77, 0xb6, 0x1e, 0x48, 0x9f, 0xf7, 0x0e, 0x0d, 0x38, 0xb6, 0x54, 0xf4, 0x34, 0x89, 0xa5, + 0x24, 0x18, 0xd3, 0xf8, 0xac, 0x87, 0xf9, 0xd7, 0x8d, 0xf2, 0x32, 0x6c, 0x4d, 0x11, 0xc0, 0x98, + 0x16, 0x79, 0x05, 0xa6, 0x65, 0xbe, 0xec, 0x75, 0xbf, 0x75, 0xdd, 0x09, 0xb7, 0xe5, 0x91, 0x4f, + 0x1f, 0x51, 0x97, 0x12, 0x50, 0x4c, 0x61, 0xf3, 0x6f, 0x8b, 0x93, 0x92, 0x73, 0x02, 0x13, 0xc9, + 0x17, 0x59, 0x96, 0x92, 0x60, 0x4c, 0xe3, 0x93, 0x67, 0x8d, 0x6d, 0x48, 0x78, 0x47, 0xe8, 0xd5, + 0x20, 0x63, 0x2b, 0xaa, 0xc1, 0x4c, 0x9f, 0x9f, 0x90, 0x5b, 0x0a, 0x28, 0xe7, 0xa3, 0x66, 0x78, + 0x3b, 0x09, 0xc6, 0x34, 0x3e, 0x79, 0x19, 0xce, 0x05, 0x6c, 0xb1, 0xd5, 0x04, 0x84, 0xcb, 0x84, + 0xbe, 0x11, 0x47, 0x13, 0x88, 0x49, 0x5c, 0xf2, 0x2a, 0x9c, 0x8f, 0x73, 0xaa, 0x2a, 0x02, 0xc2, + 0x87, 0x42, 0x27, 0xf8, 0xab, 0xa5, 0x11, 0x70, 0xb0, 0x0e, 0xf9, 0xab, 0x30, 0x6b, 0xb4, 0xc4, + 0x8a, 0xd7, 0xa2, 0xf7, 0x65, 0xde, 0x4b, 0xfe, 0xc2, 0xd8, 0x52, 0x0a, 0x86, 0x03, 0xd8, 0xe4, + 0xe3, 0x30, 0xdd, 0xf4, 0x3b, 0x1d, 0xbe, 0xc6, 0x89, 0xd7, 0x40, 0x44, 0x82, 0x4b, 0x91, 0x0a, + 0x34, 0x01, 0xc1, 0x14, 0x26, 0xb9, 0x01, 0xc4, 0xdf, 0x64, 0xea, 0x15, 0x6d, 0xbd, 0x4a, 0x3d, + 0x2a, 0x35, 0x8e, 0x73, 0xc9, 0x88, 0x9b, 0x5b, 0x03, 0x18, 0x98, 0x51, 0x8b, 0xe7, 0x07, 0x34, + 0x22, 0x94, 0xa7, 0xf3, 0xc8, 0x48, 0x9e, 0xb6, 0xe7, 0x1c, 0x19, 0x9e, 0x1c, 0xc0, 0x84, 0x08, + 0x80, 0xca, 0x27, 0xd3, 0xa5, 0xf9, 0x30, 0x40, 0xbc, 0x47, 0x88, 0x52, 0x94, 0x9c, 0xc8, 0xcf, + 0x43, 0x79, 0x53, 0xbd, 0x12, 0xc3, 0xd3, 0x5b, 0x8e, 0xbc, 0x2f, 0xa6, 0x1e, 0x3c, 0x8a, 0xed, + 0x15, 0x1a, 0x80, 0x31, 0x4b, 0xf2, 0x14, 0x54, 0xae, 0xaf, 0xd7, 0xf4, 0x28, 0x3c, 0xcf, 0x7b, + 0x7f, 0x9c, 0x55, 0x41, 0x13, 0xc0, 0x66, 0x98, 0x56, 0xdf, 0x48, 0xd2, 0x2d, 0x20, 0x43, 0x1b, + 0x63, 0xd8, 0xdc, 0xcf, 0x01, 0x1b, 0x73, 0x17, 0x52, 0xd8, 0xb2, 0x1c, 0x35, 0x06, 0x79, 0x13, + 0x2a, 0x72, 0xbf, 0xe0, 0x6b, 0xd3, 0xc5, 0xd3, 0x45, 0xbf, 0x63, 0x4c, 0x02, 0x4d, 0x7a, 0xfc, + 0x82, 0x9a, 0x3f, 0x9e, 0x41, 0xaf, 0xf5, 0x3b, 0x9d, 0xb9, 0x4b, 0x7c, 0xdd, 0x8c, 0x2f, 0xa8, + 0x63, 0x10, 0x9a, 0x78, 0xe4, 0x79, 0xe5, 0xaf, 0xf6, 0x70, 0xe2, 0xc6, 0x5e, 0xfb, 0xab, 0x69, + 0xa5, 0x7b, 0x48, 0x80, 0xcc, 0x23, 0x47, 0x38, 0x8a, 0x6d, 0xc2, 0xbc, 0xd2, 0xf8, 0x06, 0x27, + 0xc9, 0xdc, 0x5c, 0xc2, 0x76, 0x34, 0x7f, 0x67, 0x28, 0x26, 0x1e, 0x42, 0x85, 0x6c, 0x42, 0xc1, + 0xe9, 0x6c, 0xce, 0x3d, 0x9a, 0x87, 0xea, 0x5a, 0x5b, 0xad, 0xcb, 0x11, 0xc5, 0x9d, 0x5a, 0x6b, + 0xab, 0x75, 0x64, 0xc4, 0x89, 0x0b, 0xe3, 0x4e, 0x67, 0x33, 0x9c, 0x9b, 0xe7, 0x73, 0x36, 0x37, + 0x26, 0xb1, 0xf1, 0x60, 0xb5, 0x1e, 0x22, 0x67, 0x61, 0x7f, 0x71, 0x4c, 0xdf, 0x12, 0xe9, 0x64, + 0xe3, 0x6f, 0x9b, 0x13, 0x48, 0x1c, 0x77, 0x6e, 0xe5, 0x36, 0x81, 0xa4, 0x7a, 0x71, 0x6e, 0xe8, + 0xf4, 0xe9, 0xe9, 0x25, 0x23, 0x97, 0x2c, 0x65, 0xc9, 0x44, 0xea, 0xe2, 0xf4, 0x9c, 0x5c, 0x30, + 0xec, 0x2f, 0x55, 0xb4, 0x15, 0x34, 0xe5, 0xeb, 0x15, 0x40, 0xd1, 0x0d, 0x23, 0xd7, 0xcf, 0x31, + 0x28, 0x3c, 0x95, 0x81, 0x9c, 0xc7, 0x9c, 0x70, 0x00, 0x0a, 0x56, 0x8c, 0xa7, 0xd7, 0x76, 0xbd, + 0xfb, 0xf2, 0xf3, 0x5f, 0xcf, 0xdd, 0x89, 0x4b, 0xf0, 0xe4, 0x00, 0x14, 0xac, 0xc8, 0x5d, 0x31, + 0xa8, 0x0b, 0x79, 0xf4, 0x75, 0x6d, 0xb5, 0x9e, 0xe2, 0x97, 0x1c, 0xdc, 0x77, 0xa1, 0x10, 0x76, + 0x5d, 0xa9, 0x2e, 0x8d, 0xc8, 0xab, 0xb1, 0xb6, 0x92, 0xc5, 0xab, 0xb1, 0xb6, 0x82, 0x8c, 0x09, + 0xf9, 0x8a, 0x05, 0xe0, 0x74, 0x37, 0x9d, 0x30, 0x74, 0x5a, 0xda, 0x3a, 0x33, 0xe2, 0x23, 0x2b, + 0x35, 0x4d, 0x2f, 0xc5, 0x9a, 0xbb, 0x2d, 0xc7, 0x50, 0x34, 0x38, 0x93, 0xb7, 0x60, 0xd2, 0x11, + 0xaf, 0x58, 0x4a, 0x0f, 0xfc, 0x7c, 0x9e, 0x66, 0x4d, 0x49, 0xc0, 0xcd, 0x34, 0x12, 0x84, 0x8a, + 0x21, 0xe3, 0x1d, 0x05, 0x0e, 0xdd, 0x72, 0x77, 0xa4, 0x71, 0xa8, 0x31, 0xf2, 0x3b, 0x2b, 0x8c, + 0x58, 0x16, 0x6f, 0x09, 0x42, 0xc5, 0x90, 0xfc, 0x82, 0x05, 0xe7, 0xba, 0x8e, 0xe7, 0xe8, 0xb8, + 0xca, 0x7c, 0xa2, 0x6f, 0xcd, 0x48, 0xcd, 0x58, 0x43, 0x5c, 0x33, 0x19, 0x61, 0x92, 0x2f, 0xd9, + 0x85, 0x09, 0x87, 0xbf, 0xaf, 0x2b, 0x8f, 0x62, 0x98, 0xc7, 0x5b, 0xbd, 0xa9, 0x36, 0xe0, 0x8b, + 0x8b, 0x7c, 0xc5, 0x57, 0x72, 0x23, 0xbf, 0x6e, 0xc1, 0xa4, 0x70, 0x0e, 0x67, 0x0a, 0x29, 0xfb, + 0xf6, 0xcf, 0x9e, 0xc1, 0x4b, 0x06, 0xd2, 0x71, 0x5d, 0xba, 0x1f, 0x7d, 0x48, 0x7b, 0xbe, 0x8a, + 0xd2, 0x43, 0x5d, 0xd7, 0x95, 0x74, 0x4c, 0xf5, 0xed, 0x3a, 0xf7, 0x13, 0xaf, 0xe8, 0x98, 0xaa, + 0xef, 0x5a, 0x0a, 0x86, 0x03, 0xd8, 0xf3, 0x1f, 0x87, 0x29, 0x53, 0x8e, 0x13, 0xb9, 0xbf, 0xff, + 0xa8, 0x00, 0xc0, 0xbb, 0x4a, 0xe4, 0x62, 0xe9, 0xf2, 0xc4, 0xcd, 0xdb, 0x7e, 0x2b, 0xa7, 0xd7, + 0x3c, 0x8d, 0x94, 0x2a, 0x20, 0xb3, 0x34, 0x6f, 0xfb, 0x2d, 0x94, 0x4c, 0x48, 0x1b, 0xc6, 0x7b, + 0x4e, 0xb4, 0x9d, 0x7f, 0xfe, 0x96, 0x92, 0x08, 0x4a, 0x8e, 0xb6, 0x91, 0x33, 0x20, 0xef, 0x58, + 0xb1, 0x67, 0x4f, 0x21, 0x8f, 0xdc, 0xb3, 0x71, 0x9b, 0x2d, 0x48, 0x5f, 0x9e, 0x54, 0x0a, 0xd6, + 0xb4, 0x87, 0xcf, 0xfc, 0xbb, 0x16, 0x4c, 0x99, 0xa8, 0x19, 0xdd, 0xf4, 0x73, 0x66, 0x37, 0xe5, + 0xd9, 0x1e, 0x66, 0x8f, 0xff, 0x37, 0x0b, 0x00, 0xfb, 0x5e, 0xa3, 0xdf, 0xed, 0x32, 0xb5, 0x5d, + 0x7b, 0xf9, 0x5b, 0xc7, 0xf6, 0xf2, 0x1f, 0x3b, 0xa1, 0x97, 0x7f, 0xe1, 0x44, 0x5e, 0xfe, 0xe3, + 0x27, 0xf7, 0xf2, 0x2f, 0x0e, 0xf7, 0xf2, 0xb7, 0xbf, 0x69, 0xc1, 0xf9, 0x81, 0xfd, 0x8a, 0x69, + 0xd2, 0x81, 0xef, 0x47, 0x43, 0x3c, 0x44, 0x31, 0x06, 0xa1, 0x89, 0x47, 0x96, 0x61, 0x56, 0x3e, + 0x53, 0xd2, 0xe8, 0x75, 0xdc, 0xcc, 0xdc, 0x3a, 0x1b, 0x29, 0x38, 0x0e, 0xd4, 0xb0, 0x7f, 0xdb, + 0x82, 0x8a, 0x11, 0x91, 0xcf, 0xbe, 0x83, 0xbb, 0x09, 0x4b, 0x31, 0xe2, 0x17, 0x5a, 0xf8, 0x55, + 0x97, 0x80, 0x89, 0x6b, 0xe8, 0xb6, 0x91, 0xc4, 0x3e, 0xbe, 0x86, 0x66, 0xa5, 0x28, 0xa1, 0x22, + 0x3d, 0x39, 0xed, 0xf1, 0x46, 0x2f, 0x98, 0xe9, 0xc9, 0x69, 0x0f, 0x39, 0x84, 0xb3, 0x63, 0x47, + 0x0a, 0xe9, 0x01, 0x6c, 0x3c, 0x08, 0xe3, 0x04, 0x11, 0x0a, 0x18, 0x79, 0x02, 0x0a, 0xd4, 0x6b, + 0x49, 0xfb, 0x87, 0x7e, 0xbd, 0xf6, 0xaa, 0xd7, 0x42, 0x56, 0x6e, 0xdf, 0x82, 0x29, 0xe1, 0xfd, + 0xfc, 0x1a, 0xdd, 0x3b, 0xf6, 0x73, 0xb8, 0x6c, 0xb4, 0xa7, 0x9e, 0xc3, 0x65, 0xd5, 0x59, 0xb9, + 0xfd, 0x8f, 0x2c, 0x48, 0xbd, 0x91, 0x64, 0xdc, 0xc0, 0x58, 0x43, 0x6f, 0x60, 0x4c, 0xab, 0xfd, + 0xd8, 0xa1, 0x56, 0xfb, 0x1b, 0x40, 0xba, 0x6c, 0x2a, 0x24, 0x17, 0xda, 0x42, 0xf2, 0x29, 0x89, + 0xb5, 0x01, 0x0c, 0xcc, 0xa8, 0x65, 0xff, 0x43, 0x21, 0xac, 0xf9, 0x6a, 0xd2, 0xd1, 0x0d, 0xd0, + 0x87, 0x22, 0x27, 0x25, 0xed, 0x6f, 0x23, 0xda, 0xae, 0x07, 0xf3, 0x68, 0xc5, 0x1d, 0x29, 0xa7, + 0x3c, 0xe7, 0x66, 0xff, 0xbe, 0x90, 0xd5, 0x7c, 0x56, 0xe9, 0x68, 0x59, 0xbb, 0x49, 0x59, 0xaf, + 0xe7, 0xb5, 0x56, 0x66, 0xcb, 0x48, 0x16, 0x00, 0x7a, 0x34, 0x68, 0x52, 0x2f, 0x52, 0x71, 0x49, + 0x45, 0x19, 0x21, 0xab, 0x4b, 0xd1, 0xc0, 0xb0, 0xbf, 0xc1, 0x26, 0x50, 0xfc, 0x50, 0x34, 0x79, + 0x3a, 0xed, 0xea, 0x9a, 0x9e, 0x1c, 0xda, 0xd3, 0xd5, 0x88, 0x56, 0x19, 0x3b, 0x22, 0x5a, 0xe5, + 0x19, 0x98, 0x0c, 0xfc, 0x0e, 0xad, 0x05, 0x5e, 0xda, 0x47, 0x07, 0x59, 0x31, 0xde, 0x44, 0x05, + 0xb7, 0x7f, 0xd5, 0x82, 0xd9, 0x74, 0x38, 0x5d, 0xee, 0xfe, 0xb7, 0x66, 0xcc, 0x7f, 0xe1, 0xe4, + 0x31, 0xff, 0xf6, 0x3f, 0x2d, 0xc0, 0x6c, 0xfa, 0x01, 0x3b, 0xc6, 0xd9, 0xe5, 0xc6, 0xb6, 0xd4, + 0xea, 0x2f, 0xac, 0x6c, 0x02, 0xa6, 0xc7, 0xcb, 0xd8, 0xd0, 0xf1, 0xf2, 0xd3, 0xc9, 0xfc, 0xcb, + 0x57, 0xd2, 0x16, 0x86, 0x99, 0x98, 0xf1, 0x29, 0x33, 0x30, 0x27, 0xb3, 0x70, 0x14, 0xcf, 0x2c, + 0x0b, 0xc7, 0x44, 0xae, 0x59, 0x38, 0x5e, 0xd1, 0xde, 0x56, 0x93, 0xb1, 0xab, 0xbf, 0xf6, 0xb4, + 0x3a, 0xc4, 0xd5, 0x5f, 0x3a, 0x93, 0xbe, 0xc3, 0x06, 0x56, 0xe4, 0x36, 0x77, 0x5c, 0x4f, 0xa4, + 0x36, 0x60, 0xa3, 0xfd, 0x19, 0x98, 0xa4, 0xf2, 0x91, 0x62, 0x61, 0xfa, 0xd7, 0x8d, 0xa6, 0xde, + 0x26, 0x56, 0x70, 0x52, 0x83, 0x19, 0x75, 0xe1, 0xa9, 0xee, 0x6b, 0x44, 0x4a, 0x16, 0x6d, 0x1f, + 0x5e, 0x4e, 0x82, 0x31, 0x8d, 0x6f, 0x7f, 0x01, 0x2a, 0x86, 0x22, 0xc1, 0xf7, 0xdc, 0xfb, 0x4e, + 0x33, 0x4a, 0xef, 0x55, 0x57, 0x59, 0x21, 0x0a, 0x18, 0xbf, 0x56, 0x12, 0x11, 0x5a, 0xa9, 0xbd, + 0x4a, 0xc6, 0x65, 0x49, 0x28, 0x23, 0x16, 0xd0, 0x36, 0xbd, 0xaf, 0xde, 0x85, 0x50, 0xc4, 0x90, + 0x15, 0xa2, 0x80, 0xd9, 0xcf, 0x42, 0x49, 0x25, 0xce, 0xe2, 0xd9, 0x67, 0xd4, 0x95, 0x87, 0x99, + 0x7d, 0xc6, 0x0f, 0x22, 0xe4, 0x10, 0xfb, 0x0d, 0x28, 0xa9, 0xfc, 0x5e, 0x47, 0x63, 0xb3, 0xed, + 0x23, 0xf4, 0xdc, 0xeb, 0x7e, 0x18, 0xa9, 0xa4, 0x64, 0xe2, 0x56, 0xf6, 0xe6, 0x0a, 0x2f, 0x43, + 0x0d, 0xb5, 0xff, 0xd4, 0x82, 0xca, 0xc6, 0xc6, 0xaa, 0x36, 0xd6, 0x20, 0x3c, 0x1c, 0x8a, 0x16, + 0xaa, 0x6d, 0x45, 0xd4, 0x74, 0xff, 0x10, 0x33, 0x69, 0xfe, 0x60, 0xbf, 0xfa, 0x70, 0x23, 0x13, + 0x03, 0x87, 0xd4, 0x24, 0x2b, 0x70, 0xc1, 0x84, 0xc8, 0x64, 0x11, 0x72, 0x5f, 0xe3, 0xaf, 0x5a, + 0x37, 0x06, 0xc1, 0x98, 0x55, 0x27, 0x4d, 0x4a, 0xaa, 0x68, 0xe6, 0x03, 0xd9, 0x8d, 0x41, 0x30, + 0x66, 0xd5, 0xb1, 0x9f, 0x87, 0x99, 0x94, 0x5f, 0xc2, 0x31, 0x92, 0xf4, 0xfc, 0x4e, 0x01, 0xa6, + 0xcc, 0xeb, 0xe9, 0x63, 0xec, 0x39, 0xc7, 0xdf, 0xca, 0x33, 0xae, 0x94, 0x0b, 0x27, 0xbc, 0x52, + 0x36, 0xef, 0xf0, 0xc7, 0xcf, 0xf6, 0x0e, 0xbf, 0x98, 0xcf, 0x1d, 0xbe, 0xe1, 0x6b, 0x32, 0xf1, + 0xe0, 0x7c, 0x4d, 0x7e, 0xab, 0x08, 0xd3, 0xc9, 0xac, 0xaf, 0xc7, 0xe8, 0xc9, 0x67, 0x07, 0x7a, + 0xf2, 0x84, 0x77, 0x58, 0x85, 0x51, 0xef, 0xb0, 0xc6, 0x47, 0xbd, 0xc3, 0x2a, 0x9e, 0xe2, 0x0e, + 0x6b, 0xf0, 0x06, 0x6a, 0xe2, 0xd8, 0x37, 0x50, 0x9f, 0x48, 0x6c, 0x14, 0xb1, 0xdb, 0x56, 0xbc, + 0x59, 0x90, 0x64, 0x37, 0x2c, 0xf9, 0xad, 0x4c, 0x77, 0xe2, 0xd2, 0x11, 0xdb, 0x68, 0x90, 0xe9, + 0x45, 0x7b, 0xf2, 0x6b, 0xf2, 0x87, 0x4f, 0xe0, 0x41, 0xfb, 0x22, 0x54, 0xe4, 0x78, 0xe2, 0x07, + 0x26, 0x48, 0x1e, 0xb6, 0x1a, 0x31, 0x08, 0x4d, 0x3c, 0x36, 0x30, 0x7a, 0xf1, 0x04, 0xe1, 0xb7, + 0xa9, 0x95, 0xe4, 0x6d, 0xea, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xfb, 0xf3, 0x70, 0x29, 0xd3, 0x6c, + 0xc6, 0xaf, 0x2c, 0xb8, 0x2e, 0x4f, 0x5b, 0x12, 0xc1, 0x10, 0x23, 0xf5, 0x18, 0xcc, 0xfc, 0x9d, + 0xa1, 0x98, 0x78, 0x08, 0x15, 0xfb, 0x37, 0x0b, 0x30, 0x9d, 0x7c, 0x1c, 0x99, 0xdc, 0xd3, 0x46, + 0xf6, 0x5c, 0xec, 0xfb, 0x82, 0xac, 0x91, 0x49, 0x74, 0xe8, 0xe5, 0xdc, 0x3d, 0x3e, 0xbe, 0x36, + 0x75, 0x5a, 0xd3, 0xb3, 0x63, 0x2c, 0x6f, 0xc5, 0x24, 0x3b, 0xfe, 0xc4, 0x70, 0x1c, 0x74, 0x2c, + 0x6d, 0x2f, 0xb9, 0x73, 0x8f, 0x83, 0x67, 0x35, 0x2b, 0x34, 0xd8, 0xb2, 0xbd, 0x65, 0x97, 0x06, + 0xee, 0x96, 0x4b, 0x5b, 0x32, 0xcb, 0x3c, 0x5f, 0xb9, 0xdf, 0x90, 0x65, 0xa8, 0xa1, 0xf6, 0x3b, + 0x63, 0x50, 0xe6, 0x39, 0xd2, 0xae, 0x05, 0x7e, 0x97, 0x3f, 0x9b, 0x19, 0x1a, 0xe7, 0x5c, 0xd9, + 0x6d, 0x37, 0x46, 0x7d, 0x09, 0x37, 0xa6, 0x28, 0x43, 0x14, 0x8c, 0x12, 0x4c, 0x70, 0x24, 0x3d, + 0x28, 0x6d, 0xc9, 0x9c, 0xce, 0xb2, 0xef, 0x46, 0xcc, 0x4b, 0xaa, 0x32, 0x44, 0x8b, 0x26, 0x50, + 0xff, 0x50, 0x73, 0xb1, 0x1d, 0x98, 0x49, 0x25, 0xb9, 0xc9, 0x3d, 0x13, 0xf4, 0xff, 0x1c, 0x87, + 0xb2, 0x8e, 0x8d, 0x23, 0x1f, 0x4b, 0x18, 0x1d, 0xcb, 0xf5, 0x9f, 0x30, 0xde, 0x74, 0xdb, 0xf6, + 0x5b, 0xec, 0xfc, 0xa0, 0x91, 0x53, 0x06, 0xc4, 0x27, 0xa0, 0xd0, 0x0f, 0x3a, 0x69, 0xab, 0xc2, + 0x6d, 0x5c, 0x45, 0x56, 0x6e, 0xc6, 0xf3, 0x15, 0x1e, 0x68, 0x3c, 0x1f, 0xdb, 0x25, 0x37, 0xfd, + 0xd6, 0x5e, 0xfa, 0x0d, 0xb8, 0xba, 0xdf, 0xda, 0x43, 0x0e, 0x21, 0xaf, 0xc0, 0xb4, 0x0c, 0x52, + 0x54, 0x4a, 0x4c, 0x91, 0xeb, 0xa9, 0xda, 0xd9, 0x64, 0x23, 0x01, 0xc5, 0x14, 0x36, 0xdb, 0x65, + 0xd9, 0xb1, 0x81, 0xe7, 0xf7, 0x9e, 0x48, 0xde, 0x4c, 0xdf, 0x68, 0xdc, 0xba, 0xc9, 0x8d, 0x9f, + 0x1a, 0x23, 0x11, 0x07, 0x39, 0x79, 0x64, 0x1c, 0xe4, 0xb2, 0xa0, 0xcd, 0xa4, 0xe5, 0x3b, 0xca, + 0x54, 0xfd, 0x69, 0x45, 0x97, 0x95, 0x1d, 0x7a, 0x76, 0xd1, 0x35, 0xb3, 0x22, 0x46, 0xcb, 0xef, + 0x5f, 0xc4, 0xa8, 0x7d, 0x1b, 0x66, 0x52, 0xfd, 0xa7, 0x8c, 0x52, 0x56, 0xb6, 0x51, 0xea, 0x78, + 0xaf, 0xc8, 0xfd, 0x33, 0x0b, 0xce, 0x0f, 0xac, 0x48, 0xc7, 0x0d, 0xdd, 0x4d, 0xef, 0x8d, 0x63, + 0xa7, 0xdf, 0x1b, 0x0b, 0x27, 0xdb, 0x1b, 0xeb, 0x9b, 0xdf, 0xfb, 0xe1, 0xe5, 0x87, 0xbe, 0xff, + 0xc3, 0xcb, 0x0f, 0xfd, 0xc1, 0x0f, 0x2f, 0x3f, 0xf4, 0xce, 0xc1, 0x65, 0xeb, 0x7b, 0x07, 0x97, + 0xad, 0xef, 0x1f, 0x5c, 0xb6, 0xfe, 0xe0, 0xe0, 0xb2, 0xf5, 0x9f, 0x0f, 0x2e, 0x5b, 0xdf, 0xfc, + 0xe3, 0xcb, 0x0f, 0x7d, 0xea, 0x13, 0x71, 0x4f, 0x2d, 0xaa, 0x9e, 0xe2, 0x3f, 0x3e, 0xac, 0xfa, + 0x65, 0xb1, 0xb7, 0xd3, 0x5e, 0x64, 0x3d, 0xb5, 0xa8, 0x4b, 0x54, 0x4f, 0xfd, 0xdf, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x10, 0x97, 0xcb, 0x70, 0x0f, 0xaa, 0x00, 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -8019,14 +8018,6 @@ func (m *PluginStep) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - i-- - if m.AbortOnFailure { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x18 if m.Config != nil { i -= len(m.Config) copy(dAtA[i:], m.Config) @@ -12128,7 +12119,6 @@ func (m *PluginStep) Size() (n int) { l = len(m.Config) n += 1 + l + sovGenerated(uint64(l)) } - n += 2 return n } @@ -14205,7 +14195,6 @@ func (this *PluginStep) String() string { s := strings.Join([]string{`&PluginStep{`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, `Config:` + valueToStringGenerated(this.Config) + `,`, - `AbortOnFailure:` + fmt.Sprintf("%v", this.AbortOnFailure) + `,`, `}`, }, "") return s @@ -27897,26 +27886,6 @@ func (m *PluginStep) Unmarshal(dAtA []byte) error { m.Config = []byte{} } iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AbortOnFailure", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.AbortOnFailure = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 3b4c533d38..582b8844c2 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1188,8 +1188,6 @@ message PluginStep { // Name the name of the hashicorp go-plugin step to query optional string name = 1; - optional bool abortOnFailure = 3; - // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 2d4d68ff1e..5e98a242ab 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -97,6 +97,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.PluginStep": schema_pkg_apis_rollouts_v1alpha1_PluginStep(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), @@ -126,6 +127,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute": schema_pkg_apis_rollouts_v1alpha1_SetMirrorRoute(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.Sigv4Config": schema_pkg_apis_rollouts_v1alpha1_Sigv4Config(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SkyWalkingMetric": schema_pkg_apis_rollouts_v1alpha1_SkyWalkingMetric(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StepPluginStatus": schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StickinessConfig": schema_pkg_apis_rollouts_v1alpha1_StickinessConfig(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StringMatch": schema_pkg_apis_rollouts_v1alpha1_StringMatch(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TCPRoute": schema_pkg_apis_rollouts_v1alpha1_TCPRoute(ref), @@ -1417,11 +1419,25 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStatus(ref common.ReferenceCallback Format: "", }, }, + "stepPluginStatuses": { + SchemaProps: spec.SchemaProps{ + Description: "StepPluginStatuses Hold the status of the step plugins executed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StepPluginStatus"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysisRunStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysisRunStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StepPluginStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights"}, } } @@ -1475,11 +1491,17 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStep(ref common.ReferenceCallback) Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute"), }, }, + "plugin": { + SchemaProps: spec.SchemaProps{ + Description: "Plugin defines a plugin to execute for a step", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginStep"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutExperimentStep", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutPause", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetCanaryScale", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetHeaderRoute", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginStep", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutExperimentStep", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutPause", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetCanaryScale", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetHeaderRoute", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute"}, } } @@ -3509,6 +3531,41 @@ func schema_pkg_apis_rollouts_v1alpha1_PingPongSpec(ref common.ReferenceCallback } } +func schema_pkg_apis_rollouts_v1alpha1_PluginStep(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name the name of the hashicorp go-plugin step to query", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "AbortOnFailure": { + SchemaProps: spec.SchemaProps{ + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "config": { + SchemaProps: spec.SchemaProps{ + Description: "Config the configuration object for the specified plugin", + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"name", "AbortOnFailure"}, + }, + }, + } +} + func schema_pkg_apis_rollouts_v1alpha1_PodTemplateMetadata(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -5126,6 +5183,64 @@ func schema_pkg_apis_rollouts_v1alpha1_SkyWalkingMetric(ref common.ReferenceCall } } +func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "index": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "phase": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "startedAt": { + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "finishedAt": { + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"index", "name", "phase"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + func schema_pkg_apis_rollouts_v1alpha1_StickinessConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index c68d3502c3..e1097760a0 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -644,7 +644,6 @@ type PluginStep struct { // Name the name of the hashicorp go-plugin step to query Name string `json:"name" protobuf:"bytes,1,opt,name=name"` - AbortOnFailure bool // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object diff --git a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go index 496cedc2a0..e59b93341a 100644 --- a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go @@ -794,6 +794,13 @@ func (in *CanaryStatus) DeepCopyInto(out *CanaryStatus) { *out = new(TrafficWeights) (*in).DeepCopyInto(*out) } + if in.StepPluginStatuses != nil { + in, out := &in.StepPluginStatuses, &out.StepPluginStatuses + *out = make([]StepPluginStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -845,6 +852,11 @@ func (in *CanaryStep) DeepCopyInto(out *CanaryStep) { *out = new(SetMirrorRoute) (*in).DeepCopyInto(*out) } + if in.Plugin != nil { + in, out := &in.Plugin, &out.Plugin + *out = new(PluginStep) + (*in).DeepCopyInto(*out) + } return } @@ -1931,6 +1943,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 *PluginStep) DeepCopyInto(out *PluginStep) { + *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 PluginStep. +func (in *PluginStep) DeepCopy() *PluginStep { + if in == nil { + return nil + } + out := new(PluginStep) + 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 @@ -2739,6 +2772,35 @@ func (in *SkyWalkingMetric) DeepCopy() *SkyWalkingMetric { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepPluginStatus) DeepCopyInto(out *StepPluginStatus) { + *out = *in + if in.StartedAt != nil { + in, out := &in.StartedAt, &out.StartedAt + *out = (*in).DeepCopy() + } + if in.FinishedAt != nil { + in, out := &in.FinishedAt, &out.FinishedAt + *out = (*in).DeepCopy() + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepPluginStatus. +func (in *StepPluginStatus) DeepCopy() *StepPluginStatus { + if in == nil { + return nil + } + out := new(StepPluginStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StickinessConfig) DeepCopyInto(out *StickinessConfig) { *out = *in diff --git a/rollout/steps/plugin/mocks/Resolver.go b/rollout/steps/plugin/mocks/Resolver.go index dcd198f3b0..3a909039c7 100644 --- a/rollout/steps/plugin/mocks/Resolver.go +++ b/rollout/steps/plugin/mocks/Resolver.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.32.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks @@ -17,6 +17,10 @@ type Resolver struct { func (_m *Resolver) Resolve(index int32, _a1 v1alpha1.PluginStep) (plugin.StepPlugin, error) { ret := _m.Called(index, _a1) + if len(ret) == 0 { + panic("no return value specified for Resolve") + } + var r0 plugin.StepPlugin var r1 error if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep) (plugin.StepPlugin, error)); ok { diff --git a/rollout/steps/plugin/mocks/StepPlugin.go b/rollout/steps/plugin/mocks/StepPlugin.go index 0bc8884ce9..d612909edf 100644 --- a/rollout/steps/plugin/mocks/StepPlugin.go +++ b/rollout/steps/plugin/mocks/StepPlugin.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.32.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks @@ -17,6 +17,10 @@ type StepPlugin struct { func (_m *StepPlugin) Abort(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for Abort") + } + var r0 *v1alpha1.StepPluginStatus var r1 error if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error)); ok { @@ -43,6 +47,10 @@ func (_m *StepPlugin) Abort(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *plugin.StepResult, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for Run") + } + var r0 *v1alpha1.StepPluginStatus var r1 *plugin.StepResult var r2 error @@ -78,6 +86,10 @@ func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *p func (_m *StepPlugin) Terminate(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for Terminate") + } + var r0 *v1alpha1.StepPluginStatus var r1 error if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error)); ok { diff --git a/ui/src/models/rollout/generated/api.ts b/ui/src/models/rollout/generated/api.ts index 562b02c1e9..baac4b306f 100755 --- a/ui/src/models/rollout/generated/api.ts +++ b/ui/src/models/rollout/generated/api.ts @@ -1806,12 +1806,6 @@ export interface GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1PluginStep * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1PluginStep */ name?: string; - /** - * - * @type {boolean} - * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1PluginStep - */ - abortOnFailure?: boolean; /** * * @type {string} From 2d0513dd7b572f9599ca283962e7c46f9b843ca7 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 09:34:43 -0400 Subject: [PATCH 03/41] unit tests Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index e98571ca7f..f46f88bb4c 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -68,8 +68,14 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { roCtx, runStatus := setup(t) runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful - existingStatus := runStatus.DeepCopy() - roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{} + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Message: "this is the existing status", + Phase: v1alpha1.StepPluginPhaseRunning, + }, + } err := roCtx.reconcileCanaryPluginStep() From da408a0e118ff1ef99d25207dc5b893124ad8587 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 11:21:24 -0400 Subject: [PATCH 04/41] rpc tests Signed-off-by: Alexandre Gaudreault --- rollout/steps/plugin/rpc/rpc.go | 18 ++++++------- rollout/steps/plugin/rpc/rpc_test.go | 40 +++++++--------------------- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/rollout/steps/plugin/rpc/rpc.go b/rollout/steps/plugin/rpc/rpc.go index 56f4ff6989..f460361f39 100644 --- a/rollout/steps/plugin/rpc/rpc.go +++ b/rollout/steps/plugin/rpc/rpc.go @@ -13,17 +13,17 @@ import ( type RunArgs struct { Rollout *v1alpha1.Rollout - Context types.RpcStepContext + Context *types.RpcStepContext } type TerminateArgs struct { Rollout *v1alpha1.Rollout - Context types.RpcStepContext + Context *types.RpcStepContext } type AbortArgs struct { Rollout *v1alpha1.Rollout - Context types.RpcStepContext + Context *types.RpcStepContext } type Response struct { @@ -59,7 +59,7 @@ func (g *StepPluginRPC) InitPlugin() types.RpcError { } // Run executes the step -func (g *StepPluginRPC) Run(rollout *v1alpha1.Rollout, context types.RpcStepContext) (types.RpcStepResult, types.RpcError) { +func (g *StepPluginRPC) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { var resp Response var args any = RunArgs{ Rollout: rollout, @@ -73,7 +73,7 @@ func (g *StepPluginRPC) Run(rollout *v1alpha1.Rollout, context types.RpcStepCont } // Terminate stops the execution of a running step and exits early -func (g *StepPluginRPC) Terminate(rollout *v1alpha1.Rollout, context types.RpcStepContext) (types.RpcStepResult, types.RpcError) { +func (g *StepPluginRPC) Terminate(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { var resp Response var args any = TerminateArgs{ Rollout: rollout, @@ -87,7 +87,7 @@ func (g *StepPluginRPC) Terminate(rollout *v1alpha1.Rollout, context types.RpcSt } // Abort reverts previous operation executed by the step if necessary -func (g *StepPluginRPC) Abort(rollout *v1alpha1.Rollout, context types.RpcStepContext) (types.RpcStepResult, types.RpcError) { +func (g *StepPluginRPC) Abort(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { var resp Response var args any = AbortArgs{ Rollout: rollout, @@ -131,7 +131,7 @@ func (s *StepRPCServer) Run(args any, resp *Response) error { if !ok { return fmt.Errorf("invalid args %s", args) } - result, err := s.Impl.Run(runArgs.Rollout, &runArgs.Context) + result, err := s.Impl.Run(runArgs.Rollout, runArgs.Context) *resp = Response{ Result: result, Error: err, @@ -145,7 +145,7 @@ func (s *StepRPCServer) Terminate(args any, resp *Response) error { if !ok { return fmt.Errorf("invalid args %s", args) } - result, err := s.Impl.Terminate(runArgs.Rollout, &runArgs.Context) + result, err := s.Impl.Terminate(runArgs.Rollout, runArgs.Context) *resp = Response{ Result: result, Error: err, @@ -159,7 +159,7 @@ func (s *StepRPCServer) Abort(args any, resp *Response) error { if !ok { return fmt.Errorf("invalid args %s", args) } - result, err := s.Impl.Abort(runArgs.Rollout, &runArgs.Context) + result, err := s.Impl.Abort(runArgs.Rollout, runArgs.Context) *resp = Response{ Result: result, Error: err, diff --git a/rollout/steps/plugin/rpc/rpc_test.go b/rollout/steps/plugin/rpc/rpc_test.go index 9469c17af9..b5bac5e3f6 100644 --- a/rollout/steps/plugin/rpc/rpc_test.go +++ b/rollout/steps/plugin/rpc/rpc_test.go @@ -88,27 +88,17 @@ func TestPlugin(t *testing.T) { ro := v1alpha1.Rollout{} - err = plugin.RemoveManagedRoutes(&ro) + _, err = plugin.Run(&ro, &types.RpcStepContext{}) assert.Equal(t, "", err.Error()) - err = plugin.SetMirrorRoute(&ro, &v1alpha1.SetMirrorRoute{}) + _, err = plugin.Terminate(&ro, &types.RpcStepContext{}) assert.Equal(t, "", err.Error()) - err = plugin.SetHeaderRoute(&ro, &v1alpha1.SetHeaderRoute{}) - assert.Equal(t, "", err.Error()) - - err = plugin.SetWeight(&ro, 0, []v1alpha1.WeightDestination{}) - assert.Equal(t, "", err.Error()) - - b, err := plugin.VerifyWeight(&ro, 0, []v1alpha1.WeightDestination{}) - assert.Equal(t, "", err.Error()) - assert.Equal(t, true, *b.IsVerified()) - - err = plugin.UpdateHash(&ro, "canary-hash", "stable-hash", []v1alpha1.WeightDestination{}) + _, err = plugin.Abort(&ro, &types.RpcStepContext{}) assert.Equal(t, "", err.Error()) typeString := plugin.Type() - assert.Equal(t, "TestRPCPlugin", typeString) + assert.Equal(t, "StepPlugin Test", typeString) // Canceling should cause an exit cancel() @@ -141,31 +131,19 @@ func TestPluginClosedConnection(t *testing.T) { } func TestInvalidArgs(t *testing.T) { - server := TrafficRouterRPCServer{} + server := StepRPCServer{} badtype := struct { Args string }{} - var errRpc types.RpcError - err := server.SetMirrorRoute(badtype, &errRpc) + var resp Response + err := server.Run(badtype, &resp) assert.Error(t, err) - err = server.RemoveManagedRoutes(badtype, &errRpc) + err = server.Terminate(badtype, &resp) assert.Error(t, err) - var vw VerifyWeightResponse - err = server.VerifyWeight(badtype, &vw) + err = server.Abort(badtype, &resp) assert.Error(t, err) - err = server.SetMirrorRoute(badtype, &errRpc) - assert.Error(t, err) - - err = server.SetHeaderRoute(badtype, &errRpc) - assert.Error(t, err) - - err = server.SetWeight(badtype, &errRpc) - assert.Error(t, err) - - err = server.UpdateHash(badtype, &errRpc) - assert.Error(t, err) } From 2169e35e9e8b2841615c320f1a42ceba46484fbb Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 14:47:25 -0400 Subject: [PATCH 05/41] add rpc plugin tests Signed-off-by: Alexandre Gaudreault --- hack/update-mocks.sh | 5 + .../rollouts/v1alpha1/openapi_generated.go | 9 +- rollout/stepplugin.go | 16 +- rollout/stepplugin_test.go | 296 ++++++++++----- rollout/steps/plugin/plugin.go | 7 +- rollout/steps/plugin/plugin_test.go | 359 ++++++++++++++++++ rollout/steps/plugin/rpc/mocks/StepPlugin.go | 150 ++++++++ 7 files changed, 737 insertions(+), 105 deletions(-) create mode 100644 rollout/steps/plugin/plugin_test.go create mode 100644 rollout/steps/plugin/rpc/mocks/StepPlugin.go diff --git a/hack/update-mocks.sh b/hack/update-mocks.sh index 5412469908..9e4f397db1 100755 --- a/hack/update-mocks.sh +++ b/hack/update-mocks.sh @@ -26,3 +26,8 @@ mockery \ --dir "${PROJECT_ROOT}"/rollout/steps/plugin \ --name "Resolver|StepPlugin" \ --output "${PROJECT_ROOT}"/rollout/steps/plugin/mocks + +mockery \ + --dir "${PROJECT_ROOT}"/rollout/steps/plugin/rpc \ + --name "StepPlugin" \ + --output "${PROJECT_ROOT}"/rollout/steps/plugin/rpc/mocks diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 5e98a242ab..4840e5c63d 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -3545,13 +3545,6 @@ func schema_pkg_apis_rollouts_v1alpha1_PluginStep(ref common.ReferenceCallback) Format: "", }, }, - "AbortOnFailure": { - SchemaProps: spec.SchemaProps{ - Default: false, - Type: []string{"boolean"}, - Format: "", - }, - }, "config": { SchemaProps: spec.SchemaProps{ Description: "Config the configuration object for the specified plugin", @@ -3560,7 +3553,7 @@ func schema_pkg_apis_rollouts_v1alpha1_PluginStep(ref common.ReferenceCallback) }, }, }, - Required: []string{"name", "AbortOnFailure"}, + Required: []string{"name"}, }, }, } diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 1f6619cf79..cf176cc476 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -20,7 +20,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { status, result, err := stepPlugin.Run(c.rollout) if err != nil { - return fmt.Errorf("TODO") + return fmt.Errorf("Error calling Run on plugin: %w", err) } // Update new status and preserve order @@ -41,22 +41,24 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if status.Phase == v1alpha1.StepPluginPhaseRunning && result.RequeueAfter != nil { c.enqueueRolloutAfter(c.rollout, *result.RequeueAfter) - } - - if status.Phase == v1alpha1.StepPluginPhaseFailed { - c.pauseContext.AddAbort(status.Message) - // Call each plugin in reverse order? + return nil } if status.Phase == v1alpha1.StepPluginPhaseError { c.persistRolloutStatus(&c.newStatus) + return err + } + + if status.Phase == v1alpha1.StepPluginPhaseFailed { + // Call each plugin in reverse order? + c.pauseContext.AddAbort(status.Message) } return nil } func (c *rolloutContext) isPluginStepCompleted(stepIndex int32) bool { - status := findCurrentStepStatus(c.rollout.Status.Canary.StepPluginStatuses, stepIndex) + status := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex) return status != nil && (status.Phase == v1alpha1.StepPluginPhaseSuccessful || status.Phase == v1alpha1.StepPluginPhaseFailed || status.Phase == v1alpha1.StepPluginPhaseError) diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index f46f88bb4c..ea927d1970 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -3,15 +3,17 @@ package rollout import ( "encoding/json" "testing" + "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/mocks" logutil "github.com/argoproj/argo-rollouts/utils/log" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func newStepPluginRollout() *v1alpha1.Rollout { @@ -22,7 +24,7 @@ func newStepPluginRollout() *v1alpha1.Rollout { }, }, } - return newCanaryRollout("foo", 3, nil, steps, pointer.Int32(0), intstr.FromInt(1), intstr.FromInt(0)) + return newCanaryRollout("foo", 3, nil, steps, ptr.To(int32(0)), intstr.FromInt(1), intstr.FromInt(0)) } func newStepPluginStatus() *v1alpha1.StepPluginStatus { @@ -44,7 +46,9 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { rollout: r, log: logutil.WithRollout(r), reconcilerBase: reconcilerBase{ - stepPluginResolver: stepPluginResolver, + stepPluginResolver: stepPluginResolver, + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, } @@ -85,108 +89,228 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }) } -//Controller: -// Add test for plugin config -// Add InitPlugin call test +func Test_StepPlugin_RunningReconciliation(t *testing.T) { + setup := func(t *testing.T, phase v1alpha1.StepPluginPhase, requeueAfter *time.Duration) (*rolloutContext, *v1alpha1.StepPluginStatus) { + stepPluginResolver := mocks.NewResolver(t) + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything).Return(stepPluginMock, nil) -//Reconcile: -// Add disable feature + r := newStepPluginRollout() + roCtx := &rolloutContext{ + rollout: r, + log: logutil.WithRollout(r), + reconcilerBase: reconcilerBase{ + stepPluginResolver: stepPluginResolver, + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + }, + } -//RPC: -// Test config -// Test state on first tun -// Test state with existing + runStatus := newStepPluginStatus() + runResult := &plugin.StepResult{ + RequeueAfter: requeueAfter, + } -// if running || failed || success, state saved -// if running, requeue after -// if failed, abort -// if success, next step, else current step + stepPluginMock.On("Run", r).Return(runStatus, runResult, nil) + runStatus.Phase = phase + return roCtx, runStatus + } -//if run error, save message+phase, but not state + t.Run("Status is added when not present", func(t *testing.T) { + roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseRunning, nil) -//When promote-full, terminate called on current step -//When abort, abort all steps? validate status? validate order + err := roCtx.reconcileCanaryPluginStep() -//error during run? -//error during abort? -//error during terminate? safe to ignore? + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + }) + t.Run("Status is updated when existing", func(t *testing.T) { + roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseRunning, nil) -// cannot modify ptr reference of rollout input object + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Message: "this is the existing status", + Phase: v1alpha1.StepPluginPhaseRunning, + }, + } -//input rollout contains all plugin status state + err := roCtx.reconcileCanaryPluginStep() -// Helper: write helper functions? + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + }) + t.Run("Rollout is added to the queue", func(t *testing.T) { + expectedRequeueAfter := 123 * time.Second + roCtx, _ := setup(t, v1alpha1.StepPluginPhaseRunning, &expectedRequeueAfter) + + var requeuedAfter time.Duration + roCtx.enqueueRolloutAfter = func(obj any, duration time.Duration) { + requeuedAfter = duration + } + + err := roCtx.reconcileCanaryPluginStep() -func TestReconcileCanaryPluginStep(t *testing.T) { - t.Run("The plugin is skippped if it is disabled globally", func(t *testing.T) { - t.Fail() + require.NoError(t, err) + assert.Equal(t, expectedRequeueAfter, requeuedAfter) }) +} + +func Test_StepPlugin_FailedReconciliation(t *testing.T) { + setup := func(t *testing.T, phase v1alpha1.StepPluginPhase) (*rolloutContext, *v1alpha1.StepPluginStatus) { + stepPluginResolver := mocks.NewResolver(t) + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything).Return(stepPluginMock, nil) - t.Run("The plugin receives the Rollout user configuration", func(t *testing.T) { + r := newStepPluginRollout() + logCtx := logutil.WithRollout(r) + roCtx := &rolloutContext{ + rollout: r, + log: logCtx, + reconcilerBase: reconcilerBase{ + stepPluginResolver: stepPluginResolver, + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, + } - t.Fail() + runStatus := newStepPluginStatus() + stepPluginMock.On("Run", r).Return(runStatus, nil, nil) + runStatus.Phase = phase + return roCtx, runStatus + } + + t.Run("Status is added when not present", func(t *testing.T) { + roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseFailed) + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) }) + t.Run("Status is updated when existing", func(t *testing.T) { + roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseFailed) - t.Run("The plugin receives an empty state the first time it is executed", func(t *testing.T) { + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Message: "this is the existing status", + Phase: v1alpha1.StepPluginPhaseRunning, + }, + } - t.Fail() + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) }) + t.Run("Rollout is aborted", func(t *testing.T) { + roCtx, _ := setup(t, v1alpha1.StepPluginPhaseFailed) - t.Run("The plugin receives the existing state if it is present", func(t *testing.T) { + err := roCtx.reconcileCanaryPluginStep() - t.Fail() + require.NoError(t, err) + assert.True(t, roCtx.pauseContext.IsAborted()) }) } -// func Test_rolloutContext_reconcileCanaryPluginStep(t *testing.T) { -// type fields struct { -// reconcilerBase reconcilerBase -// log *log.Entry -// rollout *v1alpha1.Rollout -// newRollout *v1alpha1.Rollout -// newRS *appsv1.ReplicaSet -// stableRS *appsv1.ReplicaSet -// allRSs []*appsv1.ReplicaSet -// olderRSs []*appsv1.ReplicaSet -// otherRSs []*appsv1.ReplicaSet -// currentArs analysisutil.CurrentAnalysisRuns -// otherArs []*v1alpha1.AnalysisRun -// currentEx *v1alpha1.Experiment -// otherExs []*v1alpha1.Experiment -// newStatus v1alpha1.RolloutStatus -// pauseContext *pauseContext -// targetsVerified *bool -// } -// tests := []struct { -// name string -// fields fields -// wantErr bool -// }{ -// // TODO: Add test cases. -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// c := &rolloutContext{ -// reconcilerBase: tt.fields.reconcilerBase, -// log: tt.fields.log, -// rollout: tt.fields.rollout, -// newRollout: tt.fields.newRollout, -// newRS: tt.fields.newRS, -// stableRS: tt.fields.stableRS, -// allRSs: tt.fields.allRSs, -// olderRSs: tt.fields.olderRSs, -// otherRSs: tt.fields.otherRSs, -// currentArs: tt.fields.currentArs, -// otherArs: tt.fields.otherArs, -// currentEx: tt.fields.currentEx, -// otherExs: tt.fields.otherExs, -// newStatus: tt.fields.newStatus, -// pauseContext: tt.fields.pauseContext, -// targetsVerified: tt.fields.targetsVerified, -// } -// if err := c.reconcileCanaryPluginStep(); (err != nil) != tt.wantErr { -// t.Errorf("rolloutContext.reconcileCanaryPluginStep() error = %v, wantErr %v", err, tt.wantErr) -// } -// }) -// } -// } +//Controller: +// Add test for plugin config +// Add InitPlugin call test + +//Reconcile: +// Add disable feature + +// Plugin: +//if run error, save message+phase, but not state + +//When promote-full, terminate called on current step +//When abort, abort all steps? validate status? validate order + +//error during run? +//error during abort? +//error during terminate? safe to ignore? + +// Helper: write helper functions? + +func Test_rolloutContext_isPluginStepCompleted(t *testing.T) { + newRolloutContext := func(status *v1alpha1.StepPluginStatus) *rolloutContext { + r := newStepPluginRollout() + logCtx := logutil.WithRollout(r) + roCtx := &rolloutContext{ + rollout: r, + log: logCtx, + } + roCtx.newStatus = v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + } + if status != nil { + roCtx.newStatus.Canary.StepPluginStatuses = append(roCtx.newStatus.Canary.StepPluginStatuses, *status) + } + return roCtx + } + + tests := []struct { + name string + status *v1alpha1.StepPluginStatus + index int32 + want bool + }{ + { + name: "Status is not set", + status: nil, + index: 0, + want: false, + }, + { + name: "Phase is successful", + status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseSuccessful}, + index: 0, + want: true, + }, + { + name: "Phase is failed", + status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseFailed}, + index: 0, + want: true, + }, + { + name: "Phase is error", + status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseError}, + index: 0, + want: true, + }, + { + name: "Phase is running", + status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseRunning}, + index: 0, + want: false, + }, + { + name: "status for index is missing", + status: &v1alpha1.StepPluginStatus{Index: 1, Phase: v1alpha1.StepPluginPhaseSuccessful}, + index: 0, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := newRolloutContext(tt.status) + if got := c.isPluginStepCompleted(tt.index); got != tt.want { + t.Errorf("rolloutContext.isPluginStepCompleted() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 907ce668c6..12d4191881 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -53,8 +53,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, stepStatus.Phase = v1alpha1.StepPluginPhaseError stepStatus.Message = err.Error() stepStatus.FinishedAt = &finishedAt - // return err nil ? - return stepStatus, result, fmt.Errorf("failed to run step via plugin: %w", err) + return stepStatus, result, nil } stepStatus.Message = resp.Message @@ -70,7 +69,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { result.RequeueAfter = &defaultRequeuDuration - if resp.RequeueAfter > minRequeueDuration { + if resp.RequeueAfter < minRequeueDuration { result.RequeueAfter = &resp.RequeueAfter } } @@ -88,7 +87,7 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout) *v1alpha1.StepPluginStatus { for _, s := range rollout.Status.Canary.StepPluginStatuses { if s.Index == p.index && s.Name == p.name { - return &s + return s.DeepCopy() } } return nil diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go new file mode 100644 index 0000000000..350b4053e5 --- /dev/null +++ b/rollout/steps/plugin/plugin_test.go @@ -0,0 +1,359 @@ +package plugin + +import ( + "encoding/json" + "testing" + "time" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc/mocks" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_stepPlugin_Run(t *testing.T) { + setup := func(t *testing.T) (*stepPlugin, *mocks.StepPlugin) { + plugin := &stepPlugin{ + name: "test-plugin", + index: 0, + config: json.RawMessage("value"), + } + rpcPluginMock := mocks.NewStepPlugin(t) + plugin.rpc = rpcPluginMock + return plugin, rpcPluginMock + } + + t.Run("Argument set without status", func(t *testing.T) { + p, rpcMock := setup(t) + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + }, + }, + }, + }, + } + validateArguments := func(args mock.Arguments) { + rollout, ok0 := args.Get(0).(*v1alpha1.Rollout) + context, ok1 := args.Get(1).(*types.RpcStepContext) + require.Truef(t, ok0, "Argument 0 is of the wrong type") + require.Truef(t, ok1, "Argument 1 is of the wrong type") + + assert.NotNil(t, rollout) + assert.NotSame(t, r, rollout) + assert.NotNil(t, context) + assert.Equal(t, p.name, context.PluginName) + assert.Equal(t, p.config, context.Config) + assert.Nil(t, context.Status) + } + + rpcMock.On("Run", mock.Anything, mock.Anything).Run(validateArguments).Return(types.RpcStepResult{}, types.RpcError{}).Once() + + p.index = 1 + _, _, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + }) + t.Run("Argument set with status", func(t *testing.T) { + p, rpcMock := setup(t) + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + }, + }, + }, + }, + } + validateArguments := func(args mock.Arguments) { + rollout, ok0 := args.Get(0).(*v1alpha1.Rollout) + context, ok1 := args.Get(1).(*types.RpcStepContext) + require.Truef(t, ok0, "Argument 0 is of the wrong type") + require.Truef(t, ok1, "Argument 1 is of the wrong type") + + assert.NotNil(t, rollout) + assert.NotSame(t, r, rollout) + assert.NotNil(t, context) + assert.Equal(t, p.name, context.PluginName) + assert.Equal(t, p.config, context.Config) + assert.Equal(t, r.Status.Canary.StepPluginStatuses[0].Status, context.Status) + } + + rpcMock.On("Run", mock.Anything, mock.Anything).Run(validateArguments).Return(types.RpcStepResult{}, types.RpcError{}).Once() + + p.index = 0 + _, _, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + }) + t.Run("use existing state", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := &v1alpha1.StepPluginStatus{ + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + Phase: v1alpha1.StepPluginPhaseRunning, + } + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + *currentStatus, + }, + }, + }, + } + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Equal(t, rpcResult.Status, status.Status) + assert.NotNil(t, status.FinishedAt) + assert.Nil(t, result.RequeueAfter) + }) + t.Run("Successful status", func(t *testing.T) { + p, rpcMock := setup(t) + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + }, + } + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.StartedAt) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Equal(t, rpcResult.Status, status.Status) + assert.Nil(t, result.RequeueAfter) + }) + t.Run("Running status", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := &v1alpha1.StepPluginStatus{ + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + } + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + *currentStatus, + }, + }, + }, + } + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseRunning, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.StartedAt) + assert.Nil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Equal(t, rpcResult.Status, status.Status) + assert.Equal(t, rpcResult.RequeueAfter, result.RequeueAfter) + }) + t.Run("Running status without requeue", func(t *testing.T) { + p, rpcMock := setup(t) + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + }, + } + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseRunning, + Message: "Good message", + Status: json.RawMessage("status"), + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.StartedAt) + assert.Nil(t, status.FinishedAt) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Equal(t, rpcResult.Status, status.Status) + assert.Equal(t, defaultRequeuDuration, *result.RequeueAfter) + }) + t.Run("Running status with requeue too fast", func(t *testing.T) { + p, rpcMock := setup(t) + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + }, + } + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseRunning, + Message: "Good message", + RequeueAfter: 1 * time.Second, + Status: json.RawMessage("status"), + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.StartedAt) + assert.Nil(t, status.FinishedAt) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Equal(t, rpcResult.Status, status.Status) + assert.Equal(t, minRequeueDuration, *result.RequeueAfter) + }) + t.Run("Failed status", func(t *testing.T) { + p, rpcMock := setup(t) + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + }, + } + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.StartedAt) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Equal(t, rpcResult.Status, status.Status) + assert.Nil(t, result.RequeueAfter) + }) + t.Run("Error status", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := &v1alpha1.StepPluginStatus{ + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + } + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + *currentStatus, + }, + }, + }, + } + + invalidResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "This message should not be used", + RequeueAfter: time.Hour, + Status: json.RawMessage("invalid status"), + } + expectedError := types.RpcError{ + ErrorString: "This is an error", + } + rpcMock.On("Run", mock.Anything, mock.Anything).Return(invalidResult, expectedError).Once() + + status, result, err := p.Run(r) + + require.NoError(t, err) + rpcMock.AssertExpectations(t) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) + assert.Equal(t, expectedError.Error(), status.Message) + assert.Equal(t, currentStatus.Status, status.Status) + assert.NotNil(t, status.FinishedAt) + assert.Nil(t, result.RequeueAfter) + }) +} diff --git a/rollout/steps/plugin/rpc/mocks/StepPlugin.go b/rollout/steps/plugin/rpc/mocks/StepPlugin.go new file mode 100644 index 0000000000..c858f4fa58 --- /dev/null +++ b/rollout/steps/plugin/rpc/mocks/StepPlugin.go @@ -0,0 +1,150 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + + types "github.com/argoproj/argo-rollouts/utils/plugin/types" + + v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" +) + +// StepPlugin is an autogenerated mock type for the StepPlugin type +type StepPlugin struct { + mock.Mock +} + +// Abort provides a mock function with given fields: _a0, _a1 +func (_m *StepPlugin) Abort(_a0 *v1alpha1.Rollout, _a1 *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Abort") + } + + var r0 types.RpcStepResult + var r1 types.RpcError + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout, *types.RpcStepContext) (types.RpcStepResult, types.RpcError)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout, *types.RpcStepContext) types.RpcStepResult); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(types.RpcStepResult) + } + + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout, *types.RpcStepContext) types.RpcError); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Get(1).(types.RpcError) + } + + return r0, r1 +} + +// InitPlugin provides a mock function with given fields: +func (_m *StepPlugin) InitPlugin() types.RpcError { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for InitPlugin") + } + + var r0 types.RpcError + if rf, ok := ret.Get(0).(func() types.RpcError); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(types.RpcError) + } + + return r0 +} + +// Run provides a mock function with given fields: _a0, _a1 +func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout, _a1 *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Run") + } + + var r0 types.RpcStepResult + var r1 types.RpcError + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout, *types.RpcStepContext) (types.RpcStepResult, types.RpcError)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout, *types.RpcStepContext) types.RpcStepResult); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(types.RpcStepResult) + } + + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout, *types.RpcStepContext) types.RpcError); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Get(1).(types.RpcError) + } + + return r0, r1 +} + +// Terminate provides a mock function with given fields: _a0, _a1 +func (_m *StepPlugin) Terminate(_a0 *v1alpha1.Rollout, _a1 *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Terminate") + } + + var r0 types.RpcStepResult + var r1 types.RpcError + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout, *types.RpcStepContext) (types.RpcStepResult, types.RpcError)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout, *types.RpcStepContext) types.RpcStepResult); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(types.RpcStepResult) + } + + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout, *types.RpcStepContext) types.RpcError); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Get(1).(types.RpcError) + } + + return r0, r1 +} + +// Type provides a mock function with given fields: +func (_m *StepPlugin) Type() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Type") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// NewStepPlugin creates a new instance of StepPlugin. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStepPlugin(t interface { + mock.TestingT + Cleanup(func()) +}) *StepPlugin { + mock := &StepPlugin{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} From c76da2da3a4d22c5bbf2fe3d421d33f04e5b3db4 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 14:48:10 -0400 Subject: [PATCH 06/41] better message Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index cf176cc476..cb47c7ac00 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -20,7 +20,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { status, result, err := stepPlugin.Run(c.rollout) if err != nil { - return fmt.Errorf("Error calling Run on plugin: %w", err) + return fmt.Errorf("failed to run plugin: %w", err) } // Update new status and preserve order From e61ca78ecbcad4caf372f8ba9bdf730d6da4ed19 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 14:53:30 -0400 Subject: [PATCH 07/41] add order test Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index ea927d1970..fc59996bab 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -87,6 +87,33 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) }) + t.Run("Status order is preserved when updating", func(t *testing.T) { + roCtx, runStatus := setup(t) + runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 123, + Name: runStatus.Name, + }, + { + Index: runStatus.Index, + Name: runStatus.Name, + }, + { + Index: 456, + Name: "other", + }, + } + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 3) + assert.Equal(t, int32(123), roCtx.newStatus.Canary.StepPluginStatuses[0].Index) + assert.Equal(t, runStatus.Index, roCtx.newStatus.Canary.StepPluginStatuses[1].Index) + assert.Equal(t, int32(456), roCtx.newStatus.Canary.StepPluginStatuses[2].Index) + }) } func Test_StepPlugin_RunningReconciliation(t *testing.T) { From 129ff0c2d7f64f3116c9a424576ac14fd59ed0a0 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 10 Apr 2024 16:45:29 -0400 Subject: [PATCH 08/41] implement terminate Signed-off-by: Alexandre Gaudreault --- rollout/canary.go | 2 +- rollout/stepplugin.go | 52 +++++++++++++++++--------- rollout/stepplugin_test.go | 6 +-- rollout/steps/plugin/mocks/Resolver.go | 25 +++++++------ rollout/steps/plugin/plugin.go | 33 +++++++++++++++- rollout/steps/plugin/resolver.go | 9 +++-- 6 files changed, 89 insertions(+), 38 deletions(-) diff --git a/rollout/canary.go b/rollout/canary.go index 3826cd2637..65db8355c9 100644 --- a/rollout/canary.go +++ b/rollout/canary.go @@ -350,7 +350,7 @@ func (c *rolloutContext) completedCurrentCanaryStep() bool { case currentStep.SetMirrorRoute != nil: return true case currentStep.Plugin != nil: - return c.isPluginStepCompleted(*currentStepIndex) + return c.isStepPluginCompleted(*currentStepIndex) } return false } diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index cb47c7ac00..7ad46f6525 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -13,31 +13,29 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } - stepPlugin, err := c.stepPluginResolver.Resolve(*currentStepIndex, *currentStep.Plugin) + stepPlugin, err := c.stepPluginResolver.Resolve(*currentStepIndex, *currentStep.Plugin, c.log) if err != nil { return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) } + if c.rollout.Status.PromoteFull { + currentStatus := findCurrentStepStatus(c.rollout.Status.Canary.StepPluginStatuses, *currentStepIndex) + if currentStatus != nil && currentStatus.Phase == v1alpha1.StepPluginPhaseRunning { + status, err := stepPlugin.Terminate(c.rollout) + if err != nil { + return fmt.Errorf("failed to terminate plugin: %w", err) + } + c.newStatus.Canary.StepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + } + + return nil + } + status, result, err := stepPlugin.Run(c.rollout) if err != nil { return fmt.Errorf("failed to run plugin: %w", err) } - - // Update new status and preserve order - pluginStatuses := []v1alpha1.StepPluginStatus{} - statusAdded := false - for _, s := range c.rollout.Status.Canary.StepPluginStatuses { - if s.Index == *currentStepIndex { - pluginStatuses = append(pluginStatuses, *status) - statusAdded = true - continue - } - pluginStatuses = append(pluginStatuses, s) - } - if !statusAdded { - pluginStatuses = append(pluginStatuses, *status) - } - c.newStatus.Canary.StepPluginStatuses = pluginStatuses + c.newStatus.Canary.StepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) if status.Phase == v1alpha1.StepPluginPhaseRunning && result.RequeueAfter != nil { c.enqueueRolloutAfter(c.rollout, *result.RequeueAfter) @@ -57,7 +55,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } -func (c *rolloutContext) isPluginStepCompleted(stepIndex int32) bool { +func (c *rolloutContext) isStepPluginCompleted(stepIndex int32) bool { status := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex) return status != nil && (status.Phase == v1alpha1.StepPluginPhaseSuccessful || status.Phase == v1alpha1.StepPluginPhaseFailed || @@ -72,3 +70,21 @@ func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32) } return nil } + +func updateStepPluginStatus(statuses []v1alpha1.StepPluginStatus, status *v1alpha1.StepPluginStatus) []v1alpha1.StepPluginStatus { + // Update new status and preserve order + newStatuses := []v1alpha1.StepPluginStatus{} + statusAdded := false + for _, s := range statuses { + if !statusAdded && s.Index == status.Index { + newStatuses = append(newStatuses, *status) + statusAdded = true + continue + } + newStatuses = append(newStatuses, s) + } + if !statusAdded { + newStatuses = append(newStatuses, *status) + } + return newStatuses +} diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index fc59996bab..fbb8032da8 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -270,7 +270,7 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { // Helper: write helper functions? -func Test_rolloutContext_isPluginStepCompleted(t *testing.T) { +func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { newRolloutContext := func(status *v1alpha1.StepPluginStatus) *rolloutContext { r := newStepPluginRollout() logCtx := logutil.WithRollout(r) @@ -335,8 +335,8 @@ func Test_rolloutContext_isPluginStepCompleted(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := newRolloutContext(tt.status) - if got := c.isPluginStepCompleted(tt.index); got != tt.want { - t.Errorf("rolloutContext.isPluginStepCompleted() = %v, want %v", got, tt.want) + if got := c.isStepPluginCompleted(tt.index); got != tt.want { + t.Errorf("rolloutContext.isStepPluginCompleted() = %v, want %v", got, tt.want) } }) } diff --git a/rollout/steps/plugin/mocks/Resolver.go b/rollout/steps/plugin/mocks/Resolver.go index 3a909039c7..356b69e0b5 100644 --- a/rollout/steps/plugin/mocks/Resolver.go +++ b/rollout/steps/plugin/mocks/Resolver.go @@ -3,9 +3,12 @@ package mocks import ( - v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" - plugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" + logrus "github.com/sirupsen/logrus" mock "github.com/stretchr/testify/mock" + + plugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" + + v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" ) // Resolver is an autogenerated mock type for the Resolver type @@ -13,9 +16,9 @@ type Resolver struct { mock.Mock } -// Resolve provides a mock function with given fields: index, _a1 -func (_m *Resolver) Resolve(index int32, _a1 v1alpha1.PluginStep) (plugin.StepPlugin, error) { - ret := _m.Called(index, _a1) +// Resolve provides a mock function with given fields: index, _a1, log +func (_m *Resolver) Resolve(index int32, _a1 v1alpha1.PluginStep, log *logrus.Entry) (plugin.StepPlugin, error) { + ret := _m.Called(index, _a1, log) if len(ret) == 0 { panic("no return value specified for Resolve") @@ -23,19 +26,19 @@ func (_m *Resolver) Resolve(index int32, _a1 v1alpha1.PluginStep) (plugin.StepPl var r0 plugin.StepPlugin var r1 error - if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep) (plugin.StepPlugin, error)); ok { - return rf(index, _a1) + if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep, *logrus.Entry) (plugin.StepPlugin, error)); ok { + return rf(index, _a1, log) } - if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep) plugin.StepPlugin); ok { - r0 = rf(index, _a1) + if rf, ok := ret.Get(0).(func(int32, v1alpha1.PluginStep, *logrus.Entry) plugin.StepPlugin); ok { + r0 = rf(index, _a1, log) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(plugin.StepPlugin) } } - if rf, ok := ret.Get(1).(func(int32, v1alpha1.PluginStep) error); ok { - r1 = rf(index, _a1) + if rf, ok := ret.Get(1).(func(int32, v1alpha1.PluginStep, *logrus.Entry) error); ok { + r1 = rf(index, _a1, log) } else { r1 = ret.Error(1) } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 12d4191881..c991d18371 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -9,6 +9,7 @@ import ( "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" "github.com/argoproj/argo-rollouts/utils/plugin/types" metatime "github.com/argoproj/argo-rollouts/utils/time" + log "github.com/sirupsen/logrus" ) type stepPlugin struct { @@ -16,6 +17,7 @@ type stepPlugin struct { index int32 name string config json.RawMessage + log *log.Entry } type StepResult struct { @@ -60,7 +62,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, if resp.Phase != "" { stepStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) } - // validate phase or Error + if stepStatus.Phase == v1alpha1.StepPluginPhaseSuccessful || stepStatus.Phase == v1alpha1.StepPluginPhaseFailed { stepStatus.FinishedAt = &finishedAt } @@ -78,8 +80,35 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, } func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { - return nil, fmt.Errorf("Not implemented") + stepStatus := p.getStepStatus(rollout) + if stepStatus == nil || stepStatus.Phase != v1alpha1.StepPluginPhaseRunning { + return stepStatus, nil + } + + resp, err := p.rpc.Terminate(rollout.DeepCopy(), p.getStepContext(stepStatus)) + finishedAt := metatime.MetaNow() + if err.HasError() { + stepStatus.Phase = v1alpha1.StepPluginPhaseError + stepStatus.Message = fmt.Sprintf("Terminated: %s", err.Error()) + stepStatus.FinishedAt = &finishedAt + return stepStatus, nil + } + + if resp.Phase != "" { + stepStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + } + + if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { + p.log.Warnf("terminate cannot run asynchronously. Overriding status phase to %s.", v1alpha1.StepPluginPhaseSuccessful) + stepStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + } + + stepStatus.Message = fmt.Sprintf("Terminated: %s", resp.Message) + stepStatus.FinishedAt = &finishedAt + stepStatus.Status = resp.Status + return stepStatus, nil } + func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { return nil, fmt.Errorf("Not implemented") } diff --git a/rollout/steps/plugin/resolver.go b/rollout/steps/plugin/resolver.go index c1f328aaaa..cb60aa980a 100644 --- a/rollout/steps/plugin/resolver.go +++ b/rollout/steps/plugin/resolver.go @@ -5,19 +5,21 @@ import ( "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/client" + log "github.com/sirupsen/logrus" ) -type resolver struct{} +type resolver struct { +} type Resolver interface { - Resolve(index int32, plugin v1alpha1.PluginStep) (StepPlugin, error) + Resolve(index int32, plugin v1alpha1.PluginStep, log *log.Entry) (StepPlugin, error) } func NewResolver() Resolver { return &resolver{} } -func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep) (StepPlugin, error) { +func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep, log *log.Entry) (StepPlugin, error) { pluginClient, err := client.GetPlugin(plugin.Name) if err != nil { return nil, fmt.Errorf("failed to get step plugin %s: %w", plugin.Name, err) @@ -28,5 +30,6 @@ func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep) (StepPlugin, index: index, name: plugin.Name, config: plugin.Config, + log: log.WithField("stepPlugin", plugin.Name), }, nil } From b61011241edfc7723078ca640cf224d6606ae25c Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 12 Apr 2024 10:50:06 -0400 Subject: [PATCH 09/41] Terminate tests Signed-off-by: Alexandre Gaudreault --- rollout/canary.go | 1 + rollout/context.go | 3 + rollout/stepplugin.go | 14 ++- rollout/stepplugin_test.go | 126 +++++++++++++++++++++----- rollout/steps/plugin/plugin.go | 4 +- rollout/steps/plugin/plugin_test.go | 136 ++++++++++++++++++++++++++++ rollout/sync.go | 1 + 7 files changed, 260 insertions(+), 25 deletions(-) diff --git a/rollout/canary.go b/rollout/canary.go index 65db8355c9..a9a2cd162d 100644 --- a/rollout/canary.go +++ b/rollout/canary.go @@ -361,6 +361,7 @@ func (c *rolloutContext) syncRolloutStatusCanary() error { newStatus.HPAReplicas = replicasetutil.GetActualReplicaCountForReplicaSets(c.allRSs) newStatus.Selector = metav1.FormatLabelSelector(c.rollout.Spec.Selector) newStatus.Canary.StablePingPong = c.rollout.Status.Canary.StablePingPong + newStatus.Canary.StepPluginStatuses = c.calculateStepPluginStatus() currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) newStatus.StableRS = c.rollout.Status.StableRS diff --git a/rollout/context.go b/rollout/context.go index f8fa5b5f03..64a9772923 100644 --- a/rollout/context.go +++ b/rollout/context.go @@ -42,6 +42,9 @@ type rolloutContext struct { newStatus v1alpha1.RolloutStatus pauseContext *pauseContext + // stepPluginStatuses are the mutated values to use in the newStatus + stepPluginStatuses []v1alpha1.StepPluginStatus + // targetsVerified indicates if the pods targets have been verified with underlying LoadBalancer. // This is used in pod-aware flat networks where LoadBalancers target Pods and not Nodes. // nil indicates the check was unnecessary or not performed. diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 7ad46f6525..0b5d68752d 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -25,7 +25,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if err != nil { return fmt.Errorf("failed to terminate plugin: %w", err) } - c.newStatus.Canary.StepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) } return nil @@ -35,7 +35,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if err != nil { return fmt.Errorf("failed to run plugin: %w", err) } - c.newStatus.Canary.StepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) if status.Phase == v1alpha1.StepPluginPhaseRunning && result.RequeueAfter != nil { c.enqueueRolloutAfter(c.rollout, *result.RequeueAfter) @@ -43,6 +43,8 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { } if status.Phase == v1alpha1.StepPluginPhaseError { + // TODO: fix this + panic("this is wrong. cant do that") c.persistRolloutStatus(&c.newStatus) return err } @@ -55,6 +57,14 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } +func (c *rolloutContext) calculateStepPluginStatus() []v1alpha1.StepPluginStatus { + if c.stepPluginStatuses == nil { + return c.rollout.Status.Canary.StepPluginStatuses + } + + return c.stepPluginStatuses +} + func (c *rolloutContext) isStepPluginCompleted(stepIndex int32) bool { status := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex) return status != nil && (status.Phase == v1alpha1.StepPluginPhaseSuccessful || diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index fbb8032da8..19dfbe9cc2 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -39,7 +39,7 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) - stepPluginResolver.On("Resolve", int32(0), mock.Anything).Return(stepPluginMock, nil) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() roCtx := &rolloutContext{ @@ -65,8 +65,8 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t) @@ -84,8 +84,8 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) }) t.Run("Status order is preserved when updating", func(t *testing.T) { roCtx, runStatus := setup(t) @@ -109,10 +109,10 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 3) - assert.Equal(t, int32(123), roCtx.newStatus.Canary.StepPluginStatuses[0].Index) - assert.Equal(t, runStatus.Index, roCtx.newStatus.Canary.StepPluginStatuses[1].Index) - assert.Equal(t, int32(456), roCtx.newStatus.Canary.StepPluginStatuses[2].Index) + require.Len(t, roCtx.stepPluginStatuses, 3) + assert.Equal(t, int32(123), roCtx.stepPluginStatuses[0].Index) + assert.Equal(t, runStatus.Index, roCtx.stepPluginStatuses[1].Index) + assert.Equal(t, int32(456), roCtx.stepPluginStatuses[2].Index) }) } @@ -120,7 +120,7 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase, requeueAfter *time.Duration) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) - stepPluginResolver.On("Resolve", int32(0), mock.Anything).Return(stepPluginMock, nil) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() roCtx := &rolloutContext{ @@ -149,8 +149,8 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseRunning, nil) @@ -167,8 +167,8 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) }) t.Run("Rollout is added to the queue", func(t *testing.T) { expectedRequeueAfter := 123 * time.Second @@ -190,7 +190,7 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) - stepPluginResolver.On("Resolve", int32(0), mock.Anything).Return(stepPluginMock, nil) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() logCtx := logutil.WithRollout(r) @@ -220,8 +220,8 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseFailed) @@ -238,8 +238,8 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.newStatus.Canary.StepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.newStatus.Canary.StepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) }) t.Run("Rollout is aborted", func(t *testing.T) { roCtx, _ := setup(t, v1alpha1.StepPluginPhaseFailed) @@ -251,6 +251,90 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { }) } +func Test_StepPlugin_FullyPromoted(t *testing.T) { + setup := func(t *testing.T) (*rolloutContext, *mocks.StepPlugin) { + stepPluginResolver := mocks.NewResolver(t) + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) + + r := newStepPluginRollout() + r.Status.PromoteFull = true + + logCtx := logutil.WithRollout(r) + roCtx := &rolloutContext{ + rollout: r, + log: logCtx, + reconcilerBase: reconcilerBase{ + stepPluginResolver: stepPluginResolver, + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, + } + + return roCtx, stepPluginMock + } + + t.Run("Terminate not called when status is missing", func(t *testing.T) { + roCtx, stepPluginMock := setup(t) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 999, + Name: "not current plugin", + Message: "other status", + Phase: v1alpha1.StepPluginPhaseRunning, + }, + } + + stepPluginMock.On("Terminate", mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginStatuses, 0) + }) + t.Run("Terminate not called when status is not running", func(t *testing.T) { + roCtx, stepPluginMock := setup(t) + runStatus := newStepPluginStatus() + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + } + + stepPluginMock.On("Terminate", mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginStatuses, 0) + }) + t.Run("Rollout is Terminated on full promotion if current step is running", func(t *testing.T) { + roCtx, stepPluginMock := setup(t) + runStatus := newStepPluginStatus() + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseRunning, + }, + } + + stepPluginMock.On("Terminate", mock.Anything).Return(runStatus, nil) + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + }) +} + //Controller: // Add test for plugin config // Add InitPlugin call test @@ -261,7 +345,6 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { // Plugin: //if run error, save message+phase, but not state -//When promote-full, terminate called on current step //When abort, abort all steps? validate status? validate order //error during run? @@ -284,8 +367,9 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { }, } if status != nil { - roCtx.newStatus.Canary.StepPluginStatuses = append(roCtx.newStatus.Canary.StepPluginStatuses, *status) + roCtx.stepPluginStatuses = append(roCtx.stepPluginStatuses, *status) } + roCtx.newStatus.Canary.StepPluginStatuses = roCtx.calculateStepPluginStatus() return roCtx } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index c991d18371..7611d3c500 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -99,8 +99,8 @@ func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginS } if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { - p.log.Warnf("terminate cannot run asynchronously. Overriding status phase to %s.", v1alpha1.StepPluginPhaseSuccessful) - stepStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + p.log.Warnf("terminate cannot run asynchronously. Overriding status phase to %s.", v1alpha1.StepPluginPhaseFailed) + stepStatus.Phase = v1alpha1.StepPluginPhaseFailed } stepStatus.Message = fmt.Sprintf("Terminated: %s", resp.Message) diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index 350b4053e5..ce7c765eb6 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -2,9 +2,12 @@ package plugin import ( "encoding/json" + "strings" "testing" "time" + log "github.com/sirupsen/logrus" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc/mocks" "github.com/argoproj/argo-rollouts/utils/plugin/types" @@ -20,6 +23,7 @@ func Test_stepPlugin_Run(t *testing.T) { name: "test-plugin", index: 0, config: json.RawMessage("value"), + log: log.WithFields(log.Fields{}), } rpcPluginMock := mocks.NewStepPlugin(t) plugin.rpc = rpcPluginMock @@ -357,3 +361,135 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Nil(t, result.RequeueAfter) }) } + +func Test_stepPlugin_Terminate(t *testing.T) { + setup := func(t *testing.T) (*stepPlugin, *mocks.StepPlugin) { + plugin := &stepPlugin{ + name: "test-plugin", + index: 0, + config: json.RawMessage("value"), + log: log.WithFields(log.Fields{}), + } + rpcPluginMock := mocks.NewStepPlugin(t) + plugin.rpc = rpcPluginMock + return plugin, rpcPluginMock + } + newRunningStatus := func() *v1alpha1.StepPluginStatus { + return &v1alpha1.StepPluginStatus{ + Index: 0, + Name: "test-plugin", + Status: json.RawMessage("step status value"), + StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + Phase: v1alpha1.StepPluginPhaseRunning, + } + } + newRollout := func(s *v1alpha1.StepPluginStatus) *v1alpha1.Rollout { + return &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + *s, + }, + }, + }, + } + } + + t.Run("Return existing status if not running", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + currentStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + r := newRollout(currentStatus) + + rpcMock.On("Terminate", mock.Anything, mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") + + status, err := p.Terminate(r) + + require.NoError(t, err) + assert.Equal(t, currentStatus, status) + }) + t.Run("Running phase overridden to failed if running", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + r := newRollout(currentStatus) + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseRunning, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Terminate", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}) + + status, err := p.Terminate(r) + + require.NoError(t, err) + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhaseFailed, status.Phase) + assert.Contains(t, status.Message, rpcResult.Message) + assert.True(t, strings.HasPrefix(status.Message, "Terminated:")) + assert.Equal(t, rpcResult.Status, status.Status) + }) + t.Run("Completes successfully", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + r := newRollout(currentStatus) + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Terminate", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}) + + status, err := p.Terminate(r) + + require.NoError(t, err) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Contains(t, status.Message, rpcResult.Message) + assert.True(t, strings.HasPrefix(status.Message, "Terminated:")) + assert.Equal(t, rpcResult.Status, status.Status) + }) + + t.Run("Error status", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + r := newRollout(currentStatus) + + invalidResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "This message should not be used", + RequeueAfter: time.Hour, + Status: json.RawMessage("invalid status"), + } + expectedError := types.RpcError{ + ErrorString: "This is an error", + } + rpcMock.On("Terminate", mock.Anything, mock.Anything).Return(invalidResult, expectedError) + + status, err := p.Terminate(r) + + require.NoError(t, err) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) + assert.Contains(t, status.Message, expectedError.Error()) + assert.True(t, strings.HasPrefix(status.Message, "Terminated:")) + assert.Equal(t, currentStatus.Status, status.Status) + }) +} diff --git a/rollout/sync.go b/rollout/sync.go index 875949ee55..db6debb0d3 100644 --- a/rollout/sync.go +++ b/rollout/sync.go @@ -903,6 +903,7 @@ func (c *rolloutContext) resetRolloutStatus(newStatus *v1alpha1.RolloutStatus) { newStatus.BlueGreen.ScaleUpPreviewCheckPoint = false newStatus.Canary.CurrentStepAnalysisRunStatus = nil newStatus.Canary.CurrentBackgroundAnalysisRunStatus = nil + newStatus.Canary.StepPluginStatuses = nil newStatus.CurrentStepIndex = replicasetutil.ResetCurrentStepIndex(c.rollout) } From 0db60eaba2ca4fe4768f50084e2589de91c3da8c Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 12 Apr 2024 17:24:15 -0400 Subject: [PATCH 10/41] aborted logic + some unit test Signed-off-by: Alexandre Gaudreault --- manifests/crds/rollout-crd.yaml | 3 + manifests/install.yaml | 3 + pkg/apiclient/rollout/rollout.swagger.json | 3 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 904 +++++++++--------- pkg/apis/rollouts/v1alpha1/generated.proto | 12 +- .../rollouts/v1alpha1/openapi_generated.go | 9 +- pkg/apis/rollouts/v1alpha1/types.go | 24 +- rollout/stepplugin.go | 72 +- rollout/stepplugin_test.go | 176 +++- rollout/steps/plugin/plugin.go | 91 +- rollout/steps/plugin/resolver.go | 3 +- ui/src/models/rollout/generated/api.ts | 6 + 12 files changed, 782 insertions(+), 524 deletions(-) diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index 297472042f..f20783133c 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -3740,6 +3740,8 @@ spec: type: string name: type: string + operation: + type: string phase: type: string startedAt: @@ -3751,6 +3753,7 @@ spec: required: - index - name + - operation - phase type: object type: array diff --git a/manifests/install.yaml b/manifests/install.yaml index 27d0fcd178..34815cff40 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -16230,6 +16230,8 @@ spec: type: string name: type: string + operation: + type: string phase: type: string startedAt: @@ -16241,6 +16243,7 @@ spec: required: - index - name + - operation - phase type: object type: array diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index 5388e53696..e27b980946 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -2534,6 +2534,9 @@ "name": { "type": "string" }, + "operation": { + "type": "string" + }, "phase": { "type": "string" }, diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index 8e790ef4c3..c97a41064f 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -3407,15 +3407,15 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 8715 bytes of a gzipped FileDescriptorProto + // 8743 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x6c, 0x64, 0xd7, 0x75, 0x98, 0x1e, 0x87, 0x43, 0xce, 0x9c, 0xe1, 0x92, 0xdc, 0xbb, 0xbb, 0x12, 0x45, 0x49, 0x3b, - 0x9b, 0xa7, 0x54, 0x95, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, + 0xca, 0x53, 0xaa, 0xae, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, 0x72, 0x45, 0xee, 0x52, 0x67, 0xb8, 0xda, 0xf8, 0x43, 0x89, 0x1f, 0x67, 0x2e, 0x87, 0x6f, 0x39, 0xf3, 0xde, 0xf8, 0xbd, 0x37, 0xdc, 0xa5, 0x2c, 0xc4, 0xb2, 0x0d, 0x39, 0x8e, 0x6b, 0x23, 0x6e, - 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0xe9, 0x8f, 0x36, 0x70, 0xd1, 0xfe, 0x08, + 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0xe9, 0x8f, 0x22, 0x70, 0xd1, 0xfe, 0x08, 0xd0, 0xa0, 0x6e, 0x0a, 0x07, 0x68, 0x0a, 0xe7, 0x47, 0xeb, 0xb4, 0x40, 0x98, 0x9a, 0xe9, 0x9f, - 0x06, 0x2d, 0x8c, 0x16, 0x2e, 0x82, 0xea, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, + 0x06, 0x2d, 0x8c, 0x16, 0x2e, 0x82, 0xe8, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, 0x9a, 0xc7, 0x95, 0xd2, 0xe6, 0xdf, 0xcc, 0x3d, 0xe7, 0x9e, 0x73, 0xde, 0xfd, 0x3c, 0xf7, 0xdc, 0x73, 0xce, 0x85, 0xd5, 0xb6, 0x1b, 0x6d, 0xf7, 0x37, 0x17, 0x9a, 0x7e, 0x77, 0xd1, 0x09, 0xda, 0x7e, 0x2f, 0xf0, 0xef, 0xf2, 0x1f, 0x1f, 0x0e, 0xfc, 0x4e, 0xc7, 0xef, 0x47, 0xe1, 0x62, 0x6f, @@ -3423,20 +3423,20 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0x2e, 0xb6, 0xa9, 0x47, 0x03, 0x27, 0xa2, 0xad, 0x85, 0x5e, 0xe0, 0x47, 0x3e, 0xf9, 0x44, 0x4c, 0x6d, 0x41, 0x51, 0xe3, 0x3f, 0x7e, 0x4e, 0xd5, 0x5d, 0xe8, 0xed, 0xb4, 0x17, 0x18, 0xb5, 0x05, 0x5d, 0xa2, 0xa8, 0xcd, 0x7f, 0xd8, 0x90, 0xa5, 0xed, 0xb7, 0xfd, 0x45, 0x4e, 0x74, 0xb3, 0xbf, - 0xc5, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x60, 0x36, 0xff, 0xe4, 0xce, 0x4b, 0xe1, 0x82, 0xeb, 0x33, + 0xc5, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x60, 0x36, 0xff, 0xd4, 0xce, 0x4b, 0xe1, 0x82, 0xeb, 0x33, 0xd9, 0x16, 0x37, 0x9d, 0xa8, 0xb9, 0xbd, 0xb8, 0x3b, 0x20, 0xd1, 0xbc, 0x6d, 0x20, 0x35, 0xfd, 0x80, 0x66, 0xe1, 0xbc, 0x10, 0xe3, 0x74, 0x9d, 0xe6, 0xb6, 0xeb, 0xd1, 0x60, 0x2f, 0xfe, 0xea, 0x2e, 0x8d, 0x9c, 0xac, 0x5a, 0x8b, 0xc3, 0x6a, 0x05, 0x7d, 0x2f, 0x72, 0xbb, 0x74, 0xa0, 0xc2, 0x4f, 0x1f, 0x55, 0x21, 0x6c, 0x6e, 0xd3, 0xae, 0x33, 0x50, 0xef, 0xf9, 0x61, 0xf5, 0xfa, 0x91, 0xdb, 0x59, 0x74, 0xbd, 0x28, 0x8c, 0x82, 0x74, 0x25, 0xfb, 0x47, 0x05, 0x28, 0xd7, 0x56, 0xeb, 0x8d, 0xc8, 0x89, 0xfa, 0x21, 0xf9, 0x8a, 0x05, 0x53, 0x1d, 0xdf, 0x69, 0xd5, 0x9d, 0x8e, 0xe3, - 0x35, 0x69, 0x30, 0x67, 0x5d, 0xb1, 0x9e, 0xae, 0x3c, 0xb7, 0xba, 0x30, 0x4a, 0x7f, 0x2d, 0xd4, + 0x35, 0x69, 0x30, 0x67, 0x3d, 0x69, 0x5d, 0xa9, 0x3c, 0xb7, 0xba, 0x30, 0x4a, 0x7f, 0x2d, 0xd4, 0xee, 0x85, 0x48, 0x43, 0xbf, 0x1f, 0x34, 0x29, 0xd2, 0xad, 0xfa, 0xc5, 0xef, 0xed, 0x57, 0x1f, 0x3a, 0xd8, 0xaf, 0x4e, 0xad, 0x1a, 0x9c, 0x30, 0xc1, 0x97, 0x7c, 0xcb, 0x82, 0xf3, 0x4d, 0xc7, 0x73, 0x82, 0xbd, 0x0d, 0x27, 0x68, 0xd3, 0xe8, 0xd5, 0xc0, 0xef, 0xf7, 0xe6, 0xc6, 0xce, 0x40, 0x9a, 0x47, 0xa5, 0x34, 0xe7, 0x97, 0xd2, 0xec, 0x70, 0x50, 0x02, 0x2e, 0x57, 0x18, 0x39, 0x9b, 0x1d, 0x6a, 0xca, 0x55, 0x38, 0x4b, 0xb9, 0x1a, 0x69, 0x76, 0x38, 0x28, 0x01, 0x79, 0x06, 0x26, - 0x5d, 0xaf, 0x1d, 0xd0, 0x30, 0x9c, 0x1b, 0xbf, 0x62, 0x3d, 0x5d, 0xae, 0xcf, 0xc8, 0xea, 0x93, + 0x5d, 0xaf, 0x1d, 0xd0, 0x30, 0x9c, 0x1b, 0x7f, 0xd2, 0xba, 0x52, 0xae, 0xcf, 0xc8, 0xea, 0x93, 0x2b, 0xa2, 0x18, 0x15, 0xdc, 0xfe, 0xcd, 0x02, 0x9c, 0xaf, 0xad, 0xd6, 0x37, 0x02, 0x67, 0x6b, 0xcb, 0x6d, 0xa2, 0xdf, 0x8f, 0x5c, 0xaf, 0x6d, 0x12, 0xb0, 0x0e, 0x27, 0x40, 0x5e, 0x84, 0x4a, 0x48, 0x83, 0x5d, 0xb7, 0x49, 0xd7, 0xfd, 0x20, 0xe2, 0x9d, 0x52, 0xac, 0x5f, 0x90, 0xe8, 0x95, @@ -3445,31 +3445,31 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0x40, 0xb7, 0xdc, 0xfb, 0xf2, 0x13, 0xe7, 0x64, 0xdd, 0xd9, 0x5a, 0x0a, 0x8e, 0x03, 0x35, 0xc8, 0x37, 0x2d, 0x98, 0x0d, 0x23, 0xb7, 0xb9, 0xe3, 0x7a, 0x34, 0x0c, 0x97, 0x7c, 0x6f, 0xcb, 0x6d, 0xcf, 0x15, 0x79, 0xb7, 0xdd, 0x1c, 0xad, 0xdb, 0x1a, 0x29, 0xaa, 0xf5, 0x8b, 0x4c, 0xa4, 0x74, - 0x29, 0x0e, 0x70, 0x27, 0x1f, 0x82, 0xb2, 0x6c, 0x51, 0x1a, 0xce, 0x4d, 0x5c, 0x29, 0x3c, 0x5d, + 0x29, 0x0e, 0x70, 0x27, 0x1f, 0x82, 0xb2, 0x6c, 0x51, 0x1a, 0xce, 0x4d, 0x3c, 0x59, 0xb8, 0x52, 0xae, 0x9f, 0x3b, 0xd8, 0xaf, 0x96, 0x57, 0x54, 0x21, 0xc6, 0x70, 0x7b, 0x19, 0xe6, 0x6a, 0xdd, - 0x4d, 0x27, 0x0c, 0x9d, 0x96, 0x1f, 0xa4, 0xba, 0xee, 0x69, 0x28, 0x75, 0x9d, 0x5e, 0xcf, 0xf5, - 0xda, 0xac, 0xef, 0x18, 0x9d, 0xa9, 0x83, 0xfd, 0x6a, 0x69, 0x4d, 0x96, 0xa1, 0x86, 0xda, 0xff, - 0x71, 0x0c, 0x2a, 0x35, 0xcf, 0xe9, 0xec, 0x85, 0x6e, 0x88, 0x7d, 0x8f, 0x7c, 0x16, 0x4a, 0x6c, - 0xd5, 0x6a, 0x39, 0x91, 0x23, 0x67, 0xfa, 0x47, 0x16, 0xc4, 0x22, 0xb2, 0x60, 0x2e, 0x22, 0xf1, - 0xe7, 0x33, 0xec, 0x85, 0xdd, 0x8f, 0x2e, 0xdc, 0xda, 0xbc, 0x4b, 0x9b, 0xd1, 0x1a, 0x8d, 0x9c, - 0x3a, 0x91, 0xbd, 0x00, 0x71, 0x19, 0x6a, 0xaa, 0xc4, 0x87, 0xf1, 0xb0, 0x47, 0x9b, 0x72, 0xe6, - 0xae, 0x8d, 0x38, 0x43, 0x62, 0xd1, 0x1b, 0x3d, 0xda, 0xac, 0x4f, 0x49, 0xd6, 0xe3, 0xec, 0x1f, - 0x72, 0x46, 0xe4, 0x1e, 0x4c, 0x84, 0x7c, 0x2d, 0x93, 0x93, 0xf2, 0x56, 0x7e, 0x2c, 0x39, 0xd9, - 0xfa, 0xb4, 0x64, 0x3a, 0x21, 0xfe, 0xa3, 0x64, 0x67, 0xff, 0x27, 0x0b, 0x2e, 0x18, 0xd8, 0xb5, - 0xa0, 0xdd, 0xef, 0x52, 0x2f, 0x22, 0x57, 0x60, 0xdc, 0x73, 0xba, 0x54, 0xce, 0x2a, 0x2d, 0xf2, - 0x4d, 0xa7, 0x4b, 0x91, 0x43, 0xc8, 0x93, 0x50, 0xdc, 0x75, 0x3a, 0x7d, 0xca, 0x1b, 0xa9, 0x5c, + 0x4d, 0x27, 0x0c, 0x9d, 0x96, 0x1f, 0xa4, 0xba, 0xee, 0x0a, 0x94, 0xba, 0x4e, 0xaf, 0xe7, 0x7a, + 0x6d, 0xd6, 0x77, 0x8c, 0xce, 0xd4, 0xc1, 0x7e, 0xb5, 0xb4, 0x26, 0xcb, 0x50, 0x43, 0xed, 0xff, + 0x34, 0x06, 0x95, 0x9a, 0xe7, 0x74, 0xf6, 0x42, 0x37, 0xc4, 0xbe, 0x47, 0x3e, 0x0b, 0x25, 0xb6, + 0x6a, 0xb5, 0x9c, 0xc8, 0x91, 0x33, 0xfd, 0x23, 0x0b, 0x62, 0x11, 0x59, 0x30, 0x17, 0x91, 0xf8, + 0xf3, 0x19, 0xf6, 0xc2, 0xee, 0x47, 0x17, 0x6e, 0x6d, 0xde, 0xa5, 0xcd, 0x68, 0x8d, 0x46, 0x4e, + 0x9d, 0xc8, 0x5e, 0x80, 0xb8, 0x0c, 0x35, 0x55, 0xe2, 0xc3, 0x78, 0xd8, 0xa3, 0x4d, 0x39, 0x73, + 0xd7, 0x46, 0x9c, 0x21, 0xb1, 0xe8, 0x8d, 0x1e, 0x6d, 0xd6, 0xa7, 0x24, 0xeb, 0x71, 0xf6, 0x0f, + 0x39, 0x23, 0x72, 0x0f, 0x26, 0x42, 0xbe, 0x96, 0xc9, 0x49, 0x79, 0x2b, 0x3f, 0x96, 0x9c, 0x6c, + 0x7d, 0x5a, 0x32, 0x9d, 0x10, 0xff, 0x51, 0xb2, 0xb3, 0xff, 0xb3, 0x05, 0x17, 0x0c, 0xec, 0x5a, + 0xd0, 0xee, 0x77, 0xa9, 0x17, 0x91, 0x27, 0x61, 0xdc, 0x73, 0xba, 0x54, 0xce, 0x2a, 0x2d, 0xf2, + 0x4d, 0xa7, 0x4b, 0x91, 0x43, 0xc8, 0x53, 0x50, 0xdc, 0x75, 0x3a, 0x7d, 0xca, 0x1b, 0xa9, 0x5c, 0x3f, 0x27, 0x51, 0x8a, 0x6f, 0xb0, 0x42, 0x14, 0x30, 0xf2, 0x36, 0x94, 0xf9, 0x8f, 0x6b, 0x81, 0xdf, 0xcd, 0xe9, 0xd3, 0xa4, 0x84, 0x6f, 0x28, 0xb2, 0x62, 0xf8, 0xe9, 0xbf, 0x18, 0x33, 0xb4, 0xff, 0xc8, 0x82, 0x19, 0xe3, 0xe3, 0x56, 0xdd, 0x30, 0x22, 0x9f, 0x19, 0x18, 0x3c, 0x0b, 0xc7, 0x1b, 0x3c, 0xac, 0x36, 0x1f, 0x3a, 0xb3, 0xf2, 0x4b, 0x4b, 0xaa, 0xc4, 0x18, 0x38, 0x1e, 0x14, - 0xdd, 0x88, 0x76, 0xc3, 0xb9, 0xb1, 0x2b, 0x85, 0xa7, 0x2b, 0xcf, 0xad, 0xe4, 0xd6, 0x8d, 0x71, + 0xdd, 0x88, 0x76, 0xc3, 0xb9, 0xb1, 0x27, 0x0b, 0x57, 0x2a, 0xcf, 0xad, 0xe4, 0xd6, 0x8d, 0x71, 0xfb, 0xae, 0x30, 0xfa, 0x28, 0xd8, 0xd8, 0xdf, 0x29, 0x24, 0xba, 0x6f, 0x4d, 0xc9, 0xf1, 0xae, 0x05, 0x13, 0x1d, 0x67, 0x93, 0x76, 0xc4, 0xdc, 0xaa, 0x3c, 0xf7, 0x66, 0x6e, 0x92, 0x28, 0x1e, 0x0b, 0xab, 0x9c, 0xfe, 0x55, 0x2f, 0x0a, 0xf6, 0xe2, 0xe1, 0x25, 0x0a, 0x51, 0x32, 0x27, 0x7f, - 0xcb, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, + 0xc7, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, 0x25, 0xda, 0x80, 0xa0, 0x29, 0xcb, 0xfc, 0xc7, 0xa0, 0x62, 0x7c, 0x02, 0x99, 0x85, 0xc2, 0x0e, 0xdd, 0x13, 0x03, 0x1e, 0xd9, 0x4f, 0x72, 0x31, 0x31, 0xc2, 0xe5, 0x90, 0xfe, 0xf8, 0xd8, 0x4b, - 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x29, 0x26, 0x06, 0x26, 0x5b, + 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x2b, 0x26, 0x06, 0x26, 0x5b, 0x08, 0x88, 0x0f, 0x93, 0x5d, 0x1a, 0x05, 0x6e, 0x53, 0x75, 0xd9, 0xf2, 0x68, 0xad, 0xb4, 0xc6, 0x89, 0xc5, 0x1b, 0xa2, 0xf8, 0x1f, 0xa2, 0xe2, 0x42, 0xb6, 0x61, 0xdc, 0x09, 0xda, 0xaa, 0x4f, 0xae, 0xe5, 0x33, 0x2d, 0xe3, 0xa5, 0xa2, 0x16, 0xb4, 0x43, 0xe4, 0x1c, 0xc8, 0x22, 0x94, 0x23, @@ -3479,7 +3479,7 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xa0, 0xec, 0x13, 0x90, 0x46, 0xd4, 0x63, 0x1d, 0x3b, 0x57, 0xe4, 0xcc, 0x71, 0xd4, 0x7e, 0x18, 0xa4, 0x5c, 0x7f, 0x5c, 0x8a, 0x72, 0x31, 0x0b, 0x8a, 0x99, 0xd2, 0x90, 0xb7, 0xa1, 0x12, 0x45, 0x9d, 0x46, 0xc4, 0xf4, 0xe0, 0xf6, 0xde, 0xdc, 0x04, 0x5f, 0xbc, 0x46, 0x5c, 0x61, 0x36, 0x36, - 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x51, 0x84, 0xf3, + 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x59, 0x84, 0xf3, 0x03, 0xdb, 0x0a, 0x79, 0x01, 0x8a, 0xbd, 0x6d, 0x27, 0x54, 0xfb, 0xc4, 0x65, 0xb5, 0x48, 0xad, 0xb3, 0xc2, 0xf7, 0xf6, 0xab, 0xe7, 0x54, 0x15, 0x5e, 0x80, 0x02, 0x99, 0x69, 0x6d, 0x5d, 0x1a, 0x86, 0x4e, 0x5b, 0x6d, 0x1e, 0xc6, 0x20, 0xe5, 0xc5, 0xa8, 0xe0, 0xe4, 0x17, 0x2c, 0x38, 0x27, @@ -3490,20 +3490,20 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xae, 0x13, 0xec, 0x49, 0xed, 0xee, 0xfa, 0x68, 0x9f, 0x87, 0x9a, 0x5e, 0xac, 0xe8, 0xc4, 0x65, 0x68, 0xf0, 0x23, 0x5f, 0xb4, 0xe0, 0x9c, 0x98, 0x07, 0x4a, 0x82, 0x89, 0x9c, 0x25, 0x38, 0xcf, 0x9a, 0x76, 0xd9, 0x64, 0x81, 0x49, 0x8e, 0xe4, 0x4d, 0xa8, 0x34, 0xfd, 0x6e, 0xaf, 0x43, 0x45, - 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0xf7, 0x49, + 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0x0f, 0x49, 0x1d, 0x47, 0x0d, 0x69, 0xf2, 0x69, 0x78, 0x34, 0xec, 0x37, 0x9b, 0x34, 0x0c, 0xb7, 0xfa, 0x1d, 0xec, 0x7b, 0xd7, 0xdd, 0x30, 0xf2, 0x83, 0xbd, 0x55, 0xb7, 0xeb, 0x46, 0x7c, 0x40, 0x17, 0xeb, 0x4f, 0x1c, 0xec, 0x57, 0x1f, 0x6d, 0x0c, 0x43, 0xc2, 0xe1, 0xf5, 0x89, 0x03, 0x8f, 0xf5, 0xbd, 0xe1, 0xe4, 0xc5, 0xf1, 0xa3, 0x7a, 0xb0, 0x5f, 0x7d, 0xec, 0xf6, 0x70, 0x34, 0x3c, 0x8c, 0x86, 0xfd, 0x27, 0x16, 0xdb, 0x86, 0xc4, 0x77, 0x6d, 0xd0, 0x6e, 0xaf, 0xc3, 0x96, 0xce, 0xb3, 0x57, - 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0x5f, 0x2d, + 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0xdf, 0x2c, 0xb8, 0x98, 0x46, 0x7e, 0x00, 0x0a, 0x5d, 0x98, 0x54, 0xe8, 0x6e, 0xe6, 0xfb, 0xb5, 0x43, 0xb4, 0xba, 0x5f, 0x34, 0x06, 0xac, 0x42, 0x45, 0xba, 0x45, 0x5e, 0x82, 0xa9, 0x48, 0xfe, 0xbd, 0x19, 0x2b, 0xe7, 0xda, 0x30, 0xb1, 0x61, 0xc0, 0x30, 0x81, 0xc9, 0x6a, 0x36, 0x3b, 0xfd, 0x30, 0xa2, 0x41, 0xa3, 0xe9, 0xf7, 0xc4, 0xb2, 0x5b, 0x8a, 0x6b, 0x2e, 0x19, 0x30, 0x4c, 0x60, 0xda, 0x7f, - 0xad, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, + 0xa3, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, 0x0f, 0x94, 0xfa, 0xf1, 0x25, 0x8b, 0x69, 0x71, 0x62, 0x00, 0x84, 0x52, 0x35, 0x7a, 0x3d, 0xdf, - 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x60, 0x1c, 0xa6, 0x6a, + 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x68, 0x1c, 0xa6, 0x6a, 0x5e, 0xe4, 0xd6, 0xb6, 0xb6, 0x5c, 0xcf, 0x8d, 0xf6, 0xc8, 0xd7, 0xc7, 0x60, 0xb1, 0x17, 0xd0, 0x2d, 0x1a, 0x04, 0xb4, 0xb5, 0xdc, 0x0f, 0x5c, 0xaf, 0xdd, 0x68, 0x6e, 0xd3, 0x56, 0xbf, 0xe3, 0x7a, 0xed, 0x95, 0xb6, 0xe7, 0xeb, 0xe2, 0xab, 0xf7, 0x69, 0xb3, 0xcf, 0xdb, 0x55, 0xac, 0x12, @@ -3516,12 +3516,12 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xe4, 0xc8, 0x1a, 0xf5, 0xd4, 0x1f, 0x4b, 0x2d, 0x85, 0x60, 0x3f, 0x51, 0xb0, 0xb0, 0xbf, 0x3b, 0x06, 0x97, 0x6a, 0xbd, 0xde, 0x1a, 0x0d, 0xb7, 0x53, 0x52, 0xfc, 0x92, 0x05, 0xd3, 0xbb, 0x6e, 0x10, 0xf5, 0x9d, 0x8e, 0xb2, 0x56, 0x0a, 0x79, 0x1a, 0xa3, 0xca, 0xc3, 0xb9, 0xbd, 0x91, 0x20, - 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x69, 0xc1, 0xac, 0x2c, + 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x6d, 0xc1, 0xac, 0x2c, 0xba, 0xe9, 0xb7, 0xa8, 0x69, 0x0d, 0xbf, 0x9d, 0xa7, 0x4c, 0x9a, 0xb8, 0xb0, 0x62, 0xa6, 0x4b, - 0x71, 0x40, 0x08, 0xfb, 0xbf, 0x8f, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, + 0x71, 0x40, 0x08, 0xfb, 0x7f, 0x8c, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, 0xa1, 0x1b, 0x20, 0xa4, 0x5b, 0xb2, 0x35, 0x3f, 0x99, 0xb7, 0xe4, 0xc8, 0xa6, 0x38, 0xf5, 0x9a, 0xb4, 0x3e, 0xc7, 0x96, 0xe4, 0xa5, 0x0c, 0xd6, 0x98, 0x29, 0x10, 0x97, 0x54, 0x18, 0xd5, 0x53, - 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc0, 0x63, 0x87, + 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc1, 0x63, 0x87, 0x90, 0x3b, 0x7a, 0x72, 0xda, 0x6f, 0xea, 0x51, 0x9f, 0x1c, 0x73, 0xc7, 0x98, 0xd7, 0x36, 0x4c, 0xf0, 0xa9, 0xa3, 0x26, 0x36, 0xb0, 0x3d, 0x98, 0xcf, 0xa9, 0x10, 0x25, 0xc4, 0xfe, 0xae, 0x05, 0xa5, 0x13, 0xd8, 0x3e, 0xab, 0x49, 0xdb, 0x67, 0x79, 0xc0, 0xee, 0x19, 0x0d, 0xda, 0x3d, 0x5f, @@ -3535,16 +3535,16 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xf2, 0x88, 0x96, 0x89, 0x5b, 0xec, 0x73, 0x9e, 0x93, 0x1c, 0xb5, 0xca, 0x28, 0x4a, 0x51, 0x72, 0xb2, 0xbf, 0x00, 0xd3, 0xc9, 0x7b, 0xb7, 0x63, 0x8c, 0xd9, 0x27, 0xa0, 0xe0, 0x04, 0x9e, 0x1c, 0xb1, 0x15, 0x89, 0x50, 0xa8, 0xe1, 0x4d, 0x64, 0xe5, 0xe4, 0x59, 0x28, 0x6d, 0xf5, 0x3b, 0x1d, - 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0xf7, 0x38, - 0xcc, 0xd4, 0x3b, 0x7d, 0xfa, 0x6a, 0x40, 0xa9, 0xb2, 0x05, 0xd5, 0x60, 0xa6, 0x17, 0xd0, 0x5d, - 0x97, 0xde, 0x6b, 0xd0, 0x0e, 0x6d, 0x46, 0x7e, 0x20, 0xa5, 0x79, 0x44, 0x12, 0x9a, 0x59, 0x4f, - 0x82, 0x31, 0x8d, 0x4f, 0x5e, 0x81, 0x69, 0xa7, 0x19, 0xb9, 0xbb, 0x54, 0x53, 0x10, 0xe2, 0x3e, - 0x2c, 0x29, 0x4c, 0xd7, 0x12, 0x50, 0x4c, 0x61, 0x93, 0xcf, 0xc0, 0x5c, 0xd8, 0x74, 0x3a, 0xf4, - 0x76, 0x4f, 0xb2, 0x5a, 0xda, 0xa6, 0xcd, 0x9d, 0x75, 0xdf, 0xf5, 0x22, 0x69, 0x77, 0xbc, 0x22, - 0x29, 0xcd, 0x35, 0x86, 0xe0, 0xe1, 0x50, 0x0a, 0xe4, 0x5f, 0x5a, 0xf0, 0x44, 0x2f, 0xa0, 0xeb, + 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0x6c, 0x1c, + 0x66, 0xea, 0x9d, 0x3e, 0x7d, 0x35, 0xa0, 0x54, 0xd9, 0x82, 0x6a, 0x30, 0xd3, 0x0b, 0xe8, 0xae, + 0x4b, 0xef, 0x35, 0x68, 0x87, 0x36, 0x23, 0x3f, 0x90, 0xd2, 0x3c, 0x22, 0x09, 0xcd, 0xac, 0x27, + 0xc1, 0x98, 0xc6, 0x27, 0xaf, 0xc0, 0xb4, 0xd3, 0x8c, 0xdc, 0x5d, 0xaa, 0x29, 0x08, 0x71, 0x1f, + 0x96, 0x14, 0xa6, 0x6b, 0x09, 0x28, 0xa6, 0xb0, 0xc9, 0x67, 0x60, 0x2e, 0x6c, 0x3a, 0x1d, 0x7a, + 0xbb, 0x27, 0x59, 0x2d, 0x6d, 0xd3, 0xe6, 0xce, 0xba, 0xef, 0x7a, 0x91, 0xb4, 0x3b, 0x3e, 0x29, + 0x29, 0xcd, 0x35, 0x86, 0xe0, 0xe1, 0x50, 0x0a, 0xe4, 0x5f, 0x59, 0xf0, 0x44, 0x2f, 0xa0, 0xeb, 0x81, 0xdf, 0xf5, 0xd9, 0x50, 0x1b, 0x30, 0x87, 0x49, 0xb3, 0xd0, 0x1b, 0x23, 0xea, 0x52, 0xa2, 0x64, 0xf0, 0x0e, 0xe7, 0x27, 0x0e, 0xf6, 0xab, 0x4f, 0xac, 0x1f, 0x26, 0x00, 0x1e, 0x2e, 0x1f, - 0xf9, 0x57, 0x16, 0x5c, 0xee, 0xf9, 0x61, 0x74, 0xc8, 0x27, 0x14, 0xcf, 0xf4, 0x13, 0xec, 0x83, + 0xf9, 0xd7, 0x16, 0x5c, 0xee, 0xf9, 0x61, 0x74, 0xc8, 0x27, 0x14, 0xcf, 0xf4, 0x13, 0xec, 0x83, 0xfd, 0xea, 0xe5, 0xf5, 0x43, 0x25, 0xc0, 0x23, 0x24, 0xb4, 0x0f, 0x2a, 0x70, 0xde, 0x18, 0x7b, 0xd2, 0x98, 0xf3, 0x32, 0x9c, 0x53, 0x83, 0x21, 0xd6, 0x7d, 0xca, 0xb1, 0x6d, 0xaf, 0x66, 0x02, 0x31, 0x89, 0xcb, 0xc6, 0x9d, 0x1e, 0x8a, 0xa2, 0x76, 0x6a, 0xdc, 0xad, 0x27, 0xa0, 0x98, 0xc2, @@ -3558,401 +3558,403 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0x85, 0x29, 0xda, 0xe4, 0x16, 0x5c, 0xe2, 0xd3, 0x71, 0xd9, 0xbf, 0xe7, 0x2d, 0xd3, 0x8e, 0xb3, 0xa7, 0x3e, 0x60, 0x92, 0x7f, 0xc0, 0xa3, 0x07, 0xfb, 0xd5, 0x4b, 0x8d, 0x2c, 0x04, 0xcc, 0xae, 0x47, 0x1c, 0x78, 0x2c, 0x09, 0x40, 0xba, 0xeb, 0x86, 0xae, 0xef, 0x09, 0xb3, 0x5c, 0x29, 0x36, - 0xcb, 0x35, 0x86, 0xa3, 0xe1, 0x61, 0x34, 0xc8, 0xdf, 0xb1, 0xe0, 0x62, 0xd6, 0x34, 0x9c, 0x2b, + 0xcb, 0x35, 0x86, 0xa3, 0xe1, 0x61, 0x34, 0xc8, 0xdf, 0xb3, 0xe0, 0x62, 0xd6, 0x34, 0x9c, 0x2b, 0xe7, 0x71, 0x9b, 0x9c, 0x9a, 0x5a, 0x62, 0x44, 0x64, 0x2e, 0x0a, 0x99, 0x42, 0x90, 0x77, 0x2c, 0x98, 0x72, 0x8c, 0x13, 0xf4, 0x1c, 0xe4, 0xb1, 0x6b, 0x99, 0x67, 0xf2, 0xfa, 0xec, 0xc1, 0x7e, - 0x35, 0x71, 0x4a, 0xc7, 0x04, 0x47, 0xf2, 0xf7, 0x2c, 0xb8, 0x94, 0x39, 0xc7, 0xe7, 0x2a, 0x67, + 0x35, 0x71, 0x4a, 0xc7, 0x04, 0x47, 0xf2, 0x0f, 0x2c, 0xb8, 0x94, 0x39, 0xc7, 0xe7, 0x2a, 0x67, 0xd1, 0x42, 0x7c, 0x90, 0x64, 0xaf, 0x39, 0xd9, 0x62, 0x90, 0x6f, 0x5a, 0x7a, 0x2b, 0x53, 0x17, 0x8c, 0x73, 0x53, 0x5c, 0xb4, 0x11, 0x0d, 0x1e, 0x86, 0x1a, 0xa5, 0x08, 0xd7, 0x2f, 0x18, 0x3b, 0xa3, 0x2a, 0xc4, 0x34, 0x7b, 0xf2, 0x0d, 0x4b, 0x6d, 0x8d, 0x5a, 0xa2, 0x73, 0x67, 0x25, 0x11, 0x89, 0x77, 0x5a, 0x2d, 0x50, 0x8a, 0x39, 0xf9, 0x59, 0x98, 0x77, 0x36, 0xfd, 0x20, 0xca, 0x9c, 0x7c, 0x73, 0xd3, 0x7c, 0x1a, 0x5d, 0x3e, 0xd8, 0xaf, 0xce, 0xd7, 0x86, 0x62, 0xe1, 0x21, 0x14, 0xec, 0xdf, 0x9d, 0x80, 0x29, 0x71, 0x12, 0x92, 0x5b, 0xd7, 0x6f, 0x59, 0xf0, 0x78, 0xb3, 0x1f, - 0x04, 0xd4, 0x8b, 0x1a, 0x11, 0xed, 0x0d, 0x6e, 0x5c, 0xd6, 0x99, 0x6e, 0x5c, 0x57, 0x0e, 0xf6, - 0xab, 0x8f, 0x2f, 0x1d, 0xc2, 0x1f, 0x0f, 0x95, 0x8e, 0xfc, 0x3b, 0x0b, 0x6c, 0x89, 0x50, 0x77, - 0x9a, 0x3b, 0xed, 0xc0, 0xef, 0x7b, 0xad, 0xc1, 0x8f, 0x18, 0x3b, 0xd3, 0x8f, 0x78, 0xea, 0x60, - 0xbf, 0x6a, 0x2f, 0x1d, 0x29, 0x05, 0x1e, 0x43, 0x52, 0xf2, 0x2a, 0x9c, 0x97, 0x58, 0x57, 0xef, - 0xf7, 0x68, 0xe0, 0xb2, 0x33, 0x87, 0x54, 0x1c, 0x63, 0xdf, 0xb4, 0x34, 0x02, 0x0e, 0xd6, 0x21, - 0x21, 0x4c, 0xde, 0xa3, 0x6e, 0x7b, 0x3b, 0x52, 0xea, 0xd3, 0x88, 0x0e, 0x69, 0xd2, 0x2a, 0x72, - 0x47, 0xd0, 0xac, 0x57, 0x0e, 0xf6, 0xab, 0x93, 0xf2, 0x0f, 0x2a, 0x4e, 0xe4, 0x26, 0x4c, 0x8b, - 0x73, 0xea, 0xba, 0xeb, 0xb5, 0xd7, 0x7d, 0x4f, 0x78, 0x55, 0x95, 0xeb, 0x4f, 0xa9, 0x0d, 0xbf, - 0x91, 0x80, 0xbe, 0xb7, 0x5f, 0x9d, 0x52, 0xbf, 0x37, 0xf6, 0x7a, 0x14, 0x53, 0xb5, 0xc9, 0xdf, - 0xb6, 0x80, 0x84, 0x11, 0xed, 0xad, 0x77, 0xfa, 0x6d, 0x57, 0x36, 0x91, 0xf4, 0x8f, 0xca, 0xc1, - 0x55, 0x2b, 0x49, 0xb7, 0x3e, 0x2f, 0x85, 0x24, 0x8d, 0x01, 0x8e, 0x98, 0x21, 0x85, 0xfd, 0x9d, - 0x49, 0x00, 0x35, 0x97, 0x68, 0x8f, 0x7c, 0x08, 0xca, 0x21, 0x8d, 0x44, 0x93, 0xc8, 0x6b, 0x2e, - 0x71, 0x39, 0xa9, 0x0a, 0x31, 0x86, 0x93, 0x1d, 0x28, 0xf6, 0x9c, 0x7e, 0x48, 0xf3, 0x39, 0xdc, - 0xc8, 0x91, 0xb9, 0xce, 0x28, 0x8a, 0x53, 0x33, 0xff, 0x89, 0x82, 0x07, 0xf9, 0xb2, 0x05, 0x40, - 0x93, 0xa3, 0x69, 0x64, 0xeb, 0x95, 0x64, 0x19, 0x0f, 0x38, 0xd6, 0x06, 0xf5, 0xe9, 0x83, 0xfd, - 0x2a, 0x18, 0xe3, 0xd2, 0x60, 0x4b, 0xee, 0x41, 0xc9, 0x51, 0x1b, 0xd2, 0xf8, 0x59, 0x6c, 0x48, - 0xfc, 0x30, 0xab, 0x67, 0x94, 0x66, 0x46, 0xbe, 0x6a, 0xc1, 0x74, 0x48, 0x23, 0xd9, 0x55, 0x6c, - 0x59, 0x94, 0xda, 0xf8, 0x88, 0x33, 0xa2, 0x91, 0xa0, 0x29, 0x96, 0xf7, 0x64, 0x19, 0xa6, 0xf8, - 0x2a, 0x51, 0xae, 0x53, 0xa7, 0x45, 0x03, 0x6e, 0x2b, 0x91, 0x6a, 0xde, 0xe8, 0xa2, 0x18, 0x34, - 0xb5, 0x28, 0x46, 0x19, 0xa6, 0xf8, 0x2a, 0x51, 0xd6, 0xdc, 0x20, 0xf0, 0xa5, 0x28, 0xa5, 0x9c, - 0x44, 0x31, 0x68, 0x6a, 0x51, 0x8c, 0x32, 0x4c, 0xf1, 0x25, 0x1d, 0x98, 0xe8, 0xf1, 0xa9, 0x25, - 0x55, 0xb9, 0x11, 0xef, 0xc8, 0xd5, 0x34, 0xa5, 0x3d, 0x61, 0x93, 0x12, 0xff, 0x51, 0xf2, 0xb0, - 0xbf, 0x7d, 0x0e, 0xa6, 0xd5, 0xb4, 0x8d, 0x0f, 0x39, 0xc2, 0x10, 0x38, 0xe4, 0x90, 0xb3, 0x64, - 0x02, 0x31, 0x89, 0xcb, 0x2a, 0x8b, 0x55, 0x2b, 0x79, 0xc6, 0xd1, 0x95, 0x1b, 0x26, 0x10, 0x93, - 0xb8, 0xa4, 0x0b, 0x45, 0xb6, 0xb2, 0x28, 0xf7, 0x8b, 0x11, 0xbf, 0x3c, 0x5e, 0x8d, 0x0c, 0xa3, - 0x0a, 0x23, 0x8f, 0x82, 0x0b, 0xb7, 0x65, 0x47, 0x09, 0xf3, 0xb6, 0x9c, 0x8a, 0xf9, 0xac, 0x06, - 0x49, 0xcb, 0xb9, 0xe8, 0xfb, 0x64, 0x19, 0xa6, 0xd8, 0x67, 0x9c, 0x7b, 0x8a, 0x67, 0x78, 0xee, - 0xf9, 0x14, 0x94, 0xba, 0xce, 0xfd, 0x46, 0x3f, 0x68, 0x9f, 0xfe, 0x7c, 0x25, 0xdd, 0x69, 0x05, - 0x15, 0xd4, 0xf4, 0xc8, 0x17, 0x2d, 0x63, 0x81, 0x13, 0xbe, 0x16, 0x77, 0xf2, 0x5d, 0xe0, 0xb4, - 0xda, 0x30, 0x74, 0xa9, 0x1b, 0x38, 0x85, 0x94, 0x1e, 0xf8, 0x29, 0x84, 0x69, 0xd4, 0x62, 0x82, - 0x68, 0x8d, 0xba, 0x7c, 0xa6, 0x1a, 0xf5, 0x52, 0x82, 0x19, 0xa6, 0x98, 0x73, 0x79, 0xc4, 0x9c, - 0xd3, 0xf2, 0xc0, 0x99, 0xca, 0xd3, 0x48, 0x30, 0xc3, 0x14, 0xf3, 0xe1, 0x47, 0xef, 0xca, 0xd9, - 0x1c, 0xbd, 0xa7, 0x72, 0x38, 0x7a, 0x1f, 0x7e, 0x2a, 0x39, 0x37, 0xea, 0xa9, 0x84, 0xdc, 0x00, - 0xd2, 0xda, 0xf3, 0x9c, 0xae, 0xdb, 0x94, 0x8b, 0x25, 0xdf, 0xa4, 0xa7, 0xb9, 0x69, 0x46, 0x6b, - 0x65, 0xcb, 0x03, 0x18, 0x98, 0x51, 0x8b, 0x44, 0x50, 0xea, 0x29, 0xe5, 0x73, 0x26, 0x8f, 0xd1, - 0xaf, 0x94, 0x51, 0xe1, 0x42, 0xc3, 0x26, 0x9e, 0x2a, 0x41, 0xcd, 0x89, 0xac, 0xc2, 0xc5, 0xae, - 0xeb, 0xad, 0xfb, 0xad, 0x70, 0x9d, 0x06, 0xd2, 0xf0, 0xd4, 0xa0, 0xd1, 0xdc, 0x2c, 0x6f, 0x1b, - 0x6e, 0x4c, 0x58, 0xcb, 0x80, 0x63, 0x66, 0x2d, 0xfb, 0x7f, 0x59, 0x30, 0xbb, 0xd4, 0xf1, 0xfb, - 0xad, 0x3b, 0x4e, 0xd4, 0xdc, 0x16, 0x1e, 0x1b, 0xe4, 0x15, 0x28, 0xb9, 0x5e, 0x44, 0x83, 0x5d, - 0xa7, 0x23, 0xf7, 0x27, 0x5b, 0x59, 0x92, 0x57, 0x64, 0xf9, 0x7b, 0xfb, 0xd5, 0xe9, 0xe5, 0x7e, - 0xc0, 0x0d, 0xf6, 0x62, 0xb5, 0x42, 0x5d, 0x87, 0x7c, 0xdb, 0x82, 0xf3, 0xc2, 0xe7, 0x63, 0xd9, - 0x89, 0x9c, 0xd7, 0xfb, 0x34, 0x70, 0xa9, 0xf2, 0xfa, 0x18, 0x71, 0xa1, 0x4a, 0xcb, 0xaa, 0x18, - 0xec, 0xc5, 0x67, 0x96, 0xb5, 0x34, 0x67, 0x1c, 0x14, 0xc6, 0xfe, 0xe5, 0x02, 0x3c, 0x3a, 0x94, - 0x16, 0x99, 0x87, 0x31, 0xb7, 0x25, 0x3f, 0x1d, 0x24, 0xdd, 0xb1, 0x95, 0x16, 0x8e, 0xb9, 0x2d, - 0xb2, 0xc0, 0x35, 0xdc, 0x80, 0x86, 0xa1, 0xba, 0x7b, 0x2f, 0x6b, 0x65, 0x54, 0x96, 0xa2, 0x81, - 0x41, 0xaa, 0x50, 0xe4, 0xae, 0xd4, 0xf2, 0x68, 0xc5, 0x75, 0x66, 0xee, 0xb5, 0x8c, 0xa2, 0x9c, - 0x7c, 0xc9, 0x02, 0x10, 0x02, 0x32, 0x7d, 0x5f, 0xee, 0x92, 0x98, 0x6f, 0x33, 0x31, 0xca, 0x42, - 0xca, 0xf8, 0x3f, 0x1a, 0x5c, 0xc9, 0x06, 0x4c, 0x30, 0xf5, 0xd9, 0x6f, 0x9d, 0x7a, 0x53, 0x14, - 0x0a, 0x10, 0xa7, 0x81, 0x92, 0x16, 0x6b, 0xab, 0x80, 0x46, 0xfd, 0xc0, 0x63, 0x4d, 0xcb, 0xb7, - 0xc1, 0x92, 0x90, 0x02, 0x75, 0x29, 0x1a, 0x18, 0xf6, 0x3f, 0x1f, 0x83, 0x8b, 0x59, 0xa2, 0xb3, - 0xdd, 0x66, 0x42, 0x48, 0x2b, 0xad, 0x04, 0x3f, 0x93, 0x7f, 0xfb, 0x48, 0xf7, 0x25, 0x7d, 0x63, - 0x23, 0x7d, 0x49, 0x25, 0x5f, 0xf2, 0x33, 0xba, 0x85, 0xc6, 0x4e, 0xd9, 0x42, 0x9a, 0x72, 0xaa, - 0x95, 0xae, 0xc0, 0x78, 0xc8, 0x7a, 0xbe, 0x90, 0xbc, 0xf9, 0xe1, 0x7d, 0xc4, 0x21, 0x0c, 0xa3, - 0xef, 0xb9, 0x91, 0x8c, 0x3f, 0xd2, 0x18, 0xb7, 0x3d, 0x37, 0x42, 0x0e, 0xb1, 0xbf, 0x35, 0x06, - 0xf3, 0xc3, 0x3f, 0x8a, 0x7c, 0xcb, 0x02, 0x68, 0xb1, 0xc3, 0x51, 0xc8, 0x9d, 0xf8, 0x85, 0xbb, - 0x97, 0x73, 0x56, 0x6d, 0xb8, 0xac, 0x38, 0xc5, 0x7e, 0x88, 0xba, 0x28, 0x44, 0x43, 0x10, 0xf2, - 0x9c, 0x1a, 0xfa, 0xfc, 0xd6, 0x4a, 0x4c, 0x26, 0x5d, 0x67, 0x4d, 0x43, 0xd0, 0xc0, 0x62, 0xa7, - 0x5f, 0xcf, 0xe9, 0xd2, 0xb0, 0xe7, 0xe8, 0x68, 0x2e, 0x7e, 0xfa, 0xbd, 0xa9, 0x0a, 0x31, 0x86, - 0xdb, 0x1d, 0x78, 0xf2, 0x18, 0x72, 0xe6, 0x14, 0x2c, 0x63, 0xff, 0x0f, 0x0b, 0x1e, 0x91, 0x9e, - 0x78, 0xff, 0xdf, 0xb8, 0x75, 0xfe, 0xa9, 0x05, 0x8f, 0x0d, 0xf9, 0xe6, 0x07, 0xe0, 0xdd, 0xf9, - 0x56, 0xd2, 0xbb, 0xf3, 0xf6, 0xa8, 0x43, 0x3a, 0xf3, 0x3b, 0x86, 0x38, 0x79, 0xfe, 0x6e, 0x01, - 0xce, 0xb1, 0x65, 0xab, 0xe5, 0xb7, 0x73, 0xda, 0x38, 0x9f, 0x84, 0xe2, 0xe7, 0xd8, 0x06, 0x94, - 0x1e, 0x64, 0x7c, 0x57, 0x42, 0x01, 0x23, 0x5f, 0xb6, 0x60, 0xf2, 0x73, 0x72, 0x4f, 0x15, 0x67, - 0xb9, 0x11, 0x17, 0xc3, 0xc4, 0x37, 0x2c, 0xc8, 0x1d, 0x52, 0xc4, 0xe0, 0x68, 0x5f, 0x4e, 0xb5, - 0x95, 0x2a, 0xce, 0xe4, 0x19, 0x98, 0xdc, 0xf2, 0x83, 0x6e, 0xbf, 0xe3, 0xa4, 0x03, 0x3f, 0xaf, - 0x89, 0x62, 0x54, 0x70, 0x36, 0xc9, 0x9d, 0x9e, 0xfb, 0x06, 0x0d, 0x42, 0x11, 0x92, 0x91, 0x98, - 0xe4, 0x35, 0x0d, 0x41, 0x03, 0x8b, 0xd7, 0x69, 0xb7, 0x03, 0xda, 0x76, 0x22, 0x3f, 0xe0, 0x3b, - 0x87, 0x59, 0x47, 0x43, 0xd0, 0xc0, 0x9a, 0xff, 0x38, 0x4c, 0x99, 0xc2, 0x9f, 0x28, 0x9e, 0xe7, - 0x13, 0x20, 0x9d, 0x3a, 0x53, 0x4b, 0x92, 0x75, 0x9c, 0x25, 0xc9, 0xfe, 0x0f, 0x63, 0x60, 0xd8, - 0xa2, 0x1e, 0xc0, 0x54, 0xf7, 0x12, 0x53, 0x7d, 0x44, 0x3b, 0x8a, 0x61, 0x59, 0x1b, 0x16, 0xdd, - 0xb8, 0x9b, 0x8a, 0x6e, 0xbc, 0x99, 0x1b, 0xc7, 0xc3, 0x83, 0x1b, 0x7f, 0x60, 0xc1, 0x63, 0x31, - 0xf2, 0xa0, 0x0d, 0xfb, 0xe8, 0x75, 0xfb, 0x45, 0xa8, 0x38, 0x71, 0x35, 0x39, 0xb1, 0x8c, 0xd0, - 0x32, 0x0d, 0x42, 0x13, 0x2f, 0x0e, 0x8b, 0x29, 0x9c, 0x32, 0x2c, 0x66, 0xfc, 0xf0, 0xb0, 0x18, - 0xfb, 0xc7, 0x63, 0xf0, 0xc4, 0xe0, 0x97, 0x99, 0xbe, 0xe2, 0x47, 0x7f, 0x5b, 0xda, 0x9b, 0x7c, - 0xec, 0xd4, 0xde, 0xe4, 0x85, 0xe3, 0x7a, 0x93, 0x6b, 0x1f, 0xee, 0xf1, 0x33, 0xf7, 0xe1, 0x6e, - 0xc0, 0x25, 0xe5, 0x30, 0x7a, 0xcd, 0x0f, 0x64, 0x6c, 0x88, 0x5a, 0x41, 0x4a, 0xf5, 0x27, 0x64, - 0x95, 0x4b, 0x98, 0x85, 0x84, 0xd9, 0x75, 0xed, 0x1f, 0x14, 0xe0, 0x42, 0xdc, 0xec, 0x4b, 0xbe, - 0xd7, 0x72, 0xb9, 0xcf, 0xd1, 0xcb, 0x30, 0x1e, 0xed, 0xf5, 0x54, 0x63, 0xff, 0x45, 0x25, 0xce, - 0xc6, 0x5e, 0x8f, 0xf5, 0xf6, 0x23, 0x19, 0x55, 0xf8, 0x2d, 0x02, 0xaf, 0x44, 0x56, 0xf5, 0xec, - 0x10, 0x3d, 0xf0, 0x42, 0x72, 0x34, 0xbf, 0xb7, 0x5f, 0xcd, 0xc8, 0xf2, 0xb0, 0xa0, 0x29, 0x25, - 0xc7, 0x3c, 0xb9, 0x0b, 0xd3, 0x1d, 0x27, 0x8c, 0x6e, 0xf7, 0x5a, 0x4e, 0x44, 0x37, 0x5c, 0xe9, - 0xcd, 0x73, 0xb2, 0x70, 0x1a, 0xed, 0xf6, 0xb0, 0x9a, 0xa0, 0x84, 0x29, 0xca, 0x64, 0x17, 0x08, - 0x2b, 0xd9, 0x08, 0x1c, 0x2f, 0x14, 0x5f, 0xc5, 0xf8, 0x9d, 0x3c, 0x36, 0x4a, 0x1f, 0x9d, 0x57, - 0x07, 0xa8, 0x61, 0x06, 0x07, 0xf2, 0x14, 0x4c, 0x04, 0xd4, 0x09, 0xf5, 0x76, 0xa0, 0xe7, 0x3f, - 0xf2, 0x52, 0x94, 0x50, 0x73, 0x42, 0x4d, 0x1c, 0x31, 0xa1, 0xfe, 0xd0, 0x82, 0xe9, 0xb8, 0x9b, - 0x1e, 0x80, 0xea, 0xd1, 0x4d, 0xaa, 0x1e, 0xd7, 0xf3, 0x5a, 0x12, 0x87, 0x68, 0x1b, 0x7f, 0x32, - 0x69, 0x7e, 0x1f, 0x0f, 0xe0, 0xf8, 0xbc, 0xe9, 0xcf, 0x6f, 0xe5, 0x11, 0x55, 0x97, 0xd0, 0xf6, - 0x0e, 0x75, 0xe4, 0x67, 0xba, 0x4e, 0x4b, 0xea, 0x31, 0x72, 0xd8, 0x6b, 0x5d, 0x47, 0xe9, 0x37, - 0x59, 0xba, 0x8e, 0xaa, 0x43, 0x6e, 0xc3, 0x23, 0xbd, 0xc0, 0xe7, 0x79, 0x06, 0x96, 0xa9, 0xd3, - 0xea, 0xb8, 0x1e, 0x55, 0x66, 0x1e, 0xe1, 0x75, 0xf3, 0xd8, 0xc1, 0x7e, 0xf5, 0x91, 0xf5, 0x6c, - 0x14, 0x1c, 0x56, 0x37, 0x19, 0xa9, 0x3a, 0x7e, 0x8c, 0x48, 0xd5, 0x5f, 0xd4, 0xc6, 0x54, 0x1d, - 0x14, 0xf1, 0xe9, 0xbc, 0xba, 0x32, 0x2b, 0x3c, 0x42, 0x0f, 0xa9, 0x9a, 0x64, 0x8a, 0x9a, 0xfd, - 0x70, 0x8b, 0xdd, 0xc4, 0x29, 0x2d, 0x76, 0x71, 0x1c, 0xcc, 0xe4, 0xfb, 0x19, 0x07, 0x53, 0xfa, - 0x40, 0xc5, 0xc1, 0x7c, 0xdb, 0x82, 0x0b, 0xce, 0x60, 0x04, 0x7a, 0x3e, 0xc6, 0xe3, 0x8c, 0xd0, - 0xf6, 0xfa, 0x63, 0x52, 0xc8, 0xac, 0x40, 0x7f, 0xcc, 0x12, 0xc5, 0x7e, 0xb7, 0x08, 0xb3, 0x69, - 0x25, 0xe9, 0xec, 0x43, 0x75, 0xff, 0x86, 0x05, 0xb3, 0x6a, 0x82, 0xeb, 0x1b, 0x70, 0x71, 0xc4, - 0x58, 0xcd, 0x69, 0x5d, 0x11, 0xea, 0x9e, 0xce, 0xa0, 0xb2, 0x91, 0xe2, 0x86, 0x03, 0xfc, 0xc9, - 0x9b, 0x50, 0xd1, 0xb7, 0x2a, 0xa7, 0x8a, 0xdb, 0xe5, 0xa1, 0xa5, 0xb5, 0x98, 0x04, 0x9a, 0xf4, - 0xc8, 0xbb, 0x16, 0x40, 0x53, 0xed, 0xc4, 0x39, 0x45, 0x45, 0x65, 0x68, 0x0b, 0xb1, 0x3e, 0xaf, - 0x8b, 0x42, 0x34, 0x18, 0x93, 0x5f, 0xe6, 0xf7, 0x29, 0x7a, 0x24, 0x28, 0xcf, 0x83, 0x4f, 0xe6, - 0xbd, 0x14, 0xc5, 0xbe, 0x24, 0x5a, 0xdb, 0x33, 0x40, 0x21, 0x26, 0x84, 0xb0, 0x5f, 0x06, 0xed, - 0xb3, 0xcd, 0x56, 0x56, 0xee, 0xb5, 0xbd, 0xee, 0x44, 0xdb, 0x72, 0x08, 0xea, 0x95, 0xf5, 0x9a, - 0x02, 0x60, 0x8c, 0x63, 0x7f, 0x16, 0xa6, 0x5f, 0x0d, 0x9c, 0xde, 0xb6, 0xcb, 0xef, 0x2d, 0xd8, - 0xf9, 0xf8, 0x19, 0x98, 0x74, 0x5a, 0xad, 0xac, 0x64, 0x3f, 0x35, 0x51, 0x8c, 0x0a, 0x7e, 0xac, - 0xa3, 0xb0, 0xfd, 0x6f, 0x2c, 0x20, 0xf1, 0x4d, 0xb3, 0xeb, 0xb5, 0xd7, 0x9c, 0xa8, 0xb9, 0xcd, - 0x8e, 0x70, 0xdb, 0xbc, 0x34, 0xeb, 0x08, 0x77, 0x5d, 0x43, 0xd0, 0xc0, 0x22, 0x6f, 0x43, 0x45, - 0xfc, 0x7b, 0x43, 0x1f, 0x10, 0x47, 0x77, 0x3d, 0xe7, 0x7b, 0x1e, 0x97, 0x49, 0x8c, 0xc2, 0xeb, - 0x31, 0x07, 0x34, 0xd9, 0xb1, 0xa6, 0x5a, 0xf1, 0xb6, 0x3a, 0xfd, 0xfb, 0xad, 0xcd, 0xb8, 0xa9, - 0x7a, 0x81, 0xbf, 0xe5, 0x76, 0x68, 0xba, 0xa9, 0xd6, 0x45, 0x31, 0x2a, 0xf8, 0xf1, 0x9a, 0xea, - 0x5f, 0x5b, 0x70, 0x71, 0x25, 0x8c, 0x5c, 0x7f, 0x99, 0x86, 0x11, 0xdb, 0xf9, 0xd8, 0xfa, 0xd8, - 0xef, 0x1c, 0x27, 0xfc, 0x62, 0x19, 0x66, 0xe5, 0x3d, 0x74, 0x7f, 0x33, 0xa4, 0x91, 0x71, 0xd4, - 0xd0, 0xf3, 0x78, 0x29, 0x05, 0xc7, 0x81, 0x1a, 0x8c, 0x8a, 0xbc, 0x90, 0x8e, 0xa9, 0x14, 0x92, - 0x54, 0x1a, 0x29, 0x38, 0x0e, 0xd4, 0xb0, 0xbf, 0x5f, 0x80, 0x0b, 0xfc, 0x33, 0x52, 0xa1, 0x53, - 0xdf, 0x18, 0x16, 0x3a, 0x35, 0xe2, 0x54, 0xe6, 0xbc, 0x4e, 0x11, 0x38, 0xf5, 0xd7, 0x2d, 0x98, - 0x69, 0x25, 0x5b, 0x3a, 0x1f, 0xbb, 0x5c, 0x56, 0x1f, 0x0a, 0x0f, 0xc4, 0x54, 0x21, 0xa6, 0xf9, - 0x93, 0x5f, 0xb1, 0x60, 0x26, 0x29, 0xa6, 0x5a, 0xdd, 0xcf, 0xa0, 0x91, 0x74, 0xc8, 0x40, 0xb2, - 0x3c, 0xc4, 0xb4, 0x08, 0xf6, 0xef, 0x8d, 0xc9, 0x2e, 0x3d, 0x8b, 0xb8, 0x20, 0x72, 0x0f, 0xca, - 0x51, 0x27, 0x14, 0x85, 0xf2, 0x6b, 0x47, 0x3c, 0xb4, 0x6e, 0xac, 0x36, 0x84, 0xc3, 0x49, 0xac, - 0x57, 0xca, 0x12, 0xa6, 0x1f, 0x2b, 0x5e, 0x9c, 0x71, 0xb3, 0x27, 0x19, 0xe7, 0x72, 0x5a, 0xde, - 0x58, 0x5a, 0x4f, 0x33, 0x96, 0x25, 0x8c, 0xb1, 0xe2, 0x65, 0xff, 0x86, 0x05, 0xe5, 0x1b, 0xbe, - 0x5a, 0x47, 0x7e, 0x36, 0x07, 0x5b, 0x94, 0x56, 0x59, 0xb5, 0xd2, 0x12, 0x9f, 0x82, 0x5e, 0x49, - 0x58, 0xa2, 0x1e, 0x37, 0x68, 0x2f, 0xf0, 0x9c, 0x87, 0x8c, 0xd4, 0x0d, 0x7f, 0x73, 0xa8, 0xf9, - 0xf8, 0x57, 0x8b, 0x70, 0xee, 0x35, 0x67, 0x8f, 0x7a, 0x91, 0x73, 0xf2, 0x4d, 0xe2, 0x45, 0xa8, - 0x38, 0x3d, 0x7e, 0x97, 0x69, 0x1c, 0x43, 0x62, 0xe3, 0x4e, 0x0c, 0x42, 0x13, 0x2f, 0x5e, 0xd0, - 0x44, 0x90, 0x4e, 0xd6, 0x52, 0xb4, 0x94, 0x82, 0xe3, 0x40, 0x0d, 0x72, 0x03, 0x88, 0x0c, 0x6c, - 0xaf, 0x35, 0x9b, 0x7e, 0xdf, 0x13, 0x4b, 0x9a, 0xb0, 0xfb, 0xe8, 0xf3, 0xf0, 0xda, 0x00, 0x06, - 0x66, 0xd4, 0x22, 0x9f, 0x81, 0xb9, 0x26, 0xa7, 0x2c, 0x4f, 0x47, 0x26, 0x45, 0x71, 0x42, 0xd6, - 0x61, 0x2f, 0x4b, 0x43, 0xf0, 0x70, 0x28, 0x05, 0x26, 0x69, 0x18, 0xf9, 0x81, 0xd3, 0xa6, 0x26, - 0xdd, 0x89, 0xa4, 0xa4, 0x8d, 0x01, 0x0c, 0xcc, 0xa8, 0x45, 0xbe, 0x00, 0xe5, 0x68, 0x3b, 0xa0, - 0xe1, 0xb6, 0xdf, 0x69, 0x49, 0xdf, 0x93, 0x11, 0x8d, 0x81, 0xb2, 0xf7, 0x37, 0x14, 0x55, 0x63, - 0x78, 0xab, 0x22, 0x8c, 0x79, 0x92, 0x00, 0x26, 0xc2, 0xa6, 0xdf, 0xa3, 0xa1, 0x3c, 0x55, 0xdc, - 0xc8, 0x85, 0x3b, 0x37, 0x6e, 0x19, 0x66, 0x48, 0xce, 0x01, 0x25, 0x27, 0xfb, 0x77, 0xc6, 0x60, - 0xca, 0x44, 0x3c, 0xc6, 0xda, 0xf4, 0x65, 0x0b, 0xa6, 0x9a, 0xbe, 0x17, 0x05, 0x7e, 0x27, 0x4e, - 0xd8, 0x30, 0xba, 0x46, 0xc1, 0x48, 0x2d, 0xd3, 0xc8, 0x71, 0x3b, 0x86, 0xb5, 0xce, 0x60, 0x83, - 0x09, 0xa6, 0xe4, 0xeb, 0x16, 0xcc, 0xc4, 0x8e, 0x91, 0xb1, 0xad, 0x2f, 0x57, 0x41, 0xf4, 0x52, - 0x7f, 0x35, 0xc9, 0x09, 0xd3, 0xac, 0xed, 0x4d, 0x98, 0x4d, 0xf7, 0x36, 0x6b, 0xca, 0x9e, 0x23, - 0xe7, 0x7a, 0x21, 0x6e, 0xca, 0x75, 0x27, 0x0c, 0x91, 0x43, 0xc8, 0xb3, 0x50, 0xea, 0x3a, 0x41, - 0xdb, 0xf5, 0x9c, 0x0e, 0x6f, 0xc5, 0x82, 0xb1, 0x20, 0xc9, 0x72, 0xd4, 0x18, 0xf6, 0x47, 0x60, - 0x6a, 0xcd, 0xf1, 0xda, 0xb4, 0x25, 0xd7, 0xe1, 0xa3, 0x23, 0x53, 0xff, 0x78, 0x1c, 0x2a, 0xc6, - 0xf1, 0xf1, 0xec, 0xcf, 0x59, 0x89, 0x44, 0x44, 0x85, 0x1c, 0x13, 0x11, 0x7d, 0x0a, 0x60, 0xcb, - 0xf5, 0xdc, 0x70, 0xfb, 0x94, 0x29, 0x8e, 0xf8, 0xdd, 0xfc, 0x35, 0x4d, 0x01, 0x0d, 0x6a, 0xf1, - 0x05, 0x68, 0xf1, 0x90, 0x6c, 0x81, 0xef, 0x5a, 0xc6, 0x76, 0x33, 0x91, 0x87, 0xc3, 0x87, 0xd1, - 0x31, 0x0b, 0x6a, 0xfb, 0x11, 0x77, 0x53, 0x87, 0xed, 0x4a, 0x1b, 0x50, 0x0a, 0x68, 0xd8, 0xef, - 0xd2, 0x53, 0x25, 0x23, 0xe2, 0xae, 0x37, 0x28, 0xeb, 0xa3, 0xa6, 0x34, 0xff, 0x32, 0x9c, 0x4b, - 0x88, 0x70, 0xa2, 0x1b, 0x26, 0x1f, 0x32, 0x6d, 0x14, 0xa7, 0xb9, 0x6f, 0x62, 0x7d, 0xd1, 0x31, - 0x92, 0x10, 0xe9, 0xbe, 0x10, 0x0e, 0x56, 0x02, 0x66, 0xff, 0x78, 0x02, 0xa4, 0x0f, 0xc3, 0x31, - 0x96, 0x2b, 0xf3, 0xe6, 0x72, 0xec, 0x14, 0x37, 0x97, 0x37, 0x60, 0xca, 0xf5, 0xdc, 0xc8, 0x75, - 0x3a, 0xdc, 0xfe, 0x24, 0xb7, 0x53, 0xe5, 0x8c, 0x3f, 0xb5, 0x62, 0xc0, 0x32, 0xe8, 0x24, 0xea, - 0x92, 0xd7, 0xa1, 0xc8, 0xf7, 0x1b, 0x39, 0x80, 0x4f, 0xee, 0x68, 0xc1, 0x7d, 0x6c, 0x44, 0x84, - 0x9e, 0xa0, 0xc4, 0x0f, 0x1f, 0x22, 0x0b, 0x93, 0x3e, 0x7e, 0xcb, 0x71, 0x1c, 0x1f, 0x3e, 0x52, - 0x70, 0x1c, 0xa8, 0xc1, 0xa8, 0x6c, 0x39, 0x6e, 0xa7, 0x1f, 0xd0, 0x98, 0xca, 0x44, 0x92, 0xca, - 0xb5, 0x14, 0x1c, 0x07, 0x6a, 0x90, 0x2d, 0x98, 0x92, 0x65, 0xc2, 0x6d, 0x6e, 0xf2, 0x94, 0x5f, - 0xc9, 0xdd, 0x23, 0xaf, 0x19, 0x94, 0x30, 0x41, 0x97, 0xf4, 0xe1, 0xbc, 0xeb, 0x35, 0x7d, 0xaf, - 0xd9, 0xe9, 0x87, 0xee, 0x2e, 0x8d, 0xc3, 0xe3, 0x4e, 0xc3, 0xec, 0xd2, 0xc1, 0x7e, 0xf5, 0xfc, - 0x4a, 0x9a, 0x1c, 0x0e, 0x72, 0x20, 0x5f, 0xb4, 0xe0, 0x52, 0xd3, 0xf7, 0x42, 0x9e, 0xc5, 0x63, - 0x97, 0x5e, 0x0d, 0x02, 0x3f, 0x10, 0xbc, 0xcb, 0xa7, 0xe4, 0xcd, 0xcd, 0x9e, 0x4b, 0x59, 0x24, - 0x31, 0x9b, 0x13, 0x79, 0x0b, 0x4a, 0xbd, 0xc0, 0xdf, 0x75, 0x5b, 0x34, 0x90, 0x2e, 0x98, 0xab, - 0x79, 0xa4, 0x36, 0x5a, 0x97, 0x34, 0xe3, 0xa5, 0x47, 0x95, 0xa0, 0xe6, 0x67, 0xff, 0x9f, 0x0a, - 0x4c, 0x27, 0xd1, 0xc9, 0xcf, 0x03, 0xf4, 0x02, 0xbf, 0x4b, 0xa3, 0x6d, 0xaa, 0xc3, 0x9c, 0x6e, - 0x8e, 0x9a, 0xbc, 0x46, 0xd1, 0x53, 0x6e, 0x4b, 0x6c, 0xb9, 0x88, 0x4b, 0xd1, 0xe0, 0x48, 0x02, - 0x98, 0xdc, 0x11, 0xdb, 0xae, 0xd4, 0x42, 0x5e, 0xcb, 0x45, 0x67, 0x92, 0x9c, 0x79, 0x7c, 0x8e, - 0x2c, 0x42, 0xc5, 0x88, 0x6c, 0x42, 0xe1, 0x1e, 0xdd, 0xcc, 0x27, 0x73, 0xc2, 0x1d, 0x2a, 0x4f, - 0x33, 0xf5, 0xc9, 0x83, 0xfd, 0x6a, 0xe1, 0x0e, 0xdd, 0x44, 0x46, 0x9c, 0x7d, 0x57, 0x4b, 0xf8, - 0x2e, 0xc8, 0xa5, 0xe2, 0xb5, 0x1c, 0x1d, 0x21, 0xc4, 0x77, 0xc9, 0x22, 0x54, 0x8c, 0xc8, 0x5b, - 0x50, 0xbe, 0xe7, 0xec, 0xd2, 0xad, 0xc0, 0xf7, 0x22, 0xe9, 0x2b, 0x37, 0x62, 0x70, 0xc9, 0x1d, - 0x45, 0x4e, 0xf2, 0xe5, 0xdb, 0xbb, 0x2e, 0xc4, 0x98, 0x1d, 0xd9, 0x85, 0x92, 0x47, 0xef, 0x21, - 0xed, 0xb8, 0xcd, 0x7c, 0x82, 0x39, 0x6e, 0x4a, 0x6a, 0x92, 0x33, 0xdf, 0xf7, 0x54, 0x19, 0x6a, - 0x5e, 0xac, 0x2f, 0xef, 0xfa, 0x9b, 0x72, 0xa1, 0x1a, 0xb1, 0x2f, 0xf5, 0xc9, 0x54, 0xf4, 0xe5, - 0x0d, 0x7f, 0x13, 0x19, 0x71, 0x36, 0x47, 0x9a, 0xda, 0x51, 0x4b, 0x2e, 0x53, 0x37, 0xf3, 0x75, - 0x50, 0x13, 0x73, 0x24, 0x2e, 0x45, 0x83, 0x23, 0x6b, 0xdb, 0xb6, 0x34, 0x56, 0xca, 0x85, 0x6a, - 0xc4, 0xb6, 0x4d, 0x9a, 0x3e, 0x45, 0xdb, 0xaa, 0x32, 0xd4, 0xbc, 0x18, 0x5f, 0x57, 0x5a, 0xfe, - 0xf2, 0x59, 0xaa, 0x92, 0x76, 0x44, 0xc1, 0x57, 0x95, 0xa1, 0xe6, 0xc5, 0xda, 0x3b, 0xdc, 0xd9, - 0xbb, 0xe7, 0x74, 0x76, 0x5c, 0xaf, 0x2d, 0xc3, 0x76, 0x47, 0x0d, 0x73, 0xdb, 0xd9, 0xbb, 0x23, - 0xe8, 0x99, 0xed, 0x1d, 0x97, 0xa2, 0xc1, 0x91, 0xfc, 0x5d, 0x4b, 0x87, 0xe2, 0x4c, 0xe5, 0xe1, - 0xc4, 0x94, 0x5c, 0x72, 0x65, 0x64, 0x8e, 0x50, 0x14, 0x7f, 0x4a, 0xfb, 0x5d, 0xf2, 0xc2, 0xaf, - 0xfd, 0x51, 0x75, 0x8e, 0x7a, 0x4d, 0xbf, 0xe5, 0x7a, 0xed, 0xc5, 0xbb, 0xa1, 0xef, 0x2d, 0xa0, - 0x73, 0x4f, 0xe9, 0xe8, 0x52, 0xa6, 0xf9, 0x8f, 0x41, 0xc5, 0x20, 0x71, 0x94, 0xa2, 0x37, 0x65, - 0x2a, 0x7a, 0xbf, 0x31, 0x01, 0x53, 0x66, 0x1e, 0xd2, 0x63, 0x68, 0x5f, 0xfa, 0xc4, 0x31, 0x76, - 0x92, 0x13, 0x07, 0x3b, 0x62, 0x1a, 0x17, 0x5c, 0xca, 0xbc, 0xb5, 0x92, 0x9b, 0xc2, 0x1d, 0x1f, - 0x31, 0x8d, 0xc2, 0x10, 0x13, 0x4c, 0x4f, 0xe0, 0xf3, 0xc2, 0xd4, 0x56, 0xa1, 0xd8, 0x15, 0x93, - 0x6a, 0x6b, 0x42, 0x55, 0x7b, 0x0e, 0x20, 0x4e, 0x98, 0x29, 0x2f, 0x3e, 0xb5, 0x3e, 0x6c, 0x24, - 0xf2, 0x34, 0xb0, 0xc8, 0x53, 0x30, 0xc1, 0x54, 0x1f, 0xda, 0x92, 0x59, 0x05, 0xf4, 0x39, 0xfe, - 0x1a, 0x2f, 0x45, 0x09, 0x25, 0x2f, 0x31, 0x2d, 0x35, 0x56, 0x58, 0x64, 0xb2, 0x80, 0x8b, 0xb1, - 0x96, 0x1a, 0xc3, 0x30, 0x81, 0xc9, 0x44, 0xa7, 0x4c, 0xbf, 0xe0, 0x6b, 0x83, 0x21, 0x3a, 0x57, - 0x3a, 0x50, 0xc0, 0xb8, 0x5d, 0x29, 0xa5, 0x8f, 0xf0, 0x39, 0x5d, 0x34, 0xec, 0x4a, 0x29, 0x38, - 0x0e, 0xd4, 0x60, 0x1f, 0x23, 0xef, 0x6c, 0x2b, 0xc2, 0x61, 0x7a, 0xc8, 0x6d, 0xeb, 0x57, 0xcc, - 0xb3, 0x56, 0x8e, 0x73, 0x48, 0x8c, 0xda, 0xe3, 0x1f, 0xb6, 0x46, 0x3b, 0x16, 0x7d, 0x16, 0xa6, - 0x93, 0xbb, 0x50, 0xee, 0x37, 0x1f, 0x5f, 0x1d, 0x87, 0x0b, 0x37, 0xdb, 0xae, 0x97, 0xce, 0xf9, - 0x96, 0xf5, 0xc0, 0x83, 0x75, 0xe2, 0x07, 0x1e, 0x74, 0x4c, 0x9e, 0x7c, 0x3e, 0x21, 0x3b, 0x26, - 0x4f, 0xbd, 0x65, 0x91, 0xc4, 0x25, 0x7f, 0x68, 0xc1, 0xe3, 0x4e, 0x4b, 0x9c, 0x0b, 0x9c, 0x8e, - 0x2c, 0x35, 0xf2, 0x92, 0xcb, 0x19, 0x1d, 0x8e, 0xb8, 0xcb, 0x0f, 0x7e, 0xfc, 0x42, 0xed, 0x10, - 0xae, 0xa2, 0xc7, 0x7f, 0x52, 0x7e, 0xc1, 0xe3, 0x87, 0xa1, 0xe2, 0xa1, 0xe2, 0x93, 0xbf, 0x0c, - 0x33, 0x89, 0x0f, 0x96, 0x96, 0xf0, 0xb2, 0xb8, 0xb0, 0x68, 0x24, 0x41, 0x98, 0xc6, 0x9d, 0xbf, - 0x05, 0x3f, 0x71, 0xa4, 0x9c, 0x27, 0x1a, 0x6c, 0xdf, 0xb3, 0x60, 0xca, 0x4c, 0xcf, 0x44, 0x9e, - 0x85, 0x52, 0xe4, 0xef, 0x50, 0xef, 0x76, 0xa0, 0x1c, 0x76, 0xf5, 0x40, 0xdf, 0xe0, 0xe5, 0xb8, - 0x8a, 0x1a, 0x83, 0x61, 0x37, 0x3b, 0x2e, 0xf5, 0xa2, 0x95, 0x96, 0xec, 0x66, 0x8d, 0xbd, 0x24, - 0xca, 0x97, 0x51, 0x63, 0x08, 0x1f, 0x3b, 0xf6, 0xbb, 0x41, 0x9b, 0x01, 0x55, 0xee, 0xfd, 0x86, - 0x8f, 0x5d, 0x0c, 0xc3, 0x04, 0x26, 0xb1, 0xb5, 0x89, 0x73, 0x3c, 0xbe, 0xd7, 0x48, 0x99, 0x24, - 0xbf, 0x63, 0x41, 0x59, 0x98, 0xe8, 0x91, 0x6e, 0xa5, 0x5c, 0x6c, 0x53, 0x46, 0x84, 0xda, 0xfa, - 0x4a, 0x96, 0x8b, 0xed, 0x15, 0x18, 0xdf, 0x71, 0x3d, 0xf5, 0x25, 0x7a, 0x5b, 0x7a, 0xcd, 0xf5, - 0x5a, 0xc8, 0x21, 0x7a, 0xe3, 0x2a, 0x0c, 0xdd, 0xb8, 0x16, 0xa1, 0xac, 0x1d, 0x4f, 0xe4, 0xf2, - 0xaf, 0xad, 0xb7, 0xda, 0x51, 0x05, 0x63, 0x1c, 0xfb, 0xd7, 0x2c, 0x98, 0xe6, 0x11, 0xe3, 0xf1, - 0x79, 0xf8, 0x45, 0xed, 0x0b, 0x26, 0xe4, 0x7e, 0x22, 0xe9, 0x0b, 0xf6, 0xde, 0x7e, 0xb5, 0x22, - 0x62, 0xcc, 0x93, 0xae, 0x61, 0x9f, 0x96, 0x46, 0x34, 0xee, 0xb1, 0x36, 0x76, 0x62, 0x1b, 0x4f, - 0x2c, 0xa6, 0x22, 0x82, 0x31, 0x3d, 0xfb, 0x6d, 0x98, 0x32, 0x83, 0xb1, 0xc8, 0x8b, 0x50, 0xe9, - 0xb9, 0x5e, 0x3b, 0x19, 0xb4, 0xab, 0x2f, 0x1a, 0xd6, 0x63, 0x10, 0x9a, 0x78, 0xbc, 0x9a, 0x1f, - 0x57, 0x4b, 0xdd, 0x4f, 0xac, 0xfb, 0x66, 0xb5, 0xf8, 0x8f, 0xed, 0x01, 0xc4, 0x91, 0xc5, 0xc7, - 0x32, 0xde, 0x4c, 0x08, 0xdb, 0xbf, 0x50, 0x46, 0x78, 0x96, 0x88, 0x09, 0x31, 0xc2, 0xdf, 0xdb, - 0x3f, 0x4c, 0xd9, 0x11, 0xb5, 0xf8, 0x1b, 0x14, 0x19, 0x41, 0x86, 0xb9, 0xbf, 0x41, 0x91, 0xc1, - 0xe3, 0xfd, 0x7b, 0x83, 0x22, 0x4b, 0x98, 0x3f, 0x5b, 0x6f, 0x50, 0x7c, 0x12, 0x4e, 0x9a, 0x8e, - 0x96, 0xe9, 0x16, 0xf7, 0xcc, 0xb4, 0x11, 0xba, 0xc5, 0x65, 0xde, 0x08, 0x09, 0xb5, 0x7f, 0xbb, - 0x00, 0xb3, 0x69, 0x13, 0x43, 0xde, 0xde, 0x1b, 0xe4, 0xeb, 0x16, 0x4c, 0x3b, 0x89, 0xd4, 0x7f, - 0x39, 0x3d, 0x68, 0x95, 0xa0, 0x69, 0xa4, 0x9e, 0x4b, 0x94, 0x63, 0x8a, 0x37, 0xf9, 0x0b, 0x30, - 0x19, 0xb9, 0x5d, 0xea, 0xf7, 0x85, 0xe1, 0xb1, 0x20, 0x0c, 0x00, 0x1b, 0xa2, 0x08, 0x15, 0x8c, - 0x6d, 0x02, 0x2e, 0xd7, 0xd8, 0x02, 0x2a, 0x3d, 0x91, 0x67, 0x63, 0x4b, 0xa9, 0x28, 0x47, 0x8d, - 0x41, 0xee, 0xc3, 0xa4, 0xf0, 0xf3, 0x50, 0x0e, 0x3d, 0x6b, 0x39, 0x99, 0x42, 0x84, 0x2b, 0x49, - 0xdc, 0x05, 0xe2, 0x7f, 0x88, 0x8a, 0x9d, 0xfd, 0x11, 0x38, 0x61, 0x7e, 0x5e, 0xfb, 0x2a, 0x10, - 0xf4, 0x3b, 0x9d, 0x4d, 0xa7, 0xb9, 0x73, 0xc7, 0xf5, 0x5a, 0xfe, 0x3d, 0xbe, 0xf4, 0x2d, 0x42, - 0x39, 0x90, 0x21, 0xba, 0xa1, 0x1c, 0x35, 0x7a, 0xed, 0x54, 0xb1, 0xbb, 0x21, 0xc6, 0x38, 0xf6, - 0xef, 0x8d, 0xc1, 0xa4, 0x8c, 0x27, 0x7f, 0x00, 0x91, 0x10, 0x3b, 0x89, 0xfb, 0xe7, 0x95, 0x5c, - 0xc2, 0xe0, 0x87, 0x86, 0x41, 0x84, 0xa9, 0x30, 0x88, 0xd7, 0xf2, 0x61, 0x77, 0x78, 0x0c, 0xc4, - 0x77, 0x8b, 0x30, 0x93, 0x8a, 0xcf, 0x4f, 0xa5, 0xf2, 0xb6, 0xde, 0x97, 0x54, 0xde, 0x24, 0x4c, - 0xa4, 0x73, 0xcf, 0xcf, 0x6f, 0xf2, 0xcf, 0x33, 0xbb, 0xe7, 0xe5, 0xd1, 0x5a, 0xfc, 0xe0, 0x78, - 0xb4, 0xfe, 0x17, 0x0b, 0x1e, 0x1d, 0x9a, 0x65, 0x82, 0xe7, 0x6b, 0x0b, 0x92, 0x50, 0xb9, 0x5e, - 0xe4, 0x9c, 0xb9, 0x47, 0xdf, 0x55, 0xa7, 0x53, 0x6c, 0xa5, 0xd9, 0x93, 0x17, 0x60, 0x8a, 0xeb, - 0x83, 0x6c, 0xe5, 0x8c, 0x68, 0x4f, 0x5e, 0xb5, 0xf1, 0x4b, 0x97, 0x86, 0x51, 0x8e, 0x09, 0x2c, - 0xfb, 0xdb, 0x16, 0xcc, 0x0d, 0xcb, 0xde, 0x75, 0x0c, 0x4d, 0xee, 0x2f, 0xa5, 0x22, 0x49, 0xaa, - 0x03, 0x91, 0x24, 0x29, 0x53, 0x90, 0x0a, 0x1a, 0x31, 0xac, 0x30, 0x85, 0x23, 0x02, 0x25, 0x7e, - 0xbf, 0x00, 0xb3, 0x52, 0xc4, 0x58, 0x09, 0x7f, 0x29, 0x11, 0xff, 0xf2, 0x93, 0xa9, 0xf8, 0x97, - 0x8b, 0x69, 0xfc, 0x3f, 0x0f, 0x7e, 0xf9, 0x60, 0x05, 0xbf, 0x7c, 0xad, 0x08, 0x97, 0x32, 0xf3, - 0x64, 0x91, 0xaf, 0x66, 0xec, 0x14, 0x77, 0x72, 0x4e, 0xc8, 0xa5, 0xe3, 0x64, 0xcf, 0x36, 0x62, - 0xe4, 0x57, 0xcc, 0x48, 0x0d, 0xb1, 0xfa, 0x6f, 0x9d, 0x41, 0x6a, 0xb1, 0x93, 0x06, 0x6d, 0x3c, - 0xd8, 0xa7, 0xce, 0xfe, 0x0c, 0x2c, 0xf5, 0x5f, 0x2b, 0xc0, 0xd3, 0xc7, 0x6d, 0xd9, 0x0f, 0x68, - 0x94, 0x63, 0x98, 0x88, 0x72, 0x7c, 0x40, 0xaa, 0xcd, 0x99, 0x04, 0x3c, 0xfe, 0xfd, 0x71, 0xbd, - 0xef, 0x0e, 0x4e, 0xd8, 0x63, 0xd9, 0x16, 0x26, 0x99, 0xea, 0xab, 0x12, 0xc2, 0xc7, 0x7b, 0xc3, - 0x64, 0x43, 0x14, 0xbf, 0xb7, 0x5f, 0x3d, 0x1f, 0x27, 0x94, 0x91, 0x85, 0xa8, 0x2a, 0x91, 0xa7, - 0xa1, 0x14, 0x08, 0xa8, 0x8a, 0xeb, 0x92, 0xde, 0x35, 0xa2, 0x0c, 0x35, 0x94, 0x7c, 0xc1, 0x38, - 0x2b, 0x8c, 0x9f, 0x55, 0xde, 0xa4, 0xc3, 0x9c, 0x86, 0xde, 0x84, 0x52, 0xa8, 0xb2, 0x96, 0x8b, - 0xe9, 0xf4, 0xfc, 0x31, 0xc3, 0x05, 0x9d, 0x4d, 0xda, 0x51, 0x29, 0xcc, 0xc5, 0xf7, 0xe9, 0x04, - 0xe7, 0x9a, 0x24, 0xb1, 0xf5, 0xd9, 0x5b, 0x5c, 0x6a, 0xc0, 0xe0, 0xb9, 0x9b, 0x44, 0x30, 0x29, - 0x9f, 0x2e, 0x96, 0xb7, 0xad, 0x6b, 0x39, 0xc5, 0xdd, 0x48, 0xaf, 0x6c, 0x7e, 0xa4, 0x55, 0x36, - 0x27, 0xc5, 0xca, 0xfe, 0x81, 0x05, 0x15, 0x39, 0x46, 0x1e, 0x40, 0xdc, 0xe4, 0xdd, 0x64, 0xdc, - 0xe4, 0xd5, 0x5c, 0x96, 0xf0, 0x21, 0x41, 0x93, 0x77, 0x61, 0xca, 0xcc, 0x58, 0x49, 0x3e, 0x65, - 0x6c, 0x41, 0xd6, 0x28, 0x59, 0xd9, 0xd4, 0x26, 0x15, 0x6f, 0x4f, 0xf6, 0x3f, 0x2e, 0xeb, 0x56, - 0xe4, 0x07, 0x67, 0x73, 0xe4, 0x5b, 0x87, 0x8e, 0x7c, 0x73, 0xe0, 0x8d, 0xe5, 0x3f, 0xf0, 0x5e, - 0x87, 0x92, 0x5a, 0x16, 0xa5, 0x36, 0xf5, 0xa4, 0xe9, 0xa6, 0xcd, 0x54, 0x32, 0x46, 0xcc, 0x98, - 0x2e, 0xfc, 0x00, 0x1c, 0x5b, 0xc2, 0xd5, 0x72, 0xad, 0xc9, 0x90, 0xb7, 0xa0, 0x72, 0xcf, 0x0f, - 0x76, 0x3a, 0xbe, 0xc3, 0x9f, 0x8a, 0x80, 0x3c, 0x3c, 0x03, 0xb4, 0x35, 0x5b, 0xc4, 0xca, 0xdc, - 0x89, 0xe9, 0xa3, 0xc9, 0x8c, 0xd4, 0x60, 0xa6, 0xeb, 0x7a, 0x48, 0x9d, 0x96, 0x0e, 0x8f, 0x1c, - 0x17, 0x69, 0xda, 0x95, 0x6e, 0xbf, 0x96, 0x04, 0x63, 0x1a, 0x9f, 0x5b, 0x9e, 0x82, 0x84, 0xa9, - 0x43, 0xe6, 0x62, 0x5e, 0x1f, 0x7d, 0x30, 0x26, 0xcd, 0x27, 0x22, 0x58, 0x24, 0x59, 0x8e, 0x29, - 0xde, 0xe4, 0xf3, 0x50, 0x0a, 0xd5, 0xa3, 0xa0, 0xc5, 0x1c, 0x4f, 0x3d, 0xfa, 0x61, 0x50, 0xdd, - 0x95, 0xfa, 0x65, 0x50, 0xcd, 0x90, 0xac, 0xc2, 0x45, 0x65, 0xbb, 0x49, 0xbc, 0x6f, 0x38, 0x11, - 0xe7, 0x13, 0xc3, 0x0c, 0x38, 0x66, 0xd6, 0x62, 0xba, 0x2d, 0xcf, 0x04, 0x2b, 0x6e, 0x62, 0x8d, - 0xcb, 0x4b, 0x3e, 0xff, 0x5a, 0x28, 0xa1, 0x87, 0x45, 0xff, 0x96, 0x46, 0x88, 0xfe, 0x6d, 0xc0, - 0xa5, 0x34, 0x88, 0x27, 0x8a, 0xe3, 0xb9, 0xe9, 0x8c, 0x2d, 0x74, 0x3d, 0x0b, 0x09, 0xb3, 0xeb, - 0x92, 0x3b, 0x50, 0x0e, 0x28, 0x3f, 0xe5, 0xd5, 0x94, 0x13, 0xdb, 0x89, 0xdd, 0x75, 0x51, 0x11, - 0xc0, 0x98, 0x16, 0xeb, 0x77, 0x27, 0x99, 0x38, 0xfd, 0xf5, 0x1c, 0x5f, 0x0d, 0x97, 0x7d, 0x3f, - 0x24, 0x81, 0xa3, 0xfd, 0x6f, 0x67, 0xe0, 0x5c, 0xc2, 0x00, 0x45, 0x9e, 0x84, 0x22, 0xcf, 0x9c, - 0xc7, 0x57, 0xab, 0x52, 0xbc, 0xa2, 0x8a, 0xc6, 0x11, 0x30, 0xf2, 0x4b, 0x16, 0xcc, 0xf4, 0x12, - 0x17, 0x38, 0x6a, 0x21, 0x1f, 0xd1, 0x6a, 0x9b, 0xbc, 0x15, 0x32, 0x9e, 0x1c, 0x49, 0x32, 0xc3, - 0x34, 0x77, 0xb6, 0x1e, 0x48, 0x9f, 0xf7, 0x0e, 0x0d, 0x38, 0xb6, 0x54, 0xf4, 0x34, 0x89, 0xa5, - 0x24, 0x18, 0xd3, 0xf8, 0xac, 0x87, 0xf9, 0xd7, 0x8d, 0xf2, 0x32, 0x6c, 0x4d, 0x11, 0xc0, 0x98, - 0x16, 0x79, 0x05, 0xa6, 0x65, 0xbe, 0xec, 0x75, 0xbf, 0x75, 0xdd, 0x09, 0xb7, 0xe5, 0x91, 0x4f, - 0x1f, 0x51, 0x97, 0x12, 0x50, 0x4c, 0x61, 0xf3, 0x6f, 0x8b, 0x93, 0x92, 0x73, 0x02, 0x13, 0xc9, - 0x17, 0x59, 0x96, 0x92, 0x60, 0x4c, 0xe3, 0x93, 0x67, 0x8d, 0x6d, 0x48, 0x78, 0x47, 0xe8, 0xd5, - 0x20, 0x63, 0x2b, 0xaa, 0xc1, 0x4c, 0x9f, 0x9f, 0x90, 0x5b, 0x0a, 0x28, 0xe7, 0xa3, 0x66, 0x78, - 0x3b, 0x09, 0xc6, 0x34, 0x3e, 0x79, 0x19, 0xce, 0x05, 0x6c, 0xb1, 0xd5, 0x04, 0x84, 0xcb, 0x84, - 0xbe, 0x11, 0x47, 0x13, 0x88, 0x49, 0x5c, 0xf2, 0x2a, 0x9c, 0x8f, 0x73, 0xaa, 0x2a, 0x02, 0xc2, - 0x87, 0x42, 0x27, 0xf8, 0xab, 0xa5, 0x11, 0x70, 0xb0, 0x0e, 0xf9, 0xab, 0x30, 0x6b, 0xb4, 0xc4, - 0x8a, 0xd7, 0xa2, 0xf7, 0x65, 0xde, 0x4b, 0xfe, 0xc2, 0xd8, 0x52, 0x0a, 0x86, 0x03, 0xd8, 0xe4, - 0xe3, 0x30, 0xdd, 0xf4, 0x3b, 0x1d, 0xbe, 0xc6, 0x89, 0xd7, 0x40, 0x44, 0x82, 0x4b, 0x91, 0x0a, - 0x34, 0x01, 0xc1, 0x14, 0x26, 0xb9, 0x01, 0xc4, 0xdf, 0x64, 0xea, 0x15, 0x6d, 0xbd, 0x4a, 0x3d, - 0x2a, 0x35, 0x8e, 0x73, 0xc9, 0x88, 0x9b, 0x5b, 0x03, 0x18, 0x98, 0x51, 0x8b, 0xe7, 0x07, 0x34, - 0x22, 0x94, 0xa7, 0xf3, 0xc8, 0x48, 0x9e, 0xb6, 0xe7, 0x1c, 0x19, 0x9e, 0x1c, 0xc0, 0x84, 0x08, - 0x80, 0xca, 0x27, 0xd3, 0xa5, 0xf9, 0x30, 0x40, 0xbc, 0x47, 0x88, 0x52, 0x94, 0x9c, 0xc8, 0xcf, - 0x43, 0x79, 0x53, 0xbd, 0x12, 0xc3, 0xd3, 0x5b, 0x8e, 0xbc, 0x2f, 0xa6, 0x1e, 0x3c, 0x8a, 0xed, - 0x15, 0x1a, 0x80, 0x31, 0x4b, 0xf2, 0x14, 0x54, 0xae, 0xaf, 0xd7, 0xf4, 0x28, 0x3c, 0xcf, 0x7b, - 0x7f, 0x9c, 0x55, 0x41, 0x13, 0xc0, 0x66, 0x98, 0x56, 0xdf, 0x48, 0xd2, 0x2d, 0x20, 0x43, 0x1b, - 0x63, 0xd8, 0xdc, 0xcf, 0x01, 0x1b, 0x73, 0x17, 0x52, 0xd8, 0xb2, 0x1c, 0x35, 0x06, 0x79, 0x13, - 0x2a, 0x72, 0xbf, 0xe0, 0x6b, 0xd3, 0xc5, 0xd3, 0x45, 0xbf, 0x63, 0x4c, 0x02, 0x4d, 0x7a, 0xfc, - 0x82, 0x9a, 0x3f, 0x9e, 0x41, 0xaf, 0xf5, 0x3b, 0x9d, 0xb9, 0x4b, 0x7c, 0xdd, 0x8c, 0x2f, 0xa8, - 0x63, 0x10, 0x9a, 0x78, 0xe4, 0x79, 0xe5, 0xaf, 0xf6, 0x70, 0xe2, 0xc6, 0x5e, 0xfb, 0xab, 0x69, - 0xa5, 0x7b, 0x48, 0x80, 0xcc, 0x23, 0x47, 0x38, 0x8a, 0x6d, 0xc2, 0xbc, 0xd2, 0xf8, 0x06, 0x27, - 0xc9, 0xdc, 0x5c, 0xc2, 0x76, 0x34, 0x7f, 0x67, 0x28, 0x26, 0x1e, 0x42, 0x85, 0x6c, 0x42, 0xc1, - 0xe9, 0x6c, 0xce, 0x3d, 0x9a, 0x87, 0xea, 0x5a, 0x5b, 0xad, 0xcb, 0x11, 0xc5, 0x9d, 0x5a, 0x6b, - 0xab, 0x75, 0x64, 0xc4, 0x89, 0x0b, 0xe3, 0x4e, 0x67, 0x33, 0x9c, 0x9b, 0xe7, 0x73, 0x36, 0x37, - 0x26, 0xb1, 0xf1, 0x60, 0xb5, 0x1e, 0x22, 0x67, 0x61, 0x7f, 0x71, 0x4c, 0xdf, 0x12, 0xe9, 0x64, - 0xe3, 0x6f, 0x9b, 0x13, 0x48, 0x1c, 0x77, 0x6e, 0xe5, 0x36, 0x81, 0xa4, 0x7a, 0x71, 0x6e, 0xe8, - 0xf4, 0xe9, 0xe9, 0x25, 0x23, 0x97, 0x2c, 0x65, 0xc9, 0x44, 0xea, 0xe2, 0xf4, 0x9c, 0x5c, 0x30, - 0xec, 0x2f, 0x55, 0xb4, 0x15, 0x34, 0xe5, 0xeb, 0x15, 0x40, 0xd1, 0x0d, 0x23, 0xd7, 0xcf, 0x31, - 0x28, 0x3c, 0x95, 0x81, 0x9c, 0xc7, 0x9c, 0x70, 0x00, 0x0a, 0x56, 0x8c, 0xa7, 0xd7, 0x76, 0xbd, - 0xfb, 0xf2, 0xf3, 0x5f, 0xcf, 0xdd, 0x89, 0x4b, 0xf0, 0xe4, 0x00, 0x14, 0xac, 0xc8, 0x5d, 0x31, - 0xa8, 0x0b, 0x79, 0xf4, 0x75, 0x6d, 0xb5, 0x9e, 0xe2, 0x97, 0x1c, 0xdc, 0x77, 0xa1, 0x10, 0x76, - 0x5d, 0xa9, 0x2e, 0x8d, 0xc8, 0xab, 0xb1, 0xb6, 0x92, 0xc5, 0xab, 0xb1, 0xb6, 0x82, 0x8c, 0x09, - 0xf9, 0x8a, 0x05, 0xe0, 0x74, 0x37, 0x9d, 0x30, 0x74, 0x5a, 0xda, 0x3a, 0x33, 0xe2, 0x23, 0x2b, - 0x35, 0x4d, 0x2f, 0xc5, 0x9a, 0xbb, 0x2d, 0xc7, 0x50, 0x34, 0x38, 0x93, 0xb7, 0x60, 0xd2, 0x11, - 0xaf, 0x58, 0x4a, 0x0f, 0xfc, 0x7c, 0x9e, 0x66, 0x4d, 0x49, 0xc0, 0xcd, 0x34, 0x12, 0x84, 0x8a, - 0x21, 0xe3, 0x1d, 0x05, 0x0e, 0xdd, 0x72, 0x77, 0xa4, 0x71, 0xa8, 0x31, 0xf2, 0x3b, 0x2b, 0x8c, - 0x58, 0x16, 0x6f, 0x09, 0x42, 0xc5, 0x90, 0xfc, 0x82, 0x05, 0xe7, 0xba, 0x8e, 0xe7, 0xe8, 0xb8, - 0xca, 0x7c, 0xa2, 0x6f, 0xcd, 0x48, 0xcd, 0x58, 0x43, 0x5c, 0x33, 0x19, 0x61, 0x92, 0x2f, 0xd9, - 0x85, 0x09, 0x87, 0xbf, 0xaf, 0x2b, 0x8f, 0x62, 0x98, 0xc7, 0x5b, 0xbd, 0xa9, 0x36, 0xe0, 0x8b, - 0x8b, 0x7c, 0xc5, 0x57, 0x72, 0x23, 0xbf, 0x6e, 0xc1, 0xa4, 0x70, 0x0e, 0x67, 0x0a, 0x29, 0xfb, - 0xf6, 0xcf, 0x9e, 0xc1, 0x4b, 0x06, 0xd2, 0x71, 0x5d, 0xba, 0x1f, 0x7d, 0x48, 0x7b, 0xbe, 0x8a, - 0xd2, 0x43, 0x5d, 0xd7, 0x95, 0x74, 0x4c, 0xf5, 0xed, 0x3a, 0xf7, 0x13, 0xaf, 0xe8, 0x98, 0xaa, - 0xef, 0x5a, 0x0a, 0x86, 0x03, 0xd8, 0xf3, 0x1f, 0x87, 0x29, 0x53, 0x8e, 0x13, 0xb9, 0xbf, 0xff, - 0xa8, 0x00, 0xc0, 0xbb, 0x4a, 0xe4, 0x62, 0xe9, 0xf2, 0xc4, 0xcd, 0xdb, 0x7e, 0x2b, 0xa7, 0xd7, - 0x3c, 0x8d, 0x94, 0x2a, 0x20, 0xb3, 0x34, 0x6f, 0xfb, 0x2d, 0x94, 0x4c, 0x48, 0x1b, 0xc6, 0x7b, - 0x4e, 0xb4, 0x9d, 0x7f, 0xfe, 0x96, 0x92, 0x08, 0x4a, 0x8e, 0xb6, 0x91, 0x33, 0x20, 0xef, 0x58, - 0xb1, 0x67, 0x4f, 0x21, 0x8f, 0xdc, 0xb3, 0x71, 0x9b, 0x2d, 0x48, 0x5f, 0x9e, 0x54, 0x0a, 0xd6, - 0xb4, 0x87, 0xcf, 0xfc, 0xbb, 0x16, 0x4c, 0x99, 0xa8, 0x19, 0xdd, 0xf4, 0x73, 0x66, 0x37, 0xe5, - 0xd9, 0x1e, 0x66, 0x8f, 0xff, 0x37, 0x0b, 0x00, 0xfb, 0x5e, 0xa3, 0xdf, 0xed, 0x32, 0xb5, 0x5d, - 0x7b, 0xf9, 0x5b, 0xc7, 0xf6, 0xf2, 0x1f, 0x3b, 0xa1, 0x97, 0x7f, 0xe1, 0x44, 0x5e, 0xfe, 0xe3, - 0x27, 0xf7, 0xf2, 0x2f, 0x0e, 0xf7, 0xf2, 0xb7, 0xbf, 0x69, 0xc1, 0xf9, 0x81, 0xfd, 0x8a, 0x69, - 0xd2, 0x81, 0xef, 0x47, 0x43, 0x3c, 0x44, 0x31, 0x06, 0xa1, 0x89, 0x47, 0x96, 0x61, 0x56, 0x3e, - 0x53, 0xd2, 0xe8, 0x75, 0xdc, 0xcc, 0xdc, 0x3a, 0x1b, 0x29, 0x38, 0x0e, 0xd4, 0xb0, 0x7f, 0xdb, - 0x82, 0x8a, 0x11, 0x91, 0xcf, 0xbe, 0x83, 0xbb, 0x09, 0x4b, 0x31, 0xe2, 0x17, 0x5a, 0xf8, 0x55, - 0x97, 0x80, 0x89, 0x6b, 0xe8, 0xb6, 0x91, 0xc4, 0x3e, 0xbe, 0x86, 0x66, 0xa5, 0x28, 0xa1, 0x22, - 0x3d, 0x39, 0xed, 0xf1, 0x46, 0x2f, 0x98, 0xe9, 0xc9, 0x69, 0x0f, 0x39, 0x84, 0xb3, 0x63, 0x47, - 0x0a, 0xe9, 0x01, 0x6c, 0x3c, 0x08, 0xe3, 0x04, 0x11, 0x0a, 0x18, 0x79, 0x02, 0x0a, 0xd4, 0x6b, - 0x49, 0xfb, 0x87, 0x7e, 0xbd, 0xf6, 0xaa, 0xd7, 0x42, 0x56, 0x6e, 0xdf, 0x82, 0x29, 0xe1, 0xfd, - 0xfc, 0x1a, 0xdd, 0x3b, 0xf6, 0x73, 0xb8, 0x6c, 0xb4, 0xa7, 0x9e, 0xc3, 0x65, 0xd5, 0x59, 0xb9, - 0xfd, 0x8f, 0x2c, 0x48, 0xbd, 0x91, 0x64, 0xdc, 0xc0, 0x58, 0x43, 0x6f, 0x60, 0x4c, 0xab, 0xfd, - 0xd8, 0xa1, 0x56, 0xfb, 0x1b, 0x40, 0xba, 0x6c, 0x2a, 0x24, 0x17, 0xda, 0x42, 0xf2, 0x29, 0x89, - 0xb5, 0x01, 0x0c, 0xcc, 0xa8, 0x65, 0xff, 0x43, 0x21, 0xac, 0xf9, 0x6a, 0xd2, 0xd1, 0x0d, 0xd0, - 0x87, 0x22, 0x27, 0x25, 0xed, 0x6f, 0x23, 0xda, 0xae, 0x07, 0xf3, 0x68, 0xc5, 0x1d, 0x29, 0xa7, - 0x3c, 0xe7, 0x66, 0xff, 0xbe, 0x90, 0xd5, 0x7c, 0x56, 0xe9, 0x68, 0x59, 0xbb, 0x49, 0x59, 0xaf, - 0xe7, 0xb5, 0x56, 0x66, 0xcb, 0x48, 0x16, 0x00, 0x7a, 0x34, 0x68, 0x52, 0x2f, 0x52, 0x71, 0x49, - 0x45, 0x19, 0x21, 0xab, 0x4b, 0xd1, 0xc0, 0xb0, 0xbf, 0xc1, 0x26, 0x50, 0xfc, 0x50, 0x34, 0x79, - 0x3a, 0xed, 0xea, 0x9a, 0x9e, 0x1c, 0xda, 0xd3, 0xd5, 0x88, 0x56, 0x19, 0x3b, 0x22, 0x5a, 0xe5, + 0x04, 0xd4, 0x8b, 0x1a, 0x11, 0xed, 0x0d, 0x6e, 0x5c, 0xd6, 0x99, 0x6e, 0x5c, 0x4f, 0x1e, 0xec, + 0x57, 0x1f, 0x5f, 0x3a, 0x84, 0x3f, 0x1e, 0x2a, 0x1d, 0xf9, 0xf7, 0x16, 0xd8, 0x12, 0xa1, 0xee, + 0x34, 0x77, 0xda, 0x81, 0xdf, 0xf7, 0x5a, 0x83, 0x1f, 0x31, 0x76, 0xa6, 0x1f, 0xf1, 0xf4, 0xc1, + 0x7e, 0xd5, 0x5e, 0x3a, 0x52, 0x0a, 0x3c, 0x86, 0xa4, 0xe4, 0x55, 0x38, 0x2f, 0xb1, 0xae, 0xde, + 0xef, 0xd1, 0xc0, 0x65, 0x67, 0x0e, 0xa9, 0x38, 0xc6, 0xbe, 0x69, 0x69, 0x04, 0x1c, 0xac, 0x43, + 0x42, 0x98, 0xbc, 0x47, 0xdd, 0xf6, 0x76, 0xa4, 0xd4, 0xa7, 0x11, 0x1d, 0xd2, 0xa4, 0x55, 0xe4, + 0x8e, 0xa0, 0x59, 0xaf, 0x1c, 0xec, 0x57, 0x27, 0xe5, 0x1f, 0x54, 0x9c, 0xc8, 0x4d, 0x98, 0x16, + 0xe7, 0xd4, 0x75, 0xd7, 0x6b, 0xaf, 0xfb, 0x9e, 0xf0, 0xaa, 0x2a, 0xd7, 0x9f, 0x56, 0x1b, 0x7e, + 0x23, 0x01, 0x7d, 0x6f, 0xbf, 0x3a, 0xa5, 0x7e, 0x6f, 0xec, 0xf5, 0x28, 0xa6, 0x6a, 0x93, 0xbf, + 0x6b, 0x01, 0x09, 0x23, 0xda, 0x5b, 0xef, 0xf4, 0xdb, 0xae, 0x6c, 0x22, 0xe9, 0x1f, 0x95, 0x83, + 0xab, 0x56, 0x92, 0x6e, 0x7d, 0x5e, 0x0a, 0x49, 0x1a, 0x03, 0x1c, 0x31, 0x43, 0x0a, 0xfb, 0x3b, + 0x93, 0x00, 0x6a, 0x2e, 0xd1, 0x1e, 0xf9, 0x10, 0x94, 0x43, 0x1a, 0x89, 0x26, 0x91, 0xd7, 0x5c, + 0xe2, 0x72, 0x52, 0x15, 0x62, 0x0c, 0x27, 0x3b, 0x50, 0xec, 0x39, 0xfd, 0x90, 0xe6, 0x73, 0xb8, + 0x91, 0x23, 0x73, 0x9d, 0x51, 0x14, 0xa7, 0x66, 0xfe, 0x13, 0x05, 0x0f, 0xf2, 0x65, 0x0b, 0x80, + 0x26, 0x47, 0xd3, 0xc8, 0xd6, 0x2b, 0xc9, 0x32, 0x1e, 0x70, 0xac, 0x0d, 0xea, 0xd3, 0x07, 0xfb, + 0x55, 0x30, 0xc6, 0xa5, 0xc1, 0x96, 0xdc, 0x83, 0x92, 0xa3, 0x36, 0xa4, 0xf1, 0xb3, 0xd8, 0x90, + 0xf8, 0x61, 0x56, 0xcf, 0x28, 0xcd, 0x8c, 0x7c, 0xd5, 0x82, 0xe9, 0x90, 0x46, 0xb2, 0xab, 0xd8, + 0xb2, 0x28, 0xb5, 0xf1, 0x11, 0x67, 0x44, 0x23, 0x41, 0x53, 0x2c, 0xef, 0xc9, 0x32, 0x4c, 0xf1, + 0x55, 0xa2, 0x5c, 0xa7, 0x4e, 0x8b, 0x06, 0xdc, 0x56, 0x22, 0xd5, 0xbc, 0xd1, 0x45, 0x31, 0x68, + 0x6a, 0x51, 0x8c, 0x32, 0x4c, 0xf1, 0x55, 0xa2, 0xac, 0xb9, 0x41, 0xe0, 0x4b, 0x51, 0x4a, 0x39, + 0x89, 0x62, 0xd0, 0xd4, 0xa2, 0x18, 0x65, 0x98, 0xe2, 0x4b, 0x3a, 0x30, 0xd1, 0xe3, 0x53, 0x4b, + 0xaa, 0x72, 0x23, 0xde, 0x91, 0xab, 0x69, 0x4a, 0x7b, 0xc2, 0x26, 0x25, 0xfe, 0xa3, 0xe4, 0x61, + 0x7f, 0xfb, 0x1c, 0x4c, 0xab, 0x69, 0x1b, 0x1f, 0x72, 0x84, 0x21, 0x70, 0xc8, 0x21, 0x67, 0xc9, + 0x04, 0x62, 0x12, 0x97, 0x55, 0x16, 0xab, 0x56, 0xf2, 0x8c, 0xa3, 0x2b, 0x37, 0x4c, 0x20, 0x26, + 0x71, 0x49, 0x17, 0x8a, 0x6c, 0x65, 0x51, 0xee, 0x17, 0x23, 0x7e, 0x79, 0xbc, 0x1a, 0x19, 0x46, + 0x15, 0x46, 0x1e, 0x05, 0x17, 0x6e, 0xcb, 0x8e, 0x12, 0xe6, 0x6d, 0x39, 0x15, 0xf3, 0x59, 0x0d, + 0x92, 0x96, 0x73, 0xd1, 0xf7, 0xc9, 0x32, 0x4c, 0xb1, 0xcf, 0x38, 0xf7, 0x14, 0xcf, 0xf0, 0xdc, + 0xf3, 0x29, 0x28, 0x75, 0x9d, 0xfb, 0x8d, 0x7e, 0xd0, 0x3e, 0xfd, 0xf9, 0x4a, 0xba, 0xd3, 0x0a, + 0x2a, 0xa8, 0xe9, 0x91, 0x2f, 0x5a, 0xc6, 0x02, 0x27, 0x7c, 0x2d, 0xee, 0xe4, 0xbb, 0xc0, 0x69, + 0xb5, 0x61, 0xe8, 0x52, 0x37, 0x70, 0x0a, 0x29, 0x3d, 0xf0, 0x53, 0x08, 0xd3, 0xa8, 0xc5, 0x04, + 0xd1, 0x1a, 0x75, 0xf9, 0x4c, 0x35, 0xea, 0xa5, 0x04, 0x33, 0x4c, 0x31, 0xe7, 0xf2, 0x88, 0x39, + 0xa7, 0xe5, 0x81, 0x33, 0x95, 0xa7, 0x91, 0x60, 0x86, 0x29, 0xe6, 0xc3, 0x8f, 0xde, 0x95, 0xb3, + 0x39, 0x7a, 0x4f, 0xe5, 0x70, 0xf4, 0x3e, 0xfc, 0x54, 0x72, 0x6e, 0xd4, 0x53, 0x09, 0xb9, 0x01, + 0xa4, 0xb5, 0xe7, 0x39, 0x5d, 0xb7, 0x29, 0x17, 0x4b, 0xbe, 0x49, 0x4f, 0x73, 0xd3, 0x8c, 0xd6, + 0xca, 0x96, 0x07, 0x30, 0x30, 0xa3, 0x16, 0x89, 0xa0, 0xd4, 0x53, 0xca, 0xe7, 0x4c, 0x1e, 0xa3, + 0x5f, 0x29, 0xa3, 0xc2, 0x85, 0x86, 0x4d, 0x3c, 0x55, 0x82, 0x9a, 0x13, 0x59, 0x85, 0x8b, 0x5d, + 0xd7, 0x5b, 0xf7, 0x5b, 0xe1, 0x3a, 0x0d, 0xa4, 0xe1, 0xa9, 0x41, 0xa3, 0xb9, 0x59, 0xde, 0x36, + 0xdc, 0x98, 0xb0, 0x96, 0x01, 0xc7, 0xcc, 0x5a, 0xf6, 0xff, 0xb6, 0x60, 0x76, 0xa9, 0xe3, 0xf7, + 0x5b, 0x77, 0x9c, 0xa8, 0xb9, 0x2d, 0x3c, 0x36, 0xc8, 0x2b, 0x50, 0x72, 0xbd, 0x88, 0x06, 0xbb, + 0x4e, 0x47, 0xee, 0x4f, 0xb6, 0xb2, 0x24, 0xaf, 0xc8, 0xf2, 0xf7, 0xf6, 0xab, 0xd3, 0xcb, 0xfd, + 0x80, 0x1b, 0xec, 0xc5, 0x6a, 0x85, 0xba, 0x0e, 0xf9, 0xb6, 0x05, 0xe7, 0x85, 0xcf, 0xc7, 0xb2, + 0x13, 0x39, 0xaf, 0xf7, 0x69, 0xe0, 0x52, 0xe5, 0xf5, 0x31, 0xe2, 0x42, 0x95, 0x96, 0x55, 0x31, + 0xd8, 0x8b, 0xcf, 0x2c, 0x6b, 0x69, 0xce, 0x38, 0x28, 0x8c, 0xfd, 0xcb, 0x05, 0x78, 0x74, 0x28, + 0x2d, 0x32, 0x0f, 0x63, 0x6e, 0x4b, 0x7e, 0x3a, 0x48, 0xba, 0x63, 0x2b, 0x2d, 0x1c, 0x73, 0x5b, + 0x64, 0x81, 0x6b, 0xb8, 0x01, 0x0d, 0x43, 0x75, 0xf7, 0x5e, 0xd6, 0xca, 0xa8, 0x2c, 0x45, 0x03, + 0x83, 0x54, 0xa1, 0xc8, 0x5d, 0xa9, 0xe5, 0xd1, 0x8a, 0xeb, 0xcc, 0xdc, 0x6b, 0x19, 0x45, 0x39, + 0xf9, 0x92, 0x05, 0x20, 0x04, 0x64, 0xfa, 0xbe, 0xdc, 0x25, 0x31, 0xdf, 0x66, 0x62, 0x94, 0x85, + 0x94, 0xf1, 0x7f, 0x34, 0xb8, 0x92, 0x0d, 0x98, 0x60, 0xea, 0xb3, 0xdf, 0x3a, 0xf5, 0xa6, 0x28, + 0x14, 0x20, 0x4e, 0x03, 0x25, 0x2d, 0xd6, 0x56, 0x01, 0x8d, 0xfa, 0x81, 0xc7, 0x9a, 0x96, 0x6f, + 0x83, 0x25, 0x21, 0x05, 0xea, 0x52, 0x34, 0x30, 0xec, 0x7f, 0x31, 0x06, 0x17, 0xb3, 0x44, 0x67, + 0xbb, 0xcd, 0x84, 0x90, 0x56, 0x5a, 0x09, 0x7e, 0x26, 0xff, 0xf6, 0x91, 0xee, 0x4b, 0xfa, 0xc6, + 0x46, 0xfa, 0x92, 0x4a, 0xbe, 0xe4, 0x67, 0x74, 0x0b, 0x8d, 0x9d, 0xb2, 0x85, 0x34, 0xe5, 0x54, + 0x2b, 0x3d, 0x09, 0xe3, 0x21, 0xeb, 0xf9, 0x42, 0xf2, 0xe6, 0x87, 0xf7, 0x11, 0x87, 0x30, 0x8c, + 0xbe, 0xe7, 0x46, 0x32, 0xfe, 0x48, 0x63, 0xdc, 0xf6, 0xdc, 0x08, 0x39, 0xc4, 0xfe, 0xd6, 0x18, + 0xcc, 0x0f, 0xff, 0x28, 0xf2, 0x2d, 0x0b, 0xa0, 0xc5, 0x0e, 0x47, 0x21, 0x77, 0xe2, 0x17, 0xee, + 0x5e, 0xce, 0x59, 0xb5, 0xe1, 0xb2, 0xe2, 0x14, 0xfb, 0x21, 0xea, 0xa2, 0x10, 0x0d, 0x41, 0xc8, + 0x73, 0x6a, 0xe8, 0xf3, 0x5b, 0x2b, 0x31, 0x99, 0x74, 0x9d, 0x35, 0x0d, 0x41, 0x03, 0x8b, 0x9d, + 0x7e, 0x3d, 0xa7, 0x4b, 0xc3, 0x9e, 0xa3, 0xa3, 0xb9, 0xf8, 0xe9, 0xf7, 0xa6, 0x2a, 0xc4, 0x18, + 0x6e, 0x77, 0xe0, 0xa9, 0x63, 0xc8, 0x99, 0x53, 0xb0, 0x8c, 0xfd, 0x3f, 0x2d, 0x78, 0x44, 0x7a, + 0xe2, 0xfd, 0x7f, 0xe3, 0xd6, 0xf9, 0xa7, 0x16, 0x3c, 0x36, 0xe4, 0x9b, 0x1f, 0x80, 0x77, 0xe7, + 0x5b, 0x49, 0xef, 0xce, 0xdb, 0xa3, 0x0e, 0xe9, 0xcc, 0xef, 0x18, 0xe2, 0xe4, 0xf9, 0xbb, 0x05, + 0x38, 0xc7, 0x96, 0xad, 0x96, 0xdf, 0xce, 0x69, 0xe3, 0x7c, 0x0a, 0x8a, 0x9f, 0x63, 0x1b, 0x50, + 0x7a, 0x90, 0xf1, 0x5d, 0x09, 0x05, 0x8c, 0x7c, 0xd9, 0x82, 0xc9, 0xcf, 0xc9, 0x3d, 0x55, 0x9c, + 0xe5, 0x46, 0x5c, 0x0c, 0x13, 0xdf, 0xb0, 0x20, 0x77, 0x48, 0x11, 0x83, 0xa3, 0x7d, 0x39, 0xd5, + 0x56, 0xaa, 0x38, 0x93, 0x67, 0x60, 0x72, 0xcb, 0x0f, 0xba, 0xfd, 0x8e, 0x93, 0x0e, 0xfc, 0xbc, + 0x26, 0x8a, 0x51, 0xc1, 0xd9, 0x24, 0x77, 0x7a, 0xee, 0x1b, 0x34, 0x08, 0x45, 0x48, 0x46, 0x62, + 0x92, 0xd7, 0x34, 0x04, 0x0d, 0x2c, 0x5e, 0xa7, 0xdd, 0x0e, 0x68, 0xdb, 0x89, 0xfc, 0x80, 0xef, + 0x1c, 0x66, 0x1d, 0x0d, 0x41, 0x03, 0x6b, 0xfe, 0xe3, 0x30, 0x65, 0x0a, 0x7f, 0xa2, 0x78, 0x9e, + 0x4f, 0x80, 0x74, 0xea, 0x4c, 0x2d, 0x49, 0xd6, 0x71, 0x96, 0x24, 0xfb, 0x3f, 0x8e, 0x81, 0x61, + 0x8b, 0x7a, 0x00, 0x53, 0xdd, 0x4b, 0x4c, 0xf5, 0x11, 0xed, 0x28, 0x86, 0x65, 0x6d, 0x58, 0x74, + 0xe3, 0x6e, 0x2a, 0xba, 0xf1, 0x66, 0x6e, 0x1c, 0x0f, 0x0f, 0x6e, 0xfc, 0x81, 0x05, 0x8f, 0xc5, + 0xc8, 0x83, 0x36, 0xec, 0xa3, 0xd7, 0xed, 0x17, 0xa1, 0xe2, 0xc4, 0xd5, 0xe4, 0xc4, 0x32, 0x42, + 0xcb, 0x34, 0x08, 0x4d, 0xbc, 0x38, 0x2c, 0xa6, 0x70, 0xca, 0xb0, 0x98, 0xf1, 0xc3, 0xc3, 0x62, + 0xec, 0x1f, 0x8f, 0xc1, 0x13, 0x83, 0x5f, 0x66, 0xfa, 0x8a, 0x1f, 0xfd, 0x6d, 0x69, 0x6f, 0xf2, + 0xb1, 0x53, 0x7b, 0x93, 0x17, 0x8e, 0xeb, 0x4d, 0xae, 0x7d, 0xb8, 0xc7, 0xcf, 0xdc, 0x87, 0xbb, + 0x01, 0x97, 0x94, 0xc3, 0xe8, 0x35, 0x3f, 0x90, 0xb1, 0x21, 0x6a, 0x05, 0x29, 0xd5, 0x9f, 0x90, + 0x55, 0x2e, 0x61, 0x16, 0x12, 0x66, 0xd7, 0xb5, 0x7f, 0x50, 0x80, 0x0b, 0x71, 0xb3, 0x2f, 0xf9, + 0x5e, 0xcb, 0xe5, 0x3e, 0x47, 0x2f, 0xc3, 0x78, 0xb4, 0xd7, 0x53, 0x8d, 0xfd, 0x97, 0x95, 0x38, + 0x1b, 0x7b, 0x3d, 0xd6, 0xdb, 0x8f, 0x64, 0x54, 0xe1, 0xb7, 0x08, 0xbc, 0x12, 0x59, 0xd5, 0xb3, + 0x43, 0xf4, 0xc0, 0x0b, 0xc9, 0xd1, 0xfc, 0xde, 0x7e, 0x35, 0x23, 0xcb, 0xc3, 0x82, 0xa6, 0x94, + 0x1c, 0xf3, 0xe4, 0x2e, 0x4c, 0x77, 0x9c, 0x30, 0xba, 0xdd, 0x6b, 0x39, 0x11, 0xdd, 0x70, 0xa5, + 0x37, 0xcf, 0xc9, 0xc2, 0x69, 0xb4, 0xdb, 0xc3, 0x6a, 0x82, 0x12, 0xa6, 0x28, 0x93, 0x5d, 0x20, + 0xac, 0x64, 0x23, 0x70, 0xbc, 0x50, 0x7c, 0x15, 0xe3, 0x77, 0xf2, 0xd8, 0x28, 0x7d, 0x74, 0x5e, + 0x1d, 0xa0, 0x86, 0x19, 0x1c, 0xc8, 0xd3, 0x30, 0x11, 0x50, 0x27, 0xd4, 0xdb, 0x81, 0x9e, 0xff, + 0xc8, 0x4b, 0x51, 0x42, 0xcd, 0x09, 0x35, 0x71, 0xc4, 0x84, 0xfa, 0x43, 0x0b, 0xa6, 0xe3, 0x6e, + 0x7a, 0x00, 0xaa, 0x47, 0x37, 0xa9, 0x7a, 0x5c, 0xcf, 0x6b, 0x49, 0x1c, 0xa2, 0x6d, 0xfc, 0xc9, + 0xa4, 0xf9, 0x7d, 0x3c, 0x80, 0xe3, 0xf3, 0xa6, 0x3f, 0xbf, 0x95, 0x47, 0x54, 0x5d, 0x42, 0xdb, + 0x3b, 0xd4, 0x91, 0x9f, 0xe9, 0x3a, 0x2d, 0xa9, 0xc7, 0xc8, 0x61, 0xaf, 0x75, 0x1d, 0xa5, 0xdf, + 0x64, 0xe9, 0x3a, 0xaa, 0x0e, 0xb9, 0x0d, 0x8f, 0xf4, 0x02, 0x9f, 0xe7, 0x19, 0x58, 0xa6, 0x4e, + 0xab, 0xe3, 0x7a, 0x54, 0x99, 0x79, 0x84, 0xd7, 0xcd, 0x63, 0x07, 0xfb, 0xd5, 0x47, 0xd6, 0xb3, + 0x51, 0x70, 0x58, 0xdd, 0x64, 0xa4, 0xea, 0xf8, 0x31, 0x22, 0x55, 0x7f, 0x51, 0x1b, 0x53, 0x75, + 0x50, 0xc4, 0xa7, 0xf3, 0xea, 0xca, 0xac, 0xf0, 0x08, 0x3d, 0xa4, 0x6a, 0x92, 0x29, 0x6a, 0xf6, + 0xc3, 0x2d, 0x76, 0x13, 0xa7, 0xb4, 0xd8, 0xc5, 0x71, 0x30, 0x93, 0xef, 0x67, 0x1c, 0x4c, 0xe9, + 0x03, 0x15, 0x07, 0xf3, 0x6d, 0x0b, 0x2e, 0x38, 0x83, 0x11, 0xe8, 0xf9, 0x18, 0x8f, 0x33, 0x42, + 0xdb, 0xeb, 0x8f, 0x49, 0x21, 0xb3, 0x02, 0xfd, 0x31, 0x4b, 0x14, 0xfb, 0xdd, 0x22, 0xcc, 0xa6, + 0x95, 0xa4, 0xb3, 0x0f, 0xd5, 0xfd, 0x5b, 0x16, 0xcc, 0xaa, 0x09, 0xae, 0x6f, 0xc0, 0xc5, 0x11, + 0x63, 0x35, 0xa7, 0x75, 0x45, 0xa8, 0x7b, 0x3a, 0x83, 0xca, 0x46, 0x8a, 0x1b, 0x0e, 0xf0, 0x27, + 0x6f, 0x42, 0x45, 0xdf, 0xaa, 0x9c, 0x2a, 0x6e, 0x97, 0x87, 0x96, 0xd6, 0x62, 0x12, 0x68, 0xd2, + 0x23, 0xef, 0x5a, 0x00, 0x4d, 0xb5, 0x13, 0xe7, 0x14, 0x15, 0x95, 0xa1, 0x2d, 0xc4, 0xfa, 0xbc, + 0x2e, 0x0a, 0xd1, 0x60, 0x4c, 0x7e, 0x99, 0xdf, 0xa7, 0xe8, 0x91, 0xa0, 0x3c, 0x0f, 0x3e, 0x99, + 0xf7, 0x52, 0x14, 0xfb, 0x92, 0x68, 0x6d, 0xcf, 0x00, 0x85, 0x98, 0x10, 0xc2, 0x7e, 0x19, 0xb4, + 0xcf, 0x36, 0x5b, 0x59, 0xb9, 0xd7, 0xf6, 0xba, 0x13, 0x6d, 0xcb, 0x21, 0xa8, 0x57, 0xd6, 0x6b, + 0x0a, 0x80, 0x31, 0x8e, 0xfd, 0x59, 0x98, 0x7e, 0x35, 0x70, 0x7a, 0xdb, 0x2e, 0xbf, 0xb7, 0x60, + 0xe7, 0xe3, 0x67, 0x60, 0xd2, 0x69, 0xb5, 0xb2, 0x92, 0xfd, 0xd4, 0x44, 0x31, 0x2a, 0xf8, 0xb1, + 0x8e, 0xc2, 0xf6, 0xbf, 0xb5, 0x80, 0xc4, 0x37, 0xcd, 0xae, 0xd7, 0x5e, 0x73, 0xa2, 0xe6, 0x36, + 0x3b, 0xc2, 0x6d, 0xf3, 0xd2, 0xac, 0x23, 0xdc, 0x75, 0x0d, 0x41, 0x03, 0x8b, 0xbc, 0x0d, 0x15, + 0xf1, 0xef, 0x0d, 0x7d, 0x40, 0x1c, 0xdd, 0xf5, 0x9c, 0xef, 0x79, 0x5c, 0x26, 0x31, 0x0a, 0xaf, + 0xc7, 0x1c, 0xd0, 0x64, 0xc7, 0x9a, 0x6a, 0xc5, 0xdb, 0xea, 0xf4, 0xef, 0xb7, 0x36, 0xe3, 0xa6, + 0xea, 0x05, 0xfe, 0x96, 0xdb, 0xa1, 0xe9, 0xa6, 0x5a, 0x17, 0xc5, 0xa8, 0xe0, 0xc7, 0x6b, 0xaa, + 0x7f, 0x63, 0xc1, 0xc5, 0x95, 0x30, 0x72, 0xfd, 0x65, 0x1a, 0x46, 0x6c, 0xe7, 0x63, 0xeb, 0x63, + 0xbf, 0x73, 0x9c, 0xf0, 0x8b, 0x65, 0x98, 0x95, 0xf7, 0xd0, 0xfd, 0xcd, 0x90, 0x46, 0xc6, 0x51, + 0x43, 0xcf, 0xe3, 0xa5, 0x14, 0x1c, 0x07, 0x6a, 0x30, 0x2a, 0xf2, 0x42, 0x3a, 0xa6, 0x52, 0x48, + 0x52, 0x69, 0xa4, 0xe0, 0x38, 0x50, 0xc3, 0xfe, 0x7e, 0x01, 0x2e, 0xf0, 0xcf, 0x48, 0x85, 0x4e, + 0x7d, 0x63, 0x58, 0xe8, 0xd4, 0x88, 0x53, 0x99, 0xf3, 0x3a, 0x45, 0xe0, 0xd4, 0xdf, 0xb4, 0x60, + 0xa6, 0x95, 0x6c, 0xe9, 0x7c, 0xec, 0x72, 0x59, 0x7d, 0x28, 0x3c, 0x10, 0x53, 0x85, 0x98, 0xe6, + 0x4f, 0x7e, 0xc5, 0x82, 0x99, 0xa4, 0x98, 0x6a, 0x75, 0x3f, 0x83, 0x46, 0xd2, 0x21, 0x03, 0xc9, + 0xf2, 0x10, 0xd3, 0x22, 0xd8, 0xbf, 0x37, 0x26, 0xbb, 0xf4, 0x2c, 0xe2, 0x82, 0xc8, 0x3d, 0x28, + 0x47, 0x9d, 0x50, 0x14, 0xca, 0xaf, 0x1d, 0xf1, 0xd0, 0xba, 0xb1, 0xda, 0x10, 0x0e, 0x27, 0xb1, + 0x5e, 0x29, 0x4b, 0x98, 0x7e, 0xac, 0x78, 0x71, 0xc6, 0xcd, 0x9e, 0x64, 0x9c, 0xcb, 0x69, 0x79, + 0x63, 0x69, 0x3d, 0xcd, 0x58, 0x96, 0x30, 0xc6, 0x8a, 0x97, 0xfd, 0x1b, 0x16, 0x94, 0x6f, 0xf8, + 0x6a, 0x1d, 0xf9, 0xd9, 0x1c, 0x6c, 0x51, 0x5a, 0x65, 0xd5, 0x4a, 0x4b, 0x7c, 0x0a, 0x7a, 0x25, + 0x61, 0x89, 0x7a, 0xdc, 0xa0, 0xbd, 0xc0, 0x73, 0x1e, 0x32, 0x52, 0x37, 0xfc, 0xcd, 0xa1, 0xe6, + 0xe3, 0x5f, 0x2d, 0xc2, 0xb9, 0xd7, 0x9c, 0x3d, 0xea, 0x45, 0xce, 0xc9, 0x37, 0x89, 0x17, 0xa1, + 0xe2, 0xf4, 0xf8, 0x5d, 0xa6, 0x71, 0x0c, 0x89, 0x8d, 0x3b, 0x31, 0x08, 0x4d, 0xbc, 0x78, 0x41, + 0x13, 0x41, 0x3a, 0x59, 0x4b, 0xd1, 0x52, 0x0a, 0x8e, 0x03, 0x35, 0xc8, 0x0d, 0x20, 0x32, 0xb0, + 0xbd, 0xd6, 0x6c, 0xfa, 0x7d, 0x4f, 0x2c, 0x69, 0xc2, 0xee, 0xa3, 0xcf, 0xc3, 0x6b, 0x03, 0x18, + 0x98, 0x51, 0x8b, 0x7c, 0x06, 0xe6, 0x9a, 0x9c, 0xb2, 0x3c, 0x1d, 0x99, 0x14, 0xc5, 0x09, 0x59, + 0x87, 0xbd, 0x2c, 0x0d, 0xc1, 0xc3, 0xa1, 0x14, 0x98, 0xa4, 0x61, 0xe4, 0x07, 0x4e, 0x9b, 0x9a, + 0x74, 0x27, 0x92, 0x92, 0x36, 0x06, 0x30, 0x30, 0xa3, 0x16, 0xf9, 0x02, 0x94, 0xa3, 0xed, 0x80, + 0x86, 0xdb, 0x7e, 0xa7, 0x25, 0x7d, 0x4f, 0x46, 0x34, 0x06, 0xca, 0xde, 0xdf, 0x50, 0x54, 0x8d, + 0xe1, 0xad, 0x8a, 0x30, 0xe6, 0x49, 0x02, 0x98, 0x08, 0x9b, 0x7e, 0x8f, 0x86, 0xf2, 0x54, 0x71, + 0x23, 0x17, 0xee, 0xdc, 0xb8, 0x65, 0x98, 0x21, 0x39, 0x07, 0x94, 0x9c, 0xec, 0xdf, 0x19, 0x83, + 0x29, 0x13, 0xf1, 0x18, 0x6b, 0xd3, 0x97, 0x2d, 0x98, 0x6a, 0xfa, 0x5e, 0x14, 0xf8, 0x9d, 0x38, + 0x61, 0xc3, 0xe8, 0x1a, 0x05, 0x23, 0xb5, 0x4c, 0x23, 0xc7, 0xed, 0x18, 0xd6, 0x3a, 0x83, 0x0d, + 0x26, 0x98, 0x92, 0xaf, 0x5b, 0x30, 0x13, 0x3b, 0x46, 0xc6, 0xb6, 0xbe, 0x5c, 0x05, 0xd1, 0x4b, + 0xfd, 0xd5, 0x24, 0x27, 0x4c, 0xb3, 0xb6, 0x37, 0x61, 0x36, 0xdd, 0xdb, 0xac, 0x29, 0x7b, 0x8e, + 0x9c, 0xeb, 0x85, 0xb8, 0x29, 0xd7, 0x9d, 0x30, 0x44, 0x0e, 0x21, 0xcf, 0x42, 0xa9, 0xeb, 0x04, + 0x6d, 0xd7, 0x73, 0x3a, 0xbc, 0x15, 0x0b, 0xc6, 0x82, 0x24, 0xcb, 0x51, 0x63, 0xd8, 0x1f, 0x81, + 0xa9, 0x35, 0xc7, 0x6b, 0xd3, 0x96, 0x5c, 0x87, 0x8f, 0x8e, 0x4c, 0xfd, 0xe3, 0x71, 0xa8, 0x18, + 0xc7, 0xc7, 0xb3, 0x3f, 0x67, 0x25, 0x12, 0x11, 0x15, 0x72, 0x4c, 0x44, 0xf4, 0x29, 0x80, 0x2d, + 0xd7, 0x73, 0xc3, 0xed, 0x53, 0xa6, 0x38, 0xe2, 0x77, 0xf3, 0xd7, 0x34, 0x05, 0x34, 0xa8, 0xc5, + 0x17, 0xa0, 0xc5, 0x43, 0xb2, 0x05, 0xbe, 0x6b, 0x19, 0xdb, 0xcd, 0x44, 0x1e, 0x0e, 0x1f, 0x46, + 0xc7, 0x2c, 0xa8, 0xed, 0x47, 0xdc, 0x4d, 0x1d, 0xb6, 0x2b, 0x6d, 0x40, 0x29, 0xa0, 0x61, 0xbf, + 0x4b, 0x4f, 0x95, 0x8c, 0x88, 0xbb, 0xde, 0xa0, 0xac, 0x8f, 0x9a, 0xd2, 0xfc, 0xcb, 0x70, 0x2e, + 0x21, 0xc2, 0x89, 0x6e, 0x98, 0x7c, 0xc8, 0xb4, 0x51, 0x9c, 0xe6, 0xbe, 0x89, 0xf5, 0x45, 0xc7, + 0x48, 0x42, 0xa4, 0xfb, 0x42, 0x38, 0x58, 0x09, 0x98, 0xfd, 0xe3, 0x09, 0x90, 0x3e, 0x0c, 0xc7, + 0x58, 0xae, 0xcc, 0x9b, 0xcb, 0xb1, 0x53, 0xdc, 0x5c, 0xde, 0x80, 0x29, 0xd7, 0x73, 0x23, 0xd7, + 0xe9, 0x70, 0xfb, 0x93, 0xdc, 0x4e, 0x95, 0x33, 0xfe, 0xd4, 0x8a, 0x01, 0xcb, 0xa0, 0x93, 0xa8, + 0x4b, 0x5e, 0x87, 0x22, 0xdf, 0x6f, 0xe4, 0x00, 0x3e, 0xb9, 0xa3, 0x05, 0xf7, 0xb1, 0x11, 0x11, + 0x7a, 0x82, 0x12, 0x3f, 0x7c, 0x88, 0x2c, 0x4c, 0xfa, 0xf8, 0x2d, 0xc7, 0x71, 0x7c, 0xf8, 0x48, + 0xc1, 0x71, 0xa0, 0x06, 0xa3, 0xb2, 0xe5, 0xb8, 0x9d, 0x7e, 0x40, 0x63, 0x2a, 0x13, 0x49, 0x2a, + 0xd7, 0x52, 0x70, 0x1c, 0xa8, 0x41, 0xb6, 0x60, 0x4a, 0x96, 0x09, 0xb7, 0xb9, 0xc9, 0x53, 0x7e, + 0x25, 0x77, 0x8f, 0xbc, 0x66, 0x50, 0xc2, 0x04, 0x5d, 0xd2, 0x87, 0xf3, 0xae, 0xd7, 0xf4, 0xbd, + 0x66, 0xa7, 0x1f, 0xba, 0xbb, 0x34, 0x0e, 0x8f, 0x3b, 0x0d, 0xb3, 0x4b, 0x07, 0xfb, 0xd5, 0xf3, + 0x2b, 0x69, 0x72, 0x38, 0xc8, 0x81, 0x7c, 0xd1, 0x82, 0x4b, 0x4d, 0xdf, 0x0b, 0x79, 0x16, 0x8f, + 0x5d, 0x7a, 0x35, 0x08, 0xfc, 0x40, 0xf0, 0x2e, 0x9f, 0x92, 0x37, 0x37, 0x7b, 0x2e, 0x65, 0x91, + 0xc4, 0x6c, 0x4e, 0xe4, 0x2d, 0x28, 0xf5, 0x02, 0x7f, 0xd7, 0x6d, 0xd1, 0x40, 0xba, 0x60, 0xae, + 0xe6, 0x91, 0xda, 0x68, 0x5d, 0xd2, 0x8c, 0x97, 0x1e, 0x55, 0x82, 0x9a, 0x9f, 0xfd, 0x7f, 0x2a, + 0x30, 0x9d, 0x44, 0x27, 0x3f, 0x0f, 0xd0, 0x0b, 0xfc, 0x2e, 0x8d, 0xb6, 0xa9, 0x0e, 0x73, 0xba, + 0x39, 0x6a, 0xf2, 0x1a, 0x45, 0x4f, 0xb9, 0x2d, 0xb1, 0xe5, 0x22, 0x2e, 0x45, 0x83, 0x23, 0x09, + 0x60, 0x72, 0x47, 0x6c, 0xbb, 0x52, 0x0b, 0x79, 0x2d, 0x17, 0x9d, 0x49, 0x72, 0xe6, 0xf1, 0x39, + 0xb2, 0x08, 0x15, 0x23, 0xb2, 0x09, 0x85, 0x7b, 0x74, 0x33, 0x9f, 0xcc, 0x09, 0x77, 0xa8, 0x3c, + 0xcd, 0xd4, 0x27, 0x0f, 0xf6, 0xab, 0x85, 0x3b, 0x74, 0x13, 0x19, 0x71, 0xf6, 0x5d, 0x2d, 0xe1, + 0xbb, 0x20, 0x97, 0x8a, 0xd7, 0x72, 0x74, 0x84, 0x10, 0xdf, 0x25, 0x8b, 0x50, 0x31, 0x22, 0x6f, + 0x41, 0xf9, 0x9e, 0xb3, 0x4b, 0xb7, 0x02, 0xdf, 0x8b, 0xa4, 0xaf, 0xdc, 0x88, 0xc1, 0x25, 0x77, + 0x14, 0x39, 0xc9, 0x97, 0x6f, 0xef, 0xba, 0x10, 0x63, 0x76, 0x64, 0x17, 0x4a, 0x1e, 0xbd, 0x87, + 0xb4, 0xe3, 0x36, 0xf3, 0x09, 0xe6, 0xb8, 0x29, 0xa9, 0x49, 0xce, 0x7c, 0xdf, 0x53, 0x65, 0xa8, + 0x79, 0xb1, 0xbe, 0xbc, 0xeb, 0x6f, 0xca, 0x85, 0x6a, 0xc4, 0xbe, 0xd4, 0x27, 0x53, 0xd1, 0x97, + 0x37, 0xfc, 0x4d, 0x64, 0xc4, 0xd9, 0x1c, 0x69, 0x6a, 0x47, 0x2d, 0xb9, 0x4c, 0xdd, 0xcc, 0xd7, + 0x41, 0x4d, 0xcc, 0x91, 0xb8, 0x14, 0x0d, 0x8e, 0xac, 0x6d, 0xdb, 0xd2, 0x58, 0x29, 0x17, 0xaa, + 0x11, 0xdb, 0x36, 0x69, 0xfa, 0x14, 0x6d, 0xab, 0xca, 0x50, 0xf3, 0x62, 0x7c, 0x5d, 0x69, 0xf9, + 0xcb, 0x67, 0xa9, 0x4a, 0xda, 0x11, 0x05, 0x5f, 0x55, 0x86, 0x9a, 0x17, 0x6b, 0xef, 0x70, 0x67, + 0xef, 0x9e, 0xd3, 0xd9, 0x71, 0xbd, 0xb6, 0x0c, 0xdb, 0x1d, 0x35, 0xcc, 0x6d, 0x67, 0xef, 0x8e, + 0xa0, 0x67, 0xb6, 0x77, 0x5c, 0x8a, 0x06, 0x47, 0xf2, 0xf7, 0x2d, 0x1d, 0x8a, 0x33, 0x95, 0x87, + 0x13, 0x53, 0x72, 0xc9, 0x95, 0x91, 0x39, 0x42, 0x51, 0xfc, 0x29, 0xed, 0x77, 0xc9, 0x0b, 0xbf, + 0xf6, 0x47, 0xd5, 0x39, 0xea, 0x35, 0xfd, 0x96, 0xeb, 0xb5, 0x17, 0xef, 0x86, 0xbe, 0xb7, 0x80, + 0xce, 0x3d, 0xa5, 0xa3, 0x4b, 0x99, 0xe6, 0x3f, 0x06, 0x15, 0x83, 0xc4, 0x51, 0x8a, 0xde, 0x94, + 0xa9, 0xe8, 0xfd, 0xc6, 0x04, 0x4c, 0x99, 0x79, 0x48, 0x8f, 0xa1, 0x7d, 0xe9, 0x13, 0xc7, 0xd8, + 0x49, 0x4e, 0x1c, 0xec, 0x88, 0x69, 0x5c, 0x70, 0x29, 0xf3, 0xd6, 0x4a, 0x6e, 0x0a, 0x77, 0x7c, + 0xc4, 0x34, 0x0a, 0x43, 0x4c, 0x30, 0x3d, 0x81, 0xcf, 0x0b, 0x53, 0x5b, 0x85, 0x62, 0x57, 0x4c, + 0xaa, 0xad, 0x09, 0x55, 0xed, 0x39, 0x80, 0x38, 0x61, 0xa6, 0xbc, 0xf8, 0xd4, 0xfa, 0xb0, 0x91, + 0xc8, 0xd3, 0xc0, 0x22, 0x4f, 0xc3, 0x04, 0x53, 0x7d, 0x68, 0x4b, 0x66, 0x15, 0xd0, 0xe7, 0xf8, + 0x6b, 0xbc, 0x14, 0x25, 0x94, 0xbc, 0xc4, 0xb4, 0xd4, 0x58, 0x61, 0x91, 0xc9, 0x02, 0x2e, 0xc6, + 0x5a, 0x6a, 0x0c, 0xc3, 0x04, 0x26, 0x13, 0x9d, 0x32, 0xfd, 0x82, 0xaf, 0x0d, 0x86, 0xe8, 0x5c, + 0xe9, 0x40, 0x01, 0xe3, 0x76, 0xa5, 0x94, 0x3e, 0xc2, 0xe7, 0x74, 0xd1, 0xb0, 0x2b, 0xa5, 0xe0, + 0x38, 0x50, 0x83, 0x7d, 0x8c, 0xbc, 0xb3, 0xad, 0x08, 0x87, 0xe9, 0x21, 0xb7, 0xad, 0x5f, 0x31, + 0xcf, 0x5a, 0x39, 0xce, 0x21, 0x31, 0x6a, 0x8f, 0x7f, 0xd8, 0x1a, 0xed, 0x58, 0xf4, 0x59, 0x98, + 0x4e, 0xee, 0x42, 0xb9, 0xdf, 0x7c, 0x7c, 0x75, 0x1c, 0x2e, 0xdc, 0x6c, 0xbb, 0x5e, 0x3a, 0xe7, + 0x5b, 0xd6, 0x03, 0x0f, 0xd6, 0x89, 0x1f, 0x78, 0xd0, 0x31, 0x79, 0xf2, 0xf9, 0x84, 0xec, 0x98, + 0x3c, 0xf5, 0x96, 0x45, 0x12, 0x97, 0xfc, 0xa1, 0x05, 0x8f, 0x3b, 0x2d, 0x71, 0x2e, 0x70, 0x3a, + 0xb2, 0xd4, 0xc8, 0x4b, 0x2e, 0x67, 0x74, 0x38, 0xe2, 0x2e, 0x3f, 0xf8, 0xf1, 0x0b, 0xb5, 0x43, + 0xb8, 0x8a, 0x1e, 0xff, 0x49, 0xf9, 0x05, 0x8f, 0x1f, 0x86, 0x8a, 0x87, 0x8a, 0x4f, 0xfe, 0x2a, + 0xcc, 0x24, 0x3e, 0x58, 0x5a, 0xc2, 0xcb, 0xe2, 0xc2, 0xa2, 0x91, 0x04, 0x61, 0x1a, 0x77, 0xfe, + 0x16, 0xfc, 0xc4, 0x91, 0x72, 0x9e, 0x68, 0xb0, 0x7d, 0xcf, 0x82, 0x29, 0x33, 0x3d, 0x13, 0x79, + 0x16, 0x4a, 0x91, 0xbf, 0x43, 0xbd, 0xdb, 0x81, 0x72, 0xd8, 0xd5, 0x03, 0x7d, 0x83, 0x97, 0xe3, + 0x2a, 0x6a, 0x0c, 0x86, 0xdd, 0xec, 0xb8, 0xd4, 0x8b, 0x56, 0x5a, 0xb2, 0x9b, 0x35, 0xf6, 0x92, + 0x28, 0x5f, 0x46, 0x8d, 0x21, 0x7c, 0xec, 0xd8, 0xef, 0x06, 0x6d, 0x06, 0x54, 0xb9, 0xf7, 0x1b, + 0x3e, 0x76, 0x31, 0x0c, 0x13, 0x98, 0xc4, 0xd6, 0x26, 0xce, 0xf1, 0xf8, 0x5e, 0x23, 0x65, 0x92, + 0xfc, 0x8e, 0x05, 0x65, 0x61, 0xa2, 0x47, 0xba, 0x95, 0x72, 0xb1, 0x4d, 0x19, 0x11, 0x6a, 0xeb, + 0x2b, 0x59, 0x2e, 0xb6, 0x4f, 0xc2, 0xf8, 0x8e, 0xeb, 0xa9, 0x2f, 0xd1, 0xdb, 0xd2, 0x6b, 0xae, + 0xd7, 0x42, 0x0e, 0xd1, 0x1b, 0x57, 0x61, 0xe8, 0xc6, 0xb5, 0x08, 0x65, 0xed, 0x78, 0x22, 0x97, + 0x7f, 0x6d, 0xbd, 0xd5, 0x8e, 0x2a, 0x18, 0xe3, 0xd8, 0xbf, 0x66, 0xc1, 0x34, 0x8f, 0x18, 0x8f, + 0xcf, 0xc3, 0x2f, 0x6a, 0x5f, 0x30, 0x21, 0xf7, 0x13, 0x49, 0x5f, 0xb0, 0xf7, 0xf6, 0xab, 0x15, + 0x11, 0x63, 0x9e, 0x74, 0x0d, 0xfb, 0xb4, 0x34, 0xa2, 0x71, 0x8f, 0xb5, 0xb1, 0x13, 0xdb, 0x78, + 0x62, 0x31, 0x15, 0x11, 0x8c, 0xe9, 0xd9, 0x6f, 0xc3, 0x94, 0x19, 0x8c, 0x45, 0x5e, 0x84, 0x4a, + 0xcf, 0xf5, 0xda, 0xc9, 0xa0, 0x5d, 0x7d, 0xd1, 0xb0, 0x1e, 0x83, 0xd0, 0xc4, 0xe3, 0xd5, 0xfc, + 0xb8, 0x5a, 0xea, 0x7e, 0x62, 0xdd, 0x37, 0xab, 0xc5, 0x7f, 0x6c, 0x0f, 0x20, 0x8e, 0x2c, 0x3e, + 0x96, 0xf1, 0x66, 0x42, 0xd8, 0xfe, 0x85, 0x32, 0xc2, 0xb3, 0x44, 0x4c, 0x88, 0x11, 0xfe, 0xde, + 0xfe, 0x61, 0xca, 0x8e, 0xa8, 0xc5, 0xdf, 0xa0, 0xc8, 0x08, 0x32, 0xcc, 0xfd, 0x0d, 0x8a, 0x0c, + 0x1e, 0xef, 0xdf, 0x1b, 0x14, 0x59, 0xc2, 0xfc, 0xf9, 0x7a, 0x83, 0xe2, 0x93, 0x70, 0xd2, 0x74, + 0xb4, 0x4c, 0xb7, 0xb8, 0x67, 0xa6, 0x8d, 0xd0, 0x2d, 0x2e, 0xf3, 0x46, 0x48, 0xa8, 0xfd, 0xdb, + 0x05, 0x98, 0x4d, 0x9b, 0x18, 0xf2, 0xf6, 0xde, 0x20, 0x5f, 0xb7, 0x60, 0xda, 0x49, 0xa4, 0xfe, + 0xcb, 0xe9, 0x41, 0xab, 0x04, 0x4d, 0x23, 0xf5, 0x5c, 0xa2, 0x1c, 0x53, 0xbc, 0xc9, 0x5f, 0x82, + 0xc9, 0xc8, 0xed, 0x52, 0xbf, 0x2f, 0x0c, 0x8f, 0x05, 0x61, 0x00, 0xd8, 0x10, 0x45, 0xa8, 0x60, + 0x6c, 0x13, 0x70, 0xb9, 0xc6, 0x16, 0x50, 0xe9, 0x89, 0x3c, 0x1b, 0x5b, 0x4a, 0x45, 0x39, 0x6a, + 0x0c, 0x72, 0x1f, 0x26, 0x85, 0x9f, 0x87, 0x72, 0xe8, 0x59, 0xcb, 0xc9, 0x14, 0x22, 0x5c, 0x49, + 0xe2, 0x2e, 0x10, 0xff, 0x43, 0x54, 0xec, 0xec, 0x8f, 0xc0, 0x09, 0xf3, 0xf3, 0xda, 0x57, 0x81, + 0xa0, 0xdf, 0xe9, 0x6c, 0x3a, 0xcd, 0x9d, 0x3b, 0xae, 0xd7, 0xf2, 0xef, 0xf1, 0xa5, 0x6f, 0x11, + 0xca, 0x81, 0x0c, 0xd1, 0x0d, 0xe5, 0xa8, 0xd1, 0x6b, 0xa7, 0x8a, 0xdd, 0x0d, 0x31, 0xc6, 0xb1, + 0x7f, 0x6f, 0x0c, 0x26, 0x65, 0x3c, 0xf9, 0x03, 0x88, 0x84, 0xd8, 0x49, 0xdc, 0x3f, 0xaf, 0xe4, + 0x12, 0x06, 0x3f, 0x34, 0x0c, 0x22, 0x4c, 0x85, 0x41, 0xbc, 0x96, 0x0f, 0xbb, 0xc3, 0x63, 0x20, + 0xbe, 0x5b, 0x84, 0x99, 0x54, 0x7c, 0x7e, 0x2a, 0x95, 0xb7, 0xf5, 0xbe, 0xa4, 0xf2, 0x26, 0x61, + 0x22, 0x9d, 0x7b, 0x7e, 0x7e, 0x93, 0x7f, 0x91, 0xd9, 0x3d, 0x2f, 0x8f, 0xd6, 0xe2, 0x07, 0xc7, + 0xa3, 0xf5, 0xbf, 0x5a, 0xf0, 0xe8, 0xd0, 0x2c, 0x13, 0x3c, 0x5f, 0x5b, 0x90, 0x84, 0xca, 0xf5, + 0x22, 0xe7, 0xcc, 0x3d, 0xfa, 0xae, 0x3a, 0x9d, 0x62, 0x2b, 0xcd, 0x9e, 0xbc, 0x00, 0x53, 0x5c, + 0x1f, 0x64, 0x2b, 0x67, 0x44, 0x7b, 0xf2, 0xaa, 0x8d, 0x5f, 0xba, 0x34, 0x8c, 0x72, 0x4c, 0x60, + 0xd9, 0xdf, 0xb6, 0x60, 0x6e, 0x58, 0xf6, 0xae, 0x63, 0x68, 0x72, 0x7f, 0x25, 0x15, 0x49, 0x52, + 0x1d, 0x88, 0x24, 0x49, 0x99, 0x82, 0x54, 0xd0, 0x88, 0x61, 0x85, 0x29, 0x1c, 0x11, 0x28, 0xf1, + 0xfb, 0x05, 0x98, 0x95, 0x22, 0xc6, 0x4a, 0xf8, 0x4b, 0x89, 0xf8, 0x97, 0x9f, 0x4c, 0xc5, 0xbf, + 0x5c, 0x4c, 0xe3, 0xff, 0x45, 0xf0, 0xcb, 0x07, 0x2b, 0xf8, 0xe5, 0x6b, 0x45, 0xb8, 0x94, 0x99, + 0x27, 0x8b, 0x7c, 0x35, 0x63, 0xa7, 0xb8, 0x93, 0x73, 0x42, 0x2e, 0x1d, 0x27, 0x7b, 0xb6, 0x11, + 0x23, 0xbf, 0x62, 0x46, 0x6a, 0x88, 0xd5, 0x7f, 0xeb, 0x0c, 0x52, 0x8b, 0x9d, 0x34, 0x68, 0xe3, + 0xc1, 0x3e, 0x75, 0xf6, 0xe7, 0x60, 0xa9, 0xff, 0x5a, 0x01, 0xae, 0x1c, 0xb7, 0x65, 0x3f, 0xa0, + 0x51, 0x8e, 0x61, 0x22, 0xca, 0xf1, 0x01, 0xa9, 0x36, 0x67, 0x12, 0xf0, 0xf8, 0x0f, 0xc7, 0xf5, + 0xbe, 0x3b, 0x38, 0x61, 0x8f, 0x65, 0x5b, 0x98, 0x64, 0xaa, 0xaf, 0x4a, 0x08, 0x1f, 0xef, 0x0d, + 0x93, 0x0d, 0x51, 0xfc, 0xde, 0x7e, 0xf5, 0x7c, 0x9c, 0x50, 0x46, 0x16, 0xa2, 0xaa, 0x44, 0xae, + 0x40, 0x29, 0x10, 0x50, 0x15, 0xd7, 0x25, 0xbd, 0x6b, 0x44, 0x19, 0x6a, 0x28, 0xf9, 0x82, 0x71, + 0x56, 0x18, 0x3f, 0xab, 0xbc, 0x49, 0x87, 0x39, 0x0d, 0xbd, 0x09, 0xa5, 0x50, 0x65, 0x2d, 0x17, + 0xd3, 0xe9, 0xf9, 0x63, 0x86, 0x0b, 0x3a, 0x9b, 0xb4, 0xa3, 0x52, 0x98, 0x8b, 0xef, 0xd3, 0x09, + 0xce, 0x35, 0x49, 0x62, 0xeb, 0xb3, 0xb7, 0xb8, 0xd4, 0x80, 0xc1, 0x73, 0x37, 0x89, 0x60, 0x52, + 0x3e, 0x5d, 0x2c, 0x6f, 0x5b, 0xd7, 0x72, 0x8a, 0xbb, 0x91, 0x5e, 0xd9, 0xfc, 0x48, 0xab, 0x6c, + 0x4e, 0x8a, 0x95, 0xfd, 0x03, 0x0b, 0x2a, 0x72, 0x8c, 0x3c, 0x80, 0xb8, 0xc9, 0xbb, 0xc9, 0xb8, + 0xc9, 0xab, 0xb9, 0x2c, 0xe1, 0x43, 0x82, 0x26, 0xef, 0xc2, 0x94, 0x99, 0xb1, 0x92, 0x7c, 0xca, + 0xd8, 0x82, 0xac, 0x51, 0xb2, 0xb2, 0xa9, 0x4d, 0x2a, 0xde, 0x9e, 0xec, 0x7f, 0x5a, 0xd6, 0xad, + 0xc8, 0x0f, 0xce, 0xe6, 0xc8, 0xb7, 0x0e, 0x1d, 0xf9, 0xe6, 0xc0, 0x1b, 0xcb, 0x7f, 0xe0, 0xbd, + 0x0e, 0x25, 0xb5, 0x2c, 0x4a, 0x6d, 0xea, 0x29, 0xd3, 0x4d, 0x9b, 0xa9, 0x64, 0x8c, 0x98, 0x31, + 0x5d, 0xf8, 0x01, 0x38, 0xb6, 0x84, 0xab, 0xe5, 0x5a, 0x93, 0x21, 0x6f, 0x41, 0xe5, 0x9e, 0x1f, + 0xec, 0x74, 0x7c, 0x87, 0x3f, 0x15, 0x01, 0x79, 0x78, 0x06, 0x68, 0x6b, 0xb6, 0x88, 0x95, 0xb9, + 0x13, 0xd3, 0x47, 0x93, 0x19, 0xa9, 0xc1, 0x4c, 0xd7, 0xf5, 0x90, 0x3a, 0x2d, 0x1d, 0x1e, 0x39, + 0x2e, 0xd2, 0xb4, 0x2b, 0xdd, 0x7e, 0x2d, 0x09, 0xc6, 0x34, 0x3e, 0xb7, 0x3c, 0x05, 0x09, 0x53, + 0x87, 0xcc, 0xc5, 0xbc, 0x3e, 0xfa, 0x60, 0x4c, 0x9a, 0x4f, 0x44, 0xb0, 0x48, 0xb2, 0x1c, 0x53, + 0xbc, 0xc9, 0xe7, 0xa1, 0x14, 0xaa, 0x47, 0x41, 0x8b, 0x39, 0x9e, 0x7a, 0xf4, 0xc3, 0xa0, 0xba, + 0x2b, 0xf5, 0xcb, 0xa0, 0x9a, 0x21, 0x59, 0x85, 0x8b, 0xca, 0x76, 0x93, 0x78, 0xdf, 0x70, 0x22, + 0xce, 0x27, 0x86, 0x19, 0x70, 0xcc, 0xac, 0xc5, 0x74, 0x5b, 0x9e, 0x09, 0x56, 0xdc, 0xc4, 0x1a, + 0x97, 0x97, 0x7c, 0xfe, 0xb5, 0x50, 0x42, 0x0f, 0x8b, 0xfe, 0x2d, 0x8d, 0x10, 0xfd, 0xdb, 0x80, + 0x4b, 0x69, 0x10, 0x4f, 0x14, 0xc7, 0x73, 0xd3, 0x19, 0x5b, 0xe8, 0x7a, 0x16, 0x12, 0x66, 0xd7, + 0x25, 0x77, 0xa0, 0x1c, 0x50, 0x7e, 0xca, 0xab, 0x29, 0x27, 0xb6, 0x13, 0xbb, 0xeb, 0xa2, 0x22, + 0x80, 0x31, 0x2d, 0xd6, 0xef, 0x4e, 0x32, 0x71, 0xfa, 0xeb, 0x39, 0xbe, 0x1a, 0x2e, 0xfb, 0x7e, + 0x48, 0x02, 0x47, 0xfb, 0xdf, 0xcd, 0xc0, 0xb9, 0x84, 0x01, 0x8a, 0x3c, 0x05, 0x45, 0x9e, 0x39, + 0x8f, 0xaf, 0x56, 0xa5, 0x78, 0x45, 0x15, 0x8d, 0x23, 0x60, 0xe4, 0x97, 0x2c, 0x98, 0xe9, 0x25, + 0x2e, 0x70, 0xd4, 0x42, 0x3e, 0xa2, 0xd5, 0x36, 0x79, 0x2b, 0x64, 0x3c, 0x39, 0x92, 0x64, 0x86, + 0x69, 0xee, 0x6c, 0x3d, 0x90, 0x3e, 0xef, 0x1d, 0x1a, 0x70, 0x6c, 0xa9, 0xe8, 0x69, 0x12, 0x4b, + 0x49, 0x30, 0xa6, 0xf1, 0x59, 0x0f, 0xf3, 0xaf, 0x1b, 0xe5, 0x65, 0xd8, 0x9a, 0x22, 0x80, 0x31, + 0x2d, 0xf2, 0x0a, 0x4c, 0xcb, 0x7c, 0xd9, 0xeb, 0x7e, 0xeb, 0xba, 0x13, 0x6e, 0xcb, 0x23, 0x9f, + 0x3e, 0xa2, 0x2e, 0x25, 0xa0, 0x98, 0xc2, 0xe6, 0xdf, 0x16, 0x27, 0x25, 0xe7, 0x04, 0x26, 0x92, + 0x2f, 0xb2, 0x2c, 0x25, 0xc1, 0x98, 0xc6, 0x27, 0xcf, 0x1a, 0xdb, 0x90, 0xf0, 0x8e, 0xd0, 0xab, + 0x41, 0xc6, 0x56, 0x54, 0x83, 0x99, 0x3e, 0x3f, 0x21, 0xb7, 0x14, 0x50, 0xce, 0x47, 0xcd, 0xf0, + 0x76, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0x32, 0x9c, 0x0b, 0xd8, 0x62, 0xab, 0x09, 0x08, 0x97, 0x09, + 0x7d, 0x23, 0x8e, 0x26, 0x10, 0x93, 0xb8, 0xe4, 0x55, 0x38, 0x1f, 0xe7, 0x54, 0x55, 0x04, 0x84, + 0x0f, 0x85, 0x4e, 0xf0, 0x57, 0x4b, 0x23, 0xe0, 0x60, 0x1d, 0xf2, 0xd7, 0x61, 0xd6, 0x68, 0x89, + 0x15, 0xaf, 0x45, 0xef, 0xcb, 0xbc, 0x97, 0xfc, 0x85, 0xb1, 0xa5, 0x14, 0x0c, 0x07, 0xb0, 0xc9, + 0xc7, 0x61, 0xba, 0xe9, 0x77, 0x3a, 0x7c, 0x8d, 0x13, 0xaf, 0x81, 0x88, 0x04, 0x97, 0x22, 0x15, + 0x68, 0x02, 0x82, 0x29, 0x4c, 0x72, 0x03, 0x88, 0xbf, 0xc9, 0xd4, 0x2b, 0xda, 0x7a, 0x95, 0x7a, + 0x54, 0x6a, 0x1c, 0xe7, 0x92, 0x11, 0x37, 0xb7, 0x06, 0x30, 0x30, 0xa3, 0x16, 0xcf, 0x0f, 0x68, + 0x44, 0x28, 0x4f, 0xe7, 0x91, 0x91, 0x3c, 0x6d, 0xcf, 0x39, 0x32, 0x3c, 0x39, 0x80, 0x09, 0x11, + 0x00, 0x95, 0x4f, 0xa6, 0x4b, 0xf3, 0x61, 0x80, 0x78, 0x8f, 0x10, 0xa5, 0x28, 0x39, 0x91, 0x9f, + 0x87, 0xf2, 0xa6, 0x7a, 0x25, 0x86, 0xa7, 0xb7, 0x1c, 0x79, 0x5f, 0x4c, 0x3d, 0x78, 0x14, 0xdb, + 0x2b, 0x34, 0x00, 0x63, 0x96, 0xe4, 0x69, 0xa8, 0x5c, 0x5f, 0xaf, 0xe9, 0x51, 0x78, 0x9e, 0xf7, + 0xfe, 0x38, 0xab, 0x82, 0x26, 0x80, 0xcd, 0x30, 0xad, 0xbe, 0x91, 0xa4, 0x5b, 0x40, 0x86, 0x36, + 0xc6, 0xb0, 0xb9, 0x9f, 0x03, 0x36, 0xe6, 0x2e, 0xa4, 0xb0, 0x65, 0x39, 0x6a, 0x0c, 0xf2, 0x26, + 0x54, 0xe4, 0x7e, 0xc1, 0xd7, 0xa6, 0x8b, 0xa7, 0x8b, 0x7e, 0xc7, 0x98, 0x04, 0x9a, 0xf4, 0xf8, + 0x05, 0x35, 0x7f, 0x3c, 0x83, 0x5e, 0xeb, 0x77, 0x3a, 0x73, 0x97, 0xf8, 0xba, 0x19, 0x5f, 0x50, + 0xc7, 0x20, 0x34, 0xf1, 0xc8, 0xf3, 0xca, 0x5f, 0xed, 0xe1, 0xc4, 0x8d, 0xbd, 0xf6, 0x57, 0xd3, + 0x4a, 0xf7, 0x90, 0x00, 0x99, 0x47, 0x8e, 0x70, 0x14, 0xdb, 0x84, 0x79, 0xa5, 0xf1, 0x0d, 0x4e, + 0x92, 0xb9, 0xb9, 0x84, 0xed, 0x68, 0xfe, 0xce, 0x50, 0x4c, 0x3c, 0x84, 0x0a, 0xd9, 0x84, 0x82, + 0xd3, 0xd9, 0x9c, 0x7b, 0x34, 0x0f, 0xd5, 0xb5, 0xb6, 0x5a, 0x97, 0x23, 0x8a, 0x3b, 0xb5, 0xd6, + 0x56, 0xeb, 0xc8, 0x88, 0x13, 0x17, 0xc6, 0x9d, 0xce, 0x66, 0x38, 0x37, 0xcf, 0xe7, 0x6c, 0x6e, + 0x4c, 0x62, 0xe3, 0xc1, 0x6a, 0x3d, 0x44, 0xce, 0xc2, 0xfe, 0xe2, 0x98, 0xbe, 0x25, 0xd2, 0xc9, + 0xc6, 0xdf, 0x36, 0x27, 0x90, 0x38, 0xee, 0xdc, 0xca, 0x6d, 0x02, 0x49, 0xf5, 0xe2, 0xdc, 0xd0, + 0xe9, 0xd3, 0xd3, 0x4b, 0x46, 0x2e, 0x59, 0xca, 0x92, 0x89, 0xd4, 0xc5, 0xe9, 0x39, 0xb9, 0x60, + 0xd8, 0x5f, 0xaa, 0x68, 0x2b, 0x68, 0xca, 0xd7, 0x2b, 0x80, 0xa2, 0x1b, 0x46, 0xae, 0x9f, 0x63, + 0x50, 0x78, 0x2a, 0x03, 0x39, 0x8f, 0x39, 0xe1, 0x00, 0x14, 0xac, 0x18, 0x4f, 0xaf, 0xed, 0x7a, + 0xf7, 0xe5, 0xe7, 0xbf, 0x9e, 0xbb, 0x13, 0x97, 0xe0, 0xc9, 0x01, 0x28, 0x58, 0x91, 0xbb, 0x62, + 0x50, 0x17, 0xf2, 0xe8, 0xeb, 0xda, 0x6a, 0x3d, 0xc5, 0x2f, 0x39, 0xb8, 0xef, 0x42, 0x21, 0xec, + 0xba, 0x52, 0x5d, 0x1a, 0x91, 0x57, 0x63, 0x6d, 0x25, 0x8b, 0x57, 0x63, 0x6d, 0x05, 0x19, 0x13, + 0xf2, 0x15, 0x0b, 0xc0, 0xe9, 0x6e, 0x3a, 0x61, 0xe8, 0xb4, 0xb4, 0x75, 0x66, 0xc4, 0x47, 0x56, + 0x6a, 0x9a, 0x5e, 0x8a, 0x35, 0x77, 0x5b, 0x8e, 0xa1, 0x68, 0x70, 0x26, 0x6f, 0xc1, 0xa4, 0x23, + 0x5e, 0xb1, 0x94, 0x1e, 0xf8, 0xf9, 0x3c, 0xcd, 0x9a, 0x92, 0x80, 0x9b, 0x69, 0x24, 0x08, 0x15, + 0x43, 0xc6, 0x3b, 0x0a, 0x1c, 0xba, 0xe5, 0xee, 0x48, 0xe3, 0x50, 0x63, 0xe4, 0x77, 0x56, 0x18, + 0xb1, 0x2c, 0xde, 0x12, 0x84, 0x8a, 0x21, 0xf9, 0x05, 0x0b, 0xce, 0x75, 0x1d, 0xcf, 0xd1, 0x71, + 0x95, 0xf9, 0x44, 0xdf, 0x9a, 0x91, 0x9a, 0xb1, 0x86, 0xb8, 0x66, 0x32, 0xc2, 0x24, 0x5f, 0xb2, + 0x0b, 0x13, 0x0e, 0x7f, 0x5f, 0x57, 0x1e, 0xc5, 0x30, 0x8f, 0xb7, 0x7a, 0x53, 0x6d, 0xc0, 0x17, + 0x17, 0xf9, 0x8a, 0xaf, 0xe4, 0x46, 0x7e, 0xdd, 0x82, 0x49, 0xe1, 0x1c, 0xce, 0x14, 0x52, 0xf6, + 0xed, 0x9f, 0x3d, 0x83, 0x97, 0x0c, 0xa4, 0xe3, 0xba, 0x74, 0x3f, 0xfa, 0x90, 0xf6, 0x7c, 0x15, + 0xa5, 0x87, 0xba, 0xae, 0x2b, 0xe9, 0x98, 0xea, 0xdb, 0x75, 0xee, 0x27, 0x5e, 0xd1, 0x31, 0x55, + 0xdf, 0xb5, 0x14, 0x0c, 0x07, 0xb0, 0xe7, 0x3f, 0x0e, 0x53, 0xa6, 0x1c, 0x27, 0x72, 0x7f, 0xff, + 0x51, 0x01, 0x80, 0x77, 0x95, 0xc8, 0xc5, 0xd2, 0xe5, 0x89, 0x9b, 0xb7, 0xfd, 0x56, 0x4e, 0xaf, + 0x79, 0x1a, 0x29, 0x55, 0x40, 0x66, 0x69, 0xde, 0xf6, 0x5b, 0x28, 0x99, 0x90, 0x36, 0x8c, 0xf7, + 0x9c, 0x68, 0x3b, 0xff, 0xfc, 0x2d, 0x25, 0x11, 0x94, 0x1c, 0x6d, 0x23, 0x67, 0x40, 0xde, 0xb1, + 0x62, 0xcf, 0x9e, 0x42, 0x1e, 0xb9, 0x67, 0xe3, 0x36, 0x5b, 0x90, 0xbe, 0x3c, 0xa9, 0x14, 0xac, + 0x69, 0x0f, 0x9f, 0xf9, 0x77, 0x2d, 0x98, 0x32, 0x51, 0x33, 0xba, 0xe9, 0xe7, 0xcc, 0x6e, 0xca, + 0xb3, 0x3d, 0xcc, 0x1e, 0xff, 0xef, 0x16, 0x00, 0xf6, 0xbd, 0x46, 0xbf, 0xdb, 0x65, 0x6a, 0xbb, + 0xf6, 0xf2, 0xb7, 0x8e, 0xed, 0xe5, 0x3f, 0x76, 0x42, 0x2f, 0xff, 0xc2, 0x89, 0xbc, 0xfc, 0xc7, + 0x4f, 0xee, 0xe5, 0x5f, 0x1c, 0xee, 0xe5, 0x6f, 0x7f, 0xd3, 0x82, 0xf3, 0x03, 0xfb, 0x15, 0xd3, + 0xa4, 0x03, 0xdf, 0x8f, 0x86, 0x78, 0x88, 0x62, 0x0c, 0x42, 0x13, 0x8f, 0x2c, 0xc3, 0xac, 0x7c, + 0xa6, 0xa4, 0xd1, 0xeb, 0xb8, 0x99, 0xb9, 0x75, 0x36, 0x52, 0x70, 0x1c, 0xa8, 0x61, 0xff, 0xb6, + 0x05, 0x15, 0x23, 0x22, 0x9f, 0x7d, 0x07, 0x77, 0x13, 0x96, 0x62, 0xc4, 0x2f, 0xb4, 0xf0, 0xab, + 0x2e, 0x01, 0x13, 0xd7, 0xd0, 0x6d, 0x23, 0x89, 0x7d, 0x7c, 0x0d, 0xcd, 0x4a, 0x51, 0x42, 0x45, + 0x7a, 0x72, 0xda, 0xe3, 0x8d, 0x5e, 0x30, 0xd3, 0x93, 0xd3, 0x1e, 0x72, 0x08, 0x67, 0xc7, 0x8e, + 0x14, 0xd2, 0x03, 0xd8, 0x78, 0x10, 0xc6, 0x09, 0x22, 0x14, 0x30, 0xf2, 0x04, 0x14, 0xa8, 0xd7, + 0x92, 0xf6, 0x0f, 0xfd, 0x7a, 0xed, 0x55, 0xaf, 0x85, 0xac, 0xdc, 0xbe, 0x05, 0x53, 0xc2, 0xfb, + 0xf9, 0x35, 0xba, 0x77, 0xec, 0xe7, 0x70, 0xd9, 0x68, 0x4f, 0x3d, 0x87, 0xcb, 0xaa, 0xb3, 0x72, + 0xfb, 0x9f, 0x58, 0x90, 0x7a, 0x23, 0xc9, 0xb8, 0x81, 0xb1, 0x86, 0xde, 0xc0, 0x98, 0x56, 0xfb, + 0xb1, 0x43, 0xad, 0xf6, 0x37, 0x80, 0x74, 0xd9, 0x54, 0x48, 0x2e, 0xb4, 0x85, 0xe4, 0x53, 0x12, + 0x6b, 0x03, 0x18, 0x98, 0x51, 0xcb, 0xfe, 0xc7, 0x42, 0x58, 0xf3, 0xd5, 0xa4, 0xa3, 0x1b, 0xa0, + 0x0f, 0x45, 0x4e, 0x4a, 0xda, 0xdf, 0x46, 0xb4, 0x5d, 0x0f, 0xe6, 0xd1, 0x8a, 0x3b, 0x52, 0x4e, + 0x79, 0xce, 0xcd, 0xfe, 0x7d, 0x21, 0xab, 0xf9, 0xac, 0xd2, 0xd1, 0xb2, 0x76, 0x93, 0xb2, 0x5e, + 0xcf, 0x6b, 0xad, 0xcc, 0x96, 0x91, 0x2c, 0x00, 0xf4, 0x68, 0xd0, 0xa4, 0x5e, 0xa4, 0xe2, 0x92, + 0x8a, 0x32, 0x42, 0x56, 0x97, 0xa2, 0x81, 0x61, 0x7f, 0x83, 0x4d, 0xa0, 0xf8, 0xa1, 0x68, 0x72, + 0x25, 0xed, 0xea, 0x9a, 0x9e, 0x1c, 0xda, 0xd3, 0xd5, 0x88, 0x56, 0x19, 0x3b, 0x22, 0x5a, 0xe5, 0x19, 0x98, 0x0c, 0xfc, 0x0e, 0xad, 0x05, 0x5e, 0xda, 0x47, 0x07, 0x59, 0x31, 0xde, 0x44, 0x05, 0xb7, 0x7f, 0xd5, 0x82, 0xd9, 0x74, 0x38, 0x5d, 0xee, 0xfe, 0xb7, 0x66, 0xcc, 0x7f, 0xe1, 0xe4, - 0x31, 0xff, 0xf6, 0x3f, 0x2d, 0xc0, 0x6c, 0xfa, 0x01, 0x3b, 0xc6, 0xd9, 0xe5, 0xc6, 0xb6, 0xd4, - 0xea, 0x2f, 0xac, 0x6c, 0x02, 0xa6, 0xc7, 0xcb, 0xd8, 0xd0, 0xf1, 0xf2, 0xd3, 0xc9, 0xfc, 0xcb, - 0x57, 0xd2, 0x16, 0x86, 0x99, 0x98, 0xf1, 0x29, 0x33, 0x30, 0x27, 0xb3, 0x70, 0x14, 0xcf, 0x2c, - 0x0b, 0xc7, 0x44, 0xae, 0x59, 0x38, 0x5e, 0xd1, 0xde, 0x56, 0x93, 0xb1, 0xab, 0xbf, 0xf6, 0xb4, - 0x3a, 0xc4, 0xd5, 0x5f, 0x3a, 0x93, 0xbe, 0xc3, 0x06, 0x56, 0xe4, 0x36, 0x77, 0x5c, 0x4f, 0xa4, - 0x36, 0x60, 0xa3, 0xfd, 0x19, 0x98, 0xa4, 0xf2, 0x91, 0x62, 0x61, 0xfa, 0xd7, 0x8d, 0xa6, 0xde, - 0x26, 0x56, 0x70, 0x52, 0x83, 0x19, 0x75, 0xe1, 0xa9, 0xee, 0x6b, 0x44, 0x4a, 0x16, 0x6d, 0x1f, - 0x5e, 0x4e, 0x82, 0x31, 0x8d, 0x6f, 0x7f, 0x01, 0x2a, 0x86, 0x22, 0xc1, 0xf7, 0xdc, 0xfb, 0x4e, - 0x33, 0x4a, 0xef, 0x55, 0x57, 0x59, 0x21, 0x0a, 0x18, 0xbf, 0x56, 0x12, 0x11, 0x5a, 0xa9, 0xbd, - 0x4a, 0xc6, 0x65, 0x49, 0x28, 0x23, 0x16, 0xd0, 0x36, 0xbd, 0xaf, 0xde, 0x85, 0x50, 0xc4, 0x90, - 0x15, 0xa2, 0x80, 0xd9, 0xcf, 0x42, 0x49, 0x25, 0xce, 0xe2, 0xd9, 0x67, 0xd4, 0x95, 0x87, 0x99, - 0x7d, 0xc6, 0x0f, 0x22, 0xe4, 0x10, 0xfb, 0x0d, 0x28, 0xa9, 0xfc, 0x5e, 0x47, 0x63, 0xb3, 0xed, - 0x23, 0xf4, 0xdc, 0xeb, 0x7e, 0x18, 0xa9, 0xa4, 0x64, 0xe2, 0x56, 0xf6, 0xe6, 0x0a, 0x2f, 0x43, - 0x0d, 0xb5, 0xff, 0xd4, 0x82, 0xca, 0xc6, 0xc6, 0xaa, 0x36, 0xd6, 0x20, 0x3c, 0x1c, 0x8a, 0x16, - 0xaa, 0x6d, 0x45, 0xd4, 0x74, 0xff, 0x10, 0x33, 0x69, 0xfe, 0x60, 0xbf, 0xfa, 0x70, 0x23, 0x13, - 0x03, 0x87, 0xd4, 0x24, 0x2b, 0x70, 0xc1, 0x84, 0xc8, 0x64, 0x11, 0x72, 0x5f, 0xe3, 0xaf, 0x5a, - 0x37, 0x06, 0xc1, 0x98, 0x55, 0x27, 0x4d, 0x4a, 0xaa, 0x68, 0xe6, 0x03, 0xd9, 0x8d, 0x41, 0x30, - 0x66, 0xd5, 0xb1, 0x9f, 0x87, 0x99, 0x94, 0x5f, 0xc2, 0x31, 0x92, 0xf4, 0xfc, 0x4e, 0x01, 0xa6, - 0xcc, 0xeb, 0xe9, 0x63, 0xec, 0x39, 0xc7, 0xdf, 0xca, 0x33, 0xae, 0x94, 0x0b, 0x27, 0xbc, 0x52, - 0x36, 0xef, 0xf0, 0xc7, 0xcf, 0xf6, 0x0e, 0xbf, 0x98, 0xcf, 0x1d, 0xbe, 0xe1, 0x6b, 0x32, 0xf1, - 0xe0, 0x7c, 0x4d, 0x7e, 0xab, 0x08, 0xd3, 0xc9, 0xac, 0xaf, 0xc7, 0xe8, 0xc9, 0x67, 0x07, 0x7a, - 0xf2, 0x84, 0x77, 0x58, 0x85, 0x51, 0xef, 0xb0, 0xc6, 0x47, 0xbd, 0xc3, 0x2a, 0x9e, 0xe2, 0x0e, - 0x6b, 0xf0, 0x06, 0x6a, 0xe2, 0xd8, 0x37, 0x50, 0x9f, 0x48, 0x6c, 0x14, 0xb1, 0xdb, 0x56, 0xbc, - 0x59, 0x90, 0x64, 0x37, 0x2c, 0xf9, 0xad, 0x4c, 0x77, 0xe2, 0xd2, 0x11, 0xdb, 0x68, 0x90, 0xe9, - 0x45, 0x7b, 0xf2, 0x6b, 0xf2, 0x87, 0x4f, 0xe0, 0x41, 0xfb, 0x22, 0x54, 0xe4, 0x78, 0xe2, 0x07, - 0x26, 0x48, 0x1e, 0xb6, 0x1a, 0x31, 0x08, 0x4d, 0x3c, 0x36, 0x30, 0x7a, 0xf1, 0x04, 0xe1, 0xb7, - 0xa9, 0x95, 0xe4, 0x6d, 0xea, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xfb, 0xf3, 0x70, 0x29, 0xd3, 0x6c, - 0xc6, 0xaf, 0x2c, 0xb8, 0x2e, 0x4f, 0x5b, 0x12, 0xc1, 0x10, 0x23, 0xf5, 0x18, 0xcc, 0xfc, 0x9d, - 0xa1, 0x98, 0x78, 0x08, 0x15, 0xfb, 0x37, 0x0b, 0x30, 0x9d, 0x7c, 0x1c, 0x99, 0xdc, 0xd3, 0x46, - 0xf6, 0x5c, 0xec, 0xfb, 0x82, 0xac, 0x91, 0x49, 0x74, 0xe8, 0xe5, 0xdc, 0x3d, 0x3e, 0xbe, 0x36, - 0x75, 0x5a, 0xd3, 0xb3, 0x63, 0x2c, 0x6f, 0xc5, 0x24, 0x3b, 0xfe, 0xc4, 0x70, 0x1c, 0x74, 0x2c, - 0x6d, 0x2f, 0xb9, 0x73, 0x8f, 0x83, 0x67, 0x35, 0x2b, 0x34, 0xd8, 0xb2, 0xbd, 0x65, 0x97, 0x06, - 0xee, 0x96, 0x4b, 0x5b, 0x32, 0xcb, 0x3c, 0x5f, 0xb9, 0xdf, 0x90, 0x65, 0xa8, 0xa1, 0xf6, 0x3b, - 0x63, 0x50, 0xe6, 0x39, 0xd2, 0xae, 0x05, 0x7e, 0x97, 0x3f, 0x9b, 0x19, 0x1a, 0xe7, 0x5c, 0xd9, - 0x6d, 0x37, 0x46, 0x7d, 0x09, 0x37, 0xa6, 0x28, 0x43, 0x14, 0x8c, 0x12, 0x4c, 0x70, 0x24, 0x3d, - 0x28, 0x6d, 0xc9, 0x9c, 0xce, 0xb2, 0xef, 0x46, 0xcc, 0x4b, 0xaa, 0x32, 0x44, 0x8b, 0x26, 0x50, - 0xff, 0x50, 0x73, 0xb1, 0x1d, 0x98, 0x49, 0x25, 0xb9, 0xc9, 0x3d, 0x13, 0xf4, 0xff, 0x1c, 0x87, - 0xb2, 0x8e, 0x8d, 0x23, 0x1f, 0x4b, 0x18, 0x1d, 0xcb, 0xf5, 0x9f, 0x30, 0xde, 0x74, 0xdb, 0xf6, - 0x5b, 0xec, 0xfc, 0xa0, 0x91, 0x53, 0x06, 0xc4, 0x27, 0xa0, 0xd0, 0x0f, 0x3a, 0x69, 0xab, 0xc2, - 0x6d, 0x5c, 0x45, 0x56, 0x6e, 0xc6, 0xf3, 0x15, 0x1e, 0x68, 0x3c, 0x1f, 0xdb, 0x25, 0x37, 0xfd, - 0xd6, 0x5e, 0xfa, 0x0d, 0xb8, 0xba, 0xdf, 0xda, 0x43, 0x0e, 0x21, 0xaf, 0xc0, 0xb4, 0x0c, 0x52, - 0x54, 0x4a, 0x4c, 0x91, 0xeb, 0xa9, 0xda, 0xd9, 0x64, 0x23, 0x01, 0xc5, 0x14, 0x36, 0xdb, 0x65, - 0xd9, 0xb1, 0x81, 0xe7, 0xf7, 0x9e, 0x48, 0xde, 0x4c, 0xdf, 0x68, 0xdc, 0xba, 0xc9, 0x8d, 0x9f, - 0x1a, 0x23, 0x11, 0x07, 0x39, 0x79, 0x64, 0x1c, 0xe4, 0xb2, 0xa0, 0xcd, 0xa4, 0xe5, 0x3b, 0xca, - 0x54, 0xfd, 0x69, 0x45, 0x97, 0x95, 0x1d, 0x7a, 0x76, 0xd1, 0x35, 0xb3, 0x22, 0x46, 0xcb, 0xef, - 0x5f, 0xc4, 0xa8, 0x7d, 0x1b, 0x66, 0x52, 0xfd, 0xa7, 0x8c, 0x52, 0x56, 0xb6, 0x51, 0xea, 0x78, - 0xaf, 0xc8, 0xfd, 0x33, 0x0b, 0xce, 0x0f, 0xac, 0x48, 0xc7, 0x0d, 0xdd, 0x4d, 0xef, 0x8d, 0x63, - 0xa7, 0xdf, 0x1b, 0x0b, 0x27, 0xdb, 0x1b, 0xeb, 0x9b, 0xdf, 0xfb, 0xe1, 0xe5, 0x87, 0xbe, 0xff, - 0xc3, 0xcb, 0x0f, 0xfd, 0xc1, 0x0f, 0x2f, 0x3f, 0xf4, 0xce, 0xc1, 0x65, 0xeb, 0x7b, 0x07, 0x97, - 0xad, 0xef, 0x1f, 0x5c, 0xb6, 0xfe, 0xe0, 0xe0, 0xb2, 0xf5, 0x9f, 0x0f, 0x2e, 0x5b, 0xdf, 0xfc, - 0xe3, 0xcb, 0x0f, 0x7d, 0xea, 0x13, 0x71, 0x4f, 0x2d, 0xaa, 0x9e, 0xe2, 0x3f, 0x3e, 0xac, 0xfa, - 0x65, 0xb1, 0xb7, 0xd3, 0x5e, 0x64, 0x3d, 0xb5, 0xa8, 0x4b, 0x54, 0x4f, 0xfd, 0xdf, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x10, 0x97, 0xcb, 0x70, 0x0f, 0xaa, 0x00, 0x00, + 0x31, 0xff, 0xf6, 0x9f, 0x15, 0x60, 0x36, 0xfd, 0x80, 0x1d, 0xe3, 0xec, 0x72, 0x63, 0x5b, 0x6a, + 0xf5, 0x17, 0x56, 0x36, 0x01, 0xd3, 0xe3, 0x65, 0x6c, 0xe8, 0x78, 0xb9, 0x06, 0x65, 0xbf, 0xa7, + 0x0e, 0xfc, 0x42, 0xb8, 0x2b, 0xca, 0x58, 0x73, 0x4b, 0x01, 0xde, 0xdb, 0xaf, 0x5e, 0x88, 0x05, + 0xd0, 0xc5, 0x18, 0x57, 0x25, 0x3f, 0xad, 0x2c, 0x15, 0xe3, 0x89, 0x2c, 0x3a, 0xda, 0x52, 0x31, + 0x13, 0xd7, 0x1f, 0x66, 0xac, 0x28, 0x9e, 0x24, 0x9b, 0xc7, 0xc4, 0x99, 0x65, 0xf3, 0x98, 0xcc, + 0x35, 0x9b, 0xc7, 0x2b, 0xda, 0x6b, 0xab, 0x14, 0x87, 0x0c, 0x68, 0x8f, 0xad, 0x43, 0x42, 0x06, + 0xa4, 0x53, 0xea, 0x3b, 0x6c, 0x80, 0x46, 0x6e, 0x73, 0xc7, 0xf5, 0x44, 0x8a, 0x04, 0x36, 0x6b, + 0x9e, 0x81, 0x49, 0x2a, 0x1f, 0x3b, 0x16, 0x57, 0x08, 0xba, 0xd1, 0xd4, 0x1b, 0xc7, 0x0a, 0x4e, + 0x6a, 0x30, 0xa3, 0x2e, 0x4e, 0xd5, 0xbd, 0x8f, 0x48, 0xed, 0xa2, 0xed, 0xcc, 0xcb, 0x49, 0x30, + 0xa6, 0xf1, 0xed, 0x2f, 0x40, 0xc5, 0x50, 0x48, 0xf8, 0xde, 0x7d, 0xdf, 0x69, 0x46, 0xe9, 0x3d, + 0xef, 0x2a, 0x2b, 0x44, 0x01, 0xe3, 0xd7, 0x53, 0x22, 0xd2, 0x2b, 0xb5, 0xe7, 0xc9, 0xf8, 0x2e, + 0x09, 0x65, 0xc4, 0x02, 0xda, 0xa6, 0xf7, 0xd5, 0xfb, 0x12, 0x8a, 0x18, 0xb2, 0x42, 0x14, 0x30, + 0xfb, 0x59, 0x28, 0xa9, 0x04, 0x5c, 0x3c, 0x8b, 0x8d, 0xba, 0x3a, 0x31, 0xb3, 0xd8, 0xf8, 0x41, + 0x84, 0x1c, 0x62, 0xbf, 0x01, 0x25, 0x95, 0x27, 0xec, 0x68, 0x6c, 0xb6, 0x0d, 0x85, 0x9e, 0x7b, + 0xdd, 0x0f, 0x23, 0x95, 0xdc, 0x4c, 0xdc, 0xee, 0xde, 0x5c, 0xe1, 0x65, 0xa8, 0xa1, 0xf6, 0x9f, + 0x5a, 0x50, 0xd9, 0xd8, 0x58, 0xd5, 0x46, 0x1f, 0x84, 0x87, 0x43, 0xd1, 0x42, 0xb5, 0xad, 0x88, + 0x9a, 0x6e, 0x24, 0x62, 0x46, 0xce, 0x1f, 0xec, 0x57, 0x1f, 0x6e, 0x64, 0x62, 0xe0, 0x90, 0x9a, + 0x64, 0x05, 0x2e, 0x98, 0x10, 0x99, 0x74, 0x42, 0xee, 0x8f, 0xfc, 0x75, 0xec, 0xc6, 0x20, 0x18, + 0xb3, 0xea, 0xa4, 0x49, 0x49, 0x55, 0xcf, 0x7c, 0x68, 0xbb, 0x31, 0x08, 0xc6, 0xac, 0x3a, 0xf6, + 0xf3, 0x30, 0x93, 0xf2, 0x6f, 0x38, 0x46, 0xb2, 0x9f, 0xdf, 0x29, 0xc0, 0x94, 0x79, 0xcd, 0x7d, + 0x8c, 0xbd, 0xeb, 0xf8, 0x2a, 0x41, 0xc6, 0xd5, 0x74, 0xe1, 0x84, 0x57, 0xd3, 0xa6, 0x2f, 0xc0, + 0xf8, 0xd9, 0xfa, 0x02, 0x14, 0xf3, 0xf1, 0x05, 0x30, 0x7c, 0x56, 0x26, 0x1e, 0x9c, 0xcf, 0xca, + 0x6f, 0x15, 0x61, 0x3a, 0x99, 0x3d, 0xf6, 0x18, 0x3d, 0xf9, 0xec, 0x40, 0x4f, 0x9e, 0xf0, 0x2e, + 0xac, 0x30, 0xea, 0x5d, 0xd8, 0xf8, 0xa8, 0x77, 0x61, 0xc5, 0x53, 0xdc, 0x85, 0x0d, 0xde, 0x64, + 0x4d, 0x1c, 0xfb, 0x26, 0xeb, 0x13, 0x7a, 0xa3, 0x98, 0x4c, 0xb8, 0x7f, 0xc5, 0x9b, 0x05, 0x49, + 0x76, 0xc3, 0x92, 0xdf, 0xca, 0x74, 0x4b, 0x2e, 0x1d, 0xb1, 0x8d, 0x06, 0x99, 0xde, 0xb8, 0x27, + 0xbf, 0x6e, 0x7f, 0xf8, 0x04, 0x9e, 0xb8, 0x2f, 0x42, 0x45, 0x8e, 0x27, 0x7e, 0xf0, 0x82, 0xe4, + 0xa1, 0xad, 0x11, 0x83, 0xd0, 0xc4, 0x63, 0x03, 0xa3, 0x17, 0x4f, 0x10, 0x7e, 0x2b, 0x5b, 0x49, + 0xde, 0xca, 0xae, 0x27, 0xc1, 0x98, 0xc6, 0xb7, 0x3f, 0x0f, 0x97, 0x32, 0xcd, 0x6f, 0xfc, 0xea, + 0x83, 0x9f, 0x09, 0x68, 0x4b, 0x22, 0x18, 0x62, 0xa4, 0x1e, 0x95, 0x99, 0xbf, 0x33, 0x14, 0x13, + 0x0f, 0xa1, 0x62, 0xff, 0x66, 0x01, 0xa6, 0x93, 0x8f, 0x2c, 0x93, 0x7b, 0xda, 0x58, 0x9f, 0xcb, + 0x3d, 0x81, 0x20, 0x6b, 0x64, 0x24, 0x1d, 0x7a, 0xc9, 0x77, 0x8f, 0x8f, 0xaf, 0x4d, 0x9d, 0x1e, + 0xf5, 0xec, 0x18, 0xcb, 0xdb, 0x35, 0xc9, 0x8e, 0x3f, 0x55, 0x1c, 0x07, 0x2f, 0x4b, 0x1b, 0x4e, + 0xee, 0xdc, 0xe3, 0x20, 0x5c, 0xcd, 0x0a, 0x0d, 0xb6, 0x6c, 0x6f, 0xd9, 0xa5, 0x81, 0xbb, 0xe5, + 0xd2, 0x96, 0xcc, 0x56, 0xcf, 0x57, 0xee, 0x37, 0x64, 0x19, 0x6a, 0xa8, 0xfd, 0xce, 0x18, 0x94, + 0x79, 0xae, 0xb5, 0x6b, 0x81, 0xdf, 0xe5, 0xcf, 0x6f, 0x86, 0xc6, 0x79, 0x59, 0x76, 0xdb, 0x8d, + 0x51, 0x5f, 0xd4, 0x8d, 0x29, 0xca, 0x50, 0x07, 0xa3, 0x04, 0x13, 0x1c, 0x49, 0x0f, 0x4a, 0x5b, + 0x32, 0x37, 0xb4, 0xec, 0xbb, 0x11, 0xf3, 0x9b, 0xaa, 0x4c, 0xd3, 0xa2, 0x09, 0xd4, 0x3f, 0xd4, + 0x5c, 0x6c, 0x07, 0x66, 0x52, 0xc9, 0x72, 0x72, 0xcf, 0x28, 0xfd, 0xbf, 0xc6, 0xa1, 0xac, 0x63, + 0xec, 0xc8, 0xc7, 0x12, 0xc6, 0xcb, 0x72, 0xfd, 0x27, 0x8c, 0xb7, 0xe1, 0xb6, 0xfd, 0x16, 0x3b, + 0x3f, 0x68, 0xe4, 0x94, 0x21, 0xf2, 0x09, 0x28, 0xf4, 0x83, 0x4e, 0xda, 0x3a, 0x71, 0x1b, 0x57, + 0x91, 0x95, 0x9b, 0x71, 0x81, 0x85, 0x07, 0x1a, 0x17, 0xc8, 0x76, 0xc9, 0x4d, 0xbf, 0xb5, 0x97, + 0x7e, 0x4b, 0xae, 0xee, 0xb7, 0xf6, 0x90, 0x43, 0xc8, 0x2b, 0x30, 0x2d, 0x83, 0x1d, 0x95, 0x12, + 0x53, 0xe4, 0x7a, 0xaa, 0x76, 0x5a, 0xd9, 0x48, 0x40, 0x31, 0x85, 0xcd, 0x76, 0x59, 0x76, 0x6c, + 0xe0, 0x79, 0xc2, 0x27, 0x92, 0x37, 0xdc, 0x37, 0x1a, 0xb7, 0x6e, 0x72, 0x23, 0xaa, 0xc6, 0x48, + 0xc4, 0x53, 0x4e, 0x1e, 0x19, 0x4f, 0xb9, 0x2c, 0x68, 0x33, 0x69, 0xe5, 0xc9, 0xe5, 0x8a, 0xa2, + 0xcb, 0xca, 0x0e, 0x3d, 0xbb, 0xe8, 0x9a, 0x59, 0x91, 0xa7, 0xe5, 0xf7, 0x2f, 0xf2, 0xd4, 0xbe, + 0x0d, 0x33, 0xa9, 0xfe, 0x53, 0xc6, 0x2d, 0x2b, 0xdb, 0xb8, 0x75, 0xbc, 0xd7, 0xe8, 0xfe, 0xb9, + 0x05, 0xe7, 0x07, 0x56, 0xa4, 0xe3, 0x86, 0x00, 0xa7, 0xf7, 0xc6, 0xb1, 0xd3, 0xef, 0x8d, 0x85, + 0x93, 0xed, 0x8d, 0xf5, 0xcd, 0xef, 0xfd, 0xf0, 0xf2, 0x43, 0xdf, 0xff, 0xe1, 0xe5, 0x87, 0xfe, + 0xe0, 0x87, 0x97, 0x1f, 0x7a, 0xe7, 0xe0, 0xb2, 0xf5, 0xbd, 0x83, 0xcb, 0xd6, 0xf7, 0x0f, 0x2e, + 0x5b, 0x7f, 0x70, 0x70, 0xd9, 0xfa, 0x2f, 0x07, 0x97, 0xad, 0x6f, 0xfe, 0xf1, 0xe5, 0x87, 0x3e, + 0xf5, 0x89, 0xb8, 0xa7, 0x16, 0x55, 0x4f, 0xf1, 0x1f, 0x1f, 0x56, 0xfd, 0xb2, 0xd8, 0xdb, 0x69, + 0x2f, 0xb2, 0x9e, 0x5a, 0xd4, 0x25, 0xaa, 0xa7, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, + 0xa0, 0x6a, 0xd7, 0x57, 0xaa, 0x00, 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -9869,7 +9871,7 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Status) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status))) i-- - dAtA[i] = 0x3a + dAtA[i] = 0x42 } if m.FinishedAt != nil { { @@ -9881,7 +9883,7 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a } if m.StartedAt != nil { { @@ -9893,17 +9895,22 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x2a + dAtA[i] = 0x32 } i -= len(m.Message) copy(dAtA[i:], m.Message) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message))) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x2a i -= len(m.Phase) copy(dAtA[i:], m.Phase) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Phase))) i-- + dAtA[i] = 0x22 + i -= len(m.Operation) + copy(dAtA[i:], m.Operation) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Operation))) + i-- dAtA[i] = 0x1a i -= len(m.Name) copy(dAtA[i:], m.Name) @@ -12785,6 +12792,8 @@ func (m *StepPluginStatus) Size() (n int) { n += 1 + sovGenerated(uint64(m.Index)) l = len(m.Name) n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Operation) + n += 1 + l + sovGenerated(uint64(l)) l = len(m.Phase) n += 1 + l + sovGenerated(uint64(l)) l = len(m.Message) @@ -14719,6 +14728,7 @@ func (this *StepPluginStatus) String() string { s := strings.Join([]string{`&StepPluginStatus{`, `Index:` + fmt.Sprintf("%v", this.Index) + `,`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Operation:` + fmt.Sprintf("%v", this.Operation) + `,`, `Phase:` + fmt.Sprintf("%v", this.Phase) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`, `StartedAt:` + strings.Replace(fmt.Sprintf("%v", this.StartedAt), "Time", "v1.Time", 1) + `,`, @@ -33738,6 +33748,38 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Operation", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Operation = StepPluginOperation(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Phase", wireType) } @@ -33769,7 +33811,7 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { } m.Phase = StepPluginPhase(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) } @@ -33801,7 +33843,7 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { } m.Message = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field StartedAt", wireType) } @@ -33837,7 +33879,7 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field FinishedAt", wireType) } @@ -33873,7 +33915,7 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 7: + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 582b8844c2..12b7d084d6 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1759,15 +1759,17 @@ message StepPluginStatus { optional string name = 2; - optional string phase = 3; + optional string operation = 3; - optional string message = 4; + optional string phase = 4; + + optional string message = 5; - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 5; + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 6; - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 6; + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 7; - optional bytes status = 7; + optional bytes status = 8; } message StickinessConfig { diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 4840e5c63d..a0c5c93955 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -5196,6 +5196,13 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall Format: "", }, }, + "operation": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, "phase": { SchemaProps: spec.SchemaProps{ Default: "", @@ -5226,7 +5233,7 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall }, }, }, - Required: []string{"index", "name", "phase"}, + Required: []string{"index", "name", "operation", "phase"}, }, }, Dependencies: []string{ diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index e1097760a0..4b8151e2c4 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -1039,13 +1039,14 @@ type RolloutAnalysisRunStatus struct { } type StepPluginStatus struct { - Index int32 `json:"index" protobuf:"bytes,1,opt,name=index"` - Name string `json:"name" protobuf:"bytes,2,opt,name=name"` - Phase StepPluginPhase `json:"phase" protobuf:"bytes,3,opt,name=phase"` - Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"` - StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,5,opt,name=startedAt"` - FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,6,opt,name=finishedAt"` - Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,7,opt,name=status"` + Index int32 `json:"index" protobuf:"bytes,1,name=index"` + Name string `json:"name" protobuf:"bytes,2,name=name"` + Operation StepPluginOperation `json:"operation" protobuf:"bytes,3,name=operation"` + Phase StepPluginPhase `json:"phase" protobuf:"bytes,4,name=phase"` + Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` + StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,6,name=startedAt"` + FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,7,opt,name=finishedAt"` + Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,8,opt,name=status"` } // StepPluginPhase is the overall phase of a StepPlugin @@ -1059,6 +1060,15 @@ const ( StepPluginPhaseError StepPluginPhase = "Error" ) +type StepPluginOperation string + +// Possible StepPluginOperation values +const ( + StepPluginOperationRun StepPluginOperation = "Run" + StepPluginOperationTerminate StepPluginOperation = "Terminate" + StepPluginOperationAbort StepPluginOperation = "Abort" +) + type ALBStatus struct { LoadBalancer AwsResourceRef `json:"loadBalancer,omitempty" protobuf:"bytes,1,opt,name=loadBalancer"` CanaryTargetGroup AwsResourceRef `json:"canaryTargetGroup,omitempty" protobuf:"bytes,2,opt,name=canaryTargetGroup"` diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 0b5d68752d..984f401328 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -2,12 +2,40 @@ package rollout import ( "fmt" + "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" replicasetutil "github.com/argoproj/argo-rollouts/utils/replicaset" ) func (c *rolloutContext) reconcileCanaryPluginStep() error { + + //On abort, we need to abort all successful previous steps + if c.pauseContext.IsAborted() { + c.stepPluginStatuses = c.rollout.Status.Canary.StepPluginStatuses + + // In an abort, the current step might be the current or last, depending on when the abort happened. + _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) + startingIndex := *currentStepIndex + for i := startingIndex; i >= 0; i-- { + currentStep := &c.rollout.Spec.Strategy.Canary.Steps[i] + if currentStep.Plugin == nil { + continue + } + + stepPlugin, err := c.stepPluginResolver.Resolve(i, *currentStep.Plugin, c.log) + if err != nil { + return fmt.Errorf("could not create step plugin at index %d : %w", i, err) + } + status, err := stepPlugin.Abort(c.rollout) + if err != nil { + return fmt.Errorf("failed to abort plugin: %w", err) + } + c.stepPluginStatuses = updateStepPluginStatus(c.stepPluginStatuses, status) + } + return nil + } + currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) if currentStep == nil || currentStep.Plugin == nil { return nil @@ -18,19 +46,17 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) } + // On full promotion, we want to Terminate the current step if c.rollout.Status.PromoteFull { - currentStatus := findCurrentStepStatus(c.rollout.Status.Canary.StepPluginStatuses, *currentStepIndex) - if currentStatus != nil && currentStatus.Phase == v1alpha1.StepPluginPhaseRunning { - status, err := stepPlugin.Terminate(c.rollout) - if err != nil { - return fmt.Errorf("failed to terminate plugin: %w", err) - } - c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + status, err := stepPlugin.Terminate(c.rollout) + if err != nil { + return fmt.Errorf("failed to terminate plugin: %w", err) } - + c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) return nil } + // Normal execution of a step plugin status, result, err := stepPlugin.Run(c.rollout) if err != nil { return fmt.Errorf("failed to run plugin: %w", err) @@ -43,14 +69,12 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { } if status.Phase == v1alpha1.StepPluginPhaseError { - // TODO: fix this - panic("this is wrong. cant do that") - c.persistRolloutStatus(&c.newStatus) - return err + // It could be interesting to implement a backoff mechanism + c.enqueueRolloutAfter(c.rollout, 30*time.Second) + return nil } if status.Phase == v1alpha1.StepPluginPhaseFailed { - // Call each plugin in reverse order? c.pauseContext.AddAbort(status.Message) } @@ -66,15 +90,19 @@ func (c *rolloutContext) calculateStepPluginStatus() []v1alpha1.StepPluginStatus } func (c *rolloutContext) isStepPluginCompleted(stepIndex int32) bool { - status := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex) - return status != nil && (status.Phase == v1alpha1.StepPluginPhaseSuccessful || - status.Phase == v1alpha1.StepPluginPhaseFailed || - status.Phase == v1alpha1.StepPluginPhaseError) + runStatus := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex, v1alpha1.StepPluginOperationRun) + isRunning := runStatus != nil && runStatus.Phase == v1alpha1.StepPluginPhaseRunning + if isRunning { + terminateStatus := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex, v1alpha1.StepPluginOperationTerminate) + abortStatus := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex, v1alpha1.StepPluginOperationAbort) + isRunning = terminateStatus == nil && abortStatus == nil + } + return runStatus != nil && ((!isRunning && runStatus.Phase == v1alpha1.StepPluginPhaseRunning) || runStatus.Phase == v1alpha1.StepPluginPhaseFailed || runStatus.Phase == v1alpha1.StepPluginPhaseSuccessful) } -func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32) *v1alpha1.StepPluginStatus { +func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { for _, s := range status { - if s.Index == stepIndex { + if s.Index == stepIndex && s.Operation == operation { return &s } } @@ -82,11 +110,15 @@ func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32) } func updateStepPluginStatus(statuses []v1alpha1.StepPluginStatus, status *v1alpha1.StepPluginStatus) []v1alpha1.StepPluginStatus { + if status == nil { + return statuses + } + // Update new status and preserve order newStatuses := []v1alpha1.StepPluginStatus{} statusAdded := false for _, s := range statuses { - if !statusAdded && s.Index == status.Index { + if !statusAdded && s.Index == status.Index && s.Operation == status.Operation { newStatuses = append(newStatuses, *status) statusAdded = true continue diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index 19dfbe9cc2..c9331c2d7f 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -335,6 +335,81 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { }) } +func Test_StepPlugin_Aborted(t *testing.T) { + setup := func(t *testing.T) (*rolloutContext, *mocks.Resolver) { + stepPluginResolver := mocks.NewResolver(t) + + r := newStepPluginRollout() + r.Status.Abort = true + + logCtx := logutil.WithRollout(r) + roCtx := &rolloutContext{ + rollout: r, + log: logCtx, + reconcilerBase: reconcilerBase{ + stepPluginResolver: stepPluginResolver, + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, + } + + return roCtx, stepPluginResolver + } + t.Run("Abort called on each plugin step", func(t *testing.T) { + roCtx, stepPluginResolver := setup(t) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + } + roCtx.rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + { + Pause: &v1alpha1.RolloutPause{}, // Not a step plugin + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + } + roCtx.rollout.Status.CurrentStepIndex = int32Ptr(2) + + expectedAbortStatus := []*v1alpha1.StepPluginStatus{} + for _, stepIndex := range []int32{0, 2} { + abortStatus := &v1alpha1.StepPluginStatus{ + Index: stepIndex, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationAbort, + Phase: v1alpha1.StepPluginPhaseSuccessful, + } + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", stepIndex, mock.Anything, mock.Anything).Return(stepPluginMock, nil) + stepPluginMock.On("Abort", mock.Anything).Return(abortStatus, nil) + expectedAbortStatus = append(expectedAbortStatus, abortStatus) + } + + err := roCtx.reconcileCanaryPluginStep() + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginStatuses, 3) + assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[0], roCtx.stepPluginStatuses[0]) + assert.EqualExportedValues(t, *expectedAbortStatus[1], roCtx.stepPluginStatuses[1]) + assert.EqualExportedValues(t, *expectedAbortStatus[0], roCtx.stepPluginStatuses[2]) + }) +} + //Controller: // Add test for plugin config // Add InitPlugin call test @@ -342,19 +417,10 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { //Reconcile: // Add disable feature -// Plugin: -//if run error, save message+phase, but not state - -//When abort, abort all steps? validate status? validate order - -//error during run? -//error during abort? -//error during terminate? safe to ignore? - // Helper: write helper functions? func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { - newRolloutContext := func(status *v1alpha1.StepPluginStatus) *rolloutContext { + newRolloutContext := func(statuses []*v1alpha1.StepPluginStatus) *rolloutContext { r := newStepPluginRollout() logCtx := logutil.WithRollout(r) roCtx := &rolloutContext{ @@ -366,59 +432,87 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { StepPluginStatuses: []v1alpha1.StepPluginStatus{}, }, } - if status != nil { - roCtx.stepPluginStatuses = append(roCtx.stepPluginStatuses, *status) + for _, s := range statuses { + roCtx.stepPluginStatuses = append(roCtx.stepPluginStatuses, *s) } roCtx.newStatus.Canary.StepPluginStatuses = roCtx.calculateStepPluginStatus() return roCtx } tests := []struct { - name string - status *v1alpha1.StepPluginStatus - index int32 - want bool + name string + statuses []*v1alpha1.StepPluginStatus + index int32 + want bool }{ { - name: "Status is not set", - status: nil, - index: 0, - want: false, + name: "Status is not set", + statuses: nil, + index: 0, + want: false, }, { - name: "Phase is successful", - status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseSuccessful}, - index: 0, - want: true, + name: "Phase is successful", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseSuccessful}, + }, + index: 0, + want: true, }, { - name: "Phase is failed", - status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseFailed}, - index: 0, - want: true, + name: "Phase is failed", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseFailed}, + }, + index: 0, + want: true, }, { - name: "Phase is error", - status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseError}, - index: 0, - want: true, + name: "Phase is error", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseError}, + }, + index: 0, + want: false, }, { - name: "Phase is running", - status: &v1alpha1.StepPluginStatus{Index: 0, Phase: v1alpha1.StepPluginPhaseRunning}, - index: 0, - want: false, + name: "Phase is running", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseRunning}, + }, + index: 0, + want: false, }, { - name: "status for index is missing", - status: &v1alpha1.StepPluginStatus{Index: 1, Phase: v1alpha1.StepPluginPhaseSuccessful}, - index: 0, - want: false, + name: "Phase is running, but terminated", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseRunning}, + {Index: 0, Operation: v1alpha1.StepPluginOperationTerminate}, + }, + index: 0, + want: true, + }, + { + name: "Phase is running, but aborted", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseRunning}, + {Index: 0, Operation: v1alpha1.StepPluginOperationTerminate}, + }, + index: 0, + want: true, + }, + { + name: "status for index is missing", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 1, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseSuccessful}, + }, + index: 0, + want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c := newRolloutContext(tt.status) + c := newRolloutContext(tt.statuses) if got := c.isStepPluginCompleted(tt.index); got != tt.want { t.Errorf("rolloutContext.isStepPluginCompleted() = %v, want %v", got, tt.want) } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 7611d3c500..f57d3d5be2 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -2,7 +2,6 @@ package plugin import ( "encoding/json" - "fmt" "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" @@ -39,19 +38,21 @@ var ( func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *StepResult, error) { result := &StepResult{} - stepStatus := p.getStepStatus(rollout) + stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) if stepStatus == nil { now := metatime.MetaNow() stepStatus = &v1alpha1.StepPluginStatus{ Index: p.index, Name: p.name, StartedAt: &now, + Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseRunning, } } resp, err := p.rpc.Run(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() if err.HasError() { + p.log.Errorf("error during plugin execution") stepStatus.Phase = v1alpha1.StepPluginPhaseError stepStatus.Message = err.Error() stepStatus.FinishedAt = &finishedAt @@ -80,42 +81,96 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, } func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { - stepStatus := p.getStepStatus(rollout) + terminateStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationTerminate) + if terminateStatus != nil { + // Already terminated + return nil, nil + } + + stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) if stepStatus == nil || stepStatus.Phase != v1alpha1.StepPluginPhaseRunning { - return stepStatus, nil + // Step is not running, no need to call terminate + return nil, nil } + now := metatime.MetaNow() + terminateStatus = &v1alpha1.StepPluginStatus{ + Index: stepStatus.Index, + Name: stepStatus.Name, + StartedAt: &now, + Operation: v1alpha1.StepPluginOperationTerminate, + Phase: v1alpha1.StepPluginPhaseSuccessful, + } resp, err := p.rpc.Terminate(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() if err.HasError() { - stepStatus.Phase = v1alpha1.StepPluginPhaseError - stepStatus.Message = fmt.Sprintf("Terminated: %s", err.Error()) - stepStatus.FinishedAt = &finishedAt - return stepStatus, nil + terminateStatus.Phase = v1alpha1.StepPluginPhaseError + terminateStatus.Message = err.Error() + terminateStatus.FinishedAt = &finishedAt + return terminateStatus, nil } if resp.Phase != "" { - stepStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + terminateStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) } - if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { + if terminateStatus.Phase == v1alpha1.StepPluginPhaseRunning { p.log.Warnf("terminate cannot run asynchronously. Overriding status phase to %s.", v1alpha1.StepPluginPhaseFailed) - stepStatus.Phase = v1alpha1.StepPluginPhaseFailed + terminateStatus.Phase = v1alpha1.StepPluginPhaseFailed } - stepStatus.Message = fmt.Sprintf("Terminated: %s", resp.Message) - stepStatus.FinishedAt = &finishedAt - stepStatus.Status = resp.Status - return stepStatus, nil + terminateStatus.Message = resp.Message + terminateStatus.FinishedAt = &finishedAt + return terminateStatus, nil } func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { - return nil, fmt.Errorf("Not implemented") + abortStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationAbort) + if abortStatus != nil { + // Already aborted + return nil, nil + } + + stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) + if stepStatus == nil || (stepStatus.Phase != v1alpha1.StepPluginPhaseRunning && stepStatus.Phase != v1alpha1.StepPluginPhaseSuccessful) { + // Step plugin isn't in a phase where it needs to be aborted + return nil, nil + } + + now := metatime.MetaNow() + abortStatus = &v1alpha1.StepPluginStatus{ + Index: stepStatus.Index, + Name: stepStatus.Name, + StartedAt: &now, + Operation: v1alpha1.StepPluginOperationAbort, + Phase: v1alpha1.StepPluginPhaseSuccessful, + } + resp, err := p.rpc.Terminate(rollout.DeepCopy(), p.getStepContext(stepStatus)) + finishedAt := metatime.MetaNow() + if err.HasError() { + abortStatus.Phase = v1alpha1.StepPluginPhaseError + abortStatus.Message = err.Error() + abortStatus.FinishedAt = &finishedAt + return abortStatus, nil + } + + if resp.Phase != "" { + abortStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + } + + if abortStatus.Phase == v1alpha1.StepPluginPhaseRunning { + p.log.Warnf("abort cannot run asynchronously. Overriding status phase to %s.", v1alpha1.StepPluginPhaseFailed) + abortStatus.Phase = v1alpha1.StepPluginPhaseFailed + } + + abortStatus.Message = resp.Message + abortStatus.FinishedAt = &finishedAt + return abortStatus, nil } -func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout) *v1alpha1.StepPluginStatus { +func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { for _, s := range rollout.Status.Canary.StepPluginStatuses { - if s.Index == p.index && s.Name == p.name { + if s.Index == p.index && s.Name == p.name && s.Operation == operation { return s.DeepCopy() } } diff --git a/rollout/steps/plugin/resolver.go b/rollout/steps/plugin/resolver.go index cb60aa980a..cb6a717072 100644 --- a/rollout/steps/plugin/resolver.go +++ b/rollout/steps/plugin/resolver.go @@ -5,6 +5,7 @@ import ( "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/client" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) @@ -30,6 +31,6 @@ func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep, log *log.Ent index: index, name: plugin.Name, config: plugin.Config, - log: log.WithField("stepPlugin", plugin.Name), + log: log.WithFields(logrus.Fields{"stepplugin": plugin.Name, "stepindex": index}), }, nil } diff --git a/ui/src/models/rollout/generated/api.ts b/ui/src/models/rollout/generated/api.ts index baac4b306f..c86ec12c90 100755 --- a/ui/src/models/rollout/generated/api.ts +++ b/ui/src/models/rollout/generated/api.ts @@ -2807,6 +2807,12 @@ export interface GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginS * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus */ name?: string; + /** + * + * @type {string} + * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus + */ + operation?: string; /** * * @type {string} From 67e1f329d3cb6c23819b13d9aa62b9f999ccc029 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 15 Apr 2024 09:16:38 -0400 Subject: [PATCH 11/41] unit test Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin_test.go | 57 +++++++---------------- rollout/steps/plugin/plugin.go | 2 +- rollout/steps/plugin/plugin_test.go | 70 +++++++++++++++++++---------- 3 files changed, 65 insertions(+), 64 deletions(-) diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index c9331c2d7f..6c816ed3fc 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -42,6 +42,7 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() + logCtx := logutil.WithRollout(r) roCtx := &rolloutContext{ rollout: r, log: logutil.WithRollout(r), @@ -50,6 +51,10 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, } runStatus := newStepPluginStatus() @@ -123,6 +128,7 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() + logCtx := logutil.WithRollout(r) roCtx := &rolloutContext{ rollout: r, log: logutil.WithRollout(r), @@ -131,6 +137,10 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, } runStatus := newStepPluginStatus() @@ -278,50 +288,17 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { return roCtx, stepPluginMock } - t.Run("Terminate not called when status is missing", func(t *testing.T) { - roCtx, stepPluginMock := setup(t) - roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ - { - Index: 999, - Name: "not current plugin", - Message: "other status", - Phase: v1alpha1.StepPluginPhaseRunning, - }, - } - - stepPluginMock.On("Terminate", mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") - - err := roCtx.reconcileCanaryPluginStep() - - require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 0) - }) - t.Run("Terminate not called when status is not running", func(t *testing.T) { - roCtx, stepPluginMock := setup(t) - runStatus := newStepPluginStatus() - roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ - { - Index: runStatus.Index, - Name: runStatus.Name, - Phase: v1alpha1.StepPluginPhaseSuccessful, - }, - } - - stepPluginMock.On("Terminate", mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") - - err := roCtx.reconcileCanaryPluginStep() - - require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 0) - }) - t.Run("Rollout is Terminated on full promotion if current step is running", func(t *testing.T) { + t.Run("Rollout is Terminated on full promotion", func(t *testing.T) { roCtx, stepPluginMock := setup(t) runStatus := newStepPluginStatus() + runStatus.Operation = v1alpha1.StepPluginOperationTerminate + runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { - Index: runStatus.Index, - Name: runStatus.Name, - Phase: v1alpha1.StepPluginPhaseRunning, + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseSuccessful, + Operation: v1alpha1.StepPluginOperationTerminate, }, } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index f57d3d5be2..17a3d83e9c 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -72,7 +72,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { result.RequeueAfter = &defaultRequeuDuration - if resp.RequeueAfter < minRequeueDuration { + if resp.RequeueAfter > minRequeueDuration { result.RequeueAfter = &resp.RequeueAfter } } diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index ce7c765eb6..21bc6e5225 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -2,7 +2,6 @@ package plugin import ( "encoding/json" - "strings" "testing" "time" @@ -37,9 +36,10 @@ func Test_stepPlugin_Run(t *testing.T) { Canary: v1alpha1.CanaryStatus{ StepPluginStatuses: []v1alpha1.StepPluginStatus{ { - Index: 0, - Name: p.name, - Status: json.RawMessage("step status value"), + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + Operation: v1alpha1.StepPluginOperationRun, }, }, }, @@ -75,9 +75,10 @@ func Test_stepPlugin_Run(t *testing.T) { Canary: v1alpha1.CanaryStatus{ StepPluginStatuses: []v1alpha1.StepPluginStatus{ { - Index: 0, - Name: p.name, - Status: json.RawMessage("step status value"), + Index: 0, + Name: p.name, + Status: json.RawMessage("step status value"), + Operation: v1alpha1.StepPluginOperationRun, }, }, }, @@ -114,6 +115,7 @@ func Test_stepPlugin_Run(t *testing.T) { Status: json.RawMessage("step status value"), StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, } r := &v1alpha1.Rollout{ Status: v1alpha1.RolloutStatus{ @@ -142,6 +144,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, p.index, status.Index) assert.Equal(t, currentStatus.StartedAt, status.StartedAt) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.NotNil(t, status.FinishedAt) @@ -176,6 +179,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.NotNil(t, status.FinishedAt) assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.Nil(t, result.RequeueAfter) @@ -187,6 +191,7 @@ func Test_stepPlugin_Run(t *testing.T) { Name: p.name, Status: json.RawMessage("step status value"), StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + Operation: v1alpha1.StepPluginOperationRun, } r := &v1alpha1.Rollout{ Status: v1alpha1.RolloutStatus{ @@ -215,11 +220,11 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, p.index, status.Index) assert.NotNil(t, status.StartedAt) assert.Nil(t, status.FinishedAt) - assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Equal(t, rpcResult.RequeueAfter, result.RequeueAfter) + assert.Equal(t, rpcResult.RequeueAfter, *result.RequeueAfter) }) t.Run("Running status without requeue", func(t *testing.T) { p, rpcMock := setup(t) @@ -248,6 +253,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.NotNil(t, status.StartedAt) assert.Nil(t, status.FinishedAt) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.Equal(t, defaultRequeuDuration, *result.RequeueAfter) @@ -280,9 +286,10 @@ func Test_stepPlugin_Run(t *testing.T) { assert.NotNil(t, status.StartedAt) assert.Nil(t, status.FinishedAt) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Equal(t, minRequeueDuration, *result.RequeueAfter) + assert.Equal(t, defaultRequeuDuration, *result.RequeueAfter) }) t.Run("Failed status", func(t *testing.T) { p, rpcMock := setup(t) @@ -313,6 +320,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.NotNil(t, status.FinishedAt) assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.Nil(t, result.RequeueAfter) @@ -324,6 +332,7 @@ func Test_stepPlugin_Run(t *testing.T) { Name: p.name, Status: json.RawMessage("step status value"), StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + Operation: v1alpha1.StepPluginOperationRun, } r := &v1alpha1.Rollout{ Status: v1alpha1.RolloutStatus{ @@ -355,6 +364,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, p.index, status.Index) assert.Equal(t, currentStatus.StartedAt, status.StartedAt) assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, expectedError.Error(), status.Message) assert.Equal(t, currentStatus.Status, status.Status) assert.NotNil(t, status.FinishedAt) @@ -381,6 +391,7 @@ func Test_stepPlugin_Terminate(t *testing.T) { Status: json.RawMessage("step status value"), StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, } } newRollout := func(s *v1alpha1.StepPluginStatus) *v1alpha1.Rollout { @@ -395,10 +406,26 @@ func Test_stepPlugin_Terminate(t *testing.T) { } } - t.Run("Return existing status if not running", func(t *testing.T) { + t.Run("Return nil status if not running", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + currentStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + currentStatus.Operation = v1alpha1.StepPluginOperationRun + r := newRollout(currentStatus) + + rpcMock.On("Terminate", mock.Anything, mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") + + status, err := p.Terminate(r) + + require.NoError(t, err) + assert.Nil(t, status) + }) + + t.Run("Return nil status if already terminated", func(t *testing.T) { p, rpcMock := setup(t) currentStatus := newRunningStatus() currentStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + currentStatus.Operation = v1alpha1.StepPluginOperationTerminate r := newRollout(currentStatus) rpcMock.On("Terminate", mock.Anything, mock.Anything).Maybe().Panic("Terminate should not be called when plugin is not running") @@ -406,7 +433,7 @@ func Test_stepPlugin_Terminate(t *testing.T) { status, err := p.Terminate(r) require.NoError(t, err) - assert.Equal(t, currentStatus, status) + assert.Nil(t, status) }) t.Run("Running phase overridden to failed if running", func(t *testing.T) { p, rpcMock := setup(t) @@ -426,13 +453,12 @@ func Test_stepPlugin_Terminate(t *testing.T) { require.NoError(t, err) assert.Equal(t, p.name, status.Name) assert.Equal(t, p.index, status.Index) - assert.Equal(t, currentStatus.StartedAt, status.StartedAt) assert.NotNil(t, status.FinishedAt) assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginOperationTerminate, status.Operation) assert.Equal(t, v1alpha1.StepPluginPhaseFailed, status.Phase) - assert.Contains(t, status.Message, rpcResult.Message) - assert.True(t, strings.HasPrefix(status.Message, "Terminated:")) - assert.Equal(t, rpcResult.Status, status.Status) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Nil(t, status.Status) }) t.Run("Completes successfully", func(t *testing.T) { p, rpcMock := setup(t) @@ -453,13 +479,12 @@ func Test_stepPlugin_Terminate(t *testing.T) { assert.Equal(t, p.name, status.Name) assert.Equal(t, p.index, status.Index) - assert.Equal(t, currentStatus.StartedAt, status.StartedAt) assert.NotNil(t, status.FinishedAt) assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) - assert.Contains(t, status.Message, rpcResult.Message) - assert.True(t, strings.HasPrefix(status.Message, "Terminated:")) - assert.Equal(t, rpcResult.Status, status.Status) + assert.Equal(t, v1alpha1.StepPluginOperationTerminate, status.Operation) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Nil(t, status.Status) }) t.Run("Error status", func(t *testing.T) { @@ -484,12 +509,11 @@ func Test_stepPlugin_Terminate(t *testing.T) { assert.Equal(t, p.name, status.Name) assert.Equal(t, p.index, status.Index) - assert.Equal(t, currentStatus.StartedAt, status.StartedAt) assert.NotNil(t, status.FinishedAt) assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginOperationTerminate, status.Operation) assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) assert.Contains(t, status.Message, expectedError.Error()) - assert.True(t, strings.HasPrefix(status.Message, "Terminated:")) - assert.Equal(t, currentStatus.Status, status.Status) + assert.Nil(t, status.Status) }) } From 37171bd53c672a080cc3d077ae91ad3e204092b2 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 15 Apr 2024 09:24:49 -0400 Subject: [PATCH 12/41] abort test Signed-off-by: Alexandre Gaudreault --- rollout/steps/plugin/plugin.go | 2 +- rollout/steps/plugin/plugin_test.go | 161 ++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 17a3d83e9c..7a3ac9ad08 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -145,7 +145,7 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu Operation: v1alpha1.StepPluginOperationAbort, Phase: v1alpha1.StepPluginPhaseSuccessful, } - resp, err := p.rpc.Terminate(rollout.DeepCopy(), p.getStepContext(stepStatus)) + resp, err := p.rpc.Abort(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() if err.HasError() { abortStatus.Phase = v1alpha1.StepPluginPhaseError diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index 21bc6e5225..aa4a295fcd 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -517,3 +517,164 @@ func Test_stepPlugin_Terminate(t *testing.T) { assert.Nil(t, status.Status) }) } + +func Test_stepPlugin_Abort(t *testing.T) { + setup := func(t *testing.T) (*stepPlugin, *mocks.StepPlugin) { + plugin := &stepPlugin{ + name: "test-plugin", + index: 0, + config: json.RawMessage("value"), + log: log.WithFields(log.Fields{}), + } + rpcPluginMock := mocks.NewStepPlugin(t) + plugin.rpc = rpcPluginMock + return plugin, rpcPluginMock + } + newRunningStatus := func() *v1alpha1.StepPluginStatus { + return &v1alpha1.StepPluginStatus{ + Index: 0, + Name: "test-plugin", + Status: json.RawMessage("step status value"), + StartedAt: &v1.Time{Time: time.Now().Add(30 * time.Minute * -1)}, + Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, + } + } + newRollout := func(s *v1alpha1.StepPluginStatus) *v1alpha1.Rollout { + return &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + *s, + }, + }, + }, + } + } + + t.Run("Return nil status if run is in error", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + currentStatus.Phase = v1alpha1.StepPluginPhaseError + currentStatus.Operation = v1alpha1.StepPluginOperationRun + r := newRollout(currentStatus) + + rpcMock.On("Abort", mock.Anything, mock.Anything).Maybe().Panic("Abort should not be called when plugin is not running or copmpleted") + + status, err := p.Abort(r) + + require.NoError(t, err) + assert.Nil(t, status) + }) + + t.Run("Return nil status if run has failed", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + currentStatus.Phase = v1alpha1.StepPluginPhaseFailed + currentStatus.Operation = v1alpha1.StepPluginOperationRun + r := newRollout(currentStatus) + + rpcMock.On("Abort", mock.Anything, mock.Anything).Maybe().Panic("Abort should not be called when plugin is not running or completed") + + status, err := p.Abort(r) + + require.NoError(t, err) + assert.Nil(t, status) + }) + + t.Run("Return nil status if already aborted", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + currentStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + currentStatus.Operation = v1alpha1.StepPluginOperationAbort + r := newRollout(currentStatus) + + rpcMock.On("Abort", mock.Anything, mock.Anything).Maybe().Panic("Abort should not be called when plugin is not running") + + status, err := p.Abort(r) + + require.NoError(t, err) + assert.Nil(t, status) + }) + t.Run("Running phase overridden to failed if running", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + r := newRollout(currentStatus) + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseRunning, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Abort", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}) + + status, err := p.Abort(r) + + require.NoError(t, err) + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginOperationAbort, status.Operation) + assert.Equal(t, v1alpha1.StepPluginPhaseFailed, status.Phase) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Nil(t, status.Status) + }) + t.Run("Completes successfully", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + r := newRollout(currentStatus) + + rpcResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "Good message", + RequeueAfter: time.Hour, + Status: json.RawMessage("status"), + } + rpcMock.On("Abort", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}) + + status, err := p.Abort(r) + + require.NoError(t, err) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) + assert.Equal(t, v1alpha1.StepPluginOperationAbort, status.Operation) + assert.Equal(t, rpcResult.Message, status.Message) + assert.Nil(t, status.Status) + }) + + t.Run("Error status", func(t *testing.T) { + p, rpcMock := setup(t) + currentStatus := newRunningStatus() + r := newRollout(currentStatus) + + invalidResult := types.RpcStepResult{ + Phase: types.PhaseSuccessful, + Message: "This message should not be used", + RequeueAfter: time.Hour, + Status: json.RawMessage("invalid status"), + } + expectedError := types.RpcError{ + ErrorString: "This is an error", + } + rpcMock.On("Abort", mock.Anything, mock.Anything).Return(invalidResult, expectedError) + + status, err := p.Abort(r) + + require.NoError(t, err) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.NotNil(t, status.FinishedAt) + assert.Greater(t, status.FinishedAt.Time, status.StartedAt.Time) + assert.Equal(t, v1alpha1.StepPluginOperationAbort, status.Operation) + assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) + assert.Contains(t, status.Message, expectedError.Error()) + assert.Nil(t, status.Status) + }) +} From c6e2a98ac0145d03dd880d66bbdc7ba1ce989766 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 15 Apr 2024 09:47:16 -0400 Subject: [PATCH 13/41] load plugin Signed-off-by: Alexandre Gaudreault --- utils/config/config.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/utils/config/config.go b/utils/config/config.go index 7989374e8e..310ca64680 100644 --- a/utils/config/config.go +++ b/utils/config/config.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "regexp" + "slices" "sync" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,10 +52,15 @@ func InitializeConfig(k8sClientset kubernetes.Interface, configMapName string) ( return nil, fmt.Errorf("failed to unmarshal metric provider plugins while initializing: %w", err) } + var stepPlugins []types.PluginItem + if err = yaml.Unmarshal([]byte(configMapCluster.Data["stepPlugins"]), &stepPlugins); err != nil { + return nil, fmt.Errorf("failed to unmarshal step plugins while initializing: %w", err) + } + mutex.Lock() configMemoryCache = &Config{ configMap: configMapCluster, - plugins: append(trafficRouterPlugins, metricProviderPlugins...), + plugins: slices.Concat(trafficRouterPlugins, metricProviderPlugins, stepPlugins), } mutex.Unlock() From 790bc1b55db99c090fb7fb9e4ecdd31e6186caa8 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 15 Apr 2024 16:28:30 -0400 Subject: [PATCH 14/41] more tests Signed-off-by: Alexandre Gaudreault --- .../internal/plugin/plugin.go | 80 +++- .../internal/plugin/plugin_test.go | 368 ++++++++++++++++++ test/cmd/step-plugin-sample/main_test.go | 107 +++++ 3 files changed, 539 insertions(+), 16 deletions(-) create mode 100644 test/cmd/step-plugin-sample/internal/plugin/plugin_test.go create mode 100644 test/cmd/step-plugin-sample/main_test.go diff --git a/test/cmd/step-plugin-sample/internal/plugin/plugin.go b/test/cmd/step-plugin-sample/internal/plugin/plugin.go index 44bec6e9da..de2341dfd1 100644 --- a/test/cmd/step-plugin-sample/internal/plugin/plugin.go +++ b/test/cmd/step-plugin-sample/internal/plugin/plugin.go @@ -12,7 +12,7 @@ import ( "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" "github.com/argoproj/argo-rollouts/utils/plugin/types" "github.com/google/uuid" - "github.com/sirupsen/logrus" + log "github.com/sirupsen/logrus" ) type Config struct { @@ -33,7 +33,7 @@ type Result struct { } type rpcPlugin struct { - LogCtx *logrus.Entry + LogCtx *log.Entry Seed int64 lock *sync.RWMutex @@ -41,7 +41,7 @@ type rpcPlugin struct { randomMap map[string]*Result } -func New(logCtx *logrus.Entry, seed int64) rpc.StepPlugin { +func New(logCtx *log.Entry, seed int64) rpc.StepPlugin { return &rpcPlugin{ LogCtx: logCtx, Seed: seed, @@ -54,7 +54,7 @@ func (p *rpcPlugin) InitPlugin() types.RpcError { defer p.lock.Unlock() p.LogCtx.Infof("InitPlugin with seed %d", p.Seed) - rand.New(rand.NewSource(p.Seed)) + p.generator = rand.New(rand.NewSource(p.Seed)) p.randomMap = map[string]*Result{} return types.RpcError{} } @@ -68,11 +68,15 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext var config Config var state State if context != nil { - if err := json.Unmarshal(context.Config, &config); err != nil { - return types.RpcStepResult{}, types.RpcError{ErrorString: "could not unmarshal config"} + if context.Config != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal config: %w", err).Error()} + } } - if err := json.Unmarshal(context.Status, &state); err != nil { - return types.RpcStepResult{}, types.RpcError{ErrorString: "could not unmarshal status"} + if context.Status != nil { + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal status: %w", err).Error()} + } } } @@ -81,7 +85,8 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext return CompletedResult(state) } - if config.Aggregate && state.SharedId != "" { + // If Aggregate, look for previous steps. We want to re-use the value in memory for that step id + if config.Aggregate && state.SharedId == "" { lastStep := getLastStep(rollout, context.PluginName) if lastStep != nil { var lastState State @@ -89,20 +94,23 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext return types.RpcStepResult{}, types.RpcError{ErrorString: "could not unmarshal last step status"} } if lastState.SharedId != "" { + // consecutive aggregate steps all use the same id state.SharedId = lastState.SharedId } else { + // Most likely the last step was not an aggregate, so we restart a sequence with this id state.SharedId = lastState.Id } } } - // Already started + // Already started, look if it is completed if state.Id != "" { p.lock.RLock() v, ok := p.randomMap[state.getId()] p.lock.RUnlock() if ok { if v.Id == state.Id { + // Make sure the current step is the one that updated the value state.Value = strconv.Itoa(v.Value) return CompletedResult(state) } @@ -125,16 +133,54 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext } -func (p *rpcPlugin) Terminate(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { +func (p *rpcPlugin) Terminate(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + // Get configs + var config Config + var state State + if context != nil { + if context.Config != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal config: %w", err).Error()} + } + } + if context.Status != nil { + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal status: %w", err).Error()} + } + } + } + + log.Infof("Ignoring future value for '%s'", state.Id) + state.Value = "0" + return CompletedResult(state) - // probably need to use channel to cancel the sleep and not generate a number - panic("not implemented") // TODO: Implement } -func (p *rpcPlugin) Abort(_ *v1alpha1.Rollout, _ *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { +func (p *rpcPlugin) Abort(_ *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + + // Get configs + var config Config + var state State + if context != nil { + if context.Config != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal config: %w", err).Error()} + } + } + if context.Status != nil { + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal status: %w", err).Error()} + } + } + } - // just for show, set value to zero - panic("not implemented") // TODO: Implement + p.lock.Lock() + defer p.lock.Unlock() + + log.Infof("deleting entry for id '%s'", state.getId()) + delete(p.randomMap, state.getId()) + + return CompletedResult(state) } func (p *rpcPlugin) Type() string { @@ -153,6 +199,7 @@ func (p *rpcPlugin) generate(state State) *Result { if state.SharedId != "" { v, ok := p.randomMap[state.SharedId] if ok { + log.Infof("Using base '%d' for aggregate %s", v.Value, state.SharedId) base = v.Value } } @@ -162,6 +209,7 @@ func (p *rpcPlugin) generate(state State) *Result { Id: state.Id, } p.randomMap[state.getId()] = result + log.Infof("Set '%d' for id %s", result.Value, state.getId()) return result } diff --git a/test/cmd/step-plugin-sample/internal/plugin/plugin_test.go b/test/cmd/step-plugin-sample/internal/plugin/plugin_test.go new file mode 100644 index 0000000000..97897217c0 --- /dev/null +++ b/test/cmd/step-plugin-sample/internal/plugin/plugin_test.go @@ -0,0 +1,368 @@ +package plugin + +import ( + "encoding/json" + "sync" + "testing" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/utils/ptr" +) + +func new(logCtx *log.Entry, seed int64) *rpcPlugin { + return &rpcPlugin{ + LogCtx: logCtx, + Seed: seed, + lock: &sync.RWMutex{}, + } +} + +func newRollout() *v1alpha1.Rollout { + return &v1alpha1.Rollout{ + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{}, + }, + }, + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{}, + }, + } +} + +func getStateFromResult(t *testing.T, result types.RpcStepResult) *State { + require.NotNil(t, result) + + var state *State + if err := json.Unmarshal(result.Status, &state); err != nil { + require.NotNil(t, err) + } + return state +} + +func toRaw(obj any) json.RawMessage { + raw, err := json.Marshal(obj) + if err != nil { + panic(err) + } + return raw +} + +func Test_rpcPlugin_Run(t *testing.T) { + t.Run("Return value with nil context", func(t *testing.T) { + p := New(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + + rollout := newRollout() + + got, err := p.Run(rollout, nil) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "74", state.Value) + + }) + t.Run("Return value with empty context", func(t *testing.T) { + p := New(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + + rollout := newRollout() + context := &types.RpcStepContext{ + PluginName: "test", + Config: nil, + Status: nil, + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "74", state.Value) + + }) + + t.Run("Return value with existing state", func(t *testing.T) { + p := New(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + + rollout := newRollout() + context := &types.RpcStepContext{ + PluginName: "test", + Config: nil, + Status: toRaw(&State{ + Id: "fake-id", + Value: "123", + }), + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "123", state.Value) + }) + + t.Run("Running status with async config", func(t *testing.T) { + p := New(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + + rollout := newRollout() + context := &types.RpcStepContext{ + PluginName: "test", + Config: toRaw(&Config{ + Async: true, + }), + Status: nil, + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseRunning, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "", state.Value) + }) + + t.Run("Return running with async config and existing state not completed", func(t *testing.T) { + p := new(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + + rollout := newRollout() + context := &types.RpcStepContext{ + PluginName: "test", + Config: toRaw(&Config{ + Async: true, + }), + Status: toRaw(&State{ + Id: "fake-id", + }), + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseRunning, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "", state.Value) + }) + + t.Run("Return value with async config and existing state", func(t *testing.T) { + p := new(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + p.randomMap["fake-id"] = &Result{ + Value: 44, + Id: "fake-id", + } + + rollout := newRollout() + context := &types.RpcStepContext{ + PluginName: "test", + Config: toRaw(&Config{ + Async: true, + }), + Status: toRaw(&State{ + Id: "fake-id", + }), + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "44", state.Value) + }) + + t.Run("Return value with aggregate and no previous step", func(t *testing.T) { + p := new(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + p.randomMap["foo"] = &Result{ + Value: 6, + Id: "foo", + } + + rollout := newRollout() + rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + } + rollout.Status.CurrentStepIndex = ptr.To(int32(0)) + rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test", + Status: toRaw(&State{ + Id: "foo", + Value: "99", + }), + }, + } + context := &types.RpcStepContext{ + PluginName: "test", + Config: toRaw(&Config{ + Aggregate: true, + }), + Status: nil, + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "74", state.Value) + }) + + t.Run("Return value with aggregate", func(t *testing.T) { + p := new(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + p.randomMap["foo"] = &Result{ + Value: 6, + Id: "foo", + } + + rollout := newRollout() + rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + } + rollout.Status.CurrentStepIndex = ptr.To(int32(1)) + rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test", + Status: toRaw(&State{ + Id: "foo", + Value: "6", + }), + }, + } + context := &types.RpcStepContext{ + PluginName: "test", + Config: toRaw(&Config{ + Aggregate: true, + }), + Status: nil, + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "80", state.Value) + }) + + t.Run("Return value with aggregate of an aggregate", func(t *testing.T) { + p := new(log.WithFields(log.Fields{}), 0) + err := p.InitPlugin() + if err.HasError() { + t.Fatalf("Got error during init: %s", err.Error()) + } + p.randomMap["foo"] = &Result{ + Value: 80, + Id: "bar", + } + + rollout := newRollout() + rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test", + }, + }, + } + rollout.Status.CurrentStepIndex = ptr.To(int32(2)) + rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test", + Status: toRaw(&State{ + Id: "foo", + Value: "6", + }), + }, + { + Index: 1, + Name: "test", + Status: toRaw(&State{ + Id: "bar", + SharedId: "foo", + Value: "80", + }), + }, + } + context := &types.RpcStepContext{ + PluginName: "test", + Config: toRaw(&Config{ + Aggregate: true, + }), + Status: nil, + } + + got, err := p.Run(rollout, context) + + require.False(t, err.HasError(), "Error: %s", err.Error()) + assert.Equal(t, types.PhaseSuccessful, got.Phase) + state := getStateFromResult(t, got) + assert.Equal(t, "154", state.Value) + }) + +} diff --git a/test/cmd/step-plugin-sample/main_test.go b/test/cmd/step-plugin-sample/main_test.go new file mode 100644 index 0000000000..17bc5730b7 --- /dev/null +++ b/test/cmd/step-plugin-sample/main_test.go @@ -0,0 +1,107 @@ +package main + +import ( + "context" + "testing" + "time" + + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + rolloutsPlugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/test/cmd/step-plugin-sample/internal/plugin" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + goPlugin "github.com/hashicorp/go-plugin" + log "github.com/sirupsen/logrus" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/tj/assert" +) + +var testHandshake = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "step", +} + +func pluginClient(t *testing.T) (rpc.StepPlugin, goPlugin.ClientProtocol, func(), chan struct{}) { + ctx, cancel := context.WithCancel(context.Background()) + + pluginImpl := plugin.New(log.WithFields(log.Fields{}), 0) + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcStepPlugin": &rolloutsPlugin.RpcStepPlugin{Impl: pluginImpl}, + } + + 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("RpcStepPlugin") + if err != nil { + t.Fail() + } + + plugin, ok := raw.(rpc.StepPlugin) + if !ok { + t.Fail() + } + + return plugin, client, cancel, closeCh +} + +func TestPlugin(t *testing.T) { + plugin, _, cancel, closeCh := pluginClient(t) + defer cancel() + + err := plugin.InitPlugin() + if err.Error() != "" { + t.Fail() + } + + ro := v1alpha1.Rollout{} + rpcCtx := &types.RpcStepContext{ + PluginName: "test-1", + Config: nil, + Status: nil, + } + + result, err := plugin.Run(&ro, rpcCtx) + assert.Equal(t, "", err.Error()) + assert.NotNil(t, result) + + // Canceling should cause an exit + cancel() + <-closeCh +} From c25ce26028e2b136802aa3714c41c1b1463f401a Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 15 Apr 2024 16:55:33 -0400 Subject: [PATCH 15/41] dont use newStatus Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 984f401328..f85ca9f7cf 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -90,11 +90,12 @@ func (c *rolloutContext) calculateStepPluginStatus() []v1alpha1.StepPluginStatus } func (c *rolloutContext) isStepPluginCompleted(stepIndex int32) bool { - runStatus := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex, v1alpha1.StepPluginOperationRun) + updatedPluginStatus := c.calculateStepPluginStatus() + runStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationRun) isRunning := runStatus != nil && runStatus.Phase == v1alpha1.StepPluginPhaseRunning if isRunning { - terminateStatus := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex, v1alpha1.StepPluginOperationTerminate) - abortStatus := findCurrentStepStatus(c.newStatus.Canary.StepPluginStatuses, stepIndex, v1alpha1.StepPluginOperationAbort) + terminateStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationTerminate) + abortStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationAbort) isRunning = terminateStatus == nil && abortStatus == nil } return runStatus != nil && ((!isRunning && runStatus.Phase == v1alpha1.StepPluginPhaseRunning) || runStatus.Phase == v1alpha1.StepPluginPhaseFailed || runStatus.Phase == v1alpha1.StepPluginPhaseSuccessful) From 5ed7955a5616a0f2c8fdda556771544f40386acf Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 15 Apr 2024 16:56:15 -0400 Subject: [PATCH 16/41] codegen preserve fields Signed-off-by: Alexandre Gaudreault --- manifests/crds/rollout-crd.yaml | 4 ++-- manifests/install.yaml | 4 ++-- pkg/apiclient/rollout/rollout.swagger.json | 3 ++- pkg/apis/rollouts/v1alpha1/generated.proto | 3 +++ pkg/apis/rollouts/v1alpha1/types.go | 6 +++++- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index f20783133c..b084183c88 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -3748,8 +3748,8 @@ spec: format: date-time type: string status: - format: byte - type: string + type: object + x-kubernetes-preserve-unknown-fields: true required: - index - name diff --git a/manifests/install.yaml b/manifests/install.yaml index 34815cff40..3cd5d85f5e 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -16238,8 +16238,8 @@ spec: format: date-time type: string status: - format: byte - type: string + type: object + x-kubernetes-preserve-unknown-fields: true required: - index - name diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index e27b980946..d1d9b8c1d9 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -2551,7 +2551,8 @@ }, "status": { "type": "string", - "format": "byte" + "format": "byte", + "title": "+kubebuilder:validation:Schemaless\n+kubebuilder:pruning:PreserveUnknownFields\n+kubebuilder:validation:Type=object" } } }, diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 12b7d084d6..a2d6087480 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1769,6 +1769,9 @@ message StepPluginStatus { optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 7; + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Type=object optional bytes status = 8; } diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 4b8151e2c4..45a6762e72 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -1046,7 +1046,11 @@ type StepPluginStatus struct { Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,6,name=startedAt"` FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,7,opt,name=finishedAt"` - Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,8,opt,name=status"` + + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Type=object + Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,8,opt,name=status"` } // StepPluginPhase is the overall phase of a StepPlugin From a0c30c95a1ec281881e8cb1b8cb5ec27af8bdf80 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Thu, 18 Apr 2024 11:08:55 -0400 Subject: [PATCH 17/41] some test before full promote problem Signed-off-by: Alexandre Gaudreault --- Makefile | 16 +- docs/CONTRIBUTING.md | 80 ++++---- pkg/apis/rollouts/v1alpha1/types.go | 13 ++ rollout/stepplugin.go | 6 +- rollout/steps/plugin/plugin.go | 14 ++ .../step-plugin-e2e/internal/plugin/plugin.go | 178 ++++++++++++++++++ test/cmd/step-plugin-e2e/main.go | 60 ++++++ test/e2e/canary_test.go | 2 +- .../e2e/step-plugin/argo-rollouts-config.yaml | 17 ++ test/e2e/step-plugin/template-rollout.yaml | 31 +++ test/e2e/step-plugin/test.yaml | 34 ++++ test/e2e/step_plugin_test.go | 138 ++++++++++++++ test/fixtures/common.go | 12 ++ test/fixtures/given.go | 7 +- test/fixtures/when.go | 12 ++ utils/plugin/types/steps.go | 13 ++ utils/plugin/types/types.go | 1 + 17 files changed, 591 insertions(+), 43 deletions(-) create mode 100644 test/cmd/step-plugin-e2e/internal/plugin/plugin.go create mode 100644 test/cmd/step-plugin-e2e/main.go create mode 100644 test/e2e/step-plugin/argo-rollouts-config.yaml create mode 100644 test/e2e/step-plugin/template-rollout.yaml create mode 100644 test/e2e/step-plugin/test.yaml create mode 100644 test/e2e/step_plugin_test.go diff --git a/Makefile b/Makefile index 8dc2821a13..86f2624a73 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ IMAGE_TAG=latest DEV_IMAGE ?= false # E2E variables +E2E_K8S_CONTEXT ?= rancher-desktop E2E_INSTANCE_ID ?= argo-rollouts-e2e E2E_TEST_OPTIONS ?= E2E_PARALLEL ?= 1 @@ -215,11 +216,15 @@ endif # 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: ## build sample metric plugin with debug info - go build -gcflags="all=-N -l" -o metric-plugin test/cmd/metrics-plugin-sample/main.go + go build -gcflags="all=-N -l" -o plugin-bin/metric-plugin test/cmd/metrics-plugin-sample/main.go .PHONY: build-sample-traffic-plugin-debug build-sample-traffic-plugin-debug: ## build sample traffic plugin with debug info - go build -gcflags="all=-N -l" -o traffic-plugin test/cmd/trafficrouter-plugin-sample/main.go + go build -gcflags="all=-N -l" -o plugin-bin/traffic-plugin test/cmd/trafficrouter-plugin-sample/main.go + +.PHONY: build-sample-step-plugin-debug +build-sample-step-plugin-debug: ## build sample traffic plugin with debug info + go build -gcflags="all=-N -l" -o plugin-bin/step-plugin test/cmd/step-plugin-sample/main.go .PHONY: plugin-image plugin-image: ## build plugin image @@ -236,6 +241,13 @@ test: test-kustomize ## run all tests test-kustomize: ## run kustomize tests ./test/kustomize/test.sh +step-plugin-e2e-setup: + @go build -gcflags="all=-N -l" -o plugin-bin/e2e-step-plugin test/cmd/step-plugin-e2e/main.go + @kubectl apply --context='${E2E_K8S_CONTEXT}' -n argo-rollouts -f test/e2e/step-plugin/argo-rollouts-config.yaml + +step-plugin-e2e-run: + ${DIST_DIR}/gotestsum --rerun-fails-report=rerunreport.txt --junitfile=junit.xml --format=testname --packages="./test/e2e" --rerun-fails=0 -- -timeout 60m -count 1 --tags e2e -p ${E2E_PARALLEL} -parallel ${E2E_PARALLEL} -v --short ./test/e2e -run 'TestStepPluginSuite' + .PHONY: start-e2e start-e2e: ## start e2e test environment go run ./cmd/rollouts-controller/main.go --instance-id ${E2E_INSTANCE_ID} --loglevel debug --kloglevel 6 diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index f727834d8b..54bb7cb939 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,24 +1,27 @@ # Contributing + ## Before You Start + Argo Rollouts is written in Golang. If you do not have a good grounding in Go, try out [the tutorial](https://tour.golang.org/). ## Pre-requisites + Install: -* [docker](https://docs.docker.com/install/#supported-platforms) -* [golang](https://golang.org/) -* [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) -* [kustomize](https://github.com/kubernetes-sigs/kustomize/releases) >= 4.5.5 -* [k3d](https://k3d.io/) recommended +- [docker](https://docs.docker.com/install/#supported-platforms) +- [golang](https://golang.org/) +- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) +- [kustomize](https://github.com/kubernetes-sigs/kustomize/releases) >= 4.5.5 +- [k3d](https://k3d.io/) recommended Kustomize is required for unit tests (`make test` is using it), so you [must install it](https://kubectl.docs.kubernetes.io/installation/kustomize/) locally if you wish to make code contributions to Argo Rollouts. Argo Rollout additionally uses the following tools -* `golangci-lint` to lint the project. -* `protoc` and `swagger-codegen` to generate proto related files -* `yarn` to build the UI +- `golangci-lint` to lint the project. +- `protoc` and `swagger-codegen` to generate proto related files +- `yarn` to build the UI Run the following commands to install them: @@ -56,10 +59,9 @@ cd ~/go/src/github.com/argoproj/argo-rollouts The `make controller` command will build the controller. -* `make install-tools-local` - Runs scripts to install codegen utility CLIs necessary for codegen. - -* `make codegen` - Runs the code generator that creates the informers, client, lister, and deepcopies from the types.go and modifies the open-api spec. +- `make install-tools-local` - Runs scripts to install codegen utility CLIs necessary for codegen. +- `make codegen` - Runs the code generator that creates the informers, client, lister, and deepcopies from the types.go and modifies the open-api spec. ## Running Controller Locally @@ -83,11 +85,7 @@ make test ## Running E2E tests The end-to-end tests need to run against a kubernetes cluster with the Argo Rollouts controller -running. The rollout controller can be started with the command: - -``` -make start-e2e -``` +running. Start and prepare your cluster for e2e tests: @@ -98,6 +96,12 @@ kubectl apply -k manifests/crds kubectl apply -f test/e2e/crds ``` +The rollout controller can be started with the command: + +``` +make start-e2e +``` + Then run the e2e tests: ``` @@ -112,9 +116,10 @@ E2E_TEST_OPTIONS="-run 'TestCanarySuite' -testify.m 'TestCanaryScaleDownOnAbortN ## Running the UI -If you'd like to run the UI locally, you first need a running Rollouts controller. This can be a locally running controller with a k3d cluster, as described above, or a controller running in a remote Kubernetes cluster. +If you'd like to run the UI locally, you first need a running Rollouts controller. This can be a locally running controller with a k3d cluster, as described above, or a controller running in a remote Kubernetes cluster. In order for the local React app to communicate with the controller and Kubernetes API, run the following to open a port forward to the dashboard: + ```bash kubectl argo rollouts dashboard ``` @@ -127,6 +132,7 @@ make plugin ``` In another terminal, run the following to start the UI: + ```bash cd ui yarn install @@ -142,11 +148,11 @@ that handle a specific aspect of Progressive Delivery. The controllers are: -* [Rollout Controller](https://github.com/argoproj/argo-rollouts/blob/master/rollout/controller.go) -* [Service Controller](https://github.com/argoproj/argo-rollouts/blob/master/service/service.go) -* [Ingress Controller](https://github.com/argoproj/argo-rollouts/blob/master/ingress/ingress.go) -* [Experiment Controller](https://github.com/argoproj/argo-rollouts/blob/master/experiments/controller.go) -* [AnalysisRun Controller](https://github.com/argoproj/argo-rollouts/blob/master/analysis/controller.go) +- [Rollout Controller](https://github.com/argoproj/argo-rollouts/blob/master/rollout/controller.go) +- [Service Controller](https://github.com/argoproj/argo-rollouts/blob/master/service/service.go) +- [Ingress Controller](https://github.com/argoproj/argo-rollouts/blob/master/ingress/ingress.go) +- [Experiment Controller](https://github.com/argoproj/argo-rollouts/blob/master/experiments/controller.go) +- [AnalysisRun Controller](https://github.com/argoproj/argo-rollouts/blob/master/analysis/controller.go) ### Tips @@ -158,36 +164,35 @@ KUBECONFIG=~/.kube/minikube make test-e2e ``` 2. To run a specific e2e test, set the `E2E_TEST_OPTIONS` environment variable to specify the test -(or test regex): + (or test regex): ```shell make test-e2e E2E_TEST_OPTIONS="-testify.m ^TestRolloutRestart$" ``` 3. The e2e tests are designed to run as quickly as possible, eliminating readiness and termination -delays. However, it is often desired to artificially slow down the tests for debugging purposes, -as well as to understand what the test is doing. To delay startup and termination of pods, set the -`E2E_POD_DELAY` to an integer value in seconds. This environment variable is often coupled with -`E2E_TEST_OPTIONS` to debug and slow down a specific test. + delays. However, it is often desired to artificially slow down the tests for debugging purposes, + as well as to understand what the test is doing. To delay startup and termination of pods, set the + `E2E_POD_DELAY` to an integer value in seconds. This environment variable is often coupled with + `E2E_TEST_OPTIONS` to debug and slow down a specific test. ```shell make test-e2e E2E_POD_DELAY=10 ``` 4. Increasing the timeout. The E2E tests time out waiting on conditions to be met within 60 seconds. -If debugging the rollout controller, it may be useful to increase this timeout while say sitting -at a debugger breakpoint: + If debugging the rollout controller, it may be useful to increase this timeout while say sitting + at a debugger breakpoint: ```shell make test-e2e E2E_WAIT_TIMEOUT=999999 ``` - 5. The e2e tests leverage a feature of the controller allowing the controller to be sharded with -a user-specific "instance id" label. This allows the tests to operate only on rollouts with the -specified label, and prevents any other controllers (including the system rollout controller), -from also operating on the same set of rollouts. This value can be changed (from the default of -`argo-rollouts-e2e`), using the `E2E_INSTANCE_ID` environment variable: + a user-specific "instance id" label. This allows the tests to operate only on rollouts with the + specified label, and prevents any other controllers (including the system rollout controller), + from also operating on the same set of rollouts. This value can be changed (from the default of + `argo-rollouts-e2e`), using the `E2E_INSTANCE_ID` environment variable: ```shell make start-e2e E2E_INSTANCE_ID=foo @@ -200,7 +205,6 @@ Alternatively, the e2e tests can be run against the system controller (i.e. with make start-e2e E2E_INSTANCE_ID='' ``` - 6. Working on CRDs? While editing them directly works when you are finding the shape of things you want, the final CRDs are autogenerated. Make sure to regenerate them before submitting PRs. They are controlled by the relevant annotations in the types file: eg: Analysis Templates are controlled by annotations in `pkg/apis/rollouts/v1alpha1/analysis_types.go`. @@ -242,14 +246,16 @@ kubectl -n argo-rollouts apply -f manifests/install.yaml ``` ## Upgrading Kubernetes Libraries + Argo Rollouts has a dependency on the kubernetes/kubernetes repo for some of the functionality that has not been pushed into the other kubernetes repositories yet. In order to import the kubernetes/kubernetes repo, all of the associated repos have to pinned to the correct version specified by the kubernetes/kubernetes release. The `./hack/update-k8s-dependencies.sh` updates all the dependencies to the those correct versions. ## Upgrading Notifications Engine -Argo Rollouts has a dependency on the [argoproj/notifications-engines](https://github.com/argoproj/notifications-engine) repo -for the notifications functionality and related documentation. + +Argo Rollouts has a dependency on the [argoproj/notifications-engines](https://github.com/argoproj/notifications-engine) repo +for the notifications functionality and related documentation. This is updated by upgrading the Go library in `go.mod` by running the commands: diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 45a6762e72..6d4bcbfc46 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -2,6 +2,7 @@ package v1alpha1 import ( "encoding/json" + fmt "fmt" "strconv" "time" @@ -1064,6 +1065,18 @@ const ( StepPluginPhaseError StepPluginPhase = "Error" ) +func (p StepPluginPhase) Validate() error { + switch p { + case StepPluginPhaseRunning: + case StepPluginPhaseSuccessful: + case StepPluginPhaseFailed: + case StepPluginPhaseError: + default: + return fmt.Errorf("phase '%s' is not valid", p) + } + return nil +} + type StepPluginOperation string // Possible StepPluginOperation values diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index f85ca9f7cf..75e816abbb 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -63,7 +63,11 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { } c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) - if status.Phase == v1alpha1.StepPluginPhaseRunning && result.RequeueAfter != nil { + if status == nil { + return nil + } + + if status.Phase == v1alpha1.StepPluginPhaseRunning && result != nil && result.RequeueAfter != nil { c.enqueueRolloutAfter(c.rollout, *result.RequeueAfter) return nil } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 7a3ac9ad08..5737b284ed 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -2,6 +2,7 @@ package plugin import ( "encoding/json" + "fmt" "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" @@ -49,6 +50,10 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, Phase: v1alpha1.StepPluginPhaseRunning, } } + if stepStatus.Phase == v1alpha1.StepPluginPhaseSuccessful || stepStatus.Phase == v1alpha1.StepPluginPhaseFailed { + return nil, nil, nil + } + resp, err := p.rpc.Run(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() if err.HasError() { @@ -62,6 +67,9 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, stepStatus.Message = resp.Message if resp.Phase != "" { stepStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + if err := stepStatus.Phase.Validate(); err != nil { + return nil, nil, fmt.Errorf("could not validate rpc phase: %w", err) + } } if stepStatus.Phase == v1alpha1.StepPluginPhaseSuccessful || stepStatus.Phase == v1alpha1.StepPluginPhaseFailed { @@ -112,6 +120,9 @@ func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginS if resp.Phase != "" { terminateStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + if err := terminateStatus.Phase.Validate(); err != nil { + return nil, fmt.Errorf("could not validate rpc phase: %w", err) + } } if terminateStatus.Phase == v1alpha1.StepPluginPhaseRunning { @@ -156,6 +167,9 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu if resp.Phase != "" { abortStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) + if err := abortStatus.Phase.Validate(); err != nil { + return nil, fmt.Errorf("could not validate rpc phase: %w", err) + } } if abortStatus.Phase == v1alpha1.StepPluginPhaseRunning { diff --git a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go new file mode 100644 index 0000000000..3d6cc606e9 --- /dev/null +++ b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go @@ -0,0 +1,178 @@ +package plugin + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +type Config struct { + Return string + Requeue string + + Abort Abort + Terminate Terminate +} + +type Abort struct { + Return string +} + +type Terminate struct { + Return string +} + +type State struct { + Data string +} + +type rpcPlugin struct { + LogCtx *log.Entry +} + +func New(logCtx *log.Entry) rpc.StepPlugin { + return &rpcPlugin{ + LogCtx: logCtx, + } +} + +func (p *rpcPlugin) InitPlugin() types.RpcError { + p.LogCtx.Infof("InitPlugin") + return types.RpcError{} +} + +func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + p.LogCtx.Infof("Run plugin for rollout %s/%s", rollout.Namespace, rollout.Name) + + // Get configs + var config Config + var state State + if context != nil { + if context.Config != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal config: %w", err).Error()} + } + p.LogCtx.Infof("Using config: %+v", config) + } + if context.Status != nil { + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal status: %w", err).Error()} + } + p.LogCtx.Infof("Using status: %+v", state) + } + } + + if state.Data == "" { + state.Data = uuid.New().String() + } + + var requeue time.Duration + if config.Requeue != "" { + v, err := time.ParseDuration(string(config.Requeue)) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse requeue duration: %w", err).Error()} + } + requeue = v + } + + phase := types.PhaseSuccessful + if config.Return != "" { + phase = types.Phase(config.Return) + if err := phase.Validate(); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse phase: %w", err).Error()} + } + } + + return Result(state, phase, requeue) +} + +func (p *rpcPlugin) Terminate(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + p.LogCtx.Infof("Terminate plugin for rollout %s/%s", rollout.Namespace, rollout.Name) + + // Get configs + var config Config + var state State + if context != nil { + if context.Config != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal config: %w", err).Error()} + } + } + if context.Status != nil { + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal status: %w", err).Error()} + } + } + } + + if state.Data == "" { + state.Data = uuid.New().String() + } + + phase := types.PhaseSuccessful + if config.Terminate.Return != "" { + phase = types.Phase(config.Terminate.Return) + if err := phase.Validate(); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse phase: %w", err).Error()} + } + } + + return Result(state, phase, 0) +} + +func (p *rpcPlugin) Abort(rollout *v1alpha1.Rollout, context *types.RpcStepContext) (types.RpcStepResult, types.RpcError) { + p.LogCtx.Infof("Abort plugin for rollout %s/%s", rollout.Namespace, rollout.Name) + + // Get configs + var config Config + var state State + if context != nil { + if context.Config != nil { + if err := json.Unmarshal(context.Config, &config); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal config: %w", err).Error()} + } + } + if context.Status != nil { + if err := json.Unmarshal(context.Status, &state); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not unmarshal status: %w", err).Error()} + } + } + } + + if state.Data == "" { + state.Data = uuid.New().String() + } + + phase := types.PhaseSuccessful + if config.Abort.Return != "" { + phase = types.Phase(config.Abort.Return) + if err := phase.Validate(); err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse phase: %w", err).Error()} + } + } + + return Result(state, phase, 0) +} + +func (p *rpcPlugin) Type() string { + return "e2e-plugin" +} + +func Result(state State, phase types.Phase, requeue time.Duration) (types.RpcStepResult, types.RpcError) { + stateRaw, err := json.Marshal(state) + if err != nil { + return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Could not marshal state: %v", err)} + } + + return types.RpcStepResult{ + Phase: phase, + RequeueAfter: requeue, + Status: stateRaw, + }, types.RpcError{} +} diff --git a/test/cmd/step-plugin-e2e/main.go b/test/cmd/step-plugin-e2e/main.go new file mode 100644 index 0000000000..995b0fe690 --- /dev/null +++ b/test/cmd/step-plugin-e2e/main.go @@ -0,0 +1,60 @@ +package main + +import ( + "strings" + + rolloutsPlugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" + "github.com/argoproj/argo-rollouts/test/cmd/step-plugin-e2e/internal/plugin" + goPlugin "github.com/hashicorp/go-plugin" + log "github.com/sirupsen/logrus" +) + +var handshakeConfig = goPlugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "ARGO_ROLLOUTS_RPC_PLUGIN", + MagicCookieValue: "step", +} + +func main() { + logCtx := log.WithFields(log.Fields{"plugin": "e2e"}) + + setLogLevel("debug") + log.SetFormatter(createFormatter("text")) + + // pluginMap is the map of plugins we can dispense. + var pluginMap = map[string]goPlugin.Plugin{ + "RpcStepPlugin": &rolloutsPlugin.RpcStepPlugin{Impl: plugin.New(logCtx)}, + } + + goPlugin.Serve(&goPlugin.ServeConfig{ + HandshakeConfig: handshakeConfig, + Plugins: pluginMap, + }) +} + +func createFormatter(logFormat string) log.Formatter { + var formatType log.Formatter + switch strings.ToLower(logFormat) { + case "json": + formatType = &log.JSONFormatter{} + case "text": + formatType = &log.TextFormatter{ + FullTimestamp: true, + } + default: + log.Infof("Unknown format: %s. Using text logformat", logFormat) + formatType = &log.TextFormatter{ + FullTimestamp: true, + } + } + + return formatType +} + +func setLogLevel(logLevel string) { + level, err := log.ParseLevel(logLevel) + if err != nil { + log.Fatal(err) + } + log.SetLevel(level) +} diff --git a/test/e2e/canary_test.go b/test/e2e/canary_test.go index 2c68ec8bd7..47d07ec246 100644 --- a/test/e2e/canary_test.go +++ b/test/e2e/canary_test.go @@ -47,7 +47,7 @@ func (s *CanarySuite) TestCanarySetCanaryScale() { - pause: {duration: 5s} ` s.Given(). - RolloutTemplate("@functional/nginx-template.yaml", "set-canary-scale"). + RolloutTemplate("@functional/nginx-template.yaml", map[string]string{"REPLACEME": "set-canary-scale"}). SetSteps(canarySteps). When(). ApplyManifests(). diff --git a/test/e2e/step-plugin/argo-rollouts-config.yaml b/test/e2e/step-plugin/argo-rollouts-config.yaml new file mode 100644 index 0000000000..281d851d7a --- /dev/null +++ b/test/e2e/step-plugin/argo-rollouts-config.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: rollouts-controller + app.kubernetes.io/name: argo-rollouts + app.kubernetes.io/part-of: argo-rollouts + name: argo-rollouts-config + namespace: argo-rollouts +data: + stepPlugins: |- + - name: "step/e2e-test" # name of the plugin, it must match the name required by the plugin so it can find it's configuration + location: "file://plugin-bin/e2e-step-plugin" # supports http(s):// urls and file:// + disabled: false + - name: "step/e2e-test-disabled" # name of the plugin, it must match the name required by the plugin so it can find it's configuration + location: "file://plugin-bin/e2e-step-plugin" # supports http(s):// urls and file:// + disabled: true diff --git a/test/e2e/step-plugin/template-rollout.yaml b/test/e2e/step-plugin/template-rollout.yaml new file mode 100644 index 0000000000..312e80b7f1 --- /dev/null +++ b/test/e2e/step-plugin/template-rollout.yaml @@ -0,0 +1,31 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: step-plugin-e2e-$$name$$ +spec: + selector: + matchLabels: + app: step-plugin-e2e-$$name$$ + strategy: + canary: + steps: + - plugin: + name: step/e2e-test + config: + return: Successful + - plugin: + name: step/e2e-test + config: + return: $$phase$$ + template: + metadata: + labels: + app: step-plugin-e2e-$$name$$ + spec: + containers: + - name: basic + image: nginx:1.19-alpine + resources: + requests: + memory: 16Mi + cpu: 1m diff --git a/test/e2e/step-plugin/test.yaml b/test/e2e/step-plugin/test.yaml new file mode 100644 index 0000000000..c079c96feb --- /dev/null +++ b/test/e2e/step-plugin/test.yaml @@ -0,0 +1,34 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: manual-test + labels: + argo-rollouts.argoproj.io/controller-instance-id: argo-rollouts-e2e +spec: + selector: + matchLabels: + app: manual-test + strategy: + canary: + steps: + - plugin: + name: step/e2e-test + config: + return: Successful + - plugin: + name: step/e2e-test + config: + return: Running + template: + metadata: + labels: + app: manual-test + x: d + spec: + containers: + - name: basic + image: nginx:1.19-alpine + resources: + requests: + memory: 16Mi + cpu: 1m diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go new file mode 100644 index 0000000000..8772b6d88d --- /dev/null +++ b/test/e2e/step_plugin_test.go @@ -0,0 +1,138 @@ +//go:build e2e +// +build e2e + +package e2e + +import ( + "testing" + + "github.com/stretchr/testify/suite" + "github.com/tj/assert" + "gopkg.in/yaml.v2" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/test/fixtures" + "github.com/argoproj/argo-rollouts/utils/plugin/types" + corev1 "k8s.io/api/core/v1" +) + +const E2EStepPluginName = "step/e2e-test" +const E2EStepPluginNameDisabled = "step/e2e-test-disabled" +const E2EStepPluginNameInvalid = "step/e2e-test-invalid" + +type StepPluginSuite struct { + fixtures.E2ESuite +} + +func TestStepPluginSuite(t *testing.T) { + suite.Run(t, new(StepPluginSuite)) +} + +func (s *StepPluginSuite) SetupSuite() { + s.E2ESuite.SetupSuite() + + // if !IsStepPluginConfigured(&s.Common, s.GetControllerConfig()) { + // s.T().SkipNow() + // } +} + +// getControllerConfiguredPlugin look at the controller default config map to find the list of plugins +// This is a best effort because it does not mean the controller have these plugins configured in-memory +func IsStepPluginConfigured(c *fixtures.Common, config *corev1.ConfigMap) bool { + var stepPlugins []types.PluginItem + if err := yaml.Unmarshal([]byte(config.Data["stepPlugins"]), &stepPlugins); err != nil { + c.CheckError(err) + } + + hasPlugin := false + hasPluginDisabled := false + for _, p := range stepPlugins { + if p.Name == E2EStepPluginName { + hasPlugin = true + } + if p.Name == E2EStepPluginNameDisabled { + hasPluginDisabled = true + } + } + return hasPlugin && hasPluginDisabled +} + +// test rollout retry until deadline if plugins error +// test rollout requeued when plugin is running +// test rollout has new step status on new rollout +// test step terminated on full promotion when running +// test step aborted when rollout is aborted + +// test step plugin ignored when disabled +// test rollout error when step plugin not configured + +func (s *StepPluginSuite) TestRolloutCompletesWhenStepSuccessful() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "successful", "$$phase$$": string(types.PhaseSuccessful)}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Healthy").Then(). + ExpectStableRevision("2"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 2, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + }) +} + +func (s *StepPluginSuite) TestRolloutAbortWhenStepFails() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "failed", "$$phase$$": string(types.PhaseFailed)}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Degraded").Then(). + ExpectStableRevision("1"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.True(s.T(), rollout.Status.Abort) + assert.EqualValues(s.T(), 3, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseFailed, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + + stepStatus = rollout.Status.Canary.StepPluginStatuses[2] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 0, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationAbort, stepStatus.Operation) + }) +} + +func (s *StepPluginSuite) TestRolloutCompletesWhenPromotedAndStepRunning() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "running-promotion", "$$phase$$": string(types.PhaseRunning)}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Progressing"). + WaitForRolloutCanaryStepIndex(1). + WaitForRolloutStepPluginRunning(). + PromoteRolloutFull(). + WaitForRolloutStatus("Healthy"). + Then(). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 3, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseRunning, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + + stepStatus = rollout.Status.Canary.StepPluginStatuses[2] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationTerminate, stepStatus.Operation) + }) +} diff --git a/test/fixtures/common.go b/test/fixtures/common.go index 670d2dd2f4..b5c5dae7b0 100644 --- a/test/fixtures/common.go +++ b/test/fixtures/common.go @@ -13,6 +13,7 @@ import ( "time" a6util "github.com/argoproj/argo-rollouts/utils/apisix" + k8errors "k8s.io/apimachinery/pkg/api/errors" smiv1alpha1 "github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1" smiclientset "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned" @@ -681,6 +682,17 @@ func (c *Common) GetRolloutEventReasons() []string { return reasons } +func (c *Common) GetControllerConfig() *corev1.ConfigMap { + configMap, err := c.kubeClient.CoreV1().ConfigMaps(c.namespace).Get(c.Context, "argo-rollouts-config", metav1.GetOptions{}) + if err != nil { + if k8errors.IsNotFound(err) { + return nil + } + c.CheckError(err) + } + return configMap +} + // PrintRolloutEvents prints all Kubernetes events associated with the given rollout. func (c *Common) PrintRolloutEvents(ro *v1alpha1.Rollout) { opts := metav1.ListOptions{FieldSelector: fields.ParseSelectorOrDie(fmt.Sprintf("involvedObject.uid=%s", ro.UID)).String()} diff --git a/test/fixtures/given.go b/test/fixtures/given.go index 57e17251c6..a6e332d69a 100644 --- a/test/fixtures/given.go +++ b/test/fixtures/given.go @@ -34,9 +34,12 @@ func (g *Given) RolloutObjects(text string) *Given { return g } -func (g *Given) RolloutTemplate(text, name string) *Given { +func (g *Given) RolloutTemplate(text string, values map[string]string) *Given { yamlBytes := g.yamlBytes(text) - newText := strings.ReplaceAll(string(yamlBytes), "REPLACEME", name) + newText := string(yamlBytes) + for k, v := range values { + newText = strings.ReplaceAll(newText, k, v) + } return g.RolloutObjects(newText) } diff --git a/test/fixtures/when.go b/test/fixtures/when.go index d9696a7761..a5806befb9 100644 --- a/test/fixtures/when.go +++ b/test/fixtures/when.go @@ -415,6 +415,18 @@ func (w *When) WaitForActiveRevision(revision string, timeout ...time.Duration) return w.WaitForRolloutCondition(checkStatus, fmt.Sprintf("active revision=%s", revision), timeout...) } +func (w *When) WaitForRolloutStepPluginRunning(timeout ...time.Duration) *When { + checkStatus := func(ro *rov1.Rollout) bool { + for _, s := range ro.Status.Canary.StepPluginStatuses { + if s.Index == *ro.Status.CurrentStepIndex && s.Operation == rov1.StepPluginOperationRun && s.Phase == v1alpha1.StepPluginPhaseRunning { + return true + } + } + return false + } + return w.WaitForRolloutCondition(checkStatus, fmt.Sprintf("stepPluginStatus[currentIndex].phase=Running"), timeout...) +} + func (w *When) WaitForRolloutCondition(test func(ro *rov1.Rollout) bool, condition string, timeouts ...time.Duration) *When { start := time.Now() w.log.Infof("Waiting for condition: %s", condition) diff --git a/utils/plugin/types/steps.go b/utils/plugin/types/steps.go index 5c774ae68d..9c0e7e235b 100644 --- a/utils/plugin/types/steps.go +++ b/utils/plugin/types/steps.go @@ -2,6 +2,7 @@ package types import ( "encoding/json" + "fmt" "time" ) @@ -26,3 +27,15 @@ type RpcStepResult struct { RequeueAfter time.Duration Status json.RawMessage } + +func (p Phase) Validate() error { + switch p { + case PhaseRunning: + case PhaseSuccessful: + case PhaseFailed: + case PhaseError: + default: + return fmt.Errorf("phase '%s' is not valid", p) + } + return nil +} diff --git a/utils/plugin/types/types.go b/utils/plugin/types/types.go index 931c7fdb14..d6a92e7f19 100644 --- a/utils/plugin/types/types.go +++ b/utils/plugin/types/types.go @@ -114,6 +114,7 @@ type PluginItem struct { Name string `json:"name" yaml:"name"` Location string `json:"location" yaml:"location"` Sha256 string `json:"sha256" yaml:"sha256"` + Disabled bool `json:"disabled" yaml:"disabled"` // Args holds command line arguments Args []string `json:"args" yaml:"args"` From db17cb573a8f9613a58456617bebe658e750d84d Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Thu, 18 Apr 2024 12:05:03 -0400 Subject: [PATCH 18/41] fix full promotion Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 51 +++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 75e816abbb..c2a6c99f46 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -6,6 +6,7 @@ import ( "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" replicasetutil "github.com/argoproj/argo-rollouts/utils/replicaset" + rolloututil "github.com/argoproj/argo-rollouts/utils/rollout" ) func (c *rolloutContext) reconcileCanaryPluginStep() error { @@ -18,6 +19,9 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) startingIndex := *currentStepIndex for i := startingIndex; i >= 0; i-- { + if i >= int32(len(c.rollout.Spec.Strategy.Canary.Steps)) { + continue + } currentStep := &c.rollout.Spec.Strategy.Canary.Steps[i] if currentStep.Plugin == nil { continue @@ -36,6 +40,41 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } + // On full promotion, we want to Terminate the last step stuck in Running + // At this point, the currentStepIndex is the current or last one + if c.rollout.Status.PromoteFull || rolloututil.IsFullyPromoted(c.rollout) { + _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) + startingIndex := *currentStepIndex + + for i := startingIndex; i >= 0; i-- { + if i >= int32(len(c.rollout.Spec.Strategy.Canary.Steps)) { + continue + } + currentStep := &c.rollout.Spec.Strategy.Canary.Steps[i] + if currentStep.Plugin == nil { + continue + } + runningStatus := findCurrentStepStatus(c.rollout.Status.Canary.StepPluginStatuses, i, v1alpha1.StepPluginOperationRun) + if runningStatus == nil || runningStatus.Phase != v1alpha1.StepPluginPhaseRunning { + continue + } + + // found the last running step + stepPlugin, err := c.stepPluginResolver.Resolve(i, *currentStep.Plugin, c.log) + if err != nil { + return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) + } + + status, err := stepPlugin.Terminate(c.rollout) + if err != nil { + return fmt.Errorf("failed to terminate plugin: %w", err) + } + c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + } + return nil + } + + // Normal execution flow of a step plugin currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) if currentStep == nil || currentStep.Plugin == nil { return nil @@ -45,18 +84,6 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if err != nil { return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) } - - // On full promotion, we want to Terminate the current step - if c.rollout.Status.PromoteFull { - status, err := stepPlugin.Terminate(c.rollout) - if err != nil { - return fmt.Errorf("failed to terminate plugin: %w", err) - } - c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) - return nil - } - - // Normal execution of a step plugin status, result, err := stepPlugin.Run(c.rollout) if err != nil { return fmt.Errorf("failed to run plugin: %w", err) From 5dedcc29593c0e2a078857709e9ceb79262e02f0 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Thu, 18 Apr 2024 17:42:49 -0400 Subject: [PATCH 19/41] fix plugins Signed-off-by: Alexandre Gaudreault --- Makefile | 1 + pkg/apis/rollouts/v1alpha1/types.go | 3 +- rollout/stepplugin.go | 1 + rollout/stepplugin_test.go | 8 +- rollout/steps/plugin/client/client.go | 3 + rollout/steps/plugin/plugin.go | 9 +- rollout/steps/plugin/plugin_test.go | 3 +- .../step-plugin-e2e/internal/plugin/plugin.go | 12 +- test/e2e/step-plugin/test.yaml | 34 ----- test/e2e/step_plugin_test.go | 135 ++++++++++++++++-- 10 files changed, 147 insertions(+), 62 deletions(-) delete mode 100644 test/e2e/step-plugin/test.yaml diff --git a/Makefile b/Makefile index 86f2624a73..e6b2c62753 100644 --- a/Makefile +++ b/Makefile @@ -242,6 +242,7 @@ test-kustomize: ## run kustomize tests ./test/kustomize/test.sh step-plugin-e2e-setup: + @rm -rf plugin-bin @go build -gcflags="all=-N -l" -o plugin-bin/e2e-step-plugin test/cmd/step-plugin-e2e/main.go @kubectl apply --context='${E2E_K8S_CONTEXT}' -n argo-rollouts -f test/e2e/step-plugin/argo-rollouts-config.yaml diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 6d4bcbfc46..0a4d78538f 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -1046,7 +1046,8 @@ type StepPluginStatus struct { Phase StepPluginPhase `json:"phase" protobuf:"bytes,4,name=phase"` Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,6,name=startedAt"` - FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,7,opt,name=finishedAt"` + UpdatedAt *metav1.Time `json:"updatedAt,omitempty" protobuf:"bytes,7,opt,name=updatedAt"` + FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,8,opt,name=finishedAt"` // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index c2a6c99f46..71cccfc94c 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -70,6 +70,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return fmt.Errorf("failed to terminate plugin: %w", err) } c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + return nil } return nil } diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index 6c816ed3fc..295f2d6e78 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -297,8 +297,8 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { { Index: runStatus.Index, Name: runStatus.Name, - Phase: v1alpha1.StepPluginPhaseSuccessful, - Operation: v1alpha1.StepPluginOperationTerminate, + Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, }, } @@ -307,8 +307,8 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { err := roCtx.reconcileCanaryPluginStep() require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginStatuses, 2) + assert.EqualExportedValues(t, roCtx.stepPluginStatuses[1], *runStatus) }) } diff --git a/rollout/steps/plugin/client/client.go b/rollout/steps/plugin/client/client.go index bb19ec9ab1..78fc745c12 100644 --- a/rollout/steps/plugin/client/client.go +++ b/rollout/steps/plugin/client/client.go @@ -89,6 +89,9 @@ func (t *stepPlugin) startPlugin(pluginName string) (rpc.StepPlugin, error) { client, err := t.client[pluginName].Client() if err != nil { + // If we are not able to create the client, something is utterly wrong + // we should try to re-download the plugin and restart because the file + // can be corrupted return nil, fmt.Errorf("unable to get plugin client (%s) for ping: %w", pluginName, err) } if err := client.Ping(); err != nil { diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 5737b284ed..a5d93d09e5 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -56,11 +56,11 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, resp, err := p.rpc.Run(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() + stepStatus.UpdatedAt = &finishedAt if err.HasError() { p.log.Errorf("error during plugin execution") stepStatus.Phase = v1alpha1.StepPluginPhaseError stepStatus.Message = err.Error() - stepStatus.FinishedAt = &finishedAt return stepStatus, result, nil } @@ -76,7 +76,10 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, stepStatus.FinishedAt = &finishedAt } - stepStatus.Status = resp.Status + if stepStatus.Phase != v1alpha1.StepPluginPhaseError { + // do not update status on error because it can be invalid and we want to retry later on current status + stepStatus.Status = resp.Status + } if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { result.RequeueAfter = &defaultRequeuDuration @@ -111,6 +114,7 @@ func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginS } resp, err := p.rpc.Terminate(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() + stepStatus.UpdatedAt = &finishedAt if err.HasError() { terminateStatus.Phase = v1alpha1.StepPluginPhaseError terminateStatus.Message = err.Error() @@ -158,6 +162,7 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu } resp, err := p.rpc.Abort(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() + stepStatus.UpdatedAt = &finishedAt if err.HasError() { abortStatus.Phase = v1alpha1.StepPluginPhaseError abortStatus.Message = err.Error() diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index aa4a295fcd..5f0267b785 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -143,6 +143,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, p.name, status.Name) assert.Equal(t, p.index, status.Index) assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.NotEqual(t, currentStatus.UpdatedAt, status.UpdatedAt) assert.Equal(t, v1alpha1.StepPluginPhase(rpcResult.Phase), status.Phase) assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) @@ -363,11 +364,11 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, p.name, status.Name) assert.Equal(t, p.index, status.Index) assert.Equal(t, currentStatus.StartedAt, status.StartedAt) + assert.NotEqual(t, currentStatus.UpdatedAt, status.UpdatedAt) assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, expectedError.Error(), status.Message) assert.Equal(t, currentStatus.Status, status.Status) - assert.NotNil(t, status.FinishedAt) assert.Nil(t, result.RequeueAfter) }) } diff --git a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go index 3d6cc606e9..efe70cab93 100644 --- a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go +++ b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go @@ -29,7 +29,8 @@ type Terminate struct { } type State struct { - Data string + Data string + Count int } type rpcPlugin struct { @@ -71,6 +72,7 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext if state.Data == "" { state.Data = uuid.New().String() } + state.Count = state.Count + 1 var requeue time.Duration if config.Requeue != "" { @@ -111,10 +113,6 @@ func (p *rpcPlugin) Terminate(rollout *v1alpha1.Rollout, context *types.RpcStepC } } - if state.Data == "" { - state.Data = uuid.New().String() - } - phase := types.PhaseSuccessful if config.Terminate.Return != "" { phase = types.Phase(config.Terminate.Return) @@ -145,10 +143,6 @@ func (p *rpcPlugin) Abort(rollout *v1alpha1.Rollout, context *types.RpcStepConte } } - if state.Data == "" { - state.Data = uuid.New().String() - } - phase := types.PhaseSuccessful if config.Abort.Return != "" { phase = types.Phase(config.Abort.Return) diff --git a/test/e2e/step-plugin/test.yaml b/test/e2e/step-plugin/test.yaml deleted file mode 100644 index c079c96feb..0000000000 --- a/test/e2e/step-plugin/test.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Rollout -metadata: - name: manual-test - labels: - argo-rollouts.argoproj.io/controller-instance-id: argo-rollouts-e2e -spec: - selector: - matchLabels: - app: manual-test - strategy: - canary: - steps: - - plugin: - name: step/e2e-test - config: - return: Successful - - plugin: - name: step/e2e-test - config: - return: Running - template: - metadata: - labels: - app: manual-test - x: d - spec: - containers: - - name: basic - image: nginx:1.19-alpine - resources: - requests: - memory: 16Mi - cpu: 1m diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index 8772b6d88d..077c2e5acc 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -5,6 +5,7 @@ package e2e import ( "testing" + "time" "github.com/stretchr/testify/suite" "github.com/tj/assert" @@ -30,10 +31,9 @@ func TestStepPluginSuite(t *testing.T) { func (s *StepPluginSuite) SetupSuite() { s.E2ESuite.SetupSuite() - - // if !IsStepPluginConfigured(&s.Common, s.GetControllerConfig()) { - // s.T().SkipNow() - // } + if !IsStepPluginConfigured(&s.Common, s.GetControllerConfig()) { + s.T().SkipNow() + } } // getControllerConfiguredPlugin look at the controller default config map to find the list of plugins @@ -57,12 +57,6 @@ func IsStepPluginConfigured(c *fixtures.Common, config *corev1.ConfigMap) bool { return hasPlugin && hasPluginDisabled } -// test rollout retry until deadline if plugins error -// test rollout requeued when plugin is running -// test rollout has new step status on new rollout -// test step terminated on full promotion when running -// test step aborted when rollout is aborted - // test step plugin ignored when disabled // test rollout error when step plugin not configured @@ -109,9 +103,44 @@ func (s *StepPluginSuite) TestRolloutAbortWhenStepFails() { }) } +func (s *StepPluginSuite) TestRolloutAbortStepsWhenAborted() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "aborted", "$$phase$$": string(types.PhaseRunning)}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Progressing"). + WaitForRolloutCanaryStepIndex(1). + WaitForRolloutStepPluginRunning(). + AbortRollout(). + WaitForRolloutStatus("Degraded"). + Then(). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.True(s.T(), rollout.Status.Abort) + assert.EqualValues(s.T(), 4, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseRunning, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + + stepStatus = rollout.Status.Canary.StepPluginStatuses[2] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationAbort, stepStatus.Operation) + + stepStatus = rollout.Status.Canary.StepPluginStatuses[3] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 0, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationAbort, stepStatus.Operation) + }) +} + func (s *StepPluginSuite) TestRolloutCompletesWhenPromotedAndStepRunning() { s.Given(). - RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "running-promotion", "$$phase$$": string(types.PhaseRunning)}). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "full-promotion", "$$phase$$": string(types.PhaseRunning)}). When().ApplyManifests().WaitForRolloutStatus("Healthy"). UpdateSpec().WaitForRolloutStatus("Progressing"). WaitForRolloutCanaryStepIndex(1). @@ -136,3 +165,87 @@ func (s *StepPluginSuite) TestRolloutCompletesWhenPromotedAndStepRunning() { assert.EqualValues(s.T(), v1alpha1.StepPluginOperationTerminate, stepStatus.Operation) }) } + +func (s *StepPluginSuite) TestRolloutRetriesUntilDeadlineWhenRunning() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "running", "$$phase$$": string(types.PhaseRunning)}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec(` +spec: + progressDeadlineSeconds: 15`). + UpdateSpec().WaitForRolloutStatus("Progressing"). + WaitForRolloutCanaryStepIndex(1). + WaitForRolloutStepPluginRunning(). + Wait(20 * time.Second). + Then(). + ExpectRolloutStatus("Degraded"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 1, *rollout.Status.CurrentStepIndex) + assert.EqualValues(s.T(), 2, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseRunning, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + assert.NotEmpty(s.T(), stepStatus.Status) + + }) +} + +func (s *StepPluginSuite) TestRolloutRetriesUntilDeadlineWhenError() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "error", "$$phase$$": "invalidPhaseCausingPluginError"}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec(` +spec: + progressDeadlineSeconds: 15`). + UpdateSpec().WaitForRolloutStatus("Progressing"). + Wait(20 * time.Second). + Then(). + ExpectRolloutStatus("Degraded"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 1, *rollout.Status.CurrentStepIndex) + assert.EqualValues(s.T(), 2, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseError, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + assert.Contains(s.T(), stepStatus.Message, "phase 'invalidPhaseCausingPluginError' is not valid") + assert.Empty(s.T(), stepStatus.Status) + + }) +} + +func (s *StepPluginSuite) TestRolloutStatusIsNotUsedOnNewRollout() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "run-again", "$$phase$$": string(types.PhaseSuccessful)}). + When().ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Healthy").Then(). + ExpectStableRevision("2"). + When().UpdateSpec(` +spec: + strategy: + canary: + steps: + - plugin: + name: step/e2e-test + config: + return: Successful`). + UpdateSpec().WaitForRolloutStatus("Healthy").Then(). + ExpectStableRevision("3"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 1, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[0] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 0, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + }) +} From ce17794427570fa54f008621c63a588df333469a Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Thu, 18 Apr 2024 17:49:23 -0400 Subject: [PATCH 20/41] codegen Signed-off-by: Alexandre Gaudreault --- manifests/crds/rollout-crd.yaml | 3 + manifests/install.yaml | 3 + pkg/apiclient/rollout/rollout.swagger.json | 3 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 928 +++++++++--------- pkg/apis/rollouts/v1alpha1/generated.proto | 6 +- pkg/apis/rollouts/v1alpha1/types.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 4 + ui/src/models/rollout/generated/api.ts | 6 + 8 files changed, 515 insertions(+), 440 deletions(-) diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index b084183c88..0e5646b673 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -3750,6 +3750,9 @@ spec: status: type: object x-kubernetes-preserve-unknown-fields: true + updatedAt: + format: date-time + type: string required: - index - name diff --git a/manifests/install.yaml b/manifests/install.yaml index 3cd5d85f5e..ea40be19ae 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -16240,6 +16240,9 @@ spec: status: type: object x-kubernetes-preserve-unknown-fields: true + updatedAt: + format: date-time + type: string required: - index - name diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index d1d9b8c1d9..fb0336fe08 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -2546,6 +2546,9 @@ "startedAt": { "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" }, + "updatedAt": { + "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" + }, "finishedAt": { "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" }, diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index c97a41064f..dfcab4177a 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -3407,15 +3407,15 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 8743 bytes of a gzipped FileDescriptorProto + // 8763 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x6c, 0x64, 0xd7, 0x75, 0x98, 0x1e, 0x87, 0x43, 0xce, 0x9c, 0xe1, 0x92, 0xdc, 0xbb, 0xbb, 0x12, 0x45, 0x49, 0x3b, 0xca, 0x53, 0xaa, 0xae, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, 0x72, 0x45, 0xee, 0x52, 0x67, 0xb8, 0xda, 0xf8, 0x43, 0x89, 0x1f, 0x67, 0x2e, 0x87, 0x6f, 0x39, 0xf3, 0xde, 0xf8, 0xbd, 0x37, 0xdc, 0xa5, 0x2c, 0xc4, 0xb2, 0x0d, 0x39, 0x8e, 0x6b, 0x23, 0x6e, 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0xe9, 0x8f, 0x22, 0x70, 0xd1, 0xfe, 0x08, - 0xd0, 0xa0, 0x6e, 0x0a, 0x07, 0x68, 0x0a, 0xe7, 0x47, 0xeb, 0xb4, 0x40, 0x98, 0x9a, 0xe9, 0x9f, - 0x06, 0x2d, 0x8c, 0x16, 0x2e, 0x82, 0xe8, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, + 0xd0, 0xa0, 0x6e, 0x0a, 0x07, 0x68, 0x0a, 0xa7, 0x40, 0xeb, 0xb4, 0x40, 0x98, 0x9a, 0xe9, 0x9f, + 0x06, 0x2d, 0x8c, 0x16, 0x2e, 0x82, 0xea, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, 0x9a, 0xc7, 0x95, 0xd2, 0xe6, 0xdf, 0xcc, 0x3d, 0xe7, 0x9e, 0x73, 0xde, 0xfd, 0x3c, 0xf7, 0xdc, 0x73, 0xce, 0x85, 0xd5, 0xb6, 0x1b, 0x6d, 0xf7, 0x37, 0x17, 0x9a, 0x7e, 0x77, 0xd1, 0x09, 0xda, 0x7e, 0x2f, 0xf0, 0xef, 0xf2, 0x1f, 0x1f, 0x0e, 0xfc, 0x4e, 0xc7, 0xef, 0x47, 0xe1, 0x62, 0x6f, @@ -3449,13 +3449,13 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xae, 0x9f, 0x3b, 0xd8, 0xaf, 0x96, 0x57, 0x54, 0x21, 0xc6, 0x70, 0x7b, 0x19, 0xe6, 0x6a, 0xdd, 0x4d, 0x27, 0x0c, 0x9d, 0x96, 0x1f, 0xa4, 0xba, 0xee, 0x0a, 0x94, 0xba, 0x4e, 0xaf, 0xe7, 0x7a, 0x6d, 0xd6, 0x77, 0x8c, 0xce, 0xd4, 0xc1, 0x7e, 0xb5, 0xb4, 0x26, 0xcb, 0x50, 0x43, 0xed, 0xff, - 0x34, 0x06, 0x95, 0x9a, 0xe7, 0x74, 0xf6, 0x42, 0x37, 0xc4, 0xbe, 0x47, 0x3e, 0x0b, 0x25, 0xb6, + 0x38, 0x06, 0x95, 0x9a, 0xe7, 0x74, 0xf6, 0x42, 0x37, 0xc4, 0xbe, 0x47, 0x3e, 0x0b, 0x25, 0xb6, 0x6a, 0xb5, 0x9c, 0xc8, 0x91, 0x33, 0xfd, 0x23, 0x0b, 0x62, 0x11, 0x59, 0x30, 0x17, 0x91, 0xf8, 0xf3, 0x19, 0xf6, 0xc2, 0xee, 0x47, 0x17, 0x6e, 0x6d, 0xde, 0xa5, 0xcd, 0x68, 0x8d, 0x46, 0x4e, 0x9d, 0xc8, 0x5e, 0x80, 0xb8, 0x0c, 0x35, 0x55, 0xe2, 0xc3, 0x78, 0xd8, 0xa3, 0x4d, 0x39, 0x73, 0xd7, 0x46, 0x9c, 0x21, 0xb1, 0xe8, 0x8d, 0x1e, 0x6d, 0xd6, 0xa7, 0x24, 0xeb, 0x71, 0xf6, 0x0f, 0x39, 0x23, 0x72, 0x0f, 0x26, 0x42, 0xbe, 0x96, 0xc9, 0x49, 0x79, 0x2b, 0x3f, 0x96, 0x9c, 0x6c, - 0x7d, 0x5a, 0x32, 0x9d, 0x10, 0xff, 0x51, 0xb2, 0xb3, 0xff, 0xb3, 0x05, 0x17, 0x0c, 0xec, 0x5a, + 0x7d, 0x5a, 0x32, 0x9d, 0x10, 0xff, 0x51, 0xb2, 0xb3, 0xff, 0x93, 0x05, 0x17, 0x0c, 0xec, 0x5a, 0xd0, 0xee, 0x77, 0xa9, 0x17, 0x91, 0x27, 0x61, 0xdc, 0x73, 0xba, 0x54, 0xce, 0x2a, 0x2d, 0xf2, 0x4d, 0xa7, 0x4b, 0x91, 0x43, 0xc8, 0x53, 0x50, 0xdc, 0x75, 0x3a, 0x7d, 0xca, 0x1b, 0xa9, 0x5c, 0x3f, 0x27, 0x51, 0x8a, 0x6f, 0xb0, 0x42, 0x14, 0x30, 0xf2, 0x36, 0x94, 0xf9, 0x8f, 0x6b, 0x81, @@ -3466,10 +3466,10 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xfb, 0xae, 0x30, 0xfa, 0x28, 0xd8, 0xd8, 0xdf, 0x29, 0x24, 0xba, 0x6f, 0x4d, 0xc9, 0xf1, 0xae, 0x05, 0x13, 0x1d, 0x67, 0x93, 0x76, 0xc4, 0xdc, 0xaa, 0x3c, 0xf7, 0x66, 0x6e, 0x92, 0x28, 0x1e, 0x0b, 0xab, 0x9c, 0xfe, 0x55, 0x2f, 0x0a, 0xf6, 0xe2, 0xe1, 0x25, 0x0a, 0x51, 0x32, 0x27, 0x7f, - 0xc7, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, + 0xcb, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, 0x25, 0xda, 0x80, 0xa0, 0x29, 0xcb, 0xfc, 0xc7, 0xa0, 0x62, 0x7c, 0x02, 0x99, 0x85, 0xc2, 0x0e, 0xdd, 0x13, 0x03, 0x1e, 0xd9, 0x4f, 0x72, 0x31, 0x31, 0xc2, 0xe5, 0x90, 0xfe, 0xf8, 0xd8, 0x4b, - 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x2b, 0x26, 0x06, 0x26, 0x5b, + 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x29, 0x26, 0x06, 0x26, 0x5b, 0x08, 0x88, 0x0f, 0x93, 0x5d, 0x1a, 0x05, 0x6e, 0x53, 0x75, 0xd9, 0xf2, 0x68, 0xad, 0xb4, 0xc6, 0x89, 0xc5, 0x1b, 0xa2, 0xf8, 0x1f, 0xa2, 0xe2, 0x42, 0xb6, 0x61, 0xdc, 0x09, 0xda, 0xaa, 0x4f, 0xae, 0xe5, 0x33, 0x2d, 0xe3, 0xa5, 0xa2, 0x16, 0xb4, 0x43, 0xe4, 0x1c, 0xc8, 0x22, 0x94, 0x23, @@ -3479,7 +3479,7 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xa0, 0xec, 0x13, 0x90, 0x46, 0xd4, 0x63, 0x1d, 0x3b, 0x57, 0xe4, 0xcc, 0x71, 0xd4, 0x7e, 0x18, 0xa4, 0x5c, 0x7f, 0x5c, 0x8a, 0x72, 0x31, 0x0b, 0x8a, 0x99, 0xd2, 0x90, 0xb7, 0xa1, 0x12, 0x45, 0x9d, 0x46, 0xc4, 0xf4, 0xe0, 0xf6, 0xde, 0xdc, 0x04, 0x5f, 0xbc, 0x46, 0x5c, 0x61, 0x36, 0x36, - 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x59, 0x84, 0xf3, + 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x5e, 0x84, 0xf3, 0x03, 0xdb, 0x0a, 0x79, 0x01, 0x8a, 0xbd, 0x6d, 0x27, 0x54, 0xfb, 0xc4, 0x65, 0xb5, 0x48, 0xad, 0xb3, 0xc2, 0xf7, 0xf6, 0xab, 0xe7, 0x54, 0x15, 0x5e, 0x80, 0x02, 0x99, 0x69, 0x6d, 0x5d, 0x1a, 0x86, 0x4e, 0x5b, 0x6d, 0x1e, 0xc6, 0x20, 0xe5, 0xc5, 0xa8, 0xe0, 0xe4, 0x17, 0x2c, 0x38, 0x27, @@ -3490,20 +3490,20 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xae, 0x13, 0xec, 0x49, 0xed, 0xee, 0xfa, 0x68, 0x9f, 0x87, 0x9a, 0x5e, 0xac, 0xe8, 0xc4, 0x65, 0x68, 0xf0, 0x23, 0x5f, 0xb4, 0xe0, 0x9c, 0x98, 0x07, 0x4a, 0x82, 0x89, 0x9c, 0x25, 0x38, 0xcf, 0x9a, 0x76, 0xd9, 0x64, 0x81, 0x49, 0x8e, 0xe4, 0x4d, 0xa8, 0x34, 0xfd, 0x6e, 0xaf, 0x43, 0x45, - 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0x0f, 0x49, + 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0xf7, 0x49, 0x1d, 0x47, 0x0d, 0x69, 0xf2, 0x69, 0x78, 0x34, 0xec, 0x37, 0x9b, 0x34, 0x0c, 0xb7, 0xfa, 0x1d, 0xec, 0x7b, 0xd7, 0xdd, 0x30, 0xf2, 0x83, 0xbd, 0x55, 0xb7, 0xeb, 0x46, 0x7c, 0x40, 0x17, 0xeb, 0x4f, 0x1c, 0xec, 0x57, 0x1f, 0x6d, 0x0c, 0x43, 0xc2, 0xe1, 0xf5, 0x89, 0x03, 0x8f, 0xf5, 0xbd, 0xe1, 0xe4, 0xc5, 0xf1, 0xa3, 0x7a, 0xb0, 0x5f, 0x7d, 0xec, 0xf6, 0x70, 0x34, 0x3c, 0x8c, 0x86, 0xfd, 0x27, 0x16, 0xdb, 0x86, 0xc4, 0x77, 0x6d, 0xd0, 0x6e, 0xaf, 0xc3, 0x96, 0xce, 0xb3, 0x57, - 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0xdf, 0x2c, + 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0x5f, 0x2d, 0xb8, 0x98, 0x46, 0x7e, 0x00, 0x0a, 0x5d, 0x98, 0x54, 0xe8, 0x6e, 0xe6, 0xfb, 0xb5, 0x43, 0xb4, 0xba, 0x5f, 0x34, 0x06, 0xac, 0x42, 0x45, 0xba, 0x45, 0x5e, 0x82, 0xa9, 0x48, 0xfe, 0xbd, 0x19, 0x2b, 0xe7, 0xda, 0x30, 0xb1, 0x61, 0xc0, 0x30, 0x81, 0xc9, 0x6a, 0x36, 0x3b, 0xfd, 0x30, 0xa2, 0x41, 0xa3, 0xe9, 0xf7, 0xc4, 0xb2, 0x5b, 0x8a, 0x6b, 0x2e, 0x19, 0x30, 0x4c, 0x60, 0xda, 0x7f, - 0xa3, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, + 0xad, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, 0x0f, 0x94, 0xfa, 0xf1, 0x25, 0x8b, 0x69, 0x71, 0x62, 0x00, 0x84, 0x52, 0x35, 0x7a, 0x3d, 0xdf, - 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x68, 0x1c, 0xa6, 0x6a, + 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x60, 0x1c, 0xa6, 0x6a, 0x5e, 0xe4, 0xd6, 0xb6, 0xb6, 0x5c, 0xcf, 0x8d, 0xf6, 0xc8, 0xd7, 0xc7, 0x60, 0xb1, 0x17, 0xd0, 0x2d, 0x1a, 0x04, 0xb4, 0xb5, 0xdc, 0x0f, 0x5c, 0xaf, 0xdd, 0x68, 0x6e, 0xd3, 0x56, 0xbf, 0xe3, 0x7a, 0xed, 0x95, 0xb6, 0xe7, 0xeb, 0xe2, 0xab, 0xf7, 0x69, 0xb3, 0xcf, 0xdb, 0x55, 0xac, 0x12, @@ -3516,12 +3516,12 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xe4, 0xc8, 0x1a, 0xf5, 0xd4, 0x1f, 0x4b, 0x2d, 0x85, 0x60, 0x3f, 0x51, 0xb0, 0xb0, 0xbf, 0x3b, 0x06, 0x97, 0x6a, 0xbd, 0xde, 0x1a, 0x0d, 0xb7, 0x53, 0x52, 0xfc, 0x92, 0x05, 0xd3, 0xbb, 0x6e, 0x10, 0xf5, 0x9d, 0x8e, 0xb2, 0x56, 0x0a, 0x79, 0x1a, 0xa3, 0xca, 0xc3, 0xb9, 0xbd, 0x91, 0x20, - 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x6d, 0xc1, 0xac, 0x2c, + 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x69, 0xc1, 0xac, 0x2c, 0xba, 0xe9, 0xb7, 0xa8, 0x69, 0x0d, 0xbf, 0x9d, 0xa7, 0x4c, 0x9a, 0xb8, 0xb0, 0x62, 0xa6, 0x4b, - 0x71, 0x40, 0x08, 0xfb, 0x7f, 0x8c, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, + 0x71, 0x40, 0x08, 0xfb, 0xbf, 0x8f, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, 0xa1, 0x1b, 0x20, 0xa4, 0x5b, 0xb2, 0x35, 0x3f, 0x99, 0xb7, 0xe4, 0xc8, 0xa6, 0x38, 0xf5, 0x9a, 0xb4, 0x3e, 0xc7, 0x96, 0xe4, 0xa5, 0x0c, 0xd6, 0x98, 0x29, 0x10, 0x97, 0x54, 0x18, 0xd5, 0x53, - 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc1, 0x63, 0x87, + 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc0, 0x63, 0x87, 0x90, 0x3b, 0x7a, 0x72, 0xda, 0x6f, 0xea, 0x51, 0x9f, 0x1c, 0x73, 0xc7, 0x98, 0xd7, 0x36, 0x4c, 0xf0, 0xa9, 0xa3, 0x26, 0x36, 0xb0, 0x3d, 0x98, 0xcf, 0xa9, 0x10, 0x25, 0xc4, 0xfe, 0xae, 0x05, 0xa5, 0x13, 0xd8, 0x3e, 0xab, 0x49, 0xdb, 0x67, 0x79, 0xc0, 0xee, 0x19, 0x0d, 0xda, 0x3d, 0x5f, @@ -3535,426 +3535,427 @@ var fileDescriptor_e0e705f843545fab = []byte{ 0xf2, 0x88, 0x96, 0x89, 0x5b, 0xec, 0x73, 0x9e, 0x93, 0x1c, 0xb5, 0xca, 0x28, 0x4a, 0x51, 0x72, 0xb2, 0xbf, 0x00, 0xd3, 0xc9, 0x7b, 0xb7, 0x63, 0x8c, 0xd9, 0x27, 0xa0, 0xe0, 0x04, 0x9e, 0x1c, 0xb1, 0x15, 0x89, 0x50, 0xa8, 0xe1, 0x4d, 0x64, 0xe5, 0xe4, 0x59, 0x28, 0x6d, 0xf5, 0x3b, 0x1d, - 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0x6c, 0x1c, - 0x66, 0xea, 0x9d, 0x3e, 0x7d, 0x35, 0xa0, 0x54, 0xd9, 0x82, 0x6a, 0x30, 0xd3, 0x0b, 0xe8, 0xae, - 0x4b, 0xef, 0x35, 0x68, 0x87, 0x36, 0x23, 0x3f, 0x90, 0xd2, 0x3c, 0x22, 0x09, 0xcd, 0xac, 0x27, - 0xc1, 0x98, 0xc6, 0x27, 0xaf, 0xc0, 0xb4, 0xd3, 0x8c, 0xdc, 0x5d, 0xaa, 0x29, 0x08, 0x71, 0x1f, - 0x96, 0x14, 0xa6, 0x6b, 0x09, 0x28, 0xa6, 0xb0, 0xc9, 0x67, 0x60, 0x2e, 0x6c, 0x3a, 0x1d, 0x7a, - 0xbb, 0x27, 0x59, 0x2d, 0x6d, 0xd3, 0xe6, 0xce, 0xba, 0xef, 0x7a, 0x91, 0xb4, 0x3b, 0x3e, 0x29, - 0x29, 0xcd, 0x35, 0x86, 0xe0, 0xe1, 0x50, 0x0a, 0xe4, 0x5f, 0x59, 0xf0, 0x44, 0x2f, 0xa0, 0xeb, - 0x81, 0xdf, 0xf5, 0xd9, 0x50, 0x1b, 0x30, 0x87, 0x49, 0xb3, 0xd0, 0x1b, 0x23, 0xea, 0x52, 0xa2, - 0x64, 0xf0, 0x0e, 0xe7, 0x27, 0x0e, 0xf6, 0xab, 0x4f, 0xac, 0x1f, 0x26, 0x00, 0x1e, 0x2e, 0x1f, - 0xf9, 0xd7, 0x16, 0x5c, 0xee, 0xf9, 0x61, 0x74, 0xc8, 0x27, 0x14, 0xcf, 0xf4, 0x13, 0xec, 0x83, - 0xfd, 0xea, 0xe5, 0xf5, 0x43, 0x25, 0xc0, 0x23, 0x24, 0xb4, 0x0f, 0x2a, 0x70, 0xde, 0x18, 0x7b, - 0xd2, 0x98, 0xf3, 0x32, 0x9c, 0x53, 0x83, 0x21, 0xd6, 0x7d, 0xca, 0xb1, 0x6d, 0xaf, 0x66, 0x02, - 0x31, 0x89, 0xcb, 0xc6, 0x9d, 0x1e, 0x8a, 0xa2, 0x76, 0x6a, 0xdc, 0xad, 0x27, 0xa0, 0x98, 0xc2, - 0x26, 0x2b, 0x70, 0x41, 0x96, 0x20, 0xed, 0x75, 0xdc, 0xa6, 0xb3, 0xe4, 0xf7, 0xe5, 0x90, 0x2b, - 0xd6, 0x1f, 0x39, 0xd8, 0xaf, 0x5e, 0x58, 0x1f, 0x04, 0x63, 0x56, 0x1d, 0xb2, 0x0a, 0x17, 0x9d, - 0x7e, 0xe4, 0xeb, 0xef, 0xbf, 0xea, 0xb1, 0xed, 0xb4, 0xc5, 0x87, 0x56, 0x49, 0xec, 0xbb, 0xb5, - 0x0c, 0x38, 0x66, 0xd6, 0x22, 0xeb, 0x29, 0x6a, 0x0d, 0xda, 0xf4, 0xbd, 0x96, 0xe8, 0xe5, 0x62, - 0x7c, 0x0c, 0xac, 0x65, 0xe0, 0x60, 0x66, 0x4d, 0xd2, 0x81, 0xe9, 0xae, 0x73, 0xff, 0xb6, 0xe7, - 0xec, 0x3a, 0x6e, 0x87, 0x31, 0x91, 0xf6, 0xc2, 0xe1, 0x56, 0xa6, 0x7e, 0xe4, 0x76, 0x16, 0x84, - 0x1f, 0xc7, 0xc2, 0x8a, 0x17, 0xdd, 0x0a, 0x1a, 0x11, 0xd3, 0xd4, 0x85, 0x06, 0xb9, 0x96, 0xa0, - 0x85, 0x29, 0xda, 0xe4, 0x16, 0x5c, 0xe2, 0xd3, 0x71, 0xd9, 0xbf, 0xe7, 0x2d, 0xd3, 0x8e, 0xb3, - 0xa7, 0x3e, 0x60, 0x92, 0x7f, 0xc0, 0xa3, 0x07, 0xfb, 0xd5, 0x4b, 0x8d, 0x2c, 0x04, 0xcc, 0xae, - 0x47, 0x1c, 0x78, 0x2c, 0x09, 0x40, 0xba, 0xeb, 0x86, 0xae, 0xef, 0x09, 0xb3, 0x5c, 0x29, 0x36, - 0xcb, 0x35, 0x86, 0xa3, 0xe1, 0x61, 0x34, 0xc8, 0xdf, 0xb3, 0xe0, 0x62, 0xd6, 0x34, 0x9c, 0x2b, - 0xe7, 0x71, 0x9b, 0x9c, 0x9a, 0x5a, 0x62, 0x44, 0x64, 0x2e, 0x0a, 0x99, 0x42, 0x90, 0x77, 0x2c, - 0x98, 0x72, 0x8c, 0x13, 0xf4, 0x1c, 0xe4, 0xb1, 0x6b, 0x99, 0x67, 0xf2, 0xfa, 0xec, 0xc1, 0x7e, - 0x35, 0x71, 0x4a, 0xc7, 0x04, 0x47, 0xf2, 0x0f, 0x2c, 0xb8, 0x94, 0x39, 0xc7, 0xe7, 0x2a, 0x67, - 0xd1, 0x42, 0x7c, 0x90, 0x64, 0xaf, 0x39, 0xd9, 0x62, 0x90, 0x6f, 0x5a, 0x7a, 0x2b, 0x53, 0x17, - 0x8c, 0x73, 0x53, 0x5c, 0xb4, 0x11, 0x0d, 0x1e, 0x86, 0x1a, 0xa5, 0x08, 0xd7, 0x2f, 0x18, 0x3b, - 0xa3, 0x2a, 0xc4, 0x34, 0x7b, 0xf2, 0x0d, 0x4b, 0x6d, 0x8d, 0x5a, 0xa2, 0x73, 0x67, 0x25, 0x11, - 0x89, 0x77, 0x5a, 0x2d, 0x50, 0x8a, 0x39, 0xf9, 0x59, 0x98, 0x77, 0x36, 0xfd, 0x20, 0xca, 0x9c, - 0x7c, 0x73, 0xd3, 0x7c, 0x1a, 0x5d, 0x3e, 0xd8, 0xaf, 0xce, 0xd7, 0x86, 0x62, 0xe1, 0x21, 0x14, - 0xec, 0xdf, 0x9d, 0x80, 0x29, 0x71, 0x12, 0x92, 0x5b, 0xd7, 0x6f, 0x59, 0xf0, 0x78, 0xb3, 0x1f, - 0x04, 0xd4, 0x8b, 0x1a, 0x11, 0xed, 0x0d, 0x6e, 0x5c, 0xd6, 0x99, 0x6e, 0x5c, 0x4f, 0x1e, 0xec, - 0x57, 0x1f, 0x5f, 0x3a, 0x84, 0x3f, 0x1e, 0x2a, 0x1d, 0xf9, 0xf7, 0x16, 0xd8, 0x12, 0xa1, 0xee, - 0x34, 0x77, 0xda, 0x81, 0xdf, 0xf7, 0x5a, 0x83, 0x1f, 0x31, 0x76, 0xa6, 0x1f, 0xf1, 0xf4, 0xc1, - 0x7e, 0xd5, 0x5e, 0x3a, 0x52, 0x0a, 0x3c, 0x86, 0xa4, 0xe4, 0x55, 0x38, 0x2f, 0xb1, 0xae, 0xde, - 0xef, 0xd1, 0xc0, 0x65, 0x67, 0x0e, 0xa9, 0x38, 0xc6, 0xbe, 0x69, 0x69, 0x04, 0x1c, 0xac, 0x43, - 0x42, 0x98, 0xbc, 0x47, 0xdd, 0xf6, 0x76, 0xa4, 0xd4, 0xa7, 0x11, 0x1d, 0xd2, 0xa4, 0x55, 0xe4, - 0x8e, 0xa0, 0x59, 0xaf, 0x1c, 0xec, 0x57, 0x27, 0xe5, 0x1f, 0x54, 0x9c, 0xc8, 0x4d, 0x98, 0x16, - 0xe7, 0xd4, 0x75, 0xd7, 0x6b, 0xaf, 0xfb, 0x9e, 0xf0, 0xaa, 0x2a, 0xd7, 0x9f, 0x56, 0x1b, 0x7e, - 0x23, 0x01, 0x7d, 0x6f, 0xbf, 0x3a, 0xa5, 0x7e, 0x6f, 0xec, 0xf5, 0x28, 0xa6, 0x6a, 0x93, 0xbf, - 0x6b, 0x01, 0x09, 0x23, 0xda, 0x5b, 0xef, 0xf4, 0xdb, 0xae, 0x6c, 0x22, 0xe9, 0x1f, 0x95, 0x83, - 0xab, 0x56, 0x92, 0x6e, 0x7d, 0x5e, 0x0a, 0x49, 0x1a, 0x03, 0x1c, 0x31, 0x43, 0x0a, 0xfb, 0x3b, - 0x93, 0x00, 0x6a, 0x2e, 0xd1, 0x1e, 0xf9, 0x10, 0x94, 0x43, 0x1a, 0x89, 0x26, 0x91, 0xd7, 0x5c, - 0xe2, 0x72, 0x52, 0x15, 0x62, 0x0c, 0x27, 0x3b, 0x50, 0xec, 0x39, 0xfd, 0x90, 0xe6, 0x73, 0xb8, - 0x91, 0x23, 0x73, 0x9d, 0x51, 0x14, 0xa7, 0x66, 0xfe, 0x13, 0x05, 0x0f, 0xf2, 0x65, 0x0b, 0x80, - 0x26, 0x47, 0xd3, 0xc8, 0xd6, 0x2b, 0xc9, 0x32, 0x1e, 0x70, 0xac, 0x0d, 0xea, 0xd3, 0x07, 0xfb, - 0x55, 0x30, 0xc6, 0xa5, 0xc1, 0x96, 0xdc, 0x83, 0x92, 0xa3, 0x36, 0xa4, 0xf1, 0xb3, 0xd8, 0x90, - 0xf8, 0x61, 0x56, 0xcf, 0x28, 0xcd, 0x8c, 0x7c, 0xd5, 0x82, 0xe9, 0x90, 0x46, 0xb2, 0xab, 0xd8, - 0xb2, 0x28, 0xb5, 0xf1, 0x11, 0x67, 0x44, 0x23, 0x41, 0x53, 0x2c, 0xef, 0xc9, 0x32, 0x4c, 0xf1, - 0x55, 0xa2, 0x5c, 0xa7, 0x4e, 0x8b, 0x06, 0xdc, 0x56, 0x22, 0xd5, 0xbc, 0xd1, 0x45, 0x31, 0x68, - 0x6a, 0x51, 0x8c, 0x32, 0x4c, 0xf1, 0x55, 0xa2, 0xac, 0xb9, 0x41, 0xe0, 0x4b, 0x51, 0x4a, 0x39, - 0x89, 0x62, 0xd0, 0xd4, 0xa2, 0x18, 0x65, 0x98, 0xe2, 0x4b, 0x3a, 0x30, 0xd1, 0xe3, 0x53, 0x4b, - 0xaa, 0x72, 0x23, 0xde, 0x91, 0xab, 0x69, 0x4a, 0x7b, 0xc2, 0x26, 0x25, 0xfe, 0xa3, 0xe4, 0x61, - 0x7f, 0xfb, 0x1c, 0x4c, 0xab, 0x69, 0x1b, 0x1f, 0x72, 0x84, 0x21, 0x70, 0xc8, 0x21, 0x67, 0xc9, - 0x04, 0x62, 0x12, 0x97, 0x55, 0x16, 0xab, 0x56, 0xf2, 0x8c, 0xa3, 0x2b, 0x37, 0x4c, 0x20, 0x26, - 0x71, 0x49, 0x17, 0x8a, 0x6c, 0x65, 0x51, 0xee, 0x17, 0x23, 0x7e, 0x79, 0xbc, 0x1a, 0x19, 0x46, - 0x15, 0x46, 0x1e, 0x05, 0x17, 0x6e, 0xcb, 0x8e, 0x12, 0xe6, 0x6d, 0x39, 0x15, 0xf3, 0x59, 0x0d, - 0x92, 0x96, 0x73, 0xd1, 0xf7, 0xc9, 0x32, 0x4c, 0xb1, 0xcf, 0x38, 0xf7, 0x14, 0xcf, 0xf0, 0xdc, - 0xf3, 0x29, 0x28, 0x75, 0x9d, 0xfb, 0x8d, 0x7e, 0xd0, 0x3e, 0xfd, 0xf9, 0x4a, 0xba, 0xd3, 0x0a, - 0x2a, 0xa8, 0xe9, 0x91, 0x2f, 0x5a, 0xc6, 0x02, 0x27, 0x7c, 0x2d, 0xee, 0xe4, 0xbb, 0xc0, 0x69, - 0xb5, 0x61, 0xe8, 0x52, 0x37, 0x70, 0x0a, 0x29, 0x3d, 0xf0, 0x53, 0x08, 0xd3, 0xa8, 0xc5, 0x04, - 0xd1, 0x1a, 0x75, 0xf9, 0x4c, 0x35, 0xea, 0xa5, 0x04, 0x33, 0x4c, 0x31, 0xe7, 0xf2, 0x88, 0x39, - 0xa7, 0xe5, 0x81, 0x33, 0x95, 0xa7, 0x91, 0x60, 0x86, 0x29, 0xe6, 0xc3, 0x8f, 0xde, 0x95, 0xb3, - 0x39, 0x7a, 0x4f, 0xe5, 0x70, 0xf4, 0x3e, 0xfc, 0x54, 0x72, 0x6e, 0xd4, 0x53, 0x09, 0xb9, 0x01, - 0xa4, 0xb5, 0xe7, 0x39, 0x5d, 0xb7, 0x29, 0x17, 0x4b, 0xbe, 0x49, 0x4f, 0x73, 0xd3, 0x8c, 0xd6, - 0xca, 0x96, 0x07, 0x30, 0x30, 0xa3, 0x16, 0x89, 0xa0, 0xd4, 0x53, 0xca, 0xe7, 0x4c, 0x1e, 0xa3, - 0x5f, 0x29, 0xa3, 0xc2, 0x85, 0x86, 0x4d, 0x3c, 0x55, 0x82, 0x9a, 0x13, 0x59, 0x85, 0x8b, 0x5d, - 0xd7, 0x5b, 0xf7, 0x5b, 0xe1, 0x3a, 0x0d, 0xa4, 0xe1, 0xa9, 0x41, 0xa3, 0xb9, 0x59, 0xde, 0x36, - 0xdc, 0x98, 0xb0, 0x96, 0x01, 0xc7, 0xcc, 0x5a, 0xf6, 0xff, 0xb6, 0x60, 0x76, 0xa9, 0xe3, 0xf7, - 0x5b, 0x77, 0x9c, 0xa8, 0xb9, 0x2d, 0x3c, 0x36, 0xc8, 0x2b, 0x50, 0x72, 0xbd, 0x88, 0x06, 0xbb, - 0x4e, 0x47, 0xee, 0x4f, 0xb6, 0xb2, 0x24, 0xaf, 0xc8, 0xf2, 0xf7, 0xf6, 0xab, 0xd3, 0xcb, 0xfd, - 0x80, 0x1b, 0xec, 0xc5, 0x6a, 0x85, 0xba, 0x0e, 0xf9, 0xb6, 0x05, 0xe7, 0x85, 0xcf, 0xc7, 0xb2, - 0x13, 0x39, 0xaf, 0xf7, 0x69, 0xe0, 0x52, 0xe5, 0xf5, 0x31, 0xe2, 0x42, 0x95, 0x96, 0x55, 0x31, - 0xd8, 0x8b, 0xcf, 0x2c, 0x6b, 0x69, 0xce, 0x38, 0x28, 0x8c, 0xfd, 0xcb, 0x05, 0x78, 0x74, 0x28, - 0x2d, 0x32, 0x0f, 0x63, 0x6e, 0x4b, 0x7e, 0x3a, 0x48, 0xba, 0x63, 0x2b, 0x2d, 0x1c, 0x73, 0x5b, - 0x64, 0x81, 0x6b, 0xb8, 0x01, 0x0d, 0x43, 0x75, 0xf7, 0x5e, 0xd6, 0xca, 0xa8, 0x2c, 0x45, 0x03, - 0x83, 0x54, 0xa1, 0xc8, 0x5d, 0xa9, 0xe5, 0xd1, 0x8a, 0xeb, 0xcc, 0xdc, 0x6b, 0x19, 0x45, 0x39, - 0xf9, 0x92, 0x05, 0x20, 0x04, 0x64, 0xfa, 0xbe, 0xdc, 0x25, 0x31, 0xdf, 0x66, 0x62, 0x94, 0x85, - 0x94, 0xf1, 0x7f, 0x34, 0xb8, 0x92, 0x0d, 0x98, 0x60, 0xea, 0xb3, 0xdf, 0x3a, 0xf5, 0xa6, 0x28, - 0x14, 0x20, 0x4e, 0x03, 0x25, 0x2d, 0xd6, 0x56, 0x01, 0x8d, 0xfa, 0x81, 0xc7, 0x9a, 0x96, 0x6f, - 0x83, 0x25, 0x21, 0x05, 0xea, 0x52, 0x34, 0x30, 0xec, 0x7f, 0x31, 0x06, 0x17, 0xb3, 0x44, 0x67, - 0xbb, 0xcd, 0x84, 0x90, 0x56, 0x5a, 0x09, 0x7e, 0x26, 0xff, 0xf6, 0x91, 0xee, 0x4b, 0xfa, 0xc6, - 0x46, 0xfa, 0x92, 0x4a, 0xbe, 0xe4, 0x67, 0x74, 0x0b, 0x8d, 0x9d, 0xb2, 0x85, 0x34, 0xe5, 0x54, - 0x2b, 0x3d, 0x09, 0xe3, 0x21, 0xeb, 0xf9, 0x42, 0xf2, 0xe6, 0x87, 0xf7, 0x11, 0x87, 0x30, 0x8c, - 0xbe, 0xe7, 0x46, 0x32, 0xfe, 0x48, 0x63, 0xdc, 0xf6, 0xdc, 0x08, 0x39, 0xc4, 0xfe, 0xd6, 0x18, - 0xcc, 0x0f, 0xff, 0x28, 0xf2, 0x2d, 0x0b, 0xa0, 0xc5, 0x0e, 0x47, 0x21, 0x77, 0xe2, 0x17, 0xee, - 0x5e, 0xce, 0x59, 0xb5, 0xe1, 0xb2, 0xe2, 0x14, 0xfb, 0x21, 0xea, 0xa2, 0x10, 0x0d, 0x41, 0xc8, - 0x73, 0x6a, 0xe8, 0xf3, 0x5b, 0x2b, 0x31, 0x99, 0x74, 0x9d, 0x35, 0x0d, 0x41, 0x03, 0x8b, 0x9d, - 0x7e, 0x3d, 0xa7, 0x4b, 0xc3, 0x9e, 0xa3, 0xa3, 0xb9, 0xf8, 0xe9, 0xf7, 0xa6, 0x2a, 0xc4, 0x18, - 0x6e, 0x77, 0xe0, 0xa9, 0x63, 0xc8, 0x99, 0x53, 0xb0, 0x8c, 0xfd, 0x3f, 0x2d, 0x78, 0x44, 0x7a, - 0xe2, 0xfd, 0x7f, 0xe3, 0xd6, 0xf9, 0xa7, 0x16, 0x3c, 0x36, 0xe4, 0x9b, 0x1f, 0x80, 0x77, 0xe7, - 0x5b, 0x49, 0xef, 0xce, 0xdb, 0xa3, 0x0e, 0xe9, 0xcc, 0xef, 0x18, 0xe2, 0xe4, 0xf9, 0xbb, 0x05, - 0x38, 0xc7, 0x96, 0xad, 0x96, 0xdf, 0xce, 0x69, 0xe3, 0x7c, 0x0a, 0x8a, 0x9f, 0x63, 0x1b, 0x50, - 0x7a, 0x90, 0xf1, 0x5d, 0x09, 0x05, 0x8c, 0x7c, 0xd9, 0x82, 0xc9, 0xcf, 0xc9, 0x3d, 0x55, 0x9c, - 0xe5, 0x46, 0x5c, 0x0c, 0x13, 0xdf, 0xb0, 0x20, 0x77, 0x48, 0x11, 0x83, 0xa3, 0x7d, 0x39, 0xd5, - 0x56, 0xaa, 0x38, 0x93, 0x67, 0x60, 0x72, 0xcb, 0x0f, 0xba, 0xfd, 0x8e, 0x93, 0x0e, 0xfc, 0xbc, - 0x26, 0x8a, 0x51, 0xc1, 0xd9, 0x24, 0x77, 0x7a, 0xee, 0x1b, 0x34, 0x08, 0x45, 0x48, 0x46, 0x62, - 0x92, 0xd7, 0x34, 0x04, 0x0d, 0x2c, 0x5e, 0xa7, 0xdd, 0x0e, 0x68, 0xdb, 0x89, 0xfc, 0x80, 0xef, - 0x1c, 0x66, 0x1d, 0x0d, 0x41, 0x03, 0x6b, 0xfe, 0xe3, 0x30, 0x65, 0x0a, 0x7f, 0xa2, 0x78, 0x9e, - 0x4f, 0x80, 0x74, 0xea, 0x4c, 0x2d, 0x49, 0xd6, 0x71, 0x96, 0x24, 0xfb, 0x3f, 0x8e, 0x81, 0x61, - 0x8b, 0x7a, 0x00, 0x53, 0xdd, 0x4b, 0x4c, 0xf5, 0x11, 0xed, 0x28, 0x86, 0x65, 0x6d, 0x58, 0x74, - 0xe3, 0x6e, 0x2a, 0xba, 0xf1, 0x66, 0x6e, 0x1c, 0x0f, 0x0f, 0x6e, 0xfc, 0x81, 0x05, 0x8f, 0xc5, - 0xc8, 0x83, 0x36, 0xec, 0xa3, 0xd7, 0xed, 0x17, 0xa1, 0xe2, 0xc4, 0xd5, 0xe4, 0xc4, 0x32, 0x42, - 0xcb, 0x34, 0x08, 0x4d, 0xbc, 0x38, 0x2c, 0xa6, 0x70, 0xca, 0xb0, 0x98, 0xf1, 0xc3, 0xc3, 0x62, - 0xec, 0x1f, 0x8f, 0xc1, 0x13, 0x83, 0x5f, 0x66, 0xfa, 0x8a, 0x1f, 0xfd, 0x6d, 0x69, 0x6f, 0xf2, - 0xb1, 0x53, 0x7b, 0x93, 0x17, 0x8e, 0xeb, 0x4d, 0xae, 0x7d, 0xb8, 0xc7, 0xcf, 0xdc, 0x87, 0xbb, - 0x01, 0x97, 0x94, 0xc3, 0xe8, 0x35, 0x3f, 0x90, 0xb1, 0x21, 0x6a, 0x05, 0x29, 0xd5, 0x9f, 0x90, - 0x55, 0x2e, 0x61, 0x16, 0x12, 0x66, 0xd7, 0xb5, 0x7f, 0x50, 0x80, 0x0b, 0x71, 0xb3, 0x2f, 0xf9, - 0x5e, 0xcb, 0xe5, 0x3e, 0x47, 0x2f, 0xc3, 0x78, 0xb4, 0xd7, 0x53, 0x8d, 0xfd, 0x97, 0x95, 0x38, - 0x1b, 0x7b, 0x3d, 0xd6, 0xdb, 0x8f, 0x64, 0x54, 0xe1, 0xb7, 0x08, 0xbc, 0x12, 0x59, 0xd5, 0xb3, - 0x43, 0xf4, 0xc0, 0x0b, 0xc9, 0xd1, 0xfc, 0xde, 0x7e, 0x35, 0x23, 0xcb, 0xc3, 0x82, 0xa6, 0x94, - 0x1c, 0xf3, 0xe4, 0x2e, 0x4c, 0x77, 0x9c, 0x30, 0xba, 0xdd, 0x6b, 0x39, 0x11, 0xdd, 0x70, 0xa5, - 0x37, 0xcf, 0xc9, 0xc2, 0x69, 0xb4, 0xdb, 0xc3, 0x6a, 0x82, 0x12, 0xa6, 0x28, 0x93, 0x5d, 0x20, - 0xac, 0x64, 0x23, 0x70, 0xbc, 0x50, 0x7c, 0x15, 0xe3, 0x77, 0xf2, 0xd8, 0x28, 0x7d, 0x74, 0x5e, - 0x1d, 0xa0, 0x86, 0x19, 0x1c, 0xc8, 0xd3, 0x30, 0x11, 0x50, 0x27, 0xd4, 0xdb, 0x81, 0x9e, 0xff, - 0xc8, 0x4b, 0x51, 0x42, 0xcd, 0x09, 0x35, 0x71, 0xc4, 0x84, 0xfa, 0x43, 0x0b, 0xa6, 0xe3, 0x6e, - 0x7a, 0x00, 0xaa, 0x47, 0x37, 0xa9, 0x7a, 0x5c, 0xcf, 0x6b, 0x49, 0x1c, 0xa2, 0x6d, 0xfc, 0xc9, - 0xa4, 0xf9, 0x7d, 0x3c, 0x80, 0xe3, 0xf3, 0xa6, 0x3f, 0xbf, 0x95, 0x47, 0x54, 0x5d, 0x42, 0xdb, - 0x3b, 0xd4, 0x91, 0x9f, 0xe9, 0x3a, 0x2d, 0xa9, 0xc7, 0xc8, 0x61, 0xaf, 0x75, 0x1d, 0xa5, 0xdf, - 0x64, 0xe9, 0x3a, 0xaa, 0x0e, 0xb9, 0x0d, 0x8f, 0xf4, 0x02, 0x9f, 0xe7, 0x19, 0x58, 0xa6, 0x4e, - 0xab, 0xe3, 0x7a, 0x54, 0x99, 0x79, 0x84, 0xd7, 0xcd, 0x63, 0x07, 0xfb, 0xd5, 0x47, 0xd6, 0xb3, - 0x51, 0x70, 0x58, 0xdd, 0x64, 0xa4, 0xea, 0xf8, 0x31, 0x22, 0x55, 0x7f, 0x51, 0x1b, 0x53, 0x75, - 0x50, 0xc4, 0xa7, 0xf3, 0xea, 0xca, 0xac, 0xf0, 0x08, 0x3d, 0xa4, 0x6a, 0x92, 0x29, 0x6a, 0xf6, - 0xc3, 0x2d, 0x76, 0x13, 0xa7, 0xb4, 0xd8, 0xc5, 0x71, 0x30, 0x93, 0xef, 0x67, 0x1c, 0x4c, 0xe9, - 0x03, 0x15, 0x07, 0xf3, 0x6d, 0x0b, 0x2e, 0x38, 0x83, 0x11, 0xe8, 0xf9, 0x18, 0x8f, 0x33, 0x42, - 0xdb, 0xeb, 0x8f, 0x49, 0x21, 0xb3, 0x02, 0xfd, 0x31, 0x4b, 0x14, 0xfb, 0xdd, 0x22, 0xcc, 0xa6, - 0x95, 0xa4, 0xb3, 0x0f, 0xd5, 0xfd, 0x5b, 0x16, 0xcc, 0xaa, 0x09, 0xae, 0x6f, 0xc0, 0xc5, 0x11, - 0x63, 0x35, 0xa7, 0x75, 0x45, 0xa8, 0x7b, 0x3a, 0x83, 0xca, 0x46, 0x8a, 0x1b, 0x0e, 0xf0, 0x27, - 0x6f, 0x42, 0x45, 0xdf, 0xaa, 0x9c, 0x2a, 0x6e, 0x97, 0x87, 0x96, 0xd6, 0x62, 0x12, 0x68, 0xd2, - 0x23, 0xef, 0x5a, 0x00, 0x4d, 0xb5, 0x13, 0xe7, 0x14, 0x15, 0x95, 0xa1, 0x2d, 0xc4, 0xfa, 0xbc, - 0x2e, 0x0a, 0xd1, 0x60, 0x4c, 0x7e, 0x99, 0xdf, 0xa7, 0xe8, 0x91, 0xa0, 0x3c, 0x0f, 0x3e, 0x99, - 0xf7, 0x52, 0x14, 0xfb, 0x92, 0x68, 0x6d, 0xcf, 0x00, 0x85, 0x98, 0x10, 0xc2, 0x7e, 0x19, 0xb4, - 0xcf, 0x36, 0x5b, 0x59, 0xb9, 0xd7, 0xf6, 0xba, 0x13, 0x6d, 0xcb, 0x21, 0xa8, 0x57, 0xd6, 0x6b, - 0x0a, 0x80, 0x31, 0x8e, 0xfd, 0x59, 0x98, 0x7e, 0x35, 0x70, 0x7a, 0xdb, 0x2e, 0xbf, 0xb7, 0x60, - 0xe7, 0xe3, 0x67, 0x60, 0xd2, 0x69, 0xb5, 0xb2, 0x92, 0xfd, 0xd4, 0x44, 0x31, 0x2a, 0xf8, 0xb1, - 0x8e, 0xc2, 0xf6, 0xbf, 0xb5, 0x80, 0xc4, 0x37, 0xcd, 0xae, 0xd7, 0x5e, 0x73, 0xa2, 0xe6, 0x36, - 0x3b, 0xc2, 0x6d, 0xf3, 0xd2, 0xac, 0x23, 0xdc, 0x75, 0x0d, 0x41, 0x03, 0x8b, 0xbc, 0x0d, 0x15, - 0xf1, 0xef, 0x0d, 0x7d, 0x40, 0x1c, 0xdd, 0xf5, 0x9c, 0xef, 0x79, 0x5c, 0x26, 0x31, 0x0a, 0xaf, - 0xc7, 0x1c, 0xd0, 0x64, 0xc7, 0x9a, 0x6a, 0xc5, 0xdb, 0xea, 0xf4, 0xef, 0xb7, 0x36, 0xe3, 0xa6, - 0xea, 0x05, 0xfe, 0x96, 0xdb, 0xa1, 0xe9, 0xa6, 0x5a, 0x17, 0xc5, 0xa8, 0xe0, 0xc7, 0x6b, 0xaa, - 0x7f, 0x63, 0xc1, 0xc5, 0x95, 0x30, 0x72, 0xfd, 0x65, 0x1a, 0x46, 0x6c, 0xe7, 0x63, 0xeb, 0x63, - 0xbf, 0x73, 0x9c, 0xf0, 0x8b, 0x65, 0x98, 0x95, 0xf7, 0xd0, 0xfd, 0xcd, 0x90, 0x46, 0xc6, 0x51, - 0x43, 0xcf, 0xe3, 0xa5, 0x14, 0x1c, 0x07, 0x6a, 0x30, 0x2a, 0xf2, 0x42, 0x3a, 0xa6, 0x52, 0x48, - 0x52, 0x69, 0xa4, 0xe0, 0x38, 0x50, 0xc3, 0xfe, 0x7e, 0x01, 0x2e, 0xf0, 0xcf, 0x48, 0x85, 0x4e, - 0x7d, 0x63, 0x58, 0xe8, 0xd4, 0x88, 0x53, 0x99, 0xf3, 0x3a, 0x45, 0xe0, 0xd4, 0xdf, 0xb4, 0x60, - 0xa6, 0x95, 0x6c, 0xe9, 0x7c, 0xec, 0x72, 0x59, 0x7d, 0x28, 0x3c, 0x10, 0x53, 0x85, 0x98, 0xe6, - 0x4f, 0x7e, 0xc5, 0x82, 0x99, 0xa4, 0x98, 0x6a, 0x75, 0x3f, 0x83, 0x46, 0xd2, 0x21, 0x03, 0xc9, - 0xf2, 0x10, 0xd3, 0x22, 0xd8, 0xbf, 0x37, 0x26, 0xbb, 0xf4, 0x2c, 0xe2, 0x82, 0xc8, 0x3d, 0x28, - 0x47, 0x9d, 0x50, 0x14, 0xca, 0xaf, 0x1d, 0xf1, 0xd0, 0xba, 0xb1, 0xda, 0x10, 0x0e, 0x27, 0xb1, - 0x5e, 0x29, 0x4b, 0x98, 0x7e, 0xac, 0x78, 0x71, 0xc6, 0xcd, 0x9e, 0x64, 0x9c, 0xcb, 0x69, 0x79, - 0x63, 0x69, 0x3d, 0xcd, 0x58, 0x96, 0x30, 0xc6, 0x8a, 0x97, 0xfd, 0x1b, 0x16, 0x94, 0x6f, 0xf8, - 0x6a, 0x1d, 0xf9, 0xd9, 0x1c, 0x6c, 0x51, 0x5a, 0x65, 0xd5, 0x4a, 0x4b, 0x7c, 0x0a, 0x7a, 0x25, - 0x61, 0x89, 0x7a, 0xdc, 0xa0, 0xbd, 0xc0, 0x73, 0x1e, 0x32, 0x52, 0x37, 0xfc, 0xcd, 0xa1, 0xe6, - 0xe3, 0x5f, 0x2d, 0xc2, 0xb9, 0xd7, 0x9c, 0x3d, 0xea, 0x45, 0xce, 0xc9, 0x37, 0x89, 0x17, 0xa1, - 0xe2, 0xf4, 0xf8, 0x5d, 0xa6, 0x71, 0x0c, 0x89, 0x8d, 0x3b, 0x31, 0x08, 0x4d, 0xbc, 0x78, 0x41, - 0x13, 0x41, 0x3a, 0x59, 0x4b, 0xd1, 0x52, 0x0a, 0x8e, 0x03, 0x35, 0xc8, 0x0d, 0x20, 0x32, 0xb0, - 0xbd, 0xd6, 0x6c, 0xfa, 0x7d, 0x4f, 0x2c, 0x69, 0xc2, 0xee, 0xa3, 0xcf, 0xc3, 0x6b, 0x03, 0x18, - 0x98, 0x51, 0x8b, 0x7c, 0x06, 0xe6, 0x9a, 0x9c, 0xb2, 0x3c, 0x1d, 0x99, 0x14, 0xc5, 0x09, 0x59, - 0x87, 0xbd, 0x2c, 0x0d, 0xc1, 0xc3, 0xa1, 0x14, 0x98, 0xa4, 0x61, 0xe4, 0x07, 0x4e, 0x9b, 0x9a, - 0x74, 0x27, 0x92, 0x92, 0x36, 0x06, 0x30, 0x30, 0xa3, 0x16, 0xf9, 0x02, 0x94, 0xa3, 0xed, 0x80, - 0x86, 0xdb, 0x7e, 0xa7, 0x25, 0x7d, 0x4f, 0x46, 0x34, 0x06, 0xca, 0xde, 0xdf, 0x50, 0x54, 0x8d, - 0xe1, 0xad, 0x8a, 0x30, 0xe6, 0x49, 0x02, 0x98, 0x08, 0x9b, 0x7e, 0x8f, 0x86, 0xf2, 0x54, 0x71, - 0x23, 0x17, 0xee, 0xdc, 0xb8, 0x65, 0x98, 0x21, 0x39, 0x07, 0x94, 0x9c, 0xec, 0xdf, 0x19, 0x83, - 0x29, 0x13, 0xf1, 0x18, 0x6b, 0xd3, 0x97, 0x2d, 0x98, 0x6a, 0xfa, 0x5e, 0x14, 0xf8, 0x9d, 0x38, - 0x61, 0xc3, 0xe8, 0x1a, 0x05, 0x23, 0xb5, 0x4c, 0x23, 0xc7, 0xed, 0x18, 0xd6, 0x3a, 0x83, 0x0d, - 0x26, 0x98, 0x92, 0xaf, 0x5b, 0x30, 0x13, 0x3b, 0x46, 0xc6, 0xb6, 0xbe, 0x5c, 0x05, 0xd1, 0x4b, - 0xfd, 0xd5, 0x24, 0x27, 0x4c, 0xb3, 0xb6, 0x37, 0x61, 0x36, 0xdd, 0xdb, 0xac, 0x29, 0x7b, 0x8e, - 0x9c, 0xeb, 0x85, 0xb8, 0x29, 0xd7, 0x9d, 0x30, 0x44, 0x0e, 0x21, 0xcf, 0x42, 0xa9, 0xeb, 0x04, - 0x6d, 0xd7, 0x73, 0x3a, 0xbc, 0x15, 0x0b, 0xc6, 0x82, 0x24, 0xcb, 0x51, 0x63, 0xd8, 0x1f, 0x81, - 0xa9, 0x35, 0xc7, 0x6b, 0xd3, 0x96, 0x5c, 0x87, 0x8f, 0x8e, 0x4c, 0xfd, 0xe3, 0x71, 0xa8, 0x18, - 0xc7, 0xc7, 0xb3, 0x3f, 0x67, 0x25, 0x12, 0x11, 0x15, 0x72, 0x4c, 0x44, 0xf4, 0x29, 0x80, 0x2d, - 0xd7, 0x73, 0xc3, 0xed, 0x53, 0xa6, 0x38, 0xe2, 0x77, 0xf3, 0xd7, 0x34, 0x05, 0x34, 0xa8, 0xc5, - 0x17, 0xa0, 0xc5, 0x43, 0xb2, 0x05, 0xbe, 0x6b, 0x19, 0xdb, 0xcd, 0x44, 0x1e, 0x0e, 0x1f, 0x46, - 0xc7, 0x2c, 0xa8, 0xed, 0x47, 0xdc, 0x4d, 0x1d, 0xb6, 0x2b, 0x6d, 0x40, 0x29, 0xa0, 0x61, 0xbf, - 0x4b, 0x4f, 0x95, 0x8c, 0x88, 0xbb, 0xde, 0xa0, 0xac, 0x8f, 0x9a, 0xd2, 0xfc, 0xcb, 0x70, 0x2e, - 0x21, 0xc2, 0x89, 0x6e, 0x98, 0x7c, 0xc8, 0xb4, 0x51, 0x9c, 0xe6, 0xbe, 0x89, 0xf5, 0x45, 0xc7, - 0x48, 0x42, 0xa4, 0xfb, 0x42, 0x38, 0x58, 0x09, 0x98, 0xfd, 0xe3, 0x09, 0x90, 0x3e, 0x0c, 0xc7, - 0x58, 0xae, 0xcc, 0x9b, 0xcb, 0xb1, 0x53, 0xdc, 0x5c, 0xde, 0x80, 0x29, 0xd7, 0x73, 0x23, 0xd7, - 0xe9, 0x70, 0xfb, 0x93, 0xdc, 0x4e, 0x95, 0x33, 0xfe, 0xd4, 0x8a, 0x01, 0xcb, 0xa0, 0x93, 0xa8, - 0x4b, 0x5e, 0x87, 0x22, 0xdf, 0x6f, 0xe4, 0x00, 0x3e, 0xb9, 0xa3, 0x05, 0xf7, 0xb1, 0x11, 0x11, - 0x7a, 0x82, 0x12, 0x3f, 0x7c, 0x88, 0x2c, 0x4c, 0xfa, 0xf8, 0x2d, 0xc7, 0x71, 0x7c, 0xf8, 0x48, - 0xc1, 0x71, 0xa0, 0x06, 0xa3, 0xb2, 0xe5, 0xb8, 0x9d, 0x7e, 0x40, 0x63, 0x2a, 0x13, 0x49, 0x2a, - 0xd7, 0x52, 0x70, 0x1c, 0xa8, 0x41, 0xb6, 0x60, 0x4a, 0x96, 0x09, 0xb7, 0xb9, 0xc9, 0x53, 0x7e, - 0x25, 0x77, 0x8f, 0xbc, 0x66, 0x50, 0xc2, 0x04, 0x5d, 0xd2, 0x87, 0xf3, 0xae, 0xd7, 0xf4, 0xbd, - 0x66, 0xa7, 0x1f, 0xba, 0xbb, 0x34, 0x0e, 0x8f, 0x3b, 0x0d, 0xb3, 0x4b, 0x07, 0xfb, 0xd5, 0xf3, - 0x2b, 0x69, 0x72, 0x38, 0xc8, 0x81, 0x7c, 0xd1, 0x82, 0x4b, 0x4d, 0xdf, 0x0b, 0x79, 0x16, 0x8f, - 0x5d, 0x7a, 0x35, 0x08, 0xfc, 0x40, 0xf0, 0x2e, 0x9f, 0x92, 0x37, 0x37, 0x7b, 0x2e, 0x65, 0x91, - 0xc4, 0x6c, 0x4e, 0xe4, 0x2d, 0x28, 0xf5, 0x02, 0x7f, 0xd7, 0x6d, 0xd1, 0x40, 0xba, 0x60, 0xae, - 0xe6, 0x91, 0xda, 0x68, 0x5d, 0xd2, 0x8c, 0x97, 0x1e, 0x55, 0x82, 0x9a, 0x9f, 0xfd, 0x7f, 0x2a, - 0x30, 0x9d, 0x44, 0x27, 0x3f, 0x0f, 0xd0, 0x0b, 0xfc, 0x2e, 0x8d, 0xb6, 0xa9, 0x0e, 0x73, 0xba, - 0x39, 0x6a, 0xf2, 0x1a, 0x45, 0x4f, 0xb9, 0x2d, 0xb1, 0xe5, 0x22, 0x2e, 0x45, 0x83, 0x23, 0x09, - 0x60, 0x72, 0x47, 0x6c, 0xbb, 0x52, 0x0b, 0x79, 0x2d, 0x17, 0x9d, 0x49, 0x72, 0xe6, 0xf1, 0x39, - 0xb2, 0x08, 0x15, 0x23, 0xb2, 0x09, 0x85, 0x7b, 0x74, 0x33, 0x9f, 0xcc, 0x09, 0x77, 0xa8, 0x3c, - 0xcd, 0xd4, 0x27, 0x0f, 0xf6, 0xab, 0x85, 0x3b, 0x74, 0x13, 0x19, 0x71, 0xf6, 0x5d, 0x2d, 0xe1, - 0xbb, 0x20, 0x97, 0x8a, 0xd7, 0x72, 0x74, 0x84, 0x10, 0xdf, 0x25, 0x8b, 0x50, 0x31, 0x22, 0x6f, - 0x41, 0xf9, 0x9e, 0xb3, 0x4b, 0xb7, 0x02, 0xdf, 0x8b, 0xa4, 0xaf, 0xdc, 0x88, 0xc1, 0x25, 0x77, - 0x14, 0x39, 0xc9, 0x97, 0x6f, 0xef, 0xba, 0x10, 0x63, 0x76, 0x64, 0x17, 0x4a, 0x1e, 0xbd, 0x87, - 0xb4, 0xe3, 0x36, 0xf3, 0x09, 0xe6, 0xb8, 0x29, 0xa9, 0x49, 0xce, 0x7c, 0xdf, 0x53, 0x65, 0xa8, - 0x79, 0xb1, 0xbe, 0xbc, 0xeb, 0x6f, 0xca, 0x85, 0x6a, 0xc4, 0xbe, 0xd4, 0x27, 0x53, 0xd1, 0x97, - 0x37, 0xfc, 0x4d, 0x64, 0xc4, 0xd9, 0x1c, 0x69, 0x6a, 0x47, 0x2d, 0xb9, 0x4c, 0xdd, 0xcc, 0xd7, - 0x41, 0x4d, 0xcc, 0x91, 0xb8, 0x14, 0x0d, 0x8e, 0xac, 0x6d, 0xdb, 0xd2, 0x58, 0x29, 0x17, 0xaa, - 0x11, 0xdb, 0x36, 0x69, 0xfa, 0x14, 0x6d, 0xab, 0xca, 0x50, 0xf3, 0x62, 0x7c, 0x5d, 0x69, 0xf9, - 0xcb, 0x67, 0xa9, 0x4a, 0xda, 0x11, 0x05, 0x5f, 0x55, 0x86, 0x9a, 0x17, 0x6b, 0xef, 0x70, 0x67, - 0xef, 0x9e, 0xd3, 0xd9, 0x71, 0xbd, 0xb6, 0x0c, 0xdb, 0x1d, 0x35, 0xcc, 0x6d, 0x67, 0xef, 0x8e, - 0xa0, 0x67, 0xb6, 0x77, 0x5c, 0x8a, 0x06, 0x47, 0xf2, 0xf7, 0x2d, 0x1d, 0x8a, 0x33, 0x95, 0x87, - 0x13, 0x53, 0x72, 0xc9, 0x95, 0x91, 0x39, 0x42, 0x51, 0xfc, 0x29, 0xed, 0x77, 0xc9, 0x0b, 0xbf, - 0xf6, 0x47, 0xd5, 0x39, 0xea, 0x35, 0xfd, 0x96, 0xeb, 0xb5, 0x17, 0xef, 0x86, 0xbe, 0xb7, 0x80, - 0xce, 0x3d, 0xa5, 0xa3, 0x4b, 0x99, 0xe6, 0x3f, 0x06, 0x15, 0x83, 0xc4, 0x51, 0x8a, 0xde, 0x94, - 0xa9, 0xe8, 0xfd, 0xc6, 0x04, 0x4c, 0x99, 0x79, 0x48, 0x8f, 0xa1, 0x7d, 0xe9, 0x13, 0xc7, 0xd8, - 0x49, 0x4e, 0x1c, 0xec, 0x88, 0x69, 0x5c, 0x70, 0x29, 0xf3, 0xd6, 0x4a, 0x6e, 0x0a, 0x77, 0x7c, - 0xc4, 0x34, 0x0a, 0x43, 0x4c, 0x30, 0x3d, 0x81, 0xcf, 0x0b, 0x53, 0x5b, 0x85, 0x62, 0x57, 0x4c, - 0xaa, 0xad, 0x09, 0x55, 0xed, 0x39, 0x80, 0x38, 0x61, 0xa6, 0xbc, 0xf8, 0xd4, 0xfa, 0xb0, 0x91, - 0xc8, 0xd3, 0xc0, 0x22, 0x4f, 0xc3, 0x04, 0x53, 0x7d, 0x68, 0x4b, 0x66, 0x15, 0xd0, 0xe7, 0xf8, - 0x6b, 0xbc, 0x14, 0x25, 0x94, 0xbc, 0xc4, 0xb4, 0xd4, 0x58, 0x61, 0x91, 0xc9, 0x02, 0x2e, 0xc6, - 0x5a, 0x6a, 0x0c, 0xc3, 0x04, 0x26, 0x13, 0x9d, 0x32, 0xfd, 0x82, 0xaf, 0x0d, 0x86, 0xe8, 0x5c, - 0xe9, 0x40, 0x01, 0xe3, 0x76, 0xa5, 0x94, 0x3e, 0xc2, 0xe7, 0x74, 0xd1, 0xb0, 0x2b, 0xa5, 0xe0, - 0x38, 0x50, 0x83, 0x7d, 0x8c, 0xbc, 0xb3, 0xad, 0x08, 0x87, 0xe9, 0x21, 0xb7, 0xad, 0x5f, 0x31, - 0xcf, 0x5a, 0x39, 0xce, 0x21, 0x31, 0x6a, 0x8f, 0x7f, 0xd8, 0x1a, 0xed, 0x58, 0xf4, 0x59, 0x98, - 0x4e, 0xee, 0x42, 0xb9, 0xdf, 0x7c, 0x7c, 0x75, 0x1c, 0x2e, 0xdc, 0x6c, 0xbb, 0x5e, 0x3a, 0xe7, - 0x5b, 0xd6, 0x03, 0x0f, 0xd6, 0x89, 0x1f, 0x78, 0xd0, 0x31, 0x79, 0xf2, 0xf9, 0x84, 0xec, 0x98, - 0x3c, 0xf5, 0x96, 0x45, 0x12, 0x97, 0xfc, 0xa1, 0x05, 0x8f, 0x3b, 0x2d, 0x71, 0x2e, 0x70, 0x3a, - 0xb2, 0xd4, 0xc8, 0x4b, 0x2e, 0x67, 0x74, 0x38, 0xe2, 0x2e, 0x3f, 0xf8, 0xf1, 0x0b, 0xb5, 0x43, - 0xb8, 0x8a, 0x1e, 0xff, 0x49, 0xf9, 0x05, 0x8f, 0x1f, 0x86, 0x8a, 0x87, 0x8a, 0x4f, 0xfe, 0x2a, - 0xcc, 0x24, 0x3e, 0x58, 0x5a, 0xc2, 0xcb, 0xe2, 0xc2, 0xa2, 0x91, 0x04, 0x61, 0x1a, 0x77, 0xfe, - 0x16, 0xfc, 0xc4, 0x91, 0x72, 0x9e, 0x68, 0xb0, 0x7d, 0xcf, 0x82, 0x29, 0x33, 0x3d, 0x13, 0x79, - 0x16, 0x4a, 0x91, 0xbf, 0x43, 0xbd, 0xdb, 0x81, 0x72, 0xd8, 0xd5, 0x03, 0x7d, 0x83, 0x97, 0xe3, - 0x2a, 0x6a, 0x0c, 0x86, 0xdd, 0xec, 0xb8, 0xd4, 0x8b, 0x56, 0x5a, 0xb2, 0x9b, 0x35, 0xf6, 0x92, - 0x28, 0x5f, 0x46, 0x8d, 0x21, 0x7c, 0xec, 0xd8, 0xef, 0x06, 0x6d, 0x06, 0x54, 0xb9, 0xf7, 0x1b, - 0x3e, 0x76, 0x31, 0x0c, 0x13, 0x98, 0xc4, 0xd6, 0x26, 0xce, 0xf1, 0xf8, 0x5e, 0x23, 0x65, 0x92, - 0xfc, 0x8e, 0x05, 0x65, 0x61, 0xa2, 0x47, 0xba, 0x95, 0x72, 0xb1, 0x4d, 0x19, 0x11, 0x6a, 0xeb, - 0x2b, 0x59, 0x2e, 0xb6, 0x4f, 0xc2, 0xf8, 0x8e, 0xeb, 0xa9, 0x2f, 0xd1, 0xdb, 0xd2, 0x6b, 0xae, - 0xd7, 0x42, 0x0e, 0xd1, 0x1b, 0x57, 0x61, 0xe8, 0xc6, 0xb5, 0x08, 0x65, 0xed, 0x78, 0x22, 0x97, - 0x7f, 0x6d, 0xbd, 0xd5, 0x8e, 0x2a, 0x18, 0xe3, 0xd8, 0xbf, 0x66, 0xc1, 0x34, 0x8f, 0x18, 0x8f, - 0xcf, 0xc3, 0x2f, 0x6a, 0x5f, 0x30, 0x21, 0xf7, 0x13, 0x49, 0x5f, 0xb0, 0xf7, 0xf6, 0xab, 0x15, - 0x11, 0x63, 0x9e, 0x74, 0x0d, 0xfb, 0xb4, 0x34, 0xa2, 0x71, 0x8f, 0xb5, 0xb1, 0x13, 0xdb, 0x78, - 0x62, 0x31, 0x15, 0x11, 0x8c, 0xe9, 0xd9, 0x6f, 0xc3, 0x94, 0x19, 0x8c, 0x45, 0x5e, 0x84, 0x4a, - 0xcf, 0xf5, 0xda, 0xc9, 0xa0, 0x5d, 0x7d, 0xd1, 0xb0, 0x1e, 0x83, 0xd0, 0xc4, 0xe3, 0xd5, 0xfc, - 0xb8, 0x5a, 0xea, 0x7e, 0x62, 0xdd, 0x37, 0xab, 0xc5, 0x7f, 0x6c, 0x0f, 0x20, 0x8e, 0x2c, 0x3e, - 0x96, 0xf1, 0x66, 0x42, 0xd8, 0xfe, 0x85, 0x32, 0xc2, 0xb3, 0x44, 0x4c, 0x88, 0x11, 0xfe, 0xde, - 0xfe, 0x61, 0xca, 0x8e, 0xa8, 0xc5, 0xdf, 0xa0, 0xc8, 0x08, 0x32, 0xcc, 0xfd, 0x0d, 0x8a, 0x0c, - 0x1e, 0xef, 0xdf, 0x1b, 0x14, 0x59, 0xc2, 0xfc, 0xf9, 0x7a, 0x83, 0xe2, 0x93, 0x70, 0xd2, 0x74, - 0xb4, 0x4c, 0xb7, 0xb8, 0x67, 0xa6, 0x8d, 0xd0, 0x2d, 0x2e, 0xf3, 0x46, 0x48, 0xa8, 0xfd, 0xdb, - 0x05, 0x98, 0x4d, 0x9b, 0x18, 0xf2, 0xf6, 0xde, 0x20, 0x5f, 0xb7, 0x60, 0xda, 0x49, 0xa4, 0xfe, - 0xcb, 0xe9, 0x41, 0xab, 0x04, 0x4d, 0x23, 0xf5, 0x5c, 0xa2, 0x1c, 0x53, 0xbc, 0xc9, 0x5f, 0x82, - 0xc9, 0xc8, 0xed, 0x52, 0xbf, 0x2f, 0x0c, 0x8f, 0x05, 0x61, 0x00, 0xd8, 0x10, 0x45, 0xa8, 0x60, - 0x6c, 0x13, 0x70, 0xb9, 0xc6, 0x16, 0x50, 0xe9, 0x89, 0x3c, 0x1b, 0x5b, 0x4a, 0x45, 0x39, 0x6a, - 0x0c, 0x72, 0x1f, 0x26, 0x85, 0x9f, 0x87, 0x72, 0xe8, 0x59, 0xcb, 0xc9, 0x14, 0x22, 0x5c, 0x49, - 0xe2, 0x2e, 0x10, 0xff, 0x43, 0x54, 0xec, 0xec, 0x8f, 0xc0, 0x09, 0xf3, 0xf3, 0xda, 0x57, 0x81, - 0xa0, 0xdf, 0xe9, 0x6c, 0x3a, 0xcd, 0x9d, 0x3b, 0xae, 0xd7, 0xf2, 0xef, 0xf1, 0xa5, 0x6f, 0x11, - 0xca, 0x81, 0x0c, 0xd1, 0x0d, 0xe5, 0xa8, 0xd1, 0x6b, 0xa7, 0x8a, 0xdd, 0x0d, 0x31, 0xc6, 0xb1, - 0x7f, 0x6f, 0x0c, 0x26, 0x65, 0x3c, 0xf9, 0x03, 0x88, 0x84, 0xd8, 0x49, 0xdc, 0x3f, 0xaf, 0xe4, - 0x12, 0x06, 0x3f, 0x34, 0x0c, 0x22, 0x4c, 0x85, 0x41, 0xbc, 0x96, 0x0f, 0xbb, 0xc3, 0x63, 0x20, - 0xbe, 0x5b, 0x84, 0x99, 0x54, 0x7c, 0x7e, 0x2a, 0x95, 0xb7, 0xf5, 0xbe, 0xa4, 0xf2, 0x26, 0x61, - 0x22, 0x9d, 0x7b, 0x7e, 0x7e, 0x93, 0x7f, 0x91, 0xd9, 0x3d, 0x2f, 0x8f, 0xd6, 0xe2, 0x07, 0xc7, - 0xa3, 0xf5, 0xbf, 0x5a, 0xf0, 0xe8, 0xd0, 0x2c, 0x13, 0x3c, 0x5f, 0x5b, 0x90, 0x84, 0xca, 0xf5, - 0x22, 0xe7, 0xcc, 0x3d, 0xfa, 0xae, 0x3a, 0x9d, 0x62, 0x2b, 0xcd, 0x9e, 0xbc, 0x00, 0x53, 0x5c, - 0x1f, 0x64, 0x2b, 0x67, 0x44, 0x7b, 0xf2, 0xaa, 0x8d, 0x5f, 0xba, 0x34, 0x8c, 0x72, 0x4c, 0x60, - 0xd9, 0xdf, 0xb6, 0x60, 0x6e, 0x58, 0xf6, 0xae, 0x63, 0x68, 0x72, 0x7f, 0x25, 0x15, 0x49, 0x52, - 0x1d, 0x88, 0x24, 0x49, 0x99, 0x82, 0x54, 0xd0, 0x88, 0x61, 0x85, 0x29, 0x1c, 0x11, 0x28, 0xf1, - 0xfb, 0x05, 0x98, 0x95, 0x22, 0xc6, 0x4a, 0xf8, 0x4b, 0x89, 0xf8, 0x97, 0x9f, 0x4c, 0xc5, 0xbf, - 0x5c, 0x4c, 0xe3, 0xff, 0x45, 0xf0, 0xcb, 0x07, 0x2b, 0xf8, 0xe5, 0x6b, 0x45, 0xb8, 0x94, 0x99, - 0x27, 0x8b, 0x7c, 0x35, 0x63, 0xa7, 0xb8, 0x93, 0x73, 0x42, 0x2e, 0x1d, 0x27, 0x7b, 0xb6, 0x11, - 0x23, 0xbf, 0x62, 0x46, 0x6a, 0x88, 0xd5, 0x7f, 0xeb, 0x0c, 0x52, 0x8b, 0x9d, 0x34, 0x68, 0xe3, - 0xc1, 0x3e, 0x75, 0xf6, 0xe7, 0x60, 0xa9, 0xff, 0x5a, 0x01, 0xae, 0x1c, 0xb7, 0x65, 0x3f, 0xa0, - 0x51, 0x8e, 0x61, 0x22, 0xca, 0xf1, 0x01, 0xa9, 0x36, 0x67, 0x12, 0xf0, 0xf8, 0x0f, 0xc7, 0xf5, - 0xbe, 0x3b, 0x38, 0x61, 0x8f, 0x65, 0x5b, 0x98, 0x64, 0xaa, 0xaf, 0x4a, 0x08, 0x1f, 0xef, 0x0d, - 0x93, 0x0d, 0x51, 0xfc, 0xde, 0x7e, 0xf5, 0x7c, 0x9c, 0x50, 0x46, 0x16, 0xa2, 0xaa, 0x44, 0xae, - 0x40, 0x29, 0x10, 0x50, 0x15, 0xd7, 0x25, 0xbd, 0x6b, 0x44, 0x19, 0x6a, 0x28, 0xf9, 0x82, 0x71, - 0x56, 0x18, 0x3f, 0xab, 0xbc, 0x49, 0x87, 0x39, 0x0d, 0xbd, 0x09, 0xa5, 0x50, 0x65, 0x2d, 0x17, - 0xd3, 0xe9, 0xf9, 0x63, 0x86, 0x0b, 0x3a, 0x9b, 0xb4, 0xa3, 0x52, 0x98, 0x8b, 0xef, 0xd3, 0x09, - 0xce, 0x35, 0x49, 0x62, 0xeb, 0xb3, 0xb7, 0xb8, 0xd4, 0x80, 0xc1, 0x73, 0x37, 0x89, 0x60, 0x52, - 0x3e, 0x5d, 0x2c, 0x6f, 0x5b, 0xd7, 0x72, 0x8a, 0xbb, 0x91, 0x5e, 0xd9, 0xfc, 0x48, 0xab, 0x6c, - 0x4e, 0x8a, 0x95, 0xfd, 0x03, 0x0b, 0x2a, 0x72, 0x8c, 0x3c, 0x80, 0xb8, 0xc9, 0xbb, 0xc9, 0xb8, - 0xc9, 0xab, 0xb9, 0x2c, 0xe1, 0x43, 0x82, 0x26, 0xef, 0xc2, 0x94, 0x99, 0xb1, 0x92, 0x7c, 0xca, - 0xd8, 0x82, 0xac, 0x51, 0xb2, 0xb2, 0xa9, 0x4d, 0x2a, 0xde, 0x9e, 0xec, 0x7f, 0x5a, 0xd6, 0xad, - 0xc8, 0x0f, 0xce, 0xe6, 0xc8, 0xb7, 0x0e, 0x1d, 0xf9, 0xe6, 0xc0, 0x1b, 0xcb, 0x7f, 0xe0, 0xbd, - 0x0e, 0x25, 0xb5, 0x2c, 0x4a, 0x6d, 0xea, 0x29, 0xd3, 0x4d, 0x9b, 0xa9, 0x64, 0x8c, 0x98, 0x31, - 0x5d, 0xf8, 0x01, 0x38, 0xb6, 0x84, 0xab, 0xe5, 0x5a, 0x93, 0x21, 0x6f, 0x41, 0xe5, 0x9e, 0x1f, - 0xec, 0x74, 0x7c, 0x87, 0x3f, 0x15, 0x01, 0x79, 0x78, 0x06, 0x68, 0x6b, 0xb6, 0x88, 0x95, 0xb9, - 0x13, 0xd3, 0x47, 0x93, 0x19, 0xa9, 0xc1, 0x4c, 0xd7, 0xf5, 0x90, 0x3a, 0x2d, 0x1d, 0x1e, 0x39, - 0x2e, 0xd2, 0xb4, 0x2b, 0xdd, 0x7e, 0x2d, 0x09, 0xc6, 0x34, 0x3e, 0xb7, 0x3c, 0x05, 0x09, 0x53, - 0x87, 0xcc, 0xc5, 0xbc, 0x3e, 0xfa, 0x60, 0x4c, 0x9a, 0x4f, 0x44, 0xb0, 0x48, 0xb2, 0x1c, 0x53, - 0xbc, 0xc9, 0xe7, 0xa1, 0x14, 0xaa, 0x47, 0x41, 0x8b, 0x39, 0x9e, 0x7a, 0xf4, 0xc3, 0xa0, 0xba, - 0x2b, 0xf5, 0xcb, 0xa0, 0x9a, 0x21, 0x59, 0x85, 0x8b, 0xca, 0x76, 0x93, 0x78, 0xdf, 0x70, 0x22, - 0xce, 0x27, 0x86, 0x19, 0x70, 0xcc, 0xac, 0xc5, 0x74, 0x5b, 0x9e, 0x09, 0x56, 0xdc, 0xc4, 0x1a, - 0x97, 0x97, 0x7c, 0xfe, 0xb5, 0x50, 0x42, 0x0f, 0x8b, 0xfe, 0x2d, 0x8d, 0x10, 0xfd, 0xdb, 0x80, - 0x4b, 0x69, 0x10, 0x4f, 0x14, 0xc7, 0x73, 0xd3, 0x19, 0x5b, 0xe8, 0x7a, 0x16, 0x12, 0x66, 0xd7, - 0x25, 0x77, 0xa0, 0x1c, 0x50, 0x7e, 0xca, 0xab, 0x29, 0x27, 0xb6, 0x13, 0xbb, 0xeb, 0xa2, 0x22, - 0x80, 0x31, 0x2d, 0xd6, 0xef, 0x4e, 0x32, 0x71, 0xfa, 0xeb, 0x39, 0xbe, 0x1a, 0x2e, 0xfb, 0x7e, - 0x48, 0x02, 0x47, 0xfb, 0xdf, 0xcd, 0xc0, 0xb9, 0x84, 0x01, 0x8a, 0x3c, 0x05, 0x45, 0x9e, 0x39, - 0x8f, 0xaf, 0x56, 0xa5, 0x78, 0x45, 0x15, 0x8d, 0x23, 0x60, 0xe4, 0x97, 0x2c, 0x98, 0xe9, 0x25, - 0x2e, 0x70, 0xd4, 0x42, 0x3e, 0xa2, 0xd5, 0x36, 0x79, 0x2b, 0x64, 0x3c, 0x39, 0x92, 0x64, 0x86, - 0x69, 0xee, 0x6c, 0x3d, 0x90, 0x3e, 0xef, 0x1d, 0x1a, 0x70, 0x6c, 0xa9, 0xe8, 0x69, 0x12, 0x4b, - 0x49, 0x30, 0xa6, 0xf1, 0x59, 0x0f, 0xf3, 0xaf, 0x1b, 0xe5, 0x65, 0xd8, 0x9a, 0x22, 0x80, 0x31, - 0x2d, 0xf2, 0x0a, 0x4c, 0xcb, 0x7c, 0xd9, 0xeb, 0x7e, 0xeb, 0xba, 0x13, 0x6e, 0xcb, 0x23, 0x9f, - 0x3e, 0xa2, 0x2e, 0x25, 0xa0, 0x98, 0xc2, 0xe6, 0xdf, 0x16, 0x27, 0x25, 0xe7, 0x04, 0x26, 0x92, - 0x2f, 0xb2, 0x2c, 0x25, 0xc1, 0x98, 0xc6, 0x27, 0xcf, 0x1a, 0xdb, 0x90, 0xf0, 0x8e, 0xd0, 0xab, - 0x41, 0xc6, 0x56, 0x54, 0x83, 0x99, 0x3e, 0x3f, 0x21, 0xb7, 0x14, 0x50, 0xce, 0x47, 0xcd, 0xf0, - 0x76, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0x32, 0x9c, 0x0b, 0xd8, 0x62, 0xab, 0x09, 0x08, 0x97, 0x09, - 0x7d, 0x23, 0x8e, 0x26, 0x10, 0x93, 0xb8, 0xe4, 0x55, 0x38, 0x1f, 0xe7, 0x54, 0x55, 0x04, 0x84, - 0x0f, 0x85, 0x4e, 0xf0, 0x57, 0x4b, 0x23, 0xe0, 0x60, 0x1d, 0xf2, 0xd7, 0x61, 0xd6, 0x68, 0x89, - 0x15, 0xaf, 0x45, 0xef, 0xcb, 0xbc, 0x97, 0xfc, 0x85, 0xb1, 0xa5, 0x14, 0x0c, 0x07, 0xb0, 0xc9, - 0xc7, 0x61, 0xba, 0xe9, 0x77, 0x3a, 0x7c, 0x8d, 0x13, 0xaf, 0x81, 0x88, 0x04, 0x97, 0x22, 0x15, - 0x68, 0x02, 0x82, 0x29, 0x4c, 0x72, 0x03, 0x88, 0xbf, 0xc9, 0xd4, 0x2b, 0xda, 0x7a, 0x95, 0x7a, - 0x54, 0x6a, 0x1c, 0xe7, 0x92, 0x11, 0x37, 0xb7, 0x06, 0x30, 0x30, 0xa3, 0x16, 0xcf, 0x0f, 0x68, - 0x44, 0x28, 0x4f, 0xe7, 0x91, 0x91, 0x3c, 0x6d, 0xcf, 0x39, 0x32, 0x3c, 0x39, 0x80, 0x09, 0x11, - 0x00, 0x95, 0x4f, 0xa6, 0x4b, 0xf3, 0x61, 0x80, 0x78, 0x8f, 0x10, 0xa5, 0x28, 0x39, 0x91, 0x9f, - 0x87, 0xf2, 0xa6, 0x7a, 0x25, 0x86, 0xa7, 0xb7, 0x1c, 0x79, 0x5f, 0x4c, 0x3d, 0x78, 0x14, 0xdb, - 0x2b, 0x34, 0x00, 0x63, 0x96, 0xe4, 0x69, 0xa8, 0x5c, 0x5f, 0xaf, 0xe9, 0x51, 0x78, 0x9e, 0xf7, - 0xfe, 0x38, 0xab, 0x82, 0x26, 0x80, 0xcd, 0x30, 0xad, 0xbe, 0x91, 0xa4, 0x5b, 0x40, 0x86, 0x36, - 0xc6, 0xb0, 0xb9, 0x9f, 0x03, 0x36, 0xe6, 0x2e, 0xa4, 0xb0, 0x65, 0x39, 0x6a, 0x0c, 0xf2, 0x26, - 0x54, 0xe4, 0x7e, 0xc1, 0xd7, 0xa6, 0x8b, 0xa7, 0x8b, 0x7e, 0xc7, 0x98, 0x04, 0x9a, 0xf4, 0xf8, - 0x05, 0x35, 0x7f, 0x3c, 0x83, 0x5e, 0xeb, 0x77, 0x3a, 0x73, 0x97, 0xf8, 0xba, 0x19, 0x5f, 0x50, - 0xc7, 0x20, 0x34, 0xf1, 0xc8, 0xf3, 0xca, 0x5f, 0xed, 0xe1, 0xc4, 0x8d, 0xbd, 0xf6, 0x57, 0xd3, - 0x4a, 0xf7, 0x90, 0x00, 0x99, 0x47, 0x8e, 0x70, 0x14, 0xdb, 0x84, 0x79, 0xa5, 0xf1, 0x0d, 0x4e, - 0x92, 0xb9, 0xb9, 0x84, 0xed, 0x68, 0xfe, 0xce, 0x50, 0x4c, 0x3c, 0x84, 0x0a, 0xd9, 0x84, 0x82, - 0xd3, 0xd9, 0x9c, 0x7b, 0x34, 0x0f, 0xd5, 0xb5, 0xb6, 0x5a, 0x97, 0x23, 0x8a, 0x3b, 0xb5, 0xd6, - 0x56, 0xeb, 0xc8, 0x88, 0x13, 0x17, 0xc6, 0x9d, 0xce, 0x66, 0x38, 0x37, 0xcf, 0xe7, 0x6c, 0x6e, - 0x4c, 0x62, 0xe3, 0xc1, 0x6a, 0x3d, 0x44, 0xce, 0xc2, 0xfe, 0xe2, 0x98, 0xbe, 0x25, 0xd2, 0xc9, - 0xc6, 0xdf, 0x36, 0x27, 0x90, 0x38, 0xee, 0xdc, 0xca, 0x6d, 0x02, 0x49, 0xf5, 0xe2, 0xdc, 0xd0, - 0xe9, 0xd3, 0xd3, 0x4b, 0x46, 0x2e, 0x59, 0xca, 0x92, 0x89, 0xd4, 0xc5, 0xe9, 0x39, 0xb9, 0x60, - 0xd8, 0x5f, 0xaa, 0x68, 0x2b, 0x68, 0xca, 0xd7, 0x2b, 0x80, 0xa2, 0x1b, 0x46, 0xae, 0x9f, 0x63, - 0x50, 0x78, 0x2a, 0x03, 0x39, 0x8f, 0x39, 0xe1, 0x00, 0x14, 0xac, 0x18, 0x4f, 0xaf, 0xed, 0x7a, - 0xf7, 0xe5, 0xe7, 0xbf, 0x9e, 0xbb, 0x13, 0x97, 0xe0, 0xc9, 0x01, 0x28, 0x58, 0x91, 0xbb, 0x62, - 0x50, 0x17, 0xf2, 0xe8, 0xeb, 0xda, 0x6a, 0x3d, 0xc5, 0x2f, 0x39, 0xb8, 0xef, 0x42, 0x21, 0xec, - 0xba, 0x52, 0x5d, 0x1a, 0x91, 0x57, 0x63, 0x6d, 0x25, 0x8b, 0x57, 0x63, 0x6d, 0x05, 0x19, 0x13, - 0xf2, 0x15, 0x0b, 0xc0, 0xe9, 0x6e, 0x3a, 0x61, 0xe8, 0xb4, 0xb4, 0x75, 0x66, 0xc4, 0x47, 0x56, - 0x6a, 0x9a, 0x5e, 0x8a, 0x35, 0x77, 0x5b, 0x8e, 0xa1, 0x68, 0x70, 0x26, 0x6f, 0xc1, 0xa4, 0x23, - 0x5e, 0xb1, 0x94, 0x1e, 0xf8, 0xf9, 0x3c, 0xcd, 0x9a, 0x92, 0x80, 0x9b, 0x69, 0x24, 0x08, 0x15, - 0x43, 0xc6, 0x3b, 0x0a, 0x1c, 0xba, 0xe5, 0xee, 0x48, 0xe3, 0x50, 0x63, 0xe4, 0x77, 0x56, 0x18, - 0xb1, 0x2c, 0xde, 0x12, 0x84, 0x8a, 0x21, 0xf9, 0x05, 0x0b, 0xce, 0x75, 0x1d, 0xcf, 0xd1, 0x71, - 0x95, 0xf9, 0x44, 0xdf, 0x9a, 0x91, 0x9a, 0xb1, 0x86, 0xb8, 0x66, 0x32, 0xc2, 0x24, 0x5f, 0xb2, - 0x0b, 0x13, 0x0e, 0x7f, 0x5f, 0x57, 0x1e, 0xc5, 0x30, 0x8f, 0xb7, 0x7a, 0x53, 0x6d, 0xc0, 0x17, - 0x17, 0xf9, 0x8a, 0xaf, 0xe4, 0x46, 0x7e, 0xdd, 0x82, 0x49, 0xe1, 0x1c, 0xce, 0x14, 0x52, 0xf6, - 0xed, 0x9f, 0x3d, 0x83, 0x97, 0x0c, 0xa4, 0xe3, 0xba, 0x74, 0x3f, 0xfa, 0x90, 0xf6, 0x7c, 0x15, - 0xa5, 0x87, 0xba, 0xae, 0x2b, 0xe9, 0x98, 0xea, 0xdb, 0x75, 0xee, 0x27, 0x5e, 0xd1, 0x31, 0x55, - 0xdf, 0xb5, 0x14, 0x0c, 0x07, 0xb0, 0xe7, 0x3f, 0x0e, 0x53, 0xa6, 0x1c, 0x27, 0x72, 0x7f, 0xff, - 0x51, 0x01, 0x80, 0x77, 0x95, 0xc8, 0xc5, 0xd2, 0xe5, 0x89, 0x9b, 0xb7, 0xfd, 0x56, 0x4e, 0xaf, - 0x79, 0x1a, 0x29, 0x55, 0x40, 0x66, 0x69, 0xde, 0xf6, 0x5b, 0x28, 0x99, 0x90, 0x36, 0x8c, 0xf7, - 0x9c, 0x68, 0x3b, 0xff, 0xfc, 0x2d, 0x25, 0x11, 0x94, 0x1c, 0x6d, 0x23, 0x67, 0x40, 0xde, 0xb1, - 0x62, 0xcf, 0x9e, 0x42, 0x1e, 0xb9, 0x67, 0xe3, 0x36, 0x5b, 0x90, 0xbe, 0x3c, 0xa9, 0x14, 0xac, - 0x69, 0x0f, 0x9f, 0xf9, 0x77, 0x2d, 0x98, 0x32, 0x51, 0x33, 0xba, 0xe9, 0xe7, 0xcc, 0x6e, 0xca, - 0xb3, 0x3d, 0xcc, 0x1e, 0xff, 0xef, 0x16, 0x00, 0xf6, 0xbd, 0x46, 0xbf, 0xdb, 0x65, 0x6a, 0xbb, - 0xf6, 0xf2, 0xb7, 0x8e, 0xed, 0xe5, 0x3f, 0x76, 0x42, 0x2f, 0xff, 0xc2, 0x89, 0xbc, 0xfc, 0xc7, - 0x4f, 0xee, 0xe5, 0x5f, 0x1c, 0xee, 0xe5, 0x6f, 0x7f, 0xd3, 0x82, 0xf3, 0x03, 0xfb, 0x15, 0xd3, - 0xa4, 0x03, 0xdf, 0x8f, 0x86, 0x78, 0x88, 0x62, 0x0c, 0x42, 0x13, 0x8f, 0x2c, 0xc3, 0xac, 0x7c, - 0xa6, 0xa4, 0xd1, 0xeb, 0xb8, 0x99, 0xb9, 0x75, 0x36, 0x52, 0x70, 0x1c, 0xa8, 0x61, 0xff, 0xb6, - 0x05, 0x15, 0x23, 0x22, 0x9f, 0x7d, 0x07, 0x77, 0x13, 0x96, 0x62, 0xc4, 0x2f, 0xb4, 0xf0, 0xab, - 0x2e, 0x01, 0x13, 0xd7, 0xd0, 0x6d, 0x23, 0x89, 0x7d, 0x7c, 0x0d, 0xcd, 0x4a, 0x51, 0x42, 0x45, - 0x7a, 0x72, 0xda, 0xe3, 0x8d, 0x5e, 0x30, 0xd3, 0x93, 0xd3, 0x1e, 0x72, 0x08, 0x67, 0xc7, 0x8e, - 0x14, 0xd2, 0x03, 0xd8, 0x78, 0x10, 0xc6, 0x09, 0x22, 0x14, 0x30, 0xf2, 0x04, 0x14, 0xa8, 0xd7, - 0x92, 0xf6, 0x0f, 0xfd, 0x7a, 0xed, 0x55, 0xaf, 0x85, 0xac, 0xdc, 0xbe, 0x05, 0x53, 0xc2, 0xfb, - 0xf9, 0x35, 0xba, 0x77, 0xec, 0xe7, 0x70, 0xd9, 0x68, 0x4f, 0x3d, 0x87, 0xcb, 0xaa, 0xb3, 0x72, - 0xfb, 0x9f, 0x58, 0x90, 0x7a, 0x23, 0xc9, 0xb8, 0x81, 0xb1, 0x86, 0xde, 0xc0, 0x98, 0x56, 0xfb, - 0xb1, 0x43, 0xad, 0xf6, 0x37, 0x80, 0x74, 0xd9, 0x54, 0x48, 0x2e, 0xb4, 0x85, 0xe4, 0x53, 0x12, - 0x6b, 0x03, 0x18, 0x98, 0x51, 0xcb, 0xfe, 0xc7, 0x42, 0x58, 0xf3, 0xd5, 0xa4, 0xa3, 0x1b, 0xa0, - 0x0f, 0x45, 0x4e, 0x4a, 0xda, 0xdf, 0x46, 0xb4, 0x5d, 0x0f, 0xe6, 0xd1, 0x8a, 0x3b, 0x52, 0x4e, - 0x79, 0xce, 0xcd, 0xfe, 0x7d, 0x21, 0xab, 0xf9, 0xac, 0xd2, 0xd1, 0xb2, 0x76, 0x93, 0xb2, 0x5e, - 0xcf, 0x6b, 0xad, 0xcc, 0x96, 0x91, 0x2c, 0x00, 0xf4, 0x68, 0xd0, 0xa4, 0x5e, 0xa4, 0xe2, 0x92, - 0x8a, 0x32, 0x42, 0x56, 0x97, 0xa2, 0x81, 0x61, 0x7f, 0x83, 0x4d, 0xa0, 0xf8, 0xa1, 0x68, 0x72, - 0x25, 0xed, 0xea, 0x9a, 0x9e, 0x1c, 0xda, 0xd3, 0xd5, 0x88, 0x56, 0x19, 0x3b, 0x22, 0x5a, 0xe5, - 0x19, 0x98, 0x0c, 0xfc, 0x0e, 0xad, 0x05, 0x5e, 0xda, 0x47, 0x07, 0x59, 0x31, 0xde, 0x44, 0x05, - 0xb7, 0x7f, 0xd5, 0x82, 0xd9, 0x74, 0x38, 0x5d, 0xee, 0xfe, 0xb7, 0x66, 0xcc, 0x7f, 0xe1, 0xe4, - 0x31, 0xff, 0xf6, 0x9f, 0x15, 0x60, 0x36, 0xfd, 0x80, 0x1d, 0xe3, 0xec, 0x72, 0x63, 0x5b, 0x6a, - 0xf5, 0x17, 0x56, 0x36, 0x01, 0xd3, 0xe3, 0x65, 0x6c, 0xe8, 0x78, 0xb9, 0x06, 0x65, 0xbf, 0xa7, - 0x0e, 0xfc, 0x42, 0xb8, 0x2b, 0xca, 0x58, 0x73, 0x4b, 0x01, 0xde, 0xdb, 0xaf, 0x5e, 0x88, 0x05, - 0xd0, 0xc5, 0x18, 0x57, 0x25, 0x3f, 0xad, 0x2c, 0x15, 0xe3, 0x89, 0x2c, 0x3a, 0xda, 0x52, 0x31, - 0x13, 0xd7, 0x1f, 0x66, 0xac, 0x28, 0x9e, 0x24, 0x9b, 0xc7, 0xc4, 0x99, 0x65, 0xf3, 0x98, 0xcc, - 0x35, 0x9b, 0xc7, 0x2b, 0xda, 0x6b, 0xab, 0x14, 0x87, 0x0c, 0x68, 0x8f, 0xad, 0x43, 0x42, 0x06, - 0xa4, 0x53, 0xea, 0x3b, 0x6c, 0x80, 0x46, 0x6e, 0x73, 0xc7, 0xf5, 0x44, 0x8a, 0x04, 0x36, 0x6b, - 0x9e, 0x81, 0x49, 0x2a, 0x1f, 0x3b, 0x16, 0x57, 0x08, 0xba, 0xd1, 0xd4, 0x1b, 0xc7, 0x0a, 0x4e, - 0x6a, 0x30, 0xa3, 0x2e, 0x4e, 0xd5, 0xbd, 0x8f, 0x48, 0xed, 0xa2, 0xed, 0xcc, 0xcb, 0x49, 0x30, - 0xa6, 0xf1, 0xed, 0x2f, 0x40, 0xc5, 0x50, 0x48, 0xf8, 0xde, 0x7d, 0xdf, 0x69, 0x46, 0xe9, 0x3d, - 0xef, 0x2a, 0x2b, 0x44, 0x01, 0xe3, 0xd7, 0x53, 0x22, 0xd2, 0x2b, 0xb5, 0xe7, 0xc9, 0xf8, 0x2e, - 0x09, 0x65, 0xc4, 0x02, 0xda, 0xa6, 0xf7, 0xd5, 0xfb, 0x12, 0x8a, 0x18, 0xb2, 0x42, 0x14, 0x30, - 0xfb, 0x59, 0x28, 0xa9, 0x04, 0x5c, 0x3c, 0x8b, 0x8d, 0xba, 0x3a, 0x31, 0xb3, 0xd8, 0xf8, 0x41, - 0x84, 0x1c, 0x62, 0xbf, 0x01, 0x25, 0x95, 0x27, 0xec, 0x68, 0x6c, 0xb6, 0x0d, 0x85, 0x9e, 0x7b, - 0xdd, 0x0f, 0x23, 0x95, 0xdc, 0x4c, 0xdc, 0xee, 0xde, 0x5c, 0xe1, 0x65, 0xa8, 0xa1, 0xf6, 0x9f, - 0x5a, 0x50, 0xd9, 0xd8, 0x58, 0xd5, 0x46, 0x1f, 0x84, 0x87, 0x43, 0xd1, 0x42, 0xb5, 0xad, 0x88, - 0x9a, 0x6e, 0x24, 0x62, 0x46, 0xce, 0x1f, 0xec, 0x57, 0x1f, 0x6e, 0x64, 0x62, 0xe0, 0x90, 0x9a, - 0x64, 0x05, 0x2e, 0x98, 0x10, 0x99, 0x74, 0x42, 0xee, 0x8f, 0xfc, 0x75, 0xec, 0xc6, 0x20, 0x18, - 0xb3, 0xea, 0xa4, 0x49, 0x49, 0x55, 0xcf, 0x7c, 0x68, 0xbb, 0x31, 0x08, 0xc6, 0xac, 0x3a, 0xf6, - 0xf3, 0x30, 0x93, 0xf2, 0x6f, 0x38, 0x46, 0xb2, 0x9f, 0xdf, 0x29, 0xc0, 0x94, 0x79, 0xcd, 0x7d, - 0x8c, 0xbd, 0xeb, 0xf8, 0x2a, 0x41, 0xc6, 0xd5, 0x74, 0xe1, 0x84, 0x57, 0xd3, 0xa6, 0x2f, 0xc0, - 0xf8, 0xd9, 0xfa, 0x02, 0x14, 0xf3, 0xf1, 0x05, 0x30, 0x7c, 0x56, 0x26, 0x1e, 0x9c, 0xcf, 0xca, - 0x6f, 0x15, 0x61, 0x3a, 0x99, 0x3d, 0xf6, 0x18, 0x3d, 0xf9, 0xec, 0x40, 0x4f, 0x9e, 0xf0, 0x2e, - 0xac, 0x30, 0xea, 0x5d, 0xd8, 0xf8, 0xa8, 0x77, 0x61, 0xc5, 0x53, 0xdc, 0x85, 0x0d, 0xde, 0x64, - 0x4d, 0x1c, 0xfb, 0x26, 0xeb, 0x13, 0x7a, 0xa3, 0x98, 0x4c, 0xb8, 0x7f, 0xc5, 0x9b, 0x05, 0x49, - 0x76, 0xc3, 0x92, 0xdf, 0xca, 0x74, 0x4b, 0x2e, 0x1d, 0xb1, 0x8d, 0x06, 0x99, 0xde, 0xb8, 0x27, - 0xbf, 0x6e, 0x7f, 0xf8, 0x04, 0x9e, 0xb8, 0x2f, 0x42, 0x45, 0x8e, 0x27, 0x7e, 0xf0, 0x82, 0xe4, - 0xa1, 0xad, 0x11, 0x83, 0xd0, 0xc4, 0x63, 0x03, 0xa3, 0x17, 0x4f, 0x10, 0x7e, 0x2b, 0x5b, 0x49, - 0xde, 0xca, 0xae, 0x27, 0xc1, 0x98, 0xc6, 0xb7, 0x3f, 0x0f, 0x97, 0x32, 0xcd, 0x6f, 0xfc, 0xea, - 0x83, 0x9f, 0x09, 0x68, 0x4b, 0x22, 0x18, 0x62, 0xa4, 0x1e, 0x95, 0x99, 0xbf, 0x33, 0x14, 0x13, - 0x0f, 0xa1, 0x62, 0xff, 0x66, 0x01, 0xa6, 0x93, 0x8f, 0x2c, 0x93, 0x7b, 0xda, 0x58, 0x9f, 0xcb, - 0x3d, 0x81, 0x20, 0x6b, 0x64, 0x24, 0x1d, 0x7a, 0xc9, 0x77, 0x8f, 0x8f, 0xaf, 0x4d, 0x9d, 0x1e, - 0xf5, 0xec, 0x18, 0xcb, 0xdb, 0x35, 0xc9, 0x8e, 0x3f, 0x55, 0x1c, 0x07, 0x2f, 0x4b, 0x1b, 0x4e, - 0xee, 0xdc, 0xe3, 0x20, 0x5c, 0xcd, 0x0a, 0x0d, 0xb6, 0x6c, 0x6f, 0xd9, 0xa5, 0x81, 0xbb, 0xe5, - 0xd2, 0x96, 0xcc, 0x56, 0xcf, 0x57, 0xee, 0x37, 0x64, 0x19, 0x6a, 0xa8, 0xfd, 0xce, 0x18, 0x94, - 0x79, 0xae, 0xb5, 0x6b, 0x81, 0xdf, 0xe5, 0xcf, 0x6f, 0x86, 0xc6, 0x79, 0x59, 0x76, 0xdb, 0x8d, - 0x51, 0x5f, 0xd4, 0x8d, 0x29, 0xca, 0x50, 0x07, 0xa3, 0x04, 0x13, 0x1c, 0x49, 0x0f, 0x4a, 0x5b, - 0x32, 0x37, 0xb4, 0xec, 0xbb, 0x11, 0xf3, 0x9b, 0xaa, 0x4c, 0xd3, 0xa2, 0x09, 0xd4, 0x3f, 0xd4, - 0x5c, 0x6c, 0x07, 0x66, 0x52, 0xc9, 0x72, 0x72, 0xcf, 0x28, 0xfd, 0xbf, 0xc6, 0xa1, 0xac, 0x63, - 0xec, 0xc8, 0xc7, 0x12, 0xc6, 0xcb, 0x72, 0xfd, 0x27, 0x8c, 0xb7, 0xe1, 0xb6, 0xfd, 0x16, 0x3b, - 0x3f, 0x68, 0xe4, 0x94, 0x21, 0xf2, 0x09, 0x28, 0xf4, 0x83, 0x4e, 0xda, 0x3a, 0x71, 0x1b, 0x57, - 0x91, 0x95, 0x9b, 0x71, 0x81, 0x85, 0x07, 0x1a, 0x17, 0xc8, 0x76, 0xc9, 0x4d, 0xbf, 0xb5, 0x97, - 0x7e, 0x4b, 0xae, 0xee, 0xb7, 0xf6, 0x90, 0x43, 0xc8, 0x2b, 0x30, 0x2d, 0x83, 0x1d, 0x95, 0x12, - 0x53, 0xe4, 0x7a, 0xaa, 0x76, 0x5a, 0xd9, 0x48, 0x40, 0x31, 0x85, 0xcd, 0x76, 0x59, 0x76, 0x6c, - 0xe0, 0x79, 0xc2, 0x27, 0x92, 0x37, 0xdc, 0x37, 0x1a, 0xb7, 0x6e, 0x72, 0x23, 0xaa, 0xc6, 0x48, - 0xc4, 0x53, 0x4e, 0x1e, 0x19, 0x4f, 0xb9, 0x2c, 0x68, 0x33, 0x69, 0xe5, 0xc9, 0xe5, 0x8a, 0xa2, - 0xcb, 0xca, 0x0e, 0x3d, 0xbb, 0xe8, 0x9a, 0x59, 0x91, 0xa7, 0xe5, 0xf7, 0x2f, 0xf2, 0xd4, 0xbe, - 0x0d, 0x33, 0xa9, 0xfe, 0x53, 0xc6, 0x2d, 0x2b, 0xdb, 0xb8, 0x75, 0xbc, 0xd7, 0xe8, 0xfe, 0xb9, - 0x05, 0xe7, 0x07, 0x56, 0xa4, 0xe3, 0x86, 0x00, 0xa7, 0xf7, 0xc6, 0xb1, 0xd3, 0xef, 0x8d, 0x85, - 0x93, 0xed, 0x8d, 0xf5, 0xcd, 0xef, 0xfd, 0xf0, 0xf2, 0x43, 0xdf, 0xff, 0xe1, 0xe5, 0x87, 0xfe, - 0xe0, 0x87, 0x97, 0x1f, 0x7a, 0xe7, 0xe0, 0xb2, 0xf5, 0xbd, 0x83, 0xcb, 0xd6, 0xf7, 0x0f, 0x2e, - 0x5b, 0x7f, 0x70, 0x70, 0xd9, 0xfa, 0x2f, 0x07, 0x97, 0xad, 0x6f, 0xfe, 0xf1, 0xe5, 0x87, 0x3e, - 0xf5, 0x89, 0xb8, 0xa7, 0x16, 0x55, 0x4f, 0xf1, 0x1f, 0x1f, 0x56, 0xfd, 0xb2, 0xd8, 0xdb, 0x69, - 0x2f, 0xb2, 0x9e, 0x5a, 0xd4, 0x25, 0xaa, 0xa7, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, - 0xa0, 0x6a, 0xd7, 0x57, 0xaa, 0x00, 0x00, + 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0xf7, 0x38, + 0xcc, 0xd4, 0x3b, 0x7d, 0xfa, 0x6a, 0x40, 0xa9, 0xb2, 0x05, 0xd5, 0x60, 0xa6, 0x17, 0xd0, 0x5d, + 0x97, 0xde, 0x6b, 0xd0, 0x0e, 0x6d, 0x46, 0x7e, 0x20, 0xa5, 0x79, 0x44, 0x12, 0x9a, 0x59, 0x4f, + 0x82, 0x31, 0x8d, 0x4f, 0x5e, 0x81, 0x69, 0xa7, 0x19, 0xb9, 0xbb, 0x54, 0x53, 0x10, 0xe2, 0x3e, + 0x2c, 0x29, 0x4c, 0xd7, 0x12, 0x50, 0x4c, 0x61, 0x93, 0xcf, 0xc0, 0x5c, 0xd8, 0x74, 0x3a, 0xf4, + 0x76, 0x4f, 0xb2, 0x5a, 0xda, 0xa6, 0xcd, 0x9d, 0x75, 0xdf, 0xf5, 0x22, 0x69, 0x77, 0x7c, 0x52, + 0x52, 0x9a, 0x6b, 0x0c, 0xc1, 0xc3, 0xa1, 0x14, 0xc8, 0xbf, 0xb0, 0xe0, 0x89, 0x5e, 0x40, 0xd7, + 0x03, 0xbf, 0xeb, 0xb3, 0xa1, 0x36, 0x60, 0x0e, 0x93, 0x66, 0xa1, 0x37, 0x46, 0xd4, 0xa5, 0x44, + 0xc9, 0xe0, 0x1d, 0xce, 0x4f, 0x1c, 0xec, 0x57, 0x9f, 0x58, 0x3f, 0x4c, 0x00, 0x3c, 0x5c, 0x3e, + 0xf2, 0x2f, 0x2d, 0xb8, 0xdc, 0xf3, 0xc3, 0xe8, 0x90, 0x4f, 0x28, 0x9e, 0xe9, 0x27, 0xd8, 0x07, + 0xfb, 0xd5, 0xcb, 0xeb, 0x87, 0x4a, 0x80, 0x47, 0x48, 0x68, 0x1f, 0x54, 0xe0, 0xbc, 0x31, 0xf6, + 0xa4, 0x31, 0xe7, 0x65, 0x38, 0xa7, 0x06, 0x43, 0xac, 0xfb, 0x94, 0x63, 0xdb, 0x5e, 0xcd, 0x04, + 0x62, 0x12, 0x97, 0x8d, 0x3b, 0x3d, 0x14, 0x45, 0xed, 0xd4, 0xb8, 0x5b, 0x4f, 0x40, 0x31, 0x85, + 0x4d, 0x56, 0xe0, 0x82, 0x2c, 0x41, 0xda, 0xeb, 0xb8, 0x4d, 0x67, 0xc9, 0xef, 0xcb, 0x21, 0x57, + 0xac, 0x3f, 0x72, 0xb0, 0x5f, 0xbd, 0xb0, 0x3e, 0x08, 0xc6, 0xac, 0x3a, 0x64, 0x15, 0x2e, 0x3a, + 0xfd, 0xc8, 0xd7, 0xdf, 0x7f, 0xd5, 0x63, 0xdb, 0x69, 0x8b, 0x0f, 0xad, 0x92, 0xd8, 0x77, 0x6b, + 0x19, 0x70, 0xcc, 0xac, 0x45, 0xd6, 0x53, 0xd4, 0x1a, 0xb4, 0xe9, 0x7b, 0x2d, 0xd1, 0xcb, 0xc5, + 0xf8, 0x18, 0x58, 0xcb, 0xc0, 0xc1, 0xcc, 0x9a, 0xa4, 0x03, 0xd3, 0x5d, 0xe7, 0xfe, 0x6d, 0xcf, + 0xd9, 0x75, 0xdc, 0x0e, 0x63, 0x22, 0xed, 0x85, 0xc3, 0xad, 0x4c, 0xfd, 0xc8, 0xed, 0x2c, 0x08, + 0x3f, 0x8e, 0x85, 0x15, 0x2f, 0xba, 0x15, 0x34, 0x22, 0xa6, 0xa9, 0x0b, 0x0d, 0x72, 0x2d, 0x41, + 0x0b, 0x53, 0xb4, 0xc9, 0x2d, 0xb8, 0xc4, 0xa7, 0xe3, 0xb2, 0x7f, 0xcf, 0x5b, 0xa6, 0x1d, 0x67, + 0x4f, 0x7d, 0xc0, 0x24, 0xff, 0x80, 0x47, 0x0f, 0xf6, 0xab, 0x97, 0x1a, 0x59, 0x08, 0x98, 0x5d, + 0x8f, 0x38, 0xf0, 0x58, 0x12, 0x80, 0x74, 0xd7, 0x0d, 0x5d, 0xdf, 0x13, 0x66, 0xb9, 0x52, 0x6c, + 0x96, 0x6b, 0x0c, 0x47, 0xc3, 0xc3, 0x68, 0x90, 0xbf, 0x63, 0xc1, 0xc5, 0xac, 0x69, 0x38, 0x57, + 0xce, 0xe3, 0x36, 0x39, 0x35, 0xb5, 0xc4, 0x88, 0xc8, 0x5c, 0x14, 0x32, 0x85, 0x20, 0xef, 0x58, + 0x30, 0xe5, 0x18, 0x27, 0xe8, 0x39, 0xc8, 0x63, 0xd7, 0x32, 0xcf, 0xe4, 0xf5, 0xd9, 0x83, 0xfd, + 0x6a, 0xe2, 0x94, 0x8e, 0x09, 0x8e, 0xe4, 0xef, 0x59, 0x70, 0x29, 0x73, 0x8e, 0xcf, 0x55, 0xce, + 0xa2, 0x85, 0xf8, 0x20, 0xc9, 0x5e, 0x73, 0xb2, 0xc5, 0x20, 0xdf, 0xb4, 0xf4, 0x56, 0xa6, 0x2e, + 0x18, 0xe7, 0xa6, 0xb8, 0x68, 0x23, 0x1a, 0x3c, 0x0c, 0x35, 0x4a, 0x11, 0xae, 0x5f, 0x30, 0x76, + 0x46, 0x55, 0x88, 0x69, 0xf6, 0xe4, 0x1b, 0x96, 0xda, 0x1a, 0xb5, 0x44, 0xe7, 0xce, 0x4a, 0x22, + 0x12, 0xef, 0xb4, 0x5a, 0xa0, 0x14, 0x73, 0xf2, 0xb3, 0x30, 0xef, 0x6c, 0xfa, 0x41, 0x94, 0x39, + 0xf9, 0xe6, 0xa6, 0xf9, 0x34, 0xba, 0x7c, 0xb0, 0x5f, 0x9d, 0xaf, 0x0d, 0xc5, 0xc2, 0x43, 0x28, + 0xd8, 0xbf, 0x3b, 0x01, 0x53, 0xe2, 0x24, 0x24, 0xb7, 0xae, 0xdf, 0xb2, 0xe0, 0xf1, 0x66, 0x3f, + 0x08, 0xa8, 0x17, 0x35, 0x22, 0xda, 0x1b, 0xdc, 0xb8, 0xac, 0x33, 0xdd, 0xb8, 0x9e, 0x3c, 0xd8, + 0xaf, 0x3e, 0xbe, 0x74, 0x08, 0x7f, 0x3c, 0x54, 0x3a, 0xf2, 0x6f, 0x2d, 0xb0, 0x25, 0x42, 0xdd, + 0x69, 0xee, 0xb4, 0x03, 0xbf, 0xef, 0xb5, 0x06, 0x3f, 0x62, 0xec, 0x4c, 0x3f, 0xe2, 0xe9, 0x83, + 0xfd, 0xaa, 0xbd, 0x74, 0xa4, 0x14, 0x78, 0x0c, 0x49, 0xc9, 0xab, 0x70, 0x5e, 0x62, 0x5d, 0xbd, + 0xdf, 0xa3, 0x81, 0xcb, 0xce, 0x1c, 0x52, 0x71, 0x8c, 0x7d, 0xd3, 0xd2, 0x08, 0x38, 0x58, 0x87, + 0x84, 0x30, 0x79, 0x8f, 0xba, 0xed, 0xed, 0x48, 0xa9, 0x4f, 0x23, 0x3a, 0xa4, 0x49, 0xab, 0xc8, + 0x1d, 0x41, 0xb3, 0x5e, 0x39, 0xd8, 0xaf, 0x4e, 0xca, 0x3f, 0xa8, 0x38, 0x91, 0x9b, 0x30, 0x2d, + 0xce, 0xa9, 0xeb, 0xae, 0xd7, 0x5e, 0xf7, 0x3d, 0xe1, 0x55, 0x55, 0xae, 0x3f, 0xad, 0x36, 0xfc, + 0x46, 0x02, 0xfa, 0xde, 0x7e, 0x75, 0x4a, 0xfd, 0xde, 0xd8, 0xeb, 0x51, 0x4c, 0xd5, 0x26, 0x7f, + 0xdb, 0x02, 0x12, 0x46, 0xb4, 0xb7, 0xde, 0xe9, 0xb7, 0x5d, 0xd9, 0x44, 0xd2, 0x3f, 0x2a, 0x07, + 0x57, 0xad, 0x24, 0xdd, 0xfa, 0xbc, 0x14, 0x92, 0x34, 0x06, 0x38, 0x62, 0x86, 0x14, 0xf6, 0x77, + 0x26, 0x01, 0xd4, 0x5c, 0xa2, 0x3d, 0xf2, 0x21, 0x28, 0x87, 0x34, 0x12, 0x4d, 0x22, 0xaf, 0xb9, + 0xc4, 0xe5, 0xa4, 0x2a, 0xc4, 0x18, 0x4e, 0x76, 0xa0, 0xd8, 0x73, 0xfa, 0x21, 0xcd, 0xe7, 0x70, + 0x23, 0x47, 0xe6, 0x3a, 0xa3, 0x28, 0x4e, 0xcd, 0xfc, 0x27, 0x0a, 0x1e, 0xe4, 0xcb, 0x16, 0x00, + 0x4d, 0x8e, 0xa6, 0x91, 0xad, 0x57, 0x92, 0x65, 0x3c, 0xe0, 0x58, 0x1b, 0xd4, 0xa7, 0x0f, 0xf6, + 0xab, 0x60, 0x8c, 0x4b, 0x83, 0x2d, 0xb9, 0x07, 0x25, 0x47, 0x6d, 0x48, 0xe3, 0x67, 0xb1, 0x21, + 0xf1, 0xc3, 0xac, 0x9e, 0x51, 0x9a, 0x19, 0xf9, 0xaa, 0x05, 0xd3, 0x21, 0x8d, 0x64, 0x57, 0xb1, + 0x65, 0x51, 0x6a, 0xe3, 0x23, 0xce, 0x88, 0x46, 0x82, 0xa6, 0x58, 0xde, 0x93, 0x65, 0x98, 0xe2, + 0xab, 0x44, 0xb9, 0x4e, 0x9d, 0x16, 0x0d, 0xb8, 0xad, 0x44, 0xaa, 0x79, 0xa3, 0x8b, 0x62, 0xd0, + 0xd4, 0xa2, 0x18, 0x65, 0x98, 0xe2, 0xab, 0x44, 0x59, 0x73, 0x83, 0xc0, 0x97, 0xa2, 0x94, 0x72, + 0x12, 0xc5, 0xa0, 0xa9, 0x45, 0x31, 0xca, 0x30, 0xc5, 0x97, 0x74, 0x60, 0xa2, 0xc7, 0xa7, 0x96, + 0x54, 0xe5, 0x46, 0xbc, 0x23, 0x57, 0xd3, 0x94, 0xf6, 0x84, 0x4d, 0x4a, 0xfc, 0x47, 0xc9, 0xc3, + 0xfe, 0xf6, 0x39, 0x98, 0x56, 0xd3, 0x36, 0x3e, 0xe4, 0x08, 0x43, 0xe0, 0x90, 0x43, 0xce, 0x92, + 0x09, 0xc4, 0x24, 0x2e, 0xab, 0x2c, 0x56, 0xad, 0xe4, 0x19, 0x47, 0x57, 0x6e, 0x98, 0x40, 0x4c, + 0xe2, 0x92, 0x2e, 0x14, 0xd9, 0xca, 0xa2, 0xdc, 0x2f, 0x46, 0xfc, 0xf2, 0x78, 0x35, 0x32, 0x8c, + 0x2a, 0x8c, 0x3c, 0x0a, 0x2e, 0xdc, 0x96, 0x1d, 0x25, 0xcc, 0xdb, 0x72, 0x2a, 0xe6, 0xb3, 0x1a, + 0x24, 0x2d, 0xe7, 0xa2, 0xef, 0x93, 0x65, 0x98, 0x62, 0x9f, 0x71, 0xee, 0x29, 0x9e, 0xe1, 0xb9, + 0xe7, 0x53, 0x50, 0xea, 0x3a, 0xf7, 0x1b, 0xfd, 0xa0, 0x7d, 0xfa, 0xf3, 0x95, 0x74, 0xa7, 0x15, + 0x54, 0x50, 0xd3, 0x23, 0x5f, 0xb4, 0x8c, 0x05, 0x4e, 0xf8, 0x5a, 0xdc, 0xc9, 0x77, 0x81, 0xd3, + 0x6a, 0xc3, 0xd0, 0xa5, 0x6e, 0xe0, 0x14, 0x52, 0x7a, 0xe0, 0xa7, 0x10, 0xa6, 0x51, 0x8b, 0x09, + 0xa2, 0x35, 0xea, 0xf2, 0x99, 0x6a, 0xd4, 0x4b, 0x09, 0x66, 0x98, 0x62, 0xce, 0xe5, 0x11, 0x73, + 0x4e, 0xcb, 0x03, 0x67, 0x2a, 0x4f, 0x23, 0xc1, 0x0c, 0x53, 0xcc, 0x87, 0x1f, 0xbd, 0x2b, 0x67, + 0x73, 0xf4, 0x9e, 0xca, 0xe1, 0xe8, 0x7d, 0xf8, 0xa9, 0xe4, 0xdc, 0xa8, 0xa7, 0x12, 0x72, 0x03, + 0x48, 0x6b, 0xcf, 0x73, 0xba, 0x6e, 0x53, 0x2e, 0x96, 0x7c, 0x93, 0x9e, 0xe6, 0xa6, 0x19, 0xad, + 0x95, 0x2d, 0x0f, 0x60, 0x60, 0x46, 0x2d, 0x12, 0x41, 0xa9, 0xa7, 0x94, 0xcf, 0x99, 0x3c, 0x46, + 0xbf, 0x52, 0x46, 0x85, 0x0b, 0x0d, 0x9b, 0x78, 0xaa, 0x04, 0x35, 0x27, 0xb2, 0x0a, 0x17, 0xbb, + 0xae, 0xb7, 0xee, 0xb7, 0xc2, 0x75, 0x1a, 0x48, 0xc3, 0x53, 0x83, 0x46, 0x73, 0xb3, 0xbc, 0x6d, + 0xb8, 0x31, 0x61, 0x2d, 0x03, 0x8e, 0x99, 0xb5, 0xec, 0xff, 0x65, 0xc1, 0xec, 0x52, 0xc7, 0xef, + 0xb7, 0xee, 0x38, 0x51, 0x73, 0x5b, 0x78, 0x6c, 0x90, 0x57, 0xa0, 0xe4, 0x7a, 0x11, 0x0d, 0x76, + 0x9d, 0x8e, 0xdc, 0x9f, 0x6c, 0x65, 0x49, 0x5e, 0x91, 0xe5, 0xef, 0xed, 0x57, 0xa7, 0x97, 0xfb, + 0x01, 0x37, 0xd8, 0x8b, 0xd5, 0x0a, 0x75, 0x1d, 0xf2, 0x6d, 0x0b, 0xce, 0x0b, 0x9f, 0x8f, 0x65, + 0x27, 0x72, 0x5e, 0xef, 0xd3, 0xc0, 0xa5, 0xca, 0xeb, 0x63, 0xc4, 0x85, 0x2a, 0x2d, 0xab, 0x62, + 0xb0, 0x17, 0x9f, 0x59, 0xd6, 0xd2, 0x9c, 0x71, 0x50, 0x18, 0xfb, 0x97, 0x0b, 0xf0, 0xe8, 0x50, + 0x5a, 0x64, 0x1e, 0xc6, 0xdc, 0x96, 0xfc, 0x74, 0x90, 0x74, 0xc7, 0x56, 0x5a, 0x38, 0xe6, 0xb6, + 0xc8, 0x02, 0xd7, 0x70, 0x03, 0x1a, 0x86, 0xea, 0xee, 0xbd, 0xac, 0x95, 0x51, 0x59, 0x8a, 0x06, + 0x06, 0xa9, 0x42, 0x91, 0xbb, 0x52, 0xcb, 0xa3, 0x15, 0xd7, 0x99, 0xb9, 0xd7, 0x32, 0x8a, 0x72, + 0xf2, 0x25, 0x0b, 0x40, 0x08, 0xc8, 0xf4, 0x7d, 0xb9, 0x4b, 0x62, 0xbe, 0xcd, 0xc4, 0x28, 0x0b, + 0x29, 0xe3, 0xff, 0x68, 0x70, 0x25, 0x1b, 0x30, 0xc1, 0xd4, 0x67, 0xbf, 0x75, 0xea, 0x4d, 0x51, + 0x28, 0x40, 0x9c, 0x06, 0x4a, 0x5a, 0xac, 0xad, 0x02, 0x1a, 0xf5, 0x03, 0x8f, 0x35, 0x2d, 0xdf, + 0x06, 0x4b, 0x42, 0x0a, 0xd4, 0xa5, 0x68, 0x60, 0xd8, 0xff, 0x6c, 0x0c, 0x2e, 0x66, 0x89, 0xce, + 0x76, 0x9b, 0x09, 0x21, 0xad, 0xb4, 0x12, 0xfc, 0x4c, 0xfe, 0xed, 0x23, 0xdd, 0x97, 0xf4, 0x8d, + 0x8d, 0xf4, 0x25, 0x95, 0x7c, 0xc9, 0xcf, 0xe8, 0x16, 0x1a, 0x3b, 0x65, 0x0b, 0x69, 0xca, 0xa9, + 0x56, 0x7a, 0x12, 0xc6, 0x43, 0xd6, 0xf3, 0x85, 0xe4, 0xcd, 0x0f, 0xef, 0x23, 0x0e, 0x61, 0x18, + 0x7d, 0xcf, 0x8d, 0x64, 0xfc, 0x91, 0xc6, 0xb8, 0xed, 0xb9, 0x11, 0x72, 0x88, 0xfd, 0xad, 0x31, + 0x98, 0x1f, 0xfe, 0x51, 0xe4, 0x5b, 0x16, 0x40, 0x8b, 0x1d, 0x8e, 0x42, 0xee, 0xc4, 0x2f, 0xdc, + 0xbd, 0x9c, 0xb3, 0x6a, 0xc3, 0x65, 0xc5, 0x29, 0xf6, 0x43, 0xd4, 0x45, 0x21, 0x1a, 0x82, 0x90, + 0xe7, 0xd4, 0xd0, 0xe7, 0xb7, 0x56, 0x62, 0x32, 0xe9, 0x3a, 0x6b, 0x1a, 0x82, 0x06, 0x16, 0x3b, + 0xfd, 0x7a, 0x4e, 0x97, 0x86, 0x3d, 0x47, 0x47, 0x73, 0xf1, 0xd3, 0xef, 0x4d, 0x55, 0x88, 0x31, + 0xdc, 0xee, 0xc0, 0x53, 0xc7, 0x90, 0x33, 0xa7, 0x60, 0x19, 0xfb, 0x7f, 0x58, 0xf0, 0x88, 0xf4, + 0xc4, 0xfb, 0xff, 0xc6, 0xad, 0xf3, 0x4f, 0x2d, 0x78, 0x6c, 0xc8, 0x37, 0x3f, 0x00, 0xef, 0xce, + 0xb7, 0x92, 0xde, 0x9d, 0xb7, 0x47, 0x1d, 0xd2, 0x99, 0xdf, 0x31, 0xc4, 0xc9, 0xf3, 0x77, 0x0b, + 0x70, 0x8e, 0x2d, 0x5b, 0x2d, 0xbf, 0x9d, 0xd3, 0xc6, 0xf9, 0x14, 0x14, 0x3f, 0xc7, 0x36, 0xa0, + 0xf4, 0x20, 0xe3, 0xbb, 0x12, 0x0a, 0x18, 0xf9, 0xb2, 0x05, 0x93, 0x9f, 0x93, 0x7b, 0xaa, 0x38, + 0xcb, 0x8d, 0xb8, 0x18, 0x26, 0xbe, 0x61, 0x41, 0xee, 0x90, 0x22, 0x06, 0x47, 0xfb, 0x72, 0xaa, + 0xad, 0x54, 0x71, 0x26, 0xcf, 0xc0, 0xe4, 0x96, 0x1f, 0x74, 0xfb, 0x1d, 0x27, 0x1d, 0xf8, 0x79, + 0x4d, 0x14, 0xa3, 0x82, 0xb3, 0x49, 0xee, 0xf4, 0xdc, 0x37, 0x68, 0x10, 0x8a, 0x90, 0x8c, 0xc4, + 0x24, 0xaf, 0x69, 0x08, 0x1a, 0x58, 0xbc, 0x4e, 0xbb, 0x1d, 0xd0, 0xb6, 0x13, 0xf9, 0x01, 0xdf, + 0x39, 0xcc, 0x3a, 0x1a, 0x82, 0x06, 0xd6, 0xfc, 0xc7, 0x61, 0xca, 0x14, 0xfe, 0x44, 0xf1, 0x3c, + 0x9f, 0x00, 0xe9, 0xd4, 0x99, 0x5a, 0x92, 0xac, 0xe3, 0x2c, 0x49, 0xf6, 0x7f, 0x18, 0x03, 0xc3, + 0x16, 0xf5, 0x00, 0xa6, 0xba, 0x97, 0x98, 0xea, 0x23, 0xda, 0x51, 0x0c, 0xcb, 0xda, 0xb0, 0xe8, + 0xc6, 0xdd, 0x54, 0x74, 0xe3, 0xcd, 0xdc, 0x38, 0x1e, 0x1e, 0xdc, 0xf8, 0x03, 0x0b, 0x1e, 0x8b, + 0x91, 0x07, 0x6d, 0xd8, 0x47, 0xaf, 0xdb, 0x2f, 0x42, 0xc5, 0x89, 0xab, 0xc9, 0x89, 0x65, 0x84, + 0x96, 0x69, 0x10, 0x9a, 0x78, 0x71, 0x58, 0x4c, 0xe1, 0x94, 0x61, 0x31, 0xe3, 0x87, 0x87, 0xc5, + 0xd8, 0x3f, 0x1e, 0x83, 0x27, 0x06, 0xbf, 0xcc, 0xf4, 0x15, 0x3f, 0xfa, 0xdb, 0xd2, 0xde, 0xe4, + 0x63, 0xa7, 0xf6, 0x26, 0x2f, 0x1c, 0xd7, 0x9b, 0x5c, 0xfb, 0x70, 0x8f, 0x9f, 0xb9, 0x0f, 0x77, + 0x03, 0x2e, 0x29, 0x87, 0xd1, 0x6b, 0x7e, 0x20, 0x63, 0x43, 0xd4, 0x0a, 0x52, 0xaa, 0x3f, 0x21, + 0xab, 0x5c, 0xc2, 0x2c, 0x24, 0xcc, 0xae, 0x6b, 0xff, 0xa0, 0x00, 0x17, 0xe2, 0x66, 0x5f, 0xf2, + 0xbd, 0x96, 0xcb, 0x7d, 0x8e, 0x5e, 0x86, 0xf1, 0x68, 0xaf, 0xa7, 0x1a, 0xfb, 0x2f, 0x2a, 0x71, + 0x36, 0xf6, 0x7a, 0xac, 0xb7, 0x1f, 0xc9, 0xa8, 0xc2, 0x6f, 0x11, 0x78, 0x25, 0xb2, 0xaa, 0x67, + 0x87, 0xe8, 0x81, 0x17, 0x92, 0xa3, 0xf9, 0xbd, 0xfd, 0x6a, 0x46, 0x96, 0x87, 0x05, 0x4d, 0x29, + 0x39, 0xe6, 0xc9, 0x5d, 0x98, 0xee, 0x38, 0x61, 0x74, 0xbb, 0xd7, 0x72, 0x22, 0xba, 0xe1, 0x4a, + 0x6f, 0x9e, 0x93, 0x85, 0xd3, 0x68, 0xb7, 0x87, 0xd5, 0x04, 0x25, 0x4c, 0x51, 0x26, 0xbb, 0x40, + 0x58, 0xc9, 0x46, 0xe0, 0x78, 0xa1, 0xf8, 0x2a, 0xc6, 0xef, 0xe4, 0xb1, 0x51, 0xfa, 0xe8, 0xbc, + 0x3a, 0x40, 0x0d, 0x33, 0x38, 0x90, 0xa7, 0x61, 0x22, 0xa0, 0x4e, 0xa8, 0xb7, 0x03, 0x3d, 0xff, + 0x91, 0x97, 0xa2, 0x84, 0x9a, 0x13, 0x6a, 0xe2, 0x88, 0x09, 0xf5, 0x87, 0x16, 0x4c, 0xc7, 0xdd, + 0xf4, 0x00, 0x54, 0x8f, 0x6e, 0x52, 0xf5, 0xb8, 0x9e, 0xd7, 0x92, 0x38, 0x44, 0xdb, 0xf8, 0x93, + 0x49, 0xf3, 0xfb, 0x78, 0x00, 0xc7, 0xe7, 0x4d, 0x7f, 0x7e, 0x2b, 0x8f, 0xa8, 0xba, 0x84, 0xb6, + 0x77, 0xa8, 0x23, 0x3f, 0xd3, 0x75, 0x5a, 0x52, 0x8f, 0x91, 0xc3, 0x5e, 0xeb, 0x3a, 0x4a, 0xbf, + 0xc9, 0xd2, 0x75, 0x54, 0x1d, 0x72, 0x1b, 0x1e, 0xe9, 0x05, 0x3e, 0xcf, 0x33, 0xb0, 0x4c, 0x9d, + 0x56, 0xc7, 0xf5, 0xa8, 0x32, 0xf3, 0x08, 0xaf, 0x9b, 0xc7, 0x0e, 0xf6, 0xab, 0x8f, 0xac, 0x67, + 0xa3, 0xe0, 0xb0, 0xba, 0xc9, 0x48, 0xd5, 0xf1, 0x63, 0x44, 0xaa, 0xfe, 0xa2, 0x36, 0xa6, 0xea, + 0xa0, 0x88, 0x4f, 0xe7, 0xd5, 0x95, 0x59, 0xe1, 0x11, 0x7a, 0x48, 0xd5, 0x24, 0x53, 0xd4, 0xec, + 0x87, 0x5b, 0xec, 0x26, 0x4e, 0x69, 0xb1, 0x8b, 0xe3, 0x60, 0x26, 0xdf, 0xcf, 0x38, 0x98, 0xd2, + 0x07, 0x2a, 0x0e, 0xe6, 0xdb, 0x16, 0x5c, 0x70, 0x06, 0x23, 0xd0, 0xf3, 0x31, 0x1e, 0x67, 0x84, + 0xb6, 0xd7, 0x1f, 0x93, 0x42, 0x66, 0x05, 0xfa, 0x63, 0x96, 0x28, 0xf6, 0xbb, 0x45, 0x98, 0x4d, + 0x2b, 0x49, 0x67, 0x1f, 0xaa, 0xfb, 0x37, 0x2c, 0x98, 0x55, 0x13, 0x5c, 0xdf, 0x80, 0x8b, 0x23, + 0xc6, 0x6a, 0x4e, 0xeb, 0x8a, 0x50, 0xf7, 0x74, 0x06, 0x95, 0x8d, 0x14, 0x37, 0x1c, 0xe0, 0x4f, + 0xde, 0x84, 0x8a, 0xbe, 0x55, 0x39, 0x55, 0xdc, 0x2e, 0x0f, 0x2d, 0xad, 0xc5, 0x24, 0xd0, 0xa4, + 0x47, 0xde, 0xb5, 0x00, 0x9a, 0x6a, 0x27, 0xce, 0x29, 0x2a, 0x2a, 0x43, 0x5b, 0x88, 0xf5, 0x79, + 0x5d, 0x14, 0xa2, 0xc1, 0x98, 0xfc, 0x32, 0xbf, 0x4f, 0xd1, 0x23, 0x41, 0x79, 0x1e, 0x7c, 0x32, + 0xef, 0xa5, 0x28, 0xf6, 0x25, 0xd1, 0xda, 0x9e, 0x01, 0x0a, 0x31, 0x21, 0x84, 0xfd, 0x32, 0x68, + 0x9f, 0x6d, 0xb6, 0xb2, 0x72, 0xaf, 0xed, 0x75, 0x27, 0xda, 0x96, 0x43, 0x50, 0xaf, 0xac, 0xd7, + 0x14, 0x00, 0x63, 0x1c, 0xfb, 0xb3, 0x30, 0xfd, 0x6a, 0xe0, 0xf4, 0xb6, 0x5d, 0x7e, 0x6f, 0xc1, + 0xce, 0xc7, 0xcf, 0xc0, 0xa4, 0xd3, 0x6a, 0x65, 0x25, 0xfb, 0xa9, 0x89, 0x62, 0x54, 0xf0, 0x63, + 0x1d, 0x85, 0xed, 0x7f, 0x6d, 0x01, 0x89, 0x6f, 0x9a, 0x5d, 0xaf, 0xbd, 0xe6, 0x44, 0xcd, 0x6d, + 0x76, 0x84, 0xdb, 0xe6, 0xa5, 0x59, 0x47, 0xb8, 0xeb, 0x1a, 0x82, 0x06, 0x16, 0x79, 0x1b, 0x2a, + 0xe2, 0xdf, 0x1b, 0xfa, 0x80, 0x38, 0xba, 0xeb, 0x39, 0xdf, 0xf3, 0xb8, 0x4c, 0x62, 0x14, 0x5e, + 0x8f, 0x39, 0xa0, 0xc9, 0x8e, 0x35, 0xd5, 0x8a, 0xb7, 0xd5, 0xe9, 0xdf, 0x6f, 0x6d, 0xc6, 0x4d, + 0xd5, 0x0b, 0xfc, 0x2d, 0xb7, 0x43, 0xd3, 0x4d, 0xb5, 0x2e, 0x8a, 0x51, 0xc1, 0x8f, 0xd7, 0x54, + 0xff, 0xca, 0x82, 0x8b, 0x2b, 0x61, 0xe4, 0xfa, 0xcb, 0x34, 0x8c, 0xd8, 0xce, 0xc7, 0xd6, 0xc7, + 0x7e, 0xe7, 0x38, 0xe1, 0x17, 0xcb, 0x30, 0x2b, 0xef, 0xa1, 0xfb, 0x9b, 0x21, 0x8d, 0x8c, 0xa3, + 0x86, 0x9e, 0xc7, 0x4b, 0x29, 0x38, 0x0e, 0xd4, 0x60, 0x54, 0xe4, 0x85, 0x74, 0x4c, 0xa5, 0x90, + 0xa4, 0xd2, 0x48, 0xc1, 0x71, 0xa0, 0x86, 0xfd, 0xfd, 0x02, 0x5c, 0xe0, 0x9f, 0x91, 0x0a, 0x9d, + 0xfa, 0xc6, 0xb0, 0xd0, 0xa9, 0x11, 0xa7, 0x32, 0xe7, 0x75, 0x8a, 0xc0, 0xa9, 0xbf, 0x6e, 0xc1, + 0x4c, 0x2b, 0xd9, 0xd2, 0xf9, 0xd8, 0xe5, 0xb2, 0xfa, 0x50, 0x78, 0x20, 0xa6, 0x0a, 0x31, 0xcd, + 0x9f, 0xfc, 0x8a, 0x05, 0x33, 0x49, 0x31, 0xd5, 0xea, 0x7e, 0x06, 0x8d, 0xa4, 0x43, 0x06, 0x92, + 0xe5, 0x21, 0xa6, 0x45, 0xb0, 0x7f, 0x6f, 0x4c, 0x76, 0xe9, 0x59, 0xc4, 0x05, 0x91, 0x7b, 0x50, + 0x8e, 0x3a, 0xa1, 0x28, 0x94, 0x5f, 0x3b, 0xe2, 0xa1, 0x75, 0x63, 0xb5, 0x21, 0x1c, 0x4e, 0x62, + 0xbd, 0x52, 0x96, 0x30, 0xfd, 0x58, 0xf1, 0xe2, 0x8c, 0x9b, 0x3d, 0xc9, 0x38, 0x97, 0xd3, 0xf2, + 0xc6, 0xd2, 0x7a, 0x9a, 0xb1, 0x2c, 0x61, 0x8c, 0x15, 0x2f, 0xfb, 0x37, 0x2c, 0x28, 0xdf, 0xf0, + 0xd5, 0x3a, 0xf2, 0xb3, 0x39, 0xd8, 0xa2, 0xb4, 0xca, 0xaa, 0x95, 0x96, 0xf8, 0x14, 0xf4, 0x4a, + 0xc2, 0x12, 0xf5, 0xb8, 0x41, 0x7b, 0x81, 0xe7, 0x3c, 0x64, 0xa4, 0x6e, 0xf8, 0x9b, 0x43, 0xcd, + 0xc7, 0xbf, 0x5a, 0x84, 0x73, 0xaf, 0x39, 0x7b, 0xd4, 0x8b, 0x9c, 0x93, 0x6f, 0x12, 0x2f, 0x42, + 0xc5, 0xe9, 0xf1, 0xbb, 0x4c, 0xe3, 0x18, 0x12, 0x1b, 0x77, 0x62, 0x10, 0x9a, 0x78, 0xf1, 0x82, + 0x26, 0x82, 0x74, 0xb2, 0x96, 0xa2, 0xa5, 0x14, 0x1c, 0x07, 0x6a, 0x90, 0x1b, 0x40, 0x64, 0x60, + 0x7b, 0xad, 0xd9, 0xf4, 0xfb, 0x9e, 0x58, 0xd2, 0x84, 0xdd, 0x47, 0x9f, 0x87, 0xd7, 0x06, 0x30, + 0x30, 0xa3, 0x16, 0xf9, 0x0c, 0xcc, 0x35, 0x39, 0x65, 0x79, 0x3a, 0x32, 0x29, 0x8a, 0x13, 0xb2, + 0x0e, 0x7b, 0x59, 0x1a, 0x82, 0x87, 0x43, 0x29, 0x30, 0x49, 0xc3, 0xc8, 0x0f, 0x9c, 0x36, 0x35, + 0xe9, 0x4e, 0x24, 0x25, 0x6d, 0x0c, 0x60, 0x60, 0x46, 0x2d, 0xf2, 0x05, 0x28, 0x47, 0xdb, 0x01, + 0x0d, 0xb7, 0xfd, 0x4e, 0x4b, 0xfa, 0x9e, 0x8c, 0x68, 0x0c, 0x94, 0xbd, 0xbf, 0xa1, 0xa8, 0x1a, + 0xc3, 0x5b, 0x15, 0x61, 0xcc, 0x93, 0x04, 0x30, 0x11, 0x36, 0xfd, 0x1e, 0x0d, 0xe5, 0xa9, 0xe2, + 0x46, 0x2e, 0xdc, 0xb9, 0x71, 0xcb, 0x30, 0x43, 0x72, 0x0e, 0x28, 0x39, 0xd9, 0xbf, 0x33, 0x06, + 0x53, 0x26, 0xe2, 0x31, 0xd6, 0xa6, 0x2f, 0x5b, 0x30, 0xd5, 0xf4, 0xbd, 0x28, 0xf0, 0x3b, 0x71, + 0xc2, 0x86, 0xd1, 0x35, 0x0a, 0x46, 0x6a, 0x99, 0x46, 0x8e, 0xdb, 0x31, 0xac, 0x75, 0x06, 0x1b, + 0x4c, 0x30, 0x25, 0x5f, 0xb7, 0x60, 0x26, 0x76, 0x8c, 0x8c, 0x6d, 0x7d, 0xb9, 0x0a, 0xa2, 0x97, + 0xfa, 0xab, 0x49, 0x4e, 0x98, 0x66, 0x6d, 0x6f, 0xc2, 0x6c, 0xba, 0xb7, 0x59, 0x53, 0xf6, 0x1c, + 0x39, 0xd7, 0x0b, 0x71, 0x53, 0xae, 0x3b, 0x61, 0x88, 0x1c, 0x42, 0x9e, 0x85, 0x52, 0xd7, 0x09, + 0xda, 0xae, 0xe7, 0x74, 0x78, 0x2b, 0x16, 0x8c, 0x05, 0x49, 0x96, 0xa3, 0xc6, 0xb0, 0x3f, 0x02, + 0x53, 0x6b, 0x8e, 0xd7, 0xa6, 0x2d, 0xb9, 0x0e, 0x1f, 0x1d, 0x99, 0xfa, 0xc7, 0xe3, 0x50, 0x31, + 0x8e, 0x8f, 0x67, 0x7f, 0xce, 0x4a, 0x24, 0x22, 0x2a, 0xe4, 0x98, 0x88, 0xe8, 0x53, 0x00, 0x5b, + 0xae, 0xe7, 0x86, 0xdb, 0xa7, 0x4c, 0x71, 0xc4, 0xef, 0xe6, 0xaf, 0x69, 0x0a, 0x68, 0x50, 0x8b, + 0x2f, 0x40, 0x8b, 0x87, 0x64, 0x0b, 0x7c, 0xd7, 0x32, 0xb6, 0x9b, 0x89, 0x3c, 0x1c, 0x3e, 0x8c, + 0x8e, 0x59, 0x50, 0xdb, 0x8f, 0xb8, 0x9b, 0x3a, 0x6c, 0x57, 0xda, 0x80, 0x52, 0x40, 0xc3, 0x7e, + 0x97, 0x9e, 0x2a, 0x19, 0x11, 0x77, 0xbd, 0x41, 0x59, 0x1f, 0x35, 0xa5, 0xf9, 0x97, 0xe1, 0x5c, + 0x42, 0x84, 0x13, 0xdd, 0x30, 0xf9, 0x90, 0x69, 0xa3, 0x38, 0xcd, 0x7d, 0x13, 0xeb, 0x8b, 0x8e, + 0x91, 0x84, 0x48, 0xf7, 0x85, 0x70, 0xb0, 0x12, 0x30, 0xfb, 0xc7, 0x13, 0x20, 0x7d, 0x18, 0x8e, + 0xb1, 0x5c, 0x99, 0x37, 0x97, 0x63, 0xa7, 0xb8, 0xb9, 0xbc, 0x01, 0x53, 0xae, 0xe7, 0x46, 0xae, + 0xd3, 0xe1, 0xf6, 0x27, 0xb9, 0x9d, 0x2a, 0x67, 0xfc, 0xa9, 0x15, 0x03, 0x96, 0x41, 0x27, 0x51, + 0x97, 0xbc, 0x0e, 0x45, 0xbe, 0xdf, 0xc8, 0x01, 0x7c, 0x72, 0x47, 0x0b, 0xee, 0x63, 0x23, 0x22, + 0xf4, 0x04, 0x25, 0x7e, 0xf8, 0x10, 0x59, 0x98, 0xf4, 0xf1, 0x5b, 0x8e, 0xe3, 0xf8, 0xf0, 0x91, + 0x82, 0xe3, 0x40, 0x0d, 0x46, 0x65, 0xcb, 0x71, 0x3b, 0xfd, 0x80, 0xc6, 0x54, 0x26, 0x92, 0x54, + 0xae, 0xa5, 0xe0, 0x38, 0x50, 0x83, 0x6c, 0xc1, 0x94, 0x2c, 0x13, 0x6e, 0x73, 0x93, 0xa7, 0xfc, + 0x4a, 0xee, 0x1e, 0x79, 0xcd, 0xa0, 0x84, 0x09, 0xba, 0xa4, 0x0f, 0xe7, 0x5d, 0xaf, 0xe9, 0x7b, + 0xcd, 0x4e, 0x3f, 0x74, 0x77, 0x69, 0x1c, 0x1e, 0x77, 0x1a, 0x66, 0x97, 0x0e, 0xf6, 0xab, 0xe7, + 0x57, 0xd2, 0xe4, 0x70, 0x90, 0x03, 0xf9, 0xa2, 0x05, 0x97, 0x9a, 0xbe, 0x17, 0xf2, 0x2c, 0x1e, + 0xbb, 0xf4, 0x6a, 0x10, 0xf8, 0x81, 0xe0, 0x5d, 0x3e, 0x25, 0x6f, 0x6e, 0xf6, 0x5c, 0xca, 0x22, + 0x89, 0xd9, 0x9c, 0xc8, 0x5b, 0x50, 0xea, 0x05, 0xfe, 0xae, 0xdb, 0xa2, 0x81, 0x74, 0xc1, 0x5c, + 0xcd, 0x23, 0xb5, 0xd1, 0xba, 0xa4, 0x19, 0x2f, 0x3d, 0xaa, 0x04, 0x35, 0x3f, 0xfb, 0xff, 0x54, + 0x60, 0x3a, 0x89, 0x4e, 0x7e, 0x1e, 0xa0, 0x17, 0xf8, 0x5d, 0x1a, 0x6d, 0x53, 0x1d, 0xe6, 0x74, + 0x73, 0xd4, 0xe4, 0x35, 0x8a, 0x9e, 0x72, 0x5b, 0x62, 0xcb, 0x45, 0x5c, 0x8a, 0x06, 0x47, 0x12, + 0xc0, 0xe4, 0x8e, 0xd8, 0x76, 0xa5, 0x16, 0xf2, 0x5a, 0x2e, 0x3a, 0x93, 0xe4, 0xcc, 0xe3, 0x73, + 0x64, 0x11, 0x2a, 0x46, 0x64, 0x13, 0x0a, 0xf7, 0xe8, 0x66, 0x3e, 0x99, 0x13, 0xee, 0x50, 0x79, + 0x9a, 0xa9, 0x4f, 0x1e, 0xec, 0x57, 0x0b, 0x77, 0xe8, 0x26, 0x32, 0xe2, 0xec, 0xbb, 0x5a, 0xc2, + 0x77, 0x41, 0x2e, 0x15, 0xaf, 0xe5, 0xe8, 0x08, 0x21, 0xbe, 0x4b, 0x16, 0xa1, 0x62, 0x44, 0xde, + 0x82, 0xf2, 0x3d, 0x67, 0x97, 0x6e, 0x05, 0xbe, 0x17, 0x49, 0x5f, 0xb9, 0x11, 0x83, 0x4b, 0xee, + 0x28, 0x72, 0x92, 0x2f, 0xdf, 0xde, 0x75, 0x21, 0xc6, 0xec, 0xc8, 0x2e, 0x94, 0x3c, 0x7a, 0x0f, + 0x69, 0xc7, 0x6d, 0xe6, 0x13, 0xcc, 0x71, 0x53, 0x52, 0x93, 0x9c, 0xf9, 0xbe, 0xa7, 0xca, 0x50, + 0xf3, 0x62, 0x7d, 0x79, 0xd7, 0xdf, 0x94, 0x0b, 0xd5, 0x88, 0x7d, 0xa9, 0x4f, 0xa6, 0xa2, 0x2f, + 0x6f, 0xf8, 0x9b, 0xc8, 0x88, 0xb3, 0x39, 0xd2, 0xd4, 0x8e, 0x5a, 0x72, 0x99, 0xba, 0x99, 0xaf, + 0x83, 0x9a, 0x98, 0x23, 0x71, 0x29, 0x1a, 0x1c, 0x59, 0xdb, 0xb6, 0xa5, 0xb1, 0x52, 0x2e, 0x54, + 0x23, 0xb6, 0x6d, 0xd2, 0xf4, 0x29, 0xda, 0x56, 0x95, 0xa1, 0xe6, 0xc5, 0xf8, 0xba, 0xd2, 0xf2, + 0x97, 0xcf, 0x52, 0x95, 0xb4, 0x23, 0x0a, 0xbe, 0xaa, 0x0c, 0x35, 0x2f, 0xd6, 0xde, 0xe1, 0xce, + 0xde, 0x3d, 0xa7, 0xb3, 0xe3, 0x7a, 0x6d, 0x19, 0xb6, 0x3b, 0x6a, 0x98, 0xdb, 0xce, 0xde, 0x1d, + 0x41, 0xcf, 0x6c, 0xef, 0xb8, 0x14, 0x0d, 0x8e, 0xe4, 0xef, 0x5a, 0x3a, 0x14, 0x67, 0x2a, 0x0f, + 0x27, 0xa6, 0xe4, 0x92, 0x2b, 0x23, 0x73, 0x84, 0xa2, 0xf8, 0x53, 0xda, 0xef, 0x92, 0x17, 0x7e, + 0xed, 0x8f, 0xaa, 0x73, 0xd4, 0x6b, 0xfa, 0x2d, 0xd7, 0x6b, 0x2f, 0xde, 0x0d, 0x7d, 0x6f, 0x01, + 0x9d, 0x7b, 0x4a, 0x47, 0x97, 0x32, 0xcd, 0x7f, 0x0c, 0x2a, 0x06, 0x89, 0xa3, 0x14, 0xbd, 0x29, + 0x53, 0xd1, 0xfb, 0x8d, 0x09, 0x98, 0x32, 0xf3, 0x90, 0x1e, 0x43, 0xfb, 0xd2, 0x27, 0x8e, 0xb1, + 0x93, 0x9c, 0x38, 0xd8, 0x11, 0xd3, 0xb8, 0xe0, 0x52, 0xe6, 0xad, 0x95, 0xdc, 0x14, 0xee, 0xf8, + 0x88, 0x69, 0x14, 0x86, 0x98, 0x60, 0x7a, 0x02, 0x9f, 0x17, 0xa6, 0xb6, 0x0a, 0xc5, 0xae, 0x98, + 0x54, 0x5b, 0x13, 0xaa, 0xda, 0x73, 0x00, 0x71, 0xc2, 0x4c, 0x79, 0xf1, 0xa9, 0xf5, 0x61, 0x23, + 0x91, 0xa7, 0x81, 0x45, 0x9e, 0x86, 0x09, 0xa6, 0xfa, 0xd0, 0x96, 0xcc, 0x2a, 0xa0, 0xcf, 0xf1, + 0xd7, 0x78, 0x29, 0x4a, 0x28, 0x79, 0x89, 0x69, 0xa9, 0xb1, 0xc2, 0x22, 0x93, 0x05, 0x5c, 0x8c, + 0xb5, 0xd4, 0x18, 0x86, 0x09, 0x4c, 0x26, 0x3a, 0x65, 0xfa, 0x05, 0x5f, 0x1b, 0x0c, 0xd1, 0xb9, + 0xd2, 0x81, 0x02, 0xc6, 0xed, 0x4a, 0x29, 0x7d, 0x84, 0xcf, 0xe9, 0xa2, 0x61, 0x57, 0x4a, 0xc1, + 0x71, 0xa0, 0x06, 0xfb, 0x18, 0x79, 0x67, 0x5b, 0x11, 0x0e, 0xd3, 0x43, 0x6e, 0x5b, 0xbf, 0x62, + 0x9e, 0xb5, 0x72, 0x9c, 0x43, 0x62, 0xd4, 0x1e, 0xff, 0xb0, 0x35, 0xda, 0xb1, 0xe8, 0xb3, 0x30, + 0x9d, 0xdc, 0x85, 0x72, 0xbf, 0xf9, 0xf8, 0xea, 0x38, 0x5c, 0xb8, 0xd9, 0x76, 0xbd, 0x74, 0xce, + 0xb7, 0xac, 0x07, 0x1e, 0xac, 0x13, 0x3f, 0xf0, 0xa0, 0x63, 0xf2, 0xe4, 0xf3, 0x09, 0xd9, 0x31, + 0x79, 0xea, 0x2d, 0x8b, 0x24, 0x2e, 0xf9, 0x43, 0x0b, 0x1e, 0x77, 0x5a, 0xe2, 0x5c, 0xe0, 0x74, + 0x64, 0xa9, 0x91, 0x97, 0x5c, 0xce, 0xe8, 0x70, 0xc4, 0x5d, 0x7e, 0xf0, 0xe3, 0x17, 0x6a, 0x87, + 0x70, 0x15, 0x3d, 0xfe, 0x93, 0xf2, 0x0b, 0x1e, 0x3f, 0x0c, 0x15, 0x0f, 0x15, 0x9f, 0xfc, 0x65, + 0x98, 0x49, 0x7c, 0xb0, 0xb4, 0x84, 0x97, 0xc5, 0x85, 0x45, 0x23, 0x09, 0xc2, 0x34, 0xee, 0xfc, + 0x2d, 0xf8, 0x89, 0x23, 0xe5, 0x3c, 0xd1, 0x60, 0xfb, 0x9e, 0x05, 0x53, 0x66, 0x7a, 0x26, 0xf2, + 0x2c, 0x94, 0x22, 0x7f, 0x87, 0x7a, 0xb7, 0x03, 0xe5, 0xb0, 0xab, 0x07, 0xfa, 0x06, 0x2f, 0xc7, + 0x55, 0xd4, 0x18, 0x0c, 0xbb, 0xd9, 0x71, 0xa9, 0x17, 0xad, 0xb4, 0x64, 0x37, 0x6b, 0xec, 0x25, + 0x51, 0xbe, 0x8c, 0x1a, 0x43, 0xf8, 0xd8, 0xb1, 0xdf, 0x0d, 0xda, 0x0c, 0xa8, 0x72, 0xef, 0x37, + 0x7c, 0xec, 0x62, 0x18, 0x26, 0x30, 0x89, 0xad, 0x4d, 0x9c, 0xe3, 0xf1, 0xbd, 0x46, 0xca, 0x24, + 0xf9, 0x1d, 0x0b, 0xca, 0xc2, 0x44, 0x8f, 0x74, 0x2b, 0xe5, 0x62, 0x9b, 0x32, 0x22, 0xd4, 0xd6, + 0x57, 0xb2, 0x5c, 0x6c, 0x9f, 0x84, 0xf1, 0x1d, 0xd7, 0x53, 0x5f, 0xa2, 0xb7, 0xa5, 0xd7, 0x5c, + 0xaf, 0x85, 0x1c, 0xa2, 0x37, 0xae, 0xc2, 0xd0, 0x8d, 0x6b, 0x11, 0xca, 0xda, 0xf1, 0x44, 0x2e, + 0xff, 0xda, 0x7a, 0xab, 0x1d, 0x55, 0x30, 0xc6, 0xb1, 0x7f, 0xcd, 0x82, 0x69, 0x1e, 0x31, 0x1e, + 0x9f, 0x87, 0x5f, 0xd4, 0xbe, 0x60, 0x42, 0xee, 0x27, 0x92, 0xbe, 0x60, 0xef, 0xed, 0x57, 0x2b, + 0x22, 0xc6, 0x3c, 0xe9, 0x1a, 0xf6, 0x69, 0x69, 0x44, 0xe3, 0x1e, 0x6b, 0x63, 0x27, 0xb6, 0xf1, + 0xc4, 0x62, 0x2a, 0x22, 0x18, 0xd3, 0xb3, 0xdf, 0x86, 0x29, 0x33, 0x18, 0x8b, 0xbc, 0x08, 0x95, + 0x9e, 0xeb, 0xb5, 0x93, 0x41, 0xbb, 0xfa, 0xa2, 0x61, 0x3d, 0x06, 0xa1, 0x89, 0xc7, 0xab, 0xf9, + 0x71, 0xb5, 0xd4, 0xfd, 0xc4, 0xba, 0x6f, 0x56, 0x8b, 0xff, 0xd8, 0x1e, 0x40, 0x1c, 0x59, 0x7c, + 0x2c, 0xe3, 0xcd, 0x84, 0xb0, 0xfd, 0x0b, 0x65, 0x84, 0x67, 0x89, 0x98, 0x10, 0x23, 0xfc, 0xbd, + 0xfd, 0xc3, 0x94, 0x1d, 0x51, 0x8b, 0xbf, 0x41, 0x91, 0x11, 0x64, 0x98, 0xfb, 0x1b, 0x14, 0x19, + 0x3c, 0xde, 0xbf, 0x37, 0x28, 0xb2, 0x84, 0xf9, 0xb3, 0xf5, 0x06, 0xc5, 0x27, 0xe1, 0xa4, 0xe9, + 0x68, 0x99, 0x6e, 0x71, 0xcf, 0x4c, 0x1b, 0xa1, 0x5b, 0x5c, 0xe6, 0x8d, 0x90, 0x50, 0xfb, 0xb7, + 0x0b, 0x30, 0x9b, 0x36, 0x31, 0xe4, 0xed, 0xbd, 0x41, 0xbe, 0x6e, 0xc1, 0xb4, 0x93, 0x48, 0xfd, + 0x97, 0xd3, 0x83, 0x56, 0x09, 0x9a, 0x46, 0xea, 0xb9, 0x44, 0x39, 0xa6, 0x78, 0x93, 0xbf, 0x00, + 0x93, 0x91, 0xdb, 0xa5, 0x7e, 0x5f, 0x18, 0x1e, 0x0b, 0xc2, 0x00, 0xb0, 0x21, 0x8a, 0x50, 0xc1, + 0xd8, 0x26, 0xe0, 0x72, 0x8d, 0x2d, 0xa0, 0xd2, 0x13, 0x79, 0x36, 0xb6, 0x94, 0x8a, 0x72, 0xd4, + 0x18, 0xe4, 0x3e, 0x4c, 0x0a, 0x3f, 0x0f, 0xe5, 0xd0, 0xb3, 0x96, 0x93, 0x29, 0x44, 0xb8, 0x92, + 0xc4, 0x5d, 0x20, 0xfe, 0x87, 0xa8, 0xd8, 0xd9, 0x1f, 0x81, 0x13, 0xe6, 0xe7, 0xb5, 0xaf, 0x02, + 0x41, 0xbf, 0xd3, 0xd9, 0x74, 0x9a, 0x3b, 0x77, 0x5c, 0xaf, 0xe5, 0xdf, 0xe3, 0x4b, 0xdf, 0x22, + 0x94, 0x03, 0x19, 0xa2, 0x1b, 0xca, 0x51, 0xa3, 0xd7, 0x4e, 0x15, 0xbb, 0x1b, 0x62, 0x8c, 0x63, + 0xff, 0xde, 0x18, 0x4c, 0xca, 0x78, 0xf2, 0x07, 0x10, 0x09, 0xb1, 0x93, 0xb8, 0x7f, 0x5e, 0xc9, + 0x25, 0x0c, 0x7e, 0x68, 0x18, 0x44, 0x98, 0x0a, 0x83, 0x78, 0x2d, 0x1f, 0x76, 0x87, 0xc7, 0x40, + 0x7c, 0xb7, 0x08, 0x33, 0xa9, 0xf8, 0xfc, 0x54, 0x2a, 0x6f, 0xeb, 0x7d, 0x49, 0xe5, 0x4d, 0xc2, + 0x44, 0x3a, 0xf7, 0xfc, 0xfc, 0x26, 0xff, 0x3c, 0xb3, 0x7b, 0x5e, 0x1e, 0xad, 0xc5, 0x0f, 0x8e, + 0x47, 0xeb, 0x7f, 0xb1, 0xe0, 0xd1, 0xa1, 0x59, 0x26, 0x78, 0xbe, 0xb6, 0x20, 0x09, 0x95, 0xeb, + 0x45, 0xce, 0x99, 0x7b, 0xf4, 0x5d, 0x75, 0x3a, 0xc5, 0x56, 0x9a, 0x3d, 0x79, 0x01, 0xa6, 0xb8, + 0x3e, 0xc8, 0x56, 0xce, 0x88, 0xf6, 0xe4, 0x55, 0x1b, 0xbf, 0x74, 0x69, 0x18, 0xe5, 0x98, 0xc0, + 0xb2, 0xbf, 0x6d, 0xc1, 0xdc, 0xb0, 0xec, 0x5d, 0xc7, 0xd0, 0xe4, 0xfe, 0x52, 0x2a, 0x92, 0xa4, + 0x3a, 0x10, 0x49, 0x92, 0x32, 0x05, 0xa9, 0xa0, 0x11, 0xc3, 0x0a, 0x53, 0x38, 0x22, 0x50, 0xe2, + 0xf7, 0x0b, 0x30, 0x2b, 0x45, 0x8c, 0x95, 0xf0, 0x97, 0x12, 0xf1, 0x2f, 0x3f, 0x99, 0x8a, 0x7f, + 0xb9, 0x98, 0xc6, 0xff, 0xf3, 0xe0, 0x97, 0x0f, 0x56, 0xf0, 0xcb, 0xd7, 0x8a, 0x70, 0x29, 0x33, + 0x4f, 0x16, 0xf9, 0x6a, 0xc6, 0x4e, 0x71, 0x27, 0xe7, 0x84, 0x5c, 0x3a, 0x4e, 0xf6, 0x6c, 0x23, + 0x46, 0x7e, 0xc5, 0x8c, 0xd4, 0x10, 0xab, 0xff, 0xd6, 0x19, 0xa4, 0x16, 0x3b, 0x69, 0xd0, 0xc6, + 0x83, 0x7d, 0xea, 0xec, 0xcf, 0xc0, 0x52, 0xff, 0xb5, 0x02, 0x5c, 0x39, 0x6e, 0xcb, 0x7e, 0x40, + 0xa3, 0x1c, 0xc3, 0x44, 0x94, 0xe3, 0x03, 0x52, 0x6d, 0xce, 0x24, 0xe0, 0xf1, 0xef, 0x8f, 0xeb, + 0x7d, 0x77, 0x70, 0xc2, 0x1e, 0xcb, 0xb6, 0x30, 0xc9, 0x54, 0x5f, 0x95, 0x10, 0x3e, 0xde, 0x1b, + 0x26, 0x1b, 0xa2, 0xf8, 0xbd, 0xfd, 0xea, 0xf9, 0x38, 0xa1, 0x8c, 0x2c, 0x44, 0x55, 0x89, 0x5c, + 0x81, 0x52, 0x20, 0xa0, 0x2a, 0xae, 0x4b, 0x7a, 0xd7, 0x88, 0x32, 0xd4, 0x50, 0xf2, 0x05, 0xe3, + 0xac, 0x30, 0x7e, 0x56, 0x79, 0x93, 0x0e, 0x73, 0x1a, 0x7a, 0x13, 0x4a, 0xa1, 0xca, 0x5a, 0x2e, + 0xa6, 0xd3, 0xf3, 0xc7, 0x0c, 0x17, 0x74, 0x36, 0x69, 0x47, 0xa5, 0x30, 0x17, 0xdf, 0xa7, 0x13, + 0x9c, 0x6b, 0x92, 0xc4, 0xd6, 0x67, 0x6f, 0x71, 0xa9, 0x01, 0x83, 0xe7, 0x6e, 0x12, 0xc1, 0xa4, + 0x7c, 0xba, 0x58, 0xde, 0xb6, 0xae, 0xe5, 0x14, 0x77, 0x23, 0xbd, 0xb2, 0xf9, 0x91, 0x56, 0xd9, + 0x9c, 0x14, 0x2b, 0xfb, 0x07, 0x16, 0x54, 0xe4, 0x18, 0x79, 0x00, 0x71, 0x93, 0x77, 0x93, 0x71, + 0x93, 0x57, 0x73, 0x59, 0xc2, 0x87, 0x04, 0x4d, 0xde, 0x85, 0x29, 0x33, 0x63, 0x25, 0xf9, 0x94, + 0xb1, 0x05, 0x59, 0xa3, 0x64, 0x65, 0x53, 0x9b, 0x54, 0xbc, 0x3d, 0xd9, 0xff, 0xb8, 0xac, 0x5b, + 0x91, 0x1f, 0x9c, 0xcd, 0x91, 0x6f, 0x1d, 0x3a, 0xf2, 0xcd, 0x81, 0x37, 0x96, 0xff, 0xc0, 0x7b, + 0x1d, 0x4a, 0x6a, 0x59, 0x94, 0xda, 0xd4, 0x53, 0xa6, 0x9b, 0x36, 0x53, 0xc9, 0x18, 0x31, 0x63, + 0xba, 0xf0, 0x03, 0x70, 0x6c, 0x09, 0x57, 0xcb, 0xb5, 0x26, 0x43, 0xde, 0x82, 0xca, 0x3d, 0x3f, + 0xd8, 0xe9, 0xf8, 0x0e, 0x7f, 0x2a, 0x02, 0xf2, 0xf0, 0x0c, 0xd0, 0xd6, 0x6c, 0x11, 0x2b, 0x73, + 0x27, 0xa6, 0x8f, 0x26, 0x33, 0x52, 0x83, 0x99, 0xae, 0xeb, 0x21, 0x75, 0x5a, 0x3a, 0x3c, 0x72, + 0x5c, 0xa4, 0x69, 0x57, 0xba, 0xfd, 0x5a, 0x12, 0x8c, 0x69, 0x7c, 0x6e, 0x79, 0x0a, 0x12, 0xa6, + 0x0e, 0x99, 0x8b, 0x79, 0x7d, 0xf4, 0xc1, 0x98, 0x34, 0x9f, 0x88, 0x60, 0x91, 0x64, 0x39, 0xa6, + 0x78, 0x93, 0xcf, 0x43, 0x29, 0x54, 0x8f, 0x82, 0x16, 0x73, 0x3c, 0xf5, 0xe8, 0x87, 0x41, 0x75, + 0x57, 0xea, 0x97, 0x41, 0x35, 0x43, 0xb2, 0x0a, 0x17, 0x95, 0xed, 0x26, 0xf1, 0xbe, 0xe1, 0x44, + 0x9c, 0x4f, 0x0c, 0x33, 0xe0, 0x98, 0x59, 0x8b, 0xe9, 0xb6, 0x3c, 0x13, 0xac, 0xb8, 0x89, 0x35, + 0x2e, 0x2f, 0xf9, 0xfc, 0x6b, 0xa1, 0x84, 0x1e, 0x16, 0xfd, 0x5b, 0x1a, 0x21, 0xfa, 0xb7, 0x01, + 0x97, 0xd2, 0x20, 0x9e, 0x28, 0x8e, 0xe7, 0xa6, 0x33, 0xb6, 0xd0, 0xf5, 0x2c, 0x24, 0xcc, 0xae, + 0x4b, 0xee, 0x40, 0x39, 0xa0, 0xfc, 0x94, 0x57, 0x53, 0x4e, 0x6c, 0x27, 0x76, 0xd7, 0x45, 0x45, + 0x00, 0x63, 0x5a, 0xac, 0xdf, 0x9d, 0x64, 0xe2, 0xf4, 0xd7, 0x73, 0x7c, 0x35, 0x5c, 0xf6, 0xfd, + 0x90, 0x04, 0x8e, 0xf6, 0xbf, 0x99, 0x81, 0x73, 0x09, 0x03, 0x14, 0x79, 0x0a, 0x8a, 0x3c, 0x73, + 0x1e, 0x5f, 0xad, 0x4a, 0xf1, 0x8a, 0x2a, 0x1a, 0x47, 0xc0, 0xc8, 0x2f, 0x59, 0x30, 0xd3, 0x4b, + 0x5c, 0xe0, 0xa8, 0x85, 0x7c, 0x44, 0xab, 0x6d, 0xf2, 0x56, 0xc8, 0x78, 0x72, 0x24, 0xc9, 0x0c, + 0xd3, 0xdc, 0xd9, 0x7a, 0x20, 0x7d, 0xde, 0x3b, 0x34, 0xe0, 0xd8, 0x52, 0xd1, 0xd3, 0x24, 0x96, + 0x92, 0x60, 0x4c, 0xe3, 0xb3, 0x1e, 0xe6, 0x5f, 0x37, 0xca, 0xcb, 0xb0, 0x35, 0x45, 0x00, 0x63, + 0x5a, 0xe4, 0x15, 0x98, 0x96, 0xf9, 0xb2, 0xd7, 0xfd, 0xd6, 0x75, 0x27, 0xdc, 0x96, 0x47, 0x3e, + 0x7d, 0x44, 0x5d, 0x4a, 0x40, 0x31, 0x85, 0xcd, 0xbf, 0x2d, 0x4e, 0x4a, 0xce, 0x09, 0x4c, 0x24, + 0x5f, 0x64, 0x59, 0x4a, 0x82, 0x31, 0x8d, 0x4f, 0x9e, 0x35, 0xb6, 0x21, 0xe1, 0x1d, 0xa1, 0x57, + 0x83, 0x8c, 0xad, 0xa8, 0x06, 0x33, 0x7d, 0x7e, 0x42, 0x6e, 0x29, 0xa0, 0x9c, 0x8f, 0x9a, 0xe1, + 0xed, 0x24, 0x18, 0xd3, 0xf8, 0xe4, 0x65, 0x38, 0x17, 0xb0, 0xc5, 0x56, 0x13, 0x10, 0x2e, 0x13, + 0xfa, 0x46, 0x1c, 0x4d, 0x20, 0x26, 0x71, 0xc9, 0xab, 0x70, 0x3e, 0xce, 0xa9, 0xaa, 0x08, 0x08, + 0x1f, 0x0a, 0x9d, 0xe0, 0xaf, 0x96, 0x46, 0xc0, 0xc1, 0x3a, 0xe4, 0xaf, 0xc2, 0xac, 0xd1, 0x12, + 0x2b, 0x5e, 0x8b, 0xde, 0x97, 0x79, 0x2f, 0xf9, 0x0b, 0x63, 0x4b, 0x29, 0x18, 0x0e, 0x60, 0x93, + 0x8f, 0xc3, 0x74, 0xd3, 0xef, 0x74, 0xf8, 0x1a, 0x27, 0x5e, 0x03, 0x11, 0x09, 0x2e, 0x45, 0x2a, + 0xd0, 0x04, 0x04, 0x53, 0x98, 0xe4, 0x06, 0x10, 0x7f, 0x93, 0xa9, 0x57, 0xb4, 0xf5, 0x2a, 0xf5, + 0xa8, 0xd4, 0x38, 0xce, 0x25, 0x23, 0x6e, 0x6e, 0x0d, 0x60, 0x60, 0x46, 0x2d, 0x9e, 0x1f, 0xd0, + 0x88, 0x50, 0x9e, 0xce, 0x23, 0x23, 0x79, 0xda, 0x9e, 0x73, 0x64, 0x78, 0x72, 0x00, 0x13, 0x22, + 0x00, 0x2a, 0x9f, 0x4c, 0x97, 0xe6, 0xc3, 0x00, 0xf1, 0x1e, 0x21, 0x4a, 0x51, 0x72, 0x22, 0x3f, + 0x0f, 0xe5, 0x4d, 0xf5, 0x4a, 0x0c, 0x4f, 0x6f, 0x39, 0xf2, 0xbe, 0x98, 0x7a, 0xf0, 0x28, 0xb6, + 0x57, 0x68, 0x00, 0xc6, 0x2c, 0xc9, 0xd3, 0x50, 0xb9, 0xbe, 0x5e, 0xd3, 0xa3, 0xf0, 0x3c, 0xef, + 0xfd, 0x71, 0x56, 0x05, 0x4d, 0x00, 0x9b, 0x61, 0x5a, 0x7d, 0x23, 0x49, 0xb7, 0x80, 0x0c, 0x6d, + 0x8c, 0x61, 0x73, 0x3f, 0x07, 0x6c, 0xcc, 0x5d, 0x48, 0x61, 0xcb, 0x72, 0xd4, 0x18, 0xe4, 0x4d, + 0xa8, 0xc8, 0xfd, 0x82, 0xaf, 0x4d, 0x17, 0x4f, 0x17, 0xfd, 0x8e, 0x31, 0x09, 0x34, 0xe9, 0xf1, + 0x0b, 0x6a, 0xfe, 0x78, 0x06, 0xbd, 0xd6, 0xef, 0x74, 0xe6, 0x2e, 0xf1, 0x75, 0x33, 0xbe, 0xa0, + 0x8e, 0x41, 0x68, 0xe2, 0x91, 0xe7, 0x95, 0xbf, 0xda, 0xc3, 0x89, 0x1b, 0x7b, 0xed, 0xaf, 0xa6, + 0x95, 0xee, 0x21, 0x01, 0x32, 0x8f, 0x1c, 0xe1, 0x28, 0xb6, 0x09, 0xf3, 0x4a, 0xe3, 0x1b, 0x9c, + 0x24, 0x73, 0x73, 0x09, 0xdb, 0xd1, 0xfc, 0x9d, 0xa1, 0x98, 0x78, 0x08, 0x15, 0xb2, 0x09, 0x05, + 0xa7, 0xb3, 0x39, 0xf7, 0x68, 0x1e, 0xaa, 0x6b, 0x6d, 0xb5, 0x2e, 0x47, 0x14, 0x77, 0x6a, 0xad, + 0xad, 0xd6, 0x91, 0x11, 0x27, 0x2e, 0x8c, 0x3b, 0x9d, 0xcd, 0x70, 0x6e, 0x9e, 0xcf, 0xd9, 0xdc, + 0x98, 0xc4, 0xc6, 0x83, 0xd5, 0x7a, 0x88, 0x9c, 0x85, 0xfd, 0xc5, 0x31, 0x7d, 0x4b, 0xa4, 0x93, + 0x8d, 0xbf, 0x6d, 0x4e, 0x20, 0x71, 0xdc, 0xb9, 0x95, 0xdb, 0x04, 0x92, 0xea, 0xc5, 0xb9, 0xa1, + 0xd3, 0xa7, 0xa7, 0x97, 0x8c, 0x5c, 0xb2, 0x94, 0x25, 0x13, 0xa9, 0x8b, 0xd3, 0x73, 0x72, 0xc1, + 0xb0, 0xbf, 0x54, 0xd1, 0x56, 0xd0, 0x94, 0xaf, 0x57, 0x00, 0x45, 0x37, 0x8c, 0x5c, 0x3f, 0xc7, + 0xa0, 0xf0, 0x54, 0x06, 0x72, 0x1e, 0x73, 0xc2, 0x01, 0x28, 0x58, 0x31, 0x9e, 0x5e, 0xdb, 0xf5, + 0xee, 0xcb, 0xcf, 0x7f, 0x3d, 0x77, 0x27, 0x2e, 0xc1, 0x93, 0x03, 0x50, 0xb0, 0x22, 0x77, 0xc5, + 0xa0, 0x2e, 0xe4, 0xd1, 0xd7, 0xb5, 0xd5, 0x7a, 0x8a, 0x5f, 0x72, 0x70, 0xdf, 0x85, 0x42, 0xd8, + 0x75, 0xa5, 0xba, 0x34, 0x22, 0xaf, 0xc6, 0xda, 0x4a, 0x16, 0xaf, 0xc6, 0xda, 0x0a, 0x32, 0x26, + 0xe4, 0x2b, 0x16, 0x80, 0xd3, 0xdd, 0x74, 0xc2, 0xd0, 0x69, 0x69, 0xeb, 0xcc, 0x88, 0x8f, 0xac, + 0xd4, 0x34, 0xbd, 0x14, 0x6b, 0xee, 0xb6, 0x1c, 0x43, 0xd1, 0xe0, 0x4c, 0xde, 0x82, 0x49, 0x47, + 0xbc, 0x62, 0x29, 0x3d, 0xf0, 0xf3, 0x79, 0x9a, 0x35, 0x25, 0x01, 0x37, 0xd3, 0x48, 0x10, 0x2a, + 0x86, 0x8c, 0x77, 0x14, 0x38, 0x74, 0xcb, 0xdd, 0x91, 0xc6, 0xa1, 0xc6, 0xc8, 0xef, 0xac, 0x30, + 0x62, 0x59, 0xbc, 0x25, 0x08, 0x15, 0x43, 0xf2, 0x0b, 0x16, 0x9c, 0xeb, 0x3a, 0x9e, 0xa3, 0xe3, + 0x2a, 0xf3, 0x89, 0xbe, 0x35, 0x23, 0x35, 0x63, 0x0d, 0x71, 0xcd, 0x64, 0x84, 0x49, 0xbe, 0x64, + 0x17, 0x26, 0x1c, 0xfe, 0xbe, 0xae, 0x3c, 0x8a, 0x61, 0x1e, 0x6f, 0xf5, 0xa6, 0xda, 0x80, 0x2f, + 0x2e, 0xf2, 0x15, 0x5f, 0xc9, 0x8d, 0xfc, 0xba, 0x05, 0x93, 0xc2, 0x39, 0x9c, 0x29, 0xa4, 0xec, + 0xdb, 0x3f, 0x7b, 0x06, 0x2f, 0x19, 0x48, 0xc7, 0x75, 0xe9, 0x7e, 0xf4, 0x21, 0xed, 0xf9, 0x2a, + 0x4a, 0x0f, 0x75, 0x5d, 0x57, 0xd2, 0x31, 0xd5, 0xb7, 0xeb, 0xdc, 0x4f, 0xbc, 0xa2, 0x63, 0xaa, + 0xbe, 0x6b, 0x29, 0x18, 0x0e, 0x60, 0xcf, 0x7f, 0x1c, 0xa6, 0x4c, 0x39, 0x4e, 0xe4, 0xfe, 0xfe, + 0xa3, 0x02, 0x00, 0xef, 0x2a, 0x91, 0x8b, 0xa5, 0xcb, 0x13, 0x37, 0x6f, 0xfb, 0xad, 0x9c, 0x5e, + 0xf3, 0x34, 0x52, 0xaa, 0x80, 0xcc, 0xd2, 0xbc, 0xed, 0xb7, 0x50, 0x32, 0x21, 0x6d, 0x18, 0xef, + 0x39, 0xd1, 0x76, 0xfe, 0xf9, 0x5b, 0x4a, 0x22, 0x28, 0x39, 0xda, 0x46, 0xce, 0x80, 0xbc, 0x63, + 0xc5, 0x9e, 0x3d, 0x85, 0x3c, 0x72, 0xcf, 0xc6, 0x6d, 0xb6, 0x20, 0x7d, 0x79, 0x52, 0x29, 0x58, + 0xd3, 0x1e, 0x3e, 0xf3, 0xef, 0x5a, 0x30, 0x65, 0xa2, 0x66, 0x74, 0xd3, 0xcf, 0x99, 0xdd, 0x94, + 0x67, 0x7b, 0x98, 0x3d, 0xfe, 0xdf, 0x2c, 0x00, 0xec, 0x7b, 0x8d, 0x7e, 0xb7, 0xcb, 0xd4, 0x76, + 0xed, 0xe5, 0x6f, 0x1d, 0xdb, 0xcb, 0x7f, 0xec, 0x84, 0x5e, 0xfe, 0x85, 0x13, 0x79, 0xf9, 0x8f, + 0x9f, 0xdc, 0xcb, 0xbf, 0x38, 0xdc, 0xcb, 0xdf, 0xfe, 0xa6, 0x05, 0xe7, 0x07, 0xf6, 0x2b, 0xa6, + 0x49, 0x07, 0xbe, 0x1f, 0x0d, 0xf1, 0x10, 0xc5, 0x18, 0x84, 0x26, 0x1e, 0x59, 0x86, 0x59, 0xf9, + 0x4c, 0x49, 0xa3, 0xd7, 0x71, 0x33, 0x73, 0xeb, 0x6c, 0xa4, 0xe0, 0x38, 0x50, 0xc3, 0xfe, 0x6d, + 0x0b, 0x2a, 0x46, 0x44, 0x3e, 0xfb, 0x0e, 0xee, 0x26, 0x2c, 0xc5, 0x88, 0x5f, 0x68, 0xe1, 0x57, + 0x5d, 0x02, 0x26, 0xae, 0xa1, 0xdb, 0x46, 0x12, 0xfb, 0xf8, 0x1a, 0x9a, 0x95, 0xa2, 0x84, 0x8a, + 0xf4, 0xe4, 0xb4, 0xc7, 0x1b, 0xbd, 0x60, 0xa6, 0x27, 0xa7, 0x3d, 0xe4, 0x10, 0xce, 0x8e, 0x1d, + 0x29, 0xa4, 0x07, 0xb0, 0xf1, 0x20, 0x8c, 0x13, 0x44, 0x28, 0x60, 0xe4, 0x09, 0x28, 0x50, 0xaf, + 0x25, 0xed, 0x1f, 0xfa, 0xf5, 0xda, 0xab, 0x5e, 0x0b, 0x59, 0xb9, 0x7d, 0x0b, 0xa6, 0x84, 0xf7, + 0xf3, 0x6b, 0x74, 0xef, 0xd8, 0xcf, 0xe1, 0xb2, 0xd1, 0x9e, 0x7a, 0x0e, 0x97, 0x55, 0x67, 0xe5, + 0xf6, 0x3f, 0xb2, 0x20, 0xf5, 0x46, 0x92, 0x71, 0x03, 0x63, 0x0d, 0xbd, 0x81, 0x31, 0xad, 0xf6, + 0x63, 0x87, 0x5a, 0xed, 0x6f, 0x00, 0xe9, 0xb2, 0xa9, 0x90, 0x5c, 0x68, 0x0b, 0xc9, 0xa7, 0x24, + 0xd6, 0x06, 0x30, 0x30, 0xa3, 0x96, 0xfd, 0x0f, 0x85, 0xb0, 0xe6, 0xab, 0x49, 0x47, 0x37, 0x40, + 0x1f, 0x8a, 0x9c, 0x94, 0xb4, 0xbf, 0x8d, 0x68, 0xbb, 0x1e, 0xcc, 0xa3, 0x15, 0x77, 0xa4, 0x9c, + 0xf2, 0x9c, 0x9b, 0xfd, 0xfb, 0x42, 0x56, 0xf3, 0x59, 0xa5, 0xa3, 0x65, 0xed, 0x26, 0x65, 0xbd, + 0x9e, 0xd7, 0x5a, 0x99, 0x2d, 0x23, 0x59, 0x00, 0xe8, 0xd1, 0xa0, 0x49, 0xbd, 0x48, 0xc5, 0x25, + 0x15, 0x65, 0x84, 0xac, 0x2e, 0x45, 0x03, 0xc3, 0xfe, 0x06, 0x9b, 0x40, 0xf1, 0x43, 0xd1, 0xe4, + 0x4a, 0xda, 0xd5, 0x35, 0x3d, 0x39, 0xb4, 0xa7, 0xab, 0x11, 0xad, 0x32, 0x76, 0x44, 0xb4, 0xca, + 0x33, 0x30, 0x19, 0xf8, 0x1d, 0x5a, 0x0b, 0xbc, 0xb4, 0x8f, 0x0e, 0xb2, 0x62, 0xbc, 0x89, 0x0a, + 0x6e, 0xff, 0xaa, 0x05, 0xb3, 0xe9, 0x70, 0xba, 0xdc, 0xfd, 0x6f, 0xcd, 0x98, 0xff, 0xc2, 0xc9, + 0x63, 0xfe, 0xed, 0x7f, 0x37, 0x0e, 0xb3, 0xe9, 0x07, 0xec, 0x18, 0x67, 0x97, 0x1b, 0xdb, 0x52, + 0xab, 0xbf, 0xb0, 0xb2, 0x09, 0x98, 0x1e, 0x2f, 0x63, 0x43, 0xc7, 0xcb, 0x35, 0x28, 0xfb, 0x3d, + 0x75, 0xe0, 0x17, 0xc2, 0x5d, 0x51, 0xc6, 0x9a, 0x5b, 0x0a, 0xf0, 0xde, 0x7e, 0xf5, 0x42, 0x2c, + 0x80, 0x2e, 0xc6, 0xb8, 0x2a, 0xf9, 0x69, 0x65, 0xa9, 0x18, 0x4f, 0x64, 0xd1, 0xd1, 0x96, 0x8a, + 0x99, 0xb8, 0xfe, 0x30, 0x63, 0x45, 0xf1, 0x24, 0xd9, 0x3c, 0x26, 0x72, 0xcc, 0xe6, 0x71, 0x07, + 0xca, 0xd2, 0xb6, 0x7a, 0xaa, 0x2c, 0x16, 0x9c, 0xf0, 0x6d, 0x45, 0x00, 0x63, 0x5a, 0xa9, 0x34, + 0x21, 0xa5, 0x5c, 0xd3, 0x84, 0xbc, 0xa2, 0xdd, 0xc1, 0xca, 0x71, 0x2c, 0x82, 0x76, 0x05, 0x3b, + 0x24, 0x16, 0x41, 0x7a, 0xbb, 0xbe, 0xc3, 0x46, 0x7e, 0xe4, 0x36, 0x77, 0x5c, 0x4f, 0xe4, 0x5e, + 0x60, 0xd3, 0xf1, 0x19, 0x98, 0xa4, 0xf2, 0x15, 0x65, 0x71, 0x37, 0xa1, 0x7b, 0x43, 0x3d, 0x9e, + 0xac, 0xe0, 0xa4, 0x06, 0x33, 0xea, 0x46, 0x56, 0x5d, 0x28, 0x89, 0x9c, 0x31, 0xda, 0x80, 0xbd, + 0x9c, 0x04, 0x63, 0x1a, 0xdf, 0xfe, 0x02, 0x54, 0x0c, 0x4d, 0x87, 0x2b, 0x05, 0xf7, 0x9d, 0x66, + 0x94, 0xde, 0x4c, 0xaf, 0xb2, 0x42, 0x14, 0x30, 0x7e, 0xef, 0x25, 0x42, 0xc8, 0x52, 0x9b, 0xa9, + 0x0c, 0x1c, 0x93, 0x50, 0x46, 0x2c, 0xa0, 0x6d, 0x7a, 0x5f, 0x3d, 0x5c, 0xa1, 0x88, 0x21, 0x2b, + 0x44, 0x01, 0xb3, 0x9f, 0x85, 0x92, 0xca, 0xec, 0xc5, 0xd3, 0xe3, 0xa8, 0x3b, 0x19, 0x33, 0x3d, + 0x8e, 0x1f, 0x44, 0xc8, 0x21, 0xf6, 0x1b, 0x50, 0x52, 0x09, 0xc8, 0x8e, 0xc6, 0x66, 0xfb, 0x5b, + 0xe8, 0xb9, 0xd7, 0xfd, 0x30, 0x52, 0x59, 0xd3, 0xc4, 0xb5, 0xf1, 0xcd, 0x15, 0x5e, 0x86, 0x1a, + 0x6a, 0xff, 0xa9, 0x05, 0x95, 0x8d, 0x8d, 0x55, 0x6d, 0x4d, 0x42, 0x78, 0x38, 0x14, 0x2d, 0x54, + 0xdb, 0x8a, 0xa8, 0xe9, 0x9f, 0x22, 0xa6, 0xfa, 0xfc, 0xc1, 0x7e, 0xf5, 0xe1, 0x46, 0x26, 0x06, + 0x0e, 0xa9, 0x49, 0x56, 0xe0, 0x82, 0x09, 0x91, 0xd9, 0x2c, 0xe4, 0xc6, 0xcb, 0x9f, 0xdd, 0x6e, + 0x0c, 0x82, 0x31, 0xab, 0x4e, 0x9a, 0x94, 0xd4, 0x21, 0xcd, 0x17, 0xbc, 0x1b, 0x83, 0x60, 0xcc, + 0xaa, 0x63, 0x3f, 0x0f, 0x33, 0x29, 0xc7, 0x89, 0x63, 0x64, 0x11, 0xfa, 0x9d, 0x02, 0x4c, 0x99, + 0xf7, 0xe7, 0xc7, 0xd8, 0x14, 0x8f, 0xaf, 0x6b, 0x64, 0xdc, 0x79, 0x17, 0x4e, 0x78, 0xe7, 0x6d, + 0x3a, 0x19, 0x8c, 0x9f, 0xad, 0x93, 0x41, 0x31, 0x1f, 0x27, 0x03, 0xc3, 0x19, 0x66, 0xe2, 0xc1, + 0x39, 0xc3, 0xfc, 0x56, 0x11, 0xa6, 0x93, 0x69, 0x69, 0x8f, 0xd1, 0x93, 0xcf, 0x0e, 0xf4, 0xe4, + 0x09, 0x2f, 0xd9, 0x0a, 0xa3, 0x5e, 0xb2, 0x8d, 0x8f, 0x7a, 0xc9, 0x56, 0x3c, 0xc5, 0x25, 0xdb, + 0xe0, 0x15, 0xd9, 0xc4, 0xb1, 0xaf, 0xc8, 0x3e, 0xa1, 0x37, 0x8a, 0xc9, 0x84, 0x5f, 0x59, 0xbc, + 0x59, 0x90, 0x64, 0x37, 0x2c, 0xf9, 0xad, 0x4c, 0x7f, 0xe7, 0xd2, 0x11, 0xfb, 0x73, 0x90, 0xe9, + 0xe6, 0x7b, 0xf2, 0x7b, 0xfc, 0x87, 0x4f, 0xe0, 0xe2, 0xfb, 0x22, 0x54, 0xe4, 0x78, 0xe2, 0x27, + 0x3a, 0x48, 0x9e, 0x06, 0x1b, 0x31, 0x08, 0x4d, 0x3c, 0x36, 0x30, 0x7a, 0xf1, 0x04, 0xe1, 0xd7, + 0xbd, 0x95, 0xe4, 0x75, 0xef, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xfb, 0xf3, 0x70, 0x29, 0xd3, 0xae, + 0xc7, 0xef, 0x54, 0xf8, 0x61, 0x83, 0xb6, 0x24, 0x82, 0x21, 0x46, 0xea, 0xb5, 0x9a, 0xf9, 0x3b, + 0x43, 0x31, 0xf1, 0x10, 0x2a, 0xf6, 0x6f, 0x16, 0x60, 0x3a, 0xf9, 0x7a, 0x33, 0xb9, 0xa7, 0x6f, + 0x01, 0x72, 0xb9, 0x80, 0x10, 0x64, 0x8d, 0x54, 0xa7, 0x43, 0x6f, 0x0f, 0xef, 0xf1, 0xf1, 0xb5, + 0xa9, 0xf3, 0xae, 0x9e, 0x1d, 0x63, 0x79, 0x6d, 0x27, 0xd9, 0xf1, 0x37, 0x90, 0xe3, 0xa8, 0x68, + 0x69, 0x1c, 0xca, 0x9d, 0x7b, 0x1c, 0xdd, 0xab, 0x59, 0xa1, 0xc1, 0x96, 0xed, 0x2d, 0xbb, 0x34, + 0x70, 0xb7, 0x5c, 0xda, 0x92, 0x69, 0xf0, 0xf9, 0xca, 0xfd, 0x86, 0x2c, 0x43, 0x0d, 0xb5, 0xdf, + 0x19, 0x83, 0x32, 0x4f, 0xe2, 0x76, 0x2d, 0xf0, 0xbb, 0xfc, 0x5d, 0xcf, 0xd0, 0x38, 0x88, 0xcb, + 0x6e, 0xbb, 0x31, 0xea, 0x53, 0xbd, 0x31, 0x45, 0x19, 0x43, 0x61, 0x94, 0x60, 0x82, 0x23, 0xe9, + 0x41, 0x69, 0x4b, 0x26, 0x9d, 0x96, 0x7d, 0x37, 0x62, 0xe2, 0x54, 0x95, 0xc2, 0x5a, 0x34, 0x81, + 0xfa, 0x87, 0x9a, 0x8b, 0xed, 0xc0, 0x4c, 0x2a, 0x0b, 0x4f, 0xee, 0xa9, 0xaa, 0xff, 0xe7, 0x38, + 0x94, 0x75, 0xf0, 0x1e, 0xf9, 0x58, 0xc2, 0x2a, 0x5a, 0xae, 0xff, 0x84, 0xf1, 0xe8, 0xdc, 0xb6, + 0xdf, 0x62, 0x07, 0x13, 0x8d, 0x9c, 0xb2, 0x70, 0x3e, 0x01, 0x85, 0x7e, 0xd0, 0x49, 0x9b, 0x3d, + 0x6e, 0xe3, 0x2a, 0xb2, 0x72, 0x33, 0xe0, 0xb0, 0xf0, 0x40, 0x03, 0x0e, 0xd9, 0x2e, 0xb9, 0xe9, + 0xb7, 0xf6, 0xd2, 0x8f, 0xd4, 0xd5, 0xfd, 0xd6, 0x1e, 0x72, 0x08, 0x79, 0x05, 0xa6, 0x65, 0x14, + 0xa5, 0x52, 0x62, 0x8a, 0x5c, 0x4f, 0xd5, 0xde, 0x30, 0x1b, 0x09, 0x28, 0xa6, 0xb0, 0xd9, 0x2e, + 0xcb, 0x8e, 0x0d, 0x3c, 0x01, 0xf9, 0x44, 0xf2, 0xea, 0xfc, 0x46, 0xe3, 0xd6, 0x4d, 0x6e, 0x9d, + 0xd5, 0x18, 0x89, 0x40, 0xcd, 0xc9, 0x23, 0x03, 0x35, 0x97, 0x05, 0x6d, 0x26, 0x2d, 0xdf, 0x51, + 0xa6, 0xea, 0x57, 0x14, 0x5d, 0x56, 0x76, 0xe8, 0xd9, 0x45, 0xd7, 0xcc, 0x0a, 0x69, 0x2d, 0xbf, + 0x7f, 0x21, 0xad, 0xf6, 0x6d, 0x98, 0x49, 0xf5, 0x9f, 0xb2, 0x9a, 0x59, 0xd9, 0x56, 0xb3, 0xe3, + 0x3d, 0x73, 0xf7, 0x4f, 0x2d, 0x38, 0x3f, 0xb0, 0x22, 0x1d, 0x37, 0xb6, 0x38, 0xbd, 0x37, 0x8e, + 0x9d, 0x7e, 0x6f, 0x2c, 0x9c, 0x6c, 0x6f, 0xac, 0x6f, 0x7e, 0xef, 0x87, 0x97, 0x1f, 0xfa, 0xfe, + 0x0f, 0x2f, 0x3f, 0xf4, 0x07, 0x3f, 0xbc, 0xfc, 0xd0, 0x3b, 0x07, 0x97, 0xad, 0xef, 0x1d, 0x5c, + 0xb6, 0xbe, 0x7f, 0x70, 0xd9, 0xfa, 0x83, 0x83, 0xcb, 0xd6, 0x7f, 0x3e, 0xb8, 0x6c, 0x7d, 0xf3, + 0x8f, 0x2f, 0x3f, 0xf4, 0xa9, 0x4f, 0xc4, 0x3d, 0xb5, 0xa8, 0x7a, 0x8a, 0xff, 0xf8, 0xb0, 0xea, + 0x97, 0xc5, 0xde, 0x4e, 0x7b, 0x91, 0xf5, 0xd4, 0xa2, 0x2e, 0x51, 0x3d, 0xf5, 0x7f, 0x03, 0x00, + 0x00, 0xff, 0xff, 0x91, 0x6c, 0x1b, 0x38, 0xb0, 0xaa, 0x00, 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -9871,7 +9872,7 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Status) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status))) i-- - dAtA[i] = 0x42 + dAtA[i] = 0x4a } if m.FinishedAt != nil { { @@ -9883,6 +9884,18 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x42 + } + if m.UpdatedAt != nil { + { + size, err := m.UpdatedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0x3a } if m.StartedAt != nil { @@ -12802,6 +12815,10 @@ func (m *StepPluginStatus) Size() (n int) { l = m.StartedAt.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.UpdatedAt != nil { + l = m.UpdatedAt.Size() + n += 1 + l + sovGenerated(uint64(l)) + } if m.FinishedAt != nil { l = m.FinishedAt.Size() n += 1 + l + sovGenerated(uint64(l)) @@ -14732,6 +14749,7 @@ func (this *StepPluginStatus) String() string { `Phase:` + fmt.Sprintf("%v", this.Phase) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`, `StartedAt:` + strings.Replace(fmt.Sprintf("%v", this.StartedAt), "Time", "v1.Time", 1) + `,`, + `UpdatedAt:` + strings.Replace(fmt.Sprintf("%v", this.UpdatedAt), "Time", "v1.Time", 1) + `,`, `FinishedAt:` + strings.Replace(fmt.Sprintf("%v", this.FinishedAt), "Time", "v1.Time", 1) + `,`, `Status:` + valueToStringGenerated(this.Status) + `,`, `}`, @@ -33880,6 +33898,42 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedAt", 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.UpdatedAt == nil { + m.UpdatedAt = &v1.Time{} + } + if err := m.UpdatedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field FinishedAt", wireType) } @@ -33915,7 +33969,7 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 8: + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index a2d6087480..705b09eab0 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1767,12 +1767,14 @@ message StepPluginStatus { optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 6; - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 7; + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time updatedAt = 7; + + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 8; // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - optional bytes status = 8; + optional bytes status = 9; } message StickinessConfig { diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 0a4d78538f..1c49558220 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -1052,7 +1052,7 @@ type StepPluginStatus struct { // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,8,opt,name=status"` + Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,9,opt,name=status"` } // StepPluginPhase is the overall phase of a StepPlugin diff --git a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go index e59b93341a..3246ae513e 100644 --- a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go @@ -2779,6 +2779,10 @@ func (in *StepPluginStatus) DeepCopyInto(out *StepPluginStatus) { in, out := &in.StartedAt, &out.StartedAt *out = (*in).DeepCopy() } + if in.UpdatedAt != nil { + in, out := &in.UpdatedAt, &out.UpdatedAt + *out = (*in).DeepCopy() + } if in.FinishedAt != nil { in, out := &in.FinishedAt, &out.FinishedAt *out = (*in).DeepCopy() diff --git a/ui/src/models/rollout/generated/api.ts b/ui/src/models/rollout/generated/api.ts index c86ec12c90..157b02b45c 100755 --- a/ui/src/models/rollout/generated/api.ts +++ b/ui/src/models/rollout/generated/api.ts @@ -2831,6 +2831,12 @@ export interface GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginS * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus */ startedAt?: K8sIoApimachineryPkgApisMetaV1Time; + /** + * + * @type {K8sIoApimachineryPkgApisMetaV1Time} + * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus + */ + updatedAt?: K8sIoApimachineryPkgApisMetaV1Time; /** * * @type {K8sIoApimachineryPkgApisMetaV1Time} From 0cc4d71d7a12675d0f8ab794554c064e77f5b5e1 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 19 Apr 2024 12:52:17 -0400 Subject: [PATCH 21/41] add disabled rollout Signed-off-by: Alexandre Gaudreault --- Makefile | 1 + metricproviders/plugin/client/client.go | 3 +- .../rollouts/v1alpha1/openapi_generated.go | 5 ++ pkg/apis/rollouts/v1alpha1/types.go | 10 +-- rollout/canary.go | 2 +- rollout/stepplugin.go | 41 +++++++--- rollout/stepplugin_test.go | 2 +- rollout/steps/plugin/client/client.go | 3 +- rollout/steps/plugin/plugin.go | 42 ++++++---- rollout/steps/plugin/resolver.go | 30 ++++++++ .../trafficrouting/plugin/client/client.go | 3 +- test/e2e/step-plugin/disabled-rollout.yaml | 31 ++++++++ test/e2e/step-plugin/invalid-rollout.yaml | 26 +++++++ test/e2e/step_plugin_test.go | 76 ++++++++++++++----- utils/config/config.go | 59 +++++++++----- utils/plugin/plugin.go | 30 ++++---- utils/plugin/types/types.go | 9 +++ 17 files changed, 286 insertions(+), 87 deletions(-) create mode 100644 test/e2e/step-plugin/disabled-rollout.yaml create mode 100644 test/e2e/step-plugin/invalid-rollout.yaml diff --git a/Makefile b/Makefile index e6b2c62753..1c7be23848 100644 --- a/Makefile +++ b/Makefile @@ -244,6 +244,7 @@ test-kustomize: ## run kustomize tests step-plugin-e2e-setup: @rm -rf plugin-bin @go build -gcflags="all=-N -l" -o plugin-bin/e2e-step-plugin test/cmd/step-plugin-e2e/main.go + @kubectl apply --context='${E2E_K8S_CONTEXT}' -f manifests/crds/rollout-crd.yaml @kubectl apply --context='${E2E_K8S_CONTEXT}' -n argo-rollouts -f test/e2e/step-plugin/argo-rollouts-config.yaml step-plugin-e2e-run: diff --git a/metricproviders/plugin/client/client.go b/metricproviders/plugin/client/client.go index 9fc82ed244..d37e949d8e 100644 --- a/metricproviders/plugin/client/client.go +++ b/metricproviders/plugin/client/client.go @@ -8,6 +8,7 @@ import ( "github.com/argoproj/argo-rollouts/metricproviders/plugin/rpc" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/utils/plugin" + "github.com/argoproj/argo-rollouts/utils/plugin/types" goPlugin "github.com/hashicorp/go-plugin" ) @@ -54,7 +55,7 @@ func (m *metricPlugin) startPluginSystem(metric v1alpha1.Metric) (rpc.MetricProv // There should only ever be one plugin defined in metric.Provider.Plugin per analysis template this gets checked // during validation for pluginName := range metric.Provider.Plugin { - pluginPath, args, err := plugin.GetPluginInfo(pluginName) + pluginPath, args, err := plugin.GetPluginInfo(pluginName, types.PluginTypeMetricProvider) if err != nil { return nil, fmt.Errorf("unable to find plugin (%s): %w", pluginName, err) } diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index a0c5c93955..3d6dd3e2df 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -5221,6 +5221,11 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, + "updatedAt": { + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, "finishedAt": { SchemaProps: spec.SchemaProps{ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 1c49558220..af3b49b205 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -650,8 +650,6 @@ type PluginStep struct { // +kubebuilder:validation:Type=object // Config the configuration object for the specified plugin Config json.RawMessage `json:"config,omitempty" protobuf:"bytes,2,opt,name=config"` - - // json.RawMessage `json:"config,omitempty" protobuf:"bytes,2,opt,name=config"` } type SetMirrorRoute struct { @@ -1042,17 +1040,19 @@ type RolloutAnalysisRunStatus struct { type StepPluginStatus struct { Index int32 `json:"index" protobuf:"bytes,1,name=index"` Name string `json:"name" protobuf:"bytes,2,name=name"` - Operation StepPluginOperation `json:"operation" protobuf:"bytes,3,name=operation"` - Phase StepPluginPhase `json:"phase" protobuf:"bytes,4,name=phase"` + Operation StepPluginOperation `json:"operation" protobuf:"bytes,3,name=operation,casttype=StepPluginOperation"` + Phase StepPluginPhase `json:"phase" protobuf:"bytes,4,name=phase,casttype=StepPluginPhase"` Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,6,name=startedAt"` UpdatedAt *metav1.Time `json:"updatedAt,omitempty" protobuf:"bytes,7,opt,name=updatedAt"` FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,8,opt,name=finishedAt"` + Backoff DurationString `json:"backoff,omitempty" protobuf:"bytes,9,opt,name=backoff,casttype=DurationString"` + Executions int32 `json:"executions,omitempty" protobuf:"varint,10,opt,name=executions"` // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,9,opt,name=status"` + Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,11,opt,name=status"` } // StepPluginPhase is the overall phase of a StepPlugin diff --git a/rollout/canary.go b/rollout/canary.go index a9a2cd162d..d6635ee8bb 100644 --- a/rollout/canary.go +++ b/rollout/canary.go @@ -350,7 +350,7 @@ func (c *rolloutContext) completedCurrentCanaryStep() bool { case currentStep.SetMirrorRoute != nil: return true case currentStep.Plugin != nil: - return c.isStepPluginCompleted(*currentStepIndex) + return c.isStepPluginCompleted(*currentStepIndex, currentStep.Plugin) } return false } diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 71cccfc94c..4fc8c2231d 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -85,7 +85,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if err != nil { return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) } - status, result, err := stepPlugin.Run(c.rollout) + status, err := stepPlugin.Run(c.rollout) if err != nil { return fmt.Errorf("failed to run plugin: %w", err) } @@ -95,14 +95,14 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } - if status.Phase == v1alpha1.StepPluginPhaseRunning && result != nil && result.RequeueAfter != nil { - c.enqueueRolloutAfter(c.rollout, *result.RequeueAfter) - return nil - } - - if status.Phase == v1alpha1.StepPluginPhaseError { - // It could be interesting to implement a backoff mechanism - c.enqueueRolloutAfter(c.rollout, 30*time.Second) + if status.Phase == v1alpha1.StepPluginPhaseRunning || status.Phase == v1alpha1.StepPluginPhaseError { + duration, err := status.Backoff.Duration() + if err != nil { + return fmt.Errorf("failed to parse backoff duration: %w", err) + } + // Add a little delay to make sure we reconcile after the backoff + duration += 5 * time.Second + c.enqueueRolloutAfter(c.rollout, duration) return nil } @@ -121,7 +121,22 @@ func (c *rolloutContext) calculateStepPluginStatus() []v1alpha1.StepPluginStatus return c.stepPluginStatuses } -func (c *rolloutContext) isStepPluginCompleted(stepIndex int32) bool { +func (c *rolloutContext) isStepPluginDisabled(stepIndex int32, step *v1alpha1.PluginStep) (bool, error) { + stepPlugin, err := c.stepPluginResolver.Resolve(stepIndex, *step, c.log) + if err != nil { + return false, err + } + return !stepPlugin.Enabled(), nil +} + +func (c *rolloutContext) isStepPluginCompleted(stepIndex int32, step *v1alpha1.PluginStep) bool { + disabled, err := c.isStepPluginDisabled(stepIndex, step) + if err != nil { + // If there is an error, the plugin might not exist in the config. We do + c.log.Errorf("cannot resolve step plugin %s at index %d. Assuming it is enabled.", step.Name, stepIndex) + disabled = false + } + updatedPluginStatus := c.calculateStepPluginStatus() runStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationRun) isRunning := runStatus != nil && runStatus.Phase == v1alpha1.StepPluginPhaseRunning @@ -130,7 +145,11 @@ func (c *rolloutContext) isStepPluginCompleted(stepIndex int32) bool { abortStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationAbort) isRunning = terminateStatus == nil && abortStatus == nil } - return runStatus != nil && ((!isRunning && runStatus.Phase == v1alpha1.StepPluginPhaseRunning) || runStatus.Phase == v1alpha1.StepPluginPhaseFailed || runStatus.Phase == v1alpha1.StepPluginPhaseSuccessful) + return disabled || + (runStatus != nil && + ((!isRunning && runStatus.Phase == v1alpha1.StepPluginPhaseRunning) || + runStatus.Phase == v1alpha1.StepPluginPhaseFailed || + runStatus.Phase == v1alpha1.StepPluginPhaseSuccessful)) } func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index 295f2d6e78..ebe3542b91 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -490,7 +490,7 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := newRolloutContext(tt.statuses) - if got := c.isStepPluginCompleted(tt.index); got != tt.want { + if got := c.isStepPluginCompleted(tt.index, c.rollout.Spec.Strategy.Canary.Steps[tt.index].Plugin); got != tt.want { t.Errorf("rolloutContext.isStepPluginCompleted() = %v, want %v", got, tt.want) } }) diff --git a/rollout/steps/plugin/client/client.go b/rollout/steps/plugin/client/client.go index 78fc745c12..584f9bbd19 100644 --- a/rollout/steps/plugin/client/client.go +++ b/rollout/steps/plugin/client/client.go @@ -7,6 +7,7 @@ import ( "github.com/argoproj/argo-rollouts/rollout/steps/plugin/rpc" "github.com/argoproj/argo-rollouts/utils/plugin" + "github.com/argoproj/argo-rollouts/utils/plugin/types" goPlugin "github.com/hashicorp/go-plugin" ) @@ -52,7 +53,7 @@ func (t *stepPlugin) startPlugin(pluginName string) (rpc.StepPlugin, error) { if t.client[pluginName] == nil || t.client[pluginName].Exited() { - pluginPath, args, err := plugin.GetPluginInfo(pluginName) + pluginPath, args, err := plugin.GetPluginInfo(pluginName, types.PluginTypeStep) if err != nil { return nil, fmt.Errorf("unable to find plugin (%s): %w", pluginName, err) } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index a5d93d09e5..4a03a7eb6a 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -20,14 +20,11 @@ type stepPlugin struct { log *log.Entry } -type StepResult struct { - RequeueAfter *time.Duration -} - type StepPlugin interface { - Run(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *StepResult, error) + Run(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) Terminate(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) Abort(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) + Enabled() bool } var ( @@ -36,9 +33,7 @@ var ( ) // Run exectues a plugin -func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *StepResult, error) { - result := &StepResult{} - +func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) if stepStatus == nil { now := metatime.MetaNow() @@ -50,25 +45,39 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, Phase: v1alpha1.StepPluginPhaseRunning, } } + if stepStatus.Phase == v1alpha1.StepPluginPhaseSuccessful || stepStatus.Phase == v1alpha1.StepPluginPhaseFailed { - return nil, nil, nil + return nil, nil + } + + if stepStatus.Executions > 0 { + backoff, err := stepStatus.Backoff.Duration() + if err != nil { + return nil, fmt.Errorf("could not parse backoff duration: %w", err) + } + if stepStatus.UpdatedAt.Add(backoff).After(metatime.Now()) { + return nil, nil + } } resp, err := p.rpc.Run(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() + stepStatus.Backoff = "" stepStatus.UpdatedAt = &finishedAt + stepStatus.Executions++ if err.HasError() { p.log.Errorf("error during plugin execution") stepStatus.Phase = v1alpha1.StepPluginPhaseError stepStatus.Message = err.Error() - return stepStatus, result, nil + stepStatus.Backoff = v1alpha1.DurationString(30 * time.Second) + return stepStatus, nil } stepStatus.Message = resp.Message if resp.Phase != "" { stepStatus.Phase = v1alpha1.StepPluginPhase(resp.Phase) if err := stepStatus.Phase.Validate(); err != nil { - return nil, nil, fmt.Errorf("could not validate rpc phase: %w", err) + return nil, fmt.Errorf("could not validate rpc phase: %w", err) } } @@ -82,13 +91,14 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, } if stepStatus.Phase == v1alpha1.StepPluginPhaseRunning { - result.RequeueAfter = &defaultRequeuDuration + backoff := defaultRequeuDuration if resp.RequeueAfter > minRequeueDuration { - result.RequeueAfter = &resp.RequeueAfter + backoff = resp.RequeueAfter } + stepStatus.Backoff = v1alpha1.DurationString(backoff.String()) } - return stepStatus, result, nil + return stepStatus, nil } func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { @@ -187,6 +197,10 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu return abortStatus, nil } +func (p *stepPlugin) Enabled() bool { + return true +} + func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { for _, s := range rollout.Status.Canary.StepPluginStatuses { if s.Index == p.index && s.Name == p.name && s.Operation == operation { diff --git a/rollout/steps/plugin/resolver.go b/rollout/steps/plugin/resolver.go index cb6a717072..17c1b3891a 100644 --- a/rollout/steps/plugin/resolver.go +++ b/rollout/steps/plugin/resolver.go @@ -5,10 +5,31 @@ import ( "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/client" + "github.com/argoproj/argo-rollouts/utils/config" + "github.com/argoproj/argo-rollouts/utils/plugin/types" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) +type disabledStepPlugin struct { +} + +func (p *disabledStepPlugin) Run(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, nil +} + +func (p *disabledStepPlugin) Terminate(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, nil +} + +func (p *disabledStepPlugin) Abort(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, nil +} + +func (p *disabledStepPlugin) Enabled() bool { + return false +} + type resolver struct { } @@ -21,6 +42,15 @@ func NewResolver() Resolver { } func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep, log *log.Entry) (StepPlugin, error) { + if config, err := config.GetConfig(); err != nil { + return nil, fmt.Errorf("could not get config: %w", err) + } else { + plugin := config.GetPlugin(plugin.Name, types.PluginTypeStep) + if plugin != nil && plugin.Disabled { + return &disabledStepPlugin{}, nil + } + } + pluginClient, err := client.GetPlugin(plugin.Name) if err != nil { return nil, fmt.Errorf("failed to get step plugin %s: %w", plugin.Name, err) diff --git a/rollout/trafficrouting/plugin/client/client.go b/rollout/trafficrouting/plugin/client/client.go index a9a8b0b713..05ec1bc169 100644 --- a/rollout/trafficrouting/plugin/client/client.go +++ b/rollout/trafficrouting/plugin/client/client.go @@ -7,6 +7,7 @@ import ( "github.com/argoproj/argo-rollouts/rollout/trafficrouting/plugin/rpc" "github.com/argoproj/argo-rollouts/utils/plugin" + "github.com/argoproj/argo-rollouts/utils/plugin/types" goPlugin "github.com/hashicorp/go-plugin" ) @@ -52,7 +53,7 @@ func (t *trafficPlugin) startPlugin(pluginName string) (rpc.TrafficRouterPlugin, if t.pluginClient[pluginName] == nil || t.pluginClient[pluginName].Exited() { - pluginPath, args, err := plugin.GetPluginInfo(pluginName) + pluginPath, args, err := plugin.GetPluginInfo(pluginName, types.PluginTypeTrafficRouter) if err != nil { return nil, fmt.Errorf("unable to find plugin (%s): %w", pluginName, err) } diff --git a/test/e2e/step-plugin/disabled-rollout.yaml b/test/e2e/step-plugin/disabled-rollout.yaml new file mode 100644 index 0000000000..3ebc15c679 --- /dev/null +++ b/test/e2e/step-plugin/disabled-rollout.yaml @@ -0,0 +1,31 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: disabled-step-plugin +spec: + selector: + matchLabels: + app: disabled-step-plugin + strategy: + canary: + steps: + - plugin: + name: $$disabled_plugin$$ + config: + return: Successful + - plugin: + name: step/e2e-test + config: + return: Successful + template: + metadata: + labels: + app: disabled-step-plugin + spec: + containers: + - name: basic + image: nginx:1.19-alpine + resources: + requests: + memory: 16Mi + cpu: 1m diff --git a/test/e2e/step-plugin/invalid-rollout.yaml b/test/e2e/step-plugin/invalid-rollout.yaml new file mode 100644 index 0000000000..df75248db1 --- /dev/null +++ b/test/e2e/step-plugin/invalid-rollout.yaml @@ -0,0 +1,26 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: invalid-step-plugin +spec: + progressDeadlineSeconds: 15 + selector: + matchLabels: + app: invalid-step-plugin + strategy: + canary: + steps: + - plugin: + name: step/e2e-test-invalid-name + template: + metadata: + labels: + app: invalid-step-plugin + spec: + containers: + - name: basic + image: nginx:1.19-alpine + resources: + requests: + memory: 16Mi + cpu: 1m diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index 077c2e5acc..5766822af5 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -19,7 +19,6 @@ import ( const E2EStepPluginName = "step/e2e-test" const E2EStepPluginNameDisabled = "step/e2e-test-disabled" -const E2EStepPluginNameInvalid = "step/e2e-test-invalid" type StepPluginSuite struct { fixtures.E2ESuite @@ -63,8 +62,10 @@ func IsStepPluginConfigured(c *fixtures.Common, config *corev1.ConfigMap) bool { func (s *StepPluginSuite) TestRolloutCompletesWhenStepSuccessful() { s.Given(). RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "successful", "$$phase$$": string(types.PhaseSuccessful)}). - When().ApplyManifests().WaitForRolloutStatus("Healthy"). - UpdateSpec().WaitForRolloutStatus("Healthy").Then(). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Healthy"). + Then(). ExpectStableRevision("2"). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() @@ -81,8 +82,10 @@ func (s *StepPluginSuite) TestRolloutCompletesWhenStepSuccessful() { func (s *StepPluginSuite) TestRolloutAbortWhenStepFails() { s.Given(). RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "failed", "$$phase$$": string(types.PhaseFailed)}). - When().ApplyManifests().WaitForRolloutStatus("Healthy"). - UpdateSpec().WaitForRolloutStatus("Degraded").Then(). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Degraded"). + Then(). ExpectStableRevision("1"). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() @@ -106,12 +109,12 @@ func (s *StepPluginSuite) TestRolloutAbortWhenStepFails() { func (s *StepPluginSuite) TestRolloutAbortStepsWhenAborted() { s.Given(). RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "aborted", "$$phase$$": string(types.PhaseRunning)}). - When().ApplyManifests().WaitForRolloutStatus("Healthy"). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). UpdateSpec().WaitForRolloutStatus("Progressing"). WaitForRolloutCanaryStepIndex(1). WaitForRolloutStepPluginRunning(). - AbortRollout(). - WaitForRolloutStatus("Degraded"). + AbortRollout().WaitForRolloutStatus("Degraded"). Then(). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() @@ -141,12 +144,12 @@ func (s *StepPluginSuite) TestRolloutAbortStepsWhenAborted() { func (s *StepPluginSuite) TestRolloutCompletesWhenPromotedAndStepRunning() { s.Given(). RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "full-promotion", "$$phase$$": string(types.PhaseRunning)}). - When().ApplyManifests().WaitForRolloutStatus("Healthy"). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). UpdateSpec().WaitForRolloutStatus("Progressing"). WaitForRolloutCanaryStepIndex(1). WaitForRolloutStepPluginRunning(). - PromoteRolloutFull(). - WaitForRolloutStatus("Healthy"). + PromoteRolloutFull().WaitForRolloutStatus("Healthy"). Then(). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() @@ -177,8 +180,8 @@ spec: WaitForRolloutCanaryStepIndex(1). WaitForRolloutStepPluginRunning(). Wait(20 * time.Second). + WaitForRolloutStatus("Degraded"). Then(). - ExpectRolloutStatus("Degraded"). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() assert.EqualValues(s.T(), 1, *rollout.Status.CurrentStepIndex) @@ -203,8 +206,8 @@ spec: progressDeadlineSeconds: 15`). UpdateSpec().WaitForRolloutStatus("Progressing"). Wait(20 * time.Second). + WaitForRolloutStatus("Degraded"). Then(). - ExpectRolloutStatus("Degraded"). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() assert.EqualValues(s.T(), 1, *rollout.Status.CurrentStepIndex) @@ -224,10 +227,10 @@ spec: func (s *StepPluginSuite) TestRolloutStatusIsNotUsedOnNewRollout() { s.Given(). RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "run-again", "$$phase$$": string(types.PhaseSuccessful)}). - When().ApplyManifests().WaitForRolloutStatus("Healthy"). - UpdateSpec().WaitForRolloutStatus("Healthy").Then(). - ExpectStableRevision("2"). - When().UpdateSpec(` + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Healthy").Then().ExpectStableRevision("2").When(). + UpdateSpec(` spec: strategy: canary: @@ -236,7 +239,8 @@ spec: name: step/e2e-test config: return: Successful`). - UpdateSpec().WaitForRolloutStatus("Healthy").Then(). + UpdateSpec().WaitForRolloutStatus("Healthy"). + Then(). ExpectStableRevision("3"). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() @@ -249,3 +253,39 @@ spec: assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) }) } + +func (s *StepPluginSuite) TestRolloutErrorWhenStepPluginNotConfigured() { + s.Given(). + RolloutObjects("@step-plugin/invalid-rollout.yaml"). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Degraded"). + Then(). + ExpectStableRevision("1"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 0, *rollout.Status.CurrentStepIndex) + assert.EqualValues(s.T(), 0, len(rollout.Status.Canary.StepPluginStatuses)) + // Should really have some error returned to the user... + }) +} + +func (s *StepPluginSuite) TestRolloutSkipPluginWhenDisabled() { + s.Given(). + RolloutTemplate("@step-plugin/disabled-rollout.yaml", map[string]string{"$$disabled_plugin$$": E2EStepPluginNameDisabled}). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Healthy"). + Then(). + ExpectStableRevision("2"). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.EqualValues(s.T(), 1, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[0] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + }) +} diff --git a/utils/config/config.go b/utils/config/config.go index 310ca64680..3eb9a1f86f 100644 --- a/utils/config/config.go +++ b/utils/config/config.go @@ -21,10 +21,11 @@ import ( type Config struct { configMap *v1.ConfigMap plugins []types.PluginItem + lock *sync.RWMutex } var configMemoryCache *Config -var mutex sync.RWMutex +var mutex = &sync.RWMutex{} // Regex to match plugin names, this matches github username and repo limits var re = regexp.MustCompile(`^([a-zA-Z0-9\-]+)\/{1}([a-zA-Z0-9_\-.]+)$`) @@ -35,7 +36,9 @@ func InitializeConfig(k8sClientset kubernetes.Interface, configMapName string) ( configMapCluster, err := k8sClientset.CoreV1().ConfigMaps(defaults.Namespace()).Get(context.Background(), configMapName, metav1.GetOptions{}) if err != nil { if k8errors.IsNotFound(err) { - configMemoryCache = &Config{} // We create an empty config so that we don't try to initialize again + configMemoryCache = &Config{ + lock: &sync.RWMutex{}, + } // We create an empty config so that we don't try to initialize again // If the configmap is not found, we return return configMemoryCache, nil } @@ -46,21 +49,31 @@ func InitializeConfig(k8sClientset kubernetes.Interface, configMapName string) ( if err = yaml.Unmarshal([]byte(configMapCluster.Data["trafficRouterPlugins"]), &trafficRouterPlugins); err != nil { return nil, fmt.Errorf("failed to unmarshal traffic router plugins while initializing: %w", err) } + for i := range trafficRouterPlugins { + trafficRouterPlugins[i].Type = types.PluginTypeTrafficRouter + } var metricProviderPlugins []types.PluginItem if err = yaml.Unmarshal([]byte(configMapCluster.Data["metricProviderPlugins"]), &metricProviderPlugins); err != nil { return nil, fmt.Errorf("failed to unmarshal metric provider plugins while initializing: %w", err) } + for i := range metricProviderPlugins { + metricProviderPlugins[i].Type = types.PluginTypeMetricProvider + } var stepPlugins []types.PluginItem if err = yaml.Unmarshal([]byte(configMapCluster.Data["stepPlugins"]), &stepPlugins); err != nil { return nil, fmt.Errorf("failed to unmarshal step plugins while initializing: %w", err) } + for i := range stepPlugins { + stepPlugins[i].Type = types.PluginTypeStep + } mutex.Lock() configMemoryCache = &Config{ configMap: configMapCluster, plugins: slices.Concat(trafficRouterPlugins, metricProviderPlugins, stepPlugins), + lock: &sync.RWMutex{}, } mutex.Unlock() @@ -76,6 +89,7 @@ func InitializeConfig(k8sClientset kubernetes.Interface, configMapName string) ( func GetConfig() (*Config, error) { mutex.RLock() defer mutex.RUnlock() + if configMemoryCache == nil { return nil, fmt.Errorf("config not initialized, please initialize before use") } @@ -91,12 +105,30 @@ func UnInitializeConfig() { // GetAllPlugins returns a flattened list of plugin items. This is useful for iterating over all plugins. func (c *Config) GetAllPlugins() []types.PluginItem { - mutex.RLock() - defer mutex.RUnlock() + c.lock.RLock() + defer c.lock.RUnlock() + // Return a copy of the slice + return append([]types.PluginItem{}, c.plugins...) +} - var copiedPlugins []types.PluginItem - copiedPlugins = append(copiedPlugins, configMemoryCache.plugins...) - return copiedPlugins +// GetPlugin returns the plugin item by name and type if it exists +func (c *Config) GetPlugin(name string, pluginType types.PluginType) *types.PluginItem { + for _, plugin := range c.GetAllPlugins() { + if plugin.Name == name && plugin.Type == pluginType { + return &plugin + } + } + return nil +} + +func (c *Config) ValidateConfig() error { + for _, pluginItem := range c.GetAllPlugins() { + matches := re.FindAllStringSubmatch(pluginItem.Name, -1) + if len(matches) != 1 || len(matches[0]) != 3 { + return fmt.Errorf("plugin repository (%s) must be in the format of /", pluginItem.Name) + } + } + return nil } // GetPluginDirectoryAndFilename this functions return the directory and file name from a given pluginName such as @@ -111,16 +143,3 @@ func GetPluginDirectoryAndFilename(pluginName string) (directory string, filenam return namespace, plugin, nil } - -func (c *Config) ValidateConfig() error { - mutex.RLock() - defer mutex.RUnlock() - - for _, pluginItem := range c.GetAllPlugins() { - matches := re.FindAllStringSubmatch(pluginItem.Name, -1) - if len(matches) != 1 || len(matches[0]) != 3 { - return fmt.Errorf("plugin repository (%s) must be in the format of /", pluginItem.Name) - } - } - return nil -} diff --git a/utils/plugin/plugin.go b/utils/plugin/plugin.go index 3fd7a013a0..a76ed5e942 100644 --- a/utils/plugin/plugin.go +++ b/utils/plugin/plugin.go @@ -5,30 +5,32 @@ import ( "path/filepath" "github.com/argoproj/argo-rollouts/utils/defaults" + "github.com/argoproj/argo-rollouts/utils/plugin/types" "github.com/argoproj/argo-rollouts/utils/config" ) // GetPluginInfo returns the location & command arguments of the plugin on the filesystem via plugin name. If the plugin is not // configured in the configmap, an error is returned. -func GetPluginInfo(pluginName string) (string, []string, error) { +func GetPluginInfo(pluginName string, pluginType types.PluginType) (string, []string, error) { configMap, err := config.GetConfig() if err != nil { return "", nil, fmt.Errorf("failed to get config: %w", err) } - for _, item := range configMap.GetAllPlugins() { - if pluginName == item.Name { - dir, filename, err := config.GetPluginDirectoryAndFilename(item.Name) - if err != nil { - return "", nil, err - } - absFilePath, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, dir, filename)) - if err != nil { - return "", nil, fmt.Errorf("failed to get absolute path of plugin folder: %w", err) - } - return absFilePath, item.Args, nil - } + plugin := configMap.GetPlugin(pluginName, pluginType) + if plugin == nil { + return "", nil, fmt.Errorf("plugin %s not configured in configmap", pluginName) } - return "", nil, fmt.Errorf("plugin %s not configured in configmap", pluginName) + + dir, filename, err := config.GetPluginDirectoryAndFilename(plugin.Name) + if err != nil { + return "", nil, err + } + absFilePath, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, dir, filename)) + if err != nil { + return "", nil, fmt.Errorf("failed to get absolute path of plugin folder: %w", err) + } + return absFilePath, plugin.Args, nil + } diff --git a/utils/plugin/types/types.go b/utils/plugin/types/types.go index d6a92e7f19..3b16d75a46 100644 --- a/utils/plugin/types/types.go +++ b/utils/plugin/types/types.go @@ -110,11 +110,20 @@ type StepPlugins struct { Steps []PluginItem `json:"stepPlugins" yaml:"stepPlugins"` } +type PluginType string + +const ( + PluginTypeMetricProvider PluginType = "MetricProvider" + PluginTypeTrafficRouter PluginType = "TrafficRouter" + PluginTypeStep PluginType = "Step" +) + type PluginItem struct { Name string `json:"name" yaml:"name"` Location string `json:"location" yaml:"location"` Sha256 string `json:"sha256" yaml:"sha256"` Disabled bool `json:"disabled" yaml:"disabled"` + Type PluginType // Args holds command line arguments Args []string `json:"args" yaml:"args"` From c007efac4a575e004c633fa3a4b6ef13eac228fe Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 19 Apr 2024 13:00:19 -0400 Subject: [PATCH 22/41] codegen Signed-off-by: Alexandre Gaudreault --- manifests/crds/rollout-crd.yaml | 5 + manifests/install.yaml | 5 + pkg/apiclient/rollout/rollout.swagger.json | 7 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 1167 +++++++++++--------- pkg/apis/rollouts/v1alpha1/generated.proto | 6 +- rollout/steps/plugin/mocks/StepPlugin.go | 43 +- ui/src/models/rollout/generated/api.ts | 12 + 7 files changed, 677 insertions(+), 568 deletions(-) diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index 0e5646b673..110cc2c337 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -3730,6 +3730,11 @@ spec: stepPluginStatuses: items: properties: + backoff: + type: string + executions: + format: int32 + type: integer finishedAt: format: date-time type: string diff --git a/manifests/install.yaml b/manifests/install.yaml index ea40be19ae..2dae9c8969 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -16220,6 +16220,11 @@ spec: stepPluginStatuses: items: properties: + backoff: + type: string + executions: + format: int32 + type: integer finishedAt: format: date-time type: string diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index fb0336fe08..9cdec0184b 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -2552,6 +2552,13 @@ "finishedAt": { "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" }, + "backoff": { + "type": "string" + }, + "executions": { + "type": "integer", + "format": "int32" + }, "status": { "type": "string", "format": "byte", diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index dfcab4177a..fcbb2559f0 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -3407,555 +3407,558 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 8763 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x6c, 0x64, 0xd7, - 0x75, 0x98, 0x1e, 0x87, 0x43, 0xce, 0x9c, 0xe1, 0x92, 0xdc, 0xbb, 0xbb, 0x12, 0x45, 0x49, 0x3b, - 0xca, 0x53, 0xaa, 0xae, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, - 0x72, 0x45, 0xee, 0x52, 0x67, 0xb8, 0xda, 0xf8, 0x43, 0x89, 0x1f, 0x67, 0x2e, 0x87, 0x6f, 0x39, - 0xf3, 0xde, 0xf8, 0xbd, 0x37, 0xdc, 0xa5, 0x2c, 0xc4, 0xb2, 0x0d, 0x39, 0x8e, 0x6b, 0x23, 0x6e, - 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0xe9, 0x8f, 0x22, 0x70, 0xd1, 0xfe, 0x08, - 0xd0, 0xa0, 0x6e, 0x0a, 0x07, 0x68, 0x0a, 0xa7, 0x40, 0xeb, 0xb4, 0x40, 0x98, 0x9a, 0xe9, 0x9f, - 0x06, 0x2d, 0x8c, 0x16, 0x2e, 0x82, 0xea, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, - 0x9a, 0xc7, 0x95, 0xd2, 0xe6, 0xdf, 0xcc, 0x3d, 0xe7, 0x9e, 0x73, 0xde, 0xfd, 0x3c, 0xf7, 0xdc, - 0x73, 0xce, 0x85, 0xd5, 0xb6, 0x1b, 0x6d, 0xf7, 0x37, 0x17, 0x9a, 0x7e, 0x77, 0xd1, 0x09, 0xda, - 0x7e, 0x2f, 0xf0, 0xef, 0xf2, 0x1f, 0x1f, 0x0e, 0xfc, 0x4e, 0xc7, 0xef, 0x47, 0xe1, 0x62, 0x6f, - 0xa7, 0xbd, 0xe8, 0xf4, 0xdc, 0x70, 0x51, 0x97, 0xec, 0x7e, 0xd4, 0xe9, 0xf4, 0xb6, 0x9d, 0x8f, - 0x2e, 0xb6, 0xa9, 0x47, 0x03, 0x27, 0xa2, 0xad, 0x85, 0x5e, 0xe0, 0x47, 0x3e, 0xf9, 0x44, 0x4c, - 0x6d, 0x41, 0x51, 0xe3, 0x3f, 0x7e, 0x4e, 0xd5, 0x5d, 0xe8, 0xed, 0xb4, 0x17, 0x18, 0xb5, 0x05, - 0x5d, 0xa2, 0xa8, 0xcd, 0x7f, 0xd8, 0x90, 0xa5, 0xed, 0xb7, 0xfd, 0x45, 0x4e, 0x74, 0xb3, 0xbf, - 0xc5, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x60, 0x36, 0xff, 0xd4, 0xce, 0x4b, 0xe1, 0x82, 0xeb, 0x33, - 0xd9, 0x16, 0x37, 0x9d, 0xa8, 0xb9, 0xbd, 0xb8, 0x3b, 0x20, 0xd1, 0xbc, 0x6d, 0x20, 0x35, 0xfd, - 0x80, 0x66, 0xe1, 0xbc, 0x10, 0xe3, 0x74, 0x9d, 0xe6, 0xb6, 0xeb, 0xd1, 0x60, 0x2f, 0xfe, 0xea, - 0x2e, 0x8d, 0x9c, 0xac, 0x5a, 0x8b, 0xc3, 0x6a, 0x05, 0x7d, 0x2f, 0x72, 0xbb, 0x74, 0xa0, 0xc2, - 0x4f, 0x1f, 0x55, 0x21, 0x6c, 0x6e, 0xd3, 0xae, 0x33, 0x50, 0xef, 0xf9, 0x61, 0xf5, 0xfa, 0x91, - 0xdb, 0x59, 0x74, 0xbd, 0x28, 0x8c, 0x82, 0x74, 0x25, 0xfb, 0x47, 0x05, 0x28, 0xd7, 0x56, 0xeb, - 0x8d, 0xc8, 0x89, 0xfa, 0x21, 0xf9, 0x8a, 0x05, 0x53, 0x1d, 0xdf, 0x69, 0xd5, 0x9d, 0x8e, 0xe3, - 0x35, 0x69, 0x30, 0x67, 0x3d, 0x69, 0x5d, 0xa9, 0x3c, 0xb7, 0xba, 0x30, 0x4a, 0x7f, 0x2d, 0xd4, - 0xee, 0x85, 0x48, 0x43, 0xbf, 0x1f, 0x34, 0x29, 0xd2, 0xad, 0xfa, 0xc5, 0xef, 0xed, 0x57, 0x1f, - 0x3a, 0xd8, 0xaf, 0x4e, 0xad, 0x1a, 0x9c, 0x30, 0xc1, 0x97, 0x7c, 0xcb, 0x82, 0xf3, 0x4d, 0xc7, - 0x73, 0x82, 0xbd, 0x0d, 0x27, 0x68, 0xd3, 0xe8, 0xd5, 0xc0, 0xef, 0xf7, 0xe6, 0xc6, 0xce, 0x40, - 0x9a, 0x47, 0xa5, 0x34, 0xe7, 0x97, 0xd2, 0xec, 0x70, 0x50, 0x02, 0x2e, 0x57, 0x18, 0x39, 0x9b, - 0x1d, 0x6a, 0xca, 0x55, 0x38, 0x4b, 0xb9, 0x1a, 0x69, 0x76, 0x38, 0x28, 0x01, 0x79, 0x06, 0x26, - 0x5d, 0xaf, 0x1d, 0xd0, 0x30, 0x9c, 0x1b, 0x7f, 0xd2, 0xba, 0x52, 0xae, 0xcf, 0xc8, 0xea, 0x93, - 0x2b, 0xa2, 0x18, 0x15, 0xdc, 0xfe, 0xcd, 0x02, 0x9c, 0xaf, 0xad, 0xd6, 0x37, 0x02, 0x67, 0x6b, - 0xcb, 0x6d, 0xa2, 0xdf, 0x8f, 0x5c, 0xaf, 0x6d, 0x12, 0xb0, 0x0e, 0x27, 0x40, 0x5e, 0x84, 0x4a, - 0x48, 0x83, 0x5d, 0xb7, 0x49, 0xd7, 0xfd, 0x20, 0xe2, 0x9d, 0x52, 0xac, 0x5f, 0x90, 0xe8, 0x95, - 0x46, 0x0c, 0x42, 0x13, 0x8f, 0x55, 0x0b, 0x7c, 0x3f, 0x92, 0x70, 0xde, 0x66, 0xe5, 0xb8, 0x1a, - 0xc6, 0x20, 0x34, 0xf1, 0xc8, 0x32, 0xcc, 0x3a, 0x9e, 0xe7, 0x47, 0x4e, 0xe4, 0xfa, 0xde, 0x7a, - 0x40, 0xb7, 0xdc, 0xfb, 0xf2, 0x13, 0xe7, 0x64, 0xdd, 0xd9, 0x5a, 0x0a, 0x8e, 0x03, 0x35, 0xc8, - 0x37, 0x2d, 0x98, 0x0d, 0x23, 0xb7, 0xb9, 0xe3, 0x7a, 0x34, 0x0c, 0x97, 0x7c, 0x6f, 0xcb, 0x6d, - 0xcf, 0x15, 0x79, 0xb7, 0xdd, 0x1c, 0xad, 0xdb, 0x1a, 0x29, 0xaa, 0xf5, 0x8b, 0x4c, 0xa4, 0x74, - 0x29, 0x0e, 0x70, 0x27, 0x1f, 0x82, 0xb2, 0x6c, 0x51, 0x1a, 0xce, 0x4d, 0x3c, 0x59, 0xb8, 0x52, - 0xae, 0x9f, 0x3b, 0xd8, 0xaf, 0x96, 0x57, 0x54, 0x21, 0xc6, 0x70, 0x7b, 0x19, 0xe6, 0x6a, 0xdd, - 0x4d, 0x27, 0x0c, 0x9d, 0x96, 0x1f, 0xa4, 0xba, 0xee, 0x0a, 0x94, 0xba, 0x4e, 0xaf, 0xe7, 0x7a, - 0x6d, 0xd6, 0x77, 0x8c, 0xce, 0xd4, 0xc1, 0x7e, 0xb5, 0xb4, 0x26, 0xcb, 0x50, 0x43, 0xed, 0xff, - 0x38, 0x06, 0x95, 0x9a, 0xe7, 0x74, 0xf6, 0x42, 0x37, 0xc4, 0xbe, 0x47, 0x3e, 0x0b, 0x25, 0xb6, - 0x6a, 0xb5, 0x9c, 0xc8, 0x91, 0x33, 0xfd, 0x23, 0x0b, 0x62, 0x11, 0x59, 0x30, 0x17, 0x91, 0xf8, - 0xf3, 0x19, 0xf6, 0xc2, 0xee, 0x47, 0x17, 0x6e, 0x6d, 0xde, 0xa5, 0xcd, 0x68, 0x8d, 0x46, 0x4e, - 0x9d, 0xc8, 0x5e, 0x80, 0xb8, 0x0c, 0x35, 0x55, 0xe2, 0xc3, 0x78, 0xd8, 0xa3, 0x4d, 0x39, 0x73, - 0xd7, 0x46, 0x9c, 0x21, 0xb1, 0xe8, 0x8d, 0x1e, 0x6d, 0xd6, 0xa7, 0x24, 0xeb, 0x71, 0xf6, 0x0f, - 0x39, 0x23, 0x72, 0x0f, 0x26, 0x42, 0xbe, 0x96, 0xc9, 0x49, 0x79, 0x2b, 0x3f, 0x96, 0x9c, 0x6c, - 0x7d, 0x5a, 0x32, 0x9d, 0x10, 0xff, 0x51, 0xb2, 0xb3, 0xff, 0x93, 0x05, 0x17, 0x0c, 0xec, 0x5a, - 0xd0, 0xee, 0x77, 0xa9, 0x17, 0x91, 0x27, 0x61, 0xdc, 0x73, 0xba, 0x54, 0xce, 0x2a, 0x2d, 0xf2, - 0x4d, 0xa7, 0x4b, 0x91, 0x43, 0xc8, 0x53, 0x50, 0xdc, 0x75, 0x3a, 0x7d, 0xca, 0x1b, 0xa9, 0x5c, - 0x3f, 0x27, 0x51, 0x8a, 0x6f, 0xb0, 0x42, 0x14, 0x30, 0xf2, 0x36, 0x94, 0xf9, 0x8f, 0x6b, 0x81, - 0xdf, 0xcd, 0xe9, 0xd3, 0xa4, 0x84, 0x6f, 0x28, 0xb2, 0x62, 0xf8, 0xe9, 0xbf, 0x18, 0x33, 0xb4, - 0xff, 0xc8, 0x82, 0x19, 0xe3, 0xe3, 0x56, 0xdd, 0x30, 0x22, 0x9f, 0x19, 0x18, 0x3c, 0x0b, 0xc7, - 0x1b, 0x3c, 0xac, 0x36, 0x1f, 0x3a, 0xb3, 0xf2, 0x4b, 0x4b, 0xaa, 0xc4, 0x18, 0x38, 0x1e, 0x14, - 0xdd, 0x88, 0x76, 0xc3, 0xb9, 0xb1, 0x27, 0x0b, 0x57, 0x2a, 0xcf, 0xad, 0xe4, 0xd6, 0x8d, 0x71, - 0xfb, 0xae, 0x30, 0xfa, 0x28, 0xd8, 0xd8, 0xdf, 0x29, 0x24, 0xba, 0x6f, 0x4d, 0xc9, 0xf1, 0xae, - 0x05, 0x13, 0x1d, 0x67, 0x93, 0x76, 0xc4, 0xdc, 0xaa, 0x3c, 0xf7, 0x66, 0x6e, 0x92, 0x28, 0x1e, - 0x0b, 0xab, 0x9c, 0xfe, 0x55, 0x2f, 0x0a, 0xf6, 0xe2, 0xe1, 0x25, 0x0a, 0x51, 0x32, 0x27, 0x7f, - 0xcb, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, - 0x25, 0xda, 0x80, 0xa0, 0x29, 0xcb, 0xfc, 0xc7, 0xa0, 0x62, 0x7c, 0x02, 0x99, 0x85, 0xc2, 0x0e, - 0xdd, 0x13, 0x03, 0x1e, 0xd9, 0x4f, 0x72, 0x31, 0x31, 0xc2, 0xe5, 0x90, 0xfe, 0xf8, 0xd8, 0x4b, - 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x29, 0x26, 0x06, 0x26, 0x5b, - 0x08, 0x88, 0x0f, 0x93, 0x5d, 0x1a, 0x05, 0x6e, 0x53, 0x75, 0xd9, 0xf2, 0x68, 0xad, 0xb4, 0xc6, - 0x89, 0xc5, 0x1b, 0xa2, 0xf8, 0x1f, 0xa2, 0xe2, 0x42, 0xb6, 0x61, 0xdc, 0x09, 0xda, 0xaa, 0x4f, - 0xae, 0xe5, 0x33, 0x2d, 0xe3, 0xa5, 0xa2, 0x16, 0xb4, 0x43, 0xe4, 0x1c, 0xc8, 0x22, 0x94, 0x23, - 0x1a, 0x74, 0x5d, 0xcf, 0x89, 0xc4, 0x0e, 0x5a, 0xaa, 0x9f, 0x97, 0x68, 0xe5, 0x0d, 0x05, 0xc0, - 0x18, 0x87, 0x74, 0x60, 0xa2, 0x15, 0xec, 0x61, 0xdf, 0x9b, 0x1b, 0xcf, 0xa3, 0x29, 0x96, 0x39, - 0xad, 0x78, 0x90, 0x8a, 0xff, 0x28, 0x79, 0x90, 0x5f, 0xb3, 0xe0, 0x62, 0x97, 0x3a, 0x61, 0x3f, - 0xa0, 0xec, 0x13, 0x90, 0x46, 0xd4, 0x63, 0x1d, 0x3b, 0x57, 0xe4, 0xcc, 0x71, 0xd4, 0x7e, 0x18, - 0xa4, 0x5c, 0x7f, 0x5c, 0x8a, 0x72, 0x31, 0x0b, 0x8a, 0x99, 0xd2, 0x90, 0xb7, 0xa1, 0x12, 0x45, - 0x9d, 0x46, 0xc4, 0xf4, 0xe0, 0xf6, 0xde, 0xdc, 0x04, 0x5f, 0xbc, 0x46, 0x5c, 0x61, 0x36, 0x36, - 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x5e, 0x84, 0xf3, - 0x03, 0xdb, 0x0a, 0x79, 0x01, 0x8a, 0xbd, 0x6d, 0x27, 0x54, 0xfb, 0xc4, 0x65, 0xb5, 0x48, 0xad, - 0xb3, 0xc2, 0xf7, 0xf6, 0xab, 0xe7, 0x54, 0x15, 0x5e, 0x80, 0x02, 0x99, 0x69, 0x6d, 0x5d, 0x1a, - 0x86, 0x4e, 0x5b, 0x6d, 0x1e, 0xc6, 0x20, 0xe5, 0xc5, 0xa8, 0xe0, 0xe4, 0x17, 0x2c, 0x38, 0x27, - 0x06, 0x2c, 0xd2, 0xb0, 0xdf, 0x89, 0xd8, 0x06, 0xc9, 0x3a, 0xe5, 0x46, 0x1e, 0x93, 0x43, 0x90, - 0xac, 0x5f, 0x92, 0xdc, 0xcf, 0x99, 0xa5, 0x21, 0x26, 0xf9, 0x92, 0x3b, 0x50, 0x0e, 0x23, 0x27, - 0x88, 0x68, 0xab, 0x16, 0x71, 0x55, 0xae, 0xf2, 0xdc, 0x4f, 0x1d, 0x6f, 0xe7, 0xd8, 0x70, 0xbb, - 0x54, 0xec, 0x52, 0x0d, 0x45, 0x00, 0x63, 0x5a, 0xe4, 0x6d, 0x80, 0xa0, 0xef, 0x35, 0xfa, 0xdd, - 0xae, 0x13, 0xec, 0x49, 0xed, 0xee, 0xfa, 0x68, 0x9f, 0x87, 0x9a, 0x5e, 0xac, 0xe8, 0xc4, 0x65, - 0x68, 0xf0, 0x23, 0x5f, 0xb4, 0xe0, 0x9c, 0x98, 0x07, 0x4a, 0x82, 0x89, 0x9c, 0x25, 0x38, 0xcf, - 0x9a, 0x76, 0xd9, 0x64, 0x81, 0x49, 0x8e, 0xe4, 0x4d, 0xa8, 0x34, 0xfd, 0x6e, 0xaf, 0x43, 0x45, - 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0xf7, 0x49, - 0x1d, 0x47, 0x0d, 0x69, 0xf2, 0x69, 0x78, 0x34, 0xec, 0x37, 0x9b, 0x34, 0x0c, 0xb7, 0xfa, 0x1d, - 0xec, 0x7b, 0xd7, 0xdd, 0x30, 0xf2, 0x83, 0xbd, 0x55, 0xb7, 0xeb, 0x46, 0x7c, 0x40, 0x17, 0xeb, - 0x4f, 0x1c, 0xec, 0x57, 0x1f, 0x6d, 0x0c, 0x43, 0xc2, 0xe1, 0xf5, 0x89, 0x03, 0x8f, 0xf5, 0xbd, - 0xe1, 0xe4, 0xc5, 0xf1, 0xa3, 0x7a, 0xb0, 0x5f, 0x7d, 0xec, 0xf6, 0x70, 0x34, 0x3c, 0x8c, 0x86, - 0xfd, 0x27, 0x16, 0xdb, 0x86, 0xc4, 0x77, 0x6d, 0xd0, 0x6e, 0xaf, 0xc3, 0x96, 0xce, 0xb3, 0x57, - 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0x5f, 0x2d, - 0xb8, 0x98, 0x46, 0x7e, 0x00, 0x0a, 0x5d, 0x98, 0x54, 0xe8, 0x6e, 0xe6, 0xfb, 0xb5, 0x43, 0xb4, - 0xba, 0x5f, 0x34, 0x06, 0xac, 0x42, 0x45, 0xba, 0x45, 0x5e, 0x82, 0xa9, 0x48, 0xfe, 0xbd, 0x19, - 0x2b, 0xe7, 0xda, 0x30, 0xb1, 0x61, 0xc0, 0x30, 0x81, 0xc9, 0x6a, 0x36, 0x3b, 0xfd, 0x30, 0xa2, - 0x41, 0xa3, 0xe9, 0xf7, 0xc4, 0xb2, 0x5b, 0x8a, 0x6b, 0x2e, 0x19, 0x30, 0x4c, 0x60, 0xda, 0x7f, - 0xad, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, - 0x0f, 0x94, 0xfa, 0xf1, 0x25, 0x8b, 0x69, 0x71, 0x62, 0x00, 0x84, 0x52, 0x35, 0x7a, 0x3d, 0xdf, - 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x60, 0x1c, 0xa6, 0x6a, - 0x5e, 0xe4, 0xd6, 0xb6, 0xb6, 0x5c, 0xcf, 0x8d, 0xf6, 0xc8, 0xd7, 0xc7, 0x60, 0xb1, 0x17, 0xd0, - 0x2d, 0x1a, 0x04, 0xb4, 0xb5, 0xdc, 0x0f, 0x5c, 0xaf, 0xdd, 0x68, 0x6e, 0xd3, 0x56, 0xbf, 0xe3, - 0x7a, 0xed, 0x95, 0xb6, 0xe7, 0xeb, 0xe2, 0xab, 0xf7, 0x69, 0xb3, 0xcf, 0xdb, 0x55, 0xac, 0x12, - 0xdd, 0xd1, 0x64, 0x5f, 0x3f, 0x19, 0xd3, 0xfa, 0xf3, 0x07, 0xfb, 0xd5, 0xc5, 0x13, 0x56, 0xc2, - 0x93, 0x7e, 0x1a, 0xf9, 0xea, 0x18, 0x2c, 0x04, 0xf4, 0x73, 0x7d, 0xf7, 0xf8, 0xad, 0x21, 0x96, - 0xf1, 0xce, 0x88, 0xdb, 0xfd, 0x89, 0x78, 0xd6, 0x9f, 0x3b, 0xd8, 0xaf, 0x9e, 0xb0, 0x0e, 0x9e, - 0xf0, 0xbb, 0xec, 0x75, 0xa8, 0xd4, 0x7a, 0x6e, 0xe8, 0xde, 0x47, 0xbf, 0x1f, 0xd1, 0x63, 0x18, - 0x34, 0xaa, 0x50, 0x0c, 0xfa, 0x1d, 0x2a, 0x16, 0x98, 0x72, 0xbd, 0xcc, 0x96, 0x65, 0x64, 0x05, - 0x28, 0xca, 0xed, 0x2f, 0xb1, 0x2d, 0x88, 0x93, 0x4c, 0x99, 0xb2, 0xee, 0x42, 0x31, 0x60, 0x4c, - 0xe4, 0xc8, 0x1a, 0xf5, 0xd4, 0x1f, 0x4b, 0x2d, 0x85, 0x60, 0x3f, 0x51, 0xb0, 0xb0, 0xbf, 0x3b, - 0x06, 0x97, 0x6a, 0xbd, 0xde, 0x1a, 0x0d, 0xb7, 0x53, 0x52, 0xfc, 0x92, 0x05, 0xd3, 0xbb, 0x6e, - 0x10, 0xf5, 0x9d, 0x8e, 0xb2, 0x56, 0x0a, 0x79, 0x1a, 0xa3, 0xca, 0xc3, 0xb9, 0xbd, 0x91, 0x20, - 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x69, 0xc1, 0xac, 0x2c, - 0xba, 0xe9, 0xb7, 0xa8, 0x69, 0x0d, 0xbf, 0x9d, 0xa7, 0x4c, 0x9a, 0xb8, 0xb0, 0x62, 0xa6, 0x4b, - 0x71, 0x40, 0x08, 0xfb, 0xbf, 0x8f, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, - 0xa1, 0x1b, 0x20, 0xa4, 0x5b, 0xb2, 0x35, 0x3f, 0x99, 0xb7, 0xe4, 0xc8, 0xa6, 0x38, 0xf5, 0x9a, - 0xb4, 0x3e, 0xc7, 0x96, 0xe4, 0xa5, 0x0c, 0xd6, 0x98, 0x29, 0x10, 0x97, 0x54, 0x18, 0xd5, 0x53, - 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc0, 0x63, 0x87, - 0x90, 0x3b, 0x7a, 0x72, 0xda, 0x6f, 0xea, 0x51, 0x9f, 0x1c, 0x73, 0xc7, 0x98, 0xd7, 0x36, 0x4c, - 0xf0, 0xa9, 0xa3, 0x26, 0x36, 0xb0, 0x3d, 0x98, 0xcf, 0xa9, 0x10, 0x25, 0xc4, 0xfe, 0xae, 0x05, - 0xa5, 0x13, 0xd8, 0x3e, 0xab, 0x49, 0xdb, 0x67, 0x79, 0xc0, 0xee, 0x19, 0x0d, 0xda, 0x3d, 0x5f, - 0x1d, 0xad, 0x37, 0x8e, 0x63, 0xef, 0xfc, 0x91, 0x05, 0xe7, 0x07, 0xec, 0xa3, 0x64, 0x1b, 0x2e, - 0xf6, 0xfc, 0x96, 0xda, 0x4e, 0xaf, 0x3b, 0xe1, 0x36, 0x87, 0xc9, 0xcf, 0x7b, 0x81, 0xf5, 0xe4, - 0x7a, 0x06, 0xfc, 0xbd, 0xfd, 0xea, 0x9c, 0x26, 0x92, 0x42, 0xc0, 0x4c, 0x8a, 0xa4, 0x07, 0xa5, - 0x2d, 0x97, 0x76, 0x5a, 0xf1, 0x10, 0x1c, 0x51, 0x4b, 0xbb, 0x26, 0xa9, 0x89, 0xab, 0x01, 0xf5, - 0x0f, 0x35, 0x17, 0xfb, 0xc7, 0x16, 0x4c, 0xd7, 0xfa, 0xd1, 0x36, 0xd3, 0x51, 0x9a, 0xdc, 0x1a, - 0x47, 0x3c, 0x28, 0x86, 0x6e, 0x7b, 0xf7, 0x85, 0x7c, 0x16, 0xe3, 0x06, 0x23, 0x25, 0xaf, 0x48, - 0xb4, 0xb2, 0xce, 0x0b, 0x51, 0xb0, 0x21, 0x01, 0x4c, 0xf8, 0x4e, 0x3f, 0xda, 0x7e, 0x4e, 0x7e, - 0xf2, 0x88, 0x96, 0x89, 0x5b, 0xec, 0x73, 0x9e, 0x93, 0x1c, 0xb5, 0xca, 0x28, 0x4a, 0x51, 0x72, - 0xb2, 0xbf, 0x00, 0xd3, 0xc9, 0x7b, 0xb7, 0x63, 0x8c, 0xd9, 0x27, 0xa0, 0xe0, 0x04, 0x9e, 0x1c, - 0xb1, 0x15, 0x89, 0x50, 0xa8, 0xe1, 0x4d, 0x64, 0xe5, 0xe4, 0x59, 0x28, 0x6d, 0xf5, 0x3b, 0x1d, - 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0xf7, 0x38, - 0xcc, 0xd4, 0x3b, 0x7d, 0xfa, 0x6a, 0x40, 0xa9, 0xb2, 0x05, 0xd5, 0x60, 0xa6, 0x17, 0xd0, 0x5d, - 0x97, 0xde, 0x6b, 0xd0, 0x0e, 0x6d, 0x46, 0x7e, 0x20, 0xa5, 0x79, 0x44, 0x12, 0x9a, 0x59, 0x4f, - 0x82, 0x31, 0x8d, 0x4f, 0x5e, 0x81, 0x69, 0xa7, 0x19, 0xb9, 0xbb, 0x54, 0x53, 0x10, 0xe2, 0x3e, - 0x2c, 0x29, 0x4c, 0xd7, 0x12, 0x50, 0x4c, 0x61, 0x93, 0xcf, 0xc0, 0x5c, 0xd8, 0x74, 0x3a, 0xf4, - 0x76, 0x4f, 0xb2, 0x5a, 0xda, 0xa6, 0xcd, 0x9d, 0x75, 0xdf, 0xf5, 0x22, 0x69, 0x77, 0x7c, 0x52, - 0x52, 0x9a, 0x6b, 0x0c, 0xc1, 0xc3, 0xa1, 0x14, 0xc8, 0xbf, 0xb0, 0xe0, 0x89, 0x5e, 0x40, 0xd7, - 0x03, 0xbf, 0xeb, 0xb3, 0xa1, 0x36, 0x60, 0x0e, 0x93, 0x66, 0xa1, 0x37, 0x46, 0xd4, 0xa5, 0x44, - 0xc9, 0xe0, 0x1d, 0xce, 0x4f, 0x1c, 0xec, 0x57, 0x9f, 0x58, 0x3f, 0x4c, 0x00, 0x3c, 0x5c, 0x3e, - 0xf2, 0x2f, 0x2d, 0xb8, 0xdc, 0xf3, 0xc3, 0xe8, 0x90, 0x4f, 0x28, 0x9e, 0xe9, 0x27, 0xd8, 0x07, - 0xfb, 0xd5, 0xcb, 0xeb, 0x87, 0x4a, 0x80, 0x47, 0x48, 0x68, 0x1f, 0x54, 0xe0, 0xbc, 0x31, 0xf6, - 0xa4, 0x31, 0xe7, 0x65, 0x38, 0xa7, 0x06, 0x43, 0xac, 0xfb, 0x94, 0x63, 0xdb, 0x5e, 0xcd, 0x04, - 0x62, 0x12, 0x97, 0x8d, 0x3b, 0x3d, 0x14, 0x45, 0xed, 0xd4, 0xb8, 0x5b, 0x4f, 0x40, 0x31, 0x85, - 0x4d, 0x56, 0xe0, 0x82, 0x2c, 0x41, 0xda, 0xeb, 0xb8, 0x4d, 0x67, 0xc9, 0xef, 0xcb, 0x21, 0x57, - 0xac, 0x3f, 0x72, 0xb0, 0x5f, 0xbd, 0xb0, 0x3e, 0x08, 0xc6, 0xac, 0x3a, 0x64, 0x15, 0x2e, 0x3a, - 0xfd, 0xc8, 0xd7, 0xdf, 0x7f, 0xd5, 0x63, 0xdb, 0x69, 0x8b, 0x0f, 0xad, 0x92, 0xd8, 0x77, 0x6b, - 0x19, 0x70, 0xcc, 0xac, 0x45, 0xd6, 0x53, 0xd4, 0x1a, 0xb4, 0xe9, 0x7b, 0x2d, 0xd1, 0xcb, 0xc5, - 0xf8, 0x18, 0x58, 0xcb, 0xc0, 0xc1, 0xcc, 0x9a, 0xa4, 0x03, 0xd3, 0x5d, 0xe7, 0xfe, 0x6d, 0xcf, - 0xd9, 0x75, 0xdc, 0x0e, 0x63, 0x22, 0xed, 0x85, 0xc3, 0xad, 0x4c, 0xfd, 0xc8, 0xed, 0x2c, 0x08, - 0x3f, 0x8e, 0x85, 0x15, 0x2f, 0xba, 0x15, 0x34, 0x22, 0xa6, 0xa9, 0x0b, 0x0d, 0x72, 0x2d, 0x41, - 0x0b, 0x53, 0xb4, 0xc9, 0x2d, 0xb8, 0xc4, 0xa7, 0xe3, 0xb2, 0x7f, 0xcf, 0x5b, 0xa6, 0x1d, 0x67, - 0x4f, 0x7d, 0xc0, 0x24, 0xff, 0x80, 0x47, 0x0f, 0xf6, 0xab, 0x97, 0x1a, 0x59, 0x08, 0x98, 0x5d, - 0x8f, 0x38, 0xf0, 0x58, 0x12, 0x80, 0x74, 0xd7, 0x0d, 0x5d, 0xdf, 0x13, 0x66, 0xb9, 0x52, 0x6c, - 0x96, 0x6b, 0x0c, 0x47, 0xc3, 0xc3, 0x68, 0x90, 0xbf, 0x63, 0xc1, 0xc5, 0xac, 0x69, 0x38, 0x57, - 0xce, 0xe3, 0x36, 0x39, 0x35, 0xb5, 0xc4, 0x88, 0xc8, 0x5c, 0x14, 0x32, 0x85, 0x20, 0xef, 0x58, - 0x30, 0xe5, 0x18, 0x27, 0xe8, 0x39, 0xc8, 0x63, 0xd7, 0x32, 0xcf, 0xe4, 0xf5, 0xd9, 0x83, 0xfd, - 0x6a, 0xe2, 0x94, 0x8e, 0x09, 0x8e, 0xe4, 0xef, 0x59, 0x70, 0x29, 0x73, 0x8e, 0xcf, 0x55, 0xce, - 0xa2, 0x85, 0xf8, 0x20, 0xc9, 0x5e, 0x73, 0xb2, 0xc5, 0x20, 0xdf, 0xb4, 0xf4, 0x56, 0xa6, 0x2e, - 0x18, 0xe7, 0xa6, 0xb8, 0x68, 0x23, 0x1a, 0x3c, 0x0c, 0x35, 0x4a, 0x11, 0xae, 0x5f, 0x30, 0x76, - 0x46, 0x55, 0x88, 0x69, 0xf6, 0xe4, 0x1b, 0x96, 0xda, 0x1a, 0xb5, 0x44, 0xe7, 0xce, 0x4a, 0x22, - 0x12, 0xef, 0xb4, 0x5a, 0xa0, 0x14, 0x73, 0xf2, 0xb3, 0x30, 0xef, 0x6c, 0xfa, 0x41, 0x94, 0x39, - 0xf9, 0xe6, 0xa6, 0xf9, 0x34, 0xba, 0x7c, 0xb0, 0x5f, 0x9d, 0xaf, 0x0d, 0xc5, 0xc2, 0x43, 0x28, - 0xd8, 0xbf, 0x3b, 0x01, 0x53, 0xe2, 0x24, 0x24, 0xb7, 0xae, 0xdf, 0xb2, 0xe0, 0xf1, 0x66, 0x3f, - 0x08, 0xa8, 0x17, 0x35, 0x22, 0xda, 0x1b, 0xdc, 0xb8, 0xac, 0x33, 0xdd, 0xb8, 0x9e, 0x3c, 0xd8, - 0xaf, 0x3e, 0xbe, 0x74, 0x08, 0x7f, 0x3c, 0x54, 0x3a, 0xf2, 0x6f, 0x2d, 0xb0, 0x25, 0x42, 0xdd, - 0x69, 0xee, 0xb4, 0x03, 0xbf, 0xef, 0xb5, 0x06, 0x3f, 0x62, 0xec, 0x4c, 0x3f, 0xe2, 0xe9, 0x83, - 0xfd, 0xaa, 0xbd, 0x74, 0xa4, 0x14, 0x78, 0x0c, 0x49, 0xc9, 0xab, 0x70, 0x5e, 0x62, 0x5d, 0xbd, - 0xdf, 0xa3, 0x81, 0xcb, 0xce, 0x1c, 0x52, 0x71, 0x8c, 0x7d, 0xd3, 0xd2, 0x08, 0x38, 0x58, 0x87, - 0x84, 0x30, 0x79, 0x8f, 0xba, 0xed, 0xed, 0x48, 0xa9, 0x4f, 0x23, 0x3a, 0xa4, 0x49, 0xab, 0xc8, - 0x1d, 0x41, 0xb3, 0x5e, 0x39, 0xd8, 0xaf, 0x4e, 0xca, 0x3f, 0xa8, 0x38, 0x91, 0x9b, 0x30, 0x2d, - 0xce, 0xa9, 0xeb, 0xae, 0xd7, 0x5e, 0xf7, 0x3d, 0xe1, 0x55, 0x55, 0xae, 0x3f, 0xad, 0x36, 0xfc, - 0x46, 0x02, 0xfa, 0xde, 0x7e, 0x75, 0x4a, 0xfd, 0xde, 0xd8, 0xeb, 0x51, 0x4c, 0xd5, 0x26, 0x7f, - 0xdb, 0x02, 0x12, 0x46, 0xb4, 0xb7, 0xde, 0xe9, 0xb7, 0x5d, 0xd9, 0x44, 0xd2, 0x3f, 0x2a, 0x07, - 0x57, 0xad, 0x24, 0xdd, 0xfa, 0xbc, 0x14, 0x92, 0x34, 0x06, 0x38, 0x62, 0x86, 0x14, 0xf6, 0x77, - 0x26, 0x01, 0xd4, 0x5c, 0xa2, 0x3d, 0xf2, 0x21, 0x28, 0x87, 0x34, 0x12, 0x4d, 0x22, 0xaf, 0xb9, - 0xc4, 0xe5, 0xa4, 0x2a, 0xc4, 0x18, 0x4e, 0x76, 0xa0, 0xd8, 0x73, 0xfa, 0x21, 0xcd, 0xe7, 0x70, - 0x23, 0x47, 0xe6, 0x3a, 0xa3, 0x28, 0x4e, 0xcd, 0xfc, 0x27, 0x0a, 0x1e, 0xe4, 0xcb, 0x16, 0x00, - 0x4d, 0x8e, 0xa6, 0x91, 0xad, 0x57, 0x92, 0x65, 0x3c, 0xe0, 0x58, 0x1b, 0xd4, 0xa7, 0x0f, 0xf6, - 0xab, 0x60, 0x8c, 0x4b, 0x83, 0x2d, 0xb9, 0x07, 0x25, 0x47, 0x6d, 0x48, 0xe3, 0x67, 0xb1, 0x21, - 0xf1, 0xc3, 0xac, 0x9e, 0x51, 0x9a, 0x19, 0xf9, 0xaa, 0x05, 0xd3, 0x21, 0x8d, 0x64, 0x57, 0xb1, - 0x65, 0x51, 0x6a, 0xe3, 0x23, 0xce, 0x88, 0x46, 0x82, 0xa6, 0x58, 0xde, 0x93, 0x65, 0x98, 0xe2, - 0xab, 0x44, 0xb9, 0x4e, 0x9d, 0x16, 0x0d, 0xb8, 0xad, 0x44, 0xaa, 0x79, 0xa3, 0x8b, 0x62, 0xd0, - 0xd4, 0xa2, 0x18, 0x65, 0x98, 0xe2, 0xab, 0x44, 0x59, 0x73, 0x83, 0xc0, 0x97, 0xa2, 0x94, 0x72, - 0x12, 0xc5, 0xa0, 0xa9, 0x45, 0x31, 0xca, 0x30, 0xc5, 0x97, 0x74, 0x60, 0xa2, 0xc7, 0xa7, 0x96, - 0x54, 0xe5, 0x46, 0xbc, 0x23, 0x57, 0xd3, 0x94, 0xf6, 0x84, 0x4d, 0x4a, 0xfc, 0x47, 0xc9, 0xc3, - 0xfe, 0xf6, 0x39, 0x98, 0x56, 0xd3, 0x36, 0x3e, 0xe4, 0x08, 0x43, 0xe0, 0x90, 0x43, 0xce, 0x92, - 0x09, 0xc4, 0x24, 0x2e, 0xab, 0x2c, 0x56, 0xad, 0xe4, 0x19, 0x47, 0x57, 0x6e, 0x98, 0x40, 0x4c, - 0xe2, 0x92, 0x2e, 0x14, 0xd9, 0xca, 0xa2, 0xdc, 0x2f, 0x46, 0xfc, 0xf2, 0x78, 0x35, 0x32, 0x8c, - 0x2a, 0x8c, 0x3c, 0x0a, 0x2e, 0xdc, 0x96, 0x1d, 0x25, 0xcc, 0xdb, 0x72, 0x2a, 0xe6, 0xb3, 0x1a, - 0x24, 0x2d, 0xe7, 0xa2, 0xef, 0x93, 0x65, 0x98, 0x62, 0x9f, 0x71, 0xee, 0x29, 0x9e, 0xe1, 0xb9, - 0xe7, 0x53, 0x50, 0xea, 0x3a, 0xf7, 0x1b, 0xfd, 0xa0, 0x7d, 0xfa, 0xf3, 0x95, 0x74, 0xa7, 0x15, - 0x54, 0x50, 0xd3, 0x23, 0x5f, 0xb4, 0x8c, 0x05, 0x4e, 0xf8, 0x5a, 0xdc, 0xc9, 0x77, 0x81, 0xd3, - 0x6a, 0xc3, 0xd0, 0xa5, 0x6e, 0xe0, 0x14, 0x52, 0x7a, 0xe0, 0xa7, 0x10, 0xa6, 0x51, 0x8b, 0x09, - 0xa2, 0x35, 0xea, 0xf2, 0x99, 0x6a, 0xd4, 0x4b, 0x09, 0x66, 0x98, 0x62, 0xce, 0xe5, 0x11, 0x73, - 0x4e, 0xcb, 0x03, 0x67, 0x2a, 0x4f, 0x23, 0xc1, 0x0c, 0x53, 0xcc, 0x87, 0x1f, 0xbd, 0x2b, 0x67, - 0x73, 0xf4, 0x9e, 0xca, 0xe1, 0xe8, 0x7d, 0xf8, 0xa9, 0xe4, 0xdc, 0xa8, 0xa7, 0x12, 0x72, 0x03, - 0x48, 0x6b, 0xcf, 0x73, 0xba, 0x6e, 0x53, 0x2e, 0x96, 0x7c, 0x93, 0x9e, 0xe6, 0xa6, 0x19, 0xad, - 0x95, 0x2d, 0x0f, 0x60, 0x60, 0x46, 0x2d, 0x12, 0x41, 0xa9, 0xa7, 0x94, 0xcf, 0x99, 0x3c, 0x46, - 0xbf, 0x52, 0x46, 0x85, 0x0b, 0x0d, 0x9b, 0x78, 0xaa, 0x04, 0x35, 0x27, 0xb2, 0x0a, 0x17, 0xbb, - 0xae, 0xb7, 0xee, 0xb7, 0xc2, 0x75, 0x1a, 0x48, 0xc3, 0x53, 0x83, 0x46, 0x73, 0xb3, 0xbc, 0x6d, - 0xb8, 0x31, 0x61, 0x2d, 0x03, 0x8e, 0x99, 0xb5, 0xec, 0xff, 0x65, 0xc1, 0xec, 0x52, 0xc7, 0xef, - 0xb7, 0xee, 0x38, 0x51, 0x73, 0x5b, 0x78, 0x6c, 0x90, 0x57, 0xa0, 0xe4, 0x7a, 0x11, 0x0d, 0x76, - 0x9d, 0x8e, 0xdc, 0x9f, 0x6c, 0x65, 0x49, 0x5e, 0x91, 0xe5, 0xef, 0xed, 0x57, 0xa7, 0x97, 0xfb, - 0x01, 0x37, 0xd8, 0x8b, 0xd5, 0x0a, 0x75, 0x1d, 0xf2, 0x6d, 0x0b, 0xce, 0x0b, 0x9f, 0x8f, 0x65, - 0x27, 0x72, 0x5e, 0xef, 0xd3, 0xc0, 0xa5, 0xca, 0xeb, 0x63, 0xc4, 0x85, 0x2a, 0x2d, 0xab, 0x62, - 0xb0, 0x17, 0x9f, 0x59, 0xd6, 0xd2, 0x9c, 0x71, 0x50, 0x18, 0xfb, 0x97, 0x0b, 0xf0, 0xe8, 0x50, - 0x5a, 0x64, 0x1e, 0xc6, 0xdc, 0x96, 0xfc, 0x74, 0x90, 0x74, 0xc7, 0x56, 0x5a, 0x38, 0xe6, 0xb6, - 0xc8, 0x02, 0xd7, 0x70, 0x03, 0x1a, 0x86, 0xea, 0xee, 0xbd, 0xac, 0x95, 0x51, 0x59, 0x8a, 0x06, - 0x06, 0xa9, 0x42, 0x91, 0xbb, 0x52, 0xcb, 0xa3, 0x15, 0xd7, 0x99, 0xb9, 0xd7, 0x32, 0x8a, 0x72, - 0xf2, 0x25, 0x0b, 0x40, 0x08, 0xc8, 0xf4, 0x7d, 0xb9, 0x4b, 0x62, 0xbe, 0xcd, 0xc4, 0x28, 0x0b, - 0x29, 0xe3, 0xff, 0x68, 0x70, 0x25, 0x1b, 0x30, 0xc1, 0xd4, 0x67, 0xbf, 0x75, 0xea, 0x4d, 0x51, - 0x28, 0x40, 0x9c, 0x06, 0x4a, 0x5a, 0xac, 0xad, 0x02, 0x1a, 0xf5, 0x03, 0x8f, 0x35, 0x2d, 0xdf, - 0x06, 0x4b, 0x42, 0x0a, 0xd4, 0xa5, 0x68, 0x60, 0xd8, 0xff, 0x6c, 0x0c, 0x2e, 0x66, 0x89, 0xce, - 0x76, 0x9b, 0x09, 0x21, 0xad, 0xb4, 0x12, 0xfc, 0x4c, 0xfe, 0xed, 0x23, 0xdd, 0x97, 0xf4, 0x8d, - 0x8d, 0xf4, 0x25, 0x95, 0x7c, 0xc9, 0xcf, 0xe8, 0x16, 0x1a, 0x3b, 0x65, 0x0b, 0x69, 0xca, 0xa9, - 0x56, 0x7a, 0x12, 0xc6, 0x43, 0xd6, 0xf3, 0x85, 0xe4, 0xcd, 0x0f, 0xef, 0x23, 0x0e, 0x61, 0x18, - 0x7d, 0xcf, 0x8d, 0x64, 0xfc, 0x91, 0xc6, 0xb8, 0xed, 0xb9, 0x11, 0x72, 0x88, 0xfd, 0xad, 0x31, - 0x98, 0x1f, 0xfe, 0x51, 0xe4, 0x5b, 0x16, 0x40, 0x8b, 0x1d, 0x8e, 0x42, 0xee, 0xc4, 0x2f, 0xdc, - 0xbd, 0x9c, 0xb3, 0x6a, 0xc3, 0x65, 0xc5, 0x29, 0xf6, 0x43, 0xd4, 0x45, 0x21, 0x1a, 0x82, 0x90, - 0xe7, 0xd4, 0xd0, 0xe7, 0xb7, 0x56, 0x62, 0x32, 0xe9, 0x3a, 0x6b, 0x1a, 0x82, 0x06, 0x16, 0x3b, - 0xfd, 0x7a, 0x4e, 0x97, 0x86, 0x3d, 0x47, 0x47, 0x73, 0xf1, 0xd3, 0xef, 0x4d, 0x55, 0x88, 0x31, - 0xdc, 0xee, 0xc0, 0x53, 0xc7, 0x90, 0x33, 0xa7, 0x60, 0x19, 0xfb, 0x7f, 0x58, 0xf0, 0x88, 0xf4, - 0xc4, 0xfb, 0xff, 0xc6, 0xad, 0xf3, 0x4f, 0x2d, 0x78, 0x6c, 0xc8, 0x37, 0x3f, 0x00, 0xef, 0xce, - 0xb7, 0x92, 0xde, 0x9d, 0xb7, 0x47, 0x1d, 0xd2, 0x99, 0xdf, 0x31, 0xc4, 0xc9, 0xf3, 0x77, 0x0b, - 0x70, 0x8e, 0x2d, 0x5b, 0x2d, 0xbf, 0x9d, 0xd3, 0xc6, 0xf9, 0x14, 0x14, 0x3f, 0xc7, 0x36, 0xa0, - 0xf4, 0x20, 0xe3, 0xbb, 0x12, 0x0a, 0x18, 0xf9, 0xb2, 0x05, 0x93, 0x9f, 0x93, 0x7b, 0xaa, 0x38, - 0xcb, 0x8d, 0xb8, 0x18, 0x26, 0xbe, 0x61, 0x41, 0xee, 0x90, 0x22, 0x06, 0x47, 0xfb, 0x72, 0xaa, - 0xad, 0x54, 0x71, 0x26, 0xcf, 0xc0, 0xe4, 0x96, 0x1f, 0x74, 0xfb, 0x1d, 0x27, 0x1d, 0xf8, 0x79, - 0x4d, 0x14, 0xa3, 0x82, 0xb3, 0x49, 0xee, 0xf4, 0xdc, 0x37, 0x68, 0x10, 0x8a, 0x90, 0x8c, 0xc4, - 0x24, 0xaf, 0x69, 0x08, 0x1a, 0x58, 0xbc, 0x4e, 0xbb, 0x1d, 0xd0, 0xb6, 0x13, 0xf9, 0x01, 0xdf, - 0x39, 0xcc, 0x3a, 0x1a, 0x82, 0x06, 0xd6, 0xfc, 0xc7, 0x61, 0xca, 0x14, 0xfe, 0x44, 0xf1, 0x3c, - 0x9f, 0x00, 0xe9, 0xd4, 0x99, 0x5a, 0x92, 0xac, 0xe3, 0x2c, 0x49, 0xf6, 0x7f, 0x18, 0x03, 0xc3, - 0x16, 0xf5, 0x00, 0xa6, 0xba, 0x97, 0x98, 0xea, 0x23, 0xda, 0x51, 0x0c, 0xcb, 0xda, 0xb0, 0xe8, - 0xc6, 0xdd, 0x54, 0x74, 0xe3, 0xcd, 0xdc, 0x38, 0x1e, 0x1e, 0xdc, 0xf8, 0x03, 0x0b, 0x1e, 0x8b, - 0x91, 0x07, 0x6d, 0xd8, 0x47, 0xaf, 0xdb, 0x2f, 0x42, 0xc5, 0x89, 0xab, 0xc9, 0x89, 0x65, 0x84, - 0x96, 0x69, 0x10, 0x9a, 0x78, 0x71, 0x58, 0x4c, 0xe1, 0x94, 0x61, 0x31, 0xe3, 0x87, 0x87, 0xc5, - 0xd8, 0x3f, 0x1e, 0x83, 0x27, 0x06, 0xbf, 0xcc, 0xf4, 0x15, 0x3f, 0xfa, 0xdb, 0xd2, 0xde, 0xe4, - 0x63, 0xa7, 0xf6, 0x26, 0x2f, 0x1c, 0xd7, 0x9b, 0x5c, 0xfb, 0x70, 0x8f, 0x9f, 0xb9, 0x0f, 0x77, - 0x03, 0x2e, 0x29, 0x87, 0xd1, 0x6b, 0x7e, 0x20, 0x63, 0x43, 0xd4, 0x0a, 0x52, 0xaa, 0x3f, 0x21, - 0xab, 0x5c, 0xc2, 0x2c, 0x24, 0xcc, 0xae, 0x6b, 0xff, 0xa0, 0x00, 0x17, 0xe2, 0x66, 0x5f, 0xf2, - 0xbd, 0x96, 0xcb, 0x7d, 0x8e, 0x5e, 0x86, 0xf1, 0x68, 0xaf, 0xa7, 0x1a, 0xfb, 0x2f, 0x2a, 0x71, - 0x36, 0xf6, 0x7a, 0xac, 0xb7, 0x1f, 0xc9, 0xa8, 0xc2, 0x6f, 0x11, 0x78, 0x25, 0xb2, 0xaa, 0x67, - 0x87, 0xe8, 0x81, 0x17, 0x92, 0xa3, 0xf9, 0xbd, 0xfd, 0x6a, 0x46, 0x96, 0x87, 0x05, 0x4d, 0x29, - 0x39, 0xe6, 0xc9, 0x5d, 0x98, 0xee, 0x38, 0x61, 0x74, 0xbb, 0xd7, 0x72, 0x22, 0xba, 0xe1, 0x4a, - 0x6f, 0x9e, 0x93, 0x85, 0xd3, 0x68, 0xb7, 0x87, 0xd5, 0x04, 0x25, 0x4c, 0x51, 0x26, 0xbb, 0x40, - 0x58, 0xc9, 0x46, 0xe0, 0x78, 0xa1, 0xf8, 0x2a, 0xc6, 0xef, 0xe4, 0xb1, 0x51, 0xfa, 0xe8, 0xbc, - 0x3a, 0x40, 0x0d, 0x33, 0x38, 0x90, 0xa7, 0x61, 0x22, 0xa0, 0x4e, 0xa8, 0xb7, 0x03, 0x3d, 0xff, - 0x91, 0x97, 0xa2, 0x84, 0x9a, 0x13, 0x6a, 0xe2, 0x88, 0x09, 0xf5, 0x87, 0x16, 0x4c, 0xc7, 0xdd, - 0xf4, 0x00, 0x54, 0x8f, 0x6e, 0x52, 0xf5, 0xb8, 0x9e, 0xd7, 0x92, 0x38, 0x44, 0xdb, 0xf8, 0x93, - 0x49, 0xf3, 0xfb, 0x78, 0x00, 0xc7, 0xe7, 0x4d, 0x7f, 0x7e, 0x2b, 0x8f, 0xa8, 0xba, 0x84, 0xb6, - 0x77, 0xa8, 0x23, 0x3f, 0xd3, 0x75, 0x5a, 0x52, 0x8f, 0x91, 0xc3, 0x5e, 0xeb, 0x3a, 0x4a, 0xbf, - 0xc9, 0xd2, 0x75, 0x54, 0x1d, 0x72, 0x1b, 0x1e, 0xe9, 0x05, 0x3e, 0xcf, 0x33, 0xb0, 0x4c, 0x9d, - 0x56, 0xc7, 0xf5, 0xa8, 0x32, 0xf3, 0x08, 0xaf, 0x9b, 0xc7, 0x0e, 0xf6, 0xab, 0x8f, 0xac, 0x67, - 0xa3, 0xe0, 0xb0, 0xba, 0xc9, 0x48, 0xd5, 0xf1, 0x63, 0x44, 0xaa, 0xfe, 0xa2, 0x36, 0xa6, 0xea, - 0xa0, 0x88, 0x4f, 0xe7, 0xd5, 0x95, 0x59, 0xe1, 0x11, 0x7a, 0x48, 0xd5, 0x24, 0x53, 0xd4, 0xec, - 0x87, 0x5b, 0xec, 0x26, 0x4e, 0x69, 0xb1, 0x8b, 0xe3, 0x60, 0x26, 0xdf, 0xcf, 0x38, 0x98, 0xd2, - 0x07, 0x2a, 0x0e, 0xe6, 0xdb, 0x16, 0x5c, 0x70, 0x06, 0x23, 0xd0, 0xf3, 0x31, 0x1e, 0x67, 0x84, - 0xb6, 0xd7, 0x1f, 0x93, 0x42, 0x66, 0x05, 0xfa, 0x63, 0x96, 0x28, 0xf6, 0xbb, 0x45, 0x98, 0x4d, - 0x2b, 0x49, 0x67, 0x1f, 0xaa, 0xfb, 0x37, 0x2c, 0x98, 0x55, 0x13, 0x5c, 0xdf, 0x80, 0x8b, 0x23, - 0xc6, 0x6a, 0x4e, 0xeb, 0x8a, 0x50, 0xf7, 0x74, 0x06, 0x95, 0x8d, 0x14, 0x37, 0x1c, 0xe0, 0x4f, - 0xde, 0x84, 0x8a, 0xbe, 0x55, 0x39, 0x55, 0xdc, 0x2e, 0x0f, 0x2d, 0xad, 0xc5, 0x24, 0xd0, 0xa4, - 0x47, 0xde, 0xb5, 0x00, 0x9a, 0x6a, 0x27, 0xce, 0x29, 0x2a, 0x2a, 0x43, 0x5b, 0x88, 0xf5, 0x79, - 0x5d, 0x14, 0xa2, 0xc1, 0x98, 0xfc, 0x32, 0xbf, 0x4f, 0xd1, 0x23, 0x41, 0x79, 0x1e, 0x7c, 0x32, - 0xef, 0xa5, 0x28, 0xf6, 0x25, 0xd1, 0xda, 0x9e, 0x01, 0x0a, 0x31, 0x21, 0x84, 0xfd, 0x32, 0x68, - 0x9f, 0x6d, 0xb6, 0xb2, 0x72, 0xaf, 0xed, 0x75, 0x27, 0xda, 0x96, 0x43, 0x50, 0xaf, 0xac, 0xd7, - 0x14, 0x00, 0x63, 0x1c, 0xfb, 0xb3, 0x30, 0xfd, 0x6a, 0xe0, 0xf4, 0xb6, 0x5d, 0x7e, 0x6f, 0xc1, - 0xce, 0xc7, 0xcf, 0xc0, 0xa4, 0xd3, 0x6a, 0x65, 0x25, 0xfb, 0xa9, 0x89, 0x62, 0x54, 0xf0, 0x63, - 0x1d, 0x85, 0xed, 0x7f, 0x6d, 0x01, 0x89, 0x6f, 0x9a, 0x5d, 0xaf, 0xbd, 0xe6, 0x44, 0xcd, 0x6d, - 0x76, 0x84, 0xdb, 0xe6, 0xa5, 0x59, 0x47, 0xb8, 0xeb, 0x1a, 0x82, 0x06, 0x16, 0x79, 0x1b, 0x2a, - 0xe2, 0xdf, 0x1b, 0xfa, 0x80, 0x38, 0xba, 0xeb, 0x39, 0xdf, 0xf3, 0xb8, 0x4c, 0x62, 0x14, 0x5e, - 0x8f, 0x39, 0xa0, 0xc9, 0x8e, 0x35, 0xd5, 0x8a, 0xb7, 0xd5, 0xe9, 0xdf, 0x6f, 0x6d, 0xc6, 0x4d, - 0xd5, 0x0b, 0xfc, 0x2d, 0xb7, 0x43, 0xd3, 0x4d, 0xb5, 0x2e, 0x8a, 0x51, 0xc1, 0x8f, 0xd7, 0x54, - 0xff, 0xca, 0x82, 0x8b, 0x2b, 0x61, 0xe4, 0xfa, 0xcb, 0x34, 0x8c, 0xd8, 0xce, 0xc7, 0xd6, 0xc7, - 0x7e, 0xe7, 0x38, 0xe1, 0x17, 0xcb, 0x30, 0x2b, 0xef, 0xa1, 0xfb, 0x9b, 0x21, 0x8d, 0x8c, 0xa3, - 0x86, 0x9e, 0xc7, 0x4b, 0x29, 0x38, 0x0e, 0xd4, 0x60, 0x54, 0xe4, 0x85, 0x74, 0x4c, 0xa5, 0x90, - 0xa4, 0xd2, 0x48, 0xc1, 0x71, 0xa0, 0x86, 0xfd, 0xfd, 0x02, 0x5c, 0xe0, 0x9f, 0x91, 0x0a, 0x9d, - 0xfa, 0xc6, 0xb0, 0xd0, 0xa9, 0x11, 0xa7, 0x32, 0xe7, 0x75, 0x8a, 0xc0, 0xa9, 0xbf, 0x6e, 0xc1, - 0x4c, 0x2b, 0xd9, 0xd2, 0xf9, 0xd8, 0xe5, 0xb2, 0xfa, 0x50, 0x78, 0x20, 0xa6, 0x0a, 0x31, 0xcd, - 0x9f, 0xfc, 0x8a, 0x05, 0x33, 0x49, 0x31, 0xd5, 0xea, 0x7e, 0x06, 0x8d, 0xa4, 0x43, 0x06, 0x92, - 0xe5, 0x21, 0xa6, 0x45, 0xb0, 0x7f, 0x6f, 0x4c, 0x76, 0xe9, 0x59, 0xc4, 0x05, 0x91, 0x7b, 0x50, - 0x8e, 0x3a, 0xa1, 0x28, 0x94, 0x5f, 0x3b, 0xe2, 0xa1, 0x75, 0x63, 0xb5, 0x21, 0x1c, 0x4e, 0x62, - 0xbd, 0x52, 0x96, 0x30, 0xfd, 0x58, 0xf1, 0xe2, 0x8c, 0x9b, 0x3d, 0xc9, 0x38, 0x97, 0xd3, 0xf2, - 0xc6, 0xd2, 0x7a, 0x9a, 0xb1, 0x2c, 0x61, 0x8c, 0x15, 0x2f, 0xfb, 0x37, 0x2c, 0x28, 0xdf, 0xf0, - 0xd5, 0x3a, 0xf2, 0xb3, 0x39, 0xd8, 0xa2, 0xb4, 0xca, 0xaa, 0x95, 0x96, 0xf8, 0x14, 0xf4, 0x4a, - 0xc2, 0x12, 0xf5, 0xb8, 0x41, 0x7b, 0x81, 0xe7, 0x3c, 0x64, 0xa4, 0x6e, 0xf8, 0x9b, 0x43, 0xcd, - 0xc7, 0xbf, 0x5a, 0x84, 0x73, 0xaf, 0x39, 0x7b, 0xd4, 0x8b, 0x9c, 0x93, 0x6f, 0x12, 0x2f, 0x42, - 0xc5, 0xe9, 0xf1, 0xbb, 0x4c, 0xe3, 0x18, 0x12, 0x1b, 0x77, 0x62, 0x10, 0x9a, 0x78, 0xf1, 0x82, - 0x26, 0x82, 0x74, 0xb2, 0x96, 0xa2, 0xa5, 0x14, 0x1c, 0x07, 0x6a, 0x90, 0x1b, 0x40, 0x64, 0x60, - 0x7b, 0xad, 0xd9, 0xf4, 0xfb, 0x9e, 0x58, 0xd2, 0x84, 0xdd, 0x47, 0x9f, 0x87, 0xd7, 0x06, 0x30, - 0x30, 0xa3, 0x16, 0xf9, 0x0c, 0xcc, 0x35, 0x39, 0x65, 0x79, 0x3a, 0x32, 0x29, 0x8a, 0x13, 0xb2, - 0x0e, 0x7b, 0x59, 0x1a, 0x82, 0x87, 0x43, 0x29, 0x30, 0x49, 0xc3, 0xc8, 0x0f, 0x9c, 0x36, 0x35, - 0xe9, 0x4e, 0x24, 0x25, 0x6d, 0x0c, 0x60, 0x60, 0x46, 0x2d, 0xf2, 0x05, 0x28, 0x47, 0xdb, 0x01, - 0x0d, 0xb7, 0xfd, 0x4e, 0x4b, 0xfa, 0x9e, 0x8c, 0x68, 0x0c, 0x94, 0xbd, 0xbf, 0xa1, 0xa8, 0x1a, - 0xc3, 0x5b, 0x15, 0x61, 0xcc, 0x93, 0x04, 0x30, 0x11, 0x36, 0xfd, 0x1e, 0x0d, 0xe5, 0xa9, 0xe2, - 0x46, 0x2e, 0xdc, 0xb9, 0x71, 0xcb, 0x30, 0x43, 0x72, 0x0e, 0x28, 0x39, 0xd9, 0xbf, 0x33, 0x06, - 0x53, 0x26, 0xe2, 0x31, 0xd6, 0xa6, 0x2f, 0x5b, 0x30, 0xd5, 0xf4, 0xbd, 0x28, 0xf0, 0x3b, 0x71, - 0xc2, 0x86, 0xd1, 0x35, 0x0a, 0x46, 0x6a, 0x99, 0x46, 0x8e, 0xdb, 0x31, 0xac, 0x75, 0x06, 0x1b, - 0x4c, 0x30, 0x25, 0x5f, 0xb7, 0x60, 0x26, 0x76, 0x8c, 0x8c, 0x6d, 0x7d, 0xb9, 0x0a, 0xa2, 0x97, - 0xfa, 0xab, 0x49, 0x4e, 0x98, 0x66, 0x6d, 0x6f, 0xc2, 0x6c, 0xba, 0xb7, 0x59, 0x53, 0xf6, 0x1c, - 0x39, 0xd7, 0x0b, 0x71, 0x53, 0xae, 0x3b, 0x61, 0x88, 0x1c, 0x42, 0x9e, 0x85, 0x52, 0xd7, 0x09, - 0xda, 0xae, 0xe7, 0x74, 0x78, 0x2b, 0x16, 0x8c, 0x05, 0x49, 0x96, 0xa3, 0xc6, 0xb0, 0x3f, 0x02, - 0x53, 0x6b, 0x8e, 0xd7, 0xa6, 0x2d, 0xb9, 0x0e, 0x1f, 0x1d, 0x99, 0xfa, 0xc7, 0xe3, 0x50, 0x31, - 0x8e, 0x8f, 0x67, 0x7f, 0xce, 0x4a, 0x24, 0x22, 0x2a, 0xe4, 0x98, 0x88, 0xe8, 0x53, 0x00, 0x5b, - 0xae, 0xe7, 0x86, 0xdb, 0xa7, 0x4c, 0x71, 0xc4, 0xef, 0xe6, 0xaf, 0x69, 0x0a, 0x68, 0x50, 0x8b, - 0x2f, 0x40, 0x8b, 0x87, 0x64, 0x0b, 0x7c, 0xd7, 0x32, 0xb6, 0x9b, 0x89, 0x3c, 0x1c, 0x3e, 0x8c, - 0x8e, 0x59, 0x50, 0xdb, 0x8f, 0xb8, 0x9b, 0x3a, 0x6c, 0x57, 0xda, 0x80, 0x52, 0x40, 0xc3, 0x7e, - 0x97, 0x9e, 0x2a, 0x19, 0x11, 0x77, 0xbd, 0x41, 0x59, 0x1f, 0x35, 0xa5, 0xf9, 0x97, 0xe1, 0x5c, - 0x42, 0x84, 0x13, 0xdd, 0x30, 0xf9, 0x90, 0x69, 0xa3, 0x38, 0xcd, 0x7d, 0x13, 0xeb, 0x8b, 0x8e, - 0x91, 0x84, 0x48, 0xf7, 0x85, 0x70, 0xb0, 0x12, 0x30, 0xfb, 0xc7, 0x13, 0x20, 0x7d, 0x18, 0x8e, - 0xb1, 0x5c, 0x99, 0x37, 0x97, 0x63, 0xa7, 0xb8, 0xb9, 0xbc, 0x01, 0x53, 0xae, 0xe7, 0x46, 0xae, - 0xd3, 0xe1, 0xf6, 0x27, 0xb9, 0x9d, 0x2a, 0x67, 0xfc, 0xa9, 0x15, 0x03, 0x96, 0x41, 0x27, 0x51, - 0x97, 0xbc, 0x0e, 0x45, 0xbe, 0xdf, 0xc8, 0x01, 0x7c, 0x72, 0x47, 0x0b, 0xee, 0x63, 0x23, 0x22, - 0xf4, 0x04, 0x25, 0x7e, 0xf8, 0x10, 0x59, 0x98, 0xf4, 0xf1, 0x5b, 0x8e, 0xe3, 0xf8, 0xf0, 0x91, - 0x82, 0xe3, 0x40, 0x0d, 0x46, 0x65, 0xcb, 0x71, 0x3b, 0xfd, 0x80, 0xc6, 0x54, 0x26, 0x92, 0x54, - 0xae, 0xa5, 0xe0, 0x38, 0x50, 0x83, 0x6c, 0xc1, 0x94, 0x2c, 0x13, 0x6e, 0x73, 0x93, 0xa7, 0xfc, - 0x4a, 0xee, 0x1e, 0x79, 0xcd, 0xa0, 0x84, 0x09, 0xba, 0xa4, 0x0f, 0xe7, 0x5d, 0xaf, 0xe9, 0x7b, - 0xcd, 0x4e, 0x3f, 0x74, 0x77, 0x69, 0x1c, 0x1e, 0x77, 0x1a, 0x66, 0x97, 0x0e, 0xf6, 0xab, 0xe7, - 0x57, 0xd2, 0xe4, 0x70, 0x90, 0x03, 0xf9, 0xa2, 0x05, 0x97, 0x9a, 0xbe, 0x17, 0xf2, 0x2c, 0x1e, - 0xbb, 0xf4, 0x6a, 0x10, 0xf8, 0x81, 0xe0, 0x5d, 0x3e, 0x25, 0x6f, 0x6e, 0xf6, 0x5c, 0xca, 0x22, - 0x89, 0xd9, 0x9c, 0xc8, 0x5b, 0x50, 0xea, 0x05, 0xfe, 0xae, 0xdb, 0xa2, 0x81, 0x74, 0xc1, 0x5c, - 0xcd, 0x23, 0xb5, 0xd1, 0xba, 0xa4, 0x19, 0x2f, 0x3d, 0xaa, 0x04, 0x35, 0x3f, 0xfb, 0xff, 0x54, - 0x60, 0x3a, 0x89, 0x4e, 0x7e, 0x1e, 0xa0, 0x17, 0xf8, 0x5d, 0x1a, 0x6d, 0x53, 0x1d, 0xe6, 0x74, - 0x73, 0xd4, 0xe4, 0x35, 0x8a, 0x9e, 0x72, 0x5b, 0x62, 0xcb, 0x45, 0x5c, 0x8a, 0x06, 0x47, 0x12, - 0xc0, 0xe4, 0x8e, 0xd8, 0x76, 0xa5, 0x16, 0xf2, 0x5a, 0x2e, 0x3a, 0x93, 0xe4, 0xcc, 0xe3, 0x73, - 0x64, 0x11, 0x2a, 0x46, 0x64, 0x13, 0x0a, 0xf7, 0xe8, 0x66, 0x3e, 0x99, 0x13, 0xee, 0x50, 0x79, - 0x9a, 0xa9, 0x4f, 0x1e, 0xec, 0x57, 0x0b, 0x77, 0xe8, 0x26, 0x32, 0xe2, 0xec, 0xbb, 0x5a, 0xc2, - 0x77, 0x41, 0x2e, 0x15, 0xaf, 0xe5, 0xe8, 0x08, 0x21, 0xbe, 0x4b, 0x16, 0xa1, 0x62, 0x44, 0xde, - 0x82, 0xf2, 0x3d, 0x67, 0x97, 0x6e, 0x05, 0xbe, 0x17, 0x49, 0x5f, 0xb9, 0x11, 0x83, 0x4b, 0xee, - 0x28, 0x72, 0x92, 0x2f, 0xdf, 0xde, 0x75, 0x21, 0xc6, 0xec, 0xc8, 0x2e, 0x94, 0x3c, 0x7a, 0x0f, - 0x69, 0xc7, 0x6d, 0xe6, 0x13, 0xcc, 0x71, 0x53, 0x52, 0x93, 0x9c, 0xf9, 0xbe, 0xa7, 0xca, 0x50, - 0xf3, 0x62, 0x7d, 0x79, 0xd7, 0xdf, 0x94, 0x0b, 0xd5, 0x88, 0x7d, 0xa9, 0x4f, 0xa6, 0xa2, 0x2f, - 0x6f, 0xf8, 0x9b, 0xc8, 0x88, 0xb3, 0x39, 0xd2, 0xd4, 0x8e, 0x5a, 0x72, 0x99, 0xba, 0x99, 0xaf, - 0x83, 0x9a, 0x98, 0x23, 0x71, 0x29, 0x1a, 0x1c, 0x59, 0xdb, 0xb6, 0xa5, 0xb1, 0x52, 0x2e, 0x54, - 0x23, 0xb6, 0x6d, 0xd2, 0xf4, 0x29, 0xda, 0x56, 0x95, 0xa1, 0xe6, 0xc5, 0xf8, 0xba, 0xd2, 0xf2, - 0x97, 0xcf, 0x52, 0x95, 0xb4, 0x23, 0x0a, 0xbe, 0xaa, 0x0c, 0x35, 0x2f, 0xd6, 0xde, 0xe1, 0xce, - 0xde, 0x3d, 0xa7, 0xb3, 0xe3, 0x7a, 0x6d, 0x19, 0xb6, 0x3b, 0x6a, 0x98, 0xdb, 0xce, 0xde, 0x1d, - 0x41, 0xcf, 0x6c, 0xef, 0xb8, 0x14, 0x0d, 0x8e, 0xe4, 0xef, 0x5a, 0x3a, 0x14, 0x67, 0x2a, 0x0f, - 0x27, 0xa6, 0xe4, 0x92, 0x2b, 0x23, 0x73, 0x84, 0xa2, 0xf8, 0x53, 0xda, 0xef, 0x92, 0x17, 0x7e, - 0xed, 0x8f, 0xaa, 0x73, 0xd4, 0x6b, 0xfa, 0x2d, 0xd7, 0x6b, 0x2f, 0xde, 0x0d, 0x7d, 0x6f, 0x01, - 0x9d, 0x7b, 0x4a, 0x47, 0x97, 0x32, 0xcd, 0x7f, 0x0c, 0x2a, 0x06, 0x89, 0xa3, 0x14, 0xbd, 0x29, - 0x53, 0xd1, 0xfb, 0x8d, 0x09, 0x98, 0x32, 0xf3, 0x90, 0x1e, 0x43, 0xfb, 0xd2, 0x27, 0x8e, 0xb1, - 0x93, 0x9c, 0x38, 0xd8, 0x11, 0xd3, 0xb8, 0xe0, 0x52, 0xe6, 0xad, 0x95, 0xdc, 0x14, 0xee, 0xf8, - 0x88, 0x69, 0x14, 0x86, 0x98, 0x60, 0x7a, 0x02, 0x9f, 0x17, 0xa6, 0xb6, 0x0a, 0xc5, 0xae, 0x98, - 0x54, 0x5b, 0x13, 0xaa, 0xda, 0x73, 0x00, 0x71, 0xc2, 0x4c, 0x79, 0xf1, 0xa9, 0xf5, 0x61, 0x23, - 0x91, 0xa7, 0x81, 0x45, 0x9e, 0x86, 0x09, 0xa6, 0xfa, 0xd0, 0x96, 0xcc, 0x2a, 0xa0, 0xcf, 0xf1, - 0xd7, 0x78, 0x29, 0x4a, 0x28, 0x79, 0x89, 0x69, 0xa9, 0xb1, 0xc2, 0x22, 0x93, 0x05, 0x5c, 0x8c, - 0xb5, 0xd4, 0x18, 0x86, 0x09, 0x4c, 0x26, 0x3a, 0x65, 0xfa, 0x05, 0x5f, 0x1b, 0x0c, 0xd1, 0xb9, - 0xd2, 0x81, 0x02, 0xc6, 0xed, 0x4a, 0x29, 0x7d, 0x84, 0xcf, 0xe9, 0xa2, 0x61, 0x57, 0x4a, 0xc1, - 0x71, 0xa0, 0x06, 0xfb, 0x18, 0x79, 0x67, 0x5b, 0x11, 0x0e, 0xd3, 0x43, 0x6e, 0x5b, 0xbf, 0x62, - 0x9e, 0xb5, 0x72, 0x9c, 0x43, 0x62, 0xd4, 0x1e, 0xff, 0xb0, 0x35, 0xda, 0xb1, 0xe8, 0xb3, 0x30, - 0x9d, 0xdc, 0x85, 0x72, 0xbf, 0xf9, 0xf8, 0xea, 0x38, 0x5c, 0xb8, 0xd9, 0x76, 0xbd, 0x74, 0xce, - 0xb7, 0xac, 0x07, 0x1e, 0xac, 0x13, 0x3f, 0xf0, 0xa0, 0x63, 0xf2, 0xe4, 0xf3, 0x09, 0xd9, 0x31, - 0x79, 0xea, 0x2d, 0x8b, 0x24, 0x2e, 0xf9, 0x43, 0x0b, 0x1e, 0x77, 0x5a, 0xe2, 0x5c, 0xe0, 0x74, - 0x64, 0xa9, 0x91, 0x97, 0x5c, 0xce, 0xe8, 0x70, 0xc4, 0x5d, 0x7e, 0xf0, 0xe3, 0x17, 0x6a, 0x87, - 0x70, 0x15, 0x3d, 0xfe, 0x93, 0xf2, 0x0b, 0x1e, 0x3f, 0x0c, 0x15, 0x0f, 0x15, 0x9f, 0xfc, 0x65, - 0x98, 0x49, 0x7c, 0xb0, 0xb4, 0x84, 0x97, 0xc5, 0x85, 0x45, 0x23, 0x09, 0xc2, 0x34, 0xee, 0xfc, - 0x2d, 0xf8, 0x89, 0x23, 0xe5, 0x3c, 0xd1, 0x60, 0xfb, 0x9e, 0x05, 0x53, 0x66, 0x7a, 0x26, 0xf2, - 0x2c, 0x94, 0x22, 0x7f, 0x87, 0x7a, 0xb7, 0x03, 0xe5, 0xb0, 0xab, 0x07, 0xfa, 0x06, 0x2f, 0xc7, - 0x55, 0xd4, 0x18, 0x0c, 0xbb, 0xd9, 0x71, 0xa9, 0x17, 0xad, 0xb4, 0x64, 0x37, 0x6b, 0xec, 0x25, - 0x51, 0xbe, 0x8c, 0x1a, 0x43, 0xf8, 0xd8, 0xb1, 0xdf, 0x0d, 0xda, 0x0c, 0xa8, 0x72, 0xef, 0x37, - 0x7c, 0xec, 0x62, 0x18, 0x26, 0x30, 0x89, 0xad, 0x4d, 0x9c, 0xe3, 0xf1, 0xbd, 0x46, 0xca, 0x24, - 0xf9, 0x1d, 0x0b, 0xca, 0xc2, 0x44, 0x8f, 0x74, 0x2b, 0xe5, 0x62, 0x9b, 0x32, 0x22, 0xd4, 0xd6, - 0x57, 0xb2, 0x5c, 0x6c, 0x9f, 0x84, 0xf1, 0x1d, 0xd7, 0x53, 0x5f, 0xa2, 0xb7, 0xa5, 0xd7, 0x5c, - 0xaf, 0x85, 0x1c, 0xa2, 0x37, 0xae, 0xc2, 0xd0, 0x8d, 0x6b, 0x11, 0xca, 0xda, 0xf1, 0x44, 0x2e, - 0xff, 0xda, 0x7a, 0xab, 0x1d, 0x55, 0x30, 0xc6, 0xb1, 0x7f, 0xcd, 0x82, 0x69, 0x1e, 0x31, 0x1e, - 0x9f, 0x87, 0x5f, 0xd4, 0xbe, 0x60, 0x42, 0xee, 0x27, 0x92, 0xbe, 0x60, 0xef, 0xed, 0x57, 0x2b, - 0x22, 0xc6, 0x3c, 0xe9, 0x1a, 0xf6, 0x69, 0x69, 0x44, 0xe3, 0x1e, 0x6b, 0x63, 0x27, 0xb6, 0xf1, - 0xc4, 0x62, 0x2a, 0x22, 0x18, 0xd3, 0xb3, 0xdf, 0x86, 0x29, 0x33, 0x18, 0x8b, 0xbc, 0x08, 0x95, - 0x9e, 0xeb, 0xb5, 0x93, 0x41, 0xbb, 0xfa, 0xa2, 0x61, 0x3d, 0x06, 0xa1, 0x89, 0xc7, 0xab, 0xf9, - 0x71, 0xb5, 0xd4, 0xfd, 0xc4, 0xba, 0x6f, 0x56, 0x8b, 0xff, 0xd8, 0x1e, 0x40, 0x1c, 0x59, 0x7c, - 0x2c, 0xe3, 0xcd, 0x84, 0xb0, 0xfd, 0x0b, 0x65, 0x84, 0x67, 0x89, 0x98, 0x10, 0x23, 0xfc, 0xbd, - 0xfd, 0xc3, 0x94, 0x1d, 0x51, 0x8b, 0xbf, 0x41, 0x91, 0x11, 0x64, 0x98, 0xfb, 0x1b, 0x14, 0x19, - 0x3c, 0xde, 0xbf, 0x37, 0x28, 0xb2, 0x84, 0xf9, 0xb3, 0xf5, 0x06, 0xc5, 0x27, 0xe1, 0xa4, 0xe9, - 0x68, 0x99, 0x6e, 0x71, 0xcf, 0x4c, 0x1b, 0xa1, 0x5b, 0x5c, 0xe6, 0x8d, 0x90, 0x50, 0xfb, 0xb7, - 0x0b, 0x30, 0x9b, 0x36, 0x31, 0xe4, 0xed, 0xbd, 0x41, 0xbe, 0x6e, 0xc1, 0xb4, 0x93, 0x48, 0xfd, - 0x97, 0xd3, 0x83, 0x56, 0x09, 0x9a, 0x46, 0xea, 0xb9, 0x44, 0x39, 0xa6, 0x78, 0x93, 0xbf, 0x00, - 0x93, 0x91, 0xdb, 0xa5, 0x7e, 0x5f, 0x18, 0x1e, 0x0b, 0xc2, 0x00, 0xb0, 0x21, 0x8a, 0x50, 0xc1, - 0xd8, 0x26, 0xe0, 0x72, 0x8d, 0x2d, 0xa0, 0xd2, 0x13, 0x79, 0x36, 0xb6, 0x94, 0x8a, 0x72, 0xd4, - 0x18, 0xe4, 0x3e, 0x4c, 0x0a, 0x3f, 0x0f, 0xe5, 0xd0, 0xb3, 0x96, 0x93, 0x29, 0x44, 0xb8, 0x92, - 0xc4, 0x5d, 0x20, 0xfe, 0x87, 0xa8, 0xd8, 0xd9, 0x1f, 0x81, 0x13, 0xe6, 0xe7, 0xb5, 0xaf, 0x02, - 0x41, 0xbf, 0xd3, 0xd9, 0x74, 0x9a, 0x3b, 0x77, 0x5c, 0xaf, 0xe5, 0xdf, 0xe3, 0x4b, 0xdf, 0x22, - 0x94, 0x03, 0x19, 0xa2, 0x1b, 0xca, 0x51, 0xa3, 0xd7, 0x4e, 0x15, 0xbb, 0x1b, 0x62, 0x8c, 0x63, - 0xff, 0xde, 0x18, 0x4c, 0xca, 0x78, 0xf2, 0x07, 0x10, 0x09, 0xb1, 0x93, 0xb8, 0x7f, 0x5e, 0xc9, - 0x25, 0x0c, 0x7e, 0x68, 0x18, 0x44, 0x98, 0x0a, 0x83, 0x78, 0x2d, 0x1f, 0x76, 0x87, 0xc7, 0x40, - 0x7c, 0xb7, 0x08, 0x33, 0xa9, 0xf8, 0xfc, 0x54, 0x2a, 0x6f, 0xeb, 0x7d, 0x49, 0xe5, 0x4d, 0xc2, - 0x44, 0x3a, 0xf7, 0xfc, 0xfc, 0x26, 0xff, 0x3c, 0xb3, 0x7b, 0x5e, 0x1e, 0xad, 0xc5, 0x0f, 0x8e, - 0x47, 0xeb, 0x7f, 0xb1, 0xe0, 0xd1, 0xa1, 0x59, 0x26, 0x78, 0xbe, 0xb6, 0x20, 0x09, 0x95, 0xeb, - 0x45, 0xce, 0x99, 0x7b, 0xf4, 0x5d, 0x75, 0x3a, 0xc5, 0x56, 0x9a, 0x3d, 0x79, 0x01, 0xa6, 0xb8, - 0x3e, 0xc8, 0x56, 0xce, 0x88, 0xf6, 0xe4, 0x55, 0x1b, 0xbf, 0x74, 0x69, 0x18, 0xe5, 0x98, 0xc0, - 0xb2, 0xbf, 0x6d, 0xc1, 0xdc, 0xb0, 0xec, 0x5d, 0xc7, 0xd0, 0xe4, 0xfe, 0x52, 0x2a, 0x92, 0xa4, - 0x3a, 0x10, 0x49, 0x92, 0x32, 0x05, 0xa9, 0xa0, 0x11, 0xc3, 0x0a, 0x53, 0x38, 0x22, 0x50, 0xe2, - 0xf7, 0x0b, 0x30, 0x2b, 0x45, 0x8c, 0x95, 0xf0, 0x97, 0x12, 0xf1, 0x2f, 0x3f, 0x99, 0x8a, 0x7f, - 0xb9, 0x98, 0xc6, 0xff, 0xf3, 0xe0, 0x97, 0x0f, 0x56, 0xf0, 0xcb, 0xd7, 0x8a, 0x70, 0x29, 0x33, - 0x4f, 0x16, 0xf9, 0x6a, 0xc6, 0x4e, 0x71, 0x27, 0xe7, 0x84, 0x5c, 0x3a, 0x4e, 0xf6, 0x6c, 0x23, - 0x46, 0x7e, 0xc5, 0x8c, 0xd4, 0x10, 0xab, 0xff, 0xd6, 0x19, 0xa4, 0x16, 0x3b, 0x69, 0xd0, 0xc6, - 0x83, 0x7d, 0xea, 0xec, 0xcf, 0xc0, 0x52, 0xff, 0xb5, 0x02, 0x5c, 0x39, 0x6e, 0xcb, 0x7e, 0x40, - 0xa3, 0x1c, 0xc3, 0x44, 0x94, 0xe3, 0x03, 0x52, 0x6d, 0xce, 0x24, 0xe0, 0xf1, 0xef, 0x8f, 0xeb, - 0x7d, 0x77, 0x70, 0xc2, 0x1e, 0xcb, 0xb6, 0x30, 0xc9, 0x54, 0x5f, 0x95, 0x10, 0x3e, 0xde, 0x1b, - 0x26, 0x1b, 0xa2, 0xf8, 0xbd, 0xfd, 0xea, 0xf9, 0x38, 0xa1, 0x8c, 0x2c, 0x44, 0x55, 0x89, 0x5c, - 0x81, 0x52, 0x20, 0xa0, 0x2a, 0xae, 0x4b, 0x7a, 0xd7, 0x88, 0x32, 0xd4, 0x50, 0xf2, 0x05, 0xe3, - 0xac, 0x30, 0x7e, 0x56, 0x79, 0x93, 0x0e, 0x73, 0x1a, 0x7a, 0x13, 0x4a, 0xa1, 0xca, 0x5a, 0x2e, - 0xa6, 0xd3, 0xf3, 0xc7, 0x0c, 0x17, 0x74, 0x36, 0x69, 0x47, 0xa5, 0x30, 0x17, 0xdf, 0xa7, 0x13, - 0x9c, 0x6b, 0x92, 0xc4, 0xd6, 0x67, 0x6f, 0x71, 0xa9, 0x01, 0x83, 0xe7, 0x6e, 0x12, 0xc1, 0xa4, - 0x7c, 0xba, 0x58, 0xde, 0xb6, 0xae, 0xe5, 0x14, 0x77, 0x23, 0xbd, 0xb2, 0xf9, 0x91, 0x56, 0xd9, - 0x9c, 0x14, 0x2b, 0xfb, 0x07, 0x16, 0x54, 0xe4, 0x18, 0x79, 0x00, 0x71, 0x93, 0x77, 0x93, 0x71, - 0x93, 0x57, 0x73, 0x59, 0xc2, 0x87, 0x04, 0x4d, 0xde, 0x85, 0x29, 0x33, 0x63, 0x25, 0xf9, 0x94, - 0xb1, 0x05, 0x59, 0xa3, 0x64, 0x65, 0x53, 0x9b, 0x54, 0xbc, 0x3d, 0xd9, 0xff, 0xb8, 0xac, 0x5b, - 0x91, 0x1f, 0x9c, 0xcd, 0x91, 0x6f, 0x1d, 0x3a, 0xf2, 0xcd, 0x81, 0x37, 0x96, 0xff, 0xc0, 0x7b, - 0x1d, 0x4a, 0x6a, 0x59, 0x94, 0xda, 0xd4, 0x53, 0xa6, 0x9b, 0x36, 0x53, 0xc9, 0x18, 0x31, 0x63, - 0xba, 0xf0, 0x03, 0x70, 0x6c, 0x09, 0x57, 0xcb, 0xb5, 0x26, 0x43, 0xde, 0x82, 0xca, 0x3d, 0x3f, - 0xd8, 0xe9, 0xf8, 0x0e, 0x7f, 0x2a, 0x02, 0xf2, 0xf0, 0x0c, 0xd0, 0xd6, 0x6c, 0x11, 0x2b, 0x73, - 0x27, 0xa6, 0x8f, 0x26, 0x33, 0x52, 0x83, 0x99, 0xae, 0xeb, 0x21, 0x75, 0x5a, 0x3a, 0x3c, 0x72, - 0x5c, 0xa4, 0x69, 0x57, 0xba, 0xfd, 0x5a, 0x12, 0x8c, 0x69, 0x7c, 0x6e, 0x79, 0x0a, 0x12, 0xa6, - 0x0e, 0x99, 0x8b, 0x79, 0x7d, 0xf4, 0xc1, 0x98, 0x34, 0x9f, 0x88, 0x60, 0x91, 0x64, 0x39, 0xa6, - 0x78, 0x93, 0xcf, 0x43, 0x29, 0x54, 0x8f, 0x82, 0x16, 0x73, 0x3c, 0xf5, 0xe8, 0x87, 0x41, 0x75, - 0x57, 0xea, 0x97, 0x41, 0x35, 0x43, 0xb2, 0x0a, 0x17, 0x95, 0xed, 0x26, 0xf1, 0xbe, 0xe1, 0x44, - 0x9c, 0x4f, 0x0c, 0x33, 0xe0, 0x98, 0x59, 0x8b, 0xe9, 0xb6, 0x3c, 0x13, 0xac, 0xb8, 0x89, 0x35, - 0x2e, 0x2f, 0xf9, 0xfc, 0x6b, 0xa1, 0x84, 0x1e, 0x16, 0xfd, 0x5b, 0x1a, 0x21, 0xfa, 0xb7, 0x01, - 0x97, 0xd2, 0x20, 0x9e, 0x28, 0x8e, 0xe7, 0xa6, 0x33, 0xb6, 0xd0, 0xf5, 0x2c, 0x24, 0xcc, 0xae, - 0x4b, 0xee, 0x40, 0x39, 0xa0, 0xfc, 0x94, 0x57, 0x53, 0x4e, 0x6c, 0x27, 0x76, 0xd7, 0x45, 0x45, - 0x00, 0x63, 0x5a, 0xac, 0xdf, 0x9d, 0x64, 0xe2, 0xf4, 0xd7, 0x73, 0x7c, 0x35, 0x5c, 0xf6, 0xfd, - 0x90, 0x04, 0x8e, 0xf6, 0xbf, 0x99, 0x81, 0x73, 0x09, 0x03, 0x14, 0x79, 0x0a, 0x8a, 0x3c, 0x73, - 0x1e, 0x5f, 0xad, 0x4a, 0xf1, 0x8a, 0x2a, 0x1a, 0x47, 0xc0, 0xc8, 0x2f, 0x59, 0x30, 0xd3, 0x4b, - 0x5c, 0xe0, 0xa8, 0x85, 0x7c, 0x44, 0xab, 0x6d, 0xf2, 0x56, 0xc8, 0x78, 0x72, 0x24, 0xc9, 0x0c, - 0xd3, 0xdc, 0xd9, 0x7a, 0x20, 0x7d, 0xde, 0x3b, 0x34, 0xe0, 0xd8, 0x52, 0xd1, 0xd3, 0x24, 0x96, - 0x92, 0x60, 0x4c, 0xe3, 0xb3, 0x1e, 0xe6, 0x5f, 0x37, 0xca, 0xcb, 0xb0, 0x35, 0x45, 0x00, 0x63, - 0x5a, 0xe4, 0x15, 0x98, 0x96, 0xf9, 0xb2, 0xd7, 0xfd, 0xd6, 0x75, 0x27, 0xdc, 0x96, 0x47, 0x3e, - 0x7d, 0x44, 0x5d, 0x4a, 0x40, 0x31, 0x85, 0xcd, 0xbf, 0x2d, 0x4e, 0x4a, 0xce, 0x09, 0x4c, 0x24, - 0x5f, 0x64, 0x59, 0x4a, 0x82, 0x31, 0x8d, 0x4f, 0x9e, 0x35, 0xb6, 0x21, 0xe1, 0x1d, 0xa1, 0x57, - 0x83, 0x8c, 0xad, 0xa8, 0x06, 0x33, 0x7d, 0x7e, 0x42, 0x6e, 0x29, 0xa0, 0x9c, 0x8f, 0x9a, 0xe1, - 0xed, 0x24, 0x18, 0xd3, 0xf8, 0xe4, 0x65, 0x38, 0x17, 0xb0, 0xc5, 0x56, 0x13, 0x10, 0x2e, 0x13, - 0xfa, 0x46, 0x1c, 0x4d, 0x20, 0x26, 0x71, 0xc9, 0xab, 0x70, 0x3e, 0xce, 0xa9, 0xaa, 0x08, 0x08, - 0x1f, 0x0a, 0x9d, 0xe0, 0xaf, 0x96, 0x46, 0xc0, 0xc1, 0x3a, 0xe4, 0xaf, 0xc2, 0xac, 0xd1, 0x12, - 0x2b, 0x5e, 0x8b, 0xde, 0x97, 0x79, 0x2f, 0xf9, 0x0b, 0x63, 0x4b, 0x29, 0x18, 0x0e, 0x60, 0x93, - 0x8f, 0xc3, 0x74, 0xd3, 0xef, 0x74, 0xf8, 0x1a, 0x27, 0x5e, 0x03, 0x11, 0x09, 0x2e, 0x45, 0x2a, - 0xd0, 0x04, 0x04, 0x53, 0x98, 0xe4, 0x06, 0x10, 0x7f, 0x93, 0xa9, 0x57, 0xb4, 0xf5, 0x2a, 0xf5, - 0xa8, 0xd4, 0x38, 0xce, 0x25, 0x23, 0x6e, 0x6e, 0x0d, 0x60, 0x60, 0x46, 0x2d, 0x9e, 0x1f, 0xd0, - 0x88, 0x50, 0x9e, 0xce, 0x23, 0x23, 0x79, 0xda, 0x9e, 0x73, 0x64, 0x78, 0x72, 0x00, 0x13, 0x22, - 0x00, 0x2a, 0x9f, 0x4c, 0x97, 0xe6, 0xc3, 0x00, 0xf1, 0x1e, 0x21, 0x4a, 0x51, 0x72, 0x22, 0x3f, - 0x0f, 0xe5, 0x4d, 0xf5, 0x4a, 0x0c, 0x4f, 0x6f, 0x39, 0xf2, 0xbe, 0x98, 0x7a, 0xf0, 0x28, 0xb6, - 0x57, 0x68, 0x00, 0xc6, 0x2c, 0xc9, 0xd3, 0x50, 0xb9, 0xbe, 0x5e, 0xd3, 0xa3, 0xf0, 0x3c, 0xef, - 0xfd, 0x71, 0x56, 0x05, 0x4d, 0x00, 0x9b, 0x61, 0x5a, 0x7d, 0x23, 0x49, 0xb7, 0x80, 0x0c, 0x6d, - 0x8c, 0x61, 0x73, 0x3f, 0x07, 0x6c, 0xcc, 0x5d, 0x48, 0x61, 0xcb, 0x72, 0xd4, 0x18, 0xe4, 0x4d, - 0xa8, 0xc8, 0xfd, 0x82, 0xaf, 0x4d, 0x17, 0x4f, 0x17, 0xfd, 0x8e, 0x31, 0x09, 0x34, 0xe9, 0xf1, - 0x0b, 0x6a, 0xfe, 0x78, 0x06, 0xbd, 0xd6, 0xef, 0x74, 0xe6, 0x2e, 0xf1, 0x75, 0x33, 0xbe, 0xa0, - 0x8e, 0x41, 0x68, 0xe2, 0x91, 0xe7, 0x95, 0xbf, 0xda, 0xc3, 0x89, 0x1b, 0x7b, 0xed, 0xaf, 0xa6, - 0x95, 0xee, 0x21, 0x01, 0x32, 0x8f, 0x1c, 0xe1, 0x28, 0xb6, 0x09, 0xf3, 0x4a, 0xe3, 0x1b, 0x9c, - 0x24, 0x73, 0x73, 0x09, 0xdb, 0xd1, 0xfc, 0x9d, 0xa1, 0x98, 0x78, 0x08, 0x15, 0xb2, 0x09, 0x05, - 0xa7, 0xb3, 0x39, 0xf7, 0x68, 0x1e, 0xaa, 0x6b, 0x6d, 0xb5, 0x2e, 0x47, 0x14, 0x77, 0x6a, 0xad, - 0xad, 0xd6, 0x91, 0x11, 0x27, 0x2e, 0x8c, 0x3b, 0x9d, 0xcd, 0x70, 0x6e, 0x9e, 0xcf, 0xd9, 0xdc, - 0x98, 0xc4, 0xc6, 0x83, 0xd5, 0x7a, 0x88, 0x9c, 0x85, 0xfd, 0xc5, 0x31, 0x7d, 0x4b, 0xa4, 0x93, - 0x8d, 0xbf, 0x6d, 0x4e, 0x20, 0x71, 0xdc, 0xb9, 0x95, 0xdb, 0x04, 0x92, 0xea, 0xc5, 0xb9, 0xa1, - 0xd3, 0xa7, 0xa7, 0x97, 0x8c, 0x5c, 0xb2, 0x94, 0x25, 0x13, 0xa9, 0x8b, 0xd3, 0x73, 0x72, 0xc1, - 0xb0, 0xbf, 0x54, 0xd1, 0x56, 0xd0, 0x94, 0xaf, 0x57, 0x00, 0x45, 0x37, 0x8c, 0x5c, 0x3f, 0xc7, - 0xa0, 0xf0, 0x54, 0x06, 0x72, 0x1e, 0x73, 0xc2, 0x01, 0x28, 0x58, 0x31, 0x9e, 0x5e, 0xdb, 0xf5, - 0xee, 0xcb, 0xcf, 0x7f, 0x3d, 0x77, 0x27, 0x2e, 0xc1, 0x93, 0x03, 0x50, 0xb0, 0x22, 0x77, 0xc5, - 0xa0, 0x2e, 0xe4, 0xd1, 0xd7, 0xb5, 0xd5, 0x7a, 0x8a, 0x5f, 0x72, 0x70, 0xdf, 0x85, 0x42, 0xd8, - 0x75, 0xa5, 0xba, 0x34, 0x22, 0xaf, 0xc6, 0xda, 0x4a, 0x16, 0xaf, 0xc6, 0xda, 0x0a, 0x32, 0x26, - 0xe4, 0x2b, 0x16, 0x80, 0xd3, 0xdd, 0x74, 0xc2, 0xd0, 0x69, 0x69, 0xeb, 0xcc, 0x88, 0x8f, 0xac, - 0xd4, 0x34, 0xbd, 0x14, 0x6b, 0xee, 0xb6, 0x1c, 0x43, 0xd1, 0xe0, 0x4c, 0xde, 0x82, 0x49, 0x47, - 0xbc, 0x62, 0x29, 0x3d, 0xf0, 0xf3, 0x79, 0x9a, 0x35, 0x25, 0x01, 0x37, 0xd3, 0x48, 0x10, 0x2a, - 0x86, 0x8c, 0x77, 0x14, 0x38, 0x74, 0xcb, 0xdd, 0x91, 0xc6, 0xa1, 0xc6, 0xc8, 0xef, 0xac, 0x30, - 0x62, 0x59, 0xbc, 0x25, 0x08, 0x15, 0x43, 0xf2, 0x0b, 0x16, 0x9c, 0xeb, 0x3a, 0x9e, 0xa3, 0xe3, - 0x2a, 0xf3, 0x89, 0xbe, 0x35, 0x23, 0x35, 0x63, 0x0d, 0x71, 0xcd, 0x64, 0x84, 0x49, 0xbe, 0x64, - 0x17, 0x26, 0x1c, 0xfe, 0xbe, 0xae, 0x3c, 0x8a, 0x61, 0x1e, 0x6f, 0xf5, 0xa6, 0xda, 0x80, 0x2f, - 0x2e, 0xf2, 0x15, 0x5f, 0xc9, 0x8d, 0xfc, 0xba, 0x05, 0x93, 0xc2, 0x39, 0x9c, 0x29, 0xa4, 0xec, - 0xdb, 0x3f, 0x7b, 0x06, 0x2f, 0x19, 0x48, 0xc7, 0x75, 0xe9, 0x7e, 0xf4, 0x21, 0xed, 0xf9, 0x2a, - 0x4a, 0x0f, 0x75, 0x5d, 0x57, 0xd2, 0x31, 0xd5, 0xb7, 0xeb, 0xdc, 0x4f, 0xbc, 0xa2, 0x63, 0xaa, - 0xbe, 0x6b, 0x29, 0x18, 0x0e, 0x60, 0xcf, 0x7f, 0x1c, 0xa6, 0x4c, 0x39, 0x4e, 0xe4, 0xfe, 0xfe, - 0xa3, 0x02, 0x00, 0xef, 0x2a, 0x91, 0x8b, 0xa5, 0xcb, 0x13, 0x37, 0x6f, 0xfb, 0xad, 0x9c, 0x5e, - 0xf3, 0x34, 0x52, 0xaa, 0x80, 0xcc, 0xd2, 0xbc, 0xed, 0xb7, 0x50, 0x32, 0x21, 0x6d, 0x18, 0xef, - 0x39, 0xd1, 0x76, 0xfe, 0xf9, 0x5b, 0x4a, 0x22, 0x28, 0x39, 0xda, 0x46, 0xce, 0x80, 0xbc, 0x63, - 0xc5, 0x9e, 0x3d, 0x85, 0x3c, 0x72, 0xcf, 0xc6, 0x6d, 0xb6, 0x20, 0x7d, 0x79, 0x52, 0x29, 0x58, - 0xd3, 0x1e, 0x3e, 0xf3, 0xef, 0x5a, 0x30, 0x65, 0xa2, 0x66, 0x74, 0xd3, 0xcf, 0x99, 0xdd, 0x94, - 0x67, 0x7b, 0x98, 0x3d, 0xfe, 0xdf, 0x2c, 0x00, 0xec, 0x7b, 0x8d, 0x7e, 0xb7, 0xcb, 0xd4, 0x76, - 0xed, 0xe5, 0x6f, 0x1d, 0xdb, 0xcb, 0x7f, 0xec, 0x84, 0x5e, 0xfe, 0x85, 0x13, 0x79, 0xf9, 0x8f, - 0x9f, 0xdc, 0xcb, 0xbf, 0x38, 0xdc, 0xcb, 0xdf, 0xfe, 0xa6, 0x05, 0xe7, 0x07, 0xf6, 0x2b, 0xa6, - 0x49, 0x07, 0xbe, 0x1f, 0x0d, 0xf1, 0x10, 0xc5, 0x18, 0x84, 0x26, 0x1e, 0x59, 0x86, 0x59, 0xf9, - 0x4c, 0x49, 0xa3, 0xd7, 0x71, 0x33, 0x73, 0xeb, 0x6c, 0xa4, 0xe0, 0x38, 0x50, 0xc3, 0xfe, 0x6d, - 0x0b, 0x2a, 0x46, 0x44, 0x3e, 0xfb, 0x0e, 0xee, 0x26, 0x2c, 0xc5, 0x88, 0x5f, 0x68, 0xe1, 0x57, - 0x5d, 0x02, 0x26, 0xae, 0xa1, 0xdb, 0x46, 0x12, 0xfb, 0xf8, 0x1a, 0x9a, 0x95, 0xa2, 0x84, 0x8a, - 0xf4, 0xe4, 0xb4, 0xc7, 0x1b, 0xbd, 0x60, 0xa6, 0x27, 0xa7, 0x3d, 0xe4, 0x10, 0xce, 0x8e, 0x1d, - 0x29, 0xa4, 0x07, 0xb0, 0xf1, 0x20, 0x8c, 0x13, 0x44, 0x28, 0x60, 0xe4, 0x09, 0x28, 0x50, 0xaf, - 0x25, 0xed, 0x1f, 0xfa, 0xf5, 0xda, 0xab, 0x5e, 0x0b, 0x59, 0xb9, 0x7d, 0x0b, 0xa6, 0x84, 0xf7, - 0xf3, 0x6b, 0x74, 0xef, 0xd8, 0xcf, 0xe1, 0xb2, 0xd1, 0x9e, 0x7a, 0x0e, 0x97, 0x55, 0x67, 0xe5, - 0xf6, 0x3f, 0xb2, 0x20, 0xf5, 0x46, 0x92, 0x71, 0x03, 0x63, 0x0d, 0xbd, 0x81, 0x31, 0xad, 0xf6, - 0x63, 0x87, 0x5a, 0xed, 0x6f, 0x00, 0xe9, 0xb2, 0xa9, 0x90, 0x5c, 0x68, 0x0b, 0xc9, 0xa7, 0x24, - 0xd6, 0x06, 0x30, 0x30, 0xa3, 0x96, 0xfd, 0x0f, 0x85, 0xb0, 0xe6, 0xab, 0x49, 0x47, 0x37, 0x40, - 0x1f, 0x8a, 0x9c, 0x94, 0xb4, 0xbf, 0x8d, 0x68, 0xbb, 0x1e, 0xcc, 0xa3, 0x15, 0x77, 0xa4, 0x9c, - 0xf2, 0x9c, 0x9b, 0xfd, 0xfb, 0x42, 0x56, 0xf3, 0x59, 0xa5, 0xa3, 0x65, 0xed, 0x26, 0x65, 0xbd, - 0x9e, 0xd7, 0x5a, 0x99, 0x2d, 0x23, 0x59, 0x00, 0xe8, 0xd1, 0xa0, 0x49, 0xbd, 0x48, 0xc5, 0x25, - 0x15, 0x65, 0x84, 0xac, 0x2e, 0x45, 0x03, 0xc3, 0xfe, 0x06, 0x9b, 0x40, 0xf1, 0x43, 0xd1, 0xe4, - 0x4a, 0xda, 0xd5, 0x35, 0x3d, 0x39, 0xb4, 0xa7, 0xab, 0x11, 0xad, 0x32, 0x76, 0x44, 0xb4, 0xca, - 0x33, 0x30, 0x19, 0xf8, 0x1d, 0x5a, 0x0b, 0xbc, 0xb4, 0x8f, 0x0e, 0xb2, 0x62, 0xbc, 0x89, 0x0a, - 0x6e, 0xff, 0xaa, 0x05, 0xb3, 0xe9, 0x70, 0xba, 0xdc, 0xfd, 0x6f, 0xcd, 0x98, 0xff, 0xc2, 0xc9, - 0x63, 0xfe, 0xed, 0x7f, 0x37, 0x0e, 0xb3, 0xe9, 0x07, 0xec, 0x18, 0x67, 0x97, 0x1b, 0xdb, 0x52, - 0xab, 0xbf, 0xb0, 0xb2, 0x09, 0x98, 0x1e, 0x2f, 0x63, 0x43, 0xc7, 0xcb, 0x35, 0x28, 0xfb, 0x3d, - 0x75, 0xe0, 0x17, 0xc2, 0x5d, 0x51, 0xc6, 0x9a, 0x5b, 0x0a, 0xf0, 0xde, 0x7e, 0xf5, 0x42, 0x2c, - 0x80, 0x2e, 0xc6, 0xb8, 0x2a, 0xf9, 0x69, 0x65, 0xa9, 0x18, 0x4f, 0x64, 0xd1, 0xd1, 0x96, 0x8a, - 0x99, 0xb8, 0xfe, 0x30, 0x63, 0x45, 0xf1, 0x24, 0xd9, 0x3c, 0x26, 0x72, 0xcc, 0xe6, 0x71, 0x07, - 0xca, 0xd2, 0xb6, 0x7a, 0xaa, 0x2c, 0x16, 0x9c, 0xf0, 0x6d, 0x45, 0x00, 0x63, 0x5a, 0xa9, 0x34, - 0x21, 0xa5, 0x5c, 0xd3, 0x84, 0xbc, 0xa2, 0xdd, 0xc1, 0xca, 0x71, 0x2c, 0x82, 0x76, 0x05, 0x3b, - 0x24, 0x16, 0x41, 0x7a, 0xbb, 0xbe, 0xc3, 0x46, 0x7e, 0xe4, 0x36, 0x77, 0x5c, 0x4f, 0xe4, 0x5e, - 0x60, 0xd3, 0xf1, 0x19, 0x98, 0xa4, 0xf2, 0x15, 0x65, 0x71, 0x37, 0xa1, 0x7b, 0x43, 0x3d, 0x9e, - 0xac, 0xe0, 0xa4, 0x06, 0x33, 0xea, 0x46, 0x56, 0x5d, 0x28, 0x89, 0x9c, 0x31, 0xda, 0x80, 0xbd, - 0x9c, 0x04, 0x63, 0x1a, 0xdf, 0xfe, 0x02, 0x54, 0x0c, 0x4d, 0x87, 0x2b, 0x05, 0xf7, 0x9d, 0x66, - 0x94, 0xde, 0x4c, 0xaf, 0xb2, 0x42, 0x14, 0x30, 0x7e, 0xef, 0x25, 0x42, 0xc8, 0x52, 0x9b, 0xa9, - 0x0c, 0x1c, 0x93, 0x50, 0x46, 0x2c, 0xa0, 0x6d, 0x7a, 0x5f, 0x3d, 0x5c, 0xa1, 0x88, 0x21, 0x2b, - 0x44, 0x01, 0xb3, 0x9f, 0x85, 0x92, 0xca, 0xec, 0xc5, 0xd3, 0xe3, 0xa8, 0x3b, 0x19, 0x33, 0x3d, - 0x8e, 0x1f, 0x44, 0xc8, 0x21, 0xf6, 0x1b, 0x50, 0x52, 0x09, 0xc8, 0x8e, 0xc6, 0x66, 0xfb, 0x5b, - 0xe8, 0xb9, 0xd7, 0xfd, 0x30, 0x52, 0x59, 0xd3, 0xc4, 0xb5, 0xf1, 0xcd, 0x15, 0x5e, 0x86, 0x1a, - 0x6a, 0xff, 0xa9, 0x05, 0x95, 0x8d, 0x8d, 0x55, 0x6d, 0x4d, 0x42, 0x78, 0x38, 0x14, 0x2d, 0x54, - 0xdb, 0x8a, 0xa8, 0xe9, 0x9f, 0x22, 0xa6, 0xfa, 0xfc, 0xc1, 0x7e, 0xf5, 0xe1, 0x46, 0x26, 0x06, - 0x0e, 0xa9, 0x49, 0x56, 0xe0, 0x82, 0x09, 0x91, 0xd9, 0x2c, 0xe4, 0xc6, 0xcb, 0x9f, 0xdd, 0x6e, - 0x0c, 0x82, 0x31, 0xab, 0x4e, 0x9a, 0x94, 0xd4, 0x21, 0xcd, 0x17, 0xbc, 0x1b, 0x83, 0x60, 0xcc, - 0xaa, 0x63, 0x3f, 0x0f, 0x33, 0x29, 0xc7, 0x89, 0x63, 0x64, 0x11, 0xfa, 0x9d, 0x02, 0x4c, 0x99, - 0xf7, 0xe7, 0xc7, 0xd8, 0x14, 0x8f, 0xaf, 0x6b, 0x64, 0xdc, 0x79, 0x17, 0x4e, 0x78, 0xe7, 0x6d, - 0x3a, 0x19, 0x8c, 0x9f, 0xad, 0x93, 0x41, 0x31, 0x1f, 0x27, 0x03, 0xc3, 0x19, 0x66, 0xe2, 0xc1, - 0x39, 0xc3, 0xfc, 0x56, 0x11, 0xa6, 0x93, 0x69, 0x69, 0x8f, 0xd1, 0x93, 0xcf, 0x0e, 0xf4, 0xe4, - 0x09, 0x2f, 0xd9, 0x0a, 0xa3, 0x5e, 0xb2, 0x8d, 0x8f, 0x7a, 0xc9, 0x56, 0x3c, 0xc5, 0x25, 0xdb, - 0xe0, 0x15, 0xd9, 0xc4, 0xb1, 0xaf, 0xc8, 0x3e, 0xa1, 0x37, 0x8a, 0xc9, 0x84, 0x5f, 0x59, 0xbc, - 0x59, 0x90, 0x64, 0x37, 0x2c, 0xf9, 0xad, 0x4c, 0x7f, 0xe7, 0xd2, 0x11, 0xfb, 0x73, 0x90, 0xe9, - 0xe6, 0x7b, 0xf2, 0x7b, 0xfc, 0x87, 0x4f, 0xe0, 0xe2, 0xfb, 0x22, 0x54, 0xe4, 0x78, 0xe2, 0x27, - 0x3a, 0x48, 0x9e, 0x06, 0x1b, 0x31, 0x08, 0x4d, 0x3c, 0x36, 0x30, 0x7a, 0xf1, 0x04, 0xe1, 0xd7, - 0xbd, 0x95, 0xe4, 0x75, 0xef, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xfb, 0xf3, 0x70, 0x29, 0xd3, 0xae, - 0xc7, 0xef, 0x54, 0xf8, 0x61, 0x83, 0xb6, 0x24, 0x82, 0x21, 0x46, 0xea, 0xb5, 0x9a, 0xf9, 0x3b, - 0x43, 0x31, 0xf1, 0x10, 0x2a, 0xf6, 0x6f, 0x16, 0x60, 0x3a, 0xf9, 0x7a, 0x33, 0xb9, 0xa7, 0x6f, - 0x01, 0x72, 0xb9, 0x80, 0x10, 0x64, 0x8d, 0x54, 0xa7, 0x43, 0x6f, 0x0f, 0xef, 0xf1, 0xf1, 0xb5, - 0xa9, 0xf3, 0xae, 0x9e, 0x1d, 0x63, 0x79, 0x6d, 0x27, 0xd9, 0xf1, 0x37, 0x90, 0xe3, 0xa8, 0x68, - 0x69, 0x1c, 0xca, 0x9d, 0x7b, 0x1c, 0xdd, 0xab, 0x59, 0xa1, 0xc1, 0x96, 0xed, 0x2d, 0xbb, 0x34, - 0x70, 0xb7, 0x5c, 0xda, 0x92, 0x69, 0xf0, 0xf9, 0xca, 0xfd, 0x86, 0x2c, 0x43, 0x0d, 0xb5, 0xdf, - 0x19, 0x83, 0x32, 0x4f, 0xe2, 0x76, 0x2d, 0xf0, 0xbb, 0xfc, 0x5d, 0xcf, 0xd0, 0x38, 0x88, 0xcb, - 0x6e, 0xbb, 0x31, 0xea, 0x53, 0xbd, 0x31, 0x45, 0x19, 0x43, 0x61, 0x94, 0x60, 0x82, 0x23, 0xe9, - 0x41, 0x69, 0x4b, 0x26, 0x9d, 0x96, 0x7d, 0x37, 0x62, 0xe2, 0x54, 0x95, 0xc2, 0x5a, 0x34, 0x81, - 0xfa, 0x87, 0x9a, 0x8b, 0xed, 0xc0, 0x4c, 0x2a, 0x0b, 0x4f, 0xee, 0xa9, 0xaa, 0xff, 0xe7, 0x38, - 0x94, 0x75, 0xf0, 0x1e, 0xf9, 0x58, 0xc2, 0x2a, 0x5a, 0xae, 0xff, 0x84, 0xf1, 0xe8, 0xdc, 0xb6, - 0xdf, 0x62, 0x07, 0x13, 0x8d, 0x9c, 0xb2, 0x70, 0x3e, 0x01, 0x85, 0x7e, 0xd0, 0x49, 0x9b, 0x3d, - 0x6e, 0xe3, 0x2a, 0xb2, 0x72, 0x33, 0xe0, 0xb0, 0xf0, 0x40, 0x03, 0x0e, 0xd9, 0x2e, 0xb9, 0xe9, - 0xb7, 0xf6, 0xd2, 0x8f, 0xd4, 0xd5, 0xfd, 0xd6, 0x1e, 0x72, 0x08, 0x79, 0x05, 0xa6, 0x65, 0x14, - 0xa5, 0x52, 0x62, 0x8a, 0x5c, 0x4f, 0xd5, 0xde, 0x30, 0x1b, 0x09, 0x28, 0xa6, 0xb0, 0xd9, 0x2e, - 0xcb, 0x8e, 0x0d, 0x3c, 0x01, 0xf9, 0x44, 0xf2, 0xea, 0xfc, 0x46, 0xe3, 0xd6, 0x4d, 0x6e, 0x9d, - 0xd5, 0x18, 0x89, 0x40, 0xcd, 0xc9, 0x23, 0x03, 0x35, 0x97, 0x05, 0x6d, 0x26, 0x2d, 0xdf, 0x51, - 0xa6, 0xea, 0x57, 0x14, 0x5d, 0x56, 0x76, 0xe8, 0xd9, 0x45, 0xd7, 0xcc, 0x0a, 0x69, 0x2d, 0xbf, - 0x7f, 0x21, 0xad, 0xf6, 0x6d, 0x98, 0x49, 0xf5, 0x9f, 0xb2, 0x9a, 0x59, 0xd9, 0x56, 0xb3, 0xe3, - 0x3d, 0x73, 0xf7, 0x4f, 0x2d, 0x38, 0x3f, 0xb0, 0x22, 0x1d, 0x37, 0xb6, 0x38, 0xbd, 0x37, 0x8e, - 0x9d, 0x7e, 0x6f, 0x2c, 0x9c, 0x6c, 0x6f, 0xac, 0x6f, 0x7e, 0xef, 0x87, 0x97, 0x1f, 0xfa, 0xfe, - 0x0f, 0x2f, 0x3f, 0xf4, 0x07, 0x3f, 0xbc, 0xfc, 0xd0, 0x3b, 0x07, 0x97, 0xad, 0xef, 0x1d, 0x5c, - 0xb6, 0xbe, 0x7f, 0x70, 0xd9, 0xfa, 0x83, 0x83, 0xcb, 0xd6, 0x7f, 0x3e, 0xb8, 0x6c, 0x7d, 0xf3, - 0x8f, 0x2f, 0x3f, 0xf4, 0xa9, 0x4f, 0xc4, 0x3d, 0xb5, 0xa8, 0x7a, 0x8a, 0xff, 0xf8, 0xb0, 0xea, - 0x97, 0xc5, 0xde, 0x4e, 0x7b, 0x91, 0xf5, 0xd4, 0xa2, 0x2e, 0x51, 0x3d, 0xf5, 0x7f, 0x03, 0x00, - 0x00, 0xff, 0xff, 0x91, 0x6c, 0x1b, 0x38, 0xb0, 0xaa, 0x00, 0x00, + // 8802 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x5d, 0x6c, 0x24, 0xd9, + 0x75, 0x18, 0xbc, 0xc5, 0x66, 0x93, 0xdd, 0xa7, 0x39, 0x24, 0xe7, 0xce, 0xcc, 0x2e, 0x97, 0xbb, + 0x3b, 0xbd, 0xaa, 0xf5, 0xb7, 0xdf, 0xac, 0xb5, 0x22, 0xa5, 0xfd, 0x71, 0x56, 0x5a, 0x65, 0x93, + 0x6e, 0x72, 0x66, 0x87, 0xb3, 0xe4, 0x0c, 0xf7, 0x34, 0x67, 0xc7, 0xfa, 0x59, 0x5b, 0xc5, 0xee, + 0xcb, 0x66, 0x0d, 0xbb, 0xab, 0x5a, 0x55, 0xd5, 0x9c, 0xe1, 0x6a, 0x61, 0xad, 0x24, 0xac, 0x2c, + 0x2b, 0x12, 0xac, 0xc4, 0x16, 0x82, 0xfc, 0x20, 0x50, 0x0c, 0x03, 0x4e, 0xe2, 0x3c, 0x04, 0x86, + 0x82, 0xe4, 0xc1, 0x40, 0x8c, 0x28, 0x0e, 0x64, 0x20, 0x0e, 0xe4, 0x87, 0x44, 0x4e, 0x00, 0xd3, + 0x11, 0x9d, 0x97, 0x18, 0x09, 0x84, 0x04, 0x0a, 0x8c, 0xec, 0x43, 0x10, 0xdc, 0xdf, 0xba, 0x55, + 0x5d, 0xcd, 0xbf, 0x2e, 0xce, 0xae, 0x13, 0xbf, 0x75, 0xdf, 0x73, 0xee, 0x39, 0xa7, 0xee, 0xef, + 0xb9, 0xe7, 0x9e, 0x73, 0x2e, 0xac, 0xb6, 0xdd, 0x68, 0xbb, 0xbf, 0xb9, 0xd0, 0xf4, 0xbb, 0x8b, + 0x4e, 0xd0, 0xf6, 0x7b, 0x81, 0x7f, 0x97, 0xff, 0xf8, 0x48, 0xe0, 0x77, 0x3a, 0x7e, 0x3f, 0x0a, + 0x17, 0x7b, 0x3b, 0xed, 0x45, 0xa7, 0xe7, 0x86, 0x8b, 0xba, 0x64, 0xf7, 0x63, 0x4e, 0xa7, 0xb7, + 0xed, 0x7c, 0x6c, 0xb1, 0x4d, 0x3d, 0x1a, 0x38, 0x11, 0x6d, 0x2d, 0xf4, 0x02, 0x3f, 0xf2, 0xc9, + 0x27, 0x63, 0x6a, 0x0b, 0x8a, 0x1a, 0xff, 0xf1, 0xf3, 0xaa, 0xee, 0x42, 0x6f, 0xa7, 0xbd, 0xc0, + 0xa8, 0x2d, 0xe8, 0x12, 0x45, 0x6d, 0xfe, 0x23, 0x86, 0x2c, 0x6d, 0xbf, 0xed, 0x2f, 0x72, 0xa2, + 0x9b, 0xfd, 0x2d, 0xfe, 0x8f, 0xff, 0xe1, 0xbf, 0x04, 0xb3, 0xf9, 0xa7, 0x76, 0x5e, 0x0a, 0x17, + 0x5c, 0x9f, 0xc9, 0xb6, 0xb8, 0xe9, 0x44, 0xcd, 0xed, 0xc5, 0xdd, 0x01, 0x89, 0xe6, 0x6d, 0x03, + 0xa9, 0xe9, 0x07, 0x34, 0x0b, 0xe7, 0x85, 0x18, 0xa7, 0xeb, 0x34, 0xb7, 0x5d, 0x8f, 0x06, 0x7b, + 0xf1, 0x57, 0x77, 0x69, 0xe4, 0x64, 0xd5, 0x5a, 0x1c, 0x56, 0x2b, 0xe8, 0x7b, 0x91, 0xdb, 0xa5, + 0x03, 0x15, 0x7e, 0xe6, 0xa8, 0x0a, 0x61, 0x73, 0x9b, 0x76, 0x9d, 0x81, 0x7a, 0xcf, 0x0f, 0xab, + 0xd7, 0x8f, 0xdc, 0xce, 0xa2, 0xeb, 0x45, 0x61, 0x14, 0xa4, 0x2b, 0xd9, 0x3f, 0x2e, 0x40, 0xb9, + 0xb6, 0x5a, 0x6f, 0x44, 0x4e, 0xd4, 0x0f, 0xc9, 0x57, 0x2d, 0x98, 0xea, 0xf8, 0x4e, 0xab, 0xee, + 0x74, 0x1c, 0xaf, 0x49, 0x83, 0x39, 0xeb, 0x49, 0xeb, 0x4a, 0xe5, 0xb9, 0xd5, 0x85, 0x51, 0xfa, + 0x6b, 0xa1, 0x76, 0x2f, 0x44, 0x1a, 0xfa, 0xfd, 0xa0, 0x49, 0x91, 0x6e, 0xd5, 0x2f, 0x7e, 0x7f, + 0xbf, 0xfa, 0xd0, 0xc1, 0x7e, 0x75, 0x6a, 0xd5, 0xe0, 0x84, 0x09, 0xbe, 0xe4, 0xdb, 0x16, 0x9c, + 0x6f, 0x3a, 0x9e, 0x13, 0xec, 0x6d, 0x38, 0x41, 0x9b, 0x46, 0xaf, 0x06, 0x7e, 0xbf, 0x37, 0x37, + 0x76, 0x06, 0xd2, 0x3c, 0x2a, 0xa5, 0x39, 0xbf, 0x94, 0x66, 0x87, 0x83, 0x12, 0x70, 0xb9, 0xc2, + 0xc8, 0xd9, 0xec, 0x50, 0x53, 0xae, 0xc2, 0x59, 0xca, 0xd5, 0x48, 0xb3, 0xc3, 0x41, 0x09, 0xc8, + 0x33, 0x30, 0xe9, 0x7a, 0xed, 0x80, 0x86, 0xe1, 0xdc, 0xf8, 0x93, 0xd6, 0x95, 0x72, 0x7d, 0x46, + 0x56, 0x9f, 0x5c, 0x11, 0xc5, 0xa8, 0xe0, 0xf6, 0x6f, 0x15, 0xe0, 0x7c, 0x6d, 0xb5, 0xbe, 0x11, + 0x38, 0x5b, 0x5b, 0x6e, 0x13, 0xfd, 0x7e, 0xe4, 0x7a, 0x6d, 0x93, 0x80, 0x75, 0x38, 0x01, 0xf2, + 0x22, 0x54, 0x42, 0x1a, 0xec, 0xba, 0x4d, 0xba, 0xee, 0x07, 0x11, 0xef, 0x94, 0x62, 0xfd, 0x82, + 0x44, 0xaf, 0x34, 0x62, 0x10, 0x9a, 0x78, 0xac, 0x5a, 0xe0, 0xfb, 0x91, 0x84, 0xf3, 0x36, 0x2b, + 0xc7, 0xd5, 0x30, 0x06, 0xa1, 0x89, 0x47, 0x96, 0x61, 0xd6, 0xf1, 0x3c, 0x3f, 0x72, 0x22, 0xd7, + 0xf7, 0xd6, 0x03, 0xba, 0xe5, 0xde, 0x97, 0x9f, 0x38, 0x27, 0xeb, 0xce, 0xd6, 0x52, 0x70, 0x1c, + 0xa8, 0x41, 0xbe, 0x65, 0xc1, 0x6c, 0x18, 0xb9, 0xcd, 0x1d, 0xd7, 0xa3, 0x61, 0xb8, 0xe4, 0x7b, + 0x5b, 0x6e, 0x7b, 0xae, 0xc8, 0xbb, 0xed, 0xe6, 0x68, 0xdd, 0xd6, 0x48, 0x51, 0xad, 0x5f, 0x64, + 0x22, 0xa5, 0x4b, 0x71, 0x80, 0x3b, 0xf9, 0x30, 0x94, 0x65, 0x8b, 0xd2, 0x70, 0x6e, 0xe2, 0xc9, + 0xc2, 0x95, 0x72, 0xfd, 0xdc, 0xc1, 0x7e, 0xb5, 0xbc, 0xa2, 0x0a, 0x31, 0x86, 0xdb, 0xcb, 0x30, + 0x57, 0xeb, 0x6e, 0x3a, 0x61, 0xe8, 0xb4, 0xfc, 0x20, 0xd5, 0x75, 0x57, 0xa0, 0xd4, 0x75, 0x7a, + 0x3d, 0xd7, 0x6b, 0xb3, 0xbe, 0x63, 0x74, 0xa6, 0x0e, 0xf6, 0xab, 0xa5, 0x35, 0x59, 0x86, 0x1a, + 0x6a, 0xff, 0x87, 0x31, 0xa8, 0xd4, 0x3c, 0xa7, 0xb3, 0x17, 0xba, 0x21, 0xf6, 0x3d, 0xf2, 0x39, + 0x28, 0xb1, 0x55, 0xab, 0xe5, 0x44, 0x8e, 0x9c, 0xe9, 0x1f, 0x5d, 0x10, 0x8b, 0xc8, 0x82, 0xb9, + 0x88, 0xc4, 0x9f, 0xcf, 0xb0, 0x17, 0x76, 0x3f, 0xb6, 0x70, 0x6b, 0xf3, 0x2e, 0x6d, 0x46, 0x6b, + 0x34, 0x72, 0xea, 0x44, 0xf6, 0x02, 0xc4, 0x65, 0xa8, 0xa9, 0x12, 0x1f, 0xc6, 0xc3, 0x1e, 0x6d, + 0xca, 0x99, 0xbb, 0x36, 0xe2, 0x0c, 0x89, 0x45, 0x6f, 0xf4, 0x68, 0xb3, 0x3e, 0x25, 0x59, 0x8f, + 0xb3, 0x7f, 0xc8, 0x19, 0x91, 0x7b, 0x30, 0x11, 0xf2, 0xb5, 0x4c, 0x4e, 0xca, 0x5b, 0xf9, 0xb1, + 0xe4, 0x64, 0xeb, 0xd3, 0x92, 0xe9, 0x84, 0xf8, 0x8f, 0x92, 0x9d, 0xfd, 0x1f, 0x2d, 0xb8, 0x60, + 0x60, 0xd7, 0x82, 0x76, 0xbf, 0x4b, 0xbd, 0x88, 0x3c, 0x09, 0xe3, 0x9e, 0xd3, 0xa5, 0x72, 0x56, + 0x69, 0x91, 0x6f, 0x3a, 0x5d, 0x8a, 0x1c, 0x42, 0x9e, 0x82, 0xe2, 0xae, 0xd3, 0xe9, 0x53, 0xde, + 0x48, 0xe5, 0xfa, 0x39, 0x89, 0x52, 0x7c, 0x83, 0x15, 0xa2, 0x80, 0x91, 0xb7, 0xa1, 0xcc, 0x7f, + 0x5c, 0x0b, 0xfc, 0x6e, 0x4e, 0x9f, 0x26, 0x25, 0x7c, 0x43, 0x91, 0x15, 0xc3, 0x4f, 0xff, 0xc5, + 0x98, 0xa1, 0xfd, 0xc7, 0x16, 0xcc, 0x18, 0x1f, 0xb7, 0xea, 0x86, 0x11, 0xf9, 0xec, 0xc0, 0xe0, + 0x59, 0x38, 0xde, 0xe0, 0x61, 0xb5, 0xf9, 0xd0, 0x99, 0x95, 0x5f, 0x5a, 0x52, 0x25, 0xc6, 0xc0, + 0xf1, 0xa0, 0xe8, 0x46, 0xb4, 0x1b, 0xce, 0x8d, 0x3d, 0x59, 0xb8, 0x52, 0x79, 0x6e, 0x25, 0xb7, + 0x6e, 0x8c, 0xdb, 0x77, 0x85, 0xd1, 0x47, 0xc1, 0xc6, 0xfe, 0x6e, 0x21, 0xd1, 0x7d, 0x6b, 0x4a, + 0x8e, 0x77, 0x2d, 0x98, 0xe8, 0x38, 0x9b, 0xb4, 0x23, 0xe6, 0x56, 0xe5, 0xb9, 0x37, 0x73, 0x93, + 0x44, 0xf1, 0x58, 0x58, 0xe5, 0xf4, 0xaf, 0x7a, 0x51, 0xb0, 0x17, 0x0f, 0x2f, 0x51, 0x88, 0x92, + 0x39, 0xf9, 0x5b, 0x16, 0x54, 0xe2, 0x55, 0x4d, 0x35, 0xcb, 0x66, 0xfe, 0xc2, 0xc4, 0x8b, 0xa9, + 0x94, 0x48, 0x2f, 0xd1, 0x06, 0x04, 0x4d, 0x59, 0xe6, 0x3f, 0x0e, 0x15, 0xe3, 0x13, 0xc8, 0x2c, + 0x14, 0x76, 0xe8, 0x9e, 0x18, 0xf0, 0xc8, 0x7e, 0x92, 0x8b, 0x89, 0x11, 0x2e, 0x87, 0xf4, 0x27, + 0xc6, 0x5e, 0xb2, 0xe6, 0x5f, 0x81, 0xd9, 0x34, 0xc3, 0x93, 0xd4, 0xb7, 0xff, 0x49, 0x31, 0x31, + 0x30, 0xd9, 0x42, 0x40, 0x7c, 0x98, 0xec, 0xd2, 0x28, 0x70, 0x9b, 0xaa, 0xcb, 0x96, 0x47, 0x6b, + 0xa5, 0x35, 0x4e, 0x2c, 0xde, 0x10, 0xc5, 0xff, 0x10, 0x15, 0x17, 0xb2, 0x0d, 0xe3, 0x4e, 0xd0, + 0x56, 0x7d, 0x72, 0x2d, 0x9f, 0x69, 0x19, 0x2f, 0x15, 0xb5, 0xa0, 0x1d, 0x22, 0xe7, 0x40, 0x16, + 0xa1, 0x1c, 0xd1, 0xa0, 0xeb, 0x7a, 0x4e, 0x24, 0x76, 0xd0, 0x52, 0xfd, 0xbc, 0x44, 0x2b, 0x6f, + 0x28, 0x00, 0xc6, 0x38, 0xa4, 0x03, 0x13, 0xad, 0x60, 0x0f, 0xfb, 0xde, 0xdc, 0x78, 0x1e, 0x4d, + 0xb1, 0xcc, 0x69, 0xc5, 0x83, 0x54, 0xfc, 0x47, 0xc9, 0x83, 0xfc, 0xba, 0x05, 0x17, 0xbb, 0xd4, + 0x09, 0xfb, 0x01, 0x65, 0x9f, 0x80, 0x34, 0xa2, 0x1e, 0xeb, 0xd8, 0xb9, 0x22, 0x67, 0x8e, 0xa3, + 0xf6, 0xc3, 0x20, 0xe5, 0xfa, 0xe3, 0x52, 0x94, 0x8b, 0x59, 0x50, 0xcc, 0x94, 0x86, 0xbc, 0x0d, + 0x95, 0x28, 0xea, 0x34, 0x22, 0xa6, 0x07, 0xb7, 0xf7, 0xe6, 0x26, 0xf8, 0xe2, 0x35, 0xe2, 0x0a, + 0xb3, 0xb1, 0xb1, 0xaa, 0x08, 0xd6, 0x67, 0xd8, 0x6c, 0x31, 0x0a, 0xd0, 0x64, 0x67, 0xff, 0xf3, + 0x22, 0x9c, 0x1f, 0xd8, 0x56, 0xc8, 0x0b, 0x50, 0xec, 0x6d, 0x3b, 0xa1, 0xda, 0x27, 0x2e, 0xab, + 0x45, 0x6a, 0x9d, 0x15, 0xbe, 0xb7, 0x5f, 0x3d, 0xa7, 0xaa, 0xf0, 0x02, 0x14, 0xc8, 0x4c, 0x6b, + 0xeb, 0xd2, 0x30, 0x74, 0xda, 0x6a, 0xf3, 0x30, 0x06, 0x29, 0x2f, 0x46, 0x05, 0x27, 0xbf, 0x68, + 0xc1, 0x39, 0x31, 0x60, 0x91, 0x86, 0xfd, 0x4e, 0xc4, 0x36, 0x48, 0xd6, 0x29, 0x37, 0xf2, 0x98, + 0x1c, 0x82, 0x64, 0xfd, 0x92, 0xe4, 0x7e, 0xce, 0x2c, 0x0d, 0x31, 0xc9, 0x97, 0xdc, 0x81, 0x72, + 0x18, 0x39, 0x41, 0x44, 0x5b, 0xb5, 0x88, 0xab, 0x72, 0x95, 0xe7, 0x7e, 0xfa, 0x78, 0x3b, 0xc7, + 0x86, 0xdb, 0xa5, 0x62, 0x97, 0x6a, 0x28, 0x02, 0x18, 0xd3, 0x22, 0x6f, 0x03, 0x04, 0x7d, 0xaf, + 0xd1, 0xef, 0x76, 0x9d, 0x60, 0x4f, 0x6a, 0x77, 0xd7, 0x47, 0xfb, 0x3c, 0xd4, 0xf4, 0x62, 0x45, + 0x27, 0x2e, 0x43, 0x83, 0x1f, 0xf9, 0x92, 0x05, 0xe7, 0xc4, 0x3c, 0x50, 0x12, 0x4c, 0xe4, 0x2c, + 0xc1, 0x79, 0xd6, 0xb4, 0xcb, 0x26, 0x0b, 0x4c, 0x72, 0x24, 0x6f, 0x42, 0xa5, 0xe9, 0x77, 0x7b, + 0x1d, 0x2a, 0x1a, 0x77, 0xf2, 0xc4, 0x8d, 0xcb, 0x87, 0xee, 0x52, 0x4c, 0x02, 0x4d, 0x7a, 0xf6, + 0xbf, 0x4b, 0xea, 0x38, 0x6a, 0x48, 0x93, 0xcf, 0xc0, 0xa3, 0x61, 0xbf, 0xd9, 0xa4, 0x61, 0xb8, + 0xd5, 0xef, 0x60, 0xdf, 0xbb, 0xee, 0x86, 0x91, 0x1f, 0xec, 0xad, 0xba, 0x5d, 0x37, 0xe2, 0x03, + 0xba, 0x58, 0x7f, 0xe2, 0x60, 0xbf, 0xfa, 0x68, 0x63, 0x18, 0x12, 0x0e, 0xaf, 0x4f, 0x1c, 0x78, + 0xac, 0xef, 0x0d, 0x27, 0x2f, 0x8e, 0x1f, 0xd5, 0x83, 0xfd, 0xea, 0x63, 0xb7, 0x87, 0xa3, 0xe1, + 0x61, 0x34, 0xec, 0x3f, 0xb5, 0xd8, 0x36, 0x24, 0xbe, 0x6b, 0x83, 0x76, 0x7b, 0x1d, 0xb6, 0x74, + 0x9e, 0xbd, 0x72, 0x1c, 0x25, 0x94, 0x63, 0xcc, 0x67, 0x2f, 0x57, 0xf2, 0x0f, 0xd3, 0x90, 0xed, + 0xff, 0x62, 0xc1, 0xc5, 0x34, 0xf2, 0x03, 0x50, 0xe8, 0xc2, 0xa4, 0x42, 0x77, 0x33, 0xdf, 0xaf, + 0x1d, 0xa2, 0xd5, 0xfd, 0x92, 0x31, 0x60, 0x15, 0x2a, 0xd2, 0x2d, 0xf2, 0x12, 0x4c, 0x45, 0xf2, + 0xef, 0xcd, 0x58, 0x39, 0xd7, 0x86, 0x89, 0x0d, 0x03, 0x86, 0x09, 0x4c, 0x56, 0xb3, 0xd9, 0xe9, + 0x87, 0x11, 0x0d, 0x1a, 0x4d, 0xbf, 0x27, 0x96, 0xdd, 0x52, 0x5c, 0x73, 0xc9, 0x80, 0x61, 0x02, + 0xd3, 0xfe, 0x6b, 0xc5, 0xc1, 0x76, 0xff, 0xbf, 0x5d, 0x5f, 0x89, 0xd5, 0x8f, 0xc2, 0xfb, 0xa9, + 0x7e, 0x8c, 0x7f, 0xa0, 0xd4, 0x8f, 0x2f, 0x5b, 0x4c, 0x8b, 0x13, 0x03, 0x20, 0x94, 0xaa, 0xd1, + 0xeb, 0xf9, 0x4e, 0x07, 0xa4, 0x5b, 0xa6, 0x62, 0x28, 0x79, 0x61, 0xcc, 0xd6, 0xfe, 0x07, 0xe3, + 0x30, 0x55, 0xf3, 0x22, 0xb7, 0xb6, 0xb5, 0xe5, 0x7a, 0x6e, 0xb4, 0x47, 0xbe, 0x31, 0x06, 0x8b, + 0xbd, 0x80, 0x6e, 0xd1, 0x20, 0xa0, 0xad, 0xe5, 0x7e, 0xe0, 0x7a, 0xed, 0x46, 0x73, 0x9b, 0xb6, + 0xfa, 0x1d, 0xd7, 0x6b, 0xaf, 0xb4, 0x3d, 0x5f, 0x17, 0x5f, 0xbd, 0x4f, 0x9b, 0x7d, 0xde, 0xae, + 0x62, 0x95, 0xe8, 0x8e, 0x26, 0xfb, 0xfa, 0xc9, 0x98, 0xd6, 0x9f, 0x3f, 0xd8, 0xaf, 0x2e, 0x9e, + 0xb0, 0x12, 0x9e, 0xf4, 0xd3, 0xc8, 0xd7, 0xc6, 0x60, 0x21, 0xa0, 0x9f, 0xef, 0xbb, 0xc7, 0x6f, + 0x0d, 0xb1, 0x8c, 0x77, 0x46, 0xdc, 0xee, 0x4f, 0xc4, 0xb3, 0xfe, 0xdc, 0xc1, 0x7e, 0xf5, 0x84, + 0x75, 0xf0, 0x84, 0xdf, 0x65, 0xaf, 0x43, 0xa5, 0xd6, 0x73, 0x43, 0xf7, 0x3e, 0xfa, 0xfd, 0x88, + 0x1e, 0xc3, 0xa0, 0x51, 0x85, 0x62, 0xd0, 0xef, 0x50, 0xb1, 0xc0, 0x94, 0xeb, 0x65, 0xb6, 0x2c, + 0x23, 0x2b, 0x40, 0x51, 0x6e, 0x7f, 0x99, 0x6d, 0x41, 0x9c, 0x64, 0xca, 0x94, 0x75, 0x17, 0x8a, + 0x01, 0x63, 0x22, 0x47, 0xd6, 0xa8, 0xa7, 0xfe, 0x58, 0x6a, 0x29, 0x04, 0xfb, 0x89, 0x82, 0x85, + 0xfd, 0xbd, 0x31, 0xb8, 0x54, 0xeb, 0xf5, 0xd6, 0x68, 0xb8, 0x9d, 0x92, 0xe2, 0x97, 0x2d, 0x98, + 0xde, 0x75, 0x83, 0xa8, 0xef, 0x74, 0x94, 0xb5, 0x52, 0xc8, 0xd3, 0x18, 0x55, 0x1e, 0xce, 0xed, + 0x8d, 0x04, 0xe9, 0x3a, 0x39, 0xd8, 0xaf, 0x4e, 0x27, 0xcb, 0x30, 0xc5, 0x9e, 0xfc, 0x4d, 0x0b, + 0x66, 0x65, 0xd1, 0x4d, 0xbf, 0x45, 0x4d, 0x6b, 0xf8, 0xed, 0x3c, 0x65, 0xd2, 0xc4, 0x85, 0x15, + 0x33, 0x5d, 0x8a, 0x03, 0x42, 0xd8, 0xff, 0x6d, 0x0c, 0x1e, 0x19, 0x42, 0x83, 0xfc, 0x86, 0x05, + 0x17, 0x85, 0x09, 0xdd, 0x00, 0x21, 0xdd, 0x92, 0xad, 0xf9, 0xa9, 0xbc, 0x25, 0x47, 0x36, 0xc5, + 0xa9, 0xd7, 0xa4, 0xf5, 0x39, 0xb6, 0x24, 0x2f, 0x65, 0xb0, 0xc6, 0x4c, 0x81, 0xb8, 0xa4, 0xc2, + 0xa8, 0x9e, 0x92, 0x74, 0xec, 0x81, 0x48, 0xda, 0xc8, 0x60, 0x8d, 0x99, 0x02, 0xd9, 0x7f, 0x05, + 0x1e, 0x3b, 0x84, 0xdc, 0xd1, 0x93, 0xd3, 0x7e, 0x53, 0x8f, 0xfa, 0xe4, 0x98, 0x3b, 0xc6, 0xbc, + 0xb6, 0x61, 0x82, 0x4f, 0x1d, 0x35, 0xb1, 0x81, 0xed, 0xc1, 0x7c, 0x4e, 0x85, 0x28, 0x21, 0xf6, + 0xf7, 0x2c, 0x28, 0x9d, 0xc0, 0xf6, 0x59, 0x4d, 0xda, 0x3e, 0xcb, 0x03, 0x76, 0xcf, 0x68, 0xd0, + 0xee, 0xf9, 0xea, 0x68, 0xbd, 0x71, 0x1c, 0x7b, 0xe7, 0x8f, 0x2d, 0x38, 0x3f, 0x60, 0x1f, 0x25, + 0xdb, 0x70, 0xb1, 0xe7, 0xb7, 0xd4, 0x76, 0x7a, 0xdd, 0x09, 0xb7, 0x39, 0x4c, 0x7e, 0xde, 0x0b, + 0xac, 0x27, 0xd7, 0x33, 0xe0, 0xef, 0xed, 0x57, 0xe7, 0x34, 0x91, 0x14, 0x02, 0x66, 0x52, 0x24, + 0x3d, 0x28, 0x6d, 0xb9, 0xb4, 0xd3, 0x8a, 0x87, 0xe0, 0x88, 0x5a, 0xda, 0x35, 0x49, 0x4d, 0x5c, + 0x0d, 0xa8, 0x7f, 0xa8, 0xb9, 0xd8, 0x3f, 0xb1, 0x60, 0xba, 0xd6, 0x8f, 0xb6, 0x99, 0x8e, 0xd2, + 0xe4, 0xd6, 0x38, 0xe2, 0x41, 0x31, 0x74, 0xdb, 0xbb, 0x2f, 0xe4, 0xb3, 0x18, 0x37, 0x18, 0x29, + 0x79, 0x45, 0xa2, 0x95, 0x75, 0x5e, 0x88, 0x82, 0x0d, 0x09, 0x60, 0xc2, 0x77, 0xfa, 0xd1, 0xf6, + 0x73, 0xf2, 0x93, 0x47, 0xb4, 0x4c, 0xdc, 0x62, 0x9f, 0xf3, 0x9c, 0xe4, 0xa8, 0x55, 0x46, 0x51, + 0x8a, 0x92, 0x93, 0xfd, 0x45, 0x98, 0x4e, 0xde, 0xbb, 0x1d, 0x63, 0xcc, 0x3e, 0x01, 0x05, 0x27, + 0xf0, 0xe4, 0x88, 0xad, 0x48, 0x84, 0x42, 0x0d, 0x6f, 0x22, 0x2b, 0x27, 0xcf, 0x42, 0x69, 0xab, + 0xdf, 0xe9, 0xf0, 0x73, 0x85, 0xb8, 0xe4, 0xd2, 0xc7, 0xa2, 0x6b, 0xb2, 0x1c, 0x35, 0x86, 0xfd, + 0xbf, 0xc6, 0x61, 0xa6, 0xde, 0xe9, 0xd3, 0x57, 0x03, 0x4a, 0x95, 0x2d, 0xa8, 0x06, 0x33, 0xbd, + 0x80, 0xee, 0xba, 0xf4, 0x5e, 0x83, 0x76, 0x68, 0x33, 0xf2, 0x03, 0x29, 0xcd, 0x23, 0x92, 0xd0, + 0xcc, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0x0a, 0x4c, 0x3b, 0xcd, 0xc8, 0xdd, 0xa5, 0x9a, 0x82, + 0x10, 0xf7, 0x61, 0x49, 0x61, 0xba, 0x96, 0x80, 0x62, 0x0a, 0x9b, 0x7c, 0x16, 0xe6, 0xc2, 0xa6, + 0xd3, 0xa1, 0xb7, 0x7b, 0x92, 0xd5, 0xd2, 0x36, 0x6d, 0xee, 0xac, 0xfb, 0xae, 0x17, 0x49, 0xbb, + 0xe3, 0x93, 0x92, 0xd2, 0x5c, 0x63, 0x08, 0x1e, 0x0e, 0xa5, 0x40, 0xfe, 0x85, 0x05, 0x4f, 0xf4, + 0x02, 0xba, 0x1e, 0xf8, 0x5d, 0x9f, 0x0d, 0xb5, 0x01, 0x73, 0x98, 0x34, 0x0b, 0xbd, 0x31, 0xa2, + 0x2e, 0x25, 0x4a, 0x06, 0xef, 0x70, 0x3e, 0x74, 0xb0, 0x5f, 0x7d, 0x62, 0xfd, 0x30, 0x01, 0xf0, + 0x70, 0xf9, 0xc8, 0xbf, 0xb4, 0xe0, 0x72, 0xcf, 0x0f, 0xa3, 0x43, 0x3e, 0xa1, 0x78, 0xa6, 0x9f, + 0x60, 0x1f, 0xec, 0x57, 0x2f, 0xaf, 0x1f, 0x2a, 0x01, 0x1e, 0x21, 0xa1, 0x7d, 0x50, 0x81, 0xf3, + 0xc6, 0xd8, 0x93, 0xc6, 0x9c, 0x97, 0xe1, 0x9c, 0x1a, 0x0c, 0xb1, 0xee, 0x53, 0x8e, 0x6d, 0x7b, + 0x35, 0x13, 0x88, 0x49, 0x5c, 0x36, 0xee, 0xf4, 0x50, 0x14, 0xb5, 0x53, 0xe3, 0x6e, 0x3d, 0x01, + 0xc5, 0x14, 0x36, 0x59, 0x81, 0x0b, 0xb2, 0x04, 0x69, 0xaf, 0xe3, 0x36, 0x9d, 0x25, 0xbf, 0x2f, + 0x87, 0x5c, 0xb1, 0xfe, 0xc8, 0xc1, 0x7e, 0xf5, 0xc2, 0xfa, 0x20, 0x18, 0xb3, 0xea, 0x90, 0x55, + 0xb8, 0xe8, 0xf4, 0x23, 0x5f, 0x7f, 0xff, 0x55, 0x8f, 0x6d, 0xa7, 0x2d, 0x3e, 0xb4, 0x4a, 0x62, + 0xdf, 0xad, 0x65, 0xc0, 0x31, 0xb3, 0x16, 0x59, 0x4f, 0x51, 0x6b, 0xd0, 0xa6, 0xef, 0xb5, 0x44, + 0x2f, 0x17, 0xe3, 0x63, 0x60, 0x2d, 0x03, 0x07, 0x33, 0x6b, 0x92, 0x0e, 0x4c, 0x77, 0x9d, 0xfb, + 0xb7, 0x3d, 0x67, 0xd7, 0x71, 0x3b, 0x8c, 0x89, 0xb4, 0x17, 0x0e, 0xb7, 0x32, 0xf5, 0x23, 0xb7, + 0xb3, 0x20, 0xfc, 0x38, 0x16, 0x56, 0xbc, 0xe8, 0x56, 0xd0, 0x88, 0x98, 0xa6, 0x2e, 0x34, 0xc8, + 0xb5, 0x04, 0x2d, 0x4c, 0xd1, 0x26, 0xb7, 0xe0, 0x12, 0x9f, 0x8e, 0xcb, 0xfe, 0x3d, 0x6f, 0x99, + 0x76, 0x9c, 0x3d, 0xf5, 0x01, 0x93, 0xfc, 0x03, 0x1e, 0x3d, 0xd8, 0xaf, 0x5e, 0x6a, 0x64, 0x21, + 0x60, 0x76, 0x3d, 0xe2, 0xc0, 0x63, 0x49, 0x00, 0xd2, 0x5d, 0x37, 0x74, 0x7d, 0x4f, 0x98, 0xe5, + 0x4a, 0xb1, 0x59, 0xae, 0x31, 0x1c, 0x0d, 0x0f, 0xa3, 0x41, 0xfe, 0x8e, 0x05, 0x17, 0xb3, 0xa6, + 0xe1, 0x5c, 0x39, 0x8f, 0xdb, 0xe4, 0xd4, 0xd4, 0x12, 0x23, 0x22, 0x73, 0x51, 0xc8, 0x14, 0x82, + 0xbc, 0x63, 0xc1, 0x94, 0x63, 0x9c, 0xa0, 0xe7, 0x20, 0x8f, 0x5d, 0xcb, 0x3c, 0x93, 0xd7, 0x67, + 0x0f, 0xf6, 0xab, 0x89, 0x53, 0x3a, 0x26, 0x38, 0x92, 0xbf, 0x67, 0xc1, 0xa5, 0xcc, 0x39, 0x3e, + 0x57, 0x39, 0x8b, 0x16, 0xe2, 0x83, 0x24, 0x7b, 0xcd, 0xc9, 0x16, 0x83, 0x7c, 0xcb, 0xd2, 0x5b, + 0x99, 0xba, 0x60, 0x9c, 0x9b, 0xe2, 0xa2, 0x8d, 0x68, 0xf0, 0x30, 0xd4, 0x28, 0x45, 0xb8, 0x7e, + 0xc1, 0xd8, 0x19, 0x55, 0x21, 0xa6, 0xd9, 0x93, 0x6f, 0x5a, 0x6a, 0x6b, 0xd4, 0x12, 0x9d, 0x3b, + 0x2b, 0x89, 0x48, 0xbc, 0xd3, 0x6a, 0x81, 0x52, 0xcc, 0xc9, 0xcf, 0xc1, 0xbc, 0xb3, 0xe9, 0x07, + 0x51, 0xe6, 0xe4, 0x9b, 0x9b, 0xe6, 0xd3, 0xe8, 0xf2, 0xc1, 0x7e, 0x75, 0xbe, 0x36, 0x14, 0x0b, + 0x0f, 0xa1, 0x60, 0xff, 0xde, 0x04, 0x4c, 0x89, 0x93, 0x90, 0xdc, 0xba, 0x7e, 0xdb, 0x82, 0xc7, + 0x9b, 0xfd, 0x20, 0xa0, 0x5e, 0xd4, 0x88, 0x68, 0x6f, 0x70, 0xe3, 0xb2, 0xce, 0x74, 0xe3, 0x7a, + 0xf2, 0x60, 0xbf, 0xfa, 0xf8, 0xd2, 0x21, 0xfc, 0xf1, 0x50, 0xe9, 0xc8, 0xbf, 0xb5, 0xc0, 0x96, + 0x08, 0x75, 0xa7, 0xb9, 0xd3, 0x0e, 0xfc, 0xbe, 0xd7, 0x1a, 0xfc, 0x88, 0xb1, 0x33, 0xfd, 0x88, + 0xa7, 0x0f, 0xf6, 0xab, 0xf6, 0xd2, 0x91, 0x52, 0xe0, 0x31, 0x24, 0x25, 0xaf, 0xc2, 0x79, 0x89, + 0x75, 0xf5, 0x7e, 0x8f, 0x06, 0x2e, 0x3b, 0x73, 0x48, 0xc5, 0x31, 0xf6, 0x4d, 0x4b, 0x23, 0xe0, + 0x60, 0x1d, 0x12, 0xc2, 0xe4, 0x3d, 0xea, 0xb6, 0xb7, 0x23, 0xa5, 0x3e, 0x8d, 0xe8, 0x90, 0x26, + 0xad, 0x22, 0x77, 0x04, 0xcd, 0x7a, 0xe5, 0x60, 0xbf, 0x3a, 0x29, 0xff, 0xa0, 0xe2, 0x44, 0x6e, + 0xc2, 0xb4, 0x38, 0xa7, 0xae, 0xbb, 0x5e, 0x7b, 0xdd, 0xf7, 0x84, 0x57, 0x55, 0xb9, 0xfe, 0xb4, + 0xda, 0xf0, 0x1b, 0x09, 0xe8, 0x7b, 0xfb, 0xd5, 0x29, 0xf5, 0x7b, 0x63, 0xaf, 0x47, 0x31, 0x55, + 0x9b, 0xfc, 0x6d, 0x0b, 0x48, 0x18, 0xd1, 0xde, 0x7a, 0xa7, 0xdf, 0x76, 0x65, 0x13, 0x49, 0xff, + 0xa8, 0x1c, 0x5c, 0xb5, 0x92, 0x74, 0xeb, 0xf3, 0x52, 0x48, 0xd2, 0x18, 0xe0, 0x88, 0x19, 0x52, + 0xd8, 0xdf, 0x9d, 0x04, 0x50, 0x73, 0x89, 0xf6, 0xc8, 0x87, 0xa1, 0x1c, 0xd2, 0x48, 0x34, 0x89, + 0xbc, 0xe6, 0x12, 0x97, 0x93, 0xaa, 0x10, 0x63, 0x38, 0xd9, 0x81, 0x62, 0xcf, 0xe9, 0x87, 0x34, + 0x9f, 0xc3, 0x8d, 0x1c, 0x99, 0xeb, 0x8c, 0xa2, 0x38, 0x35, 0xf3, 0x9f, 0x28, 0x78, 0x90, 0xaf, + 0x58, 0x00, 0x34, 0x39, 0x9a, 0x46, 0xb6, 0x5e, 0x49, 0x96, 0xf1, 0x80, 0x63, 0x6d, 0x50, 0x9f, + 0x3e, 0xd8, 0xaf, 0x82, 0x31, 0x2e, 0x0d, 0xb6, 0xe4, 0x1e, 0x94, 0x1c, 0xb5, 0x21, 0x8d, 0x9f, + 0xc5, 0x86, 0xc4, 0x0f, 0xb3, 0x7a, 0x46, 0x69, 0x66, 0xe4, 0x6b, 0x16, 0x4c, 0x87, 0x34, 0x92, + 0x5d, 0xc5, 0x96, 0x45, 0xa9, 0x8d, 0x8f, 0x38, 0x23, 0x1a, 0x09, 0x9a, 0x62, 0x79, 0x4f, 0x96, + 0x61, 0x8a, 0xaf, 0x12, 0xe5, 0x3a, 0x75, 0x5a, 0x34, 0xe0, 0xb6, 0x12, 0xa9, 0xe6, 0x8d, 0x2e, + 0x8a, 0x41, 0x53, 0x8b, 0x62, 0x94, 0x61, 0x8a, 0xaf, 0x12, 0x65, 0xcd, 0x0d, 0x02, 0x5f, 0x8a, + 0x52, 0xca, 0x49, 0x14, 0x83, 0xa6, 0x16, 0xc5, 0x28, 0xc3, 0x14, 0x5f, 0xd2, 0x81, 0x89, 0x1e, + 0x9f, 0x5a, 0x52, 0x95, 0x1b, 0xf1, 0x8e, 0x5c, 0x4d, 0x53, 0xda, 0x13, 0x36, 0x29, 0xf1, 0x1f, + 0x25, 0x0f, 0xfb, 0x3b, 0xe7, 0x60, 0x5a, 0x4d, 0xdb, 0xf8, 0x90, 0x23, 0x0c, 0x81, 0x43, 0x0e, + 0x39, 0x4b, 0x26, 0x10, 0x93, 0xb8, 0xac, 0xb2, 0x58, 0xb5, 0x92, 0x67, 0x1c, 0x5d, 0xb9, 0x61, + 0x02, 0x31, 0x89, 0x4b, 0xba, 0x50, 0x64, 0x2b, 0x8b, 0x72, 0xbf, 0x18, 0xf1, 0xcb, 0xe3, 0xd5, + 0xc8, 0x30, 0xaa, 0x30, 0xf2, 0x28, 0xb8, 0x70, 0x5b, 0x76, 0x94, 0x30, 0x6f, 0xcb, 0xa9, 0x98, + 0xcf, 0x6a, 0x90, 0xb4, 0x9c, 0x8b, 0xbe, 0x4f, 0x96, 0x61, 0x8a, 0x7d, 0xc6, 0xb9, 0xa7, 0x78, + 0x86, 0xe7, 0x9e, 0x4f, 0x43, 0xa9, 0xeb, 0xdc, 0x6f, 0xf4, 0x83, 0xf6, 0xe9, 0xcf, 0x57, 0xd2, + 0x9d, 0x56, 0x50, 0x41, 0x4d, 0x8f, 0x7c, 0xc9, 0x32, 0x16, 0x38, 0xe1, 0x6b, 0x71, 0x27, 0xdf, + 0x05, 0x4e, 0xab, 0x0d, 0x43, 0x97, 0xba, 0x81, 0x53, 0x48, 0xe9, 0x81, 0x9f, 0x42, 0x98, 0x46, + 0x2d, 0x26, 0x88, 0xd6, 0xa8, 0xcb, 0x67, 0xaa, 0x51, 0x2f, 0x25, 0x98, 0x61, 0x8a, 0x39, 0x97, + 0x47, 0xcc, 0x39, 0x2d, 0x0f, 0x9c, 0xa9, 0x3c, 0x8d, 0x04, 0x33, 0x4c, 0x31, 0x1f, 0x7e, 0xf4, + 0xae, 0x9c, 0xcd, 0xd1, 0x7b, 0x2a, 0x87, 0xa3, 0xf7, 0xe1, 0xa7, 0x92, 0x73, 0xa3, 0x9e, 0x4a, + 0xc8, 0x0d, 0x20, 0xad, 0x3d, 0xcf, 0xe9, 0xba, 0x4d, 0xb9, 0x58, 0xf2, 0x4d, 0x7a, 0x9a, 0x9b, + 0x66, 0xb4, 0x56, 0xb6, 0x3c, 0x80, 0x81, 0x19, 0xb5, 0x48, 0x04, 0xa5, 0x9e, 0x52, 0x3e, 0x67, + 0xf2, 0x18, 0xfd, 0x4a, 0x19, 0x15, 0x2e, 0x34, 0x6c, 0xe2, 0xa9, 0x12, 0xd4, 0x9c, 0xc8, 0x2a, + 0x5c, 0xec, 0xba, 0xde, 0xba, 0xdf, 0x0a, 0xd7, 0x69, 0x20, 0x0d, 0x4f, 0x0d, 0x1a, 0xcd, 0xcd, + 0xf2, 0xb6, 0xe1, 0xc6, 0x84, 0xb5, 0x0c, 0x38, 0x66, 0xd6, 0xb2, 0xff, 0xa7, 0x05, 0xb3, 0x4b, + 0x1d, 0xbf, 0xdf, 0xba, 0xe3, 0x44, 0xcd, 0x6d, 0xe1, 0xb1, 0x41, 0x5e, 0x81, 0x92, 0xeb, 0x45, + 0x34, 0xd8, 0x75, 0x3a, 0x72, 0x7f, 0xb2, 0x95, 0x25, 0x79, 0x45, 0x96, 0xbf, 0xb7, 0x5f, 0x9d, + 0x5e, 0xee, 0x07, 0xdc, 0x60, 0x2f, 0x56, 0x2b, 0xd4, 0x75, 0xc8, 0x77, 0x2c, 0x38, 0x2f, 0x7c, + 0x3e, 0x96, 0x9d, 0xc8, 0x79, 0xbd, 0x4f, 0x03, 0x97, 0x2a, 0xaf, 0x8f, 0x11, 0x17, 0xaa, 0xb4, + 0xac, 0x8a, 0xc1, 0x5e, 0x7c, 0x66, 0x59, 0x4b, 0x73, 0xc6, 0x41, 0x61, 0xec, 0x5f, 0x29, 0xc0, + 0xa3, 0x43, 0x69, 0x91, 0x79, 0x18, 0x73, 0x5b, 0xf2, 0xd3, 0x41, 0xd2, 0x1d, 0x5b, 0x69, 0xe1, + 0x98, 0xdb, 0x22, 0x0b, 0x5c, 0xc3, 0x0d, 0x68, 0x18, 0xaa, 0xbb, 0xf7, 0xb2, 0x56, 0x46, 0x65, + 0x29, 0x1a, 0x18, 0xa4, 0x0a, 0x45, 0xee, 0x4a, 0x2d, 0x8f, 0x56, 0x5c, 0x67, 0xe6, 0x5e, 0xcb, + 0x28, 0xca, 0xc9, 0x97, 0x2d, 0x00, 0x21, 0x20, 0xd3, 0xf7, 0xe5, 0x2e, 0x89, 0xf9, 0x36, 0x13, + 0xa3, 0x2c, 0xa4, 0x8c, 0xff, 0xa3, 0xc1, 0x95, 0x6c, 0xc0, 0x04, 0x53, 0x9f, 0xfd, 0xd6, 0xa9, + 0x37, 0x45, 0xa1, 0x00, 0x71, 0x1a, 0x28, 0x69, 0xb1, 0xb6, 0x0a, 0x68, 0xd4, 0x0f, 0x3c, 0xd6, + 0xb4, 0x7c, 0x1b, 0x2c, 0x09, 0x29, 0x50, 0x97, 0xa2, 0x81, 0x61, 0xff, 0xb3, 0x31, 0xb8, 0x98, + 0x25, 0x3a, 0xdb, 0x6d, 0x26, 0x84, 0xb4, 0xd2, 0x4a, 0xf0, 0xb3, 0xf9, 0xb7, 0x8f, 0x74, 0x5f, + 0xd2, 0x37, 0x36, 0xd2, 0x97, 0x54, 0xf2, 0x25, 0x3f, 0xab, 0x5b, 0x68, 0xec, 0x94, 0x2d, 0xa4, + 0x29, 0xa7, 0x5a, 0xe9, 0x49, 0x18, 0x0f, 0x59, 0xcf, 0x17, 0x92, 0x37, 0x3f, 0xbc, 0x8f, 0x38, + 0x84, 0x61, 0xf4, 0x3d, 0x37, 0x92, 0xf1, 0x47, 0x1a, 0xe3, 0xb6, 0xe7, 0x46, 0xc8, 0x21, 0xf6, + 0xb7, 0xc7, 0x60, 0x7e, 0xf8, 0x47, 0x91, 0x6f, 0x5b, 0x00, 0x2d, 0x76, 0x38, 0x0a, 0xb9, 0x13, + 0xbf, 0x70, 0xf7, 0x72, 0xce, 0xaa, 0x0d, 0x97, 0x15, 0xa7, 0xd8, 0x0f, 0x51, 0x17, 0x85, 0x68, + 0x08, 0x42, 0x9e, 0x53, 0x43, 0x9f, 0xdf, 0x5a, 0x89, 0xc9, 0xa4, 0xeb, 0xac, 0x69, 0x08, 0x1a, + 0x58, 0xec, 0xf4, 0xeb, 0x39, 0x5d, 0x1a, 0xf6, 0x1c, 0x1d, 0xcd, 0xc5, 0x4f, 0xbf, 0x37, 0x55, + 0x21, 0xc6, 0x70, 0xbb, 0x03, 0x4f, 0x1d, 0x43, 0xce, 0x9c, 0x82, 0x65, 0xec, 0xff, 0x6e, 0xc1, + 0x23, 0xd2, 0x13, 0xef, 0xff, 0x19, 0xb7, 0xce, 0x3f, 0xb3, 0xe0, 0xb1, 0x21, 0xdf, 0xfc, 0x00, + 0xbc, 0x3b, 0xdf, 0x4a, 0x7a, 0x77, 0xde, 0x1e, 0x75, 0x48, 0x67, 0x7e, 0xc7, 0x10, 0x27, 0xcf, + 0xdf, 0x2b, 0xc0, 0x39, 0xb6, 0x6c, 0xb5, 0xfc, 0x76, 0x4e, 0x1b, 0xe7, 0x53, 0x50, 0xfc, 0x3c, + 0xdb, 0x80, 0xd2, 0x83, 0x8c, 0xef, 0x4a, 0x28, 0x60, 0xe4, 0x2b, 0x16, 0x4c, 0x7e, 0x5e, 0xee, + 0xa9, 0xe2, 0x2c, 0x37, 0xe2, 0x62, 0x98, 0xf8, 0x86, 0x05, 0xb9, 0x43, 0x8a, 0x18, 0x1c, 0xed, + 0xcb, 0xa9, 0xb6, 0x52, 0xc5, 0x99, 0x3c, 0x03, 0x93, 0x5b, 0x7e, 0xd0, 0xed, 0x77, 0x9c, 0x74, + 0xe0, 0xe7, 0x35, 0x51, 0x8c, 0x0a, 0xce, 0x26, 0xb9, 0xd3, 0x73, 0xdf, 0xa0, 0x41, 0x28, 0x42, + 0x32, 0x12, 0x93, 0xbc, 0xa6, 0x21, 0x68, 0x60, 0xf1, 0x3a, 0xed, 0x76, 0x40, 0xdb, 0x4e, 0xe4, + 0x07, 0x7c, 0xe7, 0x30, 0xeb, 0x68, 0x08, 0x1a, 0x58, 0xf3, 0x9f, 0x80, 0x29, 0x53, 0xf8, 0x13, + 0xc5, 0xf3, 0x7c, 0x12, 0xa4, 0x53, 0x67, 0x6a, 0x49, 0xb2, 0x8e, 0xb3, 0x24, 0xd9, 0xff, 0x7e, + 0x0c, 0x0c, 0x5b, 0xd4, 0x03, 0x98, 0xea, 0x5e, 0x62, 0xaa, 0x8f, 0x68, 0x47, 0x31, 0x2c, 0x6b, + 0xc3, 0xa2, 0x1b, 0x77, 0x53, 0xd1, 0x8d, 0x37, 0x73, 0xe3, 0x78, 0x78, 0x70, 0xe3, 0x0f, 0x2d, + 0x78, 0x2c, 0x46, 0x1e, 0xb4, 0x61, 0x1f, 0xbd, 0x6e, 0xbf, 0x08, 0x15, 0x27, 0xae, 0x26, 0x27, + 0x96, 0x11, 0x5a, 0xa6, 0x41, 0x68, 0xe2, 0xc5, 0x61, 0x31, 0x85, 0x53, 0x86, 0xc5, 0x8c, 0x1f, + 0x1e, 0x16, 0x63, 0xff, 0x64, 0x0c, 0x9e, 0x18, 0xfc, 0x32, 0xd3, 0x57, 0xfc, 0xe8, 0x6f, 0x4b, + 0x7b, 0x93, 0x8f, 0x9d, 0xda, 0x9b, 0xbc, 0x70, 0x5c, 0x6f, 0x72, 0xed, 0xc3, 0x3d, 0x7e, 0xe6, + 0x3e, 0xdc, 0x0d, 0xb8, 0xa4, 0x1c, 0x46, 0xaf, 0xf9, 0x81, 0x8c, 0x0d, 0x51, 0x2b, 0x48, 0xa9, + 0xfe, 0x84, 0xac, 0x72, 0x09, 0xb3, 0x90, 0x30, 0xbb, 0xae, 0xfd, 0xc3, 0x02, 0x5c, 0x88, 0x9b, + 0x7d, 0xc9, 0xf7, 0x5a, 0x2e, 0xf7, 0x39, 0x7a, 0x19, 0xc6, 0xa3, 0xbd, 0x9e, 0x6a, 0xec, 0xff, + 0x5f, 0x89, 0xb3, 0xb1, 0xd7, 0x63, 0xbd, 0xfd, 0x48, 0x46, 0x15, 0x7e, 0x8b, 0xc0, 0x2b, 0x91, + 0x55, 0x3d, 0x3b, 0x44, 0x0f, 0xbc, 0x90, 0x1c, 0xcd, 0xef, 0xed, 0x57, 0x33, 0xb2, 0x3c, 0x2c, + 0x68, 0x4a, 0xc9, 0x31, 0x4f, 0xee, 0xc2, 0x74, 0xc7, 0x09, 0xa3, 0xdb, 0xbd, 0x96, 0x13, 0xd1, + 0x0d, 0x57, 0x7a, 0xf3, 0x9c, 0x2c, 0x9c, 0x46, 0xbb, 0x3d, 0xac, 0x26, 0x28, 0x61, 0x8a, 0x32, + 0xd9, 0x05, 0xc2, 0x4a, 0x36, 0x02, 0xc7, 0x0b, 0xc5, 0x57, 0x31, 0x7e, 0x27, 0x8f, 0x8d, 0xd2, + 0x47, 0xe7, 0xd5, 0x01, 0x6a, 0x98, 0xc1, 0x81, 0x3c, 0x0d, 0x13, 0x01, 0x75, 0x42, 0xbd, 0x1d, + 0xe8, 0xf9, 0x8f, 0xbc, 0x14, 0x25, 0xd4, 0x9c, 0x50, 0x13, 0x47, 0x4c, 0xa8, 0x3f, 0xb2, 0x60, + 0x3a, 0xee, 0xa6, 0x07, 0xa0, 0x7a, 0x74, 0x93, 0xaa, 0xc7, 0xf5, 0xbc, 0x96, 0xc4, 0x21, 0xda, + 0xc6, 0x9f, 0x4e, 0x9a, 0xdf, 0xc7, 0x03, 0x38, 0xbe, 0x60, 0xfa, 0xf3, 0x5b, 0x79, 0x44, 0xd5, + 0x25, 0xb4, 0xbd, 0x43, 0x1d, 0xf9, 0x99, 0xae, 0xd3, 0x92, 0x7a, 0x8c, 0x1c, 0xf6, 0x5a, 0xd7, + 0x51, 0xfa, 0x4d, 0x96, 0xae, 0xa3, 0xea, 0x90, 0xdb, 0xf0, 0x48, 0x2f, 0xf0, 0x79, 0x9e, 0x81, + 0x65, 0xea, 0xb4, 0x3a, 0xae, 0x47, 0x95, 0x99, 0x47, 0x78, 0xdd, 0x3c, 0x76, 0xb0, 0x5f, 0x7d, + 0x64, 0x3d, 0x1b, 0x05, 0x87, 0xd5, 0x4d, 0x46, 0xaa, 0x8e, 0x1f, 0x23, 0x52, 0xf5, 0x97, 0xb4, + 0x31, 0x55, 0x07, 0x45, 0x7c, 0x26, 0xaf, 0xae, 0xcc, 0x0a, 0x8f, 0xd0, 0x43, 0xaa, 0x26, 0x99, + 0xa2, 0x66, 0x3f, 0xdc, 0x62, 0x37, 0x71, 0x4a, 0x8b, 0x5d, 0x1c, 0x07, 0x33, 0xf9, 0x7e, 0xc6, + 0xc1, 0x94, 0x3e, 0x50, 0x71, 0x30, 0xdf, 0xb1, 0xe0, 0x82, 0x33, 0x18, 0x81, 0x9e, 0x8f, 0xf1, + 0x38, 0x23, 0xb4, 0xbd, 0xfe, 0x98, 0x14, 0x32, 0x2b, 0xd0, 0x1f, 0xb3, 0x44, 0xb1, 0xdf, 0x2d, + 0xc2, 0x6c, 0x5a, 0x49, 0x3a, 0xfb, 0x50, 0xdd, 0xbf, 0x61, 0xc1, 0xac, 0x9a, 0xe0, 0xfa, 0x06, + 0x5c, 0x1c, 0x31, 0x56, 0x73, 0x5a, 0x57, 0x84, 0xba, 0xa7, 0x33, 0xa8, 0x6c, 0xa4, 0xb8, 0xe1, + 0x00, 0x7f, 0xf2, 0x26, 0x54, 0xf4, 0xad, 0xca, 0xa9, 0xe2, 0x76, 0x79, 0x68, 0x69, 0x2d, 0x26, + 0x81, 0x26, 0x3d, 0xf2, 0xae, 0x05, 0xd0, 0x54, 0x3b, 0x71, 0x4e, 0x51, 0x51, 0x19, 0xda, 0x42, + 0xac, 0xcf, 0xeb, 0xa2, 0x10, 0x0d, 0xc6, 0xe4, 0x57, 0xf8, 0x7d, 0x8a, 0x1e, 0x09, 0xca, 0xf3, + 0xe0, 0x53, 0x79, 0x2f, 0x45, 0xb1, 0x2f, 0x89, 0xd6, 0xf6, 0x0c, 0x50, 0x88, 0x09, 0x21, 0xec, + 0x97, 0x41, 0xfb, 0x6c, 0xb3, 0x95, 0x95, 0x7b, 0x6d, 0xaf, 0x3b, 0xd1, 0xb6, 0x1c, 0x82, 0x7a, + 0x65, 0xbd, 0xa6, 0x00, 0x18, 0xe3, 0xd8, 0x9f, 0x83, 0xe9, 0x57, 0x03, 0xa7, 0xb7, 0xed, 0xf2, + 0x7b, 0x0b, 0x76, 0x3e, 0x7e, 0x06, 0x26, 0x9d, 0x56, 0x2b, 0x2b, 0xd9, 0x4f, 0x4d, 0x14, 0xa3, + 0x82, 0x1f, 0xeb, 0x28, 0x6c, 0xff, 0x6b, 0x0b, 0x48, 0x7c, 0xd3, 0xec, 0x7a, 0xed, 0x35, 0x27, + 0x6a, 0x6e, 0xb3, 0x23, 0xdc, 0x36, 0x2f, 0xcd, 0x3a, 0xc2, 0x5d, 0xd7, 0x10, 0x34, 0xb0, 0xc8, + 0xdb, 0x50, 0x11, 0xff, 0xde, 0xd0, 0x07, 0xc4, 0xd1, 0x5d, 0xcf, 0xf9, 0x9e, 0xc7, 0x65, 0x12, + 0xa3, 0xf0, 0x7a, 0xcc, 0x01, 0x4d, 0x76, 0xac, 0xa9, 0x56, 0xbc, 0xad, 0x4e, 0xff, 0x7e, 0x6b, + 0x33, 0x6e, 0xaa, 0x5e, 0xe0, 0x6f, 0xb9, 0x1d, 0x9a, 0x6e, 0xaa, 0x75, 0x51, 0x8c, 0x0a, 0x7e, + 0xbc, 0xa6, 0xfa, 0x57, 0x16, 0x5c, 0x5c, 0x09, 0x23, 0xd7, 0x5f, 0xa6, 0x61, 0xc4, 0x76, 0x3e, + 0xb6, 0x3e, 0xf6, 0x3b, 0xc7, 0x09, 0xbf, 0x58, 0x86, 0x59, 0x79, 0x0f, 0xdd, 0xdf, 0x0c, 0x69, + 0x64, 0x1c, 0x35, 0xf4, 0x3c, 0x5e, 0x4a, 0xc1, 0x71, 0xa0, 0x06, 0xa3, 0x22, 0x2f, 0xa4, 0x63, + 0x2a, 0x85, 0x24, 0x95, 0x46, 0x0a, 0x8e, 0x03, 0x35, 0xec, 0x1f, 0x14, 0xe0, 0x02, 0xff, 0x8c, + 0x54, 0xe8, 0xd4, 0x37, 0x87, 0x85, 0x4e, 0x8d, 0x38, 0x95, 0x39, 0xaf, 0x53, 0x04, 0x4e, 0xfd, + 0x75, 0x0b, 0x66, 0x5a, 0xc9, 0x96, 0xce, 0xc7, 0x2e, 0x97, 0xd5, 0x87, 0xc2, 0x03, 0x31, 0x55, + 0x88, 0x69, 0xfe, 0xe4, 0x57, 0x2d, 0x98, 0x49, 0x8a, 0xa9, 0x56, 0xf7, 0x33, 0x68, 0x24, 0x1d, + 0x32, 0x90, 0x2c, 0x0f, 0x31, 0x2d, 0x82, 0xfd, 0xfb, 0x63, 0xb2, 0x4b, 0xcf, 0x22, 0x2e, 0x88, + 0xdc, 0x83, 0x72, 0xd4, 0x09, 0x45, 0xa1, 0xfc, 0xda, 0x11, 0x0f, 0xad, 0x1b, 0xab, 0x0d, 0xe1, + 0x70, 0x12, 0xeb, 0x95, 0xb2, 0x84, 0xe9, 0xc7, 0x8a, 0x17, 0x67, 0xdc, 0xec, 0x49, 0xc6, 0xb9, + 0x9c, 0x96, 0x37, 0x96, 0xd6, 0xd3, 0x8c, 0x65, 0x09, 0x63, 0xac, 0x78, 0xd9, 0xbf, 0x69, 0x41, + 0xf9, 0x86, 0xaf, 0xd6, 0x91, 0x9f, 0xcb, 0xc1, 0x16, 0xa5, 0x55, 0x56, 0xad, 0xb4, 0xc4, 0xa7, + 0xa0, 0x57, 0x12, 0x96, 0xa8, 0xc7, 0x0d, 0xda, 0x0b, 0x3c, 0xe7, 0x21, 0x23, 0x75, 0xc3, 0xdf, + 0x1c, 0x6a, 0x3e, 0xfe, 0xb5, 0x22, 0x9c, 0x7b, 0xcd, 0xd9, 0xa3, 0x5e, 0xe4, 0x9c, 0x7c, 0x93, + 0x78, 0x11, 0x2a, 0x4e, 0x8f, 0xdf, 0x65, 0x1a, 0xc7, 0x90, 0xd8, 0xb8, 0x13, 0x83, 0xd0, 0xc4, + 0x8b, 0x17, 0x34, 0x11, 0xa4, 0x93, 0xb5, 0x14, 0x2d, 0xa5, 0xe0, 0x38, 0x50, 0x83, 0xdc, 0x00, + 0x22, 0x03, 0xdb, 0x6b, 0xcd, 0xa6, 0xdf, 0xf7, 0xc4, 0x92, 0x26, 0xec, 0x3e, 0xfa, 0x3c, 0xbc, + 0x36, 0x80, 0x81, 0x19, 0xb5, 0xc8, 0x67, 0x61, 0xae, 0xc9, 0x29, 0xcb, 0xd3, 0x91, 0x49, 0x51, + 0x9c, 0x90, 0x75, 0xd8, 0xcb, 0xd2, 0x10, 0x3c, 0x1c, 0x4a, 0x81, 0x49, 0x1a, 0x46, 0x7e, 0xe0, + 0xb4, 0xa9, 0x49, 0x77, 0x22, 0x29, 0x69, 0x63, 0x00, 0x03, 0x33, 0x6a, 0x91, 0x2f, 0x42, 0x39, + 0xda, 0x0e, 0x68, 0xb8, 0xed, 0x77, 0x5a, 0xd2, 0xf7, 0x64, 0x44, 0x63, 0xa0, 0xec, 0xfd, 0x0d, + 0x45, 0xd5, 0x18, 0xde, 0xaa, 0x08, 0x63, 0x9e, 0x24, 0x80, 0x89, 0xb0, 0xe9, 0xf7, 0x68, 0x28, + 0x4f, 0x15, 0x37, 0x72, 0xe1, 0xce, 0x8d, 0x5b, 0x86, 0x19, 0x92, 0x73, 0x40, 0xc9, 0xc9, 0xfe, + 0xdd, 0x31, 0x98, 0x32, 0x11, 0x8f, 0xb1, 0x36, 0x7d, 0xc5, 0x82, 0xa9, 0xa6, 0xef, 0x45, 0x81, + 0xdf, 0x89, 0x13, 0x36, 0x8c, 0xae, 0x51, 0x30, 0x52, 0xcb, 0x34, 0x72, 0xdc, 0x8e, 0x61, 0xad, + 0x33, 0xd8, 0x60, 0x82, 0x29, 0xf9, 0x86, 0x05, 0x33, 0xb1, 0x63, 0x64, 0x6c, 0xeb, 0xcb, 0x55, + 0x10, 0xbd, 0xd4, 0x5f, 0x4d, 0x72, 0xc2, 0x34, 0x6b, 0x7b, 0x13, 0x66, 0xd3, 0xbd, 0xcd, 0x9a, + 0xb2, 0xe7, 0xc8, 0xb9, 0x5e, 0x88, 0x9b, 0x72, 0xdd, 0x09, 0x43, 0xe4, 0x10, 0xf2, 0x2c, 0x94, + 0xba, 0x4e, 0xd0, 0x76, 0x3d, 0xa7, 0xc3, 0x5b, 0xb1, 0x60, 0x2c, 0x48, 0xb2, 0x1c, 0x35, 0x86, + 0xfd, 0x51, 0x98, 0x5a, 0x73, 0xbc, 0x36, 0x6d, 0xc9, 0x75, 0xf8, 0xe8, 0xc8, 0xd4, 0x3f, 0x19, + 0x87, 0x8a, 0x71, 0x7c, 0x3c, 0xfb, 0x73, 0x56, 0x22, 0x11, 0x51, 0x21, 0xc7, 0x44, 0x44, 0x9f, + 0x06, 0xd8, 0x72, 0x3d, 0x37, 0xdc, 0x3e, 0x65, 0x8a, 0x23, 0x7e, 0x37, 0x7f, 0x4d, 0x53, 0x40, + 0x83, 0x5a, 0x7c, 0x01, 0x5a, 0x3c, 0x24, 0x5b, 0xe0, 0xbb, 0x96, 0xb1, 0xdd, 0x4c, 0xe4, 0xe1, + 0xf0, 0x61, 0x74, 0xcc, 0x82, 0xda, 0x7e, 0xc4, 0xdd, 0xd4, 0x61, 0xbb, 0xd2, 0x06, 0x94, 0x02, + 0x1a, 0xf6, 0xbb, 0xf4, 0x54, 0xc9, 0x88, 0xb8, 0xeb, 0x0d, 0xca, 0xfa, 0xa8, 0x29, 0xcd, 0xbf, + 0x0c, 0xe7, 0x12, 0x22, 0x9c, 0xe8, 0x86, 0xc9, 0x87, 0x4c, 0x1b, 0xc5, 0x69, 0xee, 0x9b, 0x58, + 0x5f, 0x74, 0x8c, 0x24, 0x44, 0xba, 0x2f, 0x84, 0x83, 0x95, 0x80, 0xd9, 0x3f, 0x99, 0x00, 0xe9, + 0xc3, 0x70, 0x8c, 0xe5, 0xca, 0xbc, 0xb9, 0x1c, 0x3b, 0xc5, 0xcd, 0xe5, 0x0d, 0x98, 0x72, 0x3d, + 0x37, 0x72, 0x9d, 0x0e, 0xb7, 0x3f, 0xc9, 0xed, 0x54, 0x39, 0xe3, 0x4f, 0xad, 0x18, 0xb0, 0x0c, + 0x3a, 0x89, 0xba, 0xe4, 0x75, 0x28, 0xf2, 0xfd, 0x46, 0x0e, 0xe0, 0x93, 0x3b, 0x5a, 0x70, 0x1f, + 0x1b, 0x11, 0xa1, 0x27, 0x28, 0xf1, 0xc3, 0x87, 0xc8, 0xc2, 0xa4, 0x8f, 0xdf, 0x72, 0x1c, 0xc7, + 0x87, 0x8f, 0x14, 0x1c, 0x07, 0x6a, 0x30, 0x2a, 0x5b, 0x8e, 0xdb, 0xe9, 0x07, 0x34, 0xa6, 0x32, + 0x91, 0xa4, 0x72, 0x2d, 0x05, 0xc7, 0x81, 0x1a, 0x64, 0x0b, 0xa6, 0x64, 0x99, 0x70, 0x9b, 0x9b, + 0x3c, 0xe5, 0x57, 0x72, 0xf7, 0xc8, 0x6b, 0x06, 0x25, 0x4c, 0xd0, 0x25, 0x7d, 0x38, 0xef, 0x7a, + 0x4d, 0xdf, 0x6b, 0x76, 0xfa, 0xa1, 0xbb, 0x4b, 0xe3, 0xf0, 0xb8, 0xd3, 0x30, 0xbb, 0x74, 0xb0, + 0x5f, 0x3d, 0xbf, 0x92, 0x26, 0x87, 0x83, 0x1c, 0xc8, 0x97, 0x2c, 0xb8, 0xd4, 0xf4, 0xbd, 0x90, + 0x67, 0xf1, 0xd8, 0xa5, 0x57, 0x83, 0xc0, 0x0f, 0x04, 0xef, 0xf2, 0x29, 0x79, 0x73, 0xb3, 0xe7, + 0x52, 0x16, 0x49, 0xcc, 0xe6, 0x44, 0xde, 0x82, 0x52, 0x2f, 0xf0, 0x77, 0xdd, 0x16, 0x0d, 0xa4, + 0x0b, 0xe6, 0x6a, 0x1e, 0xa9, 0x8d, 0xd6, 0x25, 0xcd, 0x78, 0xe9, 0x51, 0x25, 0xa8, 0xf9, 0xd9, + 0xff, 0xbb, 0x02, 0xd3, 0x49, 0x74, 0xf2, 0x0b, 0x00, 0xbd, 0xc0, 0xef, 0xd2, 0x68, 0x9b, 0xea, + 0x30, 0xa7, 0x9b, 0xa3, 0x26, 0xaf, 0x51, 0xf4, 0x94, 0xdb, 0x12, 0x5b, 0x2e, 0xe2, 0x52, 0x34, + 0x38, 0x92, 0x00, 0x26, 0x77, 0xc4, 0xb6, 0x2b, 0xb5, 0x90, 0xd7, 0x72, 0xd1, 0x99, 0x24, 0x67, + 0x1e, 0x9f, 0x23, 0x8b, 0x50, 0x31, 0x22, 0x9b, 0x50, 0xb8, 0x47, 0x37, 0xf3, 0xc9, 0x9c, 0x70, + 0x87, 0xca, 0xd3, 0x4c, 0x7d, 0xf2, 0x60, 0xbf, 0x5a, 0xb8, 0x43, 0x37, 0x91, 0x11, 0x67, 0xdf, + 0xd5, 0x12, 0xbe, 0x0b, 0x72, 0xa9, 0x78, 0x2d, 0x47, 0x47, 0x08, 0xf1, 0x5d, 0xb2, 0x08, 0x15, + 0x23, 0xf2, 0x16, 0x94, 0xef, 0x39, 0xbb, 0x74, 0x2b, 0xf0, 0xbd, 0x48, 0xfa, 0xca, 0x8d, 0x18, + 0x5c, 0x72, 0x47, 0x91, 0x93, 0x7c, 0xf9, 0xf6, 0xae, 0x0b, 0x31, 0x66, 0x47, 0x76, 0xa1, 0xe4, + 0xd1, 0x7b, 0x48, 0x3b, 0x6e, 0x33, 0x9f, 0x60, 0x8e, 0x9b, 0x92, 0x9a, 0xe4, 0xcc, 0xf7, 0x3d, + 0x55, 0x86, 0x9a, 0x17, 0xeb, 0xcb, 0xbb, 0xfe, 0xa6, 0x5c, 0xa8, 0x46, 0xec, 0x4b, 0x7d, 0x32, + 0x15, 0x7d, 0x79, 0xc3, 0xdf, 0x44, 0x46, 0x9c, 0xcd, 0x91, 0xa6, 0x76, 0xd4, 0x92, 0xcb, 0xd4, + 0xcd, 0x7c, 0x1d, 0xd4, 0xc4, 0x1c, 0x89, 0x4b, 0xd1, 0xe0, 0xc8, 0xda, 0xb6, 0x2d, 0x8d, 0x95, + 0x72, 0xa1, 0x1a, 0xb1, 0x6d, 0x93, 0xa6, 0x4f, 0xd1, 0xb6, 0xaa, 0x0c, 0x35, 0x2f, 0xc6, 0xd7, + 0x95, 0x96, 0xbf, 0x7c, 0x96, 0xaa, 0xa4, 0x1d, 0x51, 0xf0, 0x55, 0x65, 0xa8, 0x79, 0xb1, 0xf6, + 0x0e, 0x77, 0xf6, 0xee, 0x39, 0x9d, 0x1d, 0xd7, 0x6b, 0xcb, 0xb0, 0xdd, 0x51, 0xc3, 0xdc, 0x76, + 0xf6, 0xee, 0x08, 0x7a, 0x66, 0x7b, 0xc7, 0xa5, 0x68, 0x70, 0x24, 0x7f, 0xd7, 0xd2, 0xa1, 0x38, + 0x53, 0x79, 0x38, 0x31, 0x25, 0x97, 0x5c, 0x19, 0x99, 0x23, 0x14, 0xc5, 0x9f, 0xd6, 0x7e, 0x97, + 0xbc, 0xf0, 0xeb, 0x7f, 0x5c, 0x9d, 0xa3, 0x5e, 0xd3, 0x6f, 0xb9, 0x5e, 0x7b, 0xf1, 0x6e, 0xe8, + 0x7b, 0x0b, 0xe8, 0xdc, 0x53, 0x3a, 0xba, 0x94, 0x69, 0xfe, 0xe3, 0x50, 0x31, 0x48, 0x1c, 0xa5, + 0xe8, 0x4d, 0x99, 0x8a, 0xde, 0x6f, 0x4e, 0xc0, 0x94, 0x99, 0x87, 0xf4, 0x18, 0xda, 0x97, 0x3e, + 0x71, 0x8c, 0x9d, 0xe4, 0xc4, 0xc1, 0x8e, 0x98, 0xc6, 0x05, 0x97, 0x32, 0x6f, 0xad, 0xe4, 0xa6, + 0x70, 0xc7, 0x47, 0x4c, 0xa3, 0x30, 0xc4, 0x04, 0xd3, 0x13, 0xf8, 0xbc, 0x30, 0xb5, 0x55, 0x28, + 0x76, 0xc5, 0xa4, 0xda, 0x9a, 0x50, 0xd5, 0x9e, 0x03, 0x88, 0x13, 0x66, 0xca, 0x8b, 0x4f, 0xad, + 0x0f, 0x1b, 0x89, 0x3c, 0x0d, 0x2c, 0xf2, 0x34, 0x4c, 0x30, 0xd5, 0x87, 0xb6, 0x64, 0x56, 0x01, + 0x7d, 0x8e, 0xbf, 0xc6, 0x4b, 0x51, 0x42, 0xc9, 0x4b, 0x4c, 0x4b, 0x8d, 0x15, 0x16, 0x99, 0x2c, + 0xe0, 0x62, 0xac, 0xa5, 0xc6, 0x30, 0x4c, 0x60, 0x32, 0xd1, 0x29, 0xd3, 0x2f, 0xf8, 0xda, 0x60, + 0x88, 0xce, 0x95, 0x0e, 0x14, 0x30, 0x6e, 0x57, 0x4a, 0xe9, 0x23, 0x7c, 0x4e, 0x17, 0x0d, 0xbb, + 0x52, 0x0a, 0x8e, 0x03, 0x35, 0xd8, 0xc7, 0xc8, 0x3b, 0xdb, 0x8a, 0x70, 0x98, 0x1e, 0x72, 0xdb, + 0xfa, 0x55, 0xf3, 0xac, 0x95, 0xe3, 0x1c, 0x12, 0xa3, 0xf6, 0xf8, 0x87, 0xad, 0xd1, 0x8e, 0x45, + 0x9f, 0x83, 0xe9, 0xe4, 0x2e, 0x94, 0xfb, 0xcd, 0xc7, 0xd7, 0xc6, 0xe1, 0xc2, 0xcd, 0xb6, 0xeb, + 0xa5, 0x73, 0xbe, 0x65, 0x3d, 0xf0, 0x60, 0x9d, 0xf8, 0x81, 0x07, 0x1d, 0x93, 0x27, 0x9f, 0x4f, + 0xc8, 0x8e, 0xc9, 0x53, 0x6f, 0x59, 0x24, 0x71, 0xc9, 0x1f, 0x59, 0xf0, 0xb8, 0xd3, 0x12, 0xe7, + 0x02, 0xa7, 0x23, 0x4b, 0x8d, 0xbc, 0xe4, 0x72, 0x46, 0x87, 0x23, 0xee, 0xf2, 0x83, 0x1f, 0xbf, + 0x50, 0x3b, 0x84, 0xab, 0xe8, 0xf1, 0x9f, 0x92, 0x5f, 0xf0, 0xf8, 0x61, 0xa8, 0x78, 0xa8, 0xf8, + 0xe4, 0x2f, 0xc3, 0x4c, 0xe2, 0x83, 0xa5, 0x25, 0xbc, 0x2c, 0x2e, 0x2c, 0x1a, 0x49, 0x10, 0xa6, + 0x71, 0xe7, 0x6f, 0xc1, 0x87, 0x8e, 0x94, 0xf3, 0x44, 0x83, 0xed, 0xfb, 0x16, 0x4c, 0x99, 0xe9, + 0x99, 0xc8, 0xb3, 0x50, 0x8a, 0xfc, 0x1d, 0xea, 0xdd, 0x0e, 0x94, 0xc3, 0xae, 0x1e, 0xe8, 0x1b, + 0xbc, 0x1c, 0x57, 0x51, 0x63, 0x30, 0xec, 0x66, 0xc7, 0xa5, 0x5e, 0xb4, 0xd2, 0x92, 0xdd, 0xac, + 0xb1, 0x97, 0x44, 0xf9, 0x32, 0x6a, 0x0c, 0xe1, 0x63, 0xc7, 0x7e, 0x37, 0x68, 0x33, 0xa0, 0xca, + 0xbd, 0xdf, 0xf0, 0xb1, 0x8b, 0x61, 0x98, 0xc0, 0x24, 0xb6, 0x36, 0x71, 0x8e, 0xc7, 0xf7, 0x1a, + 0x29, 0x93, 0xe4, 0x77, 0x2d, 0x28, 0x0b, 0x13, 0x3d, 0xd2, 0xad, 0x94, 0x8b, 0x6d, 0xca, 0x88, + 0x50, 0x5b, 0x5f, 0xc9, 0x72, 0xb1, 0x7d, 0x12, 0xc6, 0x77, 0x5c, 0x4f, 0x7d, 0x89, 0xde, 0x96, + 0x5e, 0x73, 0xbd, 0x16, 0x72, 0x88, 0xde, 0xb8, 0x0a, 0x43, 0x37, 0xae, 0x45, 0x28, 0x6b, 0xc7, + 0x13, 0xb9, 0xfc, 0x6b, 0xeb, 0xad, 0x76, 0x54, 0xc1, 0x18, 0xc7, 0xfe, 0x75, 0x0b, 0xa6, 0x79, + 0xc4, 0x78, 0x7c, 0x1e, 0x7e, 0x51, 0xfb, 0x82, 0x09, 0xb9, 0x9f, 0x48, 0xfa, 0x82, 0xbd, 0xb7, + 0x5f, 0xad, 0x88, 0x18, 0xf3, 0xa4, 0x6b, 0xd8, 0x67, 0xa4, 0x11, 0x8d, 0x7b, 0xac, 0x8d, 0x9d, + 0xd8, 0xc6, 0x13, 0x8b, 0xa9, 0x88, 0x60, 0x4c, 0xcf, 0x7e, 0x1b, 0xa6, 0xcc, 0x60, 0x2c, 0xf2, + 0x22, 0x54, 0x7a, 0xae, 0xd7, 0x4e, 0x06, 0xed, 0xea, 0x8b, 0x86, 0xf5, 0x18, 0x84, 0x26, 0x1e, + 0xaf, 0xe6, 0xc7, 0xd5, 0x52, 0xf7, 0x13, 0xeb, 0xbe, 0x59, 0x2d, 0xfe, 0x63, 0x7b, 0x00, 0x71, + 0x64, 0xf1, 0xb1, 0x8c, 0x37, 0x13, 0xc2, 0xf6, 0x2f, 0x94, 0x11, 0x9e, 0x25, 0x62, 0x42, 0x8c, + 0xf0, 0xf7, 0xf6, 0x0f, 0x53, 0x76, 0x44, 0x2d, 0xfe, 0x06, 0x45, 0x46, 0x90, 0x61, 0xee, 0x6f, + 0x50, 0x64, 0xf0, 0x78, 0xff, 0xde, 0xa0, 0xc8, 0x12, 0xe6, 0xcf, 0xd7, 0x1b, 0x14, 0x9f, 0x82, + 0x93, 0xa6, 0xa3, 0x65, 0xba, 0xc5, 0x3d, 0x33, 0x6d, 0x84, 0x6e, 0x71, 0x99, 0x37, 0x42, 0x42, + 0xed, 0xdf, 0x29, 0xc0, 0x6c, 0xda, 0xc4, 0x90, 0xb7, 0xf7, 0x06, 0xf9, 0x86, 0x05, 0xd3, 0x4e, + 0x22, 0xf5, 0x5f, 0x4e, 0x0f, 0x5a, 0x25, 0x68, 0x1a, 0xa9, 0xe7, 0x12, 0xe5, 0x98, 0xe2, 0x4d, + 0xfe, 0x3f, 0x98, 0x8c, 0xdc, 0x2e, 0xf5, 0xfb, 0xc2, 0xf0, 0x58, 0x10, 0x06, 0x80, 0x0d, 0x51, + 0x84, 0x0a, 0xc6, 0x36, 0x01, 0x97, 0x6b, 0x6c, 0x01, 0x95, 0x9e, 0xc8, 0xb3, 0xb1, 0xa5, 0x54, + 0x94, 0xa3, 0xc6, 0x20, 0xf7, 0x61, 0x52, 0xf8, 0x79, 0x28, 0x87, 0x9e, 0xb5, 0x9c, 0x4c, 0x21, + 0xc2, 0x95, 0x24, 0xee, 0x02, 0xf1, 0x3f, 0x44, 0xc5, 0xce, 0xfe, 0x28, 0x9c, 0x30, 0x3f, 0xaf, + 0x7d, 0x15, 0x08, 0xfa, 0x9d, 0xce, 0xa6, 0xd3, 0xdc, 0xb9, 0xe3, 0x7a, 0x2d, 0xff, 0x1e, 0x5f, + 0xfa, 0x16, 0xa1, 0x1c, 0xc8, 0x10, 0xdd, 0x50, 0x8e, 0x1a, 0xbd, 0x76, 0xaa, 0xd8, 0xdd, 0x10, + 0x63, 0x1c, 0xfb, 0xf7, 0xc7, 0x60, 0x52, 0xc6, 0x93, 0x3f, 0x80, 0x48, 0x88, 0x9d, 0xc4, 0xfd, + 0xf3, 0x4a, 0x2e, 0x61, 0xf0, 0x43, 0xc3, 0x20, 0xc2, 0x54, 0x18, 0xc4, 0x6b, 0xf9, 0xb0, 0x3b, + 0x3c, 0x06, 0xe2, 0x7b, 0x45, 0x98, 0x49, 0xc5, 0xe7, 0xa7, 0x52, 0x79, 0x5b, 0xef, 0x4b, 0x2a, + 0x6f, 0x12, 0x26, 0xd2, 0xb9, 0xe7, 0xe7, 0x37, 0xf9, 0x17, 0x99, 0xdd, 0xf3, 0xf2, 0x68, 0x2d, + 0x7e, 0x70, 0x3c, 0x5a, 0xff, 0xb3, 0x05, 0x8f, 0x0e, 0xcd, 0x32, 0xc1, 0xf3, 0xb5, 0x05, 0x49, + 0xa8, 0x5c, 0x2f, 0x72, 0xce, 0xdc, 0xa3, 0xef, 0xaa, 0xd3, 0x29, 0xb6, 0xd2, 0xec, 0xc9, 0x0b, + 0x30, 0xc5, 0xf5, 0x41, 0xb6, 0x72, 0x46, 0xb4, 0x27, 0xaf, 0xda, 0xf8, 0xa5, 0x4b, 0xc3, 0x28, + 0xc7, 0x04, 0x96, 0xfd, 0x1d, 0x0b, 0xe6, 0x86, 0x65, 0xef, 0x3a, 0x86, 0x26, 0xf7, 0x97, 0x52, + 0x91, 0x24, 0xd5, 0x81, 0x48, 0x92, 0x94, 0x29, 0x48, 0x05, 0x8d, 0x18, 0x56, 0x98, 0xc2, 0x11, + 0x81, 0x12, 0x7f, 0x50, 0x80, 0x59, 0x29, 0x62, 0xac, 0x84, 0xbf, 0x94, 0x88, 0x7f, 0xf9, 0xa9, + 0x54, 0xfc, 0xcb, 0xc5, 0x34, 0xfe, 0x5f, 0x04, 0xbf, 0x7c, 0xb0, 0x82, 0x5f, 0xbe, 0x5e, 0x84, + 0x4b, 0x99, 0x79, 0xb2, 0xc8, 0xd7, 0x32, 0x76, 0x8a, 0x3b, 0x39, 0x27, 0xe4, 0xd2, 0x71, 0xb2, + 0x67, 0x1b, 0x31, 0xf2, 0xab, 0x66, 0xa4, 0x86, 0x58, 0xfd, 0xb7, 0xce, 0x20, 0xb5, 0xd8, 0x49, + 0x83, 0x36, 0x1e, 0xec, 0x53, 0x67, 0x7f, 0x0e, 0x96, 0xfa, 0xaf, 0x17, 0xe0, 0xca, 0x71, 0x5b, + 0xf6, 0x03, 0x1a, 0xe5, 0x18, 0x26, 0xa2, 0x1c, 0x1f, 0x90, 0x6a, 0x73, 0x26, 0x01, 0x8f, 0x7f, + 0x7f, 0x5c, 0xef, 0xbb, 0x83, 0x13, 0xf6, 0x58, 0xb6, 0x85, 0x49, 0xa6, 0xfa, 0xaa, 0x84, 0xf0, + 0xf1, 0xde, 0x30, 0xd9, 0x10, 0xc5, 0xef, 0xed, 0x57, 0xcf, 0xc7, 0x09, 0x65, 0x64, 0x21, 0xaa, + 0x4a, 0xe4, 0x0a, 0x94, 0x02, 0x01, 0x55, 0x71, 0x5d, 0xd2, 0xbb, 0x46, 0x94, 0xa1, 0x86, 0x92, + 0x2f, 0x1a, 0x67, 0x85, 0xf1, 0xb3, 0xca, 0x9b, 0x74, 0x98, 0xd3, 0xd0, 0x9b, 0x50, 0x0a, 0x55, + 0xd6, 0x72, 0x31, 0x9d, 0x9e, 0x3f, 0x66, 0xb8, 0xa0, 0xb3, 0x49, 0x3b, 0x2a, 0x85, 0xb9, 0xf8, + 0x3e, 0x9d, 0xe0, 0x5c, 0x93, 0x24, 0xb6, 0x3e, 0x7b, 0x8b, 0x4b, 0x0d, 0x18, 0x3c, 0x77, 0x93, + 0x08, 0x26, 0xe5, 0xd3, 0xc5, 0xf2, 0xb6, 0x75, 0x2d, 0xa7, 0xb8, 0x1b, 0xe9, 0x95, 0xcd, 0x8f, + 0xb4, 0xca, 0xe6, 0xa4, 0x58, 0xd9, 0x3f, 0xb4, 0xa0, 0x22, 0xc7, 0xc8, 0x03, 0x88, 0x9b, 0xbc, + 0x9b, 0x8c, 0x9b, 0xbc, 0x9a, 0xcb, 0x12, 0x3e, 0x24, 0x68, 0xf2, 0x2e, 0x4c, 0x99, 0x19, 0x2b, + 0xc9, 0xa7, 0x8d, 0x2d, 0xc8, 0x1a, 0x25, 0x2b, 0x9b, 0xda, 0xa4, 0xe2, 0xed, 0xc9, 0xfe, 0xc7, + 0x65, 0xdd, 0x8a, 0xfc, 0xe0, 0x6c, 0x8e, 0x7c, 0xeb, 0xd0, 0x91, 0x6f, 0x0e, 0xbc, 0xb1, 0xfc, + 0x07, 0xde, 0xeb, 0x50, 0x52, 0xcb, 0xa2, 0xd4, 0xa6, 0x9e, 0x32, 0xdd, 0xb4, 0x99, 0x4a, 0xc6, + 0x88, 0x19, 0xd3, 0x85, 0x1f, 0x80, 0x63, 0x4b, 0xb8, 0x5a, 0xae, 0x35, 0x19, 0xf2, 0x16, 0x54, + 0xee, 0xf9, 0xc1, 0x4e, 0xc7, 0x77, 0xf8, 0x53, 0x11, 0x90, 0x87, 0x67, 0x80, 0xb6, 0x66, 0x8b, + 0x58, 0x99, 0x3b, 0x31, 0x7d, 0x34, 0x99, 0x91, 0x1a, 0xcc, 0x74, 0x5d, 0x0f, 0xa9, 0xd3, 0xd2, + 0xe1, 0x91, 0xe3, 0x22, 0x4d, 0xbb, 0xd2, 0xed, 0xd7, 0x92, 0x60, 0x4c, 0xe3, 0x73, 0xcb, 0x53, + 0x90, 0x30, 0x75, 0xc8, 0x5c, 0xcc, 0xeb, 0xa3, 0x0f, 0xc6, 0xa4, 0xf9, 0x44, 0x04, 0x8b, 0x24, + 0xcb, 0x31, 0xc5, 0x9b, 0x7c, 0x01, 0x4a, 0xa1, 0x7a, 0x14, 0xb4, 0x98, 0xe3, 0xa9, 0x47, 0x3f, + 0x0c, 0xaa, 0xbb, 0x52, 0xbf, 0x0c, 0xaa, 0x19, 0x92, 0x55, 0xb8, 0xa8, 0x6c, 0x37, 0x89, 0xf7, + 0x0d, 0x27, 0xe2, 0x7c, 0x62, 0x98, 0x01, 0xc7, 0xcc, 0x5a, 0x4c, 0xb7, 0xe5, 0x99, 0x60, 0xc5, + 0x4d, 0xac, 0x71, 0x79, 0xc9, 0xe7, 0x5f, 0x0b, 0x25, 0xf4, 0xb0, 0xe8, 0xdf, 0xd2, 0x08, 0xd1, + 0xbf, 0x0d, 0xb8, 0x94, 0x06, 0xf1, 0x44, 0x71, 0x3c, 0x37, 0x9d, 0xb1, 0x85, 0xae, 0x67, 0x21, + 0x61, 0x76, 0x5d, 0x72, 0x07, 0xca, 0x01, 0xe5, 0xa7, 0xbc, 0x9a, 0x72, 0x62, 0x3b, 0xb1, 0xbb, + 0x2e, 0x2a, 0x02, 0x18, 0xd3, 0x62, 0xfd, 0xee, 0x24, 0x13, 0xa7, 0xbf, 0x9e, 0xe3, 0xab, 0xe1, + 0xb2, 0xef, 0x87, 0x24, 0x70, 0xb4, 0xff, 0xcd, 0x0c, 0x9c, 0x4b, 0x18, 0xa0, 0xc8, 0x53, 0x50, + 0xe4, 0x99, 0xf3, 0xf8, 0x6a, 0x55, 0x8a, 0x57, 0x54, 0xd1, 0x38, 0x02, 0x46, 0x7e, 0xd9, 0x82, + 0x99, 0x5e, 0xe2, 0x02, 0x47, 0x2d, 0xe4, 0x23, 0x5a, 0x6d, 0x93, 0xb7, 0x42, 0xc6, 0x93, 0x23, + 0x49, 0x66, 0x98, 0xe6, 0xce, 0xd6, 0x03, 0xe9, 0xf3, 0xde, 0xa1, 0x01, 0xc7, 0x96, 0x8a, 0x9e, + 0x26, 0xb1, 0x94, 0x04, 0x63, 0x1a, 0x9f, 0xf5, 0x30, 0xff, 0xba, 0x51, 0x5e, 0x86, 0xad, 0x29, + 0x02, 0x18, 0xd3, 0x22, 0xaf, 0xc0, 0xb4, 0xcc, 0x97, 0xbd, 0xee, 0xb7, 0xae, 0x3b, 0xe1, 0xb6, + 0x3c, 0xf2, 0xe9, 0x23, 0xea, 0x52, 0x02, 0x8a, 0x29, 0x6c, 0xfe, 0x6d, 0x71, 0x52, 0x72, 0x4e, + 0x60, 0x22, 0xf9, 0x22, 0xcb, 0x52, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0xac, 0xb1, 0x0d, 0x09, 0xef, + 0x08, 0xbd, 0x1a, 0x64, 0x6c, 0x45, 0x35, 0x98, 0xe9, 0xf3, 0x13, 0x72, 0x4b, 0x01, 0xe5, 0x7c, + 0xd4, 0x0c, 0x6f, 0x27, 0xc1, 0x98, 0xc6, 0x27, 0x2f, 0xc3, 0xb9, 0x80, 0x2d, 0xb6, 0x9a, 0x80, + 0x70, 0x99, 0xd0, 0x37, 0xe2, 0x68, 0x02, 0x31, 0x89, 0x4b, 0x5e, 0x85, 0xf3, 0x71, 0x4e, 0x55, + 0x45, 0x40, 0xf8, 0x50, 0xe8, 0x04, 0x7f, 0xb5, 0x34, 0x02, 0x0e, 0xd6, 0x21, 0x7f, 0x15, 0x66, + 0x8d, 0x96, 0x58, 0xf1, 0x5a, 0xf4, 0xbe, 0xcc, 0x7b, 0xc9, 0x5f, 0x18, 0x5b, 0x4a, 0xc1, 0x70, + 0x00, 0x9b, 0x7c, 0x02, 0xa6, 0x9b, 0x7e, 0xa7, 0xc3, 0xd7, 0x38, 0xf1, 0x1a, 0x88, 0x48, 0x70, + 0x29, 0x52, 0x81, 0x26, 0x20, 0x98, 0xc2, 0x24, 0x37, 0x80, 0xf8, 0x9b, 0x4c, 0xbd, 0xa2, 0xad, + 0x57, 0xa9, 0x47, 0xa5, 0xc6, 0x71, 0x2e, 0x19, 0x71, 0x73, 0x6b, 0x00, 0x03, 0x33, 0x6a, 0xf1, + 0xfc, 0x80, 0x46, 0x84, 0xf2, 0x74, 0x1e, 0x19, 0xc9, 0xd3, 0xf6, 0x9c, 0x23, 0xc3, 0x93, 0x03, + 0x98, 0x10, 0x01, 0x50, 0xf9, 0x64, 0xba, 0x34, 0x1f, 0x06, 0x88, 0xf7, 0x08, 0x51, 0x8a, 0x92, + 0x13, 0xf9, 0x05, 0x28, 0x6f, 0xaa, 0x57, 0x62, 0x78, 0x7a, 0xcb, 0x91, 0xf7, 0xc5, 0xd4, 0x83, + 0x47, 0xb1, 0xbd, 0x42, 0x03, 0x30, 0x66, 0x49, 0x9e, 0x86, 0xca, 0xf5, 0xf5, 0x9a, 0x1e, 0x85, + 0xe7, 0x79, 0xef, 0x8f, 0xb3, 0x2a, 0x68, 0x02, 0xd8, 0x0c, 0xd3, 0xea, 0x1b, 0x49, 0xba, 0x05, + 0x64, 0x68, 0x63, 0x0c, 0x9b, 0xfb, 0x39, 0x60, 0x63, 0xee, 0x42, 0x0a, 0x5b, 0x96, 0xa3, 0xc6, + 0x20, 0x6f, 0x42, 0x45, 0xee, 0x17, 0x7c, 0x6d, 0xba, 0x78, 0xba, 0xe8, 0x77, 0x8c, 0x49, 0xa0, + 0x49, 0x8f, 0x5f, 0x50, 0xf3, 0xc7, 0x33, 0xe8, 0xb5, 0x7e, 0xa7, 0x33, 0x77, 0x89, 0xaf, 0x9b, + 0xf1, 0x05, 0x75, 0x0c, 0x42, 0x13, 0x8f, 0x3c, 0xaf, 0xfc, 0xd5, 0x1e, 0x4e, 0xdc, 0xd8, 0x6b, + 0x7f, 0x35, 0xad, 0x74, 0x0f, 0x09, 0x90, 0x79, 0xe4, 0x08, 0x47, 0xb1, 0x4d, 0x98, 0x57, 0x1a, + 0xdf, 0xe0, 0x24, 0x99, 0x9b, 0x4b, 0xd8, 0x8e, 0xe6, 0xef, 0x0c, 0xc5, 0xc4, 0x43, 0xa8, 0x90, + 0x4d, 0x28, 0x38, 0x9d, 0xcd, 0xb9, 0x47, 0xf3, 0x50, 0x5d, 0x6b, 0xab, 0x75, 0x39, 0xa2, 0xb8, + 0x53, 0x6b, 0x6d, 0xb5, 0x8e, 0x8c, 0x38, 0x71, 0x61, 0xdc, 0xe9, 0x6c, 0x86, 0x73, 0xf3, 0x7c, + 0xce, 0xe6, 0xc6, 0x24, 0x36, 0x1e, 0xac, 0xd6, 0x43, 0xe4, 0x2c, 0xec, 0x2f, 0x8d, 0xe9, 0x5b, + 0x22, 0x9d, 0x6c, 0xfc, 0x6d, 0x73, 0x02, 0x89, 0xe3, 0xce, 0xad, 0xdc, 0x26, 0x90, 0x54, 0x2f, + 0xce, 0x0d, 0x9d, 0x3e, 0x3d, 0xbd, 0x64, 0xe4, 0x92, 0xa5, 0x2c, 0x99, 0x48, 0x5d, 0x9c, 0x9e, + 0x93, 0x0b, 0x86, 0xfd, 0xe5, 0x8a, 0xb6, 0x82, 0xa6, 0x7c, 0xbd, 0x02, 0x28, 0xba, 0x61, 0xe4, + 0xfa, 0x39, 0x06, 0x85, 0xa7, 0x32, 0x90, 0xf3, 0x98, 0x13, 0x0e, 0x40, 0xc1, 0x8a, 0xf1, 0xf4, + 0xda, 0xae, 0x77, 0x5f, 0x7e, 0xfe, 0xeb, 0xb9, 0x3b, 0x71, 0x09, 0x9e, 0x1c, 0x80, 0x82, 0x15, + 0xb9, 0x2b, 0x06, 0x75, 0x21, 0x8f, 0xbe, 0xae, 0xad, 0xd6, 0x53, 0xfc, 0x92, 0x83, 0xfb, 0x2e, + 0x14, 0xc2, 0xae, 0x2b, 0xd5, 0xa5, 0x11, 0x79, 0x35, 0xd6, 0x56, 0xb2, 0x78, 0x35, 0xd6, 0x56, + 0x90, 0x31, 0x21, 0x5f, 0xb5, 0x00, 0x9c, 0xee, 0xa6, 0x13, 0x86, 0x4e, 0x4b, 0x5b, 0x67, 0x46, + 0x7c, 0x64, 0xa5, 0xa6, 0xe9, 0xa5, 0x58, 0x73, 0xb7, 0xe5, 0x18, 0x8a, 0x06, 0x67, 0xf2, 0x16, + 0x4c, 0x3a, 0xe2, 0x15, 0x4b, 0xe9, 0x81, 0x9f, 0xcf, 0xd3, 0xac, 0x29, 0x09, 0xb8, 0x99, 0x46, + 0x82, 0x50, 0x31, 0x64, 0xbc, 0xa3, 0xc0, 0xa1, 0x5b, 0xee, 0x8e, 0x34, 0x0e, 0x35, 0x46, 0x7e, + 0x67, 0x85, 0x11, 0xcb, 0xe2, 0x2d, 0x41, 0xa8, 0x18, 0x92, 0x5f, 0xb4, 0xe0, 0x5c, 0xd7, 0xf1, + 0x1c, 0x1d, 0x57, 0x99, 0x4f, 0xf4, 0xad, 0x19, 0xa9, 0x19, 0x6b, 0x88, 0x6b, 0x26, 0x23, 0x4c, + 0xf2, 0x25, 0xbb, 0x30, 0xe1, 0xf0, 0xf7, 0x75, 0xe5, 0x51, 0x0c, 0xf3, 0x78, 0xab, 0x37, 0xd5, + 0x06, 0x7c, 0x71, 0x91, 0xaf, 0xf8, 0x4a, 0x6e, 0xe4, 0x37, 0x2c, 0x98, 0x14, 0xce, 0xe1, 0x4c, + 0x21, 0x65, 0xdf, 0xfe, 0xb9, 0x33, 0x78, 0xc9, 0x40, 0x3a, 0xae, 0x4b, 0xf7, 0xa3, 0x0f, 0x6b, + 0xcf, 0x57, 0x51, 0x7a, 0xa8, 0xeb, 0xba, 0x92, 0x8e, 0xa9, 0xbe, 0x5d, 0xe7, 0x7e, 0xe2, 0x15, + 0x1d, 0x53, 0xf5, 0x5d, 0x4b, 0xc1, 0x70, 0x00, 0x7b, 0xfe, 0x13, 0x30, 0x65, 0xca, 0x71, 0x22, + 0xf7, 0xf7, 0x1f, 0x17, 0x00, 0x78, 0x57, 0x89, 0x5c, 0x2c, 0x5d, 0x9e, 0xb8, 0x79, 0xdb, 0x6f, + 0xe5, 0xf4, 0x9a, 0xa7, 0x91, 0x52, 0x05, 0x64, 0x96, 0xe6, 0x6d, 0xbf, 0x85, 0x92, 0x09, 0x69, + 0xc3, 0x78, 0xcf, 0x89, 0xb6, 0xf3, 0xcf, 0xdf, 0x52, 0x12, 0x41, 0xc9, 0xd1, 0x36, 0x72, 0x06, + 0xe4, 0x1d, 0x2b, 0xf6, 0xec, 0x29, 0xe4, 0x91, 0x7b, 0x36, 0x6e, 0xb3, 0x05, 0xe9, 0xcb, 0x93, + 0x4a, 0xc1, 0x9a, 0xf6, 0xf0, 0x99, 0x7f, 0xd7, 0x82, 0x29, 0x13, 0x35, 0xa3, 0x9b, 0x7e, 0xde, + 0xec, 0xa6, 0x3c, 0xdb, 0xc3, 0xec, 0xf1, 0xff, 0x6a, 0x01, 0x60, 0xdf, 0x6b, 0xf4, 0xbb, 0x5d, + 0xa6, 0xb6, 0x6b, 0x2f, 0x7f, 0xeb, 0xd8, 0x5e, 0xfe, 0x63, 0x27, 0xf4, 0xf2, 0x2f, 0x9c, 0xc8, + 0xcb, 0x7f, 0xfc, 0xe4, 0x5e, 0xfe, 0xc5, 0xe1, 0x5e, 0xfe, 0xf6, 0xb7, 0x2c, 0x38, 0x3f, 0xb0, + 0x5f, 0x31, 0x4d, 0x3a, 0xf0, 0xfd, 0x68, 0x88, 0x87, 0x28, 0xc6, 0x20, 0x34, 0xf1, 0xc8, 0x32, + 0xcc, 0xca, 0x67, 0x4a, 0x1a, 0xbd, 0x8e, 0x9b, 0x99, 0x5b, 0x67, 0x23, 0x05, 0xc7, 0x81, 0x1a, + 0xf6, 0xef, 0x58, 0x50, 0x31, 0x22, 0xf2, 0xd9, 0x77, 0x70, 0x37, 0x61, 0x29, 0x46, 0xfc, 0x42, + 0x0b, 0xbf, 0xea, 0x12, 0x30, 0x71, 0x0d, 0xdd, 0x36, 0x92, 0xd8, 0xc7, 0xd7, 0xd0, 0xac, 0x14, + 0x25, 0x54, 0xa4, 0x27, 0xa7, 0x3d, 0xde, 0xe8, 0x05, 0x33, 0x3d, 0x39, 0xed, 0x21, 0x87, 0x70, + 0x76, 0xec, 0x48, 0x21, 0x3d, 0x80, 0x8d, 0x07, 0x61, 0x9c, 0x20, 0x42, 0x01, 0x23, 0x4f, 0x40, + 0x81, 0x7a, 0x2d, 0x69, 0xff, 0xd0, 0xaf, 0xd7, 0x5e, 0xf5, 0x5a, 0xc8, 0xca, 0xed, 0x5b, 0x30, + 0x25, 0xbc, 0x9f, 0x5f, 0xa3, 0x7b, 0xc7, 0x7e, 0x0e, 0x97, 0x8d, 0xf6, 0xd4, 0x73, 0xb8, 0xac, + 0x3a, 0x2b, 0xb7, 0xff, 0x91, 0x05, 0xa9, 0x37, 0x92, 0x8c, 0x1b, 0x18, 0x6b, 0xe8, 0x0d, 0x8c, + 0x69, 0xb5, 0x1f, 0x3b, 0xd4, 0x6a, 0x7f, 0x03, 0x48, 0x97, 0x4d, 0x85, 0xe4, 0x42, 0x5b, 0x48, + 0x3e, 0x25, 0xb1, 0x36, 0x80, 0x81, 0x19, 0xb5, 0xec, 0x7f, 0x28, 0x84, 0x35, 0x5f, 0x4d, 0x3a, + 0xba, 0x01, 0xfa, 0x50, 0xe4, 0xa4, 0xa4, 0xfd, 0x6d, 0x44, 0xdb, 0xf5, 0x60, 0x1e, 0xad, 0xb8, + 0x23, 0xe5, 0x94, 0xe7, 0xdc, 0xec, 0x3f, 0x10, 0xb2, 0x9a, 0xcf, 0x2a, 0x1d, 0x2d, 0x6b, 0x37, + 0x29, 0xeb, 0xf5, 0xbc, 0xd6, 0xca, 0x6c, 0x19, 0xc9, 0x02, 0x40, 0x8f, 0x06, 0x4d, 0xea, 0x45, + 0x2a, 0x2e, 0xa9, 0x28, 0x23, 0x64, 0x75, 0x29, 0x1a, 0x18, 0xf6, 0x37, 0xd9, 0x04, 0x8a, 0x1f, + 0x8a, 0x26, 0x57, 0xd2, 0xae, 0xae, 0xe9, 0xc9, 0xa1, 0x3d, 0x5d, 0x8d, 0x68, 0x95, 0xb1, 0x23, + 0xa2, 0x55, 0x9e, 0x81, 0xc9, 0xc0, 0xef, 0xd0, 0x5a, 0xe0, 0xa5, 0x7d, 0x74, 0x90, 0x15, 0xe3, + 0x4d, 0x54, 0x70, 0xfb, 0xd7, 0x2c, 0x98, 0x4d, 0x87, 0xd3, 0xe5, 0xee, 0x7f, 0x6b, 0xc6, 0xfc, + 0x17, 0x4e, 0x1e, 0xf3, 0x6f, 0x7f, 0xaf, 0x08, 0xb3, 0xe9, 0x07, 0xec, 0x18, 0x67, 0x97, 0x1b, + 0xdb, 0x52, 0xab, 0xbf, 0xb0, 0xb2, 0x09, 0x98, 0x1e, 0x2f, 0x63, 0x43, 0xc7, 0xcb, 0x35, 0x28, + 0xfb, 0x3d, 0x75, 0xe0, 0x17, 0xc2, 0x5d, 0x51, 0xc6, 0x9a, 0x5b, 0x0a, 0xf0, 0xde, 0x7e, 0xf5, + 0x42, 0x2c, 0x80, 0x2e, 0xc6, 0xb8, 0x2a, 0xf9, 0x19, 0x65, 0xa9, 0x18, 0x4f, 0x64, 0xd1, 0xd1, + 0x96, 0x8a, 0x99, 0xb8, 0xfe, 0x30, 0x63, 0x45, 0xf1, 0x24, 0xd9, 0x3c, 0x26, 0x72, 0xcc, 0xe6, + 0x71, 0x07, 0xca, 0xd2, 0xb6, 0x7a, 0xaa, 0x2c, 0x16, 0x9c, 0xf0, 0x6d, 0x45, 0x00, 0x63, 0x5a, + 0xa9, 0x34, 0x21, 0xa5, 0x5c, 0xd3, 0x84, 0xbc, 0x0c, 0x93, 0x9b, 0x4e, 0x73, 0xc7, 0xdf, 0xda, + 0xe2, 0xfa, 0x79, 0xb9, 0xfe, 0x21, 0xd5, 0x70, 0x75, 0x51, 0x9c, 0x31, 0xa4, 0x54, 0x0d, 0xa6, + 0x15, 0x50, 0xe5, 0x8e, 0xac, 0xcc, 0xbe, 0x5a, 0x2b, 0xd0, 0x8e, 0xca, 0x21, 0x1a, 0x58, 0xe4, + 0x15, 0xed, 0x7f, 0x56, 0x89, 0x83, 0x1f, 0xb4, 0xef, 0xd9, 0x21, 0xc1, 0x0f, 0xd2, 0xbd, 0xf6, + 0x1d, 0x36, 0xd5, 0x22, 0xb7, 0xb9, 0xe3, 0x7a, 0x22, 0xd9, 0x03, 0x9b, 0xff, 0xcf, 0xc0, 0x24, + 0x95, 0xcf, 0x36, 0x8b, 0xcb, 0x10, 0xdd, 0xfd, 0xea, 0xb5, 0x66, 0x05, 0x27, 0x35, 0x98, 0x51, + 0x57, 0xc0, 0xea, 0x06, 0x4b, 0x24, 0xa9, 0xd1, 0x16, 0xf3, 0xe5, 0x24, 0x18, 0xd3, 0xf8, 0xf6, + 0x17, 0xa1, 0x62, 0xa8, 0x56, 0x5c, 0x0b, 0xb9, 0xef, 0x34, 0xa3, 0xf4, 0xee, 0x7d, 0x95, 0x15, + 0xa2, 0x80, 0xf1, 0x8b, 0x36, 0x11, 0xb3, 0x96, 0xda, 0xbd, 0x65, 0xa4, 0x9a, 0x84, 0x32, 0x62, + 0x01, 0x6d, 0xd3, 0xfb, 0xea, 0xa5, 0x0c, 0x45, 0x0c, 0x59, 0x21, 0x0a, 0x98, 0xfd, 0x2c, 0x94, + 0x54, 0x2a, 0x31, 0x9e, 0x8f, 0x47, 0x5d, 0x02, 0x99, 0xf9, 0x78, 0xfc, 0x20, 0x42, 0x0e, 0xb1, + 0xdf, 0x80, 0x92, 0xca, 0x78, 0x76, 0x34, 0x36, 0xdb, 0x50, 0x43, 0xcf, 0xbd, 0xee, 0x87, 0x91, + 0x4a, 0xd3, 0x26, 0xee, 0xa9, 0x6f, 0xae, 0xf0, 0x32, 0xd4, 0x50, 0xfb, 0xcf, 0x2c, 0xa8, 0x6c, + 0x6c, 0xac, 0x6a, 0xf3, 0x15, 0xc2, 0xc3, 0xa1, 0x68, 0xa1, 0xda, 0x56, 0x44, 0x4d, 0x87, 0x18, + 0xb1, 0xb6, 0xcc, 0x1f, 0xec, 0x57, 0x1f, 0x6e, 0x64, 0x62, 0xe0, 0x90, 0x9a, 0x64, 0x05, 0x2e, + 0x98, 0x10, 0x99, 0x3e, 0x43, 0xee, 0xf4, 0xfc, 0x9d, 0xef, 0xc6, 0x20, 0x18, 0xb3, 0xea, 0xa4, + 0x49, 0x49, 0xa5, 0xd5, 0x7c, 0x32, 0xbc, 0x31, 0x08, 0xc6, 0xac, 0x3a, 0xf6, 0xf3, 0x30, 0x93, + 0xf2, 0xd4, 0x38, 0x46, 0xda, 0xa2, 0xdf, 0x2d, 0xc0, 0x94, 0x79, 0x61, 0x7f, 0x8c, 0x5d, 0xf8, + 0xf8, 0xca, 0x4d, 0xc6, 0x25, 0x7b, 0xe1, 0x84, 0x97, 0xec, 0xa6, 0x57, 0xc3, 0xf8, 0xd9, 0x7a, + 0x35, 0x14, 0xf3, 0xf1, 0x6a, 0x30, 0xbc, 0x6f, 0x26, 0x1e, 0x9c, 0xf7, 0xcd, 0x6f, 0x17, 0x61, + 0x3a, 0x99, 0x07, 0xf7, 0x18, 0x3d, 0xf9, 0xec, 0x40, 0x4f, 0x9e, 0xf0, 0x56, 0xaf, 0x30, 0xea, + 0xad, 0xde, 0xf8, 0xa8, 0xb7, 0x7a, 0xc5, 0x53, 0xdc, 0xea, 0x0d, 0xde, 0xc9, 0x4d, 0x1c, 0xfb, + 0x4e, 0xee, 0x93, 0x7a, 0xa3, 0x98, 0x4c, 0x38, 0xb2, 0xc5, 0x9b, 0x05, 0x49, 0x76, 0xc3, 0x92, + 0xdf, 0xca, 0x74, 0xb0, 0x2e, 0x1d, 0xa1, 0x10, 0x04, 0x99, 0x7e, 0xc5, 0x27, 0x77, 0x1c, 0x78, + 0xf8, 0x04, 0x3e, 0xc5, 0x2f, 0x42, 0x45, 0x8e, 0x27, 0x7e, 0x84, 0x84, 0xe4, 0xf1, 0xb3, 0x11, + 0x83, 0xd0, 0xc4, 0x63, 0x03, 0xa3, 0x17, 0x4f, 0x10, 0x7e, 0xbf, 0x5c, 0x49, 0xde, 0x2f, 0xaf, + 0x27, 0xc1, 0x98, 0xc6, 0xb7, 0xbf, 0x00, 0x97, 0x32, 0x0d, 0x89, 0xfc, 0x12, 0x87, 0x9f, 0x6e, + 0x68, 0x4b, 0x22, 0x18, 0x62, 0xa4, 0x9e, 0xc7, 0x99, 0xbf, 0x33, 0x14, 0x13, 0x0f, 0xa1, 0x62, + 0xff, 0x56, 0x01, 0xa6, 0x93, 0xcf, 0x45, 0x93, 0x7b, 0xfa, 0xda, 0x21, 0x97, 0x1b, 0x0f, 0x41, + 0xd6, 0xc8, 0xad, 0x3a, 0xf4, 0xba, 0xf2, 0x1e, 0x1f, 0x5f, 0x9b, 0x3a, 0xd1, 0xeb, 0xd9, 0x31, + 0x96, 0xf7, 0x84, 0x92, 0x1d, 0x7f, 0x74, 0x39, 0x0e, 0xc3, 0x96, 0xd6, 0xa8, 0xdc, 0xb9, 0xc7, + 0xe1, 0xc4, 0x9a, 0x15, 0x1a, 0x6c, 0xd9, 0xde, 0xb2, 0x4b, 0x03, 0x77, 0xcb, 0xa5, 0x2d, 0x99, + 0x77, 0x9f, 0xaf, 0xdc, 0x6f, 0xc8, 0x32, 0xd4, 0x50, 0xfb, 0x9d, 0x31, 0x28, 0xf3, 0xac, 0x71, + 0xd7, 0x02, 0xbf, 0xcb, 0x1f, 0x12, 0x0d, 0x8d, 0x93, 0xbf, 0xec, 0xb6, 0x1b, 0xa3, 0xbe, 0x0d, + 0x1c, 0x53, 0x94, 0x41, 0x1b, 0x46, 0x09, 0x26, 0x38, 0x92, 0x1e, 0x94, 0xb6, 0x64, 0x96, 0x6b, + 0xd9, 0x77, 0x23, 0x66, 0x6a, 0x55, 0x39, 0xb3, 0x45, 0x13, 0xa8, 0x7f, 0xa8, 0xb9, 0xd8, 0x0e, + 0xcc, 0xa4, 0xd2, 0xfe, 0xe4, 0x9e, 0x1b, 0xfb, 0x7f, 0x8c, 0x43, 0x59, 0x47, 0x0b, 0x92, 0x8f, + 0x27, 0xcc, 0xb0, 0xb1, 0x56, 0x2e, 0xed, 0xa7, 0xec, 0x24, 0xa4, 0x91, 0x53, 0x26, 0xd5, 0x27, + 0xa0, 0xd0, 0x0f, 0x3a, 0x69, 0x3b, 0xcb, 0x6d, 0x5c, 0x45, 0x56, 0x6e, 0x46, 0x38, 0x16, 0x1e, + 0x68, 0x84, 0x23, 0xdb, 0x25, 0x37, 0xfd, 0xd6, 0x5e, 0xfa, 0x55, 0xbc, 0xba, 0xdf, 0xda, 0x43, + 0x0e, 0x21, 0xaf, 0xc0, 0xb4, 0x0c, 0xdb, 0x54, 0x4a, 0x4c, 0x91, 0xeb, 0xa9, 0xda, 0xfd, 0x66, + 0x23, 0x01, 0xc5, 0x14, 0x36, 0xdb, 0x65, 0xd9, 0xb1, 0x81, 0x67, 0x3c, 0x9f, 0x48, 0xde, 0xd5, + 0xdf, 0x68, 0xdc, 0xba, 0xc9, 0xcd, 0xc1, 0x1a, 0x23, 0x11, 0x19, 0x3a, 0x79, 0x64, 0x64, 0xe8, + 0xb2, 0xa0, 0xcd, 0xa4, 0xe5, 0x3b, 0xca, 0x54, 0xfd, 0x8a, 0xa2, 0xcb, 0xca, 0x0e, 0x3d, 0xbb, + 0xe8, 0x9a, 0x59, 0x31, 0xb4, 0xe5, 0xf7, 0x2f, 0x86, 0xd6, 0xbe, 0x0d, 0x33, 0xa9, 0xfe, 0x53, + 0x66, 0x3a, 0x2b, 0xdb, 0x4c, 0x77, 0xbc, 0x77, 0xf5, 0xfe, 0xa9, 0x05, 0xe7, 0x07, 0x56, 0xa4, + 0xe3, 0x06, 0x33, 0xa7, 0xf7, 0xc6, 0xb1, 0xd3, 0xef, 0x8d, 0x85, 0x93, 0xed, 0x8d, 0xf5, 0xcd, + 0xef, 0xff, 0xe8, 0xf2, 0x43, 0x3f, 0xf8, 0xd1, 0xe5, 0x87, 0xfe, 0xf0, 0x47, 0x97, 0x1f, 0x7a, + 0xe7, 0xe0, 0xb2, 0xf5, 0xfd, 0x83, 0xcb, 0xd6, 0x0f, 0x0e, 0x2e, 0x5b, 0x7f, 0x78, 0x70, 0xd9, + 0xfa, 0x4f, 0x07, 0x97, 0xad, 0x6f, 0xfd, 0xc9, 0xe5, 0x87, 0x3e, 0xfd, 0xc9, 0xb8, 0xa7, 0x16, + 0x55, 0x4f, 0xf1, 0x1f, 0x1f, 0x51, 0xfd, 0xb2, 0xd8, 0xdb, 0x69, 0x2f, 0xb2, 0x9e, 0x5a, 0xd4, + 0x25, 0xaa, 0xa7, 0xfe, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd3, 0x74, 0x04, 0x71, 0x21, 0xab, + 0x00, 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -9872,8 +9875,16 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Status) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status))) i-- - dAtA[i] = 0x4a + dAtA[i] = 0x5a } + i = encodeVarintGenerated(dAtA, i, uint64(m.Executions)) + i-- + dAtA[i] = 0x50 + i -= len(m.Backoff) + copy(dAtA[i:], m.Backoff) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Backoff))) + i-- + dAtA[i] = 0x4a if m.FinishedAt != nil { { size, err := m.FinishedAt.MarshalToSizedBuffer(dAtA[:i]) @@ -12823,6 +12834,9 @@ func (m *StepPluginStatus) Size() (n int) { l = m.FinishedAt.Size() n += 1 + l + sovGenerated(uint64(l)) } + l = len(m.Backoff) + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.Executions)) if m.Status != nil { l = len(m.Status) n += 1 + l + sovGenerated(uint64(l)) @@ -14751,6 +14765,8 @@ func (this *StepPluginStatus) String() string { `StartedAt:` + strings.Replace(fmt.Sprintf("%v", this.StartedAt), "Time", "v1.Time", 1) + `,`, `UpdatedAt:` + strings.Replace(fmt.Sprintf("%v", this.UpdatedAt), "Time", "v1.Time", 1) + `,`, `FinishedAt:` + strings.Replace(fmt.Sprintf("%v", this.FinishedAt), "Time", "v1.Time", 1) + `,`, + `Backoff:` + fmt.Sprintf("%v", this.Backoff) + `,`, + `Executions:` + fmt.Sprintf("%v", this.Executions) + `,`, `Status:` + valueToStringGenerated(this.Status) + `,`, `}`, }, "") @@ -33970,6 +33986,57 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Backoff", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Backoff = DurationString(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Executions", wireType) + } + m.Executions = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Executions |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 705b09eab0..0ba42b6407 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1771,10 +1771,14 @@ message StepPluginStatus { optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 8; + optional string backoff = 9; + + optional int32 executions = 10; + // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - optional bytes status = 9; + optional bytes status = 11; } message StickinessConfig { diff --git a/rollout/steps/plugin/mocks/StepPlugin.go b/rollout/steps/plugin/mocks/StepPlugin.go index d612909edf..acbb3bebea 100644 --- a/rollout/steps/plugin/mocks/StepPlugin.go +++ b/rollout/steps/plugin/mocks/StepPlugin.go @@ -3,9 +3,9 @@ package mocks import ( - v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" - plugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" mock "github.com/stretchr/testify/mock" + + v1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" ) // StepPlugin is an autogenerated mock type for the StepPlugin type @@ -43,8 +43,26 @@ func (_m *StepPlugin) Abort(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, return r0, r1 } +// Enabled provides a mock function with given fields: +func (_m *StepPlugin) Enabled() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Enabled") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // Run provides a mock function with given fields: _a0 -func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *plugin.StepResult, error) { +func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { ret := _m.Called(_a0) if len(ret) == 0 { @@ -52,9 +70,8 @@ func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *p } var r0 *v1alpha1.StepPluginStatus - var r1 *plugin.StepResult - var r2 error - if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *plugin.StepResult, error)); ok { + var r1 error + if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error)); ok { return rf(_a0) } if rf, ok := ret.Get(0).(func(*v1alpha1.Rollout) *v1alpha1.StepPluginStatus); ok { @@ -65,21 +82,13 @@ func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, *p } } - if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout) *plugin.StepResult); ok { + if rf, ok := ret.Get(1).(func(*v1alpha1.Rollout) error); ok { r1 = rf(_a0) } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(*plugin.StepResult) - } - } - - if rf, ok := ret.Get(2).(func(*v1alpha1.Rollout) error); ok { - r2 = rf(_a0) - } else { - r2 = ret.Error(2) + r1 = ret.Error(1) } - return r0, r1, r2 + return r0, r1 } // Terminate provides a mock function with given fields: _a0 diff --git a/ui/src/models/rollout/generated/api.ts b/ui/src/models/rollout/generated/api.ts index 157b02b45c..084a2097cd 100755 --- a/ui/src/models/rollout/generated/api.ts +++ b/ui/src/models/rollout/generated/api.ts @@ -2843,6 +2843,18 @@ export interface GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginS * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus */ finishedAt?: K8sIoApimachineryPkgApisMetaV1Time; + /** + * + * @type {string} + * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus + */ + backoff?: string; + /** + * + * @type {number} + * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus + */ + executions?: number; /** * * @type {string} From dfeab0bebbf428d8c87f6c72362a7ee466ef4698 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 19 Apr 2024 15:52:23 -0400 Subject: [PATCH 23/41] fix duration cast Signed-off-by: Alexandre Gaudreault --- rollout/steps/plugin/plugin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 4a03a7eb6a..b30dc3afa5 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -69,7 +69,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, p.log.Errorf("error during plugin execution") stepStatus.Phase = v1alpha1.StepPluginPhaseError stepStatus.Message = err.Error() - stepStatus.Backoff = v1alpha1.DurationString(30 * time.Second) + stepStatus.Backoff = v1alpha1.DurationString((30 * time.Second).String()) return stepStatus, nil } From bcb39ade2247f0c42299682fb5dab576485c05fe Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 19 Apr 2024 20:56:40 -0400 Subject: [PATCH 24/41] refactor to use context object Signed-off-by: Alexandre Gaudreault --- controller/controller.go | 3 - rollout/canary.go | 7 +- rollout/context.go | 8 +-- rollout/controller.go | 9 +-- rollout/stepplugin.go | 127 +++++++++++++++++++-------------- rollout/stepplugin_test.go | 125 +++++++++++++++++++------------- rollout/sync.go | 2 +- utils/conditions/conditions.go | 5 ++ 8 files changed, 165 insertions(+), 121 deletions(-) diff --git a/controller/controller.go b/controller/controller.go index 16af0b34b5..e9509cd78e 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -13,7 +13,6 @@ import ( istioutil "github.com/argoproj/argo-rollouts/utils/istio" - stepPlugin "github.com/argoproj/argo-rollouts/rollout/steps/plugin" rolloutsConfig "github.com/argoproj/argo-rollouts/utils/config" goPlugin "github.com/hashicorp/go-plugin" @@ -304,7 +303,6 @@ func NewManager( serviceWorkqueue := workqueue.NewNamedRateLimitingQueue(queue.DefaultArgoRolloutsRateLimiter(), "Services") ingressWorkqueue := workqueue.NewNamedRateLimitingQueue(queue.DefaultArgoRolloutsRateLimiter(), "Ingresses") - stepPluginResolver := stepPlugin.NewResolver() refResolver := rollout.NewInformerBasedWorkloadRefResolver(namespace, dynamicclientset, discoveryClient, argoprojclientset, rolloutsInformer.Informer()) apiFactory := notificationapi.NewFactory(record.NewAPIFactorySettings(analysisRunInformer), defaults.Namespace(), notificationSecretInformerFactory.Core().V1().Secrets().Informer(), notificationConfigMapInformerFactory.Core().V1().ConfigMaps().Informer()) recorder := record.NewEventRecorder(kubeclientset, metrics.MetricRolloutEventsTotal, metrics.MetricNotificationFailedTotal, metrics.MetricNotificationSuccessTotal, metrics.MetricNotificationSend, apiFactory) @@ -347,7 +345,6 @@ func NewManager( IngressWorkQueue: ingressWorkqueue, MetricsServer: metricsServer, Recorder: recorder, - StepPluginResolver: stepPluginResolver, }) experimentController := experiments.NewController(experiments.ControllerConfig{ diff --git a/rollout/canary.go b/rollout/canary.go index d6635ee8bb..5b5b762ba5 100644 --- a/rollout/canary.go +++ b/rollout/canary.go @@ -87,7 +87,7 @@ func (c *rolloutContext) rolloutCanary() error { return c.syncRolloutStatusCanary() } - err = c.reconcileCanaryPluginStep() + err = c.stepPluginContext.reconcile(c) if err != nil { return err } @@ -350,7 +350,7 @@ func (c *rolloutContext) completedCurrentCanaryStep() bool { case currentStep.SetMirrorRoute != nil: return true case currentStep.Plugin != nil: - return c.isStepPluginCompleted(*currentStepIndex, currentStep.Plugin) + return c.stepPluginContext.isStepPluginCompleted(*currentStepIndex, currentStep.Plugin) } return false } @@ -361,7 +361,8 @@ func (c *rolloutContext) syncRolloutStatusCanary() error { newStatus.HPAReplicas = replicasetutil.GetActualReplicaCountForReplicaSets(c.allRSs) newStatus.Selector = metav1.FormatLabelSelector(c.rollout.Spec.Selector) newStatus.Canary.StablePingPong = c.rollout.Status.Canary.StablePingPong - newStatus.Canary.StepPluginStatuses = c.calculateStepPluginStatus() + newStatus.Canary.StepPluginStatuses = c.rollout.Status.Canary.StepPluginStatuses + c.stepPluginContext.updateStatus(&newStatus) currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) newStatus.StableRS = c.rollout.Status.StableRS diff --git a/rollout/context.go b/rollout/context.go index 64a9772923..c595a5718b 100644 --- a/rollout/context.go +++ b/rollout/context.go @@ -39,11 +39,9 @@ type rolloutContext struct { currentEx *v1alpha1.Experiment otherExs []*v1alpha1.Experiment - newStatus v1alpha1.RolloutStatus - pauseContext *pauseContext - - // stepPluginStatuses are the mutated values to use in the newStatus - stepPluginStatuses []v1alpha1.StepPluginStatus + newStatus v1alpha1.RolloutStatus + pauseContext *pauseContext + stepPluginContext *stepPluginContext // targetsVerified indicates if the pods targets have been verified with underlying LoadBalancer. // This is used in pod-aware flat networks where LoadBalancers target Pods and not Nodes. diff --git a/rollout/controller.go b/rollout/controller.go index 467e5cc4d7..6595d8bd9c 100644 --- a/rollout/controller.go +++ b/rollout/controller.go @@ -113,7 +113,6 @@ type ControllerConfig struct { IngressWorkQueue workqueue.RateLimitingInterface MetricsServer *metrics.MetricsServer Recorder record.EventRecorder - StepPluginResolver plugin.Resolver } // reconcilerBase is a shared datastructure containing all clients and configuration necessary to @@ -128,8 +127,7 @@ type reconcilerBase struct { dynamicclientset dynamic.Interface smiclientset smiclientset.Interface - refResolver TemplateRefResolver - stepPluginResolver plugin.Resolver + refResolver TemplateRefResolver replicaSetLister appslisters.ReplicaSetLister replicaSetSynced cache.InformerSynced @@ -202,7 +200,6 @@ func NewController(cfg ControllerConfig) *Controller { resyncPeriod: cfg.ResyncPeriod, podRestarter: podRestarter, refResolver: cfg.RefResolver, - stepPluginResolver: cfg.StepPluginResolver, } controller := &Controller{ @@ -524,6 +521,10 @@ func (c *Controller) newRolloutContext(rollout *v1alpha1.Rollout) (*rolloutConte rollout: rollout, log: logCtx, }, + stepPluginContext: &stepPluginContext{ + resolver: plugin.NewResolver(), + log: logCtx, + }, reconcilerBase: c.reconcilerBase, } if rolloututil.IsFullyPromoted(rollout) && roCtx.pauseContext.IsAborted() { diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 4fc8c2231d..ba3edc863c 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -5,16 +5,27 @@ import ( "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/rollout/steps/plugin" + "github.com/argoproj/argo-rollouts/utils/conditions" + "github.com/argoproj/argo-rollouts/utils/record" replicasetutil "github.com/argoproj/argo-rollouts/utils/replicaset" rolloututil "github.com/argoproj/argo-rollouts/utils/rollout" + log "github.com/sirupsen/logrus" ) -func (c *rolloutContext) reconcileCanaryPluginStep() error { +type stepPluginContext struct { + resolver plugin.Resolver + log *log.Entry + + stepPluginStatuses []v1alpha1.StepPluginStatus + hasError bool +} + +func (spc *stepPluginContext) reconcile(c *rolloutContext) error { + spc.stepPluginStatuses = c.rollout.Status.Canary.StepPluginStatuses //On abort, we need to abort all successful previous steps if c.pauseContext.IsAborted() { - c.stepPluginStatuses = c.rollout.Status.Canary.StepPluginStatuses - // In an abort, the current step might be the current or last, depending on when the abort happened. _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) startingIndex := *currentStepIndex @@ -27,15 +38,15 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { continue } - stepPlugin, err := c.stepPluginResolver.Resolve(i, *currentStep.Plugin, c.log) + stepPlugin, err := spc.resolver.Resolve(i, *currentStep.Plugin, c.log) if err != nil { - return fmt.Errorf("could not create step plugin at index %d : %w", i, err) + return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", i, err)) } status, err := stepPlugin.Abort(c.rollout) if err != nil { - return fmt.Errorf("failed to abort plugin: %w", err) + return spc.handleError(c, fmt.Errorf("failed to abort plugin: %w", err)) } - c.stepPluginStatuses = updateStepPluginStatus(c.stepPluginStatuses, status) + spc.updateStepPluginStatus(status) } return nil } @@ -54,22 +65,22 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if currentStep.Plugin == nil { continue } - runningStatus := findCurrentStepStatus(c.rollout.Status.Canary.StepPluginStatuses, i, v1alpha1.StepPluginOperationRun) + runningStatus := spc.findCurrentStepStatus(i, v1alpha1.StepPluginOperationRun) if runningStatus == nil || runningStatus.Phase != v1alpha1.StepPluginPhaseRunning { continue } // found the last running step - stepPlugin, err := c.stepPluginResolver.Resolve(i, *currentStep.Plugin, c.log) + stepPlugin, err := spc.resolver.Resolve(i, *currentStep.Plugin, c.log) if err != nil { - return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) + return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err)) } status, err := stepPlugin.Terminate(c.rollout) if err != nil { - return fmt.Errorf("failed to terminate plugin: %w", err) + return spc.handleError(c, fmt.Errorf("failed to terminate plugin: %w", err)) } - c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + spc.updateStepPluginStatus(status) return nil } return nil @@ -81,15 +92,15 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } - stepPlugin, err := c.stepPluginResolver.Resolve(*currentStepIndex, *currentStep.Plugin, c.log) + stepPlugin, err := spc.resolver.Resolve(*currentStepIndex, *currentStep.Plugin, c.log) if err != nil { - return fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err) + return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err)) } status, err := stepPlugin.Run(c.rollout) if err != nil { - return fmt.Errorf("failed to run plugin: %w", err) + return spc.handleError(c, fmt.Errorf("failed to run plugin: %w", err)) } - c.stepPluginStatuses = updateStepPluginStatus(c.rollout.Status.Canary.StepPluginStatuses, status) + spc.updateStepPluginStatus(status) if status == nil { return nil @@ -98,7 +109,7 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { if status.Phase == v1alpha1.StepPluginPhaseRunning || status.Phase == v1alpha1.StepPluginPhaseError { duration, err := status.Backoff.Duration() if err != nil { - return fmt.Errorf("failed to parse backoff duration: %w", err) + return spc.handleError(c, fmt.Errorf("failed to parse backoff duration: %w", err)) } // Add a little delay to make sure we reconcile after the backoff duration += 5 * time.Second @@ -113,47 +124,58 @@ func (c *rolloutContext) reconcileCanaryPluginStep() error { return nil } -func (c *rolloutContext) calculateStepPluginStatus() []v1alpha1.StepPluginStatus { - if c.stepPluginStatuses == nil { - return c.rollout.Status.Canary.StepPluginStatuses - } +// handleError handles any error that should not cause the rollout reconciliation to fail +func (spc *stepPluginContext) handleError(c *rolloutContext, e error) error { + spc.hasError = true + + msg := fmt.Sprintf(conditions.RolloutReconciliationErrorMessage, e.Error()) + c.recorder.Eventf(c.rollout, record.EventOptions{EventReason: conditions.RolloutReconciliationErrorReason}, msg) - return c.stepPluginStatuses + return nil } -func (c *rolloutContext) isStepPluginDisabled(stepIndex int32, step *v1alpha1.PluginStep) (bool, error) { - stepPlugin, err := c.stepPluginResolver.Resolve(stepIndex, *step, c.log) +func (spc *stepPluginContext) updateStatus(status *v1alpha1.RolloutStatus) { + if spc.stepPluginStatuses != nil { + status.Canary.StepPluginStatuses = spc.stepPluginStatuses + } +} + +func (spc *stepPluginContext) isStepPluginDisabled(stepIndex int32, step *v1alpha1.PluginStep) (bool, error) { + stepPlugin, err := spc.resolver.Resolve(stepIndex, *step, spc.log) if err != nil { return false, err } return !stepPlugin.Enabled(), nil } -func (c *rolloutContext) isStepPluginCompleted(stepIndex int32, step *v1alpha1.PluginStep) bool { - disabled, err := c.isStepPluginDisabled(stepIndex, step) - if err != nil { - // If there is an error, the plugin might not exist in the config. We do - c.log.Errorf("cannot resolve step plugin %s at index %d. Assuming it is enabled.", step.Name, stepIndex) - disabled = false +func (spc *stepPluginContext) isStepPluginCompleted(stepIndex int32, step *v1alpha1.PluginStep) bool { + if spc.hasError { + // If there was a transient error during the reconcile, we should retry + return false + } + + if disabled, err := spc.isStepPluginDisabled(stepIndex, step); err != nil { + // If there is an error, the plugin might not exist in the config. Assume it is not disabled. + spc.log.Errorf("cannot resolve step plugin %s at index %d. Assuming it is enabled.", step.Name, stepIndex) + } else if disabled { + return true } - updatedPluginStatus := c.calculateStepPluginStatus() - runStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationRun) + runStatus := spc.findCurrentStepStatus(stepIndex, v1alpha1.StepPluginOperationRun) isRunning := runStatus != nil && runStatus.Phase == v1alpha1.StepPluginPhaseRunning if isRunning { - terminateStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationTerminate) - abortStatus := findCurrentStepStatus(updatedPluginStatus, stepIndex, v1alpha1.StepPluginOperationAbort) + terminateStatus := spc.findCurrentStepStatus(stepIndex, v1alpha1.StepPluginOperationTerminate) + abortStatus := spc.findCurrentStepStatus(stepIndex, v1alpha1.StepPluginOperationAbort) isRunning = terminateStatus == nil && abortStatus == nil } - return disabled || - (runStatus != nil && - ((!isRunning && runStatus.Phase == v1alpha1.StepPluginPhaseRunning) || - runStatus.Phase == v1alpha1.StepPluginPhaseFailed || - runStatus.Phase == v1alpha1.StepPluginPhaseSuccessful)) + return runStatus != nil && + ((!isRunning && runStatus.Phase == v1alpha1.StepPluginPhaseRunning) || + runStatus.Phase == v1alpha1.StepPluginPhaseFailed || + runStatus.Phase == v1alpha1.StepPluginPhaseSuccessful) } -func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { - for _, s := range status { +func (spc *stepPluginContext) findCurrentStepStatus(stepIndex int32, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { + for _, s := range spc.stepPluginStatuses { if s.Index == stepIndex && s.Operation == operation { return &s } @@ -161,24 +183,21 @@ func findCurrentStepStatus(status []v1alpha1.StepPluginStatus, stepIndex int32, return nil } -func updateStepPluginStatus(statuses []v1alpha1.StepPluginStatus, status *v1alpha1.StepPluginStatus) []v1alpha1.StepPluginStatus { +func (spc *stepPluginContext) updateStepPluginStatus(status *v1alpha1.StepPluginStatus) { if status == nil { - return statuses + return } // Update new status and preserve order - newStatuses := []v1alpha1.StepPluginStatus{} - statusAdded := false - for _, s := range statuses { - if !statusAdded && s.Index == status.Index && s.Operation == status.Operation { - newStatuses = append(newStatuses, *status) - statusAdded = true - continue + statusUpdated := false + for i, s := range spc.stepPluginStatuses { + if !statusUpdated && s.Index == status.Index && s.Operation == status.Operation { + spc.stepPluginStatuses[i] = *status + statusUpdated = true + break } - newStatuses = append(newStatuses, s) } - if !statusAdded { - newStatuses = append(newStatuses, *status) + if !statusUpdated { + spc.stepPluginStatuses = append(spc.stepPluginStatuses, *status) } - return newStatuses } diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index ebe3542b91..18946a986f 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -6,7 +6,6 @@ import ( "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" - "github.com/argoproj/argo-rollouts/rollout/steps/plugin" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/mocks" logutil "github.com/argoproj/argo-rollouts/utils/log" "github.com/stretchr/testify/assert" @@ -47,7 +46,6 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { rollout: r, log: logutil.WithRollout(r), reconcilerBase: reconcilerBase{ - stepPluginResolver: stepPluginResolver, enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, @@ -55,6 +53,10 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { rollout: r, log: logCtx, }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, } runStatus := newStepPluginStatus() @@ -67,11 +69,11 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { roCtx, runStatus := setup(t) runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t) @@ -86,11 +88,11 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }, } - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Status order is preserved when updating", func(t *testing.T) { roCtx, runStatus := setup(t) @@ -111,13 +113,13 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }, } - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 3) - assert.Equal(t, int32(123), roCtx.stepPluginStatuses[0].Index) - assert.Equal(t, runStatus.Index, roCtx.stepPluginStatuses[1].Index) - assert.Equal(t, int32(456), roCtx.stepPluginStatuses[2].Index) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 3) + assert.Equal(t, int32(123), roCtx.stepPluginContext.stepPluginStatuses[0].Index) + assert.Equal(t, runStatus.Index, roCtx.stepPluginContext.stepPluginStatuses[1].Index) + assert.Equal(t, int32(456), roCtx.stepPluginContext.stepPluginStatuses[2].Index) }) } @@ -133,7 +135,6 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { rollout: r, log: logutil.WithRollout(r), reconcilerBase: reconcilerBase{ - stepPluginResolver: stepPluginResolver, enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, @@ -141,14 +142,18 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { rollout: r, log: logCtx, }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, } runStatus := newStepPluginStatus() - runResult := &plugin.StepResult{ - RequeueAfter: requeueAfter, + if requeueAfter != nil { + runStatus.Backoff = v1alpha1.DurationString(requeueAfter.String()) } - stepPluginMock.On("Run", r).Return(runStatus, runResult, nil) + stepPluginMock.On("Run", r).Return(runStatus, nil) runStatus.Phase = phase return roCtx, runStatus } @@ -156,11 +161,11 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { t.Run("Status is added when not present", func(t *testing.T) { roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseRunning, nil) - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseRunning, nil) @@ -174,11 +179,11 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { }, } - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Rollout is added to the queue", func(t *testing.T) { expectedRequeueAfter := 123 * time.Second @@ -189,7 +194,7 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { requeuedAfter = duration } - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) assert.Equal(t, expectedRequeueAfter, requeuedAfter) @@ -208,7 +213,6 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { rollout: r, log: logCtx, reconcilerBase: reconcilerBase{ - stepPluginResolver: stepPluginResolver, enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, @@ -216,6 +220,10 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { rollout: r, log: logCtx, }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, } runStatus := newStepPluginStatus() @@ -227,11 +235,11 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { t.Run("Status is added when not present", func(t *testing.T) { roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseFailed) - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t, v1alpha1.StepPluginPhaseFailed) @@ -245,16 +253,16 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { }, } - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 1) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[0], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Rollout is aborted", func(t *testing.T) { roCtx, _ := setup(t, v1alpha1.StepPluginPhaseFailed) - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) assert.True(t, roCtx.pauseContext.IsAborted()) @@ -275,7 +283,6 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { rollout: r, log: logCtx, reconcilerBase: reconcilerBase{ - stepPluginResolver: stepPluginResolver, enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, @@ -283,6 +290,10 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { rollout: r, log: logCtx, }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, } return roCtx, stepPluginMock @@ -304,11 +315,11 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { stepPluginMock.On("Terminate", mock.Anything).Return(runStatus, nil) - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 2) - assert.EqualExportedValues(t, roCtx.stepPluginStatuses[1], *runStatus) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 2) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[1], *runStatus) }) } @@ -324,7 +335,6 @@ func Test_StepPlugin_Aborted(t *testing.T) { rollout: r, log: logCtx, reconcilerBase: reconcilerBase{ - stepPluginResolver: stepPluginResolver, enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, }, @@ -332,6 +342,10 @@ func Test_StepPlugin_Aborted(t *testing.T) { rollout: r, log: logCtx, }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, } return roCtx, stepPluginResolver @@ -377,13 +391,13 @@ func Test_StepPlugin_Aborted(t *testing.T) { expectedAbortStatus = append(expectedAbortStatus, abortStatus) } - err := roCtx.reconcileCanaryPluginStep() + err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginStatuses, 3) - assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[0], roCtx.stepPluginStatuses[0]) - assert.EqualExportedValues(t, *expectedAbortStatus[1], roCtx.stepPluginStatuses[1]) - assert.EqualExportedValues(t, *expectedAbortStatus[0], roCtx.stepPluginStatuses[2]) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 3) + assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[0], roCtx.stepPluginContext.stepPluginStatuses[0]) + assert.EqualExportedValues(t, *expectedAbortStatus[1], roCtx.stepPluginContext.stepPluginStatuses[1]) + assert.EqualExportedValues(t, *expectedAbortStatus[0], roCtx.stepPluginContext.stepPluginStatuses[2]) }) } @@ -397,22 +411,21 @@ func Test_StepPlugin_Aborted(t *testing.T) { // Helper: write helper functions? func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { - newRolloutContext := func(statuses []*v1alpha1.StepPluginStatus) *rolloutContext { + newRolloutContext := func(statuses []*v1alpha1.StepPluginStatus, hasError bool) *rolloutContext { r := newStepPluginRollout() logCtx := logutil.WithRollout(r) roCtx := &rolloutContext{ rollout: r, log: logCtx, - } - roCtx.newStatus = v1alpha1.RolloutStatus{ - Canary: v1alpha1.CanaryStatus{ - StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + stepPluginContext: &stepPluginContext{ + log: logCtx, }, } + for _, s := range statuses { - roCtx.stepPluginStatuses = append(roCtx.stepPluginStatuses, *s) + roCtx.stepPluginContext.stepPluginStatuses = append(roCtx.stepPluginContext.stepPluginStatuses, *s) } - roCtx.newStatus.Canary.StepPluginStatuses = roCtx.calculateStepPluginStatus() + roCtx.stepPluginContext.hasError = hasError return roCtx } @@ -420,6 +433,7 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { name string statuses []*v1alpha1.StepPluginStatus index int32 + hasError bool want bool }{ { @@ -436,6 +450,15 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { index: 0, want: true, }, + { + name: "With transient error", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseSuccessful}, + }, + index: 0, + hasError: true, + want: false, + }, { name: "Phase is failed", statuses: []*v1alpha1.StepPluginStatus{ @@ -489,8 +512,8 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c := newRolloutContext(tt.statuses) - if got := c.isStepPluginCompleted(tt.index, c.rollout.Spec.Strategy.Canary.Steps[tt.index].Plugin); got != tt.want { + c := newRolloutContext(tt.statuses, tt.hasError) + if got := c.stepPluginContext.isStepPluginCompleted(tt.index, c.rollout.Spec.Strategy.Canary.Steps[tt.index].Plugin); got != tt.want { t.Errorf("rolloutContext.isStepPluginCompleted() = %v, want %v", got, tt.want) } }) diff --git a/rollout/sync.go b/rollout/sync.go index db6debb0d3..f6feb0281c 100644 --- a/rollout/sync.go +++ b/rollout/sync.go @@ -667,7 +667,7 @@ func (c *rolloutContext) calculateRolloutConditions(newStatus v1alpha1.RolloutSt // everything but lastTransitionTime. SetRolloutCondition already does that but // it also is not updating conditions when the reason of the new condition is the // same as the old. The Progressing condition is a special case because we want to - // update with the same reason and change just lastUpdateTime iff we notice any + // update with the same reason and change just lastUpdateTime if we notice any // progress. That's why we handle it here. if currentCond != nil { if currentCond.Status == corev1.ConditionTrue { diff --git a/utils/conditions/conditions.go b/utils/conditions/conditions.go index 77cd401c63..ec1a75824e 100644 --- a/utils/conditions/conditions.go +++ b/utils/conditions/conditions.go @@ -133,6 +133,11 @@ const ( // RolloutExperimentFailedMessage is added in a rollout when the experiment owned by a rollout fails to show any progress RolloutExperimentFailedMessage = "Experiment '%s' owned by the Rollout '%q' has timed out." + // RolloutReconciliationErrorReason is added in a rollout when the reconciliation returns an error preventing progress + RolloutReconciliationErrorReason = "ReconciliationError" + // RolloutReconciliationErrorMessage is added in a rollout when the reconciliation returns an error preventing progress + RolloutReconciliationErrorMessage = "Reconciliation failed with error: %v" + // TimedOutReason is added in a rollout when its newest replica set fails to show any progress // within the given deadline (progressDeadlineSeconds). TimedOutReason = "ProgressDeadlineExceeded" From dcc9d9381a80c0864c7d26fe2bd865be05bda20b Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Fri, 19 Apr 2024 23:37:07 -0400 Subject: [PATCH 25/41] adding debug logs. Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 36 ++++++++++++------- rollout/steps/plugin/plugin.go | 6 ++++ .../step-plugin-e2e/internal/plugin/plugin.go | 2 +- test/e2e/step-plugin/template-rollout.yaml | 1 + test/e2e/step_plugin_test.go | 17 ++++++--- test/fixtures/then.go | 9 +++++ 6 files changed, 53 insertions(+), 18 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index ba3edc863c..06cc61b5ff 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -22,18 +22,19 @@ type stepPluginContext struct { } func (spc *stepPluginContext) reconcile(c *rolloutContext) error { - spc.stepPluginStatuses = c.rollout.Status.Canary.StepPluginStatuses + rollout := c.rollout.DeepCopy() + spc.stepPluginStatuses = rollout.Status.Canary.StepPluginStatuses //On abort, we need to abort all successful previous steps if c.pauseContext.IsAborted() { // In an abort, the current step might be the current or last, depending on when the abort happened. - _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) + _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) startingIndex := *currentStepIndex for i := startingIndex; i >= 0; i-- { - if i >= int32(len(c.rollout.Spec.Strategy.Canary.Steps)) { + if i >= int32(len(rollout.Spec.Strategy.Canary.Steps)) { continue } - currentStep := &c.rollout.Spec.Strategy.Canary.Steps[i] + currentStep := &rollout.Spec.Strategy.Canary.Steps[i] if currentStep.Plugin == nil { continue } @@ -42,7 +43,7 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { if err != nil { return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", i, err)) } - status, err := stepPlugin.Abort(c.rollout) + status, err := stepPlugin.Abort(rollout) if err != nil { return spc.handleError(c, fmt.Errorf("failed to abort plugin: %w", err)) } @@ -53,15 +54,15 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { // On full promotion, we want to Terminate the last step stuck in Running // At this point, the currentStepIndex is the current or last one - if c.rollout.Status.PromoteFull || rolloututil.IsFullyPromoted(c.rollout) { - _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) + if rollout.Status.PromoteFull || rolloututil.IsFullyPromoted(rollout) { + _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) startingIndex := *currentStepIndex for i := startingIndex; i >= 0; i-- { - if i >= int32(len(c.rollout.Spec.Strategy.Canary.Steps)) { + if i >= int32(len(rollout.Spec.Strategy.Canary.Steps)) { continue } - currentStep := &c.rollout.Spec.Strategy.Canary.Steps[i] + currentStep := &rollout.Spec.Strategy.Canary.Steps[i] if currentStep.Plugin == nil { continue } @@ -76,7 +77,7 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err)) } - status, err := stepPlugin.Terminate(c.rollout) + status, err := stepPlugin.Terminate(rollout) if err != nil { return spc.handleError(c, fmt.Errorf("failed to terminate plugin: %w", err)) } @@ -87,16 +88,21 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { } // Normal execution flow of a step plugin - currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(c.rollout) + currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) if currentStep == nil || currentStep.Plugin == nil { return nil } + if rollout.Status.Phase != v1alpha1.RolloutPhaseProgressing { + spc.log.Debug("Not reconciling step plugin because it is not progressing") + return nil + } + stepPlugin, err := spc.resolver.Resolve(*currentStepIndex, *currentStep.Plugin, c.log) if err != nil { return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err)) } - status, err := stepPlugin.Run(c.rollout) + status, err := stepPlugin.Run(rollout) if err != nil { return spc.handleError(c, fmt.Errorf("failed to run plugin: %w", err)) } @@ -113,7 +119,8 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { } // Add a little delay to make sure we reconcile after the backoff duration += 5 * time.Second - c.enqueueRolloutAfter(c.rollout, duration) + c.log.Debugf("queueing up rollout in %s because step plugin phase is %s", status.Backoff, status.Phase) + c.enqueueRolloutAfter(rollout, duration) return nil } @@ -131,6 +138,9 @@ func (spc *stepPluginContext) handleError(c *rolloutContext, e error) error { msg := fmt.Sprintf(conditions.RolloutReconciliationErrorMessage, e.Error()) c.recorder.Eventf(c.rollout, record.EventOptions{EventReason: conditions.RolloutReconciliationErrorReason}, msg) + c.log.Debug("queueing up rollout in 30s because of transient error") + c.enqueueRolloutAfter(c.rollout, 30*time.Second) + return nil } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index b30dc3afa5..a54b21b348 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -56,10 +56,12 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, return nil, fmt.Errorf("could not parse backoff duration: %w", err) } if stepStatus.UpdatedAt.Add(backoff).After(metatime.Now()) { + p.log.Debug("skipping plugin Run due to backoff") return nil, nil } } + p.log.Debug("calling RPC Run") resp, err := p.rpc.Run(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() stepStatus.Backoff = "" @@ -122,6 +124,8 @@ func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginS Operation: v1alpha1.StepPluginOperationTerminate, Phase: v1alpha1.StepPluginPhaseSuccessful, } + + p.log.Debug("calling RPC Terminate") resp, err := p.rpc.Terminate(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() stepStatus.UpdatedAt = &finishedAt @@ -170,6 +174,8 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu Operation: v1alpha1.StepPluginOperationAbort, Phase: v1alpha1.StepPluginPhaseSuccessful, } + + p.log.Debug("calling RPC Abort") resp, err := p.rpc.Abort(rollout.DeepCopy(), p.getStepContext(stepStatus)) finishedAt := metatime.MetaNow() stepStatus.UpdatedAt = &finishedAt diff --git a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go index efe70cab93..3d994bfc69 100644 --- a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go +++ b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go @@ -76,7 +76,7 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext var requeue time.Duration if config.Requeue != "" { - v, err := time.ParseDuration(string(config.Requeue)) + v, err := time.ParseDuration(config.Requeue) if err != nil { return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse requeue duration: %w", err).Error()} } diff --git a/test/e2e/step-plugin/template-rollout.yaml b/test/e2e/step-plugin/template-rollout.yaml index 312e80b7f1..1d4d064662 100644 --- a/test/e2e/step-plugin/template-rollout.yaml +++ b/test/e2e/step-plugin/template-rollout.yaml @@ -17,6 +17,7 @@ spec: name: step/e2e-test config: return: $$phase$$ + requeue: 17s template: metadata: labels: diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index 5766822af5..b53139f7d4 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -175,11 +175,11 @@ func (s *StepPluginSuite) TestRolloutRetriesUntilDeadlineWhenRunning() { When().ApplyManifests().WaitForRolloutStatus("Healthy"). UpdateSpec(` spec: - progressDeadlineSeconds: 15`). + progressDeadlineSeconds: 45`). UpdateSpec().WaitForRolloutStatus("Progressing"). WaitForRolloutCanaryStepIndex(1). WaitForRolloutStepPluginRunning(). - Wait(20 * time.Second). + Wait(50 * time.Second). WaitForRolloutStatus("Degraded"). Then(). Assert(func(t *fixtures.Then) { @@ -194,6 +194,10 @@ spec: assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) assert.NotEmpty(s.T(), stepStatus.Status) + // Performance test validating that the plugin is not constantly executed + assert.EqualValues(s.T(), "17s", stepStatus.Backoff) + assert.EqualValues(s.T(), 2, stepStatus.Executions) + }) } @@ -203,9 +207,9 @@ func (s *StepPluginSuite) TestRolloutRetriesUntilDeadlineWhenError() { When().ApplyManifests().WaitForRolloutStatus("Healthy"). UpdateSpec(` spec: - progressDeadlineSeconds: 15`). + progressDeadlineSeconds: 45`). UpdateSpec().WaitForRolloutStatus("Progressing"). - Wait(20 * time.Second). + Wait(50 * time.Second). WaitForRolloutStatus("Degraded"). Then(). Assert(func(t *fixtures.Then) { @@ -221,6 +225,10 @@ spec: assert.Contains(s.T(), stepStatus.Message, "phase 'invalidPhaseCausingPluginError' is not valid") assert.Empty(s.T(), stepStatus.Status) + // Performance test validating that the plugin is not constantly executed + assert.EqualValues(s.T(), "30s", stepStatus.Backoff) + assert.EqualValues(s.T(), 2, stepStatus.Executions) + }) } @@ -262,6 +270,7 @@ func (s *StepPluginSuite) TestRolloutErrorWhenStepPluginNotConfigured() { UpdateSpec().WaitForRolloutStatus("Degraded"). Then(). ExpectStableRevision("1"). + ExpectRolloutEventsContains([]string{"ReconciliationError"}). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() assert.EqualValues(s.T(), 0, *rollout.Status.CurrentStepIndex) diff --git a/test/fixtures/then.go b/test/fixtures/then.go index 8183cc2adc..d39e054d34 100644 --- a/test/fixtures/then.go +++ b/test/fixtures/then.go @@ -494,6 +494,15 @@ func (t *Then) ExpectRolloutEvents(reasons []string) *Then { return t } +func (t *Then) ExpectRolloutEventsContains(reasons []string) *Then { + t.t.Helper() + eventReasons := t.GetRolloutEventReasons() + for _, r := range reasons { + assert.Contains(t.Common.t, eventReasons, r) + } + return t +} + func (t *Then) When() *When { return &When{ Common: t.Common, From 628237c5834ab1fe8ea0a29b50eae66a86f06de7 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Sat, 20 Apr 2024 00:22:48 -0400 Subject: [PATCH 26/41] need to adjust the backoff on each reconcile Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 11 ++++++----- rollout/steps/plugin/plugin.go | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 06cc61b5ff..d6b918b9d0 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -113,14 +113,15 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { } if status.Phase == v1alpha1.StepPluginPhaseRunning || status.Phase == v1alpha1.StepPluginPhaseError { - duration, err := status.Backoff.Duration() + backoff, err := status.Backoff.Duration() if err != nil { return spc.handleError(c, fmt.Errorf("failed to parse backoff duration: %w", err)) } - // Add a little delay to make sure we reconcile after the backoff - duration += 5 * time.Second - c.log.Debugf("queueing up rollout in %s because step plugin phase is %s", status.Backoff, status.Phase) - c.enqueueRolloutAfter(rollout, duration) + + // Get the remaining time until the backoff + a little buffer + remaining := time.Until(status.UpdatedAt.Add(backoff)) + (5 * time.Second) + c.log.Debugf("queueing up rollout in %s because step plugin phase is %s", remaining, status.Phase) + c.enqueueRolloutAfter(rollout, remaining) return nil } diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index a54b21b348..bda9b783a7 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -57,7 +57,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, } if stepStatus.UpdatedAt.Add(backoff).After(metatime.Now()) { p.log.Debug("skipping plugin Run due to backoff") - return nil, nil + return stepStatus, nil } } From 13e8829a6691e27743f00a4ac1ec5163e51251c1 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Sat, 20 Apr 2024 00:34:00 -0400 Subject: [PATCH 27/41] fix e2e Signed-off-by: Alexandre Gaudreault --- test/e2e/step_plugin_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index b53139f7d4..1821299504 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -4,6 +4,7 @@ package e2e import ( + "context" "testing" "time" @@ -196,7 +197,7 @@ spec: // Performance test validating that the plugin is not constantly executed assert.EqualValues(s.T(), "17s", stepStatus.Backoff) - assert.EqualValues(s.T(), 2, stepStatus.Executions) + assert.EqualValues(s.T(), 3, stepStatus.Executions) }) } @@ -263,7 +264,10 @@ spec: } func (s *StepPluginSuite) TestRolloutErrorWhenStepPluginNotConfigured() { + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() s.Given(). + StartEventWatch(ctx). RolloutObjects("@step-plugin/invalid-rollout.yaml"). When(). ApplyManifests().WaitForRolloutStatus("Healthy"). @@ -275,7 +279,6 @@ func (s *StepPluginSuite) TestRolloutErrorWhenStepPluginNotConfigured() { rollout := t.GetRollout() assert.EqualValues(s.T(), 0, *rollout.Status.CurrentStepIndex) assert.EqualValues(s.T(), 0, len(rollout.Status.Canary.StepPluginStatuses)) - // Should really have some error returned to the user... }) } From e3a1a3d5648557ea553339debc54a46d281c2f72 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 22 Apr 2024 09:10:54 -0400 Subject: [PATCH 28/41] unit test Signed-off-by: Alexandre Gaudreault --- utils/plugin/plugin_test.go | 56 +++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/utils/plugin/plugin_test.go b/utils/plugin/plugin_test.go index 7226d2d312..a685def3db 100644 --- a/utils/plugin/plugin_test.go +++ b/utils/plugin/plugin_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/argoproj/argo-rollouts/utils/defaults" + "github.com/argoproj/argo-rollouts/utils/plugin/types" "github.com/argoproj/argo-rollouts/utils/config" "github.com/stretchr/testify/assert" @@ -29,14 +30,14 @@ func TestGetPluginInfo(t *testing.T) { _, err := config.InitializeConfig(client, "argo-rollouts-config") assert.NoError(t, err) - location, args, err := GetPluginInfo("argoproj-labs/http") + location, args, err := GetPluginInfo("argoproj-labs/http", types.PluginTypeMetricProvider) assert.NoError(t, err) fp, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, "argoproj-labs/http")) assert.NoError(t, err) assert.Equal(t, fp, location) assert.Equal(t, args, cmdArgs) - _, args, _ = GetPluginInfo("argoproj-labs/http-sha") + _, args, _ = GetPluginInfo("argoproj-labs/http-sha", types.PluginTypeMetricProvider) assert.Equal(t, len(args), 0) }) @@ -54,14 +55,39 @@ func TestGetPluginInfo(t *testing.T) { _, err := config.InitializeConfig(client, "argo-rollouts-config") assert.NoError(t, err) - location, args, err := GetPluginInfo("argoproj-labs/router") + location, args, err := GetPluginInfo("argoproj-labs/router", types.PluginTypeTrafficRouter) assert.NoError(t, err) fp, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, "argoproj-labs/router")) assert.NoError(t, err) assert.Equal(t, fp, location) assert.Equal(t, args, cmdArgs) - _, args, _ = GetPluginInfo("argoproj-labs/router-sha") + _, args, _ = GetPluginInfo("argoproj-labs/router-sha", types.PluginTypeTrafficRouter) + assert.Equal(t, len(args), 0) + }) + + t.Run("tests getting plugin location of step plugins", func(t *testing.T) { + + cm := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "argo-rollouts-config", + Namespace: "argo-rollouts", + }, + Data: map[string]string{"steplugins": "\n - name: argoproj-labs/steps\n location: https://test/plugin\n args: [\"-l 2\"]\n - name: argoproj-labs/steps-sha\n location: https://test/plugin\n sha256: 74657374e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, + } + client := fake.NewSimpleClientset(cm) + + _, err := config.InitializeConfig(client, "argo-rollouts-config") + assert.NoError(t, err) + + location, args, err := GetPluginInfo("argoproj-labs/step", types.PluginTypeStep) + assert.NoError(t, err) + fp, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, "argoproj-labs/step")) + assert.NoError(t, err) + assert.Equal(t, fp, location) + assert.Equal(t, args, cmdArgs) + + _, args, _ = GetPluginInfo("argoproj-labs/step-sha", types.PluginTypeStep) assert.Equal(t, len(args), 0) }) @@ -78,10 +104,30 @@ func TestGetPluginInfo(t *testing.T) { _, err := config.InitializeConfig(client, "argo-rollouts-config") assert.NoError(t, err) - location, args, err := GetPluginInfo("does-not-exist") + location, args, err := GetPluginInfo("does-not-exist", types.PluginTypeMetricProvider) assert.Error(t, err) assert.Equal(t, "plugin does-not-exist not configured in configmap", err.Error()) assert.Equal(t, "", location) assert.Equal(t, len(args), 0) }) + + t.Run("test getting plugin location from a plugin of a different type", func(t *testing.T) { + cm := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "argo-rollouts-config", + Namespace: "argo-rollouts", + }, + Data: map[string]string{"metricProviderPlugins": "\n - name: argoproj-labs/http\n location: https://test/plugin\n - name: argoproj-labs/http-sha\n location: https://test/plugin\n sha256: 74657374e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, + } + client := fake.NewSimpleClientset(cm) + + _, err := config.InitializeConfig(client, "argo-rollouts-config") + assert.NoError(t, err) + + location, args, err := GetPluginInfo("argoproj-labs/http", types.PluginTypeStep) + assert.Error(t, err) + assert.Equal(t, "plugin argoproj-labs/http not configured in configmap", err.Error()) + assert.Equal(t, "", location) + assert.Equal(t, len(args), 0) + }) } From 3b58d77992c725f439dc7008a6a8ee9e0bf287ab Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Mon, 29 Apr 2024 13:18:08 -0400 Subject: [PATCH 29/41] fix abort and promote logic Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 79 ++++++++++++++++------------- rollout/steps/plugin/plugin_test.go | 26 +++++----- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index d6b918b9d0..5dc1be6d20 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -27,21 +27,20 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { //On abort, we need to abort all successful previous steps if c.pauseContext.IsAborted() { - // In an abort, the current step might be the current or last, depending on when the abort happened. - _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) - startingIndex := *currentStepIndex - for i := startingIndex; i >= 0; i-- { - if i >= int32(len(rollout.Spec.Strategy.Canary.Steps)) { + for i := len(spc.stepPluginStatuses) - 1; i >= 0; i-- { + pluginStatus := spc.stepPluginStatuses[i] + if pluginStatus.Operation != v1alpha1.StepPluginOperationRun { + // Only call abort for Run operation. continue } - currentStep := &rollout.Spec.Strategy.Canary.Steps[i] - if currentStep.Plugin == nil { + pluginStep := rollout.Spec.Strategy.Canary.Steps[pluginStatus.Index] + if pluginStep.Plugin == nil { continue } - stepPlugin, err := spc.resolver.Resolve(i, *currentStep.Plugin, c.log) + stepPlugin, err := spc.resolver.Resolve(pluginStatus.Index, *pluginStep.Plugin, c.log) if err != nil { - return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", i, err)) + return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", pluginStatus.Index, err)) } status, err := stepPlugin.Abort(rollout) if err != nil { @@ -52,38 +51,29 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { return nil } - // On full promotion, we want to Terminate the last step stuck in Running - // At this point, the currentStepIndex is the current or last one + // On full promotion, we want to Terminate only the last step still in Running, if any if rollout.Status.PromoteFull || rolloututil.IsFullyPromoted(rollout) { - _, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) - startingIndex := *currentStepIndex + stepIndex := spc.getStepToTerminate(rollout) + if stepIndex == nil { + return nil + } - for i := startingIndex; i >= 0; i-- { - if i >= int32(len(rollout.Spec.Strategy.Canary.Steps)) { - continue - } - currentStep := &rollout.Spec.Strategy.Canary.Steps[i] - if currentStep.Plugin == nil { - continue - } - runningStatus := spc.findCurrentStepStatus(i, v1alpha1.StepPluginOperationRun) - if runningStatus == nil || runningStatus.Phase != v1alpha1.StepPluginPhaseRunning { - continue - } + pluginStep := rollout.Spec.Strategy.Canary.Steps[*stepIndex] + if pluginStep.Plugin == nil { + return nil + } - // found the last running step - stepPlugin, err := spc.resolver.Resolve(i, *currentStep.Plugin, c.log) - if err != nil { - return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", *currentStepIndex, err)) - } + stepPlugin, err := spc.resolver.Resolve(*stepIndex, *pluginStep.Plugin, c.log) + if err != nil { + return spc.handleError(c, fmt.Errorf("could not create step plugin at index %d : %w", *stepIndex, err)) + } - status, err := stepPlugin.Terminate(rollout) - if err != nil { - return spc.handleError(c, fmt.Errorf("failed to terminate plugin: %w", err)) - } - spc.updateStepPluginStatus(status) - return nil + status, err := stepPlugin.Terminate(rollout) + if err != nil { + return spc.handleError(c, fmt.Errorf("failed to terminate plugin: %w", err)) } + + spc.updateStepPluginStatus(status) return nil } @@ -212,3 +202,20 @@ func (spc *stepPluginContext) updateStepPluginStatus(status *v1alpha1.StepPlugin spc.stepPluginStatuses = append(spc.stepPluginStatuses, *status) } } + +func (spc *stepPluginContext) getStepToTerminate(rollout *v1alpha1.Rollout) *int32 { + for i := len(rollout.Status.Canary.StepPluginStatuses) - 1; i >= 0; i-- { + pluginStep := rollout.Status.Canary.StepPluginStatuses[i] + + if pluginStep.Operation == v1alpha1.StepPluginOperationTerminate && pluginStep.Phase == v1alpha1.StepPluginPhaseSuccessful { + // last running step is already terminated + return nil + } + + if pluginStep.Operation == v1alpha1.StepPluginOperationRun && pluginStep.Phase == v1alpha1.StepPluginPhaseRunning { + // found the last running step + return &pluginStep.Index + } + } + return nil +} diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index 5f0267b785..4a8488596e 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -62,7 +62,7 @@ func Test_stepPlugin_Run(t *testing.T) { rpcMock.On("Run", mock.Anything, mock.Anything).Run(validateArguments).Return(types.RpcStepResult{}, types.RpcError{}).Once() p.index = 1 - _, _, err := p.Run(r) + _, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -101,7 +101,7 @@ func Test_stepPlugin_Run(t *testing.T) { rpcMock.On("Run", mock.Anything, mock.Anything).Run(validateArguments).Return(types.RpcStepResult{}, types.RpcError{}).Once() p.index = 0 - _, _, err := p.Run(r) + _, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -135,7 +135,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -149,7 +149,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.NotNil(t, status.FinishedAt) - assert.Nil(t, result.RequeueAfter) + assert.Empty(t, status.Backoff) }) t.Run("Successful status", func(t *testing.T) { p, rpcMock := setup(t) @@ -169,7 +169,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -183,7 +183,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Nil(t, result.RequeueAfter) + assert.Nil(t, status.Backoff) }) t.Run("Running status", func(t *testing.T) { p, rpcMock := setup(t) @@ -212,7 +212,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -244,7 +244,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -277,7 +277,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -310,7 +310,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(rpcResult, types.RpcError{}).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -324,7 +324,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Nil(t, result.RequeueAfter) + assert.Empty(t, status.Backoff) }) t.Run("Error status", func(t *testing.T) { p, rpcMock := setup(t) @@ -356,7 +356,7 @@ func Test_stepPlugin_Run(t *testing.T) { } rpcMock.On("Run", mock.Anything, mock.Anything).Return(invalidResult, expectedError).Once() - status, result, err := p.Run(r) + status, err := p.Run(r) require.NoError(t, err) rpcMock.AssertExpectations(t) @@ -369,7 +369,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, expectedError.Error(), status.Message) assert.Equal(t, currentStatus.Status, status.Status) - assert.Nil(t, result.RequeueAfter) + assert.Empty(t, status.Backoff) }) } From 97b8a8e7842cbe6cd60dec9480316af3249eaba8 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Tue, 30 Apr 2024 10:13:13 -0400 Subject: [PATCH 30/41] fix aborted rollout do not retry Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 30 ++++++++++++++++++++++++++++++ test/e2e/step_plugin_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 5dc1be6d20..c283c5838b 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -51,6 +51,9 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { return nil } + // If we retry an aborted rollout, we need to have a clean status + spc.cleanStatusForRetry(rollout) + // On full promotion, we want to Terminate only the last step still in Running, if any if rollout.Status.PromoteFull || rolloututil.IsFullyPromoted(rollout) { stepIndex := spc.getStepToTerminate(rollout) @@ -219,3 +222,30 @@ func (spc *stepPluginContext) getStepToTerminate(rollout *v1alpha1.Rollout) *int } return nil } + +// cleanStatusForRetry is expected to be called on a non-aborted rollout. +// It validates that stepPluginStatuses does not contain outdated results, and remove them +// if it does. +func (spc *stepPluginContext) cleanStatusForRetry(rollout *v1alpha1.Rollout) { + if len(spc.stepPluginStatuses) == 0 || rollout.Status.Abort { + return + } + + currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) + if currentStep == nil || int(*currentStepIndex) > 0 { + // Nothing to clean if rollout steps are completed or in progress + return + } + + // if we are at step 0, it could be either that we haven't started, or we are progressing. + // if step 0 is a plugin, check if it is completed. In that case, we know that we should be at step > 0 + // abd we are retrying + shouldCleanCurrentStatus := true + if currentStep.Plugin != nil { + shouldCleanCurrentStatus = spc.isStepPluginCompleted(*currentStepIndex, currentStep.Plugin) + } + + if shouldCleanCurrentStatus { + spc.stepPluginStatuses = []v1alpha1.StepPluginStatus{} + } +} diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index 1821299504..f02efde594 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -142,6 +142,30 @@ func (s *StepPluginSuite) TestRolloutAbortStepsWhenAborted() { }) } +func (s *StepPluginSuite) TestRolloutRetryAbortedRollout() { + s.Given(). + RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "aborted", "$$phase$$": string(types.PhaseRunning)}). + When(). + ApplyManifests().WaitForRolloutStatus("Healthy"). + UpdateSpec().WaitForRolloutStatus("Progressing"). + WaitForRolloutCanaryStepIndex(1). + WaitForRolloutStepPluginRunning(). + AbortRollout().WaitForRolloutStatus("Degraded"). + RetryRollout().WaitForRolloutStepPluginRunning(). + Then(). + Assert(func(t *fixtures.Then) { + rollout := t.GetRollout() + assert.False(s.T(), rollout.Status.Abort) + assert.EqualValues(s.T(), 2, len(rollout.Status.Canary.StepPluginStatuses)) + + stepStatus := rollout.Status.Canary.StepPluginStatuses[1] + assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) + assert.EqualValues(s.T(), 1, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseRunning, stepStatus.Phase) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + }) +} + func (s *StepPluginSuite) TestRolloutCompletesWhenPromotedAndStepRunning() { s.Given(). RolloutTemplate("@step-plugin/template-rollout.yaml", map[string]string{"$$name$$": "full-promotion", "$$phase$$": string(types.PhaseRunning)}). From 576169770d032dd724a64b3eb4902f472231e73c Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Tue, 30 Apr 2024 11:40:15 -0400 Subject: [PATCH 31/41] add event Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 47 +++++++++++++++++++++++++++++----- utils/conditions/conditions.go | 6 +++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index c283c5838b..317529da06 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -46,7 +46,10 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { if err != nil { return spc.handleError(c, fmt.Errorf("failed to abort plugin: %w", err)) } - spc.updateStepPluginStatus(status) + phaseTransition := spc.updateStepPluginStatus(status) + if phaseTransition { + spc.recordPhase(c, status) + } } return nil } @@ -76,7 +79,10 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { return spc.handleError(c, fmt.Errorf("failed to terminate plugin: %w", err)) } - spc.updateStepPluginStatus(status) + phaseTransition := spc.updateStepPluginStatus(status) + if phaseTransition { + spc.recordPhase(c, status) + } return nil } @@ -99,7 +105,11 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { if err != nil { return spc.handleError(c, fmt.Errorf("failed to run plugin: %w", err)) } - spc.updateStepPluginStatus(status) + + phaseTransition := spc.updateStepPluginStatus(status) + if phaseTransition { + spc.recordPhase(c, status) + } if status == nil { return nil @@ -130,7 +140,7 @@ func (spc *stepPluginContext) handleError(c *rolloutContext, e error) error { spc.hasError = true msg := fmt.Sprintf(conditions.RolloutReconciliationErrorMessage, e.Error()) - c.recorder.Eventf(c.rollout, record.EventOptions{EventReason: conditions.RolloutReconciliationErrorReason}, msg) + c.recorder.Warnf(c.rollout, record.EventOptions{EventReason: conditions.RolloutReconciliationErrorReason}, msg) c.log.Debug("queueing up rollout in 30s because of transient error") c.enqueueRolloutAfter(c.rollout, 30*time.Second) @@ -138,6 +148,26 @@ func (spc *stepPluginContext) handleError(c *rolloutContext, e error) error { return nil } +func (spc *stepPluginContext) recordPhase(c *rolloutContext, status *v1alpha1.StepPluginStatus) { + if status.Operation == v1alpha1.StepPluginOperationRun && status.Phase == v1alpha1.StepPluginPhaseSuccessful { + // If the run status is succesful, do not record event because the controller will record the RolloutStepCompleted + return + } + + msg := fmt.Sprintf(conditions.StepPluginTransitionRunMessage, status.Name, status.Index+1, status.Phase) + if status.Operation == v1alpha1.StepPluginOperationAbort { + msg = fmt.Sprintf(conditions.StepPluginTransitionAbortMessage, status.Name, status.Index+1, status.Phase) + } else if status.Operation == v1alpha1.StepPluginOperationTerminate { + msg = fmt.Sprintf(conditions.StepPluginTransitionTerminateMessage, status.Name, status.Index+1, status.Phase) + } + + if status.Phase == v1alpha1.StepPluginPhaseError || status.Phase == v1alpha1.StepPluginPhaseFailed { + c.recorder.Warnf(c.rollout, record.EventOptions{EventReason: conditions.StepPluginTransitionReason}, msg) + } else { + c.recorder.Eventf(c.rollout, record.EventOptions{EventReason: conditions.StepPluginTransitionReason}, msg) + } +} + func (spc *stepPluginContext) updateStatus(status *v1alpha1.RolloutStatus) { if spc.stepPluginStatuses != nil { status.Canary.StepPluginStatuses = spc.stepPluginStatuses @@ -187,9 +217,10 @@ func (spc *stepPluginContext) findCurrentStepStatus(stepIndex int32, operation v return nil } -func (spc *stepPluginContext) updateStepPluginStatus(status *v1alpha1.StepPluginStatus) { +func (spc *stepPluginContext) updateStepPluginStatus(status *v1alpha1.StepPluginStatus) bool { + phaseChanged := false if status == nil { - return + return phaseChanged } // Update new status and preserve order @@ -198,12 +229,16 @@ func (spc *stepPluginContext) updateStepPluginStatus(status *v1alpha1.StepPlugin if !statusUpdated && s.Index == status.Index && s.Operation == status.Operation { spc.stepPluginStatuses[i] = *status statusUpdated = true + phaseChanged = s.Phase != status.Phase break } } if !statusUpdated { spc.stepPluginStatuses = append(spc.stepPluginStatuses, *status) + phaseChanged = true } + + return phaseChanged } func (spc *stepPluginContext) getStepToTerminate(rollout *v1alpha1.Rollout) *int32 { diff --git a/utils/conditions/conditions.go b/utils/conditions/conditions.go index ec1a75824e..2e62cb80fe 100644 --- a/utils/conditions/conditions.go +++ b/utils/conditions/conditions.go @@ -162,6 +162,12 @@ const ( // ServiceReferencingManagedService is added in a rollout when the multiple rollouts reference a Rollout ServiceReferencingManagedService = "Service %q is managed by another Rollout" + // StepPluginTransitionReason is added to a Rollout when a step plugin transition to an unsuccessful phase + StepPluginTransitionReason = "StepPluginTransition" + StepPluginTransitionRunMessage = "Step plugin %s (step %d) transitioned to %s" + StepPluginTransitionAbortMessage = "Step plugin %s (step %d) aborted (%s)" + StepPluginTransitionTerminateMessage = "Step plugin %s (step %d) terminated (%s)" + // TargetGroupHealthyReason is emitted when target group has been verified TargetGroupVerifiedReason = "TargetGroupVerified" TargetGroupVerifiedRegistrationMessage = "Service %s (TargetGroup %s) verified: %d endpoints registered" From ae4e5044f44d02e8654b4823650262bcbb7c551e Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 09:22:27 -0400 Subject: [PATCH 32/41] change enabled to status Signed-off-by: Alexandre Gaudreault --- manifests/crds/rollout-crd.yaml | 2 + manifests/install.yaml | 2 + pkg/apiclient/rollout/rollout.swagger.json | 3 + pkg/apis/rollouts/v1alpha1/generated.pb.go | 1137 +++++++++-------- pkg/apis/rollouts/v1alpha1/generated.proto | 4 +- .../rollouts/v1alpha1/openapi_generated.go | 18 + pkg/apis/rollouts/v1alpha1/types.go | 3 +- rollout/stepplugin.go | 34 +- rollout/stepplugin_test.go | 117 +- rollout/steps/plugin/mocks/StepPlugin.go | 18 - rollout/steps/plugin/plugin.go | 32 +- rollout/steps/plugin/plugin_test.go | 6 +- rollout/steps/plugin/resolver.go | 24 +- test/cmd/step-plugin-sample/main.go | 2 +- ui/src/models/rollout/generated/api.ts | 6 + utils/plugin/downloader_test.go | 2 +- utils/plugin/plugin_test.go | 6 +- 17 files changed, 741 insertions(+), 675 deletions(-) diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index 110cc2c337..f49e6a5c12 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -3732,6 +3732,8 @@ spec: properties: backoff: type: string + disabled: + type: boolean executions: format: int32 type: integer diff --git a/manifests/install.yaml b/manifests/install.yaml index 2dae9c8969..11a4e66a0f 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -16222,6 +16222,8 @@ spec: properties: backoff: type: string + disabled: + type: boolean executions: format: int32 type: integer diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index 9cdec0184b..342e8aea90 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -2559,6 +2559,9 @@ "type": "integer", "format": "int32" }, + "disabled": { + "type": "boolean" + }, "status": { "type": "string", "format": "byte", diff --git a/pkg/apis/rollouts/v1alpha1/generated.pb.go b/pkg/apis/rollouts/v1alpha1/generated.pb.go index fcbb2559f0..4fc80c2b20 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.pb.go +++ b/pkg/apis/rollouts/v1alpha1/generated.pb.go @@ -3407,558 +3407,559 @@ func init() { } var fileDescriptor_e0e705f843545fab = []byte{ - // 8802 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x5d, 0x6c, 0x24, 0xd9, - 0x75, 0x18, 0xbc, 0xc5, 0x66, 0x93, 0xdd, 0xa7, 0x39, 0x24, 0xe7, 0xce, 0xcc, 0x2e, 0x97, 0xbb, - 0x3b, 0xbd, 0xaa, 0xf5, 0xb7, 0xdf, 0xac, 0xb5, 0x22, 0xa5, 0xfd, 0x71, 0x56, 0x5a, 0x65, 0x93, - 0x6e, 0x72, 0x66, 0x87, 0xb3, 0xe4, 0x0c, 0xf7, 0x34, 0x67, 0xc7, 0xfa, 0x59, 0x5b, 0xc5, 0xee, - 0xcb, 0x66, 0x0d, 0xbb, 0xab, 0x5a, 0x55, 0xd5, 0x9c, 0xe1, 0x6a, 0x61, 0xad, 0x24, 0xac, 0x2c, - 0x2b, 0x12, 0xac, 0xc4, 0x16, 0x82, 0xfc, 0x20, 0x50, 0x0c, 0x03, 0x4e, 0xe2, 0x3c, 0x04, 0x86, - 0x82, 0xe4, 0xc1, 0x40, 0x8c, 0x28, 0x0e, 0x64, 0x20, 0x0e, 0xe4, 0x87, 0x44, 0x4e, 0x00, 0xd3, - 0x11, 0x9d, 0x97, 0x18, 0x09, 0x84, 0x04, 0x0a, 0x8c, 0xec, 0x43, 0x10, 0xdc, 0xdf, 0xba, 0x55, - 0x5d, 0xcd, 0xbf, 0x2e, 0xce, 0xae, 0x13, 0xbf, 0x75, 0xdf, 0x73, 0xee, 0x39, 0xa7, 0xee, 0xef, - 0xb9, 0xe7, 0x9e, 0x73, 0x2e, 0xac, 0xb6, 0xdd, 0x68, 0xbb, 0xbf, 0xb9, 0xd0, 0xf4, 0xbb, 0x8b, - 0x4e, 0xd0, 0xf6, 0x7b, 0x81, 0x7f, 0x97, 0xff, 0xf8, 0x48, 0xe0, 0x77, 0x3a, 0x7e, 0x3f, 0x0a, - 0x17, 0x7b, 0x3b, 0xed, 0x45, 0xa7, 0xe7, 0x86, 0x8b, 0xba, 0x64, 0xf7, 0x63, 0x4e, 0xa7, 0xb7, - 0xed, 0x7c, 0x6c, 0xb1, 0x4d, 0x3d, 0x1a, 0x38, 0x11, 0x6d, 0x2d, 0xf4, 0x02, 0x3f, 0xf2, 0xc9, - 0x27, 0x63, 0x6a, 0x0b, 0x8a, 0x1a, 0xff, 0xf1, 0xf3, 0xaa, 0xee, 0x42, 0x6f, 0xa7, 0xbd, 0xc0, - 0xa8, 0x2d, 0xe8, 0x12, 0x45, 0x6d, 0xfe, 0x23, 0x86, 0x2c, 0x6d, 0xbf, 0xed, 0x2f, 0x72, 0xa2, - 0x9b, 0xfd, 0x2d, 0xfe, 0x8f, 0xff, 0xe1, 0xbf, 0x04, 0xb3, 0xf9, 0xa7, 0x76, 0x5e, 0x0a, 0x17, - 0x5c, 0x9f, 0xc9, 0xb6, 0xb8, 0xe9, 0x44, 0xcd, 0xed, 0xc5, 0xdd, 0x01, 0x89, 0xe6, 0x6d, 0x03, - 0xa9, 0xe9, 0x07, 0x34, 0x0b, 0xe7, 0x85, 0x18, 0xa7, 0xeb, 0x34, 0xb7, 0x5d, 0x8f, 0x06, 0x7b, - 0xf1, 0x57, 0x77, 0x69, 0xe4, 0x64, 0xd5, 0x5a, 0x1c, 0x56, 0x2b, 0xe8, 0x7b, 0x91, 0xdb, 0xa5, - 0x03, 0x15, 0x7e, 0xe6, 0xa8, 0x0a, 0x61, 0x73, 0x9b, 0x76, 0x9d, 0x81, 0x7a, 0xcf, 0x0f, 0xab, - 0xd7, 0x8f, 0xdc, 0xce, 0xa2, 0xeb, 0x45, 0x61, 0x14, 0xa4, 0x2b, 0xd9, 0x3f, 0x2e, 0x40, 0xb9, - 0xb6, 0x5a, 0x6f, 0x44, 0x4e, 0xd4, 0x0f, 0xc9, 0x57, 0x2d, 0x98, 0xea, 0xf8, 0x4e, 0xab, 0xee, - 0x74, 0x1c, 0xaf, 0x49, 0x83, 0x39, 0xeb, 0x49, 0xeb, 0x4a, 0xe5, 0xb9, 0xd5, 0x85, 0x51, 0xfa, - 0x6b, 0xa1, 0x76, 0x2f, 0x44, 0x1a, 0xfa, 0xfd, 0xa0, 0x49, 0x91, 0x6e, 0xd5, 0x2f, 0x7e, 0x7f, - 0xbf, 0xfa, 0xd0, 0xc1, 0x7e, 0x75, 0x6a, 0xd5, 0xe0, 0x84, 0x09, 0xbe, 0xe4, 0xdb, 0x16, 0x9c, - 0x6f, 0x3a, 0x9e, 0x13, 0xec, 0x6d, 0x38, 0x41, 0x9b, 0x46, 0xaf, 0x06, 0x7e, 0xbf, 0x37, 0x37, - 0x76, 0x06, 0xd2, 0x3c, 0x2a, 0xa5, 0x39, 0xbf, 0x94, 0x66, 0x87, 0x83, 0x12, 0x70, 0xb9, 0xc2, - 0xc8, 0xd9, 0xec, 0x50, 0x53, 0xae, 0xc2, 0x59, 0xca, 0xd5, 0x48, 0xb3, 0xc3, 0x41, 0x09, 0xc8, - 0x33, 0x30, 0xe9, 0x7a, 0xed, 0x80, 0x86, 0xe1, 0xdc, 0xf8, 0x93, 0xd6, 0x95, 0x72, 0x7d, 0x46, - 0x56, 0x9f, 0x5c, 0x11, 0xc5, 0xa8, 0xe0, 0xf6, 0x6f, 0x15, 0xe0, 0x7c, 0x6d, 0xb5, 0xbe, 0x11, - 0x38, 0x5b, 0x5b, 0x6e, 0x13, 0xfd, 0x7e, 0xe4, 0x7a, 0x6d, 0x93, 0x80, 0x75, 0x38, 0x01, 0xf2, - 0x22, 0x54, 0x42, 0x1a, 0xec, 0xba, 0x4d, 0xba, 0xee, 0x07, 0x11, 0xef, 0x94, 0x62, 0xfd, 0x82, - 0x44, 0xaf, 0x34, 0x62, 0x10, 0x9a, 0x78, 0xac, 0x5a, 0xe0, 0xfb, 0x91, 0x84, 0xf3, 0x36, 0x2b, - 0xc7, 0xd5, 0x30, 0x06, 0xa1, 0x89, 0x47, 0x96, 0x61, 0xd6, 0xf1, 0x3c, 0x3f, 0x72, 0x22, 0xd7, - 0xf7, 0xd6, 0x03, 0xba, 0xe5, 0xde, 0x97, 0x9f, 0x38, 0x27, 0xeb, 0xce, 0xd6, 0x52, 0x70, 0x1c, - 0xa8, 0x41, 0xbe, 0x65, 0xc1, 0x6c, 0x18, 0xb9, 0xcd, 0x1d, 0xd7, 0xa3, 0x61, 0xb8, 0xe4, 0x7b, - 0x5b, 0x6e, 0x7b, 0xae, 0xc8, 0xbb, 0xed, 0xe6, 0x68, 0xdd, 0xd6, 0x48, 0x51, 0xad, 0x5f, 0x64, - 0x22, 0xa5, 0x4b, 0x71, 0x80, 0x3b, 0xf9, 0x30, 0x94, 0x65, 0x8b, 0xd2, 0x70, 0x6e, 0xe2, 0xc9, - 0xc2, 0x95, 0x72, 0xfd, 0xdc, 0xc1, 0x7e, 0xb5, 0xbc, 0xa2, 0x0a, 0x31, 0x86, 0xdb, 0xcb, 0x30, - 0x57, 0xeb, 0x6e, 0x3a, 0x61, 0xe8, 0xb4, 0xfc, 0x20, 0xd5, 0x75, 0x57, 0xa0, 0xd4, 0x75, 0x7a, - 0x3d, 0xd7, 0x6b, 0xb3, 0xbe, 0x63, 0x74, 0xa6, 0x0e, 0xf6, 0xab, 0xa5, 0x35, 0x59, 0x86, 0x1a, - 0x6a, 0xff, 0x87, 0x31, 0xa8, 0xd4, 0x3c, 0xa7, 0xb3, 0x17, 0xba, 0x21, 0xf6, 0x3d, 0xf2, 0x39, - 0x28, 0xb1, 0x55, 0xab, 0xe5, 0x44, 0x8e, 0x9c, 0xe9, 0x1f, 0x5d, 0x10, 0x8b, 0xc8, 0x82, 0xb9, - 0x88, 0xc4, 0x9f, 0xcf, 0xb0, 0x17, 0x76, 0x3f, 0xb6, 0x70, 0x6b, 0xf3, 0x2e, 0x6d, 0x46, 0x6b, - 0x34, 0x72, 0xea, 0x44, 0xf6, 0x02, 0xc4, 0x65, 0xa8, 0xa9, 0x12, 0x1f, 0xc6, 0xc3, 0x1e, 0x6d, - 0xca, 0x99, 0xbb, 0x36, 0xe2, 0x0c, 0x89, 0x45, 0x6f, 0xf4, 0x68, 0xb3, 0x3e, 0x25, 0x59, 0x8f, - 0xb3, 0x7f, 0xc8, 0x19, 0x91, 0x7b, 0x30, 0x11, 0xf2, 0xb5, 0x4c, 0x4e, 0xca, 0x5b, 0xf9, 0xb1, - 0xe4, 0x64, 0xeb, 0xd3, 0x92, 0xe9, 0x84, 0xf8, 0x8f, 0x92, 0x9d, 0xfd, 0x1f, 0x2d, 0xb8, 0x60, - 0x60, 0xd7, 0x82, 0x76, 0xbf, 0x4b, 0xbd, 0x88, 0x3c, 0x09, 0xe3, 0x9e, 0xd3, 0xa5, 0x72, 0x56, - 0x69, 0x91, 0x6f, 0x3a, 0x5d, 0x8a, 0x1c, 0x42, 0x9e, 0x82, 0xe2, 0xae, 0xd3, 0xe9, 0x53, 0xde, - 0x48, 0xe5, 0xfa, 0x39, 0x89, 0x52, 0x7c, 0x83, 0x15, 0xa2, 0x80, 0x91, 0xb7, 0xa1, 0xcc, 0x7f, - 0x5c, 0x0b, 0xfc, 0x6e, 0x4e, 0x9f, 0x26, 0x25, 0x7c, 0x43, 0x91, 0x15, 0xc3, 0x4f, 0xff, 0xc5, - 0x98, 0xa1, 0xfd, 0xc7, 0x16, 0xcc, 0x18, 0x1f, 0xb7, 0xea, 0x86, 0x11, 0xf9, 0xec, 0xc0, 0xe0, - 0x59, 0x38, 0xde, 0xe0, 0x61, 0xb5, 0xf9, 0xd0, 0x99, 0x95, 0x5f, 0x5a, 0x52, 0x25, 0xc6, 0xc0, - 0xf1, 0xa0, 0xe8, 0x46, 0xb4, 0x1b, 0xce, 0x8d, 0x3d, 0x59, 0xb8, 0x52, 0x79, 0x6e, 0x25, 0xb7, - 0x6e, 0x8c, 0xdb, 0x77, 0x85, 0xd1, 0x47, 0xc1, 0xc6, 0xfe, 0x6e, 0x21, 0xd1, 0x7d, 0x6b, 0x4a, - 0x8e, 0x77, 0x2d, 0x98, 0xe8, 0x38, 0x9b, 0xb4, 0x23, 0xe6, 0x56, 0xe5, 0xb9, 0x37, 0x73, 0x93, - 0x44, 0xf1, 0x58, 0x58, 0xe5, 0xf4, 0xaf, 0x7a, 0x51, 0xb0, 0x17, 0x0f, 0x2f, 0x51, 0x88, 0x92, - 0x39, 0xf9, 0x5b, 0x16, 0x54, 0xe2, 0x55, 0x4d, 0x35, 0xcb, 0x66, 0xfe, 0xc2, 0xc4, 0x8b, 0xa9, - 0x94, 0x48, 0x2f, 0xd1, 0x06, 0x04, 0x4d, 0x59, 0xe6, 0x3f, 0x0e, 0x15, 0xe3, 0x13, 0xc8, 0x2c, - 0x14, 0x76, 0xe8, 0x9e, 0x18, 0xf0, 0xc8, 0x7e, 0x92, 0x8b, 0x89, 0x11, 0x2e, 0x87, 0xf4, 0x27, - 0xc6, 0x5e, 0xb2, 0xe6, 0x5f, 0x81, 0xd9, 0x34, 0xc3, 0x93, 0xd4, 0xb7, 0xff, 0x49, 0x31, 0x31, - 0x30, 0xd9, 0x42, 0x40, 0x7c, 0x98, 0xec, 0xd2, 0x28, 0x70, 0x9b, 0xaa, 0xcb, 0x96, 0x47, 0x6b, - 0xa5, 0x35, 0x4e, 0x2c, 0xde, 0x10, 0xc5, 0xff, 0x10, 0x15, 0x17, 0xb2, 0x0d, 0xe3, 0x4e, 0xd0, - 0x56, 0x7d, 0x72, 0x2d, 0x9f, 0x69, 0x19, 0x2f, 0x15, 0xb5, 0xa0, 0x1d, 0x22, 0xe7, 0x40, 0x16, - 0xa1, 0x1c, 0xd1, 0xa0, 0xeb, 0x7a, 0x4e, 0x24, 0x76, 0xd0, 0x52, 0xfd, 0xbc, 0x44, 0x2b, 0x6f, - 0x28, 0x00, 0xc6, 0x38, 0xa4, 0x03, 0x13, 0xad, 0x60, 0x0f, 0xfb, 0xde, 0xdc, 0x78, 0x1e, 0x4d, - 0xb1, 0xcc, 0x69, 0xc5, 0x83, 0x54, 0xfc, 0x47, 0xc9, 0x83, 0xfc, 0xba, 0x05, 0x17, 0xbb, 0xd4, - 0x09, 0xfb, 0x01, 0x65, 0x9f, 0x80, 0x34, 0xa2, 0x1e, 0xeb, 0xd8, 0xb9, 0x22, 0x67, 0x8e, 0xa3, - 0xf6, 0xc3, 0x20, 0xe5, 0xfa, 0xe3, 0x52, 0x94, 0x8b, 0x59, 0x50, 0xcc, 0x94, 0x86, 0xbc, 0x0d, - 0x95, 0x28, 0xea, 0x34, 0x22, 0xa6, 0x07, 0xb7, 0xf7, 0xe6, 0x26, 0xf8, 0xe2, 0x35, 0xe2, 0x0a, - 0xb3, 0xb1, 0xb1, 0xaa, 0x08, 0xd6, 0x67, 0xd8, 0x6c, 0x31, 0x0a, 0xd0, 0x64, 0x67, 0xff, 0xf3, - 0x22, 0x9c, 0x1f, 0xd8, 0x56, 0xc8, 0x0b, 0x50, 0xec, 0x6d, 0x3b, 0xa1, 0xda, 0x27, 0x2e, 0xab, - 0x45, 0x6a, 0x9d, 0x15, 0xbe, 0xb7, 0x5f, 0x3d, 0xa7, 0xaa, 0xf0, 0x02, 0x14, 0xc8, 0x4c, 0x6b, - 0xeb, 0xd2, 0x30, 0x74, 0xda, 0x6a, 0xf3, 0x30, 0x06, 0x29, 0x2f, 0x46, 0x05, 0x27, 0xbf, 0x68, - 0xc1, 0x39, 0x31, 0x60, 0x91, 0x86, 0xfd, 0x4e, 0xc4, 0x36, 0x48, 0xd6, 0x29, 0x37, 0xf2, 0x98, - 0x1c, 0x82, 0x64, 0xfd, 0x92, 0xe4, 0x7e, 0xce, 0x2c, 0x0d, 0x31, 0xc9, 0x97, 0xdc, 0x81, 0x72, - 0x18, 0x39, 0x41, 0x44, 0x5b, 0xb5, 0x88, 0xab, 0x72, 0x95, 0xe7, 0x7e, 0xfa, 0x78, 0x3b, 0xc7, - 0x86, 0xdb, 0xa5, 0x62, 0x97, 0x6a, 0x28, 0x02, 0x18, 0xd3, 0x22, 0x6f, 0x03, 0x04, 0x7d, 0xaf, - 0xd1, 0xef, 0x76, 0x9d, 0x60, 0x4f, 0x6a, 0x77, 0xd7, 0x47, 0xfb, 0x3c, 0xd4, 0xf4, 0x62, 0x45, - 0x27, 0x2e, 0x43, 0x83, 0x1f, 0xf9, 0x92, 0x05, 0xe7, 0xc4, 0x3c, 0x50, 0x12, 0x4c, 0xe4, 0x2c, - 0xc1, 0x79, 0xd6, 0xb4, 0xcb, 0x26, 0x0b, 0x4c, 0x72, 0x24, 0x6f, 0x42, 0xa5, 0xe9, 0x77, 0x7b, - 0x1d, 0x2a, 0x1a, 0x77, 0xf2, 0xc4, 0x8d, 0xcb, 0x87, 0xee, 0x52, 0x4c, 0x02, 0x4d, 0x7a, 0xf6, - 0xbf, 0x4b, 0xea, 0x38, 0x6a, 0x48, 0x93, 0xcf, 0xc0, 0xa3, 0x61, 0xbf, 0xd9, 0xa4, 0x61, 0xb8, - 0xd5, 0xef, 0x60, 0xdf, 0xbb, 0xee, 0x86, 0x91, 0x1f, 0xec, 0xad, 0xba, 0x5d, 0x37, 0xe2, 0x03, - 0xba, 0x58, 0x7f, 0xe2, 0x60, 0xbf, 0xfa, 0x68, 0x63, 0x18, 0x12, 0x0e, 0xaf, 0x4f, 0x1c, 0x78, - 0xac, 0xef, 0x0d, 0x27, 0x2f, 0x8e, 0x1f, 0xd5, 0x83, 0xfd, 0xea, 0x63, 0xb7, 0x87, 0xa3, 0xe1, - 0x61, 0x34, 0xec, 0x3f, 0xb5, 0xd8, 0x36, 0x24, 0xbe, 0x6b, 0x83, 0x76, 0x7b, 0x1d, 0xb6, 0x74, - 0x9e, 0xbd, 0x72, 0x1c, 0x25, 0x94, 0x63, 0xcc, 0x67, 0x2f, 0x57, 0xf2, 0x0f, 0xd3, 0x90, 0xed, - 0xff, 0x62, 0xc1, 0xc5, 0x34, 0xf2, 0x03, 0x50, 0xe8, 0xc2, 0xa4, 0x42, 0x77, 0x33, 0xdf, 0xaf, - 0x1d, 0xa2, 0xd5, 0xfd, 0x92, 0x31, 0x60, 0x15, 0x2a, 0xd2, 0x2d, 0xf2, 0x12, 0x4c, 0x45, 0xf2, - 0xef, 0xcd, 0x58, 0x39, 0xd7, 0x86, 0x89, 0x0d, 0x03, 0x86, 0x09, 0x4c, 0x56, 0xb3, 0xd9, 0xe9, - 0x87, 0x11, 0x0d, 0x1a, 0x4d, 0xbf, 0x27, 0x96, 0xdd, 0x52, 0x5c, 0x73, 0xc9, 0x80, 0x61, 0x02, - 0xd3, 0xfe, 0x6b, 0xc5, 0xc1, 0x76, 0xff, 0xbf, 0x5d, 0x5f, 0x89, 0xd5, 0x8f, 0xc2, 0xfb, 0xa9, - 0x7e, 0x8c, 0x7f, 0xa0, 0xd4, 0x8f, 0x2f, 0x5b, 0x4c, 0x8b, 0x13, 0x03, 0x20, 0x94, 0xaa, 0xd1, - 0xeb, 0xf9, 0x4e, 0x07, 0xa4, 0x5b, 0xa6, 0x62, 0x28, 0x79, 0x61, 0xcc, 0xd6, 0xfe, 0x07, 0xe3, - 0x30, 0x55, 0xf3, 0x22, 0xb7, 0xb6, 0xb5, 0xe5, 0x7a, 0x6e, 0xb4, 0x47, 0xbe, 0x31, 0x06, 0x8b, - 0xbd, 0x80, 0x6e, 0xd1, 0x20, 0xa0, 0xad, 0xe5, 0x7e, 0xe0, 0x7a, 0xed, 0x46, 0x73, 0x9b, 0xb6, - 0xfa, 0x1d, 0xd7, 0x6b, 0xaf, 0xb4, 0x3d, 0x5f, 0x17, 0x5f, 0xbd, 0x4f, 0x9b, 0x7d, 0xde, 0xae, - 0x62, 0x95, 0xe8, 0x8e, 0x26, 0xfb, 0xfa, 0xc9, 0x98, 0xd6, 0x9f, 0x3f, 0xd8, 0xaf, 0x2e, 0x9e, - 0xb0, 0x12, 0x9e, 0xf4, 0xd3, 0xc8, 0xd7, 0xc6, 0x60, 0x21, 0xa0, 0x9f, 0xef, 0xbb, 0xc7, 0x6f, - 0x0d, 0xb1, 0x8c, 0x77, 0x46, 0xdc, 0xee, 0x4f, 0xc4, 0xb3, 0xfe, 0xdc, 0xc1, 0x7e, 0xf5, 0x84, - 0x75, 0xf0, 0x84, 0xdf, 0x65, 0xaf, 0x43, 0xa5, 0xd6, 0x73, 0x43, 0xf7, 0x3e, 0xfa, 0xfd, 0x88, - 0x1e, 0xc3, 0xa0, 0x51, 0x85, 0x62, 0xd0, 0xef, 0x50, 0xb1, 0xc0, 0x94, 0xeb, 0x65, 0xb6, 0x2c, - 0x23, 0x2b, 0x40, 0x51, 0x6e, 0x7f, 0x99, 0x6d, 0x41, 0x9c, 0x64, 0xca, 0x94, 0x75, 0x17, 0x8a, - 0x01, 0x63, 0x22, 0x47, 0xd6, 0xa8, 0xa7, 0xfe, 0x58, 0x6a, 0x29, 0x04, 0xfb, 0x89, 0x82, 0x85, - 0xfd, 0xbd, 0x31, 0xb8, 0x54, 0xeb, 0xf5, 0xd6, 0x68, 0xb8, 0x9d, 0x92, 0xe2, 0x97, 0x2d, 0x98, - 0xde, 0x75, 0x83, 0xa8, 0xef, 0x74, 0x94, 0xb5, 0x52, 0xc8, 0xd3, 0x18, 0x55, 0x1e, 0xce, 0xed, - 0x8d, 0x04, 0xe9, 0x3a, 0x39, 0xd8, 0xaf, 0x4e, 0x27, 0xcb, 0x30, 0xc5, 0x9e, 0xfc, 0x4d, 0x0b, - 0x66, 0x65, 0xd1, 0x4d, 0xbf, 0x45, 0x4d, 0x6b, 0xf8, 0xed, 0x3c, 0x65, 0xd2, 0xc4, 0x85, 0x15, - 0x33, 0x5d, 0x8a, 0x03, 0x42, 0xd8, 0xff, 0x6d, 0x0c, 0x1e, 0x19, 0x42, 0x83, 0xfc, 0x86, 0x05, - 0x17, 0x85, 0x09, 0xdd, 0x00, 0x21, 0xdd, 0x92, 0xad, 0xf9, 0xa9, 0xbc, 0x25, 0x47, 0x36, 0xc5, - 0xa9, 0xd7, 0xa4, 0xf5, 0x39, 0xb6, 0x24, 0x2f, 0x65, 0xb0, 0xc6, 0x4c, 0x81, 0xb8, 0xa4, 0xc2, - 0xa8, 0x9e, 0x92, 0x74, 0xec, 0x81, 0x48, 0xda, 0xc8, 0x60, 0x8d, 0x99, 0x02, 0xd9, 0x7f, 0x05, - 0x1e, 0x3b, 0x84, 0xdc, 0xd1, 0x93, 0xd3, 0x7e, 0x53, 0x8f, 0xfa, 0xe4, 0x98, 0x3b, 0xc6, 0xbc, - 0xb6, 0x61, 0x82, 0x4f, 0x1d, 0x35, 0xb1, 0x81, 0xed, 0xc1, 0x7c, 0x4e, 0x85, 0x28, 0x21, 0xf6, - 0xf7, 0x2c, 0x28, 0x9d, 0xc0, 0xf6, 0x59, 0x4d, 0xda, 0x3e, 0xcb, 0x03, 0x76, 0xcf, 0x68, 0xd0, - 0xee, 0xf9, 0xea, 0x68, 0xbd, 0x71, 0x1c, 0x7b, 0xe7, 0x8f, 0x2d, 0x38, 0x3f, 0x60, 0x1f, 0x25, - 0xdb, 0x70, 0xb1, 0xe7, 0xb7, 0xd4, 0x76, 0x7a, 0xdd, 0x09, 0xb7, 0x39, 0x4c, 0x7e, 0xde, 0x0b, - 0xac, 0x27, 0xd7, 0x33, 0xe0, 0xef, 0xed, 0x57, 0xe7, 0x34, 0x91, 0x14, 0x02, 0x66, 0x52, 0x24, - 0x3d, 0x28, 0x6d, 0xb9, 0xb4, 0xd3, 0x8a, 0x87, 0xe0, 0x88, 0x5a, 0xda, 0x35, 0x49, 0x4d, 0x5c, - 0x0d, 0xa8, 0x7f, 0xa8, 0xb9, 0xd8, 0x3f, 0xb1, 0x60, 0xba, 0xd6, 0x8f, 0xb6, 0x99, 0x8e, 0xd2, - 0xe4, 0xd6, 0x38, 0xe2, 0x41, 0x31, 0x74, 0xdb, 0xbb, 0x2f, 0xe4, 0xb3, 0x18, 0x37, 0x18, 0x29, - 0x79, 0x45, 0xa2, 0x95, 0x75, 0x5e, 0x88, 0x82, 0x0d, 0x09, 0x60, 0xc2, 0x77, 0xfa, 0xd1, 0xf6, - 0x73, 0xf2, 0x93, 0x47, 0xb4, 0x4c, 0xdc, 0x62, 0x9f, 0xf3, 0x9c, 0xe4, 0xa8, 0x55, 0x46, 0x51, - 0x8a, 0x92, 0x93, 0xfd, 0x45, 0x98, 0x4e, 0xde, 0xbb, 0x1d, 0x63, 0xcc, 0x3e, 0x01, 0x05, 0x27, - 0xf0, 0xe4, 0x88, 0xad, 0x48, 0x84, 0x42, 0x0d, 0x6f, 0x22, 0x2b, 0x27, 0xcf, 0x42, 0x69, 0xab, - 0xdf, 0xe9, 0xf0, 0x73, 0x85, 0xb8, 0xe4, 0xd2, 0xc7, 0xa2, 0x6b, 0xb2, 0x1c, 0x35, 0x86, 0xfd, - 0xbf, 0xc6, 0x61, 0xa6, 0xde, 0xe9, 0xd3, 0x57, 0x03, 0x4a, 0x95, 0x2d, 0xa8, 0x06, 0x33, 0xbd, - 0x80, 0xee, 0xba, 0xf4, 0x5e, 0x83, 0x76, 0x68, 0x33, 0xf2, 0x03, 0x29, 0xcd, 0x23, 0x92, 0xd0, - 0xcc, 0x7a, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0x0a, 0x4c, 0x3b, 0xcd, 0xc8, 0xdd, 0xa5, 0x9a, 0x82, - 0x10, 0xf7, 0x61, 0x49, 0x61, 0xba, 0x96, 0x80, 0x62, 0x0a, 0x9b, 0x7c, 0x16, 0xe6, 0xc2, 0xa6, - 0xd3, 0xa1, 0xb7, 0x7b, 0x92, 0xd5, 0xd2, 0x36, 0x6d, 0xee, 0xac, 0xfb, 0xae, 0x17, 0x49, 0xbb, - 0xe3, 0x93, 0x92, 0xd2, 0x5c, 0x63, 0x08, 0x1e, 0x0e, 0xa5, 0x40, 0xfe, 0x85, 0x05, 0x4f, 0xf4, - 0x02, 0xba, 0x1e, 0xf8, 0x5d, 0x9f, 0x0d, 0xb5, 0x01, 0x73, 0x98, 0x34, 0x0b, 0xbd, 0x31, 0xa2, - 0x2e, 0x25, 0x4a, 0x06, 0xef, 0x70, 0x3e, 0x74, 0xb0, 0x5f, 0x7d, 0x62, 0xfd, 0x30, 0x01, 0xf0, - 0x70, 0xf9, 0xc8, 0xbf, 0xb4, 0xe0, 0x72, 0xcf, 0x0f, 0xa3, 0x43, 0x3e, 0xa1, 0x78, 0xa6, 0x9f, - 0x60, 0x1f, 0xec, 0x57, 0x2f, 0xaf, 0x1f, 0x2a, 0x01, 0x1e, 0x21, 0xa1, 0x7d, 0x50, 0x81, 0xf3, - 0xc6, 0xd8, 0x93, 0xc6, 0x9c, 0x97, 0xe1, 0x9c, 0x1a, 0x0c, 0xb1, 0xee, 0x53, 0x8e, 0x6d, 0x7b, - 0x35, 0x13, 0x88, 0x49, 0x5c, 0x36, 0xee, 0xf4, 0x50, 0x14, 0xb5, 0x53, 0xe3, 0x6e, 0x3d, 0x01, - 0xc5, 0x14, 0x36, 0x59, 0x81, 0x0b, 0xb2, 0x04, 0x69, 0xaf, 0xe3, 0x36, 0x9d, 0x25, 0xbf, 0x2f, - 0x87, 0x5c, 0xb1, 0xfe, 0xc8, 0xc1, 0x7e, 0xf5, 0xc2, 0xfa, 0x20, 0x18, 0xb3, 0xea, 0x90, 0x55, - 0xb8, 0xe8, 0xf4, 0x23, 0x5f, 0x7f, 0xff, 0x55, 0x8f, 0x6d, 0xa7, 0x2d, 0x3e, 0xb4, 0x4a, 0x62, - 0xdf, 0xad, 0x65, 0xc0, 0x31, 0xb3, 0x16, 0x59, 0x4f, 0x51, 0x6b, 0xd0, 0xa6, 0xef, 0xb5, 0x44, - 0x2f, 0x17, 0xe3, 0x63, 0x60, 0x2d, 0x03, 0x07, 0x33, 0x6b, 0x92, 0x0e, 0x4c, 0x77, 0x9d, 0xfb, - 0xb7, 0x3d, 0x67, 0xd7, 0x71, 0x3b, 0x8c, 0x89, 0xb4, 0x17, 0x0e, 0xb7, 0x32, 0xf5, 0x23, 0xb7, - 0xb3, 0x20, 0xfc, 0x38, 0x16, 0x56, 0xbc, 0xe8, 0x56, 0xd0, 0x88, 0x98, 0xa6, 0x2e, 0x34, 0xc8, - 0xb5, 0x04, 0x2d, 0x4c, 0xd1, 0x26, 0xb7, 0xe0, 0x12, 0x9f, 0x8e, 0xcb, 0xfe, 0x3d, 0x6f, 0x99, - 0x76, 0x9c, 0x3d, 0xf5, 0x01, 0x93, 0xfc, 0x03, 0x1e, 0x3d, 0xd8, 0xaf, 0x5e, 0x6a, 0x64, 0x21, - 0x60, 0x76, 0x3d, 0xe2, 0xc0, 0x63, 0x49, 0x00, 0xd2, 0x5d, 0x37, 0x74, 0x7d, 0x4f, 0x98, 0xe5, - 0x4a, 0xb1, 0x59, 0xae, 0x31, 0x1c, 0x0d, 0x0f, 0xa3, 0x41, 0xfe, 0x8e, 0x05, 0x17, 0xb3, 0xa6, - 0xe1, 0x5c, 0x39, 0x8f, 0xdb, 0xe4, 0xd4, 0xd4, 0x12, 0x23, 0x22, 0x73, 0x51, 0xc8, 0x14, 0x82, - 0xbc, 0x63, 0xc1, 0x94, 0x63, 0x9c, 0xa0, 0xe7, 0x20, 0x8f, 0x5d, 0xcb, 0x3c, 0x93, 0xd7, 0x67, - 0x0f, 0xf6, 0xab, 0x89, 0x53, 0x3a, 0x26, 0x38, 0x92, 0xbf, 0x67, 0xc1, 0xa5, 0xcc, 0x39, 0x3e, - 0x57, 0x39, 0x8b, 0x16, 0xe2, 0x83, 0x24, 0x7b, 0xcd, 0xc9, 0x16, 0x83, 0x7c, 0xcb, 0xd2, 0x5b, - 0x99, 0xba, 0x60, 0x9c, 0x9b, 0xe2, 0xa2, 0x8d, 0x68, 0xf0, 0x30, 0xd4, 0x28, 0x45, 0xb8, 0x7e, - 0xc1, 0xd8, 0x19, 0x55, 0x21, 0xa6, 0xd9, 0x93, 0x6f, 0x5a, 0x6a, 0x6b, 0xd4, 0x12, 0x9d, 0x3b, - 0x2b, 0x89, 0x48, 0xbc, 0xd3, 0x6a, 0x81, 0x52, 0xcc, 0xc9, 0xcf, 0xc1, 0xbc, 0xb3, 0xe9, 0x07, - 0x51, 0xe6, 0xe4, 0x9b, 0x9b, 0xe6, 0xd3, 0xe8, 0xf2, 0xc1, 0x7e, 0x75, 0xbe, 0x36, 0x14, 0x0b, - 0x0f, 0xa1, 0x60, 0xff, 0xde, 0x04, 0x4c, 0x89, 0x93, 0x90, 0xdc, 0xba, 0x7e, 0xdb, 0x82, 0xc7, - 0x9b, 0xfd, 0x20, 0xa0, 0x5e, 0xd4, 0x88, 0x68, 0x6f, 0x70, 0xe3, 0xb2, 0xce, 0x74, 0xe3, 0x7a, - 0xf2, 0x60, 0xbf, 0xfa, 0xf8, 0xd2, 0x21, 0xfc, 0xf1, 0x50, 0xe9, 0xc8, 0xbf, 0xb5, 0xc0, 0x96, - 0x08, 0x75, 0xa7, 0xb9, 0xd3, 0x0e, 0xfc, 0xbe, 0xd7, 0x1a, 0xfc, 0x88, 0xb1, 0x33, 0xfd, 0x88, - 0xa7, 0x0f, 0xf6, 0xab, 0xf6, 0xd2, 0x91, 0x52, 0xe0, 0x31, 0x24, 0x25, 0xaf, 0xc2, 0x79, 0x89, - 0x75, 0xf5, 0x7e, 0x8f, 0x06, 0x2e, 0x3b, 0x73, 0x48, 0xc5, 0x31, 0xf6, 0x4d, 0x4b, 0x23, 0xe0, - 0x60, 0x1d, 0x12, 0xc2, 0xe4, 0x3d, 0xea, 0xb6, 0xb7, 0x23, 0xa5, 0x3e, 0x8d, 0xe8, 0x90, 0x26, - 0xad, 0x22, 0x77, 0x04, 0xcd, 0x7a, 0xe5, 0x60, 0xbf, 0x3a, 0x29, 0xff, 0xa0, 0xe2, 0x44, 0x6e, - 0xc2, 0xb4, 0x38, 0xa7, 0xae, 0xbb, 0x5e, 0x7b, 0xdd, 0xf7, 0x84, 0x57, 0x55, 0xb9, 0xfe, 0xb4, - 0xda, 0xf0, 0x1b, 0x09, 0xe8, 0x7b, 0xfb, 0xd5, 0x29, 0xf5, 0x7b, 0x63, 0xaf, 0x47, 0x31, 0x55, - 0x9b, 0xfc, 0x6d, 0x0b, 0x48, 0x18, 0xd1, 0xde, 0x7a, 0xa7, 0xdf, 0x76, 0x65, 0x13, 0x49, 0xff, - 0xa8, 0x1c, 0x5c, 0xb5, 0x92, 0x74, 0xeb, 0xf3, 0x52, 0x48, 0xd2, 0x18, 0xe0, 0x88, 0x19, 0x52, - 0xd8, 0xdf, 0x9d, 0x04, 0x50, 0x73, 0x89, 0xf6, 0xc8, 0x87, 0xa1, 0x1c, 0xd2, 0x48, 0x34, 0x89, - 0xbc, 0xe6, 0x12, 0x97, 0x93, 0xaa, 0x10, 0x63, 0x38, 0xd9, 0x81, 0x62, 0xcf, 0xe9, 0x87, 0x34, - 0x9f, 0xc3, 0x8d, 0x1c, 0x99, 0xeb, 0x8c, 0xa2, 0x38, 0x35, 0xf3, 0x9f, 0x28, 0x78, 0x90, 0xaf, - 0x58, 0x00, 0x34, 0x39, 0x9a, 0x46, 0xb6, 0x5e, 0x49, 0x96, 0xf1, 0x80, 0x63, 0x6d, 0x50, 0x9f, - 0x3e, 0xd8, 0xaf, 0x82, 0x31, 0x2e, 0x0d, 0xb6, 0xe4, 0x1e, 0x94, 0x1c, 0xb5, 0x21, 0x8d, 0x9f, - 0xc5, 0x86, 0xc4, 0x0f, 0xb3, 0x7a, 0x46, 0x69, 0x66, 0xe4, 0x6b, 0x16, 0x4c, 0x87, 0x34, 0x92, - 0x5d, 0xc5, 0x96, 0x45, 0xa9, 0x8d, 0x8f, 0x38, 0x23, 0x1a, 0x09, 0x9a, 0x62, 0x79, 0x4f, 0x96, - 0x61, 0x8a, 0xaf, 0x12, 0xe5, 0x3a, 0x75, 0x5a, 0x34, 0xe0, 0xb6, 0x12, 0xa9, 0xe6, 0x8d, 0x2e, - 0x8a, 0x41, 0x53, 0x8b, 0x62, 0x94, 0x61, 0x8a, 0xaf, 0x12, 0x65, 0xcd, 0x0d, 0x02, 0x5f, 0x8a, - 0x52, 0xca, 0x49, 0x14, 0x83, 0xa6, 0x16, 0xc5, 0x28, 0xc3, 0x14, 0x5f, 0xd2, 0x81, 0x89, 0x1e, - 0x9f, 0x5a, 0x52, 0x95, 0x1b, 0xf1, 0x8e, 0x5c, 0x4d, 0x53, 0xda, 0x13, 0x36, 0x29, 0xf1, 0x1f, - 0x25, 0x0f, 0xfb, 0x3b, 0xe7, 0x60, 0x5a, 0x4d, 0xdb, 0xf8, 0x90, 0x23, 0x0c, 0x81, 0x43, 0x0e, - 0x39, 0x4b, 0x26, 0x10, 0x93, 0xb8, 0xac, 0xb2, 0x58, 0xb5, 0x92, 0x67, 0x1c, 0x5d, 0xb9, 0x61, - 0x02, 0x31, 0x89, 0x4b, 0xba, 0x50, 0x64, 0x2b, 0x8b, 0x72, 0xbf, 0x18, 0xf1, 0xcb, 0xe3, 0xd5, - 0xc8, 0x30, 0xaa, 0x30, 0xf2, 0x28, 0xb8, 0x70, 0x5b, 0x76, 0x94, 0x30, 0x6f, 0xcb, 0xa9, 0x98, - 0xcf, 0x6a, 0x90, 0xb4, 0x9c, 0x8b, 0xbe, 0x4f, 0x96, 0x61, 0x8a, 0x7d, 0xc6, 0xb9, 0xa7, 0x78, - 0x86, 0xe7, 0x9e, 0x4f, 0x43, 0xa9, 0xeb, 0xdc, 0x6f, 0xf4, 0x83, 0xf6, 0xe9, 0xcf, 0x57, 0xd2, - 0x9d, 0x56, 0x50, 0x41, 0x4d, 0x8f, 0x7c, 0xc9, 0x32, 0x16, 0x38, 0xe1, 0x6b, 0x71, 0x27, 0xdf, - 0x05, 0x4e, 0xab, 0x0d, 0x43, 0x97, 0xba, 0x81, 0x53, 0x48, 0xe9, 0x81, 0x9f, 0x42, 0x98, 0x46, - 0x2d, 0x26, 0x88, 0xd6, 0xa8, 0xcb, 0x67, 0xaa, 0x51, 0x2f, 0x25, 0x98, 0x61, 0x8a, 0x39, 0x97, - 0x47, 0xcc, 0x39, 0x2d, 0x0f, 0x9c, 0xa9, 0x3c, 0x8d, 0x04, 0x33, 0x4c, 0x31, 0x1f, 0x7e, 0xf4, - 0xae, 0x9c, 0xcd, 0xd1, 0x7b, 0x2a, 0x87, 0xa3, 0xf7, 0xe1, 0xa7, 0x92, 0x73, 0xa3, 0x9e, 0x4a, - 0xc8, 0x0d, 0x20, 0xad, 0x3d, 0xcf, 0xe9, 0xba, 0x4d, 0xb9, 0x58, 0xf2, 0x4d, 0x7a, 0x9a, 0x9b, - 0x66, 0xb4, 0x56, 0xb6, 0x3c, 0x80, 0x81, 0x19, 0xb5, 0x48, 0x04, 0xa5, 0x9e, 0x52, 0x3e, 0x67, - 0xf2, 0x18, 0xfd, 0x4a, 0x19, 0x15, 0x2e, 0x34, 0x6c, 0xe2, 0xa9, 0x12, 0xd4, 0x9c, 0xc8, 0x2a, - 0x5c, 0xec, 0xba, 0xde, 0xba, 0xdf, 0x0a, 0xd7, 0x69, 0x20, 0x0d, 0x4f, 0x0d, 0x1a, 0xcd, 0xcd, - 0xf2, 0xb6, 0xe1, 0xc6, 0x84, 0xb5, 0x0c, 0x38, 0x66, 0xd6, 0xb2, 0xff, 0xa7, 0x05, 0xb3, 0x4b, - 0x1d, 0xbf, 0xdf, 0xba, 0xe3, 0x44, 0xcd, 0x6d, 0xe1, 0xb1, 0x41, 0x5e, 0x81, 0x92, 0xeb, 0x45, - 0x34, 0xd8, 0x75, 0x3a, 0x72, 0x7f, 0xb2, 0x95, 0x25, 0x79, 0x45, 0x96, 0xbf, 0xb7, 0x5f, 0x9d, - 0x5e, 0xee, 0x07, 0xdc, 0x60, 0x2f, 0x56, 0x2b, 0xd4, 0x75, 0xc8, 0x77, 0x2c, 0x38, 0x2f, 0x7c, - 0x3e, 0x96, 0x9d, 0xc8, 0x79, 0xbd, 0x4f, 0x03, 0x97, 0x2a, 0xaf, 0x8f, 0x11, 0x17, 0xaa, 0xb4, - 0xac, 0x8a, 0xc1, 0x5e, 0x7c, 0x66, 0x59, 0x4b, 0x73, 0xc6, 0x41, 0x61, 0xec, 0x5f, 0x29, 0xc0, - 0xa3, 0x43, 0x69, 0x91, 0x79, 0x18, 0x73, 0x5b, 0xf2, 0xd3, 0x41, 0xd2, 0x1d, 0x5b, 0x69, 0xe1, - 0x98, 0xdb, 0x22, 0x0b, 0x5c, 0xc3, 0x0d, 0x68, 0x18, 0xaa, 0xbb, 0xf7, 0xb2, 0x56, 0x46, 0x65, - 0x29, 0x1a, 0x18, 0xa4, 0x0a, 0x45, 0xee, 0x4a, 0x2d, 0x8f, 0x56, 0x5c, 0x67, 0xe6, 0x5e, 0xcb, - 0x28, 0xca, 0xc9, 0x97, 0x2d, 0x00, 0x21, 0x20, 0xd3, 0xf7, 0xe5, 0x2e, 0x89, 0xf9, 0x36, 0x13, - 0xa3, 0x2c, 0xa4, 0x8c, 0xff, 0xa3, 0xc1, 0x95, 0x6c, 0xc0, 0x04, 0x53, 0x9f, 0xfd, 0xd6, 0xa9, - 0x37, 0x45, 0xa1, 0x00, 0x71, 0x1a, 0x28, 0x69, 0xb1, 0xb6, 0x0a, 0x68, 0xd4, 0x0f, 0x3c, 0xd6, - 0xb4, 0x7c, 0x1b, 0x2c, 0x09, 0x29, 0x50, 0x97, 0xa2, 0x81, 0x61, 0xff, 0xb3, 0x31, 0xb8, 0x98, - 0x25, 0x3a, 0xdb, 0x6d, 0x26, 0x84, 0xb4, 0xd2, 0x4a, 0xf0, 0xb3, 0xf9, 0xb7, 0x8f, 0x74, 0x5f, - 0xd2, 0x37, 0x36, 0xd2, 0x97, 0x54, 0xf2, 0x25, 0x3f, 0xab, 0x5b, 0x68, 0xec, 0x94, 0x2d, 0xa4, - 0x29, 0xa7, 0x5a, 0xe9, 0x49, 0x18, 0x0f, 0x59, 0xcf, 0x17, 0x92, 0x37, 0x3f, 0xbc, 0x8f, 0x38, - 0x84, 0x61, 0xf4, 0x3d, 0x37, 0x92, 0xf1, 0x47, 0x1a, 0xe3, 0xb6, 0xe7, 0x46, 0xc8, 0x21, 0xf6, - 0xb7, 0xc7, 0x60, 0x7e, 0xf8, 0x47, 0x91, 0x6f, 0x5b, 0x00, 0x2d, 0x76, 0x38, 0x0a, 0xb9, 0x13, - 0xbf, 0x70, 0xf7, 0x72, 0xce, 0xaa, 0x0d, 0x97, 0x15, 0xa7, 0xd8, 0x0f, 0x51, 0x17, 0x85, 0x68, - 0x08, 0x42, 0x9e, 0x53, 0x43, 0x9f, 0xdf, 0x5a, 0x89, 0xc9, 0xa4, 0xeb, 0xac, 0x69, 0x08, 0x1a, - 0x58, 0xec, 0xf4, 0xeb, 0x39, 0x5d, 0x1a, 0xf6, 0x1c, 0x1d, 0xcd, 0xc5, 0x4f, 0xbf, 0x37, 0x55, - 0x21, 0xc6, 0x70, 0xbb, 0x03, 0x4f, 0x1d, 0x43, 0xce, 0x9c, 0x82, 0x65, 0xec, 0xff, 0x6e, 0xc1, - 0x23, 0xd2, 0x13, 0xef, 0xff, 0x19, 0xb7, 0xce, 0x3f, 0xb3, 0xe0, 0xb1, 0x21, 0xdf, 0xfc, 0x00, - 0xbc, 0x3b, 0xdf, 0x4a, 0x7a, 0x77, 0xde, 0x1e, 0x75, 0x48, 0x67, 0x7e, 0xc7, 0x10, 0x27, 0xcf, - 0xdf, 0x2b, 0xc0, 0x39, 0xb6, 0x6c, 0xb5, 0xfc, 0x76, 0x4e, 0x1b, 0xe7, 0x53, 0x50, 0xfc, 0x3c, - 0xdb, 0x80, 0xd2, 0x83, 0x8c, 0xef, 0x4a, 0x28, 0x60, 0xe4, 0x2b, 0x16, 0x4c, 0x7e, 0x5e, 0xee, - 0xa9, 0xe2, 0x2c, 0x37, 0xe2, 0x62, 0x98, 0xf8, 0x86, 0x05, 0xb9, 0x43, 0x8a, 0x18, 0x1c, 0xed, - 0xcb, 0xa9, 0xb6, 0x52, 0xc5, 0x99, 0x3c, 0x03, 0x93, 0x5b, 0x7e, 0xd0, 0xed, 0x77, 0x9c, 0x74, - 0xe0, 0xe7, 0x35, 0x51, 0x8c, 0x0a, 0xce, 0x26, 0xb9, 0xd3, 0x73, 0xdf, 0xa0, 0x41, 0x28, 0x42, - 0x32, 0x12, 0x93, 0xbc, 0xa6, 0x21, 0x68, 0x60, 0xf1, 0x3a, 0xed, 0x76, 0x40, 0xdb, 0x4e, 0xe4, - 0x07, 0x7c, 0xe7, 0x30, 0xeb, 0x68, 0x08, 0x1a, 0x58, 0xf3, 0x9f, 0x80, 0x29, 0x53, 0xf8, 0x13, - 0xc5, 0xf3, 0x7c, 0x12, 0xa4, 0x53, 0x67, 0x6a, 0x49, 0xb2, 0x8e, 0xb3, 0x24, 0xd9, 0xff, 0x7e, - 0x0c, 0x0c, 0x5b, 0xd4, 0x03, 0x98, 0xea, 0x5e, 0x62, 0xaa, 0x8f, 0x68, 0x47, 0x31, 0x2c, 0x6b, - 0xc3, 0xa2, 0x1b, 0x77, 0x53, 0xd1, 0x8d, 0x37, 0x73, 0xe3, 0x78, 0x78, 0x70, 0xe3, 0x0f, 0x2d, - 0x78, 0x2c, 0x46, 0x1e, 0xb4, 0x61, 0x1f, 0xbd, 0x6e, 0xbf, 0x08, 0x15, 0x27, 0xae, 0x26, 0x27, - 0x96, 0x11, 0x5a, 0xa6, 0x41, 0x68, 0xe2, 0xc5, 0x61, 0x31, 0x85, 0x53, 0x86, 0xc5, 0x8c, 0x1f, - 0x1e, 0x16, 0x63, 0xff, 0x64, 0x0c, 0x9e, 0x18, 0xfc, 0x32, 0xd3, 0x57, 0xfc, 0xe8, 0x6f, 0x4b, - 0x7b, 0x93, 0x8f, 0x9d, 0xda, 0x9b, 0xbc, 0x70, 0x5c, 0x6f, 0x72, 0xed, 0xc3, 0x3d, 0x7e, 0xe6, - 0x3e, 0xdc, 0x0d, 0xb8, 0xa4, 0x1c, 0x46, 0xaf, 0xf9, 0x81, 0x8c, 0x0d, 0x51, 0x2b, 0x48, 0xa9, - 0xfe, 0x84, 0xac, 0x72, 0x09, 0xb3, 0x90, 0x30, 0xbb, 0xae, 0xfd, 0xc3, 0x02, 0x5c, 0x88, 0x9b, - 0x7d, 0xc9, 0xf7, 0x5a, 0x2e, 0xf7, 0x39, 0x7a, 0x19, 0xc6, 0xa3, 0xbd, 0x9e, 0x6a, 0xec, 0xff, - 0x5f, 0x89, 0xb3, 0xb1, 0xd7, 0x63, 0xbd, 0xfd, 0x48, 0x46, 0x15, 0x7e, 0x8b, 0xc0, 0x2b, 0x91, - 0x55, 0x3d, 0x3b, 0x44, 0x0f, 0xbc, 0x90, 0x1c, 0xcd, 0xef, 0xed, 0x57, 0x33, 0xb2, 0x3c, 0x2c, - 0x68, 0x4a, 0xc9, 0x31, 0x4f, 0xee, 0xc2, 0x74, 0xc7, 0x09, 0xa3, 0xdb, 0xbd, 0x96, 0x13, 0xd1, - 0x0d, 0x57, 0x7a, 0xf3, 0x9c, 0x2c, 0x9c, 0x46, 0xbb, 0x3d, 0xac, 0x26, 0x28, 0x61, 0x8a, 0x32, - 0xd9, 0x05, 0xc2, 0x4a, 0x36, 0x02, 0xc7, 0x0b, 0xc5, 0x57, 0x31, 0x7e, 0x27, 0x8f, 0x8d, 0xd2, - 0x47, 0xe7, 0xd5, 0x01, 0x6a, 0x98, 0xc1, 0x81, 0x3c, 0x0d, 0x13, 0x01, 0x75, 0x42, 0xbd, 0x1d, - 0xe8, 0xf9, 0x8f, 0xbc, 0x14, 0x25, 0xd4, 0x9c, 0x50, 0x13, 0x47, 0x4c, 0xa8, 0x3f, 0xb2, 0x60, - 0x3a, 0xee, 0xa6, 0x07, 0xa0, 0x7a, 0x74, 0x93, 0xaa, 0xc7, 0xf5, 0xbc, 0x96, 0xc4, 0x21, 0xda, - 0xc6, 0x9f, 0x4e, 0x9a, 0xdf, 0xc7, 0x03, 0x38, 0xbe, 0x60, 0xfa, 0xf3, 0x5b, 0x79, 0x44, 0xd5, - 0x25, 0xb4, 0xbd, 0x43, 0x1d, 0xf9, 0x99, 0xae, 0xd3, 0x92, 0x7a, 0x8c, 0x1c, 0xf6, 0x5a, 0xd7, - 0x51, 0xfa, 0x4d, 0x96, 0xae, 0xa3, 0xea, 0x90, 0xdb, 0xf0, 0x48, 0x2f, 0xf0, 0x79, 0x9e, 0x81, - 0x65, 0xea, 0xb4, 0x3a, 0xae, 0x47, 0x95, 0x99, 0x47, 0x78, 0xdd, 0x3c, 0x76, 0xb0, 0x5f, 0x7d, - 0x64, 0x3d, 0x1b, 0x05, 0x87, 0xd5, 0x4d, 0x46, 0xaa, 0x8e, 0x1f, 0x23, 0x52, 0xf5, 0x97, 0xb4, - 0x31, 0x55, 0x07, 0x45, 0x7c, 0x26, 0xaf, 0xae, 0xcc, 0x0a, 0x8f, 0xd0, 0x43, 0xaa, 0x26, 0x99, - 0xa2, 0x66, 0x3f, 0xdc, 0x62, 0x37, 0x71, 0x4a, 0x8b, 0x5d, 0x1c, 0x07, 0x33, 0xf9, 0x7e, 0xc6, - 0xc1, 0x94, 0x3e, 0x50, 0x71, 0x30, 0xdf, 0xb1, 0xe0, 0x82, 0x33, 0x18, 0x81, 0x9e, 0x8f, 0xf1, - 0x38, 0x23, 0xb4, 0xbd, 0xfe, 0x98, 0x14, 0x32, 0x2b, 0xd0, 0x1f, 0xb3, 0x44, 0xb1, 0xdf, 0x2d, - 0xc2, 0x6c, 0x5a, 0x49, 0x3a, 0xfb, 0x50, 0xdd, 0xbf, 0x61, 0xc1, 0xac, 0x9a, 0xe0, 0xfa, 0x06, - 0x5c, 0x1c, 0x31, 0x56, 0x73, 0x5a, 0x57, 0x84, 0xba, 0xa7, 0x33, 0xa8, 0x6c, 0xa4, 0xb8, 0xe1, - 0x00, 0x7f, 0xf2, 0x26, 0x54, 0xf4, 0xad, 0xca, 0xa9, 0xe2, 0x76, 0x79, 0x68, 0x69, 0x2d, 0x26, - 0x81, 0x26, 0x3d, 0xf2, 0xae, 0x05, 0xd0, 0x54, 0x3b, 0x71, 0x4e, 0x51, 0x51, 0x19, 0xda, 0x42, - 0xac, 0xcf, 0xeb, 0xa2, 0x10, 0x0d, 0xc6, 0xe4, 0x57, 0xf8, 0x7d, 0x8a, 0x1e, 0x09, 0xca, 0xf3, - 0xe0, 0x53, 0x79, 0x2f, 0x45, 0xb1, 0x2f, 0x89, 0xd6, 0xf6, 0x0c, 0x50, 0x88, 0x09, 0x21, 0xec, - 0x97, 0x41, 0xfb, 0x6c, 0xb3, 0x95, 0x95, 0x7b, 0x6d, 0xaf, 0x3b, 0xd1, 0xb6, 0x1c, 0x82, 0x7a, - 0x65, 0xbd, 0xa6, 0x00, 0x18, 0xe3, 0xd8, 0x9f, 0x83, 0xe9, 0x57, 0x03, 0xa7, 0xb7, 0xed, 0xf2, - 0x7b, 0x0b, 0x76, 0x3e, 0x7e, 0x06, 0x26, 0x9d, 0x56, 0x2b, 0x2b, 0xd9, 0x4f, 0x4d, 0x14, 0xa3, - 0x82, 0x1f, 0xeb, 0x28, 0x6c, 0xff, 0x6b, 0x0b, 0x48, 0x7c, 0xd3, 0xec, 0x7a, 0xed, 0x35, 0x27, - 0x6a, 0x6e, 0xb3, 0x23, 0xdc, 0x36, 0x2f, 0xcd, 0x3a, 0xc2, 0x5d, 0xd7, 0x10, 0x34, 0xb0, 0xc8, - 0xdb, 0x50, 0x11, 0xff, 0xde, 0xd0, 0x07, 0xc4, 0xd1, 0x5d, 0xcf, 0xf9, 0x9e, 0xc7, 0x65, 0x12, - 0xa3, 0xf0, 0x7a, 0xcc, 0x01, 0x4d, 0x76, 0xac, 0xa9, 0x56, 0xbc, 0xad, 0x4e, 0xff, 0x7e, 0x6b, - 0x33, 0x6e, 0xaa, 0x5e, 0xe0, 0x6f, 0xb9, 0x1d, 0x9a, 0x6e, 0xaa, 0x75, 0x51, 0x8c, 0x0a, 0x7e, - 0xbc, 0xa6, 0xfa, 0x57, 0x16, 0x5c, 0x5c, 0x09, 0x23, 0xd7, 0x5f, 0xa6, 0x61, 0xc4, 0x76, 0x3e, - 0xb6, 0x3e, 0xf6, 0x3b, 0xc7, 0x09, 0xbf, 0x58, 0x86, 0x59, 0x79, 0x0f, 0xdd, 0xdf, 0x0c, 0x69, - 0x64, 0x1c, 0x35, 0xf4, 0x3c, 0x5e, 0x4a, 0xc1, 0x71, 0xa0, 0x06, 0xa3, 0x22, 0x2f, 0xa4, 0x63, - 0x2a, 0x85, 0x24, 0x95, 0x46, 0x0a, 0x8e, 0x03, 0x35, 0xec, 0x1f, 0x14, 0xe0, 0x02, 0xff, 0x8c, - 0x54, 0xe8, 0xd4, 0x37, 0x87, 0x85, 0x4e, 0x8d, 0x38, 0x95, 0x39, 0xaf, 0x53, 0x04, 0x4e, 0xfd, - 0x75, 0x0b, 0x66, 0x5a, 0xc9, 0x96, 0xce, 0xc7, 0x2e, 0x97, 0xd5, 0x87, 0xc2, 0x03, 0x31, 0x55, - 0x88, 0x69, 0xfe, 0xe4, 0x57, 0x2d, 0x98, 0x49, 0x8a, 0xa9, 0x56, 0xf7, 0x33, 0x68, 0x24, 0x1d, - 0x32, 0x90, 0x2c, 0x0f, 0x31, 0x2d, 0x82, 0xfd, 0xfb, 0x63, 0xb2, 0x4b, 0xcf, 0x22, 0x2e, 0x88, - 0xdc, 0x83, 0x72, 0xd4, 0x09, 0x45, 0xa1, 0xfc, 0xda, 0x11, 0x0f, 0xad, 0x1b, 0xab, 0x0d, 0xe1, - 0x70, 0x12, 0xeb, 0x95, 0xb2, 0x84, 0xe9, 0xc7, 0x8a, 0x17, 0x67, 0xdc, 0xec, 0x49, 0xc6, 0xb9, - 0x9c, 0x96, 0x37, 0x96, 0xd6, 0xd3, 0x8c, 0x65, 0x09, 0x63, 0xac, 0x78, 0xd9, 0xbf, 0x69, 0x41, - 0xf9, 0x86, 0xaf, 0xd6, 0x91, 0x9f, 0xcb, 0xc1, 0x16, 0xa5, 0x55, 0x56, 0xad, 0xb4, 0xc4, 0xa7, - 0xa0, 0x57, 0x12, 0x96, 0xa8, 0xc7, 0x0d, 0xda, 0x0b, 0x3c, 0xe7, 0x21, 0x23, 0x75, 0xc3, 0xdf, - 0x1c, 0x6a, 0x3e, 0xfe, 0xb5, 0x22, 0x9c, 0x7b, 0xcd, 0xd9, 0xa3, 0x5e, 0xe4, 0x9c, 0x7c, 0x93, - 0x78, 0x11, 0x2a, 0x4e, 0x8f, 0xdf, 0x65, 0x1a, 0xc7, 0x90, 0xd8, 0xb8, 0x13, 0x83, 0xd0, 0xc4, - 0x8b, 0x17, 0x34, 0x11, 0xa4, 0x93, 0xb5, 0x14, 0x2d, 0xa5, 0xe0, 0x38, 0x50, 0x83, 0xdc, 0x00, - 0x22, 0x03, 0xdb, 0x6b, 0xcd, 0xa6, 0xdf, 0xf7, 0xc4, 0x92, 0x26, 0xec, 0x3e, 0xfa, 0x3c, 0xbc, - 0x36, 0x80, 0x81, 0x19, 0xb5, 0xc8, 0x67, 0x61, 0xae, 0xc9, 0x29, 0xcb, 0xd3, 0x91, 0x49, 0x51, - 0x9c, 0x90, 0x75, 0xd8, 0xcb, 0xd2, 0x10, 0x3c, 0x1c, 0x4a, 0x81, 0x49, 0x1a, 0x46, 0x7e, 0xe0, - 0xb4, 0xa9, 0x49, 0x77, 0x22, 0x29, 0x69, 0x63, 0x00, 0x03, 0x33, 0x6a, 0x91, 0x2f, 0x42, 0x39, - 0xda, 0x0e, 0x68, 0xb8, 0xed, 0x77, 0x5a, 0xd2, 0xf7, 0x64, 0x44, 0x63, 0xa0, 0xec, 0xfd, 0x0d, - 0x45, 0xd5, 0x18, 0xde, 0xaa, 0x08, 0x63, 0x9e, 0x24, 0x80, 0x89, 0xb0, 0xe9, 0xf7, 0x68, 0x28, - 0x4f, 0x15, 0x37, 0x72, 0xe1, 0xce, 0x8d, 0x5b, 0x86, 0x19, 0x92, 0x73, 0x40, 0xc9, 0xc9, 0xfe, - 0xdd, 0x31, 0x98, 0x32, 0x11, 0x8f, 0xb1, 0x36, 0x7d, 0xc5, 0x82, 0xa9, 0xa6, 0xef, 0x45, 0x81, - 0xdf, 0x89, 0x13, 0x36, 0x8c, 0xae, 0x51, 0x30, 0x52, 0xcb, 0x34, 0x72, 0xdc, 0x8e, 0x61, 0xad, - 0x33, 0xd8, 0x60, 0x82, 0x29, 0xf9, 0x86, 0x05, 0x33, 0xb1, 0x63, 0x64, 0x6c, 0xeb, 0xcb, 0x55, - 0x10, 0xbd, 0xd4, 0x5f, 0x4d, 0x72, 0xc2, 0x34, 0x6b, 0x7b, 0x13, 0x66, 0xd3, 0xbd, 0xcd, 0x9a, - 0xb2, 0xe7, 0xc8, 0xb9, 0x5e, 0x88, 0x9b, 0x72, 0xdd, 0x09, 0x43, 0xe4, 0x10, 0xf2, 0x2c, 0x94, - 0xba, 0x4e, 0xd0, 0x76, 0x3d, 0xa7, 0xc3, 0x5b, 0xb1, 0x60, 0x2c, 0x48, 0xb2, 0x1c, 0x35, 0x86, - 0xfd, 0x51, 0x98, 0x5a, 0x73, 0xbc, 0x36, 0x6d, 0xc9, 0x75, 0xf8, 0xe8, 0xc8, 0xd4, 0x3f, 0x19, - 0x87, 0x8a, 0x71, 0x7c, 0x3c, 0xfb, 0x73, 0x56, 0x22, 0x11, 0x51, 0x21, 0xc7, 0x44, 0x44, 0x9f, - 0x06, 0xd8, 0x72, 0x3d, 0x37, 0xdc, 0x3e, 0x65, 0x8a, 0x23, 0x7e, 0x37, 0x7f, 0x4d, 0x53, 0x40, - 0x83, 0x5a, 0x7c, 0x01, 0x5a, 0x3c, 0x24, 0x5b, 0xe0, 0xbb, 0x96, 0xb1, 0xdd, 0x4c, 0xe4, 0xe1, - 0xf0, 0x61, 0x74, 0xcc, 0x82, 0xda, 0x7e, 0xc4, 0xdd, 0xd4, 0x61, 0xbb, 0xd2, 0x06, 0x94, 0x02, - 0x1a, 0xf6, 0xbb, 0xf4, 0x54, 0xc9, 0x88, 0xb8, 0xeb, 0x0d, 0xca, 0xfa, 0xa8, 0x29, 0xcd, 0xbf, - 0x0c, 0xe7, 0x12, 0x22, 0x9c, 0xe8, 0x86, 0xc9, 0x87, 0x4c, 0x1b, 0xc5, 0x69, 0xee, 0x9b, 0x58, - 0x5f, 0x74, 0x8c, 0x24, 0x44, 0xba, 0x2f, 0x84, 0x83, 0x95, 0x80, 0xd9, 0x3f, 0x99, 0x00, 0xe9, - 0xc3, 0x70, 0x8c, 0xe5, 0xca, 0xbc, 0xb9, 0x1c, 0x3b, 0xc5, 0xcd, 0xe5, 0x0d, 0x98, 0x72, 0x3d, - 0x37, 0x72, 0x9d, 0x0e, 0xb7, 0x3f, 0xc9, 0xed, 0x54, 0x39, 0xe3, 0x4f, 0xad, 0x18, 0xb0, 0x0c, - 0x3a, 0x89, 0xba, 0xe4, 0x75, 0x28, 0xf2, 0xfd, 0x46, 0x0e, 0xe0, 0x93, 0x3b, 0x5a, 0x70, 0x1f, - 0x1b, 0x11, 0xa1, 0x27, 0x28, 0xf1, 0xc3, 0x87, 0xc8, 0xc2, 0xa4, 0x8f, 0xdf, 0x72, 0x1c, 0xc7, - 0x87, 0x8f, 0x14, 0x1c, 0x07, 0x6a, 0x30, 0x2a, 0x5b, 0x8e, 0xdb, 0xe9, 0x07, 0x34, 0xa6, 0x32, - 0x91, 0xa4, 0x72, 0x2d, 0x05, 0xc7, 0x81, 0x1a, 0x64, 0x0b, 0xa6, 0x64, 0x99, 0x70, 0x9b, 0x9b, - 0x3c, 0xe5, 0x57, 0x72, 0xf7, 0xc8, 0x6b, 0x06, 0x25, 0x4c, 0xd0, 0x25, 0x7d, 0x38, 0xef, 0x7a, - 0x4d, 0xdf, 0x6b, 0x76, 0xfa, 0xa1, 0xbb, 0x4b, 0xe3, 0xf0, 0xb8, 0xd3, 0x30, 0xbb, 0x74, 0xb0, - 0x5f, 0x3d, 0xbf, 0x92, 0x26, 0x87, 0x83, 0x1c, 0xc8, 0x97, 0x2c, 0xb8, 0xd4, 0xf4, 0xbd, 0x90, - 0x67, 0xf1, 0xd8, 0xa5, 0x57, 0x83, 0xc0, 0x0f, 0x04, 0xef, 0xf2, 0x29, 0x79, 0x73, 0xb3, 0xe7, - 0x52, 0x16, 0x49, 0xcc, 0xe6, 0x44, 0xde, 0x82, 0x52, 0x2f, 0xf0, 0x77, 0xdd, 0x16, 0x0d, 0xa4, - 0x0b, 0xe6, 0x6a, 0x1e, 0xa9, 0x8d, 0xd6, 0x25, 0xcd, 0x78, 0xe9, 0x51, 0x25, 0xa8, 0xf9, 0xd9, - 0xff, 0xbb, 0x02, 0xd3, 0x49, 0x74, 0xf2, 0x0b, 0x00, 0xbd, 0xc0, 0xef, 0xd2, 0x68, 0x9b, 0xea, - 0x30, 0xa7, 0x9b, 0xa3, 0x26, 0xaf, 0x51, 0xf4, 0x94, 0xdb, 0x12, 0x5b, 0x2e, 0xe2, 0x52, 0x34, - 0x38, 0x92, 0x00, 0x26, 0x77, 0xc4, 0xb6, 0x2b, 0xb5, 0x90, 0xd7, 0x72, 0xd1, 0x99, 0x24, 0x67, - 0x1e, 0x9f, 0x23, 0x8b, 0x50, 0x31, 0x22, 0x9b, 0x50, 0xb8, 0x47, 0x37, 0xf3, 0xc9, 0x9c, 0x70, - 0x87, 0xca, 0xd3, 0x4c, 0x7d, 0xf2, 0x60, 0xbf, 0x5a, 0xb8, 0x43, 0x37, 0x91, 0x11, 0x67, 0xdf, - 0xd5, 0x12, 0xbe, 0x0b, 0x72, 0xa9, 0x78, 0x2d, 0x47, 0x47, 0x08, 0xf1, 0x5d, 0xb2, 0x08, 0x15, - 0x23, 0xf2, 0x16, 0x94, 0xef, 0x39, 0xbb, 0x74, 0x2b, 0xf0, 0xbd, 0x48, 0xfa, 0xca, 0x8d, 0x18, - 0x5c, 0x72, 0x47, 0x91, 0x93, 0x7c, 0xf9, 0xf6, 0xae, 0x0b, 0x31, 0x66, 0x47, 0x76, 0xa1, 0xe4, - 0xd1, 0x7b, 0x48, 0x3b, 0x6e, 0x33, 0x9f, 0x60, 0x8e, 0x9b, 0x92, 0x9a, 0xe4, 0xcc, 0xf7, 0x3d, - 0x55, 0x86, 0x9a, 0x17, 0xeb, 0xcb, 0xbb, 0xfe, 0xa6, 0x5c, 0xa8, 0x46, 0xec, 0x4b, 0x7d, 0x32, - 0x15, 0x7d, 0x79, 0xc3, 0xdf, 0x44, 0x46, 0x9c, 0xcd, 0x91, 0xa6, 0x76, 0xd4, 0x92, 0xcb, 0xd4, - 0xcd, 0x7c, 0x1d, 0xd4, 0xc4, 0x1c, 0x89, 0x4b, 0xd1, 0xe0, 0xc8, 0xda, 0xb6, 0x2d, 0x8d, 0x95, - 0x72, 0xa1, 0x1a, 0xb1, 0x6d, 0x93, 0xa6, 0x4f, 0xd1, 0xb6, 0xaa, 0x0c, 0x35, 0x2f, 0xc6, 0xd7, - 0x95, 0x96, 0xbf, 0x7c, 0x96, 0xaa, 0xa4, 0x1d, 0x51, 0xf0, 0x55, 0x65, 0xa8, 0x79, 0xb1, 0xf6, - 0x0e, 0x77, 0xf6, 0xee, 0x39, 0x9d, 0x1d, 0xd7, 0x6b, 0xcb, 0xb0, 0xdd, 0x51, 0xc3, 0xdc, 0x76, - 0xf6, 0xee, 0x08, 0x7a, 0x66, 0x7b, 0xc7, 0xa5, 0x68, 0x70, 0x24, 0x7f, 0xd7, 0xd2, 0xa1, 0x38, - 0x53, 0x79, 0x38, 0x31, 0x25, 0x97, 0x5c, 0x19, 0x99, 0x23, 0x14, 0xc5, 0x9f, 0xd6, 0x7e, 0x97, - 0xbc, 0xf0, 0xeb, 0x7f, 0x5c, 0x9d, 0xa3, 0x5e, 0xd3, 0x6f, 0xb9, 0x5e, 0x7b, 0xf1, 0x6e, 0xe8, - 0x7b, 0x0b, 0xe8, 0xdc, 0x53, 0x3a, 0xba, 0x94, 0x69, 0xfe, 0xe3, 0x50, 0x31, 0x48, 0x1c, 0xa5, - 0xe8, 0x4d, 0x99, 0x8a, 0xde, 0x6f, 0x4e, 0xc0, 0x94, 0x99, 0x87, 0xf4, 0x18, 0xda, 0x97, 0x3e, - 0x71, 0x8c, 0x9d, 0xe4, 0xc4, 0xc1, 0x8e, 0x98, 0xc6, 0x05, 0x97, 0x32, 0x6f, 0xad, 0xe4, 0xa6, - 0x70, 0xc7, 0x47, 0x4c, 0xa3, 0x30, 0xc4, 0x04, 0xd3, 0x13, 0xf8, 0xbc, 0x30, 0xb5, 0x55, 0x28, - 0x76, 0xc5, 0xa4, 0xda, 0x9a, 0x50, 0xd5, 0x9e, 0x03, 0x88, 0x13, 0x66, 0xca, 0x8b, 0x4f, 0xad, - 0x0f, 0x1b, 0x89, 0x3c, 0x0d, 0x2c, 0xf2, 0x34, 0x4c, 0x30, 0xd5, 0x87, 0xb6, 0x64, 0x56, 0x01, - 0x7d, 0x8e, 0xbf, 0xc6, 0x4b, 0x51, 0x42, 0xc9, 0x4b, 0x4c, 0x4b, 0x8d, 0x15, 0x16, 0x99, 0x2c, - 0xe0, 0x62, 0xac, 0xa5, 0xc6, 0x30, 0x4c, 0x60, 0x32, 0xd1, 0x29, 0xd3, 0x2f, 0xf8, 0xda, 0x60, - 0x88, 0xce, 0x95, 0x0e, 0x14, 0x30, 0x6e, 0x57, 0x4a, 0xe9, 0x23, 0x7c, 0x4e, 0x17, 0x0d, 0xbb, - 0x52, 0x0a, 0x8e, 0x03, 0x35, 0xd8, 0xc7, 0xc8, 0x3b, 0xdb, 0x8a, 0x70, 0x98, 0x1e, 0x72, 0xdb, - 0xfa, 0x55, 0xf3, 0xac, 0x95, 0xe3, 0x1c, 0x12, 0xa3, 0xf6, 0xf8, 0x87, 0xad, 0xd1, 0x8e, 0x45, - 0x9f, 0x83, 0xe9, 0xe4, 0x2e, 0x94, 0xfb, 0xcd, 0xc7, 0xd7, 0xc6, 0xe1, 0xc2, 0xcd, 0xb6, 0xeb, - 0xa5, 0x73, 0xbe, 0x65, 0x3d, 0xf0, 0x60, 0x9d, 0xf8, 0x81, 0x07, 0x1d, 0x93, 0x27, 0x9f, 0x4f, - 0xc8, 0x8e, 0xc9, 0x53, 0x6f, 0x59, 0x24, 0x71, 0xc9, 0x1f, 0x59, 0xf0, 0xb8, 0xd3, 0x12, 0xe7, - 0x02, 0xa7, 0x23, 0x4b, 0x8d, 0xbc, 0xe4, 0x72, 0x46, 0x87, 0x23, 0xee, 0xf2, 0x83, 0x1f, 0xbf, - 0x50, 0x3b, 0x84, 0xab, 0xe8, 0xf1, 0x9f, 0x92, 0x5f, 0xf0, 0xf8, 0x61, 0xa8, 0x78, 0xa8, 0xf8, - 0xe4, 0x2f, 0xc3, 0x4c, 0xe2, 0x83, 0xa5, 0x25, 0xbc, 0x2c, 0x2e, 0x2c, 0x1a, 0x49, 0x10, 0xa6, - 0x71, 0xe7, 0x6f, 0xc1, 0x87, 0x8e, 0x94, 0xf3, 0x44, 0x83, 0xed, 0xfb, 0x16, 0x4c, 0x99, 0xe9, - 0x99, 0xc8, 0xb3, 0x50, 0x8a, 0xfc, 0x1d, 0xea, 0xdd, 0x0e, 0x94, 0xc3, 0xae, 0x1e, 0xe8, 0x1b, - 0xbc, 0x1c, 0x57, 0x51, 0x63, 0x30, 0xec, 0x66, 0xc7, 0xa5, 0x5e, 0xb4, 0xd2, 0x92, 0xdd, 0xac, - 0xb1, 0x97, 0x44, 0xf9, 0x32, 0x6a, 0x0c, 0xe1, 0x63, 0xc7, 0x7e, 0x37, 0x68, 0x33, 0xa0, 0xca, - 0xbd, 0xdf, 0xf0, 0xb1, 0x8b, 0x61, 0x98, 0xc0, 0x24, 0xb6, 0x36, 0x71, 0x8e, 0xc7, 0xf7, 0x1a, - 0x29, 0x93, 0xe4, 0x77, 0x2d, 0x28, 0x0b, 0x13, 0x3d, 0xd2, 0xad, 0x94, 0x8b, 0x6d, 0xca, 0x88, - 0x50, 0x5b, 0x5f, 0xc9, 0x72, 0xb1, 0x7d, 0x12, 0xc6, 0x77, 0x5c, 0x4f, 0x7d, 0x89, 0xde, 0x96, - 0x5e, 0x73, 0xbd, 0x16, 0x72, 0x88, 0xde, 0xb8, 0x0a, 0x43, 0x37, 0xae, 0x45, 0x28, 0x6b, 0xc7, - 0x13, 0xb9, 0xfc, 0x6b, 0xeb, 0xad, 0x76, 0x54, 0xc1, 0x18, 0xc7, 0xfe, 0x75, 0x0b, 0xa6, 0x79, - 0xc4, 0x78, 0x7c, 0x1e, 0x7e, 0x51, 0xfb, 0x82, 0x09, 0xb9, 0x9f, 0x48, 0xfa, 0x82, 0xbd, 0xb7, - 0x5f, 0xad, 0x88, 0x18, 0xf3, 0xa4, 0x6b, 0xd8, 0x67, 0xa4, 0x11, 0x8d, 0x7b, 0xac, 0x8d, 0x9d, - 0xd8, 0xc6, 0x13, 0x8b, 0xa9, 0x88, 0x60, 0x4c, 0xcf, 0x7e, 0x1b, 0xa6, 0xcc, 0x60, 0x2c, 0xf2, - 0x22, 0x54, 0x7a, 0xae, 0xd7, 0x4e, 0x06, 0xed, 0xea, 0x8b, 0x86, 0xf5, 0x18, 0x84, 0x26, 0x1e, - 0xaf, 0xe6, 0xc7, 0xd5, 0x52, 0xf7, 0x13, 0xeb, 0xbe, 0x59, 0x2d, 0xfe, 0x63, 0x7b, 0x00, 0x71, - 0x64, 0xf1, 0xb1, 0x8c, 0x37, 0x13, 0xc2, 0xf6, 0x2f, 0x94, 0x11, 0x9e, 0x25, 0x62, 0x42, 0x8c, - 0xf0, 0xf7, 0xf6, 0x0f, 0x53, 0x76, 0x44, 0x2d, 0xfe, 0x06, 0x45, 0x46, 0x90, 0x61, 0xee, 0x6f, - 0x50, 0x64, 0xf0, 0x78, 0xff, 0xde, 0xa0, 0xc8, 0x12, 0xe6, 0xcf, 0xd7, 0x1b, 0x14, 0x9f, 0x82, - 0x93, 0xa6, 0xa3, 0x65, 0xba, 0xc5, 0x3d, 0x33, 0x6d, 0x84, 0x6e, 0x71, 0x99, 0x37, 0x42, 0x42, - 0xed, 0xdf, 0x29, 0xc0, 0x6c, 0xda, 0xc4, 0x90, 0xb7, 0xf7, 0x06, 0xf9, 0x86, 0x05, 0xd3, 0x4e, - 0x22, 0xf5, 0x5f, 0x4e, 0x0f, 0x5a, 0x25, 0x68, 0x1a, 0xa9, 0xe7, 0x12, 0xe5, 0x98, 0xe2, 0x4d, - 0xfe, 0x3f, 0x98, 0x8c, 0xdc, 0x2e, 0xf5, 0xfb, 0xc2, 0xf0, 0x58, 0x10, 0x06, 0x80, 0x0d, 0x51, - 0x84, 0x0a, 0xc6, 0x36, 0x01, 0x97, 0x6b, 0x6c, 0x01, 0x95, 0x9e, 0xc8, 0xb3, 0xb1, 0xa5, 0x54, - 0x94, 0xa3, 0xc6, 0x20, 0xf7, 0x61, 0x52, 0xf8, 0x79, 0x28, 0x87, 0x9e, 0xb5, 0x9c, 0x4c, 0x21, - 0xc2, 0x95, 0x24, 0xee, 0x02, 0xf1, 0x3f, 0x44, 0xc5, 0xce, 0xfe, 0x28, 0x9c, 0x30, 0x3f, 0xaf, - 0x7d, 0x15, 0x08, 0xfa, 0x9d, 0xce, 0xa6, 0xd3, 0xdc, 0xb9, 0xe3, 0x7a, 0x2d, 0xff, 0x1e, 0x5f, - 0xfa, 0x16, 0xa1, 0x1c, 0xc8, 0x10, 0xdd, 0x50, 0x8e, 0x1a, 0xbd, 0x76, 0xaa, 0xd8, 0xdd, 0x10, - 0x63, 0x1c, 0xfb, 0xf7, 0xc7, 0x60, 0x52, 0xc6, 0x93, 0x3f, 0x80, 0x48, 0x88, 0x9d, 0xc4, 0xfd, - 0xf3, 0x4a, 0x2e, 0x61, 0xf0, 0x43, 0xc3, 0x20, 0xc2, 0x54, 0x18, 0xc4, 0x6b, 0xf9, 0xb0, 0x3b, - 0x3c, 0x06, 0xe2, 0x7b, 0x45, 0x98, 0x49, 0xc5, 0xe7, 0xa7, 0x52, 0x79, 0x5b, 0xef, 0x4b, 0x2a, - 0x6f, 0x12, 0x26, 0xd2, 0xb9, 0xe7, 0xe7, 0x37, 0xf9, 0x17, 0x99, 0xdd, 0xf3, 0xf2, 0x68, 0x2d, - 0x7e, 0x70, 0x3c, 0x5a, 0xff, 0xb3, 0x05, 0x8f, 0x0e, 0xcd, 0x32, 0xc1, 0xf3, 0xb5, 0x05, 0x49, - 0xa8, 0x5c, 0x2f, 0x72, 0xce, 0xdc, 0xa3, 0xef, 0xaa, 0xd3, 0x29, 0xb6, 0xd2, 0xec, 0xc9, 0x0b, - 0x30, 0xc5, 0xf5, 0x41, 0xb6, 0x72, 0x46, 0xb4, 0x27, 0xaf, 0xda, 0xf8, 0xa5, 0x4b, 0xc3, 0x28, - 0xc7, 0x04, 0x96, 0xfd, 0x1d, 0x0b, 0xe6, 0x86, 0x65, 0xef, 0x3a, 0x86, 0x26, 0xf7, 0x97, 0x52, - 0x91, 0x24, 0xd5, 0x81, 0x48, 0x92, 0x94, 0x29, 0x48, 0x05, 0x8d, 0x18, 0x56, 0x98, 0xc2, 0x11, - 0x81, 0x12, 0x7f, 0x50, 0x80, 0x59, 0x29, 0x62, 0xac, 0x84, 0xbf, 0x94, 0x88, 0x7f, 0xf9, 0xa9, - 0x54, 0xfc, 0xcb, 0xc5, 0x34, 0xfe, 0x5f, 0x04, 0xbf, 0x7c, 0xb0, 0x82, 0x5f, 0xbe, 0x5e, 0x84, - 0x4b, 0x99, 0x79, 0xb2, 0xc8, 0xd7, 0x32, 0x76, 0x8a, 0x3b, 0x39, 0x27, 0xe4, 0xd2, 0x71, 0xb2, - 0x67, 0x1b, 0x31, 0xf2, 0xab, 0x66, 0xa4, 0x86, 0x58, 0xfd, 0xb7, 0xce, 0x20, 0xb5, 0xd8, 0x49, - 0x83, 0x36, 0x1e, 0xec, 0x53, 0x67, 0x7f, 0x0e, 0x96, 0xfa, 0xaf, 0x17, 0xe0, 0xca, 0x71, 0x5b, - 0xf6, 0x03, 0x1a, 0xe5, 0x18, 0x26, 0xa2, 0x1c, 0x1f, 0x90, 0x6a, 0x73, 0x26, 0x01, 0x8f, 0x7f, - 0x7f, 0x5c, 0xef, 0xbb, 0x83, 0x13, 0xf6, 0x58, 0xb6, 0x85, 0x49, 0xa6, 0xfa, 0xaa, 0x84, 0xf0, - 0xf1, 0xde, 0x30, 0xd9, 0x10, 0xc5, 0xef, 0xed, 0x57, 0xcf, 0xc7, 0x09, 0x65, 0x64, 0x21, 0xaa, - 0x4a, 0xe4, 0x0a, 0x94, 0x02, 0x01, 0x55, 0x71, 0x5d, 0xd2, 0xbb, 0x46, 0x94, 0xa1, 0x86, 0x92, - 0x2f, 0x1a, 0x67, 0x85, 0xf1, 0xb3, 0xca, 0x9b, 0x74, 0x98, 0xd3, 0xd0, 0x9b, 0x50, 0x0a, 0x55, - 0xd6, 0x72, 0x31, 0x9d, 0x9e, 0x3f, 0x66, 0xb8, 0xa0, 0xb3, 0x49, 0x3b, 0x2a, 0x85, 0xb9, 0xf8, - 0x3e, 0x9d, 0xe0, 0x5c, 0x93, 0x24, 0xb6, 0x3e, 0x7b, 0x8b, 0x4b, 0x0d, 0x18, 0x3c, 0x77, 0x93, - 0x08, 0x26, 0xe5, 0xd3, 0xc5, 0xf2, 0xb6, 0x75, 0x2d, 0xa7, 0xb8, 0x1b, 0xe9, 0x95, 0xcd, 0x8f, - 0xb4, 0xca, 0xe6, 0xa4, 0x58, 0xd9, 0x3f, 0xb4, 0xa0, 0x22, 0xc7, 0xc8, 0x03, 0x88, 0x9b, 0xbc, - 0x9b, 0x8c, 0x9b, 0xbc, 0x9a, 0xcb, 0x12, 0x3e, 0x24, 0x68, 0xf2, 0x2e, 0x4c, 0x99, 0x19, 0x2b, - 0xc9, 0xa7, 0x8d, 0x2d, 0xc8, 0x1a, 0x25, 0x2b, 0x9b, 0xda, 0xa4, 0xe2, 0xed, 0xc9, 0xfe, 0xc7, - 0x65, 0xdd, 0x8a, 0xfc, 0xe0, 0x6c, 0x8e, 0x7c, 0xeb, 0xd0, 0x91, 0x6f, 0x0e, 0xbc, 0xb1, 0xfc, - 0x07, 0xde, 0xeb, 0x50, 0x52, 0xcb, 0xa2, 0xd4, 0xa6, 0x9e, 0x32, 0xdd, 0xb4, 0x99, 0x4a, 0xc6, - 0x88, 0x19, 0xd3, 0x85, 0x1f, 0x80, 0x63, 0x4b, 0xb8, 0x5a, 0xae, 0x35, 0x19, 0xf2, 0x16, 0x54, - 0xee, 0xf9, 0xc1, 0x4e, 0xc7, 0x77, 0xf8, 0x53, 0x11, 0x90, 0x87, 0x67, 0x80, 0xb6, 0x66, 0x8b, - 0x58, 0x99, 0x3b, 0x31, 0x7d, 0x34, 0x99, 0x91, 0x1a, 0xcc, 0x74, 0x5d, 0x0f, 0xa9, 0xd3, 0xd2, - 0xe1, 0x91, 0xe3, 0x22, 0x4d, 0xbb, 0xd2, 0xed, 0xd7, 0x92, 0x60, 0x4c, 0xe3, 0x73, 0xcb, 0x53, - 0x90, 0x30, 0x75, 0xc8, 0x5c, 0xcc, 0xeb, 0xa3, 0x0f, 0xc6, 0xa4, 0xf9, 0x44, 0x04, 0x8b, 0x24, - 0xcb, 0x31, 0xc5, 0x9b, 0x7c, 0x01, 0x4a, 0xa1, 0x7a, 0x14, 0xb4, 0x98, 0xe3, 0xa9, 0x47, 0x3f, - 0x0c, 0xaa, 0xbb, 0x52, 0xbf, 0x0c, 0xaa, 0x19, 0x92, 0x55, 0xb8, 0xa8, 0x6c, 0x37, 0x89, 0xf7, - 0x0d, 0x27, 0xe2, 0x7c, 0x62, 0x98, 0x01, 0xc7, 0xcc, 0x5a, 0x4c, 0xb7, 0xe5, 0x99, 0x60, 0xc5, - 0x4d, 0xac, 0x71, 0x79, 0xc9, 0xe7, 0x5f, 0x0b, 0x25, 0xf4, 0xb0, 0xe8, 0xdf, 0xd2, 0x08, 0xd1, - 0xbf, 0x0d, 0xb8, 0x94, 0x06, 0xf1, 0x44, 0x71, 0x3c, 0x37, 0x9d, 0xb1, 0x85, 0xae, 0x67, 0x21, - 0x61, 0x76, 0x5d, 0x72, 0x07, 0xca, 0x01, 0xe5, 0xa7, 0xbc, 0x9a, 0x72, 0x62, 0x3b, 0xb1, 0xbb, - 0x2e, 0x2a, 0x02, 0x18, 0xd3, 0x62, 0xfd, 0xee, 0x24, 0x13, 0xa7, 0xbf, 0x9e, 0xe3, 0xab, 0xe1, - 0xb2, 0xef, 0x87, 0x24, 0x70, 0xb4, 0xff, 0xcd, 0x0c, 0x9c, 0x4b, 0x18, 0xa0, 0xc8, 0x53, 0x50, - 0xe4, 0x99, 0xf3, 0xf8, 0x6a, 0x55, 0x8a, 0x57, 0x54, 0xd1, 0x38, 0x02, 0x46, 0x7e, 0xd9, 0x82, - 0x99, 0x5e, 0xe2, 0x02, 0x47, 0x2d, 0xe4, 0x23, 0x5a, 0x6d, 0x93, 0xb7, 0x42, 0xc6, 0x93, 0x23, - 0x49, 0x66, 0x98, 0xe6, 0xce, 0xd6, 0x03, 0xe9, 0xf3, 0xde, 0xa1, 0x01, 0xc7, 0x96, 0x8a, 0x9e, - 0x26, 0xb1, 0x94, 0x04, 0x63, 0x1a, 0x9f, 0xf5, 0x30, 0xff, 0xba, 0x51, 0x5e, 0x86, 0xad, 0x29, - 0x02, 0x18, 0xd3, 0x22, 0xaf, 0xc0, 0xb4, 0xcc, 0x97, 0xbd, 0xee, 0xb7, 0xae, 0x3b, 0xe1, 0xb6, - 0x3c, 0xf2, 0xe9, 0x23, 0xea, 0x52, 0x02, 0x8a, 0x29, 0x6c, 0xfe, 0x6d, 0x71, 0x52, 0x72, 0x4e, - 0x60, 0x22, 0xf9, 0x22, 0xcb, 0x52, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0xac, 0xb1, 0x0d, 0x09, 0xef, - 0x08, 0xbd, 0x1a, 0x64, 0x6c, 0x45, 0x35, 0x98, 0xe9, 0xf3, 0x13, 0x72, 0x4b, 0x01, 0xe5, 0x7c, - 0xd4, 0x0c, 0x6f, 0x27, 0xc1, 0x98, 0xc6, 0x27, 0x2f, 0xc3, 0xb9, 0x80, 0x2d, 0xb6, 0x9a, 0x80, - 0x70, 0x99, 0xd0, 0x37, 0xe2, 0x68, 0x02, 0x31, 0x89, 0x4b, 0x5e, 0x85, 0xf3, 0x71, 0x4e, 0x55, - 0x45, 0x40, 0xf8, 0x50, 0xe8, 0x04, 0x7f, 0xb5, 0x34, 0x02, 0x0e, 0xd6, 0x21, 0x7f, 0x15, 0x66, - 0x8d, 0x96, 0x58, 0xf1, 0x5a, 0xf4, 0xbe, 0xcc, 0x7b, 0xc9, 0x5f, 0x18, 0x5b, 0x4a, 0xc1, 0x70, - 0x00, 0x9b, 0x7c, 0x02, 0xa6, 0x9b, 0x7e, 0xa7, 0xc3, 0xd7, 0x38, 0xf1, 0x1a, 0x88, 0x48, 0x70, - 0x29, 0x52, 0x81, 0x26, 0x20, 0x98, 0xc2, 0x24, 0x37, 0x80, 0xf8, 0x9b, 0x4c, 0xbd, 0xa2, 0xad, - 0x57, 0xa9, 0x47, 0xa5, 0xc6, 0x71, 0x2e, 0x19, 0x71, 0x73, 0x6b, 0x00, 0x03, 0x33, 0x6a, 0xf1, - 0xfc, 0x80, 0x46, 0x84, 0xf2, 0x74, 0x1e, 0x19, 0xc9, 0xd3, 0xf6, 0x9c, 0x23, 0xc3, 0x93, 0x03, - 0x98, 0x10, 0x01, 0x50, 0xf9, 0x64, 0xba, 0x34, 0x1f, 0x06, 0x88, 0xf7, 0x08, 0x51, 0x8a, 0x92, - 0x13, 0xf9, 0x05, 0x28, 0x6f, 0xaa, 0x57, 0x62, 0x78, 0x7a, 0xcb, 0x91, 0xf7, 0xc5, 0xd4, 0x83, - 0x47, 0xb1, 0xbd, 0x42, 0x03, 0x30, 0x66, 0x49, 0x9e, 0x86, 0xca, 0xf5, 0xf5, 0x9a, 0x1e, 0x85, - 0xe7, 0x79, 0xef, 0x8f, 0xb3, 0x2a, 0x68, 0x02, 0xd8, 0x0c, 0xd3, 0xea, 0x1b, 0x49, 0xba, 0x05, - 0x64, 0x68, 0x63, 0x0c, 0x9b, 0xfb, 0x39, 0x60, 0x63, 0xee, 0x42, 0x0a, 0x5b, 0x96, 0xa3, 0xc6, - 0x20, 0x6f, 0x42, 0x45, 0xee, 0x17, 0x7c, 0x6d, 0xba, 0x78, 0xba, 0xe8, 0x77, 0x8c, 0x49, 0xa0, - 0x49, 0x8f, 0x5f, 0x50, 0xf3, 0xc7, 0x33, 0xe8, 0xb5, 0x7e, 0xa7, 0x33, 0x77, 0x89, 0xaf, 0x9b, - 0xf1, 0x05, 0x75, 0x0c, 0x42, 0x13, 0x8f, 0x3c, 0xaf, 0xfc, 0xd5, 0x1e, 0x4e, 0xdc, 0xd8, 0x6b, - 0x7f, 0x35, 0xad, 0x74, 0x0f, 0x09, 0x90, 0x79, 0xe4, 0x08, 0x47, 0xb1, 0x4d, 0x98, 0x57, 0x1a, - 0xdf, 0xe0, 0x24, 0x99, 0x9b, 0x4b, 0xd8, 0x8e, 0xe6, 0xef, 0x0c, 0xc5, 0xc4, 0x43, 0xa8, 0x90, - 0x4d, 0x28, 0x38, 0x9d, 0xcd, 0xb9, 0x47, 0xf3, 0x50, 0x5d, 0x6b, 0xab, 0x75, 0x39, 0xa2, 0xb8, - 0x53, 0x6b, 0x6d, 0xb5, 0x8e, 0x8c, 0x38, 0x71, 0x61, 0xdc, 0xe9, 0x6c, 0x86, 0x73, 0xf3, 0x7c, - 0xce, 0xe6, 0xc6, 0x24, 0x36, 0x1e, 0xac, 0xd6, 0x43, 0xe4, 0x2c, 0xec, 0x2f, 0x8d, 0xe9, 0x5b, - 0x22, 0x9d, 0x6c, 0xfc, 0x6d, 0x73, 0x02, 0x89, 0xe3, 0xce, 0xad, 0xdc, 0x26, 0x90, 0x54, 0x2f, - 0xce, 0x0d, 0x9d, 0x3e, 0x3d, 0xbd, 0x64, 0xe4, 0x92, 0xa5, 0x2c, 0x99, 0x48, 0x5d, 0x9c, 0x9e, - 0x93, 0x0b, 0x86, 0xfd, 0xe5, 0x8a, 0xb6, 0x82, 0xa6, 0x7c, 0xbd, 0x02, 0x28, 0xba, 0x61, 0xe4, - 0xfa, 0x39, 0x06, 0x85, 0xa7, 0x32, 0x90, 0xf3, 0x98, 0x13, 0x0e, 0x40, 0xc1, 0x8a, 0xf1, 0xf4, - 0xda, 0xae, 0x77, 0x5f, 0x7e, 0xfe, 0xeb, 0xb9, 0x3b, 0x71, 0x09, 0x9e, 0x1c, 0x80, 0x82, 0x15, - 0xb9, 0x2b, 0x06, 0x75, 0x21, 0x8f, 0xbe, 0xae, 0xad, 0xd6, 0x53, 0xfc, 0x92, 0x83, 0xfb, 0x2e, - 0x14, 0xc2, 0xae, 0x2b, 0xd5, 0xa5, 0x11, 0x79, 0x35, 0xd6, 0x56, 0xb2, 0x78, 0x35, 0xd6, 0x56, - 0x90, 0x31, 0x21, 0x5f, 0xb5, 0x00, 0x9c, 0xee, 0xa6, 0x13, 0x86, 0x4e, 0x4b, 0x5b, 0x67, 0x46, - 0x7c, 0x64, 0xa5, 0xa6, 0xe9, 0xa5, 0x58, 0x73, 0xb7, 0xe5, 0x18, 0x8a, 0x06, 0x67, 0xf2, 0x16, - 0x4c, 0x3a, 0xe2, 0x15, 0x4b, 0xe9, 0x81, 0x9f, 0xcf, 0xd3, 0xac, 0x29, 0x09, 0xb8, 0x99, 0x46, - 0x82, 0x50, 0x31, 0x64, 0xbc, 0xa3, 0xc0, 0xa1, 0x5b, 0xee, 0x8e, 0x34, 0x0e, 0x35, 0x46, 0x7e, - 0x67, 0x85, 0x11, 0xcb, 0xe2, 0x2d, 0x41, 0xa8, 0x18, 0x92, 0x5f, 0xb4, 0xe0, 0x5c, 0xd7, 0xf1, - 0x1c, 0x1d, 0x57, 0x99, 0x4f, 0xf4, 0xad, 0x19, 0xa9, 0x19, 0x6b, 0x88, 0x6b, 0x26, 0x23, 0x4c, - 0xf2, 0x25, 0xbb, 0x30, 0xe1, 0xf0, 0xf7, 0x75, 0xe5, 0x51, 0x0c, 0xf3, 0x78, 0xab, 0x37, 0xd5, - 0x06, 0x7c, 0x71, 0x91, 0xaf, 0xf8, 0x4a, 0x6e, 0xe4, 0x37, 0x2c, 0x98, 0x14, 0xce, 0xe1, 0x4c, - 0x21, 0x65, 0xdf, 0xfe, 0xb9, 0x33, 0x78, 0xc9, 0x40, 0x3a, 0xae, 0x4b, 0xf7, 0xa3, 0x0f, 0x6b, - 0xcf, 0x57, 0x51, 0x7a, 0xa8, 0xeb, 0xba, 0x92, 0x8e, 0xa9, 0xbe, 0x5d, 0xe7, 0x7e, 0xe2, 0x15, - 0x1d, 0x53, 0xf5, 0x5d, 0x4b, 0xc1, 0x70, 0x00, 0x7b, 0xfe, 0x13, 0x30, 0x65, 0xca, 0x71, 0x22, - 0xf7, 0xf7, 0x1f, 0x17, 0x00, 0x78, 0x57, 0x89, 0x5c, 0x2c, 0x5d, 0x9e, 0xb8, 0x79, 0xdb, 0x6f, - 0xe5, 0xf4, 0x9a, 0xa7, 0x91, 0x52, 0x05, 0x64, 0x96, 0xe6, 0x6d, 0xbf, 0x85, 0x92, 0x09, 0x69, - 0xc3, 0x78, 0xcf, 0x89, 0xb6, 0xf3, 0xcf, 0xdf, 0x52, 0x12, 0x41, 0xc9, 0xd1, 0x36, 0x72, 0x06, - 0xe4, 0x1d, 0x2b, 0xf6, 0xec, 0x29, 0xe4, 0x91, 0x7b, 0x36, 0x6e, 0xb3, 0x05, 0xe9, 0xcb, 0x93, - 0x4a, 0xc1, 0x9a, 0xf6, 0xf0, 0x99, 0x7f, 0xd7, 0x82, 0x29, 0x13, 0x35, 0xa3, 0x9b, 0x7e, 0xde, - 0xec, 0xa6, 0x3c, 0xdb, 0xc3, 0xec, 0xf1, 0xff, 0x6a, 0x01, 0x60, 0xdf, 0x6b, 0xf4, 0xbb, 0x5d, - 0xa6, 0xb6, 0x6b, 0x2f, 0x7f, 0xeb, 0xd8, 0x5e, 0xfe, 0x63, 0x27, 0xf4, 0xf2, 0x2f, 0x9c, 0xc8, - 0xcb, 0x7f, 0xfc, 0xe4, 0x5e, 0xfe, 0xc5, 0xe1, 0x5e, 0xfe, 0xf6, 0xb7, 0x2c, 0x38, 0x3f, 0xb0, - 0x5f, 0x31, 0x4d, 0x3a, 0xf0, 0xfd, 0x68, 0x88, 0x87, 0x28, 0xc6, 0x20, 0x34, 0xf1, 0xc8, 0x32, - 0xcc, 0xca, 0x67, 0x4a, 0x1a, 0xbd, 0x8e, 0x9b, 0x99, 0x5b, 0x67, 0x23, 0x05, 0xc7, 0x81, 0x1a, - 0xf6, 0xef, 0x58, 0x50, 0x31, 0x22, 0xf2, 0xd9, 0x77, 0x70, 0x37, 0x61, 0x29, 0x46, 0xfc, 0x42, - 0x0b, 0xbf, 0xea, 0x12, 0x30, 0x71, 0x0d, 0xdd, 0x36, 0x92, 0xd8, 0xc7, 0xd7, 0xd0, 0xac, 0x14, - 0x25, 0x54, 0xa4, 0x27, 0xa7, 0x3d, 0xde, 0xe8, 0x05, 0x33, 0x3d, 0x39, 0xed, 0x21, 0x87, 0x70, - 0x76, 0xec, 0x48, 0x21, 0x3d, 0x80, 0x8d, 0x07, 0x61, 0x9c, 0x20, 0x42, 0x01, 0x23, 0x4f, 0x40, - 0x81, 0x7a, 0x2d, 0x69, 0xff, 0xd0, 0xaf, 0xd7, 0x5e, 0xf5, 0x5a, 0xc8, 0xca, 0xed, 0x5b, 0x30, - 0x25, 0xbc, 0x9f, 0x5f, 0xa3, 0x7b, 0xc7, 0x7e, 0x0e, 0x97, 0x8d, 0xf6, 0xd4, 0x73, 0xb8, 0xac, - 0x3a, 0x2b, 0xb7, 0xff, 0x91, 0x05, 0xa9, 0x37, 0x92, 0x8c, 0x1b, 0x18, 0x6b, 0xe8, 0x0d, 0x8c, - 0x69, 0xb5, 0x1f, 0x3b, 0xd4, 0x6a, 0x7f, 0x03, 0x48, 0x97, 0x4d, 0x85, 0xe4, 0x42, 0x5b, 0x48, - 0x3e, 0x25, 0xb1, 0x36, 0x80, 0x81, 0x19, 0xb5, 0xec, 0x7f, 0x28, 0x84, 0x35, 0x5f, 0x4d, 0x3a, - 0xba, 0x01, 0xfa, 0x50, 0xe4, 0xa4, 0xa4, 0xfd, 0x6d, 0x44, 0xdb, 0xf5, 0x60, 0x1e, 0xad, 0xb8, - 0x23, 0xe5, 0x94, 0xe7, 0xdc, 0xec, 0x3f, 0x10, 0xb2, 0x9a, 0xcf, 0x2a, 0x1d, 0x2d, 0x6b, 0x37, - 0x29, 0xeb, 0xf5, 0xbc, 0xd6, 0xca, 0x6c, 0x19, 0xc9, 0x02, 0x40, 0x8f, 0x06, 0x4d, 0xea, 0x45, - 0x2a, 0x2e, 0xa9, 0x28, 0x23, 0x64, 0x75, 0x29, 0x1a, 0x18, 0xf6, 0x37, 0xd9, 0x04, 0x8a, 0x1f, - 0x8a, 0x26, 0x57, 0xd2, 0xae, 0xae, 0xe9, 0xc9, 0xa1, 0x3d, 0x5d, 0x8d, 0x68, 0x95, 0xb1, 0x23, - 0xa2, 0x55, 0x9e, 0x81, 0xc9, 0xc0, 0xef, 0xd0, 0x5a, 0xe0, 0xa5, 0x7d, 0x74, 0x90, 0x15, 0xe3, - 0x4d, 0x54, 0x70, 0xfb, 0xd7, 0x2c, 0x98, 0x4d, 0x87, 0xd3, 0xe5, 0xee, 0x7f, 0x6b, 0xc6, 0xfc, - 0x17, 0x4e, 0x1e, 0xf3, 0x6f, 0x7f, 0xaf, 0x08, 0xb3, 0xe9, 0x07, 0xec, 0x18, 0x67, 0x97, 0x1b, - 0xdb, 0x52, 0xab, 0xbf, 0xb0, 0xb2, 0x09, 0x98, 0x1e, 0x2f, 0x63, 0x43, 0xc7, 0xcb, 0x35, 0x28, - 0xfb, 0x3d, 0x75, 0xe0, 0x17, 0xc2, 0x5d, 0x51, 0xc6, 0x9a, 0x5b, 0x0a, 0xf0, 0xde, 0x7e, 0xf5, - 0x42, 0x2c, 0x80, 0x2e, 0xc6, 0xb8, 0x2a, 0xf9, 0x19, 0x65, 0xa9, 0x18, 0x4f, 0x64, 0xd1, 0xd1, - 0x96, 0x8a, 0x99, 0xb8, 0xfe, 0x30, 0x63, 0x45, 0xf1, 0x24, 0xd9, 0x3c, 0x26, 0x72, 0xcc, 0xe6, - 0x71, 0x07, 0xca, 0xd2, 0xb6, 0x7a, 0xaa, 0x2c, 0x16, 0x9c, 0xf0, 0x6d, 0x45, 0x00, 0x63, 0x5a, - 0xa9, 0x34, 0x21, 0xa5, 0x5c, 0xd3, 0x84, 0xbc, 0x0c, 0x93, 0x9b, 0x4e, 0x73, 0xc7, 0xdf, 0xda, - 0xe2, 0xfa, 0x79, 0xb9, 0xfe, 0x21, 0xd5, 0x70, 0x75, 0x51, 0x9c, 0x31, 0xa4, 0x54, 0x0d, 0xa6, - 0x15, 0x50, 0xe5, 0x8e, 0xac, 0xcc, 0xbe, 0x5a, 0x2b, 0xd0, 0x8e, 0xca, 0x21, 0x1a, 0x58, 0xe4, - 0x15, 0xed, 0x7f, 0x56, 0x89, 0x83, 0x1f, 0xb4, 0xef, 0xd9, 0x21, 0xc1, 0x0f, 0xd2, 0xbd, 0xf6, - 0x1d, 0x36, 0xd5, 0x22, 0xb7, 0xb9, 0xe3, 0x7a, 0x22, 0xd9, 0x03, 0x9b, 0xff, 0xcf, 0xc0, 0x24, - 0x95, 0xcf, 0x36, 0x8b, 0xcb, 0x10, 0xdd, 0xfd, 0xea, 0xb5, 0x66, 0x05, 0x27, 0x35, 0x98, 0x51, - 0x57, 0xc0, 0xea, 0x06, 0x4b, 0x24, 0xa9, 0xd1, 0x16, 0xf3, 0xe5, 0x24, 0x18, 0xd3, 0xf8, 0xf6, - 0x17, 0xa1, 0x62, 0xa8, 0x56, 0x5c, 0x0b, 0xb9, 0xef, 0x34, 0xa3, 0xf4, 0xee, 0x7d, 0x95, 0x15, - 0xa2, 0x80, 0xf1, 0x8b, 0x36, 0x11, 0xb3, 0x96, 0xda, 0xbd, 0x65, 0xa4, 0x9a, 0x84, 0x32, 0x62, - 0x01, 0x6d, 0xd3, 0xfb, 0xea, 0xa5, 0x0c, 0x45, 0x0c, 0x59, 0x21, 0x0a, 0x98, 0xfd, 0x2c, 0x94, - 0x54, 0x2a, 0x31, 0x9e, 0x8f, 0x47, 0x5d, 0x02, 0x99, 0xf9, 0x78, 0xfc, 0x20, 0x42, 0x0e, 0xb1, - 0xdf, 0x80, 0x92, 0xca, 0x78, 0x76, 0x34, 0x36, 0xdb, 0x50, 0x43, 0xcf, 0xbd, 0xee, 0x87, 0x91, - 0x4a, 0xd3, 0x26, 0xee, 0xa9, 0x6f, 0xae, 0xf0, 0x32, 0xd4, 0x50, 0xfb, 0xcf, 0x2c, 0xa8, 0x6c, - 0x6c, 0xac, 0x6a, 0xf3, 0x15, 0xc2, 0xc3, 0xa1, 0x68, 0xa1, 0xda, 0x56, 0x44, 0x4d, 0x87, 0x18, - 0xb1, 0xb6, 0xcc, 0x1f, 0xec, 0x57, 0x1f, 0x6e, 0x64, 0x62, 0xe0, 0x90, 0x9a, 0x64, 0x05, 0x2e, - 0x98, 0x10, 0x99, 0x3e, 0x43, 0xee, 0xf4, 0xfc, 0x9d, 0xef, 0xc6, 0x20, 0x18, 0xb3, 0xea, 0xa4, - 0x49, 0x49, 0xa5, 0xd5, 0x7c, 0x32, 0xbc, 0x31, 0x08, 0xc6, 0xac, 0x3a, 0xf6, 0xf3, 0x30, 0x93, - 0xf2, 0xd4, 0x38, 0x46, 0xda, 0xa2, 0xdf, 0x2d, 0xc0, 0x94, 0x79, 0x61, 0x7f, 0x8c, 0x5d, 0xf8, - 0xf8, 0xca, 0x4d, 0xc6, 0x25, 0x7b, 0xe1, 0x84, 0x97, 0xec, 0xa6, 0x57, 0xc3, 0xf8, 0xd9, 0x7a, - 0x35, 0x14, 0xf3, 0xf1, 0x6a, 0x30, 0xbc, 0x6f, 0x26, 0x1e, 0x9c, 0xf7, 0xcd, 0x6f, 0x17, 0x61, - 0x3a, 0x99, 0x07, 0xf7, 0x18, 0x3d, 0xf9, 0xec, 0x40, 0x4f, 0x9e, 0xf0, 0x56, 0xaf, 0x30, 0xea, - 0xad, 0xde, 0xf8, 0xa8, 0xb7, 0x7a, 0xc5, 0x53, 0xdc, 0xea, 0x0d, 0xde, 0xc9, 0x4d, 0x1c, 0xfb, - 0x4e, 0xee, 0x93, 0x7a, 0xa3, 0x98, 0x4c, 0x38, 0xb2, 0xc5, 0x9b, 0x05, 0x49, 0x76, 0xc3, 0x92, - 0xdf, 0xca, 0x74, 0xb0, 0x2e, 0x1d, 0xa1, 0x10, 0x04, 0x99, 0x7e, 0xc5, 0x27, 0x77, 0x1c, 0x78, - 0xf8, 0x04, 0x3e, 0xc5, 0x2f, 0x42, 0x45, 0x8e, 0x27, 0x7e, 0x84, 0x84, 0xe4, 0xf1, 0xb3, 0x11, - 0x83, 0xd0, 0xc4, 0x63, 0x03, 0xa3, 0x17, 0x4f, 0x10, 0x7e, 0xbf, 0x5c, 0x49, 0xde, 0x2f, 0xaf, - 0x27, 0xc1, 0x98, 0xc6, 0xb7, 0xbf, 0x00, 0x97, 0x32, 0x0d, 0x89, 0xfc, 0x12, 0x87, 0x9f, 0x6e, - 0x68, 0x4b, 0x22, 0x18, 0x62, 0xa4, 0x9e, 0xc7, 0x99, 0xbf, 0x33, 0x14, 0x13, 0x0f, 0xa1, 0x62, - 0xff, 0x56, 0x01, 0xa6, 0x93, 0xcf, 0x45, 0x93, 0x7b, 0xfa, 0xda, 0x21, 0x97, 0x1b, 0x0f, 0x41, - 0xd6, 0xc8, 0xad, 0x3a, 0xf4, 0xba, 0xf2, 0x1e, 0x1f, 0x5f, 0x9b, 0x3a, 0xd1, 0xeb, 0xd9, 0x31, - 0x96, 0xf7, 0x84, 0x92, 0x1d, 0x7f, 0x74, 0x39, 0x0e, 0xc3, 0x96, 0xd6, 0xa8, 0xdc, 0xb9, 0xc7, - 0xe1, 0xc4, 0x9a, 0x15, 0x1a, 0x6c, 0xd9, 0xde, 0xb2, 0x4b, 0x03, 0x77, 0xcb, 0xa5, 0x2d, 0x99, - 0x77, 0x9f, 0xaf, 0xdc, 0x6f, 0xc8, 0x32, 0xd4, 0x50, 0xfb, 0x9d, 0x31, 0x28, 0xf3, 0xac, 0x71, - 0xd7, 0x02, 0xbf, 0xcb, 0x1f, 0x12, 0x0d, 0x8d, 0x93, 0xbf, 0xec, 0xb6, 0x1b, 0xa3, 0xbe, 0x0d, - 0x1c, 0x53, 0x94, 0x41, 0x1b, 0x46, 0x09, 0x26, 0x38, 0x92, 0x1e, 0x94, 0xb6, 0x64, 0x96, 0x6b, - 0xd9, 0x77, 0x23, 0x66, 0x6a, 0x55, 0x39, 0xb3, 0x45, 0x13, 0xa8, 0x7f, 0xa8, 0xb9, 0xd8, 0x0e, - 0xcc, 0xa4, 0xd2, 0xfe, 0xe4, 0x9e, 0x1b, 0xfb, 0x7f, 0x8c, 0x43, 0x59, 0x47, 0x0b, 0x92, 0x8f, - 0x27, 0xcc, 0xb0, 0xb1, 0x56, 0x2e, 0xed, 0xa7, 0xec, 0x24, 0xa4, 0x91, 0x53, 0x26, 0xd5, 0x27, - 0xa0, 0xd0, 0x0f, 0x3a, 0x69, 0x3b, 0xcb, 0x6d, 0x5c, 0x45, 0x56, 0x6e, 0x46, 0x38, 0x16, 0x1e, - 0x68, 0x84, 0x23, 0xdb, 0x25, 0x37, 0xfd, 0xd6, 0x5e, 0xfa, 0x55, 0xbc, 0xba, 0xdf, 0xda, 0x43, - 0x0e, 0x21, 0xaf, 0xc0, 0xb4, 0x0c, 0xdb, 0x54, 0x4a, 0x4c, 0x91, 0xeb, 0xa9, 0xda, 0xfd, 0x66, - 0x23, 0x01, 0xc5, 0x14, 0x36, 0xdb, 0x65, 0xd9, 0xb1, 0x81, 0x67, 0x3c, 0x9f, 0x48, 0xde, 0xd5, - 0xdf, 0x68, 0xdc, 0xba, 0xc9, 0xcd, 0xc1, 0x1a, 0x23, 0x11, 0x19, 0x3a, 0x79, 0x64, 0x64, 0xe8, - 0xb2, 0xa0, 0xcd, 0xa4, 0xe5, 0x3b, 0xca, 0x54, 0xfd, 0x8a, 0xa2, 0xcb, 0xca, 0x0e, 0x3d, 0xbb, - 0xe8, 0x9a, 0x59, 0x31, 0xb4, 0xe5, 0xf7, 0x2f, 0x86, 0xd6, 0xbe, 0x0d, 0x33, 0xa9, 0xfe, 0x53, - 0x66, 0x3a, 0x2b, 0xdb, 0x4c, 0x77, 0xbc, 0x77, 0xf5, 0xfe, 0xa9, 0x05, 0xe7, 0x07, 0x56, 0xa4, - 0xe3, 0x06, 0x33, 0xa7, 0xf7, 0xc6, 0xb1, 0xd3, 0xef, 0x8d, 0x85, 0x93, 0xed, 0x8d, 0xf5, 0xcd, - 0xef, 0xff, 0xe8, 0xf2, 0x43, 0x3f, 0xf8, 0xd1, 0xe5, 0x87, 0xfe, 0xf0, 0x47, 0x97, 0x1f, 0x7a, - 0xe7, 0xe0, 0xb2, 0xf5, 0xfd, 0x83, 0xcb, 0xd6, 0x0f, 0x0e, 0x2e, 0x5b, 0x7f, 0x78, 0x70, 0xd9, - 0xfa, 0x4f, 0x07, 0x97, 0xad, 0x6f, 0xfd, 0xc9, 0xe5, 0x87, 0x3e, 0xfd, 0xc9, 0xb8, 0xa7, 0x16, - 0x55, 0x4f, 0xf1, 0x1f, 0x1f, 0x51, 0xfd, 0xb2, 0xd8, 0xdb, 0x69, 0x2f, 0xb2, 0x9e, 0x5a, 0xd4, - 0x25, 0xaa, 0xa7, 0xfe, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd3, 0x74, 0x04, 0x71, 0x21, 0xab, - 0x00, 0x00, + // 8817 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x6c, 0x64, 0xd7, + 0x75, 0x98, 0x1e, 0x87, 0x43, 0xce, 0x9c, 0xe1, 0x92, 0xdc, 0xbb, 0xbb, 0x12, 0x45, 0x49, 0x3b, + 0xca, 0x53, 0xaa, 0xae, 0x62, 0x99, 0xb4, 0xf5, 0x91, 0xca, 0x96, 0xab, 0x76, 0x86, 0xdc, 0xd5, + 0x72, 0x45, 0xee, 0x52, 0x67, 0xb8, 0xda, 0xf8, 0x43, 0x89, 0x1f, 0x67, 0x2e, 0x87, 0x6f, 0x39, + 0xf3, 0xde, 0xf8, 0xbd, 0x37, 0xdc, 0xa5, 0x2c, 0xc4, 0xb2, 0x0d, 0x39, 0x8e, 0x6b, 0x23, 0x6e, + 0x13, 0xa3, 0xe8, 0x07, 0x0a, 0x37, 0x08, 0x90, 0xb6, 0xe9, 0x8f, 0x22, 0x70, 0xd1, 0xfe, 0x08, + 0xd0, 0xa0, 0x6e, 0x0a, 0x07, 0x68, 0x0a, 0xe7, 0x47, 0xeb, 0xb4, 0x40, 0x98, 0x9a, 0xe9, 0x9f, + 0x06, 0x2d, 0x8c, 0x14, 0x2e, 0x82, 0xea, 0x47, 0x51, 0xdc, 0xcf, 0x77, 0xdf, 0x9b, 0x37, 0xfc, + 0x9a, 0xc7, 0x95, 0xd2, 0xe6, 0xdf, 0xcc, 0x3d, 0xe7, 0x9e, 0x73, 0xde, 0xfd, 0x3c, 0xf7, 0xdc, + 0x73, 0xce, 0x85, 0xd5, 0xb6, 0x1b, 0x6d, 0xf7, 0x37, 0x17, 0x9a, 0x7e, 0x77, 0xd1, 0x09, 0xda, + 0x7e, 0x2f, 0xf0, 0xef, 0xf2, 0x1f, 0x1f, 0x0e, 0xfc, 0x4e, 0xc7, 0xef, 0x47, 0xe1, 0x62, 0x6f, + 0xa7, 0xbd, 0xe8, 0xf4, 0xdc, 0x70, 0x51, 0x97, 0xec, 0x7e, 0xd4, 0xe9, 0xf4, 0xb6, 0x9d, 0x8f, + 0x2e, 0xb6, 0xa9, 0x47, 0x03, 0x27, 0xa2, 0xad, 0x85, 0x5e, 0xe0, 0x47, 0x3e, 0xf9, 0x44, 0x4c, + 0x6d, 0x41, 0x51, 0xe3, 0x3f, 0x7e, 0x4e, 0xd5, 0x5d, 0xe8, 0xed, 0xb4, 0x17, 0x18, 0xb5, 0x05, + 0x5d, 0xa2, 0xa8, 0xcd, 0x7f, 0xd8, 0x90, 0xa5, 0xed, 0xb7, 0xfd, 0x45, 0x4e, 0x74, 0xb3, 0xbf, + 0xc5, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x60, 0x36, 0xff, 0xd4, 0xce, 0x4b, 0xe1, 0x82, 0xeb, 0x33, + 0xd9, 0x16, 0x37, 0x9d, 0xa8, 0xb9, 0xbd, 0xb8, 0x3b, 0x20, 0xd1, 0xbc, 0x6d, 0x20, 0x35, 0xfd, + 0x80, 0x66, 0xe1, 0xbc, 0x10, 0xe3, 0x74, 0x9d, 0xe6, 0xb6, 0xeb, 0xd1, 0x60, 0x2f, 0xfe, 0xea, + 0x2e, 0x8d, 0x9c, 0xac, 0x5a, 0x8b, 0xc3, 0x6a, 0x05, 0x7d, 0x2f, 0x72, 0xbb, 0x74, 0xa0, 0xc2, + 0x4f, 0x1f, 0x55, 0x21, 0x6c, 0x6e, 0xd3, 0xae, 0x33, 0x50, 0xef, 0xf9, 0x61, 0xf5, 0xfa, 0x91, + 0xdb, 0x59, 0x74, 0xbd, 0x28, 0x8c, 0x82, 0x74, 0x25, 0xfb, 0x47, 0x05, 0x28, 0xd7, 0x56, 0xeb, + 0x8d, 0xc8, 0x89, 0xfa, 0x21, 0xf9, 0x8a, 0x05, 0x53, 0x1d, 0xdf, 0x69, 0xd5, 0x9d, 0x8e, 0xe3, + 0x35, 0x69, 0x30, 0x67, 0x3d, 0x69, 0x5d, 0xa9, 0x3c, 0xb7, 0xba, 0x30, 0x4a, 0x7f, 0x2d, 0xd4, + 0xee, 0x85, 0x48, 0x43, 0xbf, 0x1f, 0x34, 0x29, 0xd2, 0xad, 0xfa, 0xc5, 0xef, 0xed, 0x57, 0x1f, + 0x3a, 0xd8, 0xaf, 0x4e, 0xad, 0x1a, 0x9c, 0x30, 0xc1, 0x97, 0x7c, 0xcb, 0x82, 0xf3, 0x4d, 0xc7, + 0x73, 0x82, 0xbd, 0x0d, 0x27, 0x68, 0xd3, 0xe8, 0xd5, 0xc0, 0xef, 0xf7, 0xe6, 0xc6, 0xce, 0x40, + 0x9a, 0x47, 0xa5, 0x34, 0xe7, 0x97, 0xd2, 0xec, 0x70, 0x50, 0x02, 0x2e, 0x57, 0x18, 0x39, 0x9b, + 0x1d, 0x6a, 0xca, 0x55, 0x38, 0x4b, 0xb9, 0x1a, 0x69, 0x76, 0x38, 0x28, 0x01, 0x79, 0x06, 0x26, + 0x5d, 0xaf, 0x1d, 0xd0, 0x30, 0x9c, 0x1b, 0x7f, 0xd2, 0xba, 0x52, 0xae, 0xcf, 0xc8, 0xea, 0x93, + 0x2b, 0xa2, 0x18, 0x15, 0xdc, 0xfe, 0xcd, 0x02, 0x9c, 0xaf, 0xad, 0xd6, 0x37, 0x02, 0x67, 0x6b, + 0xcb, 0x6d, 0xa2, 0xdf, 0x8f, 0x5c, 0xaf, 0x6d, 0x12, 0xb0, 0x0e, 0x27, 0x40, 0x5e, 0x84, 0x4a, + 0x48, 0x83, 0x5d, 0xb7, 0x49, 0xd7, 0xfd, 0x20, 0xe2, 0x9d, 0x52, 0xac, 0x5f, 0x90, 0xe8, 0x95, + 0x46, 0x0c, 0x42, 0x13, 0x8f, 0x55, 0x0b, 0x7c, 0x3f, 0x92, 0x70, 0xde, 0x66, 0xe5, 0xb8, 0x1a, + 0xc6, 0x20, 0x34, 0xf1, 0xc8, 0x32, 0xcc, 0x3a, 0x9e, 0xe7, 0x47, 0x4e, 0xe4, 0xfa, 0xde, 0x7a, + 0x40, 0xb7, 0xdc, 0xfb, 0xf2, 0x13, 0xe7, 0x64, 0xdd, 0xd9, 0x5a, 0x0a, 0x8e, 0x03, 0x35, 0xc8, + 0x37, 0x2d, 0x98, 0x0d, 0x23, 0xb7, 0xb9, 0xe3, 0x7a, 0x34, 0x0c, 0x97, 0x7c, 0x6f, 0xcb, 0x6d, + 0xcf, 0x15, 0x79, 0xb7, 0xdd, 0x1c, 0xad, 0xdb, 0x1a, 0x29, 0xaa, 0xf5, 0x8b, 0x4c, 0xa4, 0x74, + 0x29, 0x0e, 0x70, 0x27, 0x1f, 0x82, 0xb2, 0x6c, 0x51, 0x1a, 0xce, 0x4d, 0x3c, 0x59, 0xb8, 0x52, + 0xae, 0x9f, 0x3b, 0xd8, 0xaf, 0x96, 0x57, 0x54, 0x21, 0xc6, 0x70, 0x7b, 0x19, 0xe6, 0x6a, 0xdd, + 0x4d, 0x27, 0x0c, 0x9d, 0x96, 0x1f, 0xa4, 0xba, 0xee, 0x0a, 0x94, 0xba, 0x4e, 0xaf, 0xe7, 0x7a, + 0x6d, 0xd6, 0x77, 0x8c, 0xce, 0xd4, 0xc1, 0x7e, 0xb5, 0xb4, 0x26, 0xcb, 0x50, 0x43, 0xed, 0xff, + 0x34, 0x06, 0x95, 0x9a, 0xe7, 0x74, 0xf6, 0x42, 0x37, 0xc4, 0xbe, 0x47, 0x3e, 0x0b, 0x25, 0xb6, + 0x6a, 0xb5, 0x9c, 0xc8, 0x91, 0x33, 0xfd, 0x23, 0x0b, 0x62, 0x11, 0x59, 0x30, 0x17, 0x91, 0xf8, + 0xf3, 0x19, 0xf6, 0xc2, 0xee, 0x47, 0x17, 0x6e, 0x6d, 0xde, 0xa5, 0xcd, 0x68, 0x8d, 0x46, 0x4e, + 0x9d, 0xc8, 0x5e, 0x80, 0xb8, 0x0c, 0x35, 0x55, 0xe2, 0xc3, 0x78, 0xd8, 0xa3, 0x4d, 0x39, 0x73, + 0xd7, 0x46, 0x9c, 0x21, 0xb1, 0xe8, 0x8d, 0x1e, 0x6d, 0xd6, 0xa7, 0x24, 0xeb, 0x71, 0xf6, 0x0f, + 0x39, 0x23, 0x72, 0x0f, 0x26, 0x42, 0xbe, 0x96, 0xc9, 0x49, 0x79, 0x2b, 0x3f, 0x96, 0x9c, 0x6c, + 0x7d, 0x5a, 0x32, 0x9d, 0x10, 0xff, 0x51, 0xb2, 0xb3, 0xff, 0xb3, 0x05, 0x17, 0x0c, 0xec, 0x5a, + 0xd0, 0xee, 0x77, 0xa9, 0x17, 0x91, 0x27, 0x61, 0xdc, 0x73, 0xba, 0x54, 0xce, 0x2a, 0x2d, 0xf2, + 0x4d, 0xa7, 0x4b, 0x91, 0x43, 0xc8, 0x53, 0x50, 0xdc, 0x75, 0x3a, 0x7d, 0xca, 0x1b, 0xa9, 0x5c, + 0x3f, 0x27, 0x51, 0x8a, 0x6f, 0xb0, 0x42, 0x14, 0x30, 0xf2, 0x36, 0x94, 0xf9, 0x8f, 0x6b, 0x81, + 0xdf, 0xcd, 0xe9, 0xd3, 0xa4, 0x84, 0x6f, 0x28, 0xb2, 0x62, 0xf8, 0xe9, 0xbf, 0x18, 0x33, 0xb4, + 0xff, 0xc8, 0x82, 0x19, 0xe3, 0xe3, 0x56, 0xdd, 0x30, 0x22, 0x9f, 0x19, 0x18, 0x3c, 0x0b, 0xc7, + 0x1b, 0x3c, 0xac, 0x36, 0x1f, 0x3a, 0xb3, 0xf2, 0x4b, 0x4b, 0xaa, 0xc4, 0x18, 0x38, 0x1e, 0x14, + 0xdd, 0x88, 0x76, 0xc3, 0xb9, 0xb1, 0x27, 0x0b, 0x57, 0x2a, 0xcf, 0xad, 0xe4, 0xd6, 0x8d, 0x71, + 0xfb, 0xae, 0x30, 0xfa, 0x28, 0xd8, 0xd8, 0xdf, 0x29, 0x24, 0xba, 0x6f, 0x4d, 0xc9, 0xf1, 0xae, + 0x05, 0x13, 0x1d, 0x67, 0x93, 0x76, 0xc4, 0xdc, 0xaa, 0x3c, 0xf7, 0x66, 0x6e, 0x92, 0x28, 0x1e, + 0x0b, 0xab, 0x9c, 0xfe, 0x55, 0x2f, 0x0a, 0xf6, 0xe2, 0xe1, 0x25, 0x0a, 0x51, 0x32, 0x27, 0x7f, + 0xc7, 0x82, 0x4a, 0xbc, 0xaa, 0xa9, 0x66, 0xd9, 0xcc, 0x5f, 0x98, 0x78, 0x31, 0x95, 0x12, 0xe9, + 0x25, 0xda, 0x80, 0xa0, 0x29, 0xcb, 0xfc, 0xc7, 0xa0, 0x62, 0x7c, 0x02, 0x99, 0x85, 0xc2, 0x0e, + 0xdd, 0x13, 0x03, 0x1e, 0xd9, 0x4f, 0x72, 0x31, 0x31, 0xc2, 0xe5, 0x90, 0xfe, 0xf8, 0xd8, 0x4b, + 0xd6, 0xfc, 0x2b, 0x30, 0x9b, 0x66, 0x78, 0x92, 0xfa, 0xf6, 0x3f, 0x2b, 0x26, 0x06, 0x26, 0x5b, + 0x08, 0x88, 0x0f, 0x93, 0x5d, 0x1a, 0x05, 0x6e, 0x53, 0x75, 0xd9, 0xf2, 0x68, 0xad, 0xb4, 0xc6, + 0x89, 0xc5, 0x1b, 0xa2, 0xf8, 0x1f, 0xa2, 0xe2, 0x42, 0xb6, 0x61, 0xdc, 0x09, 0xda, 0xaa, 0x4f, + 0xae, 0xe5, 0x33, 0x2d, 0xe3, 0xa5, 0xa2, 0x16, 0xb4, 0x43, 0xe4, 0x1c, 0xc8, 0x22, 0x94, 0x23, + 0x1a, 0x74, 0x5d, 0xcf, 0x89, 0xc4, 0x0e, 0x5a, 0xaa, 0x9f, 0x97, 0x68, 0xe5, 0x0d, 0x05, 0xc0, + 0x18, 0x87, 0x74, 0x60, 0xa2, 0x15, 0xec, 0x61, 0xdf, 0x9b, 0x1b, 0xcf, 0xa3, 0x29, 0x96, 0x39, + 0xad, 0x78, 0x90, 0x8a, 0xff, 0x28, 0x79, 0x90, 0x5f, 0xb3, 0xe0, 0x62, 0x97, 0x3a, 0x61, 0x3f, + 0xa0, 0xec, 0x13, 0x90, 0x46, 0xd4, 0x63, 0x1d, 0x3b, 0x57, 0xe4, 0xcc, 0x71, 0xd4, 0x7e, 0x18, + 0xa4, 0x5c, 0x7f, 0x5c, 0x8a, 0x72, 0x31, 0x0b, 0x8a, 0x99, 0xd2, 0x90, 0xb7, 0xa1, 0x12, 0x45, + 0x9d, 0x46, 0xc4, 0xf4, 0xe0, 0xf6, 0xde, 0xdc, 0x04, 0x5f, 0xbc, 0x46, 0x5c, 0x61, 0x36, 0x36, + 0x56, 0x15, 0xc1, 0xfa, 0x0c, 0x9b, 0x2d, 0x46, 0x01, 0x9a, 0xec, 0xec, 0x7f, 0x59, 0x84, 0xf3, + 0x03, 0xdb, 0x0a, 0x79, 0x01, 0x8a, 0xbd, 0x6d, 0x27, 0x54, 0xfb, 0xc4, 0x65, 0xb5, 0x48, 0xad, + 0xb3, 0xc2, 0xf7, 0xf6, 0xab, 0xe7, 0x54, 0x15, 0x5e, 0x80, 0x02, 0x99, 0x69, 0x6d, 0x5d, 0x1a, + 0x86, 0x4e, 0x5b, 0x6d, 0x1e, 0xc6, 0x20, 0xe5, 0xc5, 0xa8, 0xe0, 0xe4, 0x17, 0x2c, 0x38, 0x27, + 0x06, 0x2c, 0xd2, 0xb0, 0xdf, 0x89, 0xd8, 0x06, 0xc9, 0x3a, 0xe5, 0x46, 0x1e, 0x93, 0x43, 0x90, + 0xac, 0x5f, 0x92, 0xdc, 0xcf, 0x99, 0xa5, 0x21, 0x26, 0xf9, 0x92, 0x3b, 0x50, 0x0e, 0x23, 0x27, + 0x88, 0x68, 0xab, 0x16, 0x71, 0x55, 0xae, 0xf2, 0xdc, 0x4f, 0x1d, 0x6f, 0xe7, 0xd8, 0x70, 0xbb, + 0x54, 0xec, 0x52, 0x0d, 0x45, 0x00, 0x63, 0x5a, 0xe4, 0x6d, 0x80, 0xa0, 0xef, 0x35, 0xfa, 0xdd, + 0xae, 0x13, 0xec, 0x49, 0xed, 0xee, 0xfa, 0x68, 0x9f, 0x87, 0x9a, 0x5e, 0xac, 0xe8, 0xc4, 0x65, + 0x68, 0xf0, 0x23, 0x5f, 0xb4, 0xe0, 0x9c, 0x98, 0x07, 0x4a, 0x82, 0x89, 0x9c, 0x25, 0x38, 0xcf, + 0x9a, 0x76, 0xd9, 0x64, 0x81, 0x49, 0x8e, 0xe4, 0x4d, 0xa8, 0x34, 0xfd, 0x6e, 0xaf, 0x43, 0x45, + 0xe3, 0x4e, 0x9e, 0xb8, 0x71, 0xf9, 0xd0, 0x5d, 0x8a, 0x49, 0xa0, 0x49, 0xcf, 0xfe, 0x0f, 0x49, + 0x1d, 0x47, 0x0d, 0x69, 0xf2, 0x69, 0x78, 0x34, 0xec, 0x37, 0x9b, 0x34, 0x0c, 0xb7, 0xfa, 0x1d, + 0xec, 0x7b, 0xd7, 0xdd, 0x30, 0xf2, 0x83, 0xbd, 0x55, 0xb7, 0xeb, 0x46, 0x7c, 0x40, 0x17, 0xeb, + 0x4f, 0x1c, 0xec, 0x57, 0x1f, 0x6d, 0x0c, 0x43, 0xc2, 0xe1, 0xf5, 0x89, 0x03, 0x8f, 0xf5, 0xbd, + 0xe1, 0xe4, 0xc5, 0xf1, 0xa3, 0x7a, 0xb0, 0x5f, 0x7d, 0xec, 0xf6, 0x70, 0x34, 0x3c, 0x8c, 0x86, + 0xfd, 0x27, 0x16, 0xdb, 0x86, 0xc4, 0x77, 0x6d, 0xd0, 0x6e, 0xaf, 0xc3, 0x96, 0xce, 0xb3, 0x57, + 0x8e, 0xa3, 0x84, 0x72, 0x8c, 0xf9, 0xec, 0xe5, 0x4a, 0xfe, 0x61, 0x1a, 0xb2, 0xfd, 0xdf, 0x2c, + 0xb8, 0x98, 0x46, 0x7e, 0x00, 0x0a, 0x5d, 0x98, 0x54, 0xe8, 0x6e, 0xe6, 0xfb, 0xb5, 0x43, 0xb4, + 0xba, 0x5f, 0x34, 0x06, 0xac, 0x42, 0x45, 0xba, 0x45, 0x5e, 0x82, 0xa9, 0x48, 0xfe, 0xbd, 0x19, + 0x2b, 0xe7, 0xda, 0x30, 0xb1, 0x61, 0xc0, 0x30, 0x81, 0xc9, 0x6a, 0x36, 0x3b, 0xfd, 0x30, 0xa2, + 0x41, 0xa3, 0xe9, 0xf7, 0xc4, 0xb2, 0x5b, 0x8a, 0x6b, 0x2e, 0x19, 0x30, 0x4c, 0x60, 0xda, 0x7f, + 0xa3, 0x38, 0xd8, 0xee, 0xff, 0xaf, 0xeb, 0x2b, 0xb1, 0xfa, 0x51, 0x78, 0x3f, 0xd5, 0x8f, 0xf1, + 0x0f, 0x94, 0xfa, 0xf1, 0x25, 0x8b, 0x69, 0x71, 0x62, 0x00, 0x84, 0x52, 0x35, 0x7a, 0x3d, 0xdf, + 0xe9, 0x80, 0x74, 0xcb, 0x54, 0x0c, 0x25, 0x2f, 0x8c, 0xd9, 0xda, 0xff, 0x68, 0x1c, 0xa6, 0x6a, + 0x5e, 0xe4, 0xd6, 0xb6, 0xb6, 0x5c, 0xcf, 0x8d, 0xf6, 0xc8, 0xd7, 0xc7, 0x60, 0xb1, 0x17, 0xd0, + 0x2d, 0x1a, 0x04, 0xb4, 0xb5, 0xdc, 0x0f, 0x5c, 0xaf, 0xdd, 0x68, 0x6e, 0xd3, 0x56, 0xbf, 0xe3, + 0x7a, 0xed, 0x95, 0xb6, 0xe7, 0xeb, 0xe2, 0xab, 0xf7, 0x69, 0xb3, 0xcf, 0xdb, 0x55, 0xac, 0x12, + 0xdd, 0xd1, 0x64, 0x5f, 0x3f, 0x19, 0xd3, 0xfa, 0xf3, 0x07, 0xfb, 0xd5, 0xc5, 0x13, 0x56, 0xc2, + 0x93, 0x7e, 0x1a, 0xf9, 0xea, 0x18, 0x2c, 0x04, 0xf4, 0x73, 0x7d, 0xf7, 0xf8, 0xad, 0x21, 0x96, + 0xf1, 0xce, 0x88, 0xdb, 0xfd, 0x89, 0x78, 0xd6, 0x9f, 0x3b, 0xd8, 0xaf, 0x9e, 0xb0, 0x0e, 0x9e, + 0xf0, 0xbb, 0xec, 0x75, 0xa8, 0xd4, 0x7a, 0x6e, 0xe8, 0xde, 0x47, 0xbf, 0x1f, 0xd1, 0x63, 0x18, + 0x34, 0xaa, 0x50, 0x0c, 0xfa, 0x1d, 0x2a, 0x16, 0x98, 0x72, 0xbd, 0xcc, 0x96, 0x65, 0x64, 0x05, + 0x28, 0xca, 0xed, 0x2f, 0xb1, 0x2d, 0x88, 0x93, 0x4c, 0x99, 0xb2, 0xee, 0x42, 0x31, 0x60, 0x4c, + 0xe4, 0xc8, 0x1a, 0xf5, 0xd4, 0x1f, 0x4b, 0x2d, 0x85, 0x60, 0x3f, 0x51, 0xb0, 0xb0, 0xbf, 0x3b, + 0x06, 0x97, 0x6a, 0xbd, 0xde, 0x1a, 0x0d, 0xb7, 0x53, 0x52, 0xfc, 0x92, 0x05, 0xd3, 0xbb, 0x6e, + 0x10, 0xf5, 0x9d, 0x8e, 0xb2, 0x56, 0x0a, 0x79, 0x1a, 0xa3, 0xca, 0xc3, 0xb9, 0xbd, 0x91, 0x20, + 0x5d, 0x27, 0x07, 0xfb, 0xd5, 0xe9, 0x64, 0x19, 0xa6, 0xd8, 0x93, 0xbf, 0x6d, 0xc1, 0xac, 0x2c, + 0xba, 0xe9, 0xb7, 0xa8, 0x69, 0x0d, 0xbf, 0x9d, 0xa7, 0x4c, 0x9a, 0xb8, 0xb0, 0x62, 0xa6, 0x4b, + 0x71, 0x40, 0x08, 0xfb, 0x7f, 0x8c, 0xc1, 0x23, 0x43, 0x68, 0x90, 0x5f, 0xb7, 0xe0, 0xa2, 0x30, + 0xa1, 0x1b, 0x20, 0xa4, 0x5b, 0xb2, 0x35, 0x3f, 0x99, 0xb7, 0xe4, 0xc8, 0xa6, 0x38, 0xf5, 0x9a, + 0xb4, 0x3e, 0xc7, 0x96, 0xe4, 0xa5, 0x0c, 0xd6, 0x98, 0x29, 0x10, 0x97, 0x54, 0x18, 0xd5, 0x53, + 0x92, 0x8e, 0x3d, 0x10, 0x49, 0x1b, 0x19, 0xac, 0x31, 0x53, 0x20, 0xfb, 0xaf, 0xc1, 0x63, 0x87, + 0x90, 0x3b, 0x7a, 0x72, 0xda, 0x6f, 0xea, 0x51, 0x9f, 0x1c, 0x73, 0xc7, 0x98, 0xd7, 0x36, 0x4c, + 0xf0, 0xa9, 0xa3, 0x26, 0x36, 0xb0, 0x3d, 0x98, 0xcf, 0xa9, 0x10, 0x25, 0xc4, 0xfe, 0xae, 0x05, + 0xa5, 0x13, 0xd8, 0x3e, 0xab, 0x49, 0xdb, 0x67, 0x79, 0xc0, 0xee, 0x19, 0x0d, 0xda, 0x3d, 0x5f, + 0x1d, 0xad, 0x37, 0x8e, 0x63, 0xef, 0xfc, 0x91, 0x05, 0xe7, 0x07, 0xec, 0xa3, 0x64, 0x1b, 0x2e, + 0xf6, 0xfc, 0x96, 0xda, 0x4e, 0xaf, 0x3b, 0xe1, 0x36, 0x87, 0xc9, 0xcf, 0x7b, 0x81, 0xf5, 0xe4, + 0x7a, 0x06, 0xfc, 0xbd, 0xfd, 0xea, 0x9c, 0x26, 0x92, 0x42, 0xc0, 0x4c, 0x8a, 0xa4, 0x07, 0xa5, + 0x2d, 0x97, 0x76, 0x5a, 0xf1, 0x10, 0x1c, 0x51, 0x4b, 0xbb, 0x26, 0xa9, 0x89, 0xab, 0x01, 0xf5, + 0x0f, 0x35, 0x17, 0xfb, 0xc7, 0x16, 0x4c, 0xd7, 0xfa, 0xd1, 0x36, 0xd3, 0x51, 0x9a, 0xdc, 0x1a, + 0x47, 0x3c, 0x28, 0x86, 0x6e, 0x7b, 0xf7, 0x85, 0x7c, 0x16, 0xe3, 0x06, 0x23, 0x25, 0xaf, 0x48, + 0xb4, 0xb2, 0xce, 0x0b, 0x51, 0xb0, 0x21, 0x01, 0x4c, 0xf8, 0x4e, 0x3f, 0xda, 0x7e, 0x4e, 0x7e, + 0xf2, 0x88, 0x96, 0x89, 0x5b, 0xec, 0x73, 0x9e, 0x93, 0x1c, 0xb5, 0xca, 0x28, 0x4a, 0x51, 0x72, + 0xb2, 0xbf, 0x00, 0xd3, 0xc9, 0x7b, 0xb7, 0x63, 0x8c, 0xd9, 0x27, 0xa0, 0xe0, 0x04, 0x9e, 0x1c, + 0xb1, 0x15, 0x89, 0x50, 0xa8, 0xe1, 0x4d, 0x64, 0xe5, 0xe4, 0x59, 0x28, 0x6d, 0xf5, 0x3b, 0x1d, + 0x7e, 0xae, 0x10, 0x97, 0x5c, 0xfa, 0x58, 0x74, 0x4d, 0x96, 0xa3, 0xc6, 0xb0, 0xff, 0xf7, 0x38, + 0xcc, 0xd4, 0x3b, 0x7d, 0xfa, 0x6a, 0x40, 0xa9, 0xb2, 0x05, 0xd5, 0x60, 0xa6, 0x17, 0xd0, 0x5d, + 0x97, 0xde, 0x6b, 0xd0, 0x0e, 0x6d, 0x46, 0x7e, 0x20, 0xa5, 0x79, 0x44, 0x12, 0x9a, 0x59, 0x4f, + 0x82, 0x31, 0x8d, 0x4f, 0x5e, 0x81, 0x69, 0xa7, 0x19, 0xb9, 0xbb, 0x54, 0x53, 0x10, 0xe2, 0x3e, + 0x2c, 0x29, 0x4c, 0xd7, 0x12, 0x50, 0x4c, 0x61, 0x93, 0xcf, 0xc0, 0x5c, 0xd8, 0x74, 0x3a, 0xf4, + 0x76, 0x4f, 0xb2, 0x5a, 0xda, 0xa6, 0xcd, 0x9d, 0x75, 0xdf, 0xf5, 0x22, 0x69, 0x77, 0x7c, 0x52, + 0x52, 0x9a, 0x6b, 0x0c, 0xc1, 0xc3, 0xa1, 0x14, 0xc8, 0xbf, 0xb2, 0xe0, 0x89, 0x5e, 0x40, 0xd7, + 0x03, 0xbf, 0xeb, 0xb3, 0xa1, 0x36, 0x60, 0x0e, 0x93, 0x66, 0xa1, 0x37, 0x46, 0xd4, 0xa5, 0x44, + 0xc9, 0xe0, 0x1d, 0xce, 0x4f, 0x1c, 0xec, 0x57, 0x9f, 0x58, 0x3f, 0x4c, 0x00, 0x3c, 0x5c, 0x3e, + 0xf2, 0xaf, 0x2d, 0xb8, 0xdc, 0xf3, 0xc3, 0xe8, 0x90, 0x4f, 0x28, 0x9e, 0xe9, 0x27, 0xd8, 0x07, + 0xfb, 0xd5, 0xcb, 0xeb, 0x87, 0x4a, 0x80, 0x47, 0x48, 0x68, 0x1f, 0x54, 0xe0, 0xbc, 0x31, 0xf6, + 0xa4, 0x31, 0xe7, 0x65, 0x38, 0xa7, 0x06, 0x43, 0xac, 0xfb, 0x94, 0x63, 0xdb, 0x5e, 0xcd, 0x04, + 0x62, 0x12, 0x97, 0x8d, 0x3b, 0x3d, 0x14, 0x45, 0xed, 0xd4, 0xb8, 0x5b, 0x4f, 0x40, 0x31, 0x85, + 0x4d, 0x56, 0xe0, 0x82, 0x2c, 0x41, 0xda, 0xeb, 0xb8, 0x4d, 0x67, 0xc9, 0xef, 0xcb, 0x21, 0x57, + 0xac, 0x3f, 0x72, 0xb0, 0x5f, 0xbd, 0xb0, 0x3e, 0x08, 0xc6, 0xac, 0x3a, 0x64, 0x15, 0x2e, 0x3a, + 0xfd, 0xc8, 0xd7, 0xdf, 0x7f, 0xd5, 0x63, 0xdb, 0x69, 0x8b, 0x0f, 0xad, 0x92, 0xd8, 0x77, 0x6b, + 0x19, 0x70, 0xcc, 0xac, 0x45, 0xd6, 0x53, 0xd4, 0x1a, 0xb4, 0xe9, 0x7b, 0x2d, 0xd1, 0xcb, 0xc5, + 0xf8, 0x18, 0x58, 0xcb, 0xc0, 0xc1, 0xcc, 0x9a, 0xa4, 0x03, 0xd3, 0x5d, 0xe7, 0xfe, 0x6d, 0xcf, + 0xd9, 0x75, 0xdc, 0x0e, 0x63, 0x22, 0xed, 0x85, 0xc3, 0xad, 0x4c, 0xfd, 0xc8, 0xed, 0x2c, 0x08, + 0x3f, 0x8e, 0x85, 0x15, 0x2f, 0xba, 0x15, 0x34, 0x22, 0xa6, 0xa9, 0x0b, 0x0d, 0x72, 0x2d, 0x41, + 0x0b, 0x53, 0xb4, 0xc9, 0x2d, 0xb8, 0xc4, 0xa7, 0xe3, 0xb2, 0x7f, 0xcf, 0x5b, 0xa6, 0x1d, 0x67, + 0x4f, 0x7d, 0xc0, 0x24, 0xff, 0x80, 0x47, 0x0f, 0xf6, 0xab, 0x97, 0x1a, 0x59, 0x08, 0x98, 0x5d, + 0x8f, 0x38, 0xf0, 0x58, 0x12, 0x80, 0x74, 0xd7, 0x0d, 0x5d, 0xdf, 0x13, 0x66, 0xb9, 0x52, 0x6c, + 0x96, 0x6b, 0x0c, 0x47, 0xc3, 0xc3, 0x68, 0x90, 0xbf, 0x67, 0xc1, 0xc5, 0xac, 0x69, 0x38, 0x57, + 0xce, 0xe3, 0x36, 0x39, 0x35, 0xb5, 0xc4, 0x88, 0xc8, 0x5c, 0x14, 0x32, 0x85, 0x20, 0xef, 0x58, + 0x30, 0xe5, 0x18, 0x27, 0xe8, 0x39, 0xc8, 0x63, 0xd7, 0x32, 0xcf, 0xe4, 0xf5, 0xd9, 0x83, 0xfd, + 0x6a, 0xe2, 0x94, 0x8e, 0x09, 0x8e, 0xe4, 0x1f, 0x58, 0x70, 0x29, 0x73, 0x8e, 0xcf, 0x55, 0xce, + 0xa2, 0x85, 0xf8, 0x20, 0xc9, 0x5e, 0x73, 0xb2, 0xc5, 0x20, 0xdf, 0xb4, 0xf4, 0x56, 0xa6, 0x2e, + 0x18, 0xe7, 0xa6, 0xb8, 0x68, 0x23, 0x1a, 0x3c, 0x0c, 0x35, 0x4a, 0x11, 0xae, 0x5f, 0x30, 0x76, + 0x46, 0x55, 0x88, 0x69, 0xf6, 0xe4, 0x1b, 0x96, 0xda, 0x1a, 0xb5, 0x44, 0xe7, 0xce, 0x4a, 0x22, + 0x12, 0xef, 0xb4, 0x5a, 0xa0, 0x14, 0x73, 0xf2, 0xb3, 0x30, 0xef, 0x6c, 0xfa, 0x41, 0x94, 0x39, + 0xf9, 0xe6, 0xa6, 0xf9, 0x34, 0xba, 0x7c, 0xb0, 0x5f, 0x9d, 0xaf, 0x0d, 0xc5, 0xc2, 0x43, 0x28, + 0xd8, 0xbf, 0x3b, 0x01, 0x53, 0xe2, 0x24, 0x24, 0xb7, 0xae, 0xdf, 0xb2, 0xe0, 0xf1, 0x66, 0x3f, + 0x08, 0xa8, 0x17, 0x35, 0x22, 0xda, 0x1b, 0xdc, 0xb8, 0xac, 0x33, 0xdd, 0xb8, 0x9e, 0x3c, 0xd8, + 0xaf, 0x3e, 0xbe, 0x74, 0x08, 0x7f, 0x3c, 0x54, 0x3a, 0xf2, 0xef, 0x2d, 0xb0, 0x25, 0x42, 0xdd, + 0x69, 0xee, 0xb4, 0x03, 0xbf, 0xef, 0xb5, 0x06, 0x3f, 0x62, 0xec, 0x4c, 0x3f, 0xe2, 0xe9, 0x83, + 0xfd, 0xaa, 0xbd, 0x74, 0xa4, 0x14, 0x78, 0x0c, 0x49, 0xc9, 0xab, 0x70, 0x5e, 0x62, 0x5d, 0xbd, + 0xdf, 0xa3, 0x81, 0xcb, 0xce, 0x1c, 0x52, 0x71, 0x8c, 0x7d, 0xd3, 0xd2, 0x08, 0x38, 0x58, 0x87, + 0x84, 0x30, 0x79, 0x8f, 0xba, 0xed, 0xed, 0x48, 0xa9, 0x4f, 0x23, 0x3a, 0xa4, 0x49, 0xab, 0xc8, + 0x1d, 0x41, 0xb3, 0x5e, 0x39, 0xd8, 0xaf, 0x4e, 0xca, 0x3f, 0xa8, 0x38, 0x91, 0x9b, 0x30, 0x2d, + 0xce, 0xa9, 0xeb, 0xae, 0xd7, 0x5e, 0xf7, 0x3d, 0xe1, 0x55, 0x55, 0xae, 0x3f, 0xad, 0x36, 0xfc, + 0x46, 0x02, 0xfa, 0xde, 0x7e, 0x75, 0x4a, 0xfd, 0xde, 0xd8, 0xeb, 0x51, 0x4c, 0xd5, 0x26, 0x7f, + 0xd7, 0x02, 0x12, 0x46, 0xb4, 0xb7, 0xde, 0xe9, 0xb7, 0x5d, 0xd9, 0x44, 0xd2, 0x3f, 0x2a, 0x07, + 0x57, 0xad, 0x24, 0xdd, 0xfa, 0xbc, 0x14, 0x92, 0x34, 0x06, 0x38, 0x62, 0x86, 0x14, 0xf6, 0x77, + 0x26, 0x01, 0xd4, 0x5c, 0xa2, 0x3d, 0xf2, 0x21, 0x28, 0x87, 0x34, 0x12, 0x4d, 0x22, 0xaf, 0xb9, + 0xc4, 0xe5, 0xa4, 0x2a, 0xc4, 0x18, 0x4e, 0x76, 0xa0, 0xd8, 0x73, 0xfa, 0x21, 0xcd, 0xe7, 0x70, + 0x23, 0x47, 0xe6, 0x3a, 0xa3, 0x28, 0x4e, 0xcd, 0xfc, 0x27, 0x0a, 0x1e, 0xe4, 0xcb, 0x16, 0x00, + 0x4d, 0x8e, 0xa6, 0x91, 0xad, 0x57, 0x92, 0x65, 0x3c, 0xe0, 0x58, 0x1b, 0xd4, 0xa7, 0x0f, 0xf6, + 0xab, 0x60, 0x8c, 0x4b, 0x83, 0x2d, 0xb9, 0x07, 0x25, 0x47, 0x6d, 0x48, 0xe3, 0x67, 0xb1, 0x21, + 0xf1, 0xc3, 0xac, 0x9e, 0x51, 0x9a, 0x19, 0xf9, 0xaa, 0x05, 0xd3, 0x21, 0x8d, 0x64, 0x57, 0xb1, + 0x65, 0x51, 0x6a, 0xe3, 0x23, 0xce, 0x88, 0x46, 0x82, 0xa6, 0x58, 0xde, 0x93, 0x65, 0x98, 0xe2, + 0xab, 0x44, 0xb9, 0x4e, 0x9d, 0x16, 0x0d, 0xb8, 0xad, 0x44, 0xaa, 0x79, 0xa3, 0x8b, 0x62, 0xd0, + 0xd4, 0xa2, 0x18, 0x65, 0x98, 0xe2, 0xab, 0x44, 0x59, 0x73, 0x83, 0xc0, 0x97, 0xa2, 0x94, 0x72, + 0x12, 0xc5, 0xa0, 0xa9, 0x45, 0x31, 0xca, 0x30, 0xc5, 0x97, 0x74, 0x60, 0xa2, 0xc7, 0xa7, 0x96, + 0x54, 0xe5, 0x46, 0xbc, 0x23, 0x57, 0xd3, 0x94, 0xf6, 0x84, 0x4d, 0x4a, 0xfc, 0x47, 0xc9, 0xc3, + 0xfe, 0xf6, 0x39, 0x98, 0x56, 0xd3, 0x36, 0x3e, 0xe4, 0x08, 0x43, 0xe0, 0x90, 0x43, 0xce, 0x92, + 0x09, 0xc4, 0x24, 0x2e, 0xab, 0x2c, 0x56, 0xad, 0xe4, 0x19, 0x47, 0x57, 0x6e, 0x98, 0x40, 0x4c, + 0xe2, 0x92, 0x2e, 0x14, 0xd9, 0xca, 0xa2, 0xdc, 0x2f, 0x46, 0xfc, 0xf2, 0x78, 0x35, 0x32, 0x8c, + 0x2a, 0x8c, 0x3c, 0x0a, 0x2e, 0xdc, 0x96, 0x1d, 0x25, 0xcc, 0xdb, 0x72, 0x2a, 0xe6, 0xb3, 0x1a, + 0x24, 0x2d, 0xe7, 0xa2, 0xef, 0x93, 0x65, 0x98, 0x62, 0x9f, 0x71, 0xee, 0x29, 0x9e, 0xe1, 0xb9, + 0xe7, 0x53, 0x50, 0xea, 0x3a, 0xf7, 0x1b, 0xfd, 0xa0, 0x7d, 0xfa, 0xf3, 0x95, 0x74, 0xa7, 0x15, + 0x54, 0x50, 0xd3, 0x23, 0x5f, 0xb4, 0x8c, 0x05, 0x4e, 0xf8, 0x5a, 0xdc, 0xc9, 0x77, 0x81, 0xd3, + 0x6a, 0xc3, 0xd0, 0xa5, 0x6e, 0xe0, 0x14, 0x52, 0x7a, 0xe0, 0xa7, 0x10, 0xa6, 0x51, 0x8b, 0x09, + 0xa2, 0x35, 0xea, 0xf2, 0x99, 0x6a, 0xd4, 0x4b, 0x09, 0x66, 0x98, 0x62, 0xce, 0xe5, 0x11, 0x73, + 0x4e, 0xcb, 0x03, 0x67, 0x2a, 0x4f, 0x23, 0xc1, 0x0c, 0x53, 0xcc, 0x87, 0x1f, 0xbd, 0x2b, 0x67, + 0x73, 0xf4, 0x9e, 0xca, 0xe1, 0xe8, 0x7d, 0xf8, 0xa9, 0xe4, 0xdc, 0xa8, 0xa7, 0x12, 0x72, 0x03, + 0x48, 0x6b, 0xcf, 0x73, 0xba, 0x6e, 0x53, 0x2e, 0x96, 0x7c, 0x93, 0x9e, 0xe6, 0xa6, 0x19, 0xad, + 0x95, 0x2d, 0x0f, 0x60, 0x60, 0x46, 0x2d, 0x12, 0x41, 0xa9, 0xa7, 0x94, 0xcf, 0x99, 0x3c, 0x46, + 0xbf, 0x52, 0x46, 0x85, 0x0b, 0x0d, 0x9b, 0x78, 0xaa, 0x04, 0x35, 0x27, 0xb2, 0x0a, 0x17, 0xbb, + 0xae, 0xb7, 0xee, 0xb7, 0xc2, 0x75, 0x1a, 0x48, 0xc3, 0x53, 0x83, 0x46, 0x73, 0xb3, 0xbc, 0x6d, + 0xb8, 0x31, 0x61, 0x2d, 0x03, 0x8e, 0x99, 0xb5, 0xec, 0xff, 0x65, 0xc1, 0xec, 0x52, 0xc7, 0xef, + 0xb7, 0xee, 0x38, 0x51, 0x73, 0x5b, 0x78, 0x6c, 0x90, 0x57, 0xa0, 0xe4, 0x7a, 0x11, 0x0d, 0x76, + 0x9d, 0x8e, 0xdc, 0x9f, 0x6c, 0x65, 0x49, 0x5e, 0x91, 0xe5, 0xef, 0xed, 0x57, 0xa7, 0x97, 0xfb, + 0x01, 0x37, 0xd8, 0x8b, 0xd5, 0x0a, 0x75, 0x1d, 0xf2, 0x6d, 0x0b, 0xce, 0x0b, 0x9f, 0x8f, 0x65, + 0x27, 0x72, 0x5e, 0xef, 0xd3, 0xc0, 0xa5, 0xca, 0xeb, 0x63, 0xc4, 0x85, 0x2a, 0x2d, 0xab, 0x62, + 0xb0, 0x17, 0x9f, 0x59, 0xd6, 0xd2, 0x9c, 0x71, 0x50, 0x18, 0xfb, 0x97, 0x0b, 0xf0, 0xe8, 0x50, + 0x5a, 0x64, 0x1e, 0xc6, 0xdc, 0x96, 0xfc, 0x74, 0x90, 0x74, 0xc7, 0x56, 0x5a, 0x38, 0xe6, 0xb6, + 0xc8, 0x02, 0xd7, 0x70, 0x03, 0x1a, 0x86, 0xea, 0xee, 0xbd, 0xac, 0x95, 0x51, 0x59, 0x8a, 0x06, + 0x06, 0xa9, 0x42, 0x91, 0xbb, 0x52, 0xcb, 0xa3, 0x15, 0xd7, 0x99, 0xb9, 0xd7, 0x32, 0x8a, 0x72, + 0xf2, 0x25, 0x0b, 0x40, 0x08, 0xc8, 0xf4, 0x7d, 0xb9, 0x4b, 0x62, 0xbe, 0xcd, 0xc4, 0x28, 0x0b, + 0x29, 0xe3, 0xff, 0x68, 0x70, 0x25, 0x1b, 0x30, 0xc1, 0xd4, 0x67, 0xbf, 0x75, 0xea, 0x4d, 0x51, + 0x28, 0x40, 0x9c, 0x06, 0x4a, 0x5a, 0xac, 0xad, 0x02, 0x1a, 0xf5, 0x03, 0x8f, 0x35, 0x2d, 0xdf, + 0x06, 0x4b, 0x42, 0x0a, 0xd4, 0xa5, 0x68, 0x60, 0xd8, 0xff, 0x62, 0x0c, 0x2e, 0x66, 0x89, 0xce, + 0x76, 0x9b, 0x09, 0x21, 0xad, 0xb4, 0x12, 0xfc, 0x4c, 0xfe, 0xed, 0x23, 0xdd, 0x97, 0xf4, 0x8d, + 0x8d, 0xf4, 0x25, 0x95, 0x7c, 0xc9, 0xcf, 0xe8, 0x16, 0x1a, 0x3b, 0x65, 0x0b, 0x69, 0xca, 0xa9, + 0x56, 0x7a, 0x12, 0xc6, 0x43, 0xd6, 0xf3, 0x85, 0xe4, 0xcd, 0x0f, 0xef, 0x23, 0x0e, 0x61, 0x18, + 0x7d, 0xcf, 0x8d, 0x64, 0xfc, 0x91, 0xc6, 0xb8, 0xed, 0xb9, 0x11, 0x72, 0x88, 0xfd, 0xad, 0x31, + 0x98, 0x1f, 0xfe, 0x51, 0xe4, 0x5b, 0x16, 0x40, 0x8b, 0x1d, 0x8e, 0x42, 0xee, 0xc4, 0x2f, 0xdc, + 0xbd, 0x9c, 0xb3, 0x6a, 0xc3, 0x65, 0xc5, 0x29, 0xf6, 0x43, 0xd4, 0x45, 0x21, 0x1a, 0x82, 0x90, + 0xe7, 0xd4, 0xd0, 0xe7, 0xb7, 0x56, 0x62, 0x32, 0xe9, 0x3a, 0x6b, 0x1a, 0x82, 0x06, 0x16, 0x3b, + 0xfd, 0x7a, 0x4e, 0x97, 0x86, 0x3d, 0x47, 0x47, 0x73, 0xf1, 0xd3, 0xef, 0x4d, 0x55, 0x88, 0x31, + 0xdc, 0xee, 0xc0, 0x53, 0xc7, 0x90, 0x33, 0xa7, 0x60, 0x19, 0xfb, 0x4f, 0x2d, 0x78, 0x44, 0x7a, + 0xe2, 0xfd, 0x7f, 0xe3, 0xd6, 0xf9, 0x67, 0x16, 0x3c, 0x36, 0xe4, 0x9b, 0x1f, 0x80, 0x77, 0xe7, + 0x5b, 0x49, 0xef, 0xce, 0xdb, 0xa3, 0x0e, 0xe9, 0xcc, 0xef, 0x18, 0xe2, 0xe4, 0xf9, 0xbb, 0x05, + 0x38, 0xc7, 0x96, 0xad, 0x96, 0xdf, 0xce, 0x69, 0xe3, 0x7c, 0x0a, 0x8a, 0x9f, 0x63, 0x1b, 0x50, + 0x7a, 0x90, 0xf1, 0x5d, 0x09, 0x05, 0x8c, 0x7c, 0xd9, 0x82, 0xc9, 0xcf, 0xc9, 0x3d, 0x55, 0x9c, + 0xe5, 0x46, 0x5c, 0x0c, 0x13, 0xdf, 0xb0, 0x20, 0x77, 0x48, 0x11, 0x83, 0xa3, 0x7d, 0x39, 0xd5, + 0x56, 0xaa, 0x38, 0x93, 0x67, 0x60, 0x72, 0xcb, 0x0f, 0xba, 0xfd, 0x8e, 0x93, 0x0e, 0xfc, 0xbc, + 0x26, 0x8a, 0x51, 0xc1, 0xd9, 0x24, 0x77, 0x7a, 0xee, 0x1b, 0x34, 0x08, 0x45, 0x48, 0x46, 0x62, + 0x92, 0xd7, 0x34, 0x04, 0x0d, 0x2c, 0x5e, 0xa7, 0xdd, 0x0e, 0x68, 0xdb, 0x89, 0xfc, 0x80, 0xef, + 0x1c, 0x66, 0x1d, 0x0d, 0x41, 0x03, 0x6b, 0xfe, 0xe3, 0x30, 0x65, 0x0a, 0x7f, 0xa2, 0x78, 0x9e, + 0x4f, 0x80, 0x74, 0xea, 0x4c, 0x2d, 0x49, 0xd6, 0x71, 0x96, 0x24, 0xfb, 0x3f, 0x8e, 0x81, 0x61, + 0x8b, 0x7a, 0x00, 0x53, 0xdd, 0x4b, 0x4c, 0xf5, 0x11, 0xed, 0x28, 0x86, 0x65, 0x6d, 0x58, 0x74, + 0xe3, 0x6e, 0x2a, 0xba, 0xf1, 0x66, 0x6e, 0x1c, 0x0f, 0x0f, 0x6e, 0xfc, 0x81, 0x05, 0x8f, 0xc5, + 0xc8, 0x83, 0x36, 0xec, 0xa3, 0xd7, 0xed, 0x17, 0xa1, 0xe2, 0xc4, 0xd5, 0xe4, 0xc4, 0x32, 0x42, + 0xcb, 0x34, 0x08, 0x4d, 0xbc, 0x38, 0x2c, 0xa6, 0x70, 0xca, 0xb0, 0x98, 0xf1, 0xc3, 0xc3, 0x62, + 0xec, 0x1f, 0x8f, 0xc1, 0x13, 0x83, 0x5f, 0x66, 0xfa, 0x8a, 0x1f, 0xfd, 0x6d, 0x69, 0x6f, 0xf2, + 0xb1, 0x53, 0x7b, 0x93, 0x17, 0x8e, 0xeb, 0x4d, 0xae, 0x7d, 0xb8, 0xc7, 0xcf, 0xdc, 0x87, 0xbb, + 0x01, 0x97, 0x94, 0xc3, 0xe8, 0x35, 0x3f, 0x90, 0xb1, 0x21, 0x6a, 0x05, 0x29, 0xd5, 0x9f, 0x90, + 0x55, 0x2e, 0x61, 0x16, 0x12, 0x66, 0xd7, 0xb5, 0x7f, 0x50, 0x80, 0x0b, 0x71, 0xb3, 0x2f, 0xf9, + 0x5e, 0xcb, 0xe5, 0x3e, 0x47, 0x2f, 0xc3, 0x78, 0xb4, 0xd7, 0x53, 0x8d, 0xfd, 0x97, 0x95, 0x38, + 0x1b, 0x7b, 0x3d, 0xd6, 0xdb, 0x8f, 0x64, 0x54, 0xe1, 0xb7, 0x08, 0xbc, 0x12, 0x59, 0xd5, 0xb3, + 0x43, 0xf4, 0xc0, 0x0b, 0xc9, 0xd1, 0xfc, 0xde, 0x7e, 0x35, 0x23, 0xcb, 0xc3, 0x82, 0xa6, 0x94, + 0x1c, 0xf3, 0xe4, 0x2e, 0x4c, 0x77, 0x9c, 0x30, 0xba, 0xdd, 0x6b, 0x39, 0x11, 0xdd, 0x70, 0xa5, + 0x37, 0xcf, 0xc9, 0xc2, 0x69, 0xb4, 0xdb, 0xc3, 0x6a, 0x82, 0x12, 0xa6, 0x28, 0x93, 0x5d, 0x20, + 0xac, 0x64, 0x23, 0x70, 0xbc, 0x50, 0x7c, 0x15, 0xe3, 0x77, 0xf2, 0xd8, 0x28, 0x7d, 0x74, 0x5e, + 0x1d, 0xa0, 0x86, 0x19, 0x1c, 0xc8, 0xd3, 0x30, 0x11, 0x50, 0x27, 0xd4, 0xdb, 0x81, 0x9e, 0xff, + 0xc8, 0x4b, 0x51, 0x42, 0xcd, 0x09, 0x35, 0x71, 0xc4, 0x84, 0xfa, 0x43, 0x0b, 0xa6, 0xe3, 0x6e, + 0x7a, 0x00, 0xaa, 0x47, 0x37, 0xa9, 0x7a, 0x5c, 0xcf, 0x6b, 0x49, 0x1c, 0xa2, 0x6d, 0xfc, 0xc9, + 0xa4, 0xf9, 0x7d, 0x3c, 0x80, 0xe3, 0xf3, 0xa6, 0x3f, 0xbf, 0x95, 0x47, 0x54, 0x5d, 0x42, 0xdb, + 0x3b, 0xd4, 0x91, 0x9f, 0xe9, 0x3a, 0x2d, 0xa9, 0xc7, 0xc8, 0x61, 0xaf, 0x75, 0x1d, 0xa5, 0xdf, + 0x64, 0xe9, 0x3a, 0xaa, 0x0e, 0xb9, 0x0d, 0x8f, 0xf4, 0x02, 0x9f, 0xe7, 0x19, 0x58, 0xa6, 0x4e, + 0xab, 0xe3, 0x7a, 0x54, 0x99, 0x79, 0x84, 0xd7, 0xcd, 0x63, 0x07, 0xfb, 0xd5, 0x47, 0xd6, 0xb3, + 0x51, 0x70, 0x58, 0xdd, 0x64, 0xa4, 0xea, 0xf8, 0x31, 0x22, 0x55, 0x7f, 0x51, 0x1b, 0x53, 0x75, + 0x50, 0xc4, 0xa7, 0xf3, 0xea, 0xca, 0xac, 0xf0, 0x08, 0x3d, 0xa4, 0x6a, 0x92, 0x29, 0x6a, 0xf6, + 0xc3, 0x2d, 0x76, 0x13, 0xa7, 0xb4, 0xd8, 0xc5, 0x71, 0x30, 0x93, 0xef, 0x67, 0x1c, 0x4c, 0xe9, + 0x03, 0x15, 0x07, 0xf3, 0x6d, 0x0b, 0x2e, 0x38, 0x83, 0x11, 0xe8, 0xf9, 0x18, 0x8f, 0x33, 0x42, + 0xdb, 0xeb, 0x8f, 0x49, 0x21, 0xb3, 0x02, 0xfd, 0x31, 0x4b, 0x14, 0xfb, 0xdd, 0x22, 0xcc, 0xa6, + 0x95, 0xa4, 0xb3, 0x0f, 0xd5, 0xfd, 0x5b, 0x16, 0xcc, 0xaa, 0x09, 0xae, 0x6f, 0xc0, 0xc5, 0x11, + 0x63, 0x35, 0xa7, 0x75, 0x45, 0xa8, 0x7b, 0x3a, 0x83, 0xca, 0x46, 0x8a, 0x1b, 0x0e, 0xf0, 0x27, + 0x6f, 0x42, 0x45, 0xdf, 0xaa, 0x9c, 0x2a, 0x6e, 0x97, 0x87, 0x96, 0xd6, 0x62, 0x12, 0x68, 0xd2, + 0x23, 0xef, 0x5a, 0x00, 0x4d, 0xb5, 0x13, 0xe7, 0x14, 0x15, 0x95, 0xa1, 0x2d, 0xc4, 0xfa, 0xbc, + 0x2e, 0x0a, 0xd1, 0x60, 0x4c, 0x7e, 0x99, 0xdf, 0xa7, 0xe8, 0x91, 0xa0, 0x3c, 0x0f, 0x3e, 0x99, + 0xf7, 0x52, 0x14, 0xfb, 0x92, 0x68, 0x6d, 0xcf, 0x00, 0x85, 0x98, 0x10, 0xc2, 0x7e, 0x19, 0xb4, + 0xcf, 0x36, 0x5b, 0x59, 0xb9, 0xd7, 0xf6, 0xba, 0x13, 0x6d, 0xcb, 0x21, 0xa8, 0x57, 0xd6, 0x6b, + 0x0a, 0x80, 0x31, 0x8e, 0xfd, 0x59, 0x98, 0x7e, 0x35, 0x70, 0x7a, 0xdb, 0x2e, 0xbf, 0xb7, 0x60, + 0xe7, 0xe3, 0x67, 0x60, 0xd2, 0x69, 0xb5, 0xb2, 0x92, 0xfd, 0xd4, 0x44, 0x31, 0x2a, 0xf8, 0xb1, + 0x8e, 0xc2, 0xf6, 0xbf, 0xb5, 0x80, 0xc4, 0x37, 0xcd, 0xae, 0xd7, 0x5e, 0x73, 0xa2, 0xe6, 0x36, + 0x3b, 0xc2, 0x6d, 0xf3, 0xd2, 0xac, 0x23, 0xdc, 0x75, 0x0d, 0x41, 0x03, 0x8b, 0xbc, 0x0d, 0x15, + 0xf1, 0xef, 0x0d, 0x7d, 0x40, 0x1c, 0xdd, 0xf5, 0x9c, 0xef, 0x79, 0x5c, 0x26, 0x31, 0x0a, 0xaf, + 0xc7, 0x1c, 0xd0, 0x64, 0xc7, 0x9a, 0x6a, 0xc5, 0xdb, 0xea, 0xf4, 0xef, 0xb7, 0x36, 0xe3, 0xa6, + 0xea, 0x05, 0xfe, 0x96, 0xdb, 0xa1, 0xe9, 0xa6, 0x5a, 0x17, 0xc5, 0xa8, 0xe0, 0xc7, 0x6b, 0xaa, + 0x7f, 0x63, 0xc1, 0xc5, 0x95, 0x30, 0x72, 0xfd, 0x65, 0x1a, 0x46, 0x6c, 0xe7, 0x63, 0xeb, 0x63, + 0xbf, 0x73, 0x9c, 0xf0, 0x8b, 0x65, 0x98, 0x95, 0xf7, 0xd0, 0xfd, 0xcd, 0x90, 0x46, 0xc6, 0x51, + 0x43, 0xcf, 0xe3, 0xa5, 0x14, 0x1c, 0x07, 0x6a, 0x30, 0x2a, 0xf2, 0x42, 0x3a, 0xa6, 0x52, 0x48, + 0x52, 0x69, 0xa4, 0xe0, 0x38, 0x50, 0xc3, 0xfe, 0x7e, 0x01, 0x2e, 0xf0, 0xcf, 0x48, 0x85, 0x4e, + 0x7d, 0x63, 0x58, 0xe8, 0xd4, 0x88, 0x53, 0x99, 0xf3, 0x3a, 0x45, 0xe0, 0xd4, 0xdf, 0xb4, 0x60, + 0xa6, 0x95, 0x6c, 0xe9, 0x7c, 0xec, 0x72, 0x59, 0x7d, 0x28, 0x3c, 0x10, 0x53, 0x85, 0x98, 0xe6, + 0x4f, 0x7e, 0xc5, 0x82, 0x99, 0xa4, 0x98, 0x6a, 0x75, 0x3f, 0x83, 0x46, 0xd2, 0x21, 0x03, 0xc9, + 0xf2, 0x10, 0xd3, 0x22, 0xd8, 0xbf, 0x37, 0x26, 0xbb, 0xf4, 0x2c, 0xe2, 0x82, 0xc8, 0x3d, 0x28, + 0x47, 0x9d, 0x50, 0x14, 0xca, 0xaf, 0x1d, 0xf1, 0xd0, 0xba, 0xb1, 0xda, 0x10, 0x0e, 0x27, 0xb1, + 0x5e, 0x29, 0x4b, 0x98, 0x7e, 0xac, 0x78, 0x71, 0xc6, 0xcd, 0x9e, 0x64, 0x9c, 0xcb, 0x69, 0x79, + 0x63, 0x69, 0x3d, 0xcd, 0x58, 0x96, 0x30, 0xc6, 0x8a, 0x97, 0xfd, 0x1b, 0x16, 0x94, 0x6f, 0xf8, + 0x6a, 0x1d, 0xf9, 0xd9, 0x1c, 0x6c, 0x51, 0x5a, 0x65, 0xd5, 0x4a, 0x4b, 0x7c, 0x0a, 0x7a, 0x25, + 0x61, 0x89, 0x7a, 0xdc, 0xa0, 0xbd, 0xc0, 0x73, 0x1e, 0x32, 0x52, 0x37, 0xfc, 0xcd, 0xa1, 0xe6, + 0xe3, 0x5f, 0x2d, 0xc2, 0xb9, 0xd7, 0x9c, 0x3d, 0xea, 0x45, 0xce, 0xc9, 0x37, 0x89, 0x17, 0xa1, + 0xe2, 0xf4, 0xf8, 0x5d, 0xa6, 0x71, 0x0c, 0x89, 0x8d, 0x3b, 0x31, 0x08, 0x4d, 0xbc, 0x78, 0x41, + 0x13, 0x41, 0x3a, 0x59, 0x4b, 0xd1, 0x52, 0x0a, 0x8e, 0x03, 0x35, 0xc8, 0x0d, 0x20, 0x32, 0xb0, + 0xbd, 0xd6, 0x6c, 0xfa, 0x7d, 0x4f, 0x2c, 0x69, 0xc2, 0xee, 0xa3, 0xcf, 0xc3, 0x6b, 0x03, 0x18, + 0x98, 0x51, 0x8b, 0x7c, 0x06, 0xe6, 0x9a, 0x9c, 0xb2, 0x3c, 0x1d, 0x99, 0x14, 0xc5, 0x09, 0x59, + 0x87, 0xbd, 0x2c, 0x0d, 0xc1, 0xc3, 0xa1, 0x14, 0x98, 0xa4, 0x61, 0xe4, 0x07, 0x4e, 0x9b, 0x9a, + 0x74, 0x27, 0x92, 0x92, 0x36, 0x06, 0x30, 0x30, 0xa3, 0x16, 0xf9, 0x02, 0x94, 0xa3, 0xed, 0x80, + 0x86, 0xdb, 0x7e, 0xa7, 0x25, 0x7d, 0x4f, 0x46, 0x34, 0x06, 0xca, 0xde, 0xdf, 0x50, 0x54, 0x8d, + 0xe1, 0xad, 0x8a, 0x30, 0xe6, 0x49, 0x02, 0x98, 0x08, 0x9b, 0x7e, 0x8f, 0x86, 0xf2, 0x54, 0x71, + 0x23, 0x17, 0xee, 0xdc, 0xb8, 0x65, 0x98, 0x21, 0x39, 0x07, 0x94, 0x9c, 0xec, 0xdf, 0x19, 0x83, + 0x29, 0x13, 0xf1, 0x18, 0x6b, 0xd3, 0x97, 0x2d, 0x98, 0x6a, 0xfa, 0x5e, 0x14, 0xf8, 0x9d, 0x38, + 0x61, 0xc3, 0xe8, 0x1a, 0x05, 0x23, 0xb5, 0x4c, 0x23, 0xc7, 0xed, 0x18, 0xd6, 0x3a, 0x83, 0x0d, + 0x26, 0x98, 0x92, 0xaf, 0x5b, 0x30, 0x13, 0x3b, 0x46, 0xc6, 0xb6, 0xbe, 0x5c, 0x05, 0xd1, 0x4b, + 0xfd, 0xd5, 0x24, 0x27, 0x4c, 0xb3, 0xb6, 0x37, 0x61, 0x36, 0xdd, 0xdb, 0xac, 0x29, 0x7b, 0x8e, + 0x9c, 0xeb, 0x85, 0xb8, 0x29, 0xd7, 0x9d, 0x30, 0x44, 0x0e, 0x21, 0xcf, 0x42, 0xa9, 0xeb, 0x04, + 0x6d, 0xd7, 0x73, 0x3a, 0xbc, 0x15, 0x0b, 0xc6, 0x82, 0x24, 0xcb, 0x51, 0x63, 0xd8, 0x1f, 0x81, + 0xa9, 0x35, 0xc7, 0x6b, 0xd3, 0x96, 0x5c, 0x87, 0x8f, 0x8e, 0x4c, 0xfd, 0xe3, 0x71, 0xa8, 0x18, + 0xc7, 0xc7, 0xb3, 0x3f, 0x67, 0x25, 0x12, 0x11, 0x15, 0x72, 0x4c, 0x44, 0xf4, 0x29, 0x80, 0x2d, + 0xd7, 0x73, 0xc3, 0xed, 0x53, 0xa6, 0x38, 0xe2, 0x77, 0xf3, 0xd7, 0x34, 0x05, 0x34, 0xa8, 0xc5, + 0x17, 0xa0, 0xc5, 0x43, 0xb2, 0x05, 0xbe, 0x6b, 0x19, 0xdb, 0xcd, 0x44, 0x1e, 0x0e, 0x1f, 0x46, + 0xc7, 0x2c, 0xa8, 0xed, 0x47, 0xdc, 0x4d, 0x1d, 0xb6, 0x2b, 0x6d, 0x40, 0x29, 0xa0, 0x61, 0xbf, + 0x4b, 0x4f, 0x95, 0x8c, 0x88, 0xbb, 0xde, 0xa0, 0xac, 0x8f, 0x9a, 0xd2, 0xfc, 0xcb, 0x70, 0x2e, + 0x21, 0xc2, 0x89, 0x6e, 0x98, 0x7c, 0xc8, 0xb4, 0x51, 0x9c, 0xe6, 0xbe, 0x89, 0xf5, 0x45, 0xc7, + 0x48, 0x42, 0xa4, 0xfb, 0x42, 0x38, 0x58, 0x09, 0x98, 0xfd, 0xe3, 0x09, 0x90, 0x3e, 0x0c, 0xc7, + 0x58, 0xae, 0xcc, 0x9b, 0xcb, 0xb1, 0x53, 0xdc, 0x5c, 0xde, 0x80, 0x29, 0xd7, 0x73, 0x23, 0xd7, + 0xe9, 0x70, 0xfb, 0x93, 0xdc, 0x4e, 0x95, 0x33, 0xfe, 0xd4, 0x8a, 0x01, 0xcb, 0xa0, 0x93, 0xa8, + 0x4b, 0x5e, 0x87, 0x22, 0xdf, 0x6f, 0xe4, 0x00, 0x3e, 0xb9, 0xa3, 0x05, 0xf7, 0xb1, 0x11, 0x11, + 0x7a, 0x82, 0x12, 0x3f, 0x7c, 0x88, 0x2c, 0x4c, 0xfa, 0xf8, 0x2d, 0xc7, 0x71, 0x7c, 0xf8, 0x48, + 0xc1, 0x71, 0xa0, 0x06, 0xa3, 0xb2, 0xe5, 0xb8, 0x9d, 0x7e, 0x40, 0x63, 0x2a, 0x13, 0x49, 0x2a, + 0xd7, 0x52, 0x70, 0x1c, 0xa8, 0x41, 0xb6, 0x60, 0x4a, 0x96, 0x09, 0xb7, 0xb9, 0xc9, 0x53, 0x7e, + 0x25, 0x77, 0x8f, 0xbc, 0x66, 0x50, 0xc2, 0x04, 0x5d, 0xd2, 0x87, 0xf3, 0xae, 0xd7, 0xf4, 0xbd, + 0x66, 0xa7, 0x1f, 0xba, 0xbb, 0x34, 0x0e, 0x8f, 0x3b, 0x0d, 0xb3, 0x4b, 0x07, 0xfb, 0xd5, 0xf3, + 0x2b, 0x69, 0x72, 0x38, 0xc8, 0x81, 0x7c, 0xd1, 0x82, 0x4b, 0x4d, 0xdf, 0x0b, 0x79, 0x16, 0x8f, + 0x5d, 0x7a, 0x35, 0x08, 0xfc, 0x40, 0xf0, 0x2e, 0x9f, 0x92, 0x37, 0x37, 0x7b, 0x2e, 0x65, 0x91, + 0xc4, 0x6c, 0x4e, 0xe4, 0x2d, 0x28, 0xf5, 0x02, 0x7f, 0xd7, 0x6d, 0xd1, 0x40, 0xba, 0x60, 0xae, + 0xe6, 0x91, 0xda, 0x68, 0x5d, 0xd2, 0x8c, 0x97, 0x1e, 0x55, 0x82, 0x9a, 0x9f, 0xfd, 0x7f, 0x2a, + 0x30, 0x9d, 0x44, 0x27, 0x3f, 0x0f, 0xd0, 0x0b, 0xfc, 0x2e, 0x8d, 0xb6, 0xa9, 0x0e, 0x73, 0xba, + 0x39, 0x6a, 0xf2, 0x1a, 0x45, 0x4f, 0xb9, 0x2d, 0xb1, 0xe5, 0x22, 0x2e, 0x45, 0x83, 0x23, 0x09, + 0x60, 0x72, 0x47, 0x6c, 0xbb, 0x52, 0x0b, 0x79, 0x2d, 0x17, 0x9d, 0x49, 0x72, 0xe6, 0xf1, 0x39, + 0xb2, 0x08, 0x15, 0x23, 0xb2, 0x09, 0x85, 0x7b, 0x74, 0x33, 0x9f, 0xcc, 0x09, 0x77, 0xa8, 0x3c, + 0xcd, 0xd4, 0x27, 0x0f, 0xf6, 0xab, 0x85, 0x3b, 0x74, 0x13, 0x19, 0x71, 0xf6, 0x5d, 0x2d, 0xe1, + 0xbb, 0x20, 0x97, 0x8a, 0xd7, 0x72, 0x74, 0x84, 0x10, 0xdf, 0x25, 0x8b, 0x50, 0x31, 0x22, 0x6f, + 0x41, 0xf9, 0x9e, 0xb3, 0x4b, 0xb7, 0x02, 0xdf, 0x8b, 0xa4, 0xaf, 0xdc, 0x88, 0xc1, 0x25, 0x77, + 0x14, 0x39, 0xc9, 0x97, 0x6f, 0xef, 0xba, 0x10, 0x63, 0x76, 0x64, 0x17, 0x4a, 0x1e, 0xbd, 0x87, + 0xb4, 0xe3, 0x36, 0xf3, 0x09, 0xe6, 0xb8, 0x29, 0xa9, 0x49, 0xce, 0x7c, 0xdf, 0x53, 0x65, 0xa8, + 0x79, 0xb1, 0xbe, 0xbc, 0xeb, 0x6f, 0xca, 0x85, 0x6a, 0xc4, 0xbe, 0xd4, 0x27, 0x53, 0xd1, 0x97, + 0x37, 0xfc, 0x4d, 0x64, 0xc4, 0xd9, 0x1c, 0x69, 0x6a, 0x47, 0x2d, 0xb9, 0x4c, 0xdd, 0xcc, 0xd7, + 0x41, 0x4d, 0xcc, 0x91, 0xb8, 0x14, 0x0d, 0x8e, 0xac, 0x6d, 0xdb, 0xd2, 0x58, 0x29, 0x17, 0xaa, + 0x11, 0xdb, 0x36, 0x69, 0xfa, 0x14, 0x6d, 0xab, 0xca, 0x50, 0xf3, 0x62, 0x7c, 0x5d, 0x69, 0xf9, + 0xcb, 0x67, 0xa9, 0x4a, 0xda, 0x11, 0x05, 0x5f, 0x55, 0x86, 0x9a, 0x17, 0x6b, 0xef, 0x70, 0x67, + 0xef, 0x9e, 0xd3, 0xd9, 0x71, 0xbd, 0xb6, 0x0c, 0xdb, 0x1d, 0x35, 0xcc, 0x6d, 0x67, 0xef, 0x8e, + 0xa0, 0x67, 0xb6, 0x77, 0x5c, 0x8a, 0x06, 0x47, 0xf2, 0xf7, 0x2d, 0x1d, 0x8a, 0x33, 0x95, 0x87, + 0x13, 0x53, 0x72, 0xc9, 0x95, 0x91, 0x39, 0x42, 0x51, 0xfc, 0x29, 0xed, 0x77, 0xc9, 0x0b, 0xbf, + 0xf6, 0x47, 0xd5, 0x39, 0xea, 0x35, 0xfd, 0x96, 0xeb, 0xb5, 0x17, 0xef, 0x86, 0xbe, 0xb7, 0x80, + 0xce, 0x3d, 0xa5, 0xa3, 0x4b, 0x99, 0xe6, 0x3f, 0x06, 0x15, 0x83, 0xc4, 0x51, 0x8a, 0xde, 0x94, + 0xa9, 0xe8, 0xfd, 0xc6, 0x04, 0x4c, 0x99, 0x79, 0x48, 0x8f, 0xa1, 0x7d, 0xe9, 0x13, 0xc7, 0xd8, + 0x49, 0x4e, 0x1c, 0xec, 0x88, 0x69, 0x5c, 0x70, 0x29, 0xf3, 0xd6, 0x4a, 0x6e, 0x0a, 0x77, 0x7c, + 0xc4, 0x34, 0x0a, 0x43, 0x4c, 0x30, 0x3d, 0x81, 0xcf, 0x0b, 0x53, 0x5b, 0x85, 0x62, 0x57, 0x4c, + 0xaa, 0xad, 0x09, 0x55, 0xed, 0x39, 0x80, 0x38, 0x61, 0xa6, 0xbc, 0xf8, 0xd4, 0xfa, 0xb0, 0x91, + 0xc8, 0xd3, 0xc0, 0x22, 0x4f, 0xc3, 0x04, 0x53, 0x7d, 0x68, 0x4b, 0x66, 0x15, 0xd0, 0xe7, 0xf8, + 0x6b, 0xbc, 0x14, 0x25, 0x94, 0xbc, 0xc4, 0xb4, 0xd4, 0x58, 0x61, 0x91, 0xc9, 0x02, 0x2e, 0xc6, + 0x5a, 0x6a, 0x0c, 0xc3, 0x04, 0x26, 0x13, 0x9d, 0x32, 0xfd, 0x82, 0xaf, 0x0d, 0x86, 0xe8, 0x5c, + 0xe9, 0x40, 0x01, 0xe3, 0x76, 0xa5, 0x94, 0x3e, 0xc2, 0xe7, 0x74, 0xd1, 0xb0, 0x2b, 0xa5, 0xe0, + 0x38, 0x50, 0x83, 0x7d, 0x8c, 0xbc, 0xb3, 0xad, 0x08, 0x87, 0xe9, 0x21, 0xb7, 0xad, 0x5f, 0x31, + 0xcf, 0x5a, 0x39, 0xce, 0x21, 0x31, 0x6a, 0x8f, 0x7f, 0xd8, 0x1a, 0xed, 0x58, 0xf4, 0x59, 0x98, + 0x4e, 0xee, 0x42, 0xb9, 0xdf, 0x7c, 0x7c, 0x75, 0x1c, 0x2e, 0xdc, 0x6c, 0xbb, 0x5e, 0x3a, 0xe7, + 0x5b, 0xd6, 0x03, 0x0f, 0xd6, 0x89, 0x1f, 0x78, 0xd0, 0x31, 0x79, 0xf2, 0xf9, 0x84, 0xec, 0x98, + 0x3c, 0xf5, 0x96, 0x45, 0x12, 0x97, 0xfc, 0xa1, 0x05, 0x8f, 0x3b, 0x2d, 0x71, 0x2e, 0x70, 0x3a, + 0xb2, 0xd4, 0xc8, 0x4b, 0x2e, 0x67, 0x74, 0x38, 0xe2, 0x2e, 0x3f, 0xf8, 0xf1, 0x0b, 0xb5, 0x43, + 0xb8, 0x8a, 0x1e, 0xff, 0x49, 0xf9, 0x05, 0x8f, 0x1f, 0x86, 0x8a, 0x87, 0x8a, 0x4f, 0xfe, 0x2a, + 0xcc, 0x24, 0x3e, 0x58, 0x5a, 0xc2, 0xcb, 0xe2, 0xc2, 0xa2, 0x91, 0x04, 0x61, 0x1a, 0x77, 0xfe, + 0x16, 0xfc, 0xc4, 0x91, 0x72, 0x9e, 0x68, 0xb0, 0x7d, 0xcf, 0x82, 0x29, 0x33, 0x3d, 0x13, 0x79, + 0x16, 0x4a, 0x91, 0xbf, 0x43, 0xbd, 0xdb, 0x81, 0x72, 0xd8, 0xd5, 0x03, 0x7d, 0x83, 0x97, 0xe3, + 0x2a, 0x6a, 0x0c, 0x86, 0xdd, 0xec, 0xb8, 0xd4, 0x8b, 0x56, 0x5a, 0xb2, 0x9b, 0x35, 0xf6, 0x92, + 0x28, 0x5f, 0x46, 0x8d, 0x21, 0x7c, 0xec, 0xd8, 0xef, 0x06, 0x6d, 0x06, 0x54, 0xb9, 0xf7, 0x1b, + 0x3e, 0x76, 0x31, 0x0c, 0x13, 0x98, 0xc4, 0xd6, 0x26, 0xce, 0xf1, 0xf8, 0x5e, 0x23, 0x65, 0x92, + 0xfc, 0x8e, 0x05, 0x65, 0x61, 0xa2, 0x47, 0xba, 0x95, 0x72, 0xb1, 0x4d, 0x19, 0x11, 0x6a, 0xeb, + 0x2b, 0x59, 0x2e, 0xb6, 0x4f, 0xc2, 0xf8, 0x8e, 0xeb, 0xa9, 0x2f, 0xd1, 0xdb, 0xd2, 0x6b, 0xae, + 0xd7, 0x42, 0x0e, 0xd1, 0x1b, 0x57, 0x61, 0xe8, 0xc6, 0xb5, 0x08, 0x65, 0xed, 0x78, 0x22, 0x97, + 0x7f, 0x6d, 0xbd, 0xd5, 0x8e, 0x2a, 0x18, 0xe3, 0xd8, 0xbf, 0x66, 0xc1, 0x34, 0x8f, 0x18, 0x8f, + 0xcf, 0xc3, 0x2f, 0x6a, 0x5f, 0x30, 0x21, 0xf7, 0x13, 0x49, 0x5f, 0xb0, 0xf7, 0xf6, 0xab, 0x15, + 0x11, 0x63, 0x9e, 0x74, 0x0d, 0xfb, 0xb4, 0x34, 0xa2, 0x71, 0x8f, 0xb5, 0xb1, 0x13, 0xdb, 0x78, + 0x62, 0x31, 0x15, 0x11, 0x8c, 0xe9, 0xd9, 0x6f, 0xc3, 0x94, 0x19, 0x8c, 0x45, 0x5e, 0x84, 0x4a, + 0xcf, 0xf5, 0xda, 0xc9, 0xa0, 0x5d, 0x7d, 0xd1, 0xb0, 0x1e, 0x83, 0xd0, 0xc4, 0xe3, 0xd5, 0xfc, + 0xb8, 0x5a, 0xea, 0x7e, 0x62, 0xdd, 0x37, 0xab, 0xc5, 0x7f, 0x6c, 0x0f, 0x20, 0x8e, 0x2c, 0x3e, + 0x96, 0xf1, 0x66, 0x42, 0xd8, 0xfe, 0x85, 0x32, 0xc2, 0xb3, 0x44, 0x4c, 0x88, 0x11, 0xfe, 0xde, + 0xfe, 0x61, 0xca, 0x8e, 0xa8, 0xc5, 0xdf, 0xa0, 0xc8, 0x08, 0x32, 0xcc, 0xfd, 0x0d, 0x8a, 0x0c, + 0x1e, 0xef, 0xdf, 0x1b, 0x14, 0x59, 0xc2, 0xfc, 0xf9, 0x7a, 0x83, 0xe2, 0x93, 0x70, 0xd2, 0x74, + 0xb4, 0x4c, 0xb7, 0xb8, 0x67, 0xa6, 0x8d, 0xd0, 0x2d, 0x2e, 0xf3, 0x46, 0x48, 0xa8, 0xfd, 0xdb, + 0x05, 0x98, 0x4d, 0x9b, 0x18, 0xf2, 0xf6, 0xde, 0x20, 0x5f, 0xb7, 0x60, 0xda, 0x49, 0xa4, 0xfe, + 0xcb, 0xe9, 0x41, 0xab, 0x04, 0x4d, 0x23, 0xf5, 0x5c, 0xa2, 0x1c, 0x53, 0xbc, 0xc9, 0x5f, 0x82, + 0xc9, 0xc8, 0xed, 0x52, 0xbf, 0x2f, 0x0c, 0x8f, 0x05, 0x61, 0x00, 0xd8, 0x10, 0x45, 0xa8, 0x60, + 0x6c, 0x13, 0x70, 0xb9, 0xc6, 0x16, 0x50, 0xe9, 0x89, 0x3c, 0x1b, 0x5b, 0x4a, 0x45, 0x39, 0x6a, + 0x0c, 0x72, 0x1f, 0x26, 0x85, 0x9f, 0x87, 0x72, 0xe8, 0x59, 0xcb, 0xc9, 0x14, 0x22, 0x5c, 0x49, + 0xe2, 0x2e, 0x10, 0xff, 0x43, 0x54, 0xec, 0xec, 0x8f, 0xc0, 0x09, 0xf3, 0xf3, 0xda, 0x57, 0x81, + 0xa0, 0xdf, 0xe9, 0x6c, 0x3a, 0xcd, 0x9d, 0x3b, 0xae, 0xd7, 0xf2, 0xef, 0xf1, 0xa5, 0x6f, 0x11, + 0xca, 0x81, 0x0c, 0xd1, 0x0d, 0xe5, 0xa8, 0xd1, 0x6b, 0xa7, 0x8a, 0xdd, 0x0d, 0x31, 0xc6, 0xb1, + 0x7f, 0x6f, 0x0c, 0x26, 0x65, 0x3c, 0xf9, 0x03, 0x88, 0x84, 0xd8, 0x49, 0xdc, 0x3f, 0xaf, 0xe4, + 0x12, 0x06, 0x3f, 0x34, 0x0c, 0x22, 0x4c, 0x85, 0x41, 0xbc, 0x96, 0x0f, 0xbb, 0xc3, 0x63, 0x20, + 0xbe, 0x5b, 0x84, 0x99, 0x54, 0x7c, 0x7e, 0x2a, 0x95, 0xb7, 0xf5, 0xbe, 0xa4, 0xf2, 0x26, 0x61, + 0x22, 0x9d, 0x7b, 0x7e, 0x7e, 0x93, 0x7f, 0x91, 0xd9, 0x3d, 0x2f, 0x8f, 0xd6, 0xe2, 0x07, 0xc7, + 0xa3, 0xf5, 0xbf, 0x5a, 0xf0, 0xe8, 0xd0, 0x2c, 0x13, 0x3c, 0x5f, 0x5b, 0x90, 0x84, 0xca, 0xf5, + 0x22, 0xe7, 0xcc, 0x3d, 0xfa, 0xae, 0x3a, 0x9d, 0x62, 0x2b, 0xcd, 0x9e, 0xbc, 0x00, 0x53, 0x5c, + 0x1f, 0x64, 0x2b, 0x67, 0x44, 0x7b, 0xf2, 0xaa, 0x8d, 0x5f, 0xba, 0x34, 0x8c, 0x72, 0x4c, 0x60, + 0xd9, 0xdf, 0xb6, 0x60, 0x6e, 0x58, 0xf6, 0xae, 0x63, 0x68, 0x72, 0x7f, 0x25, 0x15, 0x49, 0x52, + 0x1d, 0x88, 0x24, 0x49, 0x99, 0x82, 0x54, 0xd0, 0x88, 0x61, 0x85, 0x29, 0x1c, 0x11, 0x28, 0xf1, + 0xfb, 0x05, 0x98, 0x95, 0x22, 0xc6, 0x4a, 0xf8, 0x4b, 0x89, 0xf8, 0x97, 0x9f, 0x4c, 0xc5, 0xbf, + 0x5c, 0x4c, 0xe3, 0xff, 0x45, 0xf0, 0xcb, 0x07, 0x2b, 0xf8, 0xe5, 0x6b, 0x45, 0xb8, 0x94, 0x99, + 0x27, 0x8b, 0x7c, 0x35, 0x63, 0xa7, 0xb8, 0x93, 0x73, 0x42, 0x2e, 0x1d, 0x27, 0x7b, 0xb6, 0x11, + 0x23, 0xbf, 0x62, 0x46, 0x6a, 0x88, 0xd5, 0x7f, 0xeb, 0x0c, 0x52, 0x8b, 0x9d, 0x34, 0x68, 0xe3, + 0xc1, 0x3e, 0x75, 0xf6, 0xe7, 0x60, 0xa9, 0xff, 0x5a, 0x01, 0xae, 0x1c, 0xb7, 0x65, 0x3f, 0xa0, + 0x51, 0x8e, 0x61, 0x22, 0xca, 0xf1, 0x01, 0xa9, 0x36, 0x67, 0x12, 0xf0, 0xf8, 0x0f, 0xc7, 0xf5, + 0xbe, 0x3b, 0x38, 0x61, 0x8f, 0x65, 0x5b, 0x98, 0x64, 0xaa, 0xaf, 0x4a, 0x08, 0x1f, 0xef, 0x0d, + 0x93, 0x0d, 0x51, 0xfc, 0xde, 0x7e, 0xf5, 0x7c, 0x9c, 0x50, 0x46, 0x16, 0xa2, 0xaa, 0x44, 0xae, + 0x40, 0x29, 0x10, 0x50, 0x15, 0xd7, 0x25, 0xbd, 0x6b, 0x44, 0x19, 0x6a, 0x28, 0xf9, 0x82, 0x71, + 0x56, 0x18, 0x3f, 0xab, 0xbc, 0x49, 0x87, 0x39, 0x0d, 0xbd, 0x09, 0xa5, 0x50, 0x65, 0x2d, 0x17, + 0xd3, 0xe9, 0xf9, 0x63, 0x86, 0x0b, 0x3a, 0x9b, 0xb4, 0xa3, 0x52, 0x98, 0x8b, 0xef, 0xd3, 0x09, + 0xce, 0x35, 0x49, 0x62, 0xeb, 0xb3, 0xb7, 0xb8, 0xd4, 0x80, 0xc1, 0x73, 0x37, 0x89, 0x60, 0x52, + 0x3e, 0x5d, 0x2c, 0x6f, 0x5b, 0xd7, 0x72, 0x8a, 0xbb, 0x91, 0x5e, 0xd9, 0xfc, 0x48, 0xab, 0x6c, + 0x4e, 0x8a, 0x95, 0xfd, 0x03, 0x0b, 0x2a, 0x72, 0x8c, 0x3c, 0x80, 0xb8, 0xc9, 0xbb, 0xc9, 0xb8, + 0xc9, 0xab, 0xb9, 0x2c, 0xe1, 0x43, 0x82, 0x26, 0xef, 0xc2, 0x94, 0x99, 0xb1, 0x92, 0x7c, 0xca, + 0xd8, 0x82, 0xac, 0x51, 0xb2, 0xb2, 0xa9, 0x4d, 0x2a, 0xde, 0x9e, 0xec, 0x7f, 0x5a, 0xd6, 0xad, + 0xc8, 0x0f, 0xce, 0xe6, 0xc8, 0xb7, 0x0e, 0x1d, 0xf9, 0xe6, 0xc0, 0x1b, 0xcb, 0x7f, 0xe0, 0xbd, + 0x0e, 0x25, 0xb5, 0x2c, 0x4a, 0x6d, 0xea, 0x29, 0xd3, 0x4d, 0x9b, 0xa9, 0x64, 0x8c, 0x98, 0x31, + 0x5d, 0xf8, 0x01, 0x38, 0xb6, 0x84, 0xab, 0xe5, 0x5a, 0x93, 0x21, 0x6f, 0x41, 0xe5, 0x9e, 0x1f, + 0xec, 0x74, 0x7c, 0x87, 0x3f, 0x15, 0x01, 0x79, 0x78, 0x06, 0x68, 0x6b, 0xb6, 0x88, 0x95, 0xb9, + 0x13, 0xd3, 0x47, 0x93, 0x19, 0xa9, 0xc1, 0x4c, 0xd7, 0xf5, 0x90, 0x3a, 0x2d, 0x1d, 0x1e, 0x39, + 0x2e, 0xd2, 0xb4, 0x2b, 0xdd, 0x7e, 0x2d, 0x09, 0xc6, 0x34, 0x3e, 0xb7, 0x3c, 0x05, 0x09, 0x53, + 0x87, 0xcc, 0xc5, 0xbc, 0x3e, 0xfa, 0x60, 0x4c, 0x9a, 0x4f, 0x44, 0xb0, 0x48, 0xb2, 0x1c, 0x53, + 0xbc, 0xc9, 0xe7, 0xa1, 0x14, 0xaa, 0x47, 0x41, 0x8b, 0x39, 0x9e, 0x7a, 0xf4, 0xc3, 0xa0, 0xba, + 0x2b, 0xf5, 0xcb, 0xa0, 0x9a, 0x21, 0x59, 0x85, 0x8b, 0xca, 0x76, 0x93, 0x78, 0xdf, 0x70, 0x22, + 0xce, 0x27, 0x86, 0x19, 0x70, 0xcc, 0xac, 0xc5, 0x74, 0x5b, 0x9e, 0x09, 0x56, 0xdc, 0xc4, 0x1a, + 0x97, 0x97, 0x7c, 0xfe, 0xb5, 0x50, 0x42, 0x0f, 0x8b, 0xfe, 0x2d, 0x8d, 0x10, 0xfd, 0xdb, 0x80, + 0x4b, 0x69, 0x10, 0x4f, 0x14, 0xc7, 0x73, 0xd3, 0x19, 0x5b, 0xe8, 0x7a, 0x16, 0x12, 0x66, 0xd7, + 0x25, 0x77, 0xa0, 0x1c, 0x50, 0x7e, 0xca, 0xab, 0x29, 0x27, 0xb6, 0x13, 0xbb, 0xeb, 0xa2, 0x22, + 0x80, 0x31, 0x2d, 0xd6, 0xef, 0x4e, 0x32, 0x71, 0xfa, 0xeb, 0x39, 0xbe, 0x1a, 0x2e, 0xfb, 0x7e, + 0x48, 0x02, 0x47, 0xfb, 0xdf, 0xcd, 0xc0, 0xb9, 0x84, 0x01, 0x8a, 0x3c, 0x05, 0x45, 0x9e, 0x39, + 0x8f, 0xaf, 0x56, 0xa5, 0x78, 0x45, 0x15, 0x8d, 0x23, 0x60, 0xe4, 0x97, 0x2c, 0x98, 0xe9, 0x25, + 0x2e, 0x70, 0xd4, 0x42, 0x3e, 0xa2, 0xd5, 0x36, 0x79, 0x2b, 0x64, 0x3c, 0x39, 0x92, 0x64, 0x86, + 0x69, 0xee, 0x6c, 0x3d, 0x90, 0x3e, 0xef, 0x1d, 0x1a, 0x70, 0x6c, 0xa9, 0xe8, 0x69, 0x12, 0x4b, + 0x49, 0x30, 0xa6, 0xf1, 0x59, 0x0f, 0xf3, 0xaf, 0x1b, 0xe5, 0x65, 0xd8, 0x9a, 0x22, 0x80, 0x31, + 0x2d, 0xf2, 0x0a, 0x4c, 0xcb, 0x7c, 0xd9, 0xeb, 0x7e, 0xeb, 0xba, 0x13, 0x6e, 0xcb, 0x23, 0x9f, + 0x3e, 0xa2, 0x2e, 0x25, 0xa0, 0x98, 0xc2, 0xe6, 0xdf, 0x16, 0x27, 0x25, 0xe7, 0x04, 0x26, 0x92, + 0x2f, 0xb2, 0x2c, 0x25, 0xc1, 0x98, 0xc6, 0x27, 0xcf, 0x1a, 0xdb, 0x90, 0xf0, 0x8e, 0xd0, 0xab, + 0x41, 0xc6, 0x56, 0x54, 0x83, 0x99, 0x3e, 0x3f, 0x21, 0xb7, 0x14, 0x50, 0xce, 0x47, 0xcd, 0xf0, + 0x76, 0x12, 0x8c, 0x69, 0x7c, 0xf2, 0x32, 0x9c, 0x0b, 0xd8, 0x62, 0xab, 0x09, 0x08, 0x97, 0x09, + 0x7d, 0x23, 0x8e, 0x26, 0x10, 0x93, 0xb8, 0xe4, 0x55, 0x38, 0x1f, 0xe7, 0x54, 0x55, 0x04, 0x84, + 0x0f, 0x85, 0x4e, 0xf0, 0x57, 0x4b, 0x23, 0xe0, 0x60, 0x1d, 0xf2, 0xd7, 0x61, 0xd6, 0x68, 0x89, + 0x15, 0xaf, 0x45, 0xef, 0xcb, 0xbc, 0x97, 0xfc, 0x85, 0xb1, 0xa5, 0x14, 0x0c, 0x07, 0xb0, 0xc9, + 0xc7, 0x61, 0xba, 0xe9, 0x77, 0x3a, 0x7c, 0x8d, 0x13, 0xaf, 0x81, 0x88, 0x04, 0x97, 0x22, 0x15, + 0x68, 0x02, 0x82, 0x29, 0x4c, 0x72, 0x03, 0x88, 0xbf, 0xc9, 0xd4, 0x2b, 0xda, 0x7a, 0x95, 0x7a, + 0x54, 0x6a, 0x1c, 0xe7, 0x92, 0x11, 0x37, 0xb7, 0x06, 0x30, 0x30, 0xa3, 0x16, 0xcf, 0x0f, 0x68, + 0x44, 0x28, 0x4f, 0xe7, 0x91, 0x91, 0x3c, 0x6d, 0xcf, 0x39, 0x32, 0x3c, 0x39, 0x80, 0x09, 0x11, + 0x00, 0x95, 0x4f, 0xa6, 0x4b, 0xf3, 0x61, 0x80, 0x78, 0x8f, 0x10, 0xa5, 0x28, 0x39, 0x91, 0x9f, + 0x87, 0xf2, 0xa6, 0x7a, 0x25, 0x86, 0xa7, 0xb7, 0x1c, 0x79, 0x5f, 0x4c, 0x3d, 0x78, 0x14, 0xdb, + 0x2b, 0x34, 0x00, 0x63, 0x96, 0xe4, 0x69, 0xa8, 0x5c, 0x5f, 0xaf, 0xe9, 0x51, 0x78, 0x9e, 0xf7, + 0xfe, 0x38, 0xab, 0x82, 0x26, 0x80, 0xcd, 0x30, 0xad, 0xbe, 0x91, 0xa4, 0x5b, 0x40, 0x86, 0x36, + 0xc6, 0xb0, 0xb9, 0x9f, 0x03, 0x36, 0xe6, 0x2e, 0xa4, 0xb0, 0x65, 0x39, 0x6a, 0x0c, 0xf2, 0x26, + 0x54, 0xe4, 0x7e, 0xc1, 0xd7, 0xa6, 0x8b, 0xa7, 0x8b, 0x7e, 0xc7, 0x98, 0x04, 0x9a, 0xf4, 0xf8, + 0x05, 0x35, 0x7f, 0x3c, 0x83, 0x5e, 0xeb, 0x77, 0x3a, 0x73, 0x97, 0xf8, 0xba, 0x19, 0x5f, 0x50, + 0xc7, 0x20, 0x34, 0xf1, 0xc8, 0xf3, 0xca, 0x5f, 0xed, 0xe1, 0xc4, 0x8d, 0xbd, 0xf6, 0x57, 0xd3, + 0x4a, 0xf7, 0x90, 0x00, 0x99, 0x47, 0x8e, 0x70, 0x14, 0xdb, 0x84, 0x79, 0xa5, 0xf1, 0x0d, 0x4e, + 0x92, 0xb9, 0xb9, 0x84, 0xed, 0x68, 0xfe, 0xce, 0x50, 0x4c, 0x3c, 0x84, 0x0a, 0xd9, 0x84, 0x82, + 0xd3, 0xd9, 0x9c, 0x7b, 0x34, 0x0f, 0xd5, 0xb5, 0xb6, 0x5a, 0x97, 0x23, 0x8a, 0x3b, 0xb5, 0xd6, + 0x56, 0xeb, 0xc8, 0x88, 0x13, 0x17, 0xc6, 0x9d, 0xce, 0x66, 0x38, 0x37, 0xcf, 0xe7, 0x6c, 0x6e, + 0x4c, 0x62, 0xe3, 0xc1, 0x6a, 0x3d, 0x44, 0xce, 0xc2, 0xfe, 0xe2, 0x98, 0xbe, 0x25, 0xd2, 0xc9, + 0xc6, 0xdf, 0x36, 0x27, 0x90, 0x38, 0xee, 0xdc, 0xca, 0x6d, 0x02, 0x49, 0xf5, 0xe2, 0xdc, 0xd0, + 0xe9, 0xd3, 0xd3, 0x4b, 0x46, 0x2e, 0x59, 0xca, 0x92, 0x89, 0xd4, 0xc5, 0xe9, 0x39, 0xb9, 0x60, + 0xd8, 0x5f, 0xaa, 0x68, 0x2b, 0x68, 0xca, 0xd7, 0x2b, 0x80, 0xa2, 0x1b, 0x46, 0xae, 0x9f, 0x63, + 0x50, 0x78, 0x2a, 0x03, 0x39, 0x8f, 0x39, 0xe1, 0x00, 0x14, 0xac, 0x18, 0x4f, 0xaf, 0xed, 0x7a, + 0xf7, 0xe5, 0xe7, 0xbf, 0x9e, 0xbb, 0x13, 0x97, 0xe0, 0xc9, 0x01, 0x28, 0x58, 0x91, 0xbb, 0x62, + 0x50, 0x17, 0xf2, 0xe8, 0xeb, 0xda, 0x6a, 0x3d, 0xc5, 0x2f, 0x39, 0xb8, 0xef, 0x42, 0x21, 0xec, + 0xba, 0x52, 0x5d, 0x1a, 0x91, 0x57, 0x63, 0x6d, 0x25, 0x8b, 0x57, 0x63, 0x6d, 0x05, 0x19, 0x13, + 0xf2, 0x15, 0x0b, 0xc0, 0xe9, 0x6e, 0x3a, 0x61, 0xe8, 0xb4, 0xb4, 0x75, 0x66, 0xc4, 0x47, 0x56, + 0x6a, 0x9a, 0x5e, 0x8a, 0x35, 0x77, 0x5b, 0x8e, 0xa1, 0x68, 0x70, 0x26, 0x6f, 0xc1, 0xa4, 0x23, + 0x5e, 0xb1, 0x94, 0x1e, 0xf8, 0xf9, 0x3c, 0xcd, 0x9a, 0x92, 0x80, 0x9b, 0x69, 0x24, 0x08, 0x15, + 0x43, 0xc6, 0x3b, 0x0a, 0x1c, 0xba, 0xe5, 0xee, 0x48, 0xe3, 0x50, 0x63, 0xe4, 0x77, 0x56, 0x18, + 0xb1, 0x2c, 0xde, 0x12, 0x84, 0x8a, 0x21, 0xf9, 0x05, 0x0b, 0xce, 0x75, 0x1d, 0xcf, 0xd1, 0x71, + 0x95, 0xf9, 0x44, 0xdf, 0x9a, 0x91, 0x9a, 0xb1, 0x86, 0xb8, 0x66, 0x32, 0xc2, 0x24, 0x5f, 0xb2, + 0x0b, 0x13, 0x0e, 0x7f, 0x5f, 0x57, 0x1e, 0xc5, 0x30, 0x8f, 0xb7, 0x7a, 0x53, 0x6d, 0xc0, 0x17, + 0x17, 0xf9, 0x8a, 0xaf, 0xe4, 0x46, 0x7e, 0xdd, 0x82, 0x49, 0xe1, 0x1c, 0xce, 0x14, 0x52, 0xf6, + 0xed, 0x9f, 0x3d, 0x83, 0x97, 0x0c, 0xa4, 0xe3, 0xba, 0x74, 0x3f, 0xfa, 0x90, 0xf6, 0x7c, 0x15, + 0xa5, 0x87, 0xba, 0xae, 0x2b, 0xe9, 0x98, 0xea, 0xdb, 0x75, 0xee, 0x27, 0x5e, 0xd1, 0x31, 0x55, + 0xdf, 0xb5, 0x14, 0x0c, 0x07, 0xb0, 0xe7, 0x3f, 0x0e, 0x53, 0xa6, 0x1c, 0x27, 0x72, 0x7f, 0xff, + 0x51, 0x01, 0x80, 0x77, 0x95, 0xc8, 0xc5, 0xd2, 0xe5, 0x89, 0x9b, 0xb7, 0xfd, 0x56, 0x4e, 0xaf, + 0x79, 0x1a, 0x29, 0x55, 0x40, 0x66, 0x69, 0xde, 0xf6, 0x5b, 0x28, 0x99, 0x90, 0x36, 0x8c, 0xf7, + 0x9c, 0x68, 0x3b, 0xff, 0xfc, 0x2d, 0x25, 0x11, 0x94, 0x1c, 0x6d, 0x23, 0x67, 0x40, 0xde, 0xb1, + 0x62, 0xcf, 0x9e, 0x42, 0x1e, 0xb9, 0x67, 0xe3, 0x36, 0x5b, 0x90, 0xbe, 0x3c, 0xa9, 0x14, 0xac, + 0x69, 0x0f, 0x9f, 0xf9, 0x77, 0x2d, 0x98, 0x32, 0x51, 0x33, 0xba, 0xe9, 0xe7, 0xcc, 0x6e, 0xca, + 0xb3, 0x3d, 0xcc, 0x1e, 0xff, 0xef, 0x16, 0x00, 0xf6, 0xbd, 0x46, 0xbf, 0xdb, 0x65, 0x6a, 0xbb, + 0xf6, 0xf2, 0xb7, 0x8e, 0xed, 0xe5, 0x3f, 0x76, 0x42, 0x2f, 0xff, 0xc2, 0x89, 0xbc, 0xfc, 0xc7, + 0x4f, 0xee, 0xe5, 0x5f, 0x1c, 0xee, 0xe5, 0x6f, 0x7f, 0xd3, 0x82, 0xf3, 0x03, 0xfb, 0x15, 0xd3, + 0xa4, 0x03, 0xdf, 0x8f, 0x86, 0x78, 0x88, 0x62, 0x0c, 0x42, 0x13, 0x8f, 0x2c, 0xc3, 0xac, 0x7c, + 0xa6, 0xa4, 0xd1, 0xeb, 0xb8, 0x99, 0xb9, 0x75, 0x36, 0x52, 0x70, 0x1c, 0xa8, 0x61, 0xff, 0xb6, + 0x05, 0x15, 0x23, 0x22, 0x9f, 0x7d, 0x07, 0x77, 0x13, 0x96, 0x62, 0xc4, 0x2f, 0xb4, 0xf0, 0xab, + 0x2e, 0x01, 0x13, 0xd7, 0xd0, 0x6d, 0x23, 0x89, 0x7d, 0x7c, 0x0d, 0xcd, 0x4a, 0x51, 0x42, 0x45, + 0x7a, 0x72, 0xda, 0xe3, 0x8d, 0x5e, 0x30, 0xd3, 0x93, 0xd3, 0x1e, 0x72, 0x08, 0x67, 0xc7, 0x8e, + 0x14, 0xd2, 0x03, 0xd8, 0x78, 0x10, 0xc6, 0x09, 0x22, 0x14, 0x30, 0xf2, 0x04, 0x14, 0xa8, 0xd7, + 0x92, 0xf6, 0x0f, 0xfd, 0x7a, 0xed, 0x55, 0xaf, 0x85, 0xac, 0xdc, 0xbe, 0x05, 0x53, 0xc2, 0xfb, + 0xf9, 0x35, 0xba, 0x77, 0xec, 0xe7, 0x70, 0xd9, 0x68, 0x4f, 0x3d, 0x87, 0xcb, 0xaa, 0xb3, 0x72, + 0xfb, 0x9f, 0x58, 0x90, 0x7a, 0x23, 0xc9, 0xb8, 0x81, 0xb1, 0x86, 0xde, 0xc0, 0x98, 0x56, 0xfb, + 0xb1, 0x43, 0xad, 0xf6, 0x37, 0x80, 0x74, 0xd9, 0x54, 0x48, 0x2e, 0xb4, 0x85, 0xe4, 0x53, 0x12, + 0x6b, 0x03, 0x18, 0x98, 0x51, 0xcb, 0xfe, 0xc7, 0x42, 0x58, 0xf3, 0xd5, 0xa4, 0xa3, 0x1b, 0xa0, + 0x0f, 0x45, 0x4e, 0x4a, 0xda, 0xdf, 0x46, 0xb4, 0x5d, 0x0f, 0xe6, 0xd1, 0x8a, 0x3b, 0x52, 0x4e, + 0x79, 0xce, 0xcd, 0xfe, 0x7d, 0x21, 0xab, 0xf9, 0xac, 0xd2, 0xd1, 0xb2, 0x76, 0x93, 0xb2, 0x5e, + 0xcf, 0x6b, 0xad, 0xcc, 0x96, 0x91, 0x2c, 0x00, 0xf4, 0x68, 0xd0, 0xa4, 0x5e, 0xa4, 0xe2, 0x92, + 0x8a, 0x32, 0x42, 0x56, 0x97, 0xa2, 0x81, 0x61, 0x7f, 0x83, 0x4d, 0xa0, 0xf8, 0xa1, 0x68, 0x72, + 0x25, 0xed, 0xea, 0x9a, 0x9e, 0x1c, 0xda, 0xd3, 0xd5, 0x88, 0x56, 0x19, 0x3b, 0x22, 0x5a, 0xe5, + 0x19, 0x98, 0x0c, 0xfc, 0x0e, 0xad, 0x05, 0x5e, 0xda, 0x47, 0x07, 0x59, 0x31, 0xde, 0x44, 0x05, + 0xb7, 0x7f, 0xd5, 0x82, 0xd9, 0x74, 0x38, 0x5d, 0xee, 0xfe, 0xb7, 0x66, 0xcc, 0x7f, 0xe1, 0xe4, + 0x31, 0xff, 0xf6, 0x9f, 0x16, 0x61, 0x36, 0xfd, 0x80, 0x1d, 0xe3, 0xec, 0x72, 0x63, 0x5b, 0x6a, + 0xf5, 0x17, 0x56, 0x36, 0x01, 0xd3, 0xe3, 0x65, 0x6c, 0xe8, 0x78, 0xb9, 0x06, 0x65, 0xbf, 0xa7, + 0x0e, 0xfc, 0x42, 0xb8, 0x2b, 0xca, 0x58, 0x73, 0x4b, 0x01, 0xde, 0xdb, 0xaf, 0x5e, 0x88, 0x05, + 0xd0, 0xc5, 0x18, 0x57, 0x25, 0x3f, 0xad, 0x2c, 0x15, 0xe3, 0x89, 0x2c, 0x3a, 0xda, 0x52, 0x31, + 0x13, 0xd7, 0x1f, 0x66, 0xac, 0x28, 0x9e, 0x24, 0x9b, 0xc7, 0x44, 0x8e, 0xd9, 0x3c, 0xee, 0x40, + 0x59, 0xda, 0x56, 0x4f, 0x95, 0xc5, 0x82, 0x13, 0xbe, 0xad, 0x08, 0x60, 0x4c, 0x2b, 0x95, 0x26, + 0xa4, 0x94, 0x6b, 0x9a, 0x90, 0x97, 0x61, 0x72, 0xd3, 0x69, 0xee, 0xf8, 0x5b, 0x5b, 0x5c, 0x3f, + 0x2f, 0xd7, 0x7f, 0x42, 0x35, 0x5c, 0x5d, 0x14, 0x67, 0x0c, 0x29, 0x55, 0x83, 0x69, 0x05, 0x54, + 0xb9, 0x23, 0x2b, 0xb3, 0xaf, 0xd6, 0x0a, 0xb4, 0xa3, 0x72, 0x88, 0x06, 0x16, 0x79, 0x16, 0x4a, + 0x2d, 0x37, 0x14, 0x4f, 0x2c, 0x57, 0x92, 0xfe, 0xd8, 0xcb, 0xb2, 0x1c, 0x35, 0x06, 0x79, 0x45, + 0x7b, 0xab, 0x4d, 0xc5, 0xa1, 0x12, 0xda, 0x53, 0xed, 0x90, 0x50, 0x09, 0xe9, 0x8c, 0xfb, 0x0e, + 0x9b, 0x98, 0x91, 0xdb, 0xdc, 0x71, 0x3d, 0x91, 0x1a, 0x82, 0xad, 0x16, 0xcf, 0xc0, 0x24, 0x95, + 0x8f, 0x3c, 0x8b, 0xab, 0x13, 0x3d, 0x58, 0xd4, 0xdb, 0xce, 0x0a, 0x4e, 0x6a, 0x30, 0xa3, 0x2e, + 0x8c, 0xd5, 0x7d, 0x97, 0x48, 0x69, 0xa3, 0xed, 0xeb, 0xcb, 0x49, 0x30, 0xa6, 0xf1, 0xed, 0x2f, + 0x40, 0xc5, 0x50, 0xc4, 0xb8, 0xce, 0x72, 0xdf, 0x69, 0x46, 0xe9, 0xbd, 0xfe, 0x2a, 0x2b, 0x44, + 0x01, 0xe3, 0xd7, 0x72, 0x22, 0xc2, 0x2d, 0xb5, 0xd7, 0xcb, 0xb8, 0x36, 0x09, 0x65, 0xc4, 0x02, + 0xda, 0xa6, 0xf7, 0xd5, 0xbb, 0x1a, 0x8a, 0x18, 0xb2, 0x42, 0x14, 0x30, 0xfb, 0x59, 0x28, 0xa9, + 0xc4, 0x63, 0x3c, 0x7b, 0x8f, 0xba, 0x32, 0x32, 0xb3, 0xf7, 0xf8, 0x41, 0x84, 0x1c, 0x62, 0xbf, + 0x01, 0x25, 0x95, 0x1f, 0xed, 0x68, 0x6c, 0xb6, 0xfd, 0x86, 0x9e, 0x7b, 0xdd, 0x0f, 0x23, 0x95, + 0xd4, 0x4d, 0xdc, 0x6a, 0xdf, 0x5c, 0xe1, 0x65, 0xa8, 0xa1, 0xf6, 0x9f, 0x59, 0x50, 0xd9, 0xd8, + 0x58, 0xd5, 0xc6, 0x2e, 0x84, 0x87, 0x43, 0xd1, 0x42, 0xb5, 0xad, 0x88, 0x9a, 0xee, 0x33, 0x62, + 0x25, 0x9a, 0x3f, 0xd8, 0xaf, 0x3e, 0xdc, 0xc8, 0xc4, 0xc0, 0x21, 0x35, 0xc9, 0x0a, 0x5c, 0x30, + 0x21, 0x32, 0xd9, 0x86, 0xd4, 0x0b, 0xf8, 0xab, 0xe0, 0x8d, 0x41, 0x30, 0x66, 0xd5, 0x49, 0x93, + 0x92, 0x2a, 0xae, 0xf9, 0xc0, 0x78, 0x63, 0x10, 0x8c, 0x59, 0x75, 0xec, 0xe7, 0x61, 0x26, 0xe5, + 0xd7, 0x71, 0x8c, 0x24, 0x47, 0xbf, 0x53, 0x80, 0x29, 0xf3, 0x7a, 0xff, 0x18, 0x7b, 0xf6, 0xf1, + 0x55, 0xa1, 0x8c, 0x2b, 0xf9, 0xc2, 0x09, 0xaf, 0xe4, 0x4d, 0x1f, 0x88, 0xf1, 0xb3, 0xf5, 0x81, + 0x28, 0xe6, 0xe3, 0x03, 0x61, 0xf8, 0xea, 0x4c, 0x3c, 0x38, 0x5f, 0x9d, 0xdf, 0x2a, 0xc2, 0x74, + 0x32, 0x6b, 0xee, 0x31, 0x7a, 0xf2, 0xd9, 0x81, 0x9e, 0x3c, 0xe1, 0x1d, 0x60, 0x61, 0xd4, 0x3b, + 0xc0, 0xf1, 0x51, 0xef, 0x00, 0x8b, 0xa7, 0xb8, 0x03, 0x1c, 0xbc, 0xc1, 0x9b, 0x38, 0xf6, 0x0d, + 0xde, 0x27, 0xf4, 0x46, 0x31, 0x99, 0x70, 0x7b, 0x8b, 0x37, 0x0b, 0x92, 0xec, 0x86, 0x25, 0xbf, + 0x95, 0xe9, 0x8e, 0x5d, 0x3a, 0x42, 0x7d, 0x08, 0x32, 0xbd, 0x90, 0x4f, 0xee, 0x66, 0xf0, 0xf0, + 0x09, 0x3c, 0x90, 0x5f, 0x84, 0x8a, 0x1c, 0x4f, 0xfc, 0xc0, 0x09, 0xc9, 0xc3, 0x6a, 0x23, 0x06, + 0xa1, 0x89, 0xc7, 0x06, 0x46, 0x2f, 0x9e, 0x20, 0xfc, 0x36, 0xba, 0x92, 0xbc, 0x8d, 0x5e, 0x4f, + 0x82, 0x31, 0x8d, 0x6f, 0x7f, 0x1e, 0x2e, 0x65, 0x9a, 0x1d, 0xf9, 0x95, 0x0f, 0x3f, 0x0b, 0xd1, + 0x96, 0x44, 0x30, 0xc4, 0x48, 0x3d, 0xa6, 0x33, 0x7f, 0x67, 0x28, 0x26, 0x1e, 0x42, 0xc5, 0xfe, + 0xcd, 0x02, 0x4c, 0x27, 0x1f, 0x97, 0x26, 0xf7, 0xf4, 0x25, 0x45, 0x2e, 0xf7, 0x23, 0x82, 0xac, + 0x91, 0x89, 0x75, 0xe8, 0xe5, 0xe6, 0x3d, 0x3e, 0xbe, 0x36, 0x75, 0x5a, 0xd8, 0xb3, 0x63, 0x2c, + 0x6f, 0x15, 0x25, 0x3b, 0xfe, 0x44, 0x73, 0x1c, 0xb4, 0x2d, 0x6d, 0x57, 0xb9, 0x73, 0x8f, 0x83, + 0x8f, 0x35, 0x2b, 0x34, 0xd8, 0xb2, 0xbd, 0x65, 0x97, 0x06, 0xee, 0x96, 0x4b, 0x5b, 0x32, 0x4b, + 0x3f, 0x5f, 0xb9, 0xdf, 0x90, 0x65, 0xa8, 0xa1, 0xf6, 0x3b, 0x63, 0x50, 0xe6, 0x39, 0xe6, 0xae, + 0x05, 0x7e, 0x97, 0x3f, 0x3b, 0x1a, 0x1a, 0x76, 0x02, 0xd9, 0x6d, 0x37, 0x46, 0x7d, 0x49, 0x38, + 0xa6, 0x28, 0x43, 0x3c, 0x8c, 0x12, 0x4c, 0x70, 0x24, 0x3d, 0x28, 0x6d, 0xc9, 0x9c, 0xd8, 0xb2, + 0xef, 0x46, 0xcc, 0xeb, 0xaa, 0x32, 0x6c, 0x8b, 0x26, 0x50, 0xff, 0x50, 0x73, 0xb1, 0x1d, 0x98, + 0x49, 0x25, 0x09, 0xca, 0x3d, 0x93, 0xf6, 0xff, 0x1c, 0x87, 0xb2, 0x8e, 0x2d, 0x24, 0x1f, 0x4b, + 0x18, 0x6d, 0x63, 0x1d, 0x5e, 0x5a, 0x5b, 0xd9, 0xb9, 0x49, 0x23, 0xa7, 0x0c, 0xb0, 0x4f, 0x40, + 0xa1, 0x1f, 0x74, 0xd2, 0x56, 0x99, 0xdb, 0xb8, 0x8a, 0xac, 0xdc, 0x8c, 0x87, 0x2c, 0x3c, 0xd0, + 0x78, 0x48, 0xb6, 0x4b, 0x6e, 0xfa, 0xad, 0xbd, 0xf4, 0x1b, 0x7a, 0x75, 0xbf, 0xb5, 0x87, 0x1c, + 0x42, 0x5e, 0x81, 0x69, 0x19, 0xe4, 0xa9, 0x94, 0x98, 0x22, 0xd7, 0x53, 0xb5, 0xb3, 0xce, 0x46, + 0x02, 0x8a, 0x29, 0x6c, 0xb6, 0xcb, 0xb2, 0x63, 0x03, 0xcf, 0x8f, 0x3e, 0x91, 0xbc, 0xd9, 0xbf, + 0xd1, 0xb8, 0x75, 0x93, 0x1b, 0x8f, 0x35, 0x46, 0x22, 0x8e, 0x74, 0xf2, 0xc8, 0x38, 0xd2, 0x65, + 0x41, 0x9b, 0x49, 0xcb, 0x77, 0x94, 0xa9, 0xfa, 0x15, 0x45, 0x97, 0x95, 0x1d, 0x7a, 0x76, 0xd1, + 0x35, 0xb3, 0x22, 0x6e, 0xcb, 0xef, 0x5f, 0xc4, 0xad, 0x7d, 0x1b, 0x66, 0x52, 0xfd, 0xa7, 0x8c, + 0x7a, 0x56, 0xb6, 0x51, 0xef, 0x78, 0xaf, 0xf0, 0xfd, 0x73, 0x0b, 0xce, 0x0f, 0xac, 0x48, 0xc7, + 0x0d, 0x7d, 0x4e, 0xef, 0x8d, 0x63, 0xa7, 0xdf, 0x1b, 0x0b, 0x27, 0xdb, 0x1b, 0xeb, 0x9b, 0xdf, + 0xfb, 0xe1, 0xe5, 0x87, 0xbe, 0xff, 0xc3, 0xcb, 0x0f, 0xfd, 0xc1, 0x0f, 0x2f, 0x3f, 0xf4, 0xce, + 0xc1, 0x65, 0xeb, 0x7b, 0x07, 0x97, 0xad, 0xef, 0x1f, 0x5c, 0xb6, 0xfe, 0xe0, 0xe0, 0xb2, 0xf5, + 0x5f, 0x0e, 0x2e, 0x5b, 0xdf, 0xfc, 0xe3, 0xcb, 0x0f, 0x7d, 0xea, 0x13, 0x71, 0x4f, 0x2d, 0xaa, + 0x9e, 0xe2, 0x3f, 0x3e, 0xac, 0xfa, 0x65, 0xb1, 0xb7, 0xd3, 0x5e, 0x64, 0x3d, 0xb5, 0xa8, 0x4b, + 0x54, 0x4f, 0xfd, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x29, 0xcc, 0x97, 0x3c, 0x4f, 0xab, 0x00, + 0x00, } func (m *ALBStatus) Marshal() (dAtA []byte, err error) { @@ -9875,8 +9876,16 @@ func (m *StepPluginStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Status) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status))) i-- - dAtA[i] = 0x5a + dAtA[i] = 0x62 + } + i-- + if m.Disabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 } + i-- + dAtA[i] = 0x58 i = encodeVarintGenerated(dAtA, i, uint64(m.Executions)) i-- dAtA[i] = 0x50 @@ -12837,6 +12846,7 @@ func (m *StepPluginStatus) Size() (n int) { l = len(m.Backoff) n += 1 + l + sovGenerated(uint64(l)) n += 1 + sovGenerated(uint64(m.Executions)) + n += 2 if m.Status != nil { l = len(m.Status) n += 1 + l + sovGenerated(uint64(l)) @@ -14767,6 +14777,7 @@ func (this *StepPluginStatus) String() string { `FinishedAt:` + strings.Replace(fmt.Sprintf("%v", this.FinishedAt), "Time", "v1.Time", 1) + `,`, `Backoff:` + fmt.Sprintf("%v", this.Backoff) + `,`, `Executions:` + fmt.Sprintf("%v", this.Executions) + `,`, + `Disabled:` + fmt.Sprintf("%v", this.Disabled) + `,`, `Status:` + valueToStringGenerated(this.Status) + `,`, `}`, }, "") @@ -34037,6 +34048,26 @@ func (m *StepPluginStatus) Unmarshal(dAtA []byte) error { } } case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Disabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Disabled = bool(v != 0) + case 12: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 0ba42b6407..c562635ac5 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1775,10 +1775,12 @@ message StepPluginStatus { optional int32 executions = 10; + optional bool disabled = 11; + // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - optional bytes status = 11; + optional bytes status = 12; } message StickinessConfig { diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 3d6dd3e2df..b4c6482cf4 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -5231,6 +5231,24 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, + "backoff": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "executions": { + SchemaProps: spec.SchemaProps{ + Type: []string{"integer"}, + Format: "int32", + }, + }, + "disabled": { + SchemaProps: spec.SchemaProps{ + Type: []string{"boolean"}, + Format: "", + }, + }, "status": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index af3b49b205..573d0bd7e9 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -1048,11 +1048,12 @@ type StepPluginStatus struct { FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,8,opt,name=finishedAt"` Backoff DurationString `json:"backoff,omitempty" protobuf:"bytes,9,opt,name=backoff,casttype=DurationString"` Executions int32 `json:"executions,omitempty" protobuf:"varint,10,opt,name=executions"` + Disabled bool `json:"disabled,omitempty" protobuf:"bytes,11,opt,name=disabled"` // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,11,opt,name=status"` + Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,12,opt,name=status"` } // StepPluginPhase is the overall phase of a StepPlugin diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 317529da06..609c8ec3f1 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -13,6 +13,11 @@ import ( log "github.com/sirupsen/logrus" ) +var ( + defaultControllerErrorBackoff = time.Second * 30 + defaultBackoffDelay = time.Second * 5 +) + type stepPluginContext struct { resolver plugin.Resolver log *log.Entry @@ -111,7 +116,7 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { spc.recordPhase(c, status) } - if status == nil { + if status == nil || status.Disabled { return nil } @@ -122,7 +127,7 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { } // Get the remaining time until the backoff + a little buffer - remaining := time.Until(status.UpdatedAt.Add(backoff)) + (5 * time.Second) + remaining := time.Until(status.UpdatedAt.Add(backoff)) + defaultBackoffDelay c.log.Debugf("queueing up rollout in %s because step plugin phase is %s", remaining, status.Phase) c.enqueueRolloutAfter(rollout, remaining) return nil @@ -142,15 +147,15 @@ func (spc *stepPluginContext) handleError(c *rolloutContext, e error) error { msg := fmt.Sprintf(conditions.RolloutReconciliationErrorMessage, e.Error()) c.recorder.Warnf(c.rollout, record.EventOptions{EventReason: conditions.RolloutReconciliationErrorReason}, msg) - c.log.Debug("queueing up rollout in 30s because of transient error") - c.enqueueRolloutAfter(c.rollout, 30*time.Second) + c.log.Debugf("queueing up rollout in %s because of transient error", defaultControllerErrorBackoff) + c.enqueueRolloutAfter(c.rollout, defaultControllerErrorBackoff) return nil } func (spc *stepPluginContext) recordPhase(c *rolloutContext, status *v1alpha1.StepPluginStatus) { - if status.Operation == v1alpha1.StepPluginOperationRun && status.Phase == v1alpha1.StepPluginPhaseSuccessful { - // If the run status is succesful, do not record event because the controller will record the RolloutStepCompleted + if status.Disabled || status.Operation == v1alpha1.StepPluginOperationRun && status.Phase == v1alpha1.StepPluginPhaseSuccessful { + // If the run status is successful, do not record event because the controller will record the RolloutStepCompleted return } @@ -174,28 +179,17 @@ func (spc *stepPluginContext) updateStatus(status *v1alpha1.RolloutStatus) { } } -func (spc *stepPluginContext) isStepPluginDisabled(stepIndex int32, step *v1alpha1.PluginStep) (bool, error) { - stepPlugin, err := spc.resolver.Resolve(stepIndex, *step, spc.log) - if err != nil { - return false, err - } - return !stepPlugin.Enabled(), nil -} - -func (spc *stepPluginContext) isStepPluginCompleted(stepIndex int32, step *v1alpha1.PluginStep) bool { +func (spc *stepPluginContext) isStepPluginCompleted(stepIndex int32, _ *v1alpha1.PluginStep) bool { if spc.hasError { // If there was a transient error during the reconcile, we should retry return false } - if disabled, err := spc.isStepPluginDisabled(stepIndex, step); err != nil { - // If there is an error, the plugin might not exist in the config. Assume it is not disabled. - spc.log.Errorf("cannot resolve step plugin %s at index %d. Assuming it is enabled.", step.Name, stepIndex) - } else if disabled { + runStatus := spc.findCurrentStepStatus(stepIndex, v1alpha1.StepPluginOperationRun) + if runStatus != nil && runStatus.Disabled { return true } - runStatus := spc.findCurrentStepStatus(stepIndex, v1alpha1.StepPluginOperationRun) isRunning := runStatus != nil && runStatus.Phase == v1alpha1.StepPluginPhaseRunning if isRunning { terminateStatus := spc.findCurrentStepStatus(stepIndex, v1alpha1.StepPluginOperationTerminate) diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index 18946a986f..536dfd0d94 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -8,9 +8,11 @@ import ( "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout/steps/plugin/mocks" logutil "github.com/argoproj/argo-rollouts/utils/log" + "github.com/argoproj/argo-rollouts/utils/record" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" ) @@ -26,18 +28,27 @@ func newStepPluginRollout() *v1alpha1.Rollout { return newCanaryRollout("foo", 3, nil, steps, ptr.To(int32(0)), intstr.FromInt(1), intstr.FromInt(0)) } -func newStepPluginStatus() *v1alpha1.StepPluginStatus { - return &v1alpha1.StepPluginStatus{ - Index: 0, - Name: "test-plugin", - Status: json.RawMessage("value"), +func newStepPluginStatus(operation v1alpha1.StepPluginOperation, phase v1alpha1.StepPluginPhase) *v1alpha1.StepPluginStatus { + now := metav1.Now() + status := &v1alpha1.StepPluginStatus{ + Index: 0, + Name: "test-plugin", + Status: json.RawMessage("value"), + Operation: operation, + Phase: phase, + StartedAt: &now, + UpdatedAt: &now, + Executions: 1, + Backoff: "0s", } + return status } func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) + stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -48,6 +59,7 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { reconcilerBase: reconcilerBase{ enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + recorder: record.NewFakeEventRecorder(), }, pauseContext: &pauseContext{ rollout: r, @@ -59,15 +71,13 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }, } - runStatus := newStepPluginStatus() + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationRun, v1alpha1.StepPluginPhaseSuccessful) stepPluginMock.On("Run", r).Return(runStatus, nil, nil) - runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful return roCtx, runStatus } t.Run("Status is added when not present", func(t *testing.T) { roCtx, runStatus := setup(t) - runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful err := roCtx.stepPluginContext.reconcile(roCtx) @@ -77,14 +87,14 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }) t.Run("Status is updated when existing", func(t *testing.T) { roCtx, runStatus := setup(t) - runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { - Index: runStatus.Index, - Name: runStatus.Name, - Message: "this is the existing status", - Phase: v1alpha1.StepPluginPhaseRunning, + Index: runStatus.Index, + Name: runStatus.Name, + Message: "this is the existing status", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, }, } @@ -96,20 +106,22 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }) t.Run("Status order is preserved when updating", func(t *testing.T) { roCtx, runStatus := setup(t) - runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { - Index: 123, - Name: runStatus.Name, + Index: 123, + Name: runStatus.Name, + Operation: v1alpha1.StepPluginOperationRun, }, { - Index: runStatus.Index, - Name: runStatus.Name, + Index: runStatus.Index, + Name: runStatus.Name, + Operation: v1alpha1.StepPluginOperationRun, }, { - Index: 456, - Name: "other", + Index: 456, + Name: "other", + Operation: v1alpha1.StepPluginOperationRun, }, } @@ -124,9 +136,10 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { } func Test_StepPlugin_RunningReconciliation(t *testing.T) { - setup := func(t *testing.T, phase v1alpha1.StepPluginPhase, requeueAfter *time.Duration) (*rolloutContext, *v1alpha1.StepPluginStatus) { + setup := func(t *testing.T, phase v1alpha1.StepPluginPhase, backoff *time.Duration) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) + stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -136,7 +149,8 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { log: logutil.WithRollout(r), reconcilerBase: reconcilerBase{ enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, - enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) {}, + recorder: record.NewFakeEventRecorder(), }, pauseContext: &pauseContext{ rollout: r, @@ -148,13 +162,11 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { }, } - runStatus := newStepPluginStatus() - if requeueAfter != nil { - runStatus.Backoff = v1alpha1.DurationString(requeueAfter.String()) + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationRun, phase) + if backoff != nil { + runStatus.Backoff = v1alpha1.DurationString(backoff.String()) } - stepPluginMock.On("Run", r).Return(runStatus, nil) - runStatus.Phase = phase return roCtx, runStatus } @@ -172,10 +184,11 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { - Index: runStatus.Index, - Name: runStatus.Name, - Message: "this is the existing status", - Phase: v1alpha1.StepPluginPhaseRunning, + Index: runStatus.Index, + Name: runStatus.Name, + Message: "this is the existing status", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, }, } @@ -197,7 +210,8 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - assert.Equal(t, expectedRequeueAfter, requeuedAfter) + assert.GreaterOrEqual(t, requeuedAfter, expectedRequeueAfter) + assert.LessOrEqual(t, requeuedAfter, expectedRequeueAfter+5*time.Second) }) } @@ -205,6 +219,7 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) + stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -215,6 +230,7 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { reconcilerBase: reconcilerBase{ enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + recorder: record.NewFakeEventRecorder(), }, pauseContext: &pauseContext{ rollout: r, @@ -226,9 +242,8 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { }, } - runStatus := newStepPluginStatus() + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationRun, phase) stepPluginMock.On("Run", r).Return(runStatus, nil, nil) - runStatus.Phase = phase return roCtx, runStatus } @@ -246,10 +261,11 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { - Index: runStatus.Index, - Name: runStatus.Name, - Message: "this is the existing status", - Phase: v1alpha1.StepPluginPhaseRunning, + Index: runStatus.Index, + Name: runStatus.Name, + Message: "this is the existing status", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, }, } @@ -273,6 +289,7 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *mocks.StepPlugin) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) + stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -285,6 +302,7 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { reconcilerBase: reconcilerBase{ enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + recorder: record.NewFakeEventRecorder(), }, pauseContext: &pauseContext{ rollout: r, @@ -301,9 +319,7 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { t.Run("Rollout is Terminated on full promotion", func(t *testing.T) { roCtx, stepPluginMock := setup(t) - runStatus := newStepPluginStatus() - runStatus.Operation = v1alpha1.StepPluginOperationTerminate - runStatus.Phase = v1alpha1.StepPluginPhaseSuccessful + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationTerminate, v1alpha1.StepPluginPhaseSuccessful) roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { Index: runStatus.Index, @@ -337,6 +353,7 @@ func Test_StepPlugin_Aborted(t *testing.T) { reconcilerBase: reconcilerBase{ enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + recorder: record.NewFakeEventRecorder(), }, pauseContext: &pauseContext{ rollout: r, @@ -359,6 +376,12 @@ func Test_StepPlugin_Aborted(t *testing.T) { Operation: v1alpha1.StepPluginOperationRun, Phase: v1alpha1.StepPluginPhaseSuccessful, }, + { + Index: 2, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, + }, } roCtx.rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ { @@ -375,7 +398,7 @@ func Test_StepPlugin_Aborted(t *testing.T) { }, }, } - roCtx.rollout.Status.CurrentStepIndex = int32Ptr(2) + roCtx.rollout.Status.CurrentStepIndex = int32Ptr(0) expectedAbortStatus := []*v1alpha1.StepPluginStatus{} for _, stepIndex := range []int32{0, 2} { @@ -386,6 +409,7 @@ func Test_StepPlugin_Aborted(t *testing.T) { Phase: v1alpha1.StepPluginPhaseSuccessful, } stepPluginMock := mocks.NewStepPlugin(t) + stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", stepIndex, mock.Anything, mock.Anything).Return(stepPluginMock, nil) stepPluginMock.On("Abort", mock.Anything).Return(abortStatus, nil) expectedAbortStatus = append(expectedAbortStatus, abortStatus) @@ -394,10 +418,11 @@ func Test_StepPlugin_Aborted(t *testing.T) { err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) - require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 3) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 4) assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[0], roCtx.stepPluginContext.stepPluginStatuses[0]) - assert.EqualExportedValues(t, *expectedAbortStatus[1], roCtx.stepPluginContext.stepPluginStatuses[1]) - assert.EqualExportedValues(t, *expectedAbortStatus[0], roCtx.stepPluginContext.stepPluginStatuses[2]) + assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[1], roCtx.stepPluginContext.stepPluginStatuses[1]) + assert.EqualExportedValues(t, *expectedAbortStatus[1], roCtx.stepPluginContext.stepPluginStatuses[2]) + assert.EqualExportedValues(t, *expectedAbortStatus[0], roCtx.stepPluginContext.stepPluginStatuses[3]) }) } @@ -408,8 +433,6 @@ func Test_StepPlugin_Aborted(t *testing.T) { //Reconcile: // Add disable feature -// Helper: write helper functions? - func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { newRolloutContext := func(statuses []*v1alpha1.StepPluginStatus, hasError bool) *rolloutContext { r := newStepPluginRollout() diff --git a/rollout/steps/plugin/mocks/StepPlugin.go b/rollout/steps/plugin/mocks/StepPlugin.go index acbb3bebea..2a5b7cb679 100644 --- a/rollout/steps/plugin/mocks/StepPlugin.go +++ b/rollout/steps/plugin/mocks/StepPlugin.go @@ -43,24 +43,6 @@ func (_m *StepPlugin) Abort(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, return r0, r1 } -// Enabled provides a mock function with given fields: -func (_m *StepPlugin) Enabled() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Enabled") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - // Run provides a mock function with given fields: _a0 func (_m *StepPlugin) Run(_a0 *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { ret := _m.Called(_a0) diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index bda9b783a7..37196693f1 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -20,22 +20,27 @@ type stepPlugin struct { log *log.Entry } +type disabledStepPlugin struct { + index int32 + name string +} + type StepPlugin interface { Run(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) Terminate(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) Abort(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) - Enabled() bool } var ( minRequeueDuration = time.Second * 10 defaultRequeuDuration = time.Second * 30 + defaultErrorBackoff = time.Second * 30 ) // Run exectues a plugin func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) - if stepStatus == nil { + if stepStatus == nil || stepStatus.Disabled { now := metatime.MetaNow() stepStatus = &v1alpha1.StepPluginStatus{ Index: p.index, @@ -71,7 +76,7 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, p.log.Errorf("error during plugin execution") stepStatus.Phase = v1alpha1.StepPluginPhaseError stepStatus.Message = err.Error() - stepStatus.Backoff = v1alpha1.DurationString((30 * time.Second).String()) + stepStatus.Backoff = v1alpha1.DurationString(defaultErrorBackoff.String()) return stepStatus, nil } @@ -111,7 +116,7 @@ func (p *stepPlugin) Terminate(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginS } stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) - if stepStatus == nil || stepStatus.Phase != v1alpha1.StepPluginPhaseRunning { + if stepStatus == nil || stepStatus.Disabled || stepStatus.Phase != v1alpha1.StepPluginPhaseRunning { // Step is not running, no need to call terminate return nil, nil } @@ -161,7 +166,7 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu } stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) - if stepStatus == nil || (stepStatus.Phase != v1alpha1.StepPluginPhaseRunning && stepStatus.Phase != v1alpha1.StepPluginPhaseSuccessful) { + if stepStatus == nil || stepStatus.Disabled || (stepStatus.Phase != v1alpha1.StepPluginPhaseRunning && stepStatus.Phase != v1alpha1.StepPluginPhaseSuccessful) { // Step plugin isn't in a phase where it needs to be aborted return nil, nil } @@ -203,8 +208,21 @@ func (p *stepPlugin) Abort(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatu return abortStatus, nil } -func (p *stepPlugin) Enabled() bool { - return true +func (p *disabledStepPlugin) Run(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return &v1alpha1.StepPluginStatus{ + Index: p.index, + Name: p.name, + Operation: v1alpha1.StepPluginOperationRun, + Disabled: true, + }, nil +} + +func (p *disabledStepPlugin) Terminate(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, nil +} + +func (p *disabledStepPlugin) Abort(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { + return nil, nil } func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index 4a8488596e..a03f9c7679 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -225,7 +225,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Equal(t, rpcResult.RequeueAfter, *result.RequeueAfter) + assert.EqualValues(t, rpcResult.RequeueAfter.String(), status.Backoff) }) t.Run("Running status without requeue", func(t *testing.T) { p, rpcMock := setup(t) @@ -257,7 +257,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Equal(t, defaultRequeuDuration, *result.RequeueAfter) + assert.EqualValues(t, defaultRequeuDuration.String(), status.Backoff) }) t.Run("Running status with requeue too fast", func(t *testing.T) { p, rpcMock := setup(t) @@ -290,7 +290,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Equal(t, defaultRequeuDuration, *result.RequeueAfter) + assert.EqualValues(t, defaultRequeuDuration.String(), status.Backoff) }) t.Run("Failed status", func(t *testing.T) { p, rpcMock := setup(t) diff --git a/rollout/steps/plugin/resolver.go b/rollout/steps/plugin/resolver.go index 17c1b3891a..0dffc507b5 100644 --- a/rollout/steps/plugin/resolver.go +++ b/rollout/steps/plugin/resolver.go @@ -11,25 +11,6 @@ import ( log "github.com/sirupsen/logrus" ) -type disabledStepPlugin struct { -} - -func (p *disabledStepPlugin) Run(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { - return nil, nil -} - -func (p *disabledStepPlugin) Terminate(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { - return nil, nil -} - -func (p *disabledStepPlugin) Abort(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { - return nil, nil -} - -func (p *disabledStepPlugin) Enabled() bool { - return false -} - type resolver struct { } @@ -47,7 +28,10 @@ func (r *resolver) Resolve(index int32, plugin v1alpha1.PluginStep, log *log.Ent } else { plugin := config.GetPlugin(plugin.Name, types.PluginTypeStep) if plugin != nil && plugin.Disabled { - return &disabledStepPlugin{}, nil + return &disabledStepPlugin{ + index: index, + name: plugin.Name, + }, nil } } diff --git a/test/cmd/step-plugin-sample/main.go b/test/cmd/step-plugin-sample/main.go index 77b5ec2801..f70d4d25eb 100644 --- a/test/cmd/step-plugin-sample/main.go +++ b/test/cmd/step-plugin-sample/main.go @@ -38,7 +38,7 @@ func main() { if err != nil { log.Fatal(err) } - seed = int64(n) + seed = n } else { log.Fatal("No value for --seed argument") } diff --git a/ui/src/models/rollout/generated/api.ts b/ui/src/models/rollout/generated/api.ts index 084a2097cd..5c5acde7e0 100755 --- a/ui/src/models/rollout/generated/api.ts +++ b/ui/src/models/rollout/generated/api.ts @@ -2855,6 +2855,12 @@ export interface GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginS * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus */ executions?: number; + /** + * + * @type {boolean} + * @memberof GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1StepPluginStatus + */ + disabled?: boolean; /** * * @type {string} diff --git a/utils/plugin/downloader_test.go b/utils/plugin/downloader_test.go index 75dc4cae71..84aeef9e26 100644 --- a/utils/plugin/downloader_test.go +++ b/utils/plugin/downloader_test.go @@ -107,7 +107,7 @@ func TestPlugin(t *testing.T) { cm, err := config.InitializeConfig(client, defaults.DefaultRolloutsConfigMapName) assert.NoError(t, err) - assert.Equal(t, cm, &config.Config{}) + assert.Equal(t, 0, len(cm.GetAllPlugins())) err = DownloadPlugins(MockFileDownloader{}) assert.NoError(t, err) diff --git a/utils/plugin/plugin_test.go b/utils/plugin/plugin_test.go index a685def3db..0e5d994a6c 100644 --- a/utils/plugin/plugin_test.go +++ b/utils/plugin/plugin_test.go @@ -73,16 +73,16 @@ func TestGetPluginInfo(t *testing.T) { Name: "argo-rollouts-config", Namespace: "argo-rollouts", }, - Data: map[string]string{"steplugins": "\n - name: argoproj-labs/steps\n location: https://test/plugin\n args: [\"-l 2\"]\n - name: argoproj-labs/steps-sha\n location: https://test/plugin\n sha256: 74657374e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, + Data: map[string]string{"stepPlugins": "\n - name: argoproj-labs/steps\n location: https://test/plugin\n args: [\"-l 2\"]\n - name: argoproj-labs/steps-sha\n location: https://test/plugin\n sha256: 74657374e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, } client := fake.NewSimpleClientset(cm) _, err := config.InitializeConfig(client, "argo-rollouts-config") assert.NoError(t, err) - location, args, err := GetPluginInfo("argoproj-labs/step", types.PluginTypeStep) + location, args, err := GetPluginInfo("argoproj-labs/steps", types.PluginTypeStep) assert.NoError(t, err) - fp, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, "argoproj-labs/step")) + fp, err := filepath.Abs(filepath.Join(defaults.DefaultRolloutPluginFolder, "argoproj-labs/steps")) assert.NoError(t, err) assert.Equal(t, fp, location) assert.Equal(t, args, cmdArgs) From 9d811100e3010be94f90a84076ce0183dc7db2c5 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 10:38:10 -0400 Subject: [PATCH 33/41] unit tests Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin.go | 8 +- rollout/stepplugin_test.go | 250 +++++++++++++++++++++++++--- rollout/steps/plugin/plugin_test.go | 92 +++++++++- 3 files changed, 322 insertions(+), 28 deletions(-) diff --git a/rollout/stepplugin.go b/rollout/stepplugin.go index 609c8ec3f1..eb777f6c70 100644 --- a/rollout/stepplugin.go +++ b/rollout/stepplugin.go @@ -59,9 +59,6 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { return nil } - // If we retry an aborted rollout, we need to have a clean status - spc.cleanStatusForRetry(rollout) - // On full promotion, we want to Terminate only the last step still in Running, if any if rollout.Status.PromoteFull || rolloututil.IsFullyPromoted(rollout) { stepIndex := spc.getStepToTerminate(rollout) @@ -91,6 +88,9 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { return nil } + // If we retry an aborted rollout, we need to have a clean status + spc.cleanStatusForRetry(rollout) + // Normal execution flow of a step plugin currentStep, currentStepIndex := replicasetutil.GetCurrentCanaryStep(rollout) if currentStep == nil || currentStep.Plugin == nil { @@ -134,7 +134,7 @@ func (spc *stepPluginContext) reconcile(c *rolloutContext) error { } if status.Phase == v1alpha1.StepPluginPhaseFailed { - c.pauseContext.AddAbort(status.Message) + c.pauseContext.AddAbort(fmt.Sprintf("Step Plugin %d (%s) failed: %s", status.Index+1, status.Name, status.Message)) } return nil diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index 536dfd0d94..28589a2eea 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -33,6 +33,7 @@ func newStepPluginStatus(operation v1alpha1.StepPluginOperation, phase v1alpha1. status := &v1alpha1.StepPluginStatus{ Index: 0, Name: "test-plugin", + Message: "this is a default message", Status: json.RawMessage("value"), Operation: operation, Phase: phase, @@ -48,7 +49,6 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) - stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -72,7 +72,7 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { } runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationRun, v1alpha1.StepPluginPhaseSuccessful) - stepPluginMock.On("Run", r).Return(runStatus, nil, nil) + stepPluginMock.On("Run", r).Return(runStatus, nil) return roCtx, runStatus } @@ -139,7 +139,6 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase, backoff *time.Duration) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) - stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -211,7 +210,7 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { require.NoError(t, err) assert.GreaterOrEqual(t, requeuedAfter, expectedRequeueAfter) - assert.LessOrEqual(t, requeuedAfter, expectedRequeueAfter+5*time.Second) + assert.LessOrEqual(t, requeuedAfter, expectedRequeueAfter+defaultBackoffDelay) }) } @@ -219,7 +218,6 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) - stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) r := newStepPluginRollout() @@ -243,7 +241,7 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { } runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationRun, phase) - stepPluginMock.On("Run", r).Return(runStatus, nil, nil) + stepPluginMock.On("Run", r).Return(runStatus, nil) return roCtx, runStatus } @@ -276,24 +274,19 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[0], *runStatus) }) t.Run("Rollout is aborted", func(t *testing.T) { - roCtx, _ := setup(t, v1alpha1.StepPluginPhaseFailed) + roCtx, failedStatus := setup(t, v1alpha1.StepPluginPhaseFailed) err := roCtx.stepPluginContext.reconcile(roCtx) require.NoError(t, err) assert.True(t, roCtx.pauseContext.IsAborted()) + assert.Contains(t, roCtx.pauseContext.abortMessage, failedStatus.Message) }) } func Test_StepPlugin_FullyPromoted(t *testing.T) { - setup := func(t *testing.T) (*rolloutContext, *mocks.StepPlugin) { - stepPluginResolver := mocks.NewResolver(t) - stepPluginMock := mocks.NewStepPlugin(t) - stepPluginMock.On("Enabled").Return(true).Maybe() - stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) - + newRolloutContext := func(t *testing.T) *rolloutContext { r := newStepPluginRollout() - r.Status.PromoteFull = true logCtx := logutil.WithRollout(r) roCtx := &rolloutContext{ @@ -309,16 +302,28 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { log: logCtx, }, stepPluginContext: &stepPluginContext{ - resolver: stepPluginResolver, - log: logCtx, + log: logCtx, }, } + return roCtx + } + setup := func(t *testing.T) (*rolloutContext, *mocks.StepPlugin) { + stepPluginResolver := mocks.NewResolver(t) + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) + + roCtx := newRolloutContext(t) + roCtx.stepPluginContext.resolver = stepPluginResolver return roCtx, stepPluginMock } t.Run("Rollout is Terminated on full promotion", func(t *testing.T) { roCtx, stepPluginMock := setup(t) + roCtx.rollout.Status.PromoteFull = true + roCtx.rollout.Status.StableRS = "stable-value" + roCtx.rollout.Status.CurrentPodHash = "current-value" + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationTerminate, v1alpha1.StepPluginPhaseSuccessful) roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ { @@ -337,6 +342,61 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 2) assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[1], *runStatus) }) + + t.Run("Rollout is Terminated on fully promoted", func(t *testing.T) { + roCtx, stepPluginMock := setup(t) + roCtx.rollout.Status.PromoteFull = false + roCtx.rollout.Status.StableRS = "stable-value" + roCtx.rollout.Status.CurrentPodHash = "stable-value" + + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationTerminate, v1alpha1.StepPluginPhaseSuccessful) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, + }, + } + + stepPluginMock.On("Terminate", mock.Anything).Return(runStatus, nil) + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 2) + assert.EqualExportedValues(t, roCtx.stepPluginContext.stepPluginStatuses[1], *runStatus) + }) + + t.Run("Rollout is Reconciled when already terminated", func(t *testing.T) { + roCtx := newRolloutContext(t) + roCtx.rollout.Status.PromoteFull = false + roCtx.rollout.Status.StableRS = "stable-value" + roCtx.rollout.Status.CurrentPodHash = "stable-value" + roCtx.rollout.Status.CurrentStepIndex = ptr.To(int32(1)) + + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationTerminate, v1alpha1.StepPluginPhaseSuccessful) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, + }, + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseSuccessful, + Operation: v1alpha1.StepPluginOperationTerminate, + }, + } + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 2) + assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[1], roCtx.stepPluginContext.stepPluginStatuses[1]) + }) } func Test_StepPlugin_Aborted(t *testing.T) { @@ -409,7 +469,6 @@ func Test_StepPlugin_Aborted(t *testing.T) { Phase: v1alpha1.StepPluginPhaseSuccessful, } stepPluginMock := mocks.NewStepPlugin(t) - stepPluginMock.On("Enabled").Return(true).Maybe() stepPluginResolver.On("Resolve", stepIndex, mock.Anything, mock.Anything).Return(stepPluginMock, nil) stepPluginMock.On("Abort", mock.Anything).Return(abortStatus, nil) expectedAbortStatus = append(expectedAbortStatus, abortStatus) @@ -424,14 +483,153 @@ func Test_StepPlugin_Aborted(t *testing.T) { assert.EqualExportedValues(t, *expectedAbortStatus[1], roCtx.stepPluginContext.stepPluginStatuses[2]) assert.EqualExportedValues(t, *expectedAbortStatus[0], roCtx.stepPluginContext.stepPluginStatuses[3]) }) + t.Run("Rollout is reconciled when already aborted", func(t *testing.T) { + roCtx, stepPluginResolver := setup(t) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + { + Index: 2, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, + }, + { + Index: 2, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationAbort, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + { + Index: 0, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationAbort, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + } + roCtx.rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + { + Pause: &v1alpha1.RolloutPause{}, // Not a step plugin + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + } + roCtx.rollout.Status.CurrentStepIndex = int32Ptr(0) + + for _, stepIndex := range []int32{0, 2} { + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", stepIndex, mock.Anything, mock.Anything).Return(stepPluginMock, nil) + stepPluginMock.On("Abort", mock.Anything).Return(nil, nil) + } + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 4) + assert.Equal(t, roCtx.rollout.Status.Canary.StepPluginStatuses, roCtx.stepPluginContext.stepPluginStatuses) + }) } -//Controller: -// Add test for plugin config -// Add InitPlugin call test +func Test_StepPlugin_Retry_After_Abort(t *testing.T) { + setup := func(t *testing.T) (*rolloutContext, *mocks.Resolver) { + stepPluginResolver := mocks.NewResolver(t) -//Reconcile: -// Add disable feature + r := newStepPluginRollout() + r.Status.Abort = true + + logCtx := logutil.WithRollout(r) + roCtx := &rolloutContext{ + rollout: r, + log: logCtx, + reconcilerBase: reconcilerBase{ + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + recorder: record.NewFakeEventRecorder(), + }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, + } + + return roCtx, stepPluginResolver + } + + t.Run("Rollout is retried when already aborted", func(t *testing.T) { + roCtx, stepPluginResolver := setup(t) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + { + Index: 2, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, + }, + { + Index: 2, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationAbort, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + { + Index: 0, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationAbort, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + } + roCtx.rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{ + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + { + Pause: &v1alpha1.RolloutPause{}, + }, + { + Plugin: &v1alpha1.PluginStep{ + Name: "test-plugin", + }, + }, + } + roCtx.rollout.Status.CurrentStepIndex = int32Ptr(0) + roCtx.rollout.Status.Abort = false + roCtx.rollout.Status.AbortedAt = nil + + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationRun, v1alpha1.StepPluginPhaseSuccessful) + stepPluginMock.On("Run", roCtx.rollout).Return(runStatus, nil) + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.Equal(t, *runStatus, roCtx.stepPluginContext.stepPluginStatuses[0]) + }) +} func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { newRolloutContext := func(statuses []*v1alpha1.StepPluginStatus, hasError bool) *rolloutContext { @@ -532,6 +730,14 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { index: 0, want: false, }, + { + name: "status is disabled", + statuses: []*v1alpha1.StepPluginStatus{ + {Index: 0, Operation: v1alpha1.StepPluginOperationRun, Disabled: true}, + }, + index: 0, + want: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/rollout/steps/plugin/plugin_test.go b/rollout/steps/plugin/plugin_test.go index a03f9c7679..dc041fa015 100644 --- a/rollout/steps/plugin/plugin_test.go +++ b/rollout/steps/plugin/plugin_test.go @@ -150,6 +150,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, rpcResult.Status, status.Status) assert.NotNil(t, status.FinishedAt) assert.Empty(t, status.Backoff) + assert.False(t, status.Disabled) }) t.Run("Successful status", func(t *testing.T) { p, rpcMock := setup(t) @@ -183,7 +184,8 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) - assert.Nil(t, status.Backoff) + assert.EqualValues(t, "", status.Backoff) + assert.False(t, status.Disabled) }) t.Run("Running status", func(t *testing.T) { p, rpcMock := setup(t) @@ -226,6 +228,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.EqualValues(t, rpcResult.RequeueAfter.String(), status.Backoff) + assert.False(t, status.Disabled) }) t.Run("Running status without requeue", func(t *testing.T) { p, rpcMock := setup(t) @@ -258,6 +261,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.EqualValues(t, defaultRequeuDuration.String(), status.Backoff) + assert.False(t, status.Disabled) }) t.Run("Running status with requeue too fast", func(t *testing.T) { p, rpcMock := setup(t) @@ -291,6 +295,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.EqualValues(t, defaultRequeuDuration.String(), status.Backoff) + assert.False(t, status.Disabled) }) t.Run("Failed status", func(t *testing.T) { p, rpcMock := setup(t) @@ -325,6 +330,7 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, rpcResult.Message, status.Message) assert.Equal(t, rpcResult.Status, status.Status) assert.Empty(t, status.Backoff) + assert.False(t, status.Disabled) }) t.Run("Error status", func(t *testing.T) { p, rpcMock := setup(t) @@ -369,7 +375,8 @@ func Test_stepPlugin_Run(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) assert.Equal(t, expectedError.Error(), status.Message) assert.Equal(t, currentStatus.Status, status.Status) - assert.Empty(t, status.Backoff) + assert.EqualValues(t, "30s", status.Backoff) + assert.False(t, status.Disabled) }) } @@ -460,6 +467,7 @@ func Test_stepPlugin_Terminate(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginPhaseFailed, status.Phase) assert.Equal(t, rpcResult.Message, status.Message) assert.Nil(t, status.Status) + assert.False(t, status.Disabled) }) t.Run("Completes successfully", func(t *testing.T) { p, rpcMock := setup(t) @@ -486,6 +494,7 @@ func Test_stepPlugin_Terminate(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationTerminate, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Nil(t, status.Status) + assert.False(t, status.Disabled) }) t.Run("Error status", func(t *testing.T) { @@ -516,6 +525,7 @@ func Test_stepPlugin_Terminate(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) assert.Contains(t, status.Message, expectedError.Error()) assert.Nil(t, status.Status) + assert.False(t, status.Disabled) }) } @@ -621,6 +631,7 @@ func Test_stepPlugin_Abort(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginPhaseFailed, status.Phase) assert.Equal(t, rpcResult.Message, status.Message) assert.Nil(t, status.Status) + assert.False(t, status.Disabled) }) t.Run("Completes successfully", func(t *testing.T) { p, rpcMock := setup(t) @@ -647,6 +658,7 @@ func Test_stepPlugin_Abort(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginOperationAbort, status.Operation) assert.Equal(t, rpcResult.Message, status.Message) assert.Nil(t, status.Status) + assert.False(t, status.Disabled) }) t.Run("Error status", func(t *testing.T) { @@ -677,5 +689,81 @@ func Test_stepPlugin_Abort(t *testing.T) { assert.Equal(t, v1alpha1.StepPluginPhaseError, status.Phase) assert.Contains(t, status.Message, expectedError.Error()) assert.Nil(t, status.Status) + assert.False(t, status.Disabled) + }) +} + +func Test_disabledStepPlugin(t *testing.T) { + t.Run("Run always return disabled status", func(t *testing.T) { + p := disabledStepPlugin{ + index: 0, + name: "test", + } + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + }, + } + + status, err := p.Run(r) + + require.NoError(t, err) + + assert.Equal(t, p.name, status.Name) + assert.Equal(t, p.index, status.Index) + assert.Equal(t, v1alpha1.StepPluginOperationRun, status.Operation) + assert.True(t, status.Disabled) + }) + t.Run("Abort has no effect", func(t *testing.T) { + p := disabledStepPlugin{ + index: 0, + name: "test", + } + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + }, + }, + }, + } + + status, err := p.Abort(r) + + require.NoError(t, err) + assert.Nil(t, status) + }) + t.Run("Terminate has no effect", func(t *testing.T) { + p := disabledStepPlugin{ + index: 0, + name: "test", + } + r := &v1alpha1.Rollout{ + Status: v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseRunning, + }, + }, + }, + }, + } + + status, err := p.Terminate(r) + + require.NoError(t, err) + assert.Nil(t, status) }) } From c776330f84c8f484457515efee27233e0d4057b0 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 11:19:39 -0400 Subject: [PATCH 34/41] more test Signed-off-by: Alexandre Gaudreault --- rollout/stepplugin_test.go | 160 +++++++++++++++++++++++++++++++++++-- 1 file changed, 153 insertions(+), 7 deletions(-) diff --git a/rollout/stepplugin_test.go b/rollout/stepplugin_test.go index 28589a2eea..b3959b05e1 100644 --- a/rollout/stepplugin_test.go +++ b/rollout/stepplugin_test.go @@ -2,6 +2,7 @@ package rollout import ( "encoding/json" + "fmt" "testing" "time" @@ -45,7 +46,45 @@ func newStepPluginStatus(operation v1alpha1.StepPluginOperation, phase v1alpha1. return status } -func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { +func Test_stepPluginContext_reconcile_ReconciliationError(t *testing.T) { + stepPluginResolver := mocks.NewResolver(t) + r := newStepPluginRollout() + logCtx := logutil.WithRollout(r) + roCtx := &rolloutContext{ + rollout: r, + log: logutil.WithRollout(r), + reconcilerBase: reconcilerBase{ + enqueueRollout: func(obj any) { t.Error("enqueueRollout should not be called") }, + enqueueRolloutAfter: func(obj any, duration time.Duration) { t.Error("enqueueRolloutAfter should not be called") }, + recorder: record.NewFakeEventRecorder(), + }, + pauseContext: &pauseContext{ + rollout: r, + log: logCtx, + }, + stepPluginContext: &stepPluginContext{ + resolver: stepPluginResolver, + log: logCtx, + }, + } + + stepPluginResolver.On("Resolve", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("test error")) + + var requeuedAfter time.Duration + roCtx.enqueueRolloutAfter = func(obj any, duration time.Duration) { + requeuedAfter = duration + } + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + assert.Equal(t, roCtx.rollout.Status.Canary.StepPluginStatuses, roCtx.stepPluginContext.stepPluginStatuses) + assert.Equal(t, defaultControllerErrorBackoff, requeuedAfter) + assert.True(t, roCtx.stepPluginContext.hasError) + +} + +func Test_stepPluginContext_reconcile_SuccessfulReconciliation(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) @@ -135,7 +174,7 @@ func Test_StepPlugin_SuccessfulReconciliation(t *testing.T) { }) } -func Test_StepPlugin_RunningReconciliation(t *testing.T) { +func Test_stepPluginContext_reconcile_RunningReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase, backoff *time.Duration) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) @@ -214,7 +253,7 @@ func Test_StepPlugin_RunningReconciliation(t *testing.T) { }) } -func Test_StepPlugin_FailedReconciliation(t *testing.T) { +func Test_stepPluginContext_reconcile_FailedReconciliation(t *testing.T) { setup := func(t *testing.T, phase v1alpha1.StepPluginPhase) (*rolloutContext, *v1alpha1.StepPluginStatus) { stepPluginResolver := mocks.NewResolver(t) stepPluginMock := mocks.NewStepPlugin(t) @@ -284,7 +323,7 @@ func Test_StepPlugin_FailedReconciliation(t *testing.T) { }) } -func Test_StepPlugin_FullyPromoted(t *testing.T) { +func Test_stepPluginContext_reconcile_FullyPromoted(t *testing.T) { newRolloutContext := func(t *testing.T) *rolloutContext { r := newStepPluginRollout() @@ -397,9 +436,39 @@ func Test_StepPlugin_FullyPromoted(t *testing.T) { require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 2) assert.EqualExportedValues(t, roCtx.rollout.Status.Canary.StepPluginStatuses[1], roCtx.stepPluginContext.stepPluginStatuses[1]) }) + + t.Run("Reconciliation error", func(t *testing.T) { + roCtx, stepPluginMock := setup(t) + roCtx.rollout.Status.PromoteFull = true + + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationTerminate, v1alpha1.StepPluginPhaseSuccessful) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, + }, + } + + var requeuedAfter time.Duration + roCtx.enqueueRolloutAfter = func(obj any, duration time.Duration) { + requeuedAfter = duration + } + + stepPluginMock.On("Terminate", mock.Anything).Return(nil, fmt.Errorf("error")) + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.Equal(t, roCtx.rollout.Status.Canary.StepPluginStatuses, roCtx.stepPluginContext.stepPluginStatuses) + assert.Equal(t, defaultControllerErrorBackoff, requeuedAfter) + assert.True(t, roCtx.stepPluginContext.hasError) + }) } -func Test_StepPlugin_Aborted(t *testing.T) { +func Test_stepPluginContext_reconcile_Aborted(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *mocks.Resolver) { stepPluginResolver := mocks.NewResolver(t) @@ -540,9 +609,48 @@ func Test_StepPlugin_Aborted(t *testing.T) { require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 4) assert.Equal(t, roCtx.rollout.Status.Canary.StepPluginStatuses, roCtx.stepPluginContext.stepPluginStatuses) }) + t.Run("Reconciliation error", func(t *testing.T) { + roCtx, stepPluginResolver := setup(t) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: 0, + Name: "test-plugin", + Operation: v1alpha1.StepPluginOperationRun, + Phase: v1alpha1.StepPluginPhaseSuccessful, + }, + } + roCtx.rollout.Status.CurrentStepIndex = int32Ptr(0) + + runStatus := newStepPluginStatus(v1alpha1.StepPluginOperationTerminate, v1alpha1.StepPluginPhaseSuccessful) + roCtx.rollout.Status.Canary.StepPluginStatuses = []v1alpha1.StepPluginStatus{ + { + Index: runStatus.Index, + Name: runStatus.Name, + Phase: v1alpha1.StepPluginPhaseRunning, + Operation: v1alpha1.StepPluginOperationRun, + }, + } + + var requeuedAfter time.Duration + roCtx.enqueueRolloutAfter = func(obj any, duration time.Duration) { + requeuedAfter = duration + } + + stepPluginMock := mocks.NewStepPlugin(t) + stepPluginResolver.On("Resolve", int32(0), mock.Anything, mock.Anything).Return(stepPluginMock, nil) + stepPluginMock.On("Abort", mock.Anything).Return(nil, fmt.Errorf("error")) + + err := roCtx.stepPluginContext.reconcile(roCtx) + + require.NoError(t, err) + require.Len(t, roCtx.stepPluginContext.stepPluginStatuses, 1) + assert.Equal(t, roCtx.rollout.Status.Canary.StepPluginStatuses, roCtx.stepPluginContext.stepPluginStatuses) + assert.Equal(t, defaultControllerErrorBackoff, requeuedAfter) + assert.True(t, roCtx.stepPluginContext.hasError) + }) } -func Test_StepPlugin_Retry_After_Abort(t *testing.T) { +func Test_stepPluginContext_reconcile_Retry_After_Abort(t *testing.T) { setup := func(t *testing.T) (*rolloutContext, *mocks.Resolver) { stepPluginResolver := mocks.NewResolver(t) @@ -631,7 +739,7 @@ func Test_StepPlugin_Retry_After_Abort(t *testing.T) { }) } -func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { +func Test_stepPluginContext_isStepPluginCompleted(t *testing.T) { newRolloutContext := func(statuses []*v1alpha1.StepPluginStatus, hasError bool) *rolloutContext { r := newStepPluginRollout() logCtx := logutil.WithRollout(r) @@ -748,3 +856,41 @@ func Test_rolloutContext_isStepPluginCompleted(t *testing.T) { }) } } + +func Test_stepPluginContext_updateStatus(t *testing.T) { + + t.Run("status is not", func(t *testing.T) { + stepPluginContext := stepPluginContext{ + stepPluginStatuses: nil, + } + + expected := []v1alpha1.StepPluginStatus{} + status := &v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: expected, + }, + } + + stepPluginContext.updateStatus(status) + + assert.Equal(t, expected, status.Canary.StepPluginStatuses) + }) + t.Run("status is set", func(t *testing.T) { + + expected := []v1alpha1.StepPluginStatus{{}} + + stepPluginContext := stepPluginContext{ + stepPluginStatuses: expected, + } + + status := &v1alpha1.RolloutStatus{ + Canary: v1alpha1.CanaryStatus{ + StepPluginStatuses: []v1alpha1.StepPluginStatus{}, + }, + } + + stepPluginContext.updateStatus(status) + + assert.Equal(t, expected, status.Canary.StepPluginStatuses) + }) +} From aa3723856370e671a6fa955362f67d28bccf1137 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 11:44:02 -0400 Subject: [PATCH 35/41] cleanup Signed-off-by: Alexandre Gaudreault --- test/cmd/step-plugin-sample/internal/plugin/docs.go | 3 --- test/e2e/step_plugin_test.go | 9 ++++++++- utils/rollout/rolloututil_test.go | 4 ++++ 3 files changed, 12 insertions(+), 4 deletions(-) delete mode 100644 test/cmd/step-plugin-sample/internal/plugin/docs.go diff --git a/test/cmd/step-plugin-sample/internal/plugin/docs.go b/test/cmd/step-plugin-sample/internal/plugin/docs.go deleted file mode 100644 index 65fc77527e..0000000000 --- a/test/cmd/step-plugin-sample/internal/plugin/docs.go +++ /dev/null @@ -1,3 +0,0 @@ -package plugin - -// The goal of this plugin is to diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index f02efde594..c2f9477fd0 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -316,12 +316,19 @@ func (s *StepPluginSuite) TestRolloutSkipPluginWhenDisabled() { ExpectStableRevision("2"). Assert(func(t *fixtures.Then) { rollout := t.GetRollout() - assert.EqualValues(s.T(), 1, len(rollout.Status.Canary.StepPluginStatuses)) + assert.EqualValues(s.T(), 2, len(rollout.Status.Canary.StepPluginStatuses)) stepStatus := rollout.Status.Canary.StepPluginStatuses[0] + assert.EqualValues(s.T(), E2EStepPluginNameDisabled, stepStatus.Name) + assert.EqualValues(s.T(), 0, stepStatus.Index) + assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + assert.EqualValues(s.T(), true, stepStatus.Disabled) + + stepStatus = rollout.Status.Canary.StepPluginStatuses[1] assert.EqualValues(s.T(), E2EStepPluginName, stepStatus.Name) assert.EqualValues(s.T(), 1, stepStatus.Index) assert.EqualValues(s.T(), v1alpha1.StepPluginPhaseSuccessful, stepStatus.Phase) assert.EqualValues(s.T(), v1alpha1.StepPluginOperationRun, stepStatus.Operation) + assert.EqualValues(s.T(), false, stepStatus.Disabled) }) } diff --git a/utils/rollout/rolloututil_test.go b/utils/rollout/rolloututil_test.go index 37c1810f00..a241d40f49 100644 --- a/utils/rollout/rolloututil_test.go +++ b/utils/rollout/rolloututil_test.go @@ -389,6 +389,10 @@ func TestCanaryStepString(t *testing.T) { step: v1alpha1.CanaryStep{SetCanaryScale: &v1alpha1.SetCanaryScale{Replicas: pointer.Int32Ptr(5)}}, expectedString: "setCanaryScale{replicas: 5}", }, + { + step: v1alpha1.CanaryStep{Plugin: &v1alpha1.PluginStep{Name: "foo"}}, + expectedString: "plugin: foo", + }, } for _, test := range tests { assert.Equal(t, test.expectedString, CanaryStepString(test.step)) From 4866c0cc21693eba30d67b61fa200ff74b14126a Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 14:16:38 -0400 Subject: [PATCH 36/41] add docs Signed-off-by: Alexandre Gaudreault --- manifests/crds/rollout-crd.yaml | 1 - manifests/install.yaml | 1 - pkg/apiclient/rollout/rollout.swagger.json | 41 +++++++---- pkg/apis/rollouts/v1alpha1/generated.proto | 18 ++++- .../rollouts/v1alpha1/openapi_generated.go | 68 +++++++++++-------- pkg/apis/rollouts/v1alpha1/types.go | 59 ++++++++++------ pkg/apis/rollouts/validation/validation.go | 2 +- 7 files changed, 122 insertions(+), 68 deletions(-) diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index f49e6a5c12..8ca46db74a 100755 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -3764,7 +3764,6 @@ spec: - index - name - operation - - phase type: object type: array weights: diff --git a/manifests/install.yaml b/manifests/install.yaml index 11a4e66a0f..8454c38553 100755 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -16254,7 +16254,6 @@ spec: - index - name - operation - - phase type: object type: array weights: diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index 342e8aea90..095fd17f7e 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -984,7 +984,7 @@ "items": { "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.StepPluginStatus" }, - "title": "StepPluginStatuses Hold the status of the step plugins executed" + "title": "StepPluginStatuses holds the status of the step plugins executed" } }, "title": "CanaryStatus status fields that only pertain to the canary rollout" @@ -1770,12 +1770,12 @@ "properties": { "name": { "type": "string", - "title": "Name the name of the hashicorp go-plugin step to query" + "title": "Name of the hashicorp go-plugin step to query" }, "config": { "type": "string", "format": "byte", - "title": "+kubebuilder:validation:Schemaless\n+kubebuilder:pruning:PreserveUnknownFields\n+kubebuilder:validation:Type=object\nConfig the configuration object for the specified plugin" + "title": "+kubebuilder:validation:Schemaless\n+kubebuilder:pruning:PreserveUnknownFields\n+kubebuilder:validation:Type=object\nConfig is the configuration object for the specified plugin" } } }, @@ -2529,43 +2529,54 @@ "properties": { "index": { "type": "integer", - "format": "int32" + "format": "int32", + "title": "Index is the matching step index of the executed plugin" }, "name": { - "type": "string" + "type": "string", + "title": "Name is the matching step name of the executed plugin" }, "operation": { - "type": "string" + "type": "string", + "title": "Operation is the name of the operation that produced this status" }, "phase": { - "type": "string" + "type": "string", + "title": "Phase is the resulting phase of the operation" }, "message": { - "type": "string" + "type": "string", + "title": "Message provides details on why the plugin is in its current phase" }, "startedAt": { - "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" + "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time", + "title": "StartedAt indicates when the plugin was first called for the operation" }, "updatedAt": { - "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" + "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time", + "title": "UpdatedAt indicates when the plugin was last called for the operation" }, "finishedAt": { - "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time" + "$ref": "#/definitions/k8s.io.apimachinery.pkg.apis.meta.v1.Time", + "title": "FinishedAt indicates when the operation was completed" }, "backoff": { - "type": "string" + "type": "string", + "title": "Backoff is a duration to wait before trying to execute the operation again if it was not completed" }, "executions": { "type": "integer", - "format": "int32" + "format": "int32", + "title": "Executions is the number of time the operation was executed" }, "disabled": { - "type": "boolean" + "type": "boolean", + "title": "Disabled indicates if the plugin is globally disabled" }, "status": { "type": "string", "format": "byte", - "title": "+kubebuilder:validation:Schemaless\n+kubebuilder:pruning:PreserveUnknownFields\n+kubebuilder:validation:Type=object" + "title": "+kubebuilder:validation:Schemaless\n+kubebuilder:pruning:PreserveUnknownFields\n+kubebuilder:validation:Type=object\nStatus holds the internal status of the plugin for this operation" } } }, diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index c562635ac5..e908d74761 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -449,7 +449,7 @@ message CanaryStatus { // StablePingPong For the ping-pong feature holds the current stable service, ping or pong optional string stablePingPong = 5; - // StepPluginStatuses Hold the status of the step plugins executed + // StepPluginStatuses holds the status of the step plugins executed repeated StepPluginStatus stepPluginStatuses = 6; } @@ -1185,13 +1185,13 @@ message PingPongSpec { } message PluginStep { - // Name the name of the hashicorp go-plugin step to query + // Name of the hashicorp go-plugin step to query optional string name = 1; // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - // Config the configuration object for the specified plugin + // Config is the configuration object for the specified plugin optional bytes config = 2; } @@ -1755,31 +1755,43 @@ message SkyWalkingMetric { } message StepPluginStatus { + // Index is the matching step index of the executed plugin optional int32 index = 1; + // Name is the matching step name of the executed plugin optional string name = 2; + // Operation is the name of the operation that produced this status optional string operation = 3; + // Phase is the resulting phase of the operation optional string phase = 4; + // Message provides details on why the plugin is in its current phase optional string message = 5; + // StartedAt indicates when the plugin was first called for the operation optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 6; + // UpdatedAt indicates when the plugin was last called for the operation optional k8s.io.apimachinery.pkg.apis.meta.v1.Time updatedAt = 7; + // FinishedAt indicates when the operation was completed optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 8; + // Backoff is a duration to wait before trying to execute the operation again if it was not completed optional string backoff = 9; + // Executions is the number of time the operation was executed optional int32 executions = 10; + // Disabled indicates if the plugin is globally disabled optional bool disabled = 11; // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object + // Status holds the internal status of the plugin for this operation optional bytes status = 12; } diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index b4c6482cf4..380323b027 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -1421,7 +1421,7 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStatus(ref common.ReferenceCallback }, "stepPluginStatuses": { SchemaProps: spec.SchemaProps{ - Description: "StepPluginStatuses Hold the status of the step plugins executed", + Description: "StepPluginStatuses holds the status of the step plugins executed", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -3539,7 +3539,7 @@ func schema_pkg_apis_rollouts_v1alpha1_PluginStep(ref common.ReferenceCallback) Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Description: "Name the name of the hashicorp go-plugin step to query", + Description: "Name of the hashicorp go-plugin step to query", Default: "", Type: []string{"string"}, Format: "", @@ -3547,7 +3547,7 @@ func schema_pkg_apis_rollouts_v1alpha1_PluginStep(ref common.ReferenceCallback) }, "config": { SchemaProps: spec.SchemaProps{ - Description: "Config the configuration object for the specified plugin", + Description: "Config is the configuration object for the specified plugin", Type: []string{"string"}, Format: "byte", }, @@ -5184,75 +5184,87 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall Properties: map[string]spec.Schema{ "index": { SchemaProps: spec.SchemaProps{ - Default: 0, - Type: []string{"integer"}, - Format: "int32", + Description: "Index is the matching step index of the executed plugin", + Default: 0, + Type: []string{"integer"}, + Format: "int32", }, }, "name": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Name is the matching step name of the executed plugin", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "operation": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Operation is the name of the operation that produced this status", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "phase": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Phase is the resulting phase of the operation", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "message": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Message provides details on why the plugin is in its current phase", + Type: []string{"string"}, + Format: "", }, }, "startedAt": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + Description: "StartedAt indicates when the plugin was first called for the operation", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, "updatedAt": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + Description: "UpdatedAt indicates when the plugin was last called for the operation", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, "finishedAt": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + Description: "FinishedAt indicates when the operation was completed", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, "backoff": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Backoff is a duration to wait before trying to execute the operation again if it was not completed", + Type: []string{"string"}, + Format: "", }, }, "executions": { SchemaProps: spec.SchemaProps{ - Type: []string{"integer"}, - Format: "int32", + Description: "Executions is the number of time the operation was executed", + Type: []string{"integer"}, + Format: "int32", }, }, "disabled": { SchemaProps: spec.SchemaProps{ - Type: []string{"boolean"}, - Format: "", + Description: "Disabled indicates if the plugin is globally disabled", + Type: []string{"boolean"}, + Format: "", }, }, "status": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "byte", + Description: "Status holds the internal status of the plugin for this operation", + Type: []string{"string"}, + Format: "byte", }, }, }, diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index 573d0bd7e9..4cfa912948 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -642,13 +642,13 @@ type CanaryStep struct { } type PluginStep struct { - // Name the name of the hashicorp go-plugin step to query + // Name of the hashicorp go-plugin step to query Name string `json:"name" protobuf:"bytes,1,opt,name=name"` // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object - // Config the configuration object for the specified plugin + // Config is the configuration object for the specified plugin Config json.RawMessage `json:"config,omitempty" protobuf:"bytes,2,opt,name=config"` } @@ -998,7 +998,7 @@ type CanaryStatus struct { Weights *TrafficWeights `json:"weights,omitempty" protobuf:"bytes,4,opt,name=weights"` // StablePingPong For the ping-pong feature holds the current stable service, ping or pong StablePingPong PingPongType `json:"stablePingPong,omitempty" protobuf:"bytes,5,opt,name=stablePingPong"` - // StepPluginStatuses Hold the status of the step plugins executed + // StepPluginStatuses holds the status of the step plugins executed StepPluginStatuses []StepPluginStatus `json:"stepPluginStatuses,omitempty" protobuf:"bytes,6,rep,name=stepPluginStatuses"` } @@ -1038,21 +1038,33 @@ type RolloutAnalysisRunStatus struct { } type StepPluginStatus struct { - Index int32 `json:"index" protobuf:"bytes,1,name=index"` - Name string `json:"name" protobuf:"bytes,2,name=name"` - Operation StepPluginOperation `json:"operation" protobuf:"bytes,3,name=operation,casttype=StepPluginOperation"` - Phase StepPluginPhase `json:"phase" protobuf:"bytes,4,name=phase,casttype=StepPluginPhase"` - Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` - StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,6,name=startedAt"` - UpdatedAt *metav1.Time `json:"updatedAt,omitempty" protobuf:"bytes,7,opt,name=updatedAt"` - FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,8,opt,name=finishedAt"` - Backoff DurationString `json:"backoff,omitempty" protobuf:"bytes,9,opt,name=backoff,casttype=DurationString"` - Executions int32 `json:"executions,omitempty" protobuf:"varint,10,opt,name=executions"` - Disabled bool `json:"disabled,omitempty" protobuf:"bytes,11,opt,name=disabled"` + // Index is the matching step index of the executed plugin + Index int32 `json:"index" protobuf:"bytes,1,name=index"` + // Name is the matching step name of the executed plugin + Name string `json:"name" protobuf:"bytes,2,name=name"` + // Operation is the name of the operation that produced this status + Operation StepPluginOperation `json:"operation" protobuf:"bytes,3,name=operation,casttype=StepPluginOperation"` + // Phase is the resulting phase of the operation + Phase StepPluginPhase `json:"phase,omitempty" protobuf:"bytes,4,opt,name=phase,casttype=StepPluginPhase"` + // Message provides details on why the plugin is in its current phase + Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` + // StartedAt indicates when the plugin was first called for the operation + StartedAt *metav1.Time `json:"startedAt,omitempty" protobuf:"bytes,6,name=startedAt"` + // UpdatedAt indicates when the plugin was last called for the operation + UpdatedAt *metav1.Time `json:"updatedAt,omitempty" protobuf:"bytes,7,opt,name=updatedAt"` + // FinishedAt indicates when the operation was completed + FinishedAt *metav1.Time `json:"finishedAt,omitempty" protobuf:"bytes,8,opt,name=finishedAt"` + // Backoff is a duration to wait before trying to execute the operation again if it was not completed + Backoff DurationString `json:"backoff,omitempty" protobuf:"bytes,9,opt,name=backoff,casttype=DurationString"` + // Executions is the number of time the operation was executed + Executions int32 `json:"executions,omitempty" protobuf:"varint,10,opt,name=executions"` + // Disabled indicates if the plugin is globally disabled + Disabled bool `json:"disabled,omitempty" protobuf:"bytes,11,opt,name=disabled"` // +kubebuilder:validation:Schemaless // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Type=object + // Status holds the internal status of the plugin for this operation Status json.RawMessage `json:"status,omitempty" protobuf:"bytes,12,opt,name=status"` } @@ -1061,12 +1073,17 @@ type StepPluginPhase string // Possible StepPluginPhase values const ( - StepPluginPhaseRunning StepPluginPhase = "Running" + // StepPluginPhaseRunning is the phase of a step plugin when it has not completed its execution + StepPluginPhaseRunning StepPluginPhase = "Running" + // StepPluginPhaseSuccessful is the phase of a step plugin when the operation completed successfully StepPluginPhaseSuccessful StepPluginPhase = "Successful" - StepPluginPhaseFailed StepPluginPhase = "Failed" - StepPluginPhaseError StepPluginPhase = "Error" + // StepPluginPhaseFailed is the phase of a step plugin when the operation completed unsuccessfully + StepPluginPhaseFailed StepPluginPhase = "Failed" + // StepPluginPhaseError is the phase of a step plugin when an unexpected error prevented the completion of the operation + StepPluginPhaseError StepPluginPhase = "Error" ) +// Validate that the object is a valid phase func (p StepPluginPhase) Validate() error { switch p { case StepPluginPhaseRunning: @@ -1079,13 +1096,17 @@ func (p StepPluginPhase) Validate() error { return nil } +// StepPluginOperation is the operation executed by a step plugin type StepPluginOperation string // Possible StepPluginOperation values const ( - StepPluginOperationRun StepPluginOperation = "Run" + // StepPluginOperationRun is the value for the Run operation + StepPluginOperationRun StepPluginOperation = "Run" + // StepPluginOperationRun is the value for the Terminate operation StepPluginOperationTerminate StepPluginOperation = "Terminate" - StepPluginOperationAbort StepPluginOperation = "Abort" + // StepPluginOperationRun is the value for the Abort operation + StepPluginOperationAbort StepPluginOperation = "Abort" ) type ALBStatus struct { diff --git a/pkg/apis/rollouts/validation/validation.go b/pkg/apis/rollouts/validation/validation.go index e88119ce28..6b4ddb45e2 100644 --- a/pkg/apis/rollouts/validation/validation.go +++ b/pkg/apis/rollouts/validation/validation.go @@ -309,7 +309,7 @@ func ValidateRolloutStrategyCanary(rollout *v1alpha1.Rollout, fldPath *field.Pat allErrs = append(allErrs, hasMultipleStepsType(step, stepFldPath)...) if step.Experiment == nil && step.Pause == nil && step.SetWeight == nil && step.Analysis == nil && step.SetCanaryScale == nil && step.SetHeaderRoute == nil && step.SetMirrorRoute == nil && step.Plugin == nil { - errVal := fmt.Sprintf("step.Experiment: %t step.Pause: %t step.SetWeight: %t step.Analysis: %t step.SetCanaryScale: %t step.SetHeaderRoute: %t step.SetMirrorRoutes: %t step.SetMirrorRoutes: %t", + errVal := fmt.Sprintf("step.Experiment: %t step.Pause: %t step.SetWeight: %t step.Analysis: %t step.SetCanaryScale: %t step.SetHeaderRoute: %t step.SetMirrorRoute: %t step.Plugin: %t", step.Experiment == nil, step.Pause == nil, step.SetWeight == nil, step.Analysis == nil, step.SetCanaryScale == nil, step.SetHeaderRoute == nil, step.SetMirrorRoute == nil, step.Plugin == nil) allErrs = append(allErrs, field.Invalid(stepFldPath, errVal, InvalidStepMessage)) } From d8b51713f4fbb429dee586c752424f5955f260f8 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 16:26:15 -0400 Subject: [PATCH 37/41] docs Signed-off-by: Alexandre Gaudreault --- .../rollouts/v1alpha1/openapi_generated.go | 3 +- rollout/steps/plugin/plugin.go | 6 ++++ rollout/steps/plugin/resolver.go | 3 ++ .../step-plugin-e2e/internal/plugin/plugin.go | 8 ++--- utils/plugin/types/steps.go | 36 +++++++++++++------ utils/plugin/types/types.go | 35 +++++++++++------- 6 files changed, 61 insertions(+), 30 deletions(-) diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 380323b027..609db76128 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -5209,7 +5209,6 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall "phase": { SchemaProps: spec.SchemaProps{ Description: "Phase is the resulting phase of the operation", - Default: "", Type: []string{"string"}, Format: "", }, @@ -5268,7 +5267,7 @@ func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCall }, }, }, - Required: []string{"index", "name", "operation", "phase"}, + Required: []string{"index", "name", "operation"}, }, }, Dependencies: []string{ diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 37196693f1..52d32b27da 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -25,9 +25,13 @@ type disabledStepPlugin struct { name string } +// StepPlugin allows to execute different operation for a step plugin specifc to a rollout type StepPlugin interface { + // Run executes the run operation for of a step plugin and returns a Run operation status Run(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) + // Terminate cancels an ongoing running Run operation and returns a Terminate status if it did Terminate(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) + // Abort reverts a completed Run operation and returns a Terminate status if it did Abort(*v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) } @@ -225,6 +229,7 @@ func (p *disabledStepPlugin) Abort(_ *v1alpha1.Rollout) (*v1alpha1.StepPluginSta return nil, nil } +// getStepStatus returns the existing status for the current operation func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout, operation v1alpha1.StepPluginOperation) *v1alpha1.StepPluginStatus { for _, s := range rollout.Status.Canary.StepPluginStatuses { if s.Index == p.index && s.Name == p.name && s.Operation == operation { @@ -234,6 +239,7 @@ func (p *stepPlugin) getStepStatus(rollout *v1alpha1.Rollout, operation v1alpha1 return nil } +// getStepContext returns the current step configuration with the from a previous operation, if any func (p *stepPlugin) getStepContext(stepStatus *v1alpha1.StepPluginStatus) *types.RpcStepContext { var status json.RawMessage = nil if stepStatus != nil { diff --git a/rollout/steps/plugin/resolver.go b/rollout/steps/plugin/resolver.go index 0dffc507b5..f2233526ec 100644 --- a/rollout/steps/plugin/resolver.go +++ b/rollout/steps/plugin/resolver.go @@ -14,10 +14,13 @@ import ( type resolver struct { } +// Resolver allows to resolve a StepPlugin object type Resolver interface { + // Resolve is a factory to create the correct StepPlugin based on the current step and global configurations Resolve(index int32, plugin v1alpha1.PluginStep, log *log.Entry) (StepPlugin, error) } +// NewResolver creaates a new Resolver func NewResolver() Resolver { return &resolver{} } diff --git a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go index 3d994bfc69..f46d9bfa78 100644 --- a/test/cmd/step-plugin-e2e/internal/plugin/plugin.go +++ b/test/cmd/step-plugin-e2e/internal/plugin/plugin.go @@ -85,7 +85,7 @@ func (p *rpcPlugin) Run(rollout *v1alpha1.Rollout, context *types.RpcStepContext phase := types.PhaseSuccessful if config.Return != "" { - phase = types.Phase(config.Return) + phase = types.StepPhase(config.Return) if err := phase.Validate(); err != nil { return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse phase: %w", err).Error()} } @@ -115,7 +115,7 @@ func (p *rpcPlugin) Terminate(rollout *v1alpha1.Rollout, context *types.RpcStepC phase := types.PhaseSuccessful if config.Terminate.Return != "" { - phase = types.Phase(config.Terminate.Return) + phase = types.StepPhase(config.Terminate.Return) if err := phase.Validate(); err != nil { return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse phase: %w", err).Error()} } @@ -145,7 +145,7 @@ func (p *rpcPlugin) Abort(rollout *v1alpha1.Rollout, context *types.RpcStepConte phase := types.PhaseSuccessful if config.Abort.Return != "" { - phase = types.Phase(config.Abort.Return) + phase = types.StepPhase(config.Abort.Return) if err := phase.Validate(); err != nil { return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Errorf("could not parse phase: %w", err).Error()} } @@ -158,7 +158,7 @@ func (p *rpcPlugin) Type() string { return "e2e-plugin" } -func Result(state State, phase types.Phase, requeue time.Duration) (types.RpcStepResult, types.RpcError) { +func Result(state State, phase types.StepPhase, requeue time.Duration) (types.RpcStepResult, types.RpcError) { stateRaw, err := json.Marshal(state) if err != nil { return types.RpcStepResult{}, types.RpcError{ErrorString: fmt.Sprintf("Could not marshal state: %v", err)} diff --git a/utils/plugin/types/steps.go b/utils/plugin/types/steps.go index 9c0e7e235b..f54d7ec00b 100644 --- a/utils/plugin/types/steps.go +++ b/utils/plugin/types/steps.go @@ -6,29 +6,43 @@ import ( "time" ) -type Phase string +// StepPhase is the type of phase of step plugin result +type StepPhase string const ( - PhaseRunning Phase = "Running" - PhaseSuccessful Phase = "Successful" - PhaseFailed Phase = "Failed" - PhaseError Phase = "Error" + // PhaseRunning is the Running phase of a step plugin + PhaseRunning StepPhase = "Running" + // PhaseRunning is the Successful phase of a step plugin + PhaseSuccessful StepPhase = "Successful" + // PhaseRunning is the Failed phase of a step plugin + PhaseFailed StepPhase = "Failed" + // PhaseRunning is the Error phase of a step plugin + PhaseError StepPhase = "Error" ) +// RpcStepContext is the context of the step plugin operation type RpcStepContext struct { + // PluginName is the name of the plugin as defined by the user PluginName string - Config json.RawMessage - Status json.RawMessage + // Config holds the user specified configuration in the Rollout object for this plugin step + Config json.RawMessage + // Status holds a previous execution status related to the operation + Status json.RawMessage } type RpcStepResult struct { - Phase Phase - Message string + // Phase of the operation to idicate if it has completed or not + Phase StepPhase + // Message contains information about the execution + Message string + // RequeueAfter is the duration to wait before executing the operation again when it does not return a completed phase RequeueAfter time.Duration - Status json.RawMessage + // Status hold the execution status of this plugin step. It can be used to persist a state between executions + Status json.RawMessage } -func (p Phase) Validate() error { +// Validate the phase of a step plugin +func (p StepPhase) Validate() error { switch p { case PhaseRunning: case PhaseSuccessful: diff --git a/utils/plugin/types/types.go b/utils/plugin/types/types.go index 3b16d75a46..11cd8be5e4 100644 --- a/utils/plugin/types/types.go +++ b/utils/plugin/types/types.go @@ -86,45 +86,54 @@ type RpcTrafficRoutingReconciler interface { } type RpcStep interface { + // Run executes a step plugin for the RpcStepContext and returns the result to the controller or an RpcError for unexpeted failures Run(*v1alpha1.Rollout, *RpcStepContext) (RpcStepResult, RpcError) + // Terminate stops an uncompleted operation started by the Run operation Terminate(*v1alpha1.Rollout, *RpcStepContext) (RpcStepResult, RpcError) + // Abort reverts the actions performed during the Run operation if necessary Abort(*v1alpha1.Rollout, *RpcStepContext) (RpcStepResult, RpcError) // Type returns the type of the step plugin Type() string } -//type Plugin struct { -// MetricProviders []PluginItem `json:"metricProviders" yaml:"metricProviders"` -// TrafficRouters []PluginItem `json:"trafficRouters" yaml:"trafficRouters"` -//} - type TrafficRouterPlugins struct { + // TrafficRouters is the list of plugin that implements a RpcTrafficRoutingReconciler TrafficRouters []PluginItem `json:"trafficRouterPlugins" yaml:"trafficRouterPlugins"` } type MetricProviderPlugins struct { + // MetricProviders is the list of plugin that implements a RpcMetricProvider MetricProviders []PluginItem `json:"metricProviderPlugins" yaml:"metricProviderPlugins"` } type StepPlugins struct { + // Steps is the list of plugin that implements a RpcStep Steps []PluginItem `json:"stepPlugins" yaml:"stepPlugins"` } +// PluginType is a type of plugin type PluginType string const ( + // PluginTypeMetricProvider is the type for a MetricProvider plugin PluginTypeMetricProvider PluginType = "MetricProvider" - PluginTypeTrafficRouter PluginType = "TrafficRouter" - PluginTypeStep PluginType = "Step" + // PluginTypeTrafficRouter is the type for a TrafficRouter plugin + PluginTypeTrafficRouter PluginType = "TrafficRouter" + // PluginTypeStep is the type for a Step plugin + PluginTypeStep PluginType = "Step" ) type PluginItem struct { - Name string `json:"name" yaml:"name"` + // Name of the plugin to use in the Rollout custom resources + Name string `json:"name" yaml:"name"` + // Location of the plugin. Supports http(s):// urls and file:// prefix Location string `json:"location" yaml:"location"` - Sha256 string `json:"sha256" yaml:"sha256"` - Disabled bool `json:"disabled" yaml:"disabled"` - Type PluginType - - // Args holds command line arguments + // Sha256 is the checksum of the file specified at the provided Location + Sha256 string `json:"sha256" yaml:"sha256"` + // Type of the plugin + Type PluginType + // Disabled indicates if the plugin should be ignored when referenced in Rollout custom resources. Only valid for a plugin of type Step. + Disabled bool `json:"disabled" yaml:"disabled"` + // Args holds command line arguments to initialize the plugin Args []string `json:"args" yaml:"args"` } From a4331ab9ab5d127a58662d4b1d6aeb29a90366b8 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 17:28:36 -0400 Subject: [PATCH 38/41] makefile for e2e Signed-off-by: Alexandre Gaudreault --- Dockerfile.dev | 3 +++ Makefile | 25 +++++++++++++------------ rollout/steps/plugin/plugin.go | 4 +++- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Dockerfile.dev b/Dockerfile.dev index 7c3fc3f30c..184d4e33e9 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -12,9 +12,12 @@ FROM gcr.io/distroless/static-debian11 COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY rollouts-controller-linux-amd64 /bin/rollouts-controller +COPY step-plugin-e2e-linux-amd64 /bin/plugin-files/step-plugin-e2e # Use numeric user, allows kubernetes to identify this user as being # non-root when we use a security context with runAsNonRoot: true USER 999 +WORKDIR /home/argo-rollouts + ENTRYPOINT [ "/bin/rollouts-controller" ] diff --git a/Makefile b/Makefile index 1c7be23848..8544562910 100644 --- a/Makefile +++ b/Makefile @@ -12,9 +12,12 @@ GIT_TREE_STATE=$(shell if [ -z "`git status --porcelain`" ]; then echo "clean" ; GIT_REMOTE_REPO=upstream VERSION=$(shell if [ ! -z "${GIT_TAG}" ] ; then echo "${GIT_TAG}" | sed -e "s/^v//" ; else cat VERSION ; fi) + +TARGET_ARCH?=linux/amd64 + # docker image publishing options -DOCKER_PUSH=false -IMAGE_TAG=latest +DOCKER_PUSH ?= false +IMAGE_TAG ?= latest # build development images DEV_IMAGE ?= false @@ -204,10 +207,11 @@ builder-image: ## build builder image .PHONY: image image: ifeq ($(DEV_IMAGE), true) + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/step-plugin-e2e-linux-amd64 ./test/cmd/step-plugin-e2e CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/rollouts-controller-linux-amd64 ./cmd/rollouts-controller - DOCKER_BUILDKIT=1 docker build -t $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) -f Dockerfile.dev ${DIST_DIR} + DOCKER_BUILDKIT=1 docker build --platform=$(TARGET_ARCH) -t $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) -f Dockerfile.dev ${DIST_DIR} else - DOCKER_BUILDKIT=1 docker build -t $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) . + DOCKER_BUILDKIT=1 docker build --platform=$(TARGET_ARCH) -t $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) . endif @if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) ; fi @@ -228,7 +232,7 @@ build-sample-step-plugin-debug: ## build sample traffic plugin with debug info .PHONY: plugin-image plugin-image: ## build plugin image - DOCKER_BUILDKIT=1 docker build --target kubectl-argo-rollouts -t $(IMAGE_PREFIX)kubectl-argo-rollouts:$(IMAGE_TAG) . + DOCKER_BUILDKIT=1 docker build --platform=$(TARGET_ARCH) --target kubectl-argo-rollouts -t $(IMAGE_PREFIX)kubectl-argo-rollouts:$(IMAGE_TAG) . if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)kubectl-argo-rollouts:$(IMAGE_TAG) ; fi ##@ Test @@ -241,14 +245,11 @@ test: test-kustomize ## run all tests test-kustomize: ## run kustomize tests ./test/kustomize/test.sh -step-plugin-e2e-setup: - @rm -rf plugin-bin - @go build -gcflags="all=-N -l" -o plugin-bin/e2e-step-plugin test/cmd/step-plugin-e2e/main.go +setup-e2e: @kubectl apply --context='${E2E_K8S_CONTEXT}' -f manifests/crds/rollout-crd.yaml @kubectl apply --context='${E2E_K8S_CONTEXT}' -n argo-rollouts -f test/e2e/step-plugin/argo-rollouts-config.yaml - -step-plugin-e2e-run: - ${DIST_DIR}/gotestsum --rerun-fails-report=rerunreport.txt --junitfile=junit.xml --format=testname --packages="./test/e2e" --rerun-fails=0 -- -timeout 60m -count 1 --tags e2e -p ${E2E_PARALLEL} -parallel ${E2E_PARALLEL} -v --short ./test/e2e -run 'TestStepPluginSuite' + @rm -rf plugin-bin + @go build -gcflags="all=-N -l" -o plugin-bin/e2e-step-plugin test/cmd/step-plugin-e2e/main.go .PHONY: start-e2e start-e2e: ## start e2e test environment @@ -259,7 +260,7 @@ test-e2e: install-devtools-local ${DIST_DIR}/gotestsum --rerun-fails-report=rerunreport.txt --junitfile=junit.xml --format=testname --packages="./test/e2e" --rerun-fails=5 -- -timeout 60m -count 1 --tags e2e -p ${E2E_PARALLEL} -parallel ${E2E_PARALLEL} -v --short ./test/e2e ${E2E_TEST_OPTIONS} .PHONY: test-unit - test-unit: install-devtools-local ## run unit tests +test-unit: install-devtools-local ## run unit tests ${DIST_DIR}/gotestsum --junitfile=junit.xml --format=testname -- -covermode=count -coverprofile=coverage.out `go list ./... | grep -v ./test/cmd/metrics-plugin-sample` diff --git a/rollout/steps/plugin/plugin.go b/rollout/steps/plugin/plugin.go index 52d32b27da..dd9ebe04ad 100644 --- a/rollout/steps/plugin/plugin.go +++ b/rollout/steps/plugin/plugin.go @@ -41,7 +41,6 @@ var ( defaultErrorBackoff = time.Second * 30 ) -// Run exectues a plugin func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, error) { stepStatus := p.getStepStatus(rollout, v1alpha1.StepPluginOperationRun) if stepStatus == nil || stepStatus.Disabled { @@ -56,10 +55,13 @@ func (p *stepPlugin) Run(rollout *v1alpha1.Rollout) (*v1alpha1.StepPluginStatus, } if stepStatus.Phase == v1alpha1.StepPluginPhaseSuccessful || stepStatus.Phase == v1alpha1.StepPluginPhaseFailed { + // Already completed return nil, nil } if stepStatus.Executions > 0 { + // If status existed, check the backoff to know if we are ready to retry. + // If we are not, return the status without modifying it. backoff, err := stepStatus.Backoff.Duration() if err != nil { return nil, fmt.Errorf("could not parse backoff duration: %w", err) From ee5195b0d25c562ecaa67e2fb246fd88c53a0340 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Wed, 1 May 2024 17:38:45 -0400 Subject: [PATCH 39/41] disable e2e when not configured Signed-off-by: Alexandre Gaudreault --- test/e2e/step_plugin_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/e2e/step_plugin_test.go b/test/e2e/step_plugin_test.go index c2f9477fd0..5a938f3f51 100644 --- a/test/e2e/step_plugin_test.go +++ b/test/e2e/step_plugin_test.go @@ -39,6 +39,10 @@ func (s *StepPluginSuite) SetupSuite() { // getControllerConfiguredPlugin look at the controller default config map to find the list of plugins // This is a best effort because it does not mean the controller have these plugins configured in-memory func IsStepPluginConfigured(c *fixtures.Common, config *corev1.ConfigMap) bool { + if config == nil { + return false + } + var stepPlugins []types.PluginItem if err := yaml.Unmarshal([]byte(config.Data["stepPlugins"]), &stepPlugins); err != nil { c.CheckError(err) From b1d096378080526752623341ff3141a87abd7d44 Mon Sep 17 00:00:00 2001 From: Alexandre Gaudreault Date: Thu, 2 May 2024 09:37:08 -0400 Subject: [PATCH 40/41] Add some UI for the extension Signed-off-by: Alexandre Gaudreault --- ui/src/app/components/rollout/rollout.scss | 4 ++++ ui/src/app/components/rollout/rollout.tsx | 27 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ui/src/app/components/rollout/rollout.scss b/ui/src/app/components/rollout/rollout.scss index 6ee3b71099..b93f9ed8ff 100644 --- a/ui/src/app/components/rollout/rollout.scss +++ b/ui/src/app/components/rollout/rollout.scss @@ -97,6 +97,10 @@ padding-bottom: 4px; font-size: 14px; } + + &-value { + white-space: pre-wrap; + } } } diff --git a/ui/src/app/components/rollout/rollout.tsx b/ui/src/app/components/rollout/rollout.tsx index dfecde7e84..f0cf0037bf 100644 --- a/ui/src/app/components/rollout/rollout.tsx +++ b/ui/src/app/components/rollout/rollout.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import * as YAML from 'yaml'; import {Helmet} from 'react-helmet'; import {useParams} from 'react-router-dom'; import { @@ -6,6 +7,7 @@ import { GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1HeaderRoutingMatch, GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1RolloutExperimentTemplate, GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1SetMirrorRoute, + GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1PluginStep, RolloutReplicaSetInfo, RolloutRolloutInfo, RolloutServiceApi, @@ -316,6 +318,7 @@ const Step = (props: {step: GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1 const [openAnalysis, setOpenAnalysis] = React.useState(false); const [openHeader, setOpenHeader] = React.useState(false); const [openMirror, setOpenMirror] = React.useState(false); + const [openPlugin, setOpenPlugin] = React.useState(false); let icon: string; let content = ''; @@ -359,6 +362,11 @@ const Step = (props: {step: GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1 } } + if (props.step.plugin) { + content = `${props.step.plugin.name}`; + icon = 'fa-puzzle-piece'; + } + return (
@@ -368,7 +376,8 @@ const Step = (props: {step: GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1 (props.step.setCanaryScale && openCanary) || (props.step.analysis && openAnalysis) || (props.step.setHeaderRoute && openHeader) || - (props.step.setMirrorRoute && openMirror) + (props.step.setMirrorRoute && openMirror) || + (props.step.plugin && openPlugin) ? 'steps__step-title--experiment' : '' }`} @@ -395,6 +404,11 @@ const Step = (props: {step: GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1
)} + {props.step.plugin && props.step.plugin.config && ( +
setOpenPlugin(!openPlugin)}> + +
+ )} {props.step.experiment?.templates && (
@@ -419,6 +433,7 @@ const Step = (props: {step: GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1
)} {props.step?.setCanaryScale && openCanary && } + {props.step?.plugin && openPlugin && } {props.step?.setHeaderRoute && openHeader && } {props.step?.setMirrorRoute && openMirror && } @@ -563,3 +578,13 @@ const WidgetItemSetHeader = ({values}: {values: GithubComArgoprojArgoRolloutsPkg ); }; + +const WidgetItemPlugin = ({values}: {values: GithubComArgoprojArgoRolloutsPkgApisRolloutsV1alpha1PluginStep}) => { + if (!values.config) return null; + return ( +
+
CONFIG
+
{YAML.stringify(values.config)}
+
+ ); +}; From 7459514b0288ed3924e3a454aaaf1a7c5c17f02a Mon Sep 17 00:00:00 2001 From: Zach Aller Date: Wed, 7 Aug 2024 16:19:26 -0500 Subject: [PATCH 41/41] codegen Signed-off-by: Zach Aller --- .../rollouts/v1alpha1/openapi_generated.go | 211 +++++++++++++++++- 1 file changed, 208 insertions(+), 3 deletions(-) diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 6c18e64a2b..5ba707c6ac 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -97,9 +97,11 @@ 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.PluginStep": schema_pkg_apis_rollouts_v1alpha1_PluginStep(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), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PrometheusRangeQueryArgs": schema_pkg_apis_rollouts_v1alpha1_PrometheusRangeQueryArgs(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RequiredDuringSchedulingIgnoredDuringExecution": schema_pkg_apis_rollouts_v1alpha1_RequiredDuringSchedulingIgnoredDuringExecution(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RollbackWindowSpec": schema_pkg_apis_rollouts_v1alpha1_RollbackWindowSpec(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.Rollout": schema_pkg_apis_rollouts_v1alpha1_Rollout(ref), @@ -126,6 +128,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute": schema_pkg_apis_rollouts_v1alpha1_SetMirrorRoute(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.Sigv4Config": schema_pkg_apis_rollouts_v1alpha1_Sigv4Config(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SkyWalkingMetric": schema_pkg_apis_rollouts_v1alpha1_SkyWalkingMetric(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StepPluginStatus": schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StickinessConfig": schema_pkg_apis_rollouts_v1alpha1_StickinessConfig(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StringMatch": schema_pkg_apis_rollouts_v1alpha1_StringMatch(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TCPRoute": schema_pkg_apis_rollouts_v1alpha1_TCPRoute(ref), @@ -1417,11 +1420,25 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStatus(ref common.ReferenceCallback Format: "", }, }, + "stepPluginStatuses": { + SchemaProps: spec.SchemaProps{ + Description: "StepPluginStatuses holds the status of the step plugins executed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StepPluginStatus"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysisRunStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysisRunStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.StepPluginStatus", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.TrafficWeights"}, } } @@ -1475,11 +1492,17 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStep(ref common.ReferenceCallback) Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute"), }, }, + "plugin": { + SchemaProps: spec.SchemaProps{ + Description: "Plugin defines a plugin to execute for a step", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginStep"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutExperimentStep", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutPause", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetCanaryScale", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetHeaderRoute", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PluginStep", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutExperimentStep", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutPause", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetCanaryScale", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetHeaderRoute", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.SetMirrorRoute"}, } } @@ -3356,6 +3379,21 @@ func schema_pkg_apis_rollouts_v1alpha1_NginxTrafficRouting(ref common.ReferenceC }, }, }, + "canaryIngressAnnotations": { + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, }, }, }, @@ -3509,6 +3547,34 @@ func schema_pkg_apis_rollouts_v1alpha1_PingPongSpec(ref common.ReferenceCallback } } +func schema_pkg_apis_rollouts_v1alpha1_PluginStep(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the hashicorp go-plugin step to query", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "config": { + SchemaProps: spec.SchemaProps{ + Description: "Config is the configuration object for the specified plugin", + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"name"}, + }, + }, + } +} + func schema_pkg_apis_rollouts_v1alpha1_PodTemplateMetadata(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3638,11 +3704,51 @@ func schema_pkg_apis_rollouts_v1alpha1_PrometheusMetric(ref common.ReferenceCall }, }, }, + "rangeQuery": { + SchemaProps: spec.SchemaProps{ + Description: "Arguments for prometheus", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PrometheusRangeQueryArgs"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.Authentication", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WebMetricHeader"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.Authentication", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PrometheusRangeQueryArgs", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.WebMetricHeader"}, + } +} + +func schema_pkg_apis_rollouts_v1alpha1_PrometheusRangeQueryArgs(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Arguments to perform a prometheus range query", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "start": { + SchemaProps: spec.SchemaProps{ + Description: "The start time to query in expr format e.g. now(), now() - duration(\"1h\"), now() - duration(\"{{args.lookback_duration}}\")", + Type: []string{"string"}, + Format: "", + }, + }, + "end": { + SchemaProps: spec.SchemaProps{ + Description: "The end time to query in expr format e.g. now(), now() - duration(\"1h\"), now() - duration(\"{{args.lookback_duration}}\")", + Type: []string{"string"}, + Format: "", + }, + }, + "step": { + SchemaProps: spec.SchemaProps{ + Description: "The maximum time between two slices from the start to end (e.g. 30s, 5m, 1h).", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, } } @@ -5126,6 +5232,105 @@ func schema_pkg_apis_rollouts_v1alpha1_SkyWalkingMetric(ref common.ReferenceCall } } +func schema_pkg_apis_rollouts_v1alpha1_StepPluginStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "index": { + SchemaProps: spec.SchemaProps{ + Description: "Index is the matching step index of the executed plugin", + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the matching step name of the executed plugin", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "operation": { + SchemaProps: spec.SchemaProps{ + Description: "Operation is the name of the operation that produced this status", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "phase": { + SchemaProps: spec.SchemaProps{ + Description: "Phase is the resulting phase of the operation", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "Message provides details on why the plugin is in its current phase", + Type: []string{"string"}, + Format: "", + }, + }, + "startedAt": { + SchemaProps: spec.SchemaProps{ + Description: "StartedAt indicates when the plugin was first called for the operation", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "updatedAt": { + SchemaProps: spec.SchemaProps{ + Description: "UpdatedAt indicates when the plugin was last called for the operation", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "finishedAt": { + SchemaProps: spec.SchemaProps{ + Description: "FinishedAt indicates when the operation was completed", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "backoff": { + SchemaProps: spec.SchemaProps{ + Description: "Backoff is a duration to wait before trying to execute the operation again if it was not completed", + Type: []string{"string"}, + Format: "", + }, + }, + "executions": { + SchemaProps: spec.SchemaProps{ + Description: "Executions is the number of time the operation was executed", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "disabled": { + SchemaProps: spec.SchemaProps{ + Description: "Disabled indicates if the plugin is globally disabled", + Type: []string{"boolean"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status holds the internal status of the plugin for this operation", + Type: []string{"string"}, + Format: "byte", + }, + }, + }, + Required: []string{"index", "name", "operation"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + func schema_pkg_apis_rollouts_v1alpha1_StickinessConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{